summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDivay Prakash <divayprakash@users.noreply.github.com>2020-02-02 15:13:28 +0530
committerGitHub <noreply@github.com>2020-02-02 15:13:28 +0530
commit8eb11a89a7fc84dde15544c6f7ec99a8f44b0c9f (patch)
tree7605022884b652f7acf879328887a9d191d3ef58
parentab5a1953e77288ca27bd7b4c931d8bb2e79a9966 (diff)
parentf80889ed47ae42ca4ea2b8118e2b3c48c37eeb9c (diff)
Merge branch 'master' into master
-rw-r--r--CONTRIBUTING.markdown2
-rw-r--r--ansible.html.markdown26
-rw-r--r--coq.html.markdown208
-rw-r--r--csharp.html.markdown26
-rw-r--r--d.html.markdown1
-rw-r--r--dart.html.markdown73
-rw-r--r--de-de/bash-de.html.markdown2
-rw-r--r--de-de/bc.html.markdown102
-rw-r--r--de-de/css-de.html.markdown6
-rw-r--r--de-de/html-de.html.markdown16
-rw-r--r--de-de/java-de.html.markdown2
-rw-r--r--de-de/latex-de.html.markdown8
-rw-r--r--de-de/make-de.html.markdown43
-rw-r--r--docker.html.markdown146
-rw-r--r--dynamic-programming.html.markdown14
-rw-r--r--el-gr/python3-gr.html.markdown1030
-rw-r--r--elixir.html.markdown8
-rw-r--r--es-es/hq9+-es.html.markdown44
-rw-r--r--es-es/pcre-es.html.markdown84
-rw-r--r--go.html.markdown22
-rw-r--r--haskell.html.markdown159
-rw-r--r--hdl.html.markdown231
-rw-r--r--it-it/bash-it.html.markdown2
-rw-r--r--java.html.markdown2
-rw-r--r--javascript.html.markdown2
-rw-r--r--kdb+.html.markdown2
-rw-r--r--latex.html.markdown2
-rw-r--r--linker.html.markdown2
-rw-r--r--mips.html.markdown14
-rw-r--r--php.html.markdown2
-rw-r--r--powershell.html.markdown4
-rw-r--r--pt-br/clojure-macros-pt.html.markdown16
-rw-r--r--pt-br/clojure-pt.html.markdown599
-rw-r--r--pt-br/pascal-pt.html.markdown1
-rw-r--r--pt-br/vim-pt.html.markdown11
-rw-r--r--python3.html.markdown24
-rw-r--r--ruby.html.markdown2
-rw-r--r--rust.html.markdown2
-rw-r--r--sass.html.markdown2
-rw-r--r--smalltalk.html.markdown93
-rw-r--r--standard-ml.html.markdown5
-rw-r--r--swift.html.markdown7
-rwxr-xr-xtoml.html.markdown33
-rw-r--r--typescript.html.markdown2
-rw-r--r--vimscript.html.markdown651
-rw-r--r--wasm.html.markdown85
-rw-r--r--zh-cn/css-cn.html.markdown2
-rw-r--r--zh-cn/git-cn.html.markdown2
-rw-r--r--zh-cn/markdown-cn.html.markdown2
-rw-r--r--zh-cn/powershell-cn.html.markdown325
-rw-r--r--zh-cn/racket-cn.html.markdown2
-rw-r--r--zh-cn/yaml-cn.html.markdown6
-rw-r--r--zh-tw/dart-tw.html.markdown566
53 files changed, 4226 insertions, 497 deletions
diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown
index 18a5a5d7..3dfd38ce 100644
--- a/CONTRIBUTING.markdown
+++ b/CONTRIBUTING.markdown
@@ -83,7 +83,7 @@ addition or not.
## Building the site locally
-You can buid the site locally to test your changes. Follow the steps below.
+You can build the site locally to test your changes. Follow the steps below.
* Install Ruby language runtime and RubyGems. See [here](https://middlemanapp.com/basics/install/) for more details.
* Clone or zip download the [learnxinyminutes-site](https://github.com/adambard/learnxinyminutes-site) repo.
diff --git a/ansible.html.markdown b/ansible.html.markdown
index 41a8c9b5..30dfba13 100644
--- a/ansible.html.markdown
+++ b/ansible.html.markdown
@@ -30,9 +30,9 @@ But ansible is way more! It provides execution plans, an API, library, and callb
#### Pros
-* It is an agent-less tools In most scenarios, it use ssh as a transport layer.
+* It is an agent-less tool. In most scenarios, it uses ssh as a transport layer.
In some way you can use it as 'bash on steroids'.
-* It is very easy to start. If you are familiar with ssh concept - you already
+* It is very easy to start. If you are familiar with the concept of ssh - you already
know Ansible (ALMOST).
* It executes 'as is' - other tools (salt, puppet, chef - might execute in
different scenario than you would expect)
@@ -176,7 +176,7 @@ instances in the cloud, execute shell command). The simplest module is called
Example of modules:
* Module: `ping` - the simplest module that is useful to verify host connectivity
-* Module: `shell` - a module that executes shell command on a specified host(s).
+* Module: `shell` - a module that executes a shell command on a specified host(s).
```bash
@@ -204,13 +204,13 @@ the module subsystem (useful to install python2.7)
Execution of a single Ansible **module** is called a **task**. The simplest
module is called `ping` as you could see above.
-Another example of the module that allow you to execute command remotly on
+Another example of the module that allows you to execute a command remotely on
multiple resources is called `shell`. See above how you were using them already.
### Playbook
**Execution plan** written in a form of script file(s) is called **playbook**.
-Playbook consist of multiple elements -
+Playbooks consist of multiple elements -
* a list (or group) of hosts that 'the play' is executed against
* `task(s)` or `role(s)` that are going to be executed
* multiple optional settings (like default variables, and way more)
@@ -247,7 +247,7 @@ Note: Example playbook is explained in the next chapter: 'Roles'
### Inventory
-Inventory is a set of objects or hosts, against which we are executing our
+An inventory is a set of objects or hosts, against which we are executing our
playbooks or single tasks via shell commands. For these few minutes, let's
assume that we are using the default ansible inventory (which in Debian based
system is placed in `/etc/ansible/hosts`).
@@ -303,11 +303,11 @@ Role can be included in your playbook (executed via your playbook).
```
#### For remaining examples we would use additional repository
-This example install ansible in `virtualenv` so it is independend from a system.
-You need to initialize it into your shell-context with `source environment.sh`
+This example installs ansible in `virtualenv` so it is independent from the system.
+You need to initialize it into your shell-context with the `source environment.sh`
command.
-We are going to use this repository with examples: [https://github.com/sirkubax/ansible-for-learnXinYminutes]()
+We are going to use this repository with examples: [https://github.com/sirkubax/ansible-for-learnXinYminutes](https://github.com/sirkubax/ansible-for-learnXinYminutes)
```bash
$ # The following example contains a shell-prompt to indicate the venv and relative path
@@ -513,7 +513,7 @@ $ # Now we would run the above playbook with roles
You can use the jinja in the CLI too
```bash
-ansible -m shell -a 'echo {{ my_variable }}` -e 'my_variable=something, playbook_parameter=twentytwo" localhost
+ansible -m shell -a 'echo {{ my_variable }}' -e 'my_variable=something, playbook_parameter=twentytwo' localhost
```
In fact - jinja is used to template parts of the playbooks too
@@ -551,7 +551,7 @@ provides a way to encrypt confidential files so you can store them in the
repository, yet the files are decrypted on-the-fly during ansible execution.
The best way to use it is to store the secret in some secure location, and
-configure ansible to use during runtime.
+configure ansible to use them during runtime.
```bash
# Try (this would fail)
@@ -588,7 +588,7 @@ You might like to know, that you can build your inventory dynamically.
deliver that to ansible - anything is possible.
You do not need to reinvent the wheel - there are plenty of ready to use
-inventory scripts for most popular Cloud providers and a lot of in-house
+inventory scripts for the most popular Cloud providers and a lot of in-house
popular usecases.
[AWS example](http://docs.ansible.com/ansible/latest/intro_dynamic_inventory.html#example-aws-ec2-external-inventory-script)
@@ -614,7 +614,7 @@ callback_whitelist = profile_tasks
### facts-cache and ansible-cmdb
-You can pull some information about your environment from another hosts.
+You can pull some information about your environment from another host.
If the information does not change - you may consider using a facts_cache
to speed things up.
diff --git a/coq.html.markdown b/coq.html.markdown
index 115d9ff8..4c1ad690 100644
--- a/coq.html.markdown
+++ b/coq.html.markdown
@@ -25,19 +25,20 @@ Inside Proof General `Ctrl+C Ctrl+<Enter>` will evaluate up to your cursor.
(*** Variables and functions ***)
-(* The Coq proof assistant can be controlled and queried by a command language called
- the vernacular. Vernacular keywords are capitalized and the commands end with a period.
- Variable and function declarations are formed with the Definition vernacular. *)
+(* The Coq proof assistant can be controlled and queried by a command
+ language called the vernacular. Vernacular keywords are capitalized and
+ the commands end with a period. Variable and function declarations are
+ formed with the Definition vernacular. *)
Definition x := 10.
-(* Coq can sometimes infer the types of arguments, but it is common practice to annotate
- with types. *)
+(* Coq can sometimes infer the types of arguments, but it is common practice
+ to annotate with types. *)
Definition inc_nat (x : nat) : nat := x + 1.
-(* There exists a large number of vernacular commands for querying information.
- These can be very useful. *)
+(* There exists a large number of vernacular commands for querying
+ information. These can be very useful. *)
Compute (1 + 1). (* 2 : nat *) (* Compute a result. *)
@@ -46,48 +47,50 @@ Check tt. (* tt : unit *) (* Check the type of an expressions *)
About plus. (* Prints information about an object *)
(* Print information including the definition *)
-Print true. (* Inductive bool : Set := true : Bool | false : Bool *)
+Print true. (* Inductive bool : Set := true : Bool | false : Bool *)
Search nat. (* Returns a large list of nat related values *)
Search "_ + _". (* You can also search on patterns *)
Search (?a -> ?a -> bool). (* Patterns can have named parameters *)
Search (?a * ?a).
-(* Locate tells you where notation is coming from. Very helpful when you encounter
- new notation. *)
-Locate "+".
+(* Locate tells you where notation is coming from. Very helpful when you
+ encounter new notation. *)
-(* Calling a function with insufficient number of arguments
- does not cause an error, it produces a new function. *)
+Locate "+".
+
+(* Calling a function with insufficient number of arguments does not cause
+ an error, it produces a new function. *)
Definition make_inc x y := x + y. (* make_inc is int -> int -> int *)
Definition inc_2 := make_inc 2. (* inc_2 is int -> int *)
Compute inc_2 3. (* Evaluates to 5 *)
-(* Definitions can be chained with "let ... in" construct.
- This is roughly the same to assigning values to multiple
- variables before using them in expressions in imperative
- languages. *)
+
+(* Definitions can be chained with "let ... in" construct. This is roughly
+ the same to assigning values to multiple variables before using them in
+ expressions in imperative languages. *)
+
Definition add_xy : nat := let x := 10 in
let y := 20 in
x + y.
-
(* Pattern matching is somewhat similar to switch statement in imperative
languages, but offers a lot more expressive power. *)
+
Definition is_zero (x : nat) :=
match x with
| 0 => true
| _ => false (* The "_" pattern means "anything else". *)
end.
+(* You can define recursive function definition using the Fixpoint
+ vernacular.*)
-(* You can define recursive function definition using the Fixpoint vernacular.*)
Fixpoint factorial n := match n with
| 0 => 1
| (S n') => n * factorial n'
end.
-
(* Function application usually doesn't need parentheses around arguments *)
Compute factorial 5. (* 120 : nat *)
@@ -104,11 +107,12 @@ end with
| (S n) => is_even n
end.
-(* As Coq is a total programming language, it will only accept programs when it can
- understand they terminate. It can be most easily seen when the recursive call is
- on a pattern matched out subpiece of the input, as then the input is always decreasing
- in size. Getting Coq to understand that functions terminate is not always easy. See the
- references at the end of the article for more on this topic. *)
+(* As Coq is a total programming language, it will only accept programs when
+ it can understand they terminate. It can be most easily seen when the
+ recursive call is on a pattern matched out subpiece of the input, as then
+ the input is always decreasing in size. Getting Coq to understand that
+ functions terminate is not always easy. See the references at the end of
+ the article for more on this topic. *)
(* Anonymous functions use the following syntax: *)
@@ -119,16 +123,18 @@ Definition my_id2 : forall A : Type, A -> A := fun A x => x.
Compute my_id nat 3. (* 3 : nat *)
(* You can ask Coq to infer terms with an underscore *)
-Compute my_id _ 3.
+Compute my_id _ 3.
-(* An implicit argument of a function is an argument which can be inferred from contextual
- knowledge. Parameters enclosed in {} are implicit by default *)
+(* An implicit argument of a function is an argument which can be inferred
+ from contextual knowledge. Parameters enclosed in {} are implicit by
+ default *)
Definition my_id3 {A : Type} (x : A) : A := x.
Compute my_id3 3. (* 3 : nat *)
-(* Sometimes it may be necessary to turn this off. You can make all arguments explicit
- again with @ *)
+(* Sometimes it may be necessary to turn this off. You can make all
+ arguments explicit again with @ *)
+
Compute @my_id3 nat 3.
(* Or give arguments by name *)
@@ -168,17 +174,19 @@ let rec factorial n = match n with
(*** Notation ***)
-(* Coq has a very powerful Notation system that can be used to write expressions in more
- natural forms. *)
+(* Coq has a very powerful Notation system that can be used to write
+ expressions in more natural forms. *)
+
Compute Nat.add 3 4. (* 7 : nat *)
Compute 3 + 4. (* 7 : nat *)
-(* Notation is a syntactic transformation applied to the text of the program before being
- evaluated. Notation is organized into notation scopes. Using different notation scopes
- allows for a weak notion of overloading. *)
+(* Notation is a syntactic transformation applied to the text of the program
+ before being evaluated. Notation is organized into notation scopes. Using
+ different notation scopes allows for a weak notion of overloading. *)
+
+(* Imports the Zarith module holding definitions related to the integers Z *)
-(* Imports the Zarith module containing definitions related to the integers Z *)
-Require Import ZArith.
+Require Import ZArith.
(* Notation scopes can be opened *)
Open Scope Z_scope.
@@ -187,7 +195,7 @@ Open Scope Z_scope.
Compute 1 + 7. (* 8 : Z *)
(* Integer equality checking *)
-Compute 1 =? 2. (* false : bool *)
+Compute 1 =? 2. (* false : bool *)
(* Locate is useful for finding the origin and definition of notations *)
Locate "_ =? _". (* Z.eqb x y : Z_scope *)
@@ -199,10 +207,10 @@ Compute 1 + 7. (* 8 : nat *)
(* Scopes can also be opened inline with the shorthand % *)
Compute (3 * -7)%Z. (* -21%Z : Z *)
-(* Coq declares by default the following interpretation scopes: core_scope, type_scope,
- function_scope, nat_scope, bool_scope, list_scope, int_scope, uint_scope. You may also
- want the numerical scopes Z_scope (integers) and Q_scope (fractions) held in the ZArith
- and QArith module respectively. *)
+(* Coq declares by default the following interpretation scopes: core_scope,
+ type_scope, function_scope, nat_scope, bool_scope, list_scope, int_scope,
+ uint_scope. You may also want the numerical scopes Z_scope (integers) and
+ Q_scope (fractions) held in the ZArith and QArith module respectively. *)
(* You can print the contents of scopes *)
Print Scope nat_scope.
@@ -230,17 +238,19 @@ Bound to classes nat Nat.t
"x * y" := Init.Nat.mul x y
*)
-(* Coq has exact fractions available as the type Q in the QArith module.
- Floating point numbers and real numbers are also available but are a more advanced
- topic, as proving properties about them is rather tricky. *)
+(* Coq has exact fractions available as the type Q in the QArith module.
+ Floating point numbers and real numbers are also available but are a more
+ advanced topic, as proving properties about them is rather tricky. *)
Require Import QArith.
Open Scope Q_scope.
Compute 1. (* 1 : Q *)
-Compute 2. (* 2 : nat *) (* only 1 and 0 are interpreted as fractions by Q_scope *)
+
+(* Only 1 and 0 are interpreted as fractions by Q_scope *)
+Compute 2. (* 2 : nat *)
Compute (2 # 3). (* The fraction 2/3 *)
-Compute (1 # 3) ?= (2 # 6). (* Eq : comparison *)
+Compute (1 # 3) ?= (2 # 6). (* Eq : comparison *)
Close Scope Q_scope.
Compute ( (2 # 3) / (1 # 5) )%Q. (* 10 # 3 : Q *)
@@ -279,40 +289,43 @@ Definition my_fst2 {A B : Type} (x : A * B) : A := let (a,b) := x in
(*** Lists ***)
-(* Lists are built by using cons and nil or by using notation available in list_scope. *)
+(* Lists are built by using cons and nil or by using notation available in
+ list_scope. *)
Compute cons 1 (cons 2 (cons 3 nil)). (* (1 :: 2 :: 3 :: nil)%list : list nat *)
-Compute (1 :: 2 :: 3 :: nil)%list.
+Compute (1 :: 2 :: 3 :: nil)%list.
(* There is also list notation available in the ListNotations modules *)
Require Import List.
-Import ListNotations.
+Import ListNotations.
Compute [1 ; 2 ; 3]. (* [1; 2; 3] : list nat *)
-(*
-There are a large number of list manipulation functions available, including:
+(* There is a large number of list manipulation functions available,
+ including:
• length
-• head : first element (with default)
+• head : first element (with default)
• tail : all but first element
• app : appending
• rev : reverse
• nth : accessing n-th element (with default)
• map : applying a function
-• flat_map : applying a function returning lists
+• flat_map : applying a function returning lists
• fold_left : iterator (from head to tail)
-• fold_right : iterator (from tail to head)
+• fold_right : iterator (from tail to head)
*)
Definition my_list : list nat := [47; 18; 34].
Compute List.length my_list. (* 3 : nat *)
+
(* All functions in coq must be total, so indexing requires a default value *)
-Compute List.nth 1 my_list 0. (* 18 : nat *)
+Compute List.nth 1 my_list 0. (* 18 : nat *)
Compute List.map (fun x => x * 2) my_list. (* [94; 36; 68] : list nat *)
-Compute List.filter (fun x => Nat.eqb (Nat.modulo x 2) 0) my_list. (* [18; 34] : list nat *)
-Compute (my_list ++ my_list)%list. (* [47; 18; 34; 47; 18; 34] : list nat *)
+Compute List.filter (fun x => Nat.eqb (Nat.modulo x 2) 0) my_list.
+ (* [18; 34] : list nat *)
+Compute (my_list ++ my_list)%list. (* [47; 18; 34; 47; 18; 34] : list nat *)
(*** Strings ***)
@@ -342,16 +355,19 @@ Close Scope string_scope.
• PArith : Basic positive integer arithmetic
• NArith : Basic binary natural number arithmetic
• ZArith : Basic relative integer arithmetic
-• Numbers : Various approaches to natural, integer and cyclic numbers (currently
- axiomatically and on top of 2^31 binary words)
+
+• Numbers : Various approaches to natural, integer and cyclic numbers
+ (currently axiomatically and on top of 2^31 binary words)
• Bool : Booleans (basic functions and results)
+
• Lists : Monomorphic and polymorphic lists (basic functions and results),
Streams (infinite sequences defined with co-inductive types)
• Sets : Sets (classical, constructive, finite, infinite, power set, etc.)
-• FSets : Specification and implementations of finite sets and finite maps
+• FSets : Specification and implementations of finite sets and finite maps
(by lists and by AVL trees)
-• Reals : Axiomatization of real numbers (classical, basic functions, integer part,
- fractional part, limit, derivative, Cauchy series, power series and results,...)
+• Reals : Axiomatization of real numbers (classical, basic functions,
+ integer part, fractional part, limit, derivative, Cauchy series,
+ power series and results,...)
• Relations : Relations (definitions and basic results)
• Sorting : Sorted list (basic definitions and heapsort correctness)
• Strings : 8-bits characters and strings
@@ -360,18 +376,20 @@ Close Scope string_scope.
(*** User-defined data types ***)
-(* Because Coq is dependently typed, defining type aliases is no different than defining
- an alias for a value. *)
+(* Because Coq is dependently typed, defining type aliases is no different
+ than defining an alias for a value. *)
Definition my_three : nat := 3.
Definition my_nat : Type := nat.
-(* More interesting types can be defined using the Inductive vernacular. Simple enumeration
- can be defined like so *)
+(* More interesting types can be defined using the Inductive vernacular.
+ Simple enumeration can be defined like so *)
+
Inductive ml := OCaml | StandardML | Coq.
Definition lang := Coq. (* Has type "ml". *)
-(* For more complicated types, you will need to specify the types of the constructors. *)
+(* For more complicated types, you will need to specify the types of the
+ constructors. *)
(* Type constructors don't need to be empty. *)
Inductive my_number := plus_infinity
@@ -379,23 +397,28 @@ Inductive my_number := plus_infinity
Compute nat_value 3. (* nat_value 3 : my_number *)
-(* Record syntax is sugar for tuple-like types. It defines named accessor functions for
- the components. Record types are defined with the notation {...} *)
+(* Record syntax is sugar for tuple-like types. It defines named accessor
+ functions for the components. Record types are defined with the notation
+ {...} *)
+
Record Point2d (A : Set) := mkPoint2d { x2 : A ; y2 : A }.
(* Record values are constructed with the notation {|...|} *)
Definition mypoint : Point2d nat := {| x2 := 2 ; y2 := 3 |}.
Compute x2 nat mypoint. (* 2 : nat *)
-Compute mypoint.(x2 nat). (* 2 : nat *)
+Compute mypoint.(x2 nat). (* 2 : nat *)
+
+(* Types can be parameterized, like in this type for "list of lists of
+ anything". 'a can be substituted with any type. *)
-(* Types can be parameterized, like in this type for "list of lists
- of anything". 'a can be substituted with any type. *)
Definition list_of_lists a := list (list a).
Definition list_list_nat := list_of_lists nat.
(* Types can also be recursive. Like in this type analogous to
built-in list of naturals. *)
-Inductive my_nat_list := EmptyList | NatList : nat -> my_nat_list -> my_nat_list.
+Inductive my_nat_list :=
+ EmptyList | NatList : nat -> my_nat_list -> my_nat_list.
+
Compute NatList 1 EmptyList. (* NatList 1 EmptyList : my_nat_list *)
(** Matching type constructors **)
@@ -427,31 +450,38 @@ Compute sum_list [1; 2; 3]. (* Evaluates to 6 *)
(*** A Taste of Proving ***)
-(* Explaining the proof language is out of scope for this tutorial, but here is a taste to
- whet your appetite. Check the resources below for more. *)
+(* Explaining the proof language is out of scope for this tutorial, but here
+ is a taste to whet your appetite. Check the resources below for more. *)
+
+(* A fascinating feature of dependently type based theorem provers is that
+ the same primitive constructs underly the proof language as the
+ programming features. For example, we can write and prove the
+ proposition A and B implies A in raw Gallina *)
-(* A fascinating feature of dependently type based theorem provers is that the same
- primitive constructs underly the proof language as the programming features.
- For example, we can write and prove the proposition A and B implies A in raw Gallina *)
+Definition my_theorem : forall A B, A /\ B -> A :=
+ fun A B ab => match ab with
+ | (conj a b) => a
+ end.
-Definition my_theorem : forall A B, A /\ B -> A := fun A B ab => match ab with
- | (conj a b) => a
- end.
+(* Or we can prove it using tactics. Tactics are a macro language to help
+ build proof terms in a more natural style and automate away some
+ drudgery. *)
-(* Or we can prove it using tactics. Tactics are a macro language to help build proof terms
- in a more natural style and automate away some drudgery. *)
Theorem my_theorem2 : forall A B, A /\ B -> A.
Proof.
intros A B ab. destruct ab as [ a b ]. apply a.
Qed.
-(* We can prove easily prove simple polynomial equalities using the automated tactic ring. *)
+(* We can prove easily prove simple polynomial equalities using the
+ automated tactic ring. *)
+
Require Import Ring.
Require Import Arith.
Theorem simple_poly : forall (x : nat), (x + 1) * (x + 2) = x * x + 3 * x + 2.
Proof. intros. ring. Qed.
-(* Here we prove the closed form for the sum of all numbers 1 to n using induction *)
+(* Here we prove the closed form for the sum of all numbers 1 to n using
+ induction *)
Fixpoint sumn (n : nat) : nat :=
match n with
@@ -465,8 +495,10 @@ Proof. intros n. induction n.
- simpl. ring [IHn]. (* induction step *)
Qed.
```
-
-With this we have only scratched the surface of Coq. It is a massive ecosystem with many interesting and peculiar topics leading all the way up to modern research.
+
+With this we have only scratched the surface of Coq. It is a massive
+ecosystem with many interesting and peculiar topics leading all the way up
+to modern research.
## Further reading
diff --git a/csharp.html.markdown b/csharp.html.markdown
index 37573e01..b965c2d4 100644
--- a/csharp.html.markdown
+++ b/csharp.html.markdown
@@ -653,10 +653,10 @@ on a new line! ""Wow!"", the masses cried";
return ++count;
}
- // A delegate is a reference to a method
+ // A delegate is a reference to a method.
// To reference the Increment method,
- // first declare a delegate with the same signature
- // ie. takes no arguments and returns an int
+ // first declare a delegate with the same signature,
+ // i.e. takes no arguments and returns an int
public delegate int IncrementDelegate();
// An event can also be used to trigger delegates
@@ -727,10 +727,10 @@ on a new line! ""Wow!"", the masses cried";
int _speed; // Everything is private by default: Only accessible from within this class.
// can also use keyword private
public string Name { get; set; }
-
+
// Properties also have a special syntax for when you want a readonly property
// that simply returns the result of an expression
- public string LongName => Name + " " + _speed + " speed";
+ public string LongName => Name + " " + _speed + " speed";
// Enum is a value type that consists of a set of named constants
// It is really just mapping a name to a value (an int, unless specified otherwise).
@@ -1091,7 +1091,7 @@ on a new line! ""Wow!"", the masses cried";
// Spell failed
return false;
}
- // Other exceptions, or MagicServiceException where Code is not 42
+ // Other exceptions, or MagicServiceException where Code is not 42
catch(Exception ex) when (LogException(ex))
{
// Execution never reaches this block
@@ -1215,7 +1215,7 @@ namespace Csharp7
Console.WriteLine(tt.GetLastName());
}
}
-
+
// PATTERN MATCHING
class PatternMatchingTest
{
@@ -1315,8 +1315,10 @@ namespace Csharp7
* [C# language reference](https://docs.microsoft.com/dotnet/csharp/language-reference/)
* [Learn .NET](https://dotnet.microsoft.com/learn)
* [C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions)
- * [DotNetPerls](https://www.dotnetperls.com/)
- * [C# in Depth](https://manning.com/skeet3)
- * [Programming C# 5.0](http://shop.oreilly.com/product/0636920024064)
- * [LINQ Pocket Reference](http://shop.oreilly.com/product/9780596519254)
- * [Windows Forms Programming in C#](https://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208)
+ * [DotNetPerls](http://www.dotnetperls.com)
+ * [C# in Depth](http://manning.com/skeet2)
+ * [Programming C# 5.0](http://shop.oreilly.com/product/0636920024064.do)
+ * [LINQ Pocket Reference](http://shop.oreilly.com/product/9780596519254.do)
+ * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208)
+ * [freeCodeCamp - C# Tutorial for Beginners](https://www.youtube.com/watch?v=GhQdlIFylQ8)
+ \ No newline at end of file
diff --git a/d.html.markdown b/d.html.markdown
index d2a57cae..93c08da2 100644
--- a/d.html.markdown
+++ b/d.html.markdown
@@ -212,6 +212,7 @@ found in the wonderful `std.algorithm` module!
```d
import std.algorithm : map, filter, reduce;
import std.range : iota; // builds an end-exclusive range
+import std.stdio;
void main() {
// We want to print the sum of a list of squares of even ints
diff --git a/dart.html.markdown b/dart.html.markdown
index 3b94a254..e6c66332 100644
--- a/dart.html.markdown
+++ b/dart.html.markdown
@@ -73,6 +73,7 @@ example1() {
nested2() => print("Example1 nested 1 nested 2");
nested2();
}
+
nested1();
}
@@ -82,6 +83,7 @@ example2() {
nested1(Function<void> fn) {
fn();
}
+
nested1(() => print("Example2 nested 1"));
}
@@ -92,9 +94,11 @@ example3() {
planA(fn(String informSomething)) {
fn("Example3 plan A");
}
- planB(fn) { /// Or don't declare number of parameters.
+ planB(fn) {
+ // Or don't declare number of parameters.
fn("Example3 plan B");
}
+
planA((s) => print(s));
planB((s) => print(s));
}
@@ -107,17 +111,20 @@ example4() {
nested1(fn(informSomething)) {
fn(example4Something);
}
+
nested1((s) => print(s));
}
/// Class declaration with a sayIt method, which also has closure access
/// to the outer variable as though it were a function as seen before.
var example5method = "Example5 sayIt";
+
class Example5Class {
sayIt() {
print(example5method);
}
}
+
example5() {
/// Create an anonymous instance of the Example5Class and call the sayIt
/// method on it.
@@ -134,6 +141,7 @@ class Example6Class {
print(instanceVariable);
}
}
+
example6() {
Example6Class().sayIt();
}
@@ -144,10 +152,12 @@ class Example7Class {
static sayItFromClass() {
print(classVariable);
}
+
sayItFromInstance() {
print(classVariable);
}
}
+
example7() {
Example7Class.sayItFromClass();
new Example7Class().sayItFromInstance();
@@ -289,6 +299,7 @@ example13() {
print("Example13 regexp doesn't match '${s}'");
}
}
+
match(s1);
match(s2);
}
@@ -357,9 +368,11 @@ example15() {
/// StringBuffer. Or you could join a string array.
example16() {
var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e;
- for (e in a) { sb.write(e); }
+ for (e in a) {
+ sb.write(e);
+ }
print("Example16 dynamic string created with "
- "StringBuffer '${sb.toString()}'");
+ "StringBuffer '${sb.toString()}'");
print("Example16 join string array '${a.join()}'");
}
@@ -420,11 +433,13 @@ class Example21 {
set names(List<String> list) {
_names = list;
}
+
int get length => _names.length;
void add(String name) {
_names.add(name);
}
}
+
void example21() {
Example21 o = new Example21();
o.add("c");
@@ -438,7 +453,9 @@ class Example22A {
var _name = "Some Name!";
get name => _name;
}
+
class Example22B extends Example22A {}
+
example22() {
var o = new Example22B();
print("Example22 class inheritance '${o.name}'");
@@ -452,19 +469,21 @@ example22() {
/// single inheritance doesn't get in the way of reusable code.
/// Mixins follow the "with" statement during the class declaration.
class Example23A {}
+
class Example23Utils {
addTwo(n1, n2) {
return n1 + n2;
}
}
+
class Example23B extends Example23A with Example23Utils {
addThree(n1, n2, n3) {
return addTwo(n1, n2) + n3;
}
}
+
example23() {
- var o = new Example23B(), r1 = o.addThree(1, 2, 3),
- r2 = o.addTwo(1, 2);
+ var o = new Example23B(), r1 = o.addThree(1, 2, 3), r2 = o.addTwo(1, 2);
print("Example23 addThree(1, 2, 3) results in '${r1}'");
print("Example23 addTwo(1, 2) results in '${r2}'");
}
@@ -480,12 +499,13 @@ class Example24A {
}
get value => _value;
}
+
class Example24B extends Example24A {
Example24B({value: "someOtherValue"}) : super(value: value);
}
+
example24() {
- var o1 = new Example24B(),
- o2 = new Example24B(value: "evenMore");
+ var o1 = new Example24B(), o2 = new Example24B(value: "evenMore");
print("Example24 calling super during constructor '${o1.value}'");
print("Example24 calling super during constructor '${o2.value}'");
}
@@ -497,10 +517,11 @@ class Example25 {
var value, anotherValue;
Example25({this.value, this.anotherValue});
}
+
example25() {
var o = new Example25(value: "a", anotherValue: "b");
print("Example25 shortcut for constructor '${o.value}' and "
- "'${o.anotherValue}'");
+ "'${o.anotherValue}'");
}
/// Named parameters are available when declared between {}.
@@ -512,17 +533,19 @@ example26() {
_name = name;
_surname = surname;
}
+
setConfig2(name, [surname, email]) {
_name = name;
_surname = surname;
_email = email;
}
+
setConfig1(surname: "Doe", name: "John");
print("Example26 name '${_name}', surname '${_surname}', "
- "email '${_email}'");
+ "email '${_email}'");
setConfig2("Mary", "Jane");
print("Example26 name '${_name}', surname '${_surname}', "
- "email '${_email}'");
+ "email '${_email}'");
}
/// Variables declared with final can only be set once.
@@ -534,6 +557,7 @@ class Example27 {
/// that follows the :
Example27({this.color1, color2}) : color2 = color2;
}
+
example27() {
final color = "orange", o = new Example27(color1: "lilac", color2: "white");
print("Example27 color is '${color}'");
@@ -552,6 +576,7 @@ class Example28 extends IterableBase {
}
get iterator => names.iterator;
}
+
example28() {
var o = new Example28();
o.forEach((name) => print("Example28 '${name}'"));
@@ -577,10 +602,12 @@ example29() {
callItForMe(fn()) {
return fn();
}
+
rand() {
v = new DM.Random().nextInt(50);
return v;
}
+
while (true) {
print("Example29 callItForMe(rand) '${callItForMe(rand)}'");
if (v != 30) {
@@ -595,8 +622,12 @@ example29() {
/// Parse int, convert double to int, or just keep int when dividing numbers
/// by using the ~/ operation. Let's play a guess game too.
example30() {
- var gn, tooHigh = false,
- n, n2 = (2.0).toInt(), top = int.parse("123") ~/ n2, bottom = 0;
+ var gn,
+ tooHigh = false,
+ n,
+ n2 = (2.0).toInt(),
+ top = int.parse("123") ~/ n2,
+ bottom = 0;
top = top ~/ 6;
gn = new DM.Random().nextInt(top + 1); /// +1 because nextInt top is exclusive
print("Example30 Guess a number between 0 and ${top}");
@@ -606,10 +637,11 @@ example30() {
} else {
tooHigh = n > gn;
print("Example30 Number ${n} is too "
- "${tooHigh ? 'high' : 'low'}. Try again");
+ "${tooHigh ? 'high' : 'low'}. Try again");
}
return n == gn;
}
+
n = (top - bottom) ~/ 2;
while (!guessNumber(n)) {
if (tooHigh) {
@@ -671,12 +703,15 @@ var hasValue ??= "default Value";
/// the program needs to startup with.
main() {
print("Learn Dart in 15 minutes!");
- [example1, example2, example3, example4, example5, example6, example7,
- example8, example9, example10, example11, example12, example13, example14,
- example15, example16, example17, example18, example19, example20,
- example21, example22, example23, example24, example25, example26,
- example27, example28, example29, example30, example31, example32, example33
- ].forEach((ef) => ef());
+ [
+ example1, example2, example3, example4, example5,
+ example6, example7, example8, example9, example10,
+ example11, example12, example13, example14, example15,
+ example16, example17, example18, example19, example20,
+ example21, example22, example23, example24, example25,
+ example26, example27, example28, example29,
+ example30 // Adding this comment stops the dart formatter from putting all items on a new line
+ ].forEach((ef) => ef());
}
```
diff --git a/de-de/bash-de.html.markdown b/de-de/bash-de.html.markdown
index 3fb3e71f..3a76708a 100644
--- a/de-de/bash-de.html.markdown
+++ b/de-de/bash-de.html.markdown
@@ -157,7 +157,7 @@ echo "#helloworld" | cat > output.out
echo "#helloworld" | tee output.out >/dev/null
# Löschen der Hilfsdateien von oberhalb, mit Anzeige der Dateinamen
-# (mit '-i' für "interactive" erfolgt für jede Date eine Rückfrage)
+# (mit '-i' für "interactive" erfolgt für jede Datei eine Rückfrage)
rm -v output.out error.err output-and-error.log
# Die Ausgabe von Befehlen kann mit Hilfe von $( ) in anderen Befehlen verwendet weden:
diff --git a/de-de/bc.html.markdown b/de-de/bc.html.markdown
new file mode 100644
index 00000000..49a2878d
--- /dev/null
+++ b/de-de/bc.html.markdown
@@ -0,0 +1,102 @@
+---
+language: bc
+contributors:
+ - ["caminsha", "https://github.com/caminsha"]
+filename: learnbc-de.bc
+lang: de-de
+---
+```c
+/* Das is ein mehr-
+zeiliger Kommentar */
+# Das ist ein (einzeiliger) Kommentar (in GNU bc).
+
+ /*1. Variablen und Kontrollstrukturen*/
+num = 45 /* Alle Variablen speichern nur Doubles und es ist
+ nicht möglich String-Konstanten direkt zu speichern */
+num = 45; /* Es kann nach jedem Statement ein optionales Semikolon
+ hinzugefügt werden */
+/* Blöcke werden mit den Operatoren {} (ähnlich wie in C) bezeichnet */
+while(num < 50) {
+ num += 1 /* äquivalent zu num=num+1.
+ a = a Op b ist äquivalent zu a Op= b*/
+}
+/* Ausserdem gibt es ++ (Inkrement) und -- (Dekrement) Operatoren */
+/* Es gibt 3 spezielle Variablen:
+scale: definiert die Anzahl Nachkommastellen
+ibase: definiert die Basis der Eingabe
+obase: definiert die Basis der Ausgabe*/
+/*Wenn-Bedingungen:*/
+hour = read() /*Eingabe einer Zahl*/
+
+if(hour < 12) { /*Operatoren sind genau wie in C*/
+ print "Guten Morgen\n" /*"print" Gibt Strings oder Variablen
+ mit einem Komma separiert aus.*/
+} else if(hour == 12) {
+ print "Hallo\n"
+ /* Escape-Sequenzen starten mite einem \ in einem String.
+ Um Escape-Sequenzen klarer zu machen, ist hier eine vereinfachte
+ Liste, welche in bc funktioneren.:
+ \b: Backspace
+ \c: carriage return
+ \n: Zeilenumbruch
+ \t: Tab
+ \\: Backslash*/
+} else {
+ /* Standardmässig sind Variablen global. */
+ thisIsGlobal = 5
+ /*Variablen können lokal gemacht werden. Benutze das Schlüsselwort "auto"
+ in einer Funktion.*/
+}
+
+/* Jede Variable hat als Voreinstellung den Wert 0. */
+num = blankVariable /*num wurde auf 0 gesetzt.*/
+
+/*Wie in C ist nur 0 falsch.*/
+if(!num) {print "false\n"}
+
+/*Im Gegensatz zu C hat bc den Ternäroperator ?: nicht. Zum Beispiel
+führt dieser Codeblok zu einem Fehler:
+a = (num) ? 1 : 0
+Jedoch kann dies simuliert werden:*/
+a = (num) && (1) || (0) /*&& ist das UND, || ist das ODER*/
+
+/*For-Schleifen*/
+num = 0
+for(i = 1; i <= 100; i++) {/*Gleich wie die For-Schleife in C*/
+ num += i
+}
+
+ /*2.Funktionen und Arrays*/
+define fac(n) { /*Definiere eine Funktion mit define*/
+ if(n == 1 || n == 0) {
+ return 1 /*Gebe einen Wert zurück*/
+ }
+ return n * fac(n - 1) /*Rekursion ist möglich*/
+}
+
+/*Closures und anonyme Funktionen sind nicht möglich */
+
+num = fac(4) /*24*/
+
+/*Dies ist ein Beispiel von lokalen Variabeln.*/
+define x(n) {
+ auto x
+ x = 1
+ return n + x
+}
+x(3) /*4*/
+print x /*Es stellt sich heraus, dass x ausserhalb der Funktion nicht
+ zugänglich ist.*/
+/*Arrays sind äquivalent zu C Arrays.*/
+for(i = 0; i <= 3; i++) {
+ a[i] = 1
+}
+/*Greife wie folgt darauf zu:*/
+print a[0], " ", a[1], " ", a[2], " ", a[3], "\n"
+quit /* Füge diese Codezeile hinzu, um sicherzustellen, dass
+das Programm beendet. Diese Codezeile ist optional.*/
+```
+Viel Spass mit diesem einfachen Rechner! (Oder dieser Programmiersprache, um exakt zu sein.)
+
+Das ganze Programm wurde in GNU bc geschrieben. Um es auszuführen, benutze ```bc learnbc.bc```.
+
diff --git a/de-de/css-de.html.markdown b/de-de/css-de.html.markdown
index c31e73d2..da706e91 100644
--- a/de-de/css-de.html.markdown
+++ b/de-de/css-de.html.markdown
@@ -27,7 +27,7 @@ In diesem Artikel wird am meisten auf generelle Hinweise und die Syntax geachtet
####################*/
/* Eigentlich ist das grundlegende CSS-Statement sehr simpel */
-selektor { eigenschaft: wert; /* mehr eigenschaften...*/ }
+selektor { eigenschaft: wert; /* mehr Eigenschaften...*/ }
/* Der Selektor wird dazu benutzt, ein Element auf der Seite auszuwählen.
@@ -35,7 +35,7 @@ Man kann aber auch alle Elemente auf einer Seite auswählen! */
* { color:red; } /* farbe:rot */
/*
-Angenommen wir haben folgendes Element auf einer Seite:
+Angenommen, wir haben folgendes Element auf einer Seite:
<div class='eine-klasse klasse2' id='eineId' attr='wert' />
*/
@@ -170,7 +170,7 @@ empfohlen ist -->
## Spezifität
Ein Element kann natürlich auch von mehr als einer Regel in einem Stylesheet
-angesprochen werdenm und kann eine Eigenschaft auch öfters als einmal zugewiesen
+angesprochen werden und kann eine Eigenschaft auch öfters als einmal zugewiesen
bekommen. In diesen Fällen gibt es Regeln, die die Spezifität von Selektoren regeln.
Wir haben dieses CSS:
diff --git a/de-de/html-de.html.markdown b/de-de/html-de.html.markdown
index 0bf58f9c..8b5597e7 100644
--- a/de-de/html-de.html.markdown
+++ b/de-de/html-de.html.markdown
@@ -50,10 +50,10 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
<!-- Danach startet sie mit einem Öffnungtag <html>. -->
<html>
-<!-- Dieser wird am Ende der Datei mit</html> geschlossen. -->
+<!-- Dieser wird am Ende der Datei mit </html> geschlossen. -->
</html>
-<!-- Nichts sollte nach diesen finalen Tag erscheinen. -->
+<!-- Nichts sollte nach diesem finalen Tag erscheinen. -->
<!-- Dazwischen (Zwischen dem Öffnungs- und Schließungstag <html></html>) finden wir: -->
@@ -65,13 +65,13 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
</head>
<!-- Nach dem <head> Bereich findet sich der <body> Tag -->
-<!-- Bis zu diesen Punkt wird nichts im Browerfenster angezeigt. -->
-<!-- Wir müssen den Body mit dem Inhalt füllen der angezeigt werden soll. -->
+<!-- Bis zu diesem Punkt wird nichts im Browerfenster angezeigt. -->
+<!-- Wir müssen den Body mit dem Inhalt füllen, der angezeigt werden soll. -->
<body>
<h1>Hallo, Welt!</h1> <!-- Der h1 Tag erstellt einen Titel. -->
<!-- Es gibt auch Untertitel für <h1> von den wichtigsten <h2> zu den Unwichtigsten (h6). -->
- <a href = "http://codepen.io/anon/pen/xwjLbZ">Komm, schaue was das zeigt</a> <!-- Eine URL wird zum Hyperlink, wenn es das Attribut href="" -->
+ <a href = "http://codepen.io/anon/pen/xwjLbZ">Komm, schaue was das zeigt</a> <!-- Eine URL wird zum Hyperlink, wenn es das Attribut href="" hat -->
<p>Das ist ein Absatz.</p> <!-- Der Tag <p> lässt uns Text auf die HTML Seite hinzufügen. -->
<p>Das ist ein anderer Absatz.</p>
<ul> <!-- Der <ul> Tag erstellt eine Aufzählungsliste. -->
@@ -93,12 +93,12 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
<!-- Es ist ebenso möglich eine Tabelle zu erstellen. -->
<table> <!-- Wir öffnen ein <table> Element. -->
- <tr> <!-- <tr> erlaubt es uns Reihe zu erstellen. -->
- <th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns der Tabelle einen Titel zu geben. -->
+ <tr> <!-- <tr> erlaubt es uns, Reihen zu erstellen. -->
+ <th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns, der Tabelle einen Titel zu geben. -->
<th>Zweiter Tabllenkopf</th>
</tr>
<tr>
- <td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es eine Tabellenzelle zu erstellen. -->
+ <td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es, eine Tabellenzelle zu erstellen. -->
<td>Erste Zeile, zweite Spalte</td>
</tr>
<tr>
diff --git a/de-de/java-de.html.markdown b/de-de/java-de.html.markdown
index e8ac5bda..e52087ec 100644
--- a/de-de/java-de.html.markdown
+++ b/de-de/java-de.html.markdown
@@ -477,7 +477,7 @@ Für tiefergreifende Fragen ist Google der beste Startpunkt.
* [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html)
-* [Java Code Conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html)
+* [Java Code Conventions](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf)
**Online Tutorials**
diff --git a/de-de/latex-de.html.markdown b/de-de/latex-de.html.markdown
index ee9c6e3e..8a952b15 100644
--- a/de-de/latex-de.html.markdown
+++ b/de-de/latex-de.html.markdown
@@ -39,13 +39,13 @@ filename: latex-de.tex
% Dieses Kommando kann man später benutzen.
\newcommand{\comment}[1]{}
-% Es können durchaus noch weitere Optione für das Dokument gesetzt werden!
+% Es können durchaus noch weitere Optionen für das Dokument gesetzt werden!
\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu}
\date{\today}
\title{Learn \LaTeX\ in Y Minutes!}
% Nun kann's losgehen mit unserem Dokument.
-% Alles vor dieser Zeile wird die Preamble genannt.
+% Alles vor dieser Zeile wird die Präambel genannt.
\begin{document}
\comment{
@@ -62,7 +62,7 @@ filename: latex-de.tex
% Inhalt erscheinen.
% Dieser Befehl ist in den Dokumentenklassen article und report verfügbar.
\begin{abstract}
- \LaTeX -Documentation geschrieben in \LaTeX ! Wie ungewöhnlich und garantiert nicht meine Idee!
+ \LaTeX -Dokumentation geschrieben in \LaTeX ! Wie ungewöhnlich und garantiert nicht meine Idee!
\end{abstract}
% Section Befehle sind intuitiv.
@@ -113,7 +113,7 @@ anderen Wissenschaften. Und deswegen müssen wir in der Lage sein, spezielle
Symbole zu unserem Paper hinzuzufügen! \\
Mathe kennt sehr viele Symbole, viel mehr als auf einer Tastatur zu finden sind;
-Symbole für Mengen und relationen, Pfeile, Operatoren und Griechische Buchstaben,
+Symbole für Mengen und Relationen, Pfeile, Operatoren und Griechische Buchstaben,
um nur ein paar zu nennen.\\
Mengen und Relationen spielen eine sehr wichtige Rolle in vielen mathematischen
diff --git a/de-de/make-de.html.markdown b/de-de/make-de.html.markdown
index cf90dc29..1bae332c 100644
--- a/de-de/make-de.html.markdown
+++ b/de-de/make-de.html.markdown
@@ -11,14 +11,14 @@ lang: de-de
---
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
-zu erzeugen. Es dient dazu die geringste Menge an Arbeit zu verrichten um
-ein Ziel in einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
+zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
+ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
-sehr verbreitet (vorallem im Unix umfeld) obwohl es bereits sehr viel
+sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
Konkurrenz und Kritik zu Make gibt.
-Es gibt eine vielzahl an Varianten von Make, dieser Artikel beschäftig sich
-mit der Version GNU Make. Diese Version ist standard auf Linux.
+Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
+mit der Version GNU Make. Diese Version ist Standard auf Linux.
```make
@@ -44,14 +44,15 @@ file0.txt:
# die erste Regel ist die Standard-Regel.
-# Diese Regel wird nur abgearbeitet wenn file0.txt aktueller als file1.txt ist.
+# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
file1.txt: file0.txt
cat file0.txt > file1.txt
# Verwende die selben Quoting-Regeln wie die Shell
@cat file0.txt >> file1.txt
# @ unterdrückt die Ausgabe des Befehls an stdout.
-@echo 'hello'
- # - bedeutet das Make die Abarbeitung fortsetzt auch wenn Fehler passieren.
+ # - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
+ # passieren.
# Versuche `make file1.txt` auf der Kommandozeile.
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
@@ -59,7 +60,7 @@ file2.txt file3.txt: file0.txt file1.txt
touch file2.txt
touch file3.txt
-# Make wird sich beschweren wenn es mehrere Rezepte für die gleiche Regel gibt.
+# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
# Voraussetzungen hinzuzufügen.
@@ -67,8 +68,8 @@ file2.txt file3.txt: file0.txt file1.txt
# Phony-Ziele
#-----------------------------------------------------------------------
-# Ein Phony-Ziel ist ein Ziel das keine Datei ist.
-# Es wird nie aktuell sein, daher wird Make immer versuchen es abzuarbeiten
+# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
+# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
all: maker process
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
@@ -89,14 +90,14 @@ ex0.txt ex1.txt: maker
# Automatische Variablen & Wildcards
#-----------------------------------------------------------------------
-process: file*.txt # Eine Wildcard um Dateinamen zu Vergleichen
+process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
@echo $^ # $^ ist eine Variable die eine Liste aller
# Voraussetzungen enthält.
@echo $@ # Namen des Ziels ausgeben.
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
#der Regel.)
@echo $< # Die erste Voraussetzung aus der Liste
- @echo $? # Nur die Voraussetzungen die nicht aktuell sind.
+ @echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
#@echo $| # Alle 'order only' Voraussetzungen
@@ -114,20 +115,20 @@ process: ex1.txt file0.txt
%.png: %.svg
inkscape --export-png $^
-# Muster-Vergleichs-Regeln werden nur abgearbeitet wenn make entscheidet das Ziel zu
-# erzeugen
+# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
+# Ziel zu erzeugen
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
# Aber make wird versuchen die am besten passende Regel zu verwenden.
small/%.png: %.svg
inkscape --export-png --export-dpi 30 $^
-# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden die es
+# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
# findet.
%.png: %.svg
@echo this rule is chosen
-# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden die das
+# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
# Ziel erzeugen kann.
%.png: %.ps
@echo this rule is not chosen if *.svg and *.ps are both present
@@ -171,7 +172,7 @@ name4 ?= Jean
# nicht gibt.
override name5 = David
-# Verhindert das Kommando-Zeilen Argumente diese Variable ändern können.
+# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
name4 +=grey
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
@@ -179,9 +180,9 @@ name4 +=grey
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
- # kann wenn es zu kompilizert wird!)
+ # kann, wenn es zu kompilizert wird!)
-# Ein paar Variablen die von Make automatisch definiert werden.
+# Ein paar Variablen, die von Make automatisch definiert werden.
echo_inbuilt:
echo $(CC)
echo ${CXX}
@@ -196,7 +197,7 @@ echo_inbuilt:
# Variablen 2
#-----------------------------------------------------------------------
-# Der erste Typ von Variablen wird bei jeder verwendung ausgewertet.
+# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
@@ -215,7 +216,7 @@ var4 ::= good night
# Funktionen
#-----------------------------------------------------------------------
-# Make verfügt über eine vielzahl von Funktionen.
+# Make verfügt über eine Vielzahl von Funktionen.
sourcefiles = $(wildcard *.c */*.c)
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
diff --git a/docker.html.markdown b/docker.html.markdown
new file mode 100644
index 00000000..24f85247
--- /dev/null
+++ b/docker.html.markdown
@@ -0,0 +1,146 @@
+---
+language: docker
+filename: docker.bat
+contributors:
+ - ["Ruslan López", "http://javapro.org/"]
+---
+
+```
+:: download, install and run hello-world image
+docker run hello-world
+
+:: if this is the first time you should be able to see the message
+:: Unable to find image 'hello-world:latest' locally
+:: latest: Pulling from library/hello-world
+:: 1b930d010525: Pull complete
+:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
+:: Status: Downloaded newer image for hello-world:latest
+::
+:: Hello from Docker!
+:: This message shows that your installation appears to be working correctly.
+::
+:: To generate this message, Docker took the following steps:
+:: 1. The Docker client contacted the Docker daemon.
+:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
+:: (amd64)
+:: 3. The Docker daemon created a new container from that image which runs the
+:: executable that produces the output you are currently reading.
+:: 4. The Docker daemon streamed that output to the Docker client, which sent it
+:: to your terminal.
+::
+:: To try something more ambitious, you can run an Ubuntu container with:
+:: $ docker run -it ubuntu bash
+::
+:: Share images, automate workflows, and more with a free Docker ID:
+:: https://hub.docker.com/
+::
+:: For more examples and ideas, visit:
+:: https://docs.docker.com/get-started/
+
+:: now lets see currently running images
+docker ps
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+
+:: lets see the images we have ran previously
+docker ps -a
+
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
+:: happy_poincare
+:: the name part is generated automatically so it probably will be different for you
+
+:: let's remove our previously generated image
+docker rm happy_poincare
+
+:: lets test if it was really deleted
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+
+:: specify a custom name for the container
+docker run --name test_container hello-world
+:: Hello from Docker!
+:: This message shows that your installation appears to be working correctly.
+::
+:: To generate this message, Docker took the following steps:
+:: 1. The Docker client contacted the Docker daemon.
+:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
+:: (amd64)
+:: 3. The Docker daemon created a new container from that image which runs the
+:: executable that produces the output you are currently reading.
+:: 4. The Docker daemon streamed that output to the Docker client, which sent it
+:: to your terminal.
+::
+:: To try something more ambitious, you can run an Ubuntu container with:
+:: $ docker run -it ubuntu bash
+::
+:: Share images, automate workflows, and more with a free Docker ID:
+:: https://hub.docker.com/
+::
+:: For more examples and ideas, visit:
+:: https://docs.docker.com/get-started/
+
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
+:: test_container
+:: as you can see the name is now what we have specified
+
+:: retireve logs from a named container
+docker logs test_container
+:: Hello from Docker!
+:: This message shows that your installation appears to be working correctly.
+::
+:: To generate this message, Docker took the following steps:
+:: 1. The Docker client contacted the Docker daemon.
+:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
+:: (amd64)
+:: 3. The Docker daemon created a new container from that image which runs the
+:: executable that produces the output you are currently reading.
+:: 4. The Docker daemon streamed that output to the Docker client, which sent it
+:: to your terminal.
+::
+:: To try something more ambitious, you can run an Ubuntu container with:
+:: $ docker run -it ubuntu bash
+::
+:: Share images, automate workflows, and more with a free Docker ID:
+:: https://hub.docker.com/
+::
+:: For more examples and ideas, visit:
+:: https://docs.docker.com/get-started/
+
+docker rm test_container
+
+docker run ubuntu
+:: Unable to find image 'ubuntu:latest' locally
+:: latest: Pulling from library/ubuntu
+:: 2746a4a261c9: Pull complete
+:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
+:: Status: Downloaded newer image for ubuntu:latest
+
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
+:: relaxed_nobel
+
+:: running a container in an interactive mode
+docker run -it ubuntu
+:: root@e2cac48323d2:/# uname
+:: Linux
+:: root@e2cac48323d2:/# exit
+:: exit
+
+docker rm relaxed_nobel
+
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
+:: nifty_goldwasser
+
+docker rm nifty_goldwasser
+``` \ No newline at end of file
diff --git a/dynamic-programming.html.markdown b/dynamic-programming.html.markdown
index c73b1845..5d260206 100644
--- a/dynamic-programming.html.markdown
+++ b/dynamic-programming.html.markdown
@@ -3,6 +3,7 @@ category: Algorithms & Data Structures
name: Dynamic Programming
contributors:
- ["Akashdeep Goel", "http://github.com/akashdeepgoel"]
+ - ["Miltiadis Stouras", "https://github.com/mstou"]
---
# Dynamic Programming
@@ -48,6 +49,15 @@ for i=0 to n-1
## Online Resources
-* [codechef](https://www.codechef.com/wiki/tutorial-dynamic-programming)
+* MIT 6.006: [Lessons 19,20,21,22](https://www.youtube.com/playlist?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)
+* TopCoder: [Dynamic Programming from Novice to Advanced](https://www.topcoder.com/community/data-science/data-science-tutorials/dynamic-programming-from-novice-to-advanced/)
+* [CodeChef](https://www.codechef.com/wiki/tutorial-dynamic-programming)
* [InterviewBit](https://www.interviewbit.com/courses/programming/topics/dynamic-programming/)
-
+* GeeksForGeeks:
+ * [Overlapping Subproblems](https://www.geeksforgeeks.org/dynamic-programming-set-1/)
+ * [Tabulation vs Memoization](https://www.geeksforgeeks.org/tabulation-vs-memoizatation/)
+ * [Optimal Substructure Property](https://www.geeksforgeeks.org/dynamic-programming-set-2-optimal-substructure-property/)
+ * [How to solve a DP problem](https://www.geeksforgeeks.org/solve-dynamic-programming-problem/)
+* [How to write DP solutions](https://www.quora.com/Are-there-any-good-resources-or-tutorials-for-dynamic-programming-DP-besides-the-TopCoder-tutorial/answer/Michal-Danilák)
+
+And a [quiz](https://www.commonlounge.com/discussion/cdbbfe83bcd64281964b788969247253) to test your knowledge.
diff --git a/el-gr/python3-gr.html.markdown b/el-gr/python3-gr.html.markdown
new file mode 100644
index 00000000..08c3d4aa
--- /dev/null
+++ b/el-gr/python3-gr.html.markdown
@@ -0,0 +1,1030 @@
+---
+language: python3
+contributors:
+ - ["Louie Dinh", "http://pythonpracticeprojects.com"]
+ - ["Steven Basart", "http://github.com/xksteven"]
+ - ["Andre Polykanine", "https://github.com/Oire"]
+ - ["Zachary Ferguson", "http://github.com/zfergus2"]
+ - ["evuez", "http://github.com/evuez"]
+ - ["Rommel Martinez", "https://ebzzry.io"]
+ - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"]
+filename: learnpython3.py
+---
+
+Η Python δημιουργήθηκε από τον Guido van Rossum στις αρχές των 90s. Πλέον είναι μία από τις πιο
+δημοφιλείς γλώσσες. Ερωτευεται κανείς την python για τη συντακτική της απλότητα.
+Βασικά είναι εκτελέσιμος ψευδοκώδικας.
+
+Το Feedback είναι πάντα δεκτό! Μπορείτε να με βρείτε στο [@haritonaras](http://twitter.com/haritonaras)
+ή τον αρχικό συγγραφέα στο [@louiedinh](http://twitter.com/louiedinh) ή στο
+louiedinh [at] [google's email service]
+
+Σημείωση: Το παρόν άρθρο ασχολείται μόνο με την Python 3. Δείτε [εδώ](http://learnxinyminutes.com/docs/python/) αν θέλετε να μάθετε την παλιά Python 2.7
+
+```python
+
+# Τα σχόλια μίας γραμμής ξεκινούν με #
+
+""" Τα σχόλια πολλαπλών γραμμών μπορούν
+ να γραφούν με τρία ", και συχνά χρησιμοποιούνται
+ ως documentation.
+"""
+
+####################################################
+## 1. Primitive (πρωταρχικοί) Τύποι Δεδομένων και Τελεστές
+####################################################
+
+# Αφού έχει αριθμούς
+3 # => 3
+
+# Λογικά θα έχει και Μαθηματικά...
+1 + 1 # => 2
+8 - 1 # => 7
+10 * 2 # => 20
+35 / 5 # => 7.0
+
+# Η διαίρεση ακεραίων κάνει στρογγυλοποίηση προς τα κάτω για θετικούς και αρνητικούς αριθμούς
+5 // 3 # => 1
+-5 // 3 # => -2
+5.0 // 3.0 # => 1.0 # works on floats too
+-5.0 // 3.0 # => -2.0
+
+# Το αποτέλεσμα της διαίρεσης είναι πάντα float
+10.0 / 3 # => 3.3333333333333335
+
+# Modulo τελεστής
+7 % 3 # => 1
+
+# Ύψωση σε δύναμη (x**y, x στην y-οστή δύναμη)
+2**3 # => 8
+
+# Ελέγχουμε την προτεραιότητα πράξεων με παρενθέσεις
+(1 + 3) * 2 # => 8
+
+# Οι Boolean τιμές είναι primitives (Σημ.: τα κεφαλαία)
+True
+False
+
+# άρνηση με το not
+not True # => False
+not False # => True
+
+# Boolean τελεστές
+# Σημ. ότι τα "and" και "or" είναι case-sensitive
+True and False # => False
+False or True # => True
+
+# Τα True και False είναι 1 και 0 αλλά με διαφορετικά keywords
+True + True # => 2
+True * 8 # => 8
+False - 5 # => -5
+
+# Μπορούμε να δούμε τις αριθμητικές τιμές των True και False μέσω των τελεστών σύγκρισης
+0 == False # => True
+1 == True # => True
+2 == True # => False
+-5 != False # => True
+
+# Χρησιμοποιώντας τελεστές boolean σε ακεραίους, οι ακέραιοι γίνονται cast σε
+# boolean ώστε να γίνει η αποτίμηση της έκφρασης.
+# Το αποτέλεσμα όμως είναι non-cast, δηλαδή ίδιου τύπου με τα αρχικά ορίσματα
+# Μην μπερδεύετε τις bool(ints) και bitwise and/or (&,|)
+bool(0) # => False
+bool(4) # => True
+bool(-6) # => True
+0 and 2 # => 0
+-5 or 0 # => -5
+
+# Ισότητα ==
+1 == 1 # => True
+2 == 1 # => False
+
+# Διάφορο !=
+1 != 1 # => False
+2 != 1 # => True
+
+# Περισσότερες συγκρίσεις
+1 < 10 # => True
+1 > 10 # => False
+2 <= 2 # => True
+2 >= 2 # => True
+
+# Κοιτάζουμε αν μία τιμή ανήκει σε ένα εύρος
+1 < 2 and 2 < 3 # => True
+2 < 3 and 3 < 2 # => False
+# Το Chaining (αλυσίδωση? :P) κάνει το παραπάνω πιο όμορφα
+1 < 2 < 3 # => True
+2 < 3 < 2 # => False
+
+# (is vs. ==) το is ελέγχει αν δύο μεταβλητές αναφέρονται στο ίδιο αντικείμενο,
+# αλλά το == ελέγχει αν τα αντικείμενα στα οποία αναφέρονται οι μεταβλητές έχουν τις ίδιες τιμές
+a = [1, 2, 3, 4] # το a δείχνει σε μία νέα λίστα, [1,2,3,4]
+b = a # το b δείχνει στο αντικείμενο που δείχνει το a
+b is a # => True, a και b αναφέρονται στο ίδιο αντικείμενο
+b == a # => True, τα αντικείμενα των a κι b είναι ίσα
+b = [1, 2, 3, 4] # Το b δείχνει σε μία νέα λίστα, [1, 2, 3, 4]
+b is a # => False, a και b δεν αναφέρονται στο ίδιο αντικείμενο
+b == a # => True, τα αντικείμενα των a και b είναι ίσα
+
+# Τα Strings (συμβολοσειρές) δημιουργούνται με " ή '
+"This is a string."
+'This is also a string.'
+
+# Μπορούμε και να προσθέτουμε Strings, αλλά προσπαθήστε να μην το κάνετε
+"Hello " + "world!" # => "Hello world!"
+# Τα String literals (αλλά όχι οι μεταβλητές) μπορούν να συντμιθούν και χωρίς το '+'
+"Hello " "world!" # => "Hello world!"
+
+# Μπορούμε να φερθούμε σε string σαν να είναι λίστα από χαρακτήρες
+"This is a string"[0] # => 'T'
+
+# Μπορούμε να βρούμε το μήκος ενός string
+len("This is a string") # => 16
+
+# Το .format μπορεί να χρησιμοποιηθεί για να μορφοποιήσουμε strings, όπως εδώ:
+"{} can be {}".format("Strings", "interpolated") # => "Strings can be interpolated"
+
+# Μπορείς να επαναλάβεις τα ορίσματα του formatting για να γλιτώσεις λίγο χρονο
+"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick")
+# => "Jack be nimble, Jack be quick, Jack jump over the candle stick"
+
+# Μπορείς να χρησιμοποιήσεις keywords αν βαριέσαι το μέτρημα.
+"{name} wants to eat {food}".format(name="Bob", food="lasagna") # => "Bob wants to eat lasagna"
+
+# Αν ο κώδικας Python 3 που γράφεις πρόκειται να τρέξει και με python 2.5 ή παλιότερη
+# μπορείς επίσης να χρησιμοποιήσεις το παλιό τρόπο για formatting:
+"%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way"
+
+# Μπορείς επίσης να μορφοποιήσεις χρησιμοποιώντας τα f-strings / formatted string literals (σε Python 3.6+)
+name = "Reiko"
+f"She said her name is {name}." # => "She said her name is Reiko"
+# Μπορείς βασικά να βάλεις οποιαδήποτε έκφραση Python στα άγκιστρα και θα εμφανιστεί στο string.
+f"{name} is {len(name)} characters long."
+
+
+# το None είναι ένα αντικείμενο (object)
+None # => None
+
+# Μη χρησιμοποιείτε το σύμβολο ισότητας "==" για να συγκρίνετε αντικείμενα με το None
+# Χρησιμοποιείτε το "is". Αυτό ελέγχει για ισότητα της ταυτότητας του αντικειμένου.
+"etc" is None # => False
+None is None # => True
+
+# Τα None, 0, και τα κενά strings/lists/dicts/tuples αποτιμούνται στην τιμή False
+# All other values are True
+bool(0) # => False
+bool("") # => False
+bool([]) # => False
+bool({}) # => False
+bool(()) # => False
+
+####################################################
+## 2. Μεταβλητές (variables) και Συλλογές (collections)
+####################################################
+
+# Η Python έχει μία συνάρτηση print()
+print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you!
+
+# By default, η συνάρτηση print() τυπώνει και ένα χαρακτήρα αλλαγής γραμμμής στο τέλος
+# Χρησιμοποιείτε το προαιρετικό όρισμο end για να τυπώνει οτιδήποτε άλλο
+print("Hello, World", end="!") # => Hello, World!
+
+# Απλός τρόπος για να πάρουμε δεδομένα εισόδου από το console
+input_string_var = input("Enter some data: ") # επιστρέφει τα δεδομένα ως string
+# Σημ.: Στις προηγούμενες εκδόσεις της Python, η μέθοδος input() ονομαζόταν raw_input()
+
+# Δεν υπάρχουν δηλώσεις, μόνο αναθέσεις τιμών.
+# Η σύμβαση είναι να χρησιμοποιούμε μικρά γράμματα με κάτω παύλες
+some_var = 5
+some_var # => 5
+
+# Η πρόσβαση σε μεταβλητή που δεν έχει λάβει τιμή είναι εξαίρεση
+# Δες τον Έλεγχο Ροής για να μάθεις περισσότερα για το χειρισμό εξαιρέσεων
+some_unknown_var # Προκαλέι ένα NameError
+
+# Η παρακάτω έκφραση μπορεί να χρησιμποιηθεί ισοδύναμα με τον τελεστή '?' της C
+"yahoo!" if 3 > 2 else 2 # => "yahoo!"
+
+# Οι λίστες κρατούν ακολουθίς
+li = []
+# Μπορείς να αρχίσεις με μία προ-γεμισμένη λίστα
+other_li = [4, 5, 6]
+
+# Και να βάλεις πράγματα στο τέλος με την μέθοδο append
+li.append(1) # η li τώρα είναι [1]
+li.append(2) # η li τώρα είναι [1, 2]
+li.append(4) # η li τώρα είναι [1, 2, 4]
+li.append(3) # η li τώρα είναι [1, 2, 4, 3]
+# Αφαιρούμε από το τέλος με την μέθοδο pop
+li.pop() # => 3 και η li γίνεται [1, 2, 4]
+# Ας βάλουμε το 3 πίσω στη θέση του
+li.append(3) # η li γίνεται πάλι [1, 2, 4, 3].
+
+# Προσπελαύνουμε τις λίστες όπως τους πίνακες σε άλλες γλώσσες
+li[0] # => 1
+# Το τελευταίο στοιχείο...
+li[-1] # => 3
+
+# Όταν βγαίνουμε εκτός ορίων της λίστας προκαλείται IndexError
+li[4] # προκαλεί IndexError
+
+# Μπορείς να δεις ranges μιας λίστας με το slice syntax ':'
+# Ο δείκτης εκίνησης περιλαμβάνεται στο διάστημα, ο δείκτης τερματισμού όχι
+# (είναι ανοικτό/κλειστό διάστημα για τους φίλους των μαθηματικών)
+li[1:3] # => [2, 4]
+# Αγνόησε την αρχή και επίστρεψε τη λίστα
+li[2:] # => [4, 3]
+# Αγνόησε το τέλος και επίστρεψε τη λίστα
+li[:3] # => [1, 2, 4]
+# Διάλεξε κάθε δεύτερο στοιχείο
+li[::2] # =>[1, 4]
+# Επίστρεψε ένα reversed αντίγραφο της λίστας
+li[::-1] # => [3, 4, 2, 1]
+# Χρησιμοποιείστε οποιαδήποτε συνδυασμό αυτών για να φτιάξετε πιο προχωρημένα slices
+# li[start:end:step]
+
+# Φτιάξε ένα αντίγραφο της λίστας χρησιμοποιώντας slices
+li2 = li[:] # => li2 = [1, 2, 4, 3] αλλά το (li2 is li) επιστρέφει False
+
+# Αφαίρεσε οποιοδήποτε στοιχείο από λίστα με την εντολή "del"
+del li[2] # η li γίνεται [1, 2, 3]
+
+# Αφαιρούμε το πρώτο στιγμυότυπο μιας τιμής
+li.remove(2) # η li γίνεται [1, 3]
+li.remove(2) # Προκαλεί ένα ValueError καθώς το 2 δεν βρίσκεται στη λίστα.
+
+# Εισαγωγή ενός στοιχείου σε συγκεκριμένη θέση
+li.insert(1, 2) # η li γίνεται πάλι [1, 2, 3]
+
+# Βρες το index (δείκτη) του πρώτου στοιχείου με τιμή ίση με το όρισμα
+li.index(2) # => 1
+li.index(4) # Προκαλεί ValueError καθώς το 4 δεν βρίσκεται στη λίστα
+
+# Μπορείς να προσθέτεις λίστες
+# Σημ.: οι τιμές των li, other_li δεν αλλάζουν.
+li + other_li # => [1, 2, 3, 4, 5, 6]
+
+# Σύντμιση λιστών με τη μέθοδο "extend()"
+li.extend(other_li) # Τώρα η li είναι [1, 2, 3, 4, 5, 6]
+
+# Ελεγχος της ύπαρξης στοιχείου σε λίστα με το "in"
+1 in li # => True
+
+# Εξατάζουμε το μήκος με "len()"
+len(li) # => 6
+
+
+# Τα Tuples είναι σαν τις λίστες αλλά είναι αμετάβλητα (immutable).
+tup = (1, 2, 3)
+tup[0] # => 1
+tup[0] = 3 # Προκαλεί TypeError
+
+# Σημειώστε ότι ένα tuple μήκους 1 πρέπει να έχει ένα κόμμα μετά το τελευταίο στοιχείο
+# αλλά τα tuples άλλων μηκών, ακόμα και μηδενικού μήκους, δεν χρειάζονται κόμμα.
+type((1)) # => <class 'int'>
+type((1,)) # => <class 'tuple'>
+type(()) # => <class 'tuple'>
+
+# Μπορείς να εφαρμόσεις τις περισσότερες μεθόδους των λιστών και στα tuples
+len(tup) # => 3
+tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6)
+tup[:2] # => (1, 2)
+2 in tup # => True
+
+# Μπορείς να κάνεις unpack/"ξεπακετάρεις" tuples σε μεταβλητές
+a, b, c = (1, 2, 3) # a == 1, b == 2 και c == 3
+# Μπορείς επίσης να επεκτείνεις το unpacking
+a, *b, c = (1, 2, 3, 4) # a == 1, b == [2, 3] και c == 4
+# Τα Tuples δημιουργούνται by deafult αν δεν βάλεις παρενθέσεις
+d, e, f = 4, 5, 6 # το tuple 4, 5, 6 "ξεπακετάρεται" στις μεταβλητές d, e και f
+# αντίστοιχα έτσι ώστε να γίνεται d = 4, e = 5 and f = 6
+# Δείτε πόσο εύκολα μπορούμε να εναλλάσουμε δύο τιμές
+e, d = d, e # το d παίρνει την τιμή 5 και το e παίρνει την τιμή 4
+
+
+# Τα λεξικά (Dictionaries) αποθηκεύουν απεικονίσεις από κλειδιά σε τιμές
+empty_dict = {}
+# Εδώ έχουμε ένα προ-γεμισμένο dictionary
+filled_dict = {"one": 1, "two": 2, "three": 3}
+
+# Σημ. ότι τα κλειδιά για τα dictionaries πρέπει να είναι αμετάβλητοι τύποι
+# (immutable) αυτό γίνετια για να διασφαλίσουμε ότι τα κλειδιά μπορούν να
+# μετατρέπονται σε σταθερές τιμές κατακερματισμού (hash values) για γρήγορη εύρεση.
+# Μερικοί αμετάβλητοι τύποι είναι τα ints, floats, strings, tuples.
+invalid_dict = {[1,2,3]: "123"} # => Προκαλεί TypeError: unhashable type: 'list'
+valid_dict = {(1,2,3):[1,2,3]} # Οι τιμές όμως μπορούν να έχουν οποιοδήποτε τύπο.
+
+# Βρίσκουμε τιμές με []
+filled_dict["one"] # => 1
+
+# Μπορείς να πάρεις όλα τα κλειδιά με τη μέθοδο "keys()".
+# Πρέπει να "τυλίξουμε" την κλήση με list() για να το μετατρέψουμε σε λίστα
+# Θα μιλήσουμε για αυτά αργότερα. Σημ. - σε εκδόσεις Python < 3.7, η σειρά που
+# εμφανίζονται τα κλειδιά δεν είναι εγγυημένη. Τα αποτελέσματά σας ίσως να μην
+# είναι ακριβώς ίδια με τα παρακάτω. Στην έκδοση 3.7 πάντως, τα αντικείμενα του
+# λεξικού διατηρούν τη σειρά με την οποία εισήχθησαν στο dictionary
+list(filled_dict.keys()) # => ["three", "two", "one"] σε Python <3.7
+list(filled_dict.keys()) # => ["one", "two", "three"] σε Python 3.7+
+
+# Παίρνουμε όλες τις τιμές ενός iterable με τη μέθοδο "values()". Και πάλι
+# χρειάζεται να το περιτυλίξουμε σε list()
+# Σημ. - όπως παραπάνω σχετικά με τη σειρά των keys
+list(filled_dict.values()) # => [3, 2, 1] in Python <3.7
+list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+
+
+# Έλεγχος της ύπαρξης κλειδιών σε ένα dictionary με το "in"
+"one" in filled_dict # => True
+1 in filled_dict # => False
+
+# Αν ψάξεις την τιμή ανύπαρκτου κλειδιού προκαλείται KeyError
+filled_dict["four"] # KeyError
+
+# Χρησιμοποιούμε τη μέθοδο "get()" για να αποφύγουμε το KeyError
+filled_dict.get("one") # => 1
+filled_dict.get("four") # => None
+# στο δεύτερο argument της get() μπορούμε να βάλουμε μία τιμή που πρέπει να
+# επιστρέψει αν δεν υπάρχει το key που ψάχνουμε
+filled_dict.get("one", 4) # => 1
+filled_dict.get("four", 4) # => 4
+
+# το "setdefault()" εισάγει στο dictionary μόνο αν δεν υπάρχει το κλειδί
+filled_dict.setdefault("five", 5) # filled_dict["five"] γίνεται 5
+filled_dict.setdefault("five", 6) # filled_dict["five"] μένει 5 (υπαρκτό κλειδί)
+
+# Προσθήκη σε dictionary
+filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4}
+filled_dict["four"] = 4 # β' τρόπος
+
+# Αφαίρεση κλειδιών από dictionary με del
+del filled_dict["one"] # Αφαιρεί το κλειδί "one" από το filled_dict
+
+# Από την Python 3.5 μπορείς να χρησιμοποιήσεις και πρόσθετες επιλογές για unpacking
+{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2}
+{'a': 1, **{'a': 2}} # => {'a': 2}
+
+
+
+# τα Sets -όπως όλοι περιμένουμε- αποθηκεύουν σύνολα
+empty_set = set()
+# Αρχικοποιούμε ένα set με μερικές τιμές. Ναι, μοιάζει λίγο με dictionary, Sorry.
+some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4}
+
+# Παρομοίως με τα κλειδιά του dictionary, τα στοιχεία ενός συνόλου πρέπει να είναι
+# αμετάβλητα (immutable)
+invalid_set = {[1], 1} # => Προκαλεί TypeError: unhashable type: 'list'
+valid_set = {(1,), 1}
+
+# Προσθέτουμε άλλο ένα στοιχείο στο σύνολο
+filled_set = some_set
+filled_set.add(5) # το filled_set είναι τώρα {1, 2, 3, 4, 5}
+# Τα σύνολα δεν έχουν διπλοτυπα αντικείμενα
+filled_set.add(5) # το σύνολο παραμένει ίδιο {1, 2, 3, 4, 5}
+
+# το & κάνει την τομή δύο συνόλων.
+other_set = {3, 4, 5, 6}
+filled_set & other_set # => {3, 4, 5}
+
+# και το | την ένωση
+filled_set | other_set # => {1, 2, 3, 4, 5, 6}
+
+# Η διαφορά συνόλων με το -
+{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
+
+# Το ^ επιστρέφει τη συμμετρική διαφορά
+{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5}
+
+# Ελεγχος για το αν το δεξιά σύνολο είναι υπερσύνολο του δεξιού
+{1, 2} >= {1, 2, 3} # => False
+
+# Ελεγχος για το αν το δεξιά σύνολο είναι υποσύνολο του δεξιού
+{1, 2} <= {1, 2, 3} # => True
+
+# με το in κάνουμε έλεγχο ύπαρξης στοιχείο σε σετ
+2 in filled_set # => True
+10 in filled_set # => False
+
+
+
+####################################################
+## 3. Έλεγχος Ροής και Iterables
+####################################################
+
+# Φτιάχνουμε μία μεταβλητή
+some_var = 5
+
+# Εδώ έχουμε ένα if statement. Η στοίχιση είναι σημαντική στην Python!
+# Η σύμβαση είναι να χρησιμοποιούμε 4 κενά, όχι tabs.
+# Το παρακάτω τυπώνει "some_var is smaller than 10"
+if some_var > 10:
+ print("some_var is totally bigger than 10.")
+elif some_var < 10: # το (else if) -> elif μέρος είναι προαιρετικό.
+ print("some_var is smaller than 10.")
+else: # και το else είναι προαιρετικό.
+ print("some_var is indeed 10.")
+
+
+"""
+τα for loops τρέχουν πάνω σε lists
+το παρακάτω τυπώνει:
+ dog is a mammal
+ cat is a mammal
+ mouse is a mammal
+"""
+for animal in ["dog", "cat", "mouse"]:
+ # You can use format() to interpolate formatted strings
+ print("{} is a mammal".format(animal))
+
+"""
+το "range(number)" επιστρέφει ένα iterable με αριθμούς
+από το μηδέν μέχρι τον δωσμένο αριθμό number (κλειστό/ανοικτό διάστημα)
+Το παρακάτω τυπώνει:
+ 0
+ 1
+ 2
+ 3
+"""
+for i in range(4):
+ print(i)
+
+"""
+το "range(lower, upper)" επιστρέφει ένα iterable με αριθμούς
+από το lower εώς το upper (κλειστό/ανοικτό διάστημα)
+το παρακάτω τυπώνει:
+ 4
+ 5
+ 6
+ 7
+"""
+for i in range(4, 8):
+ print(i)
+
+"""
+το "range(lower, upper, step)" επιστρέφει ένα iterable με αριθμούς
+από το lower μέχρι το upper, με βήμα step
+αν δεν δώσουμε τιμή βήματος, το default βήμα είναι 1.
+το παρακάτω τυπώνει:
+ 4
+ 6
+"""
+for i in range(4, 8, 2):
+ print(i)
+"""
+
+τα While loops τρέχουν μέχρι μία συνθήκη να γίνει ψευδής.
+το παρακάτω τυπώνει:
+ 0
+ 1
+ 2
+ 3
+"""
+x = 0
+while x < 4:
+ print(x)
+ x += 1 # Shorthand for x = x + 1
+
+# Χειριζόμαστε εξαιρέσεις με ένα try/except block
+try:
+ # Χρησιμοποιούμε το "raise" για να πετάξουμε ένα error
+ raise IndexError("This is an index error")
+except IndexError as e:
+ pass # το Pass δεν κάνει τίποτα. Συνήθως κάνουμε ανάκτηση.
+except (TypeError, NameError):
+ pass # Μπορούμε να χειριζόμαστε πολλές εξαιρέσεις μαζί, αν χρειαστεί
+else: # Προαιρετικό στο try/except block. Πρέπει να ακολουθεί όλα τα except blocks
+ print("All good!") # τρέχει μόνο αν ο κώδικας στο try δεν προκαλεί εξαιρέσεις
+finally: # Εκτελείται ό,τι και να γίνει
+ print("We can clean up resources here")
+
+# Αντί για try/finally για να καθαρίσουμε τους πόρους, μπορούμε να χρησιμοποιούμε το
+# with expression as target:
+ pass to cleanup resources you can use a with statement
+with open("myfile.txt") as f:
+ for line in f:
+ print(line)
+
+# Η Python προσφέρει μία θεμελιώδη αφαίρεση (abstraction) που λέγεται Iterable.
+# iterable είναι ένα αντικείμενο που μπορεί να χρησιμοποιηθεί ως ακολουθία.
+# Το αντικείμενο που επιστρέφει η συνάρτηση range, είναι ένα iterable.
+
+filled_dict = {"one": 1, "two": 2, "three": 3}
+our_iterable = filled_dict.keys()
+print(our_iterable) # => dict_keys(['one', 'two', 'three']).
+# Αυτό είναι ένα αντικείμενο που υλοποιεί την iterable διεπαφή μας.
+
+# μπορούμε να τρέχουμε loops πάνω του.
+for i in our_iterable:
+ print(i) # Prints one, two, three
+
+# Ωστόσο δεν μπορούμε να προσπελάσουμε τα στοιχεία του με index.
+our_iterable[1] # προκαλεί a TypeError
+
+# Ένα iterable είναι ένα αντικείμενο που ξέρει πώς να δημιουργήσει έναν iterator.
+our_iterator = iter(our_iterable)
+
+# Ο iterator μας είναι ένα αντικείμενο που μπορεί να θυμάται την κατάσταση όπως το διατρέχουμε.
+# Παίρνουμε το επόμενο αντικείμενο με το "next()"
+next(our_iterator) # => "one"
+
+# Διατηρεί την κατάσταση καθώς επαναλαμβάνουμε.
+next(our_iterator) # => "two"
+next(our_iterator) # => "three"
+
+# Όταν ο iterator έχει επιστρέψει όλα τα δεδομένα του, προκαλεί ένα μια εξαίρεση StopIteration.
+next(our_iterator) # προκαλεί StopIteration
+
+# Μπορείς να πάρεις όλα τα αντικείμενα ενός iteratior καλώντας list() πάνω του.
+list(filled_dict.keys()) # => Επιστρέφει ["one", "two", "three"]
+
+
+####################################################
+## 4. Συναρτήσεις
+####################################################
+
+# Χρησιμποιούμε το "def" για να ορίσουμε νέες συναρτήσεις
+def add(x, y):
+ print("x is {} and y is {}".format(x, y))
+ return x + y # επιστρέφει τιμές με την εντολή return
+
+# Καλούμε συναρτήσεις με παραμέτρους
+add(5, 6) # => τυπώνει "x is 5 and y is 6" και επιστρέφει 11
+
+# Ένας άλλος τρόπος να καλέσεις συνάρτησει είναι με keyword arguments (ορίσματα λέξεις-κλειδιά)
+add(y=6, x=5) # τα Keyword arguments μπορούν να δωθούν με οποιαδήποτε σειρά.
+
+# Μπορείς να ορίσεις συναρτήσεις που δέχονται μεταβλητό πλήθος ορισμάτων
+def varargs(*args):
+ return args
+
+varargs(1, 2, 3) # => (1, 2, 3)
+
+# Μπορούμε να ορίσουμε και συναρτήσεις που δέχονται μεταβλητό πλήθος keyword arguments
+def keyword_args(**kwargs):
+ return kwargs
+
+# Για να δούμε τι γίνεται αν την καλέσουμε
+keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"}
+
+
+# Μπορείς να κάνεις και τα δύο ταυτόχρονα αν θες
+def all_the_args(*args, **kwargs):
+ print(args)
+ print(kwargs)
+"""
+all_the_args(1, 2, a=3, b=4) τυπώνει:
+ (1, 2)
+ {"a": 3, "b": 4}
+"""
+
+# Όταν καλείς συναρτήσεις μπορείς να κάνεις και το αντίστροφο από args/kwargs!
+# Χρησιμοποίησε το * για να επεκτείνεις tuples και χρησιμοποίησε το ** για να επεκτείλεις kwargs
+args = (1, 2, 3, 4)
+kwargs = {"a": 3, "b": 4}
+all_the_args(*args) # ισοδύναμο με all_the_args(1, 2, 3, 4)
+all_the_args(**kwargs) # ισοδύναμο με all_the_args(a=3, b=4)
+all_the_args(*args, **kwargs) # ισοδύναμο με all_the_args(1, 2, 3, 4, a=3, b=4)
+
+# Επιστρέφουμε πλειάδα τιμών (με tuple assignments)
+def swap(x, y):
+ return y, x # Επιστρέφει πολλές τιμές ως tuple χωρίς την παρένθεση
+ # (Σημ.: οι παρενθέσεις έχουν παραλειφθεί αλλά μπορούν να γραφούν)
+
+x = 1
+y = 2
+x, y = swap(x, y) # => x = 2, y = 1
+# (x, y) = swap(x,y) # Ξανά, οι παρενθέσεις έχουν παραληφθεί αλλά μπορούν να γραφούν
+
+# Εμβέλεια συναρτήσεων
+x = 5
+
+def set_x(num):
+ # Η τοπική μεταβλητή x δεν είναι η ίδια με την global μεταβλητή x
+ x = num # => 43
+ print(x) # => 43
+
+def set_global_x(num):
+ global x
+ print(x) # => 5
+ x = num # η global μεταβλητή x τώρα είναι 6
+ print(x) # => 6
+
+set_x(43)
+set_global_x(6)
+
+
+# Η Python έχει πρώτης τάξης συναρτήσεις
+def create_adder(x):
+ def adder(y):
+ return x + y
+ return adder
+
+add_10 = create_adder(10)
+add_10(3) # => 13
+
+# Αλλά έχει και anonymous συναρτήσεις.
+(lambda x: x > 2)(3) # => True
+(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5
+
+# Υπάρχουν ενσωματωμένες συναρτήσεις μεγαλύτερης τάξης
+list(map(add_10, [1, 2, 3])) # => [11, 12, 13]
+list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3]
+
+list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7]
+
+# Μπορούμε να χρησιμοποιήσουμε list comprehensions για ωραία maps και filters
+# το List comprehension αποθηκεύει την έξοδο ως μία λίστα που μπορεί και η ίδια
+# να είναι μια εμφωλευμένη λίστα
+[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]
+
+# Μπορείς επίσης να κατασκευάσεις set και dict comprehensions.
+{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'}
+{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
+
+
+####################################################
+## 5. Modules
+####################################################
+
+# Μπορείς να κάνεις import modules
+import math
+print(math.sqrt(16)) # => 4.0
+
+# Μπορείς να πάρεις συγκεκριμένες συναρτήσεις από ένα module
+from math import ceil, floor
+print(ceil(3.7)) # => 4.0
+print(floor(3.7)) # => 3.0
+
+# Μπορείς να κάνεις import όλες τις συναρτήσεις από ένα module.
+# Προσοχή: δεν προτείνεται
+from math import *
+
+# Μπορείς να δημιουργείς συντομογραφίες για τα ονόματα των modules
+import math as m
+math.sqrt(16) == m.sqrt(16) # => True
+
+# Τα Python modules είναι απλά αρχεία Python. Μπορείς να δημιουργήσεις τα δικά σου
+# και να τα κάνεις import το όνομα του module είναι ίδιο με το όνομα του αρχείου
+
+# μπορείς να βρεις ποιες συναρτήσεις και γνωρίσματα ορίζονται στο module
+import math
+dir(math)
+
+# Αν έχεις ένα Python script με όνομα math.py στον ίδιο φάκελο με το τρέχον script
+# το αρχείο math.py θα φορτωθεί και όχι το built-in Python module
+# Αυτό συμβαίνει επειδή τα τοπικά αρχεία έχουν προτεραιότητα έναντι των built-in
+# βιβλιοθηκών της Python
+
+
+####################################################
+## 6. Κλάσεις - Classes
+####################################################
+
+# χρησιμοποιούμε το "class" statement για να δημιουργήσουμε μια κλάση
+class Human:
+
+ # Ένα γνώρισμα της κλάσης. Είναι κοινό για όλα τα στιγμιότυπα αυτής.
+ species = "H. sapiens"
+
+ # Βασικός initializer, καλείται όταν δημιουργείται στιγμιότυπο της κλάσης.
+ # Σημ. οι διπλές κάτω παύλες πριν και μετά υποδηλώνουν αντικείμενα
+ # ή γνωρίσματα που χρησιμοποιούνται από την Python αλλά ζουν σε ελεγχόμενα από
+ # το χρήση namespaces.
+ # Μέθοδοι (ή αντικείμενα ή γνωρίσματα) σαν τα __init__, __str__, __repr__ κλπ
+ # είναι ειδικές μέθοδοι (λέγονται και dunder (double underscore) μέθοδοι)
+ # Δεν πρέπει να δηλώνεις δικές σου τέτοιες συναρτήσεις
+ def __init__(self, name):
+ # Εκχώρησε στο attribute name του object το όρισμα
+ self.name = name
+
+ # Αρχικοποίησε την ιδιότητα
+ self._age = 0
+
+ # Μία μέθοδος στιγμιότυπου (instance method). Όλες οι μέθοδοι παίρνουν το
+ # "self" ως πρώτο όρισμα
+ def say(self, msg):
+ print("{name}: {message}".format(name=self.name, message=msg))
+
+ # Ακόμα μία instance method
+ def sing(self):
+ return 'yo... yo... microphone check... one two... one two...'
+
+ # Μία μέθοδος κλάσεις είναι κοινή ανάμεσα σε όλα τα instances.
+ # Καλούνται με calling class ώς πρώτο όρισμα
+ @classmethod
+ def get_species(cls):
+ return cls.species
+
+ # Μία στατική μέθοδος καλείται χωρίς αναφορά σε κλάση ή στιγμιότυπο
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+ # Ένα property είναι ακριβώς σαν ένα getter.
+ # Μετατρέπει τη μέθοδο age σε ένα γνώρισμα (attribute) μόνο-για-ανάγνωση
+ # με το ίδιο όνομα.
+ # Δεν χρειάζεται να γράφουμε τετριμένους getters και setters στην Python όμως.
+ @property
+ def age(self):
+ return self._age
+
+ # Αυτό επιτρέπει στο property να γίνει set
+ @age.setter
+ def age(self, age):
+ self._age = age
+
+ # Αυτό επιτρέπει σε ένα property να διαγραφεί
+ @age.deleter
+ def age(self):
+ del self._age
+
+
+# Όταν ο διερμηνέας της Python διαβάζει αρχείο πηγαίου κώδικα τον εκτελεί όλο.
+# Αυτός ο έλεγχος του __name__ σιγουρεύει ότι αυτό το block κώδικα τρέχει μόνο
+# αυτό το module είναι το κύριο πρόγραμμα (και όχι imported)
+if __name__ == '__main__':
+ # Δημιουργούμε στιγμιότυπο κλάσης
+ i = Human(name="Ian")
+ i.say("hi") # "Ian: hi"
+ j = Human("Joel")
+ j.say("hello") # "Joel: hello"
+ # τα i και j είναι στιγμιότυπα του τύπου Human
+
+ # Καλούμε τη μέθοδο της κλάσης
+ i.say(i.get_species()) # "Ian: H. sapiens"
+ # Αλλάζουμε το κοινό attribute των αντικειμένων της κλάσης
+ Human.species = "H. neanderthalensis"
+ i.say(i.get_species()) # => "Ian: H. neanderthalensis"
+ j.say(j.get_species()) # => "Joel: H. neanderthalensis"
+
+ # Καλούμε τη static μέθοδο
+ print(Human.grunt()) # => "*grunt*"
+
+ # Δεν μπορούμε να καλέσουμε τη στατική μέθοδο με ένα στιγμιότυπο
+ # επειδή το i.grunt() θα βάλει αυτόματα το self (δηλαδή το αντικείμενο i) ως όρισμα
+ print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
+
+ # Ενημερώνουμε το property για αυτό το στγμιότυπο
+ i.age = 42
+ # Παίρνουμε το property
+ i.say(i.age) # => "Ian: 42"
+ j.say(j.age) # => "Joel: 0"
+ # Διαγράφουμε το property
+ del i.age
+ # i.age # => αυτό θα προκαλούσε AttributeError
+
+
+####################################################
+## 6.1 Κληρονομικότητα - Inheritance
+####################################################
+
+# Η κληρονομικότητα επιτρέπει σε νέες κλάσεις-παιδιά να οριστούν και να υιοθετήσουν
+# μεθόδους και μεταβλητές από την κλάση-γονέα.
+
+# Χρησιμοποιώντας την κλάση Human που ορίστηκε πριν ως τη βασική κλάση (ή κλάση-γονέα)
+# μπορούμε να ορίσουμε τις κλάσεις-παιδιά Superhero, που κληρονομεί μεταβλητές όπως
+# "species", "name", και "age", καθώς και μεθόδους όπως "sing" και "grunt"
+# από την κλάση Human, αλλά επίσης έχει τις δικές του ξεχωριστές ιδιότητες
+
+# Για να εκμεταλλευτείς το modularization κατά αρχείο, μπορείς να βάλεις την παραπάνω κλάση
+# σε δικό της αρχείο, ας πούμε human.py
+
+# Για να κάνουμε import συναρτήσεις από άλλα αρχεία χρησιμοποιούμε το παρακάτω format
+# from "filename-without-extension" import "function-or-class"
+
+from human import Human
+
+
+# Προσδιόρισε την/τις parent class(es) ως παραμέτρους της κλάσης που ορίζεται
+class Superhero(Human):
+
+ # Αν η κλάση-παιδί πρέπει να κληρονομήσει όλους τους οεισμούς της κλάσης-γονέα
+ # χωρίς καμία αλλαγή, μπορείς απλά να γράψεις pass (και τίποτα άλλο)
+ # αλλά σε αυτή την περίπτωση είναι σχολιασμένο για να επιτρέψει τη δημιουργία
+ # ξεχωριστής κλάσης-παιδιού:
+ # pass
+
+ # Η κλάση παιδί μπορεί να υπερφορτώσει (override) τα attributes της κλάσης από την οποία κληρονομεί
+ species = 'Superhuman'
+
+ # Τα παιδιά αυτόματα, κληρονομούν τον constructo της κλάσης-γονέα
+ # συμπεριλαμβανομένων των ορισμάτων, αλλά μπορείς και να ορίσεις πρόσθετα ορίσματα
+ # ή ορισμούς και να κάνεις override τις μεθόδους, όπως τον constructor.
+ # Αυτός ο constructor κληρονομεί το όρισμα "name" από την κλάση Human και
+ # προσθέτει τα ορίσματα "superpower" και "movie":
+ def __init__(self, name, movie=False,
+ superpowers=["super strength", "bulletproofing"]):
+
+ # πρόσθήκη επιπλέον attributes της κλάσης:
+ self.fictional = True
+ self.movie = movie
+ # έχετε το νου σας τις μεταβλητές (mutable) default τιμές, καθώς είναι κοινές
+ self.superpowers = superpowers
+
+ # Η συνάρτηση "super" επιτρέπει την πρόσβαση στις μεθόδους της κλάσης-γονέα
+ # που είναι υπερφορτωμένες από το παιδί. Σε αυτή την περίπτωση τη μέθοδο __init__
+ # Το παρακάτω καλεί τον constructor της κλάσης-γονέα:
+ super().__init__(name)
+
+ # υπερφόρτωση της μεθόδου sing
+ def sing(self):
+ return 'Dun, dun, DUN!'
+
+ # προσθήκη νέας μεθόδου που εφαρμόζεται σε στιγμιότυπα
+ def boast(self):
+ for power in self.superpowers:
+ print("I wield the power of {pow}!".format(pow=power))
+
+
+if __name__ == '__main__':
+ sup = Superhero(name="Tick")
+
+ # Έλεγχος για το αν το στιγμιότυπο sup ανήκει στην κλάση Human
+ if isinstance(sup, Human):
+ print('I am human')
+ if type(sup) is Superhero:
+ print('I am a superhero')
+# TODO:
+ # Παίρνουμε το Method Resolution search Order που χρησιμοποιούν οι getattr() και super()
+ # Αυτό το attribute είναι δυναμικό και μπορεί να ανανεωθεί
+ print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
+ # => <class 'human.Human'>, <class 'object'>)
+
+ # Καλούμε μέθοδο της κλάσης-γονέα, αλλά χρησιμοποιεί το δικό της attribute
+ print(sup.get_species()) # => Superhuman
+
+ # Καλεί την υπερφορτωμένη μέθοδο
+ print(sup.sing()) # => Dun, dun, DUN!
+
+ # Καλεί μέθοδο από την κλάση Human
+ sup.say('Spoon') # => Tick: Spoon
+
+ # Καλεί μέθοδο που υπάρχει μόνο στην κλάση Superhero
+ sup.boast() # => I wield the power of super strength!
+ # => I wield the power of bulletproofing!
+
+ # Κληρονομημένο class attribute
+ sup.age = 31
+ print(sup.age) # => 31
+
+ # Attribute που υπάρχει μόνο στην μέσα στην κλάση Superhero
+ print('Am I Oscar eligible? ' + str(sup.movie))
+
+####################################################
+## 6.2 Πολλαπλή Κληρονομικότητα - Multiple Inheritance
+####################################################
+
+# Ένας ακόμη ορισμός κλάσης
+# bat.py
+class Bat:
+
+ species = 'Baty'
+
+ def __init__(self, can_fly=True):
+ self.fly = can_fly
+
+ # Αυτή η κλάση έχει επίσης μία μέθοδο say
+ def say(self, msg):
+ msg = '... ... ...'
+ return msg
+
+ # Και τη δική της μέθοδο sonar
+ def sonar(self):
+ return '))) ... ((('
+
+if __name__ == '__main__':
+ b = Bat()
+ print(b.say('hello'))
+ print(b.fly)
+
+
+# Και ορίζουμε μία ακόμα κλάση που κληρονομεί από τις κλάσεις Superhero και Bat
+# superhero.py
+from superhero import Superhero
+from bat import Bat
+
+# Ας πούμε αυτή την κλάση Batman
+class Batman(Superhero, Bat):
+
+ def __init__(self, *args, **kwargs):
+ # Τυπικά γα να κληρονομήουμε attributes πρέπει να καλέσουμε τη super:
+ # super(Batman, self).__init__(*args, **kwargs)
+ # Ωστόσο έχουμε να κάνουμε με πολλαπλή κληρονομικότητα εδώ, και το super()
+ # δουλεύει μόνο με την αμέσως ανώτερη κλάση στην ιεραρχία.
+ # Οπότε, καλούμε ρητά την __init__ για όλους τους πρόγονους
+ # Η χρήση των *args και **kwargs επιτρέπει έναν καθαρό τρόπο για να περνάμε ορίσματα
+ # με κάθε κλάση-γονέα να "βγάζει μία φλούδα από το κρεμμύδι".
+ Superhero.__init__(self, 'anonymous', movie=True,
+ superpowers=['Wealthy'], *args, **kwargs)
+ Bat.__init__(self, *args, can_fly=False, **kwargs)
+ # υπερφορτώνουμε την τιμή του γνωρίσματος name
+ self.name = 'Sad Affleck'
+
+ def sing(self):
+ return 'nan nan nan nan nan batman!'
+
+
+if __name__ == '__main__':
+ sup = Batman()
+
+ #
+ # Λάβε το Method Resolution search Order που χρησιμοποιείται από το getattr() και το super().
+ # Αυτό το attribute είναι δυναμικό και μπορεί να ενημερωθεί
+ print(Batman.__mro__) # => (<class '__main__.Batman'>,
+ # => <class 'superhero.Superhero'>,
+ # => <class 'human.Human'>,
+ # => <class 'bat.Bat'>, <class 'object'>)
+
+ # Καλεί την μέθοδο της κλάσης-πατέρα αλλά χρησιμοποιεί το attribute της δικής του κλάσης
+ print(sup.get_species()) # => Superhuman
+
+ # Καλεί την υπερφορτωμένη μέθοδο
+ print(sup.sing()) # => nan nan nan nan nan batman!
+
+ # Καλεί μέθοδο από την κλάση Human, επειδή μετράει η σειρά της κληρονομιάς
+ sup.say('I agree') # => Sad Affleck: I agree
+
+ # Καλεί μέθοδο που ανήκει μόνο στον δεύτερο πρόγονο
+ print(sup.sonar()) # => ))) ... (((
+
+ # Attribute της κληρονομημένης κλάσης
+ sup.age = 100
+ print(sup.age) # => 100
+
+ # Κληρονομούμενο attribute από τον δεύτερο πρόγονο του οποίου η default τιμή
+ # έχει υπερφορτωθεί.
+ print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
+
+
+
+####################################################
+## 7. Προχωρημένα
+####################################################
+
+# Με τους Generators μπορείς να γράψεις τεμπέλικο κώδικα.
+def double_numbers(iterable):
+ for i in iterable:
+ yield i + i
+# Οι Generators είναι αποδοτικοί από άποψη μνήμης επειδή φορτώνουν μόνο τα δεδομένα
+# που είναι αναγκαία για να επεξεργαστούμε την επόμενη τιμή του iterable.
+# Αυτό μας επιτρέπει να κάνουμε πράξεις σε τιμές που υπό άλλες συνθήκες θα ήταν
+# απαγορευτικά μεγάλες.
+for i in double_numbers(range(1, 900000000)): # το `range` είναι ένας generator.
+ print(i)
+ if i >= 30:
+ break
+
+# Όπως μπορείς να δημιουργήσεις list comprehension, έτσι μπορείς να δημιουργήσεις και
+# generator comprehensions
+values = (-x for x in [1,2,3,4,5])
+for x in values:
+ print(x) # τυπώνει -1 -2 -3 -4 -5 στο console/terminal
+
+# Μπορείς επίσης να μετατρέψεις ένα generator comprehension απευθείας σε λίστα.
+values = (-x for x in [1,2,3,4,5])
+gen_to_list = list(values)
+print(gen_to_list) # => [-1, -2, -3, -4, -5]
+
+
+# Decorators
+# σε αυτό το παράδειγμα το `beg` τυλίγει το `say`. Αν το say_please είναι True τότε
+# θα αλλάξει το μήνυμα που επιστρέφεται.
+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, "Please! I am poor :(")
+ return msg
+
+ return wrapper
+
+
+@beg
+def say(say_please=False):
+ msg = "Can you buy me a beer?"
+ return msg, say_please
+
+
+print(say()) # Can you buy me a beer?
+print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
+```
+
+## Έτοιμοι για περισσότερα?
+
+### Δωρεάν Online
+
+* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
+* [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/)
+* [Python Course](http://www.python-course.eu/index.php)
+* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
+* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python)
+* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html)
+* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/)
+* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/)
+* [Dive Into Python 3](http://www.diveintopython3.net/index.html)
+* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718)
diff --git a/elixir.html.markdown b/elixir.html.markdown
index 7af29202..0b717ca6 100644
--- a/elixir.html.markdown
+++ b/elixir.html.markdown
@@ -1,7 +1,7 @@
---
language: elixir
contributors:
- - ["Joao Marques", "http://github.com/mrshankly"]
+ - ["Joao Marques", "https://github.com/mrshankly"]
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
- ["Ryan Plant", "https://github.com/ryanplant-au"]
- ["Ev Bogdanov", "https://github.com/evbogdanov"]
@@ -451,9 +451,9 @@ Agent.update(my_agent, fn colors -> ["blue" | colors] end)
## References
-* [Getting started guide](http://elixir-lang.org/getting-started/introduction.html) from the [Elixir website](http://elixir-lang.org)
+* [Getting started guide](https://elixir-lang.org/getting-started/introduction.html) from the [Elixir website](https://elixir-lang.org)
* [Elixir Documentation](https://elixir-lang.org/docs.html)
* ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) by Dave Thomas
-* [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf)
-* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert
+* [Elixir Cheat Sheet](https://media.pragprog.com/titles/elixir/ElixirCheat.pdf)
+* ["Learn You Some Erlang for Great Good!"](https://learnyousomeerlang.com/) by Fred Hebert
* ["Programming Erlang: Software for a Concurrent World"](https://pragprog.com/book/jaerlang2/programming-erlang) by Joe Armstrong
diff --git a/es-es/hq9+-es.html.markdown b/es-es/hq9+-es.html.markdown
new file mode 100644
index 00000000..0e1a36e1
--- /dev/null
+++ b/es-es/hq9+-es.html.markdown
@@ -0,0 +1,44 @@
+---
+language: HQ9+
+filename: hq9+-es.html
+contributors:
+ - ["Alexey Nazaroff", "https://github.com/rogaven"]
+translators:
+ - ["Roberto R", "https://github.com/rrodriguze"]
+lang: es-es
+---
+
+HQ9+ es una parodia de los lenguajes de programación esotéricos y fue creado
+por Cliff Biffle.
+El lenguaje tiene solo cuatro comandos y no está completo de Turing.
+
+```
+Solo hay cuatro comandos, representados por los siguientes cuatro caracteres
+H: imprime "Hello, world!"
+Q: imprime el código fuente del programa (ein Quine)
+9: imprime la letra de "99 Bottles of Beer"
++: aumenta el acumulador en uno (el valod del acumulador no se puede leer)
+Cualquier otro caracter es ignorado.
+
+Ok. Escribamos el programa:
+ HQ
+
+Resultado:
+ Hello world!
+ HQ
+
+HQ9+ es muy simple, pero te permite hacer cosas en él. Otros lenguajes son muy
+difíciles.Por ejemplo, el siguiente programa imprime tres copias de sí mismo en
+la pantalla:
+ QQQ
+Esto imprime:
+ QQQ
+ QQQ
+ QQQ
+```
+
+Y esto es todo. Hay muchos intérpretes para HQ9+.
+A continuación encontrarás uno de ellos.
+
++ [One of online interpreters](https://almnet.de/esolang/hq9plus.php)
++ [HQ9+ official website](http://cliffle.com/esoterica/hq9plus.html)
diff --git a/es-es/pcre-es.html.markdown b/es-es/pcre-es.html.markdown
new file mode 100644
index 00000000..279c9a39
--- /dev/null
+++ b/es-es/pcre-es.html.markdown
@@ -0,0 +1,84 @@
+---
+language: PCRE
+filename: pcre-es.txt
+contributors:
+ - ["Sachin Divekar", "http://github.com/ssd532"]
+translators:
+ - ["Roberto R", "https://github.com/rrodriguze"]
+lang: es-es
+---
+
+Una expresión regular (regex o regexp para abreviar) es una cadena especial
+utilizada para definir un patrón, por ejemplo, buscar una secuencia de
+caracteres; por ejemplo, `/^[a-z]+:/` se puede usar para extraer `http:`
+desde la URL `http://github.com/`.
+
+PCRE (Pearl Compatible Regular Expressions) es una biblioteca para expresiones
+muy similar a la Perls, desde ahí el nombre. Se trata de una de las sintaxis
+más comunes para escribir expresiones regulares.
+
+Hay dos tipos de metacaracteres (caracteres con una función especial):
+
+* Caracteres reconocidos en todas partes excepto corchetes
+
+```
+ \ caracter de escape
+ ^ buscar al principio de la cadena (o línea, en modo multilínea)
+ $ busca al final de la cadena (o línea, en modo multilínea)
+ . cualquier caracter exceptoo las nuevas líneas
+ [ inicio de clase de caracter
+ | condiciones alternativas del separador
+ ( inicio del subpatrón
+ ) fin del subpatrón
+ ? cuantificador "0 o 1"
+ * quantificatore "0 o más"
+ + quantificatore "1 o más"
+ { inicio de cuantificador numérico
+```
+
+* Caracteres reconocidos entre corchetes
+
+```
+ \ caracter de escape
+ ^ negar la clase si es el primer caracter
+ - indica una serie de caracteres
+ [ clase de caracteres POSIX (si sigue la sintaxis POSIX)
+ ] termina la clase de caracteres
+```
+
+PCRE también proporciona clases de caracteres predefinidas
+
+```
+ \d cifra decimal
+ \D cifra NO decimal
+ \h espacio horizontal vacío
+ \H espacio horizontal NO vacío
+ \s espacio
+ \S NO esoacui
+ \v espacio vertical vacío
+ \V espacio vertical NO vacío
+ \w palabra
+ \W "NO palabra"
+```
+
+## Ejemplos
+
+Usaremos la siguiente cadena para nuestras pruebas:
+
+```
+66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
+```
+
+Se trata de una línea de log del servidor web Apache.
+
+| Regex | Resultado | Comentario |
+| :---- | :-------------- | :------ |
+| `GET` | GET | Busque exactamente la cadena "GET" (distingue entre mayúsculas y minúsculas) |
+| `\d+.\d+.\d+.\d+` | 66.249.64.13 | `\d+` identifica uno o más (cuantificador `+`) números [0-9], `\.` identifica el caracter `.` |
+| `(\d+\.){3}\d+` | 66.249.64.13 | `(\d+\.){3}` busca el grupo (`\d+\.`) exactamente 3 veces. |
+| `\[.+\]` | [18/Sep/2004:11:07:48 +1000] | `.+` identifica cualquier caracter, excepto las nuevas líneas; `.` indica cualquier carácter |
+| `^\S+` | 66.249.64.13 | `^` buscar al inicio de la cadena, `\S+` identifica la primera cadena de caracteres que no sea espacio |
+| `\+[0-9]+` | +1000 | `\+` identifica el caracter `+`. `[0-9]` indica una cifra de 0 a 9. La expresión es equivalente a `\+\d+` |
+
+## Otros recursos
+[Regex101](https://regex101.com/) - probador de expresiones regulares
diff --git a/go.html.markdown b/go.html.markdown
index ae99535b..49f1ade4 100644
--- a/go.html.markdown
+++ b/go.html.markdown
@@ -12,6 +12,7 @@ contributors:
- ["Alexej Friesen", "https://github.com/heyalexej"]
- ["Clayton Walker", "https://github.com/cwalk"]
- ["Leonid Shevtsov", "https://github.com/leonid-shevtsov"]
+ - ["Michael Graf", "https://github.com/maerf0x0"]
---
Go was created out of the need to get work done. It's not the latest trend
@@ -30,6 +31,12 @@ Go comes with a good standard library and a sizeable community.
/* Multi-
line comment */
+ /* A build tag is a line comment starting with // +build
+ and can be execute by go build -tags="foo bar" command.
+ Build tags are placed before the package clause near or at the top of the file
+ followed by a blank line or other line comments. */
+// +build prod, dev, test
+
// A package clause starts every source file.
// Main is a special name declaring an executable rather than a library.
package main
@@ -190,7 +197,7 @@ func learnFlowControl() {
x := 42.0
switch x {
case 0:
- case 1:
+ case 1, 2: // Can have multiple matches on one case
case 42:
// Cases don't "fall through".
/*
@@ -202,6 +209,19 @@ func learnFlowControl() {
default:
// Default case is optional.
}
+
+ // Type switch allows switching on the type of something instead of value
+ var data interface{}
+ data = ""
+ switch c := data.(type) {
+ case string:
+ fmt.Println(c, "is a string")
+ case int64:
+ fmt.Printf("%d is an int64\n", c)
+ default:
+ // all other cases
+ }
+
// Like if, for doesn't use parens either.
// Variables declared in for and if are local to their scope.
for x := 0; x < 3; x++ { // ++ is a statement.
diff --git a/haskell.html.markdown b/haskell.html.markdown
index 90d47c27..1cc79ec9 100644
--- a/haskell.html.markdown
+++ b/haskell.html.markdown
@@ -293,7 +293,13 @@ foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16
-- 7. Data Types
----------------------------------------------------
--- Here's how you make your own data type in Haskell
+-- A data type is declared with a 'type constructor' on the left
+-- and one or more 'data constructors' on the right, separated by
+-- the pipe | symbol. This is a sum/union type. Each data constructor
+-- is a (possibly nullary) function that creates an object of the type
+-- named by the type constructor.
+
+-- This is essentially an enum
data Color = Red | Blue | Green
@@ -304,7 +310,62 @@ say Red = "You are Red!"
say Blue = "You are Blue!"
say Green = "You are Green!"
--- Your data types can have parameters too:
+-- Note that the type constructor is used in the type signature
+-- and the data constructors are used in the body of the function
+-- Data constructors are primarily pattern-matched against
+
+-- This next one is a traditional container type holding two fields
+-- In a type declaration, data constructors take types as parameters
+-- Data constructors can have the same name as type constructors
+-- This is common where the type only has a single data constructor
+
+data Point = Point Float Float
+
+-- This can be used in a function like:
+
+distance :: Point -> Point -> Float
+distance (Point x y) (Point x' y') = sqrt $ dx + dy
+ where dx = (x - x') ** 2
+ dy = (y - y') ** 2
+
+-- Types can have multiple data constructors with arguments, too
+
+data Name = Mononym String
+ | FirstLastName String String
+ | FullName String String String
+
+-- To make things clearer we can use record syntax
+
+data Point2D = CartesianPoint2D { x :: Float, y :: Float }
+ | PolarPoint2D { r :: Float, theta :: Float }
+
+myPoint = CartesianPoint2D { x = 7.0, y = 10.0 }
+
+-- Using record syntax automatically creates accessor functions
+-- (the name of the field)
+
+xOfMyPoint = x myPoint
+
+-- xOfMyPoint is equal to 7.0
+
+-- Record syntax also allows a simple form of update
+
+myPoint' = myPoint { x = 9.0 }
+
+-- myPoint' is CartesianPoint2D { x = 9.0, y = 10.0 }
+
+-- Even if a type is defined with record syntax, it can be declared like
+-- a simple data constructor. This is fine:
+
+myPoint'2 = CartesianPoint2D 3.3 4.0
+
+-- It's also useful to pattern match data constructors in `case` expressions
+
+distanceFromOrigin x =
+ case x of (CartesianPoint2D x y) -> sqrt $ x ** 2 + y ** 2
+ (PolarPoint2D r _) -> r
+
+-- Your data types can have type parameters too:
data Maybe a = Nothing | Just a
@@ -313,8 +374,98 @@ Just "hello" -- of type `Maybe String`
Just 1 -- of type `Maybe Int`
Nothing -- of type `Maybe a` for any `a`
+-- For convenience we can also create type synonyms with the 'type' keyword
+
+type String = [Char]
+
+-- Unlike `data` types, type synonyms need no constructor, and can be used
+-- anywhere a synonymous data type could be used. Say we have the
+-- following type synonyms and items with the following type signatures
+
+type Weight = Float
+type Height = Float
+type Point = (Float, Float)
+getMyHeightAndWeight :: Person -> (Height, Weight)
+findCenter :: Circle -> Point
+somePerson :: Person
+someCircle :: Circle
+distance :: Point -> Point -> Float
+
+-- The following would compile and run without issue,
+-- even though it does not make sense semantically,
+-- because the type synonyms reduce to the same base types
+
+distance (getMyHeightAndWeight somePerson) (findCenter someCircle)
+
+----------------------------------------------------
+-- 8. Typeclasses
+----------------------------------------------------
+
+-- Typeclasses are one way Haskell does polymorphism
+-- They are similar to interfaces in other languages
+-- A typeclass defines a set of functions that must
+-- work on any type that is in that typeclass.
+
+-- The Eq typeclass is for types whose instances can
+-- be tested for equality with one another.
+
+class Eq a where
+ (==) :: a -> a -> Bool
+ (/=) :: a -> a -> Bool
+ x == y = not (x /= y)
+ x /= y = not (x == y)
+
+-- This defines a typeclass that requires two functions, (==) and (/=)
+-- It also declares that one function can be declared in terms of another
+-- So it is enough that *either* the (==) function or the (/=) is defined
+-- And the other will be 'filled in' based on the typeclass definition
+
+-- To make a type a member of a type class, the instance keyword is used
+
+instance Eq TrafficLight where
+ Red == Red = True
+ Green == Green = True
+ Yellow == Yellow = True
+ _ == _ = False
+
+-- Now we can use (==) and (/=) with TrafficLight objects
+
+canProceedThrough :: TrafficLight -> Bool
+canProceedThrough t = t /= Red
+
+-- You can NOT create an instance definition for a type synonym
+
+-- Functions can be written to take typeclasses with type parameters,
+-- rather than types, assuming that the function only relies on
+-- features of the typeclass
+
+isEqual (Eq a) => a -> a -> Bool
+isEqual x y = x == y
+
+-- Note that x and y MUST be the same type, as they are both defined
+-- as being of type parameter 'a'.
+-- A typeclass does not state that different types in the typeclass can
+-- be mixed together.
+-- So `isEqual Red 2` is invalid, even though 2 is an Int which is an
+-- instance of Eq, and Red is a TrafficLight which is also an instance of Eq
+
+-- Other common typeclasses are:
+-- Ord for types that can be ordered, allowing you to use >, <=, etc.
+-- Read for types that can be created from a string representation
+-- Show for types that can be converted to a string for display
+-- Num, Real, Integral, Fractional for types that can do math
+-- Enum for types that can be stepped through
+-- Bounded for types with a maximum and minimum
+
+-- Haskell can automatically make types part of Eq, Ord, Read, Show, Enum,
+-- and Bounded with the `deriving` keyword at the end of the type declaration
+
+data Point = Point Float Float deriving (Eq, Read, Show)
+
+-- In this case it is NOT necessary to create an 'instance' definition
+
----------------------------------------------------
--- 8. Haskell IO
+-- 9. Haskell IO
----------------------------------------------------
-- While IO can't be explained fully without explaining monads,
@@ -395,7 +546,7 @@ main'' = do
----------------------------------------------------
--- 9. The Haskell REPL
+-- 10. The Haskell REPL
----------------------------------------------------
-- Start the repl by typing `ghci`.
diff --git a/hdl.html.markdown b/hdl.html.markdown
new file mode 100644
index 00000000..cad07817
--- /dev/null
+++ b/hdl.html.markdown
@@ -0,0 +1,231 @@
+---
+language: hdl
+filename: learnhdl.hdl
+contributors:
+ - ["Jack Smith", "https://github.com/JSmithTech2019"]
+---
+
+HDL (hardware description language) is a specialized language used to describe the structure/behavior of real world circuits.
+
+It is used by circuit designers to simulate circuits and logic prior to wiring and fabricating a hardware circuit.
+
+HDL allows circuit designers to simulate circuits at a high level without being connected to specific components.
+
+## Basic building blocks & introduction to the language---
+This programming language is built by simulating hardware chips and wiring. Normal programming functions are replaced with specialized chips that are added to the current wiring desing. Every base chip must be written as it's own file and imported to be used in the current chip, though they may be reused as often as desired.
+
+```verilog
+// Single line comments start with two forward slashes.
+
+/*
+ * Multiline comments can be written using '/*' and 'star/'.
+ * These are often used as comments.
+ *
+ * Note that they cannot be nested and will end at the first 'star/'.
+ */
+
+////////////////////////////////////////////////////
+// 1. Chips & Components
+////////////////////////////////////////////////////
+/*
+ * Unlike other languages HDL creates an individual chip (function) per file
+ * These are defined with a name, input arguments, output arguments
+ * and finally the parts/logic of that specific chip.
+ */
+
+// Note CHIP is capitalized, the chip name does not need to be.
+CHIP Ex {
+ IN a, // Single bit (0 or 1) variable.
+ c[16]; // 16 bit variable bus of single bit values.
+
+ OUT out[16], // 16 bit variable bus output.
+ carry; // Single bit output variable
+
+ PARTS:
+ // The functional components of the chip.
+}
+
+// Lines are ended with semicolons but can be continued using commas. The
+// whitespace is ignored.
+
+
+
+////////////////////////////////////////////////////
+// 2. Inputs, Outputs, & Variables
+////////////////////////////////////////////////////
+/*
+ * Variables and IO are treated as pins/wires and can carry a single bit
+ * of data (0 or 1).
+ */
+
+// Hardware works on low level 0's and 1's, in order to use a constant
+// high or low we use the terms true and false.
+a=false; // This is a 0 value.
+b=true; // This is a 1 value.
+
+// Inputs and outputs can be defined as single bits
+IN a, b; // Creates two single bit inputs
+
+// They can also be defined as busses act as arrays where each
+// index can contain a single bit value.
+OUT c[16]; // Creates a 16 bit output array.
+
+// Bussed values can be accessed using brackets
+a[0] // The first indexed value in the bus a.
+a[0..3] // The first 4 values in the a bus.
+// Values can also be passed in entirety. For example if the function
+// foo() takes an 8 bit input bus and outputs a 2 bit bus:
+foo(in=a[0..7], out=c); // C is now a 2 bit internal bus
+
+
+// Note that internally defined busses cannot be subbussed!
+// To access these elements, output or input them seperately:
+foo(in[0]=false, in[1..7]=a[0..6], out[0]=out1, out[1]=out2);
+// out1 and out2 can then be passed into other circuits within the design.
+
+
+
+////////////////////////////////////////////////////
+// Combining Subsystems
+////////////////////////////////////////////////////
+/*
+ * HDL relies heavily on using smaller "building block" chips to then be
+ * added into larger and more complex designs. Creating the smaller components
+ * and then adding them to the larger circuit allows for fewer lines of code
+ * as well as reduction in total rewriting of code.
+ */
+
+// We are writing the function AND that checks if inputs I and K are both one.
+// To implement this chip we will use the built in NAND gate as well as design
+// a custom NOT gate to invert a single input.
+
+// First we construct the Negation (not) chip. We will use the logically
+// complete gate NAND that is built in for this task.
+CHIP Not {
+ IN i; // Not gates only take one single bit input.
+ OUT o; // The negated value of a.
+
+ PARTS:
+ // Add the input to the built in chip, which then sends output to the NOT
+ // output. This effectively negates the given value.
+ Nand(a=i, b=i, out=o);
+}
+
+// By using the built in NAND gate we were able to construct a NOT gate
+// that works like a real world hardware logic chip. Now we must construct
+// the AND gate using these two gate primitives.
+
+// We define a two input, single output AND gate:
+CHIP And {
+ IN i, k; // Two single bit inputs.
+ OUT o; // One single bit output.
+
+ PARTS:
+ // Insert I and K into the nand gate and store the output in an internal
+ // wire called notOut.
+ Nand(a=i,b=b,out=notOut);
+
+ // Use the not gate we constructed to invert notOut and send to the AND
+ // output.
+ Not(in=notOut,out=o);
+}
+
+// Easy! Now we can use Nand, And, and Not gates in higher level circuits.
+// Many of these low level components are built in to HDL but any chip can
+// be written as a submodule and used in larger designs.
+```
+
+## Test Files
+When working with the nand2tetris hardware simulator chips written using HDL will
+then be processed against test and comparison files to test functionality of the
+simulated chip versus the expected output. To do this a test file will be loaded
+into the hardware simulator and run against the simulated hardware.
+
+```verilog
+// First the chip the test file is written for is loaded
+load <chip name>.hdl
+
+// We set the output file for the simulated chip output as well as the comparison
+// file that it will be tested against. We also specify what the output is
+// expected to look like. In this case there will be two output columns, each
+// will be buffered by a single space on either side and 4 binary values in
+// the center of each column.
+output-file <chip name>.out,
+compare-to <chip name>.cmp,
+output-list in%B1.4.1 out%B1.4.1;
+
+// Then we set initial values for inputs to the chip. For example
+set enable1 1, // set input enable1 to 1
+set enable2 0, // set input enable2 to 0
+
+// The clock is also controlled in the test file using tick and tock. Tick is a
+// positive pulse and tock takes the clock back to 0. Clock cycles can be run
+// multiple times in a row with no other changes to inputs or outputs.
+tick,
+tock,
+
+// Finally we output the first expected value (from the test file) which is then
+// compared with the first line of real output from our HDL circuit. This output
+// can be viewed in the <chip name>.out file.
+output;
+
+// An example of <chip name>, a chip that takes in a 4 bit value as input and
+// adds 1 to that value could have the following as test code:
+
+// Set the input value to 0000, clock pulse, compare output from cmp file to actual out.
+set in %B0000,
+tick,
+tock,
+output;
+
+// Set the input value to 0110, clock pulse, compare output from cmp file to actual out.
+set in %B0110,
+tick,
+tock,
+output;
+
+// The expected output for case 1 should be 0001 and case 2 expects 0111, lets
+// learn a little more about comparison files before finalizing our lesson.
+```
+
+## Comparison Files
+Now lets take a look at comparison files, the files that hold what the test file
+compares with the actual output of an HDL chip in the hardware simulator!
+
+```verilog
+// Like the <chip name> example above, the structure of the comparison file
+// would look something like this
+| in | out |
+| 0000 | 0001 |
+| 0110 | 0111 |
+
+// Notice how the input values specified in the test case are equivalent to the
+// `in` column of the comparison file, and that the space buffer is 1 on either side.
+
+// If the output from the HDL code we not this, such as the output below, then the
+// test will fail and the user will know that the simulated chip is not correctly designed.
+| in | out |
+| 0000 | 0001 |
+| 0110 | 0110 | // Error! The chip did not add 1 here, something went wrong.
+
+
+```
+
+This is incredibly useful as it allows designers to simulate chip logic prior to
+fabricating real life hardware and identify problems in their designs. Be warned that
+errors in the test or comparison files can lead to both false positives and also
+the more damaging false negatives so ensure that the logic is sound behind the test
+creation.
+
+
+Good luck and happy coding!
+
+## Resources
+
+* [From Nand To Tetris](https://www.nand2tetris.org)
+
+## Further Reading
+
+* [Hardware Description Language](https://en.wikipedia.org/wiki/Hardware_description_language)
+
+* [HDL Programming Fundamentals](https://www.electronicdesign.com/products/hdl-programming-fundamentals) \ No newline at end of file
diff --git a/it-it/bash-it.html.markdown b/it-it/bash-it.html.markdown
index 099cc681..cfe58f30 100644
--- a/it-it/bash-it.html.markdown
+++ b/it-it/bash-it.html.markdown
@@ -63,7 +63,7 @@ echo ${Variabile}
# Sotto ci sono altri esempi che analizzano l'uso dell'espansione dei parametri.
# Sostituzione di stringhe nelle variabili
-echo ${Variabile/Una/A}
+echo ${Variabile/Una/La}
# Questo sostituirà la prima occorrenza di "Una" con "La"
# Sottostringa di una variabile
diff --git a/java.html.markdown b/java.html.markdown
index 4f45a268..79769352 100644
--- a/java.html.markdown
+++ b/java.html.markdown
@@ -381,7 +381,7 @@ public class LearnJava {
do {
System.out.println(fooDoWhile);
// Increment the counter
- // Iterated 99 times, fooDoWhile 0->99
+ // Iterated 100 times, fooDoWhile 0->99
fooDoWhile++;
} while(fooDoWhile < 100);
System.out.println("fooDoWhile Value: " + fooDoWhile);
diff --git a/javascript.html.markdown b/javascript.html.markdown
index ce9772ca..ad1af76a 100644
--- a/javascript.html.markdown
+++ b/javascript.html.markdown
@@ -188,7 +188,7 @@ someVar = myArray.pop(); // Remove last element and return it
// Join all elements of an array with semicolon
var myArray0 = [32,false,"js",12,56,90];
-myArray0.join(";") // = "32;false;js;12;56;90"
+myArray0.join(";"); // = "32;false;js;12;56;90"
// Get subarray of elements from index 1 (include) to 4 (exclude)
myArray0.slice(1,4); // = [false,"js",12]
diff --git a/kdb+.html.markdown b/kdb+.html.markdown
index 027b6571..680c01c1 100644
--- a/kdb+.html.markdown
+++ b/kdb+.html.markdown
@@ -771,6 +771,6 @@ select from splayed / (the columns are read from disk on request)
* [*q for mortals* q language tutorial](http://code.kx.com/q4m3/)
* [*Introduction to Kdb+* on disk data tutorial](http://code.kx.com/q4m3/14_Introduction_to_Kdb+/)
-* [q language reference](http://code.kx.com/q/ref/card/)
+* [q language reference](https://code.kx.com/q/ref/)
* [Online training courses](http://training.aquaq.co.uk/)
* [TorQ production framework](https://github.com/AquaQAnalytics/TorQ)
diff --git a/latex.html.markdown b/latex.html.markdown
index c980f5e5..e8bc6064 100644
--- a/latex.html.markdown
+++ b/latex.html.markdown
@@ -141,7 +141,7 @@ Operators are essential parts of a mathematical document:
trigonometric functions ($\sin$, $\cos$, $\tan$),
logarithms and exponentials ($\log$, $\exp$),
limits ($\lim$), etc.\
-have per-defined LaTeX commands.
+have pre-defined LaTeX commands.
Let's write an equation to see how it's done:
$\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$
diff --git a/linker.html.markdown b/linker.html.markdown
index ebe6233d..42839e05 100644
--- a/linker.html.markdown
+++ b/linker.html.markdown
@@ -5,5 +5,5 @@ contributors:
- ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
---
-This article is available in [Russian](http://localhost:4567/docs/ru-ru/linker-ru/).
+This article is available in [Russian](https://learnxinyminutes.com/docs/ru-ru/linker-ru/).
diff --git a/mips.html.markdown b/mips.html.markdown
index 4134d3fa..45e16e7b 100644
--- a/mips.html.markdown
+++ b/mips.html.markdown
@@ -20,12 +20,12 @@ gateways and routers.
# Programs typically contain a .data and .text sections
.data # Section where data is stored in memory (allocated in RAM), similar to
- # variables in higher level languages
+ # variables in higher-level languages
# Declarations follow a ( label: .type value(s) ) form of declaration
hello_world: .asciiz "Hello World\n" # Declare a null terminated string
num1: .word 42 # Integers are referred to as words
- # (32 bit value)
+ # (32-bit value)
arr1: .word 1, 2, 3, 4, 5 # Array of words
arr2: .byte 'a', 'b' # Array of chars (1 byte each)
@@ -139,7 +139,7 @@ gateways and routers.
# The basic format of these branching instructions typically follow <instr>
# <reg1> <reg2> <label> where label is the label we want to jump to if the
# given conditional evaluates to true
- # Sometimes it is easier to write the conditional logic backwards, as seen
+ # Sometimes it is easier to write the conditional logic backward, as seen
# in the simple if statement example below
beq $t0, $t1, reg_eq # Will branch to reg_eq if
@@ -156,7 +156,7 @@ gateways and routers.
ble $t0, $t1, t0_gte_t1 # Branches when $t0 <= $t1
bltz $t0, t0_lt0 # Branches when $t0 < 0
slt $s0, $t0, $t1 # Instruction that sends a signal when
- # $t0 < $t1 with reuslt in $s0 (1 for true)
+ # $t0 < $t1 with result in $s0 (1 for true)
# Simple if statement
# if (i == j)
@@ -289,12 +289,12 @@ gateways and routers.
## MACROS ##
_macros:
- # Macros are extremly useful for substituting repeated code blocks with a
+ # Macros are extremely useful for substituting repeated code blocks with a
# single label for better readability
# These are in no means substitutes for functions
# These must be declared before it is used
- # Macro for printing new lines (since these can be very repetitive)
+ # Macro for printing newlines (since these can be very repetitive)
.macro println()
la $a0, newline # New line string stored here
li $v0, 4
@@ -338,7 +338,7 @@ gateways and routers.
buffer: .space 128 # Allocates a block in memory, does
# not automatically clear
# These blocks of memory are aligned
- # next each other
+ # next to each other
.text
la $s0, list # Load address of list
diff --git a/php.html.markdown b/php.html.markdown
index 40c9dd01..d4103e97 100644
--- a/php.html.markdown
+++ b/php.html.markdown
@@ -289,7 +289,7 @@ if (false) {
print (false ? 'Does not get printed' : 'Does');
// ternary shortcut operator since PHP 5.3
-// equivalent of "$x ? $x : 'Does'""
+// equivalent of "$x ? $x : 'Does'"
$x = false;
print($x ?: 'Does');
diff --git a/powershell.html.markdown b/powershell.html.markdown
index db29bf96..5d74024d 100644
--- a/powershell.html.markdown
+++ b/powershell.html.markdown
@@ -15,7 +15,7 @@ in the shell.
A key difference with Bash is that it is mostly objects that you manipulate
rather than plain text.
-[Read more here.](https://technet.microsoft.com/en-us/library/bb978526.aspx)
+[Read more here.](https://docs.microsoft.com/powershell/scripting/overview)
If you are uncertain about your environment:
@@ -321,7 +321,7 @@ Interesting Projects
* [PSake](https://github.com/psake/psake) Build automation tool
* [Pester](https://github.com/pester/Pester) BDD Testing Framework
* [Jump-Location](https://github.com/tkellogg/Jump-Location) Powershell `cd` that reads your mind
-* [PowerShell Community Extensions](http://pscx.codeplex.com/) (Dead)
+* [PowerShell Community Extensions](https://github.com/Pscx/Pscx)
Not covered
diff --git a/pt-br/clojure-macros-pt.html.markdown b/pt-br/clojure-macros-pt.html.markdown
index d56840e0..c686bb80 100644
--- a/pt-br/clojure-macros-pt.html.markdown
+++ b/pt-br/clojure-macros-pt.html.markdown
@@ -13,15 +13,15 @@ do Clojure lhe dá acesso a toda a extensão da linguagem
para escrever rotinas de geração de código chamados "macros". Macros fornecem uma poderosa forma de adequar a linguagem
às suas necessidades.
-Pórem Tenha cuidado. É considerado má pratica escrever uma macro quando uma função vai fazer. Use uma macro apenas
-quando você precisar do controle sobre quando ou se os argumentos para um formulário será avaliado.
+Pórem, tenha cuidado. É considerado má pratica escrever uma macro quando uma função vai fazer. Use uma macro apenas
+quando você precisar de controle sobre quando ou se os argumentos de um formulário serão avaliados.
Você vai querer estar familiarizado com Clojure. Certifique-se de entender tudo em
-[Clojure em Y Minutos](/docs/clojure/).
+[Aprenda Clojure em Y Minutos](/docs/clojure/).
```clojure
-;; Defina uma macro utilizando defmacro. Sua macro deve ter como saida uma lista que possa
-;; ser avaliada como codigo Clojure.
+;; Defina uma macro utilizando defmacro. Sua macro deve ter como saída uma lista que possa
+;; ser avaliada como código Clojure.
;;
;; Essa macro é a mesma coisa que se você escrever (reverse "Hello World")
(defmacro my-first-macro []
@@ -33,14 +33,14 @@ Você vai querer estar familiarizado com Clojure. Certifique-se de entender tudo
(macroexpand '(my-first-macro))
;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World")
-;; Você pode avaliar o resultad de macroexpand diretamente:
+;; Você pode avaliar o resultado de macroexpand diretamente:
(eval (macroexpand '(my-first-macro)))
; -> (\d \l \o \r \W \space \o \l \l \e \H)
-;; mas você deve usar esse mais suscinto, sintax como de função:
+;; mas você deve usar essa sintaxe mais sucinta e familiar a funções:
(my-first-macro) ; -> (\d \l \o \r \W \space \o \l \l \e \H)
-;; Você pode tornar as coisas mais faceis pra você, utilizando a sintaxe de citação mais suscinta
+;; Você pode tornar as coisas mais fáceis pra você, utilizando a sintaxe de citação mais suscinta
;; para criar listas nas suas macros:
(defmacro my-first-quoted-macro []
'(reverse "Hello World"))
diff --git a/pt-br/clojure-pt.html.markdown b/pt-br/clojure-pt.html.markdown
index 409394f2..e40b8fe7 100644
--- a/pt-br/clojure-pt.html.markdown
+++ b/pt-br/clojure-pt.html.markdown
@@ -5,12 +5,13 @@ contributors:
- ["Adam Bard", "http://adambard.com/"]
translators:
- ["Mariane Siqueira Machado", "https://twitter.com/mariane_sm"]
+ - ["Ygor Sad", "https://github.com/ysads"]
lang: pt-br
---
-Clojure é uma linguagem da família do Lisp desenvolvida para a JVM (máquina virtual Java). Possui uma ênfase muito mais forte em [programação funcional] (https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_funcional) pura do que Common Lisp, mas inclui diversas utilidades [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) para lidar com estado a medida que isso se torna necessário.
+Clojure é uma linguagem da família do Lisp desenvolvida para a JVM (máquina virtual Java). Possui uma ênfase muito mais forte em [programação funcional] (https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_funcional) pura do que Common Lisp, mas inclui diversos recursos [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) para lidar com estado e mutabilidade, caso isso seja necessário.
-Essa combinação permite gerenciar processamento concorrente de maneira muito simples, e frequentemente de maneira automática.
+Essa combinação permite gerenciar processamento concorrente de maneira muito simples - frequentemente, de modo automático.
(Sua versão de clojure precisa ser pelo menos 1.2)
@@ -18,369 +19,551 @@ Essa combinação permite gerenciar processamento concorrente de maneira muito s
```clojure
; Comentários começam por ponto e vírgula
-; Clojure é escrito em "forms", os quais são simplesmente
-; listas de coisas dentro de parênteses, separados por espaços em branco.
+; Código Clojure é escrito em formas - 'forms', em inglês. Tais estruturas são
+; simplesmente listas de valores encapsuladas dentro de parênteses, separados por
+; espaços em branco.
-; O "reader" (leitor) de Clojure presume que o primeiro elemento de
-; uma par de parênteses é uma função ou macro, e que os resto são argumentos.
+; Ao interpretar um código em Clojure, o interpretador ou leitor - do inglês 'reader' - assume
+; que o primeiro valor dentro de uma forma é uma função ou macro, de modo que os demais valores
+; são seus argumentos. Isso se deve ao fato de que Clojure, por ser uma derivação de Lisp,
+; usa notação prefixa (ou polonesa).
-: A primeira chamada de um arquivo deve ser ns, para configurar o namespace (espaço de nomes)
+; Num arquivo, a primeira chamada deve ser sempre para a função ns,
+; que é responsável por definir em qual namespace o código em questão
+; deve ser alocado
(ns learnclojure)
; Alguns exemplos básicos:
-; str cria uma string concatenando seus argumentos
-(str "Hello" " " "World") ; => "Hello World"
+; Aqui, str é uma função e "Olá" " " e "Mundo" são seus argumentos. O que ela faz é criar
+; uma string concatenando seus argumentos.
+(str "Olá" " " "Mundo") ; => "Olá Mundo"
-; Cálculos são feitos de forma direta e intuitiva
+; Note que espaços em branco separam os argumentos de uma função. Opcionalmente vírgulas
+; podem ser usadas, se você quiser.
+(str, "Olá", " ", "Mundo") ; => "Olá Mundo"
+
+; As operações matemáticas básicas usam os operadores de sempre
(+ 1 1) ; => 2
(- 2 1) ; => 1
(* 1 2) ; => 2
(/ 2 1) ; => 2
-; Você pode comparar igualdade utilizando =
+; Esses operadores aceitam um número arbitrário de argumentos
+(+ 2 2 2) ; = 2 + 2 + 2 => 6
+(- 5 1 1) ; = 5 - 1 - 1 => 3
+(* 3 3 3 3) ; = 3 * 3 * 3 * 3 => 81
+
+; Para verificar se dois valores são iguais, o operador = pode ser usado
(= 1 1) ; => true
(= 2 1) ; => false
-; Negação para operações lógicas
-(not true) ; => false
+; Para saber se dois valores são diferentes
+(not= 1 2) ; => true
+(not (= 1 2)) ; => true
-; Aninhar "forms" funciona como esperado
+; Conforme vimos acima, é possível aninhar duas formas
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
+(* (- 3 2) (+ 1 2)) ; = (3 - 2) * (1 + 2) => 3
+
+; Se a leitura ficar comprometida, as fórmulas também podem ser escritas em múltiplas linhas
+(* (- 3 2)
+ (+ 1 2)) ; => 3
+(*
+ (- 3 2)
+ (+ 1 2)) ; => 3
+
; Tipos
;;;;;;;;;;;;;
-; Clojure usa os tipos de objetos de Java para booleanos, strings e números.
-; Use `class` para inspecioná-los
-(class 1) ; Literais Integer são java.lang.Long por padrão
-(class 1.); Literais Float são java.lang.Double
-(class ""); Strings são sempre com aspas duplas, e são java.lang.String
+; Por ter interoperabilidade com Java, Clojure usa os tipos de objetos de Java para booleanos,
+; strings e números. Para descobrir qual o tipo de um valor, você pode usar a função `class`:
+(class 1234) ; Literais Integer são java.lang.Long por padrão
+(class 1.50) ; Literais Float são java.lang.Double
+(class "oi") ; Strings sempre usam aspas duplas e são java.lang.String
(class false) ; Booleanos são java.lang.Boolean
-(class nil); O valor "null" é chamado nil
-; Se você quiser criar um lista de literais, use aspa simples para
-; ela não ser avaliada
-'(+ 1 2) ; => (+ 1 2)
-; (que é uma abreviação de (quote (+ 1 2)))
+; Tenha cuidado, ao dividir valores inteiros:
+(= (/ 1 2)
+ (/ 1.0 2.0)) ; => false
+
+(class (/ 1 2)) ; => clojure.lang.Ratio
+(class (/ 1.0 2.0)) ; => java.lang.Double
+
+; Aqui temos uma diferença em relação a Java, pois valores nulos são representados por `nil`
+(class nil) ; nil
-; É possível avaliar uma lista com aspa simples
-(eval '(+ 1 2)) ; => 3
; Coleções e sequências
;;;;;;;;;;;;;;;;;;;
-; Listas são estruturas encadeadas, enquanto vetores são implementados como arrays.
-; Listas e Vetores são classes Java também!
-(class [1 2 3]); => clojure.lang.PersistentVector
-(class '(1 2 3)); => clojure.lang.PersistentList
+; Os dois tipos básicos de coleção são listas - "list" em inglês - e vetores - "vectors"
+; no original. A principal diferença entre eles se
+; dá pela implementação:
+; - Vetores são implementados como arrays
+; - Listas são listas ligadas
+(class [1 2 3]) ; => clojure.lang.PersistentVector
+(class '(1 2 3)) ; => clojure.lang.PersistentList
-; Uma lista é escrita como (1 2 3), mas temos que colocar a aspa
-; simples para impedir o leitor (reader) de pensar que é uma função.
-; Também, (list 1 2 3) é o mesmo que '(1 2 3)
+; Outra forma de declarar listas é usando a função list
+(list 1 2 3) ; => '(1 2 3)
-; "Coleções" são apenas grupos de dados
-; Listas e vetores são ambos coleções:
+; Clojure classifica conjuntos de dados de duas maneiras
+
+; "Coleções" são grupos simples de dados
+; Tanto listas quanto vetores são coleções:
(coll? '(1 2 3)) ; => true
(coll? [1 2 3]) ; => true
; "Sequências" (seqs) são descrições abstratas de listas de dados.
-; Apenas listas são seqs.
+; Sequências - ou seqs - são conjuntos de dados com avaliação "lazy"
+; Apenas listas são seqs:
(seq? '(1 2 3)) ; => true
(seq? [1 2 3]) ; => false
-; Um seq precisa apenas prover uma entrada quando é acessada.
-; Portanto, já que seqs podem ser avaliadas sob demanda (lazy) -- elas podem definir séries infinitas:
-(range 4) ; => (0 1 2 3)
-(range) ; => (0 1 2 3 4 ...) (uma série infinita)
-(take 4 (range)) ; (0 1 2 3)
+; Ter avaliação lazy significa que uma seq somente precisa prover uma informação quando
+; ela for requisitada. Isso permite às seqs representar listas infinitas.
+(range) ; => (0 1 2 3 4 ...)
+(cycle [1 2]) ; => (1 2 1 2 1 2 ...)
+(take 4 (range)) ; => (0 1 2 3)
-; Use cons para adicionar um item no início de uma lista ou vetor
+; A função cons é usada para adicionar um item ao início de uma lista ou vetor:
(cons 4 [1 2 3]) ; => (4 1 2 3)
(cons 4 '(1 2 3)) ; => (4 1 2 3)
-; Conj adiciona um item em uma coleção sempre do jeito mais eficiente.
-; Para listas, elas inserem no início. Para vetores, é inserido no final.
+; Já conj adiciona um item em uma coleção sempre do jeito mais eficiente.
+; Em listas, isso significa inserir no início. Já em vetores, ao final.
(conj [1 2 3] 4) ; => [1 2 3 4]
(conj '(1 2 3) 4) ; => (4 1 2 3)
-; Use concat para concatenar listas e vetores
+; Concatenação de coleções pode ser feita usando concat. Note que ela sempre gera uma
+; seq como resultado e está sujeita a problemas de perfomance em coleções grandes, por
+; conta da natureza lazy das seqs.
+(concat '(1 2) [3 4]) ; => (1 2 3 4)
(concat [1 2] '(3 4)) ; => (1 2 3 4)
-; Use filter, map para interagir com coleções
+; Outra forma de concatenar coleções é usando into. Ela não está sujeita a problemas
+; com a avaliação lazy, mas o resultado final da ordem e do tipo dos argumentos passados
+(into [1 2] '(3 4)) ; => [1 2 3 4]
+(into '(1 2) [3 4]) ; => (4 3 1 2)
+
+; Note que em into a ordem dos parâmetros influencia a coleção final.
+(into [1 2] '(3 4)) ; => (1 2 3 4)
+(into '(1 2) [3 4]) ; => (4 3 1 2)
+
+; As funções filter e map podem ser usadas para interagir com as coleções. Repare que
+; elas sempre retornam seqs, independentemente do tipo do seu argumento.
(map inc [1 2 3]) ; => (2 3 4)
-(filter even? [1 2 3]) ; => (2)
+(filter even? [1 2 3 4]) ; => (2 4)
+
+; Use reduce reduzir coleções a um único valor. Também é possível passar um argumento
+; para o valor inicial das operações
+(reduce + [1 2 3]) ; = (+ (+ (+ 1 2) 3) 4) => 10
+(reduce + 10 [1 2 3 4]) ; = (+ (+ (+ (+ 10 1) 2) 3) 4) => 20
+(reduce conj [] '(3 2 1)) ; = (conj (conj (conj [] 3) 2) 1) => [3 2 1]
+
+; Reparou na semelhança entre listas e as chamadas de código Clojure? Isso se deve ao
+; fato de que todo código clojure é escrito usando listas. É por isso que elas sempre
+; são declaradas com o caracter ' na frente. Dessa forma o interpretador não tenta
+; avaliá-las.
+'(+ 2 3) ; cria uma lista com os elementos +, 2 e 3
+(+ 2 3) ; o interpretador chama a função + passando como argumentos 2 e 3
-; Use reduce para reduzi-los
-(reduce + [1 2 3 4])
-; = (+ (+ (+ 1 2) 3) 4)
-; => 10
+; Note que ' é apenas uma abreviação para a função quote.
+(quote (1 2 3)) ; => '(1 2 3)
+
+; É possível passar uma lista para que o interpretador a avalie. Note que isso está
+; sujeito ao primeiro elemento da lista ser um literal com um nome de uma função válida.
+(eval '(+ 2 3)) ; => 5
+(eval '(1 2 3)) ; dá erro pois o interpretador tenta chamar a função 1, que não existe
-; Reduce pode receber um argumento para o valor inicial
-(reduce conj [] '(3 2 1))
-; = (conj (conj (conj [] 3) 2) 1)
-; => [3 2 1]
; Funções
;;;;;;;;;;;;;;;;;;;;;
-; Use fn para criar novas funções. Uma função sempre retorna
-; sua última expressão.
-(fn [] "Hello World") ; => fn
+; Use fn para criar novas funções. Uma função sempre retorna sua última expressão.
+(fn [] "Olá Mundo") ; => fn
+
+; Para executar suas funções, é preciso chamá-las, envolvendo-as em parênteses.
+((fn [] "Olá Mundo")) ; => "Olá Mundo"
+
+; Como isso não é muito prático, você pode nomear funções atribuindo elas a literais.
+; Isso torna muito mais fácil chamá-las:
+(def ola-mundo (fn [] "Olá Mundo")) ; => fn
+(ola-mundo) ; => "Olá Mundo"
-; (É necessário colocar parênteses para chamá-los)
-((fn [] "Hello World")) ; => "Hello World"
+; Você pode abreviar esse processo usando defn:
+(defn ola-mundo [] "Olá Mundo")
-; Você pode atribuir valores a variáveis utilizando def
-(def x 1)
-x ; => 1
+; Uma função pode receber uma lista de argumentos:
+(defn ola
+ [nome]
+ (str "Olá " nome))
+(ola "Jonas") ; => "Olá Jonas"
-; Atribua uma função para uma var
-(def hello-world (fn [] "Hello World"))
-(hello-world) ; => "Hello World"
+; É possível criar funções que recebam multivariadas, isto é, que aceitam números
+; diferentes de argumentos:
+(defn soma
+ ([] 0)
+ ([a] a)
+ ([a b] (+ a b)))
-; Você pode abreviar esse processo usando defn
-(defn hello-world [] "Hello World")
+(soma) ; => 0
+(soma 1) ; => 1
+(soma 1 2) ; => 3
-; O [] é uma lista de argumentos para um função.
-(defn hello [name]
- (str "Hello " name))
-(hello "Steve") ; => "Hello Steve"
+; Funções podem agrupar argumentos extras em uma seq:
+(defn conta-args
+ [& args]
+ (str "Você passou " (count args) " argumentos: " args))
+(conta-args 1 2 3 4) ; => "Você passou 4 argumentos: (1 2 3 4)"
-; Você pode ainda usar essa abreviação para criar funcões:
-(def hello2 #(str "Hello " %1))
-(hello2 "Fanny") ; => "Hello Fanny"
+; Você pode misturar argumentos regulares e argumentos em seq:
+(defn ola-e-conta
+ [nome & args]
+ (str "Olá " nome ", você passou " (count args) " argumentos extras"))
+(ola-e-conta "Maria" 1 2 3 4) ; => "Olá Maria, você passou 4 argumentos extras"
-; Vocé pode ter funções multi-variadic, isto é, com um número variável de argumentos
-(defn hello3
- ([] "Hello World")
- ([name] (str "Hello " name)))
-(hello3 "Jake") ; => "Hello Jake"
-(hello3) ; => "Hello World"
-; Funções podem agrupar argumentos extras em uma seq
-(defn count-args [& args]
- (str "You passed " (count args) " args: " args))
-(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
+; Nos exemplos acima usamos def para associar nomes a funções, mas poderíamos usá-lo
+; para associar nomes a quaisquer valores:
+(def xis :x)
+xis ; => :x
-; Você pode misturar argumentos regulares e argumentos em seq
-(defn hello-count [name & args]
- (str "Hello " name ", you passed " (count args) " extra args"))
-(hello-count "Finn" 1 2 3)
-; => "Hello Finn, you passed 3 extra args"
+; Inclusive, tais literais podem possuir alguns caracteres não usuais em outras linguagens:
+(def *num-resposta* 42)
+(def conexao-ativa? true)
+(def grito-de-medo! "AAAAAAA")
+(def ->vector-vazio [])
+
+; É possível, inclusive, criar apelidos a nomes que já existem:
+(def somar! soma)
+(somar! 41 1) ; => 42
+
+; Uma forma rápida de criar funções é por meio de funções anônimas. Elas são ótimas
+; para manipulação de coleções e seqs, já que podem ser passadas para map, filter
+; e reduce. Nessas funções, % é substituído por cada um dos items na seq ou na coleção:
+(filter #(not= % nil) ["Joaquim" nil "Maria" nil "Antônio"]) ; => ("Joaquim" "Maria" "Antônio")
+(map #(* % (+ % 2)) [1 2]) ; => (3 8)
; Mapas
;;;;;;;;;;
-; Hash maps e array maps compartilham uma mesma interface. Hash maps são mais
-; rápidos para pesquisa mas não mantém a ordem da chave.
+; Existem dois tipos de mapas: hash maps e array maps. Ambos compartilham uma mesma
+; interface e funções. Hash maps são mais rápidos para retornar dados, mas não mantém
+; as chaves ordenadas.
(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
-; Arraymaps pode automaticamente se tornar hashmaps através da maioria das
-; operações se eles ficarem grandes o suficiente, portanto não há necessida de
-; se preocupar com isso.
-
-;Mapas podem usar qualquer valor que se pode derivar um hash como chave
+; Clojure converte automaticamente array maps em hash maps, por meio da maioria das
+; funções de manipulação de mapas, caso eles fiquem grandes o suficiente. Não é
+; preciso se preocupar com isso.
-
-; Mapas podem usar qualquer valor em que se pode derivar um hash como chave,
-; mas normalmente palavras-chave (keywords) são melhores.
-; Keywords são como strings mas com algumas vantagens.
+; Chaves podem ser qualquer valor do qual possa ser obtido um hash, mas normalmente
+; usam-se keywords como chave, por possuírem algumas vantagens.
(class :a) ; => clojure.lang.Keyword
-(def stringmap {"a" 1, "b" 2, "c" 3})
-stringmap ; => {"a" 1, "b" 2, "c" 3}
+; Keywords são como strings, porém, duas keywords de mesmo valor são sempre armazenadas
+; na mesma posição de memória, o que as torna mais eficientes.
+(identical? :a :a) ; => true
+(identical? (String. "a") (String. "a")) ; => false
-(def keymap {:a 1, :b 2, :c 3})
-keymap ; => {:a 1, :c 3, :b 2}
+(def mapa-strings {"a" 1 "b" 2 "c" 3})
+mapa-strings ; => {"a" 1, "b" 2, "c" 3}
-; A propósito, vírgulas são sempre tratadas como espaçoes em branco e não fazem nada.
+(def mapa-keywords {:a 1 :b 2 :c 3})
+mapa-keywords ; => {:a 1, :c 3, :b 2}
-; Recupere o valor de um mapa chamando ele como uma função
-(stringmap "a") ; => 1
-(keymap :a) ; => 1
+; Você pode usar um mapa como função para recuperar um valor dele:
+(mapa-strings "a") ; => 1
+(mapa-keywords :a) ; => 1
-; Uma palavra-chave pode ser usada pra recuperar os valores de um mapa
-(:b keymap) ; => 2
+; Se a chave buscada for uma keyword, ela também pode ser usada como função para recuperar
+; valores. Note que isso não funciona com strings.
+(:b mapa-keywords) ; => 2
+("b" mapa-strings) ; => java.lang.String cannot be cast to clojure.lang.IFn
-; Não tente isso com strings
-;("a" stringmap)
-; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
+; Se você buscar uma chave que não existe, Clojure retorna nil:
+(mapa-strings "d") ; => nil
-; Buscar uma chave não presente retorna nil
-(stringmap "d") ; => nil
+; Use assoc para adicionar novas chaves em um mapa.
+(def mapa-keywords-estendido (assoc mapa-keywords :d 4))
+mapa-keywords-estendido ; => {:a 1, :b 2, :c 3, :d 4}
-; Use assoc para adicionar novas chaves para hash-maps
-(def newkeymap (assoc keymap :d 4))
-newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
+; Mas lembre-se que tipos em Clojure são sempre imutáveis! Isso significa que o mapa
+; inicial continua com as mesmas informações e um novo mapa, com mais dados, é criado
+; a partir dele
+mapa-keywords ; => {:a 1, :b 2, :c 3}
-; Mas lembre-se, tipos em Clojure são sempre imutáveis!
-keymap ; => {:a 1, :b 2, :c 3}
+; assoc também pode ser usado para atualizar chaves:
+(def outro-mapa-keywords (assoc mapa-keywords :a 0))
+outro-mapa-keywords ; => {:a 0, :b 2, :c 3}
; Use dissoc para remover chaves
-(dissoc keymap :a :b) ; => {:c 3}
+(dissoc mapa-keywords :a :b) ; => {:c 3}
+
+; Mapas também são coleções - mas não seqs!
+(coll? mapa-keywords) ; => true
+(seq? mapa-keywords) ; => false
+
+; É possível usar filter, map e qualquer outra função de coleções em mapas.
+; Porém a cada iteração um vetor no formato [chave valor] vai ser passado como
+; argumento. Por isso é conveniente usar funções anônimas.
+(filter #(odd? (second %)) mapa-keywords) ; => ([:a 1] [:c 3])
+(map #(inc (second %)) mapa-keywords) ; => (2 3 4)
; Conjuntos
;;;;;;
-(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
+; Conjuntos são um tipo especial de coleções que não permitem elementos repetidos.
+; Eles podem ser criados com #{} ou com a função set.
(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
+(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
-; Adicione um membro com conj
-(conj #{1 2 3} 4) ; => #{1 2 3 4}
+; Note que nem sempre um set vai armazenar seus elementos na ordem esperada.
+(def meu-conjunto #{1 2 3})
+meu-conjunto ; => #{1 3 2}
-; Remova um membro com disj
-(disj #{1 2 3} 1) ; => #{2 3}
+; Adição funciona normalmente com conj.
+(conj meu-conjunto 4) ; => #{1 4 3 2}
-; Test por existência usando set como função:
-(#{1 2 3} 1) ; => 1
-(#{1 2 3} 4) ; => nil
+; Remoção, no entanto, precisa ser feita com disj:
+(disj meu-conjunto 1) ; => #{3 2}
-; Existem muitas outras funções no namespace clojure.sets
+; Para saber se um elemento está em um conjunto, use-o como função. Nesse aspecto
+; conjuntos funcionam de maneira semelhante a mapas.
+(meu-conjunto 1) ; => 1
+(meu-conjunto 4) ; => nil
-; Forms úteis
-;;;;;;;;;;;;;;;;;
-; Construções lógicas em Clojure são como macros, e
-; se parecem com as demais
-(if false "a" "b") ; => "b"
-(if false "a") ; => nil
+; Condicionais e blocos
+;;;;;;;;;;;;;;;;;
-; Use let para criar um novo escopo associando sîmbolos a valores (bindings)
+; Você pode usar um bloco let para criar um escopo local, no qual estarão disponíveis
+; os nomes que você definir:
(let [a 1 b 2]
- (> a b)) ; => false
+ (+ a b)) ; => 3
-; Agrupe comandos juntos com "do"
-(do
- (print "Hello")
- "World") ; => "World" (prints "Hello")
+(let [cores {:yellow "Amarelo" :blue "Azul"}
+ nova-cor :red
+ nome-cor "Vermelho"]
+ (assoc cores nova-cor nome-cor)) ; => {:yellow "Amarelo", :blue "Azul", :red "Vermelho"}
-; Funções tem um do implícito
-(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")
+; Formas do tipo if aceitam três argumentos: a condição de teste, o comando a ser
+; executado caso a condição seja positiva; e o comando para o caso de ela ser falsa.
+(if true "a" "b") ; => "a"
+(if false "a" "b") ; => "b"
+
+; Opcionalmente você pode não passar o último argumento, mas se a condição for falsa
+; o if vai retornar nil.
+(if false "a") ; => nil
+
+; A forma if somente aceita um comando para ser executado em cada caso. Se você
+; precisar executar mais comandos, você pode usar a função do:
+(if true
+ (do
+ (print "Olá ")
+ (print "Mundo"))) ; => escreve "Olá Mundo" na saída
+
+; Se você só deseja tratar o caso de sua condição ser verdadeira, o comando when é
+; uma alternativa melhor. Seu comportamento é idêntico a um if sem condição negativa.
+; Uma de suas vantagens é permitir a execução de vários comandos sem exigir do:
+(when true "a") ; => "a"
+(when true
+ (print "Olá ")
+ (print "Mundo")) ; => também escreve "Olá Mundo" na saída
+
+; Isso ocorre porque when possui um bloco do implícito. O mesmo se aplica a funções e
+; comandos let:
+(defn escreve-e-diz-xis
+ [nome]
+ (print "Diga xis, " nome)
+ (str "Olá " nome))
+(escreve-e-diz-xis "João") ;=> "Olá João", além de escrever "Diga xis, João" na saída.
+
+(let [nome "Nara"]
+ (print "Diga xis, " nome)
+ (str "Olá " nome)) ;=> "Olá João", além de escrever "Diga xis, João" na saída.
-; Assim como let
-(let [name "Urkel"]
- (print "Saying hello to " name)
- (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
; Módulos
;;;;;;;;;;;;;;;
-; Use "use" para poder usar todas as funções de um modulo
+; Você pode usar a função use para carregar todas as funções de um módulo.
(use 'clojure.set)
-; Agora nós podemos usar operações com conjuntos
+; Agora nós podemos usar operações de conjuntos definidas nesse módulo:
(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
(difference #{1 2 3} #{2 3 4}) ; => #{1}
-; Você pode escolher um subconjunto de funções para importar
-(use '[clojure.set :only [intersection]])
-
-; Use require para importar um módulo
+; Isso porém não é uma boa prática pois dificulta saber de qual módulo cada função
+; veio, além de expor o código a conflitos de nomes, caso dois módulos diferentes
+; definam funções com o mesmo nome. A melhor forma de referenciar módulos é por meio
+; de require:
(require 'clojure.string)
-; Use / para chamar funções de um módulo
+; Com isso podemos chamar as funções de clojure.string usando o operador /
; Aqui, o módulo é clojure.string e a função é blank?
(clojure.string/blank? "") ; => true
-; Você pode dar para um módulo um nome mais curto no import
+; Porém isso não é muito prático, por isso é possível dar para um nome mais curto para
+; o módulo ao carregá-lo:
(require '[clojure.string :as str])
-(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
-; (#"" denota uma expressão regular literal)
+(str/replace "alguém quer teste?" #"[aeiou]" str/upper-case) ; => "AlgUém qUEr tEstE?"
-; Você pode usar require (e até "use", mas escolha require) de um namespace utilizando :require.
-; Não é necessário usar aspa simples nos seus módulos se você usar desse jeito.
+; Nesse exemplo usamos também a construção #"", que delimita uma expressão regular.
+
+; É possível carregar outros módulos direto na definição do namespace. Note que nesse
+; contexto não é preciso usar ' antes do vetor que define a importação do módulo.
(ns test
(:require
[clojure.string :as str]
[clojure.set :as set]))
+
+; Operadores thread
+;;;;;;;;;;;;;;;;;
+
+; Uma das funções mais interessantes de clojure são os operadores -> e ->> - respectivamente
+; thread-first e thread-last macros. Elas permitem o encadeamento de chamadas de funções,
+; sendo perfeitas para melhorar a legibilidade em transformações de dados.
+
+; -> usa o resultado de uma chamada como o primeiro argumento da chamada à função seguinte:
+(-> " uMa StRIng com! aLG_uNs ##problemas. "
+ (str/replace #"[!#_]" "")
+ (str/replace #"\s+" " ")
+ str/trim ; se a função só aceitar um argumento, não é preciso usar parênteses
+ (str/lower-case)) ; => "uma string com alguns problemas."
+
+; Na thread uma string com vários problemas foi passada como primeiro argumento à função
+; str/replace, que criou uma nova string, a partir da original, porém somente com caracteres
+; alfabéticos. Essa nova string foi passada como primeiro argumento para a chamada str/replace
+; seguinte, que criou uma nova string sem espaços duplos. Essa nova string foi então passada
+; como primeiro argumento para str/trim, que removeu espaços de seu início e fim, passando essa
+; última string para str/lower-case, que a converteu para caracteres em caixa baixa.
+
+; ->> é equivalente a ->, porém o retorno de cada função é passado como último argumento da
+; função seguinte. Isso é particularmente útil para lidar com seqs, já que as funções que
+; as manipulam sempre as tomam como último argumento.
+(->> '(1 2 3 4)
+ (filter even?) ; => '(2 4)
+ (map inc) ; => '(3 5)
+ (reduce *)) ; => 15
+
+
; Java
;;;;;;;;;;;;;;;;;
-; Java tem uma biblioteca padrão enorme e muito útil,
-; portanto é importante aprender como utiliza-la.
+; A biblioteca padrão de Java é enorme e possui inúmeros algoritmos e estruturas de
+; dados já implementados. Por isso é bastante conveniente saber como usá-la dentro
+; de Clojure.
-; Use import para carregar um modulo java
+; Use import para carregar um módulo Java.
(import java.util.Date)
-; Você pode importar usando ns também.
+; Você pode importar classes Java dentro de ns também:
(ns test
(:import java.util.Date
- java.util.Calendar))
+ java.util.Calendar
+ java.util.ArrayList))
; Use o nome da clase com um "." no final para criar uma nova instância
-(Date.) ; <a date object>
+(def instante (Date.))
+(class instante) => ; java.util.Date
+
+; Para chamar um método, use o operador . com o nome do método. Outra forma é
+; usar simplesmente .<nome do método>
+(. instante getTime) ; => retorna um inteiro representando o instante
+(.getTime instante) ; => exatamente o mesmo que acima
-; Use . para chamar métodos. Ou, use o atalho ".method"
-(. (Date.) getTime) ; <a timestamp>
-(.getTime (Date.)) ; exatamente a mesma coisa.
+; Para chamar métodos estáticos dentro de classes Java, use /
+(System/currentTimeMillis) ; => retorna um timestamp
-; Use / para chamar métodos estáticos
-(System/currentTimeMillis) ; <a timestamp> (o módulo System está sempre presente)
+; Note que não é preciso importar o módulo System, pois ele está sempre presente
+
+; Caso queira submeter uma instância de uma classe mutável a uma sequência de operações,
+; você pode usar a função doto. Ela é funciona de maneira semelhante à função -> - ou
+; thread-first -, exceto pelo fato de que ele opera com valores mutáveis.
+(doto (java.util.ArrayList.)
+ (.add 11)
+ (.add 3)
+ (.add 7)
+ (java.util.Collections/sort)) ; => #<ArrayList [3, 7, 11]>
-; Use doto para pode lidar com classe (mutáveis) de forma mais tolerável
-(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 é o mecanismo que Clojure usa para gerenciar
-; estado persistente. Tem algumas construções em Clojure que o utilizam.
+; Até aqui usamos def para associar nomes a valores. Isso, no entanto, possui algumas
+; limitações, já que, uma vez definido essa associação, não podemos alterar o valor
+; para o qual um nome aponta. Isso significa que nomes definidos com def não se
+; comportam como as variáveis de outras linguagens.
+
+; Para lidar com estado persistente e mutação de valores, Clojure usa o mecanismo Software
+; Transactional Memory. O atom é o mais simples de todos. Passe pra ele um valor inicial e
+; e ele criará um objeto que é seguro de atualizar:
+(def atom-mapa (atom {}))
+
+; Para acessar o valor de um atom, você pode usar a função deref ou o operador @:
+@atom-mapa ; => {}
+(deref atom-mapa) ; => {}
-; O atom é o mais simples. Passe pra ele um valor inicial
-(def my-atom (atom {}))
+; Para mudar o valor de um atom, você deve usar a função swap!
+; O que ela faz é chamar a função passada usando o atom como seu primeiro argumento. Com
+; isso, ela altera o valor do atom de maneira segura.
+(swap! atom-mapa assoc :a 1) ; Atribui a atom-mapa o resultado de (assoc {} :a 1)
+(swap! atom-mapa assoc :b 2) ; Atribui a atom-mapa o resultado de (assoc {:a 1} :b 2)
-; Atualize o atom com um swap!.
-; swap! pega uma função e chama ela com o valor atual do atom
-; como primeiro argumento, e qualquer argumento restante como o segundo
-(swap! my-atom assoc :a 1) ; Coloca o valor do átomo my-atom como o resultado de (assoc {} :a 1)
-(swap! my-atom assoc :b 2) ; Coloca o valor do átomo my-atom como o resultado de (assoc {:a 1} :b 2)
+; Observe que essas chamadas alteraram de fato o valor de atom-mapa. Seu novo valor é:
+@atom-mapa ; => {:a 1 :b 2}
-; Use '@' para desreferenciar um atom e acessar seu valor
-my-atom ;=> Atom<#...> (Retorna o objeto do Atom)
-@my-atom ; => {:a 1 :b 2}
+; Isso é diferente de fazer:
+(def atom-mapa-2 (atom {}))
+(def atom-mapa-3 (assoc @atom-mapa-2 :a 1))
-; Abaixo um contador simples usando um atom
-(def counter (atom 0))
-(defn inc-counter []
- (swap! counter inc))
+; Nesse exemplo, atom-mapa-2 permanece com o seu valor original e é gerado um novo mapa,
+; atom-mapa-3, que contém o valor de atom-mapa-2 atualizado. Note que atom-mapa-3 é um
+; simples mapa, e não uma instância de um atom
+@atom-mapa-2 ; => {}
+atom-mapa-3 ; => {:a 1}
-(inc-counter)
-(inc-counter)
-(inc-counter)
-(inc-counter)
-(inc-counter)
+(class atom-mapa-2) ; => clojure.lang.Atom
+(class atom-mapa-3) ; => clojure.lang.PersistentArrayMap
-@counter ; => 5
+; A ideia é que o valor do atom só será atualizado se, após ser executada a função passada
+; para swap!, o atom ainda estiver com o mesmo valor de antes. Isto é, se durante a execução
+; da função alguém alterar o valor do atom, swap! reexecutará a função recebida usando o valor
+; atual do átoma como argumento.
-; Outras construção STM são refs e agents.
+; Isso é ótimo em situações nas quais é preciso garantir a consistência de algum valor - tais
+; como sistemas bancários e sites de compra. Para mais exemplos e informações sobre outras
+; construções STM:
+
+; Exemplos e aplicações: https://www.braveclojure.com/zombie-metaphysics/
; Refs: http://clojure.org/refs
; Agents: http://clojure.org/agents
```
### Leitura adicional
-Esse tutorial está longe de ser exaustivo, mas deve ser suficiente para que você possa começar.
+Esse tutorial está longe de ser completo, mas deve ser suficiente para que você possa dar seus primeiros passos em Clojure.
+Caso queira aprender mais:
-Clojure.org tem vários artigos:
+* clojure.org tem vários artigos:
[http://clojure.org/](http://clojure.org/)
-Clojuredocs.org tem documentação com exemplos para quase todas as funções principais (pertecentes ao core):
+* Brave Clojure possui um e-book que explora em profundidade diversos recursos de clojure, incluindo ótimos exemplos:
+[https://www.braveclojure.com/](https://www.braveclojure.com/)
+
+* clojuredocs.org tem documentação com exemplos para quase todas as funções principais (pertecentes ao core):
[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
-4Clojure é um grande jeito de aperfeiçoar suas habilidades em Clojure/Programação Funcional:
+* 4clojure possui alguns problemas e desafios interessantes para quem quiser treinar clojure ou programação funcional:
[http://www.4clojure.com/](http://www.4clojure.com/)
-Clojure-doc.org tem um bom número de artigos para iniciantes:
+* clojure-doc.org tem um bom número de artigos para iniciantes:
[http://clojure-doc.org/](http://clojure-doc.org/)
Clojure for the Brave and True é um livro de introdução ao Clojure e possui uma versão gratuita online:
diff --git a/pt-br/pascal-pt.html.markdown b/pt-br/pascal-pt.html.markdown
index 82cce843..72302695 100644
--- a/pt-br/pascal-pt.html.markdown
+++ b/pt-br/pascal-pt.html.markdown
@@ -4,6 +4,7 @@ filename: learnpascal-pt.pas
contributors:
- ["Ganesha Danu", "https://github.com/blinfoldking"]
- ["Keith Miyake", "https//github.com/kaymmm"]
+ - ["Raul Almeida", "https://github.com/almeidaraul"]
translators:
- ["Raul Almeida", "https://github.com/almeidaraul"]
lang: pt-br
diff --git a/pt-br/vim-pt.html.markdown b/pt-br/vim-pt.html.markdown
index d7617bbe..cc304381 100644
--- a/pt-br/vim-pt.html.markdown
+++ b/pt-br/vim-pt.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["RadhikaG", "https://github.com/RadhikaG"]
translators:
- ["David Lima", "https://github.com/davelima"]
+ - ["Raul Almeida", "https://github.com/almeidaraul"]
lang: pt-br
filename: LearnVim-pt.txt
---
@@ -24,6 +25,7 @@ para agilizar a navegação para pontos específicos no arquivo, além de ediç
:w # Salva o arquivo atual
:wq # Salva o arquivo e fecha o vim
:q! # Fecha o vim e descarta as alterações no arquivo
+ # ! depois de qualquer comando força a sua execução
# ! *força* :q a executar, fechando o vim sem salvar antes
:x # Salva o arquivo e fecha o vim (atalho para :wq)
@@ -158,7 +160,15 @@ Alguns exemplos importantes de 'Verbos', 'Modificadores' e 'Nomes':
:earlier 15m # Reverte o documento para como ele estava há 15 minutos atrás
:later 15m # Reverte o comando acima
ddp # Troca linhas consecutivas de posição, dd e depois p
+ xp # Permuta caractere atual e o seguinte
+ Xp # Permuta caractere atual e o anterior
. # Repete a última ação
+
+ # Em geral, o usuário pode associar um comando em maísculas (exemplo: D) com
+ # "executar este comando até o final da linha"
+
+ # Usar a tecla de um comando duas vezes geralmente significa executar este
+ # comando sobre toda a linha (exemplo: dd apaga a linha inteira)
```
## Macros
@@ -172,6 +182,7 @@ exatamente a mesma sequencia de ações e comandos na seleção atual.
qa # Inicia a gravação de uma macro chamado 'a'
q # Para a gravação
@a # Executa a macro
+ @@ # Executa a última macro executada
```
### Configurando o ~/.vimrc
diff --git a/python3.html.markdown b/python3.html.markdown
index 6e8d2460..f69ffb14 100644
--- a/python3.html.markdown
+++ b/python3.html.markdown
@@ -16,8 +16,6 @@ Python was created by Guido van Rossum in the early 90s. It is now one of the mo
languages in existence. I fell in love with Python for its syntactic clarity. It's basically
executable pseudocode.
-Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) or louiedinh [at] [google's email service]
-
Note: This article applies to Python 3 specifically. Check out [here](http://learnxinyminutes.com/docs/python/) if you want to learn the old Python 2.7
```python
@@ -58,11 +56,12 @@ Note: This article applies to Python 3 specifically. Check out [here](http://lea
2**3 # => 8
# Enforce precedence with parentheses
+1 + 3 * 2 # => 7
(1 + 3) * 2 # => 8
# Boolean values are primitives (Note: the capitalization)
-True
-False
+True # => True
+False # => False
# negate with not
not True # => False
@@ -138,20 +137,6 @@ b == a # => True, a's and b's objects are equal
# You can find the length of a string
len("This is a string") # => 16
-# .format can be used to format strings, like this:
-"{} can be {}".format("Strings", "interpolated") # => "Strings can be interpolated"
-
-# You can repeat the formatting arguments to save some typing.
-"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick")
-# => "Jack be nimble, Jack be quick, Jack jump over the candle stick"
-
-# You can use keywords if you don't want to count.
-"{name} wants to eat {food}".format(name="Bob", food="lasagna") # => "Bob wants to eat lasagna"
-
-# If your Python 3 code also needs to run on Python 2.5 and below, you can also
-# still use the old style of formatting:
-"%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way"
-
# You can also format using f-strings or formatted string literals (in Python 3.6+)
name = "Reiko"
f"She said her name is {name}." # => "She said her name is Reiko"
@@ -394,6 +379,9 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6}
2 in filled_set # => True
10 in filled_set # => False
+# Make a one layer deep copy
+filled_set = some_set.copy() # filled_set is {1, 2, 3, 4, 5}
+filled_set is some_set # => False
####################################################
diff --git a/ruby.html.markdown b/ruby.html.markdown
index 3fc2ed2d..376f4a47 100644
--- a/ruby.html.markdown
+++ b/ruby.html.markdown
@@ -256,7 +256,7 @@ else
'else, also optional'
end
-# If a condition controls invokation of a single statement rather than a block of code
+# If a condition controls invocation of a single statement rather than a block of code
# you can use postfix-if notation
warnings = ['Patronimic is missing', 'Address too short']
puts("Some warnings occurred:\n" + warnings.join("\n")) if !warnings.empty?
diff --git a/rust.html.markdown b/rust.html.markdown
index 92794e69..23dcbd4f 100644
--- a/rust.html.markdown
+++ b/rust.html.markdown
@@ -1,5 +1,5 @@
---
-language: rust
+language: Rust
contributors:
- ["P1start", "http://p1start.github.io/"]
filename: learnrust.rs
diff --git a/sass.html.markdown b/sass.html.markdown
index 224db80e..860e550a 100644
--- a/sass.html.markdown
+++ b/sass.html.markdown
@@ -16,7 +16,7 @@ This tutorial is written using SCSS.
If you're already familiar with CSS3, you'll be able to pick up Sass relatively quickly. It does not provide any new styling properties but rather the tools to write your CSS more efficiently and make maintenance much easier.
-```sass
+```scss
//Single line comments are removed when Sass is compiled to CSS.
diff --git a/smalltalk.html.markdown b/smalltalk.html.markdown
index ae7ecb0e..d6d369cc 100644
--- a/smalltalk.html.markdown
+++ b/smalltalk.html.markdown
@@ -30,7 +30,8 @@ The most basic operation is to send a message to an object
`anObject aMessage`
There are three sorts of messages
-- unary - a single string that may be several words conjoined in what we call camelcase form, with no arguments. For example 'size', 'reverseBytes', 'convertToLargerFormatPixels'
+
+- unary - a single symbol that may be several words conjoined in what we call camelcase form, with no arguments. For example 'size', 'reverseBytes', 'convertToLargerFormatPixels'
- binary - a small set of symbols of the sort often used for arithmetic operations in most languages, requiring a single argument. For example '+', '//', '@'. We do not use traditional arithmetic precedence, something to keep an eye on.
- keyword - the general form where multiple arguments can be passed. As with the unary form we use camelcase to join words together but arguments are inserted in the midst of the message with colons used to separate them lexically. For example 'setTemperature:', 'at:put:', 'drawFrom:to:lineWidth:fillColor:'
@@ -38,21 +39,23 @@ There are three sorts of messages
`result := myObject doSomethingWith: thatObject`
We are sending the message 'doSomethingWith:' to myObject. This happens to be a message that has a single argument but that's not important yet.
'myObject' is a 'MyExampleClass' instance so the system looks at the list of messages understood by MyExampleClass
+
- beClever
- doWierdThing:
- doSomethingWith
In searching we see what initially looks like a match - but no, it lacks the final colon. So we find the super class of MyExampleClass - BigExampleClass. Which has a list of known messages of its own
+
- beClever
- doSomethingWith:
- buildCastleInAir
- annoyUserByDoing:
-We find a proper exact match and start to execute the code
-```
+We find a proper exact match and start to execute the code:
+
+```smalltalk
doSomethingWith: argumentObject
-"A comment about what this code is meant to do and any known limitations, problems, where it might be further documented etc"
-self size > 4 ifTrue: [^argumentObject sizeRelatingTo: self].
+ self size > 4 ifTrue: [^argumentObject sizeRelatingTo: self].
```
Everything here except the `^` involves sending more messages. Event the `ifTrue:` that you might think is a language control structure is just Smalltalk code.
@@ -94,7 +97,7 @@ Taken from [Smalltalk Cheatsheet](http://www.angelfire.com/tx4/cus/notes/smallta
`"Period (.) is the statement separator. Not required on last line of a method"`
#### Transcript:
-```
+```smalltalk
Transcript clear. "clear to transcript window"
Transcript show: 'Hello World'. "output string in transcript window"
Transcript nextPutAll: 'Hello World'. "output string in transcript window"
@@ -108,26 +111,17 @@ Transcript endEntry. "flush the output buffer"
```
#### Assignment:
-```
+```smalltalk
| x y |
x _ 4. "assignment (Squeak) <-"
x := 5. "assignment"
x := y := z := 6. "compound assignment"
x := (y := 6) + 1.
x := Object new. "bind to allocated instance of a class"
-x := 123 class. "discover the object class"
-x := Integer superclass. "discover the superclass of a class"
-x := Object allInstances. "get an array of all instances of a class"
-x := Integer allSuperclasses. "get all superclasses of a class"
-x := 1.2 hash. "hash value for object"
-y := x copy. "copy object"
-y := x shallowCopy. "copy object (not overridden)"
-y := x deepCopy. "copy object and instance vars"
-y := x veryDeepCopy. "complete tree copy using a dictionary"
```
#### Constants:
-```
+```smalltalk
| b |
b := true. "true constant"
b := false. "false constant"
@@ -147,7 +141,7 @@ x := #('abc' 2 $a). "mixing of types allowed"
```
#### Booleans:
-```
+```smalltalk
| b x y |
x := 1. y := 2.
b := (x = y). "equals"
@@ -185,7 +179,7 @@ b := $A isLowercase. "test if lower case character"
```
#### Arithmetic expressions:
-```
+```smalltalk
| x |
x := 6 + 3. "addition"
x := 6 - 3. "subtraction"
@@ -241,7 +235,7 @@ x := 100 atRandom. "quick random number"
```
#### Bitwise Manipulation:
-```
+```smalltalk
| b x |
x := 16rFF bitAnd: 16r0F. "and bits"
x := 16rF0 bitOr: 16r0F. "or bits"
@@ -257,7 +251,7 @@ b := 16rFF noMask: 16r0F. "test if all bits set in mask clear in recei
```
#### Conversion:
-```
+```smalltalk
| x |
x := 3.99 asInteger. "convert number to integer (truncates in Squeak)"
x := 3.99 asFraction. "convert number to fraction"
@@ -281,7 +275,7 @@ x := 15 storeStringBase: 16.
- `^`expression terminates block & method (exits all nested blocks)
- blocks intended for long term storage should not contain `^`
-```
+```smalltalk
| x y z |
x := [ y := 1. z := 2. ]. x value. "simple block usage"
x := [ :argOne :argTwo | argOne, ' and ' , argTwo.]. "set up block with argument passing"
@@ -304,7 +298,7 @@ Transcript show: (x value: 'First' value: 'Second'); cr. "use block with argu
- private (methods private to class)
- instance-creation (class methods for creating instance)
-```
+```smalltalk
| x |
x := 2 sqrt. "unary message"
x := 2 raisedTo: 10. "keyword message"
@@ -319,7 +313,7 @@ x := 3 + 2; * 100. "result=300. Sends message to same
```
#### Conditional Statements:
-```
+```smalltalk
| x |
x > 10 ifTrue: [Transcript show: 'ifTrue'; cr]. "if then"
x > 10 ifFalse: [Transcript show: 'ifFalse'; cr]. "if else"
@@ -359,7 +353,7 @@ result := (switch at: $B) value.
```
#### Iteration statements:
-```
+```smalltalk
| x y |
x := 4. y := 1.
[x > 0] whileTrue: [x := x - 1. y := y * 2]. "while true loop"
@@ -371,7 +365,7 @@ x timesRepeat: [y := y * 2]. "times repeat loop (i := 1 to x
```
#### Character:
-```
+```smalltalk
| x y |
x := $A. "character assignment"
y := x isLowercase. "test if lower case"
@@ -391,7 +385,7 @@ y := $A max: $B.
```
#### Symbol:
-```
+```smalltalk
| b x y |
x := #Hello. "symbol assignment"
y := 'String', 'Concatenation'. "symbol concatenation (result is string)"
@@ -413,7 +407,7 @@ y := x asSet. "convert symbol to set collect
```
#### String:
-```
+```smalltalk
| b x y |
x := 'This is a string'. "string assignment"
x := 'String', 'Concatenation'. "string concatenation"
@@ -447,7 +441,7 @@ Fixed length collection
- ByteArray: Array limited to byte elements (0-255)
- WordArray: Array limited to word elements (0-2^32)
-```
+```smalltalk
| b x y sum max |
x := #(4 3 2 1). "constant array"
x := Array with: 5 with: 4 with: 3 with: 2. "create array with up to 4 elements"
@@ -490,7 +484,7 @@ y := x asSet. "convert to set collection"
#### OrderedCollection:
acts like an expandable array
-```
+```smalltalk
| b x y sum max |
x := OrderedCollection
with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements"
@@ -537,7 +531,7 @@ y := x asSet. "convert to set collection"
#### SortedCollection:
like OrderedCollection except order of elements determined by sorting criteria
-```
+```smalltalk
| b x y sum max |
x := SortedCollection
with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements"
@@ -583,7 +577,7 @@ y := x asSet. "convert to set collection"
#### Bag:
like OrderedCollection except elements are in no particular order
-```
+```smalltalk
| b x y sum max |
x := Bag with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements"
x := Bag new. "allocate collection"
@@ -619,7 +613,7 @@ like Bag except duplicates not allowed
#### IdentitySet:
uses identity test (== rather than =)
-```
+```smalltalk
| b x y sum max |
x := Set with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements"
x := Set new. "allocate collection"
@@ -649,7 +643,7 @@ y := x asSet. "convert to set collection"
```
#### Interval:
-```
+```smalltalk
| b x y sum max |
x := Interval from: 5 to: 10. "create interval object"
x := 5 to: 10.
@@ -679,7 +673,7 @@ y := x asSet. "convert to set collection"
```
#### Associations:
-```
+```smalltalk
| x y |
x := #myVar->'hello'.
y := x key.
@@ -690,7 +684,7 @@ y := x value.
#### IdentityDictionary:
uses identity test (== rather than =)
-```
+```smalltalk
| b x y |
x := Dictionary new. "allocate collection"
x add: #a->4;
@@ -757,7 +751,7 @@ Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user dictionary fr
```
#### Internal Stream:
-```
+```smalltalk
| b x ios |
ios := ReadStream on: 'Hello read stream'.
ios := ReadStream on: 'Hello read stream' from: 1 to: 5.
@@ -785,7 +779,7 @@ b := ios atEnd.
```
#### FileStream:
-```
+```smalltalk
| b x ios |
ios := FileStream newFileNamed: 'ios.txt'.
ios nextPut: $H; cr.
@@ -805,7 +799,7 @@ ios close.
```
#### Date:
-```
+```smalltalk
| x y |
x := Date today. "create date for today"
x := Date dateAndTimeNow. "create date from current time/date"
@@ -839,7 +833,7 @@ b := (x <= Date today). "comparison"
```
#### Time:
-```
+```smalltalk
| x y |
x := Time now. "create time from current time"
x := Time dateAndTimeNow. "create time from current time/date"
@@ -859,7 +853,7 @@ b := (x <= Time now). "comparison"
```
#### Point:
-```
+```smalltalk
| x y |
x := 200@100. "obtain a new point"
y := x x. "x coordinate"
@@ -884,12 +878,12 @@ x := 20@5 dotProduct: 10@2. "sum of product (x1*x2 + y1*y2)"
```
#### Rectangle:
-```
+```smalltalk
Rectangle fromUser.
```
#### Pen:
-```
+```smalltalk
| myPen |
Display restoreAfter: [
Display fillWhite.
@@ -917,7 +911,7 @@ Display height. "get display height"
```
#### Dynamic Message Calling/Compiling:
-```
+```smalltalk
| receiver message result argument keyword1 keyword2 argument1 argument2 |
"unary message"
@@ -957,7 +951,7 @@ result := (Message
```
#### Class/Meta-Class:
-```
+```smalltalk
| b x |
x := String name. "class name"
x := String category. "organization category"
@@ -990,7 +984,7 @@ Object withAllSubclasses size. "get total number of class entries"
```
#### Debugging:
-```
+```smalltalk
| a b x |
x yourself. "returns receiver"
String browse. "browse specified class"
@@ -1013,8 +1007,13 @@ Transcript show: a, b; cr.
```
#### Miscellaneous
-```
+```smalltalk
| x |
+x := 1.2 hash. "hash value for object"
+y := x copy. "copy object"
+y := x shallowCopy. "copy object (not overridden)"
+y := x deepCopy. "copy object and instance vars"
+y := x veryDeepCopy. "complete tree copy using a dictionary"
"Smalltalk condenseChanges." "compress the change file"
x := FillInTheBlank request: 'Prompt Me'. "prompt user for input"
Utilities openCommandKeyHelp
diff --git a/standard-ml.html.markdown b/standard-ml.html.markdown
index 0ba42f39..9d6b104d 100644
--- a/standard-ml.html.markdown
+++ b/standard-ml.html.markdown
@@ -2,8 +2,8 @@
language: "Standard ML"
filename: standardml.sml
contributors:
- - ["Simon Shine", "http://shine.eu.org/"]
- - ["David Pedersen", "http://lonelyproton.com/"]
+ - ["Simon Shine", "https://simonshine.dk/"]
+ - ["David Pedersen", "https://github.com/davidpdrsn"]
- ["James Baker", "http://www.jbaker.io/"]
- ["Leo Zovic", "http://langnostic.inaimathi.ca/"]
- ["Chris Wilson", "http://sencjw.com/"]
@@ -479,3 +479,4 @@ fun decrement_ret x y = (x := !x - 1; y)
* Follow the Coursera course [Programming Languages](https://www.coursera.org/course/proglang).
* Read *[ML for the Working Programmer](https://www.cl.cam.ac.uk/~lp15/MLbook/pub-details.html)* by Larry C. Paulson.
* Use [StackOverflow's sml tag](http://stackoverflow.com/questions/tagged/sml).
+* Solve exercises on [Exercism.io's Standard ML track](https://exercism.io/tracks/sml).
diff --git a/swift.html.markdown b/swift.html.markdown
index 1f9fe897..689c5191 100644
--- a/swift.html.markdown
+++ b/swift.html.markdown
@@ -692,6 +692,11 @@ print(mySquare.sideLength) // 4
// cast instance
let aShape = mySquare as Shape
+// downcast instance:
+// Because downcasting can fail, the result can be an optional (as?) or an implicitly unwrpped optional (as!).
+let anOptionalSquare = aShape as? Square // This will return nil if aShape is not a Square
+let aSquare = aShape as! Square // This will throw a runtime error if aShape is not a Square
+
// compare instances, not the same as == which compares objects (equal to)
if mySquare === mySquare {
print("Yep, it's mySquare")
@@ -904,7 +909,7 @@ func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
}
return nil
}
-findIndex(array: [1, 2, 3, 4], valueToFind: 3) // 2
+findIndex(array: [1, 2, 3, 4], valueToFind: 3) // Optional(2)
// You can extend types with generics as well
extension Array where Array.Element == Int {
diff --git a/toml.html.markdown b/toml.html.markdown
index 385a2437..2b234965 100755
--- a/toml.html.markdown
+++ b/toml.html.markdown
@@ -12,7 +12,7 @@ It is an alternative to YAML and JSON. It aims to be more human friendly than JS
Be warned, TOML's spec is still changing a lot. Until it's marked as 1.0, you
should assume that it is unstable and act accordingly. This document follows TOML v0.4.0.
-```
+```toml
# Comments in TOML look like this.
################
@@ -117,7 +117,7 @@ date4 = 1979-05-27 # without offset or time
array1 = [ 1, 2, 3 ]
array2 = [ "Commas", "are", "delimiters" ]
-array3 = [ "Don't mixed", "different", "types" ]
+array3 = [ "Don't mix", "different", "types" ]
array4 = [ [ 1.2, 2.4 ], ["all", 'strings', """are the same""", '''type'''] ]
array5 = [
"Whitespace", "is", "ignored"
@@ -171,6 +171,9 @@ c = 1
[a]
d = 2
+# Will generate the following in JSON:
+# { "a": {"b": {"c": 1}, "d": 2 } }
+
# You cannot define any key or table more than once. Doing so is invalid.
# DO NOT DO THIS
@@ -220,7 +223,27 @@ emptyTableAreAllowed = true
name = "Nail"
sku = 284758393
color = "gray"
+```
+The equivalent in JSON would be:
+```json
+{
+ "products": [
+ {
+ "name": "array of table",
+ "sku": 7385594937,
+ "emptyTableAreAllowed": true
+ },
+ {},
+ {
+ "name": "Nail",
+ "sku": 284758393,
+ "color": "gray"
+ }
+ ]
+}
+```
+```toml
# You can create nested arrays of tables as well. Each double-bracketed
# sub-table will belong to the nearest table element above it.
@@ -245,11 +268,11 @@ color = "gray"
[[fruit.color]]
name = "yellow"
note = "I am an array item in banana fruit's table/map"
-```
-
-In JSON land, this code will be:
+```
+The equivalent in JSON would be:
```json
+
{
"fruit": [
{
diff --git a/typescript.html.markdown b/typescript.html.markdown
index 7e857cc0..640be0cd 100644
--- a/typescript.html.markdown
+++ b/typescript.html.markdown
@@ -139,7 +139,7 @@ class Point3D extends Point {
// Overwrite
dist() {
let d = super.dist();
- return Math.sqrt(d * d + this.z * this.z);
+ return Math.sqrt(d() * d() + this.z * this.z);
}
}
diff --git a/vimscript.html.markdown b/vimscript.html.markdown
new file mode 100644
index 00000000..8e023713
--- /dev/null
+++ b/vimscript.html.markdown
@@ -0,0 +1,651 @@
+---
+language: Vimscript
+filename: learnvimscript.vim
+contributors:
+ - ["HiPhish", "http://hiphish.github.io/"]
+---
+
+```vim
+" ##############
+" Introduction
+" ##############
+"
+" Vim script (also called VimL) is the subset of Vim's ex-commands which
+" supplies a number of features one one would expect from a scripting language,
+" such as values, variables, functions or loops. Always keep in the back of
+" your mind that a Vim script file is just a sequence of ex-commands. It is
+" very common for a script to mix programming-language features and raw
+" ex-commands.
+"
+" You can run Vim script directly by entering the commands in command-mode
+" (press `:` to enter command-mode), or you can write them to a file (without
+" the leading `:`) and source it in a running Vim instance (`:source
+" path/to/file`). Some files are sourced automatically as part of your
+" configuration (see |startup|). This guide assumes that you are familiar
+" with ex-commands and will only cover the scripting. Help topics to the
+" relevant manual sections are included.
+"
+" See |usr_41.txt| for the official introduction to Vim script. A comment is
+" anything following an unmatched `"` until the end of the line, and `|`
+" separates instructions (what `;` does in most other languages). References to
+" the manual as surrounded with `|`, such as |help.txt|.
+
+" This is a comment
+
+" The vertical line '|' (pipe) separates commands
+echo 'Hello' | echo 'world!'
+
+" Putting a comment after a command usually works
+pwd " Displays the current working directory
+
+" Except for some commands it does not; use the command delemiter before the
+" comment (echo assumes that the quotation mark begins a string)
+echo 'Hello world!' | " Displays a message
+
+" Line breaks can be escaped by pacing a backslash as the first non-whitespace
+" character on the *following* line. Only works in script files, not on the
+" command line
+echo " Hello
+ \ world "
+
+echo [1,
+ \ 2]
+
+echo {
+ \ 'a': 1,
+ \ 'b': 2
+\}
+
+
+" #######
+" Types
+" #######
+"
+" For an overview of types see |E712|. For an overview of operators see
+" |expression-syntax|
+
+" Numbers (|expr-number|)
+" #######
+
+echo 123 | " Decimal
+echo 0b1111011 | " Binary
+echo 0173 | " Octal
+echo 0x7B | " Hexadecimal
+echo 123.0 | " Floating-point
+echo 1.23e2 | " Floating-point (scientific notation)
+
+" Note that an *integer* number with a leading `0` is in octal notation. The
+" usual arithmetic operations are supported.
+
+echo 1 + 2 | " Addition
+echo 1 - 2 | " Subtraction
+echo - 1 | " Negation (unary minus)
+echo + 1 | " Unary plus (does nothing really, but still legal)
+echo 1 * 2 | " Multiplication
+echo 1 / 2 | " Division
+echo 1 % 2 | " Modulo (remainder)
+
+" Booleans (|Boolean|)
+" ########
+"
+" The number 0 is false, every other number is true. Strings are implicitly
+" converted to numbers (see below). There are two pre-defined semantic
+" constants.
+
+echo v:true | " Evaluates to 1 or the string 'v:true'
+echo v:false | " Evaluates to 0 or the string 'v:false'
+
+" Boolean values can result from comparison of two objects.
+
+echo x == y | " Equality by value
+echo x != y | " Unequality
+echo x > y | " Greater than
+echo x >= y | " Greater than or equal
+echo x < y | " Smaller than
+echo x <= y | " Smaller than or equal
+echo x is y | " Instance identity (lists and dictionaries)
+echo x isnot y | " Instance non-identity (lists and dictionaries)
+
+" Strings are compared based on their alphanumerical ordering
+" echo 'a' < 'b'. Case sensitivity depends on the setting of 'ignorecase'
+"
+" Explicit case-sensitivity is specified by appending '#' (match case) or '?'
+" (ignore case) to the operator. Prefer explicity case sensitivity when writing
+" portable scripts.
+
+echo 'a' < 'B' | " True or false depending on 'ignorecase'
+echo 'a' <? 'B' | " True
+echo 'a' <# 'B' | " False
+
+" Regular expression matching
+echo "hi" =~ "hello" | " Regular expression match, uses 'ignorecase'
+echo "hi" =~# "hello" | " Regular expression match, case sensitive
+echo "hi" =~? "hello" | " Regular expression match, case insensitive
+echo "hi" !~ "hello" | " Regular expression unmatch, use 'ignorecase'
+echo "hi" !~# "hello" | " Regular expression unmatch, case sensitive
+echo "hi" !~? "hello" | " Regular expression unmatch, case insensitive
+
+" Boolean operations are possible.
+
+echo v:true && v:false | " Logical AND
+echo v:true || v:false | " Logical OR
+echo ! v:true | " Logical NOT
+echo v:true ? 'yes' : 'no' | " Ternary operator
+
+
+" Strings (|String|)
+" #######
+"
+" An ordered zero-indexed sequence of bytes. The encoding of text into bytes
+" depends on the option |'encoding'|.
+
+" Literal constructors
+echo "Hello world\n" | " The last two characters stand for newline
+echo 'Hello world\n' | " The last two characters are literal
+echo 'Let''s go!' | " Two single quotes become one quote character
+
+" Single-quote strings take all characters are literal, except two single
+" quotes, which are taken to be a single quote in the string itself. See
+" |expr-quote| for all possible escape sequences.
+
+" String concatenation
+" The .. operator is preferred, but only supported in since Vim 8.1.1114
+echo 'Hello ' . 'world' | " String concatenation
+echo 'Hello ' .. 'world' | " String concatenation (new variant)
+
+" String indexing
+echo 'Hello'[0] | " First byte
+echo 'Hello'[1] | " Second byte
+echo 'Hellö'[4] | " Returns a byte, not the character 'ö'
+
+" Substrings (second index is inclusive)
+echo 'Hello'[:] | " Copy of entire string
+echo 'Hello'[1:3] | " Substring, second to fourth byte
+echo 'Hello'[1:-2] | " Substring until second to last byte
+echo 'Hello'[1:] | " Substring with starting index
+echo 'Hello'[:2] | " Substring with ending index
+echo 'Hello'[-2:] | " Substring relative to end of string
+
+" A negative index is relative to the end of the string. See
+" |string-functions| for all string-related functions.
+
+" Lists (|List|)
+" #####
+"
+" An ordered zero-indexed heterogeneous sequence of arbitrary Vim script
+" objects.
+
+" Literal constructor
+echo [] | " Empty list
+echo [1, 2, 'Hello'] | " List with elements
+echo [1, 2, 'Hello', ] | " Trailing comma permitted
+echo [[1, 2], 'Hello'] | " Lists can be nested arbitrarily
+
+" List concatenation
+echo [1, 2] + [3, 4] | " Creates a new list
+
+" List indexing, negative is relative to end of list (|list-index|)
+echo [1, 2, 3, 4][2] | " Third element
+echo [1, 2, 3, 4][-1] | " Last element
+
+" List slicing (|sublist|)
+echo [1, 2, 3, 4][:] | " Shallow copy of entire list
+echo [1, 2, 3, 4][:2] | " Sublist until third item (inclusive)
+echo [1, 2, 3, 4][2:] | " Sublist from third item (inclusive)
+echo [1, 2, 3, 4][:-2] | " Sublist until second-to-last item (inclusive)
+
+" All slicing operations create new lists. To modify a list in-place use list
+" functions (|list-functions|) or assign directly to an item (see below about
+" variables).
+
+
+" Dictionaries (|Dictionary|)
+" ############
+"
+" An unordered sequence of key-value pairs, keys are always strings (numbers
+" are implicitly converted to strings).
+
+" Dictionary literal
+echo {} | " Empty dictionary
+echo {'a': 1, 'b': 2} | " Dictionary literal
+echo {'a': 1, 'b': 2, } | " Trailing comma permitted
+echo {'x': {'a': 1, 'b': 2}} | " Nested dictionary
+
+" Indexing a dictionary
+echo {'a': 1, 'b': 2}['a'] | " Literal index
+echo {'a': 1, 'b': 2}.a | " Syntactic sugar for simple keys
+
+" See |dict-functions| for dictionary manipulation functions.
+
+
+" Funcref (|Funcref|)
+" #######
+"
+" Reference to a function, uses the function name as a string for construction.
+" When stored in a variable the name of the variable has the same restrictions
+" as a function name (see below).
+
+echo function('type') | " Reference to function type()
+" Note that `funcref('type')` will throw an error because the argument must be
+" a user-defined function; see further below for defining your own functions.
+echo funcref('type') | " Reference by identity, not name
+" A lambda (|lambda|) is an anonymous function; it can only contain one
+" expression in its body, which is also its implicit return value.
+echo {x -> x * x} | " Anonymous function
+echo function('substitute', ['hello']) | " Partial function
+
+
+" Regular expression (|regular-expression|)
+" ##################
+"
+" A regular expression pattern is generally a string, but in some cases you can
+" also use a regular expression between a pair of delimiters (usually `/`, but
+" you can choose anything).
+
+" Substitute 'hello' for 'Hello'
+substitute/hello/Hello/
+
+
+" ###########################
+" Implicit type conversions
+" ###########################
+"
+" Strings are converted to numbers, and numbers to strings when necessary. A
+" number becomes its decimal notation as a string. A string becomes its
+" numerical value if it can be parsed to a number, otherwise it becomes zero.
+
+echo "1" + 1 | " Number
+echo "1" .. 1 | " String
+echo "0xA" + 1 | " Number
+
+" Strings are treated like numbers when used as booleans
+echo "true" ? 1 : 0 | " This string is parsed to 0, which is false
+
+" ###########
+" Variables
+" ###########
+"
+" Variables are bound within a scope; if no scope is provided a default is
+" chosen by Vim. Use `:let` and `:const` to bind a value and `:unlet` to unbind
+" it.
+
+let b:my_var = 1 | " Local to current buffer
+let w:my_var = 1 | " Local to current window
+let t:my_var = 1 | " Local to current tab page
+let g:my_var = 1 | " Global variable
+let l:my_var = 1 | " Local to current function (see functions below)
+let s:my_var = 1 | " Local to current script file
+let a:my_arg = 1 | " Function argument (see functions below)
+
+" The Vim scope is read-only
+echo v:true | " Special built-in Vim variables (|v:var|)
+
+" Access special Vim memory like variables
+let @a = 'Hello' | " Register
+let $PATH='' | " Environment variable
+let &textwidth = 79 | " Option
+let &l:textwidth = 79 | " Local option
+let &g:textwidth = 79 | " Global option
+
+" Access scopes as dictionaries (can be modified like all dictionaries)
+" See the |dict-functions|, especially |get()|, for access and manipulation
+echo b: | " All buffer variables
+echo w: | " All window variables
+echo t: | " All tab page variables
+echo g: | " All global variables
+echo l: | " All local variables
+echo s: | " All script variables
+echo a: | " All function arguments
+echo v: | " All Vim variables
+
+" Constant variables
+const x = 10 | " See |:const|, |:lockvar|
+
+" Function reference variables have the same restrictions as function names
+let IsString = {x -> type(x) == type('')} | " Global: capital letter
+let s:isNumber = {x -> type(x) == type(0)} | " Local: any name allowed
+
+" When omitted the scope `g:` is implied, except in functions, there `l:` is
+" implied.
+
+
+" Multiple value binding (list unpacking)
+" #######################################
+"
+" Assign values of list to multiple variables (number of items must match)
+let [x, y] = [1, 2]
+
+" Assign the remainer to a rest variable (note the semicolon)
+let [mother, father; children] = ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
+
+
+" ##############
+" Flow control
+" ##############
+
+" Conditional (|:if|, |:elseif|, |:else|, |:endif|)
+" ###########
+"
+" Conditions are set between `if` and `endif`. They can be nested.
+
+let condition = v:true
+
+if condition
+ echo 'First condition'
+elseif another_condition
+ echo 'Second condition'
+else
+ echo 'Fail'
+endif
+
+" Loops (|:for|, |:endfor|, |:while|, |:endwhile|, |:break|, |:continue|)
+" #####
+"
+" Two types of loops: `:for` and `:while`. Use `:continue` to skip to the next
+" iteration, `:break` to break out of the loop.
+
+" For-loop (|:for|, |:endfor|)
+" ========
+"
+" For-loops iterate over lists and nothing else. If you want to iterate over
+" another sequence you need to use a function which will create a list.
+
+" Iterate over a list
+for person in ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
+ echo 'Hello ' .. person
+endfor
+
+" Iterate over a nested list by unpacking it
+for [x, y] in [[1, 0], [0, 1], [-1, 0], [0, -1]]
+ echo 'Position: x =' .. x .. ', y = ' .. y
+endfor
+
+" Iterate over a range of numbers
+for i in range(10, 0, -1) " Count down from 10
+ echo 'T minus' .. i
+endfor
+
+" Iterate over the keys of a dictionary
+for symbol in keys({'π': 3.14, 'e': 2.71})
+ echo 'The constant ' .. symbol .. ' is a transcendent number'
+endfor
+
+" Iterate over the values of a dictionary
+for value in values({'π': 3.14, 'e': 2.71})
+ echo 'The value ' .. value .. ' approximates a transcendent number'
+endfor
+
+" Iterate over the keys and values of a dictionary
+for [symbol, value] in items({'π': 3.14, 'e': 2.71})
+ echo 'The number ' .. symbol .. ' is approximately ' .. value
+endfor
+
+" While-loops (|:while|, |:endwhile|)
+
+let there_yet = v:true
+while !there_yet
+ echo 'Are we there yet?'
+endwhile
+
+
+" Exception handling (|exception-handling|)
+" ##################
+"
+" Throw new exceptions as strings, catch them by pattern-matching a regular
+" expression against the string
+
+" Throw new exception
+throw "Wrong arguments"
+
+" Guard against an exception (the second catch matches any exception)
+try
+ source path/to/file
+catch /Cannot open/
+ echo 'Looks like that file does not exist'
+catch /.*/
+ echo 'Something went wrong, but I don't know what'
+finally
+ echo 'I'm done trying'
+endtry
+
+
+" ##########
+" Functions
+" ##########
+
+" Defining functions (|:function|, |:endfunction|)
+" ##################
+
+" Unscoped function names have to start with a capital letter
+function! AddNumbersLoudly(x, y)
+ " Use a: scope to access arguments
+ echo 'Adding' .. a:x .. 'and' .. a:y | " A side effect
+ return a:x + a:y | " A return value
+endfunction
+
+" Scoped function names may start with a lower-case letter
+function! s:addNumbersLoudly(x, y)
+ echo 'Adding' .. a:x .. 'and' .. a:y
+ return a:x + a:y
+endfunction
+
+" Without the exclamation mark it would be an error to re-define a function,
+" with the exclamation mark the new definition can replace the old one. Since
+" Vim script files can be reloaded several times over the course of a session
+" it is best to use the exclamation mark unless you really know what you are
+" doing.
+
+" Function definitions can have special qualifiers following the argument list.
+
+" Range functions define two implicit arguments, which will be set to the range
+" of the ex-command
+function! FirstAndLastLine() range
+ echo [a:firstline, a:lastline]
+endfunction
+
+" Prints the first and last line that match a pattern (|cmdline-ranges|)
+/^#!/,/!#$/call FirstAndLastLine()
+
+" Aborting functions, abort once error occurs (|:func-abort|)
+function! SourceMyFile() abort
+ source my-file.vim | " Try sourcing non-existing file
+ echo 'This will never be printed'
+endfunction
+
+" Closures, functions carrying values from outer scope (|:func-closure|)
+function! MakeAdder(x)
+ function! Adder(n) closure
+ return a:n + a:x
+ endfunction
+ return funcref('Adder')
+endfunction
+let AddFive = MakeAdder(5)
+echo AddFive(3) | " Prints 8
+
+" Dictionary functions, poor man's OOP methods (|Dictionary-function|)
+function! Mylen() dict
+ return len(self.data) | " Implicit variable self
+endfunction
+let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
+echo mydict.len()
+
+" Alternatively, more concise
+let mydict = {'data': [0, 1, 2, 3]}
+function! mydict.len()
+ return len(self.data)
+endfunction
+
+" Calling functions (|:call|)
+" #################
+
+" Call a function for its return value, and possibly for its side effects
+let animals = keys({'cow': 'moo', 'dog': 'woof', 'cat': 'meow'})
+
+" Call a function for its side effects only, ignore potential result
+call sign_undefine()
+
+" The call() function calls a function reference and passes parameters as a
+" list, and returns the function's result.
+echo call(function('get'), [{'a': 1, 'b': 2}, 'c', 3]) | " Prints 3
+
+" Recall that Vim script is embedded within the ex-commands, that is why we
+" cannot just call a function directly, we have to use the `:call` ex-command.
+
+" Function namespaces (|write-library-script|, |autoload|)
+" ###################
+
+" Must be defined in autoload/foo/bar.vim
+" Namspaced function names do not have to start with a capital letter
+function! foo#bar#log(value)
+ echomsg value
+endfunction
+
+call foo#bar#log('Hello')
+
+
+" #############################
+" Frequently used ex-commands
+" #############################
+
+
+" Sourcing runtime files (|'runtimepath'|)
+" ######################
+
+" Source first match among runtime paths
+runtime plugin/my-plugin.vim
+
+
+" Defining new ex-commands (|40.2|, |:command|)
+" ########################
+
+" First argument here is the name of the command, rest is the command body
+command! SwapAdjacentLines normal! ddp
+
+" The exclamation mark works the same as with `:function`. User-defined
+" commands must start with a capital letter. The `:command` command can take a
+" number of attributes (some of which have their own parameters with `=`), such
+" as `-nargs`, all of them start with a dash to set them apart from the command
+" name.
+
+:command -nargs=1 Error echoerr <args>
+
+
+" Defining auto-commands (|40.3|, |autocmd|, |autocommand-events|)
+" ######################
+
+" The arguments are "events", "patterns", rest is "commands"
+autocmd BufWritePost $MYVIMRC source $MYVIMRC
+
+" Events and patterns are separated by commas with no space between. See
+" |autocmd-events| for standard events, |User| for custom events. Everything
+" else are the ex-commands which will be executed.
+
+" Auto groups
+" ===========
+"
+" When a file is sourced multiple times the auto-commands are defined anew,
+" without deleting the old ones, causing auto-commands to pile up over time.
+" Use auto-groups and the following ritual to guard against this.
+
+augroup auto-source | " The name of the group is arbitrary
+ autocmd! | " Deletes all auto-commands in the current group
+ autocmd BufWritePost $MYVIMRC source $MYVIMRC
+augroup END | " Switch back to default auto-group
+
+" It is also possible to assign a group directly. This is useful if the
+" definition of the group is in one script and the definition of the
+" auto-command is in another script.
+
+" In one file
+augroup auto-source
+ autocmd!
+augroup END
+
+" In another file
+autocmd auto-source BufWritePost $MYVIMRC source $MYVIMRC
+
+" Executing (run-time macros of sorts)
+" ####################################
+
+" Sometimes we need to construct an ex-command where part of the command is not
+" known until runtime.
+
+let line = 3 | " Line number determined at runtime
+execute line .. 'delete' | " Delete a line
+
+" Executing normal-mode commands
+" ##############################
+"
+" Use `:normal` to play back a sequence of normal mode commands from the
+" command-line. Add an exclamation mark to ignore user mappings.
+
+normal! ggddGp | " Transplant first line to end of buffer
+
+" Window commands can be used with :normal, or with :wincmd if :normal would
+" not work
+wincmd L | " Move current window all the way to the right
+
+
+" ###########################
+" Frequently used functions
+" ###########################
+
+" Feature check
+echo has('nvim') | " Running Neovim
+echo has('python3') | " Support for Python 3 plugins
+echo has('unix') | " Running on a Unix system
+echo has('win32') | " Running on a Windows system
+
+
+" Test if something exists
+echo exists('&mouse') | " Option (exists only)
+echo exists('+mouse') | " Option (exists and works)
+echo exists('$HOSTNAME') | " Environment variable
+echo exists('*strftime') | " Built-in function
+echo exists('**s:MyFunc') | " User-defined function
+echo exists('bufcount') | " Variable (scope optional)
+echo exists('my_dict["foo"]') | " Variable (dictionary entry)
+echo exists('my_dict["foo"]') | " Variable (dictionary entry)
+echo exists(':Make') | " Command
+echo exists("#CursorHold") | " Auto-command defined for event
+echo exists("#BufReadPre#*.gz") | " Event and pattern
+echo exists("#filetypeindent") | " Auto-command group
+echo exists("##ColorScheme") | " Auto-commnand supported for event
+
+" Various dynamic values (see |expand()|)
+echo expand('%') | " Current file name
+echo expand('<cword>') | " Current word under cursor
+echo expand('%:p') | " Modifier are possible
+
+" Type tests
+echo type(my_var) == type(0) | " Number
+echo type(my_var) == type('') | " String
+echo type(my_var) == type([]) | " List
+echo type(my_var) == type({}) | " Dictionary
+echo type(my_var) == type(function('type')) | " Funcref
+
+" Format strings
+echo printf('%d in hexadecimal is %X', 123, 123)
+
+
+" #####################
+" Tricks of the trade
+" #####################
+
+" Source guard
+" ############
+
+" Prevent a file from being source multiple times; users can set the variable
+" in their configuration to prevent the plugin from loading at all.
+if exists('g:loaded_my_plugin')
+ finish
+endif
+let g:loaded_my_plugin = v:true
+
+" Default values
+" ##############
+
+" Get a default value: if the user defines a variable use it, otherwise use a
+" hard-coded default. Uses the fact that a scope is also a dictionary.
+let s:greeting = get(g:, 'my_plugin_greeting', 'Hello')
+```
diff --git a/wasm.html.markdown b/wasm.html.markdown
index 98bfc000..aba2084f 100644
--- a/wasm.html.markdown
+++ b/wasm.html.markdown
@@ -222,6 +222,91 @@ contributors:
)
)
(export "apply_cos64" (func $apply_cos64))
+
+ ;; Wasm is a stack-based language, but for returning values more complicated
+ ;; than an int/float, a separate memory stack has to be manually managed. One
+ ;; approach is to use a mutable global to store the stack_ptr. We give
+ ;; ourselves 1MiB of memstack and grow it downwards.
+ ;;
+ ;; Below is a demonstration of how this C code **might** be written by hand
+ ;;
+ ;; typedef struct {
+ ;; int a;
+ ;; int b;
+ ;; } sum_struct_t;
+ ;;
+ ;; sum_struct_t sum_struct_create(int a, int b) {
+ ;; return (sum_struct_t){a, b};
+ ;; }
+ ;;
+ ;; int sum_local() {
+ ;; sum_struct_t s = sum_struct_create(40, 2);
+ ;; return s.a + s.b;
+ ;; }
+
+ ;; Unlike C, we must manage our own memory stack. We reserve 1MiB
+ (global $memstack_ptr (mut i32) (i32.const 65536))
+
+ ;; Structs can only be returned by reference
+ (func $sum_struct_create
+ (param $sum_struct_ptr i32)
+ (param $var$a i32)
+ (param $var$b i32)
+ ;; c// sum_struct_ptr->a = a;
+ (i32.store
+ (get_local $sum_struct_ptr)
+ (get_local $var$a)
+ )
+
+ ;; c// sum_struct_ptr->b = b;
+ (i32.store offset=4
+ (get_local $sum_struct_ptr)
+ (get_local $var$b)
+ )
+ )
+
+ (func $sum_local (result i32)
+ (local $var$sum_struct$a i32)
+ (local $var$sum_struct$b i32)
+ (local $local_memstack_ptr i32)
+
+ ;; reserve memstack space
+ (i32.sub
+ (get_global $memstack_ptr)
+ (i32.const 8)
+ )
+ tee_local $local_memstack_ptr ;; tee both stores and returns given value
+ set_global $memstack_ptr
+
+ ;; call the function, storing the result in the memstack
+ (call $sum_struct_create
+ ((;$sum_struct_ptr=;) get_local $local_memstack_ptr)
+ ((;$var$a=;) i32.const 40)
+ ((;$var$b=;) i32.const 2)
+ )
+
+ ;; retrieve values from struct
+ (set_local $var$sum_struct$a
+ (i32.load offset=0 (get_local $local_memstack_ptr))
+ )
+ (set_local $var$sum_struct$b
+ (i32.load offset=4 (get_local $local_memstack_ptr))
+ )
+
+ ;; unreserve memstack space
+ (set_global $memstack_ptr
+ (i32.add
+ (get_local $local_memstack_ptr)
+ (i32.const 8)
+ )
+ )
+
+ (i32.add
+ (get_local $var$sum_struct$a)
+ (get_local $var$sum_struct$b)
+ )
+ )
+ (export "sum_local" (func $sum_local))
)
```
diff --git a/zh-cn/css-cn.html.markdown b/zh-cn/css-cn.html.markdown
index dc6dcc4f..ec937dfb 100644
--- a/zh-cn/css-cn.html.markdown
+++ b/zh-cn/css-cn.html.markdown
@@ -132,7 +132,7 @@ div.some-parent.class-name {}
font-family: Arial;
font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */
font-family: "Courier New", Trebuchet, Arial; /* 如果第一个
- 字体没找到,浏览器会使用第二个字体,一次类推 */
+ 字体没找到,浏览器会使用第二个字体,以此类推 */
}
```
diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown
index d471ab5d..63d740a1 100644
--- a/zh-cn/git-cn.html.markdown
+++ b/zh-cn/git-cn.html.markdown
@@ -234,7 +234,7 @@ $ git diff HEAD
# 在搜索结果中显示行号
$ git config --global grep.lineNumber true
-# 是搜索结果可读性更好
+# 使得搜索结果可读性更好
$ git config --global alias.g "grep --break --heading --line-number"
```
diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown
index 9b3d96ab..707d6927 100644
--- a/zh-cn/markdown-cn.html.markdown
+++ b/zh-cn/markdown-cn.html.markdown
@@ -211,7 +211,7 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以
内联代码可由反引号 ` 实现
```md
-John 甚至不知道 `go_to()` 方程是干嘛的!
+John 甚至不知道 `go_to()` 函数是干嘛的!
```
在GitHub的 Markdown(GitHub Flavored Markdown)解析器中,你可以使用特殊的语法表示代码块
diff --git a/zh-cn/powershell-cn.html.markdown b/zh-cn/powershell-cn.html.markdown
new file mode 100644
index 00000000..6ab34e9f
--- /dev/null
+++ b/zh-cn/powershell-cn.html.markdown
@@ -0,0 +1,325 @@
+---
+category: tool
+tool: powershell
+contributors:
+ - ["Wouter Van Schandevijl", "https://github.com/laoujin"]
+translators:
+ - ["Feng Gao", "https://github.com/gaufung"]
+filename: LearnPowershell-cn.ps1
+lang: zh-cn
+---
+
+PowerShell 是 Windows 平台下的脚本语言同时也是配置管理框架,它是建立在微软 .Net Framework 之上,Windows 7 以及之后版本都内置 Poweshell。下面的示例中都是 PoweShell 脚本的一部分或者直接能够在 Shell 交互窗口中执行。
+
+与 Bash 最大的不同是你大部分操作的东西是对象而不是普通的文本。
+
+[延伸阅读](https://technet.microsoft.com/en-us/library/bb978526.aspx)
+
+如果你不确定你的环境,执行如下操作:
+
+```powershell
+Get-ExecutionPolicy -List
+Set-ExecutionPolicy AllSigned
+# Execution Policy 包含以下:
+# - Restricted: 不会运行脚本。
+# - RemoteSigned: 只会运行受信任的发行商下载的脚本。
+# - AllSigned: 运行需要被信任发行商签名的脚本。
+# - Unrestricted: 运行所有脚本
+help about_Execution_Policies # 查看更多信息
+
+# 当前 PowerShell 版本
+$PSVersionTable
+```
+
+获取帮助
+
+```powershell
+# 查找命令
+Get-Command about_* # 别名: gcm
+Get-Command -Verb Add
+Get-Alias ps
+Get-Alias -Definition Get-Process
+
+Get-Help ps | less # 别名: help
+ps | Get-Member # 别名: gm
+
+Show-Command Get-EventLog # GUI 填充参数
+
+Update-Help # 管理员运行
+```
+
+接下来是教程
+
+```powershell
+# 正如你看到的,每一行开头是 # 都是注释
+
+# 简单的 Hello World 实例
+echo Hello world!
+# echo 是 Write-Output (cmdlet) 的别名
+# 大部分 cmdlet 和函数都遵循 "动词-名词" 命名规则。
+
+# 每个命令都从新的一行开始或者是一个分号
+echo 'This is the first line'; echo 'This is the second line'
+
+# 声明一个变量如下:
+$aString="Some string"
+# 或者像这样:
+$aNumber = 5 -as [double]
+$aList = 1,2,3,4,5
+$anEmptyList = @()
+$aString = $aList -join '--' # 也包含 join 方法
+$aHashtable = @{name1='val1'; name2='val2'}
+
+# 使用变量:
+echo $aString
+echo "Interpolation: $aString"
+echo "$aString has length of $($aString.Length)"
+echo '$aString'
+echo @"
+This is a Here-String
+$aString
+"@
+# 注意 ' (单引号) 不是变量的一部分
+# 在这里字符串也可以是单引号
+
+# 内置变量:
+# 下面是一些有用的内置变量,比如:
+echo "Booleans: $TRUE and $FALSE"
+echo "Empty value: $NULL"
+echo "Last program's return value: $?"
+echo "Exit code of last run Windows-based program: $LastExitCode"
+echo "The last token in the last line received by the session: $$"
+echo "The first token: $^"
+echo "Script's PID: $PID"
+echo "Full path of current script directory: $PSScriptRoot"
+echo 'Full path of current script: ' + $MyInvocation.MyCommand.Path
+echo "FUll path of current directory: $Pwd"
+echo "Bound arguments in a function, script or code block: $PSBoundParameters"
+echo "Unbound arguments: $($Args -join ', ')."
+# 更多的内置类型: `help about_Automatic_Variables`
+
+# 内联其他文件 (点操作符)
+. .\otherScriptName.ps1
+
+
+### 控制流
+# 下面是条件判断结构
+if ($Age -is [string]) {
+ echo 'But.. $Age cannot be a string!'
+} elseif ($Age -lt 12 -and $Age -gt 0) {
+ echo 'Child (Less than 12. Greater than 0)'
+} else {
+ echo 'Adult'
+}
+
+# Switch 语句比其他语言更强大
+$val = "20"
+switch($val) {
+ { $_ -eq 42 } { "The answer equals 42"; break }
+ '20' { "Exactly 20"; break }
+ { $_ -like 's*' } { "Case insensitive"; break }
+ { $_ -clike 's*'} { "clike, ceq, cne for case sensitive"; break }
+ { $_ -notmatch '^.*$'} { "Regex matching. cnotmatch, cnotlike, ..."; break }
+ { 'x' -contains 'x'} { "FALSE! -contains is for lists!"; break }
+ default { "Others" }
+}
+
+# 经典的 For 循环
+for($i = 1; $i -le 10; $i++) {
+ "Loop number $i"
+}
+# 或者可以更简洁
+1..10 | % { "Loop number $_" }
+
+# PowerShell 还提供其他循环方式
+foreach ($var in 'val1','val2','val3') { echo $var }
+# while () {}
+# do {} while ()
+# do {} until ()
+
+# 异常处理
+try {} catch {} finally {}
+try {} catch [System.NullReferenceException] {
+ echo $_.Exception | Format-List -Force
+}
+
+
+### Providers
+# 列出当前目录下的文件和子目录
+ls # 或者 `dir`
+cd ~ # 回到主目录
+
+Get-Alias ls # -> Get-ChildItem
+# 这些 cmdlet 有更加通用的名称,因为它不仅仅只操作当前目录,这一点和其他脚本语言不同。
+cd HKCU: # 跳转 HKEY_CURRENT_USER 注册表中的值
+
+# 获取当前会话中的提供者
+Get-PSProvider
+
+
+### 管道
+# Cmdlets 中的参数用来控制它们的行为:
+Get-ChildItem -Filter *.txt -Name # 获取所有 txt 文件名。
+# 需要输入足够多的参数来确保没有歧义。
+ls -fi *.txt -n # -f 是不可以的因为 -Force 同样存在。
+# 使用 `Get-Help Get-ChildItem -Full` 来查看全部参数。
+
+# 之前 cmdlet 获取的结果输出可以作为一下个输入。
+# `$_` 指代当前管道处理的对象。
+ls | Where-Object { $_.Name -match 'c' } | Export-CSV export.txt
+ls | ? { $_.Name -match 'c' } | ConvertTo-HTML | Out-File export.html
+
+# 如果对管道的对象感到疑惑,使用 `Get-Member` 来查看该对象的可使用的方法和属性。
+ls | Get-Member
+Get-Date | gm
+
+# ` 是行连续标识符,或者在每一行结尾添加一个 |
+Get-Process | Sort-Object ID -Descending | Select-Object -First 10 Name,ID,VM `
+ | Stop-Process -WhatIf
+
+Get-EventLog Application -After (Get-Date).AddHours(-2) | Format-List
+
+# 使用 % 作为 ForEach-Object 的简称。
+(a,b,c) | ForEach-Object `
+ -Begin { "Starting"; $counter = 0 } `
+ -Process { "Processing $_"; $counter++ } `
+ -End { "Finishing: $counter" }
+
+# Get-Process 返回包含三列的表
+# 第三列是使用 2 位精度数值表示 VM 属性
+# 计算出来的列也可以表示更多的信息:
+# `@{name='lbl';expression={$_}`
+ps | Format-Table ID,Name,@{n='VM(MB)';e={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize
+
+
+### 函数
+# [string] 注记是可选的。
+function foo([string]$name) {
+ echo "Hey $name, have a function"
+}
+
+# 调用你的函数
+foo "Say my name"
+
+# 函数可以包含命名参数、参数的注记和可解析的文档
+<#
+.SYNOPSIS
+Setup a new website
+.DESCRIPTION
+Creates everything your new website needs for much win
+.PARAMETER siteName
+The name for the new website
+.EXAMPLE
+New-Website -Name FancySite -Po 5000
+New-Website SiteWithDefaultPort
+New-Website siteName 2000 # ERROR! Port argument could not be validated
+('name1','name2') | New-Website -Verbose
+#>
+function New-Website() {
+ [CmdletBinding()]
+ param (
+ [Parameter(ValueFromPipeline=$true, Mandatory=$true)]
+ [Alias('name')]
+ [string]$siteName,
+ [ValidateSet(3000,5000,8000)]
+ [int]$port = 3000
+ )
+ BEGIN { Write-Verbose 'Creating new website(s)' }
+ PROCESS { echo "name: $siteName, port: $port" }
+ END { Write-Verbose 'Website(s) created' }
+}
+
+
+### 都是 .NET
+# PS 中的字符串事实上就是 .NET 的 System.String 类型
+# 所有 .NET 方法和属性都可用
+'string'.ToUpper().Replace('G', 'ggg')
+# 或者更加 PowerShell 一点
+'string'.ToUpper() -replace 'G', 'ggg'
+
+# 不确定这样的话 .NET 方法如何调用
+'string' | gm
+
+# 调用静态 .NET 方法的语法:
+[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
+
+# 注意 .NET 方法调用必须使用括号,然而 PS 函数调用不能使用括号;
+# 如果你调用 cmdlet/PS 函数使用了括号,就相当于传递了参数列表。
+$writer = New-Object System.IO.StreamWriter($path, $true)
+$writer.Write([Environment]::NewLine)
+$writer.Dispose()
+
+### IO
+# 从输入读入一个值
+$Name = Read-Host "What's your name?"
+echo "Hello, $Name!"
+[int]$Age = Read-Host "What's your age?"
+
+# Test-Path, Split-Path, Join-Path, Resolve-Path
+# Get-Content filename # 返回字符串数组 string[]
+# Set-Content, Add-Content, Clear-Content
+Get-Command ConvertTo-*,ConvertFrom-*
+
+
+### 有用的东西
+# 更新 PATH
+$env:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") +
+ ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
+
+# 找到 Python 的 PATH
+$env:PATH.Split(";") | Where-Object { $_ -like "*python*"}
+
+# 改变工作目录而不需要记住之前的路径
+Push-Location c:\temp # 改变工作目录至 c:\temp
+Pop-Location # 改变到之前的工作目录
+# 别名: pushd 和 popd
+
+# 在下载之后解除目录阻塞
+Get-ChildItem -Recurse | Unblock-File
+
+# Windows 资源管理器打开当前目录
+ii .
+
+# 按任意键退出
+$host.UI.RawUI.ReadKey()
+return
+
+# 创建快捷方式
+$WshShell = New-Object -comObject WScript.Shell
+$Shortcut = $WshShell.CreateShortcut($link)
+$Shortcut.TargetPath = $file
+$Shortcut.WorkingDirectory = Split-Path $file
+$Shortcut.Save()
+```
+
+
+配置你的 PowerShell
+
+```powershell
+# $Profile 是文件 `Microsoft.PowerShell_profile.ps1` 完整路径
+# 下面所有的代码都在 PS 会话开始的时候执行
+if (-not (Test-Path $Profile)) {
+ New-Item -Type file -Path $Profile -Force
+ notepad $Profile
+}
+# 更多信息: `help about_profiles`
+# 更多关于 Shell 有用的信息,确保查看下面的 PSReadLine 项目。
+```
+
+更多项目
+
+* [Channel9](https://channel9.msdn.com/Search?term=powershell%20pipeline#ch9Search&lang-en=en) PowerShell 教程
+* [PSGet](https://github.com/psget/psget) PowerShell NuGet 包
+* [PSReadLine](https://github.com/lzybkr/PSReadLine/) 仿 bash 按行读取( Window10 默认包含)
+* [Posh-Git](https://github.com/dahlbyk/posh-git/) Git 命令提示 (推荐!)
+* [PSake](https://github.com/psake/psake) 自动构建工作
+* [Pester](https://github.com/pester/Pester) BDD 测试框架
+* [Jump-Location](https://github.com/tkellogg/Jump-Location) Poweshell 中 `cd` 来跳转目录
+* [PowerShell Community Extensions](http://pscx.codeplex.com/) (废弃)
+
+尚未涉及
+
+* WMI: Windows 管理规范 (Get-CimInstance)
+* 多任务: Start-Job -scriptBlock {...},
+* 代码签名
+* 远程 (Enter-PSSession/Exit-PSSession; Invoke-Command)
diff --git a/zh-cn/racket-cn.html.markdown b/zh-cn/racket-cn.html.markdown
index 8ef3671f..b373e1d9 100644
--- a/zh-cn/racket-cn.html.markdown
+++ b/zh-cn/racket-cn.html.markdown
@@ -444,7 +444,7 @@ n ; => 6
(set-box! n* (add1 (unbox n*)))
(unbox n*) ; => 6
-;; 很多 Racket 诗句类型是不可变的 (对,列表,等),有一些既是可变的
+;; 很多 Racket 数据类型是不可变的 (对,列表,等),有一些既是可变的
;; 又是不可变的 (字符串,向量,散列表
;; 等...)
diff --git a/zh-cn/yaml-cn.html.markdown b/zh-cn/yaml-cn.html.markdown
index 3ba2afd8..e75fafba 100644
--- a/zh-cn/yaml-cn.html.markdown
+++ b/zh-cn/yaml-cn.html.markdown
@@ -16,6 +16,8 @@ YAML 根本不容许文字制表符。
```yaml
+--- # 文档开头
+
# YAML 中的注解看起来像这样。
################
@@ -135,7 +137,7 @@ bar: &bar
# foo 和 bar 将都含有 name: Everyone has same name
-# YAML 还有标签,你可以用它显示地声明类型。
+# YAML 还有标签,你可以用它显式地声明类型。
explicit_string: !!str 0.5
# 一些解析器实现特定语言的标签,就像这个针对 Python 的复数类型。
python_complex_number: !!python/complex 1+2j
@@ -176,7 +178,7 @@ set2:
item2: null
item3: null
-... # document end
+... # 文档结束
```
### 更多资源
diff --git a/zh-tw/dart-tw.html.markdown b/zh-tw/dart-tw.html.markdown
new file mode 100644
index 00000000..5a9241c2
--- /dev/null
+++ b/zh-tw/dart-tw.html.markdown
@@ -0,0 +1,566 @@
+---
+language: dart
+lang: zh-tw
+filename: learndart-tw.dart
+contributors:
+ - ["Joao Pedrosa", "https://github.com/jpedrosa/"]
+translators:
+ - ["Bob Lu", "https://github.com/LuPoYi/"]
+---
+
+Dart 是程式語言領域的新人。
+它借鑒了許多其他主流語言,並且不會偏離它的兄弟語言 JavaScript 太多。
+就像 JavaScript 一樣,Dart 的目標是提供良好的瀏覽器整合性。
+
+Dart 最有爭議的特性必然是它的可選類型。
+
+```javascript
+import "dart:collection";
+import "dart:math" as DM;
+
+// 歡迎進入15分鐘的 Dart 學習。 http://www.dartlang.org/
+// 這是一個可實際執行的範例。你可以用 Dart 執行它
+// 或者線上執行! 可以把程式碼複製/貼上到這個網站。 http://try.dartlang.org/
+
+// 函數宣告和方法宣告看起來一樣。
+// 函數宣告可以是巢狀的。宣告使用這種 name() {} 的形式,
+// 或者 name() => 單行表示式; 的形式。
+// 右箭頭的宣告形式會直接地返回表示式的結果。
+example1() {
+ example1nested1() {
+ example1nested2() => print("Example1 nested 1 nested 2");
+ example1nested2();
+ }
+ example1nested1();
+}
+
+// 匿名函數沒有函數名。
+example2() {
+ example2nested1(fn) {
+ fn();
+ }
+ example2nested1(() => print("Example2 nested 1"));
+}
+
+// 當宣告函數類型的參數的時候,宣告中可以包含
+// 函數參數需要的參數,指定所需的參數名即可。
+example3() {
+ example3nested1(fn(informSomething)) {
+ fn("Example3 nested 1");
+ }
+ example3planB(fn) { // 或者不宣告函數參數的參數
+ fn("Example3 plan B");
+ }
+ example3nested1((s) => print(s));
+ example3planB((s) => print(s));
+}
+
+// 函數有可以訪問到外層變數的閉包。
+var example4Something = "Example4 nested 1";
+example4() {
+ example4nested1(fn(informSomething)) {
+ fn(example4Something);
+ }
+ example4nested1((s) => print(s));
+}
+
+// 下面這個包含 sayIt 方法的類別宣告,同樣有一個可以訪問外層變數的閉包,
+// 就像前面的函數一樣。
+var example5method = "Example5 sayIt";
+class Example5Class {
+ sayIt() {
+ print(example5method);
+ }
+}
+example5() {
+ // 創建一個 Example5Class 類的匿名實例,
+ // 並呼叫它的 sayIt 方法。
+ new Example5Class().sayIt();
+}
+
+// 類別的宣告使用這種形式 class name { [classBody] }.
+// classBody 中可以包含實例方法和變數,
+// 還可以包含類別方法和變數。
+class Example6Class {
+ var example6InstanceVariable = "Example6 instance variable";
+ sayIt() {
+ print(example6InstanceVariable);
+ }
+}
+example6() {
+ new Example6Class().sayIt();
+}
+
+// 類別方法和變數使用 static 宣告。
+class Example7Class {
+ static var example7ClassVariable = "Example7 class variable";
+ static sayItFromClass() {
+ print(example7ClassVariable);
+ }
+ sayItFromInstance() {
+ print(example7ClassVariable);
+ }
+}
+example7() {
+ Example7Class.sayItFromClass();
+ new Example7Class().sayItFromInstance();
+}
+
+// 定數非常方便,但是對於在函數/方法的外層的定數有一個限制,
+// 類別的外層或外面的定數必須是常數。
+// 字串和數字預設是常數。
+// 但是 array 和 map 不是。他們需要用 "const" 宣告為常數。
+var example8Array = const ["Example8 const array"],
+ example8Map = const {"someKey": "Example8 const map"};
+example8() {
+ print(example8Array[0]);
+ print(example8Map["someKey"]);
+}
+
+// Dart 中的迴圈使用標準的 for () {} 或 while () {} 的形式,
+// 以及更加現代的 for (.. in ..) {} 的形式, 或者
+// 以 forEach 開頭並具有許多特性支援函數回呼的形式。
+var example9Array = const ["a", "b"];
+example9() {
+ for (var i = 0; i < example9Array.length; i++) {
+ print("Example9 for loop '${example9Array[i]}'");
+ }
+ var i = 0;
+ while (i < example9Array.length) {
+ print("Example9 while loop '${example9Array[i]}'");
+ i++;
+ }
+ for (var e in example9Array) {
+ print("Example9 for-in loop '${e}'");
+ }
+ example9Array.forEach((e) => print("Example9 forEach loop '${e}'"));
+}
+
+// 透過迴圈遍歷字串中的每個字元或者取出其子字串。
+var example10S = "ab";
+example10() {
+ for (var i = 0; i < example10S.length; i++) {
+ print("Example10 String character loop '${example10S[i]}'");
+ }
+ for (var i = 0; i < example10S.length; i++) {
+ print("Example10 substring loop '${example10S.substring(i, i + 1)}'");
+ }
+}
+
+// 支援兩種數字格式 int 和 double。
+example11() {
+ var i = 1 + 320, d = 3.2 + 0.01;
+ print("Example11 int ${i}");
+ print("Example11 double ${d}");
+}
+
+// DateTime 提供了日期/時間的方法。
+example12() {
+ var now = new DateTime.now();
+ print("Example12 now '${now}'");
+ now = now.add(new Duration(days: 1));
+ print("Example12 tomorrow '${now}'");
+}
+
+// 支援正規表達式。
+example13() {
+ var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$");
+ match(s) {
+ if (re.hasMatch(s)) {
+ print("Example13 regexp matches '${s}'");
+ } else {
+ print("Example13 regexp doesn't match '${s}'");
+ }
+ }
+ match(s1);
+ match(s2);
+}
+
+// 布林運算式支持隱式轉換以及動態類型
+example14() {
+ var a = true;
+ if (a) {
+ print("Example14 true, a is $a");
+ }
+ a = null;
+ if (a) {
+ print("Example14 true, a is $a");
+ } else {
+ print("Example14 false, a is $a"); // 執行到這裡
+ }
+
+// 動態類型的null可以轉換成bool型
+ var b; // b是動態類型
+ b = "abc";
+ try {
+ if (b) {
+ print("Example14 true, b is $b");
+ } else {
+ print("Example14 false, b is $b");
+ }
+ } catch (e) {
+ print("Example14 error, b is $b"); // 這段程式碼可以執行但是會報錯
+ }
+ b = null;
+ if (b) {
+ print("Example14 true, b is $b");
+ } else {
+ print("Example14 false, b is $b"); // 執行到這裡
+ }
+
+ // 靜態類型的null不能轉換成bool型
+ var c = "abc";
+ c = null;
+ // 編譯出錯
+ // if (c) {
+ // print("Example14 true, c is $c");
+ // } else {
+ // print("Example14 false, c is $c");
+ // }
+}
+
+// try/catch/finally 和 throw 語句用於例外處理。
+// throw 語句可以使用任何物件作為參數。
+example15() {
+ try {
+ try {
+ throw "Some unexpected error.";
+ } catch (e) {
+ print("Example15 an exception: '${e}'");
+ throw e; // Re-throw
+ }
+ } catch (e) {
+ print("Example15 catch exception being re-thrown: '${e}'");
+ } finally {
+ print("Example15 Still run finally");
+ }
+}
+
+// 想要有效地動態創建長字串,
+// 應該使用 StringBuffer。或者 join 一個字串的陣列。
+example16() {
+ var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e;
+ for (e in a) { sb.write(e); }
+ print("Example16 dynamic string created with "
+ "StringBuffer '${sb.toString()}'");
+ print("Example16 join string array '${a.join()}'");
+}
+
+// 字串連接只需讓相鄰的字串相連,
+// 不需要額外的操作運算符號。
+example17() {
+ print("Example17 "
+ "concatenate "
+ "strings "
+ "just like that");
+}
+
+// 字串使用單引號或雙引號做分隔,二者並沒有實際的差異。
+// 這種靈活性可以很好地避免內容中需要轉義換行的情況。
+// 例如,字串內容裡的 HTML 屬性使用了雙引號。
+example18() {
+ print('Example18 <a href="etc">'
+ "Don't can't I'm Etc"
+ '</a>');
+}
+
+// 用三個單引號或三個雙引號表示的字串
+// 可以跨越多行,並且包含換行。
+example19() {
+ print('''Example19 <a href="etc">
+Example19 Don't can't I'm Etc
+Example19 </a>''');
+}
+
+// 字串可以使用 $ 符號插入內容。
+// 使用 $ { [expression] } 的形式,表示式的值會被插入到字串中。
+// $ 跟著一個變數名會插入變數的值。
+// 如果要在字符串中插入 $ ,可以使用 \$ 的轉義形式取代。
+example20() {
+ var s1 = "'\${s}'", s2 = "'\$s'";
+ print("Example20 \$ interpolation ${s1} or $s2 works.");
+}
+
+// 可選類型允許作為 API 的標註,並且可以輔助 IDE,
+// 這樣 IDE 可以更好地提供重構、自動完成和錯誤檢測功能。
+// 目前為止我們還沒有宣告任何類型,並且程式可以執行。
+// 事實上,類型在執行時會被忽略。
+// 類型甚至可以是錯的,並且程式依然可以執行,
+// 好像和類型完全無關一樣。
+// 有一個執行時參數可以讓程式進入檢查模式,它會在執行時檢查類型錯誤。
+// 這在開發時很有用,但是由於增加了額外的檢查會使程式變慢,
+// 因此應該避免在部署時使用。
+class Example21 {
+ List<String> _names;
+ Example21() {
+ _names = ["a", "b"];
+ }
+ List<String> get names => _names;
+ set names(List<String> list) {
+ _names = list;
+ }
+ int get length => _names.length;
+ void add(String name) {
+ _names.add(name);
+ }
+}
+
+void example21() {
+ Example21 o = new Example21();
+ o.add("c");
+ print("Example21 names '${o.names}' and length '${o.length}'");
+ o.names = ["d", "e"];
+ print("Example21 names '${o.names}' and length '${o.length}'");
+}
+
+// 類型的繼承形式是 class name extends AnotherClassName {} 。
+class Example22A {
+ var _name = "Some Name!";
+ get name => _name;
+}
+class Example22B extends Example22A {}
+example22() {
+ var o = new Example22B();
+ print("Example22 class inheritance '${o.name}'");
+}
+
+// 類型也可以使用 mixin 的形式 :
+// class name extends SomeClass with AnotherClassName {}.
+// 必需繼承某個類型才能 mixin 另一個類型。
+// 當前 mixin 的模板類型不能有建構子。
+// Mixin 主要是用來和輔助的類型共享方法的,
+// 這樣單一繼承就不會影響程式碼重覆使用。
+// Mixin 宣告在類型定義的 "with" 後面。
+class Example23A {}
+class Example23Utils {
+ addTwo(n1, n2) {
+ return n1 + n2;
+ }
+}
+class Example23B extends Example23A with Example23Utils {
+ addThree(n1, n2, n3) {
+ return addTwo(n1, n2) + n3;
+ }
+}
+example23() {
+ var o = new Example23B(), r1 = o.addThree(1, 2, 3),
+ r2 = o.addTwo(1, 2);
+ print("Example23 addThree(1, 2, 3) results in '${r1}'");
+ print("Example23 addTwo(1, 2) results in '${r2}'");
+}
+
+// 類型的建構子和類型名相同,形式為
+// SomeClass() : super() {}, 其中 ": super()" 的部分是可選的,
+// 它用來傳遞參數給父類型的建構子。
+class Example24A {
+ var _value;
+ Example24A({value: "someValue"}) {
+ _value = value;
+ }
+ get value => _value;
+}
+class Example24B extends Example24A {
+ Example24B({value: "someOtherValue"}) : super(value: value);
+}
+example24() {
+ var o1 = new Example24B(),
+ o2 = new Example24B(value: "evenMore");
+ print("Example24 calling super during constructor '${o1.value}'");
+ print("Example24 calling super during constructor '${o2.value}'");
+}
+
+// 對於簡單的類型,有一種設置構造函數參數的快捷方式。
+// 只需要使用 this.parameterName 的前綴,
+// 它就會把參數設置為同名的實例變數。
+class Example25 {
+ var value, anotherValue;
+ Example25({this.value, this.anotherValue});
+}
+example25() {
+ var o = new Example25(value: "a", anotherValue: "b");
+ print("Example25 shortcut for constructor '${o.value}' and "
+ "'${o.anotherValue}'");
+}
+
+// 可以在大括號 {} 中宣告命名參數。
+// 大括號 {} 中宣告的參數的順序是隨意的。
+// 在中括號 [] 中宣告的參數也是可選的。
+example26() {
+ var _name, _surname, _email;
+ setConfig1({name, surname}) {
+ _name = name;
+ _surname = surname;
+ }
+ setConfig2(name, [surname, email]) {
+ _name = name;
+ _surname = surname;
+ _email = email;
+ }
+ setConfig1(surname: "Doe", name: "John");
+ print("Example26 name '${_name}', surname '${_surname}', "
+ "email '${_email}'");
+ setConfig2("Mary", "Jane");
+ print("Example26 name '${_name}', surname '${_surname}', "
+ "email '${_email}'");
+}
+
+// 使用 final 宣告的變數只能被設置一次。
+// 在類型裡面,final 實例變數可以通過常數的建構子參數設置。
+class Example27 {
+ final color1, color2;
+ // 更靈活一點的方法是在冒號 : 後面設置 final 實例變數。
+ Example27({this.color1, color2}) : color2 = color2;
+}
+example27() {
+ final color = "orange", o = new Example27(color1: "lilac", color2: "white");
+ print("Example27 color is '${color}'");
+ print("Example27 color is '${o.color1}' and '${o.color2}'");
+}
+
+// 要導入一個函式庫,使用 import "libraryPath" 的形式,或者如果要導入的是
+// 核心庫使用 import "dart:libraryName" 。還有一個稱為 "pub" 的套件管理工具,
+// 它使用 import "package:packageName" 的約定形式。
+// 看下這個文件頂部的 import "dart:collection"; 語法。
+// 導入語句必需在其它程式碼宣告之前出現。 IterableBase 來自於 dart:collection 。
+class Example28 extends IterableBase {
+ var names;
+ Example28() {
+ names = ["a", "b"];
+ }
+ get iterator => names.iterator;
+}
+example28() {
+ var o = new Example28();
+ o.forEach((name) => print("Example28 '${name}'"));
+}
+
+// 對於控制流程,我們有:
+// * 必需帶 break 的標準 switch 語法
+// * if-else 和三元運算子 ..?..:..
+// * 閉包和匿名函數
+// * break, continue 和 return 語法
+example29() {
+ var v = true ? 30 : 60;
+ switch (v) {
+ case 30:
+ print("Example29 switch statement");
+ break;
+ }
+ if (v < 30) {
+ } else if (v > 30) {
+ } else {
+ print("Example29 if-else statement");
+ }
+ callItForMe(fn()) {
+ return fn();
+ }
+ rand() {
+ v = new DM.Random().nextInt(50);
+ return v;
+ }
+ while (true) {
+ print("Example29 callItForMe(rand) '${callItForMe(rand)}'");
+ if (v != 30) {
+ break;
+ } else {
+ continue;
+ }
+ // 不會到這裡。
+ }
+}
+
+// 解析 int,把 double 轉成 int,或者使用 ~/ 運算符號在除法計算時僅保留整數位。
+// 讓我們也來場猜數遊戲吧。
+example30() {
+ var gn,
+ tooHigh = false,
+ n,
+ n2 = (2.0).toInt(),
+ top = int.parse("123") ~/ n2,
+ bottom = 0;
+ top = top ~/ 6;
+ gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive
+ print("Example30 Guess a number between 0 and ${top}");
+ guessNumber(i) {
+ if (n == gn) {
+ print("Example30 Guessed right! The number is ${gn}");
+ } else {
+ tooHigh = n > gn;
+ print("Example30 Number ${n} is too "
+ "${tooHigh ? 'high' : 'low'}. Try again");
+ }
+ return n == gn;
+ }
+
+ n = (top - bottom) ~/ 2;
+ while (!guessNumber(n)) {
+ if (tooHigh) {
+ top = n - 1;
+ } else {
+ bottom = n + 1;
+ }
+ n = bottom + ((top - bottom) ~/ 2);
+ }
+}
+
+// 選填位置參數:
+// 參數定義使用方括號 [ ],傳入參數是選填的。
+example31() {
+ findVolume31(int length, int breath, [int height]) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume31(10,20,30); // 可執行
+ findVolume31(10,20); // 也可執行
+}
+
+// 選填命名參數:
+// 參數定義使用大括號 { }, 傳入參數是選填的。
+// 必須傳入參數名稱及參數值,並以 : 分隔
+// 大括號的順序沒有差別
+// 這種類型參數可以幫我們避免多個參數傳入時造成混淆。
+example32() {
+ findVolume32(int length, int breath, {int height}) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume32(10,20,height:30); // 可執行 & 參數名稱在這邊有傳入
+ findVolume32(10,20); // 也可執行
+}
+
+// 選填預設參數:
+// 與選填命名參數相同,此外,我們為此參數定義的預設值
+// 如果沒有傳入值,就使用預設值
+example33() {
+ findVolume33(int length, int breath, {int height=10}) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume33(10,20,height:30); // 可執行
+ findVolume33(10,20); // 可執行
+}
+
+// 程式的唯一入口點是 main 函式。
+// 在程式開始執行 main 函式之前,不會執行任何外部程式碼。
+// 這樣有助於更快加載甚至是延遲加載程式啟動時所需要的部分;
+main() {
+ print("Learn Dart in 15 minutes!");
+ [
+ example1, example2, example3, example4, example5,
+ example6, example7, example8, example9, example10,
+ example11, example12, example13, example14, example15,
+ example16, example17, example18, example19, example20,
+ example21, example22, example23, example24, example25,
+ example26, example27, example28, example29,
+ example30 // 增加此註解可阻止dart formatter把所有項目都換行
+ ].forEach((ef) => ef());
+}
+
+```
+
+## 延伸閱讀
+
+Dart 有一個綜合性網站。它涵蓋了 API 參考、入門教學、文章以及更多,
+還包括一個有用的線上試用 Dart 頁面。
+* [https://www.dartlang.org](https://www.dartlang.org)
+* [https://try.dartlang.org](https://try.dartlang.org)