summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c++.html.markdown98
-rw-r--r--it-it/rust-it.html.markdown321
-rw-r--r--rust.html.markdown5
-rw-r--r--scala.html.markdown60
-rw-r--r--zh-cn/kotlin-cn.html.markdown346
-rw-r--r--zh-cn/r-cn.html.markdown2
6 files changed, 770 insertions, 62 deletions
diff --git a/c++.html.markdown b/c++.html.markdown
index 290633f3..5dc1af59 100644
--- a/c++.html.markdown
+++ b/c++.html.markdown
@@ -808,8 +808,8 @@ void doSomethingWithAFile(const std::string& filename)
// have default comparators, but you can override it.
class Foo {
public:
- int j;
- Foo(int a) : j(a) {}
+ int j;
+ Foo(int a) : j(a) {}
};
struct compareFunction {
bool operator()(const Foo& a, const Foo& b) const {
@@ -948,7 +948,7 @@ f1 = f2;
#include<tuple>
-// Conceptually, Tuples are similar to old data structures (C-like structs) but instead of having named data members ,
+// Conceptually, Tuples are similar to old data structures (C-like structs) but instead of having named data members,
// its elements are accessed by their order in the tuple.
// We start with constructing a tuple.
@@ -958,10 +958,10 @@ const int maxN = 1e9;
const int maxL = 15;
auto second = make_tuple(maxN, maxL);
-// printing elements of 'first' tuple
+// Printing elements of 'first' tuple
cout << get<0>(first) << " " << get<1>(first) << "\n"; //prints : 10 A
-// printing elements of 'second' tuple
+// Printing elements of 'second' tuple
cout << get<0>(second) << " " << get<1>(second) << "\n"; // prints: 1000000000 15
// Unpacking tuple into variables
@@ -989,43 +989,43 @@ cout << get<5>(concatenated_tuple) << "\n"; // prints: 'A'
/////////////////////
-// CONTAINERS
+// Containers
/////////////////////
-// Containers or the Standard Template Library are some predefined templates
-// They manages the storage space for its elements and provide
-// member functions to access and manipulate them
+// Containers or the Standard Template Library are some predefined templates.
+// They manage the storage space for its elements and provide
+// member functions to access and manipulate them.
-// Few containers are as follows:-
+// Few containers are as follows:
-// Vectors (Dynamic arrays)
+// Vector (Dynamic array)
// Allow us to Define the Array or list of objects at run time
-#include<vector> // will include the header file for vector
-vector< Data_Type > Vector_name; // used to initialize the vector
-cin>>val;
+#include<vector>
+vector<Data_Type> Vector_name; // used to initialize the vector
+cin >> val;
Vector_name.push_back(val); // will push the value of variable into array
-// To iterate through vector, we have 2 choices
-// using normal looping
+// To iterate through vector, we have 2 choices:
+// Normal looping
for(int i=0; i<Vector_name.size(); i++)
// It will iterate through the vector from index '0' till last index
-// Using Iterator
+// Iterator
vector<Data_Type>::iterator it; // initialize the iteartor for vector
for(it=vector_name.begin(); it!=vector_name.end();++it)
// For accessing the element of the vector
// Operator []
-var= vector_name[index]; //will assign value at that index to var
+var = vector_name[index]; // Will assign value at that index to var
// Set
-// Sets are containers that store unique elements following a specific order
-// Very useful container to store unique values in sorted order
-// without any other functions or code
+// Sets are containers that store unique elements following a specific order.
+// Set is a very useful container to store unique values in sorted order
+// without any other functions or code.
-#include<set> // Will include the header file for sets
-set< int > ST; // Will initialize the set of int data type
+#include<set>
+set<int> ST; // Will initialize the set of int data type
ST.insert(30); // Will insert the value 30 in set ST
ST.insert(10); // Will insert the value 10 in set ST
ST.insert(20); // Will insert the value 20 in set ST
@@ -1037,47 +1037,47 @@ ST.insert(30); // Will insert the value 30 in set ST
ST.erase(20); // Will erase element with value 20
// Set ST: 10 30
// To iterate through Set we use iterators
-set< int >::iterator it;
-for(it=ST.begin();it<ST.end();it++)
-{
- cout<<*it<<endl;
+set<int>::iterator it;
+for(it=ST.begin();it<ST.end();it++) {
+ cout << *it << endl;
}
-// OUTPUT:
+// Output:
// 10
// 30
// To clear the complete container we use Container_name.clear()
ST.clear();
-cout<<ST.size(); // will print the size of set ST
-// OUTPUT: 0
+cout << ST.size(); // will print the size of set ST
+// Output: 0
// NOTE: for duplicate elements we can use multiset
-// MAP
+// Map
// Maps store elements formed by a combination of a key value
-// and a mapped value, following a specific order
+// and a mapped value, following a specific order.
-#include<map> // Will include the header file for map
-map< char, int >mymap; // Will initalize the map with key as char and value as int
+#include<map>
+map<char, int> mymap; // Will initalize the map with key as char and value as int
-mymap.insert ( pair<char,int>('A',1) );
+mymap.insert(pair<char,int>('A',1));
// Will insert value 1 for key A
-mymap.insert ( pair<char,int>('Z',26) );
+mymap.insert(pair<char,int>('Z',26));
// Will insert value 26 for key Z
// To iterate
map<char,int>::iterator it;
for (it=mymap.begin(); it!=mymap.end(); ++it)
- std::cout << it->first << "->" << it->second <<'\n';
+ std::cout << it->first << "->" << it->second << '\n';
// Output:
// A->1
// Z->26
// To find the value correponsing to a key
it = mymap.find('Z');
-cout<<it->second;
+cout << it->second;
+
+// Output: 26
-// OUTPUT: 26
///////////////////////////////////
// Logical and Bitwise operators
@@ -1087,17 +1087,17 @@ cout<<it->second;
// Logical operators
-// C++ uses Short - circuit evaluation for boolean expressions, i.e, the second argument is executed or
+// C++ uses Short-circuit evaluation for boolean expressions, i.e, the second argument is executed or
// evaluated only if the first argument does not suffice to determine the value of the expression
true && false // Performs **logical and** to yield false
true || false // Performs **logical or** to yield true
-! true // Performs **logcical not** to yield
+! true // Performs **logical not** to yield false
// Instead of using symbols equivalent keywords can be used
true and false // Performs **logical and** to yield false
-true or false // Performs **logical or** to yield true
-not true // Performs **logcical not** to yield
+true or false // Performs **logical or** to yield true
+not true // Performs **logical not** to yield false
// Bitwise operators
@@ -1108,20 +1108,20 @@ not true // Performs **logcical not** to yield
// **>>** Right Shift Operator
-// << shifts bits to the right
+// >> shifts bits to the right
4 >> 1 // Shifts bits of 4 to right by 1 to give 2
-// x << n can be thought as x / 2^n
+// x >> n can be thought as x / 2^n
-~4 // Performs a bitwise not
+~4 // Performs a bitwise not
4 | 3 // Performs bitwise or
4 & 3 // Performs bitwise and
4 ^ 3 // Performs bitwise xor
// Equivalent keywords are
-compl 4 // Performs a bitwise not
-4 bitor 3 // Performs bitwise or
+compl 4 // Performs a bitwise not
+4 bitor 3 // Performs bitwise or
4 bitand 3 // Performs bitwise and
-4 xor 3 // Performs bitwise xor
+4 xor 3 // Performs bitwise xor
```
diff --git a/it-it/rust-it.html.markdown b/it-it/rust-it.html.markdown
new file mode 100644
index 00000000..dd5005f2
--- /dev/null
+++ b/it-it/rust-it.html.markdown
@@ -0,0 +1,321 @@
+---
+language: rust
+contributors:
+ - ["Carlo Milanesi", "http://github.com/carlomilanesi"]
+filename: rust-it.html.markdown
+---
+
+Rust è un linguaggio di programmazione sviluppato da Mozilla Research.
+Rust combina il controllo a basso livello sulle prestazioni con alcune comodità
+ad alto livello e stringenti garanzie di sicurezza.
+
+Rust raggiunge questi obiettivi senza richiedere la garbage collection né una grossa
+libreria di supporto run-time, rendendo così possibile l'uso di librerie scritte in Rust
+come rimpiazzo di librerie scritte in C.
+
+La prima versione pubblica di Rust, la 0.1, è stata rilasciata nel gennaio 2012, e per 3 anni
+lo sviluppo è proceduto così rapidamente che l'utilizzo delle versioni
+stabili veniva scoraggiato, e piuttosto si consigliava di utilizzare le versioni notturne
+(nightly build).
+
+Il 15 maggio 2015, la versione 1.0 di Rust è stata rilasciata con la garanzia
+che nelle successive versioni 1.x non ci sarebbero state modifiche che avrebbero reso
+incompatibile il codice scritto per tale versione.
+Nelle nightly build sono attualmente disponibili migliorie al tempo di compilazione
+e ad altri aspetti del compilatore. Rust ha adottato un modello di rilascio a scaglioni
+con rilasci regolari ogni sei settimane. Per esempio, la versione 1.1 beta è stata resa
+disponibile contestualmente al rilascio della versione stabile 1.0.
+
+Sebbene Rust sia un linguaggio di livello relativamente basso, Rust ha alcuni concetti
+di programmazione funzionale che solitamente si trovano solo nei linguaggi di livello più alto.
+Ciò rende Rust non solo veloce, ma anche facile ed comodo da usare.
+
+```rust
+// I commenti che stanno su una sola riga sono fatti così...
+/* ...mentre così sono fatti
+i commenti che richiedono
+più righe */
+
+///////////////////
+// 1. Fondamenti //
+///////////////////
+
+// Funzioni
+// `i32` è il tipo per gli interi a 32-bit con segno
+fn add2(x: i32, y: i32) -> i32 {
+ // return implicito (senza punto-e-virgola)
+ x + y
+}
+
+// Funzione "main"
+fn main() {
+ // Numeri //
+
+ // Binding (ossia "variabili") immutabili
+ let x: i32 = 1;
+
+ // Suffissi intero/virgola mobile
+ let y: i32 = 13i32;
+ let f: f64 = 1.3f64;
+
+ // Inferenza di tipo
+ // La maggior parte delle volte, il compilatore Rust può inferire
+ // di quale tipo sia l'espressione usata per inizializzare un binding,
+ // e quindi non è necessario specificare esplicitamente il tipo.
+ // In tutto questo tutorial, i tipi vengono specificati esplicitamente in molti posti,
+ // ma solo a scopo dimostrativo. La maggior parte delle volte se ne potrebbe
+ // fare a meno, grazie all'inferenza di tipo.
+ let implicito_x = 1;
+ let implicito_f = 1.3;
+
+ // Aritmetica
+ let somma = x + y + 13;
+
+ // Variabile mutevole
+ let mut mutevole = 1;
+ mutevole = 4;
+ mutevole += 2;
+
+ // Stringhe //
+
+ // Letterali di stringa
+ let x: &str = "Ciao mondo!";
+
+ // Stampa
+ println!("{} {}", f, x); // 1.3 Ciao mondo!
+
+ // Una `String` – una stringa allocata nello heap
+ let s: String = "Ciao mondo".to_string();
+
+ // Uno slice (fetta) di stringa – una vista immutabile
+ // all'interno di un'altra stringa.
+ // Uno slice è una coppia immutabile di puntatori al buffer contenuto
+ // nella stringa - non contiene dei caratteri, solo dei puntatori a
+ // un buffer statico o a un buffer contenuto in un altro oggetto (in questo caso, `s`)
+ let s_slice: &str = &s;
+
+ println!("{} - {}", s, s_slice); // Ciao mondo - Ciao mondo
+
+ // Vettori/array //
+
+ // Un array di lunghezza fissa
+ let quattro_int: [i32; 4] = [1, 2, 3, 4];
+
+ // Un array dinamico (vettore)
+ let mut vettore: Vec<i32> = vec![1, 2, 3, 4];
+ vettore.push(5);
+
+ // Uno slice – una vista immutabile all'interno di un vettore o di un array
+ // E' molto simile a uno slice di stringa, ma per i vettori
+ let slice: &[i32] = &vettore;
+
+ // Usa `{:?}` per stampare qualcosa a scopo di debugging
+ println!("{:?} {:?}", vettore, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
+
+ // Tuple //
+
+ // Una tupla è un insieme ordinato di dimensione fissa di valori aventi tipi eventualmente diversi
+ let x: (i32, &str, f64) = (1, "ciao", 3.4);
+
+ // Il `let` che destruttura
+ let (a, b, c) = x;
+ println!("{} {} {}", a, b, c); // 1 ciao 3.4
+
+ // Indicizzazione
+ println!("{}", x.1); // ciao
+
+ /////////////
+ // 2. Tipi //
+ /////////////
+
+ // Strutture
+ struct Point {
+ x: i32,
+ y: i32,
+ }
+
+ let origine: Punto = Punto { x: 0, y: 0 };
+
+ // Ana struct con campi senza nome, chiamata ‘tuple struct’
+ struct Punto2(i32, i32);
+
+ let origine2 = Punto2(0, 0);
+
+ // Enum basilare, analoga a quelle del linguaggio C
+ enum Direzione {
+ Sinistra,
+ Destra,
+ Su,
+ Giu,
+ }
+
+ let su = Direzione::Su;
+
+ // Enum con campi
+ enum OpzionaleI32 {
+ UnI32(i32),
+ Niente,
+ }
+
+ let due: OpzionaleI32 = OpzionaleI32::UnI32(2);
+ let niente = OpzionaleI32::Niente;
+
+ // Generici //
+
+ struct Foo<T> { bar: T }
+
+ // Questo è definito nella libreria standard come `Option`
+ enum Opzionale<T> {
+ QualcheValore(T),
+ NessunValore,
+ }
+
+ // Metodi //
+
+ impl<T> Foo<T> {
+ // I metodi di oggetto prendono un parametro `self` esplicito
+ fn get_bar(self) -> T {
+ self.bar
+ }
+ }
+
+ let a_foo = Foo { bar: 1 };
+ println!("{}", a_foo.get_bar()); // 1
+
+ // I trait (tratti), noti come "interfacce" o "mixin" in altri linguaggi
+
+ trait Maneggiamento<T> {
+ fn maneggia(self) -> Option<T>;
+ }
+
+ impl<T> Maneggiamento<T> for Foo<T> {
+ fn maneggia(self) -> Option<T> {
+ Some(self.bar)
+ }
+ }
+
+ let altro_foo = Foo { bar: 1 };
+ println!("{:?}", altro_foo.maneggia()); // Some(1)
+
+ /////////////////////////
+ // 3. Pattern matching //
+ /////////////////////////
+
+ let foo = OpzionaleI32::UnI32(1);
+ match foo {
+ OpzionaleI32::UnI32(n) => println!("E' un i32: {}", n),
+ OpzionaleI32::Niente => println!("Non vale niente!"),
+ }
+
+ // Pattern matching avanzato
+ struct FooBar { x: i32, y: OpzionaleI32 }
+ let bar = FooBar { x: 15, y: OpzionaleI32::UnI32(32) };
+
+ match bar {
+ FooBar { x: 0, y: OpzionaleI32::UnI32(0) } =>
+ println!("I numeri valgono zero!"),
+ FooBar { x: n, y: OpzionaleI32::UnI32(m) } if n == m =>
+ println!("I numeri sono identici"),
+ FooBar { x: n, y: OpzionaleI32::UnI32(m) } =>
+ println!("Numeri diversi: {} {}", n, m),
+ FooBar { x: _, y: OpzionaleI32::Niente } =>
+ println!("Il secondo numbero non vale niente!"),
+ }
+
+ ///////////////////////////////////////////
+ // 4. Flusso di controllo (Control flow) //
+ ///////////////////////////////////////////
+
+ // Ciclo/iterazione con `for`
+ let array = [1, 2, 3];
+ for i in array.iter() {
+ println!("{}", i);
+ }
+
+ // Range
+ for i in 0u32..10 {
+ print!("{} ", i);
+ }
+ println!("");
+ // Stampa `0 1 2 3 4 5 6 7 8 9 `
+
+ // `if`
+ if 1 == 1 {
+ println!("La matematica funziona!");
+ } else {
+ println!("Oh no...");
+ }
+
+ // `if` come espressione
+ let value = if true {
+ "bene"
+ } else {
+ "male"
+ };
+
+ // Ciclo `while`
+ while 1 == 1 {
+ println!("L'universo sta funzionando regolarmente.");
+ }
+
+ // Ciclo infinito
+ loop {
+ println!("Ciao!");
+ }
+
+ /////////////////////////////////////////////////
+ // 5. La sicurezza della memoria e i puntatori //
+ /////////////////////////////////////////////////
+
+ // Puntatore posseduto (owned) – solamente una cosa sola per volta può ‘possedere’ questo puntatore
+ // Ciò significa che quando il `Box` abbandona il suo scope, verrà automaticamente deallocato in sicurezza.
+ let mut mio: Box<i32> = Box::new(3);
+ *mio = 5; // dereference
+ // Qui, `adesso_e_mio` acquisisce la proprietà di `mio`. In altre parole, `mio` viene spostato.
+ let mut adesso_e_mio = mio;
+ *adesso_e_mio += 2;
+
+ println!("{}", adesso_e_mio); // 7
+ // println!("{}", mio); // questo non compilerebbe perché `adesso_e_mio` adesso possiede il puntatore
+
+ // Riferimento (reference) – un puntatore immutabile che si riferisce ad altri dati
+ // Quando un riferimento viene preso a un valore, diciamo che quel valore
+ // è stato ‘preso in prestito’ (borrowed).
+ // Mentre un valore è preso in prestito immutabilmente, non può venire mutato né spostato.
+ // Un prestito dura fino alla fine dello scope in cui è stato creato.
+ let mut var = 4;
+ var = 3;
+ let ref_var: &i32 = &var;
+
+ println!("{}", var); // Diversamente da `box`, `var` può ancora essere usato
+ println!("{}", *ref_var);
+ // var = 5; // questo non compilerebbe, perché `var` è stato preso in prestito
+ // *ref_var = 6; // neanche questo, perché `ref_var` è un riferimento immutabile
+
+ // Riferimento immutabile
+ // Mentre un valore è preso in presto mutevolmente, non può essere acceduto in nessun modo.
+ let mut var2 = 4;
+ let ref_var2: &mut i32 = &mut var2;
+ *ref_var2 += 2; // '*' serve a puntare al binding var2, preso in presto mutevolmente
+
+ println!("{}", *ref_var2); // 6
+ // var2 non compilerebbe. ref_var2 è di tipo &mut i32, e quindi
+ // immagazzina un riferimento a un i32, e non il valore stesso.
+ // var2 = 2; // questo non compilerebbe, perché `var2` è stato preso in prestito
+}
+```
+
+## Ulteriori letture
+
+C'è molto di più in Rust — questi sono solo i fondamenti di Rust, che servono a capire
+le cose più importanti.
+
+Purtroppo c'è pochissima documentazione in italiano, tra cui:
+(https://www.mozillaitalia.org/home/2015/05/30/primi-passi-con-rust/)
+
+Però ce n'è parecchia in inglese. Per saperne di più, leggi [The Rust Programming
+Language](http://doc.rust-lang.org/book/index.html) e tieni d'occhio l'area di interesse di Reddit (subreddit)
+[/r/rust](http://reddit.com/r/rust).
+
+Puoi anche provare a programmare in varie versioni di Rust usando il compilatore online al sito ufficiale
+[Rust playpen](http://play.rust-lang.org).
diff --git a/rust.html.markdown b/rust.html.markdown
index 4aa9ca7c..f1b62ef4 100644
--- a/rust.html.markdown
+++ b/rust.html.markdown
@@ -88,9 +88,10 @@ fn main() {
let s: String = "hello world".to_string();
// A string slice – an immutable view into another string
- // This is basically an immutable pointer to a string – it doesn’t
+ // This is basically an immutable pair of pointers to a string – it doesn’t
// actually contain the contents of a string, just a pointer to
- // something that does (in this case, `s`)
+ // the begin and a pointer to the end of a string buffer,
+ // statically allocated or contained in another object (in this case, `s`)
let s_slice: &str = &s;
println!("{} {}", s, s_slice); // hello world hello world
diff --git a/scala.html.markdown b/scala.html.markdown
index 7f5f0ec3..5e3ece2d 100644
--- a/scala.html.markdown
+++ b/scala.html.markdown
@@ -12,22 +12,62 @@ Scala - the scalable language
```scala
+/////////////////////////////////////////////////
+// 0. Basics
+/////////////////////////////////////////////////
/*
- Set yourself up:
+ Setup Scala:
1) Download Scala - http://www.scala-lang.org/downloads
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 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.
-
*/
+/*
+ Try the REPL
+
+ Scala has a tool called the REPL (Read-Eval-Print Loop) that is anologus to
+ commandline interpreters in many other languages. You may type any Scala
+ expression, and the result will be evaluated and printed.
+
+ The REPL is a very handy tool to test and verify code. Use it as you read
+ this tutorial to quickly explore concepts on your own.
+*/
+
+// Start a Scala REPL by running `scala`. You should see the prompt:
+$ scala
+scala>
+
+// By default each expression you type is saved as a new numbered value
+scala> 2 + 2
+res0: Int = 4
+
+// Default values can be reused. Note the value type displayed in the result..
+scala> res0 + 2
+res1: Int = 6
+
+// Scala is a strongly typed language. You can use the REPL to check the type
+// without evaluating an expression.
+scala> :type (true, 2.0)
+(Boolean, Double)
+
+// REPL sessions can be saved
+scala> :save /sites/repl-test.scala
+
+// Files can be loaded into the REPL
+scala> :load /sites/repl-test.scala
+Loading /sites/repl-test.scala...
+res2: Int = 4
+res3: Int = 6
+
+// You can search your recent history
+scala> :h?
+1 2 + 2
+2 res0 + 2
+3 :save /sites/repl-test.scala
+4 :load /sites/repl-test.scala
+5 :h?
+
+// Now that you know how to play, let's learn a little scala...
/////////////////////////////////////////////////
// 1. Basics
diff --git a/zh-cn/kotlin-cn.html.markdown b/zh-cn/kotlin-cn.html.markdown
new file mode 100644
index 00000000..1fd12f5b
--- /dev/null
+++ b/zh-cn/kotlin-cn.html.markdown
@@ -0,0 +1,346 @@
+---
+language: kotlin
+contributors:
+ - ["S Webber", "https://github.com/s-webber"]
+translators:
+ - ["Jimin Lu", "https://github.com/lujimin"]
+filename: LearnKotlin-cn.kt
+lang: zh-cn
+---
+
+Kotlin是一门适用于JVM、Android和浏览器的静态类型编程语言。它100%兼容Java。
+[了解更多。](https://kotlinlang.org/)
+
+```java
+// 单行注释从 // 开始
+/*
+多行注释看起来像这样。
+*/
+
+// "package" 关键字的工作方式与Java相同。
+package com.learnxinyminutes.kotlin
+
+/*
+Kotlin程序的入口点是一个"main"函数
+该函数传递一个包含任何命令行参数的数组。
+*/
+fun main(args: Array<String>) {
+ /*
+ 使用"var"或"val"来声明一个值。
+ "val"声明的值不能被重新赋值,而"var"声明的值可以。
+ */
+ val fooVal = 10 // 以后我们不能再次给fooVal赋值
+ var fooVar = 10
+ fooVar = 20 // fooVar可以被再次赋值
+
+ /*
+ 在大多数情况下,Kotlin可以确定变量的类型是什么,
+ 所以我们不必要每次都去明确指定它。
+ 我们可以像这样明确地声明一个变量的类型:
+ */
+ val foo : Int = 7
+
+ /*
+ 可以采取和Java类似的方法来表示一个字符串。
+ 用反斜杠来转义字符。
+ */
+ val fooString = "My String Is Here!";
+ val barString = "Printing on a new line?\nNo Problem!";
+ val bazString = "Do you want to add a tab?\tNo Problem!";
+ println(fooString);
+ println(barString);
+ println(bazString);
+
+ /*
+ 原始字符串用三重引号(""")来定义。
+ 原始字符串可以包含换行符以及其他任何字符。
+ */
+ val fooRawString = """
+fun helloWorld(val name : String) {
+ println("Hello, world!")
+}
+"""
+ println(fooRawString)
+
+ /*
+ 字符串可以包含模板表达式。
+ 模板表达式从一个美元符号($)开始。
+ */
+ val fooTemplateString = "$fooString has ${fooString.length} characters"
+ println(fooTemplateString)
+
+ /*
+ 当某个变量的值可以为 null 的时候,我们必须被明确指定它是可为空的。
+ 在变量声明处的类型后面加上?来标识它是可为空的。
+ 我们可以用?.操作符来访问可为空的变量。
+ 我们可以用?:操作符来指定一个在变量为空时使用的替代值。
+ */
+ var fooNullable: String? = "abc"
+ println(fooNullable?.length) // => 3
+ println(fooNullable?.length ?: -1) // => 3
+ fooNullable = null
+ println(fooNullable?.length) // => null
+ println(fooNullable?.length ?: -1) // => -1
+
+ /*
+ 使用"fun"关键字来声明一个函数。
+ 函数的参数在函数名后面的括号内指定。
+ 函数的参数可以设定一个默认值。
+ 如果需要的话,函数的返回值类型可以在参数后面指定。
+ */
+ fun hello(name: String = "world") : String {
+ return "Hello, $name!"
+ }
+ println(hello("foo")) // => Hello, foo!
+ println(hello(name = "bar")) // => Hello, bar!
+ println(hello()) // => Hello, world!
+
+ /*
+ 用"vararg"关键字来修饰一个函数的参数来允许可变参数传递给该函数
+ */
+ fun varargExample(vararg names: Int) {
+ println("Argument has ${names.size} elements")
+ }
+ varargExample() // => Argument has 0 elements
+ varargExample(1) // => Argument has 1 elements
+ varargExample(1, 2, 3) // => Argument has 3 elements
+
+ /*
+ 当函数只包含一个单独的表达式时,大括号可以被省略。
+ 函数体可以被指定在一个=符号后面。
+ */
+ fun odd(x: Int): Boolean = x % 2 == 1
+ println(odd(6)) // => false
+ println(odd(7)) // => true
+
+ // 如果返回值类型可以被推断,那么我们不需要指定它。
+ fun even(x: Int) = x % 2 == 0
+ println(even(6)) // => true
+ println(even(7)) // => false
+
+ // 函数可以用函数作为参数并且可以返回函数。
+ fun not(f: (Int) -> Boolean) : (Int) -> Boolean {
+ return {n -> !f.invoke(n)}
+ }
+ // 命名函数可以用::运算符被指定为参数。
+ val notOdd = not(::odd)
+ val notEven = not(::even)
+ // 匿名函数可以被指定为参数。
+ val notZero = not {n -> n == 0}
+ /*
+ 如果一个匿名函数只有一个参数
+ 那么它的声明可以被省略(连同->)。
+ 这个参数的名字是"it"。
+ */
+ val notPositive = not {it > 0}
+ for (i in 0..4) {
+ println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}")
+ }
+
+ // "class"关键字用来声明类。
+ class ExampleClass(val x: Int) {
+ fun memberFunction(y: Int) : Int {
+ return x + y
+ }
+
+ infix fun infixMemberFunction(y: Int) : Int {
+ return x * y
+ }
+ }
+ /*
+ 我们调用构造方法来创建一个新的实例。
+ 注意,Kotlin没有"new"关键字。
+ */
+ val fooExampleClass = ExampleClass(7)
+ // 可以使用一个点号来调用成员函数。
+ println(fooExampleClass.memberFunction(4)) // => 11
+ /*
+ 如果使用"infix"关键字来标记一个函数
+ 那么可以使用中缀表示法来调用该函数。
+ */
+ println(fooExampleClass infixMemberFunction 4) // => 28
+
+ /*
+ 数据类是创建只包含数据的类的一个简洁的方法。
+ "hashCode"、"equals"和"toString"方法将被自动生成。
+ */
+ data class DataClassExample (val x: Int, val y: Int, val z: Int)
+ val fooData = DataClassExample(1, 2, 4)
+ println(fooData) // => DataClassExample(x=1, y=2, z=4)
+
+ // 数据类有一个"copy"函数
+ val fooCopy = fooData.copy(y = 100)
+ println(fooCopy) // => DataClassExample(x=1, y=100, z=4)
+
+ // 对象可以被解构成为多个变量
+ val (a, b, c) = fooCopy
+ println("$a $b $c") // => 1 100 4
+
+ // "with"函数类似于JavaScript中的"with"用法。
+ data class MutableDataClassExample (var x: Int, var y: Int, var z: Int)
+ val fooMutableDate = MutableDataClassExample(7, 4, 9)
+ with (fooMutableDate) {
+ x -= 2
+ y += 2
+ z--
+ }
+ println(fooMutableDate) // => MutableDataClassExample(x=5, y=6, z=8)
+
+ /*
+ 我们可以使用"listOf"函数来创建一个list。
+ 这个list是不可变的 - 元素不可以被添加或删除。
+ */
+ val fooList = listOf("a", "b", "c")
+ println(fooList.size) // => 3
+ println(fooList.first()) // => a
+ println(fooList.last()) // => c
+ // 可以通过索引来访问list中的元素。
+ println(fooList[1]) // => b
+
+ // 可以使用"mutableListOf"函数来创建一个可变的list。
+ val fooMutableList = mutableListOf("a", "b", "c")
+ fooMutableList.add("d")
+ println(fooMutableList.last()) // => d
+ println(fooMutableList.size) // => 4
+
+ // 我们可以使用"setOf"函数来创建一个set。
+ val fooSet = setOf("a", "b", "c")
+ println(fooSet.contains("a")) // => true
+ println(fooSet.contains("z")) // => false
+
+ // 我们可以使用"mapOf"函数来创建一个map。
+ val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9)
+ // 可以通过键来访问map中的值。
+ println(fooMap["a"]) // => 8
+
+ /*
+ 序列表示惰性求值集合。
+ 我们可以使用"generateSequence"函数来创建一个序列。
+ */
+ val fooSequence = generateSequence(1, {it + 1})
+ val x = fooSequence.take(10).toList()
+ println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+ // 一个用序列来生成斐波那契数列的例子。
+ fun fibonacciSequence() : Sequence<Long> {
+ var a = 0L
+ var b = 1L
+
+ fun next() : Long {
+ val result = a + b
+ a = b
+ b = result
+ return a
+ }
+
+ return generateSequence(::next)
+ }
+ val y = fibonacciSequence().take(10).toList()
+ println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
+
+ // Kotlin为集合提供高阶函数。
+ val z = (1..9).map {it * 3}
+ .filter {it < 20}
+ .groupBy {it % 2 == 0}
+ .mapKeys {if (it.key) "even" else "odd"}
+ println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]}
+
+ // 任何提供迭代器的都可以使用"for"循环。
+ for (c in "hello") {
+ println(c)
+ }
+
+ // "while"循环的用法和其他语言一样。
+ var ctr = 0
+ while (ctr < 5) {
+ println(ctr)
+ ctr++
+ }
+ do {
+ println(ctr)
+ ctr++
+ } while (ctr < 10)
+
+ // "when"可以用来替代"if-else if"链。
+ val i = 10
+ when {
+ i < 7 -> println("first block")
+ fooString.startsWith("hello") -> println("second block")
+ else -> println("else block")
+ }
+
+ // "when"可以带参数。
+ when (i) {
+ 0, 21 -> println("0 or 21")
+ in 1..20 -> println("in the range 1 to 20")
+ else -> println("none of the above")
+ }
+
+ // "when"可以作为一个函数,提供返回值。
+ var result = when (i) {
+ 0, 21 -> "0 or 21"
+ in 1..20 -> "in the range 1 to 20"
+ else -> "none of the above"
+ }
+ println(result)
+
+ /*
+ 我们可以通过使用"is"操作符来检查一个对象是否是某个类型的。
+ 如果对象通过了类型检查那么它可以作为该类型使用而不需要强制转换它。
+ */
+ fun smartCastExample(x: Any) : Boolean {
+ if (x is Boolean) {
+ // x自动转换为Boolean
+ return x
+ } else if (x is Int) {
+ // x自动转换为Int
+ return x > 0
+ } else if (x is String) {
+ // x自动转换为String
+ return x.isNotEmpty()
+ } else {
+ return false
+ }
+ }
+ println(smartCastExample("Hello, world!")) // => true
+ println(smartCastExample("")) // => false
+ println(smartCastExample(5)) // => true
+ println(smartCastExample(0)) // => false
+ println(smartCastExample(true)) // => true
+
+ /*
+ 扩展是用来给一个类添加新的功能的。
+ 它类似于C#的扩展方法。
+ */
+ fun String.remove(c: Char): String {
+ return this.filter {it != c}
+ }
+ println("Hello, world!".remove('l')) // => Heo, word!
+
+ println(EnumExample.A) // => A
+ println(ObjectExample.hello()) // => hello
+}
+
+// 枚举类和Java的枚举类型类似。
+enum class EnumExample {
+ A, B, C
+}
+
+/*
+"object"关键字用来创建单例对象。
+我们不能把它赋给一个变量,但我们可以通过它的名字引用它。
+这类似于Scala的单例对象。
+*/
+object ObjectExample {
+ fun hello() : String {
+ return "hello"
+ }
+}
+
+```
+
+### 进一步阅读
+
+* [Kotlin教程](https://kotlinlang.org/docs/tutorials/)
+* [在您的浏览器中使用Kotlin](http://try.kotlinlang.org/)
+* [Kotlin资源列表](http://kotlin.link/)
diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown
index 0c46bc22..55a29b11 100644
--- a/zh-cn/r-cn.html.markdown
+++ b/zh-cn/r-cn.html.markdown
@@ -285,7 +285,7 @@ while (a > 4) {
}
# 记住,在 R 语言中 for / while 循环都很慢
-# 建议使用 apply()(我们一会介绍)来错做一串数据(比如一列或者一行数据)
+# 建议使用 apply()(我们一会介绍)来操作一串数据(比如一列或者一行数据)
# IF/ELSE