summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c++.html.markdown80
-rw-r--r--c.html.markdown30
-rw-r--r--chapel.html.markdown1103
-rw-r--r--de-de/json-de.html.markdown65
-rw-r--r--de-de/yaml-de.html.markdown5
-rw-r--r--el-gr/racket-gr.html.markdown745
-rw-r--r--el-gr/scala-gr.html.markdown689
-rw-r--r--elixir.html.markdown2
-rw-r--r--erlang.html.markdown7
-rw-r--r--es-es/git-es.html.markdown2
-rw-r--r--es-es/go-es.html.markdown618
-rw-r--r--es-es/javascript-es.html.markdown9
-rw-r--r--es-es/julia-es.html.markdown1268
-rw-r--r--es-es/python-es.html.markdown120
-rw-r--r--fr-fr/erlang-fr.html.markdown327
-rw-r--r--fr-fr/livescript-fr.html.markdown360
-rw-r--r--fr-fr/lua-fr.html.markdown8
-rw-r--r--fr-fr/markdown.html.markdown2
-rw-r--r--fr-fr/r-fr.html.markdown1
-rw-r--r--git.html.markdown19
-rw-r--r--groovy.html.markdown8
-rw-r--r--haskell.html.markdown9
-rw-r--r--it-it/c++-it.html.markdown2
-rw-r--r--it-it/coffeescript-it.html.markdown107
-rw-r--r--it-it/elixir-it.html.markdown418
-rw-r--r--make.html.markdown243
-rw-r--r--matlab.html.markdown2
-rw-r--r--objective-c.html.markdown2
-rw-r--r--perl.html.markdown66
-rw-r--r--perl6.html.markdown13
-rw-r--r--pl-pl/brainfuck-pl.html.markdown93
-rw-r--r--pl-pl/python-pl.html.markdown637
-rw-r--r--pt-br/groovy-pt.html.markdown10
-rw-r--r--pt-br/perl-pt.html.markdown166
-rw-r--r--pt-br/xml-pt.html.markdown6
-rw-r--r--python.html.markdown17
-rw-r--r--python3.html.markdown23
-rw-r--r--red.html.markdown4
-rw-r--r--ro-ro/clojure-ro.html.markdown386
-rw-r--r--ru-ru/bash-ru.html.markdown284
-rw-r--r--ru-ru/brainfuck-ru.html.markdown2
-rw-r--r--ru-ru/objective-c-ru.html.markdown654
-rw-r--r--ruby-ecosystem.html.markdown2
-rw-r--r--ruby.html.markdown14
-rw-r--r--rust.html.markdown8
-rw-r--r--scala.html.markdown115
-rw-r--r--swift.html.markdown57
-rw-r--r--[-rwxr-xr-x]tcl.html.markdown15
-rw-r--r--tr-tr/csharp-tr.html.markdown2
-rw-r--r--tr-tr/swift-tr.html.markdown590
-rw-r--r--visualbasic.html.markdown4
-rw-r--r--zh-cn/bash-cn.html.markdown2
-rw-r--r--zh-cn/go-cn.html.markdown4
-rw-r--r--zh-cn/groovy-cn.html.markdown420
-rw-r--r--zh-cn/java-cn.html.markdown2
-rw-r--r--zh-cn/javascript-cn.html.markdown2
-rw-r--r--zh-cn/markdown-cn.html.markdown2
-rw-r--r--zh-cn/ruby-cn.html.markdown9
-rw-r--r--zh-cn/rust-cn.html.markdown296
59 files changed, 9054 insertions, 1102 deletions
diff --git a/c++.html.markdown b/c++.html.markdown
index ff2a98fd..26dfe111 100644
--- a/c++.html.markdown
+++ b/c++.html.markdown
@@ -4,6 +4,7 @@ filename: learncpp.cpp
contributors:
- ["Steven Basart", "http://github.com/xksteven"]
- ["Matt Kline", "https://github.com/mrkline"]
+ - ["Geoff Liu", "http://geoffliu.me"]
lang: en
---
@@ -158,11 +159,12 @@ void foo()
int main()
{
- // Assume everything is from the namespace "Second"
- // unless otherwise specified.
+ // Includes all symbols from `namesapce Second` into the current scope. Note
+ // that simply `foo()` no longer works, since it is now ambiguous whether
+ // we're calling the `foo` in `namespace Second` or the top level.
using namespace Second;
- foo(); // prints "This is Second::foo"
+ Second::foo(); // prints "This is Second::foo"
First::Nested::foo(); // prints "This is First::Nested::foo"
::foo(); // prints "This is global foo"
}
@@ -248,6 +250,59 @@ const string& barRef = bar; // Create a const reference to bar.
// Like C, const values (and pointers and references) cannot be modified.
barRef += ". Hi!"; // Error, const references cannot be modified.
+// Sidetrack: Before we talk more about references, we must introduce a concept
+// called a temporary object. Suppose we have the following code:
+string tempObjectFun() { ... }
+string retVal = tempObjectFun();
+
+// What happens in the second line is actually:
+// - a string object is returned from `tempObjectFun`
+// - a new string is constructed with the returned object as arugment to the
+// constructor
+// - the returned object is destroyed
+// The returned object is called a temporary object. Temporary objects are
+// created whenever a function returns an object, and they are destroyed at the
+// end of the evaluation of the enclosing expression (Well, this is what the
+// standard says, but compilers are allowed to change this behavior. Look up
+// "return value optimization" if you're into this kind of details). So in this
+// code:
+foo(bar(tempObjectFun()))
+
+// assuming `foo` and `bar` exist, the object returned from `tempObjectFun` is
+// passed to `bar`, and it is destroyed before `foo` is called.
+
+// Now back to references. The exception to the "at the end of the enclosing
+// expression" rule is if a temporary object is bound to a const reference, in
+// which case its life gets extended to the current scope:
+
+void constReferenceTempObjectFun() {
+ // `constRef` gets the temporary object, and it is valid until the end of this
+ // function.
+ const string& constRef = tempObjectFun();
+ ...
+}
+
+// Another kind of reference introduced in C++11 is specifically for temporary
+// objects. You cannot have a variable of its type, but it takes precedence in
+// overload resolution:
+
+void someFun(string& s) { ... } // Regular reference
+void someFun(string&& s) { ... } // Reference to temporary object
+
+string foo;
+someFun(foo); // Calls the version with regular reference
+someFun(tempObjectFun()); // Calls the version with temporary reference
+
+// For example, you will see these two versions of constructors for
+// std::basic_string:
+basic_string(const basic_string& other);
+basic_string(basic_string&& other);
+
+// Idea being if we are constructing a new string from a temporary object (which
+// is going to be destroyed soon anyway), we can have a more efficient
+// constructor that "salvages" parts of that temporary string. You will see this
+// concept referred to as the move semantic.
+
//////////////////////////////////////////
// Classes and object-oriented programming
//////////////////////////////////////////
@@ -699,7 +754,8 @@ pt2 = nullptr; // Sets pt2 to null.
// '=' != '=' != '='!
-// Calls Foo::Foo(const Foo&) or some variant copy constructor.
+// Calls Foo::Foo(const Foo&) or some variant (see move semantics) copy
+// constructor.
Foo f2;
Foo f1 = f2;
@@ -713,6 +769,22 @@ Foo f1 = fooSub;
Foo f1;
f1 = f2;
+
+// How to truly clear a container:
+class Foo { ... };
+vector<Foo> v;
+for (int i = 0; i < 10; ++i)
+ v.push_back(Foo());
+
+// Following line sets size of v to 0, but destructors don't get called,
+// and resources aren't released!
+v.empty();
+v.push_back(Foo()); // New value is copied into the first Foo we inserted in the loop.
+
+// Truly destroys all values in v. See section about temporary object for
+// explanation of why this works.
+v.swap(vector<Foo>());
+
```
Further Reading:
diff --git a/c.html.markdown b/c.html.markdown
index d3f20eda..8e631de4 100644
--- a/c.html.markdown
+++ b/c.html.markdown
@@ -18,9 +18,9 @@ memory management and C will take you as far as you need to go.
```c
// Single-line comments start with // - only available in C99 and later.
- /*
+/*
Multi-line comments look like this. They work in C89 as well.
- */
+*/
/*
Multi-line comments don't nest /* Be careful */ // comment ends on this line...
@@ -55,7 +55,7 @@ int add_two_ints(int x1, int x2); // function prototype
// Your program's entry point is a function called
// main with an integer return type.
-int main() {
+int main(void) {
// print output using printf, for "print formatted"
// %d is an integer, \n is a newline
printf("%d\n", 0); // => Prints 0
@@ -157,12 +157,12 @@ int main() {
int cha = 'a'; // fine
char chb = 'a'; // fine too (implicit conversion from int to char)
- //Multi-dimensional arrays:
+ // Multi-dimensional arrays:
int multi_array[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 0}
};
- //access elements:
+ // access elements:
int array_int = multi_array[0][2]; // => 3
///////////////////////////////////////
@@ -183,8 +183,8 @@ int main() {
i1 / i2; // => 0 (0.5, but truncated towards 0)
// You need to cast at least one integer to float to get a floating-point result
- (float)i1 / i2 // => 0.5f
- i1 / (double)i2 // => 0.5 // Same with double
+ (float)i1 / i2; // => 0.5f
+ i1 / (double)i2; // => 0.5 // Same with double
f1 / f2; // => 0.5, plus or minus epsilon
// Floating-point numbers and calculations are not exact
@@ -219,13 +219,13 @@ int main() {
0 || 1; // => 1 (Logical or)
0 || 0; // => 0
- //Conditional expression ( ? : )
+ // Conditional expression ( ? : )
int e = 5;
int f = 10;
int z;
z = (e > f) ? e : f; // => 10 "if e > f return e, else return f."
- //Increment and decrement operators:
+ // Increment and decrement operators:
char *s = "iLoveC";
int j = 0;
s[j++]; // => "i". Returns the j-th item of s THEN increments value of j.
@@ -371,7 +371,7 @@ int main() {
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
+ // 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.
@@ -404,8 +404,8 @@ int main() {
*(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx
} // 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"
+ // 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,
@@ -471,13 +471,13 @@ str_reverse(c);
printf("%s\n", c); // => ".tset a si sihT"
*/
-//if referring to external variables outside function, must use extern keyword.
+// if referring to external variables outside function, must use extern keyword.
int i = 0;
void testFunc() {
extern int i; //i here is now using external variable i
}
-//make external variables private to source file with static:
+// make external variables private to source file with static:
static int j = 0; //other files using testFunc2() cannot access variable j
void testFunc2() {
extern int j;
@@ -634,7 +634,7 @@ Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://
It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. 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/).
+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).
diff --git a/chapel.html.markdown b/chapel.html.markdown
new file mode 100644
index 00000000..c8489371
--- /dev/null
+++ b/chapel.html.markdown
@@ -0,0 +1,1103 @@
+---
+language: chapel
+filename: learnchapel.chpl
+contributors:
+ - ["Ian J. Bertolacci", "http://www.cs.colostate.edu/~ibertola/"]
+---
+
+You can read all about Chapel at [Cray's official Chapel website](http://chapel.cray.com).
+In short, Chapel is an open-source, high-productivity, parallel-programming language in development at Cray Inc., and is designed to run on multi-core PCs as well as multi-kilocore supercomputers.
+
+More information and support can be found at the bottom of this document.
+
+```c
+// Comments are C-family style
+// one line comment
+/*
+ multi-line comment
+*/
+
+// Basic printing
+write( "Hello, " );
+writeln( "World!" );
+// write and writeln can take a list of things to print.
+// each thing is printed right next to each other, so include your spacing!
+writeln( "There are ", 3, " commas (\",\") in this line of code" );
+// Different output channels
+stdout.writeln( "This goes to standard output, just like plain writeln() does");
+stderr.writeln( "This goes to standard error" );
+
+// Variables don't have to be explicitly typed as long as
+// the compiler can figure out the type that it will hold.
+var myVar = 10; // 10 is an int, so myVar is implicitly an int
+myVar = -10;
+var mySecondVar = myVar;
+// var anError; // this would be a compile-time error.
+
+// We can (and should) explicitly type things
+var myThirdVar: real;
+var myFourthVar: real = -1.234;
+myThirdVar = myFourthVar;
+
+// There are a number of basic types.
+var myInt: int = -1000; // Signed ints
+var myUint: uint = 1234; // Unsigned ints
+var myReal: real = 9.876; // Floating point numbers
+var myImag: imag = 5.0i; // Imaginary numbers
+var myCplx: complex = 10 + 9i; // Complex numbers
+myCplx = myInt + myImag ; // Another way to form complex numbers
+var myBool: bool = false; // Booleans
+var myStr: string = "Some string..."; // Strings
+
+// Some types can have sizes
+var my8Int: int(8) = 10; // 8 bit (one byte) sized int;
+var my64Real: real(64) = 1.516; // 64 bit (8 bytes) sized real
+
+// Typecasting
+var intFromReal = myReal : int;
+var intFromReal2: int = myReal : int;
+
+// consts are constants, they cannot be changed after set in runtime.
+const almostPi: real = 22.0/7.0;
+
+// params are constants whose value must be known statically at compile-time
+// Their value cannot be changed.
+param compileTimeConst: int = 16;
+
+// The config modifier allows values to be set at the command line
+// and is much easier than the usual getOpts debacle
+// config vars and consts can be changed through the command line at run time
+config var varCmdLineArg: int = -123;
+config const constCmdLineArg: int = 777;
+// Set with --VarName=Value or --VarName Value at run time
+
+// config params can be set/changed at compile-time
+config param paramCmdLineArg: bool = false;
+// Set config with --set paramCmdLineArg=value at compile-time
+writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg );
+
+// refs operate much like a reference in C++
+var actual = 10;
+ref refToActual = actual; // refToActual refers to actual
+writeln( actual, " == ", refToActual ); // prints the same value
+actual = -123; // modify actual (which refToActual refers to)
+writeln( actual, " == ", refToActual ); // prints the same value
+refToActual = 99999999; // modify what refToActual refers to (which is actual)
+writeln( actual, " == ", refToActual ); // prints the same value
+
+// Math operators
+var a: int, thisInt = 1234, thatInt = 5678;
+a = thisInt + thatInt; // Addition
+a = thisInt * thatInt; // Multiplication
+a = thisInt - thatInt; // Subtraction
+a = thisInt / thatInt; // Division
+a = thisInt ** thatInt; // Exponentiation
+a = thisInt % thatInt; // Remainder (modulo)
+
+// Logical Operators
+var b: bool, thisBool = false, thatBool = true;
+b = thisBool && thatBool; // Logical and
+b = thisBool || thatBool; // Logical or
+b = !thisBool; // Logical negation
+
+// Relational Operators
+b = thisInt > thatInt; // Greater-than
+b = thisInt >= thatInt; // Greater-than-or-equal-to
+b = thisInt < a && a <= thatInt; // Less-than, and, less-than-or-equal-to
+b = thisInt != thatInt; // Not-equal-to
+b = thisInt == thatInt; // Equal-to
+
+// Bitwise operations
+a = thisInt << 10; // Left-bit-shift by 10 bits;
+a = thatInt >> 5; // Right-bit-shift by 5 bits;
+a = ~thisInt; // Bitwise-negation
+a = thisInt ^ thatInt; // Bitwise exclusive-or
+
+// Compound assignment operations
+a += thisInt; // Addition-equals ( a = a + thisInt;)
+a *= thatInt; // Times-equals ( a = a * thatInt; )
+b &&= thatBool; // Logical-and-equals ( b = b && thatBool; )
+a <<= 3; // Left-bit-shift-equals ( a = a << 10; )
+// and many, many more.
+// Unlike other C family languages there are no
+// pre/post-increment/decrement operators like
+// ++j, --j, j++, j--
+
+// Swap operator
+var old_this = thisInt;
+var old_that = thatInt;
+thisInt <=> thatInt; // Swap the values of thisInt and thatInt
+writeln( (old_this == thatInt) && (old_that == thisInt) );
+
+// Operator overloads can also be defined, as we'll see with procedures
+
+// Tuples can be of the same type
+var sameTup: 2*int = (10,-1);
+var sameTup2 = (11, -6);
+// or different types
+var diffTup: (int,real,complex) = (5, 1.928, myCplx);
+var diffTupe2 = ( 7, 5.64, 6.0+1.5i );
+
+// Accessed using array bracket notation
+// However, tuples are all 1-indexed
+writeln( "(", sameTup[1], ",", sameTup[2], ")" );
+writeln( diffTup );
+
+// Tuples can also be written into.
+diffTup[1] = -1;
+
+// Can expand tuple values into their own variables
+var (tupInt, tupReal, tupCplx) = diffTup;
+writeln( diffTup == (tupInt, tupReal, tupCplx) );
+
+// Useful for writing a list of variables ( as is common in debugging)
+writeln( (a,b,thisInt,thatInt,thisBool,thatBool) );
+
+// Type aliasing
+type chroma = int; // Type of a single hue
+type RGBColor = 3*chroma; // Type representing a full color
+var black: RGBColor = ( 0,0,0 );
+var white: RGBColor = ( 255, 255, 255 );
+
+// If-then-else works just like any other C-family language
+if 10 < 100 then
+ writeln( "All is well" );
+
+if -1 < 1 then
+ writeln( "Continuing to believe reality" );
+else
+ writeln( "Send mathematician, something's wrong" );
+
+if ( 10 > 100 ) {
+ writeln( "Universe broken. Please reboot universe." );
+}
+
+if ( a % 2 == 0 ) {
+ writeln( a, " is even." );
+} else {
+ writeln( a, " is odd." );
+}
+
+if ( a % 3 == 0 ) {
+ writeln( a, " is even divisible by 3." );
+} else if ( a % 3 == 1 ){
+ writeln( a, " is divided by 3 with a remainder of 1." );
+} else {
+ writeln( b, " is divided by 3 with a remainder of 2." );
+}
+
+// Ternary: if-then-else in a statement
+var maximum = if ( thisInt < thatInt ) then thatInt else thisInt;
+
+// Select statements are much like switch statements in other languages
+// However, Select statements don't cascade like in C or Java
+var inputOption = "anOption";
+select( inputOption ){
+ when "anOption" do writeln( "Chose 'anOption'" );
+ when "otherOption" {
+ writeln( "Chose 'otherOption'" );
+ writeln( "Which has a body" );
+ }
+ otherwise {
+ writeln( "Any other Input" );
+ writeln( "the otherwise case doesn't need a do if the body is one line" );
+ }
+}
+
+// While and Do-While loops are basically the same in every language.
+var j: int = 1;
+var jSum: int = 0;
+while( j <= 1000 ){
+ jSum += j;
+ j += 1;
+}
+writeln( jSum );
+
+// Do-While loop
+do{
+ jSum += j;
+ j += 1;
+}while( j <= 10000 );
+writeln( jSum );
+
+// For loops are much like those in python in that they iterate over a range.
+// Ranges themselves are types, and can be stuffed into variables
+// (more about that later)
+for i in 1..10 do write( i , ", ") ;
+writeln( );
+
+var iSum: int = 0;
+for i in 1..1000 {
+ iSum += i;
+}
+writeln( iSum );
+
+for x in 1..10 {
+ for y in 1..10 {
+ write( (x,y), "\t" );
+ }
+ writeln( );
+}
+
+// Ranges and Domains
+// For-loops and arrays both use ranges and domains to
+// define an index set that can be iterated over.
+// Ranges are single dimensional
+// Domains can be multi-dimensional and can
+// represent indices of different types as well.
+// They are first-class citizen types, and can be assigned into variables
+var range1to10: range = 1..10; // 1, 2, 3, ..., 10
+var range2to11 = 2..11; // 2, 3, 4, ..., 11
+var rangeThistoThat: range = thisInt..thatInt; // using variables
+var rangeEmpty: range = 100..-100 ; // this is valid but contains no indices
+
+// Ranges can be unbounded
+var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ;
+// 1, 2, 3, 4, 5, ...
+// Note: the range(boundedType= ... ) is only
+// necessary if we explicitly type the variable
+
+var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1
+
+// Ranges can be strided using the 'by' operator.
+var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10
+// Note: the range(stridable=true) is only
+// necessary if we explicitly type the variable
+
+// Use by to create a reverse range
+var reverse2to10by2 = 10..2 by -2; // 10, 8, 6, 4, 2
+
+// The end point of a range can be determined using the count (#) operator
+var rangeCount: range = -5..#12; // range from -5 to 6
+
+// Can mix operators
+var rangeCountBy: range(stridable=true) = -5..#12 by 2; // -5, -3, -1, 1, 3, 5
+writeln( rangeCountBy );
+
+// Can query properties of the range
+// Print the first index, last index, number of indices,
+// stride, and ask if 2 is include in the range
+writeln( ( rangeCountBy.first, rangeCountBy.last, rangeCountBy.length,
+ rangeCountBy.stride, rangeCountBy.member( 2 ) ) );
+
+for i in rangeCountBy{
+ write( i, if i == rangeCountBy.last then "\n" else ", " );
+}
+
+// Rectangular domains are defined using the same range syntax
+// However they are required to be bounded (unlike ranges)
+var domain1to10: domain(1) = {1..10}; // 1D domain from 1..10;
+var twoDimensions: domain(2) = {-2..2,0..2}; // 2D domain over product of ranges
+var thirdDim: range = 1..16;
+var threeDims: domain(3) = {thirdDim, 1..10, 5..10}; // using a range variable
+
+// Can iterate over the indices as tuples
+for idx in twoDimensions do
+ write( idx , ", ");
+writeln( );
+
+// or can deconstruct the tuple
+for (x,y) in twoDimensions {
+ write( "(", x, ", ", y, ")", ", " );
+}
+writeln( );
+
+// Associative domains act like sets
+var stringSet: domain(string); // empty set of strings
+stringSet += "a";
+stringSet += "b";
+stringSet += "c";
+stringSet += "a"; // Redundant add "a"
+stringSet -= "c"; // Remove "c"
+writeln( stringSet );
+
+// Both ranges and domains can be sliced to produce a range or domain with the
+// intersection of indices
+var rangeA = 1.. ; // range from 1 to infinity
+var rangeB = ..5; // range from negative infinity to 5
+var rangeC = rangeA[rangeB]; // resulting range is 1..5
+writeln( (rangeA, rangeB, rangeC ) );
+
+var domainA = {1..10, 5..20};
+var domainB = {-5..5, 1..10};
+var domainC = domainA[domainB];
+writeln( (domainA, domainB, domainC) );
+
+// Array are similar to those of other languages.
+// Their sizes are defined using domains that represent their indices
+var intArray: [1..10] int;
+var intArray2: [{1..10}] int; //equivalent
+
+// Accessed using bracket notation
+for i in 1..10 do
+ intArray[i] = -i;
+writeln( intArray );
+// We cannot access intArray[0] because it exists outside
+// of the index set, {1..10}, we defined it to have.
+// intArray[11] is illegal for the same reason.
+
+var realDomain: domain(2) = {1..5,1..7};
+var realArray: [realDomain] real;
+var realArray2: [1..5,1..7] real; // Equivalent
+var realArray3: [{1..5,1..7}] real; // Equivalent
+
+for i in 1..5 {
+ for j in realDomain.dim(2) { // Only use the 2nd dimension of the domain
+ realArray[i,j] = -1.61803 * i + 0.5 * j; // Access using index list
+ var idx: 2*int = (i,j); // Note: 'index' is a keyword
+ realArray[idx] = - realArray[(i,j)]; // Index using tuples
+ }
+}
+
+// Arrays have domains as members that we can iterate over
+for idx in realArray.domain { // Again, idx is a 2*int tuple
+ realArray[idx] = 1 / realArray[idx[1],idx[2]]; // Access by tuple and list
+}
+
+writeln( realArray );
+
+// Can also iterate over the values of an array
+var rSum: real = 0;
+for value in realArray {
+ rSum += value; // Read a value
+ value = rSum; // Write a value
+}
+writeln( rSum, "\n", realArray );
+
+// Using associative domains we can create associative arrays (dictionaries)
+var dictDomain: domain(string) = { "one", "two" };
+var dict: [dictDomain] int = [ "one" => 1, "two" => 2 ];
+dict["three"] = 3;
+for key in dictDomain do writeln( dict[key] );
+
+// Arrays can be assigned to each other in different ways
+var thisArray : [{0..5}] int = [0,1,2,3,4,5];
+var thatArray : [{0..5}] int;
+
+// Simply assign one to the other.
+// This copies thisArray into thatArray, instead of just creating a reference.
+// Modifying thisArray does not also modify thatArray.
+thatArray = thisArray;
+thatArray[1] = -1;
+writeln( (thisArray, thatArray) );
+
+// Assign a slice one array to a slice (of the same size) of the other.
+thatArray[{4..5}] = thisArray[{1..2}];
+writeln( (thisArray, thatArray) );
+
+// Operation can also be promoted to work on arrays.
+var thisPlusThat = thisArray + thatArray;
+writeln( thisPlusThat );
+
+// Arrays and loops can also be expressions, where loop
+// body's expression is the result of each iteration.
+var arrayFromLoop = for i in 1..10 do i;
+writeln( arrayFromLoop );
+
+// An expression can result in nothing,
+// such as when filtering with an if-expression
+var evensOrFives = for i in 1..10 do if (i % 2 == 0 || i % 5 == 0) then i;
+
+writeln( arrayFromLoop );
+
+// Or could be written with a bracket notation
+// Note: this syntax uses the 'forall' parallel concept discussed later.
+var evensOrFivesAgain = [ i in 1..10 ] if (i % 2 == 0 || i % 5 == 0) then i;
+
+// Or over the values of the array
+arrayFromLoop = [ value in arrayFromLoop ] value + 1;
+
+// Note: this notation can get somewhat tricky. For example:
+// evensOrFives = [ i in 1..10 ] if (i % 2 == 0 || i % 5 == 0) then i;
+// would break.
+// The reasons for this are explained in depth when discussing zipped iterators.
+
+// Chapel procedures have similar syntax to other languages functions.
+proc fibonacci( n : int ) : int {
+ if ( n <= 1 ) then return n;
+ return fibonacci( n-1 ) + fibonacci( n-2 );
+}
+
+// Input parameters can be untyped (a generic procedure)
+proc doublePrint( thing ): void {
+ write( thing, " ", thing, "\n");
+}
+
+// Return type can be inferred (as long as the compiler can figure it out)
+proc addThree( n ) {
+ return n + 3;
+}
+
+doublePrint( addThree( fibonacci( 20 ) ) );
+
+// Can also take 'unlimited' number of parameters
+proc maxOf( x ...?k ) {
+ // x refers to a tuple of one type, with k elements
+ var maximum = x[1];
+ for i in 2..k do maximum = if (maximum < x[i]) then x[i] else maximum;
+ return maximum;
+}
+writeln( maxOf( 1, -10, 189, -9071982, 5, 17, 20001, 42 ) );
+
+// The ? operator is called the query operator, and is used to take
+// undetermined values (like tuple or array sizes, and generic types).
+
+// Taking arrays as parameters.
+// The query operator is used to determine the domain of A.
+// This is important to define the return type (if you wanted to)
+proc invertArray( A: [?D] int ): [D] int{
+ for a in A do a = -a;
+ return A;
+}
+
+writeln( invertArray( intArray ) );
+
+// Procedures can have default parameter values, and
+// the parameters can be named in the call, even out of order
+proc defaultsProc( x: int, y: real = 1.2634 ): (int,real){
+ return (x,y);
+}
+
+writeln( defaultsProc( 10 ) );
+writeln( defaultsProc( x=11 ) );
+writeln( defaultsProc( x=12, y=5.432 ) );
+writeln( defaultsProc( y=9.876, x=13 ) );
+
+// Intent modifiers on the arguments convey how
+// those arguments are passed to the procedure
+// in: copy arg in, but not out
+// out: copy arg out, but not in
+// inout: copy arg in, copy arg out
+// ref: pass arg by reference
+proc intentsProc( in inarg, out outarg, inout inoutarg, ref refarg ){
+ writeln( "Inside Before: ", (inarg, outarg, inoutarg, refarg) );
+ inarg = inarg + 100;
+ outarg = outarg + 100;
+ inoutarg = inoutarg + 100;
+ refarg = refarg + 100;
+ writeln( "Inside After: ", (inarg, outarg, inoutarg, refarg) );
+}
+
+var inVar: int = 1;
+var outVar: int = 2;
+var inoutVar: int = 3;
+var refVar: int = 4;
+writeln( "Outside Before: ", (inVar, outVar, inoutVar, refVar) );
+intentsProc( inVar, outVar, inoutVar, refVar );
+writeln( "Outside After: ", (inVar, outVar, inoutVar, refVar) );
+
+// Similarly we can define intents on the return type
+// refElement returns a reference to an element of array
+proc refElement( array : [?D] ?T, idx ) ref : T {
+ return array[ idx ]; // returns a reference to
+}
+
+var myChangingArray : [1..5] int = [1,2,3,4,5];
+writeln( myChangingArray );
+// Store reference to element in ref variable
+ref refToElem = refElement( myChangingArray, 5 );
+writeln( refToElem );
+refToElem = -2; // modify reference which modifies actual value in array
+writeln( refToElem );
+writeln( myChangingArray );
+// This makes more practical sense for class methods where references to
+// elements in a data-structure are returned via a method or iterator
+
+// We can query the type of arguments to generic procedures
+// Here we define a procedure that takes two arguments of
+// the same type, yet we don't define what that type is.
+proc genericProc( arg1 : ?valueType, arg2 : valueType ): void {
+ select( valueType ){
+ when int do writeln( arg1, " and ", arg2, " are ints" );
+ when real do writeln( arg1, " and ", arg2, " are reals" );
+ otherwise writeln( arg1, " and ", arg2, " are somethings!" );
+ }
+}
+
+genericProc( 1, 2 );
+genericProc( 1.2, 2.3 );
+genericProc( 1.0+2.0i, 3.0+4.0i );
+
+// We can also enforce a form of polymorphism with the 'where' clause
+// This allows the compiler to decide which function to use.
+// Note: that means that all information needs to be known at compile-time.
+// The param modifier on the arg is used to enforce this constraint.
+proc whereProc( param N : int ): void
+ where ( N > 0 ) {
+ writeln( "N is greater than 0" );
+}
+
+proc whereProc( param N : int ): void
+ where ( N < 0 ) {
+ writeln( "N is less than 0" );
+}
+
+whereProc( 10 );
+whereProc( -1 );
+// whereProc( 0 ) would result in a compiler error because there
+// are no functions that satisfy the where clause's condition.
+// We could have defined a whereProc without a where clause that would then have
+// served as a catch all for all the other cases (of which there is only one).
+
+// Operator definitions are through procedures as well.
+// We can define the unary operators:
+// + - ! ~
+// and the binary operators:
+// + - * / % ** == <= >= < > << >> & | ˆ by
+// += -= *= /= %= **= &= |= ˆ= <<= >>= <=>
+
+// Boolean exclusive or operator
+proc ^( left : bool, right : bool ): bool {
+ return (left || right) && !( left && right );
+}
+
+writeln( true ^ true );
+writeln( false ^ true );
+writeln( true ^ false );
+writeln( false ^ false );
+
+// Define a * operator on any two types that returns a tuple of those types
+proc *( left : ?ltype, right : ?rtype): ( ltype, rtype ){
+ return (left, right );
+}
+
+writeln( 1 * "a" ); // Uses our * operator
+writeln( 1 * 2 ); // Uses the default * operator
+
+/*
+Note: You could break everything if you get careless with your overloads.
+This here will break everything. Don't do it.
+proc +( left: int, right: int ): int{
+ return left - right;
+}
+*/
+
+// Iterators are a sisters to the procedure, and almost
+// everything about procedures also applies to iterators
+// However, instead of returning a single value,
+// iterators yield many values to a loop.
+// This is useful when a complicated set or order of iterations is needed but
+// allows the code defining the iterations to be separate from the loop body.
+iter oddsThenEvens( N: int ): int {
+ for i in 1..N by 2 do
+ yield i; // yield values instead of returning.
+ for i in 2..N by 2 do
+ yield i;
+}
+
+for i in oddsThenEvens( 10 ) do write( i, ", " );
+writeln( );
+
+// Iterators can also yield conditionally, the result of which can be nothing
+iter absolutelyNothing( N ): int {
+ for i in 1..N {
+ if ( N < i ) { // Always false
+ yield i; // Yield statement never happens
+ }
+ }
+}
+
+for i in absolutelyNothing( 10 ){
+ writeln( "Woa there! absolutelyNothing yielded ", i );
+}
+
+// We can zipper together two or more iterators (who have the same number
+// of iterations) using zip() to create a single zipped iterator, where each
+// iteration of the zipped iterator yields a tuple of one value yielded
+// from each iterator.
+ // Ranges have implicit iterators
+for (positive, negative) in zip( 1..5, -5..-1) do
+ writeln( (positive, negative) );
+
+// Zipper iteration is quite important in the assignment of arrays,
+// slices of arrays, and array/loop expressions.
+var fromThatArray : [1..#5] int = [1,2,3,4,5];
+var toThisArray : [100..#5] int;
+
+// The operation
+toThisArray = fromThatArray;
+// is produced through
+for (i,j) in zip( toThisArray.domain, fromThatArray.domain) {
+ toThisArray[ i ] = fromThatArray[ j ];
+}
+
+toThisArray = [ j in -100..#5 ] j;
+writeln( toThisArray );
+// is produced through
+for (i, j) in zip( toThisArray.domain, -100..#5 ){
+ toThisArray[i] = j;
+}
+writeln( toThisArray );
+
+// This is all very important in undestanding why the statement
+// var iterArray : [1..10] int = [ i in 1..10 ] if ( i % 2 == 1 ) then j;
+// exhibits a runtime error.
+// Even though the domain of the array and the loop-expression are
+// the same size, the body of the expression can be though of as an iterator.
+// Because iterators can yield nothing, that iterator yields a different number
+// of things than the domain of the array or loop, which is not allowed.
+
+// Classes are similar to those in C++ and Java.
+// They currently lack privatization
+class MyClass {
+ // Member variables
+ var memberInt : int;
+ var memberBool : bool = true;
+
+ // Classes have default constructors that don't need to be coded (see below)
+ // Our explicitly defined constructor
+ proc MyClass( val : real ){
+ this.memberInt = ceil( val ): int;
+ }
+
+ // Our explicitly defined destructor
+ proc ~MyClass( ){
+ writeln( "MyClass Destructor called ", (this.memberInt, this.memberBool) );
+ }
+
+ // Class methods
+ proc setMemberInt( val: int ){
+ this.memberInt = val;
+ }
+
+ proc setMemberBool( val: bool ){
+ this.memberBool = val;
+ }
+
+ proc getMemberInt( ): int{
+ return this.memberInt;
+ }
+
+ proc getMemberBool( ): bool {
+ return this.memberBool;
+ }
+
+}
+
+// Construct using default constructor, using default values
+var myObject = new MyClass( 10 );
+ myObject = new MyClass( memberInt = 10 ); // Equivalent
+writeln( myObject.getMemberInt( ) );
+// ... using our values
+var myDiffObject = new MyClass( -1, true );
+ myDiffObject = new MyClass( memberInt = -1,
+ memberBool = true ); // Equivalent
+writeln( myDiffObject );
+
+// Construct using written constructor
+var myOtherObject = new MyClass( 1.95 );
+ myOtherObject = new MyClass( val = 1.95 ); // Equivalent
+writeln( myOtherObject.getMemberInt( ) );
+
+// We can define an operator on our class as well but
+// the definition has to be outside the class definition
+proc +( A : MyClass, B : MyClass) : MyClass {
+ return new MyClass( memberInt = A.getMemberInt( ) + B.getMemberInt( ),
+ memberBool = A.getMemberBool( ) || B.getMemberBool( ) );
+}
+
+var plusObject = myObject + myDiffObject;
+writeln( plusObject );
+
+// Destruction
+delete myObject;
+delete myDiffObject;
+delete myOtherObject;
+delete plusObject;
+
+// Classes can inherit from one or more parent classes
+class MyChildClass : MyClass {
+ var memberComplex: complex;
+}
+
+// Generic Classes
+class GenericClass {
+ type classType;
+ var classDomain: domain(1);
+ var classArray: [classDomain] classType;
+
+ // Explicit constructor
+ proc GenericClass( type classType, elements : int ){
+ this.classDomain = {1..#elements};
+ }
+
+ // Copy constructor
+ // Note: We still have to put the type as an argument, but we can
+ // default to the type of the other object using the query (?) operator
+ // Further, we can take advantage of this to allow our copy constructor
+ // to copy classes of different types and cast on the fly
+ proc GenericClass( other : GenericClass(?otherType),
+ type classType = otherType ) {
+ this.classDomain = other.classDomain;
+ // Copy and cast
+ for idx in this.classDomain do this[ idx ] = other[ idx ] : classType;
+ }
+
+ // Define bracket notation on a GenericClass
+ // object so it can behave like a normal array
+ // i.e. objVar[ i ] or objVar( i )
+ proc this( i : int ) ref : classType {
+ return this.classArray[ i ];
+ }
+
+ // Define an implicit iterator for the class
+ // to yield values from the array to a loop
+ // i.e. for i in objVar do ....
+ iter these( ) ref : classType {
+ for i in this.classDomain do
+ yield this[i];
+ }
+
+}
+
+var realList = new GenericClass( real, 10 );
+// We can assign to the member array of the object using the bracket
+// notation that we defined ( proc this( i: int ){ ... } )
+for i in realList.classDomain do realList[i] = i + 1.0;
+// We can iterate over the values in our list with the iterator
+// we defined ( iter these( ){ ... } )
+for value in realList do write( value, ", " );
+writeln( );
+
+// Make a copy of realList using the copy constructor
+var copyList = new GenericClass( realList );
+for value in copyList do write( value, ", " );
+writeln( );
+
+// Make a copy of realList and change the type, also using the copy constructor
+var copyNewTypeList = new GenericClass( realList, int );
+for value in copyNewTypeList do write( value, ", " );
+writeln( );
+
+// Modules are Chapel's way of managing name spaces.
+// The files containing these modules do not need to be named after the modules
+// (as in Java), but files implicitly name modules.
+// In this case, this file implicitly names the 'learnchapel' module
+
+module OurModule {
+ // We can use modules inside of other modules.
+ use Time; // Time is one of the standard modules.
+
+ // We'll use this procedure in the parallelism section.
+ proc countdown( seconds: int ){
+ for i in 1..seconds by -1 {
+ writeln( i );
+ sleep( 1 );
+ }
+ }
+
+ // Submodules of OurModule
+ // It is possible to create arbitrarily deep module nests.
+ module ChildModule {
+ proc foo(){
+ writeln( "ChildModule.foo()");
+ }
+ }
+
+ module SiblingModule {
+ proc foo(){
+ writeln( "SiblingModule.foo()" );
+ }
+ }
+} // end OurModule
+
+// Using OurModule also uses all the modules it uses.
+// Since OurModule uses Time, we also use time.
+use OurModule;
+
+// At this point we have not used ChildModule or SiblingModule so their symbols
+// (i.e. foo ) are not available to us.
+// However, the module names are, and we can explicitly call foo() through them.
+SiblingModule.foo(); // Calls SiblingModule.foo()
+
+// Super explicit naming.
+OurModule.ChildModule.foo(); // Calls ChildModule.foo()
+
+use ChildModule;
+foo(); // Less explicit call on ChildModule.foo()
+
+// We can declare a main procedure
+// Note: all the code above main still gets executed.
+proc main(){
+
+ // Parallelism
+ // In other languages, parallelism is typically done with
+ // complicated libraries and strange class structure hierarchies.
+ // Chapel has it baked right into the language.
+
+ // A begin statement will spin the body of that statement off
+ // into one new task.
+ // A sync statement will ensure that the progress of the main
+ // task will not progress until the children have synced back up.
+ sync {
+ begin { // Start of new task's body
+ var a = 0;
+ for i in 1..1000 do a += 1;
+ writeln( "Done: ", a);
+ } // End of new tasks body
+ writeln( "spun off a task!");
+ }
+ writeln( "Back together" );
+
+ proc printFibb( n: int ){
+ writeln( "fibonacci(",n,") = ", fibonacci( n ) );
+ }
+
+ // A cobegin statement will spin each statement of the body into one new task
+ cobegin {
+ printFibb( 20 ); // new task
+ printFibb( 10 ); // new task
+ printFibb( 5 ); // new task
+ {
+ // This is a nested statement body and thus is a single statement
+ // to the parent statement and is executed by a single task
+ writeln( "this gets" );
+ writeln( "executed as" );
+ writeln( "a whole" );
+ }
+ }
+ // Notice here that the prints from each statement may happen in any order.
+
+ // Coforall loop will create a new task for EACH iteration
+ var num_tasks = 10; // Number of tasks we want
+ coforall taskID in 1..#num_tasks {
+ writeln( "Hello from task# ", taskID );
+ }
+ // Again we see that prints happen in any order.
+ // NOTE! coforall should be used only for creating tasks!
+ // Using it to iterating over a structure is very a bad idea!
+
+ // forall loops are another parallel loop, but only create a smaller number
+ // of tasks, specifically --dataParTasksPerLocale=number of task
+ forall i in 1..100 {
+ write( i, ", ");
+ }
+ writeln( );
+ // Here we see that there are sections that are in order, followed by
+ // a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, ).
+ // This is because each task is taking on a chunk of the range 1..10
+ // (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens
+ // in parallel.
+ // Your results may depend on your machine and configuration
+
+ // For both the forall and coforall loops, the execution of the
+ // parent task will not continue until all the children sync up.
+
+ // forall loops are particularly useful for parallel iteration over arrays.
+ // Lets run an experiment to see how much faster a parallel loop is
+ use Time; // Import the Time module to use Timer objects
+ var timer: Timer;
+ var myBigArray: [{1..4000,1..4000}] real; // Large array we will write into
+
+ // Serial Experiment
+ timer.start( ); // Start timer
+ for (x,y) in myBigArray.domain { // Serial iteration
+ myBigArray[x,y] = (x:real) / (y:real);
+ }
+ timer.stop( ); // Stop timer
+ writeln( "Serial: ", timer.elapsed( ) ); // Print elapsed time
+ timer.clear( ); // Clear timer for parallel loop
+
+ // Parallel Experiment
+ timer.start( ); // start timer
+ forall (x,y) in myBigArray.domain { // Parallel iteration
+ myBigArray[x,y] = (x:real) / (y:real);
+ }
+ timer.stop( ); // Stop timer
+ writeln( "Parallel: ", timer.elapsed( ) ); // Print elapsed time
+ timer.clear( );
+ // You may have noticed that (depending on how many cores you have)
+ // that the parallel loop went faster than the serial loop
+
+ // The bracket style loop-expression described
+ // much earlier implicitly uses a forall loop.
+ [ val in myBigArray ] val = 1 / val; // Parallel operation
+
+ // Atomic variables, common to many languages, are ones whose operations
+ // occur uninterupted. Multiple threads can both modify atomic variables
+ // and can know that their values are safe.
+ // Chapel atomic variables can be of type bool, int, uint, and real.
+ var uranium: atomic int;
+ uranium.write( 238 ); // atomically write a variable
+ writeln( uranium.read() ); // atomically read a variable
+
+ // operations are described as functions, you could define your own operators.
+ uranium.sub( 3 ); // atomically subtract a variable
+ writeln( uranium.read() );
+
+ var replaceWith = 239;
+ var was = uranium.exchange( replaceWith );
+ writeln( "uranium was ", was, " but is now ", replaceWith );
+
+ var isEqualTo = 235;
+ if ( uranium.compareExchange( isEqualTo, replaceWith ) ) {
+ writeln( "uranium was equal to ", isEqualTo,
+ " so replaced value with ", replaceWith );
+ } else {
+ writeln( "uranium was not equal to ", isEqualTo,
+ " so value stays the same... whatever it was" );
+ }
+
+ sync {
+ begin { // Reader task
+ writeln( "Reader: waiting for uranium to be ", isEqualTo );
+ uranium.waitFor( isEqualTo );
+ writeln( "Reader: uranium was set (by someone) to ", isEqualTo );
+ }
+
+ begin { // Writer task
+ writeln( "Writer: will set uranium to the value ", isEqualTo, " in..." );
+ countdown( 3 );
+ uranium.write( isEqualTo );
+ }
+ }
+
+ // sync vars have two states: empty and full.
+ // If you read an empty variable or write a full variable, you are waited
+ // until the variable is full or empty again
+ var someSyncVar$: sync int; // varName$ is a convention not a law.
+ sync {
+ begin { // Reader task
+ writeln( "Reader: waiting to read." );
+ var read_sync = someSyncVar$;
+ writeln( "value is ", read_sync );
+ }
+
+ begin { // Writer task
+ writeln( "Writer: will write in..." );
+ countdown( 3 );
+ someSyncVar$ = 123;
+ }
+ }
+
+ // single vars can only be written once. A read on an unwritten single results
+ // in a wait, but when the variable has a value it can be read indefinitely
+ var someSingleVar$: single int; // varName$ is a convention not a law.
+ sync {
+ begin { // Reader task
+ writeln( "Reader: waiting to read." );
+ for i in 1..5 {
+ var read_single = someSingleVar$;
+ writeln( "Reader: iteration ", i,", and the value is ", read_single );
+ }
+ }
+
+ begin { // Writer task
+ writeln( "Writer: will write in..." );
+ countdown( 3 );
+ someSingleVar$ = 5; // first and only write ever.
+ }
+ }
+
+ // Heres an example of using atomics and a synch variable to create a
+ // count-down mutex (also known as a multiplexer)
+ var count: atomic int; // our counter
+ var lock$: sync bool; // the mutex lock
+
+ count.write( 2 ); // Only let two tasks in at a time.
+ lock$.writeXF( true ); // Set lock$ to full (unlocked)
+ // Note: The value doesnt actually matter, just the state
+ // (full:unlocked / empty:locked)
+ // Also, writeXF() fills (F) the sync var regardless of its state (X)
+
+ coforall task in 1..#5 { // Generate tasks
+ // Create a barrier
+ do{
+ lock$; // Read lock$ (wait)
+ }while ( count.read() < 1 ); // Keep waiting until a spot opens up
+
+ count.sub(1); // decrement the counter
+ lock$.writeXF( true ); // Set lock$ to full (signal)
+
+ // Actual 'work'
+ writeln( "Task #", task, " doing work." );
+ sleep( 2 );
+
+ count.add( 1 ); // Increment the counter
+ lock$.writeXF( true ); // Set lock$ to full (signal)
+ }
+
+ // we can define the operations + * & | ^ && || min max minloc maxloc
+ // over an entire array using scans and reductions
+ // Reductions apply the operation over the entire array and
+ // result in a single value
+ var listOfValues: [1..10] int = [15,57,354,36,45,15,456,8,678,2];
+ var sumOfValues = + reduce listOfValues;
+ var maxValue = max reduce listOfValues; // 'max' give just max value
+
+ // 'maxloc' gives max value and index of the max value
+ // Note: We have to zip the array and domain together with the zip iterator
+ var (theMaxValue, idxOfMax) = maxloc reduce zip(listOfValues,
+ listOfValues.domain);
+
+ writeln( (sumOfValues, maxValue, idxOfMax, listOfValues[ idxOfMax ] ) );
+
+ // Scans apply the operation incrementally and return an array of the
+ // value of the operation at that index as it progressed through the
+ // array from array.domain.low to array.domain.high
+ var runningSumOfValues = + scan listOfValues;
+ var maxScan = max scan listOfValues;
+ writeln( runningSumOfValues );
+ writeln( maxScan );
+} // end main()
+```
+
+Who is this tutorial for?
+-------------------------
+
+This tutorial is for people who want to learn the ropes of chapel without having to hear about what fiber mixture the ropes are, or how they were braided, or how the braid configurations differ between one another.
+It won't teach you how to develop amazingly performant code, and it's not exhaustive.
+Refer to the [language specification](http://chapel.cray.com/language.html) and the [module documentation](http://chapel.cray.com/docs/latest/) for more details.
+
+Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to see if more topics have been added or more tutorials created.
+
+### What this tutorial is lacking:
+
+ * Exposition of the standard modules
+ * Multiple Locales (distributed memory system)
+ * Records
+ * Parallel iterators
+
+Your input, questions, and discoveries are important to the developers!
+-----------------------------------------------------------------------
+
+The Chapel language is still in-development (version 1.11.0), so there are occasional hiccups with performance and language features.
+The more information you give the Chapel development team about issues you encounter or features you would like to see, the better the language becomes.
+Feel free to email the team and other developers through the [sourceforge email lists](https://sourceforge.net/p/chapel/mailman).
+
+If you're really interested in the development of the compiler or contributing to the project,
+[check out the master Github repository](https://github.com/chapel-lang/chapel).
+It is under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0).
+
+Installing the Compiler
+-----------------------
+
+Chapel can be built and installed on your average 'nix machine (and cygwin).
+[Download the latest release version](https://github.com/chapel-lang/chapel/releases/)
+and its as easy as
+
+ 1. `tar -xvf chapel-1.11.0.tar.gz`
+ 2. `cd chapel-1.11.0`
+ 3. `make`
+ 4. `source util/setchplenv.bash # or .sh or .csh or .fish`
+
+You will need to `source util/setchplenv.EXT` from within the Chapel directory (`$CHPL_HOME`) every time your terminal starts so its suggested that you drop that command in a script that will get executed on startup (like .bashrc).
+
+Chapel is easily installed with Brew for OS X
+
+ 1. `brew update`
+ 2. `brew install chapel`
+
+Compiling Code
+--------------
+
+Builds like other compilers:
+
+`chpl myFile.chpl -o myExe`
+
+Notable arguments:
+
+ * `--fast`: enables a number of optimizations and disables array bounds checks. Should only enable when application is stable.
+ * `--set <Symbol Name>=<Value>`: set config param `<Symbol Name>` to `<Value>` at compile-time.
+ * `--main-module <Module Name>`: use the main() procedure found in the module `<Module Name>` as the executable's main.
+ * `--module-dir <Directory>`: includes `<Directory>` in the module search path. \ No newline at end of file
diff --git a/de-de/json-de.html.markdown b/de-de/json-de.html.markdown
new file mode 100644
index 00000000..3cf4578c
--- /dev/null
+++ b/de-de/json-de.html.markdown
@@ -0,0 +1,65 @@
+---
+language: json
+filename: learnjson-de.json
+contributors:
+ - ["Anna Harren", "https://github.com/iirelu"]
+ - ["Marco Scannadinari", "https://github.com/marcoms"]
+translators:
+ - ["Timm Albers", "https://github.com/nunull"]
+lang: de-de
+---
+
+Da JSON ein äußerst einfaches Format für den Austausch von Daten ist, wird dieses
+Dokument das vermutlich einfachste "Learn X in Y Minutes" werden.
+
+In seiner grundlegenden Form hat JSON keine eigentlichen Kommentare. Dennoch
+akzeptieren die meisten Parser Kommentare in C-Syntax (`//`, `/* */`). Dennoch
+soll für dieses Dokument nur 100% gültiges JSON verwendet werden, weshalbt keine
+Kommentare verwendet werden. Glücklicherweise ist das nachfolgende Dokument
+selbsterklärend.
+
+```json
+{
+ "schlüssel": "wert",
+
+ "alle schlüssel": "müssen durch doppelte Anführungszeichen begrenzt werden",
+ "zahlen": 0,
+ "zeichenketten": "Alle Unicode-Zeichen (inklusive \"escaping\") sind erlaubt.",
+ "boolesche werte": true,
+ "nullwert": null,
+
+ "große zahlen": 1.2e+100,
+
+ "objekte": {
+ "kommentar": "Die meisten Datenstrukturen in JSON kommen aus Objekten.",
+
+ "array": [0, 1, 2, "Arrays können Werte jeglichen Datentyps aufnehmen.", 4],
+
+ "weiteres objekt": {
+ "kommentar": "Objekte können verschachtelt werden."
+ }
+ },
+
+ "quatsch": [
+ {
+ "quellen von kalium": ["Bananen"]
+ },
+ [
+ [1, 0, 0, 0],
+ [0, 1, 0, 0],
+ [0, 0, 1, "Neo"],
+ [0, 0, 0, 1]
+ ]
+ ],
+
+ "alternative formatierung": {
+ "kommentar": "..."
+ , "die position": "des Kommas ist nicht relevant - so lange es vor dem Wert steht."
+ , "weiterer kommentar": "wie schön"
+ , "übrigens": "Auch die Einrückung ist nicht relevant."
+ , "jede": "beliebige Anzahl von Leerzeichen / Tabs ist erlaubt.", "wirklich?":true
+ },
+
+ "das war kurz": "Und, du bist fertig. Du weißt nun (fast) alles über JSON."
+}
+```
diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown
index 88318014..19ea9e87 100644
--- a/de-de/yaml-de.html.markdown
+++ b/de-de/yaml-de.html.markdown
@@ -1,10 +1,11 @@
---
language: yaml
-filename: learnyaml.yaml
contributors:
- ["Adam Brenecki", "https://github.com/adambrenecki"]
translators:
- - ["Ruben M.", https://github.com/switchhax]
+ - ["Ruben M.", "https://github.com/switchhax"]
+filename: learnyaml-de.yaml
+lang: de-de
---
YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann.
diff --git a/el-gr/racket-gr.html.markdown b/el-gr/racket-gr.html.markdown
new file mode 100644
index 00000000..4c4576bb
--- /dev/null
+++ b/el-gr/racket-gr.html.markdown
@@ -0,0 +1,745 @@
+---
+language: racket
+filename: learnracket-gr.rkt
+contributors:
+ - ["th3rac25", "https://github.com/voila"]
+ - ["Eli Barzilay", "https://github.com/elibarzilay"]
+ - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"]
+ - ["Duong H. Nguyen", "https://github.com/cmpitg"]
+ - ["Keyan Zhang", "https://github.com/keyanzhang"]
+translators:
+ - ["Vasilis Panagiotopoulos" , "https://github.com/billpcs/"]
+lang: el-gr
+---
+
+H Racket είναι μια γενικού σκοπού, πολυ-υποδειγματική γλώσσα προγραμματισμού που ανήκει
+στην οικογένεια της Lisp/Scheme
+
+```racket
+#lang racket ; ορίζει την γλώσσα που χρησιμοποιόυμε
+
+;;; Σχόλια
+
+;; Τα σχόλια μιας γραμμής ξεκινούν με ερωτηματικό
+
+#| Τα σχόλια ολόκληρου μπλόκ
+ μπορούν να εκτείνονται σε πολλές γραμμές και...
+ #|
+ μπορούν να είναι εμφωλευμένα!
+ |#
+|#
+
+;; Τα σχόλια S-expression (εκφράσεις S) comments απορρίπτουν την
+;; έκφραση που ακολουθεί, δυνατότητα που είναι χρήσιμη για να
+;; κάνουμε σχόλια κάποιες εκφράσεις κατα τη διάρκεια του debugging
+
+#; (αυτή η έκφραση δεν θα εκτελεστεί)
+
+;; (Αν δεν καταλαβαίνεται τι είναι οι εκφράσεις , περιμένετε... Θα το μάθουμε
+;; πολύ συντομα!)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 1. Πρωτογενείς τύποι μεταβλητών και τελεστές
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Αριθμοί
+9999999999999999999999 ; ακέραιοι
+#b111 ; δυαδικοί => 7
+#o111 ; οκταδικοί => 73
+#x111 ; δεκαεξαδικοί => 273
+3.14 ; πραγματικοί
+6.02e+23
+1/2 ; ρητοί
+1+2i ; μιγαδικοί
+
+;; Οι μορφή των συναρτήσεων είναι (f x y z)
+;; όπου το f είναι η συνάρτηση και τα x y z
+;; είναι οι όροι που η συνάρτηση δέχεται
+;; ως ορίσματα. Αν θέλουμε να δημιουργήσουμε
+;; μια λίστα στην κυριολεξία απο δίαφορα δεδομένα,
+;; χρησιμοποιούμε το ' για να το εμποδίσουμε απο το να
+;; αξιολογηθεί σαν έκφραση. Για παράδειγμα:
+'(+ 1 2) ; => Παραμένει (+ 1 2) και δεν γίνεται η πράξη
+;; Τώρα , ας κάνουμε μερικές πράξεις
+(+ 1 1) ; => 2
+(- 8 1) ; => 7
+(* 10 2) ; => 20
+(expt 2 3) ; => 8
+(quotient 5 2) ; => 2
+(remainder 5 2) ; => 1
+(/ 35 5) ; => 7
+(/ 1 3) ; => 1/3
+(exact->inexact 1/3) ; => 0.3333333333333333
+(+ 1+2i 2-3i) ; => 3-1i
+
+;;; Λογικές μεταβλητές
+#t ; για το true (αληθής)
+#f ; για το false (ψευδής)
+(not #t) ; => #f
+(and 0 #f (error "doesn't get here")) ; => #f
+(or #f 0 (error "doesn't get here")) ; => 0
+
+;;; Χαρακτήρες
+#\A ; => #\A
+#\λ ; => #\λ
+#\u03BB ; => #\λ
+
+;;; Τα αλφαριθμητικά είναι πίνακες χαρακτήρων συγκεκριμένου μήκους
+"Hello, world!"
+"Benjamin \"Bugsy\" Siegel" ; Το backslash είναι χαρακτήρας διαφυγής
+"Foo\tbar\41\x21\u0021\a\r\n" ; Συμπεριλαμβάνονται οι χαρακτήες διαφυγής της C,
+ ; σε Unicode
+"λx:(μα.α→α).xx" ; Μπορούν να υπάρχουν και Unicode χαρακτήρες
+
+;; Μπορούμε να εννώσουμε αλφαριθμητικά!
+(string-append "Hello " "world!") ; => "Hello world!"
+
+;; Ένα αλφαριθμητικό μπορούμε να το χρησιμοπιησουμε
+;; όπως και μια λίστα απο χαρακτήρες
+(string-ref "Apple" 0) ; => #\A ;; Παίρνουμε το πρώτο στοιχείο
+
+;; Η συνάρτηση format μπορεί να χρησιμοποιηθεί για
+;; να μορφοποιήσουμε αλφαριθμητικά
+(format "~a can be ~a" "strings" "formatted") ;; => "strings can be formatted"
+
+;; Η εκτύπωση είναι εύκολη.
+(printf "I'm Racket. Nice to meet you!\n")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 2. Μεταβλητές
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Μπορούμε να δημιουργήσουμε μεταβλητές
+;; χρησιμοποιώντας το define.
+;; Ένα όνομα μεταβλητής μπορεί να χρησιμοποιεί οποιονδήποτε
+;; χαρακτήρα, εκτός από τους: ()[]{}",'`;#|\
+(define some-var 5)
+some-var ; => 5
+
+;; Μπορούμε επίσης να χρησιμοποιήσουμε unicode χαρακτήρες.
+(define ⊆ subset?) ;; Εδώ ουστιαστικά δίνουμε στη ήδη ύπαρχουσα συνάρτηση subset?
+ ;; ένα νέο όνομα ⊆ , και παρακάτω την καλούμε με το νέο της όνομα.
+(⊆ (set 3 2) (set 1 2 3)) ; => #t
+
+;; Αν ζητήσουμε μια μεταβλητή που δεν έχει οριστεί πρίν π.χ
+(printf name)
+;; θα πάρουμε το παρακάτω μήνυμα
+;name: undefined;
+; cannot reference undefined identifier
+; context...:
+
+;; Η τοπική δέσμευση : `me' δευσμεύεται με το "Bob" μόνο μέσα στο (let ...)
+(let ([me "Bob"])
+ "Alice"
+ me) ; => "Bob"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Δομές και συλλογές
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Δομές
+(struct dog (name breed age))
+(define my-pet
+ (dog "lassie" "collie" 5))
+my-pet ; => #<dog>
+(dog? my-pet) ; => #t
+(dog-name my-pet) ; => "lassie"
+
+;;; Ζεύγη (αμετάβλητα)
+;; Η δεσμευμένη λέξη `cons' δημιουργεί ζεύγη,
+;; και το `car' και το `cdr' εξάγουν το πρώτο και
+;; το δεύτερο στοιχείο αντίστοιχα.
+(cons 1 2) ; => '(1 . 2)
+(car (cons 1 2)) ; => 1
+(cdr (cons 1 2)) ; => 2
+
+;;; Λίστες
+
+;; Οι λίστες είναι linked-list δομές δεδομένων,
+;; που έχουν δημιουργηθεί απο ζευγάρια 'cons'
+;; και τελειώνουν με 'null' (ή αλλιώς '()) για να
+;; δηλώσουν ότι αυτό είναι το τέλος της λίστας
+(cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3)
+;; Η δεσμευμένη λέξη 'list' είναι ένας εναλλακτικός
+;; (και σαφώς πιο βολικός) τρόπος για να δημιουργούμε
+;; λίστες
+(list 1 2 3) ; => '(1 2 3)
+;; αλλά και χρησιμοποιώντας ένα μονό εισαγωγικό το
+;; το αποτέλεσμα είναι και πάλι το ίδιο
+'(1 2 3) ; => '(1 2 3)
+
+;; Μπορούμε και πάλι όμως να χρησιμοποιούμε το 'cons' για να
+;; προσθέσουμε ένα στοιχείο στην αρχή της λίστας
+(cons 4 '(1 2 3)) ; => '(4 1 2 3)
+
+;; Μπορούμε να χρησιμοποιούμε το 'append' για να προσθέτουμε
+;; στοιχεία στο τέλος μιας λίστας. Το στοιχείο αυτό μπορεί
+;; και να είναι ολόκληρη λίστα!
+(append '(1 2) '(3 4)) ; => '(1 2 3 4)
+
+;; Οι λίστες στην Racket είναι πολύ βασικές , οπότε υπάρχουν πολλές
+;; δυνατές λειτουργίες για αυτές. Παρακάτω είναι μερικά παραδείγματα:
+(map add1 '(1 2 3)) ; => '(2 3 4)
+(map + '(1 2 3) '(10 20 30)) ; => '(11 22 33)
+(filter even? '(1 2 3 4)) ; => '(2 4)
+(count even? '(1 2 3 4)) ; => 2
+(take '(1 2 3 4) 2) ; => '(1 2)
+(drop '(1 2 3 4) 2) ; => '(3 4)
+
+;;; Διανύσματα
+
+;; Τα διανύσματα είναι πίνακες σταθερού μήκους
+#(1 2 3) ; => '#(1 2 3)
+
+;; Χρησιμοποιύμε το `vector-append' για να προσθέσουμε διανύσματα
+(vector-append #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6)
+
+;;; Σύνολα
+
+;; Δημιουργούμε ένα σύνολο απο μία λίστα
+(list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3)
+
+;; Προσθέτουμε έναν αριθμό στο σύνολο χρησιμοποιώντας το `set-add'
+(set-add (set 1 2 3) 4) ; => (set 1 2 3 4)
+
+;; Αφαιρούμε με το `set-remove'
+(set-remove (set 1 2 3) 1) ; => (set 2 3)
+
+;; Βλέπουμε αν υπάρχει ένας αριθμός στο σύνολο με το `set-member?'
+(set-member? (set 1 2 3) 1) ; => #t
+(set-member? (set 1 2 3) 4) ; => #f
+
+;;; Πίνακες κατακερματισμού (Hashes)
+
+;; Δημιουργήστε ένα αμετάβλητο πίνακα κατακερματισμού
+(define m (hash 'a 1 'b 2 'c 3))
+
+;; Παίρνουμε μια τιμή απο τον πίνακα
+(hash-ref m 'a) ; => 1
+
+;; Άν ζητήσουμε μια τιμή που δέν υπάρχει παίρνουμε μία εξαίρεση
+; (hash-ref m 'd) => no value found for key
+
+;; Μπορούμε να δώσουμε μια default τιμή για τα κλειδιά που λείπουν
+(hash-ref m 'd 0) ; => 0
+
+
+;; Χρησιμοποιούμε το 'hash-set' για να επεκτείνουμε
+;; ένα πίνακα κατακερματισμού
+(define m2 (hash-set m 'd 4))
+m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3))
+
+;; Θυμηθείτε ! Αυτοί οι πίνακες κατακερματισμού
+;; είναι αμετάβλητοι!
+m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- δεν υπάρχει `d'
+
+;; Χρησιμοποιούμε το `hash-remove' για να αφαιρέσουμε
+;; κλειδία
+(hash-remove m 'a) ; => '#hash((b . 2) (c . 3))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. Συναρτήσεις
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Χρησιμοποιούμε το `lambda' για να δημιουργήσουμε συναρτήσεις.
+;; Μια συνάρτηση πάντα επιστρέφει την τιμή της τελευταίας της έκφρασης
+(lambda () "Hello World") ; => #<procedure>
+;; Μπορούμε επίσης να χρησιμοποιήσουμε το `λ'
+(λ () "Hello World") ; => Ίδια συνάρτηση
+
+;; Χρησιμοποιύμε τις παρενθέσεις για να καλέσουμε όλες τις συναρτήσεις
+;; συμπεριλαμβανομένων και των εκφράσεων 'λάμδα'
+((lambda () "Hello World")) ; => "Hello World"
+((λ () "Hello World")) ; => "Hello World"
+
+;; Εκχωρούμε σε μια μετάβλητη την συνάρτηση
+(define hello-world (lambda () "Hello World"))
+(hello-world) ; => "Hello World"
+
+;; Μπορούμε αυτό να το κάνουμε συντομότερο χρησιμοποιώντας
+;; το λεγόμενο syntactic sugar :
+(define (hello-world2) "Hello World")
+
+;; Το () στο παραπάνω είναι η λίστα από τα ορίσματα για την συνάρτηση
+
+(define hello
+ (lambda (name)
+ (string-append "Hello " name)))
+(hello "Steve") ; => "Hello Steve"
+;; ... ή ισοδύναμα, χρησιμοποιώντας sugared ορισμό:
+(define (hello2 name)
+ (string-append "Hello " name))
+
+;; Μπορούμε να έχουμε συναρτήσεις με πολλές μεταβλητές χρησιμοποιώντας
+;; το `case-lambda'
+(define hello3
+ (case-lambda
+ [() "Hello World"]
+ [(name) (string-append "Hello " name)]))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+;; ... ή να ορίσουμε προαιρετικά ορίσματα με μια έκφραση προκαθορισμένης τιμής
+(define (hello4 [name "World"])
+ (string-append "Hello " name))
+
+;; Οι συναρτήσεις μπορούν να πακετάρουν επιπλέον
+;; ορίσματα μέσα σε μια λίστα
+(define (count-args . args)
+ (format "You passed ~a args: ~a" (length args) args))
+(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
+;; ... ή με unsugared μορφή `lambda':
+(define count-args2
+ (lambda args
+ (format "You passed ~a args: ~a" (length args) args)))
+
+;; Μπορούμε να εμπλέξουμε κανονικά και πακεταρισμένα ορίσματα
+(define (hello-count name . args)
+ (format "Hello ~a, you passed ~a extra args" name (length args)))
+(hello-count "Finn" 1 2 3)
+; => "Hello Finn, you passed 3 extra args"
+;; ... και unsugared:
+(define hello-count2
+ (lambda (name . args)
+ (format "Hello ~a, you passed ~a extra args" name (length args))))
+
+;; Και με λέξεις κλειδία
+(define (hello-k #:name [name "World"] #:greeting [g "Hello"] . args)
+ (format "~a ~a, ~a extra args" g name (length args)))
+(hello-k) ; => "Hello World, 0 extra args"
+(hello-k 1 2 3) ; => "Hello World, 3 extra args"
+(hello-k #:greeting "Hi") ; => "Hi World, 0 extra args"
+(hello-k #:name "Finn" #:greeting "Hey") ; => "Hey Finn, 0 extra args"
+(hello-k 1 2 3 #:greeting "Hi" #:name "Finn" 4 5 6)
+ ; => "Hi Finn, 6 extra args"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 4. Ισότητα
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; για αριθμούς χρησιμοποιούμε το `='
+(= 3 3.0) ; => #t
+(= 2 1) ; => #f
+
+;; Το `eq?' επιστρέφει #t αν δύο 2 ορίσματα αναφέρονται στο
+;; ίδιο αντικείμενο (στη μνήμη),αλλιώς επιστρέφει #f.
+;; Με άλλα λόγια, είναι απλή σύγκριση δεικτών.
+(eq? '() '()) ; => #t, αφού υπάρχει μόνο μια άδεια λίστα στη μνήμη
+(let ([x '()] [y '()])
+ (eq? x y)) ; => #t, το ίδιο με πάνω
+
+(eq? (list 3) (list 3)) ; => #f
+(let ([x (list 3)] [y (list 3)])
+ (eq? x y)) ; => #f — δεν είναι η ίδια λίστα στην μνήμη!
+
+(let* ([x (list 3)] [y x])
+ (eq? x y)) ; => #t, Αφού το x και το y τώρα δείχνουν στην ίδια θέση
+
+(eq? 'yes 'yes) ; => #t
+(eq? 'yes 'no) ; => #f
+
+(eq? 3 3) ; => #t — να είστε προσεκτικοί εδώ
+ ; Είναι προτιμότερο να χρησιμοποιείτε `=' για την
+ ; σύγκριση αριθμών.
+(eq? 3 3.0) ; => #f
+
+(eq? (expt 2 100) (expt 2 100)) ; => #f
+(eq? (integer->char 955) (integer->char 955)) ; => #f
+
+(eq? (string-append "foo" "bar") (string-append "foo" "bar")) ; => #f
+
+;; Το `eqv?' υποστηρίζει την σύκριση αριθμών αλλα και χαρακτήρων
+;; Για άλλα ήδη μεταβλητών το `eqv?' και το `eq?' επιστρέφουν το ίδιο.
+(eqv? 3 3.0) ; => #f
+(eqv? (expt 2 100) (expt 2 100)) ; => #t
+(eqv? (integer->char 955) (integer->char 955)) ; => #t
+
+(eqv? (string-append "foo" "bar") (string-append "foo" "bar")) ; => #f
+
+;; Το `equal?' υποστηρίζει την σύγκριση των παρακάτω τύπων μεταβλητών:
+;; αλφαριθμητικά, αλφαριθμητικά από bytes, μεταβλητά ζεύγη , διανύσματα,
+;; πίνακες κατακερματισμού και δομές.
+;; Για άλλα ήδη τύπων μεταβλητών το `equal?' και το `eqv?' επιστρέφουν το
+;; ίδιο αποτέλεσμα.
+(equal? 3 3.0) ; => #f
+(equal? (string-append "foo" "bar") (string-append "foo" "bar")) ; => #t
+(equal? (list 3) (list 3)) ; => #t
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 5. Έλεχγος Ροής
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; Συνθήκες (conditionals)
+
+(if #t ; έκφραση ελέχγου
+ "this is true" ; έκφραση then
+ "this is false") ; έκφραση else
+; => "this is true"
+
+
+;; Στα conditionals, όλες οι μη #f τιμές θεωρούνται ως #t
+(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(Groucho Zeppo)
+(if (member 'Groucho '(Harpo Groucho Zeppo))
+ 'yep
+ 'nope)
+; => 'yep
+
+;; Οι αλυσίδες `cond' είναι σειρές από ελέγχους για να
+;; επιλεγεί ένα αποτέλεσμα
+(cond [(> 2 2) (error "wrong!")]
+ [(< 2 2) (error "wrong again!")]
+ [else 'ok]) ; => 'ok
+
+;;; Αντιστοίχιση μοτίβων
+
+(define (fizzbuzz? n)
+ (match (list (remainder n 3) (remainder n 5))
+ [(list 0 0) 'fizzbuzz]
+ [(list 0 _) 'fizz]
+ [(list _ 0) 'buzz]
+ [_ #f]))
+
+(fizzbuzz? 15) ; => 'fizzbuzz
+(fizzbuzz? 37) ; => #f
+
+;;; Βρόχοι
+
+;; Οι επαναλήψεις μπορούν να γίνουν μέσω αναδρομής
+(define (loop i)
+ (when (< i 10)
+ (printf "i=~a\n" i)
+ (loop (add1 i))))
+(loop 5) ; => i=5, i=6, ...
+
+;; Παρομοίως με τη χρήση 'let'
+(let loop ((i 0))
+ (when (< i 10)
+ (printf "i=~a\n" i)
+ (loop (add1 i)))) ; => i=0, i=1, ...
+
+
+;; Θα δείτε παρακάτω πως να προσθέσουμε μια νέα μορφή επανάληψης
+;; αλλά η Racket έχει ήδη πολύ ευέλικτη μορφή για τους βρόχους
+(for ([i 10])
+ (printf "i=~a\n" i)) ; => i=0, i=1, ...
+(for ([i (in-range 5 10)])
+ (printf "i=~a\n" i)) ; => i=5, i=6, ...
+
+;;;
+;;; Επανάληψη μέσα σε ακολουθίες:
+;; Το `for' επιτρέπει την επανάληψη μέσα σε πολλά
+;; άλλα ήδη από ακολουθίες: Λίστες, διανύσματα,
+;; αλφαριθμητικά, σύνολα κτλ..
+
+(for ([i (in-list '(l i s t))])
+ (displayln i))
+
+(for ([i (in-vector #(v e c t o r))])
+ (displayln i))
+
+(for ([i (in-string "string")])
+ (displayln i))
+
+(for ([i (in-set (set 'x 'y 'z))])
+ (displayln i))
+
+(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))])
+ (printf "key:~a value:~a\n" k v))
+
+;;; Πιο περίπλοκες επαναλήψεις
+
+;; Παράλληλη σάρωση σε πολλαπλές ακολουθίες
+;; (σταματά στην πιο σύντομη)
+(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j))
+; => 0:x 1:y 2:z
+
+;; Εμφολευμένοι βρόχοι
+(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j))
+; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z
+
+;; Συνθήκες
+(for ([i 1000]
+ #:when (> i 5)
+ #:unless (odd? i)
+ #:break (> i 10))
+ (printf "i=~a\n" i))
+; => i=6, i=8, i=10
+
+;;; Σάρωση σε λίστες
+;; Παρόμοιο με τους βρόχους 'for', απλά συλλέγουμε τα αποτελέσματα
+
+(for/list ([i '(1 2 3)])
+ (add1 i)) ; => '(2 3 4)
+
+(for/list ([i '(1 2 3)] #:when (even? i))
+ i) ; => '(2)
+
+(for/list ([i 10] [j '(x y z)])
+ (list i j)) ; => '((0 x) (1 y) (2 z))
+
+(for/list ([i 1000] #:when (> i 5) #:unless (odd? i) #:break (> i 10))
+ i) ; => '(6 8 10)
+
+(for/hash ([i '(1 2 3)])
+ (values i (number->string i)))
+; => '#hash((1 . "1") (2 . "2") (3 . "3"))
+
+;; Υπάρχουν πολλά είδη απο προϋπάρχοντες τρόπους για να συλλέγουμε
+;; τιμές από τους βρόχους
+
+(for/sum ([i 10]) (* i i)) ; => 285
+(for/product ([i (in-range 1 11)]) (* i i)) ; => 13168189440000
+(for/and ([i 10] [j (in-range 10 20)]) (< i j)) ; => #t
+(for/or ([i 10] [j (in-range 0 20 2)]) (= i j)) ; => #t
+
+;; Και για να χρησιμοποιήσουμε ένα αφθαίρετο συνδιασμό χρησιμοποιούμε
+;; το 'for/fold'
+(for/fold ([sum 0]) ([i '(1 2 3 4)]) (+ sum i)) ; => 10
+
+;; Αυτό συχνά μπορεί να αντικαταστήσει τους κοινούς
+;; προστακτικούς βρόχους (imperative loops)
+
+;;; Εξαιρέσεις
+
+;; Για να πιάσουμε τις εξαιρέσεις χρησιμοποιούμε το
+;; `with-handlers'
+(with-handlers ([exn:fail? (lambda (exn) 999)])
+ (+ 1 "2")) ; => 999
+(with-handlers ([exn:break? (lambda (exn) "no time")])
+ (sleep 3)
+ "phew") ; => "phew", αλλά αν γίνει το break => "no time"
+
+;; Χρησιμοποιούμε το 'raise' για να άρουμε μια εξαίρεση
+;; ή οποιαδήποτε άλλη τιμή
+(with-handlers ([number? ; πιάνουμε αριθμητικές τιμές
+ identity]) ; και τις επιστρέφουμε σαν απλές τιμές
+ (+ 1 (raise 2))) ; => 2
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 6. Αλλαγή τιμών
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Χρησιμοποιούμε το 'set!' για να θέσουμε μια νέα τιμή
+;; σε μια ήδη υπάρχουσα μεταβλητή
+(define n 5)
+(set! n (add1 n))
+n ; => 6
+
+;; Χρησιμοποιούμε τα boxes για να δηλώσουμε ρητά ότι μια μεταβητή
+;; θα είναι mutable (θα μπορεί να αλλάξη η τιμή της)
+;; Αυτό είναι παρόμοιο με τους pointers σε άλλες γλώσσες
+(define n* (box 5))
+(set-box! n* (add1 (unbox n*)))
+(unbox n*) ; => 6
+
+
+;; Πολλοί τύποι μεταβλητών στη Racket είναι αμετάβλητοι πχ τα ζεύγη, οι
+;; λίστες κτλ. Άλλοι υπάρχουν και σε μεταβλητή και σε αμετάβλητη μορφή
+;; πχ αλφαριθμητικά, διανύσματα κτλ
+(define vec (vector 2 2 3 4))
+(define wall (make-vector 100 'bottle-of-beer))
+;; Χρησιμοποιούμε το 'vector-set!' για να ανεώσουμε κάποια
+;; συγκεκριμένη θέση
+(vector-set! vec 0 1)
+(vector-set! wall 99 'down)
+vec ; => #(1 2 3 4)
+
+
+;; Έτσι δημιουργούμε ένα άδειο μεταβλητό πίνακα κατακερματισμού
+;; και τον χειριζόμαστε κατάλληλα
+(define m3 (make-hash))
+(hash-set! m3 'a 1)
+(hash-set! m3 'b 2)
+(hash-set! m3 'c 3)
+(hash-ref m3 'a) ; => 1
+(hash-ref m3 'd 0) ; => 0
+(hash-remove! m3 'a)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 7. Ενότητες (modules)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;; Οι ενότητες μας επιτρέπουν να οργανώνουμε τον κώδικα σε πολλαπλά
+;; αρχεία και επαναχρησιμοποιούμενες βιβλιοθήκες
+;; Εδώ χρησιμοποιούμε υπο-ενότητες, εμφωλευμένες μέσα σε μια
+;; άλλη ενότητα που δημιουργεί αυτό το κείμενο (ξεκινώντας από
+;; την γραμμή '#lang' )
+(module cake racket/base ; ορίζουμε μια ενότητα 'cake' βασισμένο στο
+ ; racket/base
+
+ (provide print-cake) ; συνάρτηση που εξάγεται από την ενότητα
+
+ (define (print-cake n)
+ (show " ~a " n #\.)
+ (show " .-~a-. " n #\|)
+ (show " | ~a | " n #\space)
+ (show "---~a---" n #\-))
+
+ (define (show fmt n ch) ; εσωτερική συνάρτηση
+ (printf fmt (make-string n ch))
+ (newline)))
+
+;; Χρησιμοποιομε το 'require' για να πάρουμε όλα τα
+;; παρεχόμενα ονόματα από μία ενότητα
+(require 'cake) ; το ' είναι για τοπική υποενότητα
+(print-cake 3)
+; (show "~a" 1 #\A) ; => error, το `show' δεν έχει εξαχθεί
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 8. Κλάσεις και αντικείμενα
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Δημιουργούμε μια κλάση fish% (- συνήθως χρησιμοποιούμε
+;; το % στο όνομα μιας κλάσης )
+(define fish%
+ (class object%
+ (init size) ; initialization argument
+ (super-new) ; superclass initialization
+ ;; Field
+ (define current-size size)
+ ;; Public methods
+ (define/public (get-size)
+ current-size)
+ (define/public (grow amt)
+ (set! current-size (+ amt current-size)))
+ (define/public (eat other-fish)
+ (grow (send other-fish get-size)))))
+
+;; Δημιουργούμε ένα instance του fish%
+(define charlie
+ (new fish% [size 10]))
+
+;; Χρησιμοποιούμε το 'send' για να καλέσουμε
+;; τις μεθόδους ενός αντικειμένου
+(send charlie get-size) ; => 10
+(send charlie grow 6)
+(send charlie get-size) ; => 16
+
+;; Το `fish%' είναι μία τιμή "πρώτης κλάσης"
+;; με το οποίο μπορούμε να κάνουμε προσμείξεις
+(define (add-color c%)
+ (class c%
+ (init color)
+ (super-new)
+ (define my-color color)
+ (define/public (get-color) my-color)))
+(define colored-fish% (add-color fish%))
+(define charlie2 (new colored-fish% [size 10] [color 'red]))
+(send charlie2 get-color)
+;; ή χωρίς καθόλου ονόματα :
+(send (new (add-color fish%) [size 10] [color 'red]) get-color)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 9. Μακροεντολές
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Οι μακροεντολές μας επιτρέπουν να επεκτείνουμε
+;; το συντακτικό μιάς γλώσσας.
+
+;; Ας προσθέσουμε έναν βρόχο while
+(define-syntax-rule (while condition body ...)
+ (let loop ()
+ (when condition
+ body ...
+ (loop))))
+
+(let ([i 0])
+ (while (< i 10)
+ (displayln i)
+ (set! i (add1 i))))
+
+;; Macros are hygienic, you cannot clobber existing variables!
+(define-syntax-rule (swap! x y) ; -! is idiomatic for mutation
+ (let ([tmp x])
+ (set! x y)
+ (set! y tmp)))
+
+(define tmp 2)
+(define other 3)
+(swap! tmp other)
+(printf "tmp = ~a; other = ~a\n" tmp other)
+;; Η μεταβλητή 'tmp' μετονομάζεται σε 'tmp_1'
+;; για να αποφευχθεί η σύγκρουση με τα ονόματα
+;; (let ([tmp_1 tmp])
+;; (set! tmp other)
+;; (set! other tmp_1))
+
+;; Αλλά ακόμα υπάρχουν ακόμη μετασχηματισμοί του κώδικα, π.χ:
+(define-syntax-rule (bad-while condition body ...)
+ (when condition
+ body ...
+ (bad-while condition body ...)))
+;; αυτή η μακροεντολή είναι χαλασμένη: δημιουγεί ατέρμονα βρόχο
+;; και αν προσπαθήσουμε να το χρησιμοποιήσουμε, ο μεταγλωττιστής
+;; θα μπεί στον ατέρμονα βρόχο.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 10. Συμβόλαια (Contracts)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Τα συμβόλαια βάζουν περιορισμόυς σε τιμές που προέρχονται
+;; από ενότητες (modules)
+(module bank-account racket
+ (provide (contract-out
+ [deposit (-> positive? any)] ; οι ποσότητες είναι πάντα θετικές
+ [balance (-> positive?)]))
+
+ (define amount 0)
+ (define (deposit a) (set! amount (+ amount a)))
+ (define (balance) amount)
+ )
+
+(require 'bank-account)
+(deposit 5)
+
+(balance) ; => 5
+
+;; Πελάτες που προσπαθούν να καταθέσουν ένα μη θετικό ποσό παίρνουν
+;; το μήνυμα (deposit -5) ; => deposit: contract violation
+;; expected: positive?
+;; given: -5
+;; more details....
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 11. Είσοδος και έξοδος
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Η Racket έχει την έννοια του "port", που είναι παρόμοιο με τα
+;; file descriptors σε άλλες γλώσσες.
+
+;; Ανοίγουμε το "/tmp/tmp.txt" και γράφουμε μέσα "Hello World"
+;; Αυτό θα προκαλούσε σφάλμα αν το αρχείο υπήρχε ήδη
+(define out-port (open-output-file "/tmp/tmp.txt"))
+(displayln "Hello World" out-port)
+(close-output-port out-port)
+
+;; Προσθέτουμε στο τέλος του "/tmp/tmp.txt"
+(define out-port (open-output-file "/tmp/tmp.txt"
+ #:exists 'append))
+(displayln "Hola mundo" out-port)
+(close-output-port out-port)
+
+;; Διαβάζουμε απο αρχείο ξανά
+(define in-port (open-input-file "/tmp/tmp.txt"))
+(displayln (read-line in-port))
+; => "Hello World"
+(displayln (read-line in-port))
+; => "Hola mundo"
+(close-input-port in-port)
+
+;; Εναλλακτικά, με το call-with-output-file δεν χρειάζεται να κλείσουμε
+;; ρητά το αρχείο
+(call-with-output-file "/tmp/tmp.txt"
+ #:exists 'update ; Rewrite the content
+ (λ (out-port)
+ (displayln "World Hello!" out-port)))
+
+;; Και το call-with-input-file κάνει το ίδιο πράγμα για την είσοδο
+(call-with-input-file "/tmp/tmp.txt"
+ (λ (in-port)
+ (displayln (read-line in-port))))
+```
+
+## Επιπλέον πηγές
+
+Ψάχνεις για περισσότερα ; [Getting Started with Racket](http://docs.racket-lang.org/getting-started/)
diff --git a/el-gr/scala-gr.html.markdown b/el-gr/scala-gr.html.markdown
new file mode 100644
index 00000000..e29c7e70
--- /dev/null
+++ b/el-gr/scala-gr.html.markdown
@@ -0,0 +1,689 @@
+---
+language: Scala
+contributors:
+ - ["George Petrov", "http://github.com/petrovg"]
+ - ["Dominic Bou-Samra", "http://dbousamra.github.com"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+translators:
+ - ["Vasilis Panagiotopoulos" , "https://github.com/billpcs/"]
+filename: learnscala-gr.scala
+lang: el-gr
+---
+
+Scala - Η επεκτάσιμη γλώσσα
+
+```scala
+
+/*
+ Προετοιμαστείτε:
+
+ 1) Κατεβάστε την Scala - http://www.scala-lang.org/downloads
+ 2) Κάνετε εξαγωγή στην επιθυμητή σας τοποθεσία και βάλτε τον υποφάκελο bin
+ στο path του συστήματος
+ 3) Ξεκινήστε ένα scala REPL γράφοντας scala. Θα πρέπει να βλέπετε το prompt:
+
+ scala>
+
+ Αυτό είναι το αποκαλούμενο REPL (Read-Eval-Print Loop) *.
+ Μπορείτε να πληκτρολογήσετε οποιαδήποτε έγκυρη έκφραση σε Scala μέσα του ,
+ και το αποτέλεσμα θα τυπωθεί. Θα εξηγήσουμε πως μοιάζουν τα αρχεία της Scala
+ αργότερα μέσα στο tutorial , αλλά για τώρα ας αρχίσουμε με κάποια βασικά.
+ *[Βρόχος του Διάβασε - Αξιολόγησε - Τύπωσε]
+*/
+
+
+/////////////////////////////////////////////////
+// 1. Βασικές έννοιες
+/////////////////////////////////////////////////
+
+// Τα σχόλια μίας γραμμής ξεκινούν με δύο "/" (:forward slashes) .
+
+/*
+ Τα σχόλια που επεκτείνονται σε πολλές γραμμές , όπως μπορείτε
+ να δείτε , φαίνοται κάπως έτσι.
+*/
+
+// Εκτύπωση με νέα γραμμή στην επόμενη εκτύπωση
+println("Hello world!")
+println(10)
+
+// Εκτύπωση χωρίς νέα γραμμή στην επόμενη εκτύπωση
+print("Hello world")
+
+// Η δήλωση μεταβλητών γίνεται χρησιμοποιώντας var ή val.
+// Οι δηλώσεις val είναι αμετάβλητες, ενώ οι var είναι μεταβλητές.
+// Η αμεταβλητότητα είναι συμφέρουσα και προσπαθούμε να την χρησιμοποιούμε.
+val x = 10 // το x είναι τώρα 10
+x = 20 // σφάλμα: αλλαγή σε val
+var y = 10
+y = 20 // το y είναι τώρα 20
+
+/*
+ Η Scala είναι στατικού τύπου γλώσσα, εν τούτις προσέξτε ότι στις παραπάνω
+ δηλώσεις , δεν προσδιορίσαμε κάποιον τύπο. Αυτό συμβαίνει λόγω ενός
+ χαρακτηριστικού της Scala που λέγεται συμπερασματολογία τύπων. Στις
+ περισσότερες των περιπτώσεων, ο μεταγλωττιστής της Scala μπορεί να
+ μαντέψει ποιός είναι ο τύπος μιας μεταβλητής. Μπορούμε να δηλώσουμε
+ αναλυτικά τον τύπο μιάς μεταβλητής ως εξής:
+*/
+val z: Int = 10
+val a: Double = 1.0
+
+/*
+ Προσέξτε ότι υπάρχει αυτόματη μετατροπή από ακέραιο (Int) σε διπλής
+ ακρίβειας (Double), και συνεπώς το αποτέλεσμα είναι 10.0 και όχι 10.
+*/
+val b: Double = 10
+
+// Λογικές τιμές
+true
+false
+
+// Λογικές Πράξεις
+!true // false
+!false // true
+true == false // false
+10 > 5 // true
+
+// Η αριθμιτική είναι όπως τα συνηθισμένα
+1 + 1 // 2
+2 - 1 // 1
+5 * 3 // 15
+6 / 2 // 3
+6 / 4 // 1
+6.0 / 4 // 1.5
+
+
+/*
+ Αξιολογώντας μια έκφραση στο REPL, σας δίνεται ο τύπος και
+ η τιμή του αποτελέσματος
+*/
+
+1 + 7
+
+/* Η παραπάνω γραμμή έχει το εξής αποτέλεσμα:
+
+ scala> 1 + 7
+ res29: Int = 8
+
+ Αυτό σημαίνει ότι το αποτέλεσμα της αξιολόγησης του 1 + 7 είναι ένα αντικείμενο
+ τύπου Int με τιμή 8
+
+ Σημειώστε ότι το "res29" είναι ένα σειριακά δημιουργούμενο όνομα μεταβλητής
+ για να αποθηκεύονται τα αποτελέσματα των εκφράσεων που έχετε πληκτρολογήσει
+ και συνεπώς η έξοδός σας μπορεί να διαφέρει.
+*/
+
+"Τα αλφαριθμητικά στην Scala περικλείονται από διπλά εισαγωγικά"
+'a' // Ένας χαρακτήρας στην Scala
+// res30: Char = a
+// 'Αλφαριθημτικά με μονά εισαγωγικά δεν υφίστανται <= Αυτό θα προκαλέσει σφάλμα.
+
+// Τα αλφαριθμητικά έχουν τις συνηθισμένες μεθόδους της Java ορισμένες πάνω τους.
+"hello world".length
+"hello world".substring(2, 6)
+"hello world".replace("C", "3")
+
+// Έχουν επίσης μερικές επιπλένον μεθόδους Scala.
+// Δείτε επίσης : scala.collection.immutable.StringOps
+"hello world".take(5)
+"hello world".drop(5)
+
+// Παρεμβολή αλφαριθμητικών : παρατηρήστε το πρόθεμα "s"
+val n = 45
+s"We have $n apples" // => "We have 45 apples"
+
+// Παρατηρήστε την χρήση των '{', '}'
+val a = Array(11, 9, 6)
+s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old."
+s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples."
+s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"
+
+// Μορφοποίηση με παρεμβεβλημένα αλφαριθμητικά με το πρόθεμα "f"
+f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
+f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"
+
+// Raw αλφαριθμητικά, που αγνοούν τους ειδικούς χαρακτήρες.
+raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r."
+
+// Μερικούς χαρακτήρες πρέπει να τους κάνουμε "escape",
+// λ.χ ένα διπλό εισαγωγικό μέσα σε ένα αλφαριθμητικό :
+"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown""
+
+/*
+ Τα τριπλά διπλά-εισαγωγικά επιτρέπουν στα αλφαριθμητικά να εκτείνονται σε
+ πολλαπλές γραμμές και να περιέχουν διπλά εισαγωγικά
+*/
+val html = """<form id="daform">
+ <p>Press belo', Joe</p>
+ <input type="submit">
+ </form>"""
+
+
+/////////////////////////////////////////////////
+// 2. Συναρτήσεις
+/////////////////////////////////////////////////
+
+// Οι συναρτήσεις ορίζονται ως εξής:
+//
+// def functionName(args...): ReturnType = { body... }
+//
+// Αν προέρχεστε απο πιο παραδοσιακές γλώσσες (C/C++ , Java) παρατηρήστε
+// την παράλειψη του return. Στην Scala , η τελευταία έκφραση στο μπλόκ
+// της συνάρτησης είναι η τιμή που επιστρέφει η συνάρτηση.
+def sumOfSquares(x: Int, y: Int): Int = {
+ val x2 = x * x
+ val y2 = y * y
+ x2 + y2
+}
+
+// Τα { } μπορούν να παραλειφθούν αν η συνάρτηση αποτελείται απο μια απλή έκφραση:
+def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y
+
+// Η σύνταξη για την κλήση συναρτήσεων είναι γνώριμη:
+sumOfSquares(3, 4) // => 25
+
+// Στις περισσότερες των περιπτώσεων (με τις αναδρομικές συναρτήσεις να αποτελούν
+// την πιο αξιοπρόσεκτη εξαίρεση) , ο τύπος επιστροφής της συνάρτησης μπορεί να
+// παραλειφθεί, και η ίδια συμπερασματολογία τύπων που είδαμε με τις μεταβλητές
+// θα δουλεύει και με τους τύπους επιστροφής της συνάρτησης:
+def sq(x: Int) = x * x // Ο μεταγλωττιστής μπορεί να μαντέψει ότι
+ // ο τύπος επιστροφής της συνάρτησης είναι Int
+
+// Οι συναρτήσεις μπορούν να έχουν προκαθορισμένες τιμές:
+def addWithDefault(x: Int, y: Int = 5) = x + y
+addWithDefault(1, 2) // => 3
+addWithDefault(1) // => 6
+
+
+// Οι ανώνυμες συναρτήσεις είναι ως εξής:
+(x:Int) => x * x
+
+// Σε αντίθεση με τα defs , ακόμα και ο τύπος εισόδου απο τις ανώνυμες
+// συναρτήσεις μπορεί να παραληφθεί αν τα συμφραζόμενα το κάνουν ξεκάθαρο.
+// Προσέξτε τον τύπο "Int => Int" που σημαίνει ότι μια συνάρτηση παίρνει
+// ένα Int και επιστρέφει ένα Int.
+val sq: Int => Int = x => x * x
+
+// Οι ανώνυμες συναρτήσεις μπορούν να κληθούν όπως συνήθως:
+sq(10) // => 100
+
+// Αν κάθε όρισμα στην ανώνυμη συνάρτηση χρησιμοποιείται μόνο μία φορά,
+// η Scala επιτρέπει έναν ακόμα πιο σύντομο τρόπο να οριστεί. Αυτές
+// οι ανώνυμες συναρτήσεις αποδεικνύεται ότι είναι πολύ κοινές ,
+// όπως θα γίνει προφανές στο μέρος των δομών δεδομένων.
+val addOne: Int => Int = _ + 1
+val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)
+
+addOne(5) // => 6
+weirdSum(2, 4) // => 16
+
+// Η δεσμευμένη λέξη return υπάρχει στην Scala , αλλά επιστρέφει μόνο
+// από το πιο εσωτερικό def που την περικλείει.
+// ΠΡΟΣΟΧΗ: Η χρήση του return στην Scala είναι επιρρεπής σε λάθη
+// και θα πρέπει να αποφεύγεται.
+// Δεν έχει καμία επίδραση στις ανώνυμες συναρτήσεις. Για παράδειγμα:
+def foo(x: Int): Int = {
+ val anonFunc: Int => Int = { z =>
+ if (z > 5)
+ return z // Αυτή η σειρά κάνει το z την τιμή που επιστρέφει η foo!
+ else
+ z + 2 // Αυτή η γραμμή είναι η τιμή που επιστρέφει η anonFunc
+ }
+ anonFunc(x) // Αυτή η γραμμή είναι η τιμή που επιστρέφει η foo
+}
+
+
+/////////////////////////////////////////////////
+// 3. Έλεγχος ροής
+/////////////////////////////////////////////////
+
+1 to 5
+val r = 1 to 5
+r.foreach( println )
+
+r foreach println
+// ΠΡΟΣΟΧΗ: Η Scala είναι σχετικά επιεικής ως αναφορά τις τελείες και
+// τις παρενθέσεις. Διαβάστε τους κανόνες ξεχωριστά.
+// Αυτό βοηθάει στο να γράφεις DSLs και APIs που διαβάζονται σαν τα Αγγλικά.
+
+(5 to 1 by -1) foreach ( println )
+
+// Ένας βρόχος while :
+var i = 0
+while (i < 10) { println("i " + i); i+=1 }
+
+while (i < 10) { println("i " + i); i+=1 } // Ναι ξανά! Τι συνέβει; Γιατί;
+
+i // Εμφάνισε την τιμή του i. Σημειώστε ότι ένας βρόχος while είναι βρόχος
+ // με την κλασική έννοια - εκτελείται σειριακά καθώς αλλάζει η μεταβλητή
+ // του βρόχου. Το while είναι πολύ γρήγορο , γρηγορότερο απο τους βρόχους
+ // της Java , αλλά η χρήση combinators και comprehensions όπως πιο πάνω ,
+ // είναι πιο εύκολη στην κατανόηση και στην παραλληλοποίηση.
+
+// Ένας βρόχος do while :
+do {
+ println("x is still less than 10");
+ x += 1
+} while (x < 10)
+
+// Η αναδρομή ουράς είναι ένας ιδιωματικός τρόπος να κάνεις επαναλαμβανόμενα
+// πράγματα στην Scala. Οι αναδρομικές συναρτήσεις απαιτούν να γράφτεί
+// ρητά ο τύπος που θα επιστρέψουν , αλλιώς ο μεταγλωττιστής δεν μπορεί
+// αλλιώς να τον συνάγει. Παρακάτω είναι μια συνάρτηση που επιστρέφει Unit.
+def showNumbersInRange(a:Int, b:Int):Unit = {
+ print(a)
+ if (a < b)
+ showNumbersInRange(a + 1, b)
+}
+showNumbersInRange(1,14)
+
+
+// Έλεγχος Ροής
+
+val x = 10
+
+if (x == 1) println("yeah")
+if (x == 10) println("yeah")
+if (x == 11) println("yeah")
+if (x == 11) println ("yeah") else println("nay")
+
+println(if (x == 10) "yeah" else "nope")
+val text = if (x == 10) "yeah" else "nope"
+
+
+/////////////////////////////////////////////////
+// 4. Δομές Δεδομένων
+/////////////////////////////////////////////////
+
+val a = Array(1, 2, 3, 5, 8, 13)
+a(0)
+a(3)
+a(21) // "Πετάει" exception
+
+val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo")
+m("fork")
+m("spoon")
+m("bottle") // "Πετάει" exception
+
+val safeM = m.withDefaultValue("no lo se")
+safeM("bottle")
+
+val s = Set(1, 3, 7)
+s(0)
+s(1)
+
+/* Δείτε το documentation του map εδώ -
+ * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map
+ */
+
+
+// Πλειάδες
+
+(1, 2)
+
+(4, 3, 2)
+
+(1, 2, "three")
+
+(a, 2, "three")
+
+// Γιατί να το έχουμε αυτό;
+val divideInts = (x:Int, y:Int) => (x / y, x % y)
+
+divideInts(10,3) // Η συνάρτηση divideInts επιστρέφει το αποτέλεσμα
+ // της ακαίρεας διαίρεσης και το υπόλοιπο.
+
+// Για να έχουμε πρόσβαση στα στοιχεία μιας πλειάδας, χρησιμοποιούμε το _._n
+// όπου το n είναι ο δείκτης με βάση το 1 του στοιχείου.
+val d = divideInts(10,3)
+
+d._1
+
+d._2
+
+
+/////////////////////////////////////////////////
+// 5. Αντικειμενοστραφής Προγραμματισμός
+/////////////////////////////////////////////////
+
+/*
+ Ότι έχουμε κάνει ως τώρα σε αυτό το tutorial ήταν απλές εκφράσεις
+ (τιμές , συναρτήσεις , κτλ). Αυτές οι εκφράσεις βολεύουν όταν τις
+ γράφουμε στο REPL για γρήγορες δοκιμές, αλλά δεν μπορούν να υπάρχουν
+ από μόνες τους σε ένα αρχείο Scala. Για παράδειγμα , δεν μπορούμε να
+ έχουμε μόνο ένα "val x = 5" στο αρχείο Scala. Αντί αυτού , τα μόνα
+ στοιχεία του πάνω επιπέδου που επιτρέπονται στην Scala είναι:
+
+ - αντικείμενα (objects)
+ - κλάσεις (classes)
+ - κλάσεις περίπτωσης (case classes στην Scala)
+ - Χαρακτηριστικά (traits , όπως ονομάζονται στην Scala)
+
+ Και τώρα θα εξηγήσουμε τι είναι αυτά.
+*/
+// Οι κλάσεις είναι παρόμοιες με τις κλάσεις σε άλλες γλώσσες. Τα ορίσματα του
+// "κατασκευαστή" (constructor) δηλώνονται μετά από το όνομα της κλάσης ,
+// και η αρχικοποιήση γίνεται μέσα στο σώμα της κλάσης.
+class Dog(br: String) {
+ // Κώδικας για τον "κατασκευαστή"
+ var breed: String = br
+
+ // Ορίζεται μια μέθοδος bark , που επιστρέφει ένα αλφαριθμητικό
+ def bark = "Woof, woof!"
+
+ // Οι τιμές και οι μέθοδοι είναι public εκτός αν χρησιμοποιήσουμε κάποια
+ // απο τις λέξεις κλειδιά "protected" και "private" .
+ private def sleep(hours: Int) =
+ println(s"I'm sleeping for $hours hours")
+
+ // Οι abstract μέθοδοι είναι απλά μέθοδοι χωρίς σώμα. Αν βγάζαμε
+ // το σχόλιο απο την επόμενη γραμμή η κλάση Dog θα έπρεπε να
+ // δηλωθεί ως abstract class Dog(...) { ... } :
+ // def chaseAfter(what: String): String
+}
+
+val mydog = new Dog("greyhound")
+println(mydog.breed) // => "greyhound"
+println(mydog.bark) // => "Woof, woof!"
+
+
+// Η λέξη "object" δημιουργεί ένα type ΚΑΙ ένα singleton instance αυτού.
+// Είναι κοινό για τις κλάσεις στην Scala να έχουν ένα "συντροφικό object",
+// όπου η συμπεριφορά για κάθε instance αιχμαλωτίζεται μέσα στις κλάσεις
+// αυτές καθ' αυτές, αλλά η συμπρεριφορά που σχετίζεται με όλα τα instances
+// της κλάσης πάνε μέσα στο object. Η διαφορά είναι παρόμοια με τις
+// μεθόδους κλάσεων σε σχέση με στατικές μεθόδους σε άλλες γλώσσες.
+// Προσέξτε οτι τα objects και οι κλάσεις μπορούν να έχουν το ίδιο όνομα.
+object Dog {
+ def allKnownBreeds = List("pitbull", "shepherd", "retriever")
+ def createDog(breed: String) = new Dog(breed)
+}
+
+// Οι κλάσεις περίπτωσης (case classes) είναι που έχουν την επιπλέον
+// λειτουργικότητα ενσωματωμένη. Μιά συνήθης ερώτηση για αρχάριους στην
+// Scala είναι πότε να χρησιμοπούνται κλάσεις και πότε case κλάσεις.
+// Γενικά οι κλάσεις τείνουν να εστιάζουν στην ενθυλάκωση, τον
+// πολυμορφισμό και τη συμπεριφορά. Οι τιμές μέσα σε αυτές τις κλάσεις
+// τείνουν να είναι private , και μόνο οι μέθοδοι είναι εκτεθειμένες.
+// Ο κύριος σκοπός των case classes είναι να κρατούν δεδομένα που είναι
+// σταθερές(immutable). Συνήθως έχουν λίγες μεθόδους και οι μέθοδοι σπάνια
+// έχουν παρενέργειες.
+case class Person(name: String, phoneNumber: String)
+
+// Δημιουργία ενός instance. Πραρατηρήστε ότι τα case classes
+// δεν χρειάζονται την λέξη "new" .
+val george = Person("George", "1234")
+val kate = Person("Kate", "4567")
+
+// Με τα case classes, παίρνεις μερικά προνόμια δωρεάν , όπως:
+george.phoneNumber // => "1234"
+
+// Ελέχγεται η ισότητα για κάθε πεδίο (δεν χρειάζεται να
+// κάνουμε override στο .equals)
+Person("George", "1234") == Person("Kate", "1236") // => false
+
+// Έυκολος τρόπος να κάνουμε αντιγραφή. Δημιουργούμε έναν νέο geroge:
+// otherGeorge == Person("george", "9876")
+val otherGeorge = george.copy(phoneNumber = "9876")
+
+// Και πολλά άλλα. Τα case classes έχουν και αντιστοίχιση προτύπων
+// (pattern matching) δωρεάν, δείτε παρακάτω.
+
+// Τα χαρακτηριστικά (traits) έρχονται σε λίγο καιρό !
+
+/////////////////////////////////////////////////
+// 6. Αντιστοίχιση Προτύπων
+/////////////////////////////////////////////////
+
+// Η αντιστοίχιση προτύπων (pattern matching) είναι ένα πολύ δυνατό και
+// ευρέως χρησιμοποιούμενο χαρακτηριστικό στην Scala. Παρακάτω βλέπουμε
+// πως γίνεται το pattern matching σε ένα case class. Σημείωση: Σε
+// αντίθεση με άλλες γλώσσες η Scala δεν χρειάζεται breaks, γιατί γίνεται
+// αυτόματα όταν γίνει κάποιο match.
+
+def matchPerson(person: Person): String = person match {
+ // Μετά προσδιορίζουμε το πρότυπο (pattern):
+ case Person("George", number) => "We found George! His number is " + number
+ case Person("Kate", number) => "We found Kate! Her number is " + number
+ case Person(name, number) => "We matched someone : " + name + ", phone : " + number
+}
+
+val email = "(.*)@(.*)".r // Ορίζουμε ένα regex για το επόμενο παράδειγμα.
+ // (regex <- REGular EXpression)
+
+// Το pattern matching μπορεί να μοιάζει γνώριμο απο τα switch statements σε
+// γλώσσες που ανήκουν στην οικογένεια της C αλλά είναι πολύ πιο ισχυρό.
+// Στην Scala , μπορούμε να κάνουμε match πολύ περισσότερα:
+def matchEverything(obj: Any): String = obj match {
+ // Μπορούμε να ταιριάξουμε τιμές:
+ case "Hello world" => "Got the string Hello world"
+
+ // Μπορούμε να ταιριάξουμε τύπους:
+ case x: Double => "Got a Double: " + x
+
+ // Μπορούμε να βάλουμε συνθήκες:
+ case x: Int if x > 10000 => "Got a pretty big number!"
+
+ // Μπορούμε να ταιριάξουμε case classes όπως πρίν:
+ case Person(name, number) => s"Got contact info for $name!"
+
+ // Μπορούμε να ταιριάξουμε regex:
+ case email(name, domain) => s"Got email address $name@$domain"
+
+ // Μπορούμε να ταιριάξουμε πλειάδες:
+ case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c"
+
+ // Μπορούμε να ταιριάξουμε δομές δεδομένων:
+ case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"
+
+ // Μπορούμε να ταιριάξουμε πρότυπα που το ένα είναι μέσα στο άλλο:
+ case List(List((1, 2,"YAY"))) => "Got a list of list of tuple"
+}
+
+// Στην πραγματικότητα , μπορούμε να κάνουμε pattern matching σε όποιο αντικείμενο
+// έχει την μέθοδο "unapply". Αυτό το χαρακτηριστικό είναι τόσο ισχυρό ώστε
+// η Scala επιτρέπει να ορίστούν ολόκληρες συναρτήσεις σαν patterns.
+val patternFunc: Person => String = {
+ case Person("George", number) => s"George's number: $number"
+ case Person(name, number) => s"Random person's number: $number"
+}
+
+
+/////////////////////////////////////////////////
+// 7. Συναρτησιακός Προγραμματισμός
+/////////////////////////////////////////////////
+
+// Η Scala επιτρέπει στις μεθόδους και τις συναρτήσεις να επιστρέφουν ή να
+// δέχονται ως παραμέτρους άλλες μεθόδους ή συναρτήσεις.
+
+val add10: Int => Int = _ + 10 // Μια συνάρτηση που δέχεται Int και επιστρέφει Int
+List(1, 2, 3) map add10 // List(11, 12, 13) - το add10 εφαρμόζεται σε κάθε στοιχείο
+ // μέσω του map
+
+// Οι ανώνυμες συναρτήσεις μπορούν να χρησιμοποιηθούν αντί
+// ονοματισμένων (όπως απο πάνω) :
+List(1, 2, 3) map (x => x + 10)
+
+// Και το σύμβολο της κάτω παύλας , μπορεί να χρησιμοποιηθεί αν υπάρχει μόνο
+// ένα όρισμα στην ανώνυμη συνάρτηση. Έτσι δεσμεύεται ως η μεταβλητή.
+List(1, 2, 3) map (_ + 10)
+
+// Αν το μπλόκ της ανώνυμης συνάρτησης ΚΑΙ η συνάρτηση που εφαρμόζεται
+// (στην περίπτωσή μας το foreach και το println) παίρνουν ένα όρισμα
+// μπορείτε να παραλείψετε την κάτω παύλα.
+List("Dom", "Bob", "Natalia") foreach println
+
+
+// Συνδυαστές
+
+s.map(sq)
+
+val sSquared = s. map(sq)
+
+sSquared.filter(_ < 10)
+
+sSquared.reduce (_+_)
+
+// Η συνάρτηση filter παίρνει ένα κατηγορούμενο (predicate)
+// που είναι μια συνάρτηση απο το A -> Boolean και διαλέγει
+// όλα τα στοιχεία που ικανοποιούν αυτό το κατηγορούμενο.
+List(1, 2, 3) filter (_ > 2) // List(3)
+case class Person(name:String, age:Int)
+List(
+ Person(name = "Dom", age = 23),
+ Person(name = "Bob", age = 30)
+).filter(_.age > 25) // List(Person("Bob", 30))
+
+
+// Το foreach είναι μια μέθοδος της Scala , που ορίζεται για ορισμένες
+// συλλογές (collections). Παίρνει έναν τύπο και επιστρέφει Unit
+// (μια μέθοδο void)
+val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100)
+aListOfNumbers foreach (x => println(x))
+aListOfNumbers foreach println
+
+// For comprehensions
+
+for { n <- s } yield sq(n)
+
+val nSquared2 = for { n <- s } yield sq(n)
+
+for { n <- nSquared2 if n < 10 } yield n
+
+for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared
+
+/*
+ Προσοχή : Αυτά δεν ήταν βρόχοι for. Η σημασιολογία ενός βρόχου for είναι
+ η επανάληψη, ενώ ένα for-comprehension ορίζει μια σχέση μεταξύ δύο
+ συνόλων δεδομένων.
+*/
+
+/////////////////////////////////////////////////
+// 8. Implicits
+/////////////////////////////////////////////////
+/*
+ ΠΡΟΣΟΧΗ! Τα implicits είναι ένα σύνολο απο ισχυρά χαρακτηριστικά της Scala
+ και επομένως είναι εύκολο να γίνει κατάχρηση. Οι αρχάριοι στην Scala θα
+ πρέπει να αντισταθούν στον πειρασμό να τα χρησιμοποιήσουν έως ότου, όχι
+ μόνο καταλάβουν πως λειτουργούν, αλλά ακόμα εξασκηθούν πάνω τους.
+ Ο μόνος λόγος που συμπεριλάβαμε αυτό το κομμάτι στο tutorial είναι
+ γιατί είναι τόσο κοινό στις βιβλιοθήκες της Scala , που αδύνατο να κάνεις
+ οτιδήποτε σημαντικό χωρίς να χρησιμοποιήσεις μια που να έχει implicits.
+
+*/
+
+// Κάθε τιμή (vals , συναρτήσεις , αντικείμενα , κτλ) μπορεί να δηλωθεί ως
+// implicit χρησιμοποιώντας , ναι το μαντέψατε , την λέξη "implicit".
+// Σημειώστε ότι χρησιμοποιούμε την κλάση Dog που δημιουργήσαμε στο
+// 5ο μέρος των παραδειγμάτων.
+implicit val myImplicitInt = 100
+implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed)
+
+
+// Απο μόνη της, η λέξη implicit, δεν αλλάζει την συμπεριφορά μιάς τιμής
+// οπότε οι παραπάνω μπορούν να χρησιμοποιοηθούν όπως συνήθως.
+myImplicitInt + 2 // => 102
+myImplicitFunction("Pitbull").breed // => "Golden Pitbull"
+
+// Η διαφορά είναι ότι τώρα αυτές οι τιμές έχουν την δυνατότητα να
+// χρησιμοποιηθούν όταν ένα άλλο κομμάτι κώδικα "χρειάζεται" μια
+// implicit τιμή. Μια τέτοια περίπτωση είναι τα ορίσματα μιας implicit
+// συνάρτησης:
+def sendGreetings(toWhom: String)(implicit howMany: Int) =
+ s"Hello $toWhom, $howMany blessings to you and yours!"
+
+// Άν τροφοδοτήσουμε μια τιμή για το "homMany", η συνάρτηση συμπεριφέρεται
+// ως συνήθως
+sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!"
+
+// Αλλά αν παραλείψουμε την παράμετρο implicit , μια implicit τιμή του ιδίου τύπου
+// χρησιμοποιείται, στην περίπτωσή μας, το "myImplicitInt"
+sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!"
+
+// Οι παράμετροι implicit συναρτήσεων μας επιτρέπουν να προσομοιάζουμε
+// κλάσεις τύπων (type classes) σε άλλες συναρτησιακές γλώσσες.
+// Χρησιμοποιείται τόσο συχνά που έχει την δικιά του συντομογραφία.
+// Οι επόμενες δύο γραμμές κώδικα σημαίνουν το ίδιο πράγμα.
+def foo[T](implicit c: C[T]) = ...
+def foo[T : C] = ...
+
+
+
+// Μια άλλη περίπτωση στην οποία ο μεταγλωττιστής αναζητά μια implicit τιμή
+// είναι αν έχετε obj.method (...)
+// αλλά το "obj" δεν έχει την "method" ως μέθοδο. Σε αυτή την περίπτωση,
+// αν υπάρχει μια implicit μετατροπή του τύπου Α => Β, όπου Α είναι ο τύπος
+// του obj, ενώ το Β έχει μία μέθοδο που ονομάζεται «method», εφαρμόζεται η
+// εν λόγω μετατροπή. Έτσι, έχοντας την MyImplicitFunction μέσα στο πεδίο
+// εφαρμογής(scope), μπορούμε να πούμε:
+"Retriever".breed // => "Golden Retriever"
+"Sheperd".bark // => "Woof, woof!"
+
+// Εδώ το String αρχικά μετατρέπεται σε Dog χρησιμοποιώντας την συνάρτησή μας
+// παραπάνω, και μετά καλείται η κατάλληλη μέθοδος. Αυτό είναι ένα εξερετικά
+// ισχυρό χαρακτηριστικό, αλλά δεν πρέπει να χρησιμοποιείται με ελαφριά την
+// καρδιά. Μάλιστα, όταν ορίσατε την συνάρτηση implicit παραπάνω, ο μεταγλωττιστής
+// θα πρέπει να σας έδωσε μια προειδοποιήση, ότι δεν πρέπει να το κάνετε αυτό
+// εκτός αν πραγματικά γνωρίζετε τι κάνετε.
+
+
+/////////////////////////////////////////////////
+// 9. Διάφορα
+/////////////////////////////////////////////////
+
+// Εισαγωγή βιβλιοθηκών κτλ
+import scala.collection.immutable.List
+
+// Εισαγωγή των πάντων απο το scala.collection.immutable
+import scala.collection.immutable._
+
+// Εισαγωγή πολλών κλάσεων σε μία έκφραση
+import scala.collection.immutable.{List, Map}
+
+// Δώστε ένα νέο όνομα στην εισαγωγή σας χρησιμοποιώντας το '=>'
+import scala.collection.immutable.{ List => ImmutableList }
+
+// Εισαγωγή όλων των κλάσεων εκτός απο μερικές.
+// Το επόμενο δεν εισάγει το Map και το Set:
+import scala.collection.immutable.{Map => _, Set => _, _}
+
+// Το σημείο εισαγωγής του προγράμματος σας ορίζεται σε ένα αρχείο scala ,
+// χρησιμοποιώντας ένα αντικείμενο (object), με μία μέθοδο , την main.
+object Application {
+ def main(args: Array[String]): Unit = {
+ // Εδω γράφουμε ...
+ }
+}
+
+// Files can contain multiple classes and objects. Compile with scalac
+// Τα files μπορούν να περιέχουν περισσότερες απο μία κλάσεις και
+// αντικείμενα. Το compile γίνεται με την εντολή scalac
+
+// Εισαγωγή και εξαγωγή.
+
+// Για να διβάσετε ένα αρχείο γραμμή προς γραμμή
+import scala.io.Source
+for(line <- Source.fromFile("myfile.txt").getLines())
+ println(line)
+
+// Για να γράψετε σε ένα αρχείο
+val writer = new PrintWriter("myfile.txt")
+writer.write("Writing line for line" + util.Properties.lineSeparator)
+writer.write("Another line here" + util.Properties.lineSeparator)
+writer.close()
+
+```
+
+## Further resources
+
+[Scala for the impatient](http://horstmann.com/scala/)
+
+[Twitter Scala school](http://twitter.github.io/scala_school/)
+
+[The scala documentation](http://docs.scala-lang.org/)
+
+[Try Scala in your browser](http://scalatutorials.com/tour/)
+
+Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user)
+
diff --git a/elixir.html.markdown b/elixir.html.markdown
index fb5f183a..c8599838 100644
--- a/elixir.html.markdown
+++ b/elixir.html.markdown
@@ -195,7 +195,7 @@ cond do
"But I will"
end
-# It is common to see the last condition equal to `true`, which will always match.
+# It is common to set the last condition equal to `true`, which will always match.
cond do
1 + 1 == 3 ->
"I will never be seen"
diff --git a/erlang.html.markdown b/erlang.html.markdown
index a3b571d1..8b67a76a 100644
--- a/erlang.html.markdown
+++ b/erlang.html.markdown
@@ -164,6 +164,13 @@ is_cat(A) -> false.
is_dog(A) when is_atom(A), A =:= dog -> true;
is_dog(A) -> false.
+% We won't dwell on the `=:=` operator here; just be aware that it is used to
+% check whether two Erlang expressions have the same value *and* the same type.
+% Contrast this behaviour to that of the `==` operator:
+1 + 2 =:= 3. % true
+1 + 2 =:= 3.0. % false
+1 + 2 == 3.0. % true
+
% A guard sequence is either a single guard or a series of guards, separated
% by semicolons (`;`). The guard sequence `G1; G2; ...; Gn` is true if at
% least one of the guards `G1`, `G2`, ..., `Gn` evaluates to `true`.
diff --git a/es-es/git-es.html.markdown b/es-es/git-es.html.markdown
index 5c9d3378..73853a9d 100644
--- a/es-es/git-es.html.markdown
+++ b/es-es/git-es.html.markdown
@@ -38,7 +38,7 @@ uno o varios archivos, a lo largo del tiempo.
* Se puede trabajar sin conexion.
* Colaborar con otros es sencillo!.
* Derivar, Crear ramas del proyecto (aka: Branching) es facil!.
-* Combinar (aka: Marging)
+* Combinar (aka: Merging)
* Git es rapido.
* Git es flexible.
diff --git a/es-es/go-es.html.markdown b/es-es/go-es.html.markdown
index 86de33ec..c41d693d 100644
--- a/es-es/go-es.html.markdown
+++ b/es-es/go-es.html.markdown
@@ -1,326 +1,450 @@
---
+name: Go
+category: language
language: Go
lang: es-es
filename: learngo-es.go
contributors:
- ["Sonia Keys", "https://github.com/soniakeys"]
+ - ["Christopher Bess", "https://github.com/cbess"]
+ - ["Jesse Johnson", "https://github.com/holocronweaver"]
+ - ["Quint Guvernator", "https://github.com/qguv"]
+ - ["Jose Donizetti", "https://github.com/josedonizetti"]
+ - ["Alexej Friesen", "https://github.com/heyalexej"]
translators:
- ["Adrian Espinosa", "http://www.adrianespinosa.com"]
- ["Jesse Johnson", "https://github.com/holocronweaver"]
+ - ["Nacho Pacheco -- Feb/2015", "https://github.com/gitnacho"]
---
-Go fue creado por la necesidad de hacer el trabajo rápidamente. No es
-la última tendencia en informática, pero es la forma nueva y más
-rápida de resolver problemas reales.
+Go fue creado por la necesidad de hacer el trabajo rápidamente. No es la
+última tendencia en informática, pero es la forma nueva y más rápida de
+resolver problemas reales.
-Tiene conceptos familiares de lenguajes imperativos con tipado
-estático. Es rápido compilando y rápido al ejecutar, añade una
-concurrencia fácil de entender para las CPUs de varios núcleos de hoy
-en día, y tiene características que ayudan con la programación a gran
-escala.
+Tiene conceptos familiares de lenguajes imperativos con tipado estático.
+Es rápido compilando y rápido al ejecutar, añade una concurrencia fácil de
+entender para las CPUs de varios núcleos de hoy día, y tiene
+características que ayudan con la programación a gran escala.
-Go viene con una librería estándar muy buena y una comunidad entusiasta.
+Go viene con una biblioteca estándar muy buena y una entusiasta comunidad.
```go
// Comentario de una sola línea
-/* Comentario
- multi línea */
+/* Comentario
+ multilínea */
-// La cláusula package aparece al comienzo de cada archivo fuente.
-// Main es un nombre especial que declara un ejecutable en vez de una librería.
+// La cláusula `package` aparece al comienzo de cada fichero fuente.
+// `main` es un nombre especial que declara un ejecutable en vez de una
+// biblioteca.
package main
-// La declaración Import declara los paquetes de librerías
-// referenciados en este archivo.
+// La instrucción `import` declara los paquetes de bibliotecas referidos
+// en este fichero.
import (
- "fmt" // Un paquete en la librería estándar de Go.
- "net/http" // Sí, un servidor web!
- "strconv" // Conversiones de cadenas.
- m "math" // Librería matemáticas con alias local m.
+ "fmt" // Un paquete en la biblioteca estándar de Go.
+ "io/ioutil" // Implementa algunas útiles funciones de E/S.
+ m "math" // Biblioteca de matemáticas con alias local m.
+ "net/http" // Sí, ¡un servidor web!
+ "strconv" // Conversiones de cadenas.
)
-// Definición de una función. Main es especial. Es el punto de
-// entrada para el ejecutable. Te guste o no, Go utiliza llaves.
+// Definición de una función. `main` es especial. Es el punto de entrada
+// para el ejecutable. Te guste o no, Go utiliza llaves.
func main() {
- // Println imprime una línea a stdout.
- // Cualificalo con el nombre del paquete, fmt.
- fmt.Println("Hello world!")
+ // Println imprime una línea a stdout.
+ // Cualificalo con el nombre del paquete, fmt.
+ fmt.Println("¡Hola mundo!")
- // Llama a otra función de este paquete.
- beyondHello()
+ // Llama a otra función de este paquete.
+ másAlláDelHola()
}
// Las funciones llevan parámetros entre paréntesis.
// Si no hay parámetros, los paréntesis siguen siendo obligatorios.
-func beyondHello() {
- var x int // Declaración de una variable.
- // Las variables se deben declarar antes de utilizarlas.
- x = 3 // Asignación de variables.
- // Declaración "corta" con := para inferir el tipo, declarar y asignar.
- y := 4
- sum, prod := learnMultiple(x, y) // Función devuelve dos valores.
- fmt.Println("sum:", sum, "prod:", prod) // Simple salida.
- learnTypes() // < y minutes, learn more!
+func másAlláDelHola() {
+ var x int // Declaración de una variable.
+ // Las variables se deben declarar antes de utilizarlas.
+ x = 3 // Asignación de variable.
+ // Declaración "corta" con := para inferir el tipo, declarar y asignar.
+ y := 4
+ suma, producto := aprendeMúltiple(x, y) // La función devuelve dos
+ // valores.
+ fmt.Println("suma:", suma, "producto:", producto) // Simple salida.
+ aprendeTipos() // < y minutos, ¡aprende más!
}
-// Las funciones pueden tener parámetros y (múltiples!) valores de retorno.
-func learnMultiple(x, y int) (sum, prod int) {
- return x + y, x * y // Devolver dos valores.
+// Las funciones pueden tener parámetros y (¡múltiples!) valores de
+// retorno.
+func aprendeMúltiple(x, y int) (suma, producto int) {
+ return x + y, x * y // Devuelve dos valores.
}
// Algunos tipos incorporados y literales.
-func learnTypes() {
- // La declaración corta suele darte lo que quieres.
- s := "Learn Go!" // tipo cadena
-
- s2 := ` Un tipo cadena "puro" puede incluir
+func aprendeTipos() {
+ // La declaración corta suele darte lo que quieres.
+ s := "¡Aprende Go!" // tipo cadena.
+ s2 := `Un tipo cadena "puro" puede incluir
saltos de línea.` // mismo tipo cadena
- // Literal no ASCII. Los fuentes de Go son UTF-8.
- g := 'Σ' // Tipo rune, un alias de int32, alberga un punto unicode.
- f := 3.14195 // float64, el estándar IEEE-754 de coma flotante 64-bit.
- c := 3 + 4i // complex128, representado internamente por dos float64.
- // Sintaxis Var con inicializadores.
- var u uint = 7 // Sin signo, pero la implementación depende del
- // tamaño como en int.
- var pi float32 = 22. / 7
-
- // Sintáxis de conversión con una declaración corta.
- n := byte('\n') // byte es un alias de uint8.
-
- // Los Arrays tienen un tamaño fijo a la hora de compilar.
- var a4 [4]int // Un array de 4 ints, inicializados a 0.
- a3 := [...]int{3, 1, 5} // Un array de 3 ints, inicializados como se indica.
-
- // Los Slices tienen tamaño dinámico. Los arrays y slices tienen sus ventajas
- // y desventajas pero los casos de uso para los slices son más comunes.
- s3 := []int{4, 5, 9} // Comparar con a3. No hay puntos suspensivos.
- s4 := make([]int, 4) // Asigna slices de 4 ints, inicializados a 0.
- var d2 [][]float64 // Solo declaración, sin asignación.
- bs := []byte("a slice") // Sintaxis de conversión de tipo.
-
- p, q := learnMemory() // Declara p, q para ser un tipo puntero a int.
- fmt.Println(*p, *q) // * sigue un puntero. Esto imprime dos ints.
-
- // Los Maps son arrays asociativos dinámicos, como los hash o
- // diccionarios de otros lenguajes.
- m := map[string]int{"three": 3, "four": 4}
- m["one"] = 1
-
- // Las variables no utilizadas en Go producen error.
- // El guión bajo permite "utilizar" una variable, pero descartar su valor.
- _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs
- // Esto cuenta como utilización de variables.
- fmt.Println(s, c, a4, s3, d2, m)
-
- learnFlowControl() // Vuelta al flujo.
+ // Literal no ASCII. Los ficheros fuente de Go son UTF-8.
+ g := 'Σ' // Tipo rune, un alias de int32, alberga un carácter unicode.
+ f := 3.14195 // float64, el estándar IEEE-754 de coma flotante 64-bit.
+ c := 3 + 4i // complex128, representado internamente por dos float64.
+ // Sintaxis Var con iniciadores.
+ var u uint = 7 // Sin signo, pero la implementación depende del tamaño
+ // como en int.
+ var pi float32 = 22. / 7
+
+ // Sintáxis de conversión con una declaración corta.
+ n := byte('\n') // byte es un alias para uint8.
+
+ // Los Arreglos tienen un tamaño fijo a la hora de compilar.
+ var a4 [4]int // Un arreglo de 4 ints, iniciados a 0.
+ a3 := [...]int{3, 1, 5} // Un arreglo iniciado con un tamaño fijo de tres
+ // elementos, con valores 3, 1 y 5.
+ // Los Sectores tienen tamaño dinámico. Los arreglos y sectores tienen
+ // sus ventajas y desventajas pero los casos de uso para los sectores
+ // son más comunes.
+ s3 := []int{4, 5, 9} // Comparar con a3. No hay puntos suspensivos.
+ s4 := make([]int, 4) // Asigna sectores de 4 ints, iniciados a 0.
+ var d2 [][]float64 // Solo declaración, sin asignación.
+ bs := []byte("a sector") // Sintaxis de conversión de tipo.
+ // Debido a que son dinámicos, los sectores pueden crecer bajo demanda.
+ // Para añadir elementos a un sector, se utiliza la función incorporada
+ // append().
+ // El primer argumento es el sector al que se está anexando. Comúnmente,
+ // la variable del arreglo se actualiza en su lugar, como en el
+ // siguiente ejemplo.
+ sec := []int{1, 2 , 3} // El resultado es un sector de longitud 3.
+ sec = append(sec, 4, 5, 6) // Añade 3 elementos. El sector ahora tiene una
+ // longitud de 6.
+ fmt.Println(sec) // El sector actualizado ahora es [1 2 3 4 5 6]
+ // Para anexar otro sector, en lugar de la lista de elementos atómicos
+ // podemos pasar una referencia a un sector o un sector literal como
+ // este, con elipsis al final, lo que significa tomar un sector y
+ // desempacar sus elementos, añadiéndolos al sector sec.
+ sec = append(sec, []int{7, 8, 9} ...) // El segundo argumento es un
+ // sector literal.
+ fmt.Println(sec) // El sector actualizado ahora es [1 2 3 4 5 6 7 8 9]
+ p, q := aprendeMemoria() // Declara p, q para ser un tipo puntero a
+ // int.
+ fmt.Println(*p, *q) // * sigue un puntero. Esto imprime dos ints.
+
+ // Los Mapas son arreglos asociativos dinámicos, como los hash o
+ // diccionarios de otros lenguajes.
+ m := map[string]int{"tres": 3, "cuatro": 4}
+ m["uno"] = 1
+
+ // Las variables no utilizadas en Go producen error.
+ // El guión bajo permite "utilizar" una variable, pero descartar su
+ // valor.
+ _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs
+ // Esto cuenta como utilización de variables.
+ fmt.Println(s, c, a4, s3, d2, m)
+
+ aprendeControlDeFlujo() // Vuelta al flujo.
+}
+
+// Es posible, a diferencia de muchos otros lenguajes tener valores de
+// retorno con nombre en las funciones.
+// Asignar un nombre al tipo que se devuelve en la línea de declaración de
+// la función nos permite volver fácilmente desde múltiples puntos en una
+// función, así como sólo utilizar la palabra clave `return`, sin nada
+// más.
+func aprendeRetornosNombrados(x, y int) (z int) {
+ z = x * y
+ return // aquí z es implícito, porque lo nombramos antes.
}
-// Go posee recolector de basura. Tiene puntero pero no aritmética de
-// punteros. Puedes cometer un errores con un puntero nil, pero no
+// Go posee recolector de basura. Tiene punteros pero no aritmética de
+// punteros. Puedes cometer errores con un puntero nil, pero no
// incrementando un puntero.
-func learnMemory() (p, q *int) {
- // q y p tienen un tipo puntero a int.
- p = new(int) // Función incorporada que asigna memoria.
- // La asignación de int se inicializa a 0, p ya no es nil.
- s := make([]int, 20) // Asigna 20 ints a un solo bloque de memoria.
- s[3] = 7 // Asignar uno de ellos.
- r := -2 // Declarar otra variable local.
- return &s[3], &r // & toma la dirección de un objeto.
+func aprendeMemoria() (p, q *int) {
+ // Los valores de retorno nombrados q y p tienen un tipo puntero
+ // a int.
+ p = new(int) // Función incorporada que reserva memoria.
+ // La asignación de int se inicia a 0, p ya no es nil.
+ s := make([]int, 20) // Reserva 20 ints en un solo bloque de memoria.
+ s[3] = 7 // Asigna uno de ellos.
+ r := -2 // Declara otra variable local.
+ return &s[3], &r // & toma la dirección de un objeto.
}
-func expensiveComputation() float64 {
- return m.Exp(10)
+func cálculoCaro() float64 {
+ return m.Exp(10)
}
-func learnFlowControl() {
- // La declaración If requiere llaves, pero no paréntesis.
- if true {
- fmt.Println("told ya")
- }
- // El formato está estandarizado por el comando "go fmt."
- if false {
- // Pout.
- } else {
- // Gloat.
- }
- // Utiliza switch preferiblemente para if encadenados.
- x := 42.0
- switch x {
- case 0:
- case 1:
- case 42:
- // Los cases no se mezclan, no requieren de "break".
- case 43:
- // No llega.
+func aprendeControlDeFlujo() {
+ // La declaración If requiere llaves, pero no paréntesis.
+ if true {
+ fmt.Println("ya relatado")
+ }
+ // El formato está estandarizado por la orden "go fmt."
+ if false {
+ // Abadejo.
+ } else {
+ // Relamido.
+ }
+ // Utiliza switch preferentemente para if encadenados.
+ x := 42.0
+ switch x {
+ case 0:
+ case 1:
+ case 42:
+ // Los cases no se mezclan, no requieren de "break".
+ case 43:
+ // No llega.
+ }
+ // Como if, for no utiliza paréntesis tampoco.
+ // Variables declaradas en for e if son locales a su ámbito.
+ for x := 0; x < 3; x++ { // ++ es una instrucción.
+ fmt.Println("iteración", x)
+ }
+ // aquí x == 42.
+
+ // For es la única instrucción de bucle en Go, pero tiene formas
+ // alternativas.
+ for { // Bucle infinito.
+ break // ¡Solo bromeaba!
+ continue // No llega.
+ }
+
+ // Puedes usar `range` para iterar en un arreglo, un sector, una
+ // cadena, un mapa o un canal.
+ // `range` devuelve o bien, un canal o de uno a dos valores (arreglo,
+ // sector, cadena y mapa).
+ for clave, valor := range map[string]int{"uno": 1, "dos": 2, "tres": 3} {
+ // por cada par en el mapa, imprime la clave y el valor
+ fmt.Printf("clave=%s, valor=%d\n", clave, valor)
+ }
+
+ // Como en for, := en una instrucción if significa declarar y asignar
+ // primero, luego comprobar y > x.
+ if y := cálculoCaro(); y > x {
+ x = y
}
- // Como if, for no utiliza paréntesis tampoco.
- // Variables declaradas en for y if son locales de su ámbito local.
- for x := 0; x < 3; x++ { // ++ es una sentencia.
- fmt.Println("iteration", x)
- }
- // x == 42 aqui.
+ // Las funciones literales son "cierres".
+ granX := func() bool {
+ return x > 100 // Referencia a x declarada encima de la instrucción
+ // switch.
+ }
+ fmt.Println("granX:", granX()) // cierto (la última vez asignamos
+ // 1e6 a x).
+ x /= 1.3e3 // Esto hace a x == 1300
+ fmt.Println("granX:", granX()) // Ahora es falso.
+
+ // Es más las funciones literales se pueden definir y llamar en línea,
+ // actuando como un argumento para la función, siempre y cuando:
+ // a) la función literal sea llamada inmediatamente (),
+ // b) el tipo del resultado sea del tipo esperado del argumento
+ fmt.Println("Suma dos números + doble: ",
+ func(a, b int) int {
+ return (a + b) * 2
+ }(10, 2)) // Llamada con argumentos 10 y 2
+ // => Suma dos números + doble: 24
+
+ // Cuando lo necesites, te encantará.
+ goto encanto
+encanto:
+
+ aprendeFunciónFábrica() // func devolviendo func es divertido(3)(3)
+ aprendeADiferir() // Un rápido desvío a una importante palabra clave.
+ aprendeInterfaces() // ¡Buen material dentro de poco!
+}
- // For es la única sentencia de bucle en Go, pero tiene formas alternativas.
- for { // Bucle infinito.
- break // Solo bromeaba!
- continue // No llega.
- }
- // Como en for, := en una sentencia if significa declarar y asignar primero,
- // luego comprobar y > x.
- if y := expensiveComputation(); y > x {
- x = y
- }
- // Los literales de funciones son "closures".
- xBig := func() bool {
- return x > 100 // Referencia a x declarada encima de la sentencia switch.
- }
- fmt.Println("xBig:", xBig()) // verdadero (la última vez asignamos 1e6 a x).
- x /= m.Exp(9) // Esto lo hace x == e.
- fmt.Println("xBig:", xBig()) // Ahora es falso.
+func aprendeFunciónFábrica() {
+ // Las dos siguientes son equivalentes, la segunda es más práctica
+ fmt.Println(instrucciónFábrica("día")("Un bello", "de verano"))
+
+ d := instrucciónFábrica("atardecer")
+ fmt.Println(d("Un hermoso", "de verano"))
+ fmt.Println(d("Un maravilloso", "de verano"))
+}
- // Cuando lo necesites, te encantará.
- goto love
-love:
+// Los decoradores son comunes en otros lenguajes. Lo mismo se puede hacer
+// en Go con funciónes literales que aceptan argumentos.
+func instrucciónFábrica(micadena string) func(antes, después string) string {
+ return func(antes, después string) string {
+ return fmt.Sprintf("¡%s %s %s!", antes, micadena, después) // nueva cadena
+ }
+}
- learnInterfaces() // Buen material dentro de poco!
+func aprendeADiferir() (ok bool) {
+ // las instrucciones diferidas se ejecutan justo antes de que la
+ // función regrese.
+ defer fmt.Println("las instrucciones diferidas se ejecutan en orden inverso (PEPS).")
+ defer fmt.Println("\nEsta línea se imprime primero debido a que")
+ // Defer se usa comunmente para cerrar un fichero, por lo que la
+ // función que cierra el fichero se mantiene cerca de la función que lo
+ // abrió.
+ return true
}
// Define Stringer como un tipo interfaz con un método, String.
type Stringer interface {
- String() string
+ String() string
}
-// Define pair como un struct con dos campos int, x e y.
-type pair struct {
- x, y int
+// Define par como una estructura con dos campos int, x e y.
+type par struct {
+ x, y int
}
-// Define un método del tipo pair. Pair ahora implementa Stringer.
-func (p pair) String() string { // p se llama "recibidor"
- // Sprintf es otra función pública del paquete fmt.
- // La sintaxis con punto referencia campos de p.
- return fmt.Sprintf("(%d, %d)", p.x, p.y)
+// Define un método en el tipo par. Par ahora implementa a Stringer.
+func (p par) String() string { // p se conoce como el "receptor"
+ // Sprintf es otra función pública del paquete fmt.
+ // La sintaxis con punto se refiere a los campos de p.
+ return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
-func learnInterfaces() {
- // La sintaxis de llaves es un "literal struct". Evalúa a un struct
- // inicializado. La sintaxis := declara e inicializa p a este struct.
- p := pair{3, 4}
- fmt.Println(p.String()) // Llamar al método String de p, de tipo pair.
- var i Stringer // Declarar i como interfaz tipo Stringer.
- i = p // Válido porque pair implementa Stringer.
- // Llamar al metodo String de i, de tipo Stringer. Misma salida que arriba.
- fmt.Println(i.String())
-
- // Las funciones en el paquete fmt llaman al método String para
- // preguntar a un objeto por una versión imprimible de si mismo.
- fmt.Println(p) // Salida igual que arriba. Println llama al método String.
- fmt.Println(i) // Salida igual que arriba.
-
- learnVariadicParams("great", "learning", "here!")
+func aprendeInterfaces() {
+ // La sintaxis de llaves es una "estructura literal". Evalúa a una
+ // estructura iniciada. La sintaxis := declara e inicia p a esta
+ // estructura.
+ p := par{3, 4}
+ fmt.Println(p.String()) // Llama al método String de p, de tipo par.
+ var i Stringer // Declara i como interfaz de tipo Stringer.
+ i = p // Válido porque par implementa Stringer.
+ // Llama al metodo String de i, de tipo Stringer. Misma salida que
+ // arriba.
+ fmt.Println(i.String())
+
+ // Las funciones en el paquete fmt llaman al método String para
+ // consultar un objeto por una representación imprimible de si
+ // mismo.
+ fmt.Println(p) // Salida igual que arriba. Println llama al método
+ // String.
+ fmt.Println(i) // Salida igual que arriba.
+ aprendeNúmeroVariableDeParámetros("¡gran", "aprendizaje", "aquí!")
}
// Las funciones pueden tener número variable de argumentos.
-func learnVariadicParams(myStrings ...interface{}) {
- // Iterar cada valor de la variadic.
- for _, param := range myStrings {
- fmt.Println("param:", param)
- }
-
- // Pasar valor variadic como parámetro variadic.
- fmt.Println("params:", fmt.Sprintln(myStrings...))
-
- learnErrorHandling()
+func aprendeNúmeroVariableDeParámetros(misCadenas ...interface{}) {
+ // Itera en cada valor de los argumentos variables.
+ // El espacio en blanco aquí omite el índice del argumento arreglo.
+ for _, parámetro := range misCadenas {
+ fmt.Println("parámetro:", parámetro)
+ }
+
+ // Pasa el valor de múltiples variables como parámetro variadic.
+ fmt.Println("parámetros:", fmt.Sprintln(misCadenas...))
+ aprendeManejoDeError()
}
-func learnErrorHandling() {
- // ", ok" forma utilizada para saber si algo funcionó o no.
- m := map[int]string{3: "three", 4: "four"}
- if x, ok := m[1]; !ok { // ok será falso porque 1 no está en el map.
- fmt.Println("no one there")
- } else {
- fmt.Print(x) // x sería el valor, si estuviera en el map.
- }
- // Un valor de error comunica más información sobre el problema aparte de "ok".
- if _, err := strconv.Atoi("non-int"); err != nil { // _ descarta el valor
- // Imprime "strconv.ParseInt: parsing "non-int": invalid syntax".
- fmt.Println(err)
- }
- // Revisarmeos las interfaces más tarde. Mientras tanto,
- learnConcurrency()
+func aprendeManejoDeError() {
+ // ", ok" forma utilizada para saber si algo funcionó o no.
+ m := map[int]string{3: "tres", 4: "cuatro"}
+ if x, ok := m[1]; !ok { // ok será falso porque 1 no está en el mapa.
+ fmt.Println("nada allí")
+ } else {
+ fmt.Print(x) // x sería el valor, si estuviera en el mapa.
+ }
+ // Un valor de error comunica más información sobre el problema aparte
+ // de "ok".
+ if _, err := strconv.Atoi("no-int"); err != nil { // _ descarta el
+ // valor
+ // Imprime "strconv.ParseInt: parsing "no-int": invalid syntax".
+ fmt.Println(err)
+ }
+ // Revisaremos las interfaces más adelante. Mientras tanto...
+ aprendeConcurrencia()
}
-// c es un canal, un objeto de comunicación de concurrencia segura.
+// c es un canal, un objeto de comunicación concurrente seguro.
func inc(i int, c chan int) {
- c <- i + 1 // <- es el operador "enviar" cuando un canal aparece a la izquierda.
+ c <- i + 1 // <- es el operador "enviar" cuando aparece un canal a la
+ // izquierda.
}
// Utilizaremos inc para incrementar algunos números concurrentemente.
-func learnConcurrency() {
- // Misma función make utilizada antes para crear un slice. Make asigna e
- // inicializa slices, maps, y channels.
- c := make(chan int)
- // Iniciar tres goroutines concurrentes. Los números serán incrementados
- // concurrentemente, quizás en paralelo si la máquina es capaz y
- // está correctamente configurada. Las tres envían al mismo channel.
- go inc(0, c) // go es una sentencia que inicia una nueva goroutine.
- go inc(10, c)
- go inc(-805, c)
- // Leer los tres resultados del channel e imprimirlos.
- // No se puede saber en que orden llegarán los resultados!
- fmt.Println(<-c, <-c, <-c) // Channel a la derecha, <- es el operador "recibir".
-
- cs := make(chan string) // Otro channel, este gestiona cadenas.
- ccs := make(chan chan string) // Un channel de cadenas de channels.
- go func() { c <- 84 }() // Iniciar una nueva goroutine solo para
- // enviar un valor.
- go func() { cs <- "wordy" }() // Otra vez, para cs en esta ocasión.
- // Select tiene una sintáxis parecida a la sentencia switch pero
- // cada caso involucra una operacion de channels. Selecciona un caso
- // de forma aleatoria de los casos que están listos para comunicarse.
- select {
- case i := <-c: // El valor recibido puede ser asignado a una variable,
- fmt.Printf("it's a %T", i)
- case <-cs: // o el valor puede ser descartado.
- fmt.Println("it's a string")
- case <-ccs: // Channel vacío, no está listo para la comunicación.
- fmt.Println("didn't happen.")
- }
-
- // En este punto un valor fue devuelvto de c o cs. Uno de las dos
- // goroutines que se iniciaron se ha completado, la otrá permancerá
- // bloqueada.
-
- learnWebProgramming() // Go lo hace. Tu también quieres hacerlo.
+func aprendeConcurrencia() {
+ // Misma función make utilizada antes para crear un sector. Make asigna
+ // e inicia sectores, mapas y canales.
+ c := make(chan int)
+ // Inicia tres rutinasgo concurrentes. Los números serán incrementados
+ // concurrentemente, quizás en paralelo si la máquina es capaz y está
+ // correctamente configurada. Las tres envían al mismo canal.
+ go inc(0, c) // go es una instrucción que inicia una nueva rutinago.
+ go inc(10, c)
+ go inc(-805, c)
+ // Lee los tres resultados del canal y los imprime.
+ // ¡No se puede saber en que orden llegarán los resultados!
+ fmt.Println(<-c, <-c, <-c) // Canal a la derecha, <- es el operador
+ // "recibe".
+
+ cs := make(chan string) // Otro canal, este gestiona cadenas.
+ ccs := make(chan chan string) // Un canal de canales cadena.
+ go func() { c <- 84 }() // Inicia una nueva rutinago solo para
+ // enviar un valor.
+ go func() { cs <- "verboso" }() // Otra vez, para cs en esta ocasión.
+ // Select tiene una sintáxis parecida a la instrucción switch pero cada
+ // caso involucra una operacion con un canal. Selecciona un caso de
+ // forma aleatoria de los casos que están listos para comunicarse.
+ select {
+ case i := <-c: // El valor recibido se puede asignar a una variable,
+ fmt.Printf("es un %T", i)
+ case <-cs: // o el valor se puede descartar.
+ fmt.Println("es una cadena")
+ case <-ccs: // Canal vacío, no está listo para la comunicación.
+ fmt.Println("no sucedió.")
+ }
+
+ // En este punto un valor fue devuelto de c o cs. Una de las dos
+ // rutinasgo que se iniciaron se ha completado, la otrá permancerá
+ // bloqueada.
+
+ aprendeProgramaciónWeb() // Go lo hace. Tú también quieres hacerlo.
}
// Una simple función del paquete http inicia un servidor web.
-func learnWebProgramming() {
- // El primer parámetro de la direccinón TCP a la que escuchar.
- // El segundo parámetro es una interfaz, concretamente http.Handler.
- err := http.ListenAndServe(":8080", pair{})
- fmt.Println(err) // no ignorar errores
+func aprendeProgramaciónWeb() {
+// El primer parámetro es la direccinón TCP a la que escuchar.
+ // El segundo parámetro es una interfaz, concretamente http.Handler.
+ go func() {
+ err := http.ListenAndServe(":8080", par{})
+ fmt.Println(err) // no ignora errores
+ }()
+ consultaAlServidor()
}
-// Haz pair un http.Handler implementando su único método, ServeHTTP.
-func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- // Servir datos con un método de http.ResponseWriter.
- w.Write([]byte("You learned Go in Y minutes!"))
+// Hace un http.Handler de par implementando su único método, ServeHTTP.
+func (p par) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // Sirve datos con un método de http.ResponseWriter.
+ w.Write([]byte("¡Aprendiste Go en Y minutos!"))
+}
+
+func consultaAlServidor() {
+ resp, err := http.Get("http://localhost:8080")
+ fmt.Println(err)
+ defer resp.Body.Close()
+ cuerpo, err := ioutil.ReadAll(resp.Body)
+ fmt.Printf("\nEl servidor web dijo: `%s`\n", string(cuerpo))
}
```
-## Para leer más
+## Más información
+
+La raíz de todas las cosas sobre Go es el
+[sitio web oficial de Go](http://golang.org/).
+Allí puedes seguir el tutorial, jugar interactivamente y leer mucho más.
-La raíz de todas las cosas de Go es la [web oficial de Go](http://golang.org/).
-Ahí puedes seguir el tutorial, jugar interactivamente y leer mucho.
+La definición del lenguaje es altamente recomendada. Es fácil de leer y
+sorprendentemente corta (como la definición del lenguaje Go en estos
+días).
-La propia definición del lenguaje también está altamente
-recomendada. Es fácil de leer e increíblemente corta (como otras
-definiciones de lenguajes hoy en día)
+Puedes jugar con el código en el
+[parque de diversiones Go](https://play.golang.org/p/ncRC2Zevag). ¡Trata
+de cambiarlo y ejecutarlo desde tu navegador! Ten en cuenta que puedes
+utilizar [https://play.golang.org]( https://play.golang.org) como un
+[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) para probar
+cosas y el código en el navegador, sin ni siquiera instalar Go.
-En la lista de lectura de estudiantes de Go está el código fuente de
-la librería estándar. Muy bien documentada, demuestra lo mejor de Go
-leíble, comprendible, estilo Go y formas Go. Pincha en el nombre de
-una función en la documentación y te aparecerá el código fuente!
+En la lista de lecturas para estudiantes de Go está el
+[código fuente de la biblioteca estándar](http://golang.org/src/pkg/).
+Ampliamente documentado, que demuestra lo mejor del legible y comprensible
+Go, con su característico estilo y modismos. ¡O puedes hacer clic en un
+nombre de función en [la documentación](http://golang.org/pkg/) y
+aparecerá el código fuente!
+Otro gran recurso para aprender Go está en
+[Go con ejemplos](http://goconejemplos.com/).
diff --git a/es-es/javascript-es.html.markdown b/es-es/javascript-es.html.markdown
index a1348508..fd01e7b9 100644
--- a/es-es/javascript-es.html.markdown
+++ b/es-es/javascript-es.html.markdown
@@ -16,8 +16,7 @@ con Java para aplicaciones más complejas. Debido a su integracion estrecha con
web y soporte por defecto de los navegadores modernos se ha vuelto mucho más común
para front-end que Java.
-JavaScript no sólo se limita a los navegadores web:
-* Node.js: Un proyecto que provee con un ambiente para el motor V8 de Google Chrome.
+JavaScript no sólo se limita a los navegadores web, aunque: Node.js, Un proyecto que proporciona un entorno de ejecución independiente para el motor V8 de Google Chrome, se está volviendo más y más popular.
¡La retroalimentación es bienvenida! Puedes encontrarme en:
[@adambrenecki](https://twitter.com/adambrenecki), o
@@ -49,6 +48,7 @@ hazAlgo()
// Toda la aritmética básica funciona como uno esperaría.
1 + 1; // = 2
+0.1 + 0.2; // = 0.30000000000000004
8 - 1; // = 7
10 * 2; // = 20
35 / 5; // = 7
@@ -102,9 +102,11 @@ false;
// Los tipos no importan con el operador ==...
"5" == 5; // = true
+null == undefined; // = true
// ...a menos que uses ===
"5" === 5; // = false
+null === undefined; // false
// Los Strings funcionan como arreglos de caracteres
// Puedes accesar a cada caracter con la función charAt()
@@ -126,7 +128,7 @@ undefined; // usado para indicar que un valor no está presente actualmente
// Aunque 0 === "0" sí es false.
///////////////////////////////////
-// 2. Variables, Arreglos y Objetos
+// 2. Variables, Arrays y Objetos
// Las variables se declaran con la palabra var. JavaScript cuenta con tipado dinámico,
// así que no se necesitan aplicar tipos. La asignación se logra con el operador =.
@@ -220,7 +222,6 @@ for (var i = 0; i < 5; i++){
}
// && es un "y" lógico, || es un "o" lógico
-var casa = {tamano:"grande",casa:"color"};
if (casa.tamano == "grande" && casa.color == "azul"){
casa.contiene = "oso";
}
diff --git a/es-es/julia-es.html.markdown b/es-es/julia-es.html.markdown
index 203ee3bb..1e01c2e3 100644
--- a/es-es/julia-es.html.markdown
+++ b/es-es/julia-es.html.markdown
@@ -4,757 +4,937 @@ contributors:
- ["Leah Hanson", "http://leahhanson.us"]
translators:
- ["Guillermo Garza", "http://github.com/ggarza"]
+ - ["Ismael Venegas Castelló", "https://github.com/Ismael-VC"]
filename: learnjulia-es.jl
lang: es-es
---
-Julia es un nuevo lenguaje funcional homoiconic enfocado en computación técnica.
-Aunque que tiene todo el poder de macros homoiconic, funciones de primera
-clase, y control de bajo nivel, Julia es tan fácil de aprender y utilizar como
-Python.
+![JuliaLang](https://camo.githubusercontent.com/e1ae5c7f6fe275a50134d5889a68f0acdd09ada8/687474703a2f2f6a756c69616c616e672e6f72672f696d616765732f6c6f676f5f68697265732e706e67)
-Esto se basa en la versión de desarrollo actual de Julia, del 18 de octubre de
-2013.
+[Julia](http://julialanges.github.io) es un [lenguaje de programación](http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n) [multiplataforma](http://es.wikipedia.org/wiki/Multiplataforma) y [multiparadigma](http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_multiparadigma) de [tipado dinámico](http://es.wikipedia.org/wiki/Tipado_din%C3%A1mico), [alto nivel](http://es.wikipedia.org/wiki/Lenguaje_de_alto_nivel) y [alto desempeño](http://es.wikipedia.org/wiki/Computaci%C3%B3n_de_alto_rendimiento) para la computación [genérica](http://es.wikipedia.org/wiki/Lenguaje_de_programaci%C3%B3n_de_prop%C3%B3sito_general), [técnica y científica](http://es.wikipedia.org/wiki/Computaci%C3%B3n_cient%C3%ADfica), con una sintaxis que es familiar para los usuarios de otros entornos de computación técnica y científica. Provee de un [sofisticado compilador JIT](http://es.wikipedia.org/wiki/Compilaci%C3%B3n_en_tiempo_de_ejecuci%C3%B3n), [ejecución distribuida y paralela](http://docs.julialang.org/en/release-0.3/manual/parallel-computing), [precisión numérica](http://julia.readthedocs.org/en/latest/manual/integers-and-floating-point-numbers) y de una [extensa librería con funciones matemáticas](http://docs.julialang.org/en/release-0.3/stdlib). La librería estándar, escrita casi completamente en Julia, también integra las mejores y más maduras librerías de C y Fortran para el [álgebra lineal](http://docs.julialang.org/en/release-0.3/stdlib/linalg), [generación de números aleatorios](http://docs.julialang.org/en/release-0.3/stdlib/numbers/?highlight=random#random-numbers), [procesamiento de señales](http://docs.julialang.org/en/release-0.3/stdlib/math/?highlight=signal#signal-processing), y [procesamiento de cadenas](http://docs.julialang.org/en/release-0.3/stdlib/strings). Adicionalmente, la comunidad de [desarrolladores de Julia](https://github.com/JuliaLang/julia/graphs/contributors) contribuye un número de [paquetes externos](http://pkg.julialang.org) a través del gestor de paquetes integrado de Julia a un paso acelerado. [IJulia](https://github.com/JuliaLang/IJulia.jl), una colaboración entre las comunidades de [IPython](http://ipython.org) y Julia, provee de una poderosa interfaz gráfica basada en el [navegador para Julia](https://juliabox.org).
-```ruby
+En Julia los programas están organizados entorno al [despacho múltiple](http://docs.julialang.org/en/release-0.3/manual/methods/#man-methods); definiendo funciones y sobrecargándolas para diferentes combinaciones de tipos de argumentos, los cuales también pueden ser definidos por el usuario.
-# Comentarios de una línea comienzan con una almohadilla (o signo gato)
+### ¡Prueba Julia ahora mismo!
-#= Commentarios multilinea pueden escribirse
- usando '#=' antes de el texto y '=#'
- después del texto. También se pueden anidar.
+* [TryJupyter](https://try.jupyter.org)
+* [JuliaBox](https://juliabox.org)
+* [SageMathCloud](https://cloud.sagemath.com)
+
+### Resumen de Características:
+
+* [Despacho múltiple](http://en.wikipedia.org/wiki/Multiple_dispatch): permite definir el comportamiento de las funciones a través de múltiples combinaciones de tipos de argumentos (**métodos**).
+* Sistema de **tipado dinámico**: tipos para la documentación, la optimización y el despacho.
+* [Buen desempeño](http://julialang.org/benchmarks), comparado al de lenguajes **estáticamente compilados** como C.
+* [Gestor de paquetes](http://docs.julialang.org/en/release-0.3/stdlib/pkg) integrado.
+* [Macros tipo Lisp](http://docs.julialang.org/en/release-0.3/manual/metaprogramming/#macros) y otras comodidades para la [meta programación](http://docs.julialang.org/en/release-0.3/manual/metaprogramming).
+* Llamar funciones de otros lenguajes, mediante paquetes como: **Python** ([PyCall](https://github.com/stevengj/PyCall.jl)), [Mathematica](http://github.com/one-more-minute/Mathematica.jl), **Java** ([JavaCall](http://github.com/aviks/JavaCall.jl)), **R** ([Rif](http://github.com/lgautier/Rif.jl) y [RCall](http://github.com/JuliaStats/RCall.jl)) y **Matlab** ([MATLAB](http://github.com/JuliaLang/MATLAB.jl)).
+* [Llamar funciones de C y Fortran](http://docs.julialang.org/en/release-0.3/manual/calling-c-and-fortran-code) **directamente**: sin necesidad de usar envoltorios u APIs especiales.
+* Poderosas características de **línea de comandos** para [gestionar otros procesos](http://docs.julialang.org/en/release-0.3/manual/running-external-programs).
+* Diseñado para la [computación paralela y distribuida](http://docs.julialang.org/en/release-0.3/manual/parallel-computing) **desde el principio**.
+* [Corrutinas](http://en.wikipedia.org/wiki/Coroutine): hilos ligeros "**verdes**".
+* Los [tipos definidos por el usuario](http://docs.julialang.org/en/release-0.3/manual/types) son tan **rápidos y compactos** como los tipos estándar integrados.
+* [Generación automática de código](http://docs.julialang.org/en/release-0.3/stdlib/base/?highlight=%40code#internals) **eficiente y especializado** para diferentes tipos de argumentos.
+* [Conversiones y promociones](http://docs.julialang.org/en/release-0.3/manual/conversion-and-promotion) para tipos numéricos y de otros tipos, **elegantes y extensibles**.
+* Soporte eficiente para [Unicode](http://es.wikipedia.org/wiki/Unicode), incluyendo [UTF-8](http://es.wikipedia.org/wiki/UTF-8) pero sin limitarse solo a este.
+* [Licencia MIT](https://github.com/JuliaLang/julia/blob/master/LICENSE.md): libre y de código abierto.
+
+Esto se basa en la versión `0.3.11`.
+
+```julia
+# Los comentarios de una línea comienzan con una almohadilla (o signo de gato).
+
+#=
+ Los commentarios multilínea pueden escribirse
+ usando '#=' antes de el texto y '=#'
+ después del texto. También se pueden anidar.
=#
-####################################################
-## 1. Tipos de datos primitivos y operadores.
-####################################################
-# Todo en Julia es una expresión.
+##############################################
+# 1. Tipos de datos primitivos y operadores. #
+##############################################
+
+# Todo en Julia es una expresión (Expr).
# Hay varios tipos básicos de números.
-3 # => 3 (Int64)
-3.2 # => 3.2 (Float64)
-2 + 1im # => 2 + 1im (Complex{Int64})
-2//3 # => 2//3 (Rational{Int64})
+3 # => 3 # Int64
+3.2 # => 3.2 # Float64
+2 + 1im # => 2 + 1im # Complex{Int64}
+2 // 3 # => 2//3 # Rational{Int64}
# Todos los operadores infijos normales están disponibles.
-1 + 1 # => 2
-8 - 1 # => 7
-10 * 2 # => 20
-35 / 5 # => 7.0
-5/2 # => 2.5 # dividir un Int por un Int siempre resulta en un Float
-div (5, 2) # => 2 # para un resultado truncado, usa div
-5 \ 35 # => 7.0
-2 ^ 2 # => 4 # exponente, no es xor
-12 % 10 # => 2
-
-# Refuerza la precedencia con paréntesis
-(1 + 3) * 2 # => 8
-
-# Operadores a nivel de bit
-~2 # => -3 # bitwise not
-3 & 5 # => 1 # bitwise and
-2 | 4 # => 6 # bitwise or
-2 $ 4 # => 6 # bitwise xor
-2 >>> 1 # => 1 # logical shift right
-2 >> 1 # => 1 # arithmetic shift right
-2 << 1 # => 4 # logical/arithmetic shift left
-
-# Se puede utilizar la función bits para ver la representación binaria de un
-# número.
+1 + 1 # => 2
+8 - 1 # => 7
+10 * 2 # => 20
+35 / 5 # => 7.0 # dividir un Int por un Int siempre resulta
+ # en un Float
+5 / 2 # => 2.5
+div(5, 2) # => 2 # para un resultado truncado, usa la función div
+5 \ 35 # => 7.0
+2 ^ 2 # => 4 # exponente, no es XOR
+12 % 10 # => 2
+
+# Refuerza la precedencia con paréntesis.
+(1 + 3) * 2 # => 8
+
+# Operadores a nivel de bit.
+~2 # => -3 # bitwise NOT
+3 & 5 # => 1 # bitwise AND
+2 | 4 # => 6 # bitwise OR
+2 $ 4 # => 6 # bitwise XOR
+2 >>> 1 # => 1 # desplazamiento lógico hacia la derecha
+2 >> 1 # => 1 # desplazamiento aritmético hacia la derecha
+2 << 1 # => 4 # desplazamiento lógico/aritmético hacia la izquierda
+
+# Se puede utilizar la función bits para ver la representación
+# binaria de un número.
bits(12345)
# => "0000000000000000000000000000000000000000000000000011000000111001"
+
bits(12345.0)
# => "0100000011001000000111001000000000000000000000000000000000000000"
-# Valores 'boolean' (booleanos) son primitivos
-true
-false
-
-# Operadores Boolean (booleanos)
-!true # => false
-!false # => true
-1 == 1 # => true
-2 == 1 # => false
-1 != 1 # => false
-2 != 1 # => true
-1 < 10 # => true
-1 > 10 # => false
-2 <= 2 # => true
-2 >= 2 # => true
+# Los valores booleanos (Bool) son primitivos.
+true # => true
+false # => false
+
+# Operadores booleanos.
+!true # => false
+!false # => true
+1 == 1 # => true
+2 == 1 # => false
+1 != 1 # => false
+2 != 1 # => true
+1 < 10 # => true
+1 > 10 # => false
+2 <= 2 # => true
+2 >= 2 # => true
+
# ¡Las comparaciones pueden ser concatenadas!
-1 < 2 < 3 # => true
-2 < 3 < 2 # => false
+1 < 2 < 3 # => true
+2 < 3 < 2 # => false
-# Strings se crean con "
-"Esto es un string."
+# Los literales de cadenas (String) se crean con la comilla doble: "
+"Esto es una cadena."
-# Literales de caracteres se escriben con '
+# Los literales de caracteres (Char) se crean con la comilla simple: '
'a'
-# Una string puede ser indexado como una array de caracteres
-"Esto es un string."[1] # => 'E' # Índices en Julia empiezen del 1
-# Sin embargo, esto no va a funcionar bien para strings UTF8,
+# Una cadena puede ser indexada como una arreglo de caracteres.
+"Esto es un string."[1] # => 'E' # Los índices en Julia comienzan en: 1
+
+# Sin embargo, esto no va a funcionar bien para las cadenas UTF8 (UTF8String),
# Lo que se recomienda es la iteración (map, for, etc).
-# $ puede ser utilizado para la interpolación de strings:
-"2 + 2 = $(2 + 2)" # => "2 + 2 = 4"
-# Se puede poner cualquier expresión de Julia dentro los paréntesis.
+# $ puede ser utilizado para la interpolación de cadenas, se puede poner
+# cualquier expresión de Julia dentro los paréntesis.
+"2 + 2 = $(2 + 2)" # => "2 + 2 = 4"
+
+# Otra forma para formatear cadenas es usando el macro printf.
+@printf "%d es menor de %f\n" 4.5 5.3 # 5 es menor de 5.300000
-# Otro forma de formatear strings es el macro printf
-@printf "%d es menor de %f" 4.5 5.3 # 5 es menor de 5.300000
+# ¡Imprimir es muy fácil!
+println("¡Hola Julia!") # ¡Hola Julia!
-# Imprimir es muy fácil
-println("Soy Julia. ¡Encantado de conocerte!")
-####################################################
-## 2. Variables y Colecciones
-####################################################
+##############################
+# 2. Variables y Colecciones #
+##############################
# No hay necesidad de declarar las variables antes de asignarlas.
-una_variable = 5 # => 5
-una_variable # => 5
+una_variable = 5 # => 5
+una_variable # => 5
-# Acceder a variables no asignadas previamente es una excepción.
+# Acceder a una variable no asignada previamente es una excepción.
try
- otra_variable # => ERROR: some_other_var not defined
+ otra_variable # ERROR: otra_variable not defined
catch e
- println(e)
+ println(e) # UndefVarError(:otra_variable)
end
-# Los nombres de variables comienzan con una letra.
-# Después de eso, puedes utilizar letras, dígitos, guiones y signos de
+# Los nombres de variables comienzan con una letra o guion bajo: _.
+# Después de eso, puedes utilizar letras, dígitos, guiones bajos y signos de
# exclamación.
-OtraVariable123! = 6 # => 6
+otraVariable_123! = 6 # => 6
+
+# También puedes utilizar caracteres Unicode.
+☃ = 8 # => 8
-# También puede utilizar caracteres unicode
-☃ = 8 # => 8
# Estos son especialmente útiles para la notación matemática
-2 * π # => 6.283185307179586
-
-# Una nota sobre las convenciones de nomenclatura de Julia:
-#
-# * Los nombres de las variables aparecen en minúsculas, con separación de
-# palabra indicado por underscore ('\ _').
-#
-# * Los nombres de los tipos comienzan con una letra mayúscula y separación de
-# palabras se muestra con CamelCase en vez de underscore.
-#
-# * Los nombres de las funciones y los macros están en minúsculas, sin
-# underscore.
-#
-# * Funciones que modifican sus inputs tienen nombres que terminan en!. Estos
-# funciones a veces se llaman mutating functions o in-place functions.
-
-# Los Arrays almacenan una secuencia de valores indexados entre 1 hasta n
-a = Int64[] # => 0-element Int64 Array
-
-# Literales de arrays 1-dimensionales se pueden escribir con valores separados
-# por comas.
-b = [4, 5, 6] # => 3-element Int64 Array: [4, 5, 6]
-b[1] # => 4
-b[end] # => 6
-
-# Los arrays 2-dimensionales usan valores separados por espacios y filas
-# separados por punto y coma.
-matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4]
-
-# Añadir cosas a la final de una lista con push! y append!
-push!(a,1) # => [1]
-push!(a,2) # => [1,2]
-push!(a,4) # => [1,2,4]
-push!(a,3) # => [1,2,4,3]
-append!(a,b) # => [1,2,4,3,4,5,6]
-
-# Eliminar de la final con pop
-pop!(b) # => 6 y b ahora es [4,5]
-
-# Vamos a ponerlo de nuevo
-push!(b, 6) # b es ahora [4,5,6] de nuevo.
-
-a[1] # => 1 # recuerdan que los índices de Julia empiezan desde 1, no desde 0!
-
-# end es una abreviatura para el último índice. Se puede utilizar en cualquier
-# expresión de indexación
-a[end] # => 6
-
-# tambien hay shift y unshift
-shift!(a) # => 1 y a es ahora [2,4,3,4,5,6]
-unshift!(a,7) # => [7,2,4,3,4,5,6]
-
-# Nombres de funciónes que terminan en exclamaciones indican que modifican
-# su argumento.
-arr = [5,4,6] # => 3-element Int64 Array: [5,4,6]
-sort(arr) # => [4,5,6]; arr es todavía [5,4,6]
-sort!(arr) # => [4,5,6]; arr es ahora [4,5,6]
-
-# Buscando fuera de límites es un BoundsError
+# (multiplicación implicita).
+2π # => 6.283185307179586
+
+#=
+ Una nota sobre las convenciones de nomenclatura de Julia:
+
+ * Los nombres de las variables aparecen en minúsculas, con separación de
+ palabra indicado por un guion bajo:
+
+ otra_variable
+
+ * Los nombres de los tipos comienzan con una letra mayúscula y separación de
+ palabras se muestra con CamelCase en vez de guion bajo:
+
+ OtroTipo
+
+ * Los nombres de las funciones y los macros están en minúsculas, sin
+ underscore:
+
+ otromacro
+
+ * Funciones que modifican sus entradas tienen nombres que terminan en: !.
+ Estas funciones a veces se les llaman funciones transformadoras o
+ funciones in situ:
+
+ otra_funcion!
+=#
+
+# Los arreglos (Array) almacenan una secuencia de valores indexados de entre 1 hasta n.
+a = Int64[] # => 0-element Array{Int64,1}
+
+# Los literales de arregos unidimensionales se pueden escribir con valores
+# separados por comas.
+b = [4, 5, 6]
+#=
+ => 3-element Array{Int64,1}:
+ 4
+ 5
+ 6
+=#
+b[1] # => 4
+b[end] # => 6
+
+# Los arreglos bidimensionales usan valores separados por espacios y filas
+# separadas por punto y coma.
+matrix = [1 2; 3 4]
+#=
+ => 2x2 Array{Int64,2}:
+ 1 2
+ 3 4
+=#
+
+# Añadir cosas a la final de un arreglo con push! y append!.
+push!(a, 1) # => [1]
+push!(a, 2) # => [1,2]
+push!(a, 4) # => [1,2,4]
+push!(a, 3) # => [1,2,4,3]
+append!(a, b) # => [1,2,4,3,4,5,6]
+
+# Eliminar del final con pop!.
+pop!(b) # => 6 y b ahora es: [4,5]
+
+# Vamos a ponerlo de nuevo.
+push!(b, 6) # b es ahora [4,5,6] de nuevo
+
+a[1] # => 1 # recuerda, los índices de Julia empiezan desde 1, no desde 0!
+
+# end es una abreviatura para el último índice. Se puede utilizar en cualquier
+# expresión de indexación.
+a[end] # => 6
+
+# También hay shift! y unshift!.
+shift!(a) # => 1 y a es ahora: [2,4,3,4,5,6]
+unshift!(a, 7) # => [7,2,4,3,4,5,6]
+
+# Los nombres de funciónes que terminan en exclamaciones indican que modifican
+# su o sus argumentos de entrada.
+arr = [5, 4, 6] # => 3-element Array{Int64,1}: [5,4,6]
+sort(arr) # => [4,5,6] y arr es todavía: [5,4,6]
+sort!(arr) # => [4,5,6] y arr es ahora: [4,5,6]
+
+# Buscando fuera de límites es un BoundsError.
try
- a[0] # => ERROR: BoundsError() in getindex at array.jl:270
- a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270
+ a[0] # ERROR: BoundsError() in getindex at array.jl:270
+ a[end+1] # ERROR: BoundsError() in getindex at array.jl:270
catch e
- println(e)
+ println(e) # BoundsError()
end
-# Errors dan la línea y el archivo de su procedencia, aunque sea en el standard
-# library. Si construyes Julia de source, puedes buscar en el source para
-# encontrar estos archivos.
+# Las excepciones y los errores dan la línea y el archivo de su procedencia,
+# aunque provenga de la librería estándar. Si compilas Julia del código fuente,
+# puedes buscar en el código para encontrar estos archivos.
+
+# Se puede inicializar un arreglo con un rango (Range).
+a = [1:5] # => 5-element Array{Int64,1}: [1,2,3,4,5]
-# Se puede inicializar arrays de un range
-a = [1:5] # => 5-element Int64 Array: [1,2,3,4,5]
+# Puedes mirar en los rangos con la sintaxis de rebanada.
+a[1:3] # => [1,2,3]
+a[2:end] # => [2,3,4,5]
-# Puedes mirar en ranges con sintaxis slice.
-a[1:3] # => [1, 2, 3]
-a[2:end] # => [2, 3, 4, 5]
+# Eliminar elementos de un arreglo por índice con splice!
+arr = [3, 4, 5]
+splice!(arr, 2) # => 4 y arr es ahora: [3,5]
-# Eliminar elementos de una array por índice con splice!
-arr = [3,4,5]
-splice!(arr,2) # => 4 ; arr es ahora [3,5]
+# Concatenar arreglos con append!
+b = [1, 2, 3]
+append!(a, b) # a ahora es: [1,2,3,4,5,1,2,3]
-# Concatenar listas con append!
-b = [1,2,3]
-append!(a,b) # ahroa a es [1, 2, 3, 4, 5, 1, 2, 3]
+# Comprueba la existencia de un elemento en un arreglo con in.
+in(1, a) # => true
-# Comprueba la existencia en una lista con in
-in(1, a) # => true
+# Examina la longitud con length.
+length(a) # => 8
-# Examina la longitud con length
-length(a) # => 8
+# Las tuplas (Tuple) son inmutables.
+tup = (1, 2, 3) # => (1,2,3) # una tupla tipo (Int64,Int64,Int64)
+tup[1] # => 1
-# Tuples son immutable.
-tup = (1, 2, 3) # => (1,2,3) # un (Int64,Int64,Int64) tuple.
-tup[1] # => 1
try:
- tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64)
+ tup[1] = 3 # ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64)
catch e
- println(e)
+ println(e) # MethodError(setindex!,(:tup,3,1))
end
-# Muchas funciones de lista también trabajan en las tuples
-length(tup) # => 3
-tup[1:2] # => (1,2)
-in(2, tup) # => true
+# Muchas funciones de arreglos también trabajan en con las tuplas.
+length(tup) # => 3
+tup[1:2] # => (1,2)
+in(2, tup) # => true
-# Se puede desempacar tuples en variables
-a, b, c = (1, 2, 3) # => (1,2,3) # a is now 1, b is now 2 and c is now 3
+# Se pueden desempacar las tuplas en variables individuales.
+a, b, c = (1, 2, 3) # => (1,2,3) # ahora a es 1, b es 2 y c es 3
-# Los tuples se crean, incluso si se omite el paréntesis
-d, e, f = 4, 5, 6 # => (4,5,6)
+# Los tuplas se crean, incluso si se omiten los paréntesis.
+d, e, f = 4, 5, 6 # => (4,5,6)
-# Un tuple 1-elemento es distinto del valor que contiene
-(1,) == 1 # => false
-(1) == 1 # => true
+# Una tupla de un elemento es distinta del valor que contiene.
+(1,) == 1 # => false
+(1) == 1 # => true
-# Mira que fácil es cambiar dos valores
-e, d = d, e # => (5,4) # d is now 5 and e is now 4
+# Mira que fácil es cambiar dos valores!
+e, d = d, e # => (5,4) # ahora d es 5 y e es 4
+# Los diccionarios (Dict) son arreglos asociativos.
+dicc_vacio = Dict() # => Dict{Any,Any} with 0 entries
-# Dictionaries almanecan mapeos
-dict_vacio = Dict() # => Dict{Any,Any}()
+# Se puede crear un diccionario usando una literal.
+dicc_lleno = ["uno" => 1, "dos" => 2, "tres" => 3]
+#=
+ => Dict{ASCIIString,Int64} with 3 entries:
+ "tres" => 3
+ "dos" => 2
+ "uno" => 1
+=#
+
+# Busca valores con: [].
+dicc_lleno["uno"] # => 1
+
+# Obtén todas las claves con.
+keys(dicc_lleno)
+#=
+ => KeyIterator for a Dict{ASCIIString,Int64} with 3 entries. Keys:
+ "tres"
+ "dos"
+ "uno"
+=#
-# Se puede crear un dictionary usando un literal
-dict_lleno = ["one"=> 1, "two"=> 2, "three"=> 3]
-# => Dict{ASCIIString,Int64}
+# Nota: los elementos del diccionario no están ordenados y no se guarda el orden
+# en que se insertan.
-# Busca valores con []
-dict_lleno["one"] # => 1
+# Obtén todos los valores.
+values(dicc_lleno)
+#=
+ => ValueIterator for a Dict{ASCIIString,Int64} with 3 entries. Values:
+ 3
+ 2
+ 1
+=#
-# Obtén todas las claves
-keys(dict_lleno)
-# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2])
-# Nota - claves del dictionary no están ordenados ni en el orden en que se
-# insertan.
+# Nota: igual que el anterior en cuanto a ordenamiento de los elementos.
-# Obtén todos los valores
-values(dict_lleno)
-# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2])
-# Nota - Igual que el anterior en cuanto a ordenamiento de claves.
+# Comprueba si una clave existe en un diccionario con in y haskey.
+in(("uno", 1), dicc_lleno) # => true
+in(("tres", 3), dicc_lleno) # => false
-# Compruebe si hay existencia de claves en un dictionary con in y haskey
-in(("uno", 1), dict_lleno) # => true
-in(("tres", 3), dict_lleno) # => false
-haskey(dict_lleno, "one") # => true
-haskey(dict_lleno, 1) # => false
+haskey(dicc_lleno, "uno") # => true
+haskey(dicc_lleno, 1) # => false
-# Tratando de buscar una clave que no existe producirá un error
+# Tratar de obtener un valor con una clave que no existe producirá un error.
try
- dict_lleno["dos"] # => ERROR: key not found: dos in getindex at dict.jl:489
+ # ERROR: key not found: cuatro in getindex at dict.jl:489
+ dicc_lleno["cuatro"]
catch e
- println(e)
+ println(e) # KeyError("cuatro")
end
-# Utilice el método get para evitar ese error proporcionando un valor
-# predeterminado
-# get(dictionary,key,default_value)
-get(dict_lleno,"one",4) # => 1
-get(dict_lleno,"four",4) # => 4
+# Utiliza el método get para evitar este error proporcionando un valor
+# predeterminado: get(diccionario, clave, valor_predeterminado).
+get(dicc_lleno, "uno", 4) # => 1
+get(dicc_lleno, "cuatro", 4) # => 4
+
+# Usa conjuntos (Set) para representar colecciones de valores únicos, no
+# ordenados.
+conjunto_vacio = Set() # => Set{Any}({})
-# Usa Sets para representar colecciones (conjuntos) de valores únicos, no
-# ordenadas
-conjunto_vacio = Set() # => Set{Any}()
-# Iniciar una set de valores
-conjunto_lleno = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4)
+# Iniciar una conjunto de valores.
+conjunto_lleno = Set(1, 2, 2, 3, 4) # => Set{Int64}({4,2,3,1})
-# Añadir más valores a un conjunto
-push!(conjunto_lleno,5) # => Set{Int64}(5,4,2,3,1)
-push!(conjunto_lleno,5) # => Set{Int64}(5,4,2,3,1)
+# Añadir más valores a un conjunto.
+push!(conjunto_lleno, 5) # => Set{Int64}({4,2,3,5,1})
+push!(conjunto_lleno, 5) # => Set{Int64}({4,2,3,5,1})
-# Compruebe si los valores están en el conjunto
-in(2, conjunto_lleno) # => true
-in(10, conjunto_lleno) # => false
+# Comprobar si los valores están en el conjunto.
+in(2, conjunto_lleno) # => true
+in(10, conjunto_lleno) # => false
-# Hay funciones de intersección de conjuntos, la unión, y la diferencia.
-conjunto_otro= Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3)
-intersect(conjunto_lleno, conjunto_otro) # => Set{Int64}(3,4,5)
-union(conjunto_lleno, conjunto_otro) # => Set{Int64}(1,2,3,4,5,6)
-setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4)
+# Hay funciones de intersección, unión y diferencia de conjuntos.
+otro_conjunto = Set(3, 4, 5, 6) # => Set{Int64}({6,4,5,3})
+intersect(conjunto_lleno, otro_conjunto) # => Set{Int64}({3,4,5})
+union(conjunto_lleno, otro_conjunto) # => Set{Int64}({1,2,3,4,5,6})
+setdiff(Set(1, 2, 3, 4), Set(2, 3, 5)) # => Set{Int64}({1,4})
-####################################################
-## 3. Control de Flujo
-####################################################
+#######################
+# 3. Control de Flujo #
+#######################
-# Hagamos una variable
+# Hagamos una variable.
una_variable = 5
-# Aquí está una declaración de un 'if'. La indentación no es significativa en
-# Julia
+# Aquí está la declaración de un if. La indentación no es significativa en
+# Julia.
if una_variable > 10
- println("una_variable es completamente mas grande que 10.")
-elseif una_variable < 10 # Este condición 'elseif' es opcional.
- println("una_variable es mas chica que 10.")
-else # Esto también es opcional.
- println("una_variable es de hecho 10.")
+ println("una_variable es completamente mayor que 10.")
+elseif una_variable < 10 # esta condición elseif es opcional
+ println("una_variable es menor que 10.")
+else # esto también es opcional
+ println("De echo una_variable es 10.")
end
-# => imprime "una_variable es mas chica que 10."
+# imprime: una_variable es menor que 10.
-# For itera sobre tipos iterables
-# Tipos iterables incluyen Range, Array, Set, Dict, y String.
-for animal=["perro", "gato", "raton"]
- println("$animal es un mamifero")
- # Se puede usar $ para interpolar variables o expresiónes en strings
+# El bucle for itera sobre tipos iterables, ie. Range, Array, Set,
+# Dict y String.
+for animal in ["perro", "gato", "ratón"]
+ # Se puede usar $ para interpolar variables o expresiones en ls cadenas.
+ println("$animal es un mamífero.")
end
-# imprime:
-# perro es un mamifero
-# gato es un mamifero
-# raton es un mamifero
+#=
+ imprime:
+ perro es un mamífero.
+ gato es un mamífero.
+ ratón es un mamífero.
+=#
-for a in ["perro"=>"mamifero","gato"=>"mamifero","raton"=>"mamifero"]
- println("$(a[1]) es un $(a[2])")
+for a in ["perro" => "mamífero", "gato" => "mamífero", "ratón" => "mamífero"]
+ println("$(a[1]) es un $(a[2]).")
end
-# imprime:
-# perro es un mamifero
-# gato es un mamifero
-# raton es un mamifero
+#=
+ imprime:
+ perro es un mamífero.
+ gato es un mamífero.
+ ratón es un mamífero.
+=#
-for (k,v) in ["perro"=>"mamifero", "gato"=>"mamifero", "raton"=>"mamifero"]
- println("$k es un $v")
+for (k,v) in ["perro"=>"mamífero", "gato"=>"mamífero", "ratón"=>"mamífero"]
+ println("$k es un $v.")
end
-# imprime:
-# perro es un mamifero
-# gato es un mamifero
-# raton es un mamifero
+#=
+ imprime:
+ perro es un mamífero.
+ gato es un mamífero.
+ ratón es un mamífero.
+=#
-# While itera hasta que una condición no se cumple.
+# El bucle while itera hasta que una condición se deje de cumplir.
x = 0
while x < 4
println(x)
- x += 1 # versión corta de x = x + 1
+ x += 1 # versión corta de: x = x + 1
end
-# imprime:
-# 0
-# 1
-# 2
-# 3
+#=
+imprime:
+ 0
+ 1
+ 2
+ 3
+=#
-# Maneja excepciones con un bloque try/catch
-try
- error("ayuda")
+# Maneja excepciones con un bloque try/catch.
+try # intentar
+ error("Ooops!")
catch e
- println("capturando $e")
+ println("capturando: $e") # capturando: ErrorException("Ooops!")
end
-# => capturando ErrorException("ayuda")
-####################################################
-## 4. Funciones
-####################################################
+################
+# 4. Funciones #
+################
-# Usa 'function' para crear nuevas funciones
+# Usa function para crear nuevas funciones.
-#function nombre(arglist)
-# cuerpo...
-#end
+#=
+ function nombre(arglist)
+ cuerpo...
+ end
+=#
function suma(x, y)
println("x es $x e y es $y")
- # Las funciones devuelven el valor de su última declaración
+ # las funciones devuelven el valor de su última expresión
x + y
end
+# => suma (generic function with 1 method)
-suma(5, 6) # => 11 # después de imprimir "x es 5 e y es de 6"
+suma(5, 6) # => 11 # después de imprimir: x es 5 e y es 6
+
+# También puedes usar esta otra sintaxis para definir funciones!
+resta(x, y) = x - y # => resta (generic function with 1 method)
# Puedes definir funciones que toman un número variable de
-# argumentos posicionales
+# argumentos posicionales (el ... se llama un splat).
function varargs(args...)
+ # Usa la palabra clave return para regresar desde cualquier
+ # lugar de la función.
return args
- # Usa la palabra clave return para devolver en cualquier lugar de la función
end
# => varargs (generic function with 1 method)
-varargs(1,2,3) # => (1,2,3)
+varargs(1, 2, 3) # => (1,2,3)
+varargs([1, 2, 3]) # => ([1,2,3],)
-# El ... se llama un splat.
-# Acabamos de utilizar lo en una definición de función.
-# También se puede utilizar en una llamada de función,
-# donde va splat un Array o el contenido de un Tuple en la lista de argumentos.
-Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # Produce un Set de Arrays
-Set([1,2,3]...) # => Set{Int64}(1,2,3) # esto es equivalente a Set(1,2,3)
+# Acabamos de utilizar el splat (...) en la definición de una función. También
+# se puede utilizar al llamar a una función, donde se esparce un arreglo, tupla
+# o en general una secuencia iterable en la tupla de argumentos.
+varargs([1, 2, 3]...) # => (1,2,3) # igual que: varargs(1, 2, 3)
-x = (1,2,3) # => (1,2,3)
-Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # un Set de Tuples
-Set(x...) # => Set{Int64}(2,3,1)
+x = (1, 2, 3) # => (1,2,3)
+varargs(x) # => ((1,2,3),)
+varargs(x...) # => (1,2,3)
+varargs("abc"...) # => ('a','b','c')
-# Puede definir funciones con argumentos posicionales opcionales
-function defaults(a,b,x=5,y=6)
+# Puedes definir funciones con argumentos posicionales opcionales.
+function defaults(a, b, x=5, y=6)
return "$a $b y $x $y"
end
+# => defaults (generic function with 3 methods)
+
+defaults('h', 'g') # => "h g y 5 6"
+defaults('h', 'g', 'j') # => "h g y j 6"
+defaults('h', 'g', 'j', 'k') # => "h g y j k"
-defaults('h','g') # => "h g y 5 6"
-defaults('h','g','j') # => "h g y j 6"
-defaults('h','g','j','k') # => "h g y j k"
try
- defaults('h') # => ERROR: no method defaults(Char,)
- defaults() # => ERROR: no methods defaults()
+ defaults('h') # ERROR: `defaults` has no method matching defaults(::Char)
+ defaults() # ERROR: `defaults` has no method matching defaults()
catch e
- println(e)
+ println(e) # MethodError(defaults,('h',))
end
-# Puedes definir funciones que toman argumentos de palabra clave
-function args_clave(;k1=4,nombre2="hola") # note the ;
- return ["k1"=>k1,"nombre2"=>nombre2]
+# Puedes definir funciones que tomen argumentos de palabras clave.
+function args_clave(;k1=4, nombre2="hola") # nota el punto y coma: ;
+ return ["k1" => k1, "nombre2" => nombre2]
end
+# => args_clave (generic function with 1 method)
-args_clave(nombre2="ness") # => ["nombre2"=>"ness","k1"=>4]
-args_clave(k1="mine") # => ["k1"=>"mine","nombre2"=>"hola"]
-args_clave() # => ["nombre2"=>"hola","k1"=>4]
+args_clave(nombre2="ness") # => ["nombre2"=>"ness","k1"=>4]
+args_clave(k1="mine") # => ["k1"=>"mine","nombre2"=>"hola"]
+args_clave() # => ["nombre2"=>"hola","k1"=>4]
-# Puedes combinar todo tipo de argumentos en la misma función
-function todos_los_args(arg_normal, arg_posicional_opcional=2; arg_clave="foo")
- println("argumento normal: $arg_normal")
- println("argumento optional: $arg_posicional_opcional")
- println("argumento de clave: $arg_clave")
+# Puedes combinar todo tipo de argumentos en la misma función.
+function todos_los_args(arg_posicional, arg_opcional=2; arg_clave="foo")
+ println("argumento posicional: $arg_posicional")
+ println(" argumento opcional: $arg_opcional")
+ println(" argumento clave: $arg_clave")
end
+# => todos_los_args (generic function with 2 methods)
+# No se necesita punto y coma ; al llamar la función usando un argumento clave,
+# esto solo es necesario en la definición de la función.
todos_los_args(1, 3, arg_clave=4)
-# imprime:
-# argumento normal: 1
-# argumento optional: 3
-# argumento de clave: 4
+#=
+ imprime:
+ argumento posicional: 1
+ argumento opcional: 3
+ argumento clave: 4
+=#
-# Julia tiene funciones de primera clase
+# Julia tiene funciones de primera clase.
function crear_suma(x)
- suma = function (y)
+ suma = function (y) # función anónima
return x + y
end
return suma
end
+# => crear_suma (generic function with 1 method)
-# Esta es el sintaxis "stabby lambda" para crear funciones anónimas
-(x -> x > 2)(3) # => true
+# Esta es otra sintaxis (estilo cálculo lambda), para crear funciones anónimas.
+(x -> x > 2)(3) # => true
# Esta función es idéntica a la crear_suma implementación anterior.
-function crear_suma(x)
- y -> x + y
-end
+crear_suma(x) = y -> x + y
-# También puedes nombrar la función interna, si quieres
+# También puedes nombrar la función interna, si quieres.
function crear_suma(x)
function suma(y)
x + y
end
suma
end
+# => crear_suma (generic function with 1 method)
-suma_10 = crear_suma(10)
-suma_10(3) # => 13
+suma_10 = crear_suma(10) # => suma (generic function with 1 method)
+suma_10(3) # => 13
+# Hay funciones integradas de orden superior.
+map(suma_10, [1, 2, 3]) # => [11,12,13]
+filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6,7]
-# Hay funciones integradas de orden superior
-map(suma_10, [1,2,3]) # => [11, 12, 13]
-filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
+# Se puede pasar un bloque a las funciones cuyo primer argumento posicional
+# es otra función, como en map y filter.
+map([1, 2, 3]) do arr
+ suma_10(arr)
+end
+#=
+ => 3-element Array{Int64,1}:
+ 11
+ 12
+ 13
+=#
+
+filter([3, 4, 5, 6, 7]) do arr
+ (x -> x > 5)(arr)
+end
+#=
+ => 2-element Array{Int64,1}:
+ 6
+ 7
+=#
-# Podemos usar listas por comprensión para mapeos
-[suma_10(i) for i=[1, 2, 3]] # => [11, 12, 13]
-[suma_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
+# Podemos usar comprensiones de listas multidimensionales.
+[suma_10(i) for i = [1, 2, 3]] # => [11, 12, 13] # 1D
+[suma_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
-####################################################
-## 5. Tipos
-####################################################
+[i*j for i = [1:3], j in [1:3]] # 2D
+#=
+ => 3x3 Array{Int64,2}:
+ 1 2 3
+ 2 4 6
+ 3 6 9
+=#
+
+[i*j/k for i = [1:3], j = [1:3], k in [1:3]] # 3D
+#=
+ => 3x3x3 Array{Float64,3}:
+ [:, :, 1] =
+ 1.0 2.0 3.0
+ 2.0 4.0 6.0
+ 3.0 6.0 9.0
+
+ [:, :, 2] =
+ 0.5 1.0 1.5
+ 1.0 2.0 3.0
+ 1.5 3.0 4.5
+
+ [:, :, 3] =
+ 0.333333 0.666667 1.0
+ 0.666667 1.33333 2.0
+ 1.0 2.0 3.0
+=#
+
+
+############
+# 5. Tipos #
+############
-# Julia tiene sistema de tipos.
# Cada valor tiene un tipo y las variables no tienen propios tipos.
-# Se puede utilizar la función `typeof` para obtener el tipo de un valor.
-typeof(5) # => Int64
+# Se puede utilizar la función typeof para obtener el tipo de un valor.
+typeof(5) # => Int64 # en un sistema de 64 bits, de lo contrario: Int32
-# Los tipos son valores de primera clase
-typeof(Int64) # => DataType
-typeof(DataType) # => DataType
-# DataType es el tipo que representa los tipos, incluyéndose a sí mismo.
+# Los tipos son valores de primera clase, DataType es el tipo que representa a
+# los tipos, incluyéndose a sí mismo.
+typeof(Int64) # => DataType
+typeof(DataType) # => DataType
-# Los tipos se usan para la documentación, optimizaciones, y envio.
-# No están comprobados estáticamente.
+# Los tipos se usan para la documentación, para optimizaciones
+# y el despacho múltiple. No están comprobados estáticamente.
-# Los usuarios pueden definir tipos
-# Son como registros o estructuras en otros idiomas.
-# Nuevos tipos se definen utilizado la palabra clave `type`.
+# Los usuarios pueden definir sus propios tipos.
+# Son como registros o estructuras en otros idiomas.
+# Un nuevo tipos se define utilizado la palabra clave type.
# type Nombre
-# field::OptionalType
+# atributo::UnTipo # las anotaciones de tipos son opcionales
# ...
# end
type Tigre
- longituddecola::Float64
- colordelpelaje # no incluyendo una anotación de tipo es el mismo que `::Any`
+ longitud_cola::Float64
+ color_pelaje # sin una anotación de tipo, es lo mismo que `::Any`
end
-# Los argumentos del constructor por default son las propiedades
-# del tipo, en el orden en que están listados en la definición
-tigger = Tigre(3.5,"anaranjado") # => Tiger(3.5,"anaranjado")
+# Los argumentos del constructor por defecto son los atributos
+# del tipo, en el orden en que están listados en la definición.
+tigre = Tigre(3.5, "anaranjado") # => Tigre(3.5,"anaranjado")
-# El tipo funciona como la función constructora de valores de ese tipo
-sherekhan = typeof(tigger)(5.6,"fuego") # => Tiger(5.6,"fuego")
+# El tipo funciona como método constructor para los valores de ese tipo.
+sherekhan = typeof(tigre)(5.6, "fuego") # => Tigre(5.6,"fuego")
-# Este estilo de tipos son llamados tipos concrete
-# Se pueden crear instancias, pero no pueden tener subtipos.
-# La otra clase de tipos es tipos abstractos (abstract types).
+# Este estilo de tipos son llamados tipos concretos.
+# Se pueden crear instancias de estos, pero no pueden tener subtipos.
+# La otra clase de tipos son los tipos abstractos.
# abstract Nombre
-abstract Gato # sólo un nombre y un punto en la jerarquía de tipos
-
-# De los tipos Abstract no se pueden crear instancias, pero pueden tener
-# subtipos. Por ejemplo, Number es un tipo abstracto.
-subtypes(Number) # => 6-element Array{Any,1}:
- # Complex{Float16}
- # Complex{Float32}
- # Complex{Float64}
- # Complex{T<:Real}
- # Real
-subtypes(Gato) # => 0-element Array{Any,1}
-
-# Cada tipo tiene un supertipo, utilice la función `súper` para conseguirlo.
-typeof(5) # => Int64
-super(Int64) # => Signed
-super(Signed) # => Real
-super(Real) # => Number
-super(Number) # => Any
-super(super(Signed)) # => Number
-super(Any) # => Any
-# Todo de estos tipos, a excepción de Int64, son abstractos.
-
-# <: es el operador de subtipos
-type Leon <: Gato # Leon es un subtipo de Gato
- color_de_crin
- rugido::String
-end
+abstract Gato # sólo un nombre y un punto en la jerarquía de tipos
+
+# No se pueden crear instancias de los tipos abstractos, pero pueden tener
+# subtipos. Por ejemplo, Number es un tipo abstracto.
+subtypes(Number)
+#=
+ => 2-element Array{Any,1}:
+ Complex{T<:Real}
+ Real
+=#
+
+subtypes(Gato) # => 0-element Array{Any,1}
+
+# Cada tipo tiene un supertipo, utiliza la función súper para conseguirlo.
+typeof(5) # => Int64
+super(Int64) # => Signed
+super(Signed) # => Integer
+super(Integer) # => Real
+super(Real) # => Number
+super(Number) # => Any
+super(super(Signed)) # => Real
+super(Any) # => Any
-# Se puede definir más constructores para su tipo.
-# Sólo defina una función del mismo nombre que el tipo
-# y llame a un constructor existente para obtener un valor del tipo correcto
-Leon(rugido::String) = Leon("verde",rugido)
-# Este es un constructor externo porque es fuera de la definición del tipo
-
-type Pantera <: Gato # Pantera tambien es un a subtipo de Cat
- color_de_ojos
- Pantera() = new("verde")
- # Panteras sólo tendrán este constructor, y ningún constructor
- # predeterminado.
+# Todos estos tipos, a excepción de Int64, son abstractos.
+
+# <: es el operador de subtipos.
+type Leon <: Gato # Leon es un subtipo de Gato
+ color_crin
+ rugido::String
end
-# Utilizar constructores internos, como Panther hace, te da control sobre cómo
-# se pueden crear valores del tipo. Cuando sea posible, debes utilizar
-# constructores exteriores en lugar de los internos.
-####################################################
-## 6. Envio múltiple
-####################################################
+# Se pueden definir más constructores para un tipo.
+# Sólo define una función del mismo nombre que el tipo y llama al constructor
+# existente para obtener un valor del tipo correcto.
-# En Julia, todas las funciones nombradas son funciones genéricas.
-# Esto significa que se construyen a partir de muchos métodos pequeños
-# Cada constructor de Leon es un método de la función genérica Leon.
+# Este es un constructor externo porque es fuera de la definición del tipo.
+Leon(rugido::String) = Leon("verde", rugido)
-# Por ejemplo, vamos a hacer un maullar función:
+type Pantera <: Gato # Pantera también es un a subtipo de Gato
+ color_ojos
-# Definiciones para Leon, Pantera, y Tigre
-function maullar(animal::Leon)
- animal.rugido # acceso utilizando notación de puntos
+ # Pantera sólo tendrá este constructor, y ningún constructor predeterminado.
+ Pantera() = new("verde")
end
-function maullar(animal::Pantera)
- "grrr"
-end
+# Utilizar constructores internos, como se hace en Pantera, te da control sobre
+# cómo se pueden crear valores de este tipo. Cuando sea posible, debes utilizar
+# constructores externos en lugar de internos.
-function maullar(animal::Tigre)
- "rawwwr"
-end
-# Prueba de la función maullar
-maullar(tigger) # => "rawwr"
-maullar(Leon("cafe","ROAAR")) # => "ROAAR"
-maullar(Pantera()) # => "grrr"
+########################
+# 6. Despacho Múltiple #
+########################
-# Revisar la jerarquía de tipos locales
-issubtype(Tigre,Gato) # => false
-issubtype(Leon,Gato) # => true
-issubtype(Pantera,Gato) # => true
+# En Julia, todas las funciones nombradas son funciones genéricas.
+# Esto significa que se construyen a partir de muchos métodosmás pequeños.
+# Cada constructor de Leon es un método de la función genérica Leon.
-# Definición de una función que toma Gatos
-function mascota(gato::Gato)
- println("El gato dice $(maullar(gato))")
-end
+# Por ejemplo, vamos a hacer métodos para para Leon, Pantera, y Tigre de una
+# función genérica maullar:
+
+# acceso utilizando notación de puntos
+maullar(animal::Leon) = animal.rugido
+# => maullar (generic function with 1 method)
+maullar(animal::Pantera) = "grrr"
+# => maullar (generic function with 2 methods)
+maullar(animal::Tigre) = "rawwwr"
+# => maullar (generic function with 3 methods)
+
+# Se puede obtener una lista de métodos con la función methods.
+methods(maullar)
+#=
+ # 3 methods for generic function "maullar":
+ maullar(animal::Leon) at none:1
+ maullar(animal::Pantera) at none:1
+ maullar(animal::Tigre) at none:1
+=#
+
+# Prueba de la función maullar.
+maullar(tigre) # => "rawwwr"
+maullar(Leon("cafe", "ROAAR")) # => "ROAAR"
+maullar(Pantera()) # => "grrr"
+
+# Revisar la jerarquía de tipos locales.
+issubtype(Tigre, Gato) # => false # igual que: Tigre <: Gato
+issubtype(Leon, Gato) # => true # igual que: Leon <: Gato
+issubtype(Pantera, Gato) # => true
+
+# Definición de una función que acepta argumentos de tipo Gato.
+mascota(gato::Gato) = println("El gato dice $(maullar(gato))")
+
+mascota(Leon("42")) # El gato dice 42
-mascota(Leon("42")) # => imprime "El gato dice 42"
try
- mascota(tigger) # => ERROR: no method mascota(Tigre))
+ mascota(tigre) # ERROR: `mascota` has no method matching mascota(::Tigre)
catch e
- println(e)
+ println(e) # MethodError(mascota,(Tigre(3.5,"anaranjado"),))
end
-# En los lenguajes orientados a objetos, expedición única es común. Esto
-# significa que el método se recogió basándose en el tipo del primer argumento.
-# En Julia, todos los tipos de argumentos contribuyen a seleccionar el mejor
-# método.
+# En los lenguajes orientados a objetos, el despacho simple es común. Esto
+# significa que la implementación del método a llamar se selecciona en base
+# al tipo del primer argumento.
+
+# En Julia, los tipos de todos los argumentos contribuyen a seleccionar método
+# más específico.
# Vamos a definir una función con más argumentos, para que podamos ver la
# diferencia
-function pelear(t::Tigre,c::Gato)
- println("¡El tigre $(t.colordelpelaje) gana!")
-end
+pelear(t::Tigre, c::Gato) = println("¡El tigre $(t.color_pelaje) gana!")
# => pelear (generic function with 1 method)
-pelear(tigger,Pantera()) # => imprime ¡El tigre anaranjado gana!
-pelear(tigger,Leon("ROAR")) # => ¡El tigre anaranjado gana!
+pelear(tigre, Pantera()) # ¡El tigre anaranjado gana!
+pelear(tigre, Leon("ROAR")) # ¡El tigre anaranjado gana!
-# Vamos a cambiar el comportamiento cuando el Gato es específicamente un Leon
-pelear(t::Tigre,l::Leon) = println("El león con melena $(l.color_de_crin) gana")
+# Vamos a cambiar el comportamiento cuando el Gato sea específicamente un Leon.
+pelear(t::Tigre, l::Leon) = println("El león con melena $(l.color_crin) gana.")
# => pelear (generic function with 2 methods)
-pelear(tigger,Pantera()) # => imprime ¡El tigre anaranjado gana!
-pelear(tigger,Leon("ROAR")) # => imprime El león con melena verde gana
+pelear(tigre, Pantera()) # ¡El tigre anaranjado gana!
+pelear(tigre, Leon("ROAR")) # El león con melena verde gana.
-# No necesitamos un tigre para poder luchar
-pelear(l::Leon,c::Gato) = println("El gato victorioso dice $(maullar(c))")
-# => fight (generic function with 3 methods)
+# No necesitamos un tigre para poder luchar.
+pelear(l::Leon, c::Gato) = println("El gato victorioso dice $(maullar(c)).")
+# => pelear (generic function with 3 methods)
+
+methods(pelear)
+#=
+ # 3 methods for generic function "pelear":
+ pelear(t::Tigre,l::Leon) at none:2
+ pelear(t::Tigre,c::Gato) at none:1
+ pelear(l::Leon,c::Gato) at none:2
+=#
-pelear(Leon("balooga!"),Pantera()) # => imprime El gato victorioso dice grrr
+pelear(Leon("balooga!"), Pantera()) # El gato victorioso dice grrr.
try
- pelear(Pantera(),Leon("RAWR")) # => ERROR: no method pelear(Pantera, Leon))
-catch
+ # ERROR: `pelear` has no method matching pelear(::Pantera, ::Leon)
+ pelear(Pantera(),Leon("RAWR"))
+catch # no hacer nada con la excepción atrapada
end
-# Un metodo con el gato primero
+# Un metodo con el tipo Gato primero.
pelear(c::Gato,l::Leon) = println("El gato le gana al León")
-# Warning: New definition
-# pelear(Gato,Leon) at none:1
-# is ambiguous with:
-# pelear(Leon,Gato) at none:1.
-# To fix, define
-# pelear(Leon,Leon)
-# before the new definition.
-# pelear (generic function with 4 methods)
-
-# Esta advertencia se debe a que no está claro que metodo de pelear será llamado
-# en:
-pelear(Leon("RAR"),Leon("cafe","rar")) # => imprime El gato victorioso dice rar
-# El resultado puede ser diferente en otras versiones de Julia
+#=
+ Warning: New definition
+ pelear(Gato,Leon) at none:1
+ is ambiguous with:
+ pelear(Leon,Gato) at none:1.
+ To fix, define
+ pelear(Leon,Leon)
+ before the new definition.
+ pelear (generic function with 4 methods)
+=#
+
+# Esta advertencia se debe a que no está claro que método de pelear
+# será llamado en:
+pelear(Leon("RAR"),Leon("cafe","rar")) # El gato victorioso dice rar.
+# El resultado puede ser diferente en otras versiones de Julia
pelear(l::Leon,l2::Leon) = println("Los leones llegan a un empate")
-pelear(Leon("GR"),Leon("cafe","rar")) # => imprime Los leones llegan a un empate
-
-
-# Un vistazo al nivel bajo
-# Se puede echar un vistazo a la LLVM y el código ensamblador generado.
-
-area_cuadrada(l) = l * l # area_cuadrada (generic function with 1 method)
-
-area_cuadrada(5) # => 25
-
-# ¿Qué sucede cuando damos area_cuadrada diferentes argumentos?
-code_native(area_cuadrada, (Int32,))
- # .section __TEXT,__text,regular,pure_instructions
- # Filename: none
- # Source line: 1 # Prologue
- # push RBP
- # mov RBP, RSP
- # Source line: 1
- # movsxd RAX, EDI # Fetch l from memory?
- # imul RAX, RAX # Square l and store the result in RAX
- # pop RBP # Restore old base pointer
- # ret # Result will still be in RAX
-
-code_native(area_cuadrada, (Float32,))
- # .section __TEXT,__text,regular,pure_instructions
- # Filename: none
- # Source line: 1
- # push RBP
- # mov RBP, RSP
- # Source line: 1
- # vmulss XMM0, XMM0, XMM0 # Scalar single precision multiply (AVX)
- # pop RBP
- # ret
-
-code_native(area_cuadrada, (Float64,))
- # .section __TEXT,__text,regular,pure_instructions
- # Filename: none
- # Source line: 1
- # push RBP
- # mov RBP, RSP
- # Source line: 1
- # vmulsd XMM0, XMM0, XMM0 # Scalar double precision multiply (AVX)
- # pop RBP
- # ret
- #
-
-# Ten en cuenta que Julia usará instrucciones de "floating point" si alguno de
-# los argumentos son "floats"
-# Vamos a calcular el área de un círculo
-area_circulo(r) = pi * r * r # circle_area (generic function with 1 method)
-area_circulo(5) # 78.53981633974483
+
+pelear(Leon("GR"),Leon("cafe","rar")) # Los leones llegan a un empate
+
+
+################################
+# 7. Un vistazo de bajo nivel. #
+################################
+
+# Se puede echar un vistazo al código IR de LLVM y al código
+# ensamblador generado.
+area_cuadrado(l) = l * l # => area_cuadrado (generic function with 1 method)
+
+area_cuadrado(5) # => 25
+
+# ¿Qué sucede cuando damos area_cuadrada diferentes tipos de argumentos?
+code_native(area_cuadrado, (Int32,))
+#=
+ .section __TEXT,__text,regular,pure_instructions
+ Filename: none
+ Source line: 1 # prólogo
+ push RBP
+ mov RBP, RSP
+ Source line: 1
+ imul RDI, RDI # elevar l al cuadrado
+ mov RAX, RDI # almacenar el resultado en RAX
+ pop RBP # restaurar el puntero base anterior
+ ret # el resultado estará en RAX
+=#
+
+code_native(area_cuadrado, (Float32,))
+#=
+ .section __TEXT,__text,regular,pure_instructions
+ Filename: none
+ Source line: 1
+ push RBP
+ mov RBP, RSP
+ Source line: 1
+ mulss XMM0, XMM0 # multiplicación escalar de presición simple (AVX)
+ pop RBP
+ ret
+=#
+
+code_native(area_cuadrado, (Float64,))
+#=
+ .section __TEXT,__text,regular,pure_instructions
+ Filename: none
+ Source line: 1
+ push RBP
+ mov RBP, RSP
+ Source line: 1
+ mulsd XMM0, XMM0 # multiplicación escalar de presición doble (AVX)
+ pop RBP
+ ret
+=#
+
+# Ten en cuenta que Julia usará instrucciones de punto flotante si el tipo de
+# alguno de los argumentos es flotante.
+
+# Vamos a calcular el área de un círculo.
+area_circulo(r) = π * r * r # area_circulo (generic function with 1 method)
+area_circulo(5) # 78.53981633974483
code_native(area_circulo, (Int32,))
- # .section __TEXT,__text,regular,pure_instructions
- # Filename: none
- # Source line: 1
- # push RBP
- # mov RBP, RSP
- # Source line: 1
- # vcvtsi2sd XMM0, XMM0, EDI # Load integer (r) from memory
- # movabs RAX, 4593140240 # Load pi
- # vmulsd XMM1, XMM0, QWORD PTR [RAX] # pi * r
- # vmulsd XMM0, XMM0, XMM1 # (pi * r) * r
- # pop RBP
- # ret
- #
+#=
+ .section __TEXT,__text,regular,pure_instructions
+ Filename: none
+ Source line: 1
+ push RBP
+ mov RBP, RSP
+ Source line: 1
+ cvtsi2sd XMM1, EDI # cargar entero r de la memoria
+ movabs RAX, 4477117456 # cargar constante matemática π
+ movsd XMM0, QWORD PTR [RAX]
+ mulsd XMM0, XMM1 # π * r
+ mulsd XMM0, XMM1 # (π * r) * r
+ pop RBP
+ ret
+=#
code_native(area_circulo, (Float64,))
- # .section __TEXT,__text,regular,pure_instructions
- # Filename: none
- # Source line: 1
- # push RBP
- # mov RBP, RSP
- # movabs RAX, 4593140496
- # Source line: 1
- # vmulsd XMM1, XMM0, QWORD PTR [RAX]
- # vmulsd XMM0, XMM1, XMM0
- # pop RBP
- # ret
- #
+#=
+ .section __TEXT,__text,regular,pure_instructions
+ Filename: none
+ Source line: 1
+ push RBP
+ mov RBP, RSP
+ movabs RAX, 4477120336
+ movsd XMM1, QWORD PTR [RAX]
+ Source line: 1
+ mulsd XMM1, XMM0
+ mulsd XMM1, XMM0
+ movaps XMM0, XMM1
+ pop RBP
+ ret
+=#
```
-## ¿Listo para más?
+![Julia-tan](http://www.mechajyo.org/wp/wp-content/uploads/2014/10/3a2c3b7de5dd39aa7f056a707cd4eb59.png)
-Puedes obtener muchos más detalles en [The Julia Manual](http://docs.julialang.org/en/latest/manual/)
+## ¿Listo para más?
-El mejor lugar para obtener ayuda con Julia es el (muy amable) [lista de correos](https://groups.google.com/forum/#!forum/julia-users).
+Para más detalles, lee el [manual de Julia](http://docs.julialang.org/en/release-0.3).
+El mejor lugar para obtener ayuda con Julia, es en su amigable [lista de correos](https://groups.google.com/forum/#!forum/julia-users).
diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown
index f7a0ec02..4930eebc 100644
--- a/es-es/python-es.html.markdown
+++ b/es-es/python-es.html.markdown
@@ -4,6 +4,7 @@ contributors:
- ["Louie Dinh", "http://ldinh.ca"]
translators:
- ["Camilo Garrido", "http://www.twitter.com/hirohope"]
+ - ["Fabio Souto", "http://fabiosouto.me"]
lang: es-es
filename: learnpython-es.py
---
@@ -30,27 +31,47 @@ Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser apl
# Tienes números
3 #=> 3
-# Matemática es lo que esperarías
-1 + 1 #=> 2
-8 - 1 #=> 7
-10 * 2 #=> 20
-35 / 5 #=> 7
+# Evidentemente puedes realizar operaciones matemáticas
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+35 / 5 #=> 7
# La división es un poco complicada. Es división entera y toma la parte entera
# de los resultados automáticamente.
-5 / 2 #=> 2
+5 / 2 #=> 2
# Para arreglar la división necesitamos aprender sobre 'floats'
# (números de coma flotante).
2.0 # Esto es un 'float'
-11.0 / 4.0 #=> 2.75 ahhh...mucho mejor
+11.0 / 4.0 #=> 2.75 ahhh...mucho mejor
+
+# Resultado de la división de enteros truncada para positivos y negativos
+5 // 3 # => 1
+5.0 // 3.0 # => 1.0 # funciona con números en coma flotante
+-5 // 3 # => -2
+-5.0 // 3.0 # => -2.0
+
+# El operador módulo devuelve el resto de una división entre enteros
+7 % 3 # => 1
+
+# Exponenciación (x elevado a y)
+2**4 # => 16
# Refuerza la precedencia con paréntesis
-(1 + 3) * 2 #=> 8
+(1 + 3) * 2 #=> 8
+
+# Operadores booleanos
+# Nota: "and" y "or" son sensibles a mayúsculas
+True and False #=> False
+False or True #=> True
-# Valores 'boolean' (booleanos) son primitivos
-True
-False
+# Podemos usar operadores booleanos con números enteros
+0 and 2 #=> 0
+-5 or 0 #=> -5
+0 == False #=> True
+2 == True #=> False
+1 == True #=> True
# Niega con 'not'
not True #=> False
@@ -90,7 +111,7 @@ not False #=> True
# Una forma más reciente de formatear strings es el método 'format'.
# Este método es la forma preferida
"{0} pueden ser {1}".format("strings", "formateados")
-# Puedes usar palabras claves si no quieres contar.
+# Puedes usar palabras clave si no quieres contar.
"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña")
# None es un objeto
@@ -107,8 +128,8 @@ None is None #=> True
# None, 0, y strings/listas vacíos(as) todas se evalúan como False.
# Todos los otros valores son True
-0 == False #=> True
-"" == False #=> True
+bool(0) #=> False
+bool("") #=> False
####################################################
@@ -130,16 +151,16 @@ otra_variable # Levanta un error de nombre
# 'if' puede ser usado como una expresión
"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
-# Listas almacenan secuencias
+# Las listas almacenan secuencias
lista = []
# Puedes empezar con una lista prellenada
otra_lista = [4, 5, 6]
# Añadir cosas al final de una lista con 'append'
-lista.append(1) #lista ahora es [1]
-lista.append(2) #lista ahora es [1, 2]
-lista.append(4) #lista ahora es [1, 2, 4]
-lista.append(3) #lista ahora es [1, 2, 4, 3]
+lista.append(1) # lista ahora es [1]
+lista.append(2) # lista ahora es [1, 2]
+lista.append(4) # lista ahora es [1, 2, 4]
+lista.append(3) # lista ahora es [1, 2, 4, 3]
# Remueve del final de la lista con 'pop'
lista.pop() #=> 3 y lista ahora es [1, 2, 4]
# Pongámoslo de vuelta
@@ -173,11 +194,11 @@ lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6]
# Chequea la existencia en una lista con
1 in lista #=> True
-# Examina el largo de una lista con 'len'
+# Examina el tamaño de una lista con 'len'
len(lista) #=> 6
-# Tuplas son como listas pero son inmutables.
+# Las tuplas son como las listas, pero son inmutables.
tupla = (1, 2, 3)
tupla[0] #=> 1
tupla[0] = 3 # Levanta un error TypeError
@@ -266,7 +287,7 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6}
# Hagamos sólo una variable
una_variable = 5
-# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python!
+# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python!
# imprime "una_variable es menor que 10"
if una_variable > 10:
print "una_variable es completamente mas grande que 10."
@@ -400,12 +421,12 @@ class Humano(object):
# Un atributo de clase es compartido por todas las instancias de esta clase
especie = "H. sapiens"
- # Constructor basico
+ # Constructor básico, se llama al instanciar la clase.
def __init__(self, nombre):
# Asigna el argumento al atributo nombre de la instancia
self.nombre = nombre
- # Un metodo de instancia. Todos los metodos toman self como primer argumento
+ # Un método de instancia. Todos los metodos toman self como primer argumento
def decir(self, msg):
return "%s: %s" % (self.nombre, msg)
@@ -470,6 +491,56 @@ import math
dir(math)
+####################################################
+## 7. Avanzado
+####################################################
+
+# Los generadores permiten evaluación perezosa
+def duplicar_numeros(iterable):
+ for i in iterable:
+ yield i + i
+
+# Un generador crea valores sobre la marcha
+# En vez de generar y devolver todos los valores de una vez, crea un valor
+# en cada iteración. En este ejemplo los valores mayores que 15 no serán
+# procesados en duplicar_numeros.
+# Nota: xrange es un generador que hace lo mismo que range.
+# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio.
+# xrange crea un generador, mientras que range crea toda la lista.
+# Añadimos un guion bajo a los nombres de variable que coinciden con palabras
+# reservadas de python.
+xrange_ = xrange(1, 900000000)
+
+# duplica todos los números hasta que encuentra un resultado >= 30
+for i in duplicar_numeros(xrange_):
+ print i
+ if i >= 30:
+ break
+
+# Decoradores
+# en este ejemplo pedir rodea a hablar
+# Si por_favor es True se cambiará el mensaje.
+from functools import wraps
+
+
+def pedir(target_function):
+ @wraps(target_function)
+ def wrapper(*args, **kwargs):
+ msg, por_favor = target_function(*args, **kwargs)
+ if por_favor:
+ return "{} {}".format(msg, "¡Por favor! Soy pobre :(")
+ return msg
+
+ return wrapper
+
+
+@pedir
+def hablar(por_favor=False):
+ msg = "¿Me puedes comprar una cerveza?"
+ return msg, por_favor
+
+print hablar() # ¿Me puedes comprar una cerveza?
+print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :(
```
## ¿Listo para más?
@@ -481,6 +552,7 @@ dir(math)
* [The Official Docs](http://docs.python.org/2.6/)
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
* [Python Module of the Week](http://pymotw.com/2/)
+* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
### Encuadernados
diff --git a/fr-fr/erlang-fr.html.markdown b/fr-fr/erlang-fr.html.markdown
new file mode 100644
index 00000000..55453c56
--- /dev/null
+++ b/fr-fr/erlang-fr.html.markdown
@@ -0,0 +1,327 @@
+---
+language: erlang
+contributors:
+ - ["Giovanni Cappellotto", "http://www.focustheweb.com/"]
+translators:
+ - ["Julien Cretel", "https://github.com/Jubobs"]
+filename: learnerlang-fr.erl
+lang: fr-fr
+---
+
+```erlang
+% Un signe pour cent marque le début d'un commentaire de fin de ligne.
+
+%% Deux signes pour cent sont utilisés pour commenter les fonctions.
+
+%%% Trois signes pour cent sont utilisés pour commenter les modules.
+
+% Trois symboles de ponctuation sont utilisés en Erlang.
+% Les virgules (`,`) servent à séparer les paramètres dans les appels de
+% fonctions, les contructeurs, et les motifs.
+% Les points (`.`) (suivis par des blancs) servent à séparer les fonctions et
+% les expressions dans l'interpréteur.
+% Les points-virgules (`;`) servent à séparer les clauses. Ces dernières
+% apparaissent dans différent cas de figure : définitions de fonctions et
+% expressions `case`, `if`, `try..catch`, `receive`.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 1. Variables et filtrage par motif
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+(L'équivalent anglais de *filtrage par motif* est *pattern patching*.)
+
+Nb = 42. % Chaque nom de variable doit commencer par une lettre majuscule.
+
+% Les variables Erlang ne peuvent être affectées qu'une seule fois ; si vous
+% essayez d'affecter une autre valeur à la variable `Nb`, vous obtiendrez
+% une erreur.
+Nb = 43. % ** exception error: no match of right hand side value 43
+
+% Dans la plupart des languages, `=` indique une affectation. En Erlang,
+% cependant, `=` indique un filtrage par motif. En fait, `Gauche = Droit`
+% signifie ce qui suit : évalue le côté droit (`Droit`), et ensuite filtre le
+% résultat à l'aide du motif du côté gauche (`Gauche`).
+Nb = 7 * 6.
+
+% Nombre en virgule flottante.
+Pi = 3.14159.
+
+% Les atomes représentent des valeurs constantes non-numériques. Un atome
+% commence par une lettre minuscule, suivie d'une séquence composée de
+% caractères alphanumériques, de tirets bas (`_`), ou d'arobases (`@`).
+Bonjour = bonjour.
+AutreNoeud = exemple@noeud.
+
+% Les atomes de valeur autre qu'alphanumérique peuvent être délimités par
+% des guillemets droits simples.
+AtomeAvecEspace = 'un atome contenant des espaces'.
+
+% Les tuples sont similaires aux enregistrements du language C.
+Point = {point, 10, 45}.
+
+% Pour extraire des valeurs d'un tuple, on filtre par motif avec
+% l'opérateur `=`.
+{point, X, Y} = Point. % X = 10, Y = 45
+
+% On peut utiliser `_` comme caractère joker pour les variables qui ne nous
+% intéressent pas. Le symbol `_` est appelé variable muette. Contrairement
+% aux variables normales, de multiples apparitions de `_` dans un même motif
+% ne lient pas nécessairement à la même valeur.
+Personne = {personne, {nom, {prenom, joe}, {famille, armstrong}},
+ {pointure, 42}}.
+{_, {_, {_, Qui}, _}, _} = Personne. % Qui = joe
+
+% Pour créer une liste, on écrit les éléments de la liste entre crochets, en
+% les séparant par des virgules.
+% Les éléments d'une liste peuvent avoir n'importe quel type.
+% Le premier élément d'une liste est appelé la tête de la liste. Si on retire
+% la tête d'une liste, ce qui reste est appelée la queue de la liste.
+Articles = [{pommes, 10}, {poires, 6}, {lait, 3}].
+
+% Si `Q` est une liste, alors `[T|Q]` est aussi une liste dont la tête est `T`
+% et dont la queue est `Q`. La barre verticale (`|`) sépare la tête d'une
+% liste de sa queue.
+% `[]` est la liste vide.
+% On peut extraire des éléments d'une liste par filtrage de motif. Si `L` est
+% une liste non vide, alors l'expression `[X|Y] = L`, où `X` et `Y` sont des
+% variables non affectées, va extraire la tête de la liste dans `X` et la
+% queue de la liste dans `Y`.
+[PremierArticle|AutresArticles] = Articles.
+% PremierArticle = {pommmes, 10}
+% AutresArticles = [{poires, 6}, {lait, 3}]
+
+% Il n'y a pas de chaînes de caractères en Erlang. Les chaînes de caractères
+% ne sont rien de plus que des listes d'entiers.
+% Les chaînes de caractères sont délimitées par des guillemets droits doubles
+% (`"`).
+Nom = "Bonjour".
+[66, 111, 110, 106, 111, 117, 114] = "Bonjour".
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 2. Programmation séquentielle.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Les modules constituent l'unité de base d'un programme Erlang. Toutes les
+% fonctions que l'on écrit sont enregistrées dans des modules. Les modules sont
+% enregistrés dans des fichiers avec une extension `.erl`.
+% Les modules doivent être compilés afin d'éxecuter le programme.
+% Un module compilé a une extension `.beam`.
+-module(geometrie).
+-export([aire/1]). % la liste des fonctions exportées par le module.
+
+% La fonction `aire` est composée de deux clauses. Les clauses sont séparées
+% par un point-virgule, et la dernière clause est suivie d'un point et un
+% espace blanc. Chaque clause a une en-tête et un corps ; l'en-tête consiste
+% en un nom de fonction suivi d'un motif (entre parenthèses), et le corps
+% consiste en une séquence d'expressions, qui sont évaluées si le motif de
+% l'en-tête est cohérent par rapport à la valeur des paramètres d'appel.
+% L'expression est filtrée séquentiellement par les différents motifs, dans
+% l'ordre dans lequel ils apparaissent dans la définition de la fonction.
+aire({rectangle, Largeur, Hauteur}) -> Largeur * Hauteur;
+aire({cercle, R}) -> 3.14159 * R * R.
+
+% Compilation du code du fichier geometrie.erl.
+c(geometrie). % {ok,geometrie}
+
+% Le nom du module doit être inclus avec le nom de la fonction afin
+% d'identifier précisément quelle fonction on souhaite appeler.
+geometrie:aire({rectangle, 10, 5}). % 50
+geometrie:area({cercle, 1.4}). % 6.15752
+
+% En Erlang, deux fonctions portant le même nom mais ayant des arités
+% différentes (c'est à dire ne prenant pas le même nombre de paramètres)
+% au sein d'un même module représentent des fonctions complètement
+% différentes.
+-module(lib_divers).
+-export([somme/1]). % exporte la fonction `somme` d'arité 1
+ % acceptant un paramètre : une liste d'entiers.
+somme(L) -> somme(L, 0).
+somme([], N) -> N;
+somme([T|Q], N) -> somme(Q, T+N).
+
+% Les `fun`s sont des fonctions "anonymes" ; elles sont appelées ainsi parce
+% qu'elles n'ont pas de nom. Cependant, elles peuvent être affectées à des
+% variables.
+Doubler = fun(X) -> 2 * X end. % `Doubler` pointe vers une fonction anonyme
+ % dont le handle est : #Fun<erl_eval.6.17052888>
+Doubler(2). % 4
+
+% Les fonctions peuvent prendre des `fun`s comme paramètres et peuvent renvoyer
+% des `fun`s.
+Mult = fun(Fois) -> ( fun(X) -> X * Fois end ) end.
+Tripler = Mult(3).
+Tripler(5). % 15
+
+% Les listes en compréhension sont des expressions qui créent des listes sans
+% requérir ni `fun`s, ni maps, ni filters.
+% La notation `[F(X) || X <- L]` signifie "la liste des `F(X)` où `X` est
+% extrait de la liste `L`."
+L = [1,2,3,4,5].
+[2 * X || X <- L]. % [2,4,6,8,10]
+% Une liste en compréhension peut être constituée de générateurs, ainsi que de
+% gardes, qui sélectionnent un sous-ensemble des valeurs générées.
+NombresPairs = [N || N <- [1, 2, 3, 4], N rem 2 == 0]. % [2, 4]
+
+% La garde est un élément syntaxique qui rend le filtrage par motif encore
+% plus puissant. Les gardes permettent de d'effectuer de simple tests et
+% comparaisons sur les variables d'un motif. Les gardes peuvent être
+% utilisées dans les en-têtes de fonctions, au sein desquelles elles sont
+% introduites par le mot-clé `when`, ou encore à n'importe quel endroit où
+% une expression est autorisée.
+max(X, Y) when X > Y -> X;
+max(X, Y) -> Y.
+
+% Une garde est une série d'expressions gardes, séparées par des virgules (`,`).
+% La garde `ExprGarde1, ExprGarde2, ..., ExprGardeN` est vraie si toutes les
+% expressions gardes `ExprGarde1`, `ExprGarde2, ..., `ExprGardeN` ont pour
+% valeur `true`.
+est_chat(A) when is_atom(A), A =:= chat -> true;
+est_chat(A) -> false.
+est_chien(A) when is_atom(A), A =:= chien -> true;
+est_chien(A) -> false.
+
+% Une séquence de gardes est composée soit d'une seule garde ou bien d'une
+% série de gardes, séparées par des points-virgules (`;`). La séquence de
+% gardes `G1; G2; ...; Gn` est vraie si au moins l'une des gardes `G1`, `G2`,
+% ..., `Gn` a pour valeur `true`.
+est_animal(A) when is_atom(A), (A =:= chien) or (A =:= chat) -> true;
+est_animal(A) -> false.
+
+% Attention : toutes les expressions Erlang valides ne peuvent pas être
+% utilisées comme expressions gardes ; en particulier, nos fonctions
+% `est_chat` et `est_chien` ne sont pas autorisées au sein de la séquence de
+% gardes dans la définition de `est_animal`. Pour plus de détails sur les
+% expressions autorisées ands les séquences de gardes, voir cette
+% [section](http://erlang.org/doc/reference_manual/expressions.html#id81912)
+% du manuel Erlang.
+
+% Les enregistrements permettent d'associer un nom à un certain élément dans
+% un tuple.
+% Les enregistrements peuvent être définis dans des fichiers sources Erlang
+% ou bien dans des fichiers avec une extension `.hrl`, qui sont ensuite inclus
+% dans des fichiers sources Erlang.
+-record(afaire, {
+ statut = rappel, % Valeur par défaut
+ qui = joe,
+ texte
+}).
+
+% Les définitions d'enregistrements doivent être lues dans l'interpreteur
+% pour qu'on puisse définir un enregistrement. On utilise la fonction `rr`
+% (abbréviation de *read records* en anglais, ou *lire enregistrements* en
+% français) pour ça.
+rr("enregistrements.hrl"). % [afaire]
+
+% Création et mise à jour d'enregistrements :
+X = #afaire{}.
+% #afaire{statut = rappel, qui = joe, texte = undefined}
+X1 = #afaire{statut = urgent, texte = "Corriger erreurs dans livre"}.
+% #afaire{statut = urgent, qui = joe, texte = "Corriger erreurs dans livre"}
+X2 = X1#afaire{statut = fini}.
+% #afaire{statut = fini, qui = joe, texte = "Corriger erreurs dans livre"}
+
+% Expressions `case`.
+% `filter` renvoie une liste de tous les éléments `X` d'une liste `L` pour
+% lesquels `P(X)` est vrai.
+filter(P, [H|T]) ->
+ case P(H) of
+ true -> [H|filter(P, T)];
+ false -> filter(P, T)
+ end;
+filter(P, []) -> [].
+filter(fun(X) -> X rem 2 == 0 end, [1, 2, 3, 4]). % [2, 4]
+
+% Expressions `if`.
+max(X, Y) ->
+ if
+ X > Y -> X;
+ X < Y -> Y;
+ true -> nil
+ end.
+
+% Attention : au moins l'une des gardes dans l'expression `if` doit avoir pour
+% valeur `true` ; autrement, une exception sera lancée.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 3. Exceptions.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Des exceptions sont lancées par le système quand des erreurs internes
+% surviennent, ou de manière explicite dans le programme en appelant
+% `throw(Exception)`, `exit(Exception)`, ou `erlang:error(Exception)`.
+generer_exception(1) -> a;
+generer_exception(2) -> throw(a);
+generer_exception(3) -> exit(a);
+generer_exception(4) -> {'EXIT', a};
+generer_exception(5) -> erlang:error(a).
+
+% Erlang dispose de deux méthodes pour capturer une exception. La première
+% consiste à inclure l'appel de de la fonction qui lance l'exception dans une
+% expression `try...catch`.
+catcher(N) ->
+ try generer_exception(N) of
+ Val -> {N, normal, Val}
+ catch
+ throw:X -> {N, caught, thrown, X};
+ exit:X -> {N, caught, exited, X};
+ error:X -> {N, caught, error, X}
+ end.
+
+% L'autre méthode consiste à inclure l'appel dans une expression `catch`.
+% Quand une exception est capturée, elle est convertie en un tuple qui décrit
+% l'erreur.
+catcher(N) -> catch generer_exception(N).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% 4. Concurrence
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Erlang est basé sur le modèle d'acteur pour la concurrence. Seulement trois
+% opérations sont requises pour écrire des programmes concurrents en Erlang :
+% la création de processus, l'envoi de messages, et la réception de messages.
+
+% Pour démarrer un nouveau processus, on utilise la fonction `spawn`, qui
+% prend une fonction comme paramètre.
+
+F = fun() -> 2 + 2 end. % #Fun<erl_eval.20.67289768>
+spawn(F). % <0.44.0>
+
+% `spawn` renvoie un pid (*process identifier* en anglais, ou *identifiant de
+% processus* en français), qui peut être utilisé pour envoyer des messages au
+% processus en question. Pour passer des messages, on utilise l'opérateur `!`.
+% Pour que cela soit utile, on doit aussi être en mesure de recevoir des
+% messages, ce qui est accompli grâce à une clause `receive` :
+
+-module(calculerGeometrie).
+-compile(export_all).
+calculerAire() ->
+ receive
+ {rectangle, W, H} ->
+ W * H;
+ {cercle, R} ->
+ 3.14 * R * R;
+ _ ->
+ io:format("Seule l'aire d'un rectangle / cercle peut etre calculee.")
+ end.
+
+% Compilation du module and création d'un processus qui évalue `calculerAire`
+% dans l'interpréteur.
+c(calculerGeometrie).
+CalculerAire = spawn(calculerGeometrie, calculerAire, []).
+CalculerAire ! {cercle, 2}. % 12.56000000000000049738
+
+% L'interpréteur est lui-même un processus ; on peut utiliser `self` pour
+% obtenir le pid actuel.
+self(). % <0.41.0>
+
+```
+
+## Ressources (en anglais)
+
+* ["Learn You Some Erlang for great good!"](http://learnyousomeerlang.com/)
+* ["Programming Erlang: Software for a Concurrent World" by Joe Armstrong](http://pragprog.com/book/jaerlang/programming-erlang)
+* [Erlang/OTP Reference Documentation](http://www.erlang.org/doc/)
+* [Erlang - Programming Rules and Conventions](http://www.erlang.se/doc/programming_rules.shtml)
diff --git a/fr-fr/livescript-fr.html.markdown b/fr-fr/livescript-fr.html.markdown
new file mode 100644
index 00000000..9c3b8003
--- /dev/null
+++ b/fr-fr/livescript-fr.html.markdown
@@ -0,0 +1,360 @@
+---
+language: LiveScript
+filename: learnLivescript-fr.ls
+contributors:
+ - ["Christina Whyte", "http://github.com/kurisuwhyte/"]
+translators:
+ - ["Morgan Bohn", "https://github.com/morganbohn"]
+lang: fr-fr
+---
+
+LiveScript est un langage qui compile en JavaScript. Il a un rapport direct
+avec JavaScript, et vous permet d'écrire du JavaScript plus simplement, plus
+efficacement et sans répétitivité. LiveScript ajoute non seulement des
+fonctionnalités pour écrire du code fonctionnel, mais possède aussi nombre
+d'améliorations pour la programmation orientée objet et la programmation
+impérative.
+
+LiveScript est un descendant direct de [Coco][], indirect de [CoffeeScript][],
+avec lequel il a beaucoup plus de compatibilité.
+
+[Coco]: http://satyr.github.io/coco/
+[CoffeeScript]: http://coffeescript.org/
+
+Vous pouvez contacter l'auteur du guide original en anglais ici :
+[@kurisuwhyte](https://twitter.com/kurisuwhyte)
+
+
+```coffeescript
+# Comme son cousin CoffeeScript, LiveScript utilise le symbole dièse pour les
+# commentaires sur une ligne.
+
+/*
+ Les commentaires sur plusieurs lignes utilisent la syntaxe du C. Utilisez-les
+ si vous voulez préserver les commentaires dans la sortie JavaScript.
+ */
+```
+```coffeescript
+# LiveScript utilise l'indentation pour délimiter les blocs de code plutôt que
+# les accolades, et les espaces pour appliquer les fonctions (bien que les
+# parenthèses soient utilisables).
+
+
+########################################################################
+## 1. Valeurs basiques
+########################################################################
+
+# Les valeurs non définies sont représentées par le mot clé `void` à la place de
+# `undefined`
+void # comme `undefined` mais plus sûr (ne peut pas être redéfini)
+
+# Une valeur non valide est représentée par Null.
+null
+
+
+# Les booléens s'utilisent de la façon suivante:
+true
+false
+
+# Et il existe divers alias les représentant également:
+on; off
+yes; no
+
+
+# Puis viennent les nombres entiers et décimaux.
+10
+0.4 # Notez que le `0` est requis
+
+# Dans un souci de lisibilité, vous pouvez utiliser les tirets bas et les
+# suffixes sur les nombres. Il seront ignorés à la compilation.
+12_344km
+
+
+# Les chaînes sont des séquences immutables de caractères, comme en JS:
+"Christina" # Les apostrophes fonctionnent également!
+"""Multi-line
+ strings
+ are
+ okay
+ too."""
+
+# De temps à autre, vous voulez encoder un mot clé; la notation en backslash
+# rend cela facile:
+\keyword # => 'keyword'
+
+
+# Les tableaux sont des collections ordonnées de valeurs.
+fruits =
+ * \apple
+ * \orange
+ * \pear
+
+# Il peuvent être écrits de manière plus consises à l'aide des crochets:
+fruits = [ \apple, \orange, \pear ]
+
+# Vous pouvez également utiliser la syntaxe suivante, à l'aide d'espaces, pour
+# créer votre liste de valeurs:
+fruits = <[ apple orange pear ]>
+
+# Vous pouvez récupérer une entrée à l'aide de son index:
+fruits[0] # => "apple"
+
+# Les objets sont une collection non ordonnées de paires clé/valeur, et
+# d'autres choses (que nous verrons plus tard).
+person =
+ name: "Christina"
+ likes:
+ * "kittens"
+ * "and other cute stuff"
+
+# A nouveau, vous pouvez utiliser une expression plus consise à l'aide des
+# accolades:
+person = {name: "Christina", likes: ["kittens", "and other cute stuff"]}
+
+# Vous pouvez récupérer une entrée via sa clé:
+person.name # => "Christina"
+person["name"] # => "Christina"
+
+
+# Les expressions régulières utilisent la même syntaxe que JavaScript:
+trailing-space = /\s$/ # les mots-composés deviennent motscomposés
+
+# A l'exception que vous pouvez pouvez utiliser des expressions sur plusieurs
+# lignes!
+# (les commentaires et les espaces seront ignorés)
+funRE = //
+ function\s+(.+) # nom
+ \s* \((.*)\) \s* # arguments
+ { (.*) } # corps
+ //
+
+
+########################################################################
+## 2. Les opérations basiques
+########################################################################
+
+# Les opérateurs arithmétiques sont les mêmes que pour JavaScript:
+1 + 2 # => 3
+2 - 1 # => 1
+2 * 3 # => 6
+4 / 2 # => 2
+3 % 2 # => 1
+
+
+# Les comparaisons sont presque identiques, à l'exception que `==` équivaut au
+# `===` de JS, là où le `==` de JS est `~=` en LiveScript, et `===` active la
+# comparaison d'objets et de tableaux, ainsi que les comparaisons strictes
+# (sans conversion de type)
+2 == 2 # => true
+2 == "2" # => false
+2 ~= "2" # => true
+2 === "2" # => false
+
+[1,2,3] == [1,2,3] # => false
+[1,2,3] === [1,2,3] # => true
+
++0 == -0 # => true
++0 === -0 # => false
+
+# Les opérateurs suivants sont également disponibles: <, <=, > et >=
+
+# Les valeurs logiques peuvent être combinéees grâce aux opérateurs logiques
+# `or`, `and` et `not`
+true and false # => false
+false or true # => true
+not false # => true
+
+
+# Les collections ont également des opérateurs additionnels
+[1, 2] ++ [3, 4] # => [1, 2, 3, 4]
+'a' in <[ a b c ]> # => true
+'name' of { name: 'Chris' } # => true
+
+
+########################################################################
+## 3. Fonctions
+########################################################################
+
+# Puisque LiveScript est fonctionnel, vous vous attendez à une bonne prise en
+# charge des fonctions. En LiveScript, il est encore plus évident que les
+# fonctions sont de premier ordre:
+add = (left, right) -> left + right
+add 1, 2 # => 3
+
+# Les fonctions qui ne prennent pas d'arguments peuvent être appelées avec un
+# point d'exclamation!
+two = -> 2
+two!
+
+# LiveScript utilise l'environnement de la fonction, comme JavaScript.
+# A l'inverse de JavaScript, le `=` fonctionne comme un opérateur de
+# déclaration, et il déclarera toujours la variable située à gauche (sauf si
+# la variable a été déclarée dans l'environnement parent).
+
+# L'opérateur `:=` est disponible pour réutiliser un nom provenant de
+# l'environnement parent.
+
+
+# Vous pouvez extraire les arguments d'une fonction pour récupérer
+# rapidement les valeurs qui vous intéressent dans une structure de données
+# complexe:
+tail = ([head, ...rest]) -> rest
+tail [1, 2, 3] # => [2, 3]
+
+# Vous pouvez également transformer les arguments en utilisant les opérateurs
+# binaires et unaires. Définir des arguments par défaut est aussi possible.
+foo = (a = 1, b = 2) -> a + b
+foo! # => 3
+
+# You pouvez utiliser cela pour cloner un argument en particulier pour éviter
+# les effets secondaires. Par exemple:
+copy = (^^target, source) ->
+ for k,v of source => target[k] = v
+ target
+a = { a: 1 }
+copy a, { b: 2 } # => { a: 1, b: 2 }
+a # => { a: 1 }
+
+
+# Une fonction peut être curryfiée en utilisant une longue flèche à la place
+# d'une courte:
+add = (left, right) --> left + right
+add1 = add 1
+add1 2 # => 3
+
+# Les fonctions ont un argument `it` implicite si vous n'en déclarez pas:
+identity = -> it
+identity 1 # => 1
+
+# Les opérateurs ne sont pas des fonctions en LiveScript, mais vous pouvez
+# facilement les transformer en fonction:
+divide-by-two = (/ 2)
+[2, 4, 8, 16].map(divide-by-two).reduce (+)
+
+# Comme dans tout bon langage fonctionnel, vous pouvez créer des fonctions
+# composées d'autres fonctions:
+double-minus-one = (- 1) . (* 2)
+
+# En plus de la formule mathématique `f . g`, vous avez les opérateurs `>>`
+# et `<<`, qui décrivent l'ordre d'application des fonctions composées.
+double-minus-one = (* 2) >> (- 1)
+double-minus-one = (- 1) << (* 2)
+
+
+# Pour appliquer une valeur à une fonction, vous pouvez utiliser les opérateurs
+# `|>` et `<|`:
+map = (f, xs) --> xs.map f
+[1 2 3] |> map (* 2) # => [2 4 6]
+
+# La version sans pipe correspond à:
+((map (* 2)) [1, 2, 3])
+
+# You pouvez aussi choisir où vous voulez que la valeur soit placée, en
+# marquant la position avec un tiret bas (_):
+reduce = (f, xs, initial) --> xs.reduce f, initial
+[1 2 3] |> reduce (+), _, 0 # => 6
+
+
+# Le tiret bas est également utilisé pour l'application partielle,
+# que vous pouvez utiliser pour toute fonction:
+div = (left, right) -> left / right
+div-by-two = div _, 2
+div-by-two 4 # => 2
+
+
+# Pour conclure, LiveScript vous permet d'utiliser les fonctions de rappel.
+# (mais vous devriez essayer des approches plus fonctionnelles, comme
+# Promises).
+# Un fonction de rappel est une fonction qui est passée en argument à une autre
+# fonction:
+readFile = (name, f) -> f name
+a <- readFile 'foo'
+b <- readFile 'bar'
+console.log a + b
+
+# Equivalent à:
+readFile 'foo', (a) -> readFile 'bar', (b) -> console.log a + b
+
+
+########################################################################
+## 4. Conditionnalités
+########################################################################
+
+# Vous pouvez faire de la conditionnalité à l'aide de l'expression `if...else`:
+x = if n > 0 then \positive else \negative
+
+# A la place de `then`, vous pouvez utiliser `=>`
+x = if n > 0 => \positive
+ else \negative
+
+# Pour les conditions complexes, il vaut mieux utiliser l'expresssion `switch`:
+y = {}
+x = switch
+ | (typeof y) is \number => \number
+ | (typeof y) is \string => \string
+ | 'length' of y => \array
+ | otherwise => \object # `otherwise` et `_` correspondent.
+
+# Le corps des fonctions, les déclarations et les assignements disposent d'un
+# `switch` implicite, donc vous n'avez pas besoin de le réécrire:
+take = (n, [x, ...xs]) -->
+ | n == 0 => []
+ | _ => [x] ++ take (n - 1), xs
+
+
+########################################################################
+## 5. Compréhensions
+########################################################################
+
+# Comme en python, vous allez pouvoir utiliser les listes en compréhension,
+# ce qui permet de générer rapidement et de manière élégante une liste de
+# valeurs:
+oneToTwenty = [1 to 20]
+evens = [x for x in oneToTwenty when x % 2 == 0]
+
+# `when` et `unless` peuvent être utilisés comme des filtres.
+
+# Cette technique fonctionne sur les objets de la même manière. Vous allez
+# pouvoir générer l'ensemble de paires clé/valeur via la syntaxe suivante:
+copy = { [k, v] for k, v of source }
+
+
+########################################################################
+## 4. Programmation orientée objet
+########################################################################
+
+# Bien que LiveScript soit un langage fonctionnel, il dispose d'intéressants
+# outils pour la programmation objet. La syntaxe de déclaration d'une classe
+# est héritée de CoffeeScript:
+class Animal
+ (@name, kind) ->
+ @kind = kind
+ action: (what) -> "*#{@name} (a #{@kind}) #{what}*"
+
+class Cat extends Animal
+ (@name) -> super @name, 'cat'
+ purr: -> @action 'purrs'
+
+kitten = new Cat 'Mei'
+kitten.purr! # => "*Mei (a cat) purrs*"
+
+# En plus de l'héritage classique, vous pouvez utiliser autant de mixins
+# que vous voulez pour votre classe. Les mixins sont juste des objets:
+Huggable =
+ hug: -> @action 'is hugged'
+
+class SnugglyCat extends Cat implements Huggable
+
+kitten = new SnugglyCat 'Purr'
+kitten.hug! # => "*Mei (a cat) is hugged*"
+```
+
+## Lectures complémentaires
+
+Il y a beaucoup plus de choses à dire sur LiveScript, mais ce guide devrait
+suffire pour démarrer l'écriture de petites fonctionnalités.
+Le [site officiel](http://livescript.net/) dispose de beaucoup d'information,
+ainsi que d'un compilateur en ligne vous permettant de tester le langage!
+
+Jetez également un coup d'oeil à [prelude.ls](http://gkz.github.io/prelude-ls/),
+et consultez le channel `#livescript` sur le réseau Freenode.
diff --git a/fr-fr/lua-fr.html.markdown b/fr-fr/lua-fr.html.markdown
index b4e2a161..1f592320 100644
--- a/fr-fr/lua-fr.html.markdown
+++ b/fr-fr/lua-fr.html.markdown
@@ -434,9 +434,9 @@ les librairies standard:
Autres références complémentaires:
-* <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">Lua for programmers</a>
-* <a href="lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Courte de référence de Lua</a>
-* <a href="http://www.lua.org/pil/contents.html">Programming In Lua</a>
+* <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">Lua pour programmeurs</a>
+* <a href="lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Référence condensée de Lua</a>
+* <a href="http://www.lua.org/pil/contents.html">Programmer en Lua</a>
* <a href="http://www.lua.org/manual/">Les manuels de référence Lua</a>
A propos, ce fichier est exécutable. Sauvegardez-le sous le nom *learn.lua* et
@@ -446,4 +446,4 @@ Ce tutoriel a été originalement écrit pour <a href="tylerneylon.com">tylerney
disponible en tant que <a href="https://gist.github.com/tylerneylon/5853042">gist</a>.
Il a été traduit en français par Roland Yonaba (voir son <a href="http://github.com/Yonaba">github</a>).
-Amusez-vous bien avec Lua! \ No newline at end of file
+Amusez-vous bien avec Lua!
diff --git a/fr-fr/markdown.html.markdown b/fr-fr/markdown.html.markdown
index 29c0d65d..e5e7c73a 100644
--- a/fr-fr/markdown.html.markdown
+++ b/fr-fr/markdown.html.markdown
@@ -177,7 +177,7 @@ des syntaxes spécifiques -->
\`\`\`ruby
<!-- mais enlevez les backslashes quand vous faites ça,
-gardez juste ```ruby ( ou nom de la synatxe correspondant à votre code )-->
+gardez juste ```ruby ( ou nom de la syntaxe correspondant à votre code )-->
def foobar
puts "Hello world!"
end
diff --git a/fr-fr/r-fr.html.markdown b/fr-fr/r-fr.html.markdown
index 3f225a0f..7d30a48d 100644
--- a/fr-fr/r-fr.html.markdown
+++ b/fr-fr/r-fr.html.markdown
@@ -6,6 +6,7 @@ contributors:
translators:
- ["Anne-Catherine Dehier", "https://github.com/spellart"]
filename: learnr-fr.r
+lang: fr-fr
---
R est un langage de programmation statistique. Il dispose de nombreuses
diff --git a/git.html.markdown b/git.html.markdown
index af65afb0..bf8fce0c 100644
--- a/git.html.markdown
+++ b/git.html.markdown
@@ -79,6 +79,11 @@ this pointer will automatically update and point to the latest commit.
HEAD is a pointer that points to the current branch. A repository only has 1 *active* HEAD.
head is a pointer that points to any commit. A repository can have any number of heads.
+###Stages of Git
+* Modified - Changes have been made to a file but file has not been committed to Git Database yet
+* Staged - Marks a modified file to go into your next commit snapshot
+* Committed - Files have been committed to the Git Database
+
### Conceptual Resources
* [Git For Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/)
@@ -131,6 +136,10 @@ $ git help -a
$ git help add
$ git help commit
$ git help init
+# or git <command_here> --help
+$ git add --help
+$ git commit --help
+$ git init --help
```
### status
@@ -149,8 +158,8 @@ $ git help status
### add
-To add files to the current working tree/directory/repo. If you do not `git add` new files to the
-working tree/directory, they will not be included in commits!
+To add files to the staging area/index. If you do not `git add` new files to the
+staging area/index, they will not be included in commits!
```bash
# add a file in your current working directory
@@ -163,6 +172,8 @@ $ git add /path/to/file/HelloWorld.c
$ git add ./*.java
```
+This only adds a file to the staging area/index, it doesn't commit it to the working directory/repo.
+
### branch
Manage your branches. You can view, edit, create, delete branches using this command.
@@ -451,6 +462,8 @@ $ git rm /pather/to/the/file/HelloWorld.c
* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1)
+* [Udemy Git Tutorial: A Comprehensive Guide](https://blog.udemy.com/git-tutorial-a-comprehensive-guide/)
+
* [git-scm - Video Tutorials](http://git-scm.com/videos)
* [git-scm - Documentation](http://git-scm.com/docs)
@@ -462,3 +475,5 @@ $ git rm /pather/to/the/file/HelloWorld.c
* [GitGuys](http://www.gitguys.com/)
* [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html)
+
+* [Pro Git](http://www.git-scm.com/book/en/v2)
diff --git a/groovy.html.markdown b/groovy.html.markdown
index 629b6d18..519f36ce 100644
--- a/groovy.html.markdown
+++ b/groovy.html.markdown
@@ -6,7 +6,7 @@ contributors:
filename: learngroovy.groovy
---
-Groovy - A dynamic language for the Java platform [Read more here.](http://groovy.codehaus.org)
+Groovy - A dynamic language for the Java platform [Read more here.](http://www.groovy-lang.org/)
```groovy
@@ -231,7 +231,7 @@ for ( e in map ) {
Operators
Operator Overloading for a list of the common operators that Groovy supports:
- http://groovy.codehaus.org/Operator+Overloading
+ http://www.groovy-lang.org/operators.html#Operator-Overloading
Helpful groovy operators
*/
@@ -249,7 +249,7 @@ def username = user?.username
A Groovy Closure is like a "code block" or a method pointer. It is a piece of
code that is defined and then executed at a later point.
- More info at: http://groovy.codehaus.org/Closures+-+Formal+Definition
+ More info at: http://www.groovy-lang.org/closures.html
*/
//Example:
def clos = { println "Hello World!" }
@@ -409,7 +409,7 @@ assert sum(2,5) == 7
[Groovy web console](http://groovyconsole.appspot.com/)
-Join a [Groovy user group](http://groovy.codehaus.org/User+Groups)
+Join a [Groovy user group](http://www.groovy-lang.org/usergroups.html)
## Books
diff --git a/haskell.html.markdown b/haskell.html.markdown
index 6a64442f..369b1b20 100644
--- a/haskell.html.markdown
+++ b/haskell.html.markdown
@@ -209,14 +209,15 @@ foo 5 -- 75
-- the expression on its right is applied as the parameter to the function on its left.
-- before
-(even (fib 7)) -- false
-
--- after
-even . fib $ 7 -- false
+even (fib 7) -- false
-- equivalently
even $ fib 7 -- false
+-- composing functions
+even . fib $ 7 -- false
+
+
----------------------------------------------------
-- 5. Type signatures
----------------------------------------------------
diff --git a/it-it/c++-it.html.markdown b/it-it/c++-it.html.markdown
index 4f5ac8a2..e7e1d89e 100644
--- a/it-it/c++-it.html.markdown
+++ b/it-it/c++-it.html.markdown
@@ -1,6 +1,6 @@
---
language: c++
-filename: learncpp.cpp
+filename: learncpp-it.cpp
contributors:
- ["Steven Basart", "http://github.com/xksteven"]
- ["Matt Kline", "https://github.com/mrkline"]
diff --git a/it-it/coffeescript-it.html.markdown b/it-it/coffeescript-it.html.markdown
new file mode 100644
index 00000000..16eb9bd4
--- /dev/null
+++ b/it-it/coffeescript-it.html.markdown
@@ -0,0 +1,107 @@
+---
+language: coffeescript
+contributors:
+ - ["Luca 'Kino' Maroni", "http://github.com/kino90"]
+ - ["Tenor Biel", "http://github.com/L8D"]
+ - ["Xavier Yao", "http://github.com/xavieryao"]
+filename: coffeescript-it.coffee
+lang: it-it
+---
+
+CoffeeScript è un piccolo linguaggio che compila direttamente nell'equivalente
+JavaScript, non c'è nessuna interpretazione a runtime. Come possibile
+successore di Javascript, CoffeeScript fa il suo meglio per restituire
+un codice leggibile, ben stampato e performante in ogni ambiente JavaScript.
+
+Guarda anche [il sito di CoffeeScript](http://coffeescript.org/), che ha una
+guida completa a CoffeeScript.
+
+```coffeescript
+# CoffeeScript è un linguaggio hipster.
+# Segue le mode di alcuni linguaggi moderni.
+# Quindi i commenti sono come quelli di Ruby e Python, usano il cancelletto.
+
+###
+I blocchi di commenti sono definiti con tre cancelletti, che vengono tradotti
+direttamente in `/*` e `*/` nel codice JavaScript risultante.
+
+Prima di continuare devi conoscere la maggior parte
+delle semantiche JavaScript.
+###
+
+# Assegnamento:
+numero = 42 #=> var numero = 42;
+contrario = true #=> var contrario = true;
+
+# Condizioni:
+numero = -42 if contrario #=> if(contrario) { numero = -42; }
+
+# Funzioni:
+quadrato = (x) -> x * x #=> var quadrato = function(x) { return x * x; }
+
+riempi = (contenitore, liquido = "caffè") ->
+ "Sto riempiendo #{contenitore} con #{liquido}..."
+#=>var riempi;
+#
+#riempi = function(contenitore, liquido) {
+# if (liquido == null) {
+# liquido = "caffè";
+# }
+# return "Sto riempiendo " + contenitore + " con " + liquido + "...";
+#};
+
+# Intervalli:
+lista = [1..5] #=> var lista = [1, 2, 3, 4, 5];
+
+# Oggetti:
+matematica =
+ radice: Math.sqrt
+ quadrato: quadrato
+ cubo: (x) -> x * quadrato x
+#=> var matematica = {
+# "radice": Math.sqrt,
+# "quadrato": quadrato,
+# "cubo": function(x) { return x * quadrato(x); }
+#}
+
+# Splats:
+gara = (vincitore, partecipanti...) ->
+ print vincitore, partecipanti
+#=>gara = function() {
+# var partecipanti, vincitore;
+# vincitore = arguments[0], partecipanti = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+# return print(vincitore, partecipanti);
+#};
+
+# Esistenza:
+alert "Lo sapevo!" if elvis?
+#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("Lo sapevo!"); }
+
+# Comprensione degli Array:
+cubi = (matematica.cubo num for num in lista)
+#=>cubi = (function() {
+# var _i, _len, _results;
+# _results = [];
+# for (_i = 0, _len = lista.length; _i < _len; _i++) {
+# num = lista[_i];
+# _results.push(matematica.cubo(num));
+# }
+# return _results;
+# })();
+
+cibi = ['broccoli', 'spinaci', 'cioccolato']
+mangia cibo for cibo in cibi when cibo isnt 'cioccolato'
+#=>cibi = ['broccoli', 'spinaci', 'cioccolato'];
+#
+#for (_k = 0, _len2 = cibi.length; _k < _len2; _k++) {
+# cibo = cibi[_k];
+# if (cibo !== 'cioccolato') {
+# mangia(cibo);
+# }
+#}
+```
+
+## Altre risorse
+
+- [Smooth CoffeeScript](http://autotelicum.github.io/Smooth-CoffeeScript/)
+- [CoffeeScript Ristretto](https://leanpub.com/coffeescript-ristretto/read)
diff --git a/it-it/elixir-it.html.markdown b/it-it/elixir-it.html.markdown
new file mode 100644
index 00000000..f5d0c172
--- /dev/null
+++ b/it-it/elixir-it.html.markdown
@@ -0,0 +1,418 @@
+---
+language: elixir
+contributors:
+ - ["Luca 'Kino' Maroni", "https://github.com/kino90"]
+ - ["Joao Marques", "http://github.com/mrshankly"]
+ - ["Dzianis Dashkevich", "https://github.com/dskecse"]
+filename: learnelixir-it.ex
+lang: it-it
+---
+
+Elixir è un linguaggio funzionale moderno, costruito sulla VM Erlang.
+È totalmente compatibile con Erlang, ma con una sintassi più standard
+e molte altre funzionalità.
+
+```elixir
+
+# I commenti su una riga iniziano con un cancelletto.
+
+# Non esistono commenti multilinea,
+# ma puoi concatenare più commenti.
+
+# Per usare la shell di elixir usa il comando `iex`.
+# Compila i tuoi moduli con il comando `elixirc`.
+
+# Entrambi i comandi dovrebbero già essere nel tuo PATH se hai installato
+# elixir correttamente.
+
+## ---------------------------
+## -- Tipi di base
+## ---------------------------
+
+# Numeri
+3 # intero (Integer)
+0x1F # intero
+3.0 # decimale (Float)
+
+# Atomi, che sono literals, una costante con un nome. Iniziano con `:`.
+:ciao # atomo (Atom)
+
+# Tuple che sono salvate in celle di memoria contigue.
+{1,2,3} # tupla (Tuple)
+
+# Possiamo accedere ad un elemento di una tupla con la funzione `elem`:
+elem({1, 2, 3}, 0) #=> 1
+
+# Liste, che sono implementate come liste concatenate (o linked list).
+[1,2,3] # lista (List)
+
+# Possiamo accedere alla testa (head) e alla coda (tail) delle liste così:
+[testa | coda] = [1,2,3]
+testa #=> 1
+coda #=> [2,3]
+
+# In Elixir, proprio come in Erlang, il simbolo `=` denota pattern matching e
+# non un assegnamento.
+#
+# Questo significa che la parte sinistra (pattern) viene confrontata alla
+# parte destra.
+#
+# Questo spiega il funzionamento dell'esempio dell'accesso alla lista di prima.
+
+# Un pattern match darà errore quando le parti non combaciano, ad esempio se
+# le tuple hanno dimensione differente.
+# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
+
+# Ci sono anche i binari
+<<1,2,3>> # binari (Binary)
+
+# Stringhe e liste di caratteri
+"ciao" # stringa (String)
+'ciao' # lista di caratteri (List)
+
+# Stringhe multilinea
+"""
+Sono una stringa
+multi-linea.
+"""
+#=> "Sono una stringa\nmulti-linea.\n"
+
+# Le stringhe sono tutte codificate in UTF-8:
+"cìaò"
+#=> "cìaò"
+
+# le stringhe in realtà sono dei binari, e le liste di caratteri sono liste.
+<<?a, ?b, ?c>> #=> "abc"
+[?a, ?b, ?c] #=> 'abc'
+
+# `?a` in elixir restituisce il valore ASCII della lettera `a`
+?a #=> 97
+
+# Per concatenare liste si usa `++`, per binari si usa `<>`
+[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
+'ciao ' ++ 'mondo' #=> 'ciao mondo'
+
+<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
+"ciao " <> "mondo" #=> "ciao mondo"
+
+# Gli intervalli sono rappresentati come `inizio..fine` (estremi inclusi)
+1..10 #=> 1..10 (Range)
+minore..maggiore = 1..10 # Puoi fare pattern matching anche sugli intervalli
+[minore, maggiore] #=> [1, 10]
+
+## ---------------------------
+## -- Operatori
+## ---------------------------
+
+# Un po' di matematica
+1 + 1 #=> 2
+10 - 5 #=> 5
+5 * 2 #=> 10
+10 / 2 #=> 5.0
+
+# In elixir l'operatore `/` restituisce sempre un decimale.
+
+# Per fare una divisione intera si usa `div`
+div(10, 2) #=> 5
+
+# Per ottenere il resto di una divisione si usa `rem`
+rem(10, 3) #=> 1
+
+# Ci sono anche gli operatori booleani: `or`, `and` e `not`.
+# Questi operatori si aspettano un booleano come primo argomento.
+true and true #=> true
+false or true #=> true
+# 1 and true #=> ** (ArgumentError) argument error
+
+# Elixir fornisce anche `||`, `&&` e `!` che accettano argomenti
+# di qualsiasi tipo.
+# Tutti i valori tranne `false` e `nil` saranno valutati come true.
+1 || true #=> 1
+false && 1 #=> false
+nil && 20 #=> nil
+!true #=> false
+
+# Per i confronti abbiamo: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` e `>`
+1 == 1 #=> true
+1 != 1 #=> false
+1 < 2 #=> true
+
+# `===` e `!==` sono più rigidi quando si confrontano interi e decimali:
+1 == 1.0 #=> true
+1 === 1.0 #=> false
+
+# Possiamo anche confrontare tipi di dato diversi:
+1 < :ciao #=> true
+
+# L'ordine generale è definito sotto:
+# numeri < atomi < riferimenti < funzioni < porte < pid < tuple < liste
+# < stringhe di bit
+
+# Per citare Joe Armstrong su questo: "L'ordine non è importante,
+# ma è importante che sia definito un ordine."
+
+## ---------------------------
+## -- Controllo di flusso
+## ---------------------------
+
+# espressione `se` (`if`)
+if false do
+ "Questo non si vedrà mai"
+else
+ "Questo sì"
+end
+
+# c'è anche un `se non` (`unless`)
+unless true do
+ "Questo non si vedrà mai"
+else
+ "Questo sì"
+end
+
+# Ti ricordi il pattern matching?
+# Moltre strutture di controllo di flusso in elixir si basano su di esso.
+
+# `case` ci permette di confrontare un valore a diversi pattern:
+case {:uno, :due} do
+ {:quattro, :cinque} ->
+ "Questo non farà match"
+ {:uno, x} ->
+ "Questo farà match e binderà `x` a `:due`"
+ _ ->
+ "Questo farà match con qualsiasi valore"
+end
+
+# Solitamente si usa `_` se non si ha bisogno di utilizzare un valore.
+# Ad esempio, se ci serve solo la testa di una lista:
+[testa | _] = [1,2,3]
+testa #=> 1
+
+# Per aumentare la leggibilità possiamo usarlo in questo modo:
+[testa | _coda] = [:a, :b, :c]
+testa #=> :a
+
+# `cond` ci permette di verificare più condizioni allo stesso momento.
+# Usa `cond` invece di innestare più espressioni `if`.
+cond do
+ 1 + 1 == 3 ->
+ "Questa stringa non si vedrà mai"
+ 2 * 5 == 12 ->
+ "Nemmeno questa"
+ 1 + 2 == 3 ->
+ "Questa sì!"
+end
+
+# È pratica comune mettere l'ultima condizione a `true`, che farà sempre match
+cond do
+ 1 + 1 == 3 ->
+ "Questa stringa non si vedrà mai"
+ 2 * 5 == 12 ->
+ "Nemmeno questa"
+ true ->
+ "Questa sì! (essenzialmente funziona come un else)"
+end
+
+# `try/catch` si usa per gestire i valori lanciati (throw),
+# Supporta anche una clausola `after` che è invocata in ogni caso.
+try do
+ throw(:ciao)
+catch
+ message -> "Ho ricevuto #{message}."
+after
+ IO.puts("Io sono la clausola 'after'.")
+end
+#=> Io sono la clausola 'after'
+# "Ho ricevuto :ciao"
+
+## ---------------------------
+## -- Moduli e Funzioni
+## ---------------------------
+
+# Funzioni anonime (notare il punto)
+quadrato = fn(x) -> x * x end
+quadrato.(5) #=> 25
+
+# Accettano anche guardie e condizioni multiple.
+# le guardie ti permettono di perfezionare il tuo pattern matching,
+# sono indicate dalla parola chiave `when`:
+f = fn
+ x, y when x > 0 -> x + y
+ x, y -> x * y
+end
+
+f.(1, 3) #=> 4
+f.(-1, 3) #=> -3
+
+# Elixir fornisce anche molte funzioni, disponibili nello scope corrente.
+is_number(10) #=> true
+is_list("ciao") #=> false
+elem({1,2,3}, 0) #=> 1
+
+# Puoi raggruppare delle funzioni all'interno di un modulo.
+# All'interno di un modulo usa `def` per definire le tue funzioni.
+defmodule Matematica do
+ def somma(a, b) do
+ a + b
+ end
+
+ def quadrato(x) do
+ x * x
+ end
+end
+
+Matematica.somma(1, 2) #=> 3
+Matematica.quadrato(3) #=> 9
+
+# Per compilare il modulo 'Matematica' salvalo come `matematica.ex` e usa
+# `elixirc`.
+# nel tuo terminale: elixirc matematica.ex
+
+# All'interno di un modulo possiamo definire le funzioni con `def` e funzioni
+# private con `defp`.
+# Una funzione definita con `def` è disponibile per essere invocata anche da
+# altri moduli, una funziona privata può essere invocata solo localmente.
+defmodule MatematicaPrivata do
+ def somma(a, b) do
+ esegui_somma(a, b)
+ end
+
+ defp esegui_somma(a, b) do
+ a + b
+ end
+end
+
+MatematicaPrivata.somma(1, 2) #=> 3
+# MatematicaPrivata.esegui_somma(1, 2) #=> ** (UndefinedFunctionError)
+
+# Anche le dichiarazioni di funzione supportano guardie e condizioni multiple:
+defmodule Geometria do
+ def area({:rettangolo, w, h}) do
+ w * h
+ end
+
+ def area({:cerchio, r}) when is_number(r) do
+ 3.14 * r * r
+ end
+end
+
+Geometria.area({:rettangolo, 2, 3}) #=> 6
+Geometria.area({:cerchio, 3}) #=> 28.25999999999999801048
+# Geometria.area({:cerchio, "non_un_numero"})
+#=> ** (FunctionClauseError) no function clause matching in Geometria.area/1
+
+# A causa dell'immutabilità dei dati, la ricorsione è molto frequente in elixir
+defmodule Ricorsione do
+ def somma_lista([testa | coda], accumulatore) do
+ somma_lista(coda, accumulatore + testa)
+ end
+
+ def somma_lista([], accumulatore) do
+ accumulatore
+ end
+end
+
+Ricorsione.somma_lista([1,2,3], 0) #=> 6
+
+# I moduli di Elixir supportano attributi. Ci sono degli attributi incorporati
+# e puoi anche aggiungerne di personalizzati.
+defmodule Modulo do
+ @moduledoc """
+ Questo è un attributo incorporato in un modulo di esempio.
+ """
+
+ @miei_dati 100 # Questo è un attributo personalizzato .
+ IO.inspect(@miei_dati) #=> 100
+end
+
+## ---------------------------
+## -- Strutture ed Eccezioni
+## ---------------------------
+
+
+# Le Strutture (Structs) sono estensioni alle mappe che portano
+# valori di default, garanzia alla compilazione e polimorfismo in Elixir.
+defmodule Persona do
+ defstruct nome: nil, eta: 0, altezza: 0
+end
+
+luca = %Persona{ nome: "Luca", eta: 24, altezza: 185 }
+#=> %Persona{eta: 24, altezza: 185, nome: "Luca"}
+
+# Legge al valore di 'nome'
+luca.nome #=> "Luca"
+
+# Modifica il valore di eta
+luca_invecchiato = %{ luca | eta: 25 }
+#=> %Persona{eta: 25, altezza: 185, nome: "Luca"}
+
+# Il blocco `try` con la parola chiave `rescue` è usato per gestire le eccezioni
+try do
+ raise "un errore"
+rescue
+ RuntimeError -> "Salvato un errore di Runtime"
+ _error -> "Questo salverà da qualsiasi errore"
+end
+
+# Tutte le eccezioni hanno un messaggio
+try do
+ raise "un errore"
+rescue
+ x in [RuntimeError] ->
+ x.message
+end
+
+## ---------------------------
+## -- Concorrenza
+## ---------------------------
+
+# Elixir si basa sul modello degli attori per la concorrenza.
+# Tutto ciò di cui abbiamo bisogno per scrivere programmi concorrenti in elixir
+# sono tre primitive: creare processi, inviare messaggi e ricevere messaggi.
+
+# Per creare un nuovo processo si usa la funzione `spawn`, che riceve una
+# funzione come argomento.
+f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
+spawn(f) #=> #PID<0.40.0>
+
+# `spawn` restituisce un pid (identificatore di processo). Puoi usare questo
+# pid per inviare messaggi al processo.
+# Per passare messaggi si usa l'operatore `send`.
+# Perché tutto questo sia utile dobbiamo essere capaci di ricevere messaggi,
+# oltre ad inviarli. Questo è realizzabile con `receive`:
+defmodule Geometria do
+ def calcolo_area do
+ receive do
+ {:rettangolo, w, h} ->
+ IO.puts("Area = #{w * h}")
+ calcolo_area()
+ {:cerchio, r} ->
+ IO.puts("Area = #{3.14 * r * r}")
+ calcolo_area()
+ end
+ end
+end
+
+# Compila il modulo e crea un processo che esegue `calcolo_area` nella shell
+pid = spawn(fn -> Geometria.calcolo_area() end) #=> #PID<0.40.0>
+
+# Invia un messaggio a `pid` che farà match su un pattern nel blocco in receive
+send pid, {:rettangolo, 2, 3}
+#=> Area = 6
+# {:rettangolo,2,3}
+
+send pid, {:cerchio, 2}
+#=> Area = 12.56000000000000049738
+# {:cerchio,2}
+
+# Anche la shell è un processo. Puoi usare `self` per ottenere il pid corrente
+self() #=> #PID<0.27.0>
+```
+
+## Referenze
+
+* [Getting started guide](http://elixir-lang.org/getting_started/1.html) dalla [pagina web ufficiale di elixir](http://elixir-lang.org)
+* [Documentazione Elixir](http://elixir-lang.org/docs/master/)
+* ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) di Dave Thomas
+* [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf)
+* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) di Fred Hebert
+* ["Programming Erlang: Software for a Concurrent World"](https://pragprog.com/book/jaerlang2/programming-erlang) di Joe Armstrong
diff --git a/make.html.markdown b/make.html.markdown
new file mode 100644
index 00000000..75543dcd
--- /dev/null
+++ b/make.html.markdown
@@ -0,0 +1,243 @@
+---
+language: make
+contributors:
+ - ["Robert Steed", "https://github.com/robochat"]
+filename: Makefile
+---
+
+A Makefile defines a graph of rules for creating a target (or targets).
+Its purpose is to do the minimum amount of work needed to update a
+target to the most recent version of the source. Famously written over a
+weekend by Stuart Feldman in 1976, it is still widely used (particularly
+on Unix) despite many competitors and criticisms.
+
+There are many varieties of make in existance, this article assumes that
+we are using GNU make which is the standard on Linux.
+
+```make
+
+# Comments can be written like this.
+
+# Files should be named Makefile and then be can run as `make <target>`.
+# Otherwise we use `make -f "filename" <target>`.
+
+# Warning - only use TABS to indent in Makefiles, never spaces!
+
+#-----------------------------------------------------------------------
+# Basics
+#-----------------------------------------------------------------------
+
+# A rule - this rule will only run if file0.txt doesn't exist.
+file0.txt:
+ echo "foo" > file0.txt
+ # Even comments in these 'recipe' sections get passed to the shell.
+ # Try `make file0.txt` or simply `make` - first rule is the default.
+
+
+# This rule will only run if file0.txt is newer than file1.txt.
+file1.txt: file0.txt
+ cat file0.txt > file1.txt
+ # use the same quoting rules as in the shell.
+ @cat file0.txt >> file1.txt
+ # @ stops the command from being echoed to stdout.
+ -@echo 'hello'
+ # - means that make will keep going in the case of an error.
+ # Try `make file1.txt` on the commandline.
+
+# A rule can have multiple targets and multiple prerequisites
+file2.txt file3.txt: file0.txt file1.txt
+ touch file2.txt
+ touch file3.txt
+
+# Make will complain about multiple recipes for the same rule. Empty
+# recipes don't count though and can be used to add new dependencies.
+
+#-----------------------------------------------------------------------
+# Phony Targets
+#-----------------------------------------------------------------------
+
+# A phony target. Any target that isn't a file.
+# It will never be up to date so make will always try to run it.
+all: maker process
+
+# We can declare things out of order.
+maker:
+ touch ex0.txt ex1.txt
+
+# Can avoid phony rules breaking when a real file has the same name by
+.PHONY: all maker process
+# This is a special target. There are several others.
+
+# A rule with a dependency on a phony target will always run
+ex0.txt ex1.txt: maker
+
+# Common phony targets are: all make clean install ...
+
+#-----------------------------------------------------------------------
+# Automatic Variables & Wildcards
+#-----------------------------------------------------------------------
+
+process: file*.txt #using a wildcard to match filenames
+ @echo $^ # $^ is a variable containing the list of prerequisites
+ @echo $@ # prints the target name
+ #(for multiple target rules, $@ is whichever caused the rule to run)
+ @echo $< # the first prerequisite listed
+ @echo $? # only the dependencies that are out of date
+ @echo $+ # all dependencies including duplicates (unlike normal)
+ #@echo $| # all of the 'order only' prerequisites
+
+# Even if we split up the rule dependency definitions, $^ will find them
+process: ex1.txt file0.txt
+# ex1.txt will be found but file0.txt will be deduplicated.
+
+#-----------------------------------------------------------------------
+# Patterns
+#-----------------------------------------------------------------------
+
+# Can teach make how to convert certain files into other files.
+
+%.png: %.svg
+ inkscape --export-png $^
+
+# Pattern rules will only do anything if make decides to create the \
+target.
+
+# Directory paths are normally ignored when matching pattern rules. But
+# make will try to use the most appropriate rule available.
+small/%.png: %.svg
+ inkscape --export-png --export-dpi 30 $^
+
+# make will use the last version for a pattern rule that it finds.
+%.png: %.svg
+ @echo this rule is chosen
+
+# However make will use the first pattern rule that can make the target
+%.png: %.ps
+ @echo this rule is not chosen if *.svg and *.ps are both present
+
+# make already has some pattern rules built-in. For instance, it knows
+# how to turn *.c files into *.o files.
+
+# Older makefiles might use suffix rules instead of pattern rules
+.png.ps:
+ @echo this rule is similar to a pattern rule.
+
+# Tell make about the suffix rule
+.SUFFIXES: .png
+
+#-----------------------------------------------------------------------
+# Variables
+#-----------------------------------------------------------------------
+# aka. macros
+
+# Variables are basically all string types
+
+name = Ted
+name2="Sarah"
+
+echo:
+ @echo $(name)
+ @echo ${name2}
+ @echo $name # This won't work, treated as $(n)ame.
+ @echo $(name3) # Unknown variables are treated as empty strings.
+
+# There are 4 places to set variables.
+# In order of priority from highest to lowest:
+# 1: commandline arguments
+# 2: Makefile
+# 3: shell enviroment variables - make imports these automatically.
+# 4: make has some predefined variables
+
+name4 ?= Jean
+# Only set the variable if enviroment variable is not already defined.
+
+override name5 = David
+# Stops commandline arguments from changing this variable.
+
+name4 +=grey
+# Append values to variable (includes a space).
+
+# Pattern-specific variable values (GNU extension).
+echo: name2 = Sara # True within the matching rule
+ # and also within its remade recursive dependencies
+ # (except it can break when your graph gets too complicated!)
+
+# Some variables defined automatically by make.
+echo_inbuilt:
+ echo $(CC)
+ echo ${CXX)}
+ echo $(FC)
+ echo ${CFLAGS)}
+ echo $(CPPFLAGS)
+ echo ${CXXFLAGS}
+ echo $(LDFLAGS)
+ echo ${LDLIBS}
+
+#-----------------------------------------------------------------------
+# Variables 2
+#-----------------------------------------------------------------------
+
+# The first type of variables are evaluated each time they are used.
+# This can be expensive, so a second type of variable exists which is
+# only evaluated once. (This is a GNU make extension)
+
+var := hello
+var2 ::= $(var) hello
+#:= and ::= are equivalent.
+
+# These variables are evaluated procedurely (in the order that they
+# appear), thus breaking with the rest of the language !
+
+# This doesn't work
+var3 ::= $(var4) and good luck
+var4 ::= good night
+
+#-----------------------------------------------------------------------
+# Functions
+#-----------------------------------------------------------------------
+
+# make has lots of functions available.
+
+sourcefiles = $(wildcard *.c */*.c)
+objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
+
+# Format is $(func arg0,arg1,arg2...)
+
+# Some examples
+ls: * src/*
+ @echo $(filter %.txt, $^)
+ @echo $(notdir $^)
+ @echo $(join $(dir $^),$(notdir $^))
+
+#-----------------------------------------------------------------------
+# Directives
+#-----------------------------------------------------------------------
+
+# Include other makefiles, useful for platform specific code
+include foo.mk
+
+sport = tennis
+# Conditional compilation
+report:
+ifeq ($(sport),tennis)
+ @echo 'game, set, match'
+else
+ @echo "They think it's all over; it is now"
+endif
+
+# There are also ifneq, ifdef, ifndef
+
+foo = true
+
+ifdef $(foo)
+bar = 'hello'
+endif
+```
+
+
+### More Resources
+
++ [gnu make documentation](https://www.gnu.org/software/make/manual/)
++ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
++ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
+
diff --git a/matlab.html.markdown b/matlab.html.markdown
index 9de41275..00f4c53a 100644
--- a/matlab.html.markdown
+++ b/matlab.html.markdown
@@ -43,7 +43,7 @@ edit('myfunction.m') % Open function/script in editor
type('myfunction.m') % Print the source of function/script to Command Window
profile on % turns on the code profiler
-profile of % turns off the code profiler
+profile off % turns off the code profiler
profile viewer % Open profiler
help command % Displays documentation for command in Command Window
diff --git a/objective-c.html.markdown b/objective-c.html.markdown
index 56640a87..91b84b47 100644
--- a/objective-c.html.markdown
+++ b/objective-c.html.markdown
@@ -415,7 +415,7 @@ distance = 18; // References "long distance" from MyClass implementation
+ (NSString *)classMethod
{
- return [[self alloc] init];
+ return @"Some string";
}
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
diff --git a/perl.html.markdown b/perl.html.markdown
index aac95939..4e172406 100644
--- a/perl.html.markdown
+++ b/perl.html.markdown
@@ -12,16 +12,16 @@ Perl 5 is a highly capable, feature-rich programming language with over 25 years
Perl 5 runs on over 100 platforms from portables to mainframes and is suitable for both rapid prototyping and large scale development projects.
```perl
-# Single line comments start with a number symbol.
+# Single line comments start with a number sign.
#### Perl variable types
-# Variables begin with the $ symbol.
+# Variables begin with a sigil, which is a symbol showing the type.
# A valid variable name starts with a letter or underscore,
# followed by any number of letters, numbers, or underscores.
-### Perl has three main variable types: scalars, arrays, and hashes.
+### Perl has three main variable types: $scalar, @array, and %hash.
## Scalars
# A scalar represents a single value:
@@ -47,9 +47,9 @@ my %fruit_color = ("apple", "red", "banana", "yellow");
# You can use whitespace and the "=>" operator to lay them out more nicely:
my %fruit_color = (
- apple => "red",
- banana => "yellow",
- );
+ apple => "red",
+ banana => "yellow",
+);
# Scalars, arrays and hashes are documented more fully in perldata.
# (perldoc perldata).
@@ -60,17 +60,17 @@ my %fruit_color = (
# Perl has most of the usual conditional and looping constructs.
-if ( $var ) {
- ...
-} elsif ( $var eq 'bar' ) {
- ...
+if ($var) {
+ ...
+} elsif ($var eq 'bar') {
+ ...
} else {
- ...
+ ...
}
-unless ( condition ) {
- ...
- }
+unless (condition) {
+ ...
+}
# This is provided as a more readable version of "if (!condition)"
# the Perlish post-condition way
@@ -78,19 +78,29 @@ print "Yow!" if $zippy;
print "We have no bananas" unless $bananas;
# while
- while ( condition ) {
- ...
- }
+while (condition) {
+ ...
+}
+
+# for loops and iteration
+for (my $i = 0; $i < $max; $i++) {
+ print "index is $i";
+}
-# for and foreach
-for ($i = 0; $i <= $max; $i++) {
- ...
- }
+for (my $i = 0; $i < @elements; $i++) {
+ print "Current element is " . $elements[$i];
+}
-foreach (@array) {
- print "This element is $_\n";
- }
+for my $element (@elements) {
+ print $element;
+}
+
+# implicitly
+
+for (@elements) {
+ print;
+}
#### Regular expressions
@@ -129,9 +139,11 @@ my @lines = <$in>;
# Writing subroutines is easy:
sub logger {
- my $logmessage = shift;
- open my $logfile, ">>", "my.log" or die "Could not open my.log: $!";
- print $logfile $logmessage;
+ my $logmessage = shift;
+
+ open my $logfile, ">>", "my.log" or die "Could not open my.log: $!";
+
+ print $logfile $logmessage;
}
# Now we can use the subroutine just as any other built-in function:
diff --git a/perl6.html.markdown b/perl6.html.markdown
index 3bb87916..8d425f7d 100644
--- a/perl6.html.markdown
+++ b/perl6.html.markdown
@@ -7,10 +7,13 @@ contributors:
- ["Nami-Doc", "http://github.com/Nami-Doc"]
---
-Perl 6 is a highly capable, feature-rich programming language made for the
-upcoming hundred years.
+Perl 6 is a highly capable, feature-rich programming language made for at
+least the next hundred years.
-Perl 6 runs on [the MoarVM](http://moarvm.com) and the JVM.
+The primary Perl 6 compiler is called [Rakudo](http://rakudo.org), which runs on
+the JVM and [the MoarVM](http://moarvm.com) and
+[prior to March 2015](http://pmthium.com/2015/02/suspending-rakudo-parrot/),
+[the Parrot VM](http://parrot.org/).
Meta-note : the triple pound signs are here to denote headlines,
double paragraphs, and single notes.
@@ -210,7 +213,7 @@ say $x; #=> 52
# - `if`
# Before talking about `if`, we need to know which values are "Truthy"
# (represent True), and which are "Falsey" (or "Falsy") -- represent False.
-# Only these values are Falsey: (), 0, "", Nil, A type (like `Str` or `Int`),
+# Only these values are Falsey: 0, (), {}, "", Nil, A type (like `Str` or `Int`),
# and of course False itself.
# Every other value is Truthy.
if True {
@@ -1041,7 +1044,7 @@ postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that)
# *everything* -- with great power comes great responsibility)
## Meta operators !
-# Oh boy, get ready. Get ready, because we're dwelving deep
+# Oh boy, get ready. Get ready, because we're delving deep
# into the rabbit's hole, and you probably won't want to go
# back to other languages after reading that.
# (I'm guessing you don't want to already at that point).
diff --git a/pl-pl/brainfuck-pl.html.markdown b/pl-pl/brainfuck-pl.html.markdown
new file mode 100644
index 00000000..69d814c4
--- /dev/null
+++ b/pl-pl/brainfuck-pl.html.markdown
@@ -0,0 +1,93 @@
+---
+language: brainfuck
+contributors:
+ - ["Prajit Ramachandran", "http://prajitr.github.io/"]
+ - ["Mathias Bynens", "http://mathiasbynens.be/"]
+translators:
+ - ["Jakub Młokosiewicz", "https://github.com/hckr"]
+lang: pl-pl
+---
+
+Brainfuck (pisane małymi literami, za wyjątkiem początku zdania) jest bardzo
+minimalistycznym, kompletnym w sensie Turinga, językiem programowania.
+Zawiera zaledwie 8 poleceń.
+
+Możesz przetesotwać brainfucka w swojej przeglądarce, korzystając z narzędzia
+[brainfuck-visualizer](http://fatiherikli.github.io/brainfuck-visualizer/).
+
+```
+Wszystkie znaki oprócz "><+-.,[]" (wyłączając znaki zapytania) są ignorowane.
+
+Pamięć w brainfucku jest reprezentowana przez tablicę 30.000 komórek
+zainicjalizowanych zerami, ze wskaźnikiem pokazującym na aktualną komórkę.
+
+Oto osiem poleceń brainfucka:
++ : inkrementuje (zwiększa o jeden) wartość aktualnie wskazywanej komórki
+- : dekrementuje (zmniejsza o jeden) wartość aktualnie wskazywanej komórki
+> : przesuwa wskaźnik na następną komórkę (w prawo)
+< : przesuwa wskaźnik na poprzednią komórkę (w lewo)
+. : wyświetla wartość bieżącej komórki (w formie znaku ASCII, np. 65 = 'A')
+, : wczytuje (jeden) znak z wejścia do bieżącej komórki
+ (konkretnie jego numer z tabeli ASCII)
+[ : jeśli wartość w bieżącej komórce jest rózna zero, przechodzi do
+ odpowiadającego ]; w przeciwnym wypdaku przechodzi do następnej instrukcji
+] : Jeśli wartość w bieżącej komórce jest rózna od zera, przechodzi do
+ następnej instrukcji; w przeciwnym wypdaku przechodzi do odpowiadającego [
+
+[ i ] oznaczają pętlę while. Oczywiście każda pętla rozpoczęta [
+musi być zakończona ].
+
+Zobaczmy kilka prostych programów w brainfucku.
+
+
+++++++ [ > ++++++++++ < - ] > +++++ .
+
+Ten program wypisuje literę 'A'. Najpierw zwiększa wartość komórki #1 do 6.
+Komórka #1 będzie wykorzystana w pętli. Następnie program wchodzi w pętlę ([)
+i przechodzi do komórki #2. Pętla wykonuje się sześć razy (komórka #1 jest
+dekrementowana sześć razy, nim osiągnie wartość zero, kiedy to program
+przechodzi do odpowiadającego ] i wykonuje kolejne instrukcje).
+
+W tym momencie wskaźnik pokazuje na komórkę #1, mającą wartość 0, podczas gdy
+komórka #2 ma wartość 60. Przesuwamy wskaźnik na komórkę #2, inkrementujemy ją
+pięć razy, uzyskując wartość 65. Następnie wyświetlamy wartość komórki #2.
+65 to 'A' w tabeli ASCII, więc właśnie ten znak jest wypisany na konsolę.
+
+
+, [ > + < - ] > .
+
+Ten program wczytuje znak z wejścia i umieszcza jego kod ASCII w komórce #1.
+Następnie zaczyna się pętla, w której znajdują się następujące instrukcje:
+przesunięcie wskaźnika na komórkę #2, inkrementacja wartości komóri #2,
+powrót do komórki #1 i dekrementacja wartości komórki #1. Instrukcje pętli
+wykonują się aż wartość komórki #1 osiągnie zero, a komórka #2 osiągnie
+poprednią wartość komórki #1. Ponieważ na końcu pętli wskaźnik pokazuje na
+komórkę #1, po pętli następuje instrukcja przejścia do komórki #2 i wysłanie
+jej wartości (w formie znaku ASCII) na wyjście.
+
+Zauważ, że odstępy służą wyłącznie poprawie czytelności.
+Równie dobrze można powyższy program zapisać tak:
+
+,[>+<-]>.
+
+
+Spróbuj odgadnąć, co robi poniższy program:
+
+,>,< [ > [ >+ >+ << -] >> [- << + >>] <<< -] >>
+
+Ten program pobiera z wejścia dwie liczby i je mnoży.
+
+Po wczytaniu dwóch wejść (do komórek #1 i #2) następuje pętla zewnętrzna,
+warunkowana wartością komórki #1. Następnie program przechodzi do komórki #2
+i rozpoczyna pętlę wewnętrzną z warunkiem zakończenia w komórce #2,
+inkrementującą komórkę #3. Tu jednak pojawia się problem: w chwili zakończenia
+wewnętrznej pętli komórka #2 ma wartość zero. W takim razie wewętrzna pętla
+nie wywoła się następny raz. Aby rozwiązać ten problem, inkrementujemy także
+wartość komórki #4, a następnie kopiujemy jej wartość do komórki #2.
+Ostatecznie wynik działania znajduje się w komórce #3.
+```
+
+I to właśnie jest brainfuck. Nie taki trudny, co? W ramach rozrywki możesz
+napisać własne programy w brainfucku. Możesz też napisać interpreter brainfucka
+w innym języku. Implementacja interpretera to dość proste zadanie. Jeśli
+jesteś masochistą, spróbuj napisać interpreter brainfucka w... brainfucku.
diff --git a/pl-pl/python-pl.html.markdown b/pl-pl/python-pl.html.markdown
new file mode 100644
index 00000000..c3e8287a
--- /dev/null
+++ b/pl-pl/python-pl.html.markdown
@@ -0,0 +1,637 @@
+---
+name: python
+category: language
+language: python
+filename: learnpython-pl.py
+contributors:
+ - ["Louie Dinh", "http://ldinh.ca"]
+ - ["Amin Bandali", "http://aminbandali.com"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
+translators:
+ - ["Dominik Krzemiński", "https://github.com/dokato"]
+lang: pl-pl
+---
+
+Python został opracowany przez Guido Van Rossuma na początku lat 90-tych.
+Obecnie jest jednym z najbardziej popularnych języków programowania.
+Zakochałem się w Pythonie dzięki porządkowi, jaki utrzymywany jest w kodzie.
+To po prostu wykonywalny pseudokod.
+
+Zapraszam do kontaktu. Złapiecie nas na:
+- kontakt polski: raymon92 [at] [google's email service]
+- kontakt angielski: [@louiedinh](http://twitter.com/louiedinh) lub louiedinh [at] [google's email service]
+
+Uwaga: Ten artykuł odnosi się do wersji Pythona 2.7, ale powinien
+działać w wersjach 2.x. Dla wersji 3.x znajdziesz odpowiedni artykuł na stronie głównej.
+
+```python
+# -*- coding: utf-8 -*-
+
+# Pojedyncze komentarze oznaczamy takim symbolem.
+
+""" Wielolinijkowe napisy zapisywane są przy użyciu
+ trzech znaków cudzysłowiu i często
+ wykorzystywane są jako komentarze.
+"""
+
+####################################################
+## 1. Podstawowe typy danych i operatory
+####################################################
+
+# Liczby to liczby
+3 # => 3
+
+# Matematyka jest intuicyjna
+1 + 1 # => 2
+8 - 1 # => 7
+10 * 2 # => 20
+35 / 5 # => 7
+
+# Dzielenie może być kłopotliwe. Poniższe to dzielenie
+# całkowitoliczbowe(int) i wynik jest automatycznie zaokrąglany.
+5 / 2 # => 2
+
+# Aby to naprawić musimy powiedzieć nieco o liczbach zmiennoprzecinkowych.
+2.0 # To liczba zmiennoprzecinkowa, tzw. float
+11.0 / 4.0 # => 2.75 ahhh...znacznie lepiej
+
+# Wynik dzielenia całkowitoliczbowego jest obcinany dla liczb
+# dodatnich i ujemnych.
+5 // 3 # => 1
+5.0 // 3.0 # => 1.0 # działa też na floatach
+-5 // 3 # => -2
+-5.0 // 3.0 # => -2.0
+
+# Operator modulo - wyznaczanie reszty z dzielenia
+7 % 3 # => 1
+
+# Potęgowanie (x do potęgi ytej)
+2**4 # => 16
+
+# Wymuszanie pierwszeństwa w nawiasach
+(1 + 3) * 2 # => 8
+
+# Operacje logiczne
+# Zauważ, że przy "and" i "or" trzeba zwracać uwagę na rozmiar liter
+True and False #=> False # Fałsz
+False or True #=> True # Prawda
+
+# Zauważ, że operatorów logicznych można używać z intami
+0 and 2 #=> 0
+-5 or 0 #=> -5
+0 == False #=> True
+2 == True #=> False
+k1 == True #=> True
+
+# aby zanegować użyj "not"
+not True # => False
+not False # => True
+
+# Równość ==
+1 == 1 # => True
+2 == 1 # => False
+
+# Nierówność !=
+1 != 1 # => False
+2 != 1 # => True
+
+# Więcej porównań
+1 < 10 # => True
+1 > 10 # => False
+2 <= 2 # => True
+2 >= 2 # => True
+
+# Porównania można układać w łańcuch!
+1 < 2 < 3 # => True
+2 < 3 < 2 # => False
+
+# Napisy (typ string) tworzone są przy użyciu cudzysłowów " lub '
+"Jestem napisem."
+'Ja też jestem napisem.'
+
+# Napisy można dodawać!
+"Witaj " + "świecie!" # => "Witaj świecie!"
+
+# ... a nawet mnożone
+"Hej" * 3 # => "HejHejHej"
+
+# Napis może być traktowany jako lista znaków
+"To napis"[0] # => 'T'
+
+# % może być używane do formatowania napisów:
+"%s są %s" % ("napisy", "fajne")
+
+# Jednak nowszym sposobem formatowania jest metoda "format".
+# Ta metoda jest obecnie polecana:
+"{0} są {1}".format("napisy", "fajne")
+# Jeśli nie chce ci się liczyć użyj słów kluczowych.
+"{imie} chce zjeść {jadlo}".format(imie="Bob", jasno="lasagne")
+
+# None jest obiektem
+None # => None
+
+# Nie używaj "==" w celu porównania obiektów z None
+# Zamiast tego użyj "is"
+"etc" is None # => False
+None is None # => True
+
+# Operator 'is' testuje identyczność obiektów. To nie jest zbyt
+# pożyteczne, gdy działamy tylko na prostych wartościach,
+# ale przydaje się, gdy mamy do czynienia z obiektami.
+
+# None, 0, i pusty napis "" są odpowiednikami logicznego False.
+# Wszystkie inne wartości są True
+bool(0) # => False
+bool("") # => False
+
+
+####################################################
+## 2. Zmienne i zbiory danych
+####################################################
+
+# Python ma wyrażenie wypisujące "print" we wszystkich wersjach 2.x, ale
+# zostało usunięte z wersji 3.
+print "Jestem Python. Miło poznać!"
+# Python ma też funkcję "print" dostępną w wersjach 2.7 and 3...
+# ale w 2.7 musisz dodać import (odkomentuj):
+# from __future__ import print_function
+print("Ja też jestem Python! ")
+
+# Nie trzeba deklarować zmiennych przed przypisaniem.
+jakas_zmienna = 5 # Konwencja mówi: używaj małych znaków i podłogi _
+jakas_zmienna # => 5
+
+# Próba dostępu do niezadeklarowanej zmiennej da błąd.
+# Przejdź do sekcji Obsługa wyjątków po więcej...
+inna_zmienna # Wyrzuca nazwę błędu
+
+# "if" może być użyte jako wyrażenie
+"huraaa!" if 3 > 2 else 2 # => "huraaa!"
+
+# Listy:
+li = []
+# Możesz zacząć od wypełnionej listy
+inna_li = [4, 5, 6]
+
+# Dodaj na koniec używając "append"
+li.append(1) # li to teraz [1]
+li.append(2) # li to teraz [1, 2]
+li.append(4) # li to teraz [1, 2, 4]
+li.append(3) # li to teraz [1, 2, 4, 3]
+# Usuwanie z konca da "pop"
+li.pop() # => 3 a li stanie się [1, 2, 4]
+# Dodajmy ponownie
+li.append(3) # li to znowu [1, 2, 4, 3].
+
+# Dostęp do list jak do każdej tablicy
+li[0] # => 1
+# Użyj = aby nadpisać wcześniej wypełnione miejsca w liście
+li[0] = 42
+li[0] # => 42
+li[0] = 1 # Uwaga: ustawiamy starą wartość
+# Tak podglądamy ostatni element
+li[-1] # => 3
+
+# Jeżeli wyjdziesz poza zakres...
+li[4] # ... zobaczysz IndexError
+
+# Możesz tworzyć wyniki.
+li[1:3] # => [2, 4]
+# Bez początku
+li[2:] # => [4, 3]
+# Omijamy koniec
+li[:3] # => [1, 2, 4]
+# Wybierz co drugi
+li[::2] # =>[1, 4]
+# Odwróć listę
+li[::-1] # => [3, 4, 2, 1]
+# Użyj kombinacji powyższych aby tworzyć bardziej skomplikowane wycinki
+# li[poczatek:koniec:krok]
+
+# Usuń element używając "del"
+del li[2] # li to teraz [1, 2, 3]
+
+# Listy można dodawać
+li + inna_li # => [1, 2, 3, 4, 5, 6]
+# Uwaga: wartości poszczególnych list się nie zmieniają.
+
+# Do łączenia list użyj "extend()"
+li.extend(other_li) # li to teraz [1, 2, 3, 4, 5, 6]
+
+# Sprawdź czy jest w liście używając "in"
+1 in li # => True
+
+# "len()" pokazuje długość listy
+len(li) # => 6
+
+
+# Krotki (tuple) są jak listy, ale nie można ich modyfikować.
+tup = (1, 2, 3)
+tup[0] # => 1
+tup[0] = 3 # wyrzuci TypeError
+
+# Ale wielu akcji dla list możesz używać przy krotkach
+len(tup) # => 3
+tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6)
+tup[:2] # => (1, 2)
+2 in tup # => True
+
+# Można rozpakować krotki i listy do poszczególych zmiennych
+a, b, c = (1, 2, 3) # a to teraz 1, b jest 2, a c to 3
+# Jeżeli zapomnisz nawiasów automatycznie tworzone są krotki
+d, e, f = 4, 5, 6
+# Popatrz jak prosto zamienić wartości
+e, d = d, e # d to teraz 5 a e to 4
+
+
+# Słowniki są również pożyteczne
+pusty_slownik = {}
+# Tu tworzymy wypełniony:
+pelen_slownik = {"raz": 1, "dwa": 2, "trzy": 3}
+
+# Podglądany wartość
+pelen_slownik["one"] # => 1
+
+# Wypisz wszystkie klucze używając "keys()"
+pelen_slownik.keys() # => ["trzy", "dwa", "raz"]
+# Uwaga: słowniki nie gwarantują kolejności występowania kluczy.
+
+# A teraz wszystkie wartości "values()"
+pelen_slownik.values() # => [3, 2, 1]
+# Uwaga: to samo dotyczy wartości.
+
+# Sprawdzanie czy występuje to "in"
+"raz" in pelen_slownik # => True
+1 in pelen_slownik # => False
+
+# Próba dobrania się do nieistniejącego klucza da KeyError
+pelen_slownik["cztery"] # KeyError
+
+# Użyj "get()" method aby uniknąć KeyError
+pelen_slownik.get("raz") # => 1
+pelen_slownik.get("cztery") # => None
+# Metoda get zwraca domyślną wartość gdy brakuje klucza
+pelen_slownik.get("one", 4) # => 1
+pelen_slownik.get("cztery", 4) # => 4
+# zauważ, że pelen_slownik.get("cztery") jest wciąż => None
+# (get nie ustawia wartości słownika)
+
+# przypisz wartość do klucza podobnie jak w listach
+pelen_slownik["cztery"] = 4 # teraz: pelen_slownik["cztery"] => 4
+
+# "setdefault()" wstawia do słownika tylko jeśli nie było klucza
+pelen_slownik.setdefault("piec", 5) # pelen_slownik["piec"] daje 5
+pelen_slownik.setdefault("piec", 6) # pelen_slownik["piec"] to wciąż 5
+
+
+# Teraz zbiory (set) ... cóż zbiory (to po prostu listy ale bez potórzeń)
+pusty_zbior = set()
+# Inicjalizujemy "set()" pewnymi wartościami
+jakis_zbior = set([1, 2, 2, 3, 4]) # jakis_zbior to teraz set([1, 2, 3, 4])
+
+# kolejność nie jest gwarantowana, nawet gdy wydaje się posortowane
+inny_zbior = set([4, 3, 2, 2, 1]) # inny_zbior to set([1, 2, 3, 4])
+
+# Od Pythona 2.7 nawiasy klamrowe {} mogą być użyte do deklarowania zbioru
+pelen_zbior = {1, 2, 2, 3, 4} # => {1, 2, 3, 4}
+
+# Dodaj więcej elementów przez "add()"
+pelen_zbior.add(5) # pelen_zbior is now {1, 2, 3, 4, 5}
+
+# Znajdź przecięcie zbiorów używając &
+inny_zbior = {3, 4, 5, 6}
+pelen_zbior & other_set # => {3, 4, 5}
+
+# Suma zbiorów |
+pelen_zbior | other_set # => {1, 2, 3, 4, 5, 6}
+
+# Różnicę zbiorów da znak -
+{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
+
+# Sprawdzanie obecności w zbiorze: "in".
+2 in pelen_zbior # => True
+10 in pelen_zbior # => False
+
+
+####################################################
+## 3. Kontrola przepływu
+####################################################
+
+# Tworzymy zmienną some_var
+some_var = 5
+
+# Tutaj widzisz wyrażenie warunkowe "if". Wcięcia są ważne Pythonie!
+# wypisze "some_var jest mniejsza niż 10"
+if some_var > 10:
+ print("some_var jest wieksza niż 10")
+elif some_var < 10: # This elif clause is optional.
+ print("some_var jest mniejsza niż 10")
+else: # This is optional too.
+ print("some_var jest równa 10")
+
+
+"""
+Pętla for iteruje po elementach listy wypisując:
+ pies to ssak
+ kot to ssak
+ mysz to ssak
+"""
+for zwierze in ["pies", "kot", "mysz"]:
+ # Możesz użyć % aby stworzyć sformatowane napisy
+ print("%s to ssak" % zwierze)
+
+"""
+"range(liczba)" zwraca listę liczb
+od zera do danej liczby:
+ 0
+ 1
+ 2
+ 3
+"""
+for i in range(4):
+ print(i)
+
+"""
+While to pętla która jest wykonywana dopóki spełniony jest warunek:
+ 0
+ 1
+ 2
+ 3
+"""
+x = 0
+while x < 4:
+ print(x)
+ x += 1 # Skrót od x = x + 1
+
+# Wyjątki wyłapujemy używając try, except
+
+# Działa w Pythonie 2.6 i wyższych:
+try:
+ # Użyj "raise" aby wyrzucić wyjąte
+ raise IndexError("To błąd indeksu")
+except IndexError as e:
+ pass # Pass to brak reakcji na błąd. Zazwyczaj nanosisz tu poprawki.
+except (TypeError, NameError):
+ pass # kilka wyjątków może być przechwyce razem.
+else: # Opcjonalna część bloku try/except. Musi wystąpić na końcu
+ print "Wszystko ok!" # Zadziała tylko, gdy program nie napotka wyjatku.
+
+
+####################################################
+## 4. Funkcjie
+####################################################
+
+# Użyj "def" aby stworzyć nową funkcję
+def dodaj(x, y):
+ print("x to %s a y to %s" % (x, y))
+ return x + y # słówko kluczowe return zwraca wynik działania
+
+# Tak wywołuje się funkcję z parametrami (args):
+dodaj(5, 6) # => wypisze "x to 5 a y to 6" i zwróci 11
+
+# Innym sposobem jest wywołanie z parametrami nazwanymi.
+dodaj(y=6, x=5) # tutaj kolejność podania nie ma znaczenia.
+
+
+# Można też stworzyć funkcję, które przyjmują różną ilość parametrów
+# nienazwanych args, co będzie interpretowane jako krotka jeśli nie użyjesz *
+def varargs(*args):
+ return args
+
+varargs(1, 2, 3) # => (1, 2, 3)
+
+
+# Można też stworzyć funkcję, które przyjmują różną ilość parametrów
+# nazwanych kwargs, które będa interpretowane jako słownik jeśli nie dasz **
+def keyword_args(**kwargs):
+ return kwargs
+
+# Wywołajmy to i sprawdźmy co się dzieje
+keyword_args(wielka="stopa", loch="ness") # => {"wielka": "stopa", "loch": "ness"}
+
+
+# Możesz też to pomieszać
+def all_the_args(*args, **kwargs):
+ print(args)
+ print(kwargs)
+"""
+all_the_args(1, 2, a=3, b=4) wyrzuci:
+ (1, 2)
+ {"a": 3, "b": 4}
+"""
+
+# Użyj * aby rozwinąć parametry z krotki args
+# i użyj ** aby rozwinąć parametry nazwane ze słownika kwargs.
+args = (1, 2, 3, 4)
+kwargs = {"a": 3, "b": 4}
+all_the_args(*args) # odpowiednik foo(1, 2, 3, 4)
+all_the_args(**kwargs) # odpowiednik foo(a=3, b=4)
+all_the_args(*args, **kwargs) # odpowiednik foo(1, 2, 3, 4, a=3, b=4)
+
+# Możesz podać parametry args i kwargs do funkcji równocześnie
+# przez rozwinięcie odpowiednio * i **
+def pass_all_the_args(*args, **kwargs):
+ all_the_args(*args, **kwargs)
+ print varargs(*args)
+ print keyword_args(**kwargs)
+
+# Zakres widoczności
+x = 5
+
+def setX(num):
+ # Lokalna zmienna x nie jest tym samym co zmienna x
+ x = num # => 43
+ print x # => 43
+
+def setGlobalX(num):
+ global x
+ print x # => 5
+ x = num # globalna zmienna to teraz 6
+ print x # => 6
+
+setX(43)
+setGlobalX(6)
+
+# Można tworzyć funkcje wewnętrzne i zwrócić je jako wynik
+def rob_dodawacz(x):
+ def dodawacz(y):
+ return x + y
+ return dodawacz
+
+dodaj_10 = rob_dodawacz(10)
+dodaj_10(3) # => 13
+
+# Są również funkcje nienazwane "lambda"
+(lambda x: x > 2)(3) # => True
+
+# Są także wbudowane funkcje wysokiego poziomu
+map(add_10, [1, 2, 3]) # => [11, 12, 13]
+filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
+
+# Można używać wyrażeń listowych do mapowania (map) i filtrowania (filter)
+[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. Klasy
+####################################################
+
+# Wszystkie klasy są podklasą object
+class Czlowiek(object):
+
+ # Atrybut klasy. Występuje we wszystkich instancjach klasy.
+ gatunek = "H. sapiens"
+
+ # Podstawowa inicjalizacja - wywoływana podczas tworzenia instacji.
+ # Zauważ, że podwójne podkreślenia przed i za nazwą oznaczają
+ # obietky lub atrybuty, który żyją tylko w kontrolowanej przez
+ # użytkownika przestrzeni nazw. Nie używaj ich we własnych metodach.
+ def __init__(self, nazwa):
+ # przypisz parametr "nazwa" do atrybutu instancji
+ self.nazwa = nazwa
+
+ # Metoda instancji. Wszystkie metody biorą "self" jako pierwszy argument
+ def mow(self, wiadomosc):
+ return "%s: %s" % (self.nazwa, wiadomosc)
+
+ # Metoda klasowa współdzielona przez instancje.
+ # Ma wywołującą klasę jako pierwszy argument.
+ @classmethod
+ def daj_gatunek(cls):
+ return cls.gatunek
+
+ # Metoda statyczna jest wywoływana bez argumentów klasy czy instancji.
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+
+# Instancja klasy
+i = Czlowiek(name="Ian")
+print(i.mow("cześć")) # wypisze "Ian: cześć"
+
+j = Czlowiek("Joel")
+print(j.mow("cześć")) # wypisze "Joel: cześć"
+
+# Wywołujemy naszą metodę klasową
+i.daj_gatunek() # => "H. sapiens"
+
+# Zmieniamy wspólny parametr
+Czlowiek.gatunek = "H. neanderthalensis"
+i.daj_gatunek() # => "H. neanderthalensis"
+j.daj_gatunek() # => "H. neanderthalensis"
+
+# Wywołanie metody statycznej
+Czlowiek.grunt() # => "*grunt*"
+
+
+####################################################
+## 6. Moduły
+####################################################
+
+# Tak importuje się moduły:
+import math
+print(math.sqrt(16)) # => 4
+
+# Można podać konkretne funkcje, np. ceil, floor z modułu math
+from math import ceil, floor
+print(ceil(3.7)) # => 4.0
+print(floor(3.7)) # => 3.0
+
+# Można zaimportować wszystkie funkcje z danego modułu.
+# Ostrzeżenie: nie jest to polecane.
+from math import *
+
+# Można skracać nazwy modułów.
+import math as m
+math.sqrt(16) == m.sqrt(16) # => True
+# sprawdźmy czy funkcje są równoważne
+from math import sqrt
+math.sqrt == m.sqrt == sqrt # => True
+
+# Moduły pythona to zwykłe skrypty napisane w tym języku. Możesz
+# pisać własne i importować je. Nazwa modułu to nazwa pliku.
+
+# W ten sposób sprawdzisz jakie funkcje wchodzą w skład modułu.
+import math
+dir(math)
+
+
+####################################################
+## 7. Zaawansowane
+####################################################
+
+# Generatory pomagają tworzyć tzw. "leniwy kod"
+def podwojne_liczby(iterowalne):
+ for i in iterowalne:
+ yield i + i
+
+# Generatory tworzą wartości w locie.
+# W przeciwienstwie do wygenerowania wartości raz i ich zachowania,
+# powstają one na bieżąco, w wyniku iteracji. To oznacza, że wartości
+# większe niż 15 nie będą przetworzone w funkcji "podwojne_liczby".
+# Zauważ, że xrange to generator, który wykonuje tę samą operację co range.
+# Stworzenie listy od 1 do 900000000 zajęłoby sporo czasu i pamięci,
+# a xrange tworzy obiekt generatora zamiast tworzyć całą listę jak range.
+# Użyto podkreślinika, aby odróżnić nazwę zmiennej od słówka kluczowego
+# Pythona.
+xrange_ = xrange(1, 900000000)
+
+# poniższa pętla będzie podwajać liczby aż do 30
+for i in podwojne_liczby(xrange_):
+ print(i)
+ if i >= 30:
+ break
+
+
+# Dekoratory
+# w tym przykładzie "beg" jest nakładką na "say"
+# Beg wywołuje say. Jeśli say_please jest prawdziwe wtedy wzracana wartość
+# zostanie zmieniona
+
+from functools import wraps
+
+
+def beg(target_function):
+ @wraps(target_function)
+ def wrapper(*args, **kwargs):
+ msg, say_please = target_function(*args, **kwargs)
+ if say_please:
+ return "{} {}".format(msg, "Proszę! Jestem spłukany :(")
+ return msg
+ return wrapper
+
+
+@beg
+def say(say_please=False):
+ msg = "Kupisz mi piwo?"
+ return msg, say_please
+
+
+print(say()) # Kupisz mi piwo?
+print(say(say_please=True)) # Kupisz mi piwo? Proszę! Jestem spłukany :(
+```
+
+## Gotowy na więcej?
+### Polskie
+
+* [Zanurkuj w Pythonie](http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie)
+* [LearnPythonPl](http://www.learnpython.org/pl/)
+
+### Angielskie:
+#### Darmowe źródła online
+
+* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
+* [Dive Into Python](http://www.diveintopython.net/)
+* [The Official Docs](http://docs.python.org/2.6/)
+* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
+* [Python Module of the Week](http://pymotw.com/2/)
+* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
+
+#### Inne
+
+* [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/pt-br/groovy-pt.html.markdown b/pt-br/groovy-pt.html.markdown
index 885d5b27..2ec7d967 100644
--- a/pt-br/groovy-pt.html.markdown
+++ b/pt-br/groovy-pt.html.markdown
@@ -9,7 +9,7 @@ translators:
lang: pt-br
---
-Groovy - Uma linguagem dinâmica para a plataforma Java. [Leia mais aqui.](http://groovy.codehaus.org)
+Groovy - Uma linguagem dinâmica para a plataforma Java. [Leia mais aqui.](http://www.groovy-lang.org/)
```groovy
@@ -236,7 +236,7 @@ for ( e in map ) {
Sobrecarregamento de Operadores para uma lsita dos operadores comuns que
Grooby suporta:
- http://groovy.codehaus.org/Operator+Overloading
+ http://www.groovy-lang.org/operators.html#Operator-Overloading
Operadores Groovy úteis
*/
@@ -255,7 +255,7 @@ def nomeUsuario = usuario?.nomeUsuario
Um closure, em Grooby, é como um "bloco de código" ou um ponteiro para método.
É um pedação de código que é definido e executado em um momento posterior.
- Mais informação em: http://groovy.codehaus.org/Closures+-+Formal+Definition
+ Mais informação em: http://www.groovy-lang.org/closures.html
*/
//Exemplo:
def clos = { println "Hello World!" }
@@ -413,11 +413,11 @@ assert soma(2,5) == 7
## Referências
-[Groovy documentation](http://groovy.codehaus.org/Documentation)
+[Groovy documentation](http://www.groovy-lang.org/documentation.html)
[Groovy web console](http://groovyconsole.appspot.com/)
-Junte-se a um [grupo de usuários Groovy](http://groovy.codehaus.org/User+Groups)
+Junte-se a um [grupo de usuários Groovy](http://www.groovy-lang.org/usergroups.html)
## Livro
diff --git a/pt-br/perl-pt.html.markdown b/pt-br/perl-pt.html.markdown
new file mode 100644
index 00000000..cc07a2ec
--- /dev/null
+++ b/pt-br/perl-pt.html.markdown
@@ -0,0 +1,166 @@
+---
+name: perl
+category: language
+language: perl
+filename: learnperl-pt.pl
+contributors:
+ - ["Korjavin Ivan", "http://github.com/korjavin"]
+translators:
+ - ["Miguel Araújo", "https://github.com/miguelarauj1o"]
+lang: pt-br
+---
+
+Perl 5 é, uma linguagem de programação altamente capaz, rica em recursos, com mais de 25 anos de desenvolvimento.
+
+Perl 5 roda em mais de 100 plataformas, de portáteis a mainframes e é adequada tanto para prototipagem rápida, quanto em projetos de desenvolvimento em grande escala.
+
+```perl
+# Comentários de uma linha começam com um sinal de número.
+
+#### Tipos de variáveis em Perl
+
+# Variáveis iniciam com um sigilo, que é um símbolo que mostra o tipo.
+# Um nome de variável válido começa com uma letra ou sublinhado,
+# seguido por qualquer número de letras, números ou sublinhados.
+
+### Perl has three main variable types: $scalar, @array, e %hash.
+
+## Scalars
+# Um scalar representa um valor único:
+my $animal = "camelo";
+my $resposta = 42;
+
+# Valores scalar podem ser strings, inteiros ou números ponto-flutuantes e
+# Perl vai automaticamente converter entre eles quando for preciso.
+
+## Arrays
+# Um array representa uma lista de valores:
+my @animais = ("camelo", "vaca", "boi");
+my @números = (23, 42, 69);
+my @misturado = ("camelo", 42, 1.23);
+
+## Hashes
+# Um hash representa um conjunto de pares chave/valor:
+
+my %fruta_cor = ("maçã", "vermelho", "banana", "amarelo");
+
+# Você pode usar o espaço em branco e o operador "=>" para colocá-los de
+# maneira mais agradável:
+
+my %fruta_cor = (
+ maçã => "vermelho",
+ banana => "amarelo",
+);
+
+# Scalars, arrays and hashes são documentados mais profundamentes em perldata.
+# (perldoc perldata).
+
+# Mais tipos de dados complexos podem ser construídas utilizando referências,
+# o que permite que você crie listas e hashes dentro de listas e hashes.
+
+#### Condicionais e construtores de iteração
+
+# Perl possui a maioria das construções condicionais e de iteração habituais.
+
+if ($var) {
+ ...
+} elsif ($var eq 'bar') {
+ ...
+} else {
+ ...
+}
+
+unless (condição) {
+ ...
+}
+# Isto é fornecido como uma versão mais legível de "if (!condition)"
+
+# A forma Perlish pós-condição
+print "Yow!" if $zippy;
+print "Nós não temos nenhuma banana" unless $bananas;
+
+# while
+while (condição) {
+ ...
+}
+
+# for
+for (my $i = 0; $i < $max; $i++) {
+ print "valor é $i";
+}
+
+for (my $i = 0; $i < @elements; $i++) {
+ print "Elemento atual é " . $elements[$i];
+}
+
+for my $element (@elements) {
+ print $element;
+}
+
+# implícito
+
+for (@elements) {
+ print;
+}
+
+#### Expressões regulares
+
+# O suporte a expressões regulares do Perl é ao mesmo tempo amplo e profundo,
+# e é objeto de longa documentação em perlrequick, perlretut, e em outros
+# lugares. No entanto, em suma:
+
+# Casamento simples
+if (/foo/) { ... } # verdade se $_ contém "foo"
+if ($a =~ /foo/) { ... } # verdade se $a contém "foo"
+
+# Substituição simples
+
+$a =~ s/foo/bar/; # substitui foo com bar em $a
+$a =~ s/foo/bar/g; # substitui TODAS AS INSTÂNCIAS de foo com bar em $a
+
+#### Arquivos e I/O
+
+# Você pode abrir um arquivo para entrada ou saída usando a função "open()".
+
+open(my $in, "<", "input.txt") ou desistir "Não pode abrir input.txt: $!";
+open(my $out, ">", "output.txt") ou desistir "Não pode abrir output.txt: $!";
+open(my $log, ">>", "my.log") ou desistir "Não pode abrir my.log: $!";
+
+# Você pode ler de um arquivo aberto usando o operador "<>". No contexto
+# scalar, ele lê uma única linha do arquivo, e em contexto de lista lê o
+# arquivo inteiro, atribuindo cada linha a um elemento da lista:
+
+my $linha = <$in>;
+my @linhas = <$in>;
+
+#### Escrevendo subrotinas
+
+# Escrever subrotinas é fácil:
+
+sub logger {
+ my $mensagem = shift;
+
+ open my $arquivo, ">>", "my.log" or die "Não poderia abrir my.log: $!";
+
+ print $arquivo $ensagem;
+}
+
+# Agora nós podemos usar a subrotina como qualquer outra função construída:
+
+logger("Nós temos uma subrotina de log!");
+```
+
+#### Usando módulos Perl
+
+Módulos Perl provê uma lista de recursos para lhe ajudar a evitar redesenhar
+a roda, e tudo isso pode ser baixado do CPAN (http://www.cpan.org/). Um número
+de módulos populares podem ser incluídos com a própria distribuição do Perl.
+
+perlfaq contém questões e respostas relacionadas a muitas tarefas comuns, e frequentemente provê sugestões para um bom números de módulos CPAN.
+
+#### Leitura Adicional
+
+ - [perl-tutorial](http://perl-tutorial.org/)
+ - [Learn at www.perl.com](http://www.perl.org/learn.html)
+ - [perldoc](http://perldoc.perl.org/)
+ - and perl built-in : `perldoc perlintro`
diff --git a/pt-br/xml-pt.html.markdown b/pt-br/xml-pt.html.markdown
index 40ddbc3a..f347f8ef 100644
--- a/pt-br/xml-pt.html.markdown
+++ b/pt-br/xml-pt.html.markdown
@@ -1,8 +1,8 @@
---
language: xml
-filename: learnxml.xml
+filename: learnxml-pt.xml
contributors:
- - ["João Farias", "https://github.com/JoaoGFarias"]
+ - ["João Farias", "https://github.com/JoaoGFarias"]
translators:
- ["Miguel Araújo", "https://github.com/miguelarauj1o"]
lang: pt-br
@@ -130,4 +130,4 @@ com a adição de definição DTD.-->
<preco>30.00</preco>
</livro>
</livraria>
-``` \ No newline at end of file
+```
diff --git a/python.html.markdown b/python.html.markdown
index ace3f794..16a94c8f 100644
--- a/python.html.markdown
+++ b/python.html.markdown
@@ -327,8 +327,8 @@ prints:
mouse is a mammal
"""
for animal in ["dog", "cat", "mouse"]:
- # You can use % to interpolate formatted strings
- print "%s is a mammal" % animal
+ # You can use {0} to interpolate formatted strings. (See above.)
+ print "{0} is a mammal".format(animal)
"""
"range(number)" returns a list of numbers
@@ -379,7 +379,13 @@ except (TypeError, NameError):
pass # Multiple exceptions can be handled together, if required.
else: # Optional clause to the try/except block. Must follow all except blocks
print "All good!" # Runs only if the code in try raises no exceptions
+finally: # Execute under all circumstances
+ print "We can clean up resources here"
+# Instead of try/finally to cleanup resources you can use a with statement
+with open("myfile.txt") as f:
+ for line in f:
+ print line
####################################################
## 4. Functions
@@ -387,7 +393,7 @@ else: # Optional clause to the try/except block. Must follow all except blocks
# Use "def" to create new functions
def add(x, y):
- print "x is %s and y is %s" % (x, y)
+ print "x is {0} and y is {1}".format(x, y)
return x + y # Return values with a return statement
# Calling functions with parameters
@@ -497,7 +503,7 @@ class Human(object):
# An instance method. All methods take "self" as the first argument
def say(self, msg):
- return "%s: %s" % (self.name, msg)
+ return "{0}: {1}".format(self.name, msg)
# A class method is shared among all instances
# They are called with the calling class as the first argument
@@ -624,16 +630,17 @@ print say(say_please=True) # Can you buy me a beer? Please! I am poor :(
### Free Online
+* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
* [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/)
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
+* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
### Dead Tree
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
-
diff --git a/python3.html.markdown b/python3.html.markdown
index a112912f..b3acb122 100644
--- a/python3.html.markdown
+++ b/python3.html.markdown
@@ -374,6 +374,13 @@ except (TypeError, NameError):
pass # Multiple exceptions can be handled together, if required.
else: # Optional clause to the try/except block. Must follow all except blocks
print("All good!") # Runs only if the code in try raises no exceptions
+finally: # Execute under all circumstances
+ print("We can clean up resources here")
+
+# Instead of try/finally to cleanup resources you can use a with statement
+with open("myfile.txt") as f:
+ for line in f:
+ print(line)
# Python offers a fundamental abstraction called the Iterable.
# An iterable is an object that can be treated as a sequence.
@@ -394,15 +401,15 @@ our_iterable[1] # Raises a TypeError
our_iterator = iter(our_iterable)
# Our iterator is an object that can remember the state as we traverse through it.
-# We get the next object by calling the __next__ function.
-our_iterator.__next__() #=> "one"
+# We get the next object with "next()".
+next(our_iterator) #=> "one"
-# It maintains state as we call __next__.
-our_iterator.__next__() #=> "two"
-our_iterator.__next__() #=> "three"
+# It maintains state as we iterate.
+next(our_iterator) #=> "two"
+next(our_iterator) #=> "three"
# After the iterator has returned all of its data, it gives you a StopIterator Exception
-our_iterator.__next__() # Raises StopIteration
+next(our_iterator) # Raises StopIteration
# You can grab all the elements of an iterator by calling list() on it.
list(filled_dict.keys()) #=> Returns ["one", "two", "three"]
@@ -642,18 +649,18 @@ print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
### Free Online
+* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
* [Dive Into Python](http://www.diveintopython.net/)
* [Ideas for Python Projects](http://pythonpracticeprojects.com)
-
* [The Official Docs](http://docs.python.org/3/)
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
* [Python Course](http://www.python-course.eu/index.php)
+* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
### Dead Tree
* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
-
diff --git a/red.html.markdown b/red.html.markdown
index 73a13606..f33060c4 100644
--- a/red.html.markdown
+++ b/red.html.markdown
@@ -212,7 +212,9 @@ The source can be found on [github](https://github.com/red/red).
The Red/System language specification can be found [here](http://static.red-lang.org/red-system-specs-light.html).
-To learn more about Rebol and Red join the [chat on StackOverflow](http://chat.stackoverflow.com/rooms/291/rebol-and-red). You will need 20 points to chat but if you ask or answer questions about Red or Rebol we will help you get those points. And if that is not working for you drop a mail to us on the [Red mailing list](mailto: red-langNO_SPAM@googlegroups.com) (remove NO_SPAM).
+To learn more about Rebol and Red join the [chat on Gitter](https://gitter.im/red/red). And if that is not working for you drop a mail to us on the [Red mailing list](mailto: red-langNO_SPAM@googlegroups.com) (remove NO_SPAM).
+
+Browse or ask questions on [Stack Overflow](stackoverflow.com/questions/tagged/red).
Maybe you want to try Red right away? That is possible on the [try Rebol and Red site](http://tryrebol.esperconsultancy.nl).
diff --git a/ro-ro/clojure-ro.html.markdown b/ro-ro/clojure-ro.html.markdown
new file mode 100644
index 00000000..32ba9620
--- /dev/null
+++ b/ro-ro/clojure-ro.html.markdown
@@ -0,0 +1,386 @@
+---
+language: clojure
+contributors:
+ - ["Adam Bard", "http://adambard.com/"]
+translators:
+ - ["Bogdan Paun", "http://twitter.com/bgdnpn"]
+filename: learnclojure-ro.clj
+lang: ro-ro
+---
+
+Clojure este un limbaj din familia Lisp dezvoltat pentru Masina Virtuala Java
+(Java Virtual Machine - JVM). Pune un accent mult mai puternic pe
+[programarea funcionala](https://en.wikipedia.org/wiki/Functional_programming)
+pura decat Common Lisp, dar include utilitare [STM](https://en.wikipedia.org/wiki/Software_transactional_memory)
+pentru a gestiona starea, atunci cand aceasta apare.
+
+Combinatia aceasta ii permite sa gestioneze procese concurente foarte usor,
+de multe ori in mod automat.
+
+(Aveti nevoie deo versiune Clojure 1.2 sau mai noua)
+
+
+```clojure
+; Comentariile incep cu punct si virgula.
+
+; Clojure se scrie in "forme", care nu sunt decat
+; liste de lucruri in interiorul unor paranteze, separate prin spatii.
+;
+; Reader-ul Clojure presupune ca primul lucru este o
+; functie sau un macro de apelat, iar restul sunt argumente.
+
+; Prima apelare intr-un fisier ar trebui sa fie ns, pentru a configura namespace-ul
+(ns learnclojure)
+
+; Mai multe exemple de baza:
+
+; str va crea un string folosint toate argumentele sale
+(str "Hello" " " "World") ; => "Hello World"
+
+; Matematica este simpla
+(+ 1 1) ; => 2
+(- 2 1) ; => 1
+(* 1 2) ; => 2
+(/ 2 1) ; => 2
+
+; Egalitatea este =
+(= 1 1) ; => true
+(= 2 1) ; => false
+
+; Folosim si not pentru logica
+(not true) ; => false
+
+; Formele imbricate functioneaza asa
+(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
+
+; Tipuri
+;;;;;;;;;;;;;
+
+; Clojure foloseste sistemul de obiecte Java pentru boolean, string si numere.
+; Folositi `class` pentru a le inspecta.
+(class 1) ; Numere intregi sunt jaba.lang.Long, in mod normal
+(class 1.); Numelere reale sunt java.lang.Double
+(class ""); Sirurile de caractere sunt mere intre apostrofuri duble, si sunt java.lang.String
+(class false) ; Booleanele sunt java.lang.Boolean
+(class nil); Valoarea "null" este numita nil
+
+; Daca doriti sa creati o lista de date literale, folositi ' pentru a preveni
+; evaluarea ei
+'(+ 1 2) ; => (+ 1 2)
+; (prescurtare pentru (quote (+ 1 2)))
+
+; Puteti evalua o lista cu apostrof
+(eval '(+ 1 2)) ; => 3
+
+; Colectii & Secvente
+;;;;;;;;;;;;;;;;;;;
+
+; Listele sunt structuri de date lista-inlantuita, spre deosebire de Vectori
+; Vectorii si Listele sunt si ele clase Java!
+(class [1 2 3]); => clojure.lang.PersistentVector
+(class '(1 2 3)); => clojure.lang.PersistentList
+
+; O liste ar putea fi scrisa direct ca (1 2 3), dar trebuie sa folosim apostrof
+; pentru a preveni reader-ul din a crede ca e o functie.
+; De asemenea, (list 1 2 3) este acelasi lucru cu '(1 2 3)
+
+; "Colectiile" sunt grupuri de date
+; Atat listele cat si vectorii sunt colectii:
+(coll? '(1 2 3)) ; => true
+(coll? [1 2 3]) ; => true
+
+; "Sequences" (seqs) are abstract descriptions of lists of data.
+; Only lists are seqs.
+(seq? '(1 2 3)) ; => true
+(seq? [1 2 3]) ; => false
+
+; O secventa necesita un punct de intrare doar cand este accesata.
+; Deci, secventele, care pot fi "lazy" -- pot defini serii infinite:
+(range 4) ; => (0 1 2 3)
+(range) ; => (0 1 2 3 4 ...) (o serie infinita)
+(take 4 (range)) ; (0 1 2 3)
+
+; Folositi cons pentru a adauga un element la inceputul unei liste sau unui vector
+(cons 4 [1 2 3]) ; => (4 1 2 3)
+(cons 4 '(1 2 3)) ; => (4 1 2 3)
+
+; Conj va adauga un element unei colectii in modul cel mai eficient.
+; Pentru liste, aceastea sunt inserate la inceput. Pentru vectori, sunt inserate la final.
+(conj [1 2 3] 4) ; => [1 2 3 4]
+(conj '(1 2 3) 4) ; => (4 1 2 3)
+
+; Folositi concat pentru a uni liste sau vectori
+(concat [1 2] '(3 4)) ; => (1 2 3 4)
+
+; Folositi filter, map pentru a interactiona cu colectiile
+(map inc [1 2 3]) ; => (2 3 4)
+(filter even? [1 2 3]) ; => (2)
+
+; Folositi reduce pentru a le reduce
+(reduce + [1 2 3 4])
+; = (+ (+ (+ 1 2) 3) 4)
+; => 10
+
+; Reduce poate lua un argument valoare-initiala
+(reduce conj [] '(3 2 1))
+; = (conj (conj (conj [] 3) 2) 1)
+; => [3 2 1]
+
+; Functii
+;;;;;;;;;;;;;;;;;;;;;
+
+; Folositi fn pentru a crea functii noi. O functie returneaza intotdeauna
+; ultima sa instructiune.
+(fn [] "Hello World") ; => fn
+
+; (Necesita paranteze suplimentare pentru a fi apelata)
+((fn [] "Hello World")) ; => "Hello World"
+
+; Puteti crea o variabila folosind def
+(def x 1)
+x ; => 1
+
+; Atribuiti o functie unei variabile
+(def hello-world (fn [] "Hello World"))
+(hello-world) ; => "Hello World"
+
+; Puteti scurta acest proces folosind defn
+(defn hello-world [] "Hello World")
+
+; Elementul [] este lista de argumente a functiei.
+(defn hello [name]
+ (str "Hello " name))
+(hello "Steve") ; => "Hello Steve"
+
+; Puteti, de asemenea, folosi aceasta prescurtare pentru a crea functii:
+(def hello2 #(str "Hello " %1))
+(hello2 "Fanny") ; => "Hello Fanny"
+
+; Puteti avea si functii cu mai multe variabile
+(defn hello3
+ ([] "Hello World")
+ ([name] (str "Hello " name)))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+
+; Functiile pot primi mai mult argumente dintr-o secventa
+(defn count-args [& args]
+ (str "Ati specificat " (count args) " argumente: " args))
+(count-args 1 2 3) ; => "Ati specificat 3 argumente: (1 2 3)"
+
+; Puteti interschimba argumente normale si argumente-secventa
+(defn hello-count [name & args]
+ (str "Salut " name ", ati specificat " (count args) " argumente extra"))
+(hello-count "Finn" 1 2 3)
+; => "Salut Finn, ai specificat 3 argumente extra"
+
+
+; Maps (Dictionare)
+;;;;;;;;;;
+
+; Hash maps si Array maps impart o interfata. Hash maps au cautari mai rapide
+; dar nu retin ordinea cheilor.
+(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
+(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
+
+; Arraymaps de vin automat hashmaps prin majoritatea operatiilor
+; daca sunt suficient de mari, asa ca nu trebuie sa va preocupe acest aspect.
+
+; Dictionarele pot folosi orice tip hashable ca si cheie, dar cuvintele cheie
+; (keywords) sunt, de obicei, cele mai indicate. Cuvintele cheie sunt ca niste
+; siruri de caractere cu un plus de eficienta
+(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}
+
+; Apropo, virgulele sunt intotdeauna considerate echivalente cu spatiile.
+
+; Apelati un dictionar (map) ca pe o functie pentru a primi o valoare anume
+(stringmap "a") ; => 1
+(keymap :a) ; => 1
+
+; Cuvintele cheie pot fi folosite si ele pentru a "cere" dictionarului valorile lor!
+(:b keymap) ; => 2
+
+; Nu incercati asta cu siruri de caractere.
+;("a" stringmap)
+; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
+
+; Recuperarea unei chei inexistente returneaza nil
+(stringmap "d") ; => nil
+
+; Folositi assoc pentru a adauga nou chei unui ductionar
+(def newkeymap (assoc keymap :d 4))
+newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
+
+; Dar retineti ca tipurile sunt imuabile in clojure
+keymap ; => {:a 1, :b 2, :c 3}
+
+; Folositi dissoc pentru a elimina chei
+(dissoc keymap :a :b) ; => {:c 3}
+
+; Seturi (multimi)
+;;;;;;
+
+(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
+(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
+
+; Adaugati un membru cu conj
+(conj #{1 2 3} 4) ; => #{1 2 3 4}
+
+; Eliminati unul cu disj
+(disj #{1 2 3} 1) ; => #{2 3}
+
+; Testati existenta unuia folosing setul ca o functie:
+(#{1 2 3} 1) ; => 1
+(#{1 2 3} 4) ; => nil
+
+; Exista mai multe functii in namespace-ul clojure.sets.
+
+; Forme utile
+;;;;;;;;;;;;;;;;;
+
+; In Clojure constructiile logice sunt macro-uri, si arata ca
+; oricare alta forma
+(if false "a" "b") ; => "b"
+(if false "a") ; => nil
+
+; Folositi let pentru a crea atribuiri temporare
+(let [a 1 b 2]
+ (> a b)) ; => false
+
+; Grupati instructiuni impreuna folosind do
+(do
+ (print "Hello")
+ "World") ; => "World" (prints "Hello")
+
+; Functiile contin un do implicit
+(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")
+
+; Asemanator pentru let
+(let [name "Urkel"]
+ (print "Saying hello to " name)
+ (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
+
+; Module
+;;;;;;;;;;;;;;;
+
+; Folositi "use" pentru a recupera toate functiile dintr-un modul
+(use 'clojure.set)
+
+; Acum putem folosi operatiuni pe seturi
+(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
+(difference #{1 2 3} #{2 3 4}) ; => #{1}
+
+; Puteri de asemenea alege un subset al functiilor de importat
+(use '[clojure.set :only [intersection]])
+
+; Folositi require pentru a importa un modul
+(require 'clojure.string)
+
+; Folositi / pentru a apela functii dintr-un modul
+; In acest caz, modulul este clojure.string, iar functia este blank?
+(clojure.string/blank? "") ; => true
+
+; Puteti atribui un nume mai scurt unui modul in momentul importului
+(require '[clojure.string :as str])
+(str/replace "Acesta este un test." #"[a-o]" str/upper-case) ; => "ACEstA EstE un tEst."
+; (#"" denota o expresie regulata)
+
+; Puteti folsi require (sau use, contraindicat) dintr-un namespace folosind :require.
+; Nu trebuie sa folositi apostrof pentru module daca procedati astfel.
+(ns test
+ (:require
+ [clojure.string :as str]
+ [clojure.set :as set]))
+
+; Java
+;;;;;;;;;;;;;;;;;
+
+; Java are o biblioteca standard imensa si folositoare, deci
+; ar fi util sa stiti cum sa o folositi.
+
+; Folositi import pentru a incarca un modul Java
+(import java.util.Date)
+
+; Puteti importa si dintr-un namesopace.
+(ns test
+ (:import java.util.Date
+ java.util.Calendar))
+
+; Folositi numele clasei cu "." la final pentru a crea o noua instanta
+(Date.) ; <a date object>
+
+; Folositi . pentru a apela metode. Pe scurt, folositi ".method"
+(. (Date.) getTime) ; <a timestamp>
+(.getTime (Date.)) ; exact acelasi lucru.
+
+; Folositi / pentru a apela metode statice
+(System/currentTimeMillis) ; <a timestamp> (System este prezent intotdeauna)
+
+; Folositi doto pentru a gestiona clase (mutable) mai usor
+(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
+
+; STM
+;;;;;;;;;;;;;;;;;
+
+; Software Transactional Memory este un mecanism folost de Clojure pentru
+; a gestiona stari persistente. Sunt putine instante in care este folosit.
+
+; Un atom este cel mai simplu exemplu. Dati-i o valoare initiala
+(def my-atom (atom {}))
+
+; Modificati-l cu swap!.
+; swap! primeste o functie si o apeleaza cu valoarea actuala a atomului
+; ca prim argument si orice argumente suplimentare ca al doilea
+(swap! my-atom assoc :a 1) ; Atomul ia valoarea rezultata din (assoc {} :a 1)
+(swap! my-atom assoc :b 2) ; Atomul ia valoarea rezultata din (assoc {:a 1} :b 2)
+
+; Folositi '@' pentru a dereferentia atomul si a-i recupera valoarea
+my-atom ;=> Atom<#...> (Returmeaza obiectul Atom)
+@my-atom ; => {:a 1 :b 2}
+
+; Aici avem un contor simplu care foloseste un atom
+(def counter (atom 0))
+(defn inc-counter []
+ (swap! counter inc))
+
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+
+@counter ; => 5
+
+; Alte utilizari ale STM sunt referintele (refs) si agentii (agents).
+; Refs: http://clojure.org/refs
+; Agents: http://clojure.org/agents
+```
+
+### Lectura suplimentara
+
+Lista nu este in niciun caz exhaustiva, dar speram ca este suficienta pentru
+a va oferi un inceput bun in Clojure.
+
+Clojure.org contine multe articole:
+[http://clojure.org/](http://clojure.org/)
+
+Clojuredocs.org contine documentatie cu exemple pentru majoritatea functiilor de baza:
+[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
+
+4Clojure este o metoda excelenta pentru a exersa Clojure/FP (Programarea Functionala):
+[http://www.4clojure.com/](http://www.4clojure.com/)
+
+Clojure-doc.org are un numar de article pentru incepatori:
+[http://clojure-doc.org/](http://clojure-doc.org/)
diff --git a/ru-ru/bash-ru.html.markdown b/ru-ru/bash-ru.html.markdown
new file mode 100644
index 00000000..21377b6c
--- /dev/null
+++ b/ru-ru/bash-ru.html.markdown
@@ -0,0 +1,284 @@
+---
+category: tool
+tool: bash
+contributors:
+ - ["Max Yankov", "https://github.com/golergka"]
+ - ["Darren Lin", "https://github.com/CogBear"]
+ - ["Alexandre Medeiros", "http://alemedeiros.sdf.org"]
+ - ["Denis Arh", "https://github.com/darh"]
+ - ["akirahirose", "https://twitter.com/akirahirose"]
+ - ["Anton Strömkvist", "http://lutic.org/"]
+ - ["Rahil Momin", "https://github.com/iamrahil"]
+ - ["Gregrory Kielian", "https://github.com/gskielian"]
+ - ["Etan Reisner", "https://github.com/deryni"]
+translators:
+ - ["Andrey Samsonov", "https://github.com/kryzhovnik"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
+filename: LearnBash-ru.sh
+lang: ru-ru
+---
+
+Bash - это командная оболочка unix (unix shell), которая распространялась как оболочка для операционной системы GNU и используется в качестве оболочки по умолчанию для Linux и Mac OS X.
+Почти все нижеприведенные примеры могут быть частью shell-скриптов или исполнены напрямую в shell.
+
+[Подробнее.](http://www.gnu.org/software/bash/manual/bashref.html)
+
+```bash
+#!/bin/bash
+# Первая строка скрипта - это shebang, который сообщает системе, как исполнять
+# этот скрипт: http://en.wikipedia.org/wiki/Shebang_(Unix)
+# Как вы уже поняли, комментарии начинаются с #. Shebang - тоже комментарий.
+
+# Простой пример hello world:
+echo Hello world!
+
+# Отдельные команды начинаются с новой строки или разделяются точкой с запятой:
+echo 'Это первая строка'; echo 'Это вторая строка'
+
+# Вот так объявляется переменная:
+VARIABLE="Просто строка"
+
+# но не так:
+VARIABLE = "Просто строка"
+# Bash решит, что VARIABLE - это команда, которую он должен исполнить,
+# и выдаст ошибку, потому что не сможет найти ее.
+
+# и не так:
+VARIABLE= 'Просто строка'
+# Тут Bash решит, что 'Просто строка' - это команда, которую он должен исполнить,
+# и выдаст ошибку, потому что не сможет найти такой команды
+# (здесь 'VARIABLE=' выглядит как присвоение значения переменной,
+# но только в контексте исполнения команды 'Просто строка').
+
+# Использование переменой:
+echo $VARIABLE
+echo "$VARIABLE"
+echo '$VARIABLE'
+# Когда вы используете переменную - присваиваете, экспортируете и т.д. -
+# пишите её имя без $. А для получения значения переменной используйте $.
+# Заметьте, что ' (одинарные кавычки) не раскрывают переменные в них.
+
+# Подстановка строк в переменные
+echo ${VARIABLE/Просто/A}
+# Это выражение заменит первую встреченную подстроку "Просто" на "A"
+
+# Взять подстроку из переменной
+LENGTH=7
+echo ${VARIABLE:0:LENGTH}
+# Это выражение вернет только первые 7 символов переменной VARIABLE
+
+# Значение по умолчанию
+echo ${FOO:-"DefaultValueIfFOOIsMissingOrEmpty"}
+# Это сработает при отсутствующем значении (FOO=) и пустой строке (FOO="");
+# ноль (FOO=0) вернет 0.
+# Заметьте, что в любом случае значение самой переменной FOO не изменится.
+
+# Встроенные переменные:
+# В bash есть полезные встроенные переменные, например
+echo "Последнее возвращенное значение: $?"
+echo "PID скрипта: $$"
+echo "Количество аргументов: $#"
+echo "Аргументы скрипта: $@"
+echo "Аргументы скрипта, распределённые по отдельным переменным: $1 $2..."
+
+# Чтение аргументов из устройста ввода:
+echo "Как Вас зовут?"
+read NAME # Обратите внимание, что нам не нужно определять новую переменную
+echo Привет, $NAME!
+
+# У нас есть обычная структура if:
+# наберите 'man test' для получения подробной информации о форматах условия
+if [ $NAME -ne $USER ]
+then
+ echo "Имя не совпадает с именем пользователя"
+else
+ echo "Имя совпадает с именем пользователя"
+fi
+
+# Также есть условное исполнение
+echo "Исполнится всегда" || echo "Исполнится, если первая команда завершится ошибкой"
+echo "Исполнится всегда" && echo "Исполнится, если первая команда выполнится удачно"
+
+# Можно использовать && и || в выражениях if, когда нужно несколько пар скобок:
+if [ $NAME == "Steve" ] && [ $AGE -eq 15 ]
+then
+ echo "Исполнится, если $NAME равно Steve И $AGE равно 15."
+fi
+
+if [ $NAME == "Daniya" ] || [ $NAME == "Zach" ]
+then
+ echo "Исполнится, если $NAME равно Daniya ИЛИ Zach."
+fi
+
+# Выражения обозначаются таким форматом:
+echo $(( 10 + 5 ))
+
+# В отличие от других языков программирования, Bash - это командная оболочка,
+# а значит, работает в контексте текущей директории.
+# Вы можете просматривать файлы и директории в текущей директории командой ls:
+ls
+
+# У этой команды есть опции:
+ls -l # Показать каждый файл и директорию на отдельной строке
+
+# Результат предыдущей команды может быть направлен на вход следующей.
+# Команда grep фильтрует ввод по шаблону.
+# Так мы можем просмотреть только *.txt файлы в текущей директории:
+ls -l | grep "\.txt"
+
+# Вы можете перенаправить ввод и вывод команды (stdin, stdout и stderr).
+# Следующая команда означает: читать из stdin, пока не встретится ^EOF$, и
+# перезаписать hello.py следующим строками (до строки "EOF"):
+cat > hello.py << EOF
+#!/usr/bin/env python
+from __future__ import print_function
+import sys
+print("#stdout", file=sys.stdout)
+print("#stderr", file=sys.stderr)
+for line in sys.stdin:
+ print(line, file=sys.stdout)
+EOF
+
+# Запуск hello.py с разными вариантами перенаправления потоков
+# стандартных ввода, вывода и ошибок:
+python hello.py < "input.in"
+python hello.py > "output.out"
+python hello.py 2> "error.err"
+python hello.py > "output-and-error.log" 2>&1
+python hello.py > /dev/null 2>&1
+# Поток ошибок перезапишет файл, если этот файл существует,
+# поэтому, если вы хотите дописывать файл, используйте ">>":
+python hello.py >> "output.out" 2>> "error.err"
+
+# Переписать output.txt, дописать error.err и сосчитать строки:
+info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err
+wc -l output.out error.err
+
+# Запустить команду и вывести ее файловый дескриптор (смотрите: man fd)
+echo <(echo "#helloworld")
+
+# Перезаписать output.txt строкой "#helloworld":
+cat > output.out <(echo "#helloworld")
+echo "#helloworld" > output.out
+echo "#helloworld" | cat > output.out
+echo "#helloworld" | tee output.out >/dev/null
+
+# Подчистить временные файлы с подробным выводом ('-i' - интерактивый режим)
+rm -v output.out error.err output-and-error.log
+
+# Команды могут быть подставлены в строку с помощью $( ):
+# следующие команды выводят число файлов и директорий в текущей директории.
+echo "Здесь $(ls | wc -l) элементов."
+
+# То же самое можно сделать с использованием обратных кавычек,
+# но они не могут быть вложенными, поэтому предпочтительно использовать $( ).
+echo "Здесь `ls | wc -l` элементов."
+
+# В Bash есть структура case, которая похожа на switch в Java и C++:
+case "$VARIABLE" in
+ # Перечислите шаблоны для условий, которые хотите отловить
+ 0) echo "Тут ноль.";;
+ 1) echo "Тут один.";;
+ *) echo "Это не пустое значение.";;
+esac
+
+# Цикл for перебирает элементы переданные в аргументе:
+# Содержимое $VARIABLE будет напечатано три раза.
+for VARIABLE in {1..3}
+do
+ echo "$VARIABLE"
+done
+
+# Или с использованием "традиционного" синтаксиса цикла for:
+for ((a=1; a <= 3; a++))
+do
+ echo $a
+done
+
+# Цикл for можно использовать для действий с файлами.
+# Запустим команду 'cat' для файлов file1 и file2
+for VARIABLE in file1 file2
+do
+ cat "$VARIABLE"
+done
+
+# ... или выводом из команд
+# Запустим cat для вывода из ls.
+for OUTPUT in $(ls)
+do
+ cat "$OUTPUT"
+done
+
+# Цикл while:
+while [ true ]
+do
+ echo "тело цикла здесь..."
+ break
+done
+
+# Вы можете определять функции
+# Определение:
+function foo ()
+{
+ echo "Аргументы работают также, как аргументы скрипта: $@"
+ echo "и: $1 $2..."
+ echo "Это функция"
+ return 0
+}
+
+# или просто
+bar ()
+{
+ echo "Другой способ определить функцию!"
+ return 0
+}
+
+# Вызов функции
+foo "Мое имя" $NAME
+
+# Есть много полезных команд, которые нужно знать:
+# напечатать последние 10 строк файла file.txt
+tail -n 10 file.txt
+# напечатать первые 10 строк файла file.txt
+head -n 10 file.txt
+# отсортировать строки file.txt
+sort file.txt
+# отобрать или наоборот пропустить повторяющиеся строки (с опцией -d отбирает)
+uniq -d file.txt
+# напечатать только первую колонку перед символом ','
+cut -d ',' -f 1 file.txt
+# заменить каждое 'okay' на 'great' в файле file.txt (regex поддерживается)
+sed -i 's/okay/great/g' file.txt
+# вывести в stdout все строки из file.txt, совпадающие с шаблоном regex;
+# этот пример выводит строки, которые начинаются на "foo" и оканчиваются "bar"
+grep "^foo.*bar$" file.txt
+# передайте опцию -c чтобы вывести число строк, в которых совпал шаблон
+grep -c "^foo.*bar$" file.txt
+# чтобы искать по строке, а не шаблону regex, используйте fgrep (или grep -F)
+fgrep "^foo.*bar$" file.txt
+
+# Читайте встроенную документацию оболочки Bash командой 'help':
+help
+help help
+help for
+help return
+help source
+help .
+
+# Читайте Bash man-документацию
+apropos bash
+man 1 bash
+man bash
+
+# Читайте документацию info (? для помощи)
+apropos info | grep '^info.*('
+man info
+info info
+info 5 info
+
+# Читайте bash info документацию:
+info bash
+info bash 'Bash Features'
+info bash 6
+info --apropos bash
+```
diff --git a/ru-ru/brainfuck-ru.html.markdown b/ru-ru/brainfuck-ru.html.markdown
index 500ac010..fcee185f 100644
--- a/ru-ru/brainfuck-ru.html.markdown
+++ b/ru-ru/brainfuck-ru.html.markdown
@@ -11,6 +11,8 @@ lang: ru-ru
Brainfuck (пишется маленькими буквами, кроме начала предложения) - это очень
маленький Тьюринг-полный язык программирования лишь с 8 командами.
+Вы можете испытать brainfuck в вашем браузере с помощью [brainfuck-визуализатора](http://fatiherikli.github.io/brainfuck-visualizer/).
+
```
Любой символ, кроме "><+-.,[]", игнорируется, за исключением кавычек.
diff --git a/ru-ru/objective-c-ru.html.markdown b/ru-ru/objective-c-ru.html.markdown
index 3246de82..ddff2e5c 100644
--- a/ru-ru/objective-c-ru.html.markdown
+++ b/ru-ru/objective-c-ru.html.markdown
@@ -1,106 +1,171 @@
---
language: Objective-C
-filename: LearnObjectiveC.m
+filename: LearnObjectiveC-ru.m
contributors:
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- ["Yannick Loriot", "https://github.com/YannickL"]
+ - ["Levi Bostian", "https://github.com/levibostian"]
translators:
- ["Evlogy Sutormin", "http://evlogii.com"]
+ - ["Dmitry Bessonov", "https://github.com/TheDmitry"]
lang: ru-ru
---
-Objective-C — компилируемый объектно-ориентированный язык программирования, используемый корпорацией Apple,
-построенный на основе языка Си и парадигм Smalltalk.
-В частности, объектная модель построена в стиле Smalltalk — то есть объектам посылаются сообщения.
+Objective-C — основной язык программирования, используемый корпорацией Apple
+для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и
+Cocoa Touch.
+Он является объектно-ориентированным языком программирования общего назначения,
+который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C.
```objective_c
-// Однострочный комментарий
+// Однострочные комментарии начинаются с //
/*
-Многострочный
-комментарий
+Так выглядят многострочные комментарии
*/
-// Импорт файлов фреймворка Foundation с помощью #import
+// Импорт заголовочных файлов фреймворка Foundation с помощью #import
+// Используйте <>, чтобы импортировать глобальные файлы (обычно фреймворки)
+// Используйте "", чтобы импортировать локальные файлы (из проекта)
#import <Foundation/Foundation.h>
#import "MyClass.h"
-// Точка входа в программу это функция main,
-// которая возвращает целый тип integer
+// Если вы включили модули для iOS >= 7.0 или OS X >= 10.9 проектов в
+// Xcode 5, вы можете импортировать фреймворки подобным образом:
+@import Foundation;
+
+// Точка входа в программу - это функция main,
+// которая возвращает целый тип
int main (int argc, const char * argv[])
{
- // Создание autorelease pool для управления памятью
+ // Создание autorelease pool для управления памятью в программе
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
+ // В место этого воспользуйтесь @autoreleasepool, если вы используете
+ // автоматический подсчет ссылок (ARC)
+ @autoreleasepool {
+
// Используйте NSLog для печати в консоль
- NSLog(@"Hello World!"); // Напечатает строку "Hello World!"
+ NSLog(@"Привет Мир!"); // Напечатает строку "Привет Мир!"
///////////////////////////////////////
// Типы и переменные
///////////////////////////////////////
- // Простое объявление
+ // Объявление простых типов
int myPrimitive1 = 1;
long myPrimitive2 = 234554664565;
+ // Объявление объектов
// Помещайте * в начало названия объекта для строго типизированного объявления
MyClass *myObject1 = nil; // Строгая типизация
id myObject2 = nil; // Слабая типизация
-
- NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
// %@ – это объект
- // 'description' это общий для всех объектов метод вывода данных
+ // 'description' - это общий для всех объектов метод вывода данных
+ NSLog(@"%@ and %@", myObject1, [myObject2 description]); // напечатает "(null) and (null)"
// Строка
- NSString *worldString = @"World";
- NSLog(@"Hello %@!", worldString); // напечатает "Hello World!"
+ NSString *worldString = @"Мир";
+ NSLog(@"Привет %@!", worldString); // напечатает "Привет Мир!"
+ // NSMutableString - это изменяемая версия NSString-объекта
+ NSMutableString *mutableString = [NSMutableString stringWithString:@"Привет"];
+ [mutableString appendString:@" Мир!"];
+ NSLog(@"%@", mutableString); // напечатает => "Привет Мир!"
// Символьные литералы
NSNumber *theLetterZNumber = @'Z';
- char theLetterZ = [theLetterZNumber charValue];
+ char theLetterZ = [theLetterZNumber charValue]; // или 'Z'
NSLog(@"%c", theLetterZ);
- // Целочисленный литералы
+ // Целочисленные литералы
NSNumber *fortyTwoNumber = @42;
- int fortyTwo = [fortyTwoNumber intValue];
+ int fortyTwo = [fortyTwoNumber intValue]; // или '42'
NSLog(@"%i", fortyTwo);
// Беззнаковый целочисленный литерал
NSNumber *fortyTwoUnsignedNumber = @42U;
- unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
+ unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // или 42
NSLog(@"%u", fortyTwoUnsigned);
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
- short fortyTwoShort = [fortyTwoShortNumber shortValue];
+ short fortyTwoShort = [fortyTwoShortNumber shortValue]; // или 42
NSLog(@"%hi", fortyTwoShort);
+ NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
+ unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // или 41
+ NSLog(@"%u", fortyOneUnsigned);
+
NSNumber *fortyTwoLongNumber = @42L;
- long fortyTwoLong = [fortyTwoLongNumber longValue];
+ long fortyTwoLong = [fortyTwoLongNumber longValue]; // или 42
NSLog(@"%li", fortyTwoLong);
+
+ NSNumber *fiftyThreeLongNumber = @53L;
+ unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // или 53
+ NSLog(@"%lu", fiftyThreeUnsigned);
// Вещественный литерал
NSNumber *piFloatNumber = @3.141592654F;
- float piFloat = [piFloatNumber floatValue];
- NSLog(@"%f", piFloat);
+ float piFloat = [piFloatNumber floatValue]; // или 3.141592654f
+ NSLog(@"%f", piFloat); // напечатает 3.141592654
+ NSLog(@"%5.2f", piFloat); // напечатает " 3.14"
NSNumber *piDoubleNumber = @3.1415926535;
- double piDouble = [piDoubleNumber doubleValue];
+ double piDouble = [piDoubleNumber doubleValue]; // или 3.1415926535
NSLog(@"%f", piDouble);
-
+ NSLog(@"%4.2f", piDouble); // напечатает "3.14"
+
+ // NSDecimalNumber - это класс с фиксированной точкой, который является
+ // более точным, чем float или double
+ NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"];
+ NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"];
+ // NSDecimalNumber не способен использовать стандартные +, -, *, / операторы,
+ // поэтому он предоставляет свои собственные:
+ [oneDecNum decimalNumberByAdding:twoDecNum];
+ [oneDecNum decimalNumberBySubtracting:twoDecNum];
+ [oneDecNum decimalNumberByMultiplyingBy:twoDecNum];
+ [oneDecNum decimalNumberByDividingBy:twoDecNum];
+ NSLog(@"%@", oneDecNum); // напечатает "10.99", т.к. NSDecimalNumber - изменяемый
+
// BOOL (булевый) литерал
NSNumber *yesNumber = @YES;
NSNumber *noNumber = @NO;
-
+ // или
+ BOOL yesBool = YES;
+ BOOL noBool = NO;
+ NSLog(@"%i", yesBool); // напечатает 1
+
// Массив
+ // Может содержать различные типы данных, но должен быть объектом Objective-C
NSArray *anArray = @[@1, @2, @3, @4];
NSNumber *thirdNumber = anArray[2];
- NSLog(@"Third number = %@", thirdNumber); // Print "Third number = 3"
+ NSLog(@"Третье число = %@", thirdNumber); // Напечатает "Третье число = 3"
+ // NSMutableArray - это изменяемая версия NSArray, допускающая вам изменять
+ // элементы в массиве и расширять или сокращать массив.
+ // Удобный, но не эффективный как NSArray.
+ NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2];
+ [mutableArray addObject:@"Привет"];
+ [mutableArray addObject:@"Мир"];
+ [mutableArray removeObjectAtIndex:0];
+ NSLog(@"%@", [mutableArray objectAtIndex:0]); // напечатает "Мир"
// Словарь
- NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
- NSObject *valueObject = aDictionary[@"A Key"];
- NSLog(@"Object = %@", valueObject); // Напечатает "Object = (null)"
-
+ NSDictionary *aDictionary = @{ @"ключ1" : @"значение1", @"ключ2" : @"значение2" };
+ NSObject *valueObject = aDictionary[@"Ключ"];
+ NSLog(@"Объект = %@", valueObject); // Напечатает "Объект = (null)"
+ // NSMutableDictionary тоже доступен, как изменяемый словарь
+ NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
+ [mutableDictionary setObject:@"значение1" forKey:@"ключ1"];
+ [mutableDictionary setObject:@"значение2" forKey:@"ключ2"];
+ [mutableDictionary removeObjectForKey:@"ключ1"];
+
+ // Множество
+ NSSet *set = [NSSet setWithObjects:@"Привет", @"Привет", @"Мир", nil];
+ NSLog(@"%@", set); // напечатает {(Hello, World)} (порядок может отличаться)
+ // NSMutableSet тоже доступен, как изменяемое множество
+ NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2];
+ [mutableSet addObject:@"Привет"];
+ [mutableSet addObject:@"Привет"];
+ NSLog(@"%@", mutableSet); // напечатает => {(Привет)}
+
///////////////////////////////////////
// Операторы
///////////////////////////////////////
@@ -124,13 +189,13 @@ int main (int argc, const char * argv[])
// Условный оператор
if (NO)
{
- NSLog(@"I am never run");
+ NSLog(@"Я никогда не выполнюсь");
} else if (0)
{
- NSLog(@"I am also never run");
+ NSLog(@"Я тоже никогда не выполнюсь");
} else
{
- NSLog(@"I print");
+ NSLog(@"Я напечатаюсь");
}
// Ветвление с множественным выбором
@@ -138,15 +203,15 @@ int main (int argc, const char * argv[])
{
case 0:
{
- NSLog(@"I am never run");
+ NSLog(@"Я никогда не выполнюсь");
} break;
case 1:
{
- NSLog(@"I am also never run");
+ NSLog(@"Я тоже никогда не выполнюсь");
} break;
default:
{
- NSLog(@"I print");
+ NSLog(@"Я напечатаюсь");
} break;
}
@@ -170,7 +235,7 @@ int main (int argc, const char * argv[])
// "2,"
// "3,"
- // // Цикл просмотра
+ // Цикл просмотра
NSArray *values = @[@0, @1, @2, @3];
for (NSNumber *value in values)
{
@@ -180,20 +245,32 @@ int main (int argc, const char * argv[])
// "2,"
// "3,"
+ // Цикл for для объектов. Может использоваться с любым объектом Objective-C
+ for (id item in values) {
+ NSLog(@"%@,", item);
+ } // напечатает => "0,"
+ // "1,"
+ // "2,"
+ // "3,"
+
// Обработка исключений
@try
{
// Ваше исключение здесь
@throw [NSException exceptionWithName:@"FileNotFoundException"
- reason:@"File Not Found on System" userInfo:nil];
+ reason:@"Файл не найден в системе" userInfo:nil];
} @catch (NSException * e)
{
- NSLog(@"Exception: %@", e);
+ NSLog(@"Исключение: %@", e);
} @finally
{
- NSLog(@"Finally");
- } // => напечатает "Exception: File Not Found on System"
- // "Finally"
+ NSLog(@"В конце отводится время для очистки.");
+ } // => напечатает "Исключение: Файл не найден в системе"
+ // "В конце отводится время для очистки."
+
+ // NSError - это полезные объекты для аргументов функции, чтобы заполнить их
+ // пользовательскими ошибками.
+ NSError *error = [NSError errorWithDomain:@"Неправильный эл. адрес." code:4 userInfo:nil];
///////////////////////////////////////
// Объекты
@@ -203,13 +280,16 @@ int main (int argc, const char * argv[])
// Объект не является полнофункциональным пока обе части не выполнятся.
MyClass *myObject = [[MyClass alloc] init];
- // В Objective-C можель ООП базируется на передаче сообщений.
+ // В Objective-C модель ООП базируется на передаче сообщений.
// В Objective-C Вы не просто вызваете метод; вы посылаете сообщение.
- [myObject instanceMethodWithParameter:@"Steve Jobs"];
+ [myObject instanceMethodWithParameter:@"Стив Джобс"];
// Очищайте память, перед завершением работы программы.
[pool drain];
+ // Конец @autoreleasepool
+ }
+
// Конец программы.
return 0;
}
@@ -222,63 +302,144 @@ int main (int argc, const char * argv[])
// Синтаксис объявления:
// @interface ИмяКласса : ИмяКлассаРодителя <ИмплементируемыеПротоколы>
// {
-// Объявление переменных;
+// тип имя; <= Объявление переменных;
// }
+// @property тип имя; <= объявление свойств
// -/+ (тип) Объявление метода(ов).
// @end
-
-
-@interface MyClass : NSObject <MyProtocol>
+@interface MyClass : NSObject <MyProtocol> // NSObject - это базовый класс в Objective-C.
{
- int count;
- id data;
+ // Объявления экземпляров переменных (может существовать в файлах интерфейса или реализвации)
+ int count; // По умолчанию защищенный доступ.
+ @private id data; // Приватный доступ (Намного удобнее объявлять в файле реализации)
NSString *name;
}
-// При объявлении свойств сразу генерируются геттер и сеттер
-@property int count;
-@property (copy) NSString *name; // Скопировать объект в ходе присвоения.
-@property (readonly) id data; // Генерация только геттера
+// Удобное обозначение для переменных с открытым (public) доступом
+// автоматически генерируется сеттер-метод
+// По умолчанию название сеттер-метода начинается с 'set' с последующим именем
+// переменной из @property
+@property int propInt; // Имя сеттер-метода = 'setPropInt'
+@property (copy) id copyId; // (copy) => Скопировать объект в ходе присвоения.
+// (readonly) => Не позволяет установить значение вне @interface
+@property (readonly) NSString *roString; // Используйте @synthesize
+ // в @implementation, чтобы создать аксессор
+// Вы можете настроить геттер и сеттер имена вместо используемого 'set'-имени по умолчанию:
+@property (getter=lengthGet, setter=lengthSet:) int length;
// Методы
-+/- (return type)methodSignature:(Parameter Type *)parameterName;
++/- (возвращаемый тип)сигнатураМетода:(Параметр типа *)имяПараметра;
// + для методов класса
+ (NSString *)classMethod;
++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
-// - для метода объекта
+// - для методов объекта
- (NSString *)instanceMethodWithParameter:(NSString *)string;
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
-@end
+// Методы-конструктор с аргументом:
+- (id)initWithDistance:(int)defaultDistance;
+// В Objective-C имена методов очень описательные. Всегда имена методов соответствуют своим аргументам
+
+@end // Устанавливает конец интерфейса (interface)
+
+
+// Чтобы обратиться к открытым (public) переменным из файла реализации, @property генерирует сеттер-метод
+// автоматически. Название метода - это 'set' с последующим именем переменной из @property:
+MyClass *myClass = [[MyClass alloc] init]; // создает экземпляр объекта класса MyClass
+[myClass setCount:10];
+NSLog(@"%d", [myClass count]); // напечатает => 10
+// Или используйте свой геттер и сеттер методы, которые определены в @interface:
+[myClass lengthSet:32];
+NSLog(@"%i", [myClass lengthGet]); // напечатает => 32
+// Для удобства вы можете использовать точечную нотацию,
+// чтобы установить и получить доступ к переменным объекта:
+myClass.count = 45;
+NSLog(@"%i", myClass.count); // напечатает => 45
+
+// Вызов методов класса:
+NSString *classMethodString = [MyClass classMethod];
+MyClass *classFromName = [MyClass myClassFromName:@"Привет"];
+
+// Вызов методов экземпляра:
+MyClass *myClass = [[MyClass alloc] init]; // Создает экземпляр объекта MyClass
+NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Привет"];
+
+// Селекторы
+// Это способ динамически представить методы. Используйте для вызова методов класса, передайте методы
+// через функции, чтобы сказать другим классам, что они должны вызвать их и сохранить методы
+// как переменные
+// SEL - это тип данных. @selector() вернет селектор из предоставленного имени метода
+// methodAParameterAsString:andAParameterAsNumber: - это название метода в MyClass
+SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
+if ([myClass respondsToSelector:selectorVar]) { // Проверяет содержит ли класс метод
+ // Необходимо установить все аргументы метода в один объект, что отправить его в performSelector-функцию
+ NSArray *arguments = [NSArray arrayWithObjects:@"Привет", @4, nil];
+ [myClass performSelector:selectorVar withObject:arguments]; // Вызывает метод
+} else {
+ // NSStringFromSelector() вернет NSString название метода полученного селектором
+ NSLog(@"MyClass не содержит метод: %@", NSStringFromSelector(selectedVar));
+}
// Имплементируйте методы в файле МойКласс.m:
+@implementation MyClass {
+ long distance; // Переменная экземпляра с закрытым (private) доступом
+ NSNumber height;
+}
-@implementation MyClass
+// To access a public variable from the interface file, use '_' followed by variable name:
+_count = 5; // References "int count" from MyClass interface
+// Access variables defined in implementation file:
+distance = 18; // References "long distance" from MyClass implementation
+// To use @property variable in implementation, use @synthesize to create accessor variable:
+@synthesize roString = _roString; // _roString available now in @implementation
+
+// Called before calling any class methods or instantiating any objects
++ (void)initialize
+{
+ if (self == [MyClass class]) {
+ distance = 0;
+ }
+}
// Вызывается при высвобождении памяти под объектом
- (void)dealloc
{
+ [height release]; // Если не используется ARC, убедитесь в освобождении переменных объекта класса
+ [super dealloc]; // and call parent class dealloc
}
-// Конструкторы – это способ осздания объектов класса.
-// Это обычный конструктор вызываемый при создании объекта клсааа.
+// Конструкторы – это способ создания объектов класса.
+// Это конструктор по умолчанию, который вызывается, когда объект инициализируется.
- (id)init
{
- if ((self = [super init]))
+ if ((self = [super init])) // 'super' используется для того, чтобы обратиться к методам родительского класса
{
- self.count = 1;
+ self.count = 1; // 'self' используется для вызова самого себя
}
return self;
}
+// Можно создать конструкторы, которые содержат аргументы:
+- (id)initWithDistance:(int)defaultDistance
+{
+ distance = defaultDistance;
+ return self;
+}
+ (NSString *)classMethod
{
return [[self alloc] init];
}
++ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
+{
+ height = defaultHeight;
+ return [[self alloc] init];
+}
+
- (NSString *)instanceMethodWithParameter:(NSString *)string
{
- return @"New string";
+ return @"Новая строка";
}
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
@@ -286,23 +447,364 @@ int main (int argc, const char * argv[])
return @42;
}
+// Objective-C не содержит объявление приватных методов, но вы можете имитировать их.
+// Чтобы сымитировать приватный метод, создайте метод в @implementation, но не в @interface.
+- (NSNumber *)secretPrivateMethod {
+ return @72;
+}
+[self secretPrivateMethod]; // Вызывает приватный метод
+
// Методы объявленные в МyProtocol (см. далее)
- (void)myProtocolMethod
{
- // имплементация
+ // операторы
}
+@end // Устанавливает конец реализации (implementation)
+
+///////////////////////////////////////
+// Категории
+///////////////////////////////////////
+// Категория - это группа методов предназначенные для того, чтобы расширить класс. Они позволяют вам добавить новые методы
+// к существующему классу для организационных целей. Это не стоит путать с подклассами.
+// Подклассы предназначены для ИЗМЕНЕНИЯ функциональности объекта пока как категории ДОБАВЛЯЮТ
+// функциональность в объект.
+// Категории позволяют вам:
+// -- Добавлять методы в существующий класс для организационных целей.
+// -- Допускает вам расширять объекты Objective-C классов (напр.: NSString) добавить ваши собственные методы.
+// -- Добавляет возможность создать защищенные и закрытые методы классов.
+// ПРИМЕЧАНИЕ: Не переопределяйте методы базового класса в категории даже если у вас есть возможность это сделать
+// to. Переопределение методов может привести к ошибкам компиляции позднее между различными категориями и это
+// нарушает цель категорий, чтобы добавлять только функциональность. Вместо этого подклассы переопределяют методы.
+
+// Здесь простой базовый класс Car.
+@interface Car : NSObject
+
+@property NSString *make;
+@property NSString *color;
+
+- (void)turnOn;
+- (void)accelerate;
+
@end
-/*
- * Протокол объявляет методы которые должны быть имплементированы
- * Протокол не является классом. Он просто определяет интерфейс,
- * который должен быть имплементирован.
- */
+// И реализация базового класса Car:
+#import "Car.h"
+
+@implementation Car
+
+@synthesize make = _make;
+@synthesize color = _color;
+
+- (void)turnOn {
+ NSLog(@"Машина заведена.");
+}
+- (void)accelerate {
+ NSLog(@"Ускорение.");
+}
-@protocol MyProtocol
- - (void)myProtocolMethod;
@end
+
+// Теперь, если мы хотели создать грузовой объект, мы должны вместо создания подкласса класса Car, как это будет
+// изменять функциональность Car чтобы вести себя подобно грузовику. Но давайте посмотрим, если мы хотим только добавить
+// функциональность в существующий Car. Хороший пример должен быть чистить автомобиль. Итак мы создадим
+// категорию для добавления его очистительных методов:
+// @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h)
+#import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения.
+
+@interface Car (Clean) // Имя категории внутри (), следующие после имени базового класса.
+
+- (void)washWindows; // Названия новых методов, которые мы добавляем в наш объект Car.
+- (void)wax;
+
+@end
+
+// @implementation имя файла: Car+Clean.m (ИмяБазовогоКласса+ИмяКатегории.m)
+#import "Car+Clean.h" // Импортируйте Очистку файл @interface категории.
+
+@implementation Car (Clean)
+
+- (void)washWindows {
+ NSLog(@"Окна промыли.");
+}
+- (void)wax {
+ NSLog(@"Воском натерли.");
+}
+
+@end
+
+// Любой экземпляр объекта Car имеет возможность воспользоваться категорией. Все, что нужно сделать, это импортировать ее:
+#import "Car+Clean.h" // Импортировать как множество различных категорий, как вы хотите использовать.
+#import "Car.h" // Кроме того, необходимо импортировать базовый класс для использования его оригинальные функциональные возможности.
+
+int main (int argc, const char * argv[]) {
+ @autoreleasepool {
+ Car *mustang = [[Car alloc] init];
+ mustang.color = @"Красный";
+ mustang.make = @"Форд";
+
+ [mustang turnOn]; // Используйте методы из базового класса Car.
+ [mustang washWindows]; // Используйте методы категории Clean из класса Car.
+ }
+ return 0;
+}
+
+// Objective-C не поддерживает объявление защищенных методов, но вы можете имитировать их.
+// Создайте категорию, содержащую все защищенные методы, затем импортируйте ее только в
+// @implementation-файле класса, относящегося к классу Car:
+@interface Car (Protected) // Наименование категории с помощью 'Protected'
+// дает знать, что методы защищенные.
+
+- (void)lockCar; // Здесь перечисляются методы, которые должны быть созданы
+// только с помощью объектов класса Car.
+
+@end
+// Чтобы воспользоваться защищенными методами, импортируйте категорию, затем реализуйте методы:
+#import "Car+Protected.h" // Запомните, делайте импорт только в файле с @implementation.
+
+@implementation Car
+
+- (void)lockCar {
+ NSLog(@"Машина закрыта."); // Экземпляры класса Car не могут использовать
+// метод lockCar, потому что он объявлен не в @interface.
+}
+
+@end
+
+///////////////////////////////////////
+// Расширения
+///////////////////////////////////////
+// Расширения позволяют вам переопределять атрибуты свойств и методов
+// с открытым доступом в @interface.
+// @interface имя файла: Shape.h
+@interface Shape : NSObject // Расширение базового класса Shape переопределяет
+ // свои поля ниже.
+
+@property (readonly) NSNumber *numOfSides;
+
+- (int)getNumOfSides;
+
+@end
+// Вы можете переопределить numOfSides-переменную или getNumOfSides-метод
+// Внесение изменений с помощью расширения делается следующим образом:
+// @implementation имя файла: Shape.m
+#import "Shape.h"
+// Расширения "живут" в том же файле, где и @implementation класса.
+@interface Shape () // После имени базового класса скобки () объявляют расширение.
+
+@property (copy) NSNumber *numOfSides; // Делает numOfSides-свойство
+ // копирующим (copy) вместо свойства только для чтения (readonly).
+-(NSNumber)getNumOfSides; // Изменяет метод getNumOfSides так,
+ // чтобы он возвращал объект NSNumber вместо типа int.
+-(void)privateMethod; // Вы также можете создать новый закрытый метод
+ // внутри расширения.
+
+@end
+// Главный @implementation:
+@implementation Shape
+
+@synthesize numOfSides = _numOfSides;
+
+-(NSNumber)getNumOfSides { // Все операторы внутри расширения
+ // должны быть в @implementation.
+ return _numOfSides;
+}
+-(void)privateMethod {
+ NSLog(@"Закрытый метод созданный с помощью расширения.");
+ NSLog(@"Экземпляр Shape не может вызвать этот метод.");
+}
+
+@end
+
+///////////////////////////////////////
+// Протоколы
+///////////////////////////////////////
+// Протокол объявляет методы, которые могут быть реализованы с помощью
+// любого класса. Протоколы сами по себе не являются классами. Они просто
+// определяют интерфейс, который должен быть реализован другими объектами.
+// @protocol имя файла: "CarUtilities.h"
+@protocol CarUtilities <NSObject> // <NSObject> => Имя другого протокола,
+// который включен в этот протокол.
+ @property BOOL engineOn; // Адаптирующий класс должен определить
+// все @synthesize для @property и
+ - (void)turnOnEngine; // определить все методы.
+@end
+// Ниже пример класса, реализующий протокол.
+#import "CarUtilities.h" // Импорт файла с @protocol.
+
+@interface Car : NSObject <CarUtilities> // Внутри <> имя протокола
+// Здесь вам не нужно указывать @property или имена методов для CarUtilities.
+// Они нужны только для @implementation.
+- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // Вы также можете
+// указать тип протоколов.
+@end
+// В @implementation нужно реализовать все @property и методы для протокола.
+@implementation Car : NSObject <CarUtilities>
+
+@synthesize engineOn = _engineOn; // Создайте @synthesize-оператор
+// для "@property engineOn".
+
+- (void)turnOnEngine { // Реализуйте turnOnEngine как вам угодно. Протоколы
+// не определят,
+ _engineOn = YES; // как вам реализовать метод, он только требует,
+// чтобы вы реализовали его.
+}
+// Вы можете использовать протокол как данные, если вы знаете, что он реализует
+// методы и переменные.
+- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
+ [objectOfSomeKind engineOn]; // У вас есть доступ к переменным объекта
+ [objectOfSomeKind turnOnEngine]; // и методам.
+ [objectOfSomeKind engineOn]; // Может или не может быть значение YES. Класс
+// реализует как нужно.
+}
+
+@end
+// Экземпляры класса Car сейчас имеют доступ к протоколу.
+Car *carInstance = [[Car alloc] init];
+[carInstance setEngineOn:NO];
+[carInstance turnOnEngine];
+if ([carInstance engineOn]) {
+ NSLog(@"Двигатель запущен."); // напечатает => "Двигатель запущен."
+}
+// Убедитись в том, что объект типа 'id' реализует протокол перед вызовом методов протокола:
+if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
+ NSLog(@"Не работает, т.к. класс MyClass не реализует протокол CarUtilities.");
+} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
+ NSLog(@"Работает как класс Car, который реализует протокол CarUtilities.");
+}
+// Категории тоже могут реализовать протоколы:
+// @interface Car (CarCategory) <CarUtilities>
+// Вы можете реализовать много протоколов:
+// @interface Car : NSObject <CarUtilities, CarCleaning>
+// ЗАМЕЧАНИЕ: Если два или более протоколов полагаются друг на друга,
+// убедитесь, что они ранее объявлены:
+#import "Brother.h"
+
+@protocol Brother; // Оператор раннего объявления. Без него компилятор
+// выдаст ошибку.
+
+@protocol Sister <NSObject>
+
+- (void)beNiceToBrother:(id <Brother>)brother;
+
+@end
+
+// Рассмотрите проблему, где протокол Sister полагается на протокол Brother,
+// а Brother полагается на Sister.
+#import "Sister.h"
+
+@protocol Sister; // Эти строки предотвращают рекурсию, решая этим проблему.
+
+@protocol Brother <NSObject>
+
+- (void)beNiceToSister:(id <Sister>)sister;
+
+@end
+
+
+///////////////////////////////////////
+// Блоки
+///////////////////////////////////////
+// Блоки - это операторы кода, наподобие функции, которую возможно использовать
+// как данные.
+// Ниже простой блок с целочисленным аргументом, и возвращает аргумент плюс 4.
+int (^addUp)(int n); // Объявите переменную, чтобы сохранить блок.
+void (^noParameterBlockVar)(void); // Пример объявления блока-переменной
+// без аргументов.
+// Блоки имею доступ к переменным в той же области видимости. Но переменные
+// будут только для чтения, и значения переданных в блок станут значением
+// переменной, когда блок создастся.
+int outsideVar = 17; // Если мы редактируем outsideVar после объявления addUp,
+// outsideVar остается равным 17.
+__block long mutableVar = 3; // __block делают переменные перезаписываемыми
+// в блоках, в отличие от outsideVar.
+addUp = ^(int n) { // Удалите (int n) в блоке, чтобы не принимать
+// какие-либо параметры.
+ NSLog(@"Вы можете иметь столько строк в блоке, сколько вы хотели.");
+ NSSet *blockSet; // Также вы можете объявить локальные переменные.
+ mutableVar = 32; // Присвоить новое значение к __block-переменной.
+ return n + outsideVar; // Необязательный оператор возврата.
+}
+int addUp = add(10 + 16); // Вызывает блок кода с аргументами.
+// Блоки часто используются как аргументы функции, чтобы позже их вызвать, или
+// как функции обратного вызова (callbacks).
+@implementation BlockExample : NSObject
+
+- (void)runBlock:(void (^)(NSString))block {
+ NSLog(@"В аргументе блок ничего не возвращает и принимает NSString-объект.");
+ block(@"Аргумент передан блоку на исполнение."); // Вызов блока.
+}
+
+@end
+
+
+///////////////////////////////////////
+// Управление памятью
+///////////////////////////////////////
+/*
+Для каждого объекта, используемого в приложении, должна быть выделена память
+для таких объектов. Когда приложение прекращает использование объекта, память
+должна быть освобождена, чтобы гарантировать эффективность приложения.
+Objective-C не использует сборщик мусора, а вместо этого применяет подсчет ссылок.
+Пока существует по крайней мере одна ссылка на объект (также называется
+"владение" объектом), то объект будет доступен к использованию (еще известно
+как "право владения").
+
+Когда экземпляр владеет объектом, его ссылка увеличивается на один. Когда
+объекта освобождается, счетчик ссылки уменьшается на один. Когда счетчик ссылки
+равен нулю, объект удаляется из памяти.
+
+Над всеми объектами взаимодействуют, следуя паттерну:
+(1) создание объекта, (2) использование объекта, (3) затем освобождение объекта из памяти.
+*/
+
+MyClass *classVar = [MyClass alloc]; // 'alloc' устанавливает счетчик ссылки
+// объекта classVar на 1 и возвращает указатель на объект.
+[classVar release]; // Уменьшает счетчик ссылки объекта classVar
+// 'retain' заявляет право собственности на существующий экземпляр объекта
+// и увеличивает счетчик ссылки. Затем вернет указатель на объект.
+MyClass *newVar = [classVar retain]; // Если classVar освободится, объект
+// останется в памяти, потому что newVar - владелец
+[classVar autorelease]; // Удалит право на владение объектом
+// в конце @autoreleasepool блока. Вернет указатель на объект.
+
+// @property может использовать 'retain' и 'assign' тоже для маленького
+// удобного определения
+@property (retain) MyClass *instance; // Освободит старое значение и сохранит
+// одно новое (строгая ссылка)
+@property (assign) NSSet *set; // Укажет на новое значение
+// без сохранения/освобождения старого значения (слабая ссылка)
+
+// Автоматический подсчет ссылок (ARC)
+// Управление памятью может быть трудным, поэтому в Xcode 4.2 и iOS 4 введен
+// автоматический подсчет ссылок (ARC).
+// ARC - это особенность компилятора, который помещает "retain", "release"
+// и "autorelease" автоматически за вас тогда, когда используется ARC,
+// вам не нужно больше обращаться к "retain", "relase" или "autorelease"
+MyClass *arcMyClass = [[MyClass alloc] init];
+// ... код, использующий объект arcMyClass
+// Без ARC, вам нужно было бы вызвать: [arcMyClass release] после того, как вы
+// завершите работу с объектом arcMyClass. Но с ARC,
+// теперь этого не нужно делать. Он будет помещать release-вызов за вас
+
+// Что касается 'assign' и 'retain' @property атрибутов, в ARC вы должны
+// использовать 'weak' и 'strong'
+@property (weak) MyClass *weakVar; // 'weak' не принимает право на владение
+// объектом. Если исходный счетчик ссылки экземпляра обнуляется,
+// weakVar-свойство автоматически примет значение nil,
+// во избежание падения приложения
+@property (strong) MyClass *strongVar; // 'strong' принимает право на владение
+// объектом. Гарантирует, что объект останится в памяти для использования
+
+// Для обычных переменных (не объявленных с помощью @property), используйте
+// следующий способ:
+__strong NSString *strongString; // По умолчанию. Переменная сохраняется в памяти,
+// пока она не покинет область видимости
+__weak NSSet *weakSet; // Слабая ссылка на существующий объект. Когда существующий
+// объект освобождается, weakSet принимает nil
+__unsafe_unretained NSArray *unsafeArray; // Похож на __weak, но unsafeArray
+// не принимает nil, когда существующий объект освобождается
+
```
## На почитать
diff --git a/ruby-ecosystem.html.markdown b/ruby-ecosystem.html.markdown
index 8b292edd..d8a02d36 100644
--- a/ruby-ecosystem.html.markdown
+++ b/ruby-ecosystem.html.markdown
@@ -54,7 +54,7 @@ the community has moved to at least 1.9.2 or 1.9.3.
## Ruby Implementations
The Ruby ecosystem enjoys many different implementations of Ruby, each with
-unique strengths and states of compatability. To be clear, the different
+unique strengths and states of compatibility. To be clear, the different
implementations are written in different languages, but *they are all Ruby*.
Each implementation has special hooks and extra features, but they all run
normal Ruby files well. For instance, JRuby is written in Java, but you do
diff --git a/ruby.html.markdown b/ruby.html.markdown
index 792c9c95..7bd28d86 100644
--- a/ruby.html.markdown
+++ b/ruby.html.markdown
@@ -79,10 +79,14 @@ true && false #=> false
true || false #=> true
!true #=> false
-# Alternate spellings of logical operators
-true and false #=> false
-true or false #=> true
-not true #=> false
+# There are alternate versions of the logical operators with much lower
+# precedence. These are meant to be used as flow-control constructs to chain
+# statements together until one of them returns true or false.
+
+# `do_something_else` only called if `do_something` succeeds.
+do_something() and do_something_else()
+# `log_error` only called if `do_something` fails.
+do_something() or log_error()
# Strings are objects
@@ -169,6 +173,8 @@ array[1..3] #=> [2, 3, 4]
# Add to an array like this
array << 6 #=> [1, 2, 3, 4, 5, 6]
+# Or like this
+array.push(6) #=> [1, 2, 3, 4, 5, 6]
# Check if an item exists in an array
array.include?(1) #=> true
diff --git a/rust.html.markdown b/rust.html.markdown
index 17f7dc90..4fbd6144 100644
--- a/rust.html.markdown
+++ b/rust.html.markdown
@@ -5,7 +5,7 @@ contributors:
filename: learnrust.rs
---
-Rust is an in-development programming language developed by Mozilla Research.
+Rust is a programming language developed by Mozilla Research.
Rust combines low-level control over performance with high-level convenience and
safety guarantees.
@@ -84,7 +84,7 @@ fn main() {
// This is basically an immutable pointer to a string – it doesn’t
// actually contain the contents of a string, just a pointer to
// something that does (in this case, `s`)
- let s_slice: &str = &*s;
+ let s_slice: &str = &s;
println!("{} {}", s, s_slice); // hello world hello world
@@ -99,7 +99,7 @@ fn main() {
// A slice – an immutable view into a vector or array
// This is much like a string slice, but for vectors
- let slice: &[i32] = &*vector;
+ let slice: &[i32] = &vector;
// Use `{:?}` to print something debug-style
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
@@ -281,7 +281,7 @@ fn main() {
println!("{}", var); // Unlike `box`, `var` can still be used
println!("{}", *ref_var);
// var = 5; // this would not compile because `var` is borrowed
- // *ref_var = 6; // this would too, because `ref_var` is an immutable reference
+ // *ref_var = 6; // this would not too, because `ref_var` is an immutable reference
// Mutable reference
// While a value is mutably borrowed, it cannot be accessed at all.
diff --git a/scala.html.markdown b/scala.html.markdown
index e6638121..c482752d 100644
--- a/scala.html.markdown
+++ b/scala.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["George Petrov", "http://github.com/petrovg"]
- ["Dominic Bou-Samra", "http://dbousamra.github.com"]
- ["Geoff Liu", "http://geoffliu.me"]
+ - ["Ha-Duong Nguyen", "http://reference-error.org"]
filename: learn.scala
---
@@ -16,15 +17,16 @@ Scala - the scalable language
Set yourself up:
1) Download Scala - http://www.scala-lang.org/downloads
- 2) unzip/untar in your favourite location and put the bin subdir on the path
- 3) Start a scala REPL by typing scala. You should see the prompt:
+ 2) Unzip/untar to your favourite location and put the bin subdir in your `PATH` environment variable
+ 3) Start a Scala REPL by running `scala`. You should see the prompt:
scala>
- This is the so called REPL (Read-Eval-Print Loop). You may type any valid
- Scala expression into it, and the result will be printed. We will explain what
- Scala files look like further into this tutorial, but for now, let's start
- with some basics.
+ This is the so called REPL (Read-Eval-Print Loop). You may type any Scala
+ expression, and the result will be printed. We will explain what Scala files
+ look like further into this tutorial, but for now, let's start with some
+ basics.
+
*/
@@ -32,10 +34,10 @@ Scala - the scalable language
// 1. Basics
/////////////////////////////////////////////////
-// Single line comments start with two forward slashes
+// Single-line comments start with two forward slashes
/*
- Multi line comments, as you can already see from above, look like this.
+ Multi-line comments, as you can already see from above, look like this.
*/
// Printing, and forcing a new line on the next print
@@ -46,12 +48,12 @@ println(10)
print("Hello world")
// Declaring values is done using either var or val.
-// val declarations are immutable, whereas var's are mutable. Immutability is
+// val declarations are immutable, whereas vars are mutable. Immutability is
// a good thing.
val x = 10 // x is now 10
-x = 20 // error: reassignment to val
+x = 20 // error: reassignment to val
var y = 10
-y = 20 // y is now 20
+y = 20 // y is now 20
/*
Scala is a statically typed language, yet note that in the above declarations,
@@ -71,17 +73,17 @@ true
false
// Boolean operations
-!true // false
-!false // true
+!true // false
+!false // true
true == false // false
-10 > 5 // true
+10 > 5 // true
// Math is as per usual
-1 + 1 // 2
-2 - 1 // 1
-5 * 3 // 15
-6 / 2 // 3
-6 / 4 // 1
+1 + 1 // 2
+2 - 1 // 1
+5 * 3 // 15
+6 / 2 // 3
+6 / 4 // 1
6.0 / 4 // 1.5
@@ -120,12 +122,12 @@ s"We have $n apples" // => "We have 45 apples"
// Expressions inside interpolated strings are also possible
val a = Array(11, 9, 6)
-s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old."
+s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old."
s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples."
-s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"
+s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4"
// Formatting with interpolated strings with the prefix "f"
-f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
+f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25"
f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454"
// Raw strings, ignoring special characters.
@@ -171,12 +173,12 @@ def sq(x: Int) = x * x // Compiler can guess return type is Int
// Functions can have default parameters:
def addWithDefault(x: Int, y: Int = 5) = x + y
-addWithDefault(1, 2) // => 3
-addWithDefault(1) // => 6
+addWithDefault(1, 2) // => 3
+addWithDefault(1) // => 6
// Anonymous functions look like this:
-(x:Int) => x * x
+(x: Int) => x * x
// Unlike defs, even the input type of anonymous functions can be omitted if the
// context makes it clear. Notice the type "Int => Int" which means a function
@@ -193,8 +195,8 @@ sq(10) // => 100
val addOne: Int => Int = _ + 1
val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3)
-addOne(5) // => 6
-weirdSum(2, 4) // => 16
+addOne(5) // => 6
+weirdSum(2, 4) // => 16
// The return keyword exists in Scala, but it only returns from the inner-most
@@ -204,9 +206,9 @@ weirdSum(2, 4) // => 16
def foo(x: Int): Int = {
val anonFunc: Int => Int = { z =>
if (z > 5)
- return z // This line makes z the return value of foo!
+ return z // This line makes z the return value of foo!
else
- z + 2 // This line is the return value of anonFunc
+ z + 2 // This line is the return value of anonFunc
}
anonFunc(x) // This line is the return value of foo
}
@@ -218,19 +220,19 @@ def foo(x: Int): Int = {
1 to 5
val r = 1 to 5
-r.foreach( println )
+r.foreach(println)
r foreach println
// NB: Scala is quite lenient when it comes to dots and brackets - study the
// rules separately. This helps write DSLs and APIs that read like English
-(5 to 1 by -1) foreach ( println )
+(5 to 1 by -1) foreach (println)
// A while loops
var i = 0
-while (i < 10) { println("i " + i); i+=1 }
+while (i < 10) { println("i " + i); i += 1 }
-while (i < 10) { println("i " + i); i+=1 } // Yes, again. What happened? Why?
+while (i < 10) { println("i " + i); i += 1 } // Yes, again. What happened? Why?
i // Show the value of i. Note that while is a loop in the classical sense -
// it executes sequentially while changing the loop variable. while is very
@@ -239,19 +241,19 @@ i // Show the value of i. Note that while is a loop in the classical sense -
// A do while loop
do {
- println("x is still less than 10");
+ println("x is still less than 10")
x += 1
} while (x < 10)
// Tail recursion is an idiomatic way of doing recurring things in Scala.
// Recursive functions need an explicit return type, the compiler can't infer it.
// Here it's Unit.
-def showNumbersInRange(a:Int, b:Int):Unit = {
+def showNumbersInRange(a: Int, b: Int): Unit = {
print(a)
if (a < b)
showNumbersInRange(a + 1, b)
}
-showNumbersInRange(1,14)
+showNumbersInRange(1, 14)
// Conditionals
@@ -305,13 +307,13 @@ s(1)
(a, 2, "three")
// Why have this?
-val divideInts = (x:Int, y:Int) => (x / y, x % y)
+val divideInts = (x: Int, y: Int) => (x / y, x % y)
-divideInts(10,3) // The function divideInts gives you the result and the remainder
+divideInts(10, 3) // The function divideInts gives you the result and the remainder
// To access the elements of a tuple, use _._n where n is the 1-based index of
// the element
-val d = divideInts(10,3)
+val d = divideInts(10, 3)
d._1
@@ -359,7 +361,7 @@ class Dog(br: String) {
val mydog = new Dog("greyhound")
println(mydog.breed) // => "greyhound"
-println(mydog.bark) // => "Woof, woof!"
+println(mydog.bark) // => "Woof, woof!"
// The "object" keyword creates a type AND a singleton instance of it. It is
@@ -414,8 +416,8 @@ val otherGeorge = george.copy(phoneNumber = "9876")
def matchPerson(person: Person): String = person match {
// Then you specify the patterns:
case Person("George", number) => "We found George! His number is " + number
- case Person("Kate", number) => "We found Kate! Her number is " + number
- case Person(name, number) => "We matched someone : " + name + ", phone : " + number
+ case Person("Kate", number) => "We found Kate! Her number is " + number
+ case Person(name, number) => "We matched someone : " + name + ", phone : " + number
}
val email = "(.*)@(.*)".r // Define a regex for the next example.
@@ -446,7 +448,7 @@ def matchEverything(obj: Any): String = obj match {
case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c"
// You can nest patterns:
- case List(List((1, 2,"YAY"))) => "Got a list of list of tuple"
+ case List(List((1, 2, "YAY"))) => "Got a list of list of tuple"
}
// In fact, you can pattern match any object with an "unapply" method. This
@@ -493,7 +495,7 @@ sSquared.reduce (_+_)
// The filter function takes a predicate (a function from A -> Boolean) and
// selects all elements which satisfy the predicate
List(1, 2, 3) filter (_ > 2) // List(3)
-case class Person(name:String, age:Int)
+case class Person(name: String, age: Int)
List(
Person(name = "Dom", age = 23),
Person(name = "Bob", age = 30)
@@ -541,8 +543,8 @@ implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed)
// By itself, implicit keyword doesn't change the behavior of the value, so
// above values can be used as usual.
-myImplicitInt + 2 // => 102
-myImplicitFunction("Pitbull").breed // => "Golden Pitbull"
+myImplicitInt + 2 // => 102
+myImplicitFunction("Pitbull").breed // => "Golden Pitbull"
// The difference is that these values are now eligible to be used when another
// piece of code "needs" an implicit value. One such situation is implicit
@@ -570,8 +572,8 @@ def foo[T : C] = ...
// implicit conversion of type A => B, where A is the type of obj, and B has a
// method called "method", that conversion is applied. So having
// myImplicitFunction above in scope, we can say:
-"Retriever".breed // => "Golden Retriever"
-"Sheperd".bark // => "Woof, woof!"
+"Retriever".breed // => "Golden Retriever"
+"Sheperd".bark // => "Woof, woof!"
// Here the String is first converted to Dog using our function above, and then
// the appropriate method is called. This is an extremely powerful feature, but
@@ -594,7 +596,7 @@ import scala.collection.immutable._
import scala.collection.immutable.{List, Map}
// Rename an import using '=>'
-import scala.collection.immutable.{ List => ImmutableList }
+import scala.collection.immutable.{List => ImmutableList}
// Import all classes, except some. The following excludes Map and Set:
import scala.collection.immutable.{Map => _, Set => _, _}
@@ -629,13 +631,8 @@ writer.close()
## Further resources
-[Scala for the impatient](http://horstmann.com/scala/)
-
-[Twitter Scala school](http://twitter.github.io/scala_school/)
-
-[The scala documentation](http://docs.scala-lang.org/)
-
-[Try Scala in your browser](http://scalatutorials.com/tour/)
-
-Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user)
-
+* [Scala for the impatient](http://horstmann.com/scala/)
+* [Twitter Scala school](http://twitter.github.io/scala_school/)
+* [The scala documentation](http://docs.scala-lang.org/)
+* [Try Scala in your browser](http://scalatutorials.com/tour/)
+* Join the [Scala user group](https://groups.google.com/forum/#!forum/scala-user)
diff --git a/swift.html.markdown b/swift.html.markdown
index ffc57e69..509c9d2f 100644
--- a/swift.html.markdown
+++ b/swift.html.markdown
@@ -4,6 +4,7 @@ contributors:
- ["Grant Timmerman", "http://github.com/grant"]
- ["Christopher Bess", "http://github.com/cbess"]
- ["Joey Huang", "http://github.com/kamidox"]
+ - ["Anthony Nguyen", "http://github.com/anthonyn60"]
filename: learnswift.swift
---
@@ -26,7 +27,9 @@ import UIKit
// TODO: Do something soon
// FIXME: Fix this code
-println("Hello, world")
+// In Swift 2, println and print were combined into one print method. Print automatically appends a new line.
+print("Hello, world") // println is now print
+print("Hello, world", appendNewLine: false) // printing without appending a newline
// variables (var) value can change after being set
// constants (let) value can NOT be changed after being set
@@ -46,12 +49,12 @@ let piText = "Pi = \(π), Pi 2 = \(π * 2)" // String interpolation
// Build Specific values
// uses -D build configuration
#if false
- println("Not printed")
+ print("Not printed")
let buildValue = 3
#else
let buildValue = 7
#endif
-println("Build value: \(buildValue)") // Build value: 7
+print("Build value: \(buildValue)") // Build value: 7
/*
Optionals are a Swift language feature that allows you to store a `Some` or
@@ -69,7 +72,7 @@ var someOptionalString2: Optional<String> = "optional"
if someOptionalString != nil {
// I am not nil
if someOptionalString!.hasPrefix("opt") {
- println("has the prefix")
+ print("has the prefix")
}
let empty = someOptionalString?.isEmpty
@@ -138,21 +141,21 @@ var emptyMutableDictionary = [String: Float]() // var == mutable
let myArray = [1, 1, 2, 3, 5]
for value in myArray {
if value == 1 {
- println("One!")
+ print("One!")
} else {
- println("Not one!")
+ print("Not one!")
}
}
// for loop (dictionary)
var dict = ["one": 1, "two": 2]
for (key, value) in dict {
- println("\(key): \(value)")
+ print("\(key): \(value)")
}
// for loop (range)
for i in -1...shoppingList.count {
- println(i)
+ print(i)
}
shoppingList[1...2] = ["steak", "peacons"]
// use ..< to exclude the last number
@@ -165,7 +168,7 @@ while i < 1000 {
// do-while loop
do {
- println("hello")
+ print("hello")
} while 1 == 2
// Switch
@@ -222,8 +225,8 @@ let pricesTuple = getGasPrices()
let price = pricesTuple.2 // 3.79
// Ignore Tuple (or other) values by using _ (underscore)
let (_, price1, _) = pricesTuple // price1 == 3.69
-println(price1 == pricesTuple.1) // true
-println("Gas price: \(price)")
+print(price1 == pricesTuple.1) // true
+print("Gas price: \(price)")
// Variadic Args
func setup(numbers: Int...) {
@@ -251,7 +254,7 @@ func swapTwoInts(inout a: Int, inout b: Int) {
var someIntA = 7
var someIntB = 3
swapTwoInts(&someIntA, &someIntB)
-println(someIntB) // 7
+print(someIntB) // 7
//
@@ -305,7 +308,7 @@ struct NamesTable {
// Structures have an auto-generated (implicit) designated initializer
let namesTable = NamesTable(names: ["Me", "Them"])
let name = namesTable[1]
-println("Name is \(name)") // Name is Them
+print("Name is \(name)") // Name is Them
//
// MARK: Classes
@@ -386,7 +389,7 @@ let aShape = mySquare as Shape
// compare instances, not the same as == which compares objects (equal to)
if mySquare === mySquare {
- println("Yep, it's mySquare")
+ print("Yep, it's mySquare")
}
// Optional init
@@ -409,13 +412,13 @@ class Circle: Shape {
}
var myCircle = Circle(radius: 1)
-println(myCircle?.getArea()) // Optional(3)
-println(myCircle!.getArea()) // 3
+print(myCircle?.getArea()) // Optional(3)
+print(myCircle!.getArea()) // 3
var myEmptyCircle = Circle(radius: -1)
-println(myEmptyCircle?.getArea()) // "nil"
+print(myEmptyCircle?.getArea()) // "nil"
if let circle = myEmptyCircle {
// will not execute since myEmptyCircle is nil
- println("circle is not nil")
+ print("circle is not nil")
}
@@ -447,7 +450,7 @@ enum BookName: String {
case John = "John"
case Luke = "Luke"
}
-println("Name: \(BookName.John.rawValue)")
+print("Name: \(BookName.John.rawValue)")
// Enum with associated Values
enum Furniture {
@@ -467,9 +470,9 @@ enum Furniture {
}
var desk: Furniture = .Desk(height: 80)
-println(desk.description()) // "Desk with 80 cm"
+print(desk.description()) // "Desk with 80 cm"
var chair = Furniture.Chair("Foo", 40)
-println(chair.description()) // "Chair of Foo with 40 cm"
+print(chair.description()) // "Chair of Foo with 40 cm"
//
@@ -522,7 +525,7 @@ extension Square: Printable {
}
}
-println("Square: \(mySquare)")
+print("Square: \(mySquare)")
// You can also extend built-in types
extension Int {
@@ -535,8 +538,8 @@ extension Int {
}
}
-println(7.customProperty) // "This is 7"
-println(14.multiplyBy(3)) // 42
+print(7.customProperty) // "This is 7"
+print(14.multiplyBy(3)) // 42
// Generics: Similar to Java and C#. Use the `where` keyword to specify the
// requirements of the generics.
@@ -550,7 +553,7 @@ func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
return nil
}
let foundAtIndex = findIndex([1, 2, 3, 4], 3)
-println(foundAtIndex == 2) // true
+print(foundAtIndex == 2) // true
// Operators:
// Custom operators can start with the characters:
@@ -566,9 +569,9 @@ prefix func !!! (inout shape: Square) -> Square {
}
// current value
-println(mySquare.sideLength) // 4
+print(mySquare.sideLength) // 4
// change side length using custom !!! operator, increases size by 3
!!!mySquare
-println(mySquare.sideLength) // 12
+print(mySquare.sideLength) // 12
```
diff --git a/tcl.html.markdown b/tcl.html.markdown
index 198f675e..af2911c9 100755..100644
--- a/tcl.html.markdown
+++ b/tcl.html.markdown
@@ -121,7 +121,8 @@ puts lots\nof\n\n\n\n\n\nnewlines
# A word enclosed in braces is not subject to any special interpretation or
-# substitutions, except that a backslash before a brace is not counted when look#ing for the closing brace
+# substitutions, except that a backslash before a brace is not counted when
+# looking for the closing brace
set somevar {
This is a literal $ sign, and this \} escaped
brace remains uninterpreted
@@ -148,6 +149,9 @@ set greeting "Hello, [set {first name}]"
# To promote the words within a word to individual words of the current
# command, use the expansion operator, "{*}".
+```
+
+```tcl
set {*}{name Neo}
# is equivalent to
@@ -163,7 +167,7 @@ set greeting "Hello, $person(name)"
# A namespace holds commands and variables
namespace eval people {
namespace eval person1 {
- set name Neo
+ variable name Neo
}
}
@@ -189,7 +193,10 @@ set greeting "Hello $people::person1::name"
namespace delete ::
-# Because of name resolution behaviour, it's safer to use the "variable" command to declare or to assign a value to a namespace.
+# Because of name resolution behaviour, it's safer to use the "variable" command to
+# declare or to assign a value to a namespace. If a variable called "name" already
+# exists in the global namespace, using "set" here will assign a value to the global variable
+# instead of creating a new variable in the local namespace.
namespace eval people {
namespace eval person1 {
variable name Neo
@@ -256,7 +263,7 @@ proc greet greeting\ name return\ \"Hello,\ \$name!
proc fold {cmd args} {
set res 0
foreach arg $args {
- set res [cmd $res $arg]
+ set res [$cmd $res $arg]
}
}
fold ::tcl::mathop::* 5 3 3 ;# -> 45
diff --git a/tr-tr/csharp-tr.html.markdown b/tr-tr/csharp-tr.html.markdown
index 7755ed44..a68026a5 100644
--- a/tr-tr/csharp-tr.html.markdown
+++ b/tr-tr/csharp-tr.html.markdown
@@ -8,7 +8,7 @@ contributors:
translators:
- ["Melih Mucuk", "http://melihmucuk.com"]
lang: tr-tr
-filename: LearnCSharp.cs
+filename: LearnCSharp-tr.cs
---
diff --git a/tr-tr/swift-tr.html.markdown b/tr-tr/swift-tr.html.markdown
new file mode 100644
index 00000000..41835e13
--- /dev/null
+++ b/tr-tr/swift-tr.html.markdown
@@ -0,0 +1,590 @@
+---
+language: swift
+contributors:
+ - ["Özgür Şahin", "https://github.com/ozgurshn/"]
+filename: learnswift.swift
+---
+
+Swift iOS ve OSX platformlarında geliştirme yapmak için Apple tarafından oluşturulan yeni bir programlama dilidir. Objective - C ile beraber kullanılabilecek ve de hatalı kodlara karşı daha esnek bir yapı sunacak bir şekilde tasarlanmıştır. Swift 2014 yılında Apple'ın geliştirici konferansı WWDC de tanıtıldı. Xcode 6+'a dahil edilen LLVM derleyici ile geliştirildi.
+
+The official [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) book from Apple is now available via iBooks.
+
+Apple'ın resmi [Swift Programlama Dili](https://itunes.apple.com/us/book/swift-programming-language/id881256329) kitabı iBooks'ta yerini aldı.
+
+See also Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html), which has a complete tutorial on Swift.
+
+Ayrıca Swift ile gelen tüm özellikleri görmek için Apple'ın [başlangıç kılavuzu](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html)na bakmanızda yarar var.
+
+
+
+```swift
+// modülü import etme
+import UIKit
+
+//
+// MARK: Temeller
+//
+
+
+//XCode işaretlemelerle kodunuzu bölümlere ayırmanızı ve sağ üstteki metot
+ listesinde gruplama yapmanıza olanak sağlıyor
+// MARK: Bölüm işareti
+// TODO: Daha sonra yapılacak
+// FIXME: Bu kodu düzelt
+
+
+//Swift 2 de, println ve print metotları print komutunda birleştirildi. Print
+ otomatik olarak yeni satır ekliyor.
+print("Merhaba dünya") // println print olarak kullanılıyor.
+print("Merhaba dünya", appendNewLine: false) // yeni bir satır eklemeden yazar.
+
+// variables (var) değer atandıktan sonra değiştirilebilir.
+// constants (let) değer atndıktan sonra değiştirilemez.
+
+var degiskenim = 42
+let øπΩ = "deger" // unicode degişken adları
+let π = 3.1415926
+let convenience = "keyword" // bağlamsal değişken adı
+let isim = "ahmet"; let soyad = "un" // farklı ifadeler noktalı virgül
+kullanılarak ayrılabilir.
+let `class` = "keyword" // rezerve edilmiş keywordler tek tırnak içerisine
+alınarak değişken adı olarak kullanılabilir
+let doubleOlduguBelli: Double = 70
+let intDegisken = 0007 // 7
+let largeIntDegisken = 77_000 // 77000
+let etiket = "birseyler " + String(degiskenim) // Cast etme
+let piYazi = "Pi = \(π), Pi 2 = \(π * 2)" // String içerisine değiken yazdırma
+
+
+// Builde özel değişkenler
+// -D build ayarını kullanır.
+#if false
+ print("yazılmadı")
+ let buildDegiskeni= 3
+#else
+ let buildDegiskeni = 7
+#endif
+print("Build degiskeni: \(buildDegiskeni)") // Build degeri: 7
+
+/*
+ Optionals Swift dilinde bazı değerleri veya yokluğu (None) bir değişkende
+ tutmanıza olanak sağlar.
+
+ Swift'te her bir degişkeninin bir değeri olması gerektiğinden, nil değeri
+ bile Optional değer olarak saklanır.
+
+ Optional<T> bir enum'dır.
+*/
+var baziOptionalString: String? = "optional" // nil olabilir.
+// yukarıdakiyle aynı ama ? bir postfix (sona eklenir) operatördür. (kolay
+okunabilir)
+var someOptionalString2: Optional<String> = "optional"
+
+
+if baziOptionalString != nil {
+ // ben nil değilim
+ if baziOptionalString!.hasPrefix("opt") {
+ print("ön eki var")
+ }
+
+ let bos = baziOptionalString?.isEmpty
+}
+baziOptionalString = nil
+
+// belirgin olarak acilan(unwrap) opsiyonel (optional) değer
+var acilanString: String! = "Değer bekleniliyor"
+//yukarıdakiyle aynı ama ! bir postfix operatördür (kolay okunabilir)
+var acilanString2: ImplicitlyUnwrappedOptional<String> = "Değer bekleniliyor."
+
+if let baziOpsiyonelSabitString = baziOptionalString {
+ // eğer bir değeri varsa, nil değilse
+ if ! baziOpsiyonelSabitString("tamam") {
+ // ön eke sahip değil
+ }
+}
+
+// Swift değişkenlerde herhangi bir tip saklanabilir.
+// AnyObject == id
+// Objective-C deki `id` den farklı olarak, AnyObject tüm değişkenlerle
+ çalışabilir (Class, Int, struct, etc)
+var herhangiBirObject: AnyObject = 7
+herhangiBirObject = "Değer string olarak değişti, iyi bir yöntem değil ama mümkün"
+
+/*
+ Yorumlar buraya
+
+ /*
+ İç içe yorum yazılması da mümkün
+ */
+*/
+
+//
+// MARK: Koleksiyonlar
+//
+
+/*
+ Array ve Dictionary tipleri aslında structdırlar. Bu yüzden `let` ve `var`
+ ayrıca bu tipleri tanımlarken değişebilir(var) veya değişemez(let)
+ olduğunu belirtir.
+
+*/
+
+// Diziler
+var liste = ["balik", "su", "limon"]
+liste[1] = "şişe su"
+let bosDizi = [String]() // let == değiştirilemez
+let bosDizi2 = Array<String>() // yukarıdakiyle aynı
+var bosDegistirilebilirDizi = [String]() // var == değişebilir
+
+
+// Dictionary
+var meslekler = [
+ "Kamil": "Kaptan",
+ "Ayse": "Analist"
+]
+meslekler["Cansu"] = "Halkla İlişkiler"
+let bosDictionary = [String: Float]() // let == değiştirilemez
+let bosDictionary2 = Dictionary<String, Float>() // yukarıdakiyle aynı
+var bosDegistirilebirDictionary = [String: Float]() // var == değiştirilebilir
+
+
+//
+// MARK: Kontroller
+//
+
+// for döngüsü (dizi)
+let dizi = [1, 1, 2, 3, 5]
+for deger in dizi {
+ if deger == 1 {
+ print("Bir!")
+ } else {
+ print("Bir degil!")
+ }
+}
+
+// for döngüsü (dictionary)
+var dict = ["one": 1, "two": 2]
+for (key, value) in dict {
+ print("\(key): \(value)")
+}
+
+// for döngüsü (aralık)
+for i in -1...liste.count {
+ print(i)
+}
+liste[1...2] = ["et", "yogurt"]
+// ..< kullanarak son elemanı çıkartabilirsiniz
+
+// while döngüsü
+var i = 1
+while i < 1000 {
+ i *= 2
+}
+
+// do-while döngüsü
+do {
+ print("merhaba")
+} while 1 == 2
+
+// Switch
+// Çok güçlü, `if` ifadesenin daha kolay okunabilir hali olarak düşünün
+// String, object örnekleri, ve primitif tipleri (Int, Double, vs) destekler.
+let sebze = "kırmızı biber"
+switch sebze {
+case "sogan":
+ let sebzeYorumu = "Biraz da domates ekle"
+case "domates", "salata":
+ let sebzeYorumu = "İyi bir sandviç olur"
+case let lokalScopeDegeri where lokalScopeDegeri.hasSuffix("biber"):
+ let sebzeYorumu = "Acı bir \(lokalScopeDegeri)?"
+default: // zorunludur (tüm olasılıkları yakalamak icin)
+ let sebzeYorumu = "Corbadaki herseyin tadı güzel"
+}
+
+
+//
+// MARK: Fonksiyonlar
+//
+
+// Fonksiyonlar first-class tiplerdir, yani başka fonksiyon içine konabilir
+// ve parametre olarak geçirilebilirler.
+
+// Swift dökümanlarıylaa birlikte Fonksiyonlar (format as reStructedText)
+
+/**
+ selamlama işlemi
+
+ :param: isim e isim
+ :param: gun e A gun
+ :returns: isim ve gunu iceren bir String
+*/
+func selam(isim: String, gun: String) -> String {
+ return "Merhaba \(isim), bugün \(gun)."
+}
+selam("Can", "Salı")
+
+// fonksiyon parametre davranışı hariç yukarıdakine benzer
+func selam2(#gerekliIsim: String, disParametreIsmi lokalParamtreIsmi: String) -> String {
+ return "Merhaba \(gerekliIsim), bugün \(lokalParamtreIsmi)"
+}
+selam2(gerekliIsim:"Can", disParametreIsmi: "Salı")
+
+// Bir tuple ile birden fazla deger dönen fonksiyon
+func fiyatlariGetir() -> (Double, Double, Double) {
+ return (3.59, 3.69, 3.79)
+}
+let fiyatTuple = fiyatlariGetir()
+let fiyat = fiyatTuple.2 // 3.79
+// _ (alt çizgi) kullanımı Tuple degerlerini veya diğer değerleri görmezden
+gelir
+let (_, fiyat1, _) = fiyatTuple // fiyat1 == 3.69
+print(fiyat1 == fiyatTuple.1) // true
+print("Benzin fiyatı: \(fiyat)")
+
+// Çeşitli Argümanlar
+func ayarla(sayilar: Int...) {
+ // its an array
+ let sayi = sayilar[0]
+ let argumanSAyisi = sayilar.count
+}
+
+// fonksiyonu parametre olarak geçirme veya döndürme
+func arttirmaIslemi() -> (Int -> Int) {
+ func birEkle(sayi: Int) -> Int {
+ return 1 + sayi
+ }
+ return birEkle
+}
+var arttir = arttirmaIslemi()
+arttir(7)
+
+// referans geçirme
+func yerDegistir(inout a: Int, inout b: Int) {
+ let tempA = a
+ a = b
+ b = tempA
+}
+var someIntA = 7
+var someIntB = 3
+yerDegistir(&someIntA, &someIntB)
+print(someIntB) // 7
+
+
+//
+// MARK: Closurelar
+//
+var sayilar = [1, 2, 6]
+
+// Fonksiyonlar özelleştirilmiş closurelardır. ({})
+
+// Closure örneği.
+// `->` parametrelerle dönüş tipini birbirinden ayırır
+// `in` closure başlığını closure bodysinden ayırır.
+sayilar.map({
+ (sayi: Int) -> Int in
+ let sonuc = 3 * sayi
+ return sonuc
+})
+
+// eger tip biliniyorsa, yukarıdaki gibi, şöyle yapabiliriz
+sayilar = sayilar.map({ sayi in 3 * sayi })
+// Hatta bunu
+//sayilar = sayilar.map({ $0 * 3 })
+
+print(sayilar) // [3, 6, 18]
+
+// Trailing closure
+sayilar = sorted(sayilar) { $0 > $1 }
+
+print(sayilar) // [18, 6, 3]
+
+// Super kısa hali ise, < operatörü tipleri çıkartabildiği için
+
+sayilar = sorted(sayilar, < )
+
+print(sayilar) // [3, 6, 18]
+
+//
+// MARK: Yapılar
+//
+
+// Structurelar ve sınıflar birçok aynı özelliğe sahiptir.
+struct IsimTablosu {
+ let isimler = [String]()
+
+ // Özelleştirilmiş dizi erişimi
+ subscript(index: Int) -> String {
+ return isimler[index]
+ }
+}
+
+// Structurelar otomatik oluşturulmuş kurucu metoda sahiptir.
+let isimTablosu = IsimTablosu(isimler: ["Ben", "Onlar"])
+let isim = isimTablosu[1]
+print("İsim \(name)") // İsim Onlar
+
+//
+// MARK: Sınıflar
+//
+
+// Sınıflar, structurelar ve üyeleri 3 seviye erişime sahiptir.
+// Bunlar: internal (default), public, private
+
+public class Sekil {
+ public func alaniGetir() -> Int {
+ return 0;
+ }
+}
+
+// Sınıfın tüm değişkenleri ve metotları publictir.
+// Eğer sadece veriyi yapılandırılmış bir objede
+// saklamak istiyorsanız, `struct` kullanmalısınız.
+
+internal class Rect: Sekil {
+ var yanUzunluk: Int = 1
+
+ // Özelleştirilmiş getter ve setter propertyleri
+ private var cevre: Int {
+ get {
+ return 4 * yanUzunluk
+ }
+ set {
+ // `newValue ` setterlarda yeni değere erişimi sağlar
+ yanUzunluk = newValue / 4
+ }
+ }
+
+ // Bir değişkene geç atama(lazy load) yapmak
+ // altSekil getter cağrılana dek nil (oluşturulmamış) olarak kalır
+ lazy var altSekil = Rect(yanUzunluk: 4)
+
+ // Eğer özelleştirilmiş getter ve setter a ihtiyacınız yoksa,
+ // ama bir değişkene get veya set yapıldıktan sonra bir işlem yapmak
+ // istiyorsanız, `willSet` ve `didSet` metotlarını kullanabilirsiniz
+ var identifier: String = "defaultID" {
+ // `willSet` argümanı yeni değer için değişkenin adı olacaktır.
+ willSet(someIdentifier) {
+ print(someIdentifier)
+ }
+ }
+
+ init(yanUzunluk: Int) {
+ self. yanUzunluk = yanUzunluk
+ // super.init i her zaman özelleştirilmiş değerleri oluşturduktan sonra
+ çağırın
+ super.init()
+ }
+
+ func kisalt() {
+ if yanUzunluk > 0 {
+ --yanUzunluk
+ }
+ }
+
+ override func alaniGetir() -> Int {
+ return yanUzunluk * yanUzunluk
+ }
+}
+
+// Basit `Kare` sınıfI `Rect` sınıfını extend ediyor.
+class Kare: Rect {
+ convenience init() {
+ self.init(yanUzunluk: 5)
+ }
+}
+
+var benimKarem = Kare()
+print(m benimKarem.alaniGetir()) // 25
+benimKarem.kisalt()
+print(benimKarem.yanUzunluk) // 4
+
+// sınıf örneğini cast etme
+let birSekil = benimKarem as Sekil
+
+// örnekleri karşılaştır, objeleri karşılaştıran == (equal to) ile aynı değil
+if benimKarem === benimKarem {
+ print("Evet, bu benimKarem")
+}
+
+// Opsiyonel init
+class Daire: Sekil {
+ var yaricap: Int
+ override func alaniGetir() -> Int {
+ return 3 * yaricap * yaricap
+ }
+
+ // Eğer init opsiyonelse (nil dönebilir) `init` den sonra soru işareti
+ // son eki ekle.
+ init?(yaricap: Int) {
+ self.yaricap = yaricap
+ super.init()
+
+ if yaricap <= 0 {
+ return nil
+ }
+ }
+}
+
+var benimDairem = Daire(radius: 1)
+print(benimDairem?.alaniGetir()) // Optional(3)
+print(benimDairem!. alaniGetir()) // 3
+var benimBosDairem = Daire(yaricap: -1)
+print(benimBosDairem?. alaniGetir()) // "nil"
+if let daire = benimBosDairem {
+ // benimBosDairem nil olduğu için çalışmayacak
+ print("circle is not nil")
+}
+
+
+//
+// MARK: Enumlar
+//
+
+// Enumlar opsiyonel olarak özel bir tip veya kendi tiplerinde olabilirler.
+// Sınıflar gibi metotlar içerebilirler.
+
+enum Kart {
+ case Kupa, Maca, Sinek, Karo
+ func getIcon() -> String {
+ switch self {
+ case .Maca: return "♤"
+ case .Kupa: return "♡"
+ case .Karo: return "♢"
+ case .Sinek: return "♧"
+ }
+ }
+}
+
+// Enum değerleri kısayol syntaxa izin verir. Eğer değişken tipi açık olarak belirtildiyse enum tipini yazmaya gerek kalmaz.
+var kartTipi: Kart = .Kupa
+
+// Integer olmayan enumlar direk değer (rawValue) atama gerektirir.
+enum KitapAdi: String {
+ case John = "John"
+ case Luke = "Luke"
+}
+print("Name: \(KitapAdi.John.rawValue)")
+
+// Değerlerle ilişkilendirilmiş Enum
+enum Mobilya {
+ // Int ile ilişkilendirilmiş
+ case Masa(yukseklik: Int)
+ // String ve Int ile ilişkilendirilmiş
+ case Sandalye(String, Int)
+
+ func aciklama() -> String {
+ switch self {
+ case .Masa(let yukseklik):
+ return "Masa boyu \(yukseklik) cm"
+ case .Sandalye(let marka, let yukseklik):
+ return "\(brand) marka sandalyenin boyu \(yukseklik) cm"
+ }
+ }
+}
+
+var masa: Mobilya = .Masa(yukseklik: 80)
+print(masa.aciklama()) // "Masa boyu 80 cm"
+var sandalye = Mobilya.Sandalye("Foo", 40)
+print(sandalye.aciklama()) // "Foo marka sandalyenin boyu 40 cm"
+
+
+//
+// MARK: Protokoller
+//
+
+// `protocol` onu kullanan tiplerin bazı özel değişkenleri, metotları,
+// tip metotlarını,opertörleri ve alt indisleri (subscripts) içermesini
+// zorunlu hale getirebilir.
+
+protocol SekilUretici {
+ var aktif: Bool { get set }
+ func sekilOlustur() -> Sekil
+}
+
+// @objc ile tanımlanan protokoller, uygunluğu kontrol edebilmenizi sağlayacak
+// şekilde opsiyonel fonksiyonlara izin verir
+@objc protocol SekliDondur {
+ optional func sekillendirilmis()
+ optional func sekillendirilebilir() -> Bool
+}
+
+class BenimSeklim: Rect {
+ var delegate: SekliDondur?
+
+ func buyut() {
+ yanUzlunluk += 2
+
+ // Bir çalışma zamanı hatası("optional chaining") fırlatmak yerine nil
+ //değeri görmezden gelerek nil dönmek için opsiyonel değişken, metot veya
+ // altindisten sonra soru işareti koyabilirsiniz.
+ if let izinVeriyormu = self.delegate?.sekillendirilebilir?() {
+ // önce delegate i sonra metodu test edin
+ self.delegate?.sekillendirilmis?()
+ }
+ }
+}
+
+
+//
+// MARK: Diğerleri
+//
+
+// `extension`lar: Var olan tiplere ekstra özellikler ekleyin
+
+// Kare artık `Printable` protokolüne uyuyor.
+extension Kare: Printable {
+ var description: String {
+ return "Alan: \(alaniGetir()) - ID: \(self.identifier)"
+ }
+}
+
+print("Kare: \(benimKarem)")
+
+// Dahili tipleri de yeni özellikler ekleyebilirsiniz
+extension Int {
+ var customProperty: String {
+ return "Bu sayı \(self)"
+ }
+
+ func carp(num: Int) -> Int {
+ return num * self
+ }
+}
+
+print(7.customProperty) // "Bu sayı 7"
+print(14.carp(3)) // 42
+
+// Genericler: Java ve C#'a benzer şekilde. `where` anahtar kelimesini
+// kullanarak genericlerin özelliklerini belirleyin
+
+func indexiBul<T: Equatable>(dizi: [T], bulunacakDeger: T) -> Int? {
+ for (index, deger) in enumerate(dizi) {
+ if deger == bulunacakDeger {
+ return index
+ }
+ }
+ return nil
+}
+let bulunanIndex = indexiBul([1, 2, 3, 4], 3)
+print(bulunanIndex == 2) // true
+
+// Operatorler:
+// Özel operatorler şu karakterlerle başlayabilir:
+// / = - + * % < > ! & | ^ . ~
+// veya
+// Unicode math, symbol, arrow, dingbat, ve line/box karakterleri.
+prefix operator !!! {}
+
+// Yan uzunluğu 3 katına çıkartan prefix operatörü
+prefix func !!! (inout sekil: Kare) -> Kare {
+ sekil.YanUzunluk *= 3
+ return sekil
+}
+
+// güncel deger
+print(benimKarem.YanUzunluk) // 4
+
+// yan uzunluğu !!! operatorü kullanarak 3 katına çıkar
+!!!benimKarem
+print(benimKarem.YanUzunluk) // 12
+```
diff --git a/visualbasic.html.markdown b/visualbasic.html.markdown
index fbfa500d..00d61843 100644
--- a/visualbasic.html.markdown
+++ b/visualbasic.html.markdown
@@ -159,7 +159,7 @@ Module Module1
Console.Write(a.ToString() + " - " + b.ToString())
Console.WriteLine(" = " + e.ToString.PadLeft(3))
Console.Write(a.ToString() + " / " + b.ToString())
- Console.WriteLine(" = " + e.ToString.PadLeft(3))
+ Console.WriteLine(" = " + f.ToString.PadLeft(3))
Console.ReadLine()
End Sub
@@ -189,7 +189,7 @@ Module Module1
Console.Write(a.ToString() + " - " + b.ToString())
Console.WriteLine(" = " + e.ToString.PadLeft(3))
Console.Write(a.ToString() + " / " + b.ToString())
- Console.WriteLine(" = " + e.ToString.PadLeft(3))
+ Console.WriteLine(" = " + f.ToString.PadLeft(3))
Console.ReadLine()
'Ask the question, does the user wish to continue? Unfortunately it
'is case sensitive.
diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown
index 558d9110..d85e5b8f 100644
--- a/zh-cn/bash-cn.html.markdown
+++ b/zh-cn/bash-cn.html.markdown
@@ -258,7 +258,7 @@ help return
help source
help .
-# 用 mam 指令阅读相关的 Bash 手册
+# 用 man 指令阅读相关的 Bash 手册
apropos bash
man 1 bash
man bash
diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown
index 9f6a8c15..49224085 100644
--- a/zh-cn/go-cn.html.markdown
+++ b/zh-cn/go-cn.html.markdown
@@ -239,7 +239,7 @@ func learnConcurrency() {
go inc(0, c) // go is a statement that starts a new goroutine.
go inc(10, c)
go inc(-805, c)
- // 从channel中独处结果并打印。
+ // 从channel中读取结果并打印。
// 打印出什么东西是不可预知的。
fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是读操作。
@@ -283,4 +283,4 @@ Go的根源在[Go官方网站](http://golang.org/)。
强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.)
-学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了!
+学习Go还要阅读Go[标准库的源代码](http://golang.org/src/),全部文档化了,可读性非常好,可以学到go,go style和go idioms。在[文档](http://golang.org/pkg/)中点击函数名,源代码就出来了!
diff --git a/zh-cn/groovy-cn.html.markdown b/zh-cn/groovy-cn.html.markdown
new file mode 100644
index 00000000..562a0284
--- /dev/null
+++ b/zh-cn/groovy-cn.html.markdown
@@ -0,0 +1,420 @@
+---
+language: Groovy
+filename: learngroovy-cn.groovy
+contributors:
+ - ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
+translators:
+ - ["Todd Gao", "http://github.com/7c00"]
+lang: zh-cn
+---
+
+Groovy - Java平台的动态语言。[了解更多。](http://www.groovy-lang.org/)
+
+```groovy
+
+/*
+ 安装:
+
+ 1) 安装 GVM - http://gvmtool.net/
+ 2) 安装 Groovy: gvm install groovy
+ 3) 启动 groovy 控制台,键入: groovyConsole
+
+*/
+
+// 双斜线开始的是单行注释
+/*
+像这样的是多行注释
+*/
+
+// Hello World
+println "Hello world!"
+
+/*
+ 变量:
+
+ 可以给变量赋值,以便稍后使用
+*/
+
+def x = 1
+println x
+
+x = new java.util.Date()
+println x
+
+x = -3.1499392
+println x
+
+x = false
+println x
+
+x = "Groovy!"
+println x
+
+/*
+ 集合和映射
+*/
+
+//创建一个空的列表
+def technologies = []
+
+/*** 往列表中增加一个元素 ***/
+
+// 和Java一样
+technologies.add("Grails")
+
+// 左移添加,返回该列表
+technologies << "Groovy"
+
+// 增加多个元素
+technologies.addAll(["Gradle","Griffon"])
+
+/*** 从列表中删除元素 ***/
+
+// 和Java一样
+technologies.remove("Griffon")
+
+// 减号也行
+technologies = technologies - 'Grails'
+
+/*** 遍历列表 ***/
+
+// 遍历列表中的元素
+technologies.each { println "Technology: $it"}
+technologies.eachWithIndex { it, i -> println "$i: $it"}
+
+/*** 检查列表内容 ***/
+
+//判断列表是否包含某元素,返回boolean
+contained = technologies.contains( 'Groovy' )
+
+// 或
+contained = 'Groovy' in technologies
+
+// 检查多个元素
+technologies.containsAll(['Groovy','Grails'])
+
+/*** 列表排序 ***/
+
+// 排序列表(修改原列表)
+technologies.sort()
+
+// 要想不修改原列表,可以这样:
+sortedTechnologies = technologies.sort( false )
+
+/*** 列表操作 ***/
+
+//替换列表元素
+Collections.replaceAll(technologies, 'Gradle', 'gradle')
+
+//打乱列表
+Collections.shuffle(technologies, new Random())
+
+//清空列表
+technologies.clear()
+
+//创建空的映射
+def devMap = [:]
+
+//增加值
+devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
+devMap.put('lastName','Perez')
+
+//遍历映射元素
+devMap.each { println "$it.key: $it.value" }
+devMap.eachWithIndex { it, i -> println "$i: $it"}
+
+//判断映射是否包含某键
+assert devMap.containsKey('name')
+
+//判断映射是否包含某值
+assert devMap.containsValue('Roberto')
+
+//取得映射所有的键
+println devMap.keySet()
+
+//取得映射所有的值
+println devMap.values()
+
+/*
+ Groovy Beans
+
+ GroovyBeans 是 JavaBeans,但使用了更简单的语法
+
+ Groovy 被编译为字节码时,遵循下列规则。
+
+ * 如果一个名字声明时带有访问修饰符(public, private, 或者 protected),
+ 则会生成一个字段(field)。
+
+ * 名字声明时没有访问修饰符,则会生成一个带有public getter和setter的
+ private字段,即属性(property)。
+
+ * 如果一个属性声明为final,则会创建一个final的private字段,但不会生成setter。
+
+ * 可以声明一个属性的同时定义自己的getter和setter。
+
+ * 可以声明具有相同名字的属性和字段,该属性会使用该字段。
+
+ * 如果要定义private或protected属性,必须提供声明为private或protected的getter
+ 和setter。
+
+ * 如果使用显式或隐式的 this(例如 this.foo, 或者 foo)访问类的在编译时定义的属性,
+ Groovy会直接访问对应字段,而不是使用getter或者setter
+
+ * 如果使用显式或隐式的 foo 访问一个不存在的属性,Groovy会通过元类(meta class)
+ 访问它,这可能导致运行时错误。
+
+*/
+
+class Foo {
+ // 只读属性
+ final String name = "Roberto"
+
+ // 只读属性,有public getter和protected setter
+ String language
+ protected void setLanguage(String language) { this.language = language }
+
+ // 动态类型属性
+ def lastName
+}
+
+/*
+ 逻辑分支和循环
+*/
+
+//Groovy支持常见的if - else语法
+def x = 3
+
+if(x==1) {
+ println "One"
+} else if(x==2) {
+ println "Two"
+} else {
+ println "X greater than Two"
+}
+
+//Groovy也支持三元运算符
+def y = 10
+def x = (y > 1) ? "worked" : "failed"
+assert x == "worked"
+
+//for循环
+//使用区间(range)遍历
+def x = 0
+for (i in 0 .. 30) {
+ x += i
+}
+
+//遍历列表
+x = 0
+for( i in [5,3,2,1] ) {
+ x += i
+}
+
+//遍历数组
+array = (0..20).toArray()
+x = 0
+for (i in array) {
+ x += i
+}
+
+//遍历映射
+def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy']
+x = 0
+for ( e in map ) {
+ x += e.value
+}
+
+/*
+ 运算符
+
+ 在Groovy中以下常用运算符支持重载:
+ http://www.groovy-lang.org/operators.html#Operator-Overloading
+
+ 实用的groovy运算符
+*/
+//展开(spread)运算符:对聚合对象的所有元素施加操作
+def technologies = ['Groovy','Grails','Gradle']
+technologies*.toUpperCase() // 相当于 technologies.collect { it?.toUpperCase() }
+
+//安全导航(safe navigation)运算符:用来避免NullPointerException
+def user = User.get(1)
+def username = user?.username
+
+
+/*
+ 闭包
+ Groovy闭包好比代码块或者方法指针,它是一段代码定义,可以以后执行。
+
+ 更多信息见:http://www.groovy-lang.org/closures.html
+*/
+//例子:
+def clos = { println "Hello World!" }
+
+println "Executing the Closure:"
+clos()
+
+//传参数给闭包
+def sum = { a, b -> println a+b }
+sum(2,4)
+
+//闭包可以引用参数列表以外的变量
+def x = 5
+def multiplyBy = { num -> num * x }
+println multiplyBy(10)
+
+// 只有一个参数的闭包可以省略参数的定义
+def clos = { print it }
+clos( "hi" )
+
+/*
+ Groovy可以记忆闭包结果 [1][2][3]
+*/
+def cl = {a, b ->
+ sleep(3000) // 模拟费时操作
+ a + b
+}
+
+mem = cl.memoize()
+
+def callClosure(a, b) {
+ def start = System.currentTimeMillis()
+ mem(a, b)
+ println "Inputs(a = $a, b = $b) - took ${System.currentTimeMillis() - start} msecs."
+}
+
+callClosure(1, 2)
+callClosure(1, 2)
+callClosure(2, 3)
+callClosure(2, 3)
+callClosure(3, 4)
+callClosure(3, 4)
+callClosure(1, 2)
+callClosure(2, 3)
+callClosure(3, 4)
+
+/*
+ Expando
+
+ Expando类是一种动态bean类,可以给它的实例添加属性和添加闭包作为方法
+
+ http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html
+*/
+ def user = new Expando(name:"Roberto")
+ assert 'Roberto' == user.name
+
+ user.lastName = 'Pérez'
+ assert 'Pérez' == user.lastName
+
+ user.showInfo = { out ->
+ out << "Name: $name"
+ out << ", Last name: $lastName"
+ }
+
+ def sw = new StringWriter()
+ println user.showInfo(sw)
+
+
+/*
+ 元编程(MOP)
+*/
+
+//使用ExpandoMetaClass增加行为
+String.metaClass.testAdd = {
+ println "we added this"
+}
+
+String x = "test"
+x?.testAdd()
+
+//拦截方法调用
+class Test implements GroovyInterceptable {
+ def sum(Integer x, Integer y) { x + y }
+
+ def invokeMethod(String name, args) {
+ System.out.println "Invoke method $name with args: $args"
+ }
+}
+
+def test = new Test()
+test?.sum(2,3)
+test?.multiply(2,3)
+
+//Groovy支持propertyMissing,来处理属性解析尝试
+class Foo {
+ def propertyMissing(String name) { name }
+}
+def f = new Foo()
+
+assertEquals "boo", f.boo
+
+/*
+ 类型检查和静态编译
+ Groovy天生是并将永远是一门动态语言,但也支持类型检查和静态编译
+
+ 更多: http://www.infoq.com/articles/new-groovy-20
+*/
+//类型检查
+import groovy.transform.TypeChecked
+
+void testMethod() {}
+
+@TypeChecked
+void test() {
+ testMeethod()
+
+ def name = "Roberto"
+
+ println naameee
+
+}
+
+//另一例子
+import groovy.transform.TypeChecked
+
+@TypeChecked
+Integer test() {
+ Integer num = "1"
+
+ Integer[] numbers = [1,2,3,4]
+
+ Date date = numbers[1]
+
+ return "Test"
+
+}
+
+//静态编译例子
+import groovy.transform.CompileStatic
+
+@CompileStatic
+int sum(int x, int y) {
+ x + y
+}
+
+assert sum(2,5) == 7
+
+
+```
+
+## 进阶资源
+
+[Groovy文档](http://www.groovy-lang.org/documentation.html)
+
+[Groovy web console](http://groovyconsole.appspot.com/)
+
+加入[Groovy用户组](http://www.groovy-lang.org/usergroups.html)
+
+## 图书
+
+* [Groovy Goodness] (https://leanpub.com/groovy-goodness-notebook)
+
+* [Groovy in Action] (http://manning.com/koenig2/)
+
+* [Programming Groovy 2: Dynamic Productivity for the Java Developer] (http://shop.oreilly.com/product/9781937785307.do)
+
+[1] http://roshandawrani.wordpress.com/2010/10/18/groovy-new-feature-closures-can-now-memorize-their-results/
+[2] http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize
+[3] http://mrhaki.blogspot.mx/2011/05/groovy-goodness-cache-closure-results.html
+
+
+
diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown
index f08d3507..12afa59a 100644
--- a/zh-cn/java-cn.html.markdown
+++ b/zh-cn/java-cn.html.markdown
@@ -149,7 +149,7 @@ public class LearnJava {
// 位运算操作符
/*
- ~ 补
+ ~ 取反,求反码
<< 带符号左移
>> 带符号右移
>>> 无符号右移
diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown
index b450ab84..dfeb2012 100644
--- a/zh-cn/javascript-cn.html.markdown
+++ b/zh-cn/javascript-cn.html.markdown
@@ -402,7 +402,7 @@ myObj.meaningOfLife; // = 42
// 函数也可以工作。
myObj.myFunc() // = "hello world!"
-// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型,以此类堆。
+// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型,以此类推。
myPrototype.__proto__ = {
myBoolean: true
};
diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown
index b1143dac..b633714d 100644
--- a/zh-cn/markdown-cn.html.markdown
+++ b/zh-cn/markdown-cn.html.markdown
@@ -69,7 +69,7 @@ __此文本也是__
<!-- 如果你插入一个 HTML中的<br />标签,你可以在段末加入两个以上的空格,
然后另起一段。-->
-此段落结尾有两个空格(选中以显示)。
+此段落结尾有两个空格(选中以显示)。
上文有一个 <br /> !
diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown
index 99250b43..14d38137 100644
--- a/zh-cn/ruby-cn.html.markdown
+++ b/zh-cn/ruby-cn.html.markdown
@@ -7,6 +7,7 @@ contributors:
- ["Joel Walden", "http://joelwalden.net"]
- ["Luke Holder", "http://twitter.com/lukeholder"]
- ["lidashuang", "https://github.com/lidashuang"]
+ - ["ftwbzhao", "https://github.com/ftwbzhao"]
translators:
- ["Lin Xiangyu", "https://github.com/oa414"]
---
@@ -120,11 +121,11 @@ status == :approved #=> false
# 数组
# 这是一个数组
-[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
+array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# 数组可以包含不同类型的元素
-array = [1, "hello", false] #=> => [1, "hello", false]
+[1, "hello", false] #=> [1, "hello", false]
# 数组可以被索引
# 从前面开始
@@ -140,8 +141,8 @@ array.[] 12 #=> nil
# 从尾部开始
array[-1] #=> 5
-# 同时指定开始的位置和结束的位置
-array[2, 4] #=> [3, 4, 5]
+# 同时指定开始的位置和长度
+array[2, 3] #=> [3, 4, 5]
# 或者指定一个范围
array[1..3] #=> [2, 3, 4]
diff --git a/zh-cn/rust-cn.html.markdown b/zh-cn/rust-cn.html.markdown
new file mode 100644
index 00000000..17a897df
--- /dev/null
+++ b/zh-cn/rust-cn.html.markdown
@@ -0,0 +1,296 @@
+---
+language: rust
+contributors:
+ - ["P1start", "http://p1start.github.io/"]
+translators:
+ - ["Guangming Mao", "http://maogm.com"]
+filename: learnrust-cn.rs
+lang: zh-cn
+---
+
+Rust 是由 Mozilla 研究院开发的编程语言。Rust 将底层的性能控制与高级语言的便利性和安全保障结合在了一起。
+
+而 Rust 并不需要一个垃圾回收器或者运行时即可实现这个目的,这使得 Rust 库可以成为一种 C 语言的替代品。
+
+Rust 第一版(0.1 版)发布于 2012 年 1 月,3 年以来一直在紧锣密鼓地迭代。
+因为更新太频繁,一般建议使用每夜构建版而不是稳定版,直到最近 1.0 版本的发布。
+
+2015 年 3 月 15 日,Rust 1.0 发布,完美向后兼容,最新的每夜构建版提供了缩短编译时间等新特性。
+Rust 采用了持续迭代模型,每 6 周一个发布版。Rust 1.1 beta 版在 1.0 发布时同时发布。
+
+尽管 Rust 相对来说是一门底层语言,它提供了一些常见于高级语言的函数式编程的特性。这让 Rust 不仅高效,并且易用。
+
+```rust
+// 这是注释,单行注释...
+/* ...这是多行注释 */
+
+///////////////
+// 1. 基础 //
+///////////////
+
+// 函数 (Functions)
+// `i32` 是有符号 32 位整数类型(32-bit signed integers)
+fn add2(x: i32, y: i32) -> i32 {
+ // 隐式返回 (不要分号)
+ x + y
+}
+
+// 主函数(Main function)
+fn main() {
+ // 数字 (Numbers) //
+
+ // 不可变绑定
+ let x: i32 = 1;
+
+ // 整形/浮点型数 后缀
+ let y: i32 = 13i32;
+ let f: f64 = 1.3f64;
+
+ // 类型推导
+ // 大部分时间,Rust 编译器会推导变量类型,所以不必把类型显式写出来。
+ // 这个教程里面很多地方都显式写了类型,但是只是为了示范。
+ // 绝大部分时间可以交给类型推导。
+ let implicit_x = 1;
+ let implicit_f = 1.3;
+
+ // 算术运算
+ let sum = x + y + 13;
+
+ // 可变变量
+ let mut mutable = 1;
+ mutable = 4;
+ mutable += 2;
+
+ // 字符串 (Strings) //
+
+ // 字符串字面量
+ let x: &str = "hello world!";
+
+ // 输出
+ println!("{} {}", f, x); // 1.3 hello world
+
+ // 一个 `String` – 在堆上分配空间的字符串
+ let s: String = "hello world".to_string();
+
+ // 字符串分片(slice) - 另一个字符串的不可变视图
+ // 基本上就是指向一个字符串的不可变指针,它不包含字符串里任何内容,只是一个指向某个东西的指针
+ // 比如这里就是 `s`
+ let s_slice: &str = &s;
+
+ println!("{} {}", s, s_slice); // hello world hello world
+
+ // 数组 (Vectors/arrays) //
+
+ // 长度固定的数组 (array)
+ let four_ints: [i32; 4] = [1, 2, 3, 4];
+
+ // 变长数组 (vector)
+ let mut vector: Vec<i32> = vec![1, 2, 3, 4];
+ vector.push(5);
+
+ // 分片 - 某个数组(vector/array)的不可变视图
+ // 和字符串分片基本一样,只不过是针对数组的
+ let slice: &[i32] = &vector;
+
+ // 使用 `{:?}` 按调试样式输出
+ println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
+
+ // 元组 (Tuples) //
+
+ // 元组是固定大小的一组值,可以是不同类型
+ let x: (i32, &str, f64) = (1, "hello", 3.4);
+
+ // 解构 `let`
+ let (a, b, c) = x;
+ println!("{} {} {}", a, b, c); // 1 hello 3.4
+
+ // 索引
+ println!("{}", x.1); // hello
+
+ //////////////
+ // 2. 类型 (Type) //
+ //////////////
+
+ // 结构体(Sturct)
+ struct Point {
+ x: i32,
+ y: i32,
+ }
+
+ let origin: Point = Point { x: 0, y: 0 };
+
+ // 匿名成员结构体,又叫“元组结构体”(‘tuple struct’)
+ struct Point2(i32, i32);
+
+ let origin2 = Point2(0, 0);
+
+ // 基础的 C 风格枚举类型(enum)
+ enum Direction {
+ Left,
+ Right,
+ Up,
+ Down,
+ }
+
+ let up = Direction::Up;
+
+ // 有成员的枚举类型
+ enum OptionalI32 {
+ AnI32(i32),
+ Nothing,
+ }
+
+ let two: OptionalI32 = OptionalI32::AnI32(2);
+ let nothing = OptionalI32::Nothing;
+
+ // 泛型 (Generics) //
+
+ struct Foo<T> { bar: T }
+
+ // 这个在标准库里面有实现,叫 `Option`
+ enum Optional<T> {
+ SomeVal(T),
+ NoVal,
+ }
+
+ // 方法 (Methods) //
+
+ impl<T> Foo<T> {
+ // 方法需要一个显式的 `self` 参数
+ fn get_bar(self) -> T {
+ self.bar
+ }
+ }
+
+ let a_foo = Foo { bar: 1 };
+ println!("{}", a_foo.get_bar()); // 1
+
+ // 接口(Traits) (其他语言里叫 interfaces 或 typeclasses) //
+
+ trait Frobnicate<T> {
+ fn frobnicate(self) -> Option<T>;
+ }
+
+ impl<T> Frobnicate<T> for Foo<T> {
+ fn frobnicate(self) -> Option<T> {
+ Some(self.bar)
+ }
+ }
+
+ let another_foo = Foo { bar: 1 };
+ println!("{:?}", another_foo.frobnicate()); // Some(1)
+
+ ///////////////////////////////////
+ // 3. 模式匹配 (Pattern matching) //
+ ///////////////////////////////////
+
+ let foo = OptionalI32::AnI32(1);
+ match foo {
+ OptionalI32::AnI32(n) => println!("it’s an i32: {}", n),
+ OptionalI32::Nothing => println!("it’s nothing!"),
+ }
+
+ // 高级模式匹配
+ struct FooBar { x: i32, y: OptionalI32 }
+ let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) };
+
+ match bar {
+ FooBar { x: 0, y: OptionalI32::AnI32(0) } =>
+ println!("The numbers are zero!"),
+ FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m =>
+ println!("The numbers are the same"),
+ FooBar { x: n, y: OptionalI32::AnI32(m) } =>
+ println!("Different numbers: {} {}", n, m),
+ FooBar { x: _, y: OptionalI32::Nothing } =>
+ println!("The second number is Nothing!"),
+ }
+
+ ///////////////////////////////
+ // 4. 流程控制 (Control flow) //
+ ///////////////////////////////
+
+ // `for` 循环
+ let array = [1, 2, 3];
+ for i in array.iter() {
+ println!("{}", i);
+ }
+
+ // 区间 (Ranges)
+ for i in 0u32..10 {
+ print!("{} ", i);
+ }
+ println!("");
+ // 输出 `0 1 2 3 4 5 6 7 8 9 `
+
+ // `if`
+ if 1 == 1 {
+ println!("Maths is working!");
+ } else {
+ println!("Oh no...");
+ }
+
+ // `if` 可以当表达式
+ let value = if true {
+ "good"
+ } else {
+ "bad"
+ };
+
+ // `while` 循环
+ while 1 == 1 {
+ println!("The universe is operating normally.");
+ }
+
+ // 无限循环
+ loop {
+ println!("Hello!");
+ }
+
+ ////////////////////////////////////////////////
+ // 5. 内存安全和指针 (Memory safety & pointers) //
+ ////////////////////////////////////////////////
+
+ // 独占指针 (Owned pointer) - 同一时刻只能有一个对象能“拥有”这个指针
+ // 意味着 `Box` 离开他的作用域后,会被安全地释放
+ let mut mine: Box<i32> = Box::new(3);
+ *mine = 5; // 解引用
+ // `now_its_mine` 获取了 `mine` 的所有权。换句话说,`mine` 移动 (move) 了
+ let mut now_its_mine = mine;
+ *now_its_mine += 2;
+
+ println!("{}", now_its_mine); // 7
+ // println!("{}", mine); // 编译报错,因为现在 `now_its_mine` 独占那个指针
+
+ // 引用 (Reference) – 引用其他数据的不可变指针
+ // 当引用指向某个值,我们称为“借用”这个值,因为是被不可变的借用,所以不能被修改,也不能移动
+ // 借用一直持续到生命周期结束,即离开作用域
+ let mut var = 4;
+ var = 3;
+ let ref_var: &i32 = &var;
+
+ println!("{}", var); //不像 `box`, `var` 还可以继续使用
+ println!("{}", *ref_var);
+ // var = 5; // 编译报错,因为 `var` 被借用了
+ // *ref_var = 6; // 编译报错,因为 `ref_var` 是不可变引用
+
+ // 可变引用 (Mutable reference)
+ // 当一个变量被可变地借用时,也不可使用
+ let mut var2 = 4;
+ let ref_var2: &mut i32 = &mut var2;
+ *ref_var2 += 2;
+
+ println!("{}", *ref_var2); // 6
+ // var2 = 2; // 编译报错,因为 `var2` 被借用了
+}
+```
+
+## 更深入的资料
+
+Rust 还有很多很多其他内容 - 这只是 Rust 最基本的功能,帮助你了解 Rust 里面最重要的东西。
+如果想深入学习 Rust,可以去读
+[The Rust Programming Language](http://doc.rust-lang.org/book/index.html)
+或者上 reddit [/r/rust](http://reddit.com/r/rust) 订阅。
+同时 irc.mozilla.org 的 #rust 频道上的小伙伴们也非常欢迎新来的朋友。
+
+你可以在这个在线编译器 [Rust playpen](http://play.rust-lang.org) 上尝试 Rust 的一些特性
+或者上[官方网站](http://rust-lang.org).