summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ansible.html.markdown28
-rw-r--r--awk.html.markdown2
-rw-r--r--bash.html.markdown18
-rw-r--r--bc.html.markdown98
-rw-r--r--c++.html.markdown63
-rw-r--r--c.html.markdown3
-rw-r--r--ca-es/html-ca.html.markdown176
-rw-r--r--chapel.html.markdown2
-rw-r--r--clojure.html.markdown3
-rw-r--r--common-lisp.html.markdown2
-rw-r--r--coq.html.markdown510
-rw-r--r--cs-cz/python3.html.markdown27
-rw-r--r--csharp.html.markdown72
-rw-r--r--css.html.markdown19
-rw-r--r--cypher.html.markdown2
-rw-r--r--d.html.markdown1
-rw-r--r--dart.html.markdown119
-rw-r--r--de-de/asciidoc-de.html.markdown6
-rw-r--r--de-de/bash-de.html.markdown4
-rw-r--r--de-de/c++-de.html.markdown1158
-rw-r--r--de-de/dhall-de.html.markdown380
-rw-r--r--de-de/git-de.html.markdown2
-rw-r--r--de-de/html-de.html.markdown16
-rw-r--r--de-de/java-de.html.markdown2
-rw-r--r--de-de/markdown-de.html.markdown2
-rw-r--r--de-de/nix-de.html.markdown22
-rw-r--r--de-de/python-de.html.markdown359
-rw-r--r--de-de/python3-de.html.markdown2
-rw-r--r--de-de/yaml-de.html.markdown2
-rw-r--r--dhall.html.markdown362
-rw-r--r--directx9.html.markdown827
-rw-r--r--dynamic-programming.html.markdown14
-rw-r--r--el-gr/bash-gr.html.markdown528
-rw-r--r--el-gr/html-gr.html.markdown193
-rw-r--r--elisp.html.markdown6
-rw-r--r--elixir.html.markdown8
-rw-r--r--emacs.html.markdown320
-rw-r--r--es-es/c-es.html.markdown3
-rw-r--r--es-es/dart-es.html.markdown529
-rw-r--r--es-es/factor-es.html.markdown200
-rw-r--r--es-es/hq9+-es.html.markdown44
-rw-r--r--es-es/hy-es.html.markdown176
-rw-r--r--es-es/kotlin-es.html.markdown68
-rw-r--r--es-es/pcre-es.html.markdown84
-rw-r--r--es-es/scala-es.html.markdown741
-rw-r--r--fr-fr/elixir-fr.html.markdown479
-rw-r--r--fr-fr/erlang-fr.html.markdown4
-rw-r--r--fsharp.html.markdown4
-rw-r--r--go.html.markdown6
-rw-r--r--groovy.html.markdown15
-rw-r--r--haskell.html.markdown159
-rw-r--r--haxe.html.markdown36
-rw-r--r--html.html.markdown1
-rw-r--r--it-it/bash-it.html.markdown19
-rw-r--r--it-it/elixir-it.html.markdown52
-rw-r--r--it-it/javascript-it.html.markdown617
-rw-r--r--it-it/pcre-it.html.markdown13
-rw-r--r--it-it/rust-it.html.markdown4
-rw-r--r--ja-jp/asciidoc.html.markdown135
-rw-r--r--ja-jp/python3-jp.html.markdown240
-rw-r--r--java.html.markdown12
-rw-r--r--javascript.html.markdown42
-rw-r--r--kdb+.html.markdown2
-rw-r--r--kotlin.html.markdown130
-rw-r--r--lambda-calculus.html.markdown2
-rw-r--r--latex.html.markdown2
-rw-r--r--ldpl.html.markdown183
-rw-r--r--linker.html.markdown9
-rw-r--r--lsf/lambda-calculus-lsf.html.markdown91
-rw-r--r--lsf/latex-lsf.html.markdown146
-rw-r--r--mercurial.html.markdown4
-rw-r--r--mercury.html.markdown263
-rw-r--r--mips.html.markdown14
-rw-r--r--nix.html.markdown32
-rw-r--r--opengl.html.markdown765
-rw-r--r--p5.html.markdown54
-rw-r--r--pcre.html.markdown25
-rw-r--r--perl.html.markdown2
-rw-r--r--perl6.html.markdown1966
-rw-r--r--php.html.markdown2
-rw-r--r--pl-pl/bf-pl.html.markdown5
-rw-r--r--pl-pl/java-pl.html.markdown1026
-rw-r--r--prolog.html.markdown2
-rw-r--r--protocol-buffer-3.html.markdown247
-rw-r--r--pt-br/bash-pt.html.markdown22
-rw-r--r--pt-br/c-pt.html.markdown3
-rw-r--r--pt-br/clojure-macros-pt.html.markdown16
-rw-r--r--pt-br/clojure-pt.html.markdown602
-rw-r--r--pt-br/coffeescript-pt.html.markdown46
-rw-r--r--pt-br/csharp-pt.html.markdown45
-rw-r--r--pt-br/css-pt.html.markdown24
-rw-r--r--pt-br/cypher-pt.html.markdown2
-rw-r--r--pt-br/elisp-pt.html.markdown2
-rw-r--r--pt-br/groovy-pt.html.markdown2
-rw-r--r--pt-br/haskell-pt.html.markdown4
-rw-r--r--pt-br/javascript-pt.html.markdown6
-rw-r--r--pt-br/julia-pt.html.markdown2
-rw-r--r--pt-br/latex-pt.html.markdown2
-rw-r--r--pt-br/markdown-pt.html.markdown44
-rw-r--r--pt-br/pascal-pt.html.markdown3
-rw-r--r--pt-br/php-pt.html.markdown2
-rw-r--r--pt-br/python3-pt.html.markdown36
-rwxr-xr-xpt-br/stylus-pt.html.markdown8
-rw-r--r--pt-br/typescript-pt.html.markdown6
-rw-r--r--pt-br/vim-pt.html.markdown11
-rw-r--r--pt-br/whip-pt.html.markdown2
-rw-r--r--pt-br/yaml-pt.html.markdown10
-rw-r--r--pug.html.markdown204
-rw-r--r--python3.html.markdown63
-rw-r--r--raku.html.markdown2412
-rw-r--r--reason.html.markdown544
-rw-r--r--rst.html.markdown16
-rw-r--r--ru-ru/c++-ru.html.markdown21
-rw-r--r--ru-ru/c-ru.html.markdown10
-rw-r--r--ru-ru/go-ru.html.markdown4
-rw-r--r--ru-ru/kotlin-ru.html.markdown2
-rw-r--r--ru-ru/learnvisualbasic-ru.html.markdown284
-rw-r--r--ru-ru/linker-ru.html.markdown203
-rw-r--r--ru-ru/ruby-ru.html.markdown10
-rw-r--r--ru-ru/rust-ru.html.markdown61
-rw-r--r--ru-ru/sql-ru.html.markdown120
-rw-r--r--ru-ru/yaml-ru.html.markdown2
-rw-r--r--ruby.html.markdown19
-rw-r--r--rust.html.markdown11
-rw-r--r--sass.html.markdown2
-rw-r--r--scala.html.markdown2
-rw-r--r--smalltalk.html.markdown92
-rw-r--r--solidity.html.markdown2
-rw-r--r--sql.html.markdown41
-rw-r--r--standard-ml.html.markdown3
-rw-r--r--swift.html.markdown972
-rw-r--r--ta_in/css-ta.html.markdown42
-rw-r--r--ta_in/xml-ta.html.markdown52
-rw-r--r--th-th/pascal.th.html.markdown236
-rw-r--r--th-th/typescript.th.html.markdown259
-rw-r--r--tmux.html.markdown2
-rwxr-xr-xtoml.html.markdown14
-rw-r--r--tr-tr/c-tr.html.markdown2
-rw-r--r--tr-tr/clojure-tr.html.markdown1
-rw-r--r--tr-tr/edn-tr.html.markdown157
-rw-r--r--tr-tr/sql-tr.html.markdown125
-rw-r--r--typescript.html.markdown57
-rw-r--r--uk-ua/cypher-ua.html.markdown254
-rw-r--r--uk-ua/go-ua.html.markdown449
-rw-r--r--uk-ua/kotlin-ua.html.markdown464
-rw-r--r--uk-ua/mips-ua.html.markdown366
-rw-r--r--uk-ua/python-ua.html.markdown2
-rw-r--r--uk-ua/rust-ua.html.markdown331
-rw-r--r--uk-ua/wasm-ua.html.markdown226
-rw-r--r--vyper.html.markdown872
-rw-r--r--wasm.html.markdown312
-rw-r--r--wolfram.html.markdown4
-rw-r--r--yaml.html.markdown2
-rw-r--r--zfs.html.markdown11
-rw-r--r--zh-cn/c-cn.html.markdown2
-rw-r--r--zh-cn/lambda-calculus-cn.html.markdown223
-rw-r--r--zh-cn/make-cn.html.markdown10
-rw-r--r--zh-cn/markdown-cn.html.markdown58
-rw-r--r--zh-cn/powershell-cn.html.markdown325
-rw-r--r--zh-cn/ruby-cn.html.markdown160
-rw-r--r--zh-cn/sql.html.markdown105
-rw-r--r--zh-cn/yaml-cn.html.markdown93
-rw-r--r--zh-tw/pcre-tw.html.markdown9
163 files changed, 21868 insertions, 3370 deletions
diff --git a/ansible.html.markdown b/ansible.html.markdown
index 2b61cc8e..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)
@@ -49,7 +49,7 @@ environments, it may be noticable amount.
'on-demand' - there is no built-in mechanism that would warn you about some
change automatically (this can be achieved with reasonable effort)
* Official GUI - Ansible Tower - is great but expensive.
-* There is no 'small enterprice' payment plan, however Ansible AWX is the free
+* There is no 'small enterprise' payment plan, however Ansible AWX is the free
open source version we were all waiting for.
#### Neutral
@@ -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/awk.html.markdown b/awk.html.markdown
index 1ef6b8d5..3ff3f937 100644
--- a/awk.html.markdown
+++ b/awk.html.markdown
@@ -382,3 +382,5 @@ Further Reading:
* [Awk man page](https://linux.die.net/man/1/awk)
* [The GNU Awk User's Guide](https://www.gnu.org/software/gawk/manual/gawk.html) GNU Awk is found on most Linux systems.
* [AWK one-liner collection](http://tuxgraphics.org/~guido/scripts/awk-one-liner.html)
+* [Awk alpinelinux wiki](https://wiki.alpinelinux.org/wiki/Awk) a technical summary and list of "gotchas" (places where different implementations may behave in different or unexpected ways).
+* [basic libraries for awk](https://github.com/dubiousjim/awkenough)
diff --git a/bash.html.markdown b/bash.html.markdown
index 0385c46d..856db706 100644
--- a/bash.html.markdown
+++ b/bash.html.markdown
@@ -11,13 +11,15 @@ contributors:
- ["Rahil Momin", "https://github.com/iamrahil"]
- ["Gregrory Kielian", "https://github.com/gskielian"]
- ["Etan Reisner", "https://github.com/deryni"]
- - ["Jonathan Wang", "https://github.com/Jonathansw"]
+ - ["Jonathan Wang", "https://github.com/Jonathansw"]
- ["Leo Rudberg", "https://github.com/LOZORD"]
- ["Betsy Lorton", "https://github.com/schbetsy"]
- ["John Detter", "https://github.com/jdetter"]
- ["Harry Mumford-Turner", "https://github.com/harrymt"]
- ["Martin Nicholson", "https://github.com/mn113"]
filename: LearnBash.sh
+translators:
+ - ["Dimitri Kokkonis", "https://github.com/kokkonisd"]
---
Bash is a name of the unix shell, which was also distributed as the shell
@@ -67,7 +69,7 @@ echo '$Variable' # => $Variable
# Parameter expansion ${ }:
echo ${Variable} # => Some string
# This is a simple usage of parameter expansion
-# Parameter Expansion gets a value from a variable.
+# Parameter Expansion gets a value from a variable.
# It "expands" or prints the value
# During the expansion time the value or parameter can be modified
# Below are other modifications that add onto this expansion
@@ -87,7 +89,7 @@ echo ${Variable: -5} # => tring
echo ${#Variable} # => 11
# Default value for variable
-echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"}
+echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"}
# => DefaultValueIfFooIsMissingOrEmpty
# This works for null (Foo=) and empty string (Foo=""); zero (Foo=0) returns 0.
# Note that it only returns default value and doesn't change variable value.
@@ -244,7 +246,7 @@ cp -r srcDirectory/ dst/ # recursively copy
# `mv` is also useful for renaming files!
mv s0urc3.txt dst.txt # sorry, l33t hackers...
-# Since bash works in the context of a current directory, you might want to
+# Since bash works in the context of a current directory, you might want to
# run your command in some other directory. We have cd for changing location:
cd ~ # change to home directory
cd # also goes to home directory
@@ -280,7 +282,7 @@ for line in sys.stdin:
EOF
# Variables will be expanded if the first "EOF" is not quoted
-# Run the hello.py Python script with various stdin, stdout, and
+# Run the hello.py Python script with various stdin, stdout, and
# stderr redirections:
python hello.py < "input.in" # pass input.in as input to the script
@@ -322,7 +324,7 @@ rm -r tempDir/ # recursively delete
# current directory.
echo "There are $(ls | wc -l) items here."
-# The same can be done using backticks `` but they can't be nested -
+# The same can be done using backticks `` but they can't be nested -
#the preferred way is to use $( ).
echo "There are `ls | wc -l` items here."
@@ -442,8 +444,8 @@ grep "^foo.*bar$" file.txt | grep -v "baz"
# and not the regex, use fgrep (or grep -F)
fgrep "foobar" file.txt
-# The `trap` command allows you to execute a command whenever your script
-# receives a signal. Here, `trap` will execute `rm` if it receives any of the
+# The `trap` command allows you to execute a command whenever your script
+# receives a signal. Here, `trap` will execute `rm` if it receives any of the
# three listed signals.
trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM
diff --git a/bc.html.markdown b/bc.html.markdown
new file mode 100644
index 00000000..9d63acfb
--- /dev/null
+++ b/bc.html.markdown
@@ -0,0 +1,98 @@
+---
+language: bc
+contributors:
+ - ["Btup"]
+filename: learnbc.bc
+---
+```c
+/*This is a multi-
+line comment.*/
+# This is also a (one-line) comment! (in GNU bc).
+
+ /*1. Variables and control structures*/
+num = 45 /*All variables save only doubles, and you cannot save
+ string constants directly.*/
+num = 45; /*You can choose to add a semicolon after
+ every statement. This is optional.*/
+/*Blocks are denoted using the {} operators(similar to C):*/
+while(num < 50) {
+ num += 1 /*equivalent to num=num+1.
+ a = a op b is equivalent to a op= b.*/
+}
+/*And there are ++(increment) and --(decrement) operators.*/
+/*There are 3 special variables:
+scale: defines the scale of the double numbers.
+ibase: defines the base of input.
+obase: defines the base of output.*/
+/*If clauses:*/
+hour = read() /*Input a number*/
+
+if(hour < 12) { /*Operators are exactly like C.*/
+ print "Good morning\n" /*"print" outputs strings or variables
+ separated by commas.*/
+} else if(hour == 12) {
+ print "Hello\n"
+ /*Escaping sequences start with a \ in a string.
+ In order to make the escaping sequences clearer, here
+ is a simplified list of them that will work in bc:
+ \b: backspace
+ \c: carriage return
+ \n: newline
+ \t: tab
+ \\: backslash*/
+} else {
+ /*Variables are global by default.*/
+ thisIsGlobal = 5
+ /*You can make a variable local. Use the "auto" keyword in a function.*/
+}
+
+/*Every variable is pre-set to 0.*/
+num = blankVariable /*num is set to 0.*/
+
+/*Like C, only 0 is falsy.*/
+if(!num) {print "false\n"}
+
+/*Unlike C, bc does not have the ?: operators. For example,
+ this block of code will cause an error:
+a = (num) ? 1 : 0
+However, you can simulate one:*/
+a = (num) && (1) || (0) /*&& is and, || is or*/
+
+/*For loops*/
+num = 0
+for(i = 1; i <= 100; i++) {/*Similar to the C for loop.*/
+ num += i
+}
+
+ /*2.Functions and Arrays*/
+define fac(n) { /*define a function using define.*/
+ if(n == 1 || n == 0) {
+ return 1 /*return a value*/
+ }
+ return n * fac(n - 1) /*recursion is possible*/
+}
+
+/*Closures and anonymous functions are impossible.*/
+
+num = fac(4) /*24*/
+
+/*This is an example of local variables:*/
+define x(n) {
+ auto x
+ x = 1
+ return n + x
+}
+x(3) /*4*/
+print x /*It turns out that x is not accessible out of the function.*/
+/*Arrays are equivalent to the C array.*/
+for(i = 0; i <= 3; i++) {
+ a[i] = 1
+}
+/*Access it like this:*/
+print a[0], " ", a[1], " ", a[2], " ", a[3], "\n"
+quit /*Add this line of code to make sure
+that your program exits. This line of code is optional.*/
+```
+Enjoy this simple calculator! (Or this programming language, to be exact.)
+
+This whole program is written in GNU bc. To run it, use ```bc learnbc.bc```.
diff --git a/c++.html.markdown b/c++.html.markdown
index 80ad3a6c..f3dc8e20 100644
--- a/c++.html.markdown
+++ b/c++.html.markdown
@@ -72,7 +72,7 @@ void func(); // function which may accept any number of arguments
int* ip = nullptr;
// C standard headers are available in C++.
-// C headers end in .h, while
+// C headers end in .h, while
// C++ headers are prefixed with "c" and have no ".h" suffix.
// The C++ standard version:
@@ -553,10 +553,14 @@ Point Point::operator+(const Point& rhs) const
return Point(x + rhs.x, y + rhs.y);
}
+// It's good practice to return a reference to the leftmost variable of
+// an assignment. `(a += b) == c` will work this way.
Point& Point::operator+=(const Point& rhs)
{
x += rhs.x;
y += rhs.y;
+
+ // `this` is a pointer to the object, on which a method is called.
return *this;
}
@@ -757,7 +761,7 @@ failure:
// things are a little cleaner, but still sub-optimal.
void doSomethingWithAFile(const char* filename)
{
- FILE* fh = fopen(filename, "r"); // Open the file in read mode
+ FILE* fh = fopen(filename, "r"); // Open the file in shared_ptrread mode
if (fh == nullptr)
throw std::runtime_error("Could not open the file.");
@@ -811,6 +815,57 @@ void doSomethingWithAFile(const std::string& filename)
/////////////////////
+// Smart Pointer
+/////////////////////
+
+// Generally a smart pointer is a class which wraps a "raw pointer" (usage of "new"
+// respectively malloc/calloc in C). The goal is to be able to
+// manage the lifetime of the object being pointed to without ever needing to explicitly delete
+// the object. The term itself simply describes a set of pointers with the
+// mentioned abstraction.
+// Smart pointers should preferred over raw pointers, to prevent
+// risky memory leaks, which happen if you forget to delete an object.
+
+// Usage of a raw pointer:
+Dog* ptr = new Dog();
+ptr->bark();
+delete ptr;
+
+// By using a smart pointer, you don't have to worry about the deletion
+// of the object anymore.
+// A smart pointer describes a policy, to count the references to the
+// pointer. The object gets destroyed when the last
+// reference to the object gets destroyed.
+
+// Usage of "std::shared_ptr":
+void foo()
+{
+// It's no longer necessary to delete the Dog.
+std::shared_ptr<Dog> doggo(new Dog());
+doggo->bark();
+}
+
+// Beware of possible circular references!!!
+// There will be always a reference, so it will be never destroyed!
+std::shared_ptr<Dog> doggo_one(new Dog());
+std::shared_ptr<Dog> doggo_two(new Dog());
+doggo_one = doggo_two; // p1 references p2
+doggo_two = doggo_one; // p2 references p1
+
+// There are several kinds of smart pointers.
+// The way you have to use them is always the same.
+// This leads us to the question: when should we use each kind of smart pointer?
+// std::unique_ptr - use it when you just want to hold one reference to
+// the object.
+// std::shared_ptr - use it when you want to hold multiple references to the
+// same object and want to make sure that it's deallocated
+// when all references are gone.
+// std::weak_ptr - use it when you want to access
+// the underlying object of a std::shared_ptr without causing that object to stay allocated.
+// Weak pointers are used to prevent circular referencing.
+
+
+/////////////////////
// Containers
/////////////////////
@@ -873,7 +928,7 @@ cout << ST.size(); // will print the size of set ST
// Output: 0
// NOTE: for duplicate elements we can use multiset
-// NOTE: For hash sets, use unordered_set. They are more efficient but
+// NOTE: For hash sets, use unordered_set. They are more efficient but
// do not preserve order. unordered_set is available since C++11
// Map
@@ -902,7 +957,7 @@ cout << it->second;
// Output: 26
-// NOTE: For hash maps, use unordered_map. They are more efficient but do
+// NOTE: For hash maps, use unordered_map. They are more efficient but do
// not preserve order. unordered_map is available since C++11.
// Containers with object keys of non-primitive values (custom classes) require
diff --git a/c.html.markdown b/c.html.markdown
index 7975a1c2..e5ffc379 100644
--- a/c.html.markdown
+++ b/c.html.markdown
@@ -10,6 +10,7 @@ contributors:
- ["himanshu", "https://github.com/himanshu81494"]
- ["Joshua Li", "https://github.com/JoshuaRLi"]
- ["Dragos B. Chirila", "https://github.com/dchirila"]
+ - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
---
Ah, C. Still **the** language of modern high-performance computing.
@@ -820,7 +821,7 @@ Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://
It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some
inaccuracies (well, ideas that are not considered good anymore) or now-changed practices.
-Another good resource is [Learn C The Hard Way](http://c.learncodethehardway.org/book/).
+Another good resource is [Learn C The Hard Way](http://learncodethehardway.org/c/).
If you have a question, read the [compl.lang.c Frequently Asked Questions](http://c-faq.com).
diff --git a/ca-es/html-ca.html.markdown b/ca-es/html-ca.html.markdown
new file mode 100644
index 00000000..351eb722
--- /dev/null
+++ b/ca-es/html-ca.html.markdown
@@ -0,0 +1,176 @@
+---
+language: html
+filename: html-ca.md
+contributors:
+ - ["Christophe THOMAS", "https://github.com/WinChris"]
+translators:
+ - ["Marc Auledas", "https://github.com/Auledas"]
+lang: ca-es
+---
+
+HTML significa llenguatge de marques d'hipertext (HyperText Markup Language).
+
+És un llenguatge que permet escriure pàgines pel sistema web (World Wide Web).
+És un llenguatge de marques que permet escriure pàgines web fent servir codi per indicar
+com s'ha de visualitzar el text i les dades. De fet, els fitxers html són simples
+fitxers de text.
+
+Què són les 'marques'? Són un mètode d'organitzar les dades d'una pàgina mitjançant
+etiquetes d'obertura i tancament. Aquestes marques serveixen per donar
+significat al text que hi ha entre les etiquetes. Com d'altres llenguatges de marques,
+hi ha moltes versions de l'HTML. Aquí es desenvoluparà l'HTML5.
+
+**NOTA:** Pots provar les diferents etiquetes i elements a mesura que progressis a través
+del tutorial a pàgines web com [codepen](http://codepen.io/pen/). D'aquesta manera podràs
+veure'n els efectes, entendre com funcionen i familiaritzar-te amb el llenguatge. Aquest
+article tracta principalment la sintaxi de l'HTML i alguns consells útils.
+
+
+```html
+<!-- Els comentaris s'escriuen com aquesta línia! -->
+
+<!--
+ Els comentaris
+ poden
+ ocupar
+ múltiples
+ línies!
+-->
+
+<!-- #################### Les etiquetes #################### -->
+
+<!-- Aquí hi ha un exemple de fitxer HTML que analitzarem. -->
+
+
+<!doctype html>
+ <html>
+ <head>
+ <title>El meu lloc web</title>
+ </head>
+ <body>
+ <h1>Hola, món!</h1>
+ <a href="http://codepen.io/anon/pen/xwjLbZ">
+ Fes una ullada a com es veu això.
+ </a>
+ <p>Això és un paràgraf.</p>
+ <p>Això és un altre paràgraf.</p>
+ <ul>
+ <li>Això és un element d'una llista no enumerada (llista de punts).</li>
+ <li>Això és un altre element.</li>
+ <li>I aquest és l'últim element de la llista.</li>
+ </ul>
+ </body>
+ </html>
+
+<!--
+ Un fitxer HTML sempre comença indicant al navegador que la pàgina és HTML.
+-->
+<!doctype html>
+
+<!-- Després d'això, es comença obrint l'etiqueta <html>. -->
+<html>
+
+<!-- Aquesta etiqueta s'ha de tancar al final del fitxer amb </html>. -->
+</html>
+
+<!-- No s'ha d'escriure res més després d'aquesta etiqueta final. -->
+
+<!-- Entremig (entre les etiquetes d'obertura i tancament <html></html>), trobem: -->
+
+<!-- Una capçalera definida per <head> (que s'ha de tancar emprant </head>). -->
+<!--
+ La capçalera conté descripcions i informació addicional que no es mostra,
+ això són les metadades.
+-->
+
+<head>
+ <!--
+ L'etiqueta <title> indica al navegador el títol que s'ha de visualitzar
+ a la finestra del buscador, a la barra del títol, i al nom de la pestanya.
+ -->
+ <title>El meu lloc web</title>
+</head>
+
+<!-- Després de la secció <head>, trobem l'etiqueta <body> -->
+<!-- Fins a aquest punt, res del que s'ha fet apareixerà a la finestra del navegador. -->
+<!-- Hem d'emplenar el cos amb el contingut per visualitzar. -->
+
+<body>
+ <!-- L'etiqueta h1 crea el títol. -->
+ <h1>Hola, món!</h1>
+ <!--
+ També es poden fer subtítols per <h1>, que van des del més important <h2>
+ fins al més precís <h6>.
+ -->
+
+ <!-- També es poden crear enllaços fent servir l'atribut href="" -->
+ <a href="http://codepen.io/anon/pen/xwjLbZ">
+ Fes una ullada a com es veu això.
+ </a>
+
+ <!-- L'etiqueta <p> permet incloure text a una pàgina HTML. -->
+ <p>Això és un paràgraf.</p>
+ <p>Això és un altre paràgraf.</p>
+
+ <!-- L'etiqueta <ul> crea una llista de punts. -->
+ <!--
+ Per tenir una llista enumerada s'hauria de fer servir <ol>, en comptes d'<ul>.
+ El primer element seria 1, el segon element 2, etc.
+ -->
+ <ul>
+ <li>Això és un element d'una llista no enumerada (llista de punts).</li>
+ <li>Això és un altre element.</li>
+ <li>I aquest és l'últim element de la llista.</li>
+ </ul>
+</body>
+
+<!-- I això és tot, crear un fitxer HTML pot ser molt simple. -->
+
+<!-- Però és possible afegir molts altres tipus d'etiquetes HTML addicionals. -->
+
+<!-- L'etiqueta <img /> es fa servir per afegir imatges. -->
+<!--
+ L'origen de la imatge s'indica fent servir l'atribut src=""
+ L'origen pot ser una adreça URL o la ruta a un arxiu del teu ordinador.
+-->
+<img src="http://i.imgur.com/XWG0O.gif"/>
+
+<!-- També es poden crear taules. -->
+
+<!-- L'etiqueta <table> obre la taula. -->
+<table>
+
+ <!-- <tr> permet crear files. -->
+ <tr>
+
+ <!-- <th> permet posar títol a la columna d'una taula. -->
+ <th>Primera capçalera</th>
+ <th>Segona capçalera</th>
+ </tr>
+
+ <tr>
+
+ <!-- <td> permet crear cel·les d'una taula. -->
+ <td>Primera fila, primera columna</td>
+ <td>Primera fila, segona columna</td>
+ </tr>
+
+ <tr>
+ <td>Segona fila, primera columna</td>
+ <td>Segona fila, segona columna</td>
+ </tr>
+</table>
+
+```
+
+## Ús
+
+Els arxius HTML acaben amb les extensions `.html` o `.htm`. El tipus MIME és `text/html`.
+
+**HTML NO és un llenguatge de programació**
+
+## Per aprendre'n més
+
+* [Viquipèdia](https://ca.wikipedia.org/wiki/Hyper_Text_Markup_Language)
+* [Tutorial HTML](https://developer.mozilla.org/ca/docs/Web/HTML)
+* [W3School](http://www.w3schools.com/html/html_intro.asp)
diff --git a/chapel.html.markdown b/chapel.html.markdown
index 354cd832..7e8fc41a 100644
--- a/chapel.html.markdown
+++ b/chapel.html.markdown
@@ -708,7 +708,7 @@ class MyClass {
// We also get the compiler-generated initializer, with one argument per field.
// Note that soon there will be no compiler-generated initializer when we
// define any initializer(s) explicitly.
- proc MyClass(val : real) {
+ proc init(val : real) {
this.memberInt = ceil(val): int;
}
diff --git a/clojure.html.markdown b/clojure.html.markdown
index c94625d6..16771e25 100644
--- a/clojure.html.markdown
+++ b/clojure.html.markdown
@@ -416,3 +416,6 @@ Clojuredocs.org has documentation with examples for most core functions:
Clojure-doc.org (yes, really) has a number of getting started articles:
[http://clojure-doc.org/](http://clojure-doc.org/)
+
+Clojure for the Brave and True has a great introduction to Clojure and a free online version:
+[https://www.braveclojure.com/clojure-for-the-brave-and-true/](https://www.braveclojure.com/clojure-for-the-brave-and-true/)
diff --git a/common-lisp.html.markdown b/common-lisp.html.markdown
index b12e50ca..1f2bb366 100644
--- a/common-lisp.html.markdown
+++ b/common-lisp.html.markdown
@@ -69,7 +69,7 @@ t ; another atom, denoting true
;;; is a good starting point. Third party libraries can be easily installed with
;;; Quicklisp
-;;; CL is usually developed with a text editor and a Real Eval Print
+;;; CL is usually developed with a text editor and a Read Eval Print
;;; Loop (REPL) running at the same time. The REPL allows for interactive
;;; exploration of the program while it is running "live".
diff --git a/coq.html.markdown b/coq.html.markdown
new file mode 100644
index 00000000..4c1ad690
--- /dev/null
+++ b/coq.html.markdown
@@ -0,0 +1,510 @@
+---
+language: Coq
+filename: learncoq.v
+contributors:
+ - ["Philip Zucker", "http://www.philipzucker.com/"]
+---
+
+The Coq system is a proof assistant. It is designed to build and verify mathematical proofs. The Coq system contains the functional programming language Gallina and is capable of proving properties about programs written in this language.
+
+Coq is a dependently typed language. This means that the types of the language may depend on the values of variables. In this respect, it is similar to other related languages such as Agda, Idris, F*, Lean, and others. Via the Curry-Howard correspondence, programs, properties and proofs are formalized in the same language.
+
+Coq is developed in OCaml and shares some syntactic and conceptual similarity with it. Coq is a language containing many fascinating but difficult topics. This tutorial will focus on the programming aspects of Coq, rather than the proving. It may be helpful, but not necessary to learn some OCaml first, especially if you are unfamiliar with functional programming. This tutorial is based upon its OCaml equivalent
+
+The standard usage model of Coq is to write it with interactive tool assistance, which operates like a high powered REPL. Two common such editors are the CoqIDE and Proof General Emacs mode.
+
+Inside Proof General `Ctrl+C Ctrl+<Enter>` will evaluate up to your cursor.
+
+
+```coq
+(*** Comments ***)
+
+(* Comments are enclosed in (* and *). It's fine to nest comments. *)
+
+(* There are no single-line comments. *)
+
+(*** 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. *)
+
+Definition x := 10.
+
+(* 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. *)
+
+Compute (1 + 1). (* 2 : nat *) (* Compute a result. *)
+
+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 *)
+
+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 "+".
+
+(* 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. *)
+
+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.*)
+
+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 *)
+
+(* ...unless the argument is an expression. *)
+Compute factorial (5-1). (* 24 : nat *)
+
+(* You can define mutually recursive functions using "with" *)
+Fixpoint is_even (n : nat) : bool := match n with
+ | 0 => true
+ | (S n) => is_odd n
+end with
+ is_odd n := match n with
+ | 0 => false
+ | (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. *)
+
+(* Anonymous functions use the following syntax: *)
+
+Definition my_square : nat -> nat := fun x => x * x.
+
+Definition my_id (A : Type) (x : A) : A := x.
+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.
+
+(* 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 @ *)
+
+Compute @my_id3 nat 3.
+
+(* Or give arguments by name *)
+Compute my_id3 (A:=nat) 3.
+
+(* Coq has the ability to extract code to OCaml, Haskell, and Scheme *)
+Require Extraction.
+Extraction Language OCaml.
+Extraction "factorial.ml" factorial.
+(* The above produces a file factorial.ml and factorial.mli that holds:
+
+type nat =
+| O
+| S of nat
+
+(** val add : nat -> nat -> nat **)
+
+let rec add n m =
+ match n with
+ | O -> m
+ | S p -> S (add p m)
+
+(** val mul : nat -> nat -> nat **)
+
+let rec mul n m =
+ match n with
+ | O -> O
+ | S p -> add m (mul p m)
+
+(** val factorial : nat -> nat **)
+
+let rec factorial n = match n with
+| O -> S O
+| S n' -> mul n (factorial n')
+*)
+
+
+(*** Notation ***)
+
+(* 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. *)
+
+(* Imports the Zarith module holding definitions related to the integers Z *)
+
+Require Import ZArith.
+
+(* Notation scopes can be opened *)
+Open Scope Z_scope.
+
+(* Now numerals and addition are defined on the integers. *)
+Compute 1 + 7. (* 8 : Z *)
+
+(* Integer equality checking *)
+Compute 1 =? 2. (* false : bool *)
+
+(* Locate is useful for finding the origin and definition of notations *)
+Locate "_ =? _". (* Z.eqb x y : Z_scope *)
+Close Scope Z_scope.
+
+(* We're back to nat being the default interpretation of "+" *)
+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. *)
+
+(* You can print the contents of scopes *)
+Print Scope nat_scope.
+(*
+Scope nat_scope
+Delimiting key is nat
+Bound to classes nat Nat.t
+"x 'mod' y" := Nat.modulo x y
+"x ^ y" := Nat.pow x y
+"x ?= y" := Nat.compare x y
+"x >= y" := ge x y
+"x > y" := gt x y
+"x =? y" := Nat.eqb x y
+"x <? y" := Nat.ltb x y
+"x <=? y" := Nat.leb x y
+"x <= y <= z" := and (le x y) (le y z)
+"x <= y < z" := and (le x y) (lt y z)
+"n <= m" := le n m
+"x < y <= z" := and (lt x y) (le y z)
+"x < y < z" := and (lt x y) (lt y z)
+"x < y" := lt x y
+"x / y" := Nat.div x y
+"x - y" := Init.Nat.sub x y
+"x + y" := Init.Nat.add x y
+"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. *)
+
+Require Import QArith.
+
+Open Scope Q_scope.
+Compute 1. (* 1 : Q *)
+
+(* 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 *)
+Close Scope Q_scope.
+
+Compute ( (2 # 3) / (1 # 5) )%Q. (* 10 # 3 : Q *)
+
+
+(*** Common data structures ***)
+
+(* Many common data types are included in the standard library *)
+
+(* The unit type has exactly one value, tt *)
+Check tt. (* tt : unit *)
+
+(* The option type is useful for expressing computations that might fail *)
+Compute None. (* None : option ?A *)
+Check Some 3. (* Some 3 : option nat *)
+
+(* The type sum A B allows for values of either type A or type B *)
+Print sum.
+Check inl 3. (* inl 3 : nat + ?B *)
+Check inr true. (* inr true : ?A + bool *)
+Check sum bool nat. (* (bool + nat)%type : Set *)
+Check (bool + nat)%type. (* Notation for sum *)
+
+(* Tuples are (optionally) enclosed in parentheses, items are separated
+ by commas. *)
+Check (1, true). (* (1, true) : nat * bool *)
+Compute prod nat bool. (* (nat * bool)%type : Set *)
+
+Definition my_fst {A B : Type} (x : A * B) : A := match x with
+ | (a,b) => a
+ end.
+
+(* A destructuring let is available if a pattern match is irrefutable *)
+Definition my_fst2 {A B : Type} (x : A * B) : A := let (a,b) := x in
+ a.
+
+(*** Lists ***)
+
+(* 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.
+
+(* There is also list notation available in the ListNotations modules *)
+Require Import List.
+Import ListNotations.
+Compute [1 ; 2 ; 3]. (* [1; 2; 3] : list nat *)
+
+
+(* There is a large number of list manipulation functions available,
+ including:
+
+• length
+• 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
+• fold_left : iterator (from head to tail)
+• 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.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 *)
+
+(*** Strings ***)
+
+Require Import Strings.String.
+
+(* Use double quotes for string literals. *)
+Compute "hi"%string.
+
+Open Scope string_scope.
+
+(* Strings can be concatenated with the "++" operator. *)
+Compute String.append "Hello " "World". (* "Hello World" : string *)
+Compute "Hello " ++ "World". (* "Hello World" : string *)
+
+(* Strings can be compared for equality *)
+Compute String.eqb "Coq is fun!" "Coq is fun!". (* true : bool *)
+Compute "no" =? "way". (* false : bool *)
+
+Close Scope string_scope.
+
+(*** Other Modules ***)
+
+(* Other Modules in the standard library that may be of interest:
+
+• Logic : Classical logic and dependent equality
+• Arith : Basic Peano arithmetic
+• 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)
+• 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
+ (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,...)
+• Relations : Relations (definitions and basic results)
+• Sorting : Sorted list (basic definitions and heapsort correctness)
+• Strings : 8-bits characters and strings
+• Wellfounded : Well-founded relations (basic results)
+ *)
+
+(*** User-defined data types ***)
+
+(* 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 *)
+
+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. *)
+
+(* Type constructors don't need to be empty. *)
+Inductive my_number := plus_infinity
+ | nat_value : nat -> my_number.
+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 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 *)
+
+(* 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.
+
+Compute NatList 1 EmptyList. (* NatList 1 EmptyList : my_nat_list *)
+
+(** Matching type constructors **)
+
+Inductive animal := Dog : string -> animal | Cat : string -> animal.
+
+Definition say x :=
+ match x with
+ | Dog x => (x ++ " says woof")%string
+ | Cat x => (x ++ " says meow")%string
+ end.
+
+Compute say (Cat "Fluffy"). (* "Fluffy says meow". *)
+
+(** Traversing data structures with pattern matching **)
+
+(* Recursive types can be traversed with pattern matching easily.
+ Let's see how we can traverse a data structure of the built-in list type.
+ Even though the built-in cons ("::") looks like an infix operator,
+ it's actually a type constructor and can be matched like any other. *)
+Fixpoint sum_list l :=
+ match l with
+ | [] => 0
+ | head :: tail => head + (sum_list tail)
+ end.
+
+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. *)
+
+(* 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.
+
+(* 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. *)
+
+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 *)
+
+Fixpoint sumn (n : nat) : nat :=
+ match n with
+ | 0 => 0
+ | (S n') => n + (sumn n')
+ end.
+
+Theorem sum_formula : forall n, 2 * (sumn n) = (n + 1) * n.
+Proof. intros n. induction n.
+ - reflexivity. (* 0 = 0 base case *)
+ - 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.
+
+## Further reading
+
+* [The Coq reference manual](https://coq.inria.fr/refman/)
+* [Software Foundations](https://softwarefoundations.cis.upenn.edu/)
+* [Certified Programming with Dependent Types](http://adam.chlipala.net/cpdt/)
+* [Mathematical Components](https://math-comp.github.io/mcb/)
+* [Coq'Art: The Calculus of Inductive Constructions](http://www.cse.chalmers.se/research/group/logic/TypesSS05/resources/coq/CoqArt/)
+* [FRAP](http://adam.chlipala.net/frap/)
diff --git a/cs-cz/python3.html.markdown b/cs-cz/python3.html.markdown
index 2cbf52e6..bd3690a8 100644
--- a/cs-cz/python3.html.markdown
+++ b/cs-cz/python3.html.markdown
@@ -137,12 +137,14 @@ None # => None
"něco" is None # => False
None is None # => True
-# None, 0, a prázdný řetězec/seznam/slovník se vyhodnotí jako False
+# None, 0, a prázdný řetězec/seznam/N-tice/slovník/množina se vyhodnotí jako False
# Vše ostatní se vyhodnotí jako True
-bool(0) # => False
-bool("") # => False
-bool([]) # => False
-bool({}) # => False
+bool(0) # => False
+bool("") # => False
+bool([]) # => False
+bool(tuple()) # => False
+bool({}) # => False
+bool(set()) # => False
####################################################
@@ -602,18 +604,21 @@ dir(math)
# Generátory jsou funkce, které místo return obsahují yield
def nasobicka_2(sekvence):
for i in sekvence:
+ print("Zpracovávám číslo {}".format(i))
yield 2 * i
# Generátor generuje hodnoty postupně, jak jsou potřeba. Místo toho, aby vrátil
# celou sekvenci s prvky vynásobenými dvěma, provádí jeden výpočet v každé iteraci.
-# To znamená, že čísla větší než 15 se v metodě nasobicka_2 vůbec nezpracují.
+for nasobek in nasobicka_2([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]):
+ # Vypíše postupně: "Zpracovávám číslo 1", ..., "Zpracovávám číslo 5"
+ if nasobek >= 10:
+ break
# Funkce range() je také generátor - vytváření seznamu 900000000 prvků by zabralo
# hodně času i paměti, proto se místo toho čísla generují postupně.
-
-for i in nasobicka_2(range(900000000)):
- print(i) # Vypíše čísla 0, 2, 4, 6, 8, ... 30
- if i >= 30:
+for nasobek in nasobicka_2(range(900000000)):
+ # Vypíše postupně: "Zpracovávám číslo 1", ..., "Zpracovávám číslo 5"
+ if nasobek >= 10:
break
@@ -633,7 +638,7 @@ def nekolikrat(puvodni_funkce):
def pozdrav(jmeno):
print("Měj se {}!".format(jmeno))
-pozdrav("Pepo") # Vypíše 3x: Měj se Pepo!
+pozdrav("Pepo") # Vypíše 3x: "Měj se Pepo!"
```
## Co dál?
diff --git a/csharp.html.markdown b/csharp.html.markdown
index f27adf18..0643f033 100644
--- a/csharp.html.markdown
+++ b/csharp.html.markdown
@@ -14,20 +14,22 @@ filename: LearnCSharp.cs
C# is an elegant and type-safe object-oriented language that enables developers to build a variety of secure and robust applications that run on the .NET Framework.
-[Read more here.](http://msdn.microsoft.com/en-us/library/vstudio/z1zx9t92.aspx)
+[Read more here.](https://docs.microsoft.com/dotnet/csharp/getting-started/introduction-to-the-csharp-language-and-the-net-framework)
```c#
// Single-line comments start with //
+
/*
Multi-line comments look like this
*/
+
/// <summary>
/// This is an XML documentation comment which can be used to generate external
/// documentation or provide context help within an IDE
/// </summary>
/// <param name="firstParam">This is some parameter documentation for firstParam</param>
/// <returns>Information on the returned value of a function</returns>
-//public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {}
+public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {}
// Specify the namespaces this source code will be using
// The namespaces below are all part of the standard .NET Framework Class Library
@@ -254,7 +256,7 @@ on a new line! ""Wow!"", the masses cried";
int fooWhile = 0;
while (fooWhile < 100)
{
- //Iterated 100 times, fooWhile 0->99
+ // Iterated 100 times, fooWhile 0->99
fooWhile++;
}
@@ -273,10 +275,10 @@ on a new line! ""Wow!"", the masses cried";
} while (fooDoWhile < 100);
- //for loop structure => for(<start_statement>; <conditional>; <step>)
+ // for loop structure => for(<start_statement>; <conditional>; <step>)
for (int fooFor = 0; fooFor < 10; fooFor++)
{
- //Iterated 10 times, fooFor 0->9
+ // Iterated 10 times, fooFor 0->9
}
// For Each Loop
@@ -287,7 +289,7 @@ on a new line! ""Wow!"", the masses cried";
// (The ToCharArray() could be removed, because a string also implements IEnumerable)
foreach (char character in "Hello World".ToCharArray())
{
- //Iterated over all the characters in the string
+ // Iterated over all the characters in the string
}
// Switch Case
@@ -329,7 +331,7 @@ on a new line! ""Wow!"", the masses cried";
// Convert String To Integer
// this will throw a FormatException on failure
- int.Parse("123");//returns an integer version of "123"
+ int.Parse("123"); // returns an integer version of "123"
// try parse will default to type default on failure
// in this case: 0
@@ -344,7 +346,7 @@ on a new line! ""Wow!"", the masses cried";
tryInt.ToString();
// Casting
- // Cast decimal 15 to a int
+ // Cast decimal 15 to an int
// and then implicitly cast to long
long x = (int) 15M;
}
@@ -373,7 +375,7 @@ on a new line! ""Wow!"", the masses cried";
Console.Read();
} // End main method
- // CONSOLE ENTRY A console application must have a main method as an entry point
+ // CONSOLE ENTRY - A console application must have a main method as an entry point
public static void Main(string[] args)
{
OtherInterestingFeatures();
@@ -404,7 +406,7 @@ on a new line! ""Wow!"", the masses cried";
ref int maxCount, // Pass by reference
out int count)
{
- //the argument passed in as 'count' will hold the value of 15 outside of this function
+ // the argument passed in as 'count' will hold the value of 15 outside of this function
count = 15; // out param must be assigned before control leaves the method
}
@@ -552,7 +554,7 @@ on a new line! ""Wow!"", the masses cried";
}
// PARALLEL FRAMEWORK
- // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx
+ // https://devblogs.microsoft.com/csharpfaq/parallel-programming-in-net-framework-4-getting-started/
var words = new List<string> {"dog", "cat", "horse", "pony"};
@@ -564,11 +566,11 @@ on a new line! ""Wow!"", the masses cried";
}
);
- //Running this will produce different outputs
- //since each thread finishes at different times.
- //Some example outputs are:
- //cat dog horse pony
- //dog horse pony cat
+ // Running this will produce different outputs
+ // since each thread finishes at different times.
+ // Some example outputs are:
+ // cat dog horse pony
+ // dog horse pony cat
// DYNAMIC OBJECTS (great for working with other languages)
dynamic student = new ExpandoObject();
@@ -725,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).
@@ -865,7 +867,7 @@ on a new line! ""Wow!"", the masses cried";
}
}
- //Method to display the attribute values of this Object.
+ // Method to display the attribute values of this Object.
public virtual string Info()
{
return "Gear: " + Gear +
@@ -960,7 +962,7 @@ on a new line! ""Wow!"", the masses cried";
/// <summary>
/// Used to connect to DB for LinqToSql example.
/// EntityFramework Code First is awesome (similar to Ruby's ActiveRecord, but bidirectional)
- /// http://msdn.microsoft.com/en-us/data/jj193542.aspx
+ /// https://docs.microsoft.com/ef/ef6/modeling/code-first/workflows/new-database
/// </summary>
public class BikeRepository : DbContext
{
@@ -1069,7 +1071,7 @@ on a new line! ""Wow!"", the masses cried";
{
private static bool LogException(Exception ex)
{
- /* log exception somewhere */
+ // log exception somewhere
return false;
}
@@ -1089,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
@@ -1117,12 +1119,12 @@ on a new line! ""Wow!"", the masses cried";
[Obsolete("Use NewMethod instead", false)]
public static void ObsoleteMethod()
{
- /* obsolete code */
+ // obsolete code
}
public static void NewMethod()
{
- /* new code */
+ // new code
}
public static void Main()
@@ -1154,9 +1156,9 @@ namespace Learning.More.CSharp
}
}
-//New C# 7 Feature
-//Install Microsoft.Net.Compilers Latest from Nuget
-//Install System.ValueTuple Latest from Nuget
+// New C# 7 Feature
+// Install Microsoft.Net.Compilers Latest from Nuget
+// Install System.ValueTuple Latest from Nuget
using System;
namespace Csharp7
{
@@ -1213,7 +1215,7 @@ namespace Csharp7
Console.WriteLine(tt.GetLastName());
}
}
-
+
// PATTERN MATCHING
class PatternMatchingTest
{
@@ -1310,13 +1312,13 @@ namespace Csharp7
## Further Reading
+ * [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](http://www.dotnetperls.com)
* [C# in Depth](http://manning.com/skeet2)
- * [Programming C#](http://shop.oreilly.com/product/0636920024064.do)
- * [LINQ](http://shop.oreilly.com/product/9780596519254.do)
- * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx)
- * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials)
- * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials)
- * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials)
+ * [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)
- * [C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx)
+ * [freeCodeCamp - C# Tutorial for Beginners](https://www.youtube.com/watch?v=GhQdlIFylQ8)
+ \ No newline at end of file
diff --git a/css.html.markdown b/css.html.markdown
index 64dc097c..b8adc886 100644
--- a/css.html.markdown
+++ b/css.html.markdown
@@ -164,14 +164,14 @@ selector {
max-width: 5in; /* inches */
/* Colors */
- color: #F6E; /* short hex format */
- color: #FF66EE; /* long hex format */
- color: tomato; /* a named color */
- color: rgb(255, 255, 255); /* as rgb values */
- color: rgb(10%, 20%, 50%); /* as rgb percentages */
- color: rgba(255, 0, 0, 0.3); /* as rgba values (CSS 3) Note: 0 <= a <= 1 */
- color: transparent; /* equivalent to setting the alpha to 0 */
- color: hsl(0, 100%, 50%); /* as hsl percentages (CSS 3) */
+ color: #F6E; /* short hex format */
+ color: #FF66EE; /* long hex format */
+ color: tomato; /* a named color */
+ color: rgb(255, 255, 255); /* as rgb values */
+ color: rgb(10%, 20%, 50%); /* as rgb percentages */
+ color: rgba(255, 0, 0, 0.3); /* as rgba values (CSS 3) Note: 0 <= a <= 1 */
+ color: transparent; /* equivalent to setting the alpha to 0 */
+ color: hsl(0, 100%, 50%); /* as hsl percentages (CSS 3) */
color: hsla(0, 100%, 50%, 0.3); /* as hsl percentages with alpha */
/* Borders */
@@ -179,7 +179,7 @@ selector {
border-style:solid;
border-color:red; /* similar to how background-color is set */
border: 5px solid red; /* this is a short hand approach for the same */
- border-radius:20px; /* this is a CSS3 property */
+ border-radius:20px; /* this is a CSS3 property */
/* Images as backgrounds of elements */
background-image: url(/img-path/img.jpg); /* quotes inside url() optional */
@@ -317,6 +317,7 @@ a new feature.
* [Dabblet](http://dabblet.com/) (CSS playground)
* [Mozilla Developer Network's CSS documentation](https://developer.mozilla.org/en-US/docs/Web/CSS) (Tutorials and reference)
* [Codrops' CSS Reference](http://tympanus.net/codrops/css_reference/) (Reference)
+* [DevTips' CSS Basics](https://www.youtube.com/playlist?list=PLqGj3iMvMa4IOmy04kDxh_hqODMqoeeCy) (Tutorials)
## Further Reading
diff --git a/cypher.html.markdown b/cypher.html.markdown
index acd44733..32868354 100644
--- a/cypher.html.markdown
+++ b/cypher.html.markdown
@@ -50,7 +50,7 @@ Relationships (or Edges)
**Connects two nodes**
`[:KNOWS]`
-It's a *relationship* with the *label* **KNOWS**. It's a *label* as the node's label. It begins with uppercase and use UPPER_SNAKE_CASE.
+It's a *relationship* with the *label* **KNOWS**. It's a *label* as the node's label. It begins with uppercase and use UPPER\_SNAKE\_CASE.
`[k:KNOWS]`
The same *relationship*, referred by the variable **k**, reusable in the query, but it's not necessary.
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 07f755f7..d3c231bd 100644
--- a/dart.html.markdown
+++ b/dart.html.markdown
@@ -29,6 +29,7 @@ example1() {
nested2() => print("Example1 nested 1 nested 2");
nested2();
}
+
nested1();
}
@@ -37,6 +38,7 @@ example2() {
nested1(fn) {
fn();
}
+
nested1(() => print("Example2 nested 1"));
}
@@ -47,9 +49,12 @@ example3() {
planA(fn(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));
}
@@ -60,17 +65,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.
@@ -86,6 +94,7 @@ class Example6Class {
print(instanceVariable);
}
}
+
example6() {
new Example6Class().sayIt();
}
@@ -96,10 +105,12 @@ class Example7Class {
static sayItFromClass() {
print(classVariable);
}
+
sayItFromInstance() {
print(classVariable);
}
}
+
example7() {
Example7Class.sayItFromClass();
new Example7Class().sayItFromInstance();
@@ -111,7 +122,7 @@ example7() {
// by default. But arrays and maps are not. They can be made constant by
// declaring them "const".
var example8Array = const ["Example8 const array"],
- example8Map = const {"someKey": "Example8 const map"};
+ example8Map = const {"someKey": "Example8 const map"};
example8() {
print(example8Array[0]);
print(example8Map["someKey"]);
@@ -172,6 +183,7 @@ example13() {
print("Example13 regexp doesn't match '${s}'");
}
}
+
match(s1);
match(s2);
}
@@ -190,7 +202,7 @@ example14() {
}
// dynamic typed null can be convert to bool
- var b;// b is dynamic type
+ var b; // b is dynamic type
b = "abc";
try {
if (b) {
@@ -240,9 +252,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()}'");
}
@@ -302,11 +316,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");
@@ -320,7 +336,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}'");
@@ -334,19 +352,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}'");
}
@@ -362,12 +382,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}'");
}
@@ -379,10 +400,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 {}.
@@ -394,17 +416,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.
@@ -416,6 +440,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}'");
@@ -434,6 +459,7 @@ class Example28 extends IterableBase {
}
get iterator => names.iterator;
}
+
example28() {
var o = new Example28();
o.forEach((name) => print("Example28 '${name}'"));
@@ -459,10 +485,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) {
@@ -477,8 +505,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}");
@@ -488,10 +520,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) {
@@ -503,6 +536,44 @@ example30() {
}
}
+// Optional Positional Parameter:
+// parameter will be disclosed with square bracket [ ] & square bracketed parameter are optional.
+example31() {
+ findVolume31(int length, int breath, [int height]) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume31(10,20,30); //valid
+ findVolume31(10,20); //also valid
+}
+
+// Optional Named Parameter:
+// parameter will be disclosed with curly bracket { }
+// curly bracketed parameter are optional.
+// have to use parameter name to assign a value which separated with colan :
+// in curly bracketed parameter order does not matter
+// these type parameter help us to avoid confusion while passing value for a function which has many parameter.
+example32() {
+ findVolume32(int length, int breath, {int height}) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume32(10,20,height:30);//valid & we can see the parameter name is mentioned here.
+ findVolume32(10,20);//also valid
+}
+
+// Optional Default Parameter:
+// same like optional named parameter in addition we can assign default value for this parameter.
+// which means no value is passed this default value will be taken.
+example33() {
+ findVolume33(int length, int breath, {int height=10}) {
+ print('length = $length, breath = $breath, height = $height');
+ }
+
+ findVolume33(10,20,height:30);//valid
+ findVolume33(10,20);//valid
+}
+
// Programs have only one entry point in the main function.
// Nothing is expected to be executed on the outer scope before a program
// starts running with what's in its main function.
@@ -510,12 +581,15 @@ example30() {
// 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
- ].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());
}
```
@@ -526,6 +600,3 @@ Dart has a comprehensive web-site. It covers API reference, tutorials, articles
useful Try Dart online.
[https://www.dartlang.org](https://www.dartlang.org)
[https://try.dartlang.org](https://try.dartlang.org)
-
-
-
diff --git a/de-de/asciidoc-de.html.markdown b/de-de/asciidoc-de.html.markdown
index 24100e0b..e3f64a00 100644
--- a/de-de/asciidoc-de.html.markdown
+++ b/de-de/asciidoc-de.html.markdown
@@ -88,7 +88,7 @@ Abteilungstitel
Listen
-Um eine Aufzählung zu erstellen verwendest du Sternchen.
+Um eine Aufzählung zu erstellen, verwendest du Sternchen.
```
* foo
@@ -96,7 +96,7 @@ Um eine Aufzählung zu erstellen verwendest du Sternchen.
* baz
```
-Um eine nummerierte Liste zu erstellen verwendest du Punkte.
+Um eine nummerierte Liste zu erstellen, verwendest du Punkte.
```
. item 1
@@ -104,7 +104,7 @@ Um eine nummerierte Liste zu erstellen verwendest du Punkte.
. item 3
```
-Um Listen zu verschachteln musst du zusätzliche Sternchen beziehungsweise Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
+Um Listen zu verschachteln, musst du zusätzliche Sternchen beziehungsweise Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
```
* foo 1
diff --git a/de-de/bash-de.html.markdown b/de-de/bash-de.html.markdown
index 7a0db157..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:
@@ -217,7 +217,7 @@ done
function foo ()
{
echo "Argumente funktionieren wie bei skripts: $@"
- echo Und: $1 $2..."
+ echo "Und: $1 $2..."
echo "Dies ist eine Funktion"
return 0
}
diff --git a/de-de/c++-de.html.markdown b/de-de/c++-de.html.markdown
new file mode 100644
index 00000000..87e75ad6
--- /dev/null
+++ b/de-de/c++-de.html.markdown
@@ -0,0 +1,1158 @@
+---
+language: c++
+filename: learncpp-de.cpp
+contributors:
+ - ["Steven Basart", "http://github.com/xksteven"]
+ - ["Matt Kline", "https://github.com/mrkline"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+ - ["Connor Waters", "http://github.com/connorwaters"]
+ - ["Ankush Goyal", "http://github.com/ankushg07"]
+ - ["Jatin Dhankhar", "https://github.com/jatindhankhar"]
+ - ["Maximilian Sonnenburg", "https://github.com/LamdaLamdaLamda"]
+ - ["caminsha", "https://github.com/caminsha"]
+lang: de-de
+---
+
+C++ ist eine Systemprogrammiersprache die,
+
+[laut dem Begründer Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)
+entworfen wurde um,
+
+- "besseres C" zu sein
+- Datenabstraktion zu unterstützen
+- Objektorientierung zu unterstützen
+- generische Programmierung zu unterstützen
+
+Durch seine Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein.
+
+Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welcher direkt vom Prozessor ausgeführt
+werden kann und somit eine strikte Kontrolle über die Hardware bietet und gleichzeitig
+High-Level-Features wie generics, exceptions und Klassen enthält.
+
+Diese Kombination aus Geschwindigkeit und Funktionalität bildet C++ und ist eine der
+weitverbreitesten Programmiersprachen.
+
+```c++
+//////////////////
+// Vergleich zu C
+//////////////////
+
+// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich die
+// Syntax für Variablen Deklarationen, primitiven Typen und Funktionen.
+
+// Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und
+// einen Integer als Rückgabetyp besitzt.
+
+// Dieser Wert fungiert als Beendigungsstatus des Programms.
+// Siehe: https://de.wikipedia.org/wiki/Return_Code für weitere Informationen
+int main(int argc, char** argv)
+{
+ // Kommandozeilen Argumente werden genauso wie in C über argc und argv übergeben
+ // argc entspricht der Anzahl von Argumenten und argv ist ein Array von C-style
+ // strings (char*), welche die Argumente repräsentieren.
+ // Das erste Argument ist der Name des Programms, welches aufgerufen wird.
+ // Argc und argv können, wenn nicht benötigt, weg gelassen werden, indem
+ // die Funktionssignatur "int main()" verwendet wird.
+
+ // Ein Rückgabewert von 0 repräsentiert die erfolgreiche Ausführung.
+ return 0;
+}
+
+// C++ unterscheidet sich in einigen Punkten von C:
+
+// In C++ sind Zeichen-Literale char´s
+sizeof('c') == sizeof(char) == 1
+
+// In C sind Zeichen-Literale int´s
+sizeof('c') == sizeof(int)
+
+// C++ verwendet striktes prototyping
+void func(); // Funktion ohne Argumente
+
+// In C
+void func(); // Funktion mit beliebiger Anzahl von Argumenten
+
+// Verwende nullptr, anstatt von NULL!!!
+int* ip = nullptr;
+
+// C standard header sind in C++ verfügbar.
+// C header enden mit .h, während
+// C++ header das Präfix "c" besitzen und kein ".h" Suffix verwenden.
+
+// Die C++ Standard Version:
+#include <cstdio>
+
+// Die C Standard Version:
+#include <stdio.h>
+
+int main()
+{
+ printf("Hello, world!\n");
+ return 0;
+}
+
+///////////////////////
+// Funktionsüberladung
+///////////////////////
+
+// C++ unterstützt Funktionsüberladung
+// Jede Funktion kann unterschiedliche Parameter erhalten.
+void print(char const* myString)
+{
+ printf("String %s\n", myString);
+}
+
+void print(int myInt)
+{
+ printf("My int is %d", myInt);
+}
+
+int main()
+{
+ print("Hello"); // Wird aufgelöst zu "void print(const char*)"
+ print(15); // Wird aufgelöst zu "void print(int)"
+}
+
+/////////////////////////////
+// Standard Funktionsargumente
+/////////////////////////////
+
+// Argumente können per Standard für eine Funktion gesetzt werden,
+// wenn diese beim Aufruf nicht bereitgestellt werden.
+void doSomethingWithInts(int a = 1, int b = 4)
+{
+ // führe Anweisungen mit "int´s" aus.
+}
+
+int main()
+{
+ doSomethingWithInts(); // a = 1, b = 4
+ doSomethingWithInts(20); // a = 20, b = 4
+ doSomethingWithInts(20, 5); // a = 20, b = 5
+}
+
+// Standard-Argumente müssen am Ende der Liste der Argumente stehen.
+void invalidDeclaration(int a = 1, int b) // Fehler!
+{
+}
+
+
+/////////////
+// Namespaces (Namensräume)
+/////////////
+
+// Namespaces stellen einen getrennten Gültigkeitsbereich für Variablen,
+// Funktionen und andere Deklarationen zur Verfügung.
+// Namespaces können geschachtelt werden.
+namespace First
+{
+ namespace Nested
+ {
+ void foo()
+ {
+ printf("This is First::Nested::foo\n");
+ }
+ } // Ende des Namespace "Nested"
+} // Ende des Namespace "First"
+
+namespace Second
+{
+ void foo()
+ {
+ printf("This is Second::foo\n");
+ }
+}
+
+void foo()
+{
+ printf("This is global foo\n");
+}
+
+int main()
+{
+ // Fügt alle Symbole aus dem namespace Second in den aktuellen Gültigkeitsbereich (scope).
+ // "foo()" wird nun nicht länger funktionieren, da es nun doppeldeutig ist, ob foo aus
+ // dem namespace foo oder darüberliegenden aufgerufen wird.
+ using namespace Second;
+
+ Second::foo(); // Gibt "This is Second::foo" aus.
+ First::Nested::foo(); // Gibt "This is First::Nested::foo" aus.
+ ::foo(); // Gibt "This is global foo" aus.
+}
+
+///////////////
+// Eingabe/Ausgabe
+///////////////
+
+// C++ verwendet für die Eingabe und Ausgabe streams.
+// cin, cout und cerr repräsentieren stdin, stdout und stderr.
+// << ist der Einfügeoperator und >> ist der Extraktionsoperator.
+
+#include <iostream> // Include für Eingabe/Ausgabe (I/O) streams
+
+using namespace std; // Streams befinden sich im std namespace (standard library)
+
+int main()
+{
+ int myInt;
+
+ // Ausgabe auf stdout (oder Terminal/Bildschirm)
+ cout << "Enter your favorite number:\n";
+
+ // Empfängt Eingabe
+ cin >> myInt;
+
+ // cout kann ebenfalls formatiert werden
+ cout << "Your favorite number is " << myInt << "\n";
+ // Gibt "Your favorite number is <myInt>" aus
+
+ cerr << "Used for error messages";
+}
+
+//////////
+// Zeichenketten (Strings)
+//////////
+
+// Strings in C++ sind Objekte und haben diverse member-functions
+#include <string>
+
+using namespace std; // Strings sind ebenfalls im namespace std (Standard Bibliothek)
+
+string myString = "Hello";
+string myOtherString = " World";
+
+// + wird für das Anhängen von strings verwendet.
+cout << myString + myOtherString; // "Hello World"
+
+cout << myString + " You"; // "Hello You"
+
+// C++ strings sind mutable.
+myString.append(" Dog");
+cout << myString; // "Hello Dog"
+
+
+/////////////
+// Referenzen
+/////////////
+
+// Zusätzlich zu Pointern, wie jene in C.
+// C++ besitzt _Referenzen_.
+// Diese sind Pointer-Typen, welche nicht erneut zugewiesen werden können
+// und nicht Null sein können.
+// Sie besitzen den selben Syntax wie Variablen.
+// Für die Dereferenzierung ist kein * notwendig und
+// & (die Adresse) wird nicht für die Zuweisung verwendet.
+
+using namespace std;
+
+string foo = "I am foo";
+string bar = "I am bar";
+
+
+string& fooRef = foo; // Erzeugt eine Referenz auf foo.
+fooRef += ". Hi!"; // Verändert foo durch die Referenz
+cout << fooRef; // Gibt "I am foo. Hi!" aus.
+
+
+// Weist "fooRef" nicht erneut zu. Dies ist dasselbe, wie "foo = bar" und
+// foo == "I am bar"
+// nach dieser Zeile
+cout << &fooRef << endl; // Gibt die Adresse von foo aus
+fooRef = bar;
+cout << &fooRef << endl; // Gibt ebenfalls die Adresse von foo aus
+cout << fooRef; // Gibt "I am bar" aus
+
+// Die Adresse von fooRef verbleibt die selbe, sie verweist immer noch auf foo
+
+const string& barRef = bar; // Erzeugt konstante Referenz auf bar.
+// Wie in C, können konstante Werte ( und Pointer bzw. Referenzen) nicht verändert werden.
+
+barRef += ". Hi!"; // Fehler: konstante Referenzen können nicht verändert werden.
+
+// Hinweis: bevor wir genauer Referenzen besprechen, schauen wir uns zuerst ein Konzept an,
+// welches als "temporäres Objekt" bezeichnet wird. Gehen wir von folgenden Code aus:
+string tempObjectFun() { ... }
+string retVal = tempObjectFun();
+
+// Was passiert nun in der zweiten Zeile:
+// - ein String Objekt wird von "tempObjectFun" zurückgegeben
+// - ein neuer String wird mit dem zurückgegebenen Objekt als Argument für den Konstruktor erzeugt.
+// - das zurückgegebene Objekt wird zerstört
+// Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
+// wann immer eine Funktion ein Objekt zurückgibt. Zerstört werden diese am Ende der Auswertung des Ausdrucks
+// (dies schreibt der Standard vor, aber Compiler sind berechtigt dieses Verhalten zu ändern. Siehe "return value optimization"
+// für Details). Wie in diesem Code:
+foo(bar(tempObjectFun()))
+
+// Nehmen wir an, foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben,
+// wird an bar übergeben und ist zerstört bevor foo aufgerufen wird.
+
+// Zurück zu Referenzen. Die Annahme, dass die "am Ende des Ausdrucks" Regel gültig ist,
+// wenn das temporäre Objekt an eine konstante Referenz gebunden ist, ist der Fall, wenn die Lebensdauer
+// auf den aktuellen Gültigkeitsbereich erweitert wird.
+
+void constReferenceTempObjectFun() {
+ // constRef erhält das temporäre Objekt und ist gültig bis ans Ende der Funktion
+ const string& constRef = tempObjectFun();
+ ...
+}
+
+// Eine andere Art von Referenzen wurde in C++11 eingeführt und ist speziell für
+// temporäre Objekte. Es ist nicht möglich Variablen des Typs zu besitzen, aber
+// Vorrechte bei der Auflösung zu besitzen.
+
+void someFun(string& s) { ... } // Reguläre Referenz
+void someFun(string&& s) { ... } // Referenz auf ein temporäres Objekt
+
+string foo;
+someFun(foo); // Ruft die Funktion mit der regulären Referenz auf
+someFun(tempObjectFun()); // Ruft die Funktion mit der temporären Referenz auf
+
+// Zum Beispiel existieren diese zwei Varianten von Konstruktoren für
+// std::basic_string:
+basic_string(const basic_string& other);
+basic_string(basic_string&& other);
+
+// Nehmen wir an, wir erzeugen einen neuen String eines temporären Objekts (welches später
+// zerstört wird), hierbei existiert ein effizienterer Konstruktor. Dieses Konzept wird
+// als "move semantics" bezeichnet (bewegen eines Objekts in ein anderes in C++).
+
+/////////////////////
+// Enumerations (Aufzählungstypen)
+/////////////////////
+
+// Enums sind eine einfachere Art und Weise einen Wert einer Konstante zu zuweisen.
+// Häufig wird dies verwendet, um den Code lesbarer zu gestalten bzw. zu visualisieren.
+enum ECarTypes
+{
+ Sedan,
+ Hatchback,
+ SUV,
+ Wagon
+};
+
+ECarTypes GetPreferredCarType()
+{
+ return ECarTypes::Hatchback;
+}
+
+// Mit C++11 existiert eine einfache Möglichkeit einem Typ dem Enum zuzuweisen. Dies
+// kann durchaus sinnvoll bei der Serialisierung von Daten sein, oder bei der Konvertierung
+// zwischen Typen bzw. Konstanten.
+enum ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Serialisierung von "InputValue" in eine Datei
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Das enum wird implizit zu einem "uint8_t" konvertiert. Bedingt dadurch, dass
+ // es sich um ein "enum" handelt.
+ WriteByteToFile(InputCarType);
+}
+
+// Nicht immer ist es gewünscht, dass enum´s zu einem Integer oder zu einem anderen
+// enum umgewandelt werden. Daher ist es möglich eine enum-Klasse zu erzeugen, welche
+// nicht implizit umgewandelt wird.
+enum class ECarTypes : uint8_t
+{
+ Sedan, // 0
+ Hatchback, // 1
+ SUV = 254, // 254
+ Hybrid // 255
+};
+
+void WriteByteToFile(uint8_t InputValue)
+{
+ // Serialisierung von InputValue in eine Datei
+}
+
+void WritePreferredCarTypeToFile(ECarTypes InputCarType)
+{
+ // Wird nicht kompilieren, da "ECarTypes" ein "uint8_t" ist, da das enum
+ // als "enum class" deklariert wurde!
+ WriteByteToFile(InputCarType);
+}
+
+//////////////////////////////////////////
+// Klassen und objekorientierte Programmierung
+//////////////////////////////////////////
+
+// Erstes Beispiel einer Klasse
+#include <iostream>
+
+// Deklaration einer Klasse.
+// Klassen werden üblicherweise im header (.h oder .hpp) deklariert.
+class Dog
+{
+ // Member Variablen und Funktionen sind private per default (standard).
+ std::string name;
+ int weight;
+
+// Alle nachfolgenden member sind "public" bis
+// "private:" oder "protected:" auftritt.
+public:
+
+ // Standard Konstruktor
+ Dog();
+
+ // Member-Funktionsdeklaration (Implementierung folgt).
+ // Bemerkung: std::string statt der Verwendung von namespace std;
+ // "using namespace" sollte niemals in einem header verwendet werden.
+ void setName(const std::string& dogsName);
+
+ void setWeight(int dogsWeight);
+
+ // Funktionen, die Objekte nicht ändern, sollten mit const deklariert werden.
+ // Funktionen müssen explizit als "virtual" deklariert werden, um in einer
+ // abgeleiteten Klassen überschrieben zu werden.
+ // Aus performance Gründen sind Funktionen nicht per default virtual.
+ virtual void print() const;
+
+ // Funktionen können ebenfalls im class body definiert werden.
+ // Derart definierte Funktionen sind automatisch "inline".
+ void bark() const { std::cout << name << " barks!\n"; }
+
+ // Neben Konstruktoren, bietet C++ Destruktoren.
+ // Diese werden aufgerufen, wenn ein Objekt freigegeben wird oder
+ // seinen Wertebereich verlässt.
+ // Dies ermöglicht mächtige Paradigmen, wie auch RAII.
+ // Destruktoren sollten virtual sein, wenn eine Klasse von ihr
+ // abgeleitet wird. Ist dieser nicht virtual, dann wird der
+ // Destruktor der abgeleiteten Klasse nicht aufgerufen, insofern
+ // das Objekt durch eine Referenz/Pointer der Basisklasse entfernt wird.
+ virtual ~Dog();
+
+}; // Ein Semikolon schließt die Definition der Klasse ab.
+
+// Klassen-Member-Funktionen sind üblicherweise in der .cpp Datei implementiert.
+Dog::Dog()
+{
+ std::cout << "A dog has been constructed\n";
+}
+
+// Objekte sollten als Referenz übergeben werden und wenn diese nicht
+// verändert werden sollen, sollte das Objekt als const Referenz übergeben werden.
+void Dog::setName(const std::string& dogsName)
+{
+ name = dogsName;
+}
+
+void Dog::setWeight(int dogsWeight)
+{
+ weight = dogsWeight;
+}
+
+// "Virtual" wird nur bei der Deklaration benötigt und nicht bei der Definition.
+void Dog::print() const
+{
+ std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";
+}
+
+Dog::~Dog()
+{
+ std::cout << "Goodbye " << name << "\n";
+}
+
+int main()
+{
+ Dog myDog; // Ausgabe: "A dog has been constructed"
+ myDog.setName("Barkley");
+ myDog.setWeight(10);
+ myDog.print(); // Ausgabe: "Dog is Barkley and weighs 10 kg"
+ return 0;
+} // Ausgabe: "Goodbye Barkley"
+
+// Diese Klasse erbt alles was public bzw. protected ist von der Dog-Klasse
+// und darüber hinaus auch private Methoden/Attribute, jedoch kann auf diese
+// nicht direkt zugegriffen werden. Lediglich über public/procted getter/setter.
+class OwnedDog : public Dog {
+
+public:
+ void setOwner(const std::string& dogsOwner);
+
+ // Überschreibt das Verhalten der "print" Funktion für alle "OwnedDogs".
+ // Siehe: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping
+ // für eine grundlegende Einführung in "Subtype Polymorphismus".
+ // Das "override" Schlüsselwort ist optional, aber stellt sicher, dass die
+ // Methode der Basisklasse tatsächlich überschrieben wurde.
+ void print() const override;
+
+private:
+ std::string owner;
+};
+
+// Die zugehörige .cpp Datei
+void OwnedDog::setOwner(const std::string& dogsOwner)
+{
+ owner = dogsOwner;
+}
+
+void OwnedDog::print() const
+{
+ Dog::print(); // Ruft die "print" Funktion der Basisklasse auf.
+ std::cout << "Dog is owned by " << owner << "\n";
+ // Ausgaben: "Dog is <name> and weights <weight>"
+ // "Dog is owned by <owner>"
+}
+
+//////////////////////////////////////////
+// Initialisierung und Operatorüberladung
+//////////////////////////////////////////
+
+// In C++ können Operatoren wie: +, -, *, / etc. überladen werden.
+// Dies wird umgesetzt, indem eine entsprechende Funktion definiert wird,
+// welche immer dann aufgerufen wird, sobald der Operator verwendet wird.
+#include <iostream>
+using namespace std;
+
+class Point
+{
+public:
+ // Member Variablen können mit einem default Wert initialisiert werden.
+ double x = 0;
+ double y = 0;
+
+ // Definition des Standard Konstruktor, welcher nichts tut
+ // außer den Punkt auf den default Wert (0,0) zu setzen.
+ Point() { };
+
+ // Die nachfolgende Syntax ist bekannt als "initialization list"
+ // und ist eine gängige Art Klassen-Member zu initialisieren.
+ Point (double a, double b) :
+ x(a),
+ y(b)
+ { /* Außschließliche Initialisierung der Werte */ }
+
+ // Überladung des "+" Operator.
+ Point operator+(const Point& rhs) const;
+
+ // Überladung des "+=" Operator
+ Point& operator+=(const Point& rhs);
+
+ // Sinnhaft wäre es an dieser Stelle den "-" und "-=" Operator
+ // ebenfalls zu überladen.
+};
+
+Point Point::operator+(const Point& rhs) const
+{
+ // Erzeugung eines neuen Punkts, welcher die Summe aus sich
+ // selbst und "rhs" bildet
+ return Point(x + rhs.x, y + rhs.y);
+}
+
+Point& Point::operator+=(const Point& rhs)
+{
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+}
+
+int main ()
+{
+ Point up (0,1);
+ Point right (1,0);
+
+ // Ruft den + Operator mit den entsprechenden Parametern auf.
+ Point result = up + right;
+ // Ausgabe: "Result is upright (1,1)"
+ cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
+ return 0;
+}
+
+/////////////////////
+// Templates
+/////////////////////
+
+// Templates in C++ werden in erster Linie dafür verwendet generisch zu programmieren.
+// Sie unterstützen explizite und partielle Spezialisierung und darüber hinaus können
+// sie für funktionale Klassen verwendet werden.
+// Tatsächlich bilden Templates die Turing-Vollständigkeit
+// (universelle Programmierbarkeit) ab.
+
+
+// Zu Beginn ein einführendes Beispiel der generischen Programmierung.
+// Die Definition einer Klasse bzw. Funktion, welche mit dem Typ T parametriert wird.
+template<class T>
+class Box
+{
+public:
+ // T repräsentiert an dieser Stelle einen beliebigen Typen.
+ void insert(const T&) { ... }
+};
+
+// Während der Kompilierung generiert der Compiler Kopien für jedes Template, wobei
+// hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte
+// Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template
+// komplett im header definiert.
+
+// Erzeugung einer Template-Klasse auf dem Stack:
+Box<int> intBox;
+
+// eine der zu erwartenden Verwendungen:
+intBox.insert(123);
+
+// Verschachtelungen von Templates sind möglich.
+Box<Box<int> > boxOfBox;
+boxOfBox.insert(intBox);
+
+// Bis C++11 war es erforderlich ein Leerzeichen zwischen '>' einzufügen,
+// andernfalls wurde es als '>>' geparsed (right shift).
+
+// Manchmal ist folgende Notation anzutreffen:
+// template<typename T>
+// Das 'class' Schlüsselwort und das 'typename' Schlüsselwort
+// sind fast identisch hinsichtlich der Funktionalität. Weitere
+// Informationen auf: http://en.wikipedia.org/wiki/Typename
+
+// Eine Template-Funktion:
+template<class T>
+void barkThreeTimes(const T& input)
+{
+ input.bark();
+ input.bark();
+ input.bark();
+}
+
+// Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters
+// definiert wurde. Der Compiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen
+// prüfen. Somit funktioniert die zuvor definierte Funktion für jeden Typ 'T', die die
+// const Methode 'bark' implementiert hat.
+
+Dog fluffy;
+fluffy.setName("Fluffy")
+barkThreeTimes(fluffy); // Gibt "Fluffy barks" dreimal aus.
+
+// Template Parameter müssen keine Klassen sein.
+template<int Y>
+void printMessage()
+{
+ cout << "Learn C++ in " << Y << " minutes!" << endl;
+}
+
+// Des Weiteren können Templates aus Effizienzgründen genauer spezifiziert werden.
+// Selbstverständlich sind reale Probleme, welche genauer spezifiziert werden, nicht
+// derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die
+// Funktion oder Klasse als Template deklariert werden.
+template<>
+void printMessage<10>()
+{
+ cout << "Learn C++ faster in only 10 minutes!" << endl;
+}
+
+printMessage<20>(); // Gibt "Learn C++ in 20 minutes!" aus.
+printMessage<10>(); // Gibt "Learn C++ faster in only 10 minutes!" aus.
+
+
+/////////////////////
+// Ausnahme Behandlungen (Exception-Handling)
+/////////////////////
+
+// Die Standard Bibliothek bietet einige exceptions.
+// Siehe: http://en.cppreference.com/w/cpp/error/exception.
+// Grundsätzlich können alle Typen als exception geworfen werden.
+#include <exception>
+#include <stdexcept>
+
+// Alle exceptions, die in dem "try" Block geworfen werden, können mittels
+// "catch" abgefangen werden.
+try
+{
+ // exceptions sollten nicht auf dem heap mithilfe
+ // von "new" allokiert werden.
+ throw std::runtime_error("A problem occurred");
+}
+
+// Exceptions sollten als const Referenz abgefangen werden
+// insofern diese Objekte sind.
+catch (const std::exception& ex)
+{
+ std::cout << ex.what();
+}
+
+// Abfangen aller Exceptions, welche zuvor nicht abgefangen wurden.
+catch (...)
+{
+ std::cout << "Unknown exception caught";
+ throw; // Erneutes werfen der exception
+}
+
+///////
+// RAII
+///////
+
+// RAII steht für "Resource Acquisition Is Initialization".
+// Oft wird dies als eines der wichtigsten Paradigmen in C++ betrachtet.
+// RAII beschreibt das Konzept, dass der Konstruktor für ein Objekt
+// die Ressourcen akquiriert und der Destruktor diese freigibt.
+
+// Zum Verständnis, warum dies sinnvoll ist, nachfolgend
+// ein einführendes Beispiel:
+void doSomethingWithAFile(const char* filename)
+{
+ // Wir nehmen an, dass nichts schiefgehen wird.
+ FILE* fh = fopen(filename, "r"); // Öffnen der Datei im read-mode.
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+ fclose(fh); // Schließen des file-handle.
+}
+
+// Unglücklicherweise ist die Fehlerbehandlung äußerst kompliziert.
+// Sollte fopen fehlschlagen und "doSomethingWithTheFile" bzw.
+// "doSomethingElseWithIt", geben diese einen Fehlercode zurück.
+// (Exceptions sind eine bevorzugte Möglichkeit Fehler abzufangen
+// , allerdings bei einigen Programmierern, besonders solchen die einen C
+// background besitzen, ein unbeliebtes Mittel zur Fehlerbehandlung).
+// Nun müssen wir jeden Aufruf auf mögliche auftretende Fehler überprüfen.
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
+ if (fh == nullptr) // Der Pointer ist bei einem Fehler NULL .
+ return false; // Benachrichtigt den Aufrufer über den Fehler.
+
+ // Wir nehmen an, dass jede Funktion false zurückgibt, in einem Fehlerfall
+ if (!doSomethingWithTheFile(fh))
+ {
+ fclose(fh); // File handle schließen.
+ return false; // Fehler "melden".
+ }
+
+ if (!doSomethingElseWithIt(fh))
+ {
+ fclose(fh); // File handle schließen.
+ return false; // Fehler "melden".
+ }
+
+ fclose(fh); // File handle schließen.
+ return true; // Erfolg "melden".
+}
+
+// C-Programmierer handhaben dies häufig durch goto-Anweisungen:
+bool doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r");
+ if (fh == nullptr)
+ return false;
+
+ if (!doSomethingWithTheFile(fh))
+ goto failure;
+
+ if (!doSomethingElseWithIt(fh))
+ goto failure;
+
+ fclose(fh); // File handle schließen.
+ return true; // Erfolg "melden".
+
+failure:
+ fclose(fh);
+ return false; // Fehler "melden".
+}
+
+// Insofern Funktionen Fehler durch exceptions indizieren,
+// ist dies "sauberer", aber immer noch suboptimal.
+void doSomethingWithAFile(const char* filename)
+{
+ FILE* fh = fopen(filename, "r"); // Öffnet die Datei im read-mode
+ if (fh == nullptr)
+ throw std::runtime_error("Could not open the file.");
+
+ try
+ {
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+ }
+ catch (...)
+ {
+ // Im Fehlerfall sollte sichergestellt sein, dass die
+ // Datei geschlossen wird.
+ fclose(fh);
+ throw; // Erneutes werfen der exception
+ }
+
+ fclose(fh); // Schließen der Datei
+}
+
+// Folgendes ist mit der C++ file stream Klasse (fstream) zu vergleichen.
+// fstream verwendet den Destruktor, um die Datei zu schließen.
+// Der obige Destruktor wird automatisch aufgerufen, sobald das Objekt
+// den Gültigkeitsbereich verlässt.
+void doSomethingWithAFile(const std::string& filename)
+{
+ // ifstream entspricht der Kurzform von "input file stream".
+ std::ifstream fh(filename); // Öffnen der Datei
+
+ doSomethingWithTheFile(fh);
+ doSomethingElseWithIt(fh);
+
+} // Die Datei wird automatisch vom Destruktor geschlossen.
+
+// Diese Vorgehensweise bietet massive Vorteile:
+// 1. Egal was passiert, die Ressource (das Datei-Handle) wird aufgelöst,
+// insofern der Destruktor korrekt beschrieben wurde. Es ist möglich
+// zu vergessen das Datei-Handle zu schließen, was zu einem "leak" der
+// entsprechenden Ressource führt.
+// 2. Der Code selbst ist wesentlich "sauberer".
+// Der Destruktor wird das Datei-Handle im Hintergrund schließen und der
+// Programmierer muss sich darum keinerlei Sorgen machen.
+// 3. Der Code ist "exception sicher".
+// Egal wo die exception geworfen wird, das Aufräumen wird definitiv vollzogen.
+
+// Der gesamte idiomatische C++ Code verwendet RAII für alle Ressourcen.
+// Weitere Beispiele:
+// - Speicher verwenden "unique_ptr" und "shared_ptr".
+// - Container - verkettete Listen (linked list), vector (selbst organisierende
+// Arrays), hash maps, etc., entfernen deren Inhalt, wenn diese außerhalb des
+// Gültigkeitsbereichs laufen.
+// - Mutex´s verwenden lock_guard und unique_lock.
+
+/////////////////////
+// Container
+/////////////////////
+
+// Die Container der Standard template Bibliothek beinhaltet einige vordefinierte Templates.
+// Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen
+// für den Zugriff und die Manipulation bereit.
+
+// Beispielhafte Container:
+
+// Vector (dynamisches array)
+// Erlaubt das Definieren von Arrays oder Listen zur Laufzeit
+#include <vector>
+string val;
+vector<string> my_vector; // Initialisierung des Vectors.
+cin >> val;
+my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu.
+my_vector.push_back(val); // Fügt den Wert "val" zum Vektor "my_vector" hinzu (nun zwei Elemente).
+
+// Für die Iteration über Vektoren stehen zwei Methodiken zu Verfügung:
+// Entweder die klassische Iteration über den Index:
+for (int i = 0; i < my_vector.size(); i++)
+{
+ cout << my_vector[i] << endl; // Zugriff auf die Elemente des Vektors über den [] Operator
+}
+
+// Oder die Verwendung von Iteratoren:
+vector<string>::iterator it; // Initialisierng des Iterators.
+for (it = my_vector.begin(); it != my_vector.end(); ++it)
+{
+ cout << *it << endl;
+}
+
+// Set (Mengen)
+// Sets sind Container, welche einzigartige Elemente beinhalten die einer
+// spezifischen Ordnung folgen.
+
+#include<set>
+set<int> ST; // Initialisierung des Sets mit einem Integer Datentyp.
+ST.insert(30); // Einfügen des Werts 30 in das Set ST
+ST.insert(10); // Einfügen des Werts 10 in das Set ST
+ST.insert(20); // Einfügen des Werts 20 in das Set ST
+ST.insert(30); // Einfügen des Werts 30 in das Set ST
+// Folgende Elemente befinden sich nun in dem Set:
+// 10 20 30
+
+// Entfernen eines Elements:
+ST.erase(20);
+
+// Set ST: 10 30
+// Für das iterieren verwenden wir Iteratoren:
+set<int>::iterator it;
+
+for(it=ST.begin();it<ST.end();it++)
+{
+ cout << *it << endl;
+}
+
+// Ausgabe:
+// 10
+// 30
+
+// Zum leeren des gesamten Containers wird die Methode
+// Container._name.clear() verwendet.
+ST.clear();
+cout << ST.size(); // Ausgabe der Set-Größe
+
+// Ausgabe: 0
+
+// Bemerkung: für mehrdeutige Elemente werden multisets verwendet.
+// Für hash-Sets sollten unordered_set´s verwendet werden, da diese
+// wesentlich effizienter sind, allerdings keiner Ordnung folgen.
+// Verfügbar sind diese Features ab C++11.
+
+// Map
+// Maps speichern Elemente, welche einer Kombination aus "Key"
+// und "Value" folgen.
+
+#include<map>
+map<char, int> mymap; // Initialisierung der Map: char -> Key, int -> Value.
+
+mymap.insert(pair<char,int>('A',1)); // Einfügen des Werts "1" für den Key "A".
+
+mymap.insert(pair<char,int>('Z',26)); // Einfügen des Werts "26" für den Key "Z".
+
+// Das Iterieren über Maps:
+map<char,int>::iterator it;
+for (it=mymap.begin(); it!=mymap.end(); ++it)
+ std::cout << it->first << "->" << it->second << '\n';
+
+// Ausgabe:
+// A->1
+// Z->26
+
+// Für das Finden des dazugehörigen Value des Keys.
+it = mymap.find('Z');
+cout << it->second;
+
+// Ausabe: 26
+
+// Bemerkung: für "hash maps" sollten die "unordered_map´s" verwendet werden. Diese
+// sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab
+// C++11 verfügbar.
+
+// Container für nicht-primitive Datentypen benötigen Vergleichsfunktionen im Objekt selbst,
+// oder als Funktionspointer. Primitive Datentypen besitzen default-Vergleichsfunktionen.
+// Allerdings können diese überschrieben werden.
+class Foo
+{
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+
+struct compareFunction
+{
+ bool operator()(const Foo& a, const Foo& b) const
+ {
+ return a.j < b.j;
+ }
+};
+
+// Folgender Code ist nicht valide, könnte aber von einigen Compilern
+// als valide angesehen werden:
+// std::map<Foo, int> fooMap;
+std::map<Foo, int, compareFunction> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); // Wahr
+
+
+///////////////////////////////////////
+// Lambda Ausdrücke (C++11 und höher)
+///////////////////////////////////////
+
+// Lambdas sind eine gängige Methodik, um anonyme Funktionen an dem
+// Ort der Verwendung zu definieren. Darüber hinaus auch bei der
+// Verwendung von Funktionen als Argument einer Funktion.
+
+// Nehmen wir an, es soll ein Vektor von "pairs" (Paaren) mithilfe
+// des zweiten Werts des "pairs" sortiert werden.
+
+vector<pair<int, int> > tester;
+tester.push_back(make_pair(3, 6));
+tester.push_back(make_pair(1, 9));
+tester.push_back(make_pair(5, 0));
+
+// Übergabe des Lambda-Ausdrucks als drittes Argument für die nachfolgende Sortierfunktion.
+sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs)
+{
+ return lhs.second < rhs.second;
+});
+
+// Beachte die Syntax von Lambda-Ausdrücken.
+// Die [] im Lambda Ausdruck werden für die Variablen verwendet.
+// Diese so genannte "capture list" definiert, was außerhalb des Lambdas,
+// innerhalb der Funktion verfügbar sein soll und in welcher Form.
+// Dies kann folgendes sein:
+// 1. ein Wert [x]
+// 2. eine Referenz [&x]
+// 3. eine beliebige Variable, welche sich im Gültigkeitsbereich durch
+// die Referenz [&] befindet.
+// 4. wie bei 3. aber mithilfe des Werts [=]
+// Beispiel:
+
+vector<int> dog_ids;
+
+for(int i = 0; i < 3; i++)
+{
+ dog_ids.push_back(i);
+}
+
+int weight[3] = {30, 50, 10};
+
+// Nehmen wir an wir möchten die "dog_ids" gemäß des Gewichts des Hundes sortieren.
+// So sollten sich die "dog_ids" wie folgt verhalten: [2, 0, 1]
+
+// Hier werden Lambdas praktisch:
+sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs)
+{
+ return weight[lhs] < weight[rhs];
+});
+
+
+// Weiterführender Link über Lambda-Ausdrücke:
+// http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
+
+///////////////////////////////
+// Range For (C++11 und höher)
+///////////////////////////////
+
+// Range-For Schleifen können verwendet werden, um über Container zu iterieren.
+int arr[] = {1, 10, 3};
+
+for(int elem: arr)
+{
+ cout << elem << endl;
+}
+
+// Insofern "auto" verwendet wird, muss der Typ nicht weiter beachtet werden.
+for(auto elem: arr)
+{
+ // Anweisungen ...
+}
+
+/////////////////////
+// Weiteres:
+/////////////////////
+
+// Einige Aspekte von C++ sind für Neueinsteiger häufig überraschend (aber auch für
+// C++ Veteranen).
+// Der nachfolgende Abschnitt ist leider nicht vollständig:
+// C++ ist eine der Sprachen, bei der es ein Leichtes ist, sich selbst ins Bein zu schießen.
+
+// Private-Methoden können überschrieben werden
+class Foo
+{
+ virtual void bar();
+};
+
+class FooSub : public Foo
+{
+ virtual void bar(); // Überschreibt Foo::bar!
+};
+
+// 0 == false == NULL
+bool* pt = new bool;
+*pt = 0; // Setzt den Wert des Pointers 'pt' auf false.
+pt = 0; // Setzt 'pt' auf den "null-pointer". Keine Compiler-Warnung.
+
+// nullptr sollte dieses Problem nicht lösen:
+int* pt2 = new int;
+*pt2 = nullptr; // Kompiliert nicht.
+pt2 = nullptr; // Setzt pt2 auf null.
+
+// Eine Ausnahme bilden bool´s.
+// Dies erlaubt es "null-pointer" zu testen: if(!ptr)
+// Die Konsequenz ist jedoch, dass dem nullptr ein bool zugewiesen werden kann.
+*pt = nullptr; // Kompiliert auch, wenn '*pt' ein bool ist!
+
+// '=' != '=' != '='!
+// Ruft Foo::Foo(const Foo&) auf, oder den Kopierkonstruktor
+Foo f2;
+Foo f1 = f2;
+
+// Ruft Foo::Foo(const Foo&) auf, aber kopiert lediglich den "Foo" Teil von
+// "fooSub". Alle zusätzlichen Member werden verworfen. Diese eigenartige Verhalten
+// wird auch "object slicing" genannt.
+FooSub fooSub;
+Foo f1 = fooSub;
+
+// Ruft Foo::operator=(Foo&) oder eine andere Variante auf.
+Foo f1;
+f1 = f2;
+
+///////////////////////////////////////
+// Tuple (C++11 und höher)
+///////////////////////////////////////
+
+#include<tuple>
+
+// Konzeptionell sind Tupel alten Datenstrukturen sehr ähnlich, allerdings haben diese keine
+// bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen.
+
+// Erstellen des Tupels und das Einfügen eines Werts.
+auto first = make_tuple(10, 'A');
+const int maxN = 1e9;
+const int maxL = 15;
+auto second = make_tuple(maxN, maxL);
+
+// Ausgabe der Elemente des "first" Tuple.
+cout << get<0>(first) << " " << get<1>(first) << "\n"; // Ausgabe : 10 A
+
+// Ausgabe der Elemente des "second" Tuple.
+cout << get<0>(second) << " " << get<1>(second) << "\n"; // Ausgabe: 1000000000 15
+
+int first_int;
+char first_char;
+tie(first_int, first_char) = first;
+cout << first_int << " " << first_char << "\n"; // Ausgabe : 10 A
+
+// Tuple können auch wie folgt erzeugt werden:
+
+tuple<int, char, double> third(11, 'A', 3.14141);
+// tuple_size gibt die Anzahl der Elemente in einem Tuple zurück.
+// Als "constexpr".
+
+cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3
+
+// tuple_cat fügt die Elemente eines Tupels aneinander (in der selben Reihenfolge).
+
+auto concatenated_tuple = tuple_cat(first, second, third);
+// concatenated_tuple wird zu = (10, 'A', 1e9, 15, 11, 'A', 3.14141)
+
+cout << get<0>(concatenated_tuple) << "\n"; // Ausgabe: 10
+cout << get<3>(concatenated_tuple) << "\n"; // Ausgabe: 15
+cout << get<5>(concatenated_tuple) << "\n"; // Ausgabe: 'A'
+
+
+///////////////////////////////////
+// Logische- und Bitoperatoren
+//////////////////////////////////
+
+// Die meisten Operatoren in C++ entsprechen denen aus anderen Sprachen
+
+// Logische Operatoren.
+// C++ verwendet so genannte "Short-circuit" Evaluierung für Boolean-Ausdrücke.
+// Das zweite Argument wird ausgeführt bzw. evaluiert, wenn das erste Argument genügt,
+// um den Ausdruck zu bestimmen.
+
+true && false // Führt **logisches und** aus.
+true || false // Führt **logisches oder** aus.
+! true // Führt **logisches nicht** aus.
+
+// Anstelle von Symbolen können auch Schlüsselwörter verwendet werden.
+true and false // Führt **logisches und** aus.
+true or false // Führt **logisches oder** aus.
+not true // Führt **logisches nicht** aus.
+
+// Bitoperationen
+
+// **<<** Links-Shift
+// **>>** Rechts-Shift
+
+~4 // Führt bitweises nicht aus.
+4 | 3 // Führt bitweises oder aus.
+4 & 3 // Führt bitweises und aus.
+4 ^ 3 // Führt bitweises xor aus.
+
+// Gleichwertige Schlüsselwörter:
+compl 4 // Führt bitweises nicht aus.
+4 bitor 3 // Führt bitweises oder aus.
+4 bitand 3 // Führt bitweises und aus.
+4 xor 3 // Führt bitweises xor aus.
+
+
+```
+Weiterführende Literatur:
+
+* Aktuelle Sprachen-Referenz [CPP Reference](http://cppreference.com/w/cpp).
+* Zusätzliches: [CPlusPlus](http://cplusplus.com).
+* Grundlagen Tutorial: [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).
diff --git a/de-de/dhall-de.html.markdown b/de-de/dhall-de.html.markdown
new file mode 100644
index 00000000..385c88be
--- /dev/null
+++ b/de-de/dhall-de.html.markdown
@@ -0,0 +1,380 @@
+---
+language: Dhall
+contributors:
+ - ["Gabriel Gonzalez", "http://www.haskellforall.com/"]
+translators:
+ - ["Profpatsch", "http://profpatsch.de"]
+filename: learndhall-de.py
+lang: de-de
+---
+
+Dhall ist eine programmierbare Konfigurationssprache und bietet eine
+nicht-repetetive Alternative zu YAML.
+
+Man kann Dhall sehen als: JSON + Funktionen + Typen + Importsystem
+
+Obwohl Dhall programmierbar ist, ist die Sprache nicht
+turingvollständig. Viele von Dhalls Features benutzen diese
+Einschränkung, um stärkere Sicherheitsgarantien zu bieten und besseres
+Tooling zu ermöglichen.
+
+```haskell
+-- einzeiliger Kommentar
+
+{- mehrzeiliger Kommentar
+
+ Unicode funktioniert 🙂
+
+ Diese Datei ist eine valide Dhall-Expression und evaluiert zu einem
+ großen Record, welcher die Ergebnisse jedes Schritts beinhaltet.
+
+ Das Ergebnis kann angezeigt werden, indem man die Datei evaluiert:
+
+ $ dhall --file learndhall.dhall
+
+ {- Kommentare können verschachtelt sein -}
+-}
+
+let greeting = "Hallo, Welt!"
+
+let fruits = "🍋🍓🍍🍉🍌"
+
+let interpolation = "Ein paar leckere Früchte: ${fruits}"
+
+let multilineText {- Inline-Kommentare funktionieren ebenfalls -} =
+ ''
+ In Multiline-Text-Literals wird Whitespace am Anfang der Zeile
+ entfernt.
+
+ Das bedeutet Text kann frei eingerückt oder ausgerückt werden,
+ ohne dass sich der Inhalt des Strings ändert.
+
+ Relative Einrückungen bleiben erhalten.
+
+ Ansonsten wird das Text-Literal verbatim erhalten, ähnlich
+ zu “literal”-Multiline-Strings in YAML.
+ ''
+
+let bool = True
+
+-- Typannotationen für Bindings sind optional, aber hilfreich, also
+-- benutzen wir sie hier.
+let annotation : Bool = True
+
+let renderedBool : Text = if bool then "True" else "False"
+
+-- Natürliche Zahlen sind nicht-negativ und vorzeichenlos.
+let naturalNumber : Natural = 42
+
+-- Integer können negativ sein, brauchen aber ein explizites Vorzeichen.
+let positiveInteger : Integer = +1
+
+let negativeInteger : Integer = -12
+
+let pi : Double = 3.14159265359
+
+{- Identifier dürfen eine große Anzahl an verschiedenen Zeichen
+ beinhalten (wie z.B. Anführungszeichen oder Whitespace), wenn man
+ sie mit Backticks umschließt.
+-}
+let `Avogadro's Number` : Double = 6.0221409e+23
+
+let origin : { x : Double, y : Double } = { x = 0.0, y = 0.0 }
+
+let somePrimes : List Natural = [ 2, 3, 5, 7, 11 ]
+
+{- Ein Schema ist das gleiche wie ein Typ.
+
+ Typnamen beginnen konventionell mit einem Großbuchstaben, was
+ jedoch nicht erzwungen wird.
+-}
+let Profile : Type
+ = { person :
+ { name : Text
+ , age : Natural
+ }
+ , address :
+ { country : Text
+ , state : Text
+ , city : Text
+ }
+ }
+
+let bernd : Profile =
+ { person =
+ { name = "Bernd Lauert"
+ , age = 67
+ }
+ , address =
+ { country = "Deutschland"
+ , state = "Bayern"
+ , city = "Augsburg"
+ }
+ }
+
+let augsburg : Text = bernd.address.city
+
+{- Enum-Alternativen beginnen konventionell auch mit einem
+ Großbuchstaben. Das wird ebenfalls nicht erzwungen.
+-}
+let DNA : Type = < Adenine | Cytosine | Guanine | Thymine >
+
+let dnaSequence : List DNA = [ DNA.Thymine, DNA.Guanine, DNA.Guanine ]
+
+let compactDNASequence : List DNA =
+ let a = DNA.Adenine
+ let c = DNA.Cytosine
+ let g = DNA.Guanine
+ let t = DNA.Thymine
+ in [ c, t, t, a, t, c, g, g, c ]
+
+-- Enums werden transformiert, indem man einen Record mit einem Feld
+-- pro Alternative angibt.
+let theLetterG : Text =
+ merge
+ { Adenine = "A"
+ , Cytosine = "C"
+ , Guanine = "G"
+ , Thymine = "T"
+ }
+ DNA.Guanine
+
+let presentOptionalValue : Optional Natural = Some 1
+
+let absentOptionalValue : Optional Natural = None Natural
+
+let points : List { x : Double, y : Double } =
+ [ { x = 1.1, y = -4.2 }
+ , { x = 4.4, y = -3.0 }
+ , { x = 8.2, y = -5.5 }
+ ]
+
+{- `Natural -> List Natural` ist der Funktionstyp mit Eingabetyp
+ `Natural` und Ausgabetyp `List Natural`.
+
+ Alle Funktionen in Dhall sind Anonyme Funktionen (aka. „Lambdas“),
+ denen man optional einen Namen geben kann.
+
+ Die folgende Funktion beispielsweise ist äquivalent zu diesem
+ Python Code:
+
+ lambda n : [ n, n + 1 ]
+
+ ... und diesem Javascript Code:
+
+ function (n) { return [ n, n + 1 ]; }
+-}
+let exampleFunction : Natural -> List Natural =
+ \(n : Natural) -> [ n, n + 1 ]
+
+-- Dhall unterstützt auch Unicode-Syntax, aber dieses Tutorial nutzt
+-- die ASCII-Syntax.
+let unicodeFunction : Natural → List Natural =
+ λ(n : Natural) → [ n, n + 1 ]
+
+-- Funktionsargumente brauchen keine Klammern.
+let exampleFunctionApplication : List Natural =
+ exampleFunction 2
+
+let functionOfMultipleArguments : Natural -> Natural -> List Natural =
+ \(x : Natural) -> \(y : Natural) -> [ x, y ]
+
+let functionAppliedToMultipleArguments : List Natural =
+ functionOfMultipleArguments 2 3
+
+{- Wie `exampleFunction`, aber wir geben dem Eingabetypen
+ einen Namen, `n`.
+-}
+let namedArgumentType : forall (n : Natural) -> List Natural =
+ \(n : Natural) -> [ n, n + 1 ]
+
+{- Bekommt der Eingabetyp einen Namen, kann man ihn weiter hinten in
+ der gleichen Typdefinition wiederverwenden.
+
+ Das ermöglicht Funktionen, die mit mehr als einem Eingabetypen
+ arbeiten können (aka. „polymorphe“ Funktionen).
+-}
+let duplicate : forall (a : Type) -> a -> List a =
+ \(a : Type) -> \(x : a) -> [ x, x ]
+
+let duplicatedNumber : List Natural =
+ duplicate Natural 2
+
+let duplicatedBool : List Bool =
+ duplicate Bool False
+
+{- Die Sprache hat auch eine handvoll eingebauter polymorpher
+ Funktionen, wie zum Beispiel:
+
+ List/head : forall (a : Type) -> List a -> Optional a
+-}
+let firstPrime : Optional Natural = List/head Natural somePrimes
+
+let functionOfARecord : { x : Natural, y : Natural } -> List Natural =
+ \(args : { x : Natural, y : Natural }) -> [ args.x, args.y ]
+
+let functionAppliedToARecord : List Natural =
+ functionOfARecord { x = 2, y = 5 }
+
+{- Alle Typkonversionen sind explizit.
+
+ `Natural/show` ist eine eingebaute Funktion mit dem Typ:
+
+ Natural/show : Natural -> Text
+
+ ... welche `Natural`s in ihre `Text`-Repräsentation konvertiert.
+-}
+let typeConversion : Natural -> Text =
+ \(age : Natural) -> "Ich bin ${Natural/show age} Jahre alt!"
+
+-- Ein „Template“ ist einfach eine Funktion mit Ausgabetyp `Text`.
+let mitLicense : { year : Natural, copyrightHolder : Text } -> Text =
+ \(args : { year : Natural, copyrightHolder : Text }) ->
+''
+Copyright ${Natural/show args.year} ${args.copyrightHolder}
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+''
+
+-- Template-Instanziierung ist das gleiche wie Funktionsanwendung.
+let templatedLicense : Text =
+ mitLicense { year = 2019, copyrightHolder = "Jane Smith" }
+
+{- Expressions können via URL importiert werden.
+
+ Ähnlich wie in Bash kann man Code aus dem lokalen Dateisystem
+ importieren (wird nicht gezeigt).
+
+ Sicherheitsbewusste Nutzer können via URLs importierte Expressions
+ mit einem semantischen Integritätscheck versehen („pinnen“).
+ Für gepinnte Imports wird der Dhall-Interpreter jeden Versuch
+ vereiteln, auf der Remote-Seite die Expression zu manipulieren.
+ Jedoch werden Änderungen, die den Inhalt der importierten
+ Expression nicht verändern trotzdem akzeptiert.
+
+ Auf diese Weise gepinnte Expressions werden auch in einem
+ Content-Adressable Store lokal gecached (standardmäßig in
+ `~/.cache/dhall`).
+-}
+let Natural/sum : List Natural -> Natural =
+ https://prelude.dhall-lang.org/Natural/sum
+ sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037
+
+let twentyEight : Natural = Natural/sum somePrimes
+
+-- Ein „Paket“ ist einfach ein (möglicherweise verschachtelter)
+-- Record, den man importiert.
+let Prelude = https://prelude.dhall-lang.org/package.dhall
+
+let false : Bool = Prelude.Bool.not True
+
+-- Durch das Anhängen von `as Text` wird eine Datei verbatim
+-- importiert und nicht als Dhall-Code interpretiert.
+let sourceCode : Text = https://prelude.dhall-lang.org/Bool/not as Text
+
+-- Environment-Variablen können auch imortiert werden.
+let presentWorkingDirectory = env:PWD as Text
+
+-- Mit `?` kann man eine “Fallback-Expression” angeben, für den Fall
+-- dass ein Import fehlschlägt.
+let home : Optional Text = Some env:HOME ? None Text
+
+-- Fallback-Expressions können auch alternative Imports enthalten.
+let possiblyCustomPrelude =
+ env:DHALL_PRELUDE
+ ? https://prelude.dhall-lang.org/package.dhall
+
+{- Ein ausführliches Beispiel, welches mithilfe der
+ `generate`-Funktion eine Konfiguration für 10 Build-User generiert:
+
+ Prelude.List.generate
+ : Natural -> forall (a : Type) -> (Natural -> a) -> List a
+-}
+let buildUsers =
+ let makeUser = \(user : Text) ->
+ let home = "/home/${user}"
+ let privateKey = "${home}/.ssh/id_ed25519"
+ let publicKey = "${privateKey}.pub"
+ in { home = home
+ , privateKey = privateKey
+ , publicKey = publicKey
+ }
+
+ let buildUser =
+ \(index : Natural) -> makeUser "build${Natural/show index}"
+
+ let Config =
+ { home : Text
+ , privateKey : Text
+ , publicKey : Text
+ }
+
+ in Prelude.List.generate 10 Config buildUser
+
+-- Alle Ergebnisse in einem großen Record
+in { greeting = greeting
+ , fruits = fruits
+ , interpolation = interpolation
+ , multilineText = multilineText
+ , bool = bool
+ , annotation = annotation
+ , renderedBool = renderedBool
+ , naturalNumber = naturalNumber
+ , positiveInteger = positiveInteger
+ , negativeInteger = negativeInteger
+ , pi = pi
+ , `Avogadro's Number` = `Avogadro's Number`
+ , origin = origin
+ , somePrimes = somePrimes
+ , bernd = bernd
+ , augsburg = augsburg
+ , dnaSequence = dnaSequence
+ , compactDNASequence = compactDNASequence
+ , theLetterG = theLetterG
+ , presentOptionalValue = presentOptionalValue
+ , absentOptionalValue = absentOptionalValue
+ , points = points
+ , exampleFunction = exampleFunction
+ , unicodeFunction = unicodeFunction
+ , exampleFunctionApplication = exampleFunctionApplication
+ , functionOfMultipleArguments = functionOfMultipleArguments
+ , functionAppliedToMultipleArguments = functionAppliedToMultipleArguments
+ , namedArgumentType = namedArgumentType
+ , duplicate = duplicate
+ , duplicatedNumber = duplicatedNumber
+ , duplicatedBool = duplicatedBool
+ , firstPrime = firstPrime
+ , functionOfARecord = functionOfARecord
+ , functionAppliedToARecord = functionAppliedToARecord
+ , typeConversion = typeConversion
+ , mitLicense = mitLicense
+ , templatedLicense = templatedLicense
+ , twentyEight = twentyEight
+ , false = false
+ , sourceCode = sourceCode
+ , presentWorkingDirectory = presentWorkingDirectory
+ , home = home
+ , buildUsers = buildUsers
+ }
+```
+
+Mehr Infos und Lernmaterialien gibt es auf der offiziellen Website
+(Englisch), auf der man Dhall auf im Browser ausprobieren kann:
+
+* [https://dhall-lang.org](http://dhall-lang.org/)
diff --git a/de-de/git-de.html.markdown b/de-de/git-de.html.markdown
index 7c68d785..0896f513 100644
--- a/de-de/git-de.html.markdown
+++ b/de-de/git-de.html.markdown
@@ -49,7 +49,7 @@ Ein Repository besteht in Git aus dem .git-Verzeichnis und dem Arbeitsverzeichni
### .git-Verzeichnis (Teil des Repositorys)
-Das .git-Verzeichnis enthält alle Einstellung, Logs, Branches, den HEAD und mehr.
+Das .git-Verzeichnis enthält alle Einstellungen, Logs, Branches, den HEAD und mehr.
[Ausführliche Übersicht](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html)
### Arbeitsverzeichnis (Teil des Repositorys)
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/markdown-de.html.markdown b/de-de/markdown-de.html.markdown
index cccf5e68..729e883c 100644
--- a/de-de/markdown-de.html.markdown
+++ b/de-de/markdown-de.html.markdown
@@ -144,7 +144,7 @@ indem du eine Zeile mit vier Leerzeichen oder einem Tabulator einrückst -->
puts item
end
-<!-- Innerhalb normalen Texts kannst du Code mit Backticks ` auszeichnen -->
+<!-- Innerhalb normalen Texts kannst du Code mit Backticks \` auszeichnen -->
Hermann hatte nicht die leiseste Ahnung, was dieses `go_to()` bedeuten könnte!
diff --git a/de-de/nix-de.html.markdown b/de-de/nix-de.html.markdown
index 79b60d20..ea02e81d 100644
--- a/de-de/nix-de.html.markdown
+++ b/de-de/nix-de.html.markdown
@@ -8,11 +8,11 @@ translators:
lang: de-de
---
-Nix ist eine simple funktionale Programmiersprache, die für den
+Nix ist eine simple funktionale Programmiersprache, die für den
[Nix package manager](https://nixos.org/nix/) und
[NixOS](https://nixos.org/) entwickelt wurde.
-Du kannst Nix Ausdrücke evaluieren mithilfe von
+Du kannst Nix Ausdrücke evaluieren mithilfe von
[nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate)
oder [`nix-repl`](https://github.com/edolstra/nix-repl).
@@ -24,7 +24,7 @@ with builtins; [
# Inline Kommentare sehen so aus.
- /* Multizeilen Kommentare
+ /* Multizeilen Kommentare
sehen so aus. */
@@ -61,7 +61,7 @@ with builtins; [
"String Literale sind in Anführungszeichen."
"
- String Literale können mehrere
+ String Literale können mehrere
Zeilen umspannen.
"
@@ -95,7 +95,7 @@ with builtins; [
tutorials/learn.nix
#=> /the-base-path/tutorials/learn.nix
- # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine
+ # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine
# Datei im selben Verzeichnis benötigt ein ./ Präfix.
./learn.nix
#=> /the-base-path/learn.nix
@@ -238,7 +238,7 @@ with builtins; [
#=> { d = 2; e = 3; }
# Die Nachkommen eines Attributs können in diesem Feld nicht zugeordnet werden, wenn
- # das Attribut selbst nicht zugewiesen wurde.
+ # das Attribut selbst nicht zugewiesen wurde.
{
a = { b = 1; };
a.c = 2;
@@ -261,9 +261,9 @@ with builtins; [
#=> 7
# Die erste Linie diese Tutorials startet mit "with builtins;",
- # weil builtins ein Set mit allen eingebauten
+ # weil builtins ein Set mit allen eingebauten
# Funktionen (length, head, tail, filter, etc.) umfasst.
- # Das erspart uns beispielsweise "builtins.length" zu schreiben,
+ # Das erspart uns beispielsweise "builtins.length" zu schreiben,
# anstatt nur "length".
@@ -305,7 +305,7 @@ with builtins; [
(tryEval (abort "foo"))
#=> error: evaluation aborted with the following error message: ‘foo’
- # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst
+ # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst
# löst es eine abfangbare Exception aus.
(assert 1 < 2; 42)
#=> 42
@@ -319,7 +319,7 @@ with builtins; [
#=========================================
# Da die Wiederholbarkeit von Builds für den Nix Packetmanager entscheidend ist,
- # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar
+ # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar
# unreine Elemente.
# Du kannst auf Umgebungsvariablen verweisen.
(getEnv "HOME")
@@ -355,4 +355,4 @@ with builtins; [
(https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55)
* [Susan Potter - Nix Cookbook - Nix By Example]
- (http://funops.co/nix-cookbook/nix-by-example/)
+ (https://ops.functionalalgebra.com/nix-by-example/)
diff --git a/de-de/python-de.html.markdown b/de-de/python-de.html.markdown
index d3e0fc26..ee77683e 100644
--- a/de-de/python-de.html.markdown
+++ b/de-de/python-de.html.markdown
@@ -386,25 +386,73 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
+
+####################################################
+## 5. Module
+####################################################
+
+# Wir können Module importieren
+import math
+print math.sqrt(16) #=> 4.0
+
+# Wir können auch nur spezielle Funktionen eines Moduls importieren
+from math import ceil, floor
+print ceil(3.7) #=> 4.0
+print floor(3.7) #=> 3.0
+
+# Wir können auch alle Funktionen eines Moduls importieren
+# Warnung: Dies wird nicht empfohlen
+from math import *
+
+# Wir können Modulnamen abkürzen
+import math as m
+math.sqrt(16) == m.sqrt(16) #=> True
+
+# Module sind in Python nur gewöhnliche Dateien. Wir
+# können unsere eigenen schreiben und importieren. Der Name des
+# Moduls ist der Dateiname.
+
+# Wir können herausfinden, welche Funktionen und Attribute in einem
+# Modul definiert sind.
+import math
+dir(math)
+
+# Wenn Sie ein Python-Skript namens math.py im selben Ordner
+# wie Ihr aktuelles Skript haben, wird die Datei math.py
+# anstelle des integrierten Python-Moduls geladen.
+# Dies geschieht, weil der lokale Ordner Vorrang
+# vor den in Python integrierten Bibliotheken hat.
+
+
####################################################
-## 5. Klassen
+## 6. Klassen
####################################################
-# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten.
+# Wir verwenden das Schlüsselwort "class" um eine Klasse zu erzeugen.
class Human(object):
# Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt
species = "H. sapiens"
- # Ein simpler Konstruktor
+ # Ein simpler Konstruktor, wird aufgerufen, wenn diese Klasse instanziiert wird.
+ # Beachten Sie, dass die doppelten vorangestellten und nachgestellten
+ # Unterstriche Objekte oder Attribute bezeichnen, die von Python verwendet werden,
+ # aber in benutzergesteuerten Namespaces leben.
+ # Methoden (oder Objekte oder Attribute) wie: __init__, __str__, __repr__ usw.
+ # werden als Sondermethoden (oder manchmal als Dundermethoden bezeichnet) bezeichnet.
+ # Sie sollten solche Namen nicht selbst erfinden.
def __init__(self, name):
# Wir weisen das Argument name dem name-Attribut der Instanz zu
self.name = name
- # Eine Instanzmethode. Alle Methoden erhalten self als erstes Argument.
+ # Eine Instanzmethode. Alle Methoden erhalten "self" als erstes Argument.
def say(self, msg):
return "%s: %s" % (self.name, msg)
+ # Eine weitere Instanzmethode
+ def sing(self):
+ return 'yo... yo... microphone check... one two... one two...'
+
# Eine Klassenmethode wird von allen Instanzen geteilt.
# Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen
@classmethod
@@ -416,56 +464,287 @@ class Human(object):
def grunt():
return "*grunt*"
+ # Eine Eigenschaft (Property) ist wie ein Getter.
+    # Es verwandelt die Methode age() in ein schreibgeschütztes Attribut mit demselben Namen.
+    # Es ist jedoch nicht nötig, triviale Getter und Setter in Python zu schreiben.
+ @property
+ def age(self):
+ return self._age
+
+    # Damit kann die Eigenschaft festgelegt werden
+ @age.setter
+ def age(self, age):
+ self._age = age
+
+    # Damit kann die Eigenschaft gelöscht werden
+ @age.deleter
+ def age(self):
+ del self._age
+
+# Wenn ein Python-Interpreter eine Quelldatei liest, führt er den gesamten Code aus.
+# Diese __name__-Prüfung stellt sicher, dass dieser Codeblock nur ausgeführt wird,
+# wenn dieses Modul das Hauptprogramm ist.
+if __name__ == '__main__':
+ # Eine Instanz einer Klasse erstellen
+ i = Human(name="Ian")
+ i.say("hi") # "Ian: hi"
+ j = Human("Joel")
+ j.say("hello") # "Joel: hello"
+ # i und j sind Instanzen des Typs Mensch, oder anders ausgedrückt: Sie sind Objekte des Menschen
+
+ # Rufen wir unsere Klassenmethode auf
+ i.say(i.get_species()) # "Ian: H. sapiens"
+
+ # Ändern wir das gemeinsame Attribut
+ Human.species = "H. neanderthalensis"
+ i.say(i.get_species()) # => "Ian: H. neanderthalensis"
+ j.say(j.get_species()) # => "Joel: H. neanderthalensis"
+
+ # Aufruf der statischen Methode
+ print(Human.grunt()) # => "*grunt*"
+
+ # Kann keine statische Methode mit Instanz des Objekts aufrufen,
+ # da i.grunt () automatisch "self" (das Objekt i) als Argument verwendet
+ print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
+
+ # Die Eigenschaft für diese Instanz aktualisieren
+ i.age = 42
+ # die Eigenschaft auslesen
+ i.say(i.age) # => "Ian: 42"
+ j.say(j.age) # => "Joel: 0"
+ # die Eigenschaft löschen
+ del i.age
+ # i.age # => würde einen AttributeError werfen
+
+####################################################
+## 6.1 Inheritance
+####################################################
+
+# Vererbung ermöglicht die Definition neuer untergeordneter Klassen,
+# die Methoden und Variablen von ihrer übergeordneten Klasse erben.
+
+# Wenn Sie die oben definierte Human-Klasse als Basis- oder Elternklasse verwenden,
+# können Sie eine untergeordnete Klasse, Superhero, definieren, die die Klassenvariablen
+# wie "species", "name" und "age" sowie Methoden wie "sing" und "grunzen" aus der Klasse Human erbt.
+# Die Untergeordnete Klasse kann aber auch eigene Eigenschaften haben.
+
+# Um von der Modularisierung per Datei zu profitieren, können Sie die Klassen
+# in ihren eigenen Dateien platzieren, z. B. human.py
+
+# Um Funktionen aus anderen Dateien zu importieren, verwenden Sie das folgende Format
+# from "Dateiname-ohne-Erweiterung" impotr "Funktion-oder-Klasse"
+
+from human import Human
+
+# Geben Sie die übergeordnete(n) Klasse(n) als Parameter für die Klassendefinition an
+class Superhero(Human):
+
+ # Wenn die untergeordnete Klasse alle Definitionen des übergeordneten Elements
+ # ohne Änderungen erben soll, können Sie einfach das Schlüsselwort "pass"
+ # (und nichts anderes) verwenden. In diesem Fall wird jedoch auskommentiert,
+ # um eine eindeutige untergeordnete Klasse zuzulassen:
+ # pass
+
+ # Kindklassen können die Attribute ihrer Eltern überschreiben
+ species = 'Superhuman'
+
+ # Kinder erben automatisch den Konstruktor ihrer übergeordneten Klasse
+ # einschließlich ihrer Argumente, können aber auch zusätzliche Argumente oder
+ # Definitionen definieren und ihre Methoden zB den Klassenkonstruktor überschreiben.
+ # Dieser Konstruktor erbt das Argument "name" von der Klasse "Human" und
+ # fügt die Argumente "superpowers" und "movie" hinzu:
+ def __init__(self, name, movie=False,
+ superpowers=["super strength", "bulletproofing"]):
+
+ # zusätzliche Klassenattribute hinzufügen:
+ self.fictional = True
+ self.movie = movie
+ # Beachten Sie die veränderlichen Standardwerte, da die Standardwerte gemeinsam genutzt werden
+ self.superpowers = superpowers
+
+ # Mit der Funktion "super" können Sie auf die Methoden der übergeordneten Klasse
+ # zugreifen, die vom untergeordneten Objekt überschrieben werden,
+ # in diesem Fall die Methode __init__.
+        # Dies ruft den Konstruktor der übergeordneten Klasse auf:
+ super().__init__(name)
+
+ # überschreiben der "sing" Methode
+ def sing(self):
+ return 'Dun, dun, DUN!'
+
+ # eine zusätzliche Instanzmethode hinzufügen
+ 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")
+
+ # Instanztypprüfungen
+ if isinstance(sup, Human):
+ print('I am human')
+ if type(sup) is Superhero:
+ print('I am a superhero')
+
+ # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, die sowohl von getattr() als auch von super() verwendet wird.
+    # Dieses Attribut ist dynamisch und kann aktualisiert werden.
+ print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
+ # => <class 'human.Human'>, <class 'object'>)
+
+ # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut
+ print(sup.get_species()) # => Superhuman
+
+ # Ruft die überschriebene Methode auf
+ print(sup.sing()) # => Dun, dun, DUN!
+
+ # Ruft die Methode von Human auf
+ sup.say('Spoon') # => Tick: Spoon
+
+ # Aufruf einer Methode, die nur in Superhero existiert
+ sup.boast() # => I wield the power of super strength!
+ # => I wield the power of bulletproofing!
+
+ # Vererbtes Klassenattribut
+ sup.age = 31
+ print(sup.age) # => 31
+
+ # Attribut, das nur in Superhero existiert
+ print('Am I Oscar eligible? ' + str(sup.movie))
+
+####################################################
+## 6.2 Multiple Inheritance
+####################################################
-# Eine Instanz einer Klasse erstellen
-i = Human(name="Ian")
-print i.say("hi") # gibt "Ian: hi" aus
+# Eine weitere Klassendefinition
+# bat.py
-j = Human("Joel")
-print j.say("hello") #gibt "Joel: hello" aus
+class Bat:
-# Rufen wir mal unsere Klassenmethode auf
-i.get_species() #=> "H. sapiens"
+ species = 'Baty'
-# Ändern wir mal das gemeinsame Attribut
-Human.species = "H. neanderthalensis"
-i.get_species() #=> "H. neanderthalensis"
-j.get_species() #=> "H. neanderthalensis"
+ def __init__(self, can_fly=True):
+ self.fly = can_fly
-# Aufruf der statischen Methode
-Human.grunt() #=> "*grunt*"
+ # This class also has a say method
+ def say(self, msg):
+ msg = '... ... ...'
+ return msg
+ # And its own method as well
+ def sonar(self):
+ return '))) ... ((('
+if __name__ == '__main__':
+ b = Bat()
+ print(b.say('hello'))
+ print(b.fly)
+
+# Und noch eine andere Klassendefinition, die von Superhero und Bat erbt
+# superhero.py
+from superhero import Superhero
+from bat import Bat
+
+# Definieren Sie Batman als eine Kindklasse, das von Superheld und Bat erbt
+class Batman(Superhero, Bat):
+
+ def __init__(self, *args, **kwargs):
+ # In der Regel müssen Sie super aufrufen, um Attribute zu erben:
+ # super (Batman, selbst) .__ init__ (* args, ** kwargs)
+ # Allerdings handelt es sich hier um Mehrfachvererbung, und super()
+ # funktioniert nur mit der nächsten Basisklasse in der MRO-Liste.
+ # Stattdessen rufen wir explizit __init__ für alle Vorfahren auf.
+ # Die Verwendung von *args und **kwargs ermöglicht die saubere Übergabe von
+ # Argumenten, wobei jedes übergeordnete Element eine Schicht der Zwiebel "abschält".
+ Superhero.__init__(self, 'anonymous', movie=True,
+ superpowers=['Wealthy'], *args, **kwargs)
+ Bat.__init__(self, *args, can_fly=False, **kwargs)
+ # überschreibt den Wert für das Namensattribut
+ self.name = 'Sad Affleck'
+
+ def sing(self):
+ return 'nan nan nan nan nan batman!'
+
+if __name__ == '__main__':
+ sup = Batman()
+
+ # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen,
+ # die sowohl von getattr() als auch von super() verwendet wird.
+ # Dieses Attribut ist dynamisch und kann aktualisiert werden.
+ print(Batman.__mro__) # => (<class '__main__.Batman'>,
+ # => <class 'superhero.Superhero'>,
+ # => <class 'human.Human'>,
+ # => <class 'bat.Bat'>, <class 'object'>)
+
+ # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut
+ print(sup.get_species()) # => Superhuman
+
+ # Ruft die überschriebene Methode auf
+ print(sup.sing()) # => nan nan nan nan nan batman!
+
+ # Ruft die Methode von Human auf, weil die Reihenfolge der Vererbung wichtig ist
+ sup.say('I agree') # => Sad Affleck: I agree
+
+ # Aufrufmethode, die nur im 2. Vorfahren existiert
+ print(sup.sonar()) # => ))) ... (((
+
+ # Vererbtes Klassenattribut
+ sup.age = 100
+ print(sup.age) # => 100
+
+ # Vererbtes Attribut vom 2. Vorfahren, dessen Standardwert überschrieben wurde.
+ print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
+
+
####################################################
-## 6. Module
-####################################################
-
-# Wir können Module importieren
-import math
-print math.sqrt(16) #=> 4.0
+## 7. Fortgeschrittenes
+####################################################
+
+# Generatoren helfen Ihnen, lazy Code zu erstellen.
+def double_numbers(iterable):
+ for i in iterable:
+ yield i + i
+
+# Generatoren sind speichereffizient, da sie nur die Daten laden,
+# die zur Verarbeitung des nächsten Werts in der iterierbaren Komponente
+# erforderlich sind. Dadurch können sie ansonsten unzulässig große Wertebereiche ausführen.
+# HINWEIS: `range` ersetzt` xrange` in Python 3.
+for i in double_numbers(range(1, 900000000)): # `range` ist ein Generator.
+ print(i)
+ if i >= 30:
+ break
+
+# Genauso wie Sie ein 'list comprehension' (Listen Abstraktion) erstellen können, können Sie auch 'generator comprehension' (Generator Abstraktion) erstellen.
+values = (-x for x in [1,2,3,4,5])
+for x in values:
+ print(x) # prints -1 -2 -3 -4 -5 to console/terminal
+
+# Sie können eine Generator Abstraktion auch direkt in eine Liste umwandeln (casten).
+values = (-x for x in [1,2,3,4,5])
+gen_to_list = list(values)
+print(gen_to_list) # => [-1, -2, -3, -4, -5]
-# Wir können auch nur spezielle Funktionen eines Moduls importieren
-from math import ceil, floor
-print ceil(3.7) #=> 4.0
-print floor(3.7) #=> 3.0
+# Decorators
+# In diesem Beispiel umschliesst "beg" "say". Wenn say_please True ist, wird die zurückgegebene Nachricht geändert.
+from functools import wraps
-# Wir können auch alle Funktionen eines Moduls importieren
-# Warnung: Dies wird nicht empfohlen
-from math import *
+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
-# Wir können Modulnamen abkürzen
-import math as m
-math.sqrt(16) == m.sqrt(16) #=> True
+ return wrapper
-# Module sind in Python nur gewöhnliche Dateien. Wir
-# können unsere eigenen schreiben und importieren. Der Name des
-# Moduls ist der Dateiname.
+@beg
+def say(say_please=False):
+ msg = "Can you buy me a beer?"
+ return msg, say_please
-# Wir können auch die Funktionen und Attribute eines
-# Moduls herausfinden.
-import math
-dir(math)
+print(say()) # Can you buy me a beer?
+print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
```
diff --git a/de-de/python3-de.html.markdown b/de-de/python3-de.html.markdown
index c383d742..4ef997a1 100644
--- a/de-de/python3-de.html.markdown
+++ b/de-de/python3-de.html.markdown
@@ -14,7 +14,7 @@ Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist he
Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service].
-Hinweis: Dieser Beitrag bezieht sich insplizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/python/) weiter.
+Hinweis: Dieser Beitrag bezieht sich implizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/python/) weiter.
```python
diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown
index d0e3471a..ff45dc8d 100644
--- a/de-de/yaml-de.html.markdown
+++ b/de-de/yaml-de.html.markdown
@@ -111,7 +111,7 @@ python_komplexe_Zahlen: !!python/komplex 1+2j
# EXTRA YAML TYPEN #
####################
-# Strings and Zahlen sind nicht die einzigen Skalare, welche YAML versteht.
+# Strings und Zahlen sind nicht die einzigen Skalare, welche YAML versteht.
# ISO-formatierte Datumsangaben and Zeiangaben können ebenso geparsed werden.
DatumZeit: 2001-12-15T02:59:43.1Z
DatumZeit_mit_Leerzeichen: 2001-12-14 21:59:43.10 -5
diff --git a/dhall.html.markdown b/dhall.html.markdown
new file mode 100644
index 00000000..704a94ee
--- /dev/null
+++ b/dhall.html.markdown
@@ -0,0 +1,362 @@
+---
+language: Dhall
+filename: learndhall.dhall
+contributors:
+ - ["Gabriel Gonzalez", "http://www.haskellforall.com/"]
+---
+
+Dhall is a programmable configuration language that provides a non-repetitive
+alternative to YAML.
+
+You can think of Dhall as: JSON + functions + types + imports
+
+Note that while Dhall is programmable, Dhall is not Turing-complete. Many
+of Dhall's features take advantage of this restriction to provide stronger
+safety guarantees and more powerful tooling.
+
+```haskell
+-- Single-line comment
+
+{- Multi-line comment
+
+ Unicode is fine 🙂
+
+ This file is a valid Dhall expression that evaluates to a large record
+ collecting the results of each step.
+
+ You can view the results by interpreting the file:
+
+ $ dhall --file learndhall.dhall
+
+ {- Comments can be nested -}
+-}
+
+let greeting = "Hello, world!"
+
+let fruits = "🍋🍓🍍🍉🍌"
+
+let interpolation = "Enjoy some delicious fruit: ${fruits}"
+
+let multilineText {- Inline comments work, too -} =
+ ''
+ Leading whitespace is stripped from multi-line text literals.
+
+ That means you can freely indent or dedent a text literal without
+ changing the result.
+
+ Relative indentation within the literal is still preserved.
+
+ Other than that, the text literal is preserved verbatim, similar to a
+ "literal" YAML multiline string.
+ ''
+
+let bool = True
+
+-- Type annotations on bindings are optional, but helpful, so we'll use them
+let annotation : Bool = True
+
+let renderedBool : Text = if bool then "True" else "False"
+
+-- Natural numbers are non-negative and are unsigned
+let naturalNumber : Natural = 42
+
+-- Integers may be negative, but require an explicit sign, even if positive
+let positiveInteger : Integer = +1
+
+let negativeInteger : Integer = -12
+
+let pi : Double = 3.14159265359
+
+{- You can use a wider character range for identifiers (such as quotation
+ marks and whitespace) if you quote them using backticks
+-}
+let `Avogadro's Number` : Double = 6.0221409e+23
+
+let origin : { x : Double, y : Double } = { x = 0.0, y = 0.0 }
+
+let somePrimes : List Natural = [ 2, 3, 5, 7, 11 ]
+
+{- A schema is the same thing as a type
+
+ Types begin with an uppercase letter by convention, but this convention is
+ not enforced
+-}
+let Profile : Type
+ = { person :
+ { name : Text
+ , age : Natural
+ }
+ , address :
+ { country : Text
+ , state : Text
+ , city : Text
+ }
+ }
+
+let john : Profile =
+ { person =
+ { name = "John Doe"
+ , age = 67
+ }
+ , address =
+ { country = "United States"
+ , state = "Pennsylvania"
+ , city = "Philadelphia"
+ }
+ }
+
+let philadelphia : Text = john.address.city
+
+{- Enum alternatives also begin with an uppercase letter by convention. This
+ convention is not enforced
+-}
+let DNA : Type = < Adenine | Cytosine | Guanine | Thymine >
+
+let dnaSequence : List DNA = [ DNA.Thymine, DNA.Guanine, DNA.Guanine ]
+
+let compactDNASequence : List DNA =
+ let a = DNA.Adenine
+ let c = DNA.Cytosine
+ let g = DNA.Guanine
+ let t = DNA.Thymine
+ in [ c, t, t, a, t, c, g, g, c ]
+
+-- You can transform enums by providing a record with one field per alternative
+let theLetterG : Text =
+ merge
+ { Adenine = "A"
+ , Cytosine = "C"
+ , Guanine = "G"
+ , Thymine = "T"
+ }
+ DNA.Guanine
+
+let presentOptionalValue : Optional Natural = Some 1
+
+let absentOptionalValue : Optional Natural = None Natural
+
+let points : List { x : Double, y : Double } =
+ [ { x = 1.1, y = -4.2 }
+ , { x = 4.4, y = -3.0 }
+ , { x = 8.2, y = -5.5 }
+ ]
+
+{- `Natural -> List Natural` is the type of a function whose input type is a
+ `Natural` and whose output type is a `List Natural`
+
+ All functions in Dhall are anonymous functions (a.k.a. "lambdas"),
+ which you can optionally give a name
+
+ For example, the following function is equivalent to this Python code:
+
+ lambda n : [ n, n + 1 ]
+
+ ... and this JavaScript code:
+
+ function (n) { return [ n, n + 1 ]; }
+-}
+let exampleFunction : Natural -> List Natural =
+ \(n : Natural) -> [ n, n + 1 ]
+
+-- Dhall also supports Unicode syntax, but this tutorial will stick to ASCII
+let unicodeFunction : Natural → List Natural =
+ λ(n : Natural) → [ n, n + 1 ]
+
+-- You don't need to parenthesize function arguments
+let exampleFunctionApplication : List Natural =
+ exampleFunction 2
+
+let functionOfMultipleArguments : Natural -> Natural -> List Natural =
+ \(x : Natural) -> \(y : Natural) -> [ x, y ]
+
+let functionAppliedToMultipleArguments : List Natural =
+ functionOfMultipleArguments 2 3
+
+{- Same as `exampleFunction` except we gave the function's input type a
+ name: "n"
+-}
+let namedArgumentType : forall (n : Natural) -> List Natural =
+ \(n : Natural) -> [ n, n + 1 ]
+
+{- If you name a function's input type, you can use that name later within the
+ same type
+
+ This lets you write a function that works for more than one type of input
+ (a.k.a. a "polymorphic" function)
+-}
+let duplicate : forall (a : Type) -> a -> List a =
+ \(a : Type) -> \(x : a) -> [ x, x ]
+
+let duplicatedNumber : List Natural =
+ duplicate Natural 2
+
+let duplicatedBool : List Bool =
+ duplicate Bool False
+
+{- The language also has some built-in polymorphic functions, such as:
+
+ List/head : forall (a : Type) -> List a -> Optional a
+-}
+let firstPrime : Optional Natural = List/head Natural somePrimes
+
+let functionOfARecord : { x : Natural, y : Natural } -> List Natural =
+ \(args : { x : Natural, y : Natural }) -> [ args.x, args.y ]
+
+let functionAppliedToARecord : List Natural =
+ functionOfARecord { x = 2, y = 5 }
+
+{- All type conversions are explicit
+
+ `Natural/show` is a built-in function of the following type:
+
+ Natural/show : Natural -> Text
+
+ ... that converts `Natural` numbers to their `Text` representation
+-}
+let typeConversion : Natural -> Text =
+ \(age : Natural) -> "I am ${Natural/show age} years old!"
+
+-- A "template" is the same thing as a function whose output type is `Text`
+let mitLicense : { year : Natural, copyrightHolder : Text } -> Text =
+ \(args : { year : Natural, copyrightHolder : Text }) ->
+''
+Copyright ${Natural/show args.year} ${args.copyrightHolder}
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+''
+
+-- Template instantiation is the same thing as function application
+let templatedLicense : Text =
+ mitLicense { year = 2019, copyrightHolder = "Jane Smith" }
+
+{- You can import expressions by URL
+
+ Also, like Bash, you can import code from your local filesystem (not shown)
+
+ Security-conscious users can pin remotely-imported expressions by adding a
+ semantic integrity check. The interpreter rejects any attempt to tamper with
+ an expression pinned in this way. However, behavior-preserving refactors
+ of imported content will not perturb the hash.
+
+ Imported expressions pinned in this way are also locally cached in a
+ content-addressable store (typically underneath `~/.cache/dhall`)
+-}
+let Natural/sum : List Natural -> Natural =
+ https://prelude.dhall-lang.org/Natural/sum
+ sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037
+
+let twentyEight : Natural = Natural/sum somePrimes
+
+-- A "package" is the same thing as a (possibly nested) record that you can import
+let Prelude = https://prelude.dhall-lang.org/package.dhall
+
+let false : Bool = Prelude.Bool.not True
+
+-- You can import the raw contents of a file by adding `as Text` to an import
+let sourceCode : Text = https://prelude.dhall-lang.org/Bool/not as Text
+
+-- You can import environment variables, too:
+let presentWorkingDirectory = env:PWD as Text
+
+-- You can provide a fallback expression if an import fails
+let home : Optional Text = Some env:HOME ? None Text
+
+-- Fallback expressions can contain alternative imports of their own
+let possiblyCustomPrelude =
+ env:DHALL_PRELUDE
+ ? https://prelude.dhall-lang.org/package.dhall
+
+{- Tie everything together by auto-generating configurations for 10 build users
+ using the `generate` function:
+
+ Prelude.List.generate
+ : Natural -> forall (a : Type) -> (Natural -> a) -> List a
+-}
+let buildUsers =
+ let makeUser = \(user : Text) ->
+ let home = "/home/${user}"
+ let privateKey = "${home}/.ssh/id_ed25519"
+ let publicKey = "${privateKey}.pub"
+ in { home = home
+ , privateKey = privateKey
+ , publicKey = publicKey
+ }
+
+ let buildUser =
+ \(index : Natural) -> makeUser "build${Natural/show index}"
+
+ let Config =
+ { home : Text
+ , privateKey : Text
+ , publicKey : Text
+ }
+
+ in Prelude.List.generate 10 Config buildUser
+
+-- Present all of the results in a final record
+in { greeting = greeting
+ , fruits = fruits
+ , interpolation = interpolation
+ , multilineText = multilineText
+ , bool = bool
+ , annotation = annotation
+ , renderedBool = renderedBool
+ , naturalNumber = naturalNumber
+ , positiveInteger = positiveInteger
+ , negativeInteger = negativeInteger
+ , pi = pi
+ , `Avogadro's Number` = `Avogadro's Number`
+ , origin = origin
+ , somePrimes = somePrimes
+ , john = john
+ , philadelphia = philadelphia
+ , dnaSequence = dnaSequence
+ , compactDNASequence = compactDNASequence
+ , theLetterG = theLetterG
+ , presentOptionalValue = presentOptionalValue
+ , absentOptionalValue = absentOptionalValue
+ , points = points
+ , exampleFunction = exampleFunction
+ , unicodeFunction = unicodeFunction
+ , exampleFunctionApplication = exampleFunctionApplication
+ , functionOfMultipleArguments = functionOfMultipleArguments
+ , functionAppliedToMultipleArguments = functionAppliedToMultipleArguments
+ , namedArgumentType = namedArgumentType
+ , duplicate = duplicate
+ , duplicatedNumber = duplicatedNumber
+ , duplicatedBool = duplicatedBool
+ , firstPrime = firstPrime
+ , functionOfARecord = functionOfARecord
+ , functionAppliedToARecord = functionAppliedToARecord
+ , typeConversion = typeConversion
+ , mitLicense = mitLicense
+ , templatedLicense = templatedLicense
+ , twentyEight = twentyEight
+ , false = false
+ , sourceCode = sourceCode
+ , presentWorkingDirectory = presentWorkingDirectory
+ , home = home
+ , buildUsers = buildUsers
+ }
+```
+
+To learn more, visit the official website, which also lets you try the
+language live in your browser:
+
+* [https://dhall-lang.org](http://dhall-lang.org/)
diff --git a/directx9.html.markdown b/directx9.html.markdown
new file mode 100644
index 00000000..b51f418d
--- /dev/null
+++ b/directx9.html.markdown
@@ -0,0 +1,827 @@
+---
+category: tool
+tool: DirectX 9
+filename: learndirectx9.cpp
+contributors:
+ - ["Simon Deitermann", "s.f.deitermann@t-online.de"]
+---
+
+**Microsoft DirectX** is a collection of application programming interfaces (APIs) for handling tasks related to
+multimedia, especially game programming and video, on Microsoft platforms. Originally, the names of these APIs
+all began with Direct, such as Direct3D, DirectDraw, DirectMusic, DirectPlay, DirectSound, and so forth. [...]
+Direct3D (the 3D graphics API within DirectX) is widely used in the development of video games for Microsoft
+Windows and the Xbox line of consoles.<sup>[1]</sup>
+
+In this tutorial we will be focusing on DirectX 9, which is not as low-level as it's sucessors, which are aimed at programmers very familiar with how graphics hardware works. It makes a great starting point for learning Direct3D. In this tutorial I will be using the Win32-API for window handling and the DirectX 2010 SDK.
+
+## Window creation
+
+```cpp
+#include <Windows.h>
+
+bool _running{ false };
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ // Handle incoming message.
+ switch (msg) {
+ // Set running to false if the user tries to close the window.
+ case WM_DESTROY:
+ _running = false;
+ PostQuitMessage(0);
+ break;
+ }
+ // Return the handled event.
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow) {
+ // Set window properties we want to use.
+ WNDCLASSEX wndEx{ };
+ wndEx.cbSize = sizeof(WNDCLASSEX); // structure size
+ wndEx.style = CS_VREDRAW | CS_HREDRAW; // class styles
+ wndEx.lpfnWndProc = WndProc; // window procedure
+ wndEx.cbClsExtra = 0; // extra memory (struct)
+ wndEx.cbWndExtra = 0; // extra memory (window)
+ wndEx.hInstance = hInstance; // module instance
+ wndEx.hIcon = LoadIcon(nullptr, IDI_APPLICATION); // icon
+ wndEx.hCursor = LoadCursor(nullptr, IDC_ARROW); // cursor
+ wndEx.hbrBackground = (HBRUSH) COLOR_WINDOW; // background color
+ wndEx.lpszMenuName = nullptr; // menu name
+ wndEx.lpszClassName = "DirectXClass"; // register class name
+ wndEx.hIconSm = nullptr; // small icon (taskbar)
+ // Register created class for window creation.
+ RegisterClassEx(&wndEx);
+ // Create a new window handle.
+ HWND hWnd{ nullptr };
+ // Create a new window handle using the registered class.
+ hWnd = CreateWindow("DirectXClass", // registered class
+ "directx window", // window title
+ WS_OVERLAPPEDWINDOW, // window style
+ 50, 50, // x, y (position)
+ 1024, 768, // width, height (size)
+ nullptr, // parent window
+ nullptr, // menu
+ hInstance, // module instance
+ nullptr); // struct for infos
+ // Check if a window handle has been created.
+ if (!hWnd)
+ return -1;
+ // Show and update the new window.
+ ShowWindow(hWnd, nCmdShow);
+ UpdateWindow(hWnd);
+ // Start the game loop and send incoming messages to the window procedure.
+ _running = true;
+ MSG msg{ };
+ while (_running) {
+ while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ return 0;
+}
+```
+
+This should create a window, that can the moved, resized and closed.
+
+## Direct3D initialization
+
+```cpp
+// Includes DirectX 9 structures and functions.
+// Remember to link "d3d9.lib" and "d3dx9.lib".
+// For "d3dx9.lib" the DirectX SDK (June 2010) is needed.
+// Don't forget to set your subsystem to Windows.
+#include <d3d9.h>
+#include <d3dx9.h>
+// Includes the ComPtr, a smart pointer automatically releasing COM objects.
+#include <wrl.h>
+using namespace Microsoft::WRL;
+// Next we define some Direct3D9 interface structs we need.
+ComPtr<IDirect3D9> _d3d{ };
+ComPtr<IDirect3DDevice9> _device{ };
+```
+
+With all interfaces declared we can now initialize Direct3D.
+
+```cpp
+bool InitD3D(HWND hWnd) {
+ // Store the size of the window rectangle.
+ RECT clientRect{ };
+ GetClientRect(hWnd, &clientRect);
+ // Initialize Direct3D
+ _d3d = Direct3DCreate9(D3D_SDK_VERSION);
+ // Get the display mode which format will be the window format.
+ D3DDISPLAYMODE displayMode{ };
+ _d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, // use default graphics card
+ &displayMode); // display mode pointer
+ // Next we have to set some presentation parameters.
+ D3DPRESENT_PARAMETERS pp{ };
+ pp.BackBufferWidth = clientRect.right; // width is window width
+ pp.BackBufferHeight = clientRect.bottom; // height is window height
+ pp.BackBufferFormat = displayMode.Format; // use adapter format
+ pp.BackBufferCount = 1; // 1 back buffer (default)
+ pp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard after presentation
+ pp.hDeviceWindow = hWnd; // associated window handle
+ pp.Windowed = true; // display in window mode
+ pp.Flags = 0; // no special flags
+ // Variable to store results of methods to check if everything succeded.
+ HRESULT result{ };
+ result = _d3d->CreateDevice(D3DADAPTER_DEFAULT, // use default graphics card
+ D3DDEVTYPE_HAL, // use hardware acceleration
+ hWnd, // the window handle
+ D3DCREATE_HARDWARE_VERTEXPROCESSING,
+ // vertices are processed by the hardware
+ &pp, // the present parameters
+ &_device); // struct to store the device
+ // Return false if the device creation failed.
+ // It is helpful to set breakpoints at the return line.
+ if (FAILED(result))
+ return false;
+ // Create a viewport which hold information about which region to draw to.
+ D3DVIEWPORT9 viewport{ };
+ viewport.X = 0; // start at top left corner
+ viewport.Y = 0; // ..
+ viewport.Width = clientRect.right; // use the entire window
+ viewport.Height = clientRect.bottom; // ..
+ viewport.MinZ = 0.0f; // minimun view distance
+ viewport.MaxZ = 100.0f; // maximum view distance
+ // Apply the created viewport.
+ result = _device->SetViewport(&viewport);
+ // Always check if something failed.
+ if (FAILED(result))
+ return false;
+ // Everything was successful, return true.
+ return true;
+}
+// ...
+// Back in our WinMain function we call our initialization function.
+// ...
+// Check if Direct3D initialization succeded, else exit the application.
+if (!InitD3D(hWnd))
+ return -1;
+
+MSG msg{ };
+while (_running) {
+ while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ // Clear to render target to a specified color.
+ _device->Clear(0, // number of rects to clear
+ nullptr, // indicates to clear the entire window
+ D3DCLEAR_TARGET, // clear all render targets
+ D3DXCOLOR{ 1.0f, 0.0f, 0.0f, 1.0f }, // color (red)
+ 0.0f, // depth buffer clear value
+ 0); // stencil buffer clear value
+ // ...
+ // Drawing operations go here.
+ // ...
+ // Flip the front- and backbuffer.
+ _device->Present(nullptr, // no source rectangle
+ nullptr, // no destination rectangle
+ nullptr, // don't change the current window handle
+ nullptr); // pretty much always nullptr
+}
+// ...
+```
+
+Now the window should be displayed in a bright red color.
+
+## Vertex Buffer
+
+Let's create a vertex buffer to store the vertices for our triangle
+
+```cpp
+// At the top of the file we need to add a include.
+#include <vector>
+// First we declare a new ComPtr holding a vertex buffer.
+ComPtr<IDirect3DVertexBuffer9> _vertexBuffer{ };
+// Lets define a funtion to calculate the byte size of a std::vector
+template <typename T>
+unsigned int GetByteSize(const std::vector<T>& vec) {
+ return sizeof(vec[0]) * vec.size();
+}
+// Define "flexible vertex format" describing the content of our vertex struct.
+// Use the defined color as diffuse color.
+const unsigned long VertexStructFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
+// Define a struct representing the vertex data the buffer will hold.
+struct VStruct {
+ float x, y, z; // store the 3D position
+ D3DCOLOR color; // store a color
+};
+// Declare a new function to create a vertex buffer.
+IDirect3DVertexBuffer9* CreateBuffer(const std::vector<VStruct>& vertices) {
+ // Declare the buffer to be returned.
+ IDirect3DVertexBuffer9* buffer{ };
+ HRESULT result{ };
+ result = _device->CreateVertexBuffer(
+ GetByteSize(vertices), // vector size in bytes
+ 0, // data usage
+ VertexStructFVF, // FVF of the struct
+ D3DPOOL_DEFAULT, // use default pool for the buffer
+ &buffer, // receiving buffer
+ nullptr); // special shared handle
+ // Check if buffer was created successfully.
+ if (FAILED(result))
+ return nullptr;
+ // Create a data pointer for copying the vertex data
+ void* data{ };
+ // Lock the buffer to get a buffer for data storage.
+ result = buffer->Lock(0, // byte offset
+ GetByteSize(vertices), // size to lock
+ &data, // receiving data pointer
+ 0); // special lock flags
+ // Check if buffer was locked successfully.
+ if (FAILED(result))
+ return nullptr;
+ // Copy the vertex data using C standard libraries memcpy.
+ memcpy(data, vertices.data(), GetByteSize(vertices));
+ buffer->Unlock();
+ // Set the FVF Direct3D uses for rendering.
+ _device->SetFVF(VertexStructFVF);
+ // If everything was successful return the filled vertex buffer.
+ return buffer;
+}
+```
+
+In our **WinMain** we can now call the new function after the Direct3D initialization.
+
+```cpp
+// ...
+if (!InitD3D(hWnd))
+ return -1;
+// Define the vertices we need to draw a triangle.
+// Values are declared in a clockwise direction else Direct3D would cull them.
+// If you want to diable culling just call:
+// _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+std::vector<VStruct> vertices {
+ // Bottom left
+ VStruct{ -1.0f, -1.0f, 1.0f, D3DXCOLOR{ 1.0f, 0.0f, 0.0f, 1.0f } },
+ // Top left
+ VStruct{ -1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 1.0f, 0.0f, 1.0f } },
+ // Top right
+ VStruct{ 1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 0.0f, 1.0f, 1.0f } }
+};
+// Try to create the vertex buffer else exit the application.
+if (!(_vertexBuffer = CreateBuffer(vertices)))
+ return -1;
+// ...
+```
+
+## Transformations
+
+Before we can use the vertex buffer to draw our primitives, we first need to set up the matrices.
+
+```cpp
+// Lets create a new funtions for the matrix transformations.
+bool SetupTransform() {
+ // Create a view matrix that transforms world space to
+ // view space.
+ D3DXMATRIX view{ };
+ // Use a left-handed coordinate system.
+ D3DXMatrixLookAtLH(
+ &view, // receiving matrix
+ &D3DXVECTOR3{ 0.0f, 0.0f, -20.0f }, // "camera" position
+ &D3DXVECTOR3{ 0.0f, 0.0f, 0.0f }, // position where to look at
+ &D3DXVECTOR3{ 0.0f, 1.0f, 0.0f }); // positive y-axis is up
+ HRESULT result{ };
+ result = _device->SetTransform(D3DTS_VIEW, &view); // apply the view matrix
+ if (FAILED(result))
+ return false;
+ // Create a projection matrix that defines the view frustrum.
+ // It transforms the view space to projection space.
+ D3DXMATRIX projection{ };
+ // Create a perspective projection using a left-handed coordinate system.
+ D3DXMatrixPerspectiveFovLH(
+ &projection, // receiving matrix
+ D3DXToRadian(60.0f), // field of view in radians
+ 1024.0f / 768.0f, // aspect ratio (width / height)
+ 0.0f, // minimum view distance
+ 100.0f); // maximum view distance
+ result = _device->SetTransform(D3DTS_PROJECTION, &projection);
+ if (FAILED(result))
+ return false;
+ // Disable lighting for now so we can see what we want to render.
+ result = _device->SetRenderState(D3DRS_LIGHTING, false);
+ // View and projection matrix are successfully applied, return true.
+ return true;
+}
+// ...
+// Back in the WinMain function we can now call the transformation function.
+// ...
+if (!(_vertexBuffer = CreateVertexBuffer(vertices)))
+ return -1;
+// Call the transformation setup function.
+if (!SetupTransform())
+ return -1;
+// ...
+```
+
+## Rendering
+
+Now that everything is setup we can start drawing our first 2D triangle in 3D space.
+
+```cpp
+// ...
+if (!SetupTransform())
+ return -1;
+// First we have to bind our vertex buffer to the data stream.
+HRESULT result{ };
+result = _device->SetStreamSource(0, // use the default stream
+ _vertexBuffer.Get(), // pass the vertex buffer
+ 0, // no offset
+ sizeof(VStruct)); // size of vertex struct
+if (FAILED(result))
+ return -1;
+
+// Create a world transformation matrix and set it to an identity matrix.
+D3DXMATRIX world{ };
+D3DXMatrixIdentity(&world);
+// Create a scalation matrix scaling our primitve by 10 in the x,
+// 10 in the y and keeping the z direction.
+D3DXMATRIX scaling{ };
+D3DXMatrixScaling(&scaling, // matrix to scale
+ 10, // x scaling
+ 10, // y scaling
+ 1); // z scaling
+// Create a rotation matrix storing the current rotation of our primitive.
+// We set the current rotation matrix to an identity matrix for now.
+D3DXMATRIX rotation{ };
+D3DXMatrixIdentity(&rotation);
+// Now we multiply the scalation and rotation matrix and store the result
+// in the world matrix.
+D3DXMatrixMultiply(&world, // destination matrix
+ &scaling, // matrix 1
+ &rotation); // matrix 2
+// Apply the current world matrix.
+_device->SetTransform(D3DTS_WORLD, &world);
+// Disable culling so we can see the back of our primitive when it rotates.
+_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+// The default cullmode is D3DCULL_CW.
+// After we used our the rotation matrix for multiplication we can set it
+// to rotate a small amount.
+// D3DXToRadian() function converts degree to radians.
+D3DXMatrixRotationY(&rotation, // matrix to rotate
+ D3DXToRadian(0.5f)); // rotation angle in radians
+
+MSG msg{ };
+ while (_running) {
+ // ...
+ _device->Clear(0, nullptr, D3DCLEAR_TARGET,
+ D3DXCOLOR{ 0.0f, 0.0f, 0.0f, 1.0f }, 0.0f, 0);
+ // With everything setup we can call the draw function.
+ _device->BeginScene();
+ _device->DrawPrimitive(D3DPT_TRIANGLELIST, // primitive type
+ 0, // start vertex
+ 1); // primitive count
+ _device->EndScene();
+
+ _device->Present(nullptr, nullptr, nullptr, nullptr);
+ // We can keep multiplying the world matrix with our rotation matrix
+ // to add it's rotation to the world matrix.
+ D3DXMatrixMultiply(&world, &world, &rotation);
+ // Update the modified world matrix.
+ _device->SetTransform(D3DTS_WORLD, &world);
+ // ...
+```
+
+You should now be viewing a 10x10 units colored triangle from 20 units away, rotating around its origin.<br>
+You can find the complete working code here: [DirectX - 1](https://pastebin.com/YkSF2rkk)
+
+## Indexing
+
+To make it easier to draw primitives sharing a lot of vertices we can use indexing, so we only have to declare the unique vertices and put the order they are called in another array.
+
+```cpp
+// First we declare a new ComPtr for our index buffer.
+ComPtr<IDirect3DIndexBuffer9> _indexBuffer{ };
+// ...
+// Declare a function creating a index buffer from a std::vector
+IDirect3DIndexBuffer9* CreateIBuffer(std::vector<unsigned int>& indices) {
+ IDirect3DIndexBuffer9* buffer{ };
+ HRESULT result{ };
+ result = _device->CreateIndexBuffer(
+ GetByteSize(indices), // vector size in bytes
+ 0, // data usage
+ D3DFMT_INDEX32, // format is 32 bit int
+ D3DPOOL_DEFAULT, // default pool
+ &buffer, // receiving buffer
+ nullptr); // special shared handle
+ if (FAILED(result))
+ return nullptr;
+ // Create a data pointer pointing to the buffer data.
+ void* data{ };
+ result = buffer->Lock(0, // byte offset
+ GetByteSize(indices), // byte size
+ &data, // receiving data pointer
+ 0); // special lock flag
+ if (FAILED(result))
+ return nullptr;
+ // Copy the index data and unlock after copying.
+ memcpy(data, indices.data(), GetByteSize(indices));
+ buffer->Unlock();
+ // Return the filled index buffer.
+ return buffer;
+}
+// ...
+// In our WinMain we can now change the vertex data and create new index data.
+// ...
+std::vector<VStruct> vertices {
+ VStruct{ -1.0f, -1.0f, 1.0f, D3DXCOLOR{ 1.0f, 0.0f, 0.0f, 1.0f } },
+ VStruct{ -1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 1.0f, 0.0f, 1.0f } },
+ VStruct{ 1.0f, 1.0f, 1.0f, D3DXCOLOR{ 0.0f, 0.0f, 1.0f, 1.0f } },
+ // Add a vertex for the bottom right.
+ VStruct{ 1.0f, -1.0f, 1.0f, D3DXCOLOR{ 1.0f, 1.0f, 0.0f, 1.0f } }
+};
+// Declare the index data, here we build a rectangle from two triangles.
+std::vector<unsigned int> indices {
+ 0, 1, 2, // the first triangle (b,left -> t,left -> t,right)
+ 0, 2, 3 // the second triangle (b,left -> t,right -> b,right)
+};
+// ...
+// Now we call the "CreateIBuffer" function to create a index buffer.
+// ...
+if (!(_indexBuffer = CreateIBuffer(indices)))
+ return -1;
+// ...
+// After binding the vertex buffer we have to bind the index buffer to
+// use indexed rendering.
+result = _device->SetStreamSource(0, _vertexBuffer.Get(), 0, sizeof(VStruct));
+if (FAILED(result))
+ return -1;
+// Bind the index data to the default data stream.
+result = _device->SetIndices(_indexBuffer.Get())
+if (FAILED(result))
+ return -1;
+// ...
+// Now we replace the "DrawPrimitive" function with an indexed version.
+_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, // primitive type
+ 0, // base vertex index
+ 0, // minimum index
+ indices.size(), // amount of vertices
+ 0, // start in index buffer
+ 2); // primitive count
+// ...
+```
+
+Now you should see a colored rectangle made up of 2 triangles. If you set the primitive count in the "DrawIndexedPrimitive" method to 1 only the first triangle should be rendered and if you set the start of the index buffer to 3 and the primitive count to 1 only the second triangle should be rendered.<br>
+You can find the complete working code here: [DirectX - 2](https://pastebin.com/yWBPWPRG)
+
+## Vertex declaration
+
+Instead of using the old "flexible vertex format" we should use vertex declarations instead, as the FVF declarations get converted to vertex declarations internally anyway.
+
+```cpp
+// First we have to REMOVE the following lines:
+const unsigned long VertexStructFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
+// and
+_device->SetFVF(VertexStructFVF);
+// ...
+// We also have to change the vertex buffer creation FVF-flag.
+result = _device->CreateVertexBuffer(
+ GetByteSize(vertices),
+ 0,
+ 0, // <- 0 indicates we use vertex declarations
+ D3DPOOL_DEFAULT,
+ &buffer,
+ nullptr);
+// Next we have to declare a new ComPtr.
+ComPtr<IDirect3DVertexDeclaration9> _vertexDecl{ };
+// ...
+result = _device->SetIndices(_indexBuffer.Get());
+if (FAILED(result))
+ return -1;
+// Now we have to declare and apply the vertex declaration.
+// Create a vector of vertex elements making up the vertex declaration.
+std::vector<D3DVERTEXELEMENT9> vertexDeclDesc {
+ { 0, // stream index
+ 0, // byte offset from the struct beginning
+ D3DDECLTYPE_FLOAT3, // data type (3d float vector)
+ D3DDECLMETHOD_DEFAULT, // tessellator operation
+ D3DDECLUSAGE_POSTION, // usage of the data
+ 0 }, // index (multiples usage of the same type)
+ { 0,
+ 12, // byte offset (3 * sizeof(float) bytes)
+ D3DDECLTYPE_D3DCOLOR,
+ D3DDECLMETHOD_DEFAULT,
+ D3DDECLUSAGE_COLOR,
+ 0 },
+ D3DDECL_END() // marks the end of the vertex declaration
+};
+// After having defined the vector we can create a vertex declaration from it.
+result = _device->CreateVertexDeclaration(
+ vertexDeclDesc.data(), // the vertex element array
+ &_vertexDecl); // receiving pointer
+if (FAILED(result))
+ return -1;
+// Apply the created vertex declaration.
+_device->SetVertexDeclaration(_vertexDecl.Get());
+// ...
+```
+
+## Shader
+
+The maximum shader model for Direct3D 9 is shader model 3.0. Even though every modern graphics card should support it, it is best to check for capabilities.
+
+```cpp
+// ...
+_device->SetVertexDeclaration(_vertexDecl.Get());
+// First we have to request the device capabilities.
+D3DCAPS9 deviceCaps{ };
+_device->GetDeviceCaps(&deviceCaps);
+// Now we check if shader model 3.0 is supported for the vertex shader.
+if (deviceCaps.VertexShaderVersion < D3DVS_VERSION(3, 0))
+ return -1;
+// And the same for the pixel shader.
+if (deviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
+ return -1;
+```
+
+Now that we are sure shader model 3.0 is supported let's create the vertex and pixel shader files.
+DirectX 9 introduced the HLSL (**High Level Shading Language**), a C-like shader language, which
+simplified the shader programming a lot, as you could only write shaders in shader assembly in DirectX 8.
+Let's create a simple vertex- and pixel shader.
+
+**Vertex Shader**
+
+```cpp
+// 3 4x4 float matrices representing the matrices we set in the fixed-function
+// pipeline by using the SetTransform() method.
+float4x4 projectionMatrix;
+float4x4 viewMatrix;
+float4x4 worldMatrix;
+// The input struct to the vertex shader.
+// It holds a 3d float vector for the position and a 4d float vector
+// for the color.
+struct VS_INPUT {
+ float3 position : POSITION;
+ float4 color : COLOR;
+};
+// The output struct of the vertex shader, that is passed to the pixel shader.
+struct VS_OUTPUT {
+ float4 position : POSITION;
+ float4 color : COLOR;
+};
+// The main function of the vertex shader returns the output it sends to the
+// pixel shader and receives it's input as a parameter.
+VS_OUTPUT main(VS_INPUT input) {
+ // Declare a empty struct, that the vertex shader returns.
+ VS_OUTPUT output;
+ // Set the output position to the input position and set
+ // the w-component to 1, as the input position is a 3d vector and
+ // the output position a 4d vector.
+ output.position = float4(input.position, 1.0f);
+ // Multiply the output position step by step with the world, view and
+ // projection matrices.
+ output.position = mul(output.position, worldMatrix);
+ output.position = mul(output.position, viewMatrix);
+ output.position = mul(output.position, projectionMatrix);
+ // Pass the input color unchanged to the pixel shader.
+ output.color = input.color;
+ // Return the output struct to the pixel shader.
+ // The position value is automatically used as the vertex position.
+ return output;
+}
+```
+
+**Pixel Shader**
+
+```cpp
+// The pixel shader input struct must be the same as the vertex shader output!
+struct PS_INPUT {
+ float4 position : POSITION;
+ float4 color : COLOR;
+};
+// The pixel shader simply returns a 4d vector representing the vertex color.
+// It receives it's input as a parameter just like the vertex shader.
+// We have to declare the output semantic as color to it gets interpreted
+// correctly.
+float4 main(PS_INPUT input) : COLOR {
+ return input.color;
+}
+```
+
+For more on semantics: [DirectX - Semantics](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics#vertex-shader-semantics)
+
+Now we have to do quite some changes to the code.
+
+```cpp
+ComPtr<IDirect3DDevice9> _device{ };
+ComPtr<IDirect3DVertexBuffer9> _vertexBuffer{ };
+ComPtr<IDirect3DIndexBuffer9> _indexBuffer{ };
+ComPtr<IDirect3DVertexDeclaration9> _vertexDecl{ };
+// We have to add a ComPtr for the vertex- and pixel shader, aswell as one
+// for the constants (matrices) in our vertex shader.
+ComPtr<IDirect3DVertexShader9> _vertexShader{ };
+ComPtr<IDirect3DPixelShader9> _pixelShader{ };
+ComPtr<ID3DXConstantTable> _vertexTable{ };
+// Declare the world and rotation matrix as global, because we use them in
+// WinMain and SetupTransform now.
+D3DXMATRIX _worldMatrix{ };
+D3DXMATRIX _rotationMatrix{ };
+// ...
+bool SetupTransform() {
+ // Set the world and rotation matrix to an identity matrix.
+ D3DXMatrixIdentity(&_worldMatrix);
+ D3DXMatrixIdentity(&_rotationMatrix);
+
+ D3DXMATRIX scaling{ };
+ D3DXMatrixScaling(&scaling, 10, 10, 1);
+ D3DXMatrixMultiply(&_worldMatrix, &scaling, &_rotationMatrix);
+ // After multiplying the scalation and rotation matrix the have to pass
+ // them to the shader, by using a method from the constant table
+ // of the vertex shader.
+ HRESULT result{ };
+ result = _vertexTable->SetMatrix(
+ _device.Get(), // direct3d device
+ "worldMatrix", // matrix name in the shader
+ &_worldMatrix); // pointer to the matrix
+ if (FAILED(result))
+ return false;
+
+ D3DXMATRIX view{ };
+ D3DXMatrixLookAtLH(&view, &D3DXVECTOR3{ 0.0f, 0.0f, -20.0f },
+ &D3DXVECTOR3{ 0.0f, 0.0f, 0.0f }, &D3DXVECTOR3{ 0.0f, 1.0f, 0.0f });
+ // Do the same for the view matrix.
+ result = _vertexTable->SetMatrix(
+ _device.Get(), // direct 3d device
+ "viewMatrix", // matrix name
+ &view); // matrix
+ if (FAILED(result))
+ return false;
+
+ D3DXMATRIX projection{ };
+ D3DXMatrixPerspectiveFovLH(&projection, D3DXToRadian(60.0f),
+ 1024.0f / 768.0f, 0.0f, 100.0f);
+ // And also for the projection matrix.
+ result = _vertexTable->SetMatrix(
+ _device.Get(),
+ "projectionMatrix",
+ &projection);
+ if (FAILED(result))
+ return false;
+
+ D3DXMatrixRotationY(&_rotationMatrix, D3DXToRadian(0.5f));
+ return true;
+}
+// ...
+// Vertex and index buffer creation aswell as initialization stay unchanged.
+// ...
+// After checking that shader model 3.0 is available we have to compile and
+// create the shaders.
+// Declare two temporary buffers storing the compiled shader code.
+ID3DXBuffer* vertexShaderBuffer{ };
+ID3DXBuffer* pixelShaderBuffer{ };
+result = D3DXCompileShaderFromFile("vertex.hlsl", // shader name
+ nullptr, // macro definitions
+ nullptr, // special includes
+ "main", // entry point name
+ "vs_3_0", // shader model version
+ 0, // special flags
+ &vertexShaderBuffer, // code buffer
+ nullptr, // error message
+ &_vertexTable); // constant table
+if (FAILED(result))
+ return -1;
+// After the vertex shader compile the pixel shader.
+result = D3DXCompileShaderFromFile("pixel.hlsl",
+ nullptr,
+ nullptr,
+ "main",
+ "ps_3_0", // pixel shader model 3.0
+ 0,
+ &pixelShaderBuffer,
+ nullptr,
+ nullptr); // no need for a constant table
+if (FAILED(result))
+ return -1;
+// Create the vertex shader from the code buffer.
+result = _device->CreateVertexShader(
+ (DWORD*)vertexShaderBuffer->GetBufferPointer(), // code buffer
+ &_vertexShader); // vertex shader pointer
+if (FAILED(result))
+ return -1;
+
+result = _device->CreatePixelShader(
+ (DWORD*)pixelShaderBuffer->GetBufferPointer(),
+ &_pixelShader);
+if (FAILED(result))
+ return -1;
+// Release the temporary code buffers after the shaders are created.
+vertexShaderBuffer->Release();
+pixelShaderBuffer->Release();
+// Apply the vertex- and pixel shader.
+_device->SetVertexShader(_vertexShader.Get());
+_device->SetPixelShader(_pixelShader.Get());
+// Apply the transform after the shaders have been set.
+if (!SetupTransform())
+ return -1;
+// You can also REMOVE the call so set the lighting render state.
+_device->SetRenderState(D3DRS_LIGHTING, false);
+```
+
+You can find the complete code here: [DirectX - 3](https://pastebin.com/y4NrvawY)
+
+## Texturing
+
+```cpp
+// First we need to declare a ComPtr for the texture.
+ComPtr<IDirect3DTexture9> _texture{ };
+// Then we have to change the vertex struct.
+struct VStruct {
+ float x, y, z;
+ float u, v; // Add texture u and v coordinates
+ D3DCOLOR color;
+};
+// In the vertex declaration we have to add the texture coordinates.
+// the top left of the texture is u: 0, v: 0.
+std::vector<VStruct> vertices {
+ VStruct{ -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, ... }, // bottom left
+ VStruct{ -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, ... }, // top left
+ VStruct{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, ... }, // top right
+ VStruct{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, ... } // bottom right
+};
+// Next is the vertex declaration.
+std::vector<D3DVERTEXELEMENT9> vertexDecl{
+ {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
+ // Add a 2d float vector used for texture coordinates.
+ {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
+ // The color offset is not (3 + 2) * sizeof(float) = 20 bytes
+ {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
+ D3DDECL_END()
+};
+// Now we have to load the texture and pass its to the shader.
+// ...
+_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+// Create a Direct3D texture from a png file.
+result = D3DXCreateTextureFromFile(_device.Get(), // direct3d device
+ "texture.png", // texture path
+ &_texture); // receiving texture pointer
+if (FAILED(result))
+ return -1;
+// Attach the texture to shader stage 0, which is equal to texture register 0
+// in the pixel shader.
+_device->SetTexture(0, _texture.Get());
+```
+
+With the main code ready we now have to adjust the shaders to these changes.
+
+**Vertex Shader**
+
+```cpp
+float4x4 projectionMatrix;
+float4x4 viewMatrix;
+float4x4 worldMatrix;
+// Add the texture coordinates to the vertex shader in- and output.
+struct VS_INPUT {
+ float3 position : POSITION;
+ float2 texcoord : TEXCOORD;
+ float4 color : COLOR;
+};
+
+struct VS_OUTPUT {
+ float4 position : POSITION;
+ float2 texcoord : TEXCOORD;
+ float4 color : COLOR;
+};
+
+VS_OUTPUT main(VS_INPUT input) {
+ VS_OUTPUT output;
+
+ output.position = float4(input.position, 1.0f);
+ output.position = mul(output.position, worldMatrix);
+ output.position = mul(output.position, viewMatrix);
+ output.position = mul(output.position, projectionMatrix);
+
+ output.color = input.color;
+ // Set the texcoord output to the input.
+ output.texcoord = input.texcoord;
+
+ return output;
+}
+```
+
+**Pixel Shader**
+
+```cpp
+// Create a sampler called "sam0" using sampler register 0, which is equal
+// to the texture stage 0, to which we passed the texture.
+sampler sam0 : register(s0);
+
+struct PS_INPUT {
+ float4 position : POSITION;
+ float2 texcoord : TEXCOORD;
+ float4 color : COLOR;
+};
+
+float4 main(PS_INPUT input) : COLOR{
+ // Do a linear interpolation between the texture color and the input color
+ // using 75% of the input color.
+ // tex2D returns the texture data at the specified texture coordinate.
+ return lerp(tex2D(sam0, input.texcoord), input.color, 0.75f);
+}
+```
+
+## Quotes
+<sup>[1]</sup>[DirectX - Wikipedia](https://en.wikipedia.org/wiki/DirectX)
diff --git a/dynamic-programming.html.markdown b/dynamic-programming.html.markdown
index f5f1743c..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,4 +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/bash-gr.html.markdown b/el-gr/bash-gr.html.markdown
new file mode 100644
index 00000000..2989969d
--- /dev/null
+++ b/el-gr/bash-gr.html.markdown
@@ -0,0 +1,528 @@
+---
+category: tool
+tool: bash
+contributors:
+ - ["Dimitri Kokkonis", "https://github.com/kokkonisd"]
+filename: LearnBash-gr.sh
+lang: el-gr
+---
+
+Η λέξη «bash» είναι ένα από τα ονόματα του unix shell (τερματικός), το οποίο
+διανέμεται επίσης ως προεπιλεγμένος τερματικός για το λειτουργικό σύστημα GNU, τα Linux και τα Mac OS X.
+Σχεδόν όλα τα παραδείγματα που ακολουθούν μπορούν να αποτελέσουν μέρος ενός
+προγράμματος τερματικού (shell script) ή να εκτελεσθούν απευθείας από τον
+τερματικό.
+
+[Διαβάστε περισσότερα εδώ.](http://www.gnu.org/software/bash/manual/bashref.html)
+
+```bash
+#!/usr/bin/env bash
+# Η πρώτη γραμμή του προγράμματος είναι το shebang που υποδεικνύει στο σύστημα
+# πώς να εκτελέσει το πρόγραμμα: http://en.wikipedia.org/wiki/Shebang_(Unix)
+# Όπως ήδη θα καταλάβατε, τα σχόλια ξεκινούν με τον χαρακτήρα #. Το shebang
+# είναι επίσης ένα σχόλιο.
+# ΣτΜ.: Τα ονόματα των μεταβλητών είναι γραμμένα σε greeklish καθώς η Bash δεν
+# επιτρέπει την χρήση unicode χαρακτήρων.
+
+# Ένα απλό παράδειγμα τύπου «hello world»:
+echo Καλημέρα, Κόσμε! # => Καλημέρα, Κόσμε!
+
+# Κάθε εντολή ξεκινά σε μια νέα γραμμή, ή μετά από ένα ελληνικό ερωτηματικό:
+echo 'Αυτή είναι η πρώτη γραμμή'; echo 'Αυτή είναι η δεύτερη γραμμή'
+# => Αυτή είναι η πρώτη γραμμή
+# => Αυτή είναι η δεύτερη γραμμή
+
+# Ορίζουμε μεταβλητές ως εξής:
+Metavliti="Κάποιο αλφαριθμητικό"
+
+# Αλλά όχι ως εξής:
+Metavliti = "Κάποιο αλφαριθμητικό" # => επιστρέφει το λάθος
+# «Metavliti: command not found»
+# Η Bash θα καταλάβει πως η Metavliti είναι κάποια εντολή που πρέπει να
+# εκτελέσει και θα επιστρέψει ένα λάθος γιατί δεν μπορεί να την βρει.
+
+# Ούτε έτσι μπορούμε να δηλώσουμε μεταβλητές:
+Metavliti= 'Κάποιο αλφαριθμητικό' # => επιστρέφει το λάθος: «Κάποιο
+ # αλφαριθμητικό: command not found»
+# Η Bash θα καταλάβει πως το αλφαριθμητικό «Κάποιο αλφαριθμητικό» είναι μια
+# εντολή που πρέπει να εκτελέσει και θα επιστρέψει ένα λάθος γιατί δεν μπορεί
+# να την βρει. (Σε αυτή την περίπτωση το τμήμα της εντολής «Metavliti=» θα
+# ερμηνευθεί ως ορισμός μεταβλητής ισχύων μόνο στο πλαίσιο της εντολής
+# «Κάποιο αλφαριθμητικό».)
+
+# Ας χρησιμοποιήσουμε την μεταβλητή:
+echo $Metavliti # => Κάποιο αλφαριθμητικό
+echo "$Metavliti" # => Κάποιο αλφαριθμητικό
+echo '$Metavliti' # => $Metavliti
+# Όταν χρησιμοποιούμε την ίδια την μεταβλητή - είτε είναι για να της δώσουμε
+# μια νέα αξία, για να την εξάγουμε ή για οτιδήποτε άλλο - γράφουμε το όνομά
+# της χωρίς τον χαρακτήρα $. Αν θέλουμε να χρησιμοποιήσουμε την αξία της
+# μεταβλητής, πρέπει να χρησιμοποιήσουμε τον χαρατήρα $.
+# Να σημειωθεί πώς ο χαρακτήρας ' δεν θα μετατρέψει τις μεταβλητές στις αξίες
+# τους!
+
+# Επέκταση παραμέτρων ${ }:
+echo ${Metavliti} # => Κάποιο αλφαριθμητικό
+# Αυτή είναι μια απλή χρήση της επέκτασης παραμέτρων.
+# Η επέκταση παραμέτρων εξάγει μια αξία από μια μεταβλητή.
+# Κατά την επέκταση η τιμή ή η παράμετρος μπορεί να τροποποιηθεί.
+# Ακολουθούν άλλες μετατροπές που μπορούν να προστεθούν σε αυτή την επέκταση.
+
+# Αντικατάσταση αλφαριθμητικών μέσα σε μεταβλητές
+echo ${Metavliti/Κάποιο/Ένα} # => Ένα αλφαριθμητικό
+# Αυτή η τροποποίηση θα αντικαταστήσει την πρώτη εμφάνιση της λέξης «Κάποιο»
+# με την λέξη «Ένα».
+
+# Υποαλφαριθμητικό μιας μεταβλητής
+Mikos=7
+echo ${Metavliti:0:Mikos} # => Κάποιο
+# Αυτή η τροποποίηση θα επιστρέψει μόνο τους πρώτους 7 χαρακτήρες της τιμής
+# της μεταβλητής.
+echo ${Metavliti: -5} # => ητικό
+# Αυτή η τροποποίηση θα επιστρέψει τους τελευταίους 5 χαρακτήρες (προσοχή στο
+# κενό πριν το -5).
+
+# Μήκος αλφαριθμητικού
+echo ${#Metavliti} # => 20
+
+# Προεπιλεγμένη αξία για μια μεταβλητή
+echo ${Foo:-"ΠροεπιλεγμένηΑξίαΑνΤοFooΕίναιΑόριστοΉΆδειο"}
+# => ΠροεπιλεγμένηΑξίαΑνΤοFooΕίναιΑόριστοΉΆδειο
+# Αυτό δουλεύει στην περίπτωση που το Foo είναι αόριστο (Foo=) ή άδειο
+# (Foo="")· το μηδέν (Foo=0) επιστρέφει 0.
+# Να σημειωθεί πως αυτή η εντολή απλώς επιστρέφει την προεπιλεγμένη αξία και
+# δεν τροποποιεί την αξία της μεταβλητής.
+
+# Ορισμός ενός πίνακα με 6 στοιχεία
+pinakas0=(ένα δύο τρία τέσσερα πέντε έξι)
+# Εντολή που τυπώνει το πρώτο στοιχείο
+echo $pinakas0 # => "ένα"
+# Εντολή που τυπώνει το πρώτο στοιχείο
+echo ${pinakas0[0]} # => "ένα"
+# Εντολή που τυπώνει όλα τα στοιχεία
+echo ${pinakas0[@]} # => "ένα δύο τρία τέσσερα πέντε έξι"
+# Εντολή που τυπώνει τον αριθμό των στοιχείων
+echo ${#pinakas0[@]} # => "6"
+# Εντολή που τυπώνει τον αριθμό των χαρακτήρων στο τρίτο στοιχείο
+echo ${#pinakas0[2]} # => "4"
+# Εντολή που τυπώνει δύο στοιχεία ξεκινώντας από το τέταρτο
+echo ${pinakas0[@]:3:2} # => "τέσσερα πέντε"
+# Εντολή που τυπώνει όλα τα στοιχεία, το καθένα σε διαφορετική γραμμή
+for i in "${pinakas0[@]}"; do
+ echo "$i"
+done
+
+# Επέκταση αγκίστρων { }
+# Χρησιμοποιείται για την παραγωγή αλφαριθμητικών
+echo {1..10} # => 1 2 3 4 5 6 7 8 9 10
+echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z
+# Η εντολή θα τυπώσει όλο το εύρος, από την πρώτη μέχρι την τελευταία αξία
+
+# Ενσωματωμένες μεταβλητές
+# Υπάρχουν κάποιες χρήσιμες ενσωματωμένες μεταβλητές, όπως:
+echo "Η τιμή την οποία επέστρεψε το τελευταίο πρόγραμμα: $?"
+echo "Ο αριθμός PID αυτού του script: $$"
+echo "Ο αριθμός των παραμέτρων που περάστηκαν σε αυτό το script: $#"
+echo "Όλες οι παράμετροι που περάστηκαν σε αυτό το script: $@"
+echo "Οι παράμετροι του script διαχωρισμένες σε μεταβλητές: $1 $2..."
+
+# Τώρα που γνωρίζουμε πως να τυπώνουμε (echo) και να χρησιμοποιούμε μεταβλητές,
+# ας μάθουμε κάποια από τα υπόλοιπα βασικά στοιχεία της Bash!
+
+# Ο τρέχων κατάλογος (ή αλλιώς, φάκελος) μπορεί να βρεθεί μέσω της εντολής
+# `pwd`.
+# `pwd` σημαίνει «print working directory».
+# Μπορούμε επίσης να χρησιμοποιούμε την ενσωματωμένη μεταβλητή `$PWD`.
+# Παρακολουθήστε πως οι δύο εντολές που ακολουθούν είναι ισοδύναμες:
+echo "Είμαι στον κατάλογο $(pwd)" # εκτελεί την εντολή `pwd` και τυπώνει το
+ # αποτέλεσμα
+echo "Είμαι στον κατάλογο $PWD" # τυπώνει την αξία της μεταβλητής
+
+# Αν έχετε πολλά μηνύματα στον τερματικό, η εντολή `clear` μπορεί να
+# «καθαρίσει» την οθόνη σας
+clear
+# Η συντόμευση Ctrl-L δουλεύει επίσης όσον αφορά το «καθάρισμα»
+
+# Ας διαβάσουμε μια αξία από κάποια είσοδο:
+echo "Πώς σε λένε;"
+read Onoma # Προσέξτε πως δεν χρειάστηκε να ορίσουμε μια νέα μεταβλητή
+echo Καλημέρα, $Onoma!
+
+# Η δομή των if statements έχει ως εξής:
+# (μπορείτε να εκτελέσετε την εντολή `man test` για περισσότερες πληροφορίες
+# σχετικά με τα conditionals)
+if [ $Onoma != $USER ]
+then
+ echo "Το όνομά σου δεν είναι το όνομα χρήστη σου"
+else
+ echo "Το όνομά σου είναι το όνομα χρήστη σου"
+fi
+# Η συνθήκη είναι αληθής αν η τιμή του $Onoma δεν είναι ίδια με το τρέχον
+# όνομα χρήστη στον υπολογιστή
+
+# ΣΗΜΕΙΩΣΗ: Αν το $Onoma είναι άδειο, η Bash βλέπει την συνθήκη ως:
+if [ != $USER ]
+# το οποίο αποτελεί συντακτικό λάθος
+# οπότε ο «ασφαλής» τρόπος να χρησιμοποιούμε εν δυνάμει άδειες μεταβλητές στην
+# Bash είναι ο εξής:
+if [ "$Onoma" != $USER ] ...
+# ο οποίος, όταν το $Onoma είναι άδειο, θα ερμηνευθεί από την Bash ως:
+if [ "" != $USER ] ...
+# το οποίο και δουλεύει όπως θα περιμέναμε.
+
+# Υπάρχει επίσης η εκτέλεση εντολών βάσει συνθηκών
+echo "Εκτελείται πάντα" || echo "Εκτελείται μόνο αν η πρώτη εντολή αποτύχει"
+# => Εκτελείται πάντα
+echo "Εκτελείται πάντα" && echo "Εκτελείται μόνο αν η πρώτη εντολή ΔΕΝ αποτύχει"
+# => Εκτελείται πάντα
+# => Εκτελείται μόνο αν η πρώτη εντολή ΔΕΝ αποτύχει
+
+
+# Για να χρησιμοποιήσουμε τους τελεστές && και || με τα if statements,
+# χρειαζόμαστε πολλαπλά ζευγάρια αγκύλων:
+if [ "$Onoma" == "Σταύρος" ] && [ "$Ilikia" -eq 15 ]
+then
+ echo "Αυτό θα εκτελεστεί αν το όνομα ($Onoma) είναι Σταύρος ΚΑΙ η ηλικία ($Ilikia) είναι 15."
+fi
+
+if [ "$Onoma" == "Δανάη" ] || [ "$Onoma" == "Ζαχαρίας" ]
+then
+ echo "Αυτό θα εκτελεστεί αν το όνομα ($Onoma) είναι Δανάη Ή Ζαχαρίας."
+fi
+
+# Υπάρχει επίσης ο τελεστής `=~`, που εκτελεί ένα regex πάνω σε ένα
+# αλφαριθμητικό:
+Email=me@example.com
+if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]]
+then
+ echo "Η διεύθυνση email είναι σωστά διατυπωμένη!"
+fi
+# Να σημειωθεί πως ο τελεστής `=~` δουλεύει μόνο με διπλές αγκύλες [[ ]],
+# που είναι ωστόσο διαφορετικές από τις μονές [ ].
+# Δείτε το http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs
+# για περισσότερες πληροφορίες σχετικά με αυτό.
+
+# Επαναπροσδιορισμός της εντολής `ping` ως alias (ψευδώνυμο) για την αποστολή 5
+# πακέτων
+alias ping='ping -c 5'
+# Ακύρωση του alias και χρήση της εντολής όπως είναι κανονικά ορισμένη
+\ping 192.168.1.1
+# Εκτύπωση όλων των aliases
+alias -p
+
+# Οι μαθηματικές εκφράσεις ορίζονται ως εξής:
+echo $(( 10 + 5 )) # => 15
+
+# Αντίθετα με άλλες γλώσσες προγραμματισμού, η Bash είναι επίσης ένα shell, άρα
+# δουλεύει στο πλαίσιο ενός «τρέχοντος καταλόγου». Μπορούμε να δούμε μια λίστα
+# αρχείων και καταλόγων στον τρέχων κατάλογο με την εντολή ls:
+ls # Τυπώνει μια λίστα των αρχείων και υποκαταλόγων που περιέχονται στον τρέχων
+ # κατάλογο
+
+# Αυτή η εντολή έχει επιλογές που ελέγχουν την εκτέλεσή της:
+ls -l # Τυπώνει κάθε αρχείο και κατάλογο σε διαφορετική γραμμή
+ls -t # Ταξινομεί τα περιεχόμενα του καταλόγου με βάσει την ημερομηνία
+ # τελευταίας τροποποίησης (σε φθίνουσα σειρά)
+ls -R # Εκτελεί την εντολή `ls` αναδρομικά στον τρέχων κατάλογο και σε όλους
+ # τους υποκαταλόγους του.
+
+# Τα αποτελέσματα μιας εντολής μπορούν να μεταβιβαστούν σε μιαν άλλη.
+# Η εντολή `grep` φιλτράρει τα δεδομένα που δέχεται βάσει μοτίβων.
+# Έτσι, μπορούμε να τυπώσουμε μια λίστα αρχείων κειμένου (.txt) στον τρέχων
+# κατάλογο:
+ls -l | grep "\.txt"
+
+# Μπορούμε να χρησιμοποιήσουμε την εντολή `cat` για να τυπώσουμε το περιεχόμενο
+# ενός ή περισσότερων αρχείων στην προεπιλεγμένη έξοδο (stdout):
+cat file.txt
+
+# Μπορούμε επίσης να διαβάσουμε το αρχείο μέσω της `cat`:
+Periexomena=$(cat file.txt)
+echo "ΑΡΧΗ ΤΟΥ ΑΡΧΕΙΟΥ\n$Periexomena\nΤΕΛΟΣ ΤΟΥ ΑΡΧΕΙΟΥ" # Ο χαρακτήρας "\n"
+ # δημιουργεί μια νέα
+ # γραμμή
+# => ΑΡΧΗ ΤΟΥ ΑΡΧΕΙΟΥ
+# => [περιεχόμενα του αρχείου file.txt]
+# => ΤΕΛΟΣ ΤΟΥ ΑΡΧΕΙΟΥ
+
+# Μπορούμε να χρησιμοποιήσουμε την εντολή `cp` για να αντιγράψουμε αρχεία ή
+# καταλόγους από ένα σημείο σε ένα άλλο.
+# Η εντολή `cp` δημιουργεί ΝΕΕΣ εκδοχές των πρωτοτύπων, το οποίο σημαίνει ότι
+# μια τροποποίηση του αντιγράφου δεν θα επηρεάσει το πρωτότυπο (και
+# αντιστρόφως).
+# Να σημειωθεί πως αν υπάρχει ήδη αρχείο ή κατάλογος με το ίδιο όνομα στην ίδια
+# θέση με το αντίγραφο, το αντίγραφο θα αντικαταστήσει το αρχείο/κατάλογο και
+# άρα τα δεδομένα του θα χαθούν.
+cp prototipo.txt antigrafo.txt
+cp -r prototipo/ antigrafo/ # Αναδρομική αντιγραφή (αντιγραφή όλων των
+ # περιεχομένων του καταλόγου prototipo/)
+
+# Ενημερωθείτε σχετικά με τις εντολές `scp` και `sftp` αν σχεδιάζετε να
+# αντιγράψετε αρχεία από έναν υπολογιστή σε έναν άλλο.
+# Η εντολή `scp` μοιάζει πολύ με την `cp`, ενώ η `sftp` είναι πιο διαδραστική.
+
+# Μπορούμε να χρησιμοποιήσουμε την εντολή `mv` για να μετακινήσουμε αρχεία ή
+# καταλόγους από μια θέση σε μια άλλη.
+# Η εντολή `mv` μοιάζει με την `cp`, με τη διαφορά ότι διαγράφει το πρωτότυπο.
+# Η `mv` χρησιμοποιείται επίσης για τη μετονομασία αρχείων!
+mv prototipo.txt prototipo2.txt
+
+# Δεδομένου του ότι η Bash δουλεύει στο πλαίσιο του τρέχοντος καταλόγου,
+# μπορεί να θελήσουμε να τρέξουμε κάποια εντολή σε κάποιον άλλο κατάλογο.
+# Η εντολή `cd` (Change Directory) μας επιτρέπει να αλλάξουμε θέση μέσα στο
+# σύστημα αρχείων:
+cd ~ # Μετατόπιση στον κατάλογο «home»
+cd # Αυτή η εντολή μας μετατοπίζει επίσης στον κατάλογο «home»
+cd .. # Μετατόπιση προς τα πάνω κατά έναν κατάλογο
+ # (για παράδειγμα, μετατόπιση από τη θέση /home/username/Downloads
+ # στη θέση /home/username)
+cd /home/username/Documents # Μετατόπιση προς έναν συγκεκριμένο κατάλογο
+cd ~/Documents/.. # Μετατόπιση προς τον κατάλογο «home»... σωστά;
+cd - # Μετατόπιση προς τον προηγούμενο κατάλογο
+# => /home/username/Documents
+
+# Μπορούμε να χρησιμοποιήσουμε subshells για να δουλέψουμε σε πολλούς
+# διαφορετικούς καταλόγους:
+(echo "Πρώτα, είμαι εδώ: $PWD") && (cd kapoiosKatalogos; echo "Έπειτα, είμαι εδώ: $PWD")
+pwd # Εδώ θα είμαστε στον πρώτο κατάλογο
+
+# Μπορούμε να χρησιμοποιήσουμε την εντολή `mkdir` για να δημιουργήσουμε νέους
+# καταλόγους.
+mkdir neosKatalogos
+# Η επιλογή `-p` επιτρέπει σε ενδιάμεσους καταλόγους να δημιουργηθούν αν
+# χρειάζεται.
+mkdir -p neosKatalogos/me/epipleon/katalogous
+# Αν οι ενδιάμεσοι κατάλογοι δεν υπήρχαν ήδη, η παραπάνω εντολή χωρίς την
+# επιλογή `-p` θα είχε επιστρέψει κάποιο λάθος.
+
+# Μπορούμε να διευθύνουμε τις εισόδους και εξόδους των εντολών (χρησιμοποιώντας
+# τα κανάλια stdin, stdout και stderr).
+# Για παράδειγμα, μπορούμε να «διαβάσουμε» από το stdin μέχρι να βρεθεί ένα
+# ^EOF$ (End Of File) και να αντικαταστήσουμε το περιεχόμενο του αρχείου
+# hello.py με τις γραμμές που διαβάσαμε έως και πριν το "EOF":
+cat > hello.py << EOF
+#!/usr/bin/env python
+from __future__ import print_function
+import sys
+print("#stdout", file=sys.stdout)
+print("#stderr", file=sys.stderr)
+for line in sys.stdin:
+ print(line, file=sys.stdout)
+EOF
+
+# Μπορούμε να τρέξουμε το πρόγραμμα Python «hello.py» με διάφορες
+# ανακατευθύνσεις χρησιμοποιώντας τα stdin, stdout και stderr:
+python hello.py < "eisodos.in" # Περνάμε το eisodos.in ως είσοδο στο πρόγραμμα
+
+python hello.py > "eksodos.out" # Ανακατευθύνουμε την έξοδο του προγράμματος
+ # προς το αρχείο eksodos.out
+
+python hello.py 2> "lathos.err" # ανακατευθύνουμε την έξοδο λάθους (stderr)
+ # προς το αρχείο lathos.err
+
+python hello.py > "eksodos-kai-lathos.log" 2>&1
+# Ανακατευθύνουμε την κανονική έξοδο (stdout) και την έξοδο λάθους (stderr)
+# προς το αρχείο eksodos-kai-lathos.log
+
+python hello.py > /dev/null 2>&1
+# Ανακατευθύνουμε όλες τις εξόδους προς τη «μαύρη τρύπα» που λέγεται /dev/null,
+# δηλαδή τίποτα δεν θα τυπωθεί στον τερματικό
+
+# Αν θέλετε να προσθέσετε την έξοδο σε κάποιο αρχείο αντί να διαγράψετε τα
+# περιεχόμενά του με τη νέα έξοδο, μπορείτε να χρησιμοποιήσετε τον τελεστή
+# `>>` αντί στη θέση του `>`:
+python hello.py >> "eksodos.out" 2>> "lathos.err"
+
+# Αντικατάσταση του αρχείου eksodos.out, προσθήκη στο αρχείο lathos.err, και
+# καταμέτρηση των γραμμών τους:
+info bash 'Basic Shell Features' 'Redirections' > eksodos.out 2>> lathos.err
+wc -l eksodos.out lathos.err
+
+# Μπορούμε να εκτελέσουμε μια εντολή και να τυπώσουμε τον file descriptor της
+# (https://en.wikipedia.org/wiki/File_descriptor)
+# Για παράδειγμα: /dev/fd/123
+# Δείτε επίσης: man fd
+echo <(echo "#καλημέρακόσμε")
+
+# Αντικατάσταση του περιεχομένου του αρχείου eksodos.out με το αλφαριθμητικό
+# «#καλημέρακόσμε»:
+cat > eksodos.out <(echo "#καλημέρακόσμε")
+echo "#καλημέρακόσμε" > eksodos.out
+echo "#καλημέρακόσμε" | cat > eksodos.out
+echo "#καλημέρακόσμε" | tee eksodos.out >/dev/null
+
+# Εκκαθάριση προσωρινών αρχείων με την επιλογή `-v` (verbose) (προσθέστε την
+# επιλογή `-i` για περισσότερη διάδραση)
+# ΠΡΟΣΟΧΗ: τα αποτελέσματα της εντολής `rm` είναι μόνιμα.
+rm -v eksodos.out lathos.err eksodos-kai-lathos.log
+rm -r tempDir/ # Αναδρομική διαγραφή
+
+# Οι εντολές μπορούν να αντικατασταθούν μέσα σε άλλες εντολές χρησιμοποιώντας
+# το μοτίβο $( ).
+# Το παράδειγμα που ακολουθεί τυπώνει τον αριθμό των αρχείων και των καταλόγων
+# στον τρέχων κατάλογο.
+echo "Υπάρχουν $(ls | wc -l) αντικείμενα εδώ."
+
+# Μπορούμε να επιτύχουμε το ίδιο αποτέλεσμα με τους χαρακτήρες ``, αλλά δεν
+# μπορούμε να τους χρησιμοποιήσουμε αναδρομικά (δηλαδή `` μέσα σε ``).
+# Ο προτεινόμενος τρόπος από την Bash είναι το μοτίβο $( ).
+echo "Υπάρχουν `ls | wc -l` αντικείμενα εδώ."
+
+# Η Bash έχει επίσης τη δομή `case` που δουλεύει παρόμοια με τη δομή switch
+# όπως στην Java ή την C++ για παράδειγμα:
+case "$Metavliti" in
+ # Λίστα μοτίβων για τις συνθήκες που θέλετε να ορίσετε:
+ 0) echo "Η μεταβλητή έχει ένα μηδενικό.";;
+ 1) echo "Η μεταβλητή έχει έναν άσσο.";;
+ *) echo "Η μεταβλητή δεν είναι αόριστη (null).";;
+esac
+
+# Οι βρόγχοι `for` εκτελούνται τόσες φορές όσο είναι το πλήθος των παραμέτρων
+# που τους δίνονται:
+# Το περιεχόμενο της μεταβλητής $Metavliti τυπώνεται τρεις φορές.
+for Metavliti in {1..3}
+do
+ echo "$Metavliti"
+done
+# => 1
+# => 2
+# => 3
+
+# Μπορούμε επίσης να το γράψουμε πιο «παραδοσιακά»:
+for ((a=1; a <= 3; a++))
+do
+ echo $a
+done
+# => 1
+# => 2
+# => 3
+
+# Μπορούμε επίσης να περάσουμε αρχεία ως παραμέτρους.
+# Το παράδειγμα που ακολουθεί θα τρέξει την εντολή `cat` με τα αρχεία file1
+# και file2:
+for Metavliti in file1 file2
+do
+ cat "$Metavliti"
+done
+
+# Μπορούμε ακόμα να χρησιμοποιήσουμε την έξοδο μας εντολής.
+# Το παράδειγμα που ακολουθεί θα τρέξει την εντολή `cat` με την έξοδο της
+# εντολής `ls`.
+for Output in $(ls)
+do
+ cat "$Output"
+done
+
+# Ο βρόγχος `while` έχει ως εξής:
+while [ true ]
+do
+ echo "το «σώμα» του βρόγχου μπαίνει εδώ..."
+ break
+done
+# => το «σώμα» του βρόγχου μπαίνει εδώ...
+
+# Μπορούμε επίσης να ορίσουμε συναρτήσεις, ως εξής:
+function synartisi ()
+{
+ echo "Οι παράμετροι συναρτήσεων δουλεύουν όπως αυτές των προγραμμάτων: $@"
+ echo "Και: $1 $2..."
+ echo "Αυτή είναι μια συνάρτηση"
+ return 0
+}
+# Ας καλέσουμε την συνάρτηση `synartisi` με δύο παραμέτρους, param1 και param2
+synartisi param1 param2
+# => Οι παράμετροι συναρτήσεων δουλεύουν όπως αυτές των προγραμμάτων: param1 param2
+# => Και: param1 param2...
+# => Αυτή είναι μια συνάρτηση
+
+# Ή επίσης:
+synartisi2 ()
+{
+ echo "Ένας άλλος τρόπος να ορίσουμε συναρτήσεις!"
+ return 0
+}
+# Ας καλέσουμε την συνάρτηση `synartisi2` χωρίς παραμέτρους:
+synartisi2 # => Ένας άλλος τρόπος να ορίσουμε συναρτήσεις!
+
+# Ας καλέσουμε την πρώτη συνάρτηση:
+synartisi "Το όνομά μου είναι" $Onoma
+
+# Υπάρχουν πολλές χρήσιμες εντολές που μπορείτε να μάθετε.
+# Για παράδειγμα, αυτή που ακολουθεί τυπώνει τις 10 τελευταίες γραμμές του
+# αρχείου file.txt:
+tail -n 10 file.txt
+
+# Ενώ αυτή τυπώνει τις 10 πρώτες:
+head -n 10 file.txt
+
+# Αυτή ταξινομεί τις γραμμές:
+sort file.txt
+
+# Αυτή αναφέρει ή παραλείπει τις γραμμές που επαναλαμβάνονται (η επιλογή
+# -d τις αναφέρει):
+uniq -d file.txt
+
+# Αυτή τυπώνει μόνο ό,τι βρίσκεται πριν τον πρώτο χαρακτήρα «,» σε κάθε γραμμή:
+cut -d ',' -f 1 file.txt
+
+# Αυτή αντικαθιστά κάθε εμφάνιση της λέξης «οκ» με τη λέξη «τέλεια» στο αρχείο
+# file.txt (δέχεται επίσης μοτίβα regex):
+sed -i 's/οκ/τέλεια/g' file.txt
+
+# Αυτή τυπώνει στο stdout όλες τις γραμμές που είναι συμβατές με κάποιο
+# συγκεκριμένο μοτίβο regex.
+# Για παράδειγμα, όλες τις γραμμές που ξεκινούν με «καλημέρα» και τελειώνουν με
+# «καληνύχτα»:
+grep "^καλημέρα.*καληνύχτα$" file.txt
+
+# Η επιλογή `-c` θα τυπώσει τον αριθμό των γραμμών που περιέχουν το μοτίβο:
+grep -c "^καλημέρα.*καληνύχτα$" file.txt
+
+# Άλλες χρήσιμες επιλογές:
+grep -r "^καλημέρα.*καληνύχτα$" someDir/ # Αναδρομική εκτέλεση μέσα σε κάποιο κατάλογο
+grep -n "^καλημέρα.*καληνύχτα$" file.txt # Τυπώνει επίσης τον αριθμό των γραμμών
+grep -rI "^καλημέρα.*καληνύχτα$" someDir/ # Αναδρομική εκτέλεση αγνοώντας τα αρχεία binary
+
+# Η ίδια εντολή, αλλά τώρα αγνοώντας τις γραμμές που περιέχουν «αντίο»
+grep "^καλημέρα.*καληνύχτα$" file.txt | grep -v "αντίο"
+
+# Αν θέλετε να ψάξετε κυριολεκτικά για ένα αλφαριθμητικό, και όχι για κάποιο
+# μοτίβο, μπορείτε να χρησιμοποιήσετε την εντολή `fgrep` (ή `grep -F`):
+fgrep "καλημέρα" file.txt
+
+# Η εντολή `trap` επιτρέπει την εκτέλεση μιας εντολής μόλις το πρόγραμμά μας
+# λάβει κάποιο σήμα. Στο παράδειγμα που ακολουθεί, η εντολή `trap` θα
+# εκτελέσει την εντολή `rm` αν λάβει κάποιο από τα τρία σήματα που ακολουθούν
+# (SIGHUP, SIGINT, SIGTERM):
+trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM
+
+# Η εντολή `sudo` (SuperUser Do) χρησιμοποιείται για να εκτελέσουμε εντολές
+# με προνόμια υπερχρήστη (superuser):
+ONOMA1=$(whoami)
+ONOMA2=$(sudo whoami)
+echo "Ήμουν ο $ONOMA1, και έπειτα έγινα ο πιο ισχυρός $ONOMA2"
+
+# Διαβάστε την ενσωματωμένη documentation της Bash χρησιμοποιώντας την εντολή
+# `help`:
+help
+help help
+help for
+help return
+help source
+help .
+
+# Διαβάστε τα manpages με την εντολή `man`:
+apropos bash
+man 1 bash
+man bash
+
+# Διαβάστε επίσης την info documentation με την εντολή `info`:
+apropos info | grep '^info.*('
+man info
+info info
+info 5 info
+info bash
+info bash 'Bash Features'
+info bash 6
+info --apropos bash
+```
diff --git a/el-gr/html-gr.html.markdown b/el-gr/html-gr.html.markdown
new file mode 100644
index 00000000..0ca6e326
--- /dev/null
+++ b/el-gr/html-gr.html.markdown
@@ -0,0 +1,193 @@
+---
+language: html
+filename: learnhtml-gr.html
+contributors:
+ - ["Dimitri Kokkonis", "https://github.com/kokkonisd"]
+lang: el-gr
+---
+
+Το ακρώνυμο HTML σημαίνει HyperText Markup Language.
+
+Είναι μια γλώσσα που μας επιτρέπει να δημιουργήσουμε σελίδες για το διαδίκτυο.
+Είναι μια γλώσσα σήμανσης (markup), και μας επιτρέπει να γράψουμε ιστοσελίδες
+χρησιμοποιώντας κώδικα για να υποδείξουμε πώς πρέπει να εμφανίζεται το κείμενο
+και τα δεδομένα στη σελίδα. Στην πραγματικότητα, τα αρχεία HTML είναι απλά
+αρχεία κειμένου.
+
+Τι σημαίνει όμως «γλώσσα σήμανσης»; Είναι μια μέθοδος οργάνωσης των δεδομένων
+της σελίδας, που λειτουργεί μέσω ετικετών (tags) που «ανοίγουν» ή «κλείνουν».
+Αυτή η σήμανση έχει ως σκοπό να δώσει κάποια συγκεκριμένη σημασία στο κείμενο
+που περιβάλλει. Όπως και οι περισσότερες γλώσσες υπολογιστών, η HTML έχει
+πολλές διαφορετικές εκδοχές. Εδώ θα μιλήσουμε για την HTML5.
+
+**ΣΗΜΕΙΩΣΗ :** Μπορείτε να δοκιμάσετε τις ετικέτες και τα στοιχεία που
+παρουσιάζονται εδώ σε ένα σάιτ όπως το [codepen](http://codepen.io/pen/), ούτως
+ώστε να δείτε τα αποτελέσματα που παράγουν, να καταλάβετε πώς δουλεύουν και να
+εξοικιωθείτε με την γλώσσα. Αυτό το άρθρο ασχολείται κυρίως με την σύνταξη της
+HTML και κάποιες χρήσιμες συμβουλές σχετικά με αυτήν.
+
+
+```html
+<!-- Τα σχόλια είναι περικυκλωμένα όπως αυτή η γραμμή! -->
+
+<!--
+ Τα
+ σχόλια
+ μπορούν
+ να
+ επεκταθούν
+ σε
+ πολλαπλές
+ γραμμές!
+-->
+
+<!-- #################### Οι ετικέτες #################### -->
+
+<!--Ορίστε ένα παράδειγμα αρχείου HTML, το οποίο θα αναλύσουμε. -->
+
+
+<!doctype html>
+ <html>
+ <head>
+ <title>Η σελίδα μου</title>
+ </head>
+ <body>
+ <h1>Καλημέρα, κόσμε!</h1>
+ <a href="http://codepen.io/anon/pen/xwjLbZ">
+ Δείτε τι κάνει αυτό
+ </a>
+ <p>Αυτή είναι μια παράγραφος.</p>
+ <p>Αυτή είναι μια άλλη παράγραφος.</p>
+ <ul>
+ <li>Αυτό είναι ένα αντικείμενο μέσα σε μια μη-αριθμημένη λίστα
+ (bullet list)</li>
+ <li>Αυτό είναι ένα άλλο αντικείμενο</li>
+ <li>Και αυτό είναι το τελευταίο αντικείμενο της λίστας</li>
+ </ul>
+ </body>
+ </html>
+
+<!--
+ Ένα αρχείο HTML πάντα ξεκινά υποδεικνύοντας στον περιηγητή πως η σελίδα
+ είναι γραμμένη με HTML.
+-->
+<!doctype html>
+
+<!-- Μετά από αυτό, ξεκινά ανοίγοντας μια ετικέτα <html>. -->
+<html>
+
+<!-- την οποία πρέπει να κλείσουμε στο τέλος της σελίδας γράφοντας </html>. -->
+</html>
+
+<!-- Τίποτα δεν πρέπει να βρίσκεται μετά από αυτη την τελευταία ετικέτα. -->
+
+
+<!-- Ανάμεσα από τις ετικέτες <html> και </html>, βρίσκουμε: -->
+
+<!-- Μια επικεφαλίδα ορισμένη από την ετικέτα <head> (πρέπει να την κλείσουμε
+με την ετικέτα </head>) -->
+<!--
+ Η επικεφαλίδα περιέχει κάποια περιγραφή και επιπρόσθετες πληροφορίες που δεν
+ εμφανίζονται· είναι τα λεγόμενα μεταδεδομένα (metadata).
+-->
+
+<head>
+ <!--
+ Η ετικέτα <title> υποδεικνύει στον περιηγητή τον τίτλο που πρέπει να
+ εμφανιστεί στην μπάρα τίτλου και στο όνομα της καρτέλας.
+ -->
+ <title>Η σελίδα μου</title>
+</head>
+
+<!-- Μετά την ενότητα <head>, βρίσκουμε την ετικέτα <body> -->
+<!-- Μέχρι αυτό το σημείο, τίποτα απ' όσα έχουμε περιγράψει δεν θα εμφανιστούν
+στο παράθυρο του περιηγητή. -->
+<!-- Πρέπει να συμπληρώσουμε το «σώμα» της σελίδας με το περιεχόμενο που
+θέλουμε να εμφανίζεται. -->
+
+<body>
+ <!-- Η ετικέτα h1 δημιουργεί έναν τίτλο/επικεφαλίδα. -->
+ <h1>Καλημέρα, κόσμε!</h1>
+ <!--
+ Υπάρχουν επίσης υπότιτλοι/υποκεφαλίδες, από την πιο σημαντική (h2)
+ μέχρι την πιο μικρή και ειδική (h6).
+ -->
+
+ <!-- Ένας υπερσύνδεσμος προς την διεύθυνση που δίνεται από την παράμετρο
+ href="": -->
+ <a href="http://codepen.io/anon/pen/xwjLbZ">
+ Δείτε τι κάνει αυτό
+ </a>
+
+ <!-- Η ετικέτα <p> μας επιτρέπει να εισάγουμε κείμενο στην σελίδα μας. -->
+ <p>Αυτή είναι μια παράγραφος.</p>
+ <p>Αυτή είναι μια άλλη παράγραφος.</p>
+
+ <!-- Η ετικέτα <ul> δημιουργεί μια μη-αριθμημένη λίστα. -->
+ <!--
+ Για μια αριθμημένη λίστα χρησιμοποιούμε την ετικέτα <ol>, που θα μας
+ δώσει 1. για το πρώτο στοιχείο, 2. για το δεύτερο κτλ.
+ -->
+ <ul>
+ <li>Αυτό είναι ένα αντικείμενο μέσα σε μια μη-αριθμημένη λίστα (bullet
+ list)</li>
+ <li>Αυτό είναι ένα άλλο αντικείμενο</li>
+ <li>Και αυτό είναι το τελευταίο αντικείμενο της λίστας</li>
+ </ul>
+</body>
+
+<!-- Αυτό ήταν όλο, είναι εύκολο να δημιουργήσουμε αρχεία HTML. -->
+
+<!-- Ωστόσο έχουμε την δυνατότητα να επιλέξουμε ανάμεσα σε πολλές ακόμη
+ετικέτες HTML. -->
+
+<!-- Η ετικέτα <img /> χρησιμοποιείται για να εισάγουμε μια εικόνα. -->
+<!--
+ Η πηγή της εικόνας υποδεικνύεται μέσω της παραμέτρου src="".
+ Η πηγή μπορεί να είναι μια διεύθυνση (URL) ή ακόμα και μια τοπική διεύθυνση
+ ενός αρχείου που βρίσκεται στον υπολογιστή μας.
+-->
+<img src="http://i.imgur.com/XWG0O.gif"/>
+
+<!-- Υπάρχει επίσης η δυνατότητα να δημιουργήσουμε πίνακες. -->
+
+<!-- Ανοίγουμε μια ετικέτα <table>. -->
+<table>
+
+ <!-- Η ετικέτα <tr> μας επιτρέπει να δημιουργήσουμε μια γραμμή
+ στον πίνακα. -->
+ <tr>
+
+ <!-- Η ετικέτα <th> μας επιτρέπει να δώσουμε έναν τίτλο σε μια στήλη
+ του πίνακα -->
+ <th>Πρώτος τίτλος</th>
+ <th>Δεύτερος τίτλος</th>
+ </tr>
+
+ <tr>
+
+ <!-- Η ετικέτα <td> μας επιτρέπει να δημιουργήσουμε ένα κελί μέσα στον
+ πίνακα. -->
+ <td>Πρώτη γραμμή, πρώτη στήλη</td>
+ <td>Πρώτη γραμμή, δεύτερη στήλη</td>
+ </tr>
+
+ <tr>
+ <td>Δεύτερη γραμμή, πρώτη στήλη</td>
+ <td>Δεύτερη γραμμή, δεύτερη στήλη</td>
+ </tr>
+</table>
+
+```
+
+## Χρήση
+
+Η HTML γράφεται σε αρχεία με την κατάληξη `.html` ή `.htm`. Ο τύπος MIME της
+HTML είναι
+`text/html`.
+**H HTML ΔΕΝ είναι γλώσσα προγραμματισμού.**
+## Μάθετε περισσότερα
+
+* [βικιπαίδεια](https://el.wikipedia.org/wiki/HTML)
+* [Μάθημα HTML](https://developer.mozilla.org/en-US/docs/Web/HTML)
+* [W3School](http://www.w3schools.com/html/html_intro.asp)
diff --git a/elisp.html.markdown b/elisp.html.markdown
index 518ad985..f839dac0 100644
--- a/elisp.html.markdown
+++ b/elisp.html.markdown
@@ -281,7 +281,7 @@ filename: learn-emacs-lisp.el
;; should stop searching at some point in the buffer, and whether it
;; should silently fail when nothing is found:
-;; (search-forward "Hello" nil 't) does the trick:
+;; (search-forward "Hello" nil t) does the trick:
;; The `nil' argument says: the search is not bound to a position.
;; The `'t' argument says: silently fail when nothing is found.
@@ -295,7 +295,7 @@ filename: learn-emacs-lisp.el
(mapcar 'hello list-of-names)
(goto-char (point-min))
;; Replace "Hello" by "Bonjour"
- (while (search-forward "Hello" nil 't)
+ (while (search-forward "Hello" nil t)
(replace-match "Bonjour"))
(other-window 1))
@@ -306,7 +306,7 @@ filename: learn-emacs-lisp.el
(defun boldify-names ()
(switch-to-buffer-other-window "*test*")
(goto-char (point-min))
- (while (re-search-forward "Bonjour \\(.+\\)!" nil 't)
+ (while (re-search-forward "Bonjour \\(.+\\)!" nil t)
(add-text-properties (match-beginning 1)
(match-end 1)
(list 'face 'bold)))
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/emacs.html.markdown b/emacs.html.markdown
new file mode 100644
index 00000000..ff4d3c03
--- /dev/null
+++ b/emacs.html.markdown
@@ -0,0 +1,320 @@
+---
+category: tool
+tool: emacs
+filename: emacs.txt
+contributors:
+ - ["Joseph Riad", "https://github.com/Joseph-Riad"]
+---
+
+Emacs started its life as ["the extensible, customizable display
+editor"](https://www.gnu.org/software/emacs/emacs-paper.html) and grew
+over the years into a full-blown ecosystem. Many tasks, usually
+relegated to a diverse set of tools can be accomplished from within
+Emacs in a consistent, familiar interface. Examples include directory
+management, viewing PDF documents, editing files over SSH, managing git
+repos,… (the list is quite long). In short, Emacs is yours to make of it
+what you will: the spectrum of users varies from those who use it to
+edit text files to extreme purists who use it to virtually replace their
+operating system.
+
+Emacs is extensible via a specialized dialect of Lisp known as Emacs
+Lisp (Elisp) which has a lot of macros geared towards editing text and
+managing text buffers. Any key (combination) you use in Emacs is bound
+to an Emacs Lisp function and may be remapped to any other function,
+including ones you write
+yourself.
+
+# Key Notation
+
+``` text
+The Emacs manual and the community in general uses a convention to refer to different key combinations used within Emacs. Specifically, Emacs has the notion of a "modifier key" that is pressed along with another key to modify its action.
+
+An example of this notation is "C-c". In this key combination "C" is the modifier and stands for the "Ctrl" key and "c" is the key whose action is being modified (the literal character "c").
+
+The modifier shorthand:
+"C-" --> The "CTRL" key
+"M-" --> The "Meta" key (usually, the "Alt" key)
+"s-" --> The "Super" key (the "Cmd" key on Macs and the "Windows" key on PCs)
+
+There are other, less commonly used modifiers that I will not get into here.
+
+The key combination "C-x C-s" means you press "Ctrl+x" followed by "Ctrl+s"
+
+In addition to the above modifiers, the special keys "Esc", "Return (Enter)" and "Shift" are denoted by "ESC", "RET" and "S", respectively.
+```
+
+# Basic Emacs Concepts
+
+Here, I discuss some basic Emacs concepts and terminology that may be
+confusing to newcomers (especially to people used to Vim terminology)
+
+ - A bunch of text that Emacs is editing is known as a **buffer**
+ - A buffer does not necessarily correspond to an actual file on disk.
+ It may be just a bunch of text in memory.
+ - When a buffer corresponds to a file on disk, we say that the buffer
+ is **visiting** that file.
+ - Emacs typically has many buffers open at once.
+ - The display of Emacs may be split into different **windows** (not to
+ be confused with your operating system's windows: the operating
+ system window for Emacs can have multiple Emacs windows inside it).
+ - An operating system window for Emacs is called an Emacs **frame**.
+ Thus, when the Emacs manual talks about opening a new frame, this
+ essentially means opening a new OS *window* containing an(other)
+ instance of Emacs.
+ - The concepts conventionally known as cutting and pasting are
+ referred to as **killing** and **yanking**, respectively in Emacs
+ parlance.
+ - The current position of the cursor is called the **point** in Emacs.
+ Technically, **point** is defined as the position right before the
+ character where the cursor currently is.
+ - Finally, each buffer may have several **modes** associated with it:
+ a **major mode** and possibly several **minor modes**.
+ - The **major mode** defines the main behavior of Emacs in the
+ currently selected buffer. This can be roughly thought of as the
+ file type. For example, if you're editing a Python file, the major
+ mode is (by default) `python-mode` which causes Emacs to highlight
+ Python syntax and automatically indent and outdent your code blocks
+ as syntactically required by your Python code.
+ - **Minor modes** define subtle changes in behavior and several minor
+ modes may be active at once in the same buffer. An example minor
+ mode is `flyspell-mode` which automatically highlights spelling
+ errors in your
+buffer.
+
+# Navigation Basics
+
+``` text
+The GUI version of Emacs can be navigated with the mouse like you would expect from a conventional GUI text editor.
+
+The aim here is to focus on navigation solely using the keyboard as this enhances productivity immensely.
+
+
+* Line movement
+
+C-n --> Next line
+C-p --> Previous line
+
+* Character movement
+
+C-f --> Go forward one character
+C-b --> Go backward one character
+
+* Word movement
+
+M-f --> Go forward one word
+M-b --> Go backward one word
+
+* Sentence movement
+
+M-a --> Move to the beginning of the sentence
+M-e --> Move to the end of the sentence
+
+* Beginning and end of line
+
+C-a --> Move to the beginning of the line
+C-e --> Move to the end of the line
+
+* Beginning and end of buffer
+
+M-< ("Meta+Shift+,") --> Go to the beginning of the buffer
+M-> ("Meta+Shift+.") --> Go to the end of the buffer
+
+* Screen movement
+
+C-v --> Scroll down by one screen-full (the last two lines of the previous screen are kept as overlap for a smoother transition)
+M-v --> Scroll up by one screen-full (same as above but with the first two lines)
+
+* Centering the screen
+
+C-l --> Move current line to the screen's center
+
+The above key combination actually cycles through different states depending on how many times it's been pressed.
+
+C-l --> Move current line to the screen's center
+C-l C-l --> Move current line to the top of the screen
+C-l C-l C-l --> Restore the position of the current line to where it was before the first C-l was pressed
+
+If you press "C-l" a 4th time, it cycles back to centering the current line.
+
+* Repeating movement commands
+
+Most movement commands take a numerical prefix argument that says "repeat the following command that many times".
+
+Example:
+
+C-u 3 C-p --> Go up 3 lines
+C-u 5 C-f --> Go forward 5 characters
+
+One notable exception are the screen scrolling commands:
+
+C-u 3 C-v --> Scroll downward 3 lines (maintaining the position of the cursor)
+```
+
+Bonus: many of the above navigation commands are the default navigation
+commands in Bash (e.g. pressing "C-b" while entering a Bash command
+takes you back one
+character).
+
+# File editing basics
+
+``` text
+* Quitting Emacs [ Now you can't say you don't know how to quit Emacs :-) ]
+
+C-x C-c --> Quit Emacs and get prompted to save any unsaved files (buffers not visiting a file will simply be discarded unless you're running in client-server mode)
+
+* Saving a buffer
+
+C-x C-s --> Save the current buffer. If not visiting a file, it will prompt you for a file name to use to save the buffer.
+
+* Searching within a buffer
+
+C-s --> Search forwards within the buffer. Search is incremental and case-insensitive by default.
+ Press C-s to move to the next match.
+ If you press "RET", point is moved to the currently highlighted word and the search ends.
+C-r --> Same as C-s except it searches backward
+
+C-_ or C-/ --> Undo the last action. Keep pressing it to move up the undo tree.
+C-? or M-_ --> Redo the previous change
+
+The "undo" and "redo" commands can take prefix numerical arguments to undo or redo that many actions:
+
+C-u 3 C-_ --> Undo the last 3 changes.
+```
+
+# Executing Elisp Functions
+
+``` text
+You can execute any currently loaded Elisp functions (including ones you have written yourself) via "M-x"
+
+M-x RET --> Prompts you for name of function to execute (Tab completion is available).
+
+Example:
+
+M-x RET search-forward-regexp RET --> Prompts you for a regular expression and searches forward in the buffer for it
+```
+
+# Emacs Configuration
+
+Emacs is configured using Elisp. On startup, it looks for a
+configuration file either in `~/.emacs` or `~/.emacs.d/init.el` where
+`~` refers to your home directory. If you're on Windows, consult [this
+article](https://www.gnu.org/software/emacs/manual/html_node/efaq-w32/Location-of-init-file.html)
+for the appropriate location of your configuration file.
+
+# Vim inside Emacs
+
+If you are considering the transition from Vim to Emacs and you're put
+off by the non-modal nature of Emacs editing, there is an Emacs
+extension known as `evil-mode` which lets you have many Vim concepts
+inside Emacs. Here are some things added to Emacs by `evil-mode`:
+
+ - Modal editing: you get normal, insert, visual and block visual modes
+ like Vim. In addition, you get an "Emacs" mode where movement and
+ navigation follow the Emacs bindings.
+ - Same movement keys as Vim in normal mode
+ - Leader key combinations
+ - Pressing ":" in normal mode allows you to execute commands
+ (including system commands)
+
+In my own experience, `evil-mode` helps make the transition seamless and
+allows you to blend the arguably more intuitive and ergonomic
+keybindings of Vim with the unbridled power of Emacs for a truly
+superior editing experience.
+
+# Discoverable Help
+
+Emacs features a pretty powerful help system that allows you to discover
+new functionality all the
+time.
+
+``` text
+Obtaining help on specific topics. Tab completion is available for function and variable names.
+
+C-h f RET --> Prompts you for the name of an elisp function and
+ displays help text on it along with a clickable link
+ to its source code.
+C-h v RET --> Same as above with variables
+
+C-h k RET --> Allows you to enter a key combination and displays the
+ name of the elisp function bound to it.
+
+Searching for help:
+
+C-h a --> Prompts you for a string to search for a command in the
+ help system. Similar to the 'apropos' or 'man -k'
+ commands in Unix systems.
+
+Starting a tutorial:
+
+C-h C-t --> Starts a tutorial designed to familiarize you with
+ basic Emacs functionality.
+```
+
+# Emacs "Killer Apps"
+
+As I hinted above, Emacs functionality goes way beyond being a mere text
+editor. I will list here a couple of Emacs "apps" that are fairly
+powerful and popular and may interest you in and of themselves.
+
+## Org
+
+Technnically, `org-mode`, a major mode for buffer editing that provides
+organizational tools. It is very difficult to succinctly describe what
+Org can do because it's a behemoth of a tool that has many diverse uses
+to different people. I will attempt to describe the main features I use
+briefly.
+
+ - Divide your file into sections and sub-sections for easy outlining
+ and organizing of concepts.
+ - Different headings in the outline are foldable/expandable so that
+ you can focus on what you need to focus on and eliminate
+ distractions.
+ - You can maintain a TODO list within Org
+ - You can compile TODO lists from many files into an agenda
+ - Track the time you spend on each TODO task
+ - Manage tables in plain text (including spreadsheet-like
+ capabilities)
+ - Using the extension `org-babel`, write and execute code blocks in
+ your file. The results are captured and are re-usable within the
+ file itself. Think Jupyter notebook for any language.
+ - Display inline images and LaTeX formulas as images within your file
+ (makes for a great note-taking system and/or personal wiki)
+ - Export your file into many different formats (LaTeX, PDF, html,…)
+
+Org mode is a very powerful tool to add to your productivity arsenal
+and, on a personal note, was the reason that caused me to start using
+Emacs after years of using Vim.
+
+## Magit
+
+This is a frontend to `git` from within Emacs. It features a very
+intuitive and discoverable interface, yet exposes very powerful
+functionality that allows you to manage commits at the chunk level,
+inspect diffs, rebase, cherry-pick, … all from within the comfort of
+your own editor.
+
+# A Word of Advice
+
+If you are considering using Emacs, a common trap that beginning users
+fall into is to copy someone else's configuration file and use it as is.
+I highly recommend against doing this for several reasons:
+
+ - It will discourage you from learning and finding things out for
+ yourself
+ - Someone else's configuration will probably contain many things
+ relevant to them that you won't need or ever use.
+ - It defeats the purpose of having a customizable text editor that can
+ fit your own needs.
+
+What I encourage you to do is to look at other people's configurations
+and seek to understand them and adapt only what makes sense to you. You
+can find out about new features of Emacs through many YouTube videos,
+screencasts or blog posts and then learn for yourself how to add them to
+your configuration and workflow. This way, you grow your configuration
+incrementally while increasing your knowledge of Emacs along the way.
+
+# Additional Resources
+
+ - [The GNU Emacs Manual](https://www.gnu.org/software/emacs/manual/emacs.html)
+ - [Emacs Stack Exchange](https://emacs.stackexchange.com/)
+ - [Emacs Wiki](https://www.emacswiki.org/emacs/EmacsWiki)
diff --git a/es-es/c-es.html.markdown b/es-es/c-es.html.markdown
index 8bc1eabb..cae4349e 100644
--- a/es-es/c-es.html.markdown
+++ b/es-es/c-es.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["Adam Bard", "http://adambard.com/"]
translators:
- ["Francisco García", "http://flaskbreaker.tumblr.com/"]
+ - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
lang: es-es
---
@@ -423,7 +424,7 @@ libro de C, escrito por Dennis Ritchie, creador de C y Brian Kernighan. Aún as
se cuidadoso, es antiguo, contiene algunas inexactitudes, y algunas prácticas
han cambiado.
-Otro buen recurso es [Learn C the hard way](http://c.learncodethehardway.org/book/).
+Otro buen recurso es [Learn C the hard way](http://learncodethehardway.org/c/).
Si tienes una pregunta, lee [compl.lang.c Frequently Asked Questions](http://c-faq.com).
diff --git a/es-es/dart-es.html.markdown b/es-es/dart-es.html.markdown
new file mode 100644
index 00000000..d0f57b95
--- /dev/null
+++ b/es-es/dart-es.html.markdown
@@ -0,0 +1,529 @@
+---
+language: dart
+contributors:
+ - ["Joao Pedrosa", "https://github.com/jpedrosa/"]
+translators:
+ - ["Jorge Antonio Atempa", "http://www.twitter.com/atempa09"]
+filename: dart-es.md
+lang: es-es
+---
+
+Dart es un recién llegado al ámbito de los lenguajes de programación.
+Toma prestado mucho de otros lenguajes principales, con el objetivo de no desviarse demasiado de
+su hermano JavaScript. Tal como JavaScript, Dart tiene como objetivo una gran integración en el navegador.
+
+La característica más controvertida de Dart debe ser su escritura opcional.
+
+```dart
+import "dart:collection";
+import "dart:math" as DM;
+
+// Bienvenido a Aprende Dart en 15 minutos. http://www.dartlang.org/
+// Este es un tutorial ejecutable. Puedes ejecutarlo con Dart o en
+// el sitio de ¡Try Dart! solo copiando y pegando en http://try.dartlang.org/
+
+// La declaración de función y de método tienen el mismo aspecto.
+// Las funciones pueden estar anidadas.
+// La declaración toma la forma name() {} o name() => expresionEnUnaLinea;
+// La declaración de la función de flecha gorda, tiene un retorno implícito
+// para el resultado de la expresión.
+example1() {
+ nested1() {
+ nested2() => print("example1 anidado 1 anidado 2");
+ nested2();
+ }
+ nested1();
+}
+
+// Las funciones anónimas no incluyen un nombre.
+example2() {
+ nested1(fn) {
+ fn();
+ }
+ nested1(() => print("example2 anidado 1"));
+}
+
+// Cuando se declara un parámetro de función, la declaración puede incluir el
+// número de parámetros que toma la función especificando los nombres de los
+// parámetros que lleva.
+example3() {
+ planA(fn(informSomething)) {
+ fn("example3 plan A");
+ }
+ planB(fn) { // O no declarar el número de parámetros.
+ fn("example3 plan B");
+ }
+ planA((s) => print(s));
+ planB((s) => print(s));
+}
+
+// Las funciones tienen acceso de cierre a variables externas.
+var example4Something = "Example4 anidado 1";
+example4() {
+ nested1(fn(informSomething)) {
+ fn(example4Something);
+ }
+ nested1((s) => print(s));
+}
+
+// La declaración de la clase con un método sayIt, el cual también tiene acceso de cierre
+// a la variable exterior como si fuera una función como se ha visto antes.
+var example5method = "example5 sayIt";
+class Example5Class {
+ sayIt() {
+ print(example5method);
+ }
+}
+example5() {
+ // Crear una instancia anónima de Example5Class y la llamada del método sayIt
+ new Example5Class().sayIt();
+}
+
+// La declaración de clase toma la forma NombreDeClase { [cuerpoDeClase] }.
+// Donde cuerpoDeClase puede incluir métodos de instancia y variables, pero también
+// métodos y variables de clase.
+class Example6Class {
+ var instanceVariable = "Example6 variable de instancia";
+ sayIt() {
+ print(instanceVariable);
+ }
+}
+example6() {
+ new Example6Class().sayIt();
+}
+
+// Los métodos y variables de clase son declarados con términos "static".
+class Example7Class {
+ static var classVariable = "Example7 variable de clase";
+ static sayItFromClass() {
+ print(classVariable);
+ }
+ sayItFromInstance() {
+ print(classVariable);
+ }
+}
+example7() {
+ Example7Class.sayItFromClass();
+ new Example7Class().sayItFromInstance();
+}
+
+// Las literales son geniales, pero hay una restricción para lo que pueden ser las literales
+// fuera de los cuerpos de función/método. Literales en el ámbito exterior de clase
+// o fuera de clase tienen que ser constantes. Las cadenas de caracteres y los números
+// son constantes por defecto. Pero los arreglos y mapas no lo son.
+// Ellos pueden hacerse constante anteponiendo en la declaración el término "const".
+var example8Array = const ["Example8 arreglo constante"],
+ example8Map = const {"algunaKey": "Example8 mapa constante"};
+example8() {
+ print(example8Array[0]);
+ print(example8Map["algunaKey"]);
+}
+
+// Los bucles en Dart toman la forma estándar para for () {} o ciclos while () {} ,
+// ligeramente más moderno for (.. in ..) {}, o llamadas funcionales con muchas
+// características soportadas, comenzando con forEach.
+var example9Array = const ["a", "b"];
+example9() {
+ for (var i = 0; i < example9Array.length; i++) {
+ print("example9 ciclo for '${example9Array[i]}'");
+ }
+ var i = 0;
+ while (i < example9Array.length) {
+ print("example9 ciclo while '${example9Array[i]}'");
+ i++;
+ }
+ for (var e in example9Array) {
+ print("example9 ciclo for-in '${e}'");
+ }
+ example9Array.forEach((e) => print("example9 ciclo forEach '${e}'"));
+}
+
+// Para recorrer los caracteres de una cadena o para extraer una subcadena.
+var example10String = "ab";
+example10() {
+ for (var i = 0; i < example10String.length; i++) {
+ print("example10 Recorrido de caracteres en la cadena '${example10String[i]}'");
+ }
+ for (var i = 0; i < example10String.length; i++) {
+ print("example10 ciclo de subcadena '${example10String.substring(i, i + 1)}'");
+ }
+}
+
+// Formato de números Int y double son soportados.
+example11() {
+ var i = 1 + 320, d = 3.2 + 0.01;
+ print("example11 int ${i}");
+ print("example11 double ${d}");
+}
+
+// DateTime ofrece aritmética de fecha/hora.
+example12() {
+ var now = new DateTime.now();
+ print("example12 ahora '${now}'");
+ now = now.add(new Duration(days: 1));
+ print("example12 manana '${now}'");
+}
+
+// Expresiones regulares son soportadas.
+example13() {
+ var s1 = "alguna cadena", s2 = "alguna", re = new RegExp("^s.+?g\$");
+ match(s) {
+ if (re.hasMatch(s)) {
+ print("example13 regexp embona '${s}'");
+ } else {
+ print("example13 regexp no embona '${s}'");
+ }
+ }
+ match(s1);
+ match(s2);
+}
+
+// Las expresiones booleanas admiten conversiones implícitas y tipos dinámicos.
+example14() {
+ var a = true;
+ if (a) {
+ print("true, a is $a");
+ }
+ a = null;
+ if (a) {
+ print("true, a es $a");
+ } else {
+ print("false, a es $a"); // corre aquí
+ }
+
+ // el tipado dinámico null puede convertirse a bool
+ var b; // b es de tipo dinámico
+ b = "abc";
+ try {
+ if (b) {
+ print("true, b es $b");
+ } else {
+ print("false, b es $b");
+ }
+ } catch (e) {
+ print("error, b es $b"); // esto podría ser ejecutado pero consiguió error
+ }
+ b = null;
+ if (b) {
+ print("true, b es $b");
+ } else {
+ print("false, b es $b"); // corre aquí
+ }
+
+ // tipado estático null no puede ser convertido a bool
+ var c = "abc";
+ c = null;
+ // compilación fallida
+ // if (c) {
+ // print("true, c is $c");
+ // } else {
+ // print("false, c is $c");
+ // }
+}
+
+// try/catch/finally y throw son utilizados para el manejo de excepciones.
+// throw toma cualquier objeto como parámetro;
+example15() {
+ try {
+ try {
+ throw "Algun error inesperado.";
+ } catch (e) {
+ print("example15 una excepcion: '${e}'");
+ throw e; // Re-throw
+ }
+ } catch (e) {
+ print("example15 atrapa la excepcion que ha sido relanzada: '${e}'");
+ } finally {
+ print("example15 aún ejecuta finally");
+ }
+}
+
+// Para ser eficiente cuando creas una cadena larga dinámicamente, usa
+// StringBuffer. O podrías unir un arreglo de cadena de caracteres.
+example16() {
+ var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e;
+ for (e in a) { sb.write(e); }
+ print("example16 cadena de caracteres dinamica creada con "
+ "StringBuffer '${sb.toString()}'");
+ print("example16 union de arreglo de cadena de caracteres '${a.join()}'");
+}
+
+// Las cadenas de caracteres pueden ser concatenadas contando solo
+// con literales una después de la otra sin algún otro operador necesario.
+example17() {
+ print("example17 "
+ "concatenar "
+ "cadenas "
+ "asi");
+}
+
+// Las cadenas de caracteres utilizan comilla simple o comillas dobles como delimitadores
+// sin ninguna diferencia entre ambas. Esto proporciona flexibilidad que puede ser efectiva
+// para evitar la necesidad de 'escapar' el contenido. Por ejemplo,
+// las dobles comillas de los atributos HTML.
+example18() {
+ print('Example18 <a href="etc">'
+ "Don't can't I'm Etc"
+ '</a>');
+}
+
+// Las cadenas de caracteres con triple comilla simple o triple comillas dobles
+// dividen múltiples lineas e incluyen como delimitador el salto de línea.
+example19() {
+ print('''Example19 <a href="etc">
+Example19 Don't can't I'm Etc
+Example19 </a>''');
+}
+
+// Las cadenas de caracteres cuentan con una extraordinaria característica
+// para la interpolación de caracteres utilizando el operador $
+// Con $ { [expresion] }, devolvemos la expresion interpolada.
+// $ seguido por el nombre de una variable interpola el contenido de dicha variable.
+// $ puede ser escapado con \$ para solo agregarlo a la cadena.
+example20() {
+ var s1 = "'\${s}'", s2 = "'\$s'";
+ print("Example20 \$ interpolation ${s1} or $s2 works.");
+}
+
+// Hasta ahora no hemos declarado ningún tipo de dato y los programas
+// han funcionado bien. De hecho, los tipos no se toman en cuenta durante
+// el tiempo de ejecución.
+// Los tipos incluso pueden estar equivocados y al programa todavía se le dará
+// el beneficio de la duda y se ejecutará como si los tipos no importaran.
+// Hay un parámetro de tiempo de ejecución que comprueba los errores de tipo que es
+// el modo de verificación, el cuál es útil durante el tiempo de desarrollo,
+// pero que también es más lento debido a la comprobación adicional y, por lo tanto
+// se evita durante el tiempo de ejecución de la implementación.
+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 nombres '${o.names}' y longitud '${o.length}'");
+ o.names = ["d", "e"];
+ print("example21 nombres '${o.names}' y longitud '${o.length}'");
+}
+
+// La herencia de clases toma la forma NombreDeClase extends OtraClase {}.
+class Example22A {
+ var _name = "¡Algun Nombre!";
+ get name => _name;
+}
+class Example22B extends Example22A {}
+example22() {
+ var o = new Example22B();
+ print("example22 herencia de clase '${o.name}'");
+}
+
+// La mezcla de clases también esta disponible y toman la forma de
+// NombreDeClase extends AlgunaClase with OtraClase {}.
+// Es necesario extender de alguna clase para poder mezclar con otra.
+// La clase de plantilla de mixin no puede en este momento tener un constructor.
+// Mixin se utiliza principalmente para compartir métodos con clases distantes,
+// por lo que la herencia única no interfiere con el código reutilizable.
+// Mixins se colocan despues de la palabra "with" durante la declaración de la clase.
+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}'");
+}
+
+// El método constructor de la clase utiliza el mismo nombre de la clase
+// y toma la forma de AlgunaClase() : super() {}, donde la parte ": super()"
+// es opcional y es utilizado para delegar parametros constantes
+// al método constructor de la clase padre o super clase.
+class Example24A {
+ var _value;
+ Example24A({value: "algunValor"}) {
+ _value = value;
+ }
+ get value => _value;
+}
+class Example24B extends Example24A {
+ Example24B({value: "algunOtroValor"}) : super(value: value);
+}
+example24() {
+ var o1 = new Example24B(),
+ o2 = new Example24B(value: "aunMas");
+ print("example24 llama al método super desde el constructor '${o1.value}'");
+ print("example24 llama al método super desde el constructor '${o2.value}'");
+}
+
+// Hay un atajo para configurar los parámetros del constructor en el caso de clases más simples.
+// Simplemente use el prefijo this.nombreParametro y establecerá el parámetro
+// en una variable de instancia del mismo nombre.
+class Example25 {
+ var value, anotherValue;
+ Example25({this.value, this.anotherValue});
+}
+example25() {
+ var o = new Example25(value: "a", anotherValue: "b");
+ print("example25 atajo para el constructor '${o.value}' y "
+ "'${o.anotherValue}'");
+}
+
+// Los parámetros con nombre están disponibles cuando se declaran entre {}.
+// El orden de los parámetros puede ser opcional cuando se declara entre {}.
+// Los parámetros pueden hacerse opcionales cuando se declaran entre [].
+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}'");
+}
+
+// Las variables declaradas con final solo se pueden establecer una vez.
+// En el caso de las clases, las variables de instancia final se pueden establecer
+// a través de la constante del parámetro constructor.
+class Example27 {
+ final color1, color2;
+ // Un poco de flexibilidad para establecer variables de instancia finales con la sintaxis
+ // que sigue a :
+ Example27({this.color1, color2}) : color2 = color2;
+}
+example27() {
+ final color = "orange", o = new Example27(color1: "lilac", color2: "white");
+ print("example27 color es '${color}'");
+ print("example27 color es '${o.color1}' y '${o.color2}'");
+}
+
+// Para importar una librería utiliza la palabra reservada import "rutaLibrería" o si es una biblioteca central,
+// import "dart:NombreLibrería". También está el "pub" administrador de paquetes con
+// su propia convensión import "package:NombrePaquete".
+// Ve import "dart:collection"; al inicio. Las importaciones deben venir antes
+// de la delcaración de algún otro código. IterableBase proviene de 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}'"));
+}
+
+// Para el control de flujo tenemos:
+// * estandard switch
+// * if-else if-else y el operador ternario ..?..:..
+// * closures y funciones anonimas
+// * sentencias break, continue y return
+example29() {
+ var v = true ? 30 : 60;
+ switch (v) {
+ case 30:
+ print("example29 sentencia switch");
+ break;
+ }
+ if (v < 30) {
+ } else if (v > 30) {
+ } else {
+ print("example29 sentencia if-else");
+ }
+ 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;
+ }
+ // Nunca llega aquí.
+ }
+}
+
+// La sentencia int.parse, convierte de tipo double a int, o simplemente mantener int cuando se dividen los números
+// utilizando ~/ como operación. Vamos a jugar un juego de adivinanzas también.
+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 porque nextInt top es exclusivo
+ print("example30 Adivina un número entre 0 y ${top}");
+ guessNumber(i) {
+ if (n == gn) {
+ print("example30 ¡Adivinaste correctamente! El número es ${gn}");
+ } else {
+ tooHigh = n > gn;
+ print("example30 Número ${n} es demasiado "
+ "${tooHigh ? 'high' : 'low'}. Intenta nuevamente");
+ }
+ return n == gn;
+ }
+ n = (top - bottom) ~/ 2;
+ while (!guessNumber(n)) {
+ if (tooHigh) {
+ top = n - 1;
+ } else {
+ bottom = n + 1;
+ }
+ n = bottom + ((top - bottom) ~/ 2);
+ }
+}
+
+// Los programas tienen un solo punto de entrada en la función principal.
+// No se espera que se ejecute nada en el ámbito externo antes de que un programa
+// comience a funcionar con su función principal.
+// Esto ayuda con una carga más rápida e incluso con una carga lenta
+// de lo que necesita el programa para iniciar.
+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
+ ].forEach((ef) => ef());
+}
+
+```
+
+## Lecturas adicionales
+
+Dart tiene un sitio web muy completo. Cubre referencias de API, tutoriales, artículos y más, incluyendo una
+útil sección en línea Try Dart.
+[https://www.dartlang.org](https://www.dartlang.org)
+[https://try.dartlang.org](https://try.dartlang.org)
diff --git a/es-es/factor-es.html.markdown b/es-es/factor-es.html.markdown
new file mode 100644
index 00000000..67c60de7
--- /dev/null
+++ b/es-es/factor-es.html.markdown
@@ -0,0 +1,200 @@
+---
+language: factor
+contributors:
+ - ["hyphz", "http://github.com/hyphz/"]
+translators:
+ - ["Roberto R", "https://github.com/rrodriguze"]
+filename: learnfactor-es.factor
+
+lang: es-es
+---
+Factor es un lenguaje moderno basado en la pila, basado en Forth, creado por
+Slava Pestov.
+
+El código de este archivo puede escribirse en Factor, pero no importa
+directamente porque el encabezado del vocabulario de importación haria que el
+comienzo fuera totalmente confuso.
+
+```factor
+! Esto es un comentario
+
+! Como Forth, toda la programación se realiza mediante la manipulación de la
+! pila.
+! La intruducción de un valor literal lo coloca en la pila
+5 2 3 56 76 23 65 ! No hay salida pero la pila se imprime en modo interactivo
+
+! Esos números se agregan a la pila de izquierda a derecha
+! .s imprime la pila de forma no destructiva.
+.s ! 5 2 3 56 76 23 65
+
+! La aritmética funciona manipulando datos en la pila.
+5 4 + ! Sem saída
+
+! `.` muestra el resultado superior de la pila y lo imprime.
+. ! 9
+
+! Más ejemplos de aritmética:
+6 7 * . ! 42
+1360 23 - . ! 1337
+12 12 / . ! 1
+13 2 mod . ! 1
+
+99 neg . ! -99
+-99 abs . ! 99
+52 23 max . ! 52
+52 23 min . ! 23
+
+! Se proporcionan varias palabras para manipular la pila, conocidas
+colectivamente como palabras codificadas.
+
+3 dup - ! duplica el primer item (1st ahora igual a 2nd): 3 - 3
+2 5 swap / ! intercambia el primero con el segundo elemento: 5 / 2
+4 0 drop 2 / ! elimina el primer item (no imprime en pantalla): 4 / 2
+1 2 3 nip .s ! elimina el segundo item (semejante a drop): 1 3
+1 2 clear .s ! acaba con toda la pila
+1 2 3 4 over .s ! duplica el segundo item superior: 1 2 3 4 3
+1 2 3 4 2 pick .s ! duplica el tercer item superior: 1 2 3 4 2 3
+
+! Creando Palabras
+! La palabra `:` factoriza los conjuntos en modo de compilación hasta que vea
+la palabra`;`.
+: square ( n -- n ) dup * ; ! Sin salida
+5 square . ! 25
+
+! Podemos ver lo que las palabra hacen también.
+! \ suprime la evaluación de una palabra y coloca su identificador en la pila.
+\ square see ! : square ( n -- n ) dup * ;
+
+! Después del nombre de la palabra para crear, la declaración entre paréntesis
+da efecto a la pila.
+! Podemos usar los nombres que queramos dentro de la declaración:
+: weirdsquare ( camel -- llama ) dup * ;
+
+! Mientras su recuento coincida con el efecto de pila de palabras:
+: doubledup ( a -- b ) dup dup ; ! Error: Stack effect declaration is wrong
+: doubledup ( a -- a a a ) dup dup ; ! Ok
+: weirddoubledup ( i -- am a fish ) dup dup ; ! Além disso Ok
+
+! Donde Factor difiere de Forth es en el uso de las citaciones.
+! Una citacion es un bloque de código que se coloca en la pila como un valor.
+! [ inicia el modo de citación; ] termina.
+[ 2 + ] ! La cita que suma dos queda en la pila
+4 swap call . ! 6
+
+! Y así, palabras de orden superior. TONOS de palabras de orden superior
+2 3 [ 2 + ] dip .s ! Tomar valor de la parte superior de la pilar, cotizar, retroceder: 4 3
+3 4 [ + ] keep .s ! Copiar el valor desde la parte superior de la pila, cotizar, enviar copia: 7 4
+1 [ 2 + ] [ 3 + ] bi .s ! Ejecute cada cotización en el valor superior, empuje amabos resultados: 3 4
+4 3 1 [ + ] [ + ] bi .s ! Las citas en un bi pueden extraer valores más profundos de la pila: 4 5 ( 1+3 1+4 )
+1 2 [ 2 + ] bi@ .s ! Citar en primer y segundo valor
+2 [ + ] curry ! Inyecta el valor dado al comienzo de la pila: [ 2 + ] se deja en la pila
+
+! Condicionales
+! Cualquier valor es verdadero, excepto el valor interno f.
+! no existe un valor interno, pero su uso no es esencial.
+! Los condicionales son palabras de orden superior, como con los combinadores
+! anteriores
+
+5 [ "Five is true" . ] when ! Cinco es verdadero
+0 [ "Zero is true" . ] when ! Cero es verdadero
+f [ "F is true" . ] when ! Sin salida
+f [ "F is false" . ] unless ! F es falso
+2 [ "Two is true" . ] [ "Two is false" . ] if ! Two es verdadero
+
+! Por defecto, los condicionales consumen el valor bajo prueba, pero las
+! variantes con un
+! asterisco se dejan solo si es verdad:
+
+5 [ . ] when* ! 5
+f [ . ] when* ! Sin salida, pila vacía, se consume porque f es falso
+
+
+! Lazos
+! Lo has adivinado... estas son palabras de orden superior también.
+
+5 [ . ] each-integer ! 0 1 2 3 4
+4 3 2 1 0 5 [ + . ] each-integer ! 0 2 4 6 8
+5 [ "Hello" . ] times ! Hello Hello Hello Hello Hello
+
+! Here's a list:
+{ 2 4 6 8 } ! Goes on the stack as one item
+
+! Aqui está uma lista:
+{ 2 4 6 8 } [ 1 + . ] each ! Exibe 3 5 7 9
+{ 2 4 6 8 } [ 1 + ] map ! Salida { 3 5 7 9 } de la pila
+
+! Reduzir laços ou criar listas:
+{ 1 2 3 4 5 } [ 2 mod 0 = ] filter ! Solo mantenga miembros de la lista para los cuales la cita es verdadera: { 2 4 }
+{ 2 4 6 8 } 0 [ + ] reduce . ! Como "fold" en lenguajes funcinales: exibe 20 (0+2+4+6+8)
+{ 2 4 6 8 } 0 [ + ] accumulate . . ! Como reducir, pero mantiene los valores intermedios en una lista: { 0 2 6 12 } así que 20
+1 5 [ 2 * dup ] replicate . ! Repite la cita 5 veces y recoge los resultados en una lista: { 2 4 8 16 32 }
+1 [ dup 100 < ] [ 2 * dup ] produce ! Repite la segunda cita hasta que la primera devuelva falso y recopile los resultados: { 2 4 8 16 32 64 128 }
+
+! Si todo lo demás falla, un propósito general a repetir.
+1 [ dup 10 < ] [ "Hello" . 1 + ] while ! Escribe "Hello" 10 veces
+ ! Sí, es dificil de leer
+ ! Para eso están los bucles variantes
+
+! Variables
+! Normalmente, se espera que los programas de Factor mantengan todos los datos
+! en la pila.
+! El uso de variables con nombre hace que la refactorización sea más difícil
+! (y se llama Factor por una razón)
+! Variables globales, si las necesitas:
+
+SYMBOL: name ! Crea un nombre como palabra de identificación
+"Bob" name set-global ! Sin salída
+name get-global . ! "Bob"
+
+! Las variables locales nombradas se consideran una extensión, pero están
+! disponibles
+! En una cita ..
+[| m n ! La cita captura los dos valores principales de la pila en m y n
+ | m n + ] ! Leerlos
+
+! Ou em uma palavra..
+:: lword ( -- ) ! Tenga en cuenta los dos puntos dobles para invocar la extensión de variable léxica
+ 2 :> c ! Declara la variable inmutable c para contener 2
+ c . ; ! Imprimirlo
+
+! En una palabra declarada de esta manera, el lado de entrada de la declaración
+! de la pila
+! se vuelve significativo y proporciona los valores de las variables en las que
+! se capturan los valores de pila
+:: double ( a -- result ) a 2 * ;
+
+! Las variables se declaran mutables al terminar su nombre con su signo de
+! exclamación
+:: mword2 ( a! -- x y ) ! Capture la parte superior de la pila en la variable mutable a
+ a ! Empujar a
+ a 2 * a! ! Multiplique por 2 y almacenar el resultado en a
+ a ; ! Empujar el nuevo valor de a
+5 mword2 ! Pila: 5 10
+
+! Listas y Secuencias
+! Vimos arriba cómo empujar una lista a la pila
+
+0 { 1 2 3 4 } nth ! Acceder a un miembro específico de una lista: 1
+10 { 1 2 3 4 } nth ! Error: índice de secuencia fuera de los límites
+1 { 1 2 3 4 } ?nth ! Lo mismo que nth si el índice está dentro de los límites: 2
+10 { 1 2 3 4 } ?nth ! Sin errores si está fuera de los límites: f
+
+{ "at" "the" "beginning" } "Append" prefix ! { "Append" "at" "the" "beginning" }
+{ "Append" "at" "the" } "end" suffix ! { "Append" "at" "the" "end" }
+"in" 1 { "Insert" "the" "middle" } insert-nth ! { "Insert" "in" "the" "middle" }
+"Concat" "enate" append ! "Concatenate" - strings are sequences too
+"Concatenate" "Reverse " prepend ! "Reverse Concatenate"
+{ "Concatenate " "seq " "of " "seqs" } concat ! "Concatenate seq of seqs"
+{ "Connect" "subseqs" "with" "separators" } " " join ! "Connect subseqs with separators"
+
+! Y si desea obtener meta, las citas son secuencias y se pueden desmontar
+0 [ 2 + ] nth ! 2
+1 [ 2 + ] nth ! +
+[ 2 + ] \ - suffix ! Quotation [ 2 + - ]
+
+
+```
+
+##Listo para más?
+
+* [Documentación de Factor](http://docs.factorcode.org/content/article-help.home.html)
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/hy-es.html.markdown b/es-es/hy-es.html.markdown
new file mode 100644
index 00000000..bfad3b6e
--- /dev/null
+++ b/es-es/hy-es.html.markdown
@@ -0,0 +1,176 @@
+---
+language: hy
+filename: learnhy-es.hy
+contributors:
+ - ["Abhishek L", "http://twitter.com/abhishekl"]
+translators:
+ - ["Roberto R", "https://github.com/rrodriguze"]
+lang: es-es
+---
+
+Hy es un lenguaje de Lisp escrito sobre Python. Esto es posible convirtiendo
+código Hy en un árbol abstracto de Python (ast). Por lo que, esto permite a
+Hy llamar a código Pyhton nativo y viceversa.
+
+Este tutorial funciona para hy >= 0.9.12
+
+```clojure
+;; Esto es una intrucción muy básica a Hy, como la del siguiente enlace
+;; http://try-hy.appspot.com
+;;
+; Comentarios usando punto y coma, como en otros LISPS
+
+;; Nociones básicas de expresiones
+; Los programas List están hechos de expresiones simbólicas como la siguiente
+(some-function args)
+; ahora el esencial "Hola Mundo"
+(print "hello world")
+
+;; Tipos de datos simples
+; Todos los tipos de datos simples son exactamente semejantes a sus homólogos
+; en python
+42 ; => 42
+3.14 ; => 3.14
+True ; => True
+4+10j ; => (4+10j) un número complejo
+
+; Vamos a comenzar con un poco de arimética simple
+(+ 4 1) ;=> 5
+; el operador es aplicado a todos los argumentos, como en otros lisps
+(+ 4 1 2 3) ;=> 10
+(- 2 1) ;=> 1
+(* 4 2) ;=> 8
+(/ 4 1) ;=> 4
+(% 4 2) ;=> 0 o operador módulo
+; la exponenciación es representada por el operador ** como python
+(** 3 2) ;=> 9
+; las funciones anidadas funcionan como lo esperado
+(+ 2 (* 4 2)) ;=> 10
+; también los operadores lógicos igual o no igual se comportan como se espera
+(= 5 4) ;=> False
+(not (= 5 4)) ;=> True
+
+;; variables
+; las variables se configuran usando SETV, los nombres de las variables pueden
+; usar utf-8, excepto for ()[]{}",'`;#|
+(setv a 42)
+(setv π 3.14159)
+(def *foo* 42)
+;; otros tipos de datos de almacenamiento
+; strings, lists, tuples & dicts
+; estos son exactamente los mismos tipos de almacenamiento en python
+"hello world" ;=> "hello world"
+; las operaciones de cadena funcionan de manera similar en python
+(+ "hello " "world") ;=> "hello world"
+; Las listas se crean usando [], la indexación comienza en 0
+(setv mylist [1 2 3 4])
+; las tuplas son estructuras de datos inmutables
+(setv mytuple (, 1 2))
+; los diccionarios son pares de valor-clave
+(setv dict1 {"key1" 42 "key2" 21})
+; :nombre se puede usar para definir palabras clave en Hy que se pueden usar para claves
+(setv dict2 {:key1 41 :key2 20})
+; usar 'get' para obtener un elemento en un índice/key
+(get mylist 1) ;=> 2
+(get dict1 "key1") ;=> 42
+; Alternativamente, si se usan palabras clave que podrían llamarse directamente
+(:key1 dict2) ;=> 41
+
+;; funciones y otras estructuras de programa
+; las funciones son definidas usando defn, o el último sexp se devuelve por defecto
+(defn greet [name]
+  "A simple greeting" ; un docstring opcional
+  (print "hello " name))
+
+(greet "bilbo") ;=> "hello bilbo"
+
+; las funciones pueden tener argumentos opcionales, así como argumentos-clave
+(defn foolists [arg1 &optional [arg2 2]]
+  [arg1 arg2])
+
+(foolists 3) ;=> [3 2]
+(foolists 10 3) ;=> [10 3]
+
+; las funciones anonimas son creadas usando constructores 'fn' y 'lambda'
+; que son similares a 'defn'
+(map (fn [x] (* x x)) [1 2 3 4]) ;=> [1 4 9 16]
+
+;; operaciones de secuencia
+; hy tiene algunas utilidades incluidas para operaciones de secuencia, etc.
+; recuperar el primer elemento usando 'first' o 'car'
+(setv mylist [1 2 3 4])
+(setv mydict {"a" 1 "b" 2})
+(first mylist) ;=> 1
+
+; corte listas usando 'slice'
+(slice mylist 1 3) ;=> [2 3]
+
+; obtener elementos de una lista o dict usando 'get'
+(get mylist 1) ;=> 2
+(get mydict "b") ;=> 2
+; la lista de indexación comienza a partir de 0, igual que en python
+; assoc puede definir elementos clave/índice
+(assoc mylist 2 10) ; crear mylist [1 2 10 4]
+(assoc mydict "c" 3) ; crear mydict {"a" 1 "b" 2 "c" 3}
+; hay muchas otras funciones que hacen que trabajar con secuencias sea 
+; entretenido
+
+;; Python interop
+;; los import funcionan exactamente como en python
+(import datetime)
+(import [functools [partial reduce]]) ; importa fun1 e fun2 del module1
+(import [matplotlib.pyplot :as plt]) ; haciendo una importación en foo como en bar
+; todos los métodos de python incluídos etc. son accesibles desde hy
+; a.foo(arg) is called as (.foo a arg)
+(.split (.strip "hello world  ")) ;=> ["hello" "world"]
+
+;; Condicionales
+; (if condition (body-if-true) (body-if-false)
+(if (= passcode "moria")
+  (print "welcome")
+  (print "Speak friend, and Enter!"))
+
+; anidar múltiples cláusulas 'if else if' con condiciones
+(cond
+ [(= someval 42)
+  (print "Life, universe and everything else!")]
+ [(> someval 42)
+  (print "val too large")]
+ [(< someval 42)
+  (print "val too small")])
+
+; declaraciones de grupo con 'do', son ejecutadas secuencialmente
+; formas como defn tienen un 'do' implícito
+(do
+ (setv someval 10)
+ (print "someval is set to " someval)) ;=> 10
+
+; crear enlaces léxicos con 'let', todas las variables definidas de esta manera
+; tienen alcance local
+(let [[nemesis {"superman" "lex luther"
+                "sherlock" "moriarty"
+                "seinfeld" "newman"}]]
+  (for [(, h v) (.items nemesis)]
+    (print (.format "{0}'s nemesis was {1}" h v))))
+
+;; clases
+; las clases son definidas de la siguiente manera
+(defclass Wizard [object]
+  [[--init-- (fn [self spell]
+             (setv self.spell spell) ; init the attr magic
+             None)]
+   [get-spell (fn [self]
+              self.spell)]])
+
+;; acesse hylang.org
+```
+
+### Otras lecturas
+
+Este tutorial apenas es una introducción básica para hy/lisp/python.
+
+Docs Hy: [http://hy.readthedocs.org](http://hy.readthedocs.org)
+
+Repo Hy en GitHub: [http://github.com/hylang/hy](http://github.com/hylang/hy)
+
+Acceso a freenode irc con #hy, hashtag en twitter: #hylang
diff --git a/es-es/kotlin-es.html.markdown b/es-es/kotlin-es.html.markdown
index 045f92d1..80d7a4bb 100644
--- a/es-es/kotlin-es.html.markdown
+++ b/es-es/kotlin-es.html.markdown
@@ -2,6 +2,7 @@
language: kotlin
contributors:
- ["S Webber", "https://github.com/s-webber"]
+- ["Aitor Escolar", "https://github.com/aiescola"]
translators:
- ["Ivan Alburquerque", "https://github.com/AlburIvan"]
lang: es-es
@@ -40,6 +41,12 @@ fun main(args: Array<String>) {
    Podemos declarar explícitamente el tipo de una variable así:
*/
val foo: Int = 7
+
+ /*
+ A diferencia de JavaScript, aunque el tipo se infiera, es tipado, por lo que no se puede cambiar el tipo a posteriori
+ */
+ var fooInt = 14 // Se infiere tipo Int
+ fooInt = "Cadena" // ERROR en tiempo de compilación: Type mismatch
/*
Las cadenas pueden ser representadas de la misma manera que Java.
@@ -84,7 +91,6 @@ fun main(args: Array<String>) {
println(fooNullable?.length) // => null
println(fooNullable?.length ?: -1) // => -1
-
/*
Las funciones pueden ser declaras usando la palabra clave "fun".
Los argumentos de las funciones son especificados entre corchetes despues del nombre de la función.
@@ -122,6 +128,40 @@ fun main(args: Array<String>) {
fun even(x: Int) = x % 2 == 0
println(even(6)) // => true
println(even(7)) // => false
+
+ /*
+ Kotlin permite el uso de lambdas, o funciones anónimas
+ */
+
+ // Sin lambda:
+ interface MyListener {
+ fun onClick(foo: Foo)
+ }
+
+ fun listenSomething(listener: MyListener) {
+ listener.onClick(Foo())
+ }
+
+ listenSomething(object: MyListener {
+ override fun onClick(foo: Foo) {
+ //...
+ }
+ })
+
+ // Con lambda:
+ fun listenSomethingLambda(listener: (Foo) -> Unit) {
+ listener(Foo())
+ }
+
+ listenSomethingLambda {
+ //Se recibe foo
+ }
+
+ // el operador typealias permite, entre otras cosas, simplificar las expresiones con lambdas
+ typealias MyLambdaListener = (Foo) -> Unit
+ fun listenSomethingLambda(listener: MyLambdaListener) {
+ listener(Foo())
+ }
// Las funciones pueden tomar funciones como argumentos y
// retornar funciones.
@@ -219,6 +259,11 @@ fun main(args: Array<String>) {
val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9)
// Se puede acceder a los valores del mapa por su llave.
println(fooMap["a"]) // => 8
+
+ // Tanto Map como cualquier colección iterable, tienen la función de extensión forEach
+ fooMap.forEach {
+ println("${it.key} ${it.value}")
+ }
/*
Las secuencias representan colecciones evaluadas diferidamente.
@@ -245,7 +290,7 @@ fun main(args: Array<String>) {
val y = fibonacciSequence().take(10).toList()
println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
- // Kotlin provee funciones de Orden-Mayor para trabajar con colecciones.
+ // Kotlin provee funciones de orden superior para trabajar con colecciones.
val z = (1..9).map {it * 3}
.filter {it < 20}
.groupBy {it % 2 == 0}
@@ -305,17 +350,11 @@ fun main(args: Array<String>) {
ese tipo sin convertido de forma explícita.
*/
fun smartCastExample(x: Any) : Boolean {
- if (x is Boolean) {
- // x es automaticamente convertido a Boolean
- return x
- } else if (x is Int) {
- // x es automaticamente convertido a Int
- return x > 0
- } else if (x is String) {
- // x es automaticamente convertido a String
- return x.isNotEmpty()
- } else {
- return false
+ return when (x) {
+ is Boolean -> x // x es automaticamente convertido a Boolean
+ is Int -> x > 0 // x es automaticamente convertido a Int
+ is String -> x.isNotEmpty() // x es automaticamente convertido a String
+ else -> false
}
}
println(smartCastExample("Hola, mundo!")) // => true
@@ -345,7 +384,8 @@ enum class EnumExample {
/*
La palabra clave "object" se puede utilizar para crear objetos únicos.
No podemos asignarlo a una variable, pero podemos hacer referencia a ella por su nombre.
-Esto es similar a los objetos únicos de Scala
+Esto es similar a los objetos únicos de Scala.
+En la mayoría de ocasiones, los objetos únicos se usan como alternativa a los Singleton.
*/
object ObjectExample {
fun hello() : String {
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/es-es/scala-es.html.markdown b/es-es/scala-es.html.markdown
new file mode 100644
index 00000000..2dcb9e7f
--- /dev/null
+++ b/es-es/scala-es.html.markdown
@@ -0,0 +1,741 @@
+---
+language: Scala
+filename: learnscala-es.scala
+contributors:
+ - ["George Petrov", "http://github.com/petrovg"]
+ - ["Dominic Bou-Samra", "http://dbousamra.github.com"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+ - ["Ha-Duong Nguyen", "http://reference-error.org"]
+translators:
+ - ["Pablo Arranz Ropero", "http://arranzropablo.com"]
+lang: es-es
+---
+
+Scala - El lenguaje escalable
+
+```scala
+
+/////////////////////////////////////////////////
+// 0. Básicos
+/////////////////////////////////////////////////
+/*
+ Configurar Scala:
+
+ 1) Descarga Scala - http://www.scala-lang.org/downloads
+ 2) Unzip/untar a tu carpeta elegida y pon la subcarpeta bin en tu variable de entorno `PATH`
+*/
+
+/*
+ Prueba REPL
+
+ Scala tiene una herramienta llamada REPL (Read-Eval-Print Loop, en español: Bucle de lectura-evaluación-impresión) que es analogo a interpretes de la linea de comandos en muchos otros lenguajes.
+ Puedes escribir cualquier expresión en Scala y el resultado será evaluado e impreso.
+
+ REPL es una herramienta muy práctica para testear y verificar código.
+ Puedes usarla mientras lees este tutorial para explorar conceptos por tu cuenta.
+*/
+
+// Inicia Scala REPL ejecutando `scala` en tu terminal. Deberías ver:
+$ scala
+scala>
+
+// Por defecto cada expresión que escribes es guardada como un nuevo valor numerado:
+scala> 2 + 2
+res0: Int = 4
+
+// Los valores por defecto pueden ser reusados. Fíjate en el tipo del valor mostrado en el resultado...
+scala> res0 + 2
+res1: Int = 6
+
+// Scala es un lenguaje fuertemente tipado. Puedes usar REPL para comprobar el tipo sin evaluar una expresión.
+scala> :type (true, 2.0)
+(Boolean, Double)
+
+// Las sesiones REPL pueden ser guardadas
+scala> :save /sites/repl-test.scala
+
+// Se pueden cargar archivos en REPL
+scala> :load /sites/repl-test.scala
+Loading /sites/repl-test.scala...
+res2: Int = 4
+res3: Int = 6
+
+// Puedes buscar en tu historial reciente
+scala> :h?
+1 2 + 2
+2 res0 + 2
+3 :save /sites/repl-test.scala
+4 :load /sites/repl-test.scala
+5 :h?
+
+// Ahora que sabes como jugar, aprendamos un poco de Scala...
+
+/////////////////////////////////////////////////
+// 1. Básicos
+/////////////////////////////////////////////////
+
+// Los comentarios de una linea comienzan con dos barras inclinadas
+
+/*
+ Los comentarios de varias lineas, como ya has visto arriba, se hacen de esta manera.
+*/
+
+// Así imprimimos forzando una nueva linea en la siguiente impresión
+println("Hola mundo!")
+println(10)
+// Hola mundo!
+// 10
+
+// Así imprimimos sin forzar una nueva linea en la siguiente impresión
+print("Hola mundo")
+print(10)
+// Hola mundo10
+
+// Para declarar valores usamos var o val.
+// Valores decalrados con val son inmutables, mientras que los declarados con var son mutables.
+// La inmutabilidad es algo bueno.
+val x = 10 // x es 10
+x = 20 // error: reassignment to val
+var y = 10
+y = 20 // y es 20
+
+/*
+ Scala es un lenguaje tipado estáticamente, aunque se puede ver en las expresiones anteriores que no hemos especificado un tipo.
+ Esto es debido a una funcionalidad del lenguaje llamada inferencia. En la mayoría de los casos, el compilador de Scala puede adivinar cual es el tipo de una variable, así que no hace falta escribirlo siempre.
+ Podemos declarar explicitamente el tipo de una variable de la siguiente manera:
+*/
+val z: Int = 10
+val a: Double = 1.0
+
+// Observa la conversión automática de Int a Double, el resultado será 10.0, no 10
+val b: Double = 10
+
+// Valores Booleanos
+true
+false
+
+// Operaciones Booleanas
+!true // false
+!false // true
+true == false // false
+10 > 5 // true
+
+// Las operaciones matemáticas se realizan como siempre
+1 + 1 // 2
+2 - 1 // 1
+5 * 3 // 15
+6 / 2 // 3
+6 / 4 // 1
+6.0 / 4 // 1.5
+6 / 4.0 // 1.5
+
+
+// Evaluar una expresión en REPL te da el tipo y valor del resultado
+
+1 + 7
+
+/* La linea superior tienen como resultado:
+
+ scala> 1 + 7
+ res29: Int = 8
+
+ Esto quiere decir que el resultado de evaluar 1 + 7 es un objeto de tipo Int con valor 8
+
+ Observa que "res29" es un nombre de variable secuencialmente generado para almacenar los resultados de las expresiones escritas, la salida que observes puede diferir en este sentido.
+*/
+
+"Las cadenas en Scala están rodeadas por comillas dobles"
+'a' // Un caracter en Scala
+// 'Las cadenas con comillas simples no existen' <= Esto causa un error
+
+// Las cadenas tienen los los típicos metodos de Java definidos
+"hello world".length
+"hello world".substring(2, 6)
+"hello world".replace("C", "3")
+
+// También tienen algunos métodos extra de Scala. Ver: scala.collection.immutable.StringOps
+"hello world".take(5)
+"hello world".drop(5)
+
+// Interpolación de cadenas: Observa el prefijo "s"
+val n = 45
+s"Tengo $n manzanas" // => "Tengo 45 manzanas"
+
+// Es posible colocar expresiones dentro de cadenas interpoladas
+val a = Array(11, 9, 6)
+s"Mi segunda hija tiene ${a(0) - a(2)} años." // => "Mi segunda hija tiene 5 años."
+s"Hemos doblado la cantidad de ${n / 2.0} manzanas." // => "Hemos doblado la cantidad de 22.5 manzanas."
+s"Potencia de 2: ${math.pow(2, 2)}" // => "Potencia de 2: 4"
+
+// Podemos formatear cadenas interpoladas con el prefijo "f"
+f"Potencia de 5: ${math.pow(5, 2)}%1.0f" // "Potencia de 5: 25"
+f"Raiz cuadrada de 122: ${math.sqrt(122)}%1.4f" // "Raiz cuadrada de 122: 11.0454"
+
+// Las cadenas puras ignoran caracteres especiales.
+raw"Nueva linea: \n. Retorno: \r." // => "Nueva linea: \n. Retorno: \r."
+
+// Algunos caracteres necesitn ser escapados, por ejemplo unas comillas dobles dentro de una cadena:
+"Se quedaron fuera de \"Rose and Crown\"" // => "Se quedaron fuera de "Rose and Crown""
+
+// Las triples comillas dobles dejan que las cadenas se expandan por multiples filas y contengan comillas dobles o simples
+val html = """<form id="daform">
+ <p>Press belo', Joe</p>
+ <input type="submit">
+ </form>"""
+
+
+/////////////////////////////////////////////////
+// 2. Funciones
+/////////////////////////////////////////////////
+
+// Las funciones se definen de la siguiente manera:
+//
+// def nombreFuncion(argumentos...): TipoRetorno = { cuerpo... }
+//
+// Si estás acostumbrado a lenguajes más tradicionales, observa la omisión de la palabra return.
+// En Scala, la última expresión en el bloque de función es el valor de retorno.
+def sumaDeCuadrados(x: Int, y: Int): Int = {
+ val x2 = x * x
+ val y2 = y * y
+ x2 + y2
+}
+
+// Los { } pueden omitirse si el cuerpo de la función es una única expresión:
+def sumaDeCuadradosCorta(x: Int, y: Int): Int = x * x + y * y
+
+// La sintaxis para llamar funciones es familiar:
+sumaDeCuadrados(3, 4) // => 25
+
+// Puedes usar los nombres de los parámetros para llamarlos en orden diferente
+def restar(x: Int, y: Int): Int = x - y
+
+restar(10, 3) // => 7
+restar(y=10, x=3) // => -7
+
+// En la mayoría de los casos (siendo las funciones recursivas la excepción más notable),
+// el tipo de retorno de la función puede ser omitido, y la misma inferencia de tipos que vimos con las variables
+// funcionará con los valores de retorno de las funciones:
+def sq(x: Int) = x * x // El compilador puede adivinar que el tipo de retorno es Int
+
+// Las funciones pueden tener parametros por defecto:
+def sumarConDefecto(x: Int, y: Int = 5) = x + y
+sumarConDefecto(1, 2) // => 3
+sumarConDefecto(1) // => 6
+
+
+// Las funciones anónimas se escriben así:
+(x: Int) => x * x
+
+// Al contrario que los defs, incluso el tipo de entrada de las funciones anónimas puede ser omitido si
+// el contexto lo deja claro. Observa el tipo "Int => Int" que significa que es una función
+// que recibe Int y retorna Int.
+val sq: Int => Int = x => x * x
+
+// Las funciones anónimas pueden ser llamadas como las demás:
+sq(10) // => 100
+
+// Si cada argumento en tu función anónima es usado solo una vez,
+// Scala te da una manera incluso más corta de definirlos.
+// Estas funciones anónimas son extremadamente comunes,
+// como será obvio en la sección de estructuras de datos.
+val sumarUno: Int => Int = _ + 1
+val sumaRara: (Int, Int) => Int = (_ * 2 + _ * 3)
+
+sumarUno(5) // => 6
+sumaRara(2, 4) // => 16
+
+
+// La palabra return existe en Scala, pero solo retorna desde la función más interna que la rodea.
+// ADVERTENCIA: Usar return en Scala puede inducir a errores y debe ser evitado
+// No tiene efecto en funciones anónimas. Por ejemplo:
+def foo(x: Int): Int = {
+ val funcAnon: Int => Int = { z =>
+ if (z > 5)
+ return z // Esta línea hace que z sea el valor de retorno de foo!
+ else
+ z + 2 // Esta línea es el valor de retorno de funcAnon
+ }
+ anonFunc(x) // Esta línea es el valor de retorno de foo
+}
+
+
+/////////////////////////////////////////////////
+// 3. Control del flujo
+/////////////////////////////////////////////////
+
+1 to 5
+val r = 1 to 5
+r.foreach(println)
+
+r foreach println
+// Nota: Scala es un lenguaje muy permisivo cuando se trata de puntos y parentesis - estudia las
+// reglas separadamente. Esto ayuda a escribir DSLs y APIs que se lean en lenguaje natural.
+
+// Por qué `println` no necesita parámetros aquí?
+// Presta atención a las funciones de primera clase en la sección de Programación Funcional más abajo!
+(5 to 1 by -1) foreach (println)
+
+// Un bucle while
+var i = 0
+while (i < 10) { println("i " + i); i += 1 }
+
+while (i < 10) { println("i " + i); i += 1 } // Si, de nuevo. Qué ocurrió? Por qué?
+
+i // Muestra el valor de i. Observa que while es un loop en el sentido clásico -
+ // se ejecuta secuencialmente mientras cambia la variable del bucle. while es muy
+ // rápido, pero los combinadores y comprensiones anteriores son más sencillos
+ // de entender y paralelizar
+
+// Un bucle do-while
+i = 0
+do {
+ println("i es aún menor que 10")
+ i += 1
+} while (i < 10)
+
+// La recursion es la manera idiomática de repetir una acción en Scala (como en la mayoría de
+// lenguajes funcionales).
+// Las funciones recursivas necesitan un tipo de retorno explicito, el compilador no puede inferirlo.
+// En Scala tenemos Unit, que es análogo al tipo de retorno `void` en Java
+def enseñaNumerosEnUnRango(a: Int, b: Int): Unit = {
+ print(a)
+ if (a < b)
+ enseñaNumerosEnUnRango(a + 1, b)
+}
+enseñaNumerosEnUnRango(1, 14)
+
+
+// Condicionales
+
+val x = 10
+
+if (x == 1) println("yeah")
+if (x == 10) println("yeah")
+if (x == 11) println("yeah")
+if (x == 11) println("yeah") else println("nay")
+
+println(if (x == 10) "yeah" else "nope")
+val text = if (x == 10) "yeah" else "nope"
+
+
+/////////////////////////////////////////////////
+// 4. Estructuras de datos
+/////////////////////////////////////////////////
+
+val a = Array(1, 2, 3, 5, 8, 13)
+a(0) // Int = 1
+a(3) // Int = 5
+a(21) // Lanza una excepción
+
+val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo")
+m("fork") // java.lang.String = tenedor
+m("spoon") // java.lang.String = cuchara
+m("bottle") // Lanza una excepción
+
+val mapaSeguro = m.withDefaultValue("no lo se")
+mapaSeguro("bottle") // java.lang.String = no lo se
+
+val s = Set(1, 3, 7)
+s(0) // Boolean = false
+s(1) // Boolean = true
+
+/* Hecha un vistazo a la documentación de Map aquí -
+ * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map
+ * y asegúrate de que puedes leerla
+ */
+
+
+// Tuplas
+
+(1, 2)
+
+(4, 3, 2)
+
+(1, 2, "three")
+
+(a, 2, "three")
+
+// Por qué tener esto?
+val dividirEnteros = (x: Int, y: Int) => (x / y, x % y)
+
+// La función dividirEnteros te da el resultado y el resto
+dividirEnteros(10, 3) // (Int, Int) = (3,1)
+
+// Para acceder a los elementos de una tupla, usa _._n donde n es el indice (comenzando por 1)
+// del elemento
+val d = dividirEnteros(10, 3) // (Int, Int) = (3,1)
+
+d._1 // Int = 3
+d._2 // Int = 1
+
+// Alternativamente puedes asignar multiples variables desde una tupla, lo que
+// resulta más conveniente y legible en muchos casos.
+val (div, mod) = dividirEnteros(10, 3)
+
+div // Int = 3
+mod // Int = 1
+
+
+/////////////////////////////////////////////////
+// 5. Programación Orientada a Objetos
+/////////////////////////////////////////////////
+
+/*
+ Nota: Todo lo que hemos hecho hasta ahora en este tutorial han sido
+ simples expresiones (valores, funciones, etc). Estas expresiones son validas
+ para hacer pruebas rapidas en el interprete de la linea de comandos,
+ pero no pueden existir por si solas en un archivo de Scala. Por ejemplo,
+ no puedes tener simplemente "val x = 5" en un archivo Scala. En lugar de eso,
+ las únicas construcciones de alto nivel en Scala son:
+
+ - Objetos
+ - Clases
+ - Case clases
+ - Traits
+
+ Y ahora explicaremos lo que son estas.
+*/
+
+// Las clases son similares a las clases de otros lenguajes. Los argumentos del constructor
+// son declarados despues del nombre de la clase, y la inicialización se hace en el cuerpo de la clase.
+class Perro(r: String) {
+ // Código del constructor aquí
+ var raza: String = r
+
+ // Define un método llamado ladrar, que devuelva un String
+ def ladrar = "Woof, woof!"
+
+ // Los valores y métodos son asumidos como públicos.
+ // Las palabras "protected" y "private" también son válidas.
+ private def dormir(horas: Int) =
+ println(s"Estoy durmiendo $horas horas")
+
+ // Los métodos abstractos son simplemente métodos sin cuerpo.
+ // Si descomentamos la linea de debajo, la clase Perro necesitaría ser abstracta:
+ // abstract class Perro(...) { ... }
+ // def perseguir(algo: String): String
+}
+
+val miperro = new Dog("greyhound")
+println(mydog.raza) // => "greyhound"
+println(mydog.ladrar) // => "Woof, woof!"
+
+
+// La palabra "object" crea un tipo y una instancia singleton de ese tipo.
+// Es común que las clases en Scala tengan un "companion object", de manera que
+// el comportamiento por instancia es controlado por las clases y el comportamiento
+// relacionado a todas las instancias de esa clase es controlado por el objeto
+// La relación es similar a los métodos de las clases con los métodos estáticos
+// en otros lenguajes. Observa que los objetos y clases pueden tener el mismo nombre.
+object Perro {
+ def todasLasRazasConocidas = List("pitbull", "shepherd", "retriever")
+ def crearPerro(raza: String) = new Dog(breed)
+}
+
+
+// Case clases son clases que tienen funcionalidad extra añadida. Una pregunta
+// común para los principiantes en Scala es cuando usar case clases y cuando usar
+// clases. La linea no está bien definida, pero en general, las clases tienden a
+// enfocarse en la encapsulación, polimorfismo y comportamiento. Los valores en
+// estas clases tienden a ser privados, y solo se exponen los métodos.
+// El propósito principal de las case clases es tener datos inmutables.
+// A menudo tienen pocos métodos, y los métodos raramente tienen efectos secundarios.
+case class Persona(nombre: String, telefono: String)
+
+// Para crear instancia nuevas, observa que las case clases no necesitan "new"
+val george = Persona("George", "1234")
+val kate = Persona("Kate", "4567")
+
+// Con las case clases tienes unas pocas ventajas, como el acceso a los campos:
+george.telefono // => "1234"
+
+// Para la igualdad de campos no necesitas sobreescribir el método equals
+Persona("George", "1234") == Persona("Kate", "1236") // => false
+
+// Manera fácil de copiar
+// otroGeorge == Persona("George", "9876")
+val otroGeorge = george.copy(telefono = "9876")
+
+// Y muchas otras. Las case clases también tienen comparación de patrones, que veremos más abajo.
+
+// Traits
+// De manera similar a las interfaces Java, los traits definen un tipo de objeto y métodos.
+// Scala permite la implementación parcial de dichos métodos.
+// No se permiten parámetros de constructor. Los traits pueden heredar de otros traits o
+// clases sin parámetros.
+
+trait Perro {
+ def raza: String
+ def color: String
+ def ladra: Boolean = true
+ def muerde: Boolean
+}
+class SanBernardo extends Perro {
+ val raza = "San Bernardo"
+ val color = "marrón"
+ def muerde = false
+}
+
+scala> b
+res0: SanBernardo = SanBernardo@3e57cd70
+scala> b.raza
+res1: String = San Bernardo
+scala> b.ladra
+res2: Boolean = true
+scala> b.muerde
+res3: Boolean = false
+
+// Un trait tambien puede ser usado mezclado con otros traits.
+// La clase extiende el primer trait, pero la palabra "with"
+// puede añadir traits adicionales.
+
+trait Ladra {
+ def ladra: String = "Guau"
+}
+trait Perro {
+ def raza: String
+ def color: String
+}
+class SanBernardo extends Perro with Ladra {
+ val raza = "San Bernardo"
+ val color = "marrón"
+}
+
+scala> val b = new SanBernardo
+b: SanBernardo = SanBernardo@7b69c6ba
+scala> b.ladra
+res0: String = Guau
+
+
+/////////////////////////////////////////////////
+// 6. Comparación de patrones
+/////////////////////////////////////////////////
+
+// La comparación de patrones es una poderosa función de Scala.
+// Ahora veremos como comparar patrones en una case clase.
+// Nota: A diferencia de otros lenguajes, Scala "cases" no necesitan
+// "break", porque no ejecuta los "case" posteriores.
+
+def comparaPersona(persona: Persona): String = persona match {
+ // Aqui especificas los patrones:
+ case Persona("George", telefono) => "Hemos encontrado a George! Su número es " + telefono
+ case Persona("Kate", telefono) => "Hemos encontrado a Kate! Su número es " + telefono
+ case Persona(nombre, telefono) => "Hemos encontrado alguien : " + nombre + ", teléfono : " + telefono
+}
+
+// Las expresiones regulares también están incorporadas.
+// Creas una expresión regular con el método `r` en una cadena:
+val email = "(.*)@(.*)".r
+
+// La comparación de patrones puede parecerse al bloque switch en la familia de lenguajes de C,
+// pero aquí es mucho más poderosa. En Scala, puedes hacer más comparaciones:
+def comparaTodo(obj: Any): String = obj match {
+ // Puedes comparar valores:
+ case "Hola mundo" => "Tengo la cadena Hola mundo"
+
+ // Puedes comparar tipos:
+ case x: Double => "Tengo un double: " + x
+
+ // Puedes especificar condiciones:
+ case x: Int if x > 10000 => "Tengo un número muy grande!"
+
+ // Puedes comparar case clases como antes:
+ case Persona(nombre, telefono) => s"Tengo la información de contacto de $nombre!"
+
+ // Puedes comparar expresiones regulares:
+ case email(nombre, dominio) => s"Tengo la dirección de correo $nombre@$dominio"
+
+ // Puedes comparar tuplas:
+ case (a: Int, b: Double, c: String) => s"Tengo la tupla: $a, $b, $c"
+
+ // Puedes comparar estructuras:
+ case List(1, b, c) => s"Tengo un alista con tres elementos que empieza con 1: 1, $b, $c"
+
+ // Puedes anidar patrones:
+ case List(List((1, 2, "YAY"))) => "Tengo una lista de listas de tuplas"
+
+ // Comparar cualquier case (default) si todos los anteriores no han coincido
+ case _ => "Tengo un objeto desconocido"
+}
+
+// De hecho puedes comparar un patrón con cualquier objeto con el método "unapply".
+// Esta función es tan poderosa que Scala te deja definir funciones enteras como patrones:
+val funcPatron: Person => String = {
+ case Persona("George", telefono) => s"Teléfono de George: $telefono"
+ case Persona(nombre, telefono) => s"Teléfono de una persona aleatoria: $telefono"
+}
+
+
+/////////////////////////////////////////////////
+// 7. Programación funcional
+/////////////////////////////////////////////////
+
+// Scala permite a los métodos y funciones devolver o
+// recibir como parámetros otras funciones o métodos
+
+val suma10: Int => Int = _ + 10 // Una función que recibe y devuelve un Int
+List(1, 2, 3) map suma10 // List(11, 12, 13) - suma10 es aplicado a cada elemento
+
+// Las funciones anónimas pueden ser usadas en vez de funciones con nombre:
+List(1, 2, 3) map (x => x + 10)
+
+// Y la barra baja puede ser usada si solo hay un argumento en la función anónima.
+// Se usa como la variable.
+List(1, 2, 3) map (_ + 10)
+
+// Si el bloque anónimo Y la función que estás usando usan los dos un argumento,
+// puedes incluso omitir la barra baja.
+List("Dom", "Bob", "Natalia") foreach println
+
+
+// Combinadores
+// Usando s de arriba:
+// val s = Set(1, 3, 7)
+
+s.map(sq)
+
+val sCuadrado = s. map(sq)
+
+sSquared.filter(_ < 10)
+
+sSquared.reduce (_+_)
+
+// La función filter toma un predicado (una función A -> Boolean) y
+// selecciona todos los elementos que satisfacen el predicado.
+List(1, 2, 3) filter (_ > 2) // List(3)
+case class Persona(nombre: String, edad: Int)
+List(
+ Persona(nombre = "Dom", edad = 23),
+ Persona(nombre = "Bob", edad = 30)
+).filter(_.edad > 25) // List(Persona("Bob", 30))
+
+
+// Ciertas colecciones (como List) en Scala tienen un método `foreach`,
+// que toma como argumento un tipo que devuelva Unit (un método void)
+val unaListaDeNumeros = List(1, 2, 3, 4, 10, 20, 100)
+unaListaDeNumeros foreach (x => println(x))
+unaListaDeNumeros foreach println
+
+// Para comprensiones
+
+for { n <- s } yield sq(n)
+
+val nCuadrado2 = for { n <- s } yield sq(n)
+
+for { n <- nSquared2 if n < 10 } yield n
+
+for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared
+
+/* Nota: Esos no son bucles. La semántica de un bucle es repetir, mientras que un for de comprension define una relación entre dos conjuntos de datos.*/
+
+
+/////////////////////////////////////////////////
+// 8. Implicitos
+/////////////////////////////////////////////////
+
+/* ATENCIÓN ATENCIÓN: Los implicitos son un conjunto de poderosas características de Scala
+ * y es fácil abusar de ellos. Si eres principiante en Scala deberías resistir la tentación
+ * de usarlos hasta que entiendas no solo como funcionan, sino también las mejores prácticas
+ * con ellos. Nosotros solo incluiremos esta sección en el tutorial porque son tan comunes
+ * en las librerias de Scala que es imposible hacer algo significativo sin usar una librería
+ * que tenga implicitos. Esto es para que entiendas como funcionan los implicitos, no para
+ * que definas los tuyos propios.
+ */
+
+// Cualquier valor (val, funciones, objetos, etc) puede ser declarado como implicito usando
+// la palabra "implicit". Observa que usamos la clase Perro de la sección 5.
+implicit val miEnteroImplicito = 100
+implicit def miFunciónImplicita(raza: String) = new Perro("Golden " + raza)
+
+// Por si misma, la palabra implicit no cambia el comportamiento de un valor,
+// así que estos valores pueden ser usados como siempre.
+miEnteroImplicito + 2 // => 102
+miFunciónImplicita("Pitbull").raza // => "Golden Pitbull"
+
+// La diferencia es que estos valores ahora pueden ser usados cuando otra pieza de código
+// necesite un valor implicito. Una situación así puede darse con argumentos implicitos de función:
+def enviaSaludos(aQuien: String)(implicit cuantos: Int) =
+ s"Hola $aQuien, $cuantos saludos a ti y a los tuyos!"
+
+// Si proporcionamos un valor para "cuantos", la función se comporta como siempre
+enviaSaludos("John")(1000) // => "Hola John, 1000 saludos a ti y a los tuyos!"
+
+// Pero si omitimos el parámetro implicito, un valor implicito del mismo tipo es usado,
+// en este caso, "miEnteroImplicito":
+enviaSaludos("Jane") // => "Hello Jane, 100 blessings to you and yours!"
+
+// Los parámetros de función implicit nos permiten simular clases tipo en otros lenguajes funcionales.
+// Es usado tan a menudo que tiene su propio atajo. Las dos siguientes lineas significan lo mismo:
+// def foo[T](implicit c: C[T]) = ...
+// def foo[T : C] = ...
+
+
+// Otra situación en la que el compilador busca un implicit es si tienes
+// obj.método(...)
+// pero "obj" no tiene "método" como un método. En este caso, si hay una conversión
+// implicita de tipo A => B, donde A es el tipo de obj y B tiene un método llamado
+// "método", esa conversión es aplicada. Así que teniendo miFunciónImplicita, podemos decir:
+"Retriever".raza // => "Golden Retriever"
+"Sheperd".ladra // => "Woof, woof!"
+
+// Aquí la cadena es convertida primero a Perro usando nuestra función miFunciónImplicita,
+// y entonces el método apropiado es llamado. Esta es una herramienta extremadamente poderosa
+// pero de nuevo, no puede usarse con ligereza. De hecho, cuando definiste la función implicita,
+// tu compilador debería haber mostrado una advertencia, diciendo que no deberías hacer esto
+// a no ser que realmente sepas lo que estás haciendo.
+
+/////////////////////////////////////////////////
+// 9. Misc
+/////////////////////////////////////////////////
+
+// Importando cosas
+import scala.collection.immutable.List
+
+// Importando todos los "sub paquetes"
+import scala.collection.immutable._
+
+// Importando multiples clases en una línea
+import scala.collection.immutable.{List, Map}
+
+// Renombrar un import usando '=>'
+import scala.collection.immutable.{List => ImmutableList}
+
+// Importar todas las clases, excepto algunas. La siguiente linea excluye Map y Set:
+import scala.collection.immutable.{Map => _, Set => _, _}
+
+// Las clases de Java pueden ser importadas también con sintaxis de Scala:
+import java.swing.{JFrame, JWindow}
+
+// El punto de entrada de tus programas está definido en un fichero scala usando un object,
+// con un solo método, main:
+object Application {
+ def main(args: Array[String]): Unit = {
+ // Aquí va tu código.
+ }
+}
+
+// Los ficheros pueden contener multiples clases y objetos. Compila con scalac
+
+
+// Salida y entrada
+
+// Leer un fichero línea por línea
+import scala.io.Source
+for(line <- Source.fromFile("miarchivo.txt").getLines())
+ println(line)
+
+// Para escribir un archivo usa el PrintWriter de Java
+val writer = new PrintWriter("miarchivo.txt")
+writer.write("Escribiendo linea por linea" + util.Properties.lineSeparator)
+writer.write("Otra linea" + util.Properties.lineSeparator)
+writer.close()
+
+```
+
+## Más recursos
+
+* [Scala para los impacientes](http://horstmann.com/scala/)
+* [Escuela de Scala en Twitter](http://twitter.github.io/scala_school/)
+* [La documentación de Scala](http://docs.scala-lang.org/)
+* [Prueba Scala en tu navegador](http://scalatutorials.com/tour/)
+* Unete al [grupo de usuarios de Scala](https://groups.google.com/forum/#!forum/scala-user)
diff --git a/fr-fr/elixir-fr.html.markdown b/fr-fr/elixir-fr.html.markdown
new file mode 100644
index 00000000..90cdad7c
--- /dev/null
+++ b/fr-fr/elixir-fr.html.markdown
@@ -0,0 +1,479 @@
+---
+language: elixir
+contributors:
+ - ["Joao Marques", "http://github.com/mrshankly"]
+ - ["Dzianis Dashkevich", "https://github.com/dskecse"]
+ - ["Ryan Plant", "https://github.com/ryanplant-au"]
+ - ["Ev Bogdanov", "https://github.com/evbogdanov"]
+translator:
+ - ["Timothé Pardieu", "https://github.com/timprd"]
+filename: learnelixir-fr.ex
+lang: fr-fr
+---
+Elixir est un langage de programmation fonctionnel moderne reposant sur la machine virtuelle BEAM, qui héberge aussi Erlang.
+Il est totalement compatible avec Erlang mais dispose d'une syntaxe plus agréable et apporte de nouvelles fonctionnalités.
+
+
+```elixir
+
+# Un commentaire simple sur une seule ligne commence par un dièse.
+
+# Il n'y a pas de commentaire multi-ligne,
+# Mais il est possible de les empiler comme ici.
+
+# La commande `iex` permet de lancer le shell Elixir.
+# La commande `elixirc` permet de compiler vos modules.
+
+# Les deux devraient être dans votre path si vous avez installé Elixir correctement.
+
+## ---------------------------
+## -- Types basiques
+## ---------------------------
+
+# Il y a les nombres
+3 # Integer
+0x1F # Integer
+3.0 # Float
+
+# Les atomes, des littéraux, qui sont des constantes avec comme valeur leur nom.
+# Ils commencent par `:`.
+
+:hello # atom
+
+# Il existe également des n-uplets dont les valeurs sont stockés de manière contiguë
+# en mémoire.
+
+{1,2,3} # tuple
+
+# Il est possible d'accéder à un element d'un tuple avec la fonction
+# `elem`:
+elem({1, 2, 3}, 0) #=> 1
+
+# Les listes sont implémentées sous forme de listes chainées.
+[1,2,3] # list
+
+# La tête et le reste d'une liste peuvent être récupérés comme cela :
+[head | tail] = [1,2,3]
+head #=> 1
+tail #=> [2,3]
+
+# En Elixir, comme en Erlang, le `=` dénote un 'pattern matching'
+# (Filtrage par motif) et non une affectation.
+# Cela signifie que la partie de gauche (pattern) est comparé (match) à
+# la partie de droite.
+
+
+# Une erreur sera lancée si aucun model (match) est trouvé.
+# Dans cet exemple les tuples ont des tailles différentes
+# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
+
+# Il y a aussi les binaires
+<<1,2,3>> # binary
+
+# Chaine de caractères et liste de caractères
+"hello" # string
+'hello' # char list
+
+# Chaine de caractères sur plusieurs lignes
+"""
+Je suis une chaine de caractères
+sur plusieurs lignes.
+"""
+#=> "Je suis une chaine de caractères\nsur plusieurs lignes.\n"
+
+# Les chaines de caractères sont encodées en UTF-8 :
+"héllò" #=> "héllò"
+
+# Les chaines de caractères sont des binaires tandis que
+# les listes de caractères sont des listes.
+<<?a, ?b, ?c>> #=> "abc"
+[?a, ?b, ?c] #=> 'abc'
+
+# `?a` en Elixir retourne le code ASCII (Integer) de la lettre `a`
+?a #=> 97
+
+# Pour concaténer des listes il faut utiliser `++`, et `<>` pour les
+# binaires
+[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
+'hello ' ++ 'world' #=> 'hello world'
+
+<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
+"hello " <> "world" #=> "hello world"
+
+# Les intervalles sont représentés de cette sorte `début..fin`
+# (tout deux inclusifs)
+1..10 #=> 1..10
+bas..haut = 1..10 # Possibilité d'utiliser le pattern matching sur les intervalles aussi.
+[bas, haut] #=> [1, 10]
+
+# Les Maps (Tableau associatif) sont des paires clée - valeur
+genders = %{"david" => "male", "gillian" => "female"}
+genders["david"] #=> "male"
+
+# Les maps avec des atomes peuvent être utilisés comme cela
+genders = %{david: "male", gillian: "female"}
+genders.gillian #=> "female"
+
+## ---------------------------
+## -- Operateurs
+## ---------------------------
+
+# Mathématiques
+1 + 1 #=> 2
+10 - 5 #=> 5
+5 * 2 #=> 10
+10 / 2 #=> 5.0
+
+# En Elixir l'opérateur `/` retourne toujours un Float (virgule flottante).
+
+# Pour faire une division avec entier il faut utiliser `div`
+div(10, 2) #=> 5
+
+# Pour obtenir le reste de la division il faut utiliser `rem`
+rem(10, 3) #=> 1
+
+# Il y a aussi les opérateurs booléen: `or`, `and` et `not`.
+# Ces opérateurs attendent un booléen en premier argument.
+true and true #=> true
+false or true #=> true
+# 1 and true
+#=> ** (BadBooleanError) expected a booléens on left-side of "and", got: 1
+
+# Elixir fournit aussi `||`, `&&` et `!` qui acceptent des arguments de
+# tout type.
+# Chaque valeur sauf `false` et `nil` seront évalués à vrai (true).
+1 || true #=> 1
+false && 1 #=> false
+nil && 20 #=> nil
+!true #=> false
+
+# Pour les comparaisons il y a : `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` et `>`
+1 == 1 #=> true
+1 != 1 #=> false
+1 < 2 #=> true
+
+# `===` et `!==` sont plus stricts en comparant les Integers (entiers)
+# et les Floats (nombres à virgules) :
+1 == 1.0 #=> true
+1 === 1.0 #=> false
+
+# On peut aussi comparer deux types de données différents :
+1 < :hello #=> true
+
+# L'ordre est défini de la sorte :
+# number < atom < reference < functions < port < pid < tuple < list < bit string
+
+# Pour citer Joe Armstrong : "The actual order is not important,
+# but that a total ordering is well defined is important."
+
+## ---------------------------
+## -- Structure de contrôle
+## ---------------------------
+
+# Condition avec `if` (si)
+if false do
+ "Cela ne sera pas vu"
+else
+ "Cela le sera"
+end
+
+# Condition avec `unless` (sauf).
+# Il correspond à la négation d'un `if` (si)
+unless true do
+ "Cela ne sera pas vu"
+else
+ "Cela le sera"
+end
+
+# Beaucoup de structures en Elixir se basent sur le pattern matching.
+# `case` permet de comparer une valeur à plusieurs modèles:
+case {:one, :two} do
+ {:four, :five} ->
+ "Ne match pas"
+ {:one, x} ->
+ "Match et lie `x` à `:two` dans ce cas"
+ _ ->
+ "Match toutes les valeurs"
+end
+
+# Il est commun de lier la valeur à `_` si on ne l'utilise pas.
+# Par exemple, si seulement la tête d'une liste nous intéresse:
+[head | _] = [1,2,3]
+head #=> 1
+
+# Pour plus de lisibilité, ce procédé est utilisé:
+[head | _tail] = [:a, :b, :c]
+head #=> :a
+
+# `cond` permet de vérifier plusieurs conditions à la fois.
+# Il est conseillé d'utiliser `cond` plutôt que des `if` imbriqués.
+cond do
+ 1 + 1 == 3 ->
+ "Je ne serai pas vu"
+ 2 * 5 == 12 ->
+ "Moi non plus"
+ 1 + 2 == 3 ->
+ "Mais moi oui"
+end
+
+# Il est commun d'attribuer la dernière condition à true (vrai), qui
+# matchera toujours.
+cond do
+ 1 + 1 == 3 ->
+ "Je ne serai pas vu"
+ 2 * 5 == 12 ->
+ "Moi non plus"
+ true ->
+ "Mais moi oui (représente un else)"
+end
+
+# `try/catch` est utilisé pour attraper les valeurs rejetées.
+# Il supporte aussi un
+# `after` qui est appelé autant si une valeur est jetée ou non.
+try do
+ throw(:hello)
+catch
+ message -> "Message : #{message}."
+after
+ IO.puts("Je suis la clause after (après).")
+end
+#=> Je suis la clause after (après).
+# "Message : :hello"
+
+## ---------------------------
+## -- Modules et Fonctions
+## ---------------------------
+
+# Fonctions anonymes (notez le point).
+square = fn(x) -> x * x end
+square.(5) #=> 25
+
+# Les fonctions anonymes acceptent aussi de nombreuses clauses et guards (gardes).
+# Les guards permettent d'affiner le pattern matching,
+# ils sont indiqués par le mot-clef `when` :
+f = fn
+ x, y when x > 0 -> x + y
+ x, y -> x * y
+end
+
+f.(1, 3) #=> 4
+f.(-1, 3) #=> -3
+
+# Elixir propose aussi de nombreuses fonctions internes.
+is_number(10) #=> true
+is_list("hello") #=> false
+elem({1,2,3}, 0) #=> 1
+
+# Il est possible de grouper plusieurs fonctions dans un module.
+# Dans un module, les fonctions sont définies par `def`
+defmodule Math do
+ def sum(a, b) do
+ a + b
+ end
+
+ def square(x) do
+ x * x
+ end
+end
+
+Math.sum(1, 2) #=> 3
+Math.square(3) #=> 9
+
+# Pour compiler notre module `Math`,
+# il faut le sauvegarder en tant que `math.ex` et utiliser `elixirc`.
+# Executez ainsi `elixirc math.ex` dans le terminal.
+
+# Au sein d'un module, nous pouvons définir les fonctions avec `def`
+# et `defp` pour les fonctions privées.
+# Une fonction définie par `def` est disponible dans les autres
+# modules. Une fonction privée est disponible localement seulement.
+defmodule PrivateMath do
+ def sum(a, b) do
+ do_sum(a, b)
+ end
+
+ defp do_sum(a, b) do
+ a + b
+ end
+end
+
+PrivateMath.sum(1, 2) #=> 3
+# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
+
+# La déclaration de fonction supporte également les guards (gardes)
+# et les clauses.
+# Quand une fonction avec plusieurs clauses est appelée,
+# la première fonction dont la clause est satisfaite par les arguments sera appelée.
+# Exemple: le code `area({:circle, 3})` appelle la deuxième fonction definie plus bas,
+# et non la première car ses arguments correspondent à la signature de cette dernière:
+defmodule Geometry do
+ def area({:rectangle, w, h}) do
+ w * h
+ end
+
+ def area({:circle, r}) when is_number(r) do
+ 3.14 * r * r
+ end
+end
+
+Geometry.area({:rectangle, 2, 3}) #=> 6
+Geometry.area({:circle, 3}) #=> 28.25999999999999801048
+# Geometry.area({:circle, "not_a_number"})
+#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
+
+# En raison de l'immutabilité, la récursivité est une grande partie
+# d'Elixir
+defmodule Recursion do
+ def sum_list([head | tail], acc) do
+ sum_list(tail, acc + head)
+ end
+
+ def sum_list([], acc) do
+ acc
+ end
+end
+
+Recursion.sum_list([1,2,3], 0) #=> 6
+
+# Les modules Elixir supportent des attributs internes,
+# ceux-ci peuvent aussi être personnalisés.
+defmodule MyMod do
+ @moduledoc """
+ This is a built-in attribute on a example module.
+ """
+
+ @my_data 100 # Attribut personnel.
+ IO.inspect(@my_data) #=> 100
+end
+
+# L'opérateur pipe (|>) permet de passer la sortie d'une expression
+# en premier paramètre d'une fonction.
+
+Range.new(1,10)
+|> Enum.map(fn x -> x * x end)
+|> Enum.filter(fn x -> rem(x, 2) == 0 end)
+#=> [4, 16, 36, 64, 100]
+
+## ---------------------------
+## -- Structs et Exceptions
+## ---------------------------
+
+# Les Structs sont des extensions des Maps.
+# Apportant en plus les valeurs par defaut, le polymorphisme et
+# la vérification à la compilation dans Elixir.
+defmodule Person do
+ defstruct name: nil, age: 0, height: 0
+end
+
+jean_info = %Person{ name: "Jean", age: 30, height: 180 }
+#=> %Person{age: 30, height: 180, name: "Jean"}
+
+# Access the value of name
+jean_info.name #=> "Jean"
+
+# Update the value of age
+older_jean_info = %{ jean_info | age: 31 }
+#=> %Person{age: 31, height: 180, name: "Jean"}
+
+# Le bloc `try` avec le mot-clef `rescue` est utilisé pour gérer les exceptions
+try do
+ raise "some error"
+rescue
+ RuntimeError -> "rescued a runtime error"
+ _error -> "this will rescue any error"
+end
+#=> "rescued a runtime error"
+
+# Chaque exception possède un message
+try do
+ raise "some error"
+rescue
+ x in [RuntimeError] ->
+ x.message
+end
+#=> "some error"
+
+## ---------------------------
+## -- Concurrence
+## ---------------------------
+
+# Elixir se repose sur le modèle d'acteur pour gérer la concurrence.
+# Pour écrire un programme concurrent en Elixir il faut trois
+# primitives: spawning processes (création), sending messages (envoi)
+# et receiving messages (réception).
+
+# Pour débuter un nouveau processus, il faut utiliser
+# la fonction `spawn` qui prend en argument une fonction.
+f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
+spawn(f) #=> #PID<0.40.0>
+
+# `spawn` retourn un pid (identifiant de processus), il est possible
+# d'utiliser ce pid pour envoyer un message au processus.
+# Pour faire parvenir le message il faut utiliser l'opérateur `send`.
+# Pour que cela soit utile il faut être capable de recevoir les
+# messages.
+# Cela est possible grâce au mechanisme de `receive`:
+
+# Le bloc `receive do` est utilisé pour écouter les messages et les traiter
+# au moment de la réception. Un bloc `receive do` pourra traiter un seul
+# message reçu.
+# Pour traiter plusieurs messages, une fonction avec un bloc `receive do`
+# doit s'appeler elle-même récursivement.
+
+defmodule Geometry do
+ def area_loop do
+ receive do
+ {:rectangle, w, h} ->
+ IO.puts("Area = #{w * h}")
+ area_loop()
+ {:circle, r} ->
+ IO.puts("Area = #{3.14 * r * r}")
+ area_loop()
+ end
+ end
+end
+
+# Ceci compile le module et créer un processus qui évalue dans le terminal `area_loop`
+pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
+# Alternativement
+pid = spawn(Geometry, :area_loop, [])
+
+# On envoi un message au `pid` qui correspond à la régle de réception.
+send pid, {:rectangle, 2, 3}
+#=> Area = 6
+# {:rectangle,2,3}
+
+send pid, {:circle, 2}
+#=> Area = 12.56000000000000049738
+# {:circle,2}
+
+# Le shell est aussi un processus, il est possible d'utiliser `self`
+# pour obtenir le pid du processus courant.
+self() #=> #PID<0.27.0>
+
+## ---------------------------
+## -- Agents
+## ---------------------------
+
+# Un agent est un processus qui garde les traces des valeurs modifiées.
+
+# Pour créer un agent on utilise `Agent.start_link` avec une fonction.
+# L'état initial de l'agent sera ce que la fonction retourne
+{ok, my_agent} = Agent.start_link(fn -> ["red", "green"] end)
+
+# `Agent.get` prend un nom d'agent et une fonction (`fn`).
+# Qu'importe ce que cette `fn` retourne, l'état sera ce qui est retourné.
+Agent.get(my_agent, fn colors -> colors end) #=> ["red", "green"]
+
+# Modification de l'état de l'agent
+Agent.update(my_agent, fn colors -> ["blue" | colors] end)
+```
+
+## Références
+
+* [Guide de debut](http://elixir-lang.org/getting-started/introduction.html) depuis le site [Elixir](http://elixir-lang.org)
+* [Documentation Elixir ](https://elixir-lang.org/docs.html)
+* ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) de Dave Thomas
+* [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf)
+* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) de Fred Hebert
+* ["Programming Erlang: Software for a Concurrent World"](https://pragprog.com/book/jaerlang2/programming-erlang) de Joe Armstrong
diff --git a/fr-fr/erlang-fr.html.markdown b/fr-fr/erlang-fr.html.markdown
index 55453c56..1073d6ad 100644
--- a/fr-fr/erlang-fr.html.markdown
+++ b/fr-fr/erlang-fr.html.markdown
@@ -28,7 +28,7 @@ lang: fr-fr
%% 1. Variables et filtrage par motif
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-(L'équivalent anglais de *filtrage par motif* est *pattern patching*.)
+(L'équivalent anglais de *filtrage par motif* est *pattern matching*.)
Nb = 42. % Chaque nom de variable doit commencer par une lettre majuscule.
@@ -64,7 +64,7 @@ Point = {point, 10, 45}.
{point, X, Y} = Point. % X = 10, Y = 45
% On peut utiliser `_` comme caractère joker pour les variables qui ne nous
-% intéressent pas. Le symbol `_` est appelé variable muette. Contrairement
+% intéressent pas. Le symbole `_` est appelé variable muette. Contrairement
% aux variables normales, de multiples apparitions de `_` dans un même motif
% ne lient pas nécessairement à la même valeur.
Personne = {personne, {nom, {prenom, joe}, {famille, armstrong}},
diff --git a/fsharp.html.markdown b/fsharp.html.markdown
index 59461eed..064a9fdd 100644
--- a/fsharp.html.markdown
+++ b/fsharp.html.markdown
@@ -14,7 +14,7 @@ The syntax of F# is different from C-style languages:
* Curly braces are not used to delimit blocks of code. Instead, indentation is used (like Python).
* Whitespace is used to separate parameters rather than commas.
-If you want to try out the code below, you can go to [tryfsharp.org](http://www.tryfsharp.org/Create) and paste it into an interactive REPL.
+If you want to try out the code below, you can go to [https://try.fsharp.org](https://try.fsharp.org) and paste it into an interactive REPL.
```csharp
@@ -194,7 +194,7 @@ module ListExamples =
| [] -> printfn "the list is empty"
| [first] -> printfn "the list has one element %A " first
| [first; second] -> printfn "list is %A and %A" first second
- | _ -> printfn "the list has more than two elements"
+ | first :: _ -> printfn "the list has more than two elements, first element %A" first
listMatcher [1; 2; 3; 4]
listMatcher [1; 2]
diff --git a/go.html.markdown b/go.html.markdown
index ae99535b..4fc155b5 100644
--- a/go.html.markdown
+++ b/go.html.markdown
@@ -30,6 +30,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
diff --git a/groovy.html.markdown b/groovy.html.markdown
index efbb2b32..89ca973a 100644
--- a/groovy.html.markdown
+++ b/groovy.html.markdown
@@ -181,6 +181,21 @@ class Foo {
}
/*
+ Methods with optional parameters
+*/
+
+// A mthod can have default values for parameters
+def say(msg = 'Hello', name = 'world') {
+ "$msg $name!"
+}
+
+// It can be called in 3 different ways
+assert 'Hello world!' == say()
+// Right most parameter with default value is eliminated first.
+assert 'Hi world!' == say('Hi')
+assert 'learn groovy' == say('learn', 'groovy')
+
+/*
Logical Branching and Looping
*/
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/haxe.html.markdown b/haxe.html.markdown
index f7633dbf..e086dd7a 100644
--- a/haxe.html.markdown
+++ b/haxe.html.markdown
@@ -6,8 +6,8 @@ contributors:
- ["Dan Korostelev", "https://github.com/nadako/"]
---
-Haxe is a web-oriented language that provides platform support for C++, C#,
-Swf/ActionScript, Javascript, Java, PHP, Python, Lua, HashLink, and Neko byte code
+[Haxe](https://haxe.org/) is a general-purpose language that provides platform support for C++, C#,
+Swf/ActionScript, JavaScript, Java, PHP, Python, Lua, HashLink, and Neko bytecode
(the latter two being also written by the Haxe author). Note that this guide is for
Haxe version 3. Some of the guide may be applicable to older versions, but it is
recommended to use other references.
@@ -189,7 +189,7 @@ class LearnHaxe3 {
trace(m.get('bar') + " is the value for m.get('bar')");
trace(m['bar'] + " is the value for m['bar']");
- var m2 = ['foo' => 4, 'baz' => 6]; // Alternative map syntax
+ var m2 = ['foo' => 4, 'baz' => 6]; // Alternative map syntax
trace(m2 + " is the value for m2");
// Remember, you can use type inference. The Haxe compiler will
@@ -234,10 +234,9 @@ class LearnHaxe3 {
^ Bitwise exclusive OR
| Bitwise inclusive OR
*/
-
- // increments
+
var i = 0;
- trace("Increments and decrements");
+ trace("Pre-/Post- Increments and Decrements");
trace(i++); // i = 1. Post-Increment
trace(++i); // i = 2. Pre-Increment
trace(i--); // i = 1. Post-Decrement
@@ -287,7 +286,7 @@ class LearnHaxe3 {
}
// do-while loop
- var l = 0;
+ var l = 0;
do {
trace("do statement always runs at least once");
} while (l > 0);
@@ -334,11 +333,11 @@ class LearnHaxe3 {
Switch statements in Haxe are very powerful. In addition to working
on basic values like strings and ints, they can also work on the
generalized algebraic data types in enums (more on enums later).
- Here's some basic value examples for now:
+ Here are some basic value examples for now:
*/
var my_dog_name = "fido";
var favorite_thing = "";
- switch(my_dog_name) {
+ switch (my_dog_name) {
case "fido" : favorite_thing = "bone";
case "rex" : favorite_thing = "shoe";
case "spot" : favorite_thing = "tennis ball";
@@ -366,7 +365,7 @@ class LearnHaxe3 {
trace("k equals ", k); // outputs 10
- var other_favorite_thing = switch(my_dog_name) {
+ var other_favorite_thing = switch (my_dog_name) {
case "fido" : "teddy";
case "rex" : "stick";
case "spot" : "football";
@@ -559,7 +558,7 @@ class SimpleEnumTest {
// You can specify the "full" name,
var e_explicit:SimpleEnum = SimpleEnum.Foo;
var e = Foo; // but inference will work as well.
- switch(e) {
+ switch (e) {
case Foo: trace("e was Foo");
case Bar: trace("e was Bar");
case Baz: trace("e was Baz"); // comment this line to throw an error.
@@ -572,7 +571,7 @@ class SimpleEnumTest {
You can also specify a default for enum switches as well:
*/
- switch(e) {
+ switch (e) {
case Foo: trace("e was Foo again");
default : trace("default works here too");
}
@@ -594,22 +593,22 @@ class ComplexEnumTest {
public static function example() {
var e1:ComplexEnum = IntEnum(4); // specifying the enum parameter
// Now we can switch on the enum, as well as extract any parameters
- // it might of had.
- switch(e1) {
+ // it might have had.
+ switch (e1) {
case IntEnum(x) : trace('$x was the parameter passed to e1');
default: trace("Shouldn't be printed");
}
// another parameter here that is itself an enum... an enum enum?
var e2 = SimpleEnumEnum(Foo);
- switch(e2){
+ switch (e2){
case SimpleEnumEnum(s): trace('$s was the parameter passed to e2');
default: trace("Shouldn't be printed");
}
// enums all the way down
var e3 = ComplexEnumEnum(ComplexEnumEnum(MultiEnum(4, 'hi', 4.3)));
- switch(e3) {
+ switch (e3) {
// You can look for certain nested enums by specifying them
// explicitly:
case ComplexEnumEnum(ComplexEnumEnum(MultiEnum(i,j,k))) : {
@@ -668,7 +667,7 @@ class TypedefsAndStructuralTypes {
That would give us a single "Surface" type to work with across
all of those platforms.
- */
+ */
}
}
@@ -700,8 +699,7 @@ class UsingExample {
instance, and the compiler still generates code equivalent to a
static method.
*/
- }
-
+ }
}
```
diff --git a/html.html.markdown b/html.html.markdown
index f01f139c..b8212776 100644
--- a/html.html.markdown
+++ b/html.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["Christophe THOMAS", "https://github.com/WinChris"]
translators:
- ["Robert Steed", "https://github.com/robochat"]
+ - ["Dimitri Kokkonis", "https://github.com/kokkonisd"]
---
HTML stands for HyperText Markup Language.
diff --git a/it-it/bash-it.html.markdown b/it-it/bash-it.html.markdown
index efc47969..099cc681 100644
--- a/it-it/bash-it.html.markdown
+++ b/it-it/bash-it.html.markdown
@@ -140,6 +140,25 @@ then
echo "Questo verrà eseguito se $Nome è Daniya O Zach."
fi
+# C'è anche l'operatore `=~`, che serve per confrontare una stringa con un'espressione regolare:
+Email=me@example.com
+if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]]
+then
+ echo "Email valida!"
+fi
+# L'operatore =~ funziona solo dentro alle doppie parentesi quadre [[ ]],
+# che hanno un comportamento leggermente diverso rispetto alle singole [ ].
+# Se vuoi approfondire, visita questo link (in inglese):
+# http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs
+
+# Usando `alias`, puoi definire nuovi comandi o modificare quelli già esistenti.
+# Ad esempio, così puoi ridefinire il comando ping per inviare solo 5 pacchetti
+alias ping='ping -c 5'
+# "Scavalca" l'alias e usa il comando vero, utilizzando il backslash
+\ping 192.168.1.1
+# Stampa la lista di tutti gli alias
+alias -p
+
# Le espressioni sono nel seguente formato:
echo $(( 10 + 5 ))
diff --git a/it-it/elixir-it.html.markdown b/it-it/elixir-it.html.markdown
index 60301b1a..48afe0c8 100644
--- a/it-it/elixir-it.html.markdown
+++ b/it-it/elixir-it.html.markdown
@@ -24,7 +24,7 @@ e molte altre funzionalità.
# Per usare la shell di elixir usa il comando `iex`.
# Compila i tuoi moduli con il comando `elixirc`.
-# Entrambi i comandi dovrebbero già essere nel tuo PATH se hai installato
+# Entrambi i comandi dovrebbero già essere nel tuo PATH se hai installato
# elixir correttamente.
## ---------------------------
@@ -65,7 +65,7 @@ coda #=> [2,3]
# le tuple hanno dimensione differente.
# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
-# Ci sono anche i binari
+# Ci sono anche i binari
<<1,2,3>> # binari (Binary)
# Stringhe e liste di caratteri
@@ -80,7 +80,7 @@ multi-linea.
#=> "Sono una stringa\nmulti-linea.\n"
# Le stringhe sono tutte codificate in UTF-8:
-"cìaò"
+"cìaò"
#=> "cìaò"
# le stringhe in realtà sono dei binari, e le liste di caratteri sono liste.
@@ -124,10 +124,11 @@ rem(10, 3) #=> 1
# Questi operatori si aspettano un booleano come primo argomento.
true and true #=> true
false or true #=> true
-# 1 and true #=> ** (ArgumentError) argument error
+# 1 and true
+#=> ** (BadBooleanError) expected a boolean on left-side of "and", got: 1
# Elixir fornisce anche `||`, `&&` e `!` che accettano argomenti
-# di qualsiasi tipo.
+# di qualsiasi tipo.
# Tutti i valori tranne `false` e `nil` saranno valutati come true.
1 || true #=> 1
false && 1 #=> false
@@ -147,7 +148,7 @@ nil && 20 #=> nil
1 < :ciao #=> true
# L'ordine generale è definito sotto:
-# numeri < atomi < riferimenti < funzioni < porte < pid < tuple < liste
+# numeri < atomi < riferimenti < funzioni < porte < pid < tuple < liste
# < stringhe di bit
# Per citare Joe Armstrong su questo: "L'ordine non è importante,
@@ -171,7 +172,7 @@ else
"Questo sì"
end
-# Ti ricordi il pattern matching?
+# Ti ricordi il pattern matching?
# Moltre strutture di controllo di flusso in elixir si basano su di esso.
# `case` ci permette di confrontare un valore a diversi pattern:
@@ -214,7 +215,7 @@ cond do
"Questa sì! (essenzialmente funziona come un else)"
end
-# `try/catch` si usa per gestire i valori lanciati (throw),
+# `try/catch` si usa per gestire i valori lanciati (throw),
# Supporta anche una clausola `after` che è invocata in ogni caso.
try do
throw(:ciao)
@@ -235,7 +236,7 @@ quadrato = fn(x) -> x * x end
quadrato.(5) #=> 25
# Accettano anche guardie e condizioni multiple.
-# le guardie ti permettono di perfezionare il tuo pattern matching,
+# le guardie ti permettono di perfezionare il tuo pattern matching,
# sono indicate dalla parola chiave `when`:
f = fn
x, y when x > 0 -> x + y
@@ -265,13 +266,13 @@ end
Matematica.somma(1, 2) #=> 3
Matematica.quadrato(3) #=> 9
-# Per compilare il modulo 'Matematica' salvalo come `matematica.ex` e usa
+# Per compilare il modulo 'Matematica' salvalo come `matematica.ex` e usa
# `elixirc`.
# nel tuo terminale: elixirc matematica.ex
# All'interno di un modulo possiamo definire le funzioni con `def` e funzioni
# private con `defp`.
-# Una funzione definita con `def` è disponibile per essere invocata anche da
+# Una funzione definita con `def` è disponibile per essere invocata anche da
# altri moduli, una funziona privata può essere invocata solo localmente.
defmodule MatematicaPrivata do
def somma(a, b) do
@@ -286,7 +287,11 @@ end
MatematicaPrivata.somma(1, 2) #=> 3
# MatematicaPrivata.esegui_somma(1, 2) #=> ** (UndefinedFunctionError)
-# Anche le dichiarazioni di funzione supportano guardie e condizioni multiple:
+# Anche le dichiarazioni di funzione supportano guardie e condizioni multiple.
+# Quando viene chiamata una funzione dichiarata con più match, solo la prima
+# che matcha viene effettivamente invocata.
+# Ad esempio: chiamando area({:cerchio, 3}) vedrà invocata la seconda definizione
+# di area mostrata sotto, non la prima:
defmodule Geometria do
def area({:rettangolo, w, h}) do
w * h
@@ -322,16 +327,25 @@ defmodule Modulo do
Questo è un attributo incorporato in un modulo di esempio.
"""
- @miei_dati 100 # Questo è un attributo personalizzato .
+ @miei_dati 100 # Questo è un attributo personalizzato.
IO.inspect(@miei_dati) #=> 100
end
+# L'operatore pipe |> permette di passare l'output di una espressione
+# come primo parametro di una funzione.
+# Questo facilita operazioni quali pipeline di operazioni, composizione di
+# funzioni, ecc.
+Range.new(1,10)
+|> Enum.map(fn x -> x * x end)
+|> Enum.filter(fn x -> rem(x, 2) == 0 end)
+#=> [4, 16, 36, 64, 100]
+
## ---------------------------
## -- Strutture ed Eccezioni
## ---------------------------
-# Le Strutture (Structs) sono estensioni alle mappe che portano
+# Le Strutture (Structs) sono estensioni alle mappe che portano
# valori di default, garanzia alla compilazione e polimorfismo in Elixir.
defmodule Persona do
defstruct nome: nil, eta: 0, altezza: 0
@@ -367,7 +381,7 @@ end
## -- Concorrenza
## ---------------------------
-# Elixir si basa sul modello degli attori per la concorrenza.
+# Elixir si basa sul modello degli attori per la concorrenza.
# Tutto ciò di cui abbiamo bisogno per scrivere programmi concorrenti in elixir
# sono tre primitive: creare processi, inviare messaggi e ricevere messaggi.
@@ -379,12 +393,12 @@ spawn(f) #=> #PID<0.40.0>
# `spawn` restituisce un pid (identificatore di processo). Puoi usare questo
# pid per inviare messaggi al processo.
# Per passare messaggi si usa l'operatore `send`.
-# Perché tutto questo sia utile dobbiamo essere capaci di ricevere messaggi,
+# Perché tutto questo sia utile dobbiamo essere capaci di ricevere messaggi,
# oltre ad inviarli. Questo è realizzabile con `receive`:
# Il blocco `receive do` viene usato per mettersi in ascolto di messaggi
# ed elaborarli quando vengono ricevuti. Un blocco `receive do` elabora
-# un solo messaggio ricevuto: per fare elaborazione multipla di messaggi,
+# un solo messaggio ricevuto: per fare elaborazione multipla di messaggi,
# una funzione con un blocco `receive do` al suo intero dovrà chiamare
# ricorsivamente sé stessa per entrare di nuovo nel blocco `receive do`.
defmodule Geometria do
@@ -405,7 +419,7 @@ pid = spawn(fn -> Geometria.calcolo_area() end) #=> #PID<0.40.0>
# Alternativamente
pid = spawn(Geometria, :calcolo_area, [])
-# Invia un messaggio a `pid` che farà match su un pattern nel blocco in receive
+# Invia un messaggio a `pid` che farà match su un pattern nel blocco in receive
send pid, {:rettangolo, 2, 3}
#=> Area = 6
# {:rettangolo,2,3}
@@ -421,7 +435,7 @@ self() #=> #PID<0.27.0>
## Referenze
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) dalla [pagina web ufficiale di elixir](http://elixir-lang.org)
-* [Documentazione Elixir](http://elixir-lang.org/docs/master/)
+* [Documentazione Elixir](https://elixir-lang.org/docs.html)
* ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) di Dave Thomas
* [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf)
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) di Fred Hebert
diff --git a/it-it/javascript-it.html.markdown b/it-it/javascript-it.html.markdown
new file mode 100644
index 00000000..68bf6287
--- /dev/null
+++ b/it-it/javascript-it.html.markdown
@@ -0,0 +1,617 @@
+---
+language: javascript
+contributors:
+ - ["Adam Brenecki", "http://adam.brenecki.id.au"]
+ - ["Ariel Krakowski", "http://www.learneroo.com"]
+translators:
+ - ["vinniec", "https://github.com/vinniec"]
+filename: javascript-it.js
+lang: it-it
+---
+
+JavaScript è stato creato da Netscape di Brendan Eich nel 1995. È stato originariamente pensato come un semplice linguaggio di scripting per i siti web, complementare all'uso di java per applicazioni più complesse ma la sua stretta integrazione con le pagine Web e il supporto integrato con esse ha causato il suo divenire più comune di Java per i frontend web.
+
+Tuttavia JavaScript non è semplicemente limitato ai web browser: Node.js è un progetto che fornisce una runtime standalone dell'engine JavaScript V8 per Google Chrome, sta diventando sempre più popolare.
+
+JavaScript ha una sintassi C-like, quindi se usate linguaggi come C o Java, molta della sintassi di base sarà già familiare. A dispetto di questo, e a dispetto del nome similare, il modello a oggetti di JavaScript è significativamente diverso da quello di Java.
+
+```js
+// I commenti a singola linea iniziano con due slash.
+/* I commenti multilinea cominciano con uno slash e un asterisco,
+ e terminano con un asterisco e uno slash */
+
+// Le istruzioni possono essere terminate con ;
+doStuff();
+
+// ... ma non devono esserci per forza, i punti e virgola vengono automaticamente inseriti
+// dove c'è un newline, ad eccezione di alcuni casi.
+doStuff()
+
+// Poiché questi casi possono causare risultati inaspettati, noi continueremo ad usare
+// i punti e virgola in questa guida.
+
+///////////////////////////////////
+// 1. Numeri, Stringe e Operatori
+
+// JavaScript ha un tipo numero (che è a 64-bit IEEE 754 double).
+// Double ha una mantissa di 52-bit che è abbastanza per memorizzare interi
+// fino a 9x10¹⁵ per essere precisi.
+3; // = 3
+1.5; // = 1.5
+
+// Alcuni lavori aritmetici di base come ci si può aspettare.
+1 + 1; // = 2
+0.1 + 0.2; // = 0.30000000000000004
+8 - 1; // = 7
+10 * 2; // = 20
+35 / 5; // = 7
+
+// inclusa la divisione con la virgola.
+5 / 2; // = 2.5
+
+// E il modulo.
+10 % 2; // = 0
+30 % 4; // = 2
+18.5 % 7; // = 4.5
+
+// Anche le operazioni binarie funzionano; quando effettuate una operazione binaria il vostro numero decimale
+// è convertito in un intero con segno *fino a* 32 bit..
+1 << 2; // = 4
+
+// Le precedenza è subordinata dalle parentesi.
+(1 + 3) * 2; // = 8
+
+// Ci sono tre valori speciali che non sono numeri reali:
+Infinity; // ad esempio il risultato di 1/0
+-Infinity; // ad esempio il risultato di -1/0
+NaN; // ad esempio il risultato di 0/0, sta per 'Not a Number'
+
+// Ci sono anche i tipi booleani.
+true;
+false;
+
+// Le stringe sono create con ' oppure ".
+'abc';
+"Hello, world";
+
+// La negazione usa il ! simbolo
+!true; // = false
+!false; // = true
+
+// L'uguaglianza è ===
+1 === 1; // = true
+2 === 1; // = false
+
+// L'inuguaglianza è !==
+1 !== 1; // = false
+2 !== 1; // = true
+
+// Altre comparazioni
+1 < 10; // = true
+1 > 10; // = false
+2 <= 2; // = true
+2 >= 2; // = true
+
+// Le stringhe si concatenano con il +
+"Hello " + "world!"; // = "Hello world!"
+
+// ... che funziona con qualcosa in più delle semplici stringhe
+"1, 2, " + 3; // = "1, 2, 3"
+"Hello " + ["world", "!"]; // = "Hello world,!"
+
+// e sono comparate con < e >
+"a" < "b"; // = true
+
+// La comparazione con conversione implicita si fa con il doppio uguale...
+"5" == 5; // = true
+null == undefined; // = true
+
+// ...ammenoché non si usi ===
+"5" === 5; // = false
+null === undefined; // = false
+
+// ...che può provocare strani comportamenti...
+13 + !0; // 14
+"13" + !0; // '13true'
+
+// Si può accedere ai caratteri di una stringa con `charAt`
+"This is a string".charAt(0); // = 'T'
+
+// ...o usando le `substring` per ottenere una parte.
+"Hello world".substring(0, 5); // = "Hello"
+
+// `length` è una proprietà, quindi non usate le ().
+"Hello".length; // = 5
+
+// Ci sono anche `null` e `undefined`.
+null; // usato per indicato deliberatamente un non-valore
+undefined; // usato per indicare un valore che attualmente non è presente (sebbene
+ // `undefined` sia un valore a sua stessa volta)
+
+// false, null, undefined, NaN, 0 e "" sono falsi; tutto il resto è vero.
+// Notare che 0 è falso e "0" è vero, nonostante 0 == "0".
+
+///////////////////////////////////
+// 2. Variabili, Array e Oggetti
+
+// Le variabili sono dichiarate con la parola chiave `var`. JavaScript è tipato
+// dinamicamente, quindi non serve specificare il tipo. L'assegnamento usa un carattere `=`
+// singolo.
+var someVar = 5;
+
+// Se si toglie la parola chiave var non si otterrà un errore...
+someOtherVar = 10;
+
+// ...ma la tua variabile sarà creata con visibilità globale e non
+// nel blocco dove la si è definita.
+
+// Le variabili dichiarate senza essere definite vengono impostate come undefined.
+var someThirdVar; // = undefined
+
+// Se si vuole dichiarare una coppia di variabili, lo si può fare usando una virgola
+// come separatore
+var someFourthVar = 2, someFifthVar = 4;
+
+// C'è una scorciatoia per effettuare operazioni matematiche sulle variabili:
+someVar += 5; // equivalente di someVar = someVar + 5; someVar vale 10 ora
+someVar *= 10; // ora someVar è 100
+
+// e un ulteriore scorciatoia per aggiungere o sottrarre 1
+someVar++; // ora someVar è 101
+someVar--; // di nuovo 100
+
+// Gli array sono liste ordinati di valori, di qualsiasi tipo.
+var myArray = ["Hello", 45, true];
+
+// Si può accedere ai loro membri usando la sintassi sottoscritta con le parentesi quadra.
+// Gli indici degli array iniziano a zero.
+myArray[1]; // = 45
+
+// Gli Array sono mutabili e di dimensione variabile.
+myArray.push("World");
+myArray.length; // = 4
+
+// Aggiungere/Modificare in un indice preciso
+myArray[3] = "Hello";
+
+// Aggiungere e rimovere un elemento dall'inizio o dalla fine di un array
+myArray.unshift(3); // Aggiungere come primo elemento
+someVar = myArray.shift(); // Rimuovere il primo elemento e restituirlo
+myArray.push(3); // Aggiungere come ultimo elemento
+someVar = myArray.pop(); // Rimuovere l'ultimo elemento e restituirlo
+
+// Unire tutti gli elementi di un array con un punto e virgola
+var myArray0 = [32,false,"js",12,56,90];
+myArray0.join(";") // = "32;false;js;12;56;90"
+
+// Ottenere un subarray di elementi dall'indice 1 (incluso) al 4 (escluso)
+myArray0.slice(1,4); // = [false,"js",12]
+
+// Rimuovere 4 elementi partendo dall'indice 2 e inserirci delle stringhe
+// "hi","wr" e "ld"; restituiscono i subarray rimossi
+myArray0.splice(2,4,"hi","wr","ld"); // = ["js",12,56,90]
+// myArray0 === [32,false,"hi","wr","ld"]
+
+// Gli oggetti di JavaScript sono equivalenti ai "dizionari" o "mappe" in altri
+// linguaggi: una collezione non ordinata di coppie di chiave-valore.
+var myObj = {key1: "Hello", key2: "World"};
+
+// Le chiavi sono stringhe, ma non è necessario quotarle se sono identificatori
+// JavaScript validi. I valori possono essere di ogni tipo.
+var myObj = {myKey: "myValue", "my other key": 4};
+
+// Gli attributi degli oggetti possono essere acceduti usando la sintassi "subscript",
+myObj["my other key"]; // = 4
+
+// ... o usando la notazione puntata fornendo una chiave che sia un identificatore valido.
+myObj.myKey; // = "myValue"
+
+// Gli oggetti sono mutabilil; i valori possono essere cambiati e nuove chiavi possono essere aggiunte.
+myObj.myThirdKey = true;
+
+// se si prova ad accedere ad un valore che non è stato ancora impostato, si otterrà undefined.
+myObj.myFourthKey; // = undefined
+
+///////////////////////////////////
+// 3. Strutture logiche e di controllo.
+
+// La struttura `if` funziona come ci si aspetta.
+var count = 1;
+if (count == 3){
+ // eseguito se count vale 3
+} else if (count == 4){
+ // eseguito se count vale 4
+} else {
+ // eseguito se count non è né 3 e né 4
+}
+
+// Così come il `while`.
+while (true){
+ // Un ciclo infinito!
+}
+
+// I cicli do-while sono come i cicli while ad eccezione che loro iterano almeno una volta.
+var input;
+do {
+ input = getInput();
+} while (!isValid(input));
+
+// Il ciclo `for` è lo stesso di C e di Java:
+// inizializzazione, condizione di proseguimento; iterazione.
+for (var i = 0; i < 5; i++){
+ // verrà eseguito 5 volte
+}
+
+// Uscire forzatamente da un un ciclo etichettato è simile a java:
+outer:
+for (var i = 0; i < 10; i++) {
+ for (var j = 0; j < 10; j++) {
+ if (i == 5 && j ==5) {
+ break outer;
+ // esce fuori dal ciclo outer invece che solo da quello più interno
+ }
+ }
+}
+
+// L'istruzione for/in permette l'iterazione sulle proprietà di un oggetto.
+var description = "";
+var person = {fname:"Paul", lname:"Ken", age:18};
+for (var x in person){
+ description += person[x] + " ";
+} // description = 'Paul Ken 18 '
+
+// L'istruzione for/of permette l'iterazione su oggetti iterabili (inclusi i built-in String,
+// Array, es. gli argomenti Array-like o gli oggetti NodeList, TypedArray, Map e Set,
+// e gli iterabili decisi dall'utente).
+var myPets = "";
+var pets = ["cat", "dog", "hamster", "hedgehog"];
+for (var pet of pets){
+ myPets += pet + " ";
+} // myPets = 'cat dog hamster hedgehog '
+
+// && è la congiunzione logica, || è la disgiunione logica
+if (house.size == "big" && house.colour == "blue"){
+ house.contains = "bear";
+}
+if (colour == "red" || colour == "blue"){
+ // i colori sono sia rossi che blu
+}
+
+// && e || "short circuit", utili per impostare i valori di default.
+var name = otherName || "default";
+
+// L'istruzione `switch` controlla l'uguaglianza con `===`.
+// Usare 'break' dopo ogni caso
+// oppure i casi dopo quello corretto verranno eseguiti comunque.
+grade = 'B';
+switch (grade) {
+ case 'A':
+ console.log("Great job");
+ break;
+ case 'B':
+ console.log("OK job");
+ break;
+ case 'C':
+ console.log("You can do better");
+ break;
+ default:
+ console.log("Oy vey");
+ break;
+}
+
+
+///////////////////////////////////
+// 4. Funzioni, Visibilità e Closure
+
+// Le funzioni di JavaScript sono dichiarate con la parolachiave `function`.
+function myFunction(thing){
+ return thing.toUpperCase();
+}
+myFunction("foo"); // = "FOO"
+
+// Nota che il valore da restituire deve iniziare nella stessa riga della
+// keyword `return`, altrimenti verrà sempre restituito `undefined` per via due to
+// dell'inserimento automatico dei punti e virgola. Fare attenzione a questo quando si usa lo stile Allman.
+function myFunction(){
+ return // <- punto e virgola automaticamente inserito qui
+ {thisIsAn: 'object literal'};
+}
+myFunction(); // = undefined
+
+// Le funzioni di JavaScript sono oggetti di prima classe, quindi possono essere riassegnate
+// a diversi nomi di variabili e passate ad altre funzioni come argomenti - per esempio,
+// mentre si fornisce un gestore di eventi:
+function myFunction(){
+ // questo codice sarà chiamato in 5 secondi
+}
+setTimeout(myFunction, 5000);
+// Nota: setTimeout non è parte del linguaggio JS, ma è fornito dai browser
+// e da Node.js.
+
+// Un altra funzione fornita dai browser è setInterval
+function myFunction(){
+ // questo codice verrà chiamato ogni 5 secondi
+}
+setInterval(myFunction, 5000);
+
+// Gli oggetti funzione non devono essere dichiarati con un nome - potete scrivere
+// la definizione di una funzione anonima direttamente come argomento di un'altra.
+setTimeout(function(){
+ // questo codice sarà chiamato in 5 secondi
+}, 5000);
+
+// In JavaScript le funzioni hanno una propria visibilità; le funzioni hanno
+// il loro scope ma gli altri blocchi no.
+if (true){
+ var i = 5;
+}
+i; // = 5 - non è undefined come ci si potrebbe aspettare in un linguaggio con una propria visibilità per blocco
+
+// Questo ha portato ad un pattern comune di "esecuzione immediata di funzioni
+// anonime", che previene alle variabili temporanee di finire nella
+// visibilità globale.
+(function(){
+ var temporary = 5;
+ // Noi possiamo accedere alla visibilità globale assegnando all' "oggetto globale", che
+ // in un browser web è sempre `windows`. L'oggetto globale potrebbe avere
+ // nomi differenti in ambienti diverso dal browser come Node.js.
+ window.permanent = 10;
+})();
+temporary; // solleva ReferenceError
+permanent; // = 10
+
+// Una delle più potenti caratteristiche di javascript sono le closure. Se una funzione è
+// definita dentro un'altra funzione, la funzione interna ha accesso a le variabili
+// della funzione esterna, anche dopo essere uscita dalla funzione esterna.
+function sayHelloInFiveSeconds(name){
+ var prompt = "Hello, " + name + "!";
+ // Le funzioni interne sono messe nella visibilità locale in modo predefinito, anche se vengono
+ // dichiarate con `var`.
+ function inner(){
+ alert(prompt);
+ }
+ setTimeout(inner, 5000);
+ // setTimeout è asincrono, quindi la funzione sayHelloInFiveSeconds
+ // esce immediatamente e setTimeout chiamera inner successivamente. Tuttavia,
+ // poiché inner è "chiuso prima" di sayHelloInFiveSeconds, inner ha ancora
+ // accesso alla variabile `prompt` quando viene finalmente richiamato.
+}
+sayHelloInFiveSeconds("Adam"); // aprirà un popup con "Hello, Adam!" in 5s
+
+///////////////////////////////////
+// 5. Di più sugli oggetti, costruttori e prototipi.
+
+// Gli oggetti possono contenere funzioni.
+var myObj = {
+ myFunc: function(){
+ return "Hello world!";
+ }
+};
+myObj.myFunc(); // = "Hello world!"
+
+// Quando una funzione contenuta in un oggetto viene chiamata, essa può accedere a questo oggetto
+// possono farlo usando la parola chiave `this`.
+myObj = {
+ myString: "Hello world!",
+ myFunc: function(){
+ return this.myString;
+ }
+};
+myObj.myFunc(); // = "Hello world!"
+
+// Questo ha a che fare con come la funzione è chiamata, non con dove
+// è definita. Quindi, la nostra funzione non funziona se non è chiamata
+// nel contesto dell'oggetto.
+var myFunc = myObj.myFunc;
+myFunc(); // = undefined
+
+// Al contrario, una funzione può essere assegnata ad un oggetto e poi accedere ad esso
+// attraverso `this`, anche se non è stata inserita durante la definizione.
+var myOtherFunc = function(){
+ return this.myString.toUpperCase();
+};
+myObj.myOtherFunc = myOtherFunc;
+myObj.myOtherFunc(); // = "HELLO WORLD!"
+
+// Possiamo anche specificare un contesto per una funzione da eseguire quando la invochiamo
+// usando `call` o `apply`.
+
+
+var anotherFunc = function(s){
+ return this.myString + s;
+};
+anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!"
+
+// La funzione `apply` è quasi identica, ma prende un array come lista
+// di argomenti.
+
+anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!"
+
+// Questo è utile quanso si lavora con una funzione che accetta una sequenza di
+// argomenti e si vuole passare un array.
+
+Math.min(42, 6, 27); // = 6
+Math.min([42, 6, 27]); // = NaN (uh-oh!)
+Math.min.apply(Math, [42, 6, 27]); // = 6
+
+// Ma, `call` e `apply` sono solo temporanei. Quando vogliamo incollarli, possiamo
+// usare `bind`
+
+var boundFunc = anotherFunc.bind(myObj);
+boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!"
+
+// `bind` può essere anche usato per applicare parzialmente (curry) una funzione.
+
+var product = function(a, b){ return a * b; };
+var doubler = product.bind(this, 2);
+doubler(8); // = 16
+
+// Quando si chiama una funzione con la parola chiave `new`, un nuovo oggetto viene creato
+// e reso disponibile alla funzione attraverso la parola chiave `this`. Le funzioni progettate per essere
+// invocate in questo modo sono chiamate costruttrici.
+
+var MyConstructor = function(){
+ this.myNumber = 5;
+};
+myNewObj = new MyConstructor(); // = {myNumber: 5}
+myNewObj.myNumber; // = 5
+
+// Diversamente dalla molti degli altri linguaggi orientati agli oggetti, Javascript non ha
+// il concetto di 'istanze' create sull'impronta di una 'classe'; invece Javascript
+// combina l'instanziamento e l'ereditarietà in un singolo concetto: il 'prototipo'.
+
+// Ogni oggetto Javascript ha un 'prototipo'. Quando si cerca di accedere a una proprietà
+// su un oggetto che non la contiene, l'interprete
+// guarderà i suoi prototipi.
+
+// Alcune implementazioni di JS faranno accedere al propotipo di un oggetto con la proprietà
+// magica `__proto__`: Anche se questo è utile per spiegare i prototipi, non è
+// parte dello standard; capiremo più avanti come usare i prototipi in modo standard.
+var myObj = {
+ myString: "Hello world!"
+};
+var myPrototype = {
+ meaningOfLife: 42,
+ myFunc: function(){
+ return this.myString.toLowerCase();
+ }
+};
+
+myObj.__proto__ = myPrototype;
+myObj.meaningOfLife; // = 42
+
+// Questo funziona anche per le funzioni.
+myObj.myFunc(); // = "hello world!"
+
+// Ovviamente, se la proprietà non è nel prototipo, il prototipo
+// del prototipo viene ricercato, e così via.
+myPrototype.__proto__ = {
+ myBoolean: true
+};
+myObj.myBoolean; // = true
+
+// Non c'è nessuna copia coinvolta qui; ogni oggetto mantiene una referenza al suo
+// prototipo. Questo significa che possiamo modificare il prototipo e i nostri cambiamenti
+// si rifletteranno da ogni parte.
+myPrototype.meaningOfLife = 43;
+myObj.meaningOfLife; // = 43
+
+// L'istruzione for/in permette di iterare sulle proprietà di un oggetto,
+// risalendo la catena dei prototipi finché non trova un prototipo null.
+for (var x in myObj){
+ console.log(myObj[x]);
+}
+///stampa:
+// Hello world!
+// 43
+// [Function: myFunc]
+// true
+
+// Per considerare solamente le proprietà inserite nell'oggetto stesso
+// e non i loro prototipi, usare il check `hasOwnProperty()`.
+for (var x in myObj){
+ if (myObj.hasOwnProperty(x)){
+ console.log(myObj[x]);
+ }
+}
+///stampa:
+// Hello world!
+
+// Abbiamo menzionato che `__proto__` non è standard, e non c'è nessun modo standard per
+// cambiare il prototipo di un oggetto esistente. Tuttavia, ci sono due strade per
+// creare un nuovo oggetto con un dato prototipo.
+
+// La prima è Object.create, che è una recente aggiunta a JS, e che quindi
+// non è disponibile ancora in tutte le implementazioni.
+var myObj = Object.create(myPrototype);
+myObj.meaningOfLife; // = 43
+
+// La seconda strada, che funziona ovunque, ha a che fare con i costruttori.
+// I costruttori hanno una proprietà chiamata prototype. Questo *non* è il prototipo del
+// costruttore della stessa funzione; invece è il prototipo del nuovo oggetto
+// che gli viene conferito alla creazione con quel costruttore e la parola chiave new.
+MyConstructor.prototype = {
+ myNumber: 5,
+ getMyNumber: function(){
+ return this.myNumber;
+ }
+};
+var myNewObj2 = new MyConstructor();
+myNewObj2.getMyNumber(); // = 5
+myNewObj2.myNumber = 6;
+myNewObj2.getMyNumber(); // = 6
+
+// I tipi built-in come stringhe e numeri hanno anche costruttori che creano
+// oggetti wrapper equivalenti.
+var myNumber = 12;
+var myNumberObj = new Number(12);
+myNumber == myNumberObj; // = true
+
+// Eccezione, loro non sono esattamente equivalenti.
+typeof myNumber; // = 'number'
+typeof myNumberObj; // = 'object'
+myNumber === myNumberObj; // = false
+if (0){
+ // Questo codice non verrà eseguito perchè 0 è falso.
+}
+if (new Number(0)){
+ // Questo codice verrà eseguito poiché i numeri wrappati sono oggetti e gli oggetti
+ // sono sempre veri.
+}
+
+// Tuttavia, gli oggetti wrapper e i regolari built-in condividono un prototipo, quindi
+// si possono aggiungere funzionalità ad una stringa, per esempio.
+String.prototype.firstCharacter = function(){
+ return this.charAt(0);
+};
+"abc".firstCharacter(); // = "a"
+
+// Questa caratteristica viene spesso usata nel "polyfilling", che implementa nuovi
+// aspetti in un vecchio sottoinsieme di JavaScript, in modo che si possano
+// usare in vecchi ambienti come browser non aggiornati.
+
+// Per esempio, abbiamo menzionato che Object.create non è disponibile in tutte le
+// implementazioni, ma possiamo ancora usarlo con questo polyfill:
+if (Object.create === undefined){ // non lo sovrascrive se esiste già
+ Object.create = function(proto){
+ // crea un costruttore temporaneo con il giusto prototipo
+ var Constructor = function(){};
+ Constructor.prototype = proto;
+ // quindi lo usa per creare un nuovo, propriamente-prototipato oggetto
+ return new Constructor();
+ };
+}
+```
+
+## Approfondimenti
+
+Il [Mozilla Developer Networ][1] fornisce una documentazione eccellente su come Javascript è utilizzato nei browsers. In più è un wiki, quindi si può imparare di più aiutando gli altri condividendo la propria conoscenza.
+
+MDN's [A re-introduction to JavaScript][2] copre molti dei concetti qui trattati in maggiore dettaglio. Questa guida ha deliberatamente coperto solamente il linguaggio JavaScript; se volete sapere di più su come usare JavaScript in una pagina web, iniziate leggendo il [Document Object Model][3].
+
+[Learn Javascript by Example and with Challenges][4] è una variante di questo referenziario con integrate delle sfide.
+
+[Javascript Garden][5] è una guida approfondita di tutte le parti controintuitive del linguaggio.
+
+[JavaScript: The Definitive Guide][6] è una guida classica e referenziario.
+
+[Eloqunt Javascript][8] di Marijn Haverbeke è un ottimo libro/ebook JS con terminale annesso
+
+[Javascript: The Right Way][10] è una guida dedicata all'introduzione dei nuovi sviluppatori a JavaScript e come aiuto agli sviluppatori esperti per imparare di più sulle best practice.
+
+[Javascript:info][11] è un moderno tutorial su javascript che copre le basi (linguaggio principale e lavorazione con un browser) come anche argomenti avanzati con spiegazioni concise.
+
+
+In aggiunta ai contributori di questo articolo, alcuni contenuti sono adattati dal Louie Dinh's Python tutorial su questo sito, e da [JS Tutorial][7] sul Mozilla Developer Network.
+
+
+[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
+[2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
+[3]: https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core
+[4]: http://www.learneroo.com/modules/64/nodes/350
+[5]: http://bonsaiden.github.io/JavaScript-Garden/
+[6]: http://www.amazon.com/gp/product/0596805527/
+[7]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
+[8]: http://eloquentjavascript.net/
+[10]: http://jstherightway.org/
+[11]: https://javascript.info/
diff --git a/it-it/pcre-it.html.markdown b/it-it/pcre-it.html.markdown
index 68233858..704392ef 100644
--- a/it-it/pcre-it.html.markdown
+++ b/it-it/pcre-it.html.markdown
@@ -11,7 +11,7 @@ lang: it-it
Un'espressione regolare (regex o regexp in breve) è una speciale stringa
utilizzata per definire un pattern, ad esempio per cercare una sequenza di
caratteri; ad esempio, `/^[a-z]+:/` può essere usato per estrarre `http:`
-dall'URL `http://github.com/`.
+dall'URL `http://github.com/`.
PCRE (Perl Compatible Regular Expressions) è una libreria per i regex in C.
La sintassi utilizzata per le espressioni è molto simile a quella di Perl, da
@@ -19,7 +19,9 @@ cui il nome. Si tratta di una delle sintassi più diffuse per la scrittura di
regex.
Esistono due tipi di metacaratteri (caratteri con una funzione speciale):
+
* Caratteri riconosciuti ovunque tranne che nelle parentesi quadre
+
```
\ carattere di escape
^ cerca all'inizio della stringa (o della riga, in modalità multiline)
@@ -36,16 +38,17 @@ Esistono due tipi di metacaratteri (caratteri con una funzione speciale):
```
* Caratteri riconosciuti nelle parentesi quadre
+
```
\ carattere di escape
^ nega la classe se è il primo carattere
- indica una serie di caratteri
[ classe caratteri POSIX (se seguita dalla sintassi POSIX)
] termina la classe caratteri
-
-```
+```
+
+PCRE fornisce inoltre delle classi di caratteri predefinite:
-PCRE fornisce inoltre delle classi di caratteri predefinite:
```
\d cifra decimale
\D NON cifra decimale
@@ -62,9 +65,11 @@ PCRE fornisce inoltre delle classi di caratteri predefinite:
## Esempi
Utilizzeremo la seguente stringa per i nostri test:
+
```
66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
```
+
Si tratta di una riga di log del web server Apache.
| Regex | Risultato | Commento |
diff --git a/it-it/rust-it.html.markdown b/it-it/rust-it.html.markdown
index 6b379f93..e4b7c33f 100644
--- a/it-it/rust-it.html.markdown
+++ b/it-it/rust-it.html.markdown
@@ -130,14 +130,14 @@ fn main() {
/////////////
// Strutture
- struct Point {
+ struct Punto {
x: i32,
y: i32,
}
let origine: Punto = Punto { x: 0, y: 0 };
- // Ana struct con campi senza nome, chiamata ‘tuple struct’
+ // Una struct con campi senza nome, chiamata ‘tuple struct’
struct Punto2(i32, i32);
let origine2 = Punto2(0, 0);
diff --git a/ja-jp/asciidoc.html.markdown b/ja-jp/asciidoc.html.markdown
new file mode 100644
index 00000000..7347589a
--- /dev/null
+++ b/ja-jp/asciidoc.html.markdown
@@ -0,0 +1,135 @@
+---
+language: asciidoc
+contributors:
+ - ["Ryan Mavilia", "http://unoriginality.rocks/"]
+ - ["Abel Salgado Romero", "https://twitter.com/abelsromero"]
+translators:
+ - ["Ryota Kayanuma", "https://github.com/PicoSushi"]
+filename: asciidoc-ja.md
+lang: ja-jp
+---
+
+AsciiDocはMarkdownに似たマークアップ言語で、書籍の執筆からブログを書くことまでなんでも使うことができます。2002年、Stuart RackhamによりAsciiDocは作成され、シンプルでありつつも沢山のカスタマイズを可能にしています。
+
+文書のヘッダー
+
+ヘッダーはオプションで、空行を含むことはできません。本文から1行以上の改行を開ける必要があります。
+
+タイトルのみの例
+
+```
+= 文章タイトル
+
+文書の最初の行
+```
+
+タイトルと著者
+
+```
+= 文書タイトル
+文書 太郎 <first.last@learnxinyminutes.com>
+
+文書の開始
+```
+
+複数の著者
+
+```
+= 文書タイトル
+John Doe <john@go.com>; Jane Doe<jane@yo.com>; Black Beard <beardy@pirate.com>
+
+複数の著者による文書の始まり。
+```
+
+版(著者の行を必要とします)
+
+```
+= 第一版のタイトル
+芋男 <chip@crunchy.com>
+v1.0, 2016-01-13
+
+このポテトについての文書は面白いです。
+```
+
+段落
+
+```
+段落は特別なことは不要です。
+
+空行を段落の間に入れることで、段落を分けることができます。
+
+折り返しをしたい場合、+
+を書くことで折り返せます!
+```
+
+文書の整形
+
+```
+_アンダースコアで斜体になります。_
+*アスタリスクで太字になります。*
+*_組み合わせると楽しい_*
+`バッククォートで固定幅になります。`
+`*太字の固定幅*`
+```
+
+節タイトル
+
+```
+= Level 0 (文書のヘッダーにのみ使用してください)
+
+== Level 1 <h2>
+
+=== Level 2 <h3>
+
+==== Level 3 <h4>
+
+===== Level 4 <h5>
+
+```
+
+リスト
+
+箇条書きリストを作るには、アスタリスクを使用してください。
+
+```
+* foo
+* bar
+* baz
+```
+
+番号付きリストを作るには、ピリオドを使用してください。
+
+```
+. item 1
+. item 2
+. item 3
+```
+
+リストはアスタリスクやピリオドを追加することで5段階まで入れ子にできます。
+
+```
+* foo 1
+** foo 2
+*** foo 3
+**** foo 4
+***** foo 5
+
+. foo 1
+.. foo 2
+... foo 3
+.... foo 4
+..... foo 5
+```
+
+## 補足資料
+
+AsciiDocの文書を処理するツールは2種類あります。
+
+1. [AsciiDoc](http://asciidoc.org/): オリジナルのPython実装で、Linuxで利用可能です。現在は開発されておらず、メンテナンスのみの状態です。
+2. [Asciidoctor](http://asciidoctor.org/): Rubyによる別実装で、JavaやJavascriptでも利用可能です。AsciiDocに新しい機能や出力形式を追加するため、現在活発に開発されています。
+
+以下のリンクは `AsciiDoctor` 実装関連のものです。
+
+* [Markdown - AsciiDoc syntax comparison](http://asciidoctor.org/docs/user-manual/#comparison-by-example): Common MarkdownとAsciidocの要素を並べて比較しています。
+* [Getting started](http://asciidoctor.org/docs/#get-started-with-asciidoctor): インストールから簡潔な文書を作るための簡単なガイドです。
+* [Asciidoctor User Manual](http://asciidoctor.org/docs/user-manual/): 文法のリファレンス、例、描画ツール、その他を含む完全なドキュメントです。
diff --git a/ja-jp/python3-jp.html.markdown b/ja-jp/python3-jp.html.markdown
index 3b1a0d73..b9731411 100644
--- a/ja-jp/python3-jp.html.markdown
+++ b/ja-jp/python3-jp.html.markdown
@@ -6,13 +6,16 @@ contributors:
- ["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"]
translators:
- ["kakakaya", "https://github.com/kakakaya"]
+ - ["Ryota Kayanuma", "https://github.com/PicoSushi"]
filename: learnpython3-jp.py
lang: ja-jp
---
-90年代の初め、Guido Van RossumによってPythonは作成されました。現在となっては、最も有名な言語の1つです。
+90年代の初め、Guido van RossumによってPythonは作成されました。現在となっては、最も有名な言語の1つです。
私は構文の明快さによって、Pythonと恋に落ちました。
以下は基本的に実行可能な疑似コードです。
@@ -21,12 +24,11 @@ lang: ja-jp
Note: この記事はPython 3に内容を絞っています。もし古いPython 2.7を学習したいなら、 [こちら](http://learnxinyminutes.com/docs/python/) をご確認下さい。
```python
-
# 1行のコメントは番号記号(#)から始まります。
""" 複数行の文字は、"を3つ繋げることで
書くことができます。
- また、これはコメントとしてもよく使われます。
+ また、これはドキュメントとしてもよく使われます。
"""
####################################################
@@ -44,8 +46,8 @@ Note: この記事はPython 3に内容を絞っています。もし古いPython
# 整数除算の結果は、正負に関わらず小数の切り捨てが行われます。
5 // 3 # => 1
-5.0 // 3.0 # => 1.0 # 浮動小数点でも同様に動作します。
-5 // 3 # => -2
+5.0 // 3.0 # => 1.0 # 浮動小数点でも同様に動作します。
-5.0 // 3.0 # => -2.0
# 除算の結果は常に浮動小数点になります。
@@ -55,7 +57,7 @@ Note: この記事はPython 3に内容を絞っています。もし古いPython
7 % 3 # => 1
# 冪乗 (x**y, x の y 乗)
-2**4 # => 16
+2**3 # => 8
# 括弧により、計算の順番を優先させられます。
(1 + 3) * 2 # => 8
@@ -69,16 +71,28 @@ not True # => False
not False # => True
# ブール演算
-# 注意: "and" と "or" は小文字です
+# 注意: "and" と "or" は小文字です。
True and False # => False
False or True # => True
-# 整数でブール演算をするときのメモ
-0 and 2 # => 0
--5 or 0 # => -5
+# TrueとFalseは実際には1と0になるキーワードです。
+True + True # => 2
+True * 8 # => 8
+False - 5 # => -5
+
+# 比較演算子はTrueとFalseを数値として扱います。
0 == False # => True
-2 == True # => False
1 == True # => True
+2 == True # => False
+-5 != True # => True
+
+# bool論理演算子を整数に対して使うことで整数を真偽値に変換して評価できますが、キャストされていない値が
+# bool(int)とビット演算子(& や |)を混同しないようにうにしましょう。
+bool(0) # => False
+bool(4) # => True
+bool(-6) # => True
+0 and 2 # => 0
+-5 or 0 # => -5
# 値が等しいか確認するには ==
1 == 1 # => True
@@ -94,7 +108,11 @@ False or True # => True
2 <= 2 # => True
2 >= 2 # => True
-# 比較は連結させられます!
+# 値がある範囲の中にあるか調べる方法
+1 < 2 and 2 < 3 # => True
+2 < 3 and 3 < 2 # => False
+
+# 連結させるともっと見やすくなります。
1 < 2 < 3 # => True
2 < 3 < 2 # => False
@@ -115,7 +133,7 @@ b == a # => True, a と b が参照するオブジェクトの値
# 文字列も加算をすることができます!でも、あまり行わないように。
"Hello " + "world!" # => "Hello world!"
-# '+' を使わなくても連結はできます。
+# '+' を使わなくても文字列リテラル(変数ではないもの)の連結ができます。
"Hello " "world!" # => "Hello world!"
# 文字列は文字のリストであるかのように扱うことができます。
@@ -138,6 +156,12 @@ len("This is a string") # => 16
# 旧式のフォーマット方法を使うこともできます。
"%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way"
+# Python3.6以上では、f-stringsやフォーマット文字列を使ってフォーマットすることもできます。
+name = "Reiko"
+f"She said her name is {name}." # => "She said her name is Reiko"
+
+# 基本的に、任意のPythonの文を中括弧に書くことができ、それは評価されて出力されます。
+f"{name} is {len(name)} characters long."
# None はオブジェクトです(大文字からです!)
None # => None
@@ -170,7 +194,7 @@ print("Hello, World", end="!") # => Hello, World!
input_string_var = input("Enter some data: ") # 入力を文字列として返します
# Note: Python の初期のバージョンでは、 input() は raw_input() という名前で存在します。
-# 変数に代入する前に宣言する必要はありません。
+# Pythonでは変数の宣言は存在せず、代入のみです。
# 慣例的に、小文字でアンダースコア区切り ( lower_case_with_underscores ) の変数が使われます。
some_var = 5
some_var # => 5
@@ -207,10 +231,11 @@ li[-1] # => 3
li[4] # IndexError が発生します
# スライス構文により範囲を参照できます。
+# 開始部分のインデックスに対応する部分は含まれますが、終了部分のインデックスに対応する部分は含まれません。
li[1:3] # => [2, 4]
-# 先端を取り除く
+# 先端を取り除いたリスト
li[2:] # => [4, 3]
-# 末尾を取り除く
+# 末尾を取り除いたリスト
li[:3] # => [1, 2, 4]
# 1つ飛ばしで選択する
li[::2] # =>[1, 4]
@@ -272,7 +297,7 @@ a, b, c = (1, 2, 3) # a, b, c にはそれぞれ 1, 2, 3 が代入
# 拡張記法もあります。
a, *b, c = (1, 2, 3, 4) # a は 1 、 b は [2, 3] 、c は4 になります。
# 括弧を作成しなくてもデフォルトでタプルが作成されます。
-d, e, f = 4, 5, 6
+d, e, f = 4, 5, 6 # 4、5、6がそれぞれd、 e、 fに代入されます。
# 2つの変数を交換するのがどれほど簡単か見てみましょう。
e, d = d, e # d は 5 、 e は e になります。
@@ -293,14 +318,17 @@ filled_dict["one"] # => 1
# "keys()"により、全てのキーを反復可能な形式で取り出せます。
# これをリストにするために、"list()"で囲んでいます。これについては後程解説します。
-# Note: 辞書のキーの順番は考慮されていません。実行した結果がこれと異なる場合があります。
-list(filled_dict.keys()) # => ["three", "two", "one"]
+# Note: Python3.7未満では、辞書のキーの順番は考慮されていません。実行した結果がこれと異なる場合があります。
+# しかし、Python3.7以降ではキーの挿入順を保つようになりました。
+list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7
+list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+
+
# "values()"により、全ての値を反復可能な形式で取り出せます。
# 前と同じように、これをリストにするために、"list()"で囲んでいます。
# Note: 辞書の値の順番は考慮されていません。実行した結果がこれと異なる場合があります。
-list(filled_dict.values()) # => [3, 2, 1]
-
+list(filled_dict.values()) # => [3, 2, 1] in Python <3.7
+list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+
# "in" により、辞書のキーが存在するか確認できます。
"one" in filled_dict # => True
@@ -322,7 +350,7 @@ filled_dict.setdefault("five", 6) # filled_dict["five"] は 5 のままです
# 辞書にマップを追加する
filled_dict.update({"four": 4}) # => {"one": 1, "two": 2, "three": 3, "four": 4}
-# filled_dict["four"] = 4 # 辞書に追加する別の方法
+filled_dict["four"] = 4 # 辞書に追加する別の方法
# del により辞書からキーを削除できます。
del filled_dict["one"] # "one" キーを辞書から削除します。
@@ -341,11 +369,11 @@ some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4}
invalid_set = {[1], 1} # => list はハッシュ化できないので、 TypeError が送出されます。
valid_set = {(1,), 1}
-# 新しい値を集合にセットできます。
-filled_set = some_set
-
# 集合に新しい要素を追加できます。
+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}
@@ -378,7 +406,8 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6}
# まずは変数を作りましょう。
some_var = 5
-# これはif文です。インデントがPythonでは特徴的ですね!
+# これはif文です。Pythonではインデントが特徴的ですね!
+# 規約ではタブではなく4つのスペースでインデントすることが推奨されています。
# 以下の例では"some_var is smaller than 10"と出力されます。
if some_var > 10:
print("some_var is totally bigger than 10.")
@@ -541,9 +570,9 @@ all_the_args(1, 2, a=3, b=4) prints:
# * を使ってタプルを展開したり、 ** を使って辞書を展開できます。
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
-all_the_args(*args) # foo(1, 2, 3, 4) に対応します。
-all_the_args(**kwargs) # foo(a=3, b=4) に対応します。
-all_the_args(*args, **kwargs) # foo(1, 2, 3, 4, a=3, b=4) に対応します。
+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) と等しいです。
# タプルで複数の値を返す
@@ -646,7 +675,7 @@ dir(math)
# 6. クラス
####################################################
-# クラスを作成するために、"class"という演算子を使います。
+# クラスを作成するために、class文を使います。
class Human:
# クラスの属性です。このクラスの全てのインスタンスで共有されます。
@@ -656,14 +685,14 @@ class Human:
# 2つのアンダースコアがオブジェクトや属性の前後についているとき、これらはPythonによって利用され、
# ユーザーの名前空間には存在しないということに注意してください。
# __init__ や __str__ 、 __repr__ のようなメソッド(やオブジェクト、属性)は、
- # magic methods (または dunder methods)と呼ばれます。
- # このような名前を自分で発明しないほうがよいでしょう。
+ # special methods (または dunder methods)と呼ばれます。
+ # 同じような名前を自分で発明しないほうがよいでしょう。
def __init__(self, name):
# 引数をインスタンスのname属性に設定します。
self.name = name
# プロパティの初期化
- self.age = 0
+ self._age = 0
# インスタンスメソッド。全てのメソッドは"self"を最初の引数に取ります。
def say(self, msg):
@@ -686,6 +715,7 @@ class Human:
# プロパティはgetterのようなものです。
# age() メソッドを同名の読取専用属性に変換します。
+ # Pythonではわざわざgetterやsetterを書く必要はありません。
@property
def age(self):
return self._age
@@ -720,24 +750,117 @@ if __name__ == '__main__':
j.say(j.get_species()) # => "Joel: H. neanderthalensis"
# スタティックメソッドを呼んでみましょう。
- print(Human.grunt()) # => "*grunt*"
- print(i.grunt()) # => "*grunt*"
+ print(Human.grunt()) # => "*grunt*"
+
+ # スタティックメソッドはインスタンスから呼ぶことはできません。
+ # なぜならば、 i.grunt() は自動的に"self" ( i オブジェクト ) を引数として渡してしまうからです。
+ print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given
# インスタンスのプロパティを更新してみましょう。
i.age = 42
# プロパティを取得してみましょう。
- i.say(i.age) # => 42
- j.say(j.age) # => 0
+ i.say(i.age) # => "Ian: 42"
+ j.say(j.age) # => "Joel: 0"
# プロパティを削除してみましょう。
del i.age
# i.age # => AttributeError が発生します。
####################################################
-# 6.1 多重継承
+# 6.1 継承
+####################################################
+# 継承を行うことで、親クラスからメソッドと変数を継承する新しい子クラスを定義できます。
+
+# 上記で定義されたHumanクラスを親クラス(基底クラス)として使い、Superheroという子クラスを定義します。
+# これは"species"、"name"や"age"といった変数や、"sing"や"grunt"のようなメソッドをHumanから継承しますが、
+# Superhero独自のプロパティを持つこともできます。
+
+# ファイルを分割してモジュール化の利点を活用するために、上記のHumanクラスを独自のファイル、ここでは human.py に記述ましょう。
+
+# 別のファイルから関数をインポートするには次の形式を利用してください:
+# from "拡張子なしのファイル名" import "関数やクラス"
+
+from human import Human
+
+
+# 親クラスを子クラスのパラメータとして指定します
+class Superhero(Human):
+
+ # もし子クラスが親クラスの全ての定義を変更なしで継承する場合、"pass"キーワードのみを書くだけで良いです。
+ # しかし、今回は親クラスとは異なる子クラスを作成するので、今回は以下の通りコメントアウトしています。
+ # pass
+
+ # 子クラスは親クラスの属性を上書きできます。
+ species = 'Superhuman'
+
+ # 子クラスは親クラスのコンストラクタを引数含めて自動的に継承しますが、
+ # 追加の引数や定義を行ってコンストラクタのようなメソッドを上書きすることもできます。
+ # このコンストラクタは"name"引数を"Human"クラスから継承し、"superpower"と"movie"という引数を追加します。
+ def __init__(self, name, movie=False,
+ superpowers=["super strength", "bulletproofing"]):
+
+ # 追加のクラス属性を作成する
+ self.fictional = True
+ self.movie = movie
+ # デフォルト値は共有されるので、可変のデフォルト値には注意してください。
+ self.superpowers = superpowers
+
+ # "super"関数を使うと子クラスに上書きされた親クラスのメソッド(今回は "__init__")にアクセスできます。
+ # これで、親クラスのコンストラクタを呼んでいます。
+ 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")
+
+ # インスタンスの型を調べる
+ if isinstance(sup, Human):
+ print('I am human')
+ if type(sup) is Superhero:
+ print('I am a superhero')
+
+ # getattr()とsuper()で使われるメソッドの解決順序を調べてみます。
+ # この属性は動的であり、変更可能です。
+ print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
+ # => <class 'human.Human'>, <class 'object'>)
+
+ # 親のメソッドを呼びだすものの、独自のクラス属性を参照します。
+ 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!
+
+ # 継承されたクラス属性
+ sup.age = 31
+ print(sup.age) # => 31
+
+ # Superhero限定の属性
+ print('Am I Oscar eligible? ' + str(sup.movie))
+
+
+
+####################################################
+# 6.2 多重継承
####################################################
# 別のクラスを定義します。
+# bat.py
class Bat:
species = 'Baty'
@@ -759,31 +882,22 @@ if __name__ == '__main__':
print(b.say('hello'))
print(b.fly)
-# ファイル単位のモジュール化を利用するために、上記のクラスを別々のファイルに配置することができます。
-# ここでは、human.pyとbat.pyを作成してみましょう。
-
-# 他のファイルから関数をインポートするために、次のような形式を利用してください。
-# from "拡張子無しのファイル名" import "関数またはクラス"
-
# superhero.py
-from human import Human
+from superhero import Superhero
from bat import Bat
-
-# BatmanはHumanとBatの両方を継承します。
-class Batman(Human, Bat):
-
- # Batmanは species のクラス属性に独自の値を持ちます。
- species = 'Superhero'
+# BatmanをSuperheroとBatの両方を継承した子クラスとして定義します。
+class Batman(Superhero, Bat):
def __init__(self, *args, **kwargs):
# 通常、属性を継承するにはsuper()を呼び出します。
- # super(Batman, self).__init__(*args, **kwargs)
+ # super(Batman, self).__init__(*args, **kwargs)
# しかし、ここでは多重継承を行っているので、 super() はMRO(メソッド解決順序)の次の基本クラスにのみ動作します。
# なので、全ての祖先に対して明示的に __init__ を呼ぶことにします。
# *args と **kwargs を使うことで、それぞれの継承元が
# たまねぎの皮を剥がすごとく、引数を用いることができます。
- Human.__init__(self, 'anonymous', *args, **kwargs)
+ Superhero.__init__(self, 'anonymous', movie=True,
+ superpowers=['Wealthy'], *args, **kwargs)
Bat.__init__(self, *args, can_fly=False, **kwargs)
# 名前の属性の値を上書きします。
self.name = 'Sad Affleck'
@@ -795,22 +909,18 @@ class Batman(Human, Bat):
if __name__ == '__main__':
sup = Batman()
- # インスタンスの型を調べてみましょう。
- if isinstance(sup, Human):
- print('I am human')
- if isinstance(sup, Bat):
- print('I am bat')
- if type(sup) is Batman:
- print('I am Batman')
-
# getattr() や super() の両方で使われるMROを取得します。
# この属性は動的であり、更新が可能です。
- print(Batman.__mro__) # => (<class '__main__.Batman'>, <class 'human.Human'>, <class 'bat.Bat'>, <class 'object'>)
+ print(Batman.__mro__) # => (<class '__main__.Batman'>,
+ # => <class 'superhero.Superhero'>,
+ # => <class 'human.Human'>,
+ # => <class 'bat.Bat'>, <class 'object'>)
+
# 親メソッドを呼び出しますが、独自のクラス属性を参照します。
- print(sup.get_species()) # => Superhero
+ print(sup.get_species()) # => Superhuman
- # オーバーロードされたメソッドを呼び出します。
+ # 上書きされたメソッドを呼び出します。
print(sup.sing()) # => nan nan nan nan nan batman!
# 継承順により、Humanから継承されたメソッドを呼び出します。
@@ -821,10 +931,10 @@ if __name__ == '__main__':
# 継承されたクラス属性
sup.age = 100
- print(sup.age)
+ print(sup.age) # => 100
# デフォルト値が上書きされて、2番目の先祖から継承された属性
- print('Can I fly? ' + str(sup.fly))
+ print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
####################################################
diff --git a/java.html.markdown b/java.html.markdown
index ca0b04c2..79769352 100644
--- a/java.html.markdown
+++ b/java.html.markdown
@@ -289,7 +289,7 @@ public class LearnJava {
// interface. This allows the execution time of basic
// operations, such as get and insert element, to remain
// constant-amortized even for large sets.
- // TreeMap - A Map that is sorted by its keys. Each modification
+ // TreeMap - A Map that is sorted by its keys. Each modification
// maintains the sorting defined by either a Comparator
// supplied at instantiation, or comparisons of each Object
// if they implement the Comparable interface.
@@ -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);
@@ -470,11 +470,11 @@ public class LearnJava {
// <second value>"
int foo = 5;
String bar = (foo < 10) ? "A" : "B";
- System.out.println("bar : " + bar); // Prints "bar : A", because the
+ System.out.println("bar : " + bar); // Prints "bar : A", because the
// statement is true.
// Or simply
System.out.println("bar : " + (foo < 10 ? "A" : "B"));
-
+
////////////////////////////////////////
// Converting Data Types
@@ -918,7 +918,7 @@ public class Lambdas {
planets.keySet().forEach(p -> System.out.format("%s\n", p));
// Tracing the above, we see that planets is a HashMap, keySet() returns
- // a Set of its keys, forEach applies each element as the lambda
+ // a Set of its keys, forEach applies each element as the lambda
// expression of: (parameter p) -> System.out.format("%s\n", p). Each
// time, the element is said to be "consumed" and the statement(s)
// referred to in the lambda body is applied. Remember the lambda body
@@ -998,6 +998,8 @@ The links provided here below are just to get an understanding of the topic, fee
* [Codewars - Java Katas](https://www.codewars.com/?language=java)
+* [University of Helsinki - Object-Oriented programming with Java](http://moocfi.github.io/courses/2013/programming-part-1/)
+
**Books**:
* [Head First Java](http://www.headfirstlabs.com/books/hfjava/)
diff --git a/javascript.html.markdown b/javascript.html.markdown
index c466c09b..ce9772ca 100644
--- a/javascript.html.markdown
+++ b/javascript.html.markdown
@@ -586,6 +586,48 @@ if (Object.create === undefined){ // don't overwrite it if it exists
return new Constructor();
};
}
+
+// ES6 Additions
+
+// The "let" keyword allows you to define variables in a lexical scope,
+// as opposed to a block scope like the var keyword does.
+let name = "Billy";
+
+// Variables defined with let can be reassigned new values.
+name = "William";
+
+// The "const" keyword allows you to define a variable in a lexical scope
+// like with let, but you cannot reassign the value once one has been assigned.
+
+const pi = 3.14;
+
+pi = 4.13; // You cannot do this.
+
+// There is a new syntax for functions in ES6 known as "lambda syntax".
+// This allows functions to be defined in a lexical scope like with variables
+// defined by const and let.
+
+const isEven = (number) => {
+ return number % 2 === 0;
+};
+
+isEven(7); // false
+
+// The "equivalent" of this function in the traditional syntax would look like this:
+
+function isEven(number) {
+ return number % 2 === 0;
+};
+
+// I put the word "equivalent" in double quotes because a function defined
+// using the lambda syntax cannnot be called before the definition.
+// The following is an example of invalid usage:
+
+add(1, 8);
+
+const add = (firstNumber, secondNumber) => {
+ return firstNumber + secondNumber;
+};
```
## Further Reading
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/kotlin.html.markdown b/kotlin.html.markdown
index 9bc8b420..5bbf6847 100644
--- a/kotlin.html.markdown
+++ b/kotlin.html.markdown
@@ -109,7 +109,7 @@ fun helloWorld(val name : String) {
/*
When a function consists of a single expression then the curly brackets can
- be omitted. The body is specified after a = symbol.
+ be omitted. The body is specified after the = symbol.
*/
fun odd(x: Int): Boolean = x % 2 == 1
println(odd(6)) // => false
@@ -306,7 +306,7 @@ fun helloWorld(val name : String) {
println(result)
/*
- We can check if an object is a particular type by using the "is" operator.
+ We can check if an object is of a particular type by using the "is" operator.
If an object passes a type check then it can be used as that type without
explicitly casting it.
*/
@@ -346,17 +346,25 @@ fun helloWorld(val name : String) {
return this.filter {it != c}
}
println("Hello, world!".remove('l')) // => Heo, word!
-
- println(EnumExample.A) // => A
- println(ObjectExample.hello()) // => hello
-
- testOperator()
}
// Enum classes are similar to Java enum types.
enum class EnumExample {
- A, B, C
+ A, B, C // Enum constants are separated with commas.
+}
+fun printEnum() = println(EnumExample.A) // => A
+
+// Since each enum is an instance of the enum class, they can be initialized as:
+enum class EnumExample(val value: Int) {
+ A(value = 1),
+ B(value = 2),
+ C(value = 3)
}
+fun printProperty() = println(EnumExample.A.value) // => 1
+
+// Every enum has properties to obtain its name and ordinal(position) in the enum class declaration:
+fun printName() = println(EnumExample.A.name) // => A
+fun printPosition() = println(EnumExample.A.ordinal) // => 0
/*
The "object" keyword can be used to create singleton objects.
@@ -367,11 +375,18 @@ object ObjectExample {
fun hello(): String {
return "hello"
}
+
+ override fun toString(): String {
+ return "Hello, it's me, ${ObjectExample::class.simpleName}"
+ }
}
-fun useObject() {
- ObjectExample.hello()
- val someRef: Any = ObjectExample // we use objects name just as is
+
+fun useSingletonObject() {
+ println(ObjectExample.hello()) // => hello
+ // In Kotlin, "Any" is the root of the class hierarchy, just like "Object" is in Java
+ val someRef: Any = ObjectExample
+ println(someRef) // => Hello, it's me, ObjectExample
}
@@ -381,69 +396,54 @@ throws an exception if the value is null.
var b: String? = "abc"
val l = b!!.length
-/* You can add many custom operations using symbol like +, to particular instance
-by overloading the built-in kotlin operator, using "operator" keyword
+data class Counter(var value: Int) {
+ // overload Counter += Int
+ operator fun plusAssign(increment: Int) {
+ this.value += increment
+ }
-below is the sample class to add some operator, and the most basic example
-*/
-data class SomeClass(var savedValue: Int = 0)
+ // overload Counter++ and ++Counter
+ operator fun inc() = Counter(value + 1)
-// instance += valueToAdd
-operator fun SomeClass.plusAssign(valueToAdd: Int) {
- this.savedValue += valueToAdd
-}
+ // overload Counter + Counter
+ operator fun plus(other: Counter) = Counter(this.value + other.value)
-// -instance
-operator fun SomeClass.unaryMinus() = SomeClass(-this.savedValue)
+ // overload Counter * Counter
+ operator fun times(other: Counter) = Counter(this.value * other.value)
-// ++instance or instance++
-operator fun SomeClass.inc() = SomeClass(this.savedValue + 1)
+ // overload Counter * Int
+ operator fun times(value: Int) = Counter(this.value * value)
-// instance * other
-operator fun SomeClass.times(other: SomeClass) =
- SomeClass(this.savedValue * other.savedValue)
+ // overload Counter in Counter
+ operator fun contains(other: Counter) = other.value == this.value
-// an overload for multiply
-operator fun SomeClass.times(value: Int) = SomeClass(this.savedValue * value)
+ // overload Counter[Int] = Int
+ operator fun set(index: Int, value: Int) {
+ this.value = index + value
+ }
-// other in instance
-operator fun SomeClass.contains(other: SomeClass) =
- other.savedValue == this.savedValue
+ // overload Counter instance invocation
+ operator fun invoke() = println("The value of the counter is $value")
-// instance[dummyIndex] = valueToSet
-operator fun SomeClass.set(dummyIndex: Int, valueToSet: Int) {
- this.savedValue = valueToSet + dummyIndex
}
-
-// instance()
-operator fun SomeClass.invoke() {
- println("instance invoked by invoker")
-}
-
-/* return type must be Integer,
-so that, it can be translated to "returned value" compareTo 0
-
-for equality (==,!=) using operator will violates overloading equals function,
-since it is already defined in Any class
-*/
-operator fun SomeClass.compareTo(other: SomeClass) =
- this.savedValue - other.savedValue
-
-fun testOperator() {
- var x = SomeClass(4)
-
- println(x) // => "SomeClass(savedValue=4)"
- x += 10
- println(x) // => "SomeClass(savedValue=14)"
- println(-x) // => "SomeClass(savedValue=-14)"
- println(++x) // => "SomeClass(savedValue=15)"
- println(x * SomeClass(3)) // => "SomeClass(savedValue=45)"
- println(x * 2) // => "SomeClass(savedValue=30)"
- println(SomeClass(15) in x) // => true
- x[2] = 10
- println(x) // => "SomeClass(savedValue=12)"
- x() // => "instance invoked by invoker"
- println(x >= 15) // => false
+/* You can also overload operators through an extension methods */
+// overload -Counter
+operator fun Counter.unaryMinus() = Counter(-this.value)
+
+fun operatorOverloadingDemo() {
+ var counter1 = Counter(0)
+ var counter2 = Counter(5)
+ counter1 += 7
+ println(counter1) // => Counter(value=7)
+ println(counter1 + counter2) // => Counter(value=12)
+ println(counter1 * counter2) // => Counter(value=35)
+ println(counter2 * 2) // => Counter(value=10)
+ println(counter1 in Counter(5)) // => false
+ println(counter1 in Counter(7)) // => true
+ counter1[26] = 10
+ println(counter1) // => Counter(value=36)
+ counter1() // => The value of the counter is 36
+ println(-counter2) // => Counter(value=-5)
}
```
diff --git a/lambda-calculus.html.markdown b/lambda-calculus.html.markdown
index a5535d6c..53a7a7cd 100644
--- a/lambda-calculus.html.markdown
+++ b/lambda-calculus.html.markdown
@@ -85,7 +85,7 @@ Using `IF`, we can define the basic boolean logic operators:
`a OR b` is equivalent to: `λab.IF a T b`
-`a NOT b` is equivalent to: `λa.IF a F T`
+`NOT a` is equivalent to: `λa.IF a F T`
*Note: `IF a b c` is essentially saying: `IF((a b) c)`*
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/ldpl.html.markdown b/ldpl.html.markdown
new file mode 100644
index 00000000..cc95f5fb
--- /dev/null
+++ b/ldpl.html.markdown
@@ -0,0 +1,183 @@
+---
+language: LDPL
+filename: learnLDPL.ldpl
+contributors:
+ - ["Martín del Río", "https://github.com/lartu"]
+---
+
+**LDPL** is a powerful, C++ transpiled, open-source programming language designed
+from the ground up to be excessively expressive, readable, fast and easy to learn.
+It mimics plain English, in the likeness of older programming languages like COBOL,
+with the desire that it can be understood by anybody. It's very portable and runs on a
+plethora of different architectures and operating systems and it even supports UTF-8
+out of the box.
+
+[Read more here.](https://github.com/lartu/ldpl)
+
+```coffeescript
+# This is a single line comment in LDPL.
+# LDPL doesn't have multi-line comments.
+
+# LDPL is a case-insensitive language: dIsPlaY and DISPLAY are the same
+# statement, and foo and FOO name the same variable.
+
+# An LDPL source file is divided in two sections, the DATA section and
+# the PROCEDURE section.
+
+DATA:
+# Within the DATA section, variables are declared.
+
+myNumber is number # Defines a real number.
+myString is text # Defines a string.
+myList is number list # Defines a list of numbers.
+myMap is number map # Defines a map of numbers.
+
+# LDPL understands four data types: two scalar types (NUMBER, TEXT)
+# and two container types (LISTs and MAPs).
+# LISTs can be TEXT LISTs or NUMBER LISTs, while MAPs can be
+# TEXT MAPs and NUMBER MAPs. You can also chain many containers
+# to create larger data types:
+textListList is text list list
+myMulticontainer is number list list map
+# Defines a map of lists of lists of numbers.
+
+PROCEDURE:
+# Within the PROCEDURE section, your code is written.
+
+store -19.2 in myNumber # Use the STORE statement to assign values
+store "Hi there" in myString # to variables.
+push 890 to myList # Use PUSH - TO to append values to lists.
+push 100 to myList
+push 500 to myList
+store 45 in myMap:"someIndex" # Use the : operator to index containers.
+
+push list to textListList # Push an empty list into a list of lists.
+push "LDPL is nice!" to textListList:0 #Push text to the pushed list.
+
+display "Hello World!" # Use the DISPLAY statement to print values.
+# The display statement can receive multiple values separated by spaces.
+display crlf "How are you today?" myNumber myString crlf
+# CRLF is the standard line break value in LDPL.
+display textListList:0:0 " Isn't it?" crlf
+
+# IF statements in LDPL are extremely verbose:
+if myNumber is equal to -19.2 and myList:0 is less than 900 then
+ display "Yes!" crlf
+else if myMap:"someIndex" is not equal to 45 then
+ display "This is an else if!" crlf
+else
+ display "Else!" crlf
+end if
+# Valid LDPL comparisson operators are
+# - IS EQUAL TO
+# - IS NOT EQUAL TO
+# - IS LESS THAN
+# - IS GREATER THAN
+# - IS LESS THAN OR EQUAL TO
+# - IS GREATER THAN OR EQUAL TO
+if "Hi there!" is not equal to "Bye bye!" then
+ display "Yep, those weren't equal." crlf
+end if
+# LDPL normally doesn't understand inline expressions, so you
+# cannot do stuff like:
+# if myNumber - 9 * 2 is equal to 10 then
+# LDPL will set your computer on fire and burst your screen if you do so.
+
+# WHILE loops follow the same rules
+store 0 in myNumber
+while myNumber is less than 10 do
+ display "Loop number " myNumber "..." crlf
+ in myNumber solve myNumber + 1 # You can do math like this.
+repeat
+# You can use 'break' and 'continue' inside loops just like any other language.
+
+# LDPL also has FOR loops and FOR EACH loops
+for myNumber from 0 to 100 step 2 do
+ display myNumber crlf
+repeat
+
+for each myNumber in myList do
+ display myNumber
+repeat
+
+display "Enter your name: "
+accept myString # Use ACCEPT to let the user input values.
+display "Hi there, " myString crlf
+display "How old are you?: "
+accept myNumber
+if myNumber is greater than 200 then
+ display "Woah, you are so old!" crlf
+end if
+
+wait 1000 milliseconds # Pause the program for a whole second.
+
+# Let's do some math
+store 1.2 in myNumber
+in myNumber solve myNumber * (10 / 7.2) # Operators are separated by spaces.
+floor myNumber
+display myNumber crlf
+get random in myNumber # get a random number between 0 and 1
+ # and store it in myNumber
+
+# Functions in LDPL are called sub-procedures. Sub-procedures, like source
+# files, are divided in sections. The sections found in sub-procedures are
+# the PARAMETERS section, the LOCAL DATA section and the PROCEDURE section.
+# All sections except the PROCEDURE section can be skipped if they aren't
+# used. If no PARAMTERS nor LOCAL DATA sections are used, the PROCEDURE
+# keyword may be omited.
+sub myFunction
+ parameters:
+ a is number # LDPL is pass by reference
+ b is number
+ result is number # Thus you can return values through a parameter.
+ local data:
+ c is number
+ procedure:
+ get random in c
+ in result solve a + b * c
+end sub
+
+sub sayHello
+ display "Hi there!" crlf
+ return
+ display "This won't be displayed :("
+end sub
+
+call myFunction with 1 2 myNumber
+display myNumber crlf
+call sayHello
+call sayBye # sub-procedures may be called before they are declared
+
+sub sayBye
+ display "Bye!"
+end sub
+
+# One of the greatest features of LDPL is the ability to create your
+# own statements.
+
+create statement "say hi" executing sayHello
+say hi
+
+create statement "random add $ and $ in $" executing myFunction
+random add 1 and 2 in myNumber
+display myNumber crlf
+
+exit
+```
+
+## Topics Not Covered
+
+ * [Command line arguments](https://docs.ldpl-lang.org/variables-in-ldpl/command-line-arguments)
+ * [Error variables](https://docs.ldpl-lang.org/variables-in-ldpl/errorcode-and-errortext)
+ * [Import other files](https://docs.ldpl-lang.org/structure-of-ldpl-source-code/importing-other-sources)
+ * [Identifier naming schemes](https://docs.ldpl-lang.org/naming-rules)
+ * [Text Statements](https://docs.ldpl-lang.org/text-statements/join-and-in)
+ * [List Statements](https://docs.ldpl-lang.org/list-statements/push-to)
+ * [Map Statements](https://docs.ldpl-lang.org/vector-statements/clear)
+ * [File loading / writing](https://docs.ldpl-lang.org/i-o-statements/load-file-in)
+ * [Executing commands](https://docs.ldpl-lang.org/i-o-statements/execute)
+ * [Extending LDPL with C++](https://docs.ldpl-lang.org/extensions/c++-extensions)
+
+## Further Reading
+
+ * [LDPL Docs](https://docs.ldpl-lang.org)
diff --git a/linker.html.markdown b/linker.html.markdown
new file mode 100644
index 00000000..42839e05
--- /dev/null
+++ b/linker.html.markdown
@@ -0,0 +1,9 @@
+---
+category: tool
+tool: linker
+contributors:
+ - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
+---
+
+This article is available in [Russian](https://learnxinyminutes.com/docs/ru-ru/linker-ru/).
+
diff --git a/lsf/lambda-calculus-lsf.html.markdown b/lsf/lambda-calculus-lsf.html.markdown
new file mode 100644
index 00000000..88bb638f
--- /dev/null
+++ b/lsf/lambda-calculus-lsf.html.markdown
@@ -0,0 +1,91 @@
+---
+category: Algorithms & Data Structures
+name: Lambda Calculus
+contributors:
+ - ["Max Sun", "http://github.com/maxsun"]
+translators:
+ - ["Victore Leve", "https://github.com/AcProIL"]
+lang: lsf
+---
+
+# Calculo λ
+
+Calculo lambda, creato principto per Alonzo Church, es lingua de programmatura
+computatro maximo parvo. Quamquam non habe numero, serie de charactere vel ullo
+typo de data non functionale, id pote repraesenta omne machina de Turing.
+
+Tres elemento compone calculo lambda: **quantitate variabile** (q.v.),
+**functione** et **applicatione**.
+
+| Elemento | Syntaxe | Exemplo |
+|----------------------|-----------------------------------|-----------|
+| Quantitate variabile | `<nomine>` | `x` |
+| Functione | `λ<parametro>.<corpore>` | `λx.x` |
+| Applicatione | `<functione><q.v. aut functione>` | `(λx.x)a` |
+
+Functione fundamentale es identitate: `λx.x` cum argumento primo `x` et cum
+corpore secundo `x`. In mathematica, nos scribe `id: x↦x`.
+
+## Quantitate variabile libero et ligato
+
+* In functione praecedente, `x` es q.v. ligato nam id es et in copore et
+ argumento.
+* In `λx.y`, `y` es q.v. libero nam non es declarato ante.
+
+## Valutatione
+
+Valutatione es facto per reductione beta (reductione β) que es essentialiter
+substitutione lexicale.
+
+Dum valutatione de formula `(λx.x)a`, nos substitue omne evento de `x` in
+corpore de functione pro `a`.
+
+* `(λx.x)a` vale `a`
+* `(λx.y)a` vale `y`
+
+Pote etiam crea functione de ordine supero: `(λx.(λy.x))a` vale `λy.a`.
+
+Etsi calculo lambda solo tracta functione de uno parametro, nos pote crea
+functione cum plure argumento utente methodo de Curry: `λx.(λy.(λz.xyz))`
+es scriptura informatica de formula mathematico `f: x, y, z ↦ x(y(z)))`.
+
+Ergo, interdum, nos ute `λxy.<corpore>` pro `λx.λy.<corpore>`.
+
+## Arithmetica
+
+### Logica de Boole
+
+Es nec numero nec booleano in calculo lambda.
+
+* «vero» es `v = λx.λy.x`
+* «falso» es `f = λx.λy.y`
+
+Primo, nos pote defini functione «si t tunc a alio b» per `si = λtab.tab`.
+Si `t` es vero, valutatione da `(λxy.x) a b` id es `a`. Similiter si `t` es
+falso, nos obtine `b`.
+
+Secundo, nos pote defini operatore de logica:
+
+* «a et b» es `et = λa.λb.si a b f`
+* «a vel b» es `vel = λa.λb.si a t b`
+* «non a» es `non = λa.si a f t`
+
+### Numeros
+
+Nos pone:
+
+* `0 = λf.λx.x` (`0: f↦id`)
+* `1 = λf.λx.f x` (`1: f↦f`)
+* `2 = λf.λx.f(f x)` (`2: f↦f⚬f`)
+
+Cum mente generale, successore de numero `n` es `S n = λf.λx.f((n f) x)`
+(`n+1: f↦f⚬fⁿ`). Id es **`n` est functione que da `fⁿ` ex functione `f`**.
+
+Postremo additione es `λab.(a S)b`
+
+## Ut progrede
+
+### In lingua anglo
+
+1. [A Tutorial Introduction to the Lambda Calculus](http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf) per Raúl Roja
+2. [The Lambda Calculus](http://www.cs.cornell.edu/courses/cs3110/2008fa/recitations/rec26.html), CS 312 Recitation 26
diff --git a/lsf/latex-lsf.html.markdown b/lsf/latex-lsf.html.markdown
new file mode 100644
index 00000000..18c2e62b
--- /dev/null
+++ b/lsf/latex-lsf.html.markdown
@@ -0,0 +1,146 @@
+---
+language: latex
+lang: lsf
+contributors:
+ - ["Chaitanya Krishna Ande", "http://icymist.github.io"]
+ - ["Colton Kohnke", "http://github.com/voltnor"]
+ - ["Sricharan Chiruvolu", "http://sricharan.xyz"]
+translators:
+ - ["Victore Leve", "https://github.com/AcProIL"]
+filename: learn-latex-lsf.tex
+---
+
+```tex
+% Solo existe commentario monolinea, illo incipe cum charactere %
+
+% LaTeX non es sicut MS Word aut OpenOffice: que scribe non es que obtine.
+% Primo, scribe imperio (que semper incipe cum \) et secundo programma crea
+% lima.
+
+% Nos defini typo de document (id es articulo aut libro aut libello etc.).
+% Optione muta quomodo programma age, per exemplo altore de littera.
+\documentclass[12pt]{article}
+
+% Deinde nos lista paccettos que nos vol ute. Es classe de imperio que alio
+% utatore e scribe. Pote muta funda, geometria de pagina, etc. vel adde
+% functionnalitate.
+\usepackage{euler}
+\usepackage{graphicx}
+
+% Ultimo statione ante scribe documento es metadata id es titulo, auctore et
+% tempore. Charactere ~ es spatio que non pote es secato.
+\title{Disce LaTeX in~Y Minutos!}
+\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu}
+\date{\today}
+
+% Principio de documento
+\begin{document}
+ \maketitle % Nos vol adfige metadata.
+
+ % Saepe nos adde breviario us describe texto.
+ \begin{abstract}
+ Hic es exmplo de documento sibre cum lingua de LaTeX.
+ \end{abstract}
+
+ % \section crea sectione cum titulo dato sicut sperato
+ \section{Introductione}
+
+ Traductione de hic cursu es importante.
+
+ \subsection{Methodo}
+ Iste parte non es utile.
+
+ \subsubsection{Methodo peculiare}
+ % \label da nomine ad parte ut post ute imperio de referentia \ref.
+ \label{subsec:metpec}
+
+ % Cum asteritco nos indice que nos non vol numero ante titulo de sectione.
+ \section*{Me non aestima numero…}
+
+ …sed de Peano aut de Church.
+
+ \section{Listas}
+
+ Que me debe scribe:
+
+ \begin{enumerate} % `enumerate` designa lista cum numeros contra `itemize`.
+ \item articulo,
+ \item libro,
+ \item cursu.
+ \end{enumerate}
+
+ \section{Mathematica}
+
+ Methematicas ute multo programma LaTeX ut communica suo decooperito.
+ Illo necessita symbolo multo instar de logica vel sagitta vel littera cum
+ accento.
+
+ % Fornula es in linea si nos scribe inter \( et \) (aut duo $) sed magno si
+ % nos ute \[ et \].
+ \(\forall n\in N_0\) % pro omne n in classe N₀
+ \[^{3}/_{4} = \frac{3}{4} < 1\] % ¾ < 1
+
+ Alphabeta graeco contine littera $\alpha$.
+
+ % Ut scribe equatione cum numero et nomine, existe circumiecto `equation`.
+ \begin{equation}
+ c^2 = a^2 + b^2
+ \label{eq:pythagoras}
+ \end{equation}
+
+ \begin{equation}
+ % Summa ab 1 ad n de numeros dimidio de n(n+1)
+ \sum_{i=1}^n i = \frac{n(n+1)}{2}
+ \end{equation}
+
+ \section{Figura}
+
+ % Nos adde imagine `right-triangle.png` cum latitudo de quinque centimetro,
+ % horizontaliter in centro et cum capite «Triangulo recto».
+ \begin{figure}
+ \centering
+ \includegraphics[width=5cm]{right-triangle.png}
+ \caption{Triangulo recto}
+ \label{fig:right-triangle}
+ \end{figure}
+
+ \subsection{Tabula}
+
+ \begin{table}
+ \caption{Título para la tabla.}
+ % Argumento de `tabular` es lineamente de columna.
+ % c: centro, l: sinistra, r: destra, | linea verticale
+ \begin{tabular}{c|cc}
+ Numero & B & C \\
+ \hline % linea horizontale
+ 1 & et & aut \\
+ 2 & atque & vel
+ \end{tabular}
+ \end{table}
+
+ \section{Stylo}
+
+ Texto pote es \textbf{crasso} et \textit{italico}!
+
+ \section{Texto puro}
+
+ % Circumiecto `verbatim` ignora imperio, nos saepe ute id pro monstra
+ % programma.
+ \begin{verbatim}
+from math import tau, e
+print(e ** tau)
+ \end{verbatim}
+
+ \section{Et plus!}
+ LaTeX habe facultate crea bibliographia, paritura, scaccarip… cum paccetto
+ dedicato.
+\end{document}
+```
+
+Imperio ut conge documento es `pdflatex documento` in terminale.
+
+## Ut progrede
+
+### In lingua anglo
+
+* [LaTeX tutorial](http://www.latex-tutorial.com/) per Claudio Vellage
diff --git a/mercurial.html.markdown b/mercurial.html.markdown
index 330beb35..98658f83 100644
--- a/mercurial.html.markdown
+++ b/mercurial.html.markdown
@@ -350,6 +350,6 @@ $ hg remove *.txt
## Further information
-* [Learning Mercurial in Workflows](https://www.mercurial-scm.org/guid)
+* [Learning Mercurial in Workflows](https://www.mercurial-scm.org/guide)
* [Mercurial Quick Start](https://www.mercurial-scm.org/wiki/QuickStart)
-* [Mercurial: The Definitive Guide by Bryan O'Sullivan](http://hgbook.red-bean.com/) \ No newline at end of file
+* [Mercurial: The Definitive Guide by Bryan O'Sullivan](http://hgbook.red-bean.com/)
diff --git a/mercury.html.markdown b/mercury.html.markdown
new file mode 100644
index 00000000..f749bac4
--- /dev/null
+++ b/mercury.html.markdown
@@ -0,0 +1,263 @@
+---
+language: mercury
+contributors:
+ - ["Julian Fondren", "https://mercury-in.space/"]
+---
+
+Mercury is a strict, pure functional/logic programming language, with
+influences from Prolog, ML, and Haskell.
+
+```prolog
+% Percent sign starts a one-line comment.
+
+ % foo(Bar, Baz)
+ %
+ % Documentation comments are indented before what they describe.
+:- pred foo(bar::in, baz::out) is det.
+
+% All toplevel syntax elements end with a '.' -- a full stop.
+
+% Mercury terminology comes from predicate logic. Very roughly:
+
+% | Mercury | C |
+% | | |
+% | Goal | statement |
+% | expression | expression |
+% | predicate rule | void function |
+% | function rule | function |
+% | head (of a rule) | function name and parameters |
+% | body (of a rule) | function body |
+% | fact | (rule without a body) |
+% | pred/func declaration | function signature |
+% | A, B (conjunction) | A && B |
+% | A ; B (disjunction) | if (A) {} else if (B) {} |
+
+% some facts:
+man(socrates). % "it is a fact that Socrates is a man"
+man(plato).
+man(aristotle).
+
+% a rule:
+mortal(X) :- man(X). % "It is a rule that X is a mortal if X is a man."
+% ^^^^^^-- the body of the rule
+% ^^-- an arrow <--, pointing to the head from the body
+%^^^^^^^^-- the head of the rule
+% this is also a single clause that defines the rule.
+
+% that X is capitalized is how you know it's a variable.
+% that socrates is uncapitalized is how you know it's a term.
+
+% it's an error for 'socrates' to be undefined. It must have a type:
+
+% declarations begin with ':-'
+:- type people
+ ---> socrates
+ ; plato
+ ; aristotle
+ ; hermes.
+ %<--first tab stop (using 4-space tabs)
+ %<--third tab stop (first after --->)
+
+:- pred man(people). % rules and facts also require types
+
+% a rule's modes tell you how it can be used.
+:- mode man(in) is semidet. % man(plato) succeeds. man(hermes) fails.
+:- mode man(out) is multi. % man(X) binds X to one of socrates ; plato ; aristotle
+
+% a semidet predicate is like a test. It doesn't return a value, but
+% it can succeed or fail, triggering backtracking or the other side of
+% a disjunction or conditional.
+
+% 'is semidet' provides the determinism of a mode. Other determinisms:
+% | Can fail? | 0 solutions | 1 | more than 1 |
+% | | | | |
+% | no | erroneous | det | multi |
+% | yes | failure | semidet | nondet |
+
+:- pred mortal(people::in) is semidet. % type/mode in one declaration
+
+% this rule's body consists of two conjunctions: A, B, C
+% this rule is true if A, B, and C are all true.
+% if age(P) returns 16, it fails.
+% if alive(P) fails, it fails.
+:- type voter(people::in) is semidet.
+voter(P) :-
+ alive(P),
+ registered(P, locale(P)),
+ age(P) >= 18. % age/1 is a function; int.>= is a function used as an operator
+
+% "a P is a voter if it is alive, is registered in P's locale, and if
+% P's age is 18 or older."
+
+% the >= used here is provided by the 'int' module, which isn't
+% imported by default. Mercury has a very small 'Prelude' (the
+% 'builtin' module). You even need to import the 'list' module if
+% you're going to use list literals.
+```
+
+Complete runnable example. File in 'types.m'; compile with 'mmc --make types'.
+
+```prolog
+:- module types.
+:- interface.
+:- import_module io. % required for io.io types in...
+% main/2 is usually 'det'. threading and exceptions require 'cc_multi'
+:- pred main(io::di, io::uo) is cc_multi. % program entry point
+:- implementation.
+:- import_module int, float, string, list, bool, map, exception.
+
+% enum.
+:- type days
+ ---> sunday
+ ; monday
+ ; tuesday
+ ; wednesday
+ ; thursday
+ ; friday
+ ; saturday.
+
+% discriminated union, like datatype in ML.
+:- type payment_method
+ ---> cash(int)
+ ; credit_card(
+ name :: string, % named fields
+ cc_number :: string,
+ cvv :: int,
+ expiration :: string
+ )
+ ; crypto(coin_type, wallet, amount).
+
+:- type coin_type
+ ---> etherium
+ ; monero. % "other coins are available"
+
+% type aliases.
+:- type wallet == string.
+:- type amount == int.
+
+% !IO is the pair of io.io arguments
+% pass it to anything doing I/O, in order to perform I/O.
+% many otherwise-impure functions can 'attach to the I/O state' by taking !IO
+main(!IO) :-
+ Ints = [
+ 3,
+ 1 + 1,
+ 8 - 1,
+ 10 * 2,
+ 35 / 5,
+ 5 / 2, % truncating division
+ int.div(5, 2), % floored division
+ div(5, 2), % (module is unambiguous due to types)
+ 5 `div` 2, % (any binary function can be an operator with ``)
+ 7 `mod` 3, % modulo of floored division
+ 7 `rem` 3, % remainder of truncating division
+ 2 `pow` 4, % 2 to the 4th power
+ (1 + 3) * 2, % parens have their usual meaning
+
+ 2 >> 3, % bitwise right shift
+ 128 << 3, % bitwise left shift
+ \ 0, % bitwise complement
+ 5 /\ 1, % bitwise and
+ 5 \/ 1, % bitwise or
+ 5 `xor` 3, % bitwise xor
+
+ max_int,
+ min_int,
+
+ 5 `min` 3, % ( if 5 > 3 then 3 else 5 )
+ 5 `max` 3
+ ],
+ Bools = [
+ yes,
+ no
+ % bools are much less important in Mercury because control flow goes by
+ % semidet goals instead of boolean expressions.
+ ],
+ Strings = [
+ "this is a string",
+ "strings can have "" embedded doublequotes via doubling",
+ "strings support \u4F60\u597D the usual escapes\n",
+ % no implicit concatenation of strings: "concat:" "together"
+ "but you can " ++ " use the string.++ operator",
+
+ % second param is a list(string.poly_type)
+ % s/1 is a function that takes a string and returns a poly_type
+ % i/1 takes an int. f/1 takes a float. c/1 takes a char.
+ string.format("Hello, %d'th %s\n", [i(45), s("World")])
+ ],
+
+ % start with purely functional types like 'map' and 'list'!
+ % arrays and hash tables are available too, but using them
+ % requires knowing a lot more about Mercury
+ get_map1(Map1),
+ get_map2(Map2),
+
+ % list.foldl has *many* variations
+ % this one calls io.print_line(X, !IO) for each X of the list
+ foldl(io.print_line, Ints, !IO),
+ foldl(io.print_line, Bools, !IO),
+ foldl(io.print_line, Strings, !IO),
+ io.print_line(Map1, !IO),
+ % ( if Cond then ThenGoal else ElseGoal )
+ % I/O not allowed in Cond: I/O isn't allowed to fail!
+ ( if Map2^elem(42) = Elem then
+ io.print_line(Elem, !IO)
+ else % always required
+ true % do nothing, successfully (vs. 'fail')
+ ),
+
+ % exception handling:
+ ( try [io(!IO)] ( % io/1 param required or no I/O allowed here
+ io.print_line(received(cash(1234)), !IO),
+ io.print_line(received(crypto(monero, "invalid", 123)), !IO)
+ ) then
+ io.write_string("all payments accepted\n", !IO) % never reached
+ catch "monero not yet supported" -> % extremely specific catch!
+ io.write_string("monero payment failed\n", !IO)
+ ).
+
+:- pred get_map1(map(string, int)::out) is det.
+get_map1(!:Map) :- % !:Map in the head is the final (free, unbound) Map
+ !:Map = init, % !:Map in the body is the next Map
+ det_insert("hello", 1, !Map), % pair of Map vars
+ det_insert("world", 2, !Map),
+
+ % debug print of current (bound) Map
+ % other [Params] can make it optional per runtime or compiletime flags
+ trace [io(!IO)] (io.print_line(!.Map, !IO)),
+
+ det_insert_from_corresponding_lists(K, V, !Map),
+ % this code is reordered so that K and V and defined prior to their use
+ K = ["more", "words", "here"],
+ V = [3, 4, 5].
+
+:- pred get_map2(map(int, bool)::out) is det.
+get_map2(Map) :-
+ det_insert(42, yes, map.init, Map).
+
+:- func received(payment_method) = string.
+received(cash(N)) = string.format("received %d dollars", [i(N)]).
+received(credit_card(_, _, _, _)) = "received credit card". % _ is throwaway
+received(crypto(Type, _Wallet, Amount)) = S :- % _Wallet is named throwaway
+ ( % case/switch structure
+ Type = etherium,
+ S = string.format("receiving %d ETH", [i(Amount)])
+ ;
+ Type = monero,
+ throw("monero not yet supported") % exception with string as payload
+ ).
+```
+
+## That was quick! Want more?
+
+### More Tutorials
+
+* [Mercury Tutorial](https://mercurylang.org/documentation/papers/book.pdf) (pdf link) - a more traditional tutorial with a more relaxed pace
+* [Mercury Crash Course](https://mercury-in.space/crash.html) - a dense example-driven tutorial with Q&A format
+* [Github Wiki Tutorial](https://github.com/Mercury-Language/mercury/wiki/Tutorial)
+* [Getting Started with Mercury](https://bluishcoder.co.nz/2019/06/23/getting-started-with-mercury.html) - installation and your first steps
+
+### Documentation
+
+* Language manual, user's guide, and library reference are all at
+ [mercurylang.org](https://mercurylang.org/documentation/documentation.html)
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/nix.html.markdown b/nix.html.markdown
index d078395a..5941f0e6 100644
--- a/nix.html.markdown
+++ b/nix.html.markdown
@@ -4,6 +4,7 @@ filename: learn.nix
contributors:
- ["Chris Martin", "http://chris-martin.org/"]
- ["Rommel Martinez", "https://ebzzry.io"]
+ - ["Javier Candeira", "https://candeira.com/"]
---
Nix is a simple functional language developed for the
@@ -12,7 +13,7 @@ Nix is a simple functional language developed for the
You can evaluate Nix expressions using
[nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate)
-or [`nix-repl`](https://github.com/edolstra/nix-repl).
+or [`nix repl`](https://nixos.org/nix/manual/#ssec-relnotes-2.0).
```
with builtins; [
@@ -39,18 +40,26 @@ with builtins; [
#=> "a"
- # Integers
+ # Integers and Floats
#=========================================
- # Integers are the only numeric type.
+ # There are two numeric types: integers and floats
1 0 42 (-3) # Some integers
+ 123.43 .27e13 # A couple of floats
+
+ # Operations will preserve numeric type
+
(4 + 6 + 12 - 2) # Addition
#=> 20
+ (4 - 2.5)
+ #=> 1.5
(7 / 2) # Division
#=> 3
+ (7 / 2.0)
+ #=> 3.5
# Strings
@@ -238,13 +247,20 @@ with builtins; [
}.a.c
#=> { d = 2; e = 3; }
- # An attribute's descendants cannot be assigned in this
- # way if the attribute itself has been directly assigned.
+ # Sets are immutable, so you can't redefine an attribute:
+ {
+ a = { b = 1; };
+ a.b = 2;
+ }
+ #=> attribute 'a.b' at (string):3:5 already defined at (string):2:11
+
+ # However, an attribute's set members can also be defined piecewise
+ # way even if the attribute itself has been directly assigned.
{
a = { b = 1; };
a.c = 2;
}
- #=> error: attribute ‘a’ already defined
+ #=> { a = { b = 1; c = 2; }; }
# With
@@ -321,8 +337,8 @@ with builtins; [
#=========================================
# Because repeatability of builds is critical to the Nix package
- # manager, in which, functional purity is emphasized in the Nix
- # language. But there are a few impurities.
+ # manager, functional purity is emphasized in the Nix language
+ # used to describe Nix packages. But there are a few impurities.
# You can refer to environment variables.
(getEnv "HOME")
diff --git a/opengl.html.markdown b/opengl.html.markdown
new file mode 100644
index 00000000..83ace3e8
--- /dev/null
+++ b/opengl.html.markdown
@@ -0,0 +1,765 @@
+---
+category: tool
+tool: OpenGL
+filename: learnopengl.cpp
+contributors:
+ - ["Simon Deitermann", "s.f.deitermann@t-online.de"]
+---
+
+**Open Graphics Library** (**OpenGL**) is a cross-language cross-platform application programming interface
+(API) for rendering 2D computer graphics and 3D vector graphics.<sup>[1]</sup> In this tutorial we will be
+focusing on modern OpenGL from 3.3 and above, ignoring "immediate-mode", Displaylists and
+VBO's without use of Shaders.
+I will be using C++ with SFML for window, image and context creation aswell as GLEW
+for modern OpenGL extensions, though there are many other librarys available.
+
+```cpp
+// Creating an SFML window and OpenGL basic setup.
+#include <GL/glew.h>
+#include <GL/gl.h>
+#include <SFML/Graphics.h>
+#include <iostream>
+
+int main() {
+ // First we tell SFML how to setup our OpenGL context.
+ sf::ContextSettings context{ 24, // depth buffer bits
+ 8, // stencil buffer bits
+ 4, // MSAA samples
+ 3, // major opengl version
+ 3 }; // minor opengl version
+ // Now we create the window, enable VSync
+ // and set the window active for OpenGL.
+ sf::Window window{ sf::VideoMode{ 1024, 768 },
+ "opengl window",
+ sf::Style::Default,
+ context };
+ window.setVerticalSyncEnabled(true);
+ window.setActive(true);
+ // After that we initialise GLEW and check if an error occured.
+ GLenum error;
+ glewExperimental = GL_TRUE;
+ if ((err = glewInit()) != GLEW_OK)
+ std::cout << glewGetErrorString(err) << std::endl;
+ // Here we set the color glClear will clear the buffers with.
+ glClearColor(0.0f, // red
+ 0.0f, // green
+ 0.0f, // blue
+ 1.0f); // alpha
+ // Now we can start the event loop, poll for events and draw objects.
+ sf::Event event{ };
+ while (window.isOpen()) {
+ while (window.pollEvent(event)) {
+ if (event.type == sf::Event::Closed)
+ window.close;
+ }
+ // Tell OpenGL to clear the color buffer
+ // and the depth buffer, this will clear our window.
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ // Flip front- and backbuffer.
+ window.display();
+ }
+ return 0;
+}
+```
+
+## Loading Shaders
+
+After creating a window and our event loop we should create a function,
+that sets up our shader program.
+
+```cpp
+GLuint createShaderProgram(const std::string& vertexShaderPath,
+ const std::string& fragmentShaderPath) {
+ // Load the vertex shader source.
+ std::stringstream ss{ };
+ std::string vertexShaderSource{ };
+ std::string fragmentShaderSource{ };
+ std::ifstream file{ vertexShaderPath };
+ if (file.is_open()) {
+ ss << file.rdbuf();
+ vertexShaderSource = ss.str();
+ file.close();
+ }
+ // Clear the stringstream and load the fragment shader source.
+ ss.str(std::string{ });
+ file.open(fragmentShaderPath);
+ if (file.is_open()) {
+ ss << file.rdbuf();
+ fragmentShaderSource = ss.str();
+ file.close();
+ }
+ // Create the program.
+ GLuint program = glCreateProgram();
+ // Create the shaders.
+ GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+ // Now we can load the shader source into the shader objects and compile them.
+ // Because glShaderSource() wants a const char* const*,
+ // we must first create a const char* and then pass the reference.
+ const char* cVertexSource = vertexShaderSource.c_str();
+ glShaderSource(vertexShader, // shader
+ 1, // number of strings
+ &cVertexSource, // strings
+ nullptr); // length of strings (nullptr for 1)
+ glCompileShader(vertexShader);
+ // Now we have to do the same for the fragment shader.
+ const char* cFragmentSource = fragmentShaderSource.c_str();
+ glShaderSource(fragmentShader, 1, &cFragmentSource, nullptr);
+ glCompileShader(fragmentShader);
+ // After attaching the source and compiling the shaders,
+ // we attach them to the program;
+ glAttachShader(program, vertexShader);
+ glAttachShader(program, fragmentShader);
+ glLinkProgram(program);
+ // After linking the shaders we should detach and delete
+ // them to prevent memory leak.
+ glDetachShader(program, vertexShader);
+ glDetachShader(program, fragmentShader);
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ // With everything done we can return the completed program.
+ return program;
+}
+```
+
+If you want to check the compilation log you can add the following between <code>glCompileShader()</code> and <code>glAttachShader()</code>.
+
+```cpp
+GLint logSize = 0;
+std::vector<GLchar> logText{ };
+glGetShaderiv(vertexShader, // shader
+ GL_INFO_LOG_LENGTH, // requested parameter
+ &logSize); // return object
+if (logSize > 0) {
+ logText.resize(logSize);
+ glGetShaderInfoLog(vertexShader, // shader
+ logSize, // buffer length
+ &logSize, // returned length
+ logText.data()); // buffer
+ std::cout << logText.data() << std::endl;
+}
+```
+
+The same is possibile after <code>glLinkProgram()</code>, just replace <code>glGetShaderiv()</code> with <code>glGetProgramiv()</code>
+and <code>glGetShaderInfoLog()</code> with <code>glGetProgramInfoLog()</code>.
+
+```cpp
+// Now we can create a shader program with a vertex and a fragment shader.
+// ...
+glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+GLuint program = createShaderProgram("vertex.glsl", "fragment.glsl");
+
+sf::Event event{ };
+// ...
+// We also have to delete the program at the end of the application.
+// ...
+ }
+ glDeleteProgram(program);
+ return 0;
+}
+// ...
+```
+
+Ofcourse we have to create the vertex and fragment shader before we can load them,
+so lets create two basic shaders.
+
+**Vertex Shader**
+
+```glsl
+// Declare which version of GLSL we use.
+// Here we declare, that we want to use the OpenGL 3.3 version of GLSL.
+#version 330 core
+// At attribute location 0 we want an input variable of type vec3,
+// that contains the position of the vertex.
+// Setting the location is optional, if you don't set it you can ask for the
+// location with glGetAttribLocation().
+layout(location = 0) in vec3 position;
+// Every shader starts in it's main function.
+void main() {
+ // gl_Position is a predefined variable that holds
+ // the final vertex position.
+ // It consists of a x, y, z and w coordinate.
+ gl_Position = vec4(position, 1.0);
+}
+```
+
+**Fragment Shader**
+
+```glsl
+#version 330 core
+// The fragment shader does not have a predefined variable for
+// the vertex color, so we have to define a output vec4,
+// that holds the final vertex color.
+out vec4 outColor;
+
+void main() {
+ // We simply set the ouput color to red.
+ // The parameters are red, green, blue and alpha.
+ outColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+```
+
+## VAO and VBO
+Now we need to define some vertex position we can pass to our shaders. Lets define a simple 2D quad.
+
+```cpp
+// The vertex data is defined in a counter-clockwise way,
+// as this is the default front face.
+std::vector<float> vertexData {
+ -0.5f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f,
+ 0.5f, 0.5f, 0.0f
+};
+// If you want to use a clockwise definition, you can simply call
+glFrontFace(GL_CW);
+// Next we need to define a Vertex Array Object (VAO).
+// The VAO stores the current state while its active.
+GLuint vao = 0;
+glGenVertexArrays(1, &vao);
+glBindVertexArray(vao);
+// With the VAO active we can now create a Vertex Buffer Object (VBO).
+// The VBO stores our vertex data.
+GLuint vbo = 0;
+glGenBuffers(1, &vbo);
+glBindBuffer(GL_ARRAY_BUFFER, vbo);
+// For reading and copying there are also GL_*_READ and GL_*_COPY,
+// if your data changes more often use GL_DYNAMIC_* or GL_STREAM_*.
+glBufferData(GL_ARRAY_BUFFER, // target buffer
+ sizeof(vertexData[0]) * vertexData.size(), // size
+ vertexData.data(), // data
+ GL_STATIC_DRAW); // usage
+// After filling the VBO link it to the location 0 in our vertex shader,
+// which holds the vertex position.
+// ...
+// To ask for the attibute location, if you haven't set it:
+GLint posLocation = glGetAttribLocation(program, "position");
+// ..
+glEnableVertexAttribArray(0);
+glVertexAttribPointer(0, 3, // location and size
+ GL_FLOAT, // type of data
+ GL_FALSE, // normalized (always false for floats)
+ 0, // stride (interleaved arrays)
+ nullptr); // offset (interleaved arrays)
+// Everything should now be saved in our VAO and we can unbind it and the VBO.
+glBindVertexArray(0);
+glBindBuffer(GL_ARRAY_BUFFER, 0);
+// Now we can draw the vertex data in our render loop.
+// ...
+glClear(GL_COLOR_BUFFER_BIT);
+// Tell OpenGL we want to use our shader program.
+glUseProgram(program);
+// Binding the VAO loads the data we need.
+glBindVertexArray(vao);
+// We want to draw a quad starting at index 0 of the VBO using 4 indices.
+glDrawArrays(GL_QUADS, 0, 4);
+glBindVertexArray(0);
+window.display();
+// ...
+// Ofcource we have to delete the allocated memory for the VAO and VBO at
+// the end of our application.
+// ...
+glDeleteBuffers(1, &vbo);
+glDeleteVertexArrays(1, &vao);
+glDeleteProgram(program);
+return 0;
+// ...
+```
+
+You can find the current code here: [OpenGL - 1](https://pastebin.com/W8jdmVHD).
+
+## More VBO's and Color
+Let's create another VBO for some colors.
+
+```cpp
+std::vector<float> colorData {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 0.0f
+};
+```
+
+Next we can simply change some previous parameters to create a second VBO for our colors.
+
+```cpp
+// ...
+GLuint vbo[2];
+glGenBuffers(2, vbo);
+glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
+// ...
+glDeleteBuffers(2, vbo);
+/ ...
+// With these changes made we now have to load our color data into the new VBO
+// ...
+glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
+glBufferData(GL_ARRAY_BUFFER, sizeof(colorData[0]) * colorData.size(),
+ colorData.data(), GL_STATIC_DRAW);
+glEnableVertexAttribArray(1);
+glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
+
+glBindVertexArray(0);
+// ...
+```
+
+Next we have to change our vertex shader to pass the color data to the fragment shader.<br>
+**Vertex Shader**
+
+```glsl
+#version 330 core
+
+layout(location = 0) in vec3 position;
+// The new location has to differ from any other input variable.
+// It is the same index we need to pass to
+// glEnableVertexAttribArray() and glVertexAttribPointer().
+layout(location = 1) in vec3 color;
+
+out vec3 fColor;
+
+void main() {
+ fColor = color;
+ gl_Position = vec4(position, 1.0);
+}
+```
+
+**Fragment Shader**
+
+```glsl
+#version 330 core
+
+in vec3 fColor;
+
+out vec4 outColor;
+
+void main() {
+ outColor = vec4(fColor, 1.0);
+}
+```
+
+We define a new input variable ```color``` which represents our color data, this data
+is passed on to ```fColor```, which is an output variable of our vertex shader and
+becomes an input variable for our fragment shader.
+It is imporatant that variables passed between shaders have the exact same name
+and type.
+
+## Handling VBO's
+
+```cpp
+// If you want to completely clear and refill a VBO use glBufferData(),
+// just like we did before.
+// ...
+// There are two mains ways to update a subset of a VBO's data.
+// To update a VBO with existing data
+std::vector<float> newSubData {
+ -0.25f, 0.5f, 0.0f
+};
+glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
+glBufferSubData(GL_ARRAY_BUFFER, // target buffer
+ 0, // offset
+ sizeof(newSubData[0]) * newSubData.size(), // size
+ newSubData.data()); // data
+// This would update the first three values in our vbo[0] buffer.
+// If you want to update starting at a specific location just set the second
+// parameter to that value and multiply by the types size.
+// ...
+// If you are streaming data, for example from a file,
+// it is faster to directly pass the data to the buffer.
+// Other access values are GL_READ_ONLY and GL_READ_WRITE.
+glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
+// You can static_cast<float*>() the void* to be more safe.
+void* Ptr = glMapBuffer(GL_ARRAY_BUFFER, // buffer to map
+ GL_WRITE_ONLY); // access to buffer
+memcpy(Ptr, newSubData.data(), sizeof(newSubData[0]) * newSubData.size());
+// To copy to a specific location add a destination offset to memcpy().
+glUnmapBuffer(GL_ARRAY_BUFFER);
+// ...
+// There is also a way to copy data from one buffer to another,
+// If we have two VBO's vbo[0] and vbo[1], we can copy like so
+// You can also read from GL_ARRAY_BUFFER.
+glBindBuffer(GL_COPY_READ_BUFFER, vbo[0]);
+// GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER are specifically for
+// copying buffer data.
+glBindBuffer(GL_COPY_WRITE_BUFFER, vbo[1]);
+glCopyBufferSubData(GL_COPY_READ_BUFFER, // read buffer
+ GL_COPY_WRITE_BUFFER, // write buffer
+ 0, 0, // read and write offset
+ sizeof(vbo[0]) * 3); // copy size
+// This will copy the first three elements from vbo[0] to vbo[1].
+```
+
+## Uniforms
+
+**Fragment Shader**
+
+```glsl
+// Uniforms are variables like in and out, however,
+// we can change them easily by passing new values with glUniform().
+// Lets define a time variable in our fragment shader.
+#version 330 core
+// Unlike a in/out variable we can use a uniform in every shader,
+// without the need to pass it to the next one, they are global.
+// Don't use locations already used for attributes!
+// Uniform layout locations require OpenGL 4.3!
+layout(location = 10) uniform float time;
+
+in vec3 fColor;
+
+out vec4 outColor;
+
+void main() {
+ // Create a sine wave from 0 to 1 based on the time passed to the shader.
+ float factor = (sin(time * 2) + 1) / 2;
+ outColor = vec4(fColor.r * factor, fColor.g * factor, fColor.b * factor, 1.0);
+}
+```
+
+Back to our source code.
+
+```cpp
+// If we haven't set the layout location, we can ask for it.
+GLint timeLocation = glGetUniformLocation(program, "time");
+// ...
+// Also we should define a Timer counting the current time.
+sf::Clock clock{ };
+// In out render loop we can now update the uniform every frame.
+ // ...
+ window.display();
+ glUniform1f(10, // location
+ clock.getElapsedTime().asSeconds()); // data
+}
+// ...
+```
+
+With the time getting updated every frame the quad should now be changing from
+fully colored to pitch black.
+There are different types of glUniform() you can find simple documentation here:
+[glUniform - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml)
+
+## Indexing and IBO's
+
+Element Array Buffers or more commonly Index Buffer Objects (IBO) allow us to use the
+same vertex data again which makes drawing a lot easier and faster. here's an example:
+
+```cpp
+// Lets create a quad from two rectangles.
+// We can simply use the old vertex data from before.
+// First, we have to create the IBO.
+// The index is referring to the first declaration in the VBO.
+std::vector<unsigned int> iboData {
+ 0, 1, 2,
+ 0, 2, 3
+};
+// That's it, as you can see we could reuse 0 - the top left
+// and 2 - the bottom right.
+// Now that we have our data, we have to fill it into a buffer.
+// Note that this has to happen between the two glBindVertexArray() calls,
+// so it gets saved into the VAO.
+GLuint ibo = 0;
+glGenBufferrs(1, &ibo);
+glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
+glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(iboData[0]) * iboData.size(),
+ iboData.data(), GL_STATIC_DRAW);
+// Next in our render loop, we replace glDrawArrays() with:
+glDrawElements(GL_TRIANGLES, iboData.size(), GL_UNSINGED_INT, nullptr);
+// Remember to delete the allocated memory for the IBO.
+```
+
+You can find the current code here: [OpenGL - 2](https://pastebin.com/R3Z9ACDE).
+
+## Textures
+
+To load out texture we first need a library that loads the data, for simplicity I will be
+using SFML, however there are a lot of librarys for loading image data.
+
+```cpp
+// Lets save we have a texture called "my_tex.tga", we can load it with:
+sf::Image image;
+image.loadFromFile("my_tex.tga");
+// We have to flip the texture around the y-Axis, because OpenGL's texture
+// origin is the bottom left corner, not the top left.
+image.flipVertically();
+// After loading it we have to create a OpenGL texture.
+GLuint texture = 0;
+glGenTextures(1, &texture);
+glBindTexture(GL_TEXTURE_2D, texture);
+// Specify what happens when the coordinates are out of range.
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+// Specify the filtering if the object is very large.
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+// Load the image data to the texture.
+glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr());
+// Unbind the texture to prevent modifications.
+glBindTexture(GL_TEXTURE_2D, 0);
+// Delete the texture at the end of the application.
+// ...
+glDeleteTextures(1, &texture);
+```
+
+Ofcourse there are more texture formats than only 2D textures,
+You can find further information on parameters here:
+[glBindTexture - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTexture.xhtml)<br>
+[glTexImage2D - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml)<br>
+[glTexParameter - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml)<br>
+
+```cpp
+// With the texture created, we now have to specify the UV,
+// or in OpenGL terms ST coordinates.
+std::vector<float> texCoords {
+ // The texture coordinates have to match the triangles/quad
+ // definition.
+ 0.0f, 1.0f, // start at top-left
+ 0.0f, 0.0f, // go round counter-clockwise
+ 1.0f, 0.0f,
+ 1.0f, 1.0f // end at top-right
+};
+// Now we increase the VBO's size again just like we did for the colors.
+// ...
+GLuint vbo[3];
+glGenBuffers(3, vbo);
+// ...
+glDeleteBuffers(3, vbo);
+// ...
+// Load the texture coordinates into the new buffer.
+glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
+glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords[0]) * texCoords.size(),
+ texCoords.data(), GL_STATIC_DRAW);
+glEnableVertexAttribArray(2);
+glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+// Because the VAO does not store the texture we have to bind it before drawing.
+// ...
+glBindVertexArray(vao);
+glBindTexture(GL_TEXTURE_2D, texture);
+glDrawElements(GL_TRIANGLES, iboData.size(), GL_UNSINGED_INT, nullptr);
+// ...
+```
+
+Change the shaders to pass the data to the fragment shader.<br>
+
+**Vertex Shader**
+
+```glsl
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec3 color;
+layout(location = 2) in vec2 texCoords;
+
+out vec3 fColor;
+out vec2 fTexCoords;
+
+void main() {
+ fColor = color;
+ fTexCoords = texCoords;
+ gl_Position = vec4(position, 1.0);
+}
+```
+
+**Fragment Shader**
+
+```glsl
+#version 330 core
+// sampler2D represents our 2D texture.
+uniform sampler2D tex;
+uniform float time;
+
+in vec3 fColor;
+in vec2 fTexCoords;
+
+out vec4 outColor;
+
+void main() {
+ // texture() loads the current texure data at the specified texture coords,
+ // then we can simply multiply them by our color.
+ outColor = texture(tex, fTexCoords) * vec4(fColor, 1.0);
+}
+```
+
+You can find the current code here: [OpenGL - 3](https://pastebin.com/u3bcwM6q)
+
+## Matrix Transformation
+
+**Vertex Shader**
+
+```glsl
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec3 color;
+layout(location = 2) in vec2 texCoords;
+// Create 2 4x4 matricies, 1 for the projection matrix
+// and 1 for the model matrix.
+// Because we draw in a static scene, we don't need a view matrix.
+uniform mat4 projection;
+uniform mat4 model;
+
+out vec3 fColor;
+out vec2 fTexCoords;
+
+void main() {
+ fColor = color;
+ fTexCoords = texCoords;
+ // Multiplay the position by the model matrix and then by the
+ // projection matrix.
+ // Beware order of multiplication for matricies!
+ gl_Position = projection * model * vec4(position, 1.0);
+}
+```
+
+In our source we now need to change the vertex data, create a model- and a projection matrix.
+
+```cpp
+// The new vertex data, counter-clockwise declaration.
+std::vector<float> vertexData {
+ 0.0f, 1.0f, 0.0f, // top left
+ 0.0f, 0.0f, 0.0f, // bottom left
+ 1.0f, 0.0f, 0.0f, // bottom right
+ 1.0f, 1.0f, 0.0f // top right
+};
+// Request the location of our matricies.
+GLint projectionLocation = glGetUniformLocation(program, "projection");
+GLint modelLocation = glGetUniformLocation(program, "model");
+// Declaring the matricies.
+// Orthogonal matrix for a 1024x768 window.
+std::vector<float> projection {
+ 0.001953f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -0.002604f, 0.0f, 0.0f,
+ 0.0f, 0.0f, -1.0f, 0.0f,
+ -1.0f, 1.0f, 0.0f, 1.0f
+};
+// Model matrix translating to x 50, y 50
+// and scaling to x 200, y 200.
+std::vector<float> model {
+ 200.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 200.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 50.0f, 50.0f, 0.0f, 1.0f
+};
+// Now we can send our calculated matricies to the program.
+glUseProgram(program);
+glUniformMatrix4fv(projectionLocation, // location
+ 1, // count
+ GL_FALSE, // transpose the matrix
+ projection.data()); // data
+glUniformMatrix4fv(modelLocation, 1, GL_FALSE, model.data());
+glUseProgram(0);
+// The glUniform*() calls have to be done, while the program is bound.
+```
+
+The application should now display the texture at the defined position and size.<br>
+You can find the current code here: [OpenGL - 4](https://pastebin.com/9ahpFLkY)
+
+```cpp
+// There are many math librarys for OpenGL, which create
+// matricies and vectors, the most used in C++ is glm (OpenGL Mathematics).
+// Its a header only library.
+// The same code using glm would look like:
+glm::mat4 projection{ glm::ortho(0.0f, 1024.0f, 768.0f, 0.0f) };
+glUniformMatrix4fv(projectionLocation, 1, GL_FALSE,
+ glm::value_ptr(projection));
+// Initialise the model matrix to the identity matrix, otherwise every
+// multiplication would be 0.
+glm::mat4 model{ 1.0f };
+model = glm::translate(model, glm::vec3{ 50.0f, 50.0f, 0.0f });
+model = glm::scale(model, glm::vec3{ 200.0f, 200.0f, 0.0f });
+glUniformMatrix4fv(modelLocation, 1, GL_FALSE,
+ glm::value_ptr(model));
+```
+
+## Geometry Shader
+
+Gemoetry shaders were introduced in OpenGL 3.2, they can produce vertices
+that are send to the rasterizer. They can also change the primitive type e.g.
+they can take a point as an input and output other primitives.
+Geometry shaders are inbetween the vertex and the fragment shader.
+
+**Vertex Shader**
+
+```glsl
+#version 330 core
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec3 color;
+// Create an output interface block passed to the next shadaer stage.
+// Interface blocks can be used to structure data passed between shaders.
+out VS_OUT {
+ vec3 color;
+} vs_out;
+
+void main() {
+ vs_out.color = color
+ gl_Position = vec4(position, 1.0);
+}
+```
+
+**Geometry Shader**
+
+```glsl
+#version 330 core
+// The geometry shader takes in points.
+layout(points) in;
+// It outputs a triangle every 3 vertices emitted.
+layout(triangle_strip, max_vertices = 3) out;
+// VS_OUT becomes an input variable in the geometry shader.
+// Every input to the geometry shader in treated as an array.
+in VS_OUT {
+ vec3 color;
+} gs_in[];
+// Output color for the fragment shader.
+// You can also simply define color as 'out vec3 color',
+// If you don't want to use interface blocks.
+out GS_OUT {
+ vec3 color;
+} gs_out;
+
+void main() {
+ // Each emit calls the fragment shader, so we set a color for each vertex.
+ gs_out.color = mix(gs_in[0].color, vec3(1.0, 0.0, 0.0), 0.5);
+ // Move 0.5 units to the left and emit the new vertex.
+ // gl_in[] is the current vertex from the vertex shader, here we only
+ // use 0, because we are receiving points.
+ gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, 0.0);
+ EmitVertex();
+ gs_out.color = mix(gs_in[0].color, vec3(0.0, 1.0, 0.0), 0.5);
+ // Move 0.5 units to the right and emit the new vertex.
+ gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.0, 0.0, 0.0);
+ EmitVertex();
+ gs_out.color = mix(gs_in[0].color, vec3(0.0, 0.0, 1.0), 0.5);
+ // Move 0.5 units up and emit the new vertex.
+ gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.75, 0.0, 0.0);
+ EmitVertex();
+ EndPrimitive();
+}
+```
+
+**Fragment Shader**
+
+```glsl
+in GS_OUT {
+ vec3 color;
+} fs_in;
+
+out vec4 outColor;
+
+void main() {
+ outColor = vec4(fs_in.color, 1.0);
+}
+```
+
+If you now store a single point with a single color in a VBO and draw them,
+you should see a triangle, with your color mixed half way between
+red, green and blue on each vertex.
+
+
+## Quotes
+<sup>[1]</sup>[OpenGL - Wikipedia](https://en.wikipedia.org/wiki/OpenGL)
+
+## Books
+
+- OpenGL Superbible - Fifth Edition (covering OpenGL 3.3)
+- OpenGL Programming Guide - Eighth Edition (covering OpenGL 4.3)
diff --git a/p5.html.markdown b/p5.html.markdown
index 61fe0705..be22d3e5 100644
--- a/p5.html.markdown
+++ b/p5.html.markdown
@@ -2,54 +2,52 @@
category: tool
tool: p5
contributors:
- - ["Amey Bhavsar", "https://github.com/ameybhavsar24"]
+ - ['Amey Bhavsar', 'https://github.com/ameybhavsar24']
+ - ['Claudio Busatto', 'https://github.com/cjcbusatto']
filename: p5.js
---
+
p5.js is a JavaScript library that starts with the original goal of [Processing](http://processing.org"), to make coding accessible for artists, designers, educators, and beginners, and reinterprets this for today's web.
Since p5 is a JavaScript library, you should learn [Javascript](https://learnxinyminutes.com/docs/javascript/) first.
+
```js
///////////////////////////////////
// p5.js has two important functions to work with.
function setup() {
-// the setup function gets executed just once when the window is loaded
+ // the setup function gets executed just once when the window is loaded
}
function draw() {
-// the draw function gets called every single frame. This means that for a frameRate(30) it would get called 30 times per second.
+ // the draw function gets called every single frame. This means that for a frameRate(30) it would get called 30 times per second.
}
// the following code explains all features
function setup() {
-
-createCanvas(640, 480); // creates a new canvas element with 640px as width as 480px as height
-background(128); // changes the background color of the canvas, can accept rgb values like background(100,200,20) else grayscale values like background(0) = black or background(255) = white
-
+ createCanvas(640, 480); // creates a new canvas element with 640px as width as 480px as height
+ background(128); // changes the background color of the canvas, can accept rgb values like background(100,200,20) else grayscale values like background(0) = black or background(255) = white
}
function draw() {
+ ellipse(10, 10, 50, 50); // creates a ellipse at the 10px from the left and 10px from the top with width adn height as 50 each, so its basically a circle.
+ //remember in p5.js the origin is at the top-left corner of the canvas
-ellipse(10,10, 50,50); // creates a ellipse at the 10px from the left and 10px from the top with width adn height as 50 each, so its basically a cirle.
-//remember in p5.js the origin is at the top-left corner of the canvas
-
- if (mouseIsPressed) {
- // mouseIsPressed is a boolean variable that changes to true if the mouse buttton is pressed down at that instant
-
- fill(0); // fill refers to the innner color or filling color of whatever shape you are going to draw next
-
- } else {
-
- fill(255); // you can give in rgb values like fill(72, 240, 80) to get colors, else a single values determines the grayscale where fill(255) stands for #FFF(white) and fill(0) stands for #000(black)
-
- }
-
- ellipse(mouseX, mouseY, 80, 80);
- // mouseX is the x-coordinate of the mouse's current position and mouseY is the y-coordinate of the mouse's current position
-
- // the above code creates a circle wherever mouse's current position and fills it either black or white based on the mouseIsPressed
-}
+ if (mouseIsPressed) {
+ // mouseIsPressed is a boolean variable that changes to true if the mouse buttton is pressed down at that instant
+ fill(0); // fill refers to the innner color or filling color of whatever shape you are going to draw next
+ } else {
+ fill(255); // you can give in rgb values like fill(72, 240, 80) to get colors, else a single values determines the grayscale where fill(255) stands for #FFF(white) and fill(0) stands for #000(black)
+ }
+
+ ellipse(mouseX, mouseY, 80, 80);
+ // mouseX is the x-coordinate of the mouse's current position and mouseY is the y-coordinate of the mouse's current position
+
+ // the above code creates a circle wherever mouse's current position and fills it either black or white based on the mouseIsPressed
+}
```
+
## Further Reading
-* [p5.js | get started](http://p5js.org/get-started/) The official documentation
-* [Code! Programming for Beginners with p5.js - YouTube](https://www.youtube.com/watch?v=yPWkPOfnGsw&vl=en) Introduction and Coding challenges using Processing and p5.js by Coding Train
+
+- [p5.js | get started](http://p5js.org/get-started/) The official documentation
+- [Code! Programming for Beginners with p5.js - YouTube](https://www.youtube.com/watch?v=yPWkPOfnGsw&vl=en) Introduction and Coding challenges using Processing and p5.js by Coding Train
diff --git a/pcre.html.markdown b/pcre.html.markdown
index 3e877a35..9e091721 100644
--- a/pcre.html.markdown
+++ b/pcre.html.markdown
@@ -3,16 +3,18 @@ language: PCRE
filename: pcre.txt
contributors:
- ["Sachin Divekar", "http://github.com/ssd532"]
-
+
---
-A regular expression (regex or regexp for short) is a special text string for describing a search pattern. e.g. to extract domain name from a string we can say `/^[a-z]+:/` and it will match `http:` from `http://github.com/`.
+A regular expression (regex or regexp for short) is a special text string for describing a search pattern. e.g. to extract domain name from a string we can say `/^[a-z]+:/` and it will match `http:` from `http://github.com/`.
PCRE (Perl Compatible Regular Expressions) is a C library implementing regex. It was written in 1997 when Perl was the de-facto choice for complex text processing tasks. The syntax for patterns used in PCRE closely resembles Perl. PCRE syntax is being used in many big projects including PHP, Apache, R to name a few.
There are two different sets of metacharacters:
+
* Those that are recognized anywhere in the pattern except within square brackets
+
```
\ general escape character with several uses
^ assert start of string (or line, in multiline mode)
@@ -32,18 +34,19 @@ There are two different sets of metacharacters:
```
* Those that are recognized within square brackets. Outside square brackets. They are also called as character classes.
-
+
```
-
+
\ general escape character
^ negate the class, but only if the first character
- indicates character range
[ POSIX character class (only if followed by POSIX syntax)
] terminates the character class
-
-```
-PCRE provides some generic character types, also called as character classes.
+```
+
+PCRE provides some generic character types, also called as character classes.
+
```
\d any decimal digit
\D any character that is not a decimal digit
@@ -59,7 +62,13 @@ PCRE provides some generic character types, also called as character classes.
## Examples
-We will test our examples on following string `66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"`. It is a standard Apache access log.
+We will test our examples on the following string:
+
+```
+66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1"
+```
+
+ It is a standard Apache access log.
| Regex | Result | Comment |
| :---- | :-------------- | :------ |
diff --git a/perl.html.markdown b/perl.html.markdown
index 17a538e3..08001ab0 100644
--- a/perl.html.markdown
+++ b/perl.html.markdown
@@ -152,7 +152,7 @@ while (condition) {
...
}
-
+my $max = 5;
# for loops and iteration
for my $i (0 .. $max) {
print "index is $i";
diff --git a/perl6.html.markdown b/perl6.html.markdown
deleted file mode 100644
index cb64b646..00000000
--- a/perl6.html.markdown
+++ /dev/null
@@ -1,1966 +0,0 @@
----
-category: language
-language: perl6
-filename: learnperl6.p6
-contributors:
- - ["vendethiel", "http://github.com/vendethiel"]
- - ["Samantha McVey", "https://cry.nu"]
----
-
-Perl 6 is a highly capable, feature-rich programming language made for at
-least the next hundred years.
-
-The primary Perl 6 compiler is called [Rakudo](http://rakudo.org), which runs on
-the JVM and [the MoarVM](http://moarvm.com).
-
-Meta-note: double pound signs (`##`) are used to indicate paragraphs,
-while single pound signs (`#`) indicate notes.
-
-`#=>` represents the output of a command.
-
-```perl6
-# Single line comments start with a pound sign.
-
-#`( Multiline comments use #` and a quoting construct.
- (), [], {}, 「」, etc, will work.
-)
-
-# Use the same syntax for multiline comments to embed comments.
-for #`(each element in) @array {
- put #`(or print element) $_ #`(with newline);
-}
-```
-
-## Variables
-
-```perl6
-## In Perl 6, you declare a lexical variable using the `my` keyword:
-my $variable;
-## Perl 6 has 3 basic types of variables: scalars, arrays, and hashes.
-```
-
-### Scalars
-
-```perl6
-# Scalars represent a single value. They start with the `$` sigil:
-my $str = 'String';
-
-# Double quotes allow for interpolation (which we'll see later):
-my $str2 = "String";
-
-## Variable names can contain but not end with simple quotes and dashes,
-## and can contain (and end with) underscores:
-my $person's-belongings = 'towel'; # this works!
-
-my $bool = True; # `True` and `False` are Perl 6's boolean values.
-my $inverse = !$bool; # Invert a bool with the prefix `!` operator.
-my $forced-bool = so $str; # And you can use the prefix `so` operator
-$forced-bool = ?$str; # to turn its operand into a Bool. Or use `?`.
-```
-
-### Arrays and Lists
-
-```perl6
-## Arrays represent multiple values. An array variable starts with the `@`
-## sigil. Unlike lists, from which arrays inherit, arrays are mutable.
-
-my @array = 'a', 'b', 'c';
-# equivalent to:
-my @letters = <a b c>; # array of words, delimited by space.
- # Similar to perl5's qw, or Ruby's %w.
-@array = 1, 2, 3;
-
-say @array[2]; # Array indices start at 0. Here the third element
- # is being accessed.
-
-say "Interpolate an array using []: @array[]";
-#=> Interpolate an array using []: 1 2 3
-
-@array[0] = -1; # Assigning a new value to an array index
-@array[0, 1] = 5, 6; # Assigning multiple values
-
-my @keys = 0, 2;
-@array[@keys] = @letters; # Assignment using an array containing index values
-say @array; #=> a 6 b
-```
-
-### Hashes, or key-value Pairs.
-
-```perl6
-## Hashes are pairs of keys and values. You can construct a `Pair` object
-## using the syntax `Key => Value`. Hash tables are very fast for lookup,
-## and are stored unordered. Keep in mind that keys get "flattened" in hash
-## context, and any duplicated keys are deduplicated.
-my %hash = 'a' => 1, 'b' => 2;
-
-%hash = a => 1, # keys get auto-quoted when => (fat comma) is used.
- b => 2, # Trailing commas are okay.
-;
-
-## Even though hashes are internally stored differently than arrays,
-## Perl 6 allows you to easily create a hash from an even numbered array:
-%hash = <key1 value1 key2 value2>; # Or:
-%hash = "key1", "value1", "key2", "value2";
-
-%hash = key1 => 'value1', key2 => 'value2'; # same result as above
-
-## You can also use the "colon pair" syntax. This syntax is especially
-## handy for named parameters that you'll see later.
-%hash = :w(1), # equivalent to `w => 1`
- :truey, # equivalent to `:truey(True)` or `truey => True`
- :!falsey, # equivalent to `:falsey(False)` or `falsey => False`
-;
-## The :truey and :!falsey constructs are known as the
-## `True` and `False` shortcuts respectively.
-
-say %hash{'key1'}; # You can use {} to get the value from a key.
-say %hash<key2>; # If it's a string without spaces, you can actually use
- # <> (quote-words operator). `{key1}` doesn't work,
- # as Perl6 doesn't have barewords.
-```
-
-## Subs
-
-```perl6
-## Subroutines, or functions as most other languages call them, are
-## created with the `sub` keyword.
-sub say-hello { say "Hello, world" }
-
-## You can provide (typed) arguments. If specified, the type will be checked
-## at compile-time if possible, otherwise at runtime.
-sub say-hello-to( Str $name ) {
- say "Hello, $name !";
-}
-
-## A sub returns the last value of the block. Similarly, the semicolon in
-## the last can be omitted.
-sub return-value { 5 }
-say return-value; # prints 5
-
-sub return-empty { }
-say return-empty; # prints Nil
-
-## Some control flow structures produce a value, like `if`:
-sub return-if {
- if True { "Truthy" }
-}
-say return-if; # prints Truthy
-
-## Some don't, like `for`:
-sub return-for {
- for 1, 2, 3 { 'Hi' }
-}
-say return-for; # prints Nil
-
-## Positional arguments are required by default. To make them optional, use
-## the `?` after the parameters' names.
-sub with-optional( $arg? ) {
- # This sub returns `(Any)` (Perl's null-like value) if
- # no argument is passed. Otherwise, it returns its argument.
- $arg;
-}
-with-optional; # returns Any
-with-optional(); # returns Any
-with-optional(1); # returns 1
-
-## You can also give them a default value when they're not passed.
-## Required parameters must come before optional ones.
-sub greeting( $name, $type = "Hello" ) {
- say "$type, $name!";
-}
-
-greeting("Althea"); #=> Hello, Althea!
-greeting("Arthur", "Good morning"); #=> Good morning, Arthur!
-
-## You can also, by using a syntax akin to the one of hashes
-## (yay unified syntax !), pass *named* arguments to a `sub`. They're
-## optional, and will default to "Any".
-sub with-named( $normal-arg, :$named ) {
- say $normal-arg + $named;
-}
-with-named(1, named => 6); #=> 7
-
-## There's one gotcha to be aware of, here: If you quote your key, Perl 6
-## won't be able to see it at compile time, and you'll have a single `Pair`
-## object as a positional parameter, which means
-## `with-named(1, 'named' => 6);` fails.
-
-with-named(2, :named(5)); #=> 7
-
-## To make a named argument mandatory, you can append `!` to the parameter,
-## which is the inverse of `?`:
-sub with-mandatory-named( :$str! ) {
- say "$str!";
-}
-with-mandatory-named(str => "My String"); #=> My String!
-with-mandatory-named; # runtime error:"Required named parameter not passed"
-with-mandatory-named(3);# runtime error:"Too many positional parameters passed"
-
-## If a sub takes a named boolean argument...
-sub takes-a-bool( $name, :$bool ) {
- say "$name takes $bool";
-}
-## ... you can use the same "short boolean" hash syntax:
-takes-a-bool('config', :bool); #=> config takes True
-takes-a-bool('config', :!bool); #=> config takes False
-
-## You can also provide your named arguments with default values:
-sub named-def( :$def = 5 ) {
- say $def;
-}
-named-def; #=> 5
-named-def(def => 15); #=> 15
-
-## Since you can omit parenthesis to call a function with no arguments,
-## you need `&` in the name to store `say-hello` in a variable. This means
-## `&say-hello` is a code object and not a subroutine call.
-my &s = &say-hello;
-my &other-s = sub { say "Anonymous function!" }
-
-## A sub can have a "slurpy" parameter, or "doesn't-matter-how-many". For
-## this, you must use `*@` (slurpy) which will "take everything else". You can
-## have as many parameters *before* a slurpy one, but not *after*.
-sub as-many($head, *@rest) {
- say @rest.join(' / ') ~ " !";
-}
-say as-many('Happy', 'Happy', 'Birthday');#=> Happy / Birthday !
- # Note that the splat (the *) did not
- # consume the parameter before it.
-
-## You can call a function with an array using the "argument list flattening"
-## operator `|` (it's not actually the only role of this operator,
-## but it's one of them).
-sub concat3($a, $b, $c) {
- say "$a, $b, $c";
-}
-concat3(|@array); #=> a, b, c
- # `@array` got "flattened" as a part of the argument list
-```
-
-## Containers
-
-```perl6
-## In Perl 6, values are actually stored in "containers". The assignment
-## operator asks the container on the left to store the value on its right.
-## When passed around, containers are marked as immutable which means that,
-## in a function, you'll get an error if you try to mutate one of your
-## arguments. If you really need to, you can ask for a mutable container by
-## using the `is rw` trait:
-sub mutate( $n is rw ) {
- $n++;
-}
-
-my $m = 42;
-mutate $m; #=> 43
-say $m; #=> 43
-
-## This works because we are passing the container $m to the `mutate` sub.
-## If we try to just pass a number instead of passing a variable it won't work
-## because there is no container being passed and integers are immutable by
-## themselves:
-
-mutate 42; # Parameter '$n' expected a writable container, but got Int value
-
-## Similar error would be obtained, if a bound variable is passed to
-## to the subroutine:
-
-my $v := 50; # binding 50 to the variable $v
-mutate $v; # Parameter '$n' expected a writable container, but got Int value
-
-## If what you want is a copy instead, use the `is copy` trait which will
-## cause the argument to be copied and allow you to modify the argument
-## inside the routine.
-
-## A sub itself returns a container, which means it can be marked as rw:
-my $x = 42;
-sub x-store() is rw { $x }
-x-store() = 52; # in this case, the parentheses are mandatory
- # (else Perl 6 thinks `x-store` is an identifier)
-say $x; #=> 52
-```
-
-## Control Flow Structures
-
-### Conditionals
-
-```perl6
-## - `if`
-## Before talking about `if`, we need to know which values are "Truthy"
-## (represent True), and which are "Falsey" (represent False). Only these
-## values are Falsey: 0, (), {}, "", Nil, A type (like `Str` or `Int`) and
-## of course False itself. Any other value is Truthy.
-if True {
- say "It's true!";
-}
-
-unless False {
- say "It's not false!";
-}
-
-## As you can see, you don't need parentheses around conditions. However, you
-## do need the curly braces around the "body" block. For example,
-## `if (true) say;` doesn't work.
-
-## You can also use their statement modifier (postfix) versions:
-say "Quite truthy" if True; #=> Quite truthy
-say "Quite falsey" unless False; #=> Quite falsey
-
-## - Ternary operator, "x ?? y !! z"
-## This returns $value-if-true if the condition is true and $value-if-false
-## if it is false.
-## my $result = condition ?? $value-if-true !! $value-if-false;
-
-my $age = 30;
-say $age > 18 ?? "You are an adult" !! "You are under 18";
-#=> You are an adult
-```
-
-### given/when, or Perl 6's switch construct
-
-```perl6
-## `given...when` looks like other languages' `switch`, but is much more
-## powerful thanks to smart matching and Perl 6's "topic variable", $_.
-##
-## The topic variable $_ contains the default argument of a block, a loop's
-## current iteration (unless explicitly named), etc.
-##
-## `given` simply puts its argument into `$_` (like a block would do),
-## and `when` compares it using the "smart matching" (`~~`) operator.
-##
-## Since other Perl 6 constructs use this variable (as said before, like `for`,
-## blocks, etc), this means the powerful `when` is not only applicable along
-## with a `given`, but instead anywhere a `$_` exists.
-
-given "foo bar" {
- say $_; #=> foo bar
- when /foo/ { # Don't worry about smart matching yet. Just know
- say "Yay !"; # `when` uses it. This is equivalent to `if $_ ~~ /foo/`.
-
- }
- when $_.chars > 50 { # smart matching anything with True is True,
- # i.e. (`$a ~~ True`)
- # so you can also put "normal" conditionals.
- # This `when` is equivalent to this `if`:
- # `if $_ ~~ ($_.chars > 50) {...}`
- # which means: `if $_.chars > 50 {...}`
- say "Quite a long string !";
- }
- default { # same as `when *` (using the Whatever Star)
- say "Something else"
- }
-}
-```
-
-### Looping constructs
-
-```perl6
-## - `loop` is an infinite loop if you don't pass it arguments, but can also
-## be a C-style `for` loop:
-loop {
- say "This is an infinite loop !";
- last; # last breaks out of the loop, like
- # the `break` keyword in other languages
-}
-
-loop (my $i = 0; $i < 5; $i++) {
- next if $i == 3; # `next` skips to the next iteration, like `continue`
- # in other languages. Note that you can also use postfix
- # conditionals, loops, etc.
- say "This is a C-style for loop!";
-}
-
-## - `for` - Iterating through an array
-
-my @array = 1, 2, 6, 7, 3;
-
-## Accessing the array's elements with the topic variable $_.
-for @array {
- say "I've got $_ !";
-}
-
-## Accessing the array's elements with a "pointy block", `->`.
-## Here each element is read-only.
-for @array -> $variable {
- say "I've got $variable !";
-}
-
-## Accessing the array's elements with a "doubly pointy block", `<->`.
-## Here each element is read-write so mutating `$variable` mutates
-## that element in the array.
-for @array <-> $variable {
- say "I've got $variable !";
-}
-
-## As we saw with given, a for loop's default "current iteration" variable
-## is `$_`. That means you can use `when` in a `for`loop just like you were
-## able to in a `given`.
-for @array {
- say "I've got $_";
-
- .say; # This is also allowed. A dot call with no "topic" (receiver)
- # is sent to `$_` by default
- $_.say; # This is equivalent to the above statement.
-}
-
-for @array {
- # You can...
- next if $_ == 3; # Skip to the next iteration (`continue` in C-like lang.)
- redo if $_ == 4; # Re-do iteration, keeping the same topic variable (`$_`)
- last if $_ == 5; # Or break out of loop (like `break` in C-like lang.)
-}
-
-## The "pointy block" syntax isn't specific to the `for` loop. It's just a way
-## to express a block in Perl 6.
-sub long-computation { "Finding factors of large primes" }
-if long-computation() -> $result {
- say "The result is $result.";
-}
-```
-
-## Operators
-
-```perl6
-## Since Perl languages are very much operator-based languages, Perl 6
-## operators are actually just funny-looking subroutines, in syntactic
-## categories, like infix:<+> (addition) or prefix:<!> (bool not).
-
-## The categories are:
-## - "prefix": before (like `!` in `!True`).
-## - "postfix": after (like `++` in `$a++`).
-## - "infix": in between (like `*` in `4 * 3`).
-## - "circumfix": around (like `[`-`]` in `[1, 2]`).
-## - "post-circumfix": around, after another term (like `{`-`}` in
-## `%hash{'key'}`)
-
-## The associativity and precedence list are explained below.
-
-## Alright, you're set to go!
-
-## Equality Checking
-##------------------
-
-## - `==` is numeric comparison
-3 == 4; #=> False
-3 != 4; #=> True
-
-## - `eq` is string comparison
-'a' eq 'b'; #=> False
-'a' ne 'b'; #=> True, not equal
-'a' !eq 'b'; #=> True, same as above
-
-## - `eqv` is canonical equivalence (or "deep equality")
-(1, 2) eqv (1, 3); #=> False
-(1, 2) eqv (1, 2); #=> True
-Int === Int #=> True
-
-## - `~~` is the smart match operator
-## Aliases the left hand side to $_ and then evaluates the right hand side.
-## Here are some common comparison semantics:
-
-## String or numeric equality
-'Foo' ~~ 'Foo'; # True if strings are equal.
-12.5 ~~ 12.50; # True if numbers are equal.
-
-## Regex - For matching a regular expression against the left side.
-## Returns a `Match` object, which evaluates as True if regexp matches.
-
-my $obj = 'abc' ~~ /a/;
-say $obj; #=> 「a」
-say $obj.WHAT; #=> (Match)
-
-## Hashes
-'key' ~~ %hash; # True if key exists in hash.
-
-## Type - Checks if left side "is of type" (can check superclasses and
-## roles).
-say 1 ~~ Int; #=> True
-
-## Smart-matching against a boolean always returns that boolean
-## (and will warn).
-say 1 ~~ True; #=> True
-say False ~~ True; #=> True
-
-## General syntax is `$arg ~~ &bool-returning-function;`. For a complete list
-## of combinations, use this table:
-## http://perlcabal.org/syn/S03.html#Smart_matching
-
-## Of course, you also use `<`, `<=`, `>`, `>=` for numeric comparison.
-## Their string equivalent are also available: `lt`, `le`, `gt`, `ge`.
-3 > 4; # False
-3 >= 4; # False
-3 < 4; # True
-3 <= 4; # True
-'a' gt 'b'; # False
-'a' ge 'b'; # False
-'a' lt 'b'; # True
-'a' le 'b'; # True
-
-
-## Range constructor
-##------------------
-3 .. 7; # 3 to 7, both included
-3 ..^ 7; # 3 to 7, exclude right endpoint.
-3 ^.. 7; # 3 to 7, exclude left endpoint. Same as `4..7`.
-3 ^..^ 7; # 3 to 7, exclude both endpoints. Same as `4..6`.
-
-## This also works as a shortcut for `0..^N`:
-^10; # means 0..^10
-
-## This also allows us to demonstrate that Perl 6 has lazy/infinite arrays,
-## using the Whatever Star:
-my @array = 1..*; # 1 to Infinite! Equivalent to `1..Inf`.
-say @array[^10]; # You can pass ranges as subscripts and it'll return
- # an array of results. This will print
- # "1 2 3 4 5 6 7 8 9 10" (and not run out of memory!)
-
-## Note: when reading an infinite list, Perl 6 will "reify" the elements
-## it needs, then keep them in memory. They won't be calculated more than once.
-## It also will never calculate more elements that are needed.
-
-## An array subscript can also be a closure. It'll be called with the length
-## as the argument:
-say join(' ', @array[15..*]); #=> 15 16 17 18 19
-## which is equivalent to:
-say join(' ', @array[-> $n { 15..$n }]);
-
-## Note: if you try to do either of those with an infinite array,
-## you'll trigger an infinite loop (your program won't finish).
-
-## You can use that in most places you'd expect, even when assigning to
-## an array:
-my @numbers = ^20;
-
-## Here the numbers increase by 6, like an arithmetic sequence; more on the
-## sequence (`...`) operator later.
-my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99;
-@numbers[5..*] = 3, 9 ... *; # even though the sequence is infinite,
- # only the 15 needed values will be calculated.
-say @numbers; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87
- # (only 20 values)
-
-## and (&&), or (||)
-##------------------
-3 && 4; # 4, which is Truthy. Calls `.Bool` on both 3 and 4 and gets `True`
- # so it returns 4 since both are `True`.
-3 && 0; # 0
-0 && 4; # 0
-
-0 || False; # False. Calls `.Bool` on `0` and `False` which are both `False`
- # so it retusns `False` since both are `False`.
-
-## Short-circuit (and tight) versions of the above
-## Return the first argument that evaluates to False, or the last argument.
-
-my ( $a, $b, $c ) = 1, 0, 2;
-$a && $b && $c; # Returns 0, the first False value
-
-## || Returns the first argument that evaluates to True
-$b || $a; # 1
-
-## And because you're going to want them, you also have compound assignment
-## operators:
-$a *= 2; # multiply and assignment. Equivalent to $a = $a * 2;
-$b %%= 5; # divisible by and assignment. Equivalent to $b = $b %% 2;
-$c div= 3; # return divisor and assignment. Equivalent to $c = $c div 3;
-$d mod= 4; # return remainder and assignment. Equivalent to $d = $d mod 4;
-@array .= sort; # calls the `sort` method and assigns the result back
-```
-
-## More on subs!
-
-```perl6
-## As we said before, Perl 6 has *really* powerful subs. We're going
-## to see a few more key concepts that make them better than in any
-## other language :-).
-```
-
-### Unpacking!
-
-```perl6
-## Unpacking is the ability to "extract" arrays and keys
-## (AKA "destructuring"). It'll work in `my`s and in parameter lists.
-my ($f, $g) = 1, 2;
-say $f; #=> 1
-my ($, $, $h) = 1, 2, 3; # keep the non-interesting values anonymous (`$`)
-say $h; #=> 3
-
-my ($head, *@tail) = 1, 2, 3; # Yes, it's the same as with "slurpy subs"
-my (*@small) = 1;
-
-sub unpack_array( @array [$fst, $snd] ) {
- say "My first is $fst, my second is $snd! All in all, I'm @array[].";
- # (^ remember the `[]` to interpolate the array)
-}
-unpack_array(@tail); #=> My first is 2, my second is 3! All in all, I'm 2 3.
-
-
-## If you're not using the array itself, you can also keep it anonymous,
-## much like a scalar:
-sub first-of-array( @ [$fst] ) { $fst }
-first-of-array(@small); #=> 1
-first-of-array(@tail); # Error: "Too many positional parameters passed"
- # (which means the array is too big).
-
-## You can also use a slurp...
-sub slurp-in-array(@ [$fst, *@rest]) { # You could keep `*@rest` anonymous
- say $fst + @rest.elems; # `.elems` returns a list's length.
- # Here, `@rest` is `(3,)`, since `$fst`
- # holds the `2`.
-}
-slurp-in-array(@tail); #=> 3
-
-## You could even extract on a slurpy (but it's pretty useless ;-).)
-sub fst(*@ [$fst]) { # or simply: `sub fst($fst) { ... }`
- say $fst;
-}
-fst(1); #=> 1
-fst(1, 2); # errors with "Too many positional parameters passed"
-
-## You can also destructure hashes (and classes, which you'll learn about
-## later). The syntax is basically the same as
-## `%hash-name (:key($variable-to-store-value-in))`.
-## The hash can stay anonymous if you only need the values you extracted.
-sub key-of( % (:value($val), :qua($qua)) ) {
- say "Got val $val, $qua times.";
-}
-
-## Then call it with a hash. You need to keep the curly braces for it to be a
-## hash or use `%()` instead to indicate a hash is being passed.
-key-of({value => 'foo', qua => 1}); #=> Got val foo, 1 times.
-key-of(%(value => 'foo', qua => 1)); #=> Got val foo, 1 times.
-#key-of(%hash); # the same (for an equivalent `%hash`)
-
-## The last expression of a sub is returned automatically (though you may
-## indicate explicitly by using the `return` keyword, of course):
-sub next-index( $n ) {
- $n + 1;
-}
-my $new-n = next-index(3); # $new-n is now 4
-
-## This is true for everything, except for the looping constructs (due to
-## performance reasons): there's no reason to build a list if we're just going to
-## discard all the results. If you still want to build one, you can use the
-## `do` statement prefix or the `gather` prefix, which we'll see later:
-
-sub list-of( $n ) {
- do for ^$n { # note the range-to prefix operator `^` (`0..^N`)
- $_ # current loop iteration known as the "topic" variable
- }
-}
-my @list3 = list-of(3); #=> (0, 1, 2)
-```
-
-### lambdas (or anonymous subroutines)
-
-```perl6
-## You can create a lambda with `-> {}` ("pointy block") ,
-## `{}` ("block") or `sub {}`.
-
-my &lambda1 = -> $argument {
- "The argument passed to this lambda is $argument"
-}
-
-my &lambda2 = {
- "The argument passed to this lambda is $_"
-}
-
-my &lambda3 = sub ($argument) {
- "The argument passed to this lambda is $argument"
-}
-
-## `-> {}` and `{}` are pretty much the same thing, except that the former can
-## take arguments, and that the latter can be mistaken as a hash by the parser.
-
-## We can, for example, add 3 to each value of an array using the
-## `map` function with a lambda:
-my @arrayplus3 = map({ $_ + 3 }, @array); # $_ is the implicit argument
-
-## A sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`):
-## A block doesn't have a "function context" (though it can have arguments),
-## which means that if you return from it, you're going to return from the
-## parent function. Compare:
-sub is-in( @array, $elem ) {
- # this will `return` out of the `is-in` sub once the condition evaluated
- ## to True, the loop won't be run anymore.
- map({ return True if $_ == $elem }, @array);
-}
-## with:
-sub truthy-array( @array ) {
- # this will produce an array of `True` and `False`:
- # (you can also say `anon sub` for "anonymous subroutine")
- map(sub ($i) { if $i { return True } else { return False } }, @array);
- # ^ the `return` only returns from the anonymous `sub`
-}
-
-## The `anon` declarator can be used to create an anonymous sub from a
-## regular subroutine. The regular sub knows its name but its symbol is
-## prevented from getting installed in the lexical scope, the method table
-## and everywhere else.
-
-my $anon-sum = anon sub summation(*@a) { [+] *@a }
-say $anon-sum.name; #=> summation
-say $anon-sum(2, 3, 5); #=> 10
-#say summation; #=> Error: Undeclared routine: ...
-
-## You can also use the "whatever star" to create an anonymous subroutine.
-## (it'll stop at the furthest operator in the current expression)
-my @arrayplus3 = map(*+3, @array); # `*+3` is the same as `{ $_ + 3 }`
-my @arrayplus3 = map(*+*+3, @array); # Same as `-> $a, $b { $a + $b + 3 }`
- # also `sub ($a, $b) { $a + $b + 3 }`
-say (*/2)(4); #=> 2
- # Immediately execute the function Whatever created.
-say ((*+3)/5)(5); #=> 1.6
- # It works even in parens!
-
-## But if you need to have more than one argument (`$_`) in a block (without
-## wanting to resort to `-> {}`), you can also use the implicit argument
-## syntax, `$^`:
-map({ $^a + $^b + 3 }, @array);
-# which is equivalent to the following which uses a `sub`:
-map(sub ($a, $b) { $a + $b + 3 }, @array);
-
-## The parameters `$^a`, `$^b`, etc. are known as placeholder parameters or
-## self-declared positional parameters. They're sorted lexicographically so
-## `{ $^b / $^a }` is equivalent `-> $a, $b { $b / $a }`.
-```
-
-### About types...
-
-```perl6
-## Perl 6 is gradually typed. This means you can specify the type of your
-## variables/arguments/return types, or you can omit the type annotations in
-## in which case they'll default to `Any`. Obviously you get access to a few
-## base types, like `Int` and `Str`. The constructs for declaring types are
-## "subset", "class", "role", etc. which you'll see later.
-
-## For now, let us examine "subset" which is a "sub-type" with additional
-## checks. For example, "a very big integer is an Int that's greater than 500".
-## You can specify the type you're subtyping (by default, `Any`), and add
-## additional checks with the `where` clause:
-subset VeryBigInteger of Int where * > 500;
-## Or the set of the whole numbers:
-subset WholeNumber of Int where * >= 0;
-```
-
-### Multiple Dispatch
-
-```perl6
-## Perl 6 can decide which variant of a `sub` to call based on the type of the
-## arguments, or on arbitrary preconditions, like with a type or `where`:
-
-## with types:
-multi sub sayit( Int $n ) { # note the `multi` keyword here
- say "Number: $n";
-}
-multi sayit( Str $s ) { # a multi is a `sub` by default
- say "String: $s";
-}
-sayit("foo"); #=> "String: foo"
-sayit(25); #=> "Number: 25"
-sayit(True); # fails at *compile time* with "calling 'sayit' will never
- # work with arguments of types ..."
-
-## with arbitrary preconditions (remember subsets?):
-multi is-big(Int $n where * > 50) { "Yes!" } # using a closure
-multi is-big(Int $n where {$_ > 50}) { "Yes!" } # similar to above
-multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching
- # (could use a regexp, etc)
-multi is-big(Int $) { "No" }
-
-subset Even of Int where * %% 2;
-multi odd-or-even(Even) { "Even" } # The main case using the type.
- # We don't name the argument.
-multi odd-or-even($) { "Odd" } # "everthing else" hence the $ variable
-
-## You can even dispatch based on the presence of positional and
-## named arguments:
-multi with-or-without-you($with) {
- say "I wish I could but I can't";
-}
-multi with-or-without-you(:$with) {
- say "I can live! Actually, I can't.";
-}
-multi with-or-without-you {
- say "Definitely can't live.";
-}
-
-## This is very, very useful for many purposes, like `MAIN` subs (covered
-## later), and even the language itself uses it in several places.
-##
-## - `is`, for example, is actually a `multi sub` named `trait_mod:<is>`,
-## and it works off that.
-## - `is rw`, is simply a dispatch to a function with this signature:
-## sub trait_mod:<is>(Routine $r, :$rw!) {}
-##
-## (commented out because running this would be a terrible idea!)
-```
-
-## Scoping
-
-```perl6
-## In Perl 6, unlike many scripting languages, (such as Python, Ruby, PHP),
-## you must declare your variables before using them. The `my` declarator
-## you have learned uses "lexical scoping". There are a few other declarators,
-## (`our`, `state`, ..., ) which we'll see later. This is called
-## "lexical scoping", where in inner blocks, you can access variables from
-## outer blocks.
-my $file_scoped = 'Foo';
-sub outer {
- my $outer_scoped = 'Bar';
- sub inner {
- say "$file_scoped $outer_scoped";
- }
- &inner; # return the function
-}
-outer()(); #=> 'Foo Bar'
-
-## As you can see, `$file_scoped` and `$outer_scoped` were captured.
-## But if we were to try and use `$outer_scoped` outside the `outer` sub,
-## the variable would be undefined (and you'd get a compile time error).
-```
-
-## Twigils
-
-```perl6
-## There are many special `twigils` (composed sigils) in Perl 6. Twigils
-## define the variables' scope.
-## The * and ? twigils work on standard variables:
-## * Dynamic variable
-## ? Compile-time variable
-## The ! and the . twigils are used with Perl 6's objects:
-## ! Attribute (instance attribute)
-## . Method (not really a variable)
-
-## `*` twigil: Dynamic Scope
-## These variables use the `*` twigil to mark dynamically-scoped variables.
-## Dynamically-scoped variables are looked up through the caller, not through
-## the outer scope.
-
-my $*dyn_scoped_1 = 1;
-my $*dyn_scoped_2 = 10;
-
-sub say_dyn {
- say "$*dyn_scoped_1 $*dyn_scoped_2";
-}
-
-sub call_say_dyn {
- my $*dyn_scoped_1 = 25; # Defines $*dyn_scoped_1 only for this sub.
- $*dyn_scoped_2 = 100; # Will change the value of the file scoped variable.
- say_dyn(); #=> 25 100, $*dyn_scoped 1 and 2 will be looked
- # for in the call.
- # It uses the value of $*dyn_scoped_1 from inside
- # this sub's lexical scope even though the blocks
- # aren't nested (they're call-nested).
-}
-say_dyn(); #=> 1 10
-call_say_dyn(); #=> 25 100
- # Uses $*dyn_scoped_1 as defined in call_say_dyn even though
- # we are calling it from outside.
-say_dyn(); #=> 1 100 We changed the value of $*dyn_scoped_2 in
- # call_say_dyn so now its value has changed.
-```
-
-## Object Model
-
-```perl6
-## To call a method on an object, add a dot followed by the method name:
-## `$object.method`
-
-## Classes are declared with the `class` keyword. Attributes are declared
-## with the `has` keyword, and methods declared with the `method` keyword.
-
-## Every attribute that is private uses the ! twigil. For example: `$!attr`.
-## Immutable public attributes use the `.` twigil which creates a read-only
-## method named after the attribute. In fact, declaring an attribute with `.`
-## is equivalent to declaring the same attribute with `!` and then creating
-## a read-only method with the attribute's name. However, this is done for us
-## by Perl 6 automatically. The easiest way to remember the `$.` twigil is
-## by comparing it to how methods are called.
-
-## Perl 6's object model ("SixModel") is very flexible, and allows you to
-## dynamically add methods, change semantics, etc... Unfortunately, these will
-## not all be covered here, and you should refer to:
-## https://docs.perl6.org/language/objects.html.
-
-class Human {
- has Str $.name; # `$.name` is immutable but with an accessor method.
- has Str $.bcountry; # Use `$!bplace` to modify it inside the class.
- has Str $.ccountry is rw; # This attribute can be modified from outside.
- has Int $!age = 0; # A private attribute with default value.
-
- method birthday {
- $!age += 1; # Add a year to human's age
- }
-
- method get-age {
- return $!age;
- }
-
- # This method is private to the class. Note the `!` before the
- # method's name.
- method !do-decoration {
- return "$!name was born in $!bcountry and now lives in $!ccountry."
- }
-
- # This method is public, just like `birthday` and `get-age`.
- method get-info {
- self.do-decoration; # Invoking a method on `self` inside the class.
- # Use `self!priv-method` for private method.
- # Use `self.publ-method` for public method.
- }
-};
-
-## Create a new instance of Human class with $.attrib set to 5.
-## Note: you can't set private-attribute from here (more later on).
-my $person1 = Human.new(
- name => "Jord",
- bcountry = "Iceland",
- ccountry => "Iceland"
-);
-
-say $person1.name; #=> Jord
-say $person1.bcountry; #=> Togo
-say $person1.ccountry; #=> Togo
-
-
-# $person1.bcountry = "Mali"; # This fails, because the `has $.bcountry`
- # is immutable. Jord can't change his birthplace.
-$person1.ccountry = "France"; # This works because the `$.ccountry` is mutable
- # (`is rw`). Now Jord's current country is France.
-
-# Calling methods on the instance objects.
-$person1.birthday; #=> 1
-$person1.get-info; #=> Jord was born in Togo and now lives in France.
-$person1.do-decoration; # This fails since the method `do-decoration` is
- # private.
-```
-
-### Object Inheritance
-
-```perl6
-## Perl 6 also has inheritance (along with multiple inheritance). While
-## methods are inherited, submethods are not. Submethods are useful for
-## object construction and destruction tasks, such as BUILD, or methods that
-## must be overridden by subtypes. We will learn about BUILD later on.
-
-class Parent {
- has $.age;
- has $.name;
-
- # This submethod won't be inherited by the Child class.
- submethod favorite-color {
- say "My favorite color is Blue";
- }
-
- # This method is inherited
- method talk { say "Hi, my name is $!name" }
-}
-
-# Inheritance uses the `is` keyword
-class Child is Parent {
- method talk { say "Goo goo ga ga" }
- # This shadows Parent's `talk` method.
- # This child hasn't learned to speak yet!
-}
-
-my Parent $Richard .= new(age => 40, name => 'Richard');
-$Richard.favorite-color; #=> "My favorite color is Blue"
-$Richard.talk; #=> "Hi, my name is Richard"
-## $Richard is able to access the submethod and he knows how to say his name.
-
-my Child $Madison .= new(age => 1, name => 'Madison');
-$Madison.talk; #=> "Goo goo ga ga", due to the overridden method.
-# $Madison.favorite-color # does not work since it is not inherited.
-
-## When you use `my T $var`, `$var` starts off with `T` itself in it,
-## so you can call `new` on it.
-## (`.=` is just the dot-call and the assignment operator:
-## `$a .= b` is the same as `$a = $a.b`)
-## Also note that `BUILD` (the method called inside `new`)
-## will set parent's properties too, so you can pass `val => 5`.
-```
-
-### Roles, or Mixins
-
-```perl6
-## Roles are supported too (which are called Mixins in other languages)
-role PrintableVal {
- has $!counter = 0;
- method print {
- say $.val;
- }
-}
-
-## you "apply" a role (or mixin) with `does` keyword:
-class Item does PrintableVal {
- has $.val;
-
- ## When `does`-ed, a `role` literally "mixes in" the class:
- ## the methods and attributes are put together, which means a class
- ## can access the private attributes/methods of its roles (but
- ## not the inverse!):
- method access {
- say $!counter++;
- }
-
- ## However, this:
- ## method print {}
- ## is ONLY valid when `print` isn't a `multi` with the same dispatch.
- ## (this means a parent class can shadow a child class's `multi print() {}`,
- ## but it's an error if a role does)
-
- ## NOTE: You can use a role as a class (with `is ROLE`). In this case,
- ## methods will be shadowed, since the compiler will consider `ROLE`
- ## to be a class.
-}
-```
-
-## Exceptions
-
-```perl6
-## Exceptions are built on top of classes, in the package `X` (like `X::IO`).
-## In Perl6 exceptions are automatically 'thrown':
-open 'foo'; #=> Failed to open file foo: no such file or directory
-## It will also print out what line the error was thrown at
-## and other error info.
-
-## You can throw an exception using `die`:
-die 'Error!'; #=> Error!
-
-## Or more explicitly:
-X::AdHoc.new(payload => 'Error!').throw; #=> Error!
-
-## In Perl 6, `orelse` is similar to the `or` operator, except it only matches
-## undefined variables instead of anything evaluating as `False`.
-## Undefined values include: `Nil`, `Mu` and `Failure` as well as `Int`, `Str`
-## and other types that have not been initialized to any value yet.
-## You can check if something is defined or not using the defined method:
-my $uninitialized;
-say $uninitiazilzed.defined; #=> False
-
-## When using `orelse` it will disarm the exception and alias $_ to that
-## failure. This will prevent it to being automatically handled and printing
-## lots of scary error messages to the screen. We can use the `exception`
-## method on the `$_` variable to access the exception
-open 'foo' orelse say "Something happened {.exception}";
-
-## This also works:
-open 'foo' orelse say "Something happened $_"; #=> Something happened
- #=> Failed to open file foo: no such file or directory
-## Both of those above work but in case we get an object from the left side
-## that is not a failure we will probably get a warning. We see below how we
-## can use try` and `CATCH` to be more specific with the exceptions we catch.
-```
-
-### Using `try` and `CATCH`
-
-```perl6
-## By using `try` and `CATCH` you can contain and handle exceptions without
-## disrupting the rest of the program. The `try` block will set the last
-## exception to the special variable `$!` (known as the error variable).
-## Note: This has no relation to $!variables seen inside class definitions.
-
-try open 'foo';
-say "Well, I tried! $!" if defined $!;
-#=> Well, I tried! Failed to open file foo: no such file or directory
-
-## Now, what if we want more control over handling the exception?
-## Unlike many other languages, in Perl 6, you put the `CATCH` block *within*
-## the block to `try`. Similar to how the `$_` variable was set when we
-## 'disarmed' the exception with `orelse`, we also use `$_` in the CATCH block.
-## Note: The `$!` variable is only set *after* the `try` block has caught an
-## exception. By default, a `try` block has a `CATCH` block of its own that
-## catches any exception (`CATCH { default {} }`).
-
-try {
- my $a = (0 %% 0);
- CATCH {
- say "Something happened: $_"
- }
-}
-#=> Something happened: Attempt to divide by zero using infix:<%%>
-
-## You can redefine it using `when`s (and `default`) to handle the exceptions
-## you want to catch explicitly:
-
-try {
- open 'foo';
- CATCH {
- # In the `CATCH` block, the exception is set to the $_ variable.
- when X::AdHoc {
- say "Error: $_"
- }
- when X::Numeric::DivideByZero {
- say "Error: $_";
- }
- ## Any other exceptions will be re-raised, since we don't have a `default`.
- ## Basically, if a `when` matches (or there's a `default`), the
- ## exception is marked as "handled" so as to prevent its re-throw
- ## from the `CATCH` block. You still can re-throw the exception (see below)
- ## by hand.
- }
-}
-#=>Error: Failed to open file /dir/foo: no such file or directory
-
-## There are also some subtleties to exceptions. Some Perl 6 subs return a
-## `Failure`, which is a wrapper around an `Exception` object which is
-## "unthrown". They're not thrown until you try to use the variables containing
-## them unless you call `.Bool`/`.defined` on them - then they're handled.
-## (the `.handled` method is `rw`, so you can mark it as `False` back yourself)
-## You can throw a `Failure` using `fail`. Note that if the pragma `use fatal`
-## is on, `fail` will throw an exception (like `die`).
-
-fail "foo"; # We're not trying to access the value, so no problem.
-try {
- fail "foo";
- CATCH {
- default {
- say "It threw because we tried to get the fail's value!"
- }
- }
-}
-
-## There is also another kind of exception: Control exceptions.
-## Those are "good" exceptions, which happen when you change your program's
-## flow, using operators like `return`, `next` or `last`.
-## You can "catch" those with `CONTROL` (not 100% working in Rakudo yet).
-```
-
-## Packages
-
-```perl6
-## Packages are a way to reuse code. Packages are like "namespaces", and any
-## element of the six model (`module`, `role`, `class`, `grammar`, `subset` and
-## `enum`) are actually packages. (Packages are the lowest common denominator)
-## Packages are important - especially as Perl is well-known for CPAN,
-## the Comprehensive Perl Archive Network.
-
-## You can use a module (bring its declarations into scope) with
-## the `use` keyword:
-use JSON::Tiny; # if you installed Rakudo* or Panda, you'll have this module
-say from-json('[1]').perl; #=> [1]
-
-## You should not declare packages using the `package` keyword (unlike Perl 5).
-## Instead, use `class Package::Name::Here;` to declare a class, or if you only
-## want to export variables/subs, you can use `module` instead.
-
-module Hello::World { # bracketed form
- # If `Hello` doesn't exist yet, it'll just be a "stub",
- # that can be redeclared as something else later.
-
- # ... declarations here ...
-}
-
-unit module Parse::Text; # file-scoped form which extends until
- # the end of the file
-
-grammar Parse::Text::Grammar {
- # A grammar is a package, which you could `use`.
- # You will learn more about grammars in the regex section
-}
-
-## As said before, any part of the six model is also a package.
-## Since `JSON::Tiny` uses its own `JSON::Tiny::Actions` class, you can use it:
-my $actions = JSON::Tiny::Actions.new;
-
-## We'll see how to export variables and subs in the next part.
-```
-
-## Declarators
-
-```perl6
-## In Perl 6, you get different behaviors based on how you declare a variable.
-## You've already seen `my` and `has`, we'll now explore the others.
-
-## `our` - these declarations happen at `INIT` time -- (see "Phasers" below).
-## It's like `my`, but it also creates a package variable. All packagish
-## things such as `class`, `role`, etc. are `our` by default.
-
-module Var::Increment {
- our $our-var = 1; # Note: `our`-declared variables cannot be typed.
- my $my-var = 22;
-
- our sub Inc {
- our sub available { # If you try to make inner `sub`s `our`...
- # ... Better know what you're doing (Don't !).
- say "Don't do that. Seriously. You'll get burned.";
- }
-
- my sub unavailable { # `sub`s are `my`-declared by default
- say "Can't access me from outside, I'm 'my'!";
- }
- say ++$our-var; # Increment the package variable and output its value
- }
-
-}
-
-say $Var::Increment::our-var; #=> 1, this works!
-say $Var::Increment::my-var; #=> (Any), this will not work!
-
-Var::Increment::Inc; #=> 2
-Var::Increment::Inc; #=> 3 , notice how the value of $our-var was
- # retained.
-Var::Increment::unavailable; #=> Could not find symbol '&unavailable'
-
-## `constant` - these declarations happen at `BEGIN` time. You can use
-## the `constant` keyword to declare a compile-time variable/symbol:
-constant Pi = 3.14;
-constant $var = 1;
-
-## And if you're wondering, yes, it can also contain infinite lists.
-constant why-not = 5, 15 ... *;
-say why-not[^5]; #=> 5 15 25 35 45
-
-## `state` - these declarations happen at run time, but only once. State
-## variables are only initialized one time. In other languages such as C
-## they exist as `static` variables.
-sub fixed-rand {
- state $val = rand;
- say $val;
-}
-fixed-rand for ^10; # will print the same number 10 times
-
-## Note, however, that they exist separately in different enclosing contexts.
-## If you declare a function with a `state` within a loop, it'll re-create the
-## variable for each iteration of the loop. See:
-for ^5 -> $a {
- sub foo {
- state $val = rand; # This will be a different value for
- # every value of `$a`
- }
- for ^5 -> $b {
- say foo; # This will print the same value 5 times,
- # but only 5. Next iteration will re-run `rand`.
- }
-}
-```
-
-## Phasers
-
-```perl6
-## Phasers in Perl 6 are blocks that happen at determined points of time in
-## your program. They are called phasers because they mark a change in the
-## phase of a program. For example, when the program is compiled, a for loop
-## runs, you leave a block, or an exception gets thrown (The `CATCH` block is
-## actually a phaser!). Some of them can be used for their return values,
-## some of them can't (those that can have a "[*]" in the beginning of their
-## explanation text). Let's have a look!
-
-## Compile-time phasers
-BEGIN { say "[*] Runs at compile time, as soon as possible, only once" }
-CHECK { say "[*] Runs at compile time, as late as possible, only once" }
-
-## Run-time phasers
-INIT { say "[*] Runs at run time, as soon as possible, only once" }
-END { say "Runs at run time, as late as possible, only once" }
-
-## Block phasers
-ENTER { say "[*] Runs everytime you enter a block, repeats on loop blocks" }
-LEAVE {
- say "Runs everytime you leave a block, even when an exception
- happened. Repeats on loop blocks."
-}
-
-PRE {
- say "Asserts a precondition at every block entry,
- before ENTER (especially useful for loops)";
- say "If this block doesn't return a truthy value,
- an exception of type X::Phaser::PrePost is thrown.";
-}
-
-## Example:
-for 0..2 {
- PRE { $_ > 1 } # This is going to blow up with "Precondition failed"
-}
-
-POST {
- say "Asserts a postcondition at every block exit,
- after LEAVE (especially useful for loops)";
- say "If this block doesn't return a truthy value,
- an exception of type X::Phaser::PrePost is thrown, like PRE.";
-}
-
-for 0..2 {
- POST { $_ < 2 } # This is going to blow up with "Postcondition failed"
-}
-
-## Block/exceptions phasers
-sub {
- KEEP { say "Runs when you exit a block successfully
- (without throwing an exception)" }
- UNDO { say "Runs when you exit a block unsuccessfully
- (by throwing an exception)" }
-}
-
-## Loop phasers
-for ^5 {
- FIRST { say "[*] The first time the loop is run, before ENTER" }
- NEXT { say "At loop continuation time, before LEAVE" }
- LAST { say "At loop termination time, after LEAVE" }
-}
-
-## Role/class phasers
-COMPOSE { "When a role is composed into a class. /!\ NOT YET IMPLEMENTED" }
-
-## They allow for cute tricks or clever code...:
-say "This code took " ~ (time - CHECK time) ~ "s to compile";
-
-## ... or clever organization:
-sub do-db-stuff {
- $db.start-transaction; # start a new transaction
- KEEP $db.commit; # commit the transaction if all went well
- UNDO $db.rollback; # or rollback if all hell broke loose
-}
-```
-
-## Statement prefixes
-
-```perl6
-## Those act a bit like phasers: they affect the behavior of the following
-## code. Though, they run in-line with the executable code, so they're in
-## lowercase. (`try` and `start` are theoretically in that list, but explained
-## elsewhere) Note: all of these (except start) don't need explicit curly
-## braces `{` and `}`.
-
-## `do` - (which you already saw) runs a block or a statement as a term.
-## Normally you cannot use a statement as a value (or "term"). `do` helps us
-## do it.
-
-# my $value = if True { 1 } # this fails since `if` is a statement
-my $a = do if True { 5 } # with `do`, `if` is now a term returning a value
-
-## `once` - makes sure a piece of code only runs once.
-for ^5 {
- once say 1
-}; #=> 1, only prints ... once
-
-## Similar to `state`, they're cloned per-scope.
-for ^5 {
- sub { once say 1 }()
-}; #=> 1 1 1 1 1, prints once per lexical scope.
-
-## `gather` - co-routine thread. The `gather` constructs allows us to `take`
-## several values from an array/list, much like `do`.
-say gather for ^5 {
- take $_ * 3 - 1;
- take $_ * 3 + 1;
-}
-#=> -1 1 2 4 5 7 8 10 11 13
-
-say join ',', gather if False {
- take 1;
- take 2;
- take 3;
-}
-# Doesn't print anything.
-
-## `eager` - evaluates a statement eagerly (forces eager context)
-## Don't try this at home:
-# eager 1..*; # this will probably hang for a while (and might crash ...).
-## But consider:
-constant thrice = gather for ^3 { say take $_ }; # Doesn't print anything
-## versus:
-constant thrice = eager gather for ^3 { say take $_ }; #=> 0 1 2
-```
-
-## Iterables
-
-```perl6
-## Iterables are objects that can be iterated over which are
-## are similar to the `for` construct.
-
-## `flat` - flattens iterables.
-say (1, 10, (20, 10) ); #=> (1 10 (20 10)), notice how neste lists are
- # preserved
-say (1, 10, (20, 10) ).flat; #=> (1 10 20 10), now the iterable is flat
-
-## - `lazy` - defers actual evaluation until value is fetched by forcing
-## lazy context.
-my @lazy-array = (1..100).lazy;
-say @lazy-array.is-lazy; #=> True, check for laziness with the `is-lazy` method.
-say @lazy-array; #=> [...] List has not been iterated on!
-my @lazy-array { .print }; # This works and will only do as much work as
- # is needed.
-
-# ( **TODO** explain that gather/take and map are all lazy)
-
-## `sink` - an `eager` that discards the results by forcing sink context.
-constant nilthingie = sink for ^3 { .say } #=> 0 1 2
-say nilthingie.perl; #=> Nil
-
-## `quietly` - suppresses warnings in blocks.
-quietly { warn 'This is a warning!' }; #=> No output
-
-## `contend` - attempts side effects under STM
-## Not yet implemented!
-```
-
-## More operators thingies!
-
-```perl6
-## Everybody loves operators! Let's get more of them.
-
-## The precedence list can be found here:
-## https://docs.perl6.org/language/operators#Operator_Precedence
-## But first, we need a little explanation about associativity:
-
-## Binary operators:
-$a ! $b ! $c; # with a left-associative `!`, this is `($a ! $b) ! $c`
-$a ! $b ! $c; # with a right-associative `!`, this is `$a ! ($b ! $c)`
-$a ! $b ! $c; # with a non-associative `!`, this is illegal
-$a ! $b ! $c; # with a chain-associative `!`, this is `($a ! $b) and ($b ! $c)`
-$a ! $b ! $c; # with a list-associative `!`, this is `infix:<>`
-
-## Unary operators:
-!$a! # with left-associative `!`, this is `(!$a)!`
-!$a! # with right-associative `!`, this is `!($a!)`
-!$a! # with non-associative `!`, this is illegal
-```
-
-### Create your own operators!
-
-```perl6
-## Okay, you've been reading all of that, so you might want to try something
-## more exciting?! I'll tell you a little secret (or not-so-secret):
-## In Perl 6, all operators are actually just funny-looking subroutines.
-
-## You can declare an operator just like you declare a sub:
-# prefix refers to the operator categories (prefix, infix, postfix, etc).
-sub prefix:<win>( $winner ) {
- say "$winner Won!";
-}
-win "The King"; #=> The King Won!
- # (prefix means 'before')
-
-## you can still call the sub with its "full name":
-say prefix:<!>(True); #=> False
-prefix:<win>("The Queen"); #=> The Queen Won!
-
-sub postfix:<!>( Int $n ) {
- [*] 2..$n; # using the reduce meta-operator... See below ;-)!
-}
-say 5!; #=> 120
- # Postfix operators ('after') have to come *directly* after the term.
- # No whitespace. You can use parentheses to disambiguate, i.e. `(5!)!`
-
-sub infix:<times>( Int $n, Block $r ) { # infix ('between')
- for ^$n {
- $r(); # You need the explicit parentheses to call the function in `$r`,
- # else you'd be referring at the variable itself, like with `&r`.
- }
-}
-3 times -> { say "hello" }; #=> hello
- #=> hello
- #=> hello
-## It's recommended to put spaces around your
-## infix operator calls.
-
-## For circumfix and post-circumfix ones
-sub circumfix:<[ ]>( Int $n ) {
- $n ** $n
-}
-say [5]; #=> 3125
- # circumfix means 'around'. Again, no whitespace.
-
-sub postcircumfix:<{ }>( Str $s, Int $idx ) {
- ## post-circumfix is 'after a term, around something'
- $s.substr($idx, 1);
-}
-say "abc"{1}; #=> b
- # after the term `"abc"`, and around the index (1)
-
-## This really means a lot -- because everything in Perl 6 uses this.
-## For example, to delete a key from a hash, you use the `:delete` adverb
-## (a simple named argument underneath):
-%h{$key}:delete;
-## equivalent to:
-postcircumfix:<{ }>( %h, $key, :delete ); # (you can call operators like this)
-
-## It's *all* using the same building blocks! Syntactic categories
-## (prefix infix ...), named arguments (adverbs), ..., etc. used to build
-## the language - are available to you. Obviously, you're advised against
-## making an operator out of *everything* -- with great power comes great
-## responsibility.
-```
-
-### Meta operators!
-
-```perl6
-## Oh boy, get ready!. Get ready, because we're delving deep into the rabbit's
-## hole, and you probably won't want to go back to other languages after
-## reading this. (I'm guessing you don't want to go back at this point but
-## let's continue, for the journey is long and enjoyable!).
-
-## Meta-operators, as their name suggests, are *composed* operators.
-## Basically, they're operators that act on another operators.
-
-## The reduce meta-operator is a prefix meta-operator that takes a binary
-## function and one or many lists. If it doesn't get passed any argument,
-## it either returns a "default value" for this operator (a meaningless value)
-## or `Any` if there's none (examples below). Otherwise, it pops an element
-## from the list(s) one at a time, and applies the binary function to the last
-## result (or the list's first element) and the popped element.
-
-## To sum a list, you could use the reduce meta-operator with `+`, i.e.:
-say [+] 1, 2, 3; #=> 6, equivalent to (1+2)+3.
-
-## To multiply a list
-say [*] 1..5; #=> 120, equivalent to ((((1*2)*3)*4)*5).
-
-## You can reduce with any operator, not just with mathematical ones.
-## For example, you could reduce with `//` to get first defined element
-## of a list:
-say [//] Nil, Any, False, 1, 5; #=> False
- # (Falsey, but still defined)
-## Or with relational operators, i.e., `>` to check elements of a list
-## are ordered accordingly:
-say say [>] 234, 156, 6, 3, -20; #=> True
-
-## Default value examples:
-say [*] (); #=> 1
-say [+] (); #=> 0
- # meaningless values, since N*1=N and N+0=N.
-say [//]; #=> (Any)
- # There's no "default value" for `//`.
-
-## You can also call it with a function you made up, using double brackets:
-sub add($a, $b) { $a + $b }
-say [[&add]] 1, 2, 3; #=> 6
-
-## The zip meta-operator is an infix meta-operator that also can be used as a
-## "normal" operator. It takes an optional binary function (by default, it
-## just creates a pair), and will pop one value off of each array and call
-## its binary function on these until it runs out of elements. It returns an
-## array with all of these new elements.
-say (1, 2) Z (3, 4); #=> ((1, 3), (2, 4)), since by default the function
- # makes an array.
-say 1..3 Z+ 4..6; #=> (5, 7, 9), using the custom infix:<+> function
-
-## Since `Z` is list-associative (see the list above),
-## you can use it on more than one list
-(True, False) Z|| (False, False) Z|| (False, False); # (True, False)
-
-## And, as it turns out, you can also use the reduce meta-operator with it:
-[Z||] (True, False), (False, False), (False, False); # (True, False)
-
-
-## And to end the operator list:
-
-## The sequence operator is one of Perl 6's most powerful features:
-## it's composed of first, on the left, the list you want Perl 6 to deduce from
-## (and might include a closure), and on the right, a value or the predicate
-## that says when to stop (or a Whatever Star for a lazy infinite list).
-
-my @list = 1, 2, 3...10; # basic arithmetic sequence
-# my @list = 1, 3, 6...10; # this dies because Perl 6 can't figure out the end
-my @list = 1, 2, 3...^10; # as with ranges, you can exclude the last element
- # (the iteration ends when the predicate matches).
-my @list = 1, 3, 9...* > 30; # you can use a predicate (with the Whatever Star).
-my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalent to the above
- # using a block here).
-
-my @fib = 1, 1, *+* ... *; # lazy infinite list of fibonacci sequence,
- # computed using a closure!
-my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalent to the above)
-my @fib = 1, 1, { $^a + $^b } ... *; # (also equivalent to the above)
-## $a and $b will always take the previous values, meaning here
-## they'll start with $a = 1 and $b = 1 (values we set by hand),
-## then $a = 1 and $b = 2 (result from previous $a+$b), and so on.
-
-say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55
- # (using a range as the index)
-## Note: as for ranges, once reified, elements aren't re-calculated.
-## That's why `@primes[^100]` will take a long time the first time you print
-## it, then will be instateneous.
-```
-
-## Regular Expressions
-
-```perl6
-## I'm sure a lot of you have been waiting for this one. Well, now that you know
-## a good deal of Perl 6 already, we can get started. First off, you'll have to
-## forget about "PCRE regexps" (perl-compatible regexps).
-##
-## IMPORTANT: Don't skip them because you know PCRE. They're different. Some
-## things are the same (like `?`, `+`, and `*`), but sometimes the semantics
-## change (`|`). Make sure you read carefully, because you might trip over a
-## new behavior.
-##
-## Perl 6 has many features related to RegExps. After all, Rakudo parses itself.
-## We're first going to look at the syntax itself, then talk about grammars
-## (PEG-like), differences between `token`, `regex` and `rule` declarators,
-## and some more. Side note: you still have access to PCRE regexps using the
-## `:P5` modifier which we won't be discussing this in this tutorial, though.
-##
-## In essence, Perl 6 natively implements PEG ("Parsing Expression Grammars").
-## The pecking order for ambiguous parses is determined by a multi-level
-## tie-breaking test:
-## - Longest token matching: `foo\s+` beats `foo` (by 2 or more positions)
-## - Longest literal prefix: `food\w*` beats `foo\w*` (by 1)
-## - Declaration from most-derived to less derived grammars
-## (grammars are actually classes)
-## - Earliest declaration wins
-say so 'a' ~~ /a/; #=> True
-say so 'a' ~~ / a /; #=> True, more readable with some spaces!
-
-## In all our examples, we're going to use the smart-matching operator against
-## a regexp. We're converting the result using `so` to a Boolean value because,
-## in fact, it's returning a `Match` object. They know how to respond to list
-## indexing, hash indexing, and return the matched string. The results of the
-## match are available in the `$/` variable (implicitly lexically-scoped). You
-## can also use the capture variables which start at 0: `$0`, `$1', `$2`...
-##
-## You can also note that `~~` does not perform start/end checking, meaning
-## the regexp can be matched with just one character of the string. We'll
-## explain later how you can do it.
-
-## In Perl 6, you can have any alphanumeric as a literal, everything else has
-## to be escaped by using a backslash or quotes.
-say so 'a|b' ~~ / a '|' b /; #=> `True`, it wouldn't mean the same thing if
- # `|` wasn't escaped.
-say so 'a|b' ~~ / a \| b /; #=> `True`, another way to escape it.
-
-## The whitespace in a regexp is actually not significant, unless you use the
-## `:s` (`:sigspace`, significant space) adverb.
-say so 'a b c' ~~ / a b c /; #=> `False`, space is not significant here!
-say so 'a b c' ~~ /:s a b c /; #=> `True`, we added the modifier `:s` here.
-
-## If we use only one space between strings in a regex, Perl 6 will warn us:
-say so 'a b c' ~~ / a b c /; #=> `False`, with warning about space
-say so 'a b c' ~~ / a b c /; #=> `False`
-
-## Please use quotes or :s (:sigspace) modifier (or, to suppress this warning,
-## omit the space, or otherwise change the spacing). To fix this and make the
-## spaces less ambiguous, either use at least two spaces between strings
-## or use the `:s` adverb.
-
-## As we saw before, we can embed the `:s` inside the slash delimiters, but we
-## can also put it outside of them if we specify `m` for 'match':
-say so 'a b c' ~~ m:s/a b c/; #=> `True`
-
-## By using `m` to specify 'match', we can also use delimiters other than
-## slashes:
-say so 'abc' ~~ m{a b c}; #=> `True`
-say so 'abc' ~~ m[a b c]; #=> `True`
-# m/.../ is equivalent to /.../
-
-## Use the :i adverb to specify case insensitivity:
-say so 'ABC' ~~ m:i{a b c}; #=> `True`
-
-## However, whitespace is important as for how modifiers are applied (
-## (which you'll see just below) ...
-
-## Quantifying - `?`, `+`, `*` and `**`.
-## `?` - zero or one match
-so 'ac' ~~ / a b c /; #=> `False`
-so 'ac' ~~ / a b? c /; #=> `True`, the "b" matched 0 times.
-so 'abc' ~~ / a b? c /; #=> `True`, the "b" matched 1 time.
-
-## ...As you read before, whitespace is important because it determines which
-## part of the regexp is the target of the modifier:
-so 'def' ~~ / a b c? /; #=> `False`, only the `c` is optional
-so 'def' ~~ / a b? c /; #=> `False`, whitespace is not significant
-so 'def' ~~ / 'abc'? /; #=> `True`, the whole "abc" group is optional
-
-## Here (and below) the quantifier applies only to the `b`
-
-## `+` - one or more matches
-so 'ac' ~~ / a b+ c /; #=> `False`, `+` wants at least one matching
-so 'abc' ~~ / a b+ c /; #=> `True`, one is enough
-so 'abbbbc' ~~ / a b+ c /; #=> `True`, matched 4 "b"s
-
-## `*` - zero or more matches
-so 'ac' ~~ / a b* c /; #=> `True`, they're all optional.
-so 'abc' ~~ / a b* c /; #=> `True`
-so 'abbbbc' ~~ / a b* c /; #=> `True`
-so 'aec' ~~ / a b* c /; #=> `False`. "b"(s) are optional, not replaceable.
-
-## `**` - (Unbound) Quantifier
-## If you squint hard enough, you might understand why exponentation is used
-## for quantity.
-so 'abc' ~~ / a b**1 c /; #=> `True`, (exactly one time)
-so 'abc' ~~ / a b**1..3 c /; #=> `True`, (one to three times)
-so 'abbbc' ~~ / a b**1..3 c /; #=> `True`
-so 'abbbbbbc' ~~ / a b**1..3 c /; #=> `False, (too much)
-so 'abbbbbbc' ~~ / a b**3..* c /; #=> `True`, (infinite ranges are okay)
-
-## `<[]>` - Character classes
-## Character classes are the equivalent of PCRE's `[]` classes, but they use a
-## more perl6-ish syntax:
-say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa'
-
-## You can use ranges:
-say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae'
-
-## Just like in normal regexes, if you want to use a special character, escape
-## it (the last one is escaping a space which would be equivalent to using
-## ' '):
-say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !'
-
-## You'll get a warning if you put duplicate names (which has the nice effect
-## of catching the raw quoting):
-'he he' ~~ / <[ h e ' ' ]> /;
-# Warns "Repeated character (') unexpectedly found in character class"
-
-## You can also negate character classes... (`<-[]>` equivalent to `[^]` in PCRE)
-so 'foo' ~~ / <-[ f o ]> + /; #=> False
-
-## ... and compose them:
-so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; #=> `False`, (any letter except f and o)
-so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; #=> `True`, (no letter except f and o)
-so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; #=> `True`, (the + doesn't replace the
- # left part)
-```
-
-### Grouping and capturing
-
-```perl6
-## Group: you can group parts of your regexp with `[]`. Unlike PCRE's `(?:)`,
-## these groups are *not* captured.
-so 'abc' ~~ / a [ b ] c /; # `True`. The grouping does pretty much nothing
-so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /;
-
-## The previous line returns `True`. The regex matches "012" 1 or more time
-## (achieved by the the `+` applied to the group).
-
-## But this does not go far enough, because we can't actually get back what
-## we matched.
-
-## Capture: The results of a regexp can be *captured* by using parentheses.
-so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (using `so`
- # here, `$/` below)
-
-## So, starting with the grouping explanations.
-## As we said before, our `Match` object is stored inside the `$/` variable:
-say $/; # Will either print some weird stuff or `Nil` if nothing matched.
-
-## As we also said before, it has array indexing:
-say $/[0]; #=> 「ABC」 「ABC」
- # These corner brackets are `Match` objects.
- # Here, we have an array of these.
-say $0; # The same as above.
-
-## Our capture is `$0` because it's the first and only one capture in the
-## regexp. You might be wondering why it's an array, and the answer is simple:
-## Some captures (indexed using `$0`, `$/[0]` or a named one) will be an array
-## if and only if they can have more than one element. Thus any capture with
-## `*`, `+` and `**` (whatever the operands), but not with `?`.
-## Let's use examples to see that:
-
-## Note: We quoted A B C to demonstrate that the whitespace between them isn't
-## significant. If we want the whitespace to *be* significant there, we
-## can use the :sigspace modifier.
-say so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; #=> `True`
-say $/[0]; #=> 「ABC」
-say $0.WHAT; #=> (Match)
- # There can't be more than one, so it's only a single match object.
-say so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; #=> True
-say $0.WHAT; #=> (Any)
- # This capture did not match, so it's empty
-so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; #=> `True`
-say $0.WHAT; #=> (Array)
- # A specific quantifier will always capture an Array,
- # be a range or a specific value (even 1).
-
-## The captures are indexed per nesting. This means a group in a group will be
-## nested under its parent group: `$/[0][0]`, for this code:
-'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /;
-say $/[0].Str; #=> hello~
-say $/[0][0].Str; #=> ~
-
-## This stems from a very simple fact: `$/` does not contain strings, integers
-## or arrays, it only contains Match objects. These contain the `.list`, `.hash`
-## and `.Str` methods but you can also just use `match<key>` for hash access
-## and `match[idx]` for array access.
-say $/[0].list.perl; #=> (Match.new(...),).list
- # We can see it's a list of Match objects. These contain
- # a bunch of info: where the match started/ended,
- # the "ast" (see actions later), etc.
- # You'll see named capture below with grammars.
-
-## Alternation - the `or` of regexps
-## WARNING: They are DIFFERENT from PCRE regexps.
-say so 'abc' ~~ / a [ b | y ] c /; #=> `True`. Either "b" or "y".
-say so 'ayc' ~~ / a [ b | y ] c /; #=> `True`. Obviously enough...
-
-## The difference between this `|` and the one you're used to is
-## LTM ("Longest Token Matching"). This means that the engine will always
-## try to match as much as possible in the string.
-say 'foo' ~~ / fo | foo /; #=> `foo`, instead of `fo`, because it's longer.
-
-## To decide which part is the "longest", it first splits the regex in
-## two parts:
-## The "declarative prefix" (the part that can be statically analyzed)
-## and the procedural parts:
-## - The declarative prefixes include alternations (`|`), conjunctions (`&`),
-## sub-rule calls (not yet introduced), literals, characters classes and
-## quantifiers.
-## - The procedural part include everything else: back-references,
-## code assertions, and other things that can't traditionnaly be represented
-## by normal regexps.
-##
-## Then, all the alternatives are tried at once, and the longest wins.
-## Examples:
-## DECLARATIVE | PROCEDURAL
-/ 'foo' \d+ [ <subrule1> || <subrule2> ] /;
-## DECLARATIVE (nested groups are not a problem)
-/ \s* [ \w & b ] [ c | d ] /;
-## However, closures and recursion (of named regexps) are procedural.
-## There are also more complicated rules, like specificity (literals win over
-## character classes).
-
-## Note: the first-matching `or` still exists, but is now spelled `||`
-say 'foo' ~~ / fo || foo /; #=> `fo` now.
-```
-
-## Extra: the MAIN subroutine
-
-```perl6
-## The `MAIN` subroutine is called when you run a Perl 6 file directly. It's
-## very powerful, because Perl 6 actually parses the arguments and pass them
-## as such to the sub. It also handles named argument (`--foo`) and will even
-## go as far as to autogenerate a `--help` flag.
-sub MAIN($name) {
- say "Hello, $name!";
-}
-## This produces:
-## $ perl6 cli.pl
-## Usage:
-## t.pl <name>
-
-## And since it's a regular Perl 6 sub, you can have multi-dispatch:
-## (using a "Bool" for the named argument so that we can do `--replace`
-## instead of `--replace=1`. The presence of `--replace` indicates truthness
-## while its absence falseness).
-
-subset File of Str where *.IO.d; # convert to IO object to check the file exists
-
-multi MAIN('add', $key, $value, Bool :$replace) { ... }
-multi MAIN('remove', $key) { ... }
-multi MAIN('import', File, Str :$as) { ... } # omitting parameter name
-
-## This produces:
-## $ perl6 cli.pl
-## Usage:
-## cli.p6 [--replace] add <key> <value>
-## cli.p6 remove <key>
-## cli.p6 [--as=<Str>] import <File>
-
-## As you can see, this is *very* powerful. It even went as far as to show inline
-## the constants (the type is only displayed if the argument is `$`/is named).
-```
-
-## APPENDIX A:
-### List of things
-
-```perl6
-## It's assumed by now you know the Perl6 basics. This section is just here to
-## list some common operations, but which are not in the "main part" of the
-## tutorial to avoid bloating it up.
-
-## Operators
-
-## Sort comparison - they return one value of the `Order` enum: `Less`, `Same`
-## and `More` (which numerify to -1, 0 or +1 respectively).
-1 <=> 4; # sort comparison for numerics
-'a' leg 'b'; # sort comparison for string
-$obj eqv $obj2; # sort comparison using eqv semantics
-
-## Generic ordering
-3 before 4; # True
-'b' after 'a'; # True
-
-## Short-circuit default operator - similar to `or` and `||`, but instead
-## returns the first *defined* value:
-say Any // Nil // 0 // 5; #=> 0
-
-## Short-circuit exclusive or (XOR) - returns `True` if one (and only one) of
-## its arguments is true
-say True ^^ False; #=> True
-
-## Flip flops - these operators (`ff` and `fff`, equivalent to P5's `..`
-## and `...`) are operators that take two predicates to test: They are `False`
-## until their left side returns `True`, then are `True` until their right
-## side returns `True`. Similar to ranges, you can exclude the iteration when
-## it become `True`/`False` by using `^` on either side. Let's start with an
-## example :
-for <well met young hero we shall meet later> {
- # by default, `ff`/`fff` smart-match (`~~`) against `$_`:
- if 'met' ^ff 'meet' { # Won't enter the if for "met"
- .say # (explained in details below).
- }
-
- if rand == 0 ff rand == 1 { # compare variables other than `$_`
- say "This ... probably will never run ...";
- }
-}
-
-## This will print "young hero we shall meet" (excluding "met"): the flip-flop
-## will start returning `True` when it first encounters "met" (but will still
-## return `False` for "met" itself, due to the leading `^` on `ff`), until it
-## sees "meet", which is when it'll start returning `False`.
-
-## The difference between `ff` (awk-style) and `fff` (sed-style) is that `ff`
-## will test its right side right when its left side changes to `True`, and can
-## get back to `False` right away (*except* it'll be `True` for the iteration
-## that matched) while `fff` will wait for the next iteration to try its right
-## side, once its left side changed:
-.say if 'B' ff 'B' for <A B C B A>; #=> B B
- # because the right-hand-side was tested
- # directly (and returned `True`).
- # "B"s are printed since it matched that
- # time (it just went back to `False`
- # right away).
-.say if 'B' fff 'B' for <A B C B A>; #=> B C B
- # The right-hand-side wasn't tested until
- # `$_` became "C"
- # (and thus did not match instantly).
-
-## A flip-flop can change state as many times as needed:
-for <test start print it stop not printing start print again stop not anymore> {
- .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # exclude both "start" and "stop",
- #=> "print it print again"
-}
-
-## You might also use a Whatever Star, which is equivalent to `True` for the
-## left side or `False` for the right:
-for (1, 3, 60, 3, 40, 60) { # Note: the parenthesis are superfluous here
- # (sometimes called "superstitious parentheses")
- .say if $_ > 50 ff *; # Once the flip-flop reaches a number greater
- # than 50, it'll never go back to `False`
- #=> 60 3 40 60
-}
-
-## You can also use this property to create an `if` that'll not go through the
-## first time:
-for <a b c> {
- .say if * ^ff *; # the flip-flop is `True` and never goes back to `False`,
- # but the `^` makes it *not run* on the first iteration
- #=> b c
-}
-
-## The `===` operator is the value identity operator and uses `.WHICH` on the
-## objects to compare them while `=:=` is the container identity operator
-## and uses `VAR()` on the objects to compare them.
-```
-
-If you want to go further, you can:
-
- - Read the [Perl 6 Docs](https://docs.perl6.org/). This is a great
- resource on Perl6. If you are looking for something, use the search bar.
- This will give you a dropdown menu of all the pages referencing your search
- term (Much better than using Google to find Perl 6 documents!).
- - Read the [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). This
- is a great source of Perl 6 snippets and explanations. If the docs don't
- describe something well enough, you may find more detailed information here.
- This information may be a bit older but there are many great examples and
- explanations. Posts stopped at the end of 2015 when the language was declared
- stable and Perl 6.c was released.
- - Come along on `#perl6` at `irc.freenode.net`. The folks here are
- always helpful.
- - Check the [source of Perl 6's functions and
- classes](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo is
- mainly written in Perl 6 (with a lot of NQP, "Not Quite Perl", a Perl 6 subset
- easier to implement and optimize).
- - Read [the language design documents](http://design.perl6.org). They explain
- P6 from an implementor point-of-view, but it's still very interesting.
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/pl-pl/bf-pl.html.markdown b/pl-pl/bf-pl.html.markdown
index 88f928cf..09c85362 100644
--- a/pl-pl/bf-pl.html.markdown
+++ b/pl-pl/bf-pl.html.markdown
@@ -7,6 +7,7 @@ contributors:
- ["Mathias Bynens", "http://mathiasbynens.be/"]
translators:
- ["Jakub Młokosiewicz", "https://github.com/hckr"]
+ - ["Mateusz Burniak", "https://github.com/matbur"]
lang: pl-pl
---
@@ -32,9 +33,9 @@ Oto osiem poleceń brainfucka:
. : wyświetla wartość bieżącej komórki (w formie znaku ASCII, np. 65 = 'A')
, : wczytuje (jeden) znak z wejścia do bieżącej komórki
(konkretnie jego numer z tabeli ASCII)
-[ : jeśli wartość w bieżącej komórce jest rózna zero, przechodzi do
+[ : jeśli wartość w bieżącej komórce jest równa zeru, przechodzi do
odpowiadającego ]; w przeciwnym wypdaku przechodzi do następnej instrukcji
-] : Jeśli wartość w bieżącej komórce jest rózna od zera, przechodzi do
+] : Jeśli wartość w bieżącej komórce jest równa zeru, przechodzi do
następnej instrukcji; w przeciwnym wypdaku przechodzi do odpowiadającego [
[ i ] oznaczają pętlę while. Oczywiście każda pętla rozpoczęta [
diff --git a/pl-pl/java-pl.html.markdown b/pl-pl/java-pl.html.markdown
new file mode 100644
index 00000000..0da449c5
--- /dev/null
+++ b/pl-pl/java-pl.html.markdown
@@ -0,0 +1,1026 @@
+---
+language: java
+filename: LearnJavaPl.java
+contributors:
+ - ["Jake Prather", "https://github.com/JakeHP"]
+ - ["Jakukyo Friel", "https://weakish.github.io"]
+ - ["Madison Dickson", "https://github.com/mix3d"]
+ - ["Simon Morgan", "https://sjm.io/"]
+ - ["Zachary Ferguson", "https://github.com/zfergus2"]
+ - ["Cameron Schermerhorn", "https://github.com/cschermerhorn"]
+ - ["Rachel Stiyer", "https://github.com/rstiyer"]
+ - ["Michael Dähnert", "https://github.com/JaXt0r"]
+ - ["Rob Rose", "https://github.com/RobRoseKnows"]
+ - ["Sean Nam", "https://github.com/seannam"]
+ - ["Shawn M. Hanes", "https://github.com/smhanes15"]
+filename: LearnJava.java
+translators:
+ - ["Jacek Wachowiak", "https://github.com/jacekwachowiak"]
+lang: pl-pl
+---
+
+Java jest współbieżnym, opartym na klasach, obiektowym językiem programowania
+ogólnego zastosowania.
+[Tu znajdziesz więcej informacji po angielsku.]
+(https://docs.oracle.com/javase/tutorial/java/)
+
+```java
+// Pojedyncze komentarze oznaczamy //
+
+/*
+Komentarze wieloliniowe wyglądają tak
+*/
+
+/**
+ * Komentarze JavaDoc wygladają w ten sposób. Używane są do opisu klas lub
+ * różnych właściwości klas.
+ * Główne właściwości:
+ *
+ * @author Imię i nazwisko (i kontakt np. email) autora.
+ * @version Aktualna wersja programu.
+ * @since Kiedy ta część programu została dodana.
+ * @param Służy do opisu parametrów metody.
+ * @return Służy do opisu zwracanej wartości.
+ * @deprecated Służy do oznaczenia nieaktualnego lub niezalecanego kodu.
+ * @see Linki do innej cześci dokumentacji.
+*/
+
+// Import klasy ArrayList z paczki java.util
+import java.util.ArrayList;
+// Import wszystkich klas z paczki java.security
+import java.security.*;
+
+public class LearnJava {
+
+ // Aby móc uruchomić program w języku java musi on mieć główną metodę jako
+ // punkt wejścia.
+ public static void main(String[] args) {
+
+ ///////////////////////////////////////
+ // Operacje wejścia/wyjścia (input/output)
+ ///////////////////////////////////////
+
+ /*
+ * Wyjście
+ */
+
+ // System.out.println() służy do wyświetlania linii tekstu.
+ System.out.println("Hello World!");
+ System.out.println(
+ "Integer: " + 10 +
+ " Double: " + 3.14 +
+ " Boolean: " + true);
+
+ // Aby wyświetlić bez nowej linii użyj System.out.print().
+ System.out.print("Hello ");
+ System.out.print("World");
+
+ // System.out.printf() służy do łatwego formatowania wyświetlanego elementu.
+ System.out.printf("pi = %.5f", Math.PI); // => pi = 3.14159
+
+ /*
+ * Wejście
+ */
+
+ // Scanner służy do wczytywania danych
+ // niezbędny jest import java.util.Scanner;
+ Scanner scanner = new Scanner(System.in);
+
+ // zczytaj string (tekst)
+ String name = scanner.next();
+
+ // zczytaj zmienną typu bajt
+ byte numByte = scanner.nextByte();
+
+ // zczytaj zmienną typu integer - liczba całkowita
+ int numInt = scanner.nextInt();
+
+ // zczytaj zmienną typu float - liczba zmiennoprzecinkowa
+ float numFloat = scanner.nextFloat();
+
+ // zczytaj zmienna typu double -liczba zmiennoprzecinkowa
+ double numDouble = scanner.nextDouble();
+
+ // zczytaj zmienną typu boolowskiego -
+ boolean bool = scanner.nextBoolean();
+
+ ///////////////////////////////////////
+ // Zmienne
+ ///////////////////////////////////////
+
+ /*
+ * Deklaracja zmiennych
+ */
+ // Zmienną deklaruje się poprzez <rodzaj> <nazwa>
+ int fooInt;
+ // Dozwolona jest deklaracja wielu zmiennych tego samego typu na raz
+ // rodzaj <nazwa1>, <nazwa2>, <nazwa3>
+ int fooInt1, fooInt2, fooInt3;
+
+ /*
+ * Inicjalizacja zmiennych
+ */
+
+ // Zmienną inicjalizuje się poprzez <rodzaj> <nazwa> = <wartość>
+ int barInt = 1;
+ // Możliwe jest zainicjalizowanie wielu zmiennych tego samego typu tą samą wartością
+ // rodzaj <nazwa1>, <nazwa2>, <nazwa3>
+ // <nazwa1> = <nazwa2> = <nazwa3> = <wartość>
+ int barInt1, barInt2, barInt3;
+ barInt1 = barInt2 = barInt3 = 1;
+
+ /*
+ * Rodzaje zmiennych
+ */
+ // Bajt - 8-bitowa, zawierająca ujemne wartości zmienna w dwójkowym
+ // systemie pozycyjnym
+ // (-128 <= byte <= 127)
+ byte fooByte = 100;
+
+ // Jeśli chcemy zinterpretować bajt jako zmienną typu unsigned integer
+ // - liczbę całkowitą z wartościami ujemnymi ta operacja może pomóc:
+ int unsignedIntLessThan256 = 0xff & fooByte;
+ // jako kontrast operacja zmiany typu która może zwrócić wartość ujemną.
+ int signedInt = (int) fooByte;
+
+ // Short - 16-bitowa, zawierająca ujemne wartości zmienna w dwójkowym
+ // systemie pozycyjnym (-32,768 <= short <= 32,767)
+ short fooShort = 10000;
+
+ // Integer - 32-bitowa, zawierająca ujemne wartości zmienna w dwójkowym systemie pozycyjnym
+ // (-2,147,483,648 <= int <= 2,147,483,647)
+ int bazInt = 1;
+
+ // Long - 64-bitowa, zawierająca ujemne wartości zmienna w dwójkowym
+ // systemie pozycyjnym
+ // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
+ long fooLong = 100000L;
+ // L jest używane do zaznaczenia, że wartość zmiennej jest typu Long;
+ // bez L wszystko inne będzie traktowane z założenia jako integer.
+
+ // Uwaga: byte, short, int and long zawierają ujemne wartości.
+ // Nie istnieją odpowiedniki z jedynie pozytywnymi wartościami.
+ // Jedynie char jest 16-bitowym typem zmiennej, który akceptuje tylko
+ // wartości nieujemne.
+
+ // Float - 32-bitowy typ zmiennoprzecinkowy zgodnie z IEEE 754
+ // Floating Point 2^-149 <= float <= (2-2^-23) * 2^127
+ float fooFloat = 234.5f;
+ // f or F jest używane aby zaznaczyć, że dana zmienna jest typu float;
+ // w przeciwnym razie będzie ona traktowana jako double.
+
+ // Double - 64-bitowy typ zmiennoprzecinkowy zgodnie z IEEE 754
+ // Floating Point 2^-1074 <= x <= (2-2^-52) * 2^1023
+ double fooDouble = 123.4;
+
+ // Typ boolowski - true/prawda & false/fałsz
+ boolean fooBoolean = true;
+ boolean barBoolean = false;
+
+ // Char - pojedynczy 16-bitowy symbol Unicode
+ char fooChar = 'A';
+
+ // zmienne zadeklarowane z użyciem final nie mogą być edytowane,
+ final int HOURS_I_WORK_PER_WEEK = 9001;
+ // ale możliwa jest późniejsza inicjalizacja.
+ final double E;
+ E = 2.71828;
+
+ // BigInteger - Nieedytowalny typ zmiennej o nieograniczonej długości
+ // dla liczb całkowitych
+ //
+ // BigInteger jest typem zmiennej, który pozwala na operacje na liczbach całkowitych dłuższych niż 64 bity.
+ // Liczby są przechowywane jako tablica bajtów
+ // i modyfikowane za pomocą funkcji wbudowanych w BigInteger
+ //
+ // BigInteger może być zainicjalizowany za pomocą tablicy bajtów lub jako string.
+ BigInteger fooBigInteger = new BigInteger(fooByteArray);
+
+ // BigDecimal - Nieedytowalny typ zmiennej o nieograniczonej długości dla
+ // liczb zmiennoprzecinkowych
+ //
+ // BigDecimal zaiwera 2 części: typ integer o arbitralnej precyzji bez skalowania
+ // oraz 32-bitową skalę
+ //
+ // BigDecimal pozwala programiście na całkowitą kontrolę zaokrąglenia dziesiętnego.
+ // Zalecane jest używanie BigDecimal z wartościami walut.
+ // oraz tam, gdzie absolutna dokładność jest niezbędna.
+ //
+ // BigDecimal można zainicjalizowac używając int, long, double or String
+ // a także inicjalizując nieprzeskalowaną wartość (BigInteger) i skalę (int).
+ BigDecimal fooBigDecimal = new BigDecimal(fooBigInteger, fooInt);
+
+ // Uwaga na konstruktor, który przyjmuje float lub double jako, że
+ // niedokładność float/double będzie przeniesiona do BigDecimal.
+ // Zalecane jest uzywanie konstruktora typu String gdy konieczne jest
+ // uzyskanie absolutnej precyzji.
+ BigDecimal tenCents = new BigDecimal("0.1");
+
+ // String - zmienna tekstowa
+ String fooString = "Tutaj jest mój string!";
+
+ // \n jest symbolem karetki, która rozpoczyna nową linę
+ String barString = "Wyświetlanie w nowej linii?\nNie ma problemu!";
+ // \t jest symbolem tabulatora, który dodaje odstęp.
+ String bazString = "Chesz dodać tabulator?\tBez problemu!";
+ System.out.println(fooString);
+ System.out.println(barString);
+ System.out.println(bazString);
+
+ // Budowanie Stringów
+ // #1 - za pomocą operatora dodawania
+ // To jest podstawowy sposób (zoptymalizowany)
+ String plusConcatenated = "Stringi mogą " + "być łączone " + "operatorem +.";
+ System.out.println(plusConcatenated);
+ // Wyjście: Stringi będą połączone operatorem +.
+
+ // #2 - za pomocą StringBuilder
+ // Ten sposób nie tworzy żadnych pośrednich stringów, jedynie zachowuje
+ // części i wiąże je po kolei gdy wywołane jest toString().
+ // Wskazówka: Ta klasa nie jest bezpieczna z punktu widzenia wątków.
+ // Bezpieczną alternatywą jest (wiążąca się ze spadkiem wydajności)
+ // StringBuffer.
+ StringBuilder builderConcatenated = new StringBuilder();
+ builderConcatenated.append("Możesz ");
+ builderConcatenated.append("użyć ");
+ builderConcatenated.append("klasy StringBuilder.");
+ System.out.println(builderConcatenated.toString()); // dopiero tutaj
+ //budowany jest string
+ // Wyjście: Używany jest StringBuilder.
+
+ // StringBuilder jest wydajny, gdy połączony string nie jest używany aż do końcowego przetworzenia.
+ StringBuilder stringBuilder = new StringBuilder();
+ String inefficientString = "";
+ for (int i = 0 ; i < 10; i++) {
+ stringBuilder.append(i).append(" ");
+ inefficientString += i + " ";
+ }
+ System.out.println(inefficientString);
+ System.out.println(stringBuilder.toString());
+ // inefficientString wymaga dużo więcej pracy przy stworzeniu ponieważ
+ // tworzy string przy każdej iteracji.
+ // Proste łączenie za pomocą + jest kompilowane do StringBuilder i
+ // toString(). Unikaj łączenia stringów w pętlach.
+
+ // #3 - za pomocą String formatter
+ // Inna możliwość, szybka i czytelna.
+ String.format("%s wolisz %s.", "A może", "String.format()");
+ // Wyjście: Być może wolisz String.format().
+
+ // Tablice
+ // Rozmiar tablicy musi być określony przy stworzeniu.
+ // Podane poniżej sposoby są dozwolone prz deklaracji tablicy
+ // <rodzaj>[] <nazwa> = new <rodzaj>[<rozmiar>];
+ // <rodzaj> <nazwa>[] = new <rodzaj>[<rozmiar>];
+ int[] intArray = new int[10];
+ String[] stringArray = new String[1];
+ boolean boolArray[] = new boolean[100];
+
+ // Inny sposób deklaracji i inicjalizacji tablicy
+ int[] y = {9000, 1000, 1337};
+ String names[] = {"Bob", "John", "Fred", "Juan Pedro"};
+ boolean bools[] = {true, false, false};
+
+ // Indeksowanie tablicy - dostęp do elementów
+ System.out.println("intArray @ 0: " + intArray[0]);
+
+ // Tablice zaczynają się z indeksem 0 i są edytowalne.
+ intArray[1] = 1;
+ System.out.println("intArray @ 1: " + intArray[1]); // => 1
+
+ // Inny typ zmiennej, z którymi warto się zapoznać
+ // ArrayLists - Tablice z większą funkcjonalnością
+ // i zmiennym rozmiarem.
+ // LinkedLists - Dwustronnie połączone listy. Wszystkie operacje
+ // na listach zaimpllementowane.
+ // Maps - Mapy zawierające klucz i wartość. Mapa jest interfejsem
+ // i nie może zostać zainicjalizowana.
+ // Rodzaj klucza i wartości dla mapy musi zostać określony
+ // przy inicjalizacji implementującej mapę klasy
+ // Każdy klucz przypisany jest do tylko jednej wartości,
+ // każdy klucz może wystąpić tylko raz (brak duplikatów).
+ // HashMaps - Używa tablicy hashów do implementacji interfejsu mapy
+ // Pozwala to na użycie podstawowych operacji, jak
+ // get i insert, które pozostają niezmiennie wydajne
+ // czasowo nawet dla dużych zestawów danych
+ // TreeMap - Mapa posortowana przez klucze. Każda modyfikacja
+ // utrzymuje sortowanie, zdefiniowane przez komparator
+ // dodany przy inicjalizacji lub porównanie każdego obiektu
+ // jeśli zaimplementowany jest interfejs Comparable.
+ // Niepowodzenie kluczy wimplemntacji Comparable połączone
+ // z niepowodzeniem dostarczenia komparatora spowoduje
+ // ClassCastExceptions.
+ // Dodawanie i usuwanie kosztuje O(log(n)) czasu,
+ // zalecane jest nieużywanie tego typu jeżeli sortowanie
+ // nie jest przydatne.
+
+ ///////////////////////////////////////
+ // Operatory
+ ///////////////////////////////////////
+ System.out.println("\n->Operatory");
+
+ int i1 = 1, i2 = 2; // Skrót dla wielokrotnych deklaracji
+
+ // Arytmetyka jest prosta
+ System.out.println("1+2 = " + (i1 + i2)); // => 3
+ System.out.println("2-1 = " + (i2 - i1)); // => 1
+ System.out.println("2*1 = " + (i2 * i1)); // => 2
+ System.out.println("1/2 = " + (i1 / i2)); // => 0 (int/int zwraca int)
+ System.out.println("1/2.0 = " + (i1 / (double)i2)); // => 0.5
+
+ // Modulo
+ System.out.println("11%3 = "+(11 % 3)); // => 2
+
+ // Porównania
+ System.out.println("3 == 2? " + (3 == 2)); // => false
+ System.out.println("3 != 2? " + (3 != 2)); // => true
+ System.out.println("3 > 2? " + (3 > 2)); // => true
+ System.out.println("3 < 2? " + (3 < 2)); // => false
+ System.out.println("2 <= 2? " + (2 <= 2)); // => true
+ System.out.println("2 >= 2? " + (2 >= 2)); // => true
+
+ // Operacje boolowskie
+ System.out.println("3 > 2 && 2 > 3? " + ((3 > 2) && (2 > 3))); // => false
+ System.out.println("3 > 2 || 2 > 3? " + ((3 > 2) || (2 > 3))); // => true
+ System.out.println("!(3 == 2)? " + (!(3 == 2))); // => true
+
+ // Operacje na bitach!
+ /*
+ ~ Odwrócenie bitów
+ << Przesunięcie w lewo
+ >> Przesunięcie w prawo, arytmetyczne/dla wartości ujemnych -signed
+ >>> Przesunięcie w prawo, logiczne/dla wartości dodatnich - unsigned
+ & Bitowe AND
+ ^ Bitowe XOR
+ | Bitowe OR
+ */
+
+ // Operatory inkrementacji
+ int i = 0;
+ System.out.println("\n->In/De-krementacja");
+ // Operatory ++ i -- zwiększają lub zmniejszają o 1 daną wartość.
+ // Jeżeli używane są przed zmienną, wykonywane są przed powrotem zmiennej.
+ // Użyte po zmiennej najpierw zwracają zmienną a następnie dokonują
+ // zmiany wartości.
+ System.out.println(i++); // i = 1, wyświetli 0 (post-increment)
+ System.out.println(++i); // i = 2, wyświetli 2 (pre-increment)
+ System.out.println(i--); // i = 1, wyświetli 2 (post-decrement)
+ System.out.println(--i); // i = 0, wyświetli 0 (pre-decrement)
+
+ ///////////////////////////////////////
+ // Przepływ sterowania
+ ///////////////////////////////////////
+ System.out.println("\n->Przepływ sterowania");
+
+ // Instrukcja if wygląda jak w c
+ int j = 10;
+ if (j == 10) {
+ System.out.println("Wyświetlam się");
+ } else if (j > 10) {
+ System.out.println("A ja nie");
+ } else {
+ System.out.println("Ja też nie");
+ }
+
+ // Pętla while
+ int fooWhile = 0;
+ while(fooWhile < 100) {
+ System.out.println(fooWhile);
+ // Licznik jest zwiększany
+ // Iteruje 100 razy, fooWhile 0,1,2...99
+ fooWhile++;
+ }
+ System.out.println("Wartość fooWhile: " + fooWhile);
+
+ // Pętla do while
+ int fooDoWhile = 0;
+ do {
+ System.out.println(fooDoWhile);
+ // Licznik jest zwiększany
+ // Iteruje 99 razy, fooDoWhile 0->99
+ fooDoWhile++;
+ } while(fooDoWhile < 100);
+ System.out.println("Wartość fooDoWhile: " + fooDoWhile);
+
+ // Pętla for
+ // struktura pętli for => for(<początek>; <warunek>; <krok>)
+ for (int fooFor = 0; fooFor < 10; fooFor++) {
+ System.out.println(fooFor);
+ // Iteruje 10 razy, fooFor 0->9
+ }
+ System.out.println("Wartość fooFor: " + fooFor);
+
+ // Wyjście z zagnieżdżonej, oznaczonej pętli for
+ outer:
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ if (i == 5 && j ==5) {
+ break outer;
+ // wychodzi z zewnętrznej pętli zamiast jednynie z aktualnej z
+ // powodu oznaczenia
+ }
+ }
+ }
+
+ // Pętla for each
+ // Pętla for each może iterować tablice jak i obiekty
+ // które implementują interfejs Iterable.
+ int[] fooList = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ // Struktura for each => for (<element> : <obiekt iterowany>)
+ // należy rozumieć jako: dla każdego elementu w obiekcie iterowanym
+ // uwaga: typ zdefiniowango elementu musi się zgadzać z typem w
+ //obiekcie iterowanym.
+ for (int bar : fooList) {
+ System.out.println(bar);
+ //Iteruje 9 razy i wyświetla 1-9 w nowych liniach
+ }
+
+ // Switch Case
+ // Switch (przełącznik) działa z zmiennymi typu byte, short, char, int.
+ // Działa również z enumeratorami (zobacz typ Enum),
+ // klasą String, i kilkoma specjalnymi klasami które zawierają typy
+ // podstawowe: Character, Byte, Short, and Integer.
+ // Z wersją Java 7 i wyższymi możliwe jest użycie typu String.
+ // Uwagga: Pamiętaj, że nie dodając "break" na końcu danego case
+ // spowoduje przejście do następnego (jeżeli spełniony jest warunek).
+ int month = 3;
+ String monthString;
+ switch (month) {
+ case 1: monthString = "Styczeń";
+ break;
+ case 2: monthString = "Luty";
+ break;
+ case 3: monthString = "Marzec";
+ break;
+ default: monthString = "Inny miesiąc";
+ break;
+ }
+ System.out.println("Wynik Switch Case : " + monthString);
+
+
+ // Try-with-resources (Java 7+)
+ // Try-catch-finally działa zgodnie z oczekiwaniami jednakże w Java 7+
+ // dodatkowo jest dostępny try-with-resources statement.
+ // Try-with-resources upraszcza try-catch-finally automatycznie
+ // usuwając zasoby.
+
+ // Aby użyć try-with-resources, użyj instancji klasy
+ // w części "try". Klasa musi implementować java.lang.AutoCloseable.
+ try (BufferedReader br = new BufferedReader(new FileReader("foo.txt"))) {
+ // Tutaj możesz spróbować wywołac wyjątek.
+ System.out.println(br.readLine());
+ // W Java 7 zasoby będą zawsze usuwane nawet jeśli nastąpi wyjątek.
+ } catch (Exception ex) {
+ // Zasób będzie usunięty zanim wykona się catch.
+ System.out.println("readLine() nie powiódł się.");
+ }
+ // Nie ma potrzeby używać sekcji "finally", jako że BufferedReader
+ // został już zamknięty. Ten sposób może zostać użyty aby uniknąć
+ // pewnych wartości brzegowych gdzie "finally" nie zostałoby wywołane
+ // Więcej na ten temat po angielsku:
+ // https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
+
+
+ // Skrócone instrukcje warunkowe
+ // Dozwolone jest użycie operatora '?' aby szybko sprawdzić warunek
+ // logiczny. Rozumiane jest to jako "Jeśli (warunek) jest spełniony, użyj
+ // <pierwszej wartości>, inaczej, użyj <drugiej wartości>"
+ int foo = 5;
+ String bar = (foo < 10) ? "A" : "B";
+ System.out.println("bar : " + bar); // Wyśwletli "bar : A", poineważ
+ // warunke jest spełniony.
+ // Lub prościej
+ System.out.println("bar : " + (foo < 10 ? "A" : "B"));
+
+
+ ////////////////////////////////////////
+ // Konwersja typów danych
+ ////////////////////////////////////////
+
+ // Konwersja danych
+
+ // Konwersja String do Integer
+ Integer.parseInt("123");//zwraca zmienna typu Integer o wartości "123"
+
+ // Konwersja Integer do String
+ Integer.toString(123);//zwraca zmienną typu String o wartości 123
+
+ // Inne konwersje możesz sprawdzić dla klas:
+ // Double
+ // Long
+ // String
+
+ ///////////////////////////////////////
+ // Klasy i funkcje
+ ///////////////////////////////////////
+
+ System.out.println("\n->Klasy & Funkcje");
+
+ // (definicja klasy Rower nieco niżej)
+
+ // Użyj new aby zainstancjonować klasę
+ Rower trek = new Rower();
+
+ // Wywoływanie metod klasy
+ trek.predkoscZwieksz(3); // Zawsze używaj settera i gettera jako metod
+ trek.setPedalowanie(100);
+
+ // toString zwraca reprezentację typu String tego obiektu.
+ System.out.println("trek info: " + trek.toString());
+
+ // Inicjalizacja za pomocą podwójnego nawiasu
+ // Język Java nie zawiera możliwości stworzenia statycznej kolekcji
+ // Dlatego zwykle odbywa się to w ten sposób:
+ private static final Set<String> KRAJE = new HashSet<String>();
+ static {
+ KRAJE.add("DANIA");
+ KRAJE.add("SZWECJA");
+ KRAJE.add("FINLANDIA");
+ }
+
+ // Jest jednak sprytny sposób aby łatwiej osiągnąc ten sam efekt
+ // używając czegoś nazywanego Double Brace Initialization -
+ // inicjalizacja za pomocą podwójnego nawiasu.
+ private static final Set<String> KRAJE = new HashSet<String>() {{
+ add("DANIA");
+ add("SZWECJA");
+ add("FINLANDIA");
+ }}
+
+ // Pierwszy nawias tworzy nową klasę AnonymousInnerClass,
+ // drugi deklaruje instancję bloku inicjalizacji. Blok ten
+ // jest wywoływany gdy wewnętrzna, anonimowa klasa jest tworzona.
+ // Dany sposób działa nie tylko dla kolekcji, ale również dla
+ // wszystkich nie-finalnych klas.
+
+ } // Koniec metody main
+} // Koniec klasy LearnJava
+
+// Możesz zawrzeć inne, niepubliczne, zewnętrzne klasy w pliku .java,
+// jednak nie jest to zalecane. Zalecane jest dzielenie klas na osobne pliki.
+
+// Składnia deklaracji klasy:
+// <public/private/protected> class <nazwa klasy> {
+// // pola danych, konstruktory, funkcje.
+// // w jężyku Java funkcje są wywoływane jako metody.
+// }
+
+class Rower {
+
+ // Zmienne klasy
+ public int pedalowanie; // Public: Dostępne wszędzie
+ private int predkosc; // Private: Dostępne tylko w klasie
+ protected int przerzutka; // Protected: Dostępne w klasie i podklasach
+ String nazwa; // domyślnie: Dostępne tlyko w danej paczce
+ static String nazwaKlasy; // Zmienna statyczna
+
+ // Blok statyczny
+ // Java nie posiada implemntacji konstruktorów staycznych, ale
+ // posiada blok stayczny, który może być użyty aby zainicjalizować
+ // statyczne zmienne klasy
+ // Ten blok będzie wywołane gdy klasa jest ładowana.
+ static {
+ nazwaKlasy = "Rower";
+ }
+
+ // Konstruktory służą do stworzenia instancji klas
+ // Too jest konstruktor
+ public Rower() {
+ // Możesz wywołać także inny konstruktor:
+ // this(1, 50, 5, "Bontrager");
+ przerzutka = 1;
+ pedalowanie = 50;
+ predkosc = 5;
+ nazwa = "Bontrager";
+ }
+ // To jest konstruktor, który przyjmuje argumenty
+ public Rower(int poczatkowePedalowanie, int poczatkowaPredkosc, int początkowaPrzerzutka,
+ String nazwa) {
+ this.przerzutka = początkowaPrzerzutka;
+ this.pedalowanie = poczatkowePedalowanie;
+ this.predkosc = poczatkowaPredkosc;
+ this.nazwa = nazwa;
+ }
+
+ // Składnia metod:
+ // <public/private/protected> <zwracany rodzaj> <nazwa funkcji>(<argumenty>)
+
+ // Klasy często implementują metody getter i setter dla danych wewnątrz
+
+ // Składnia deklaracji metody:
+ // <dostępność> <zwracany rodzaj> <nawa metody>(<argumenty>)
+ public int getPedalowanie() {
+ return pedalowanie;
+ }
+
+ // metody void nie wymagają słowa kluczowego return, nic nie zwracają
+ public void setPedalowanie(int newValue) {
+ pedalowanie = newValue;
+ }
+ public void setPrzerzutka(int newValue) {
+ przerzutka = newValue;
+ }
+ public void predkoscZwieksz(int inkrement) {
+ predkosc += inkrement;
+ }
+ public void predkoscZmniejsz(int dekrement) {
+ predkosc -= dekrement;
+ }
+ public void nadajNazwe(String nowaNazwa) {
+ nazwa = nowaNazwa;
+ }
+ public String zwrocNazwe() {
+ return nazwa;
+ }
+
+ // Metoda do wyświetlenia wartości atrybutów danego obiektu.
+ @Override // Dziedziczy z klasy obiektu.
+ public String toString() {
+ return "przerzutka: " + przerzutka + " pedalowanie: " + pedalowanie + " predkosc: " + predkosc +
+ " nazwa: " + nazwa;
+ }
+} // koniec klasy Rower
+
+// PennyFarthing jest podklasą klasy Rower
+class PennyFarthing extends Rower {
+ // (Penny Farthing to rower z wielkim przednim kołem.
+ // Nie ma przerzutek.)
+
+ public PennyFarthing(int poczatkowePedalowanie, int poczatkowaPredkosc) {
+ // Wywołanie kostruktora klasy z której dziedziczymy za pomocą super
+ super(poczatkowePedalowanie, poczatkowaPredkosc, 0, "PennyFarthing");
+ }
+
+ // Używamy annotacji @annotation przy przeciążaniu metod.
+ // Aby dowiedzieć się więcej o annotacjach przydatne jest przejrzenie
+ // (w języku angielskim):
+ // http://docs.oracle.com/javase/tutorial/java/annotations/
+ @Override
+ public void setPrzerzutka(int przerzutka) {
+ this.przerzutka = 0;
+ }
+}
+
+// Rzutowanie
+// Jako, że klasa PennyFarthing dziedziczy z klasy Rower, możemy uznać, że
+// instancja PennyFarthing jest typu Rower i napisać :
+// Rower rower = new PennyFarthing();
+// Dana operacja jest rzutowaniem obiektu, gdzie jego domyślna klasa jest inna niż docelowa.
+// Więcej szczegółów i przykładów oraz ciekawych konceptów (po angielsku):
+// https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
+
+// Interfejsy
+// Składnia deklaracji interfejsu
+// <dostępność> interface <nazwa interfejsu> extends <super-interfaces> {
+// // Zmienne typu constant
+// // Deklaracje metod
+// }
+
+// Przykład - Jedzenie:
+public interface Jadalne {
+ public void jedz(); // Każda klasa która implemetuje ten interfejs musi
+ // implementować tę metodę.
+}
+
+public interface Przetrawialne {
+ public void przetrawiaj();
+ // Wraz z Java 8, interfejsy mogą mieć metodę domyślną.
+ public default void defaultMethod() {
+ System.out.println("Hej z metody domyślnej ...");
+ }
+}
+
+// Teraz stworzymy klasę, która zaimplementuje oba interfejsy.
+public class Owoc implements Jadalne, Przetrawialne {
+ @Override
+ public void jedz() {
+ // ...
+ }
+
+ @Override
+ public void przetrawiaj() {
+ // ...
+ }
+}
+
+// W Javie możesz dziedziczyć jedynie z jednej klasy, jednak implementować
+// wiele interfejsów. Na przykład:
+public class Przyklad extends Przodek implements Interfejs1,
+ Interfejs2 {
+ @Override
+ public void Interfejs1Metoda() {
+ }
+
+ @Override
+ public void Interfejs2Metoda() {
+ }
+
+}
+
+// Klasy abstrakcyjne
+
+// Składnia deklaracji klasy abstrakcyjnej
+// <dostępność> abstract class <nawa klasy abstrakcyjnej> extends
+// <superklasy, z których dziedziczy> {
+// // Zmienne i stałe
+// // Deklaracje metod
+// }
+
+// Klasy abstrakcyjne nie mogą posiadać instancji.
+// Klasy abstrakcyjne mogą definiować metody abstrakcyjne.
+// Metody abstrakcyjne nie mają ciała funkcji i są oznaczone jako abstrakcyjne.
+// Nieabstrakcyjne klasy-dzieci muszą przeciążać wszystkie abstrakcyjne metody
+// superklasy.
+// Klasy abstrakcyjne są użyteczne gdy wymagana jest powtarzalna logika działania,
+// jednak należy zaauważyć, że jako, że wymagają dziedziczenia, łamią
+// zasadę "Composition over inheritance". Rozważ inne podejścia używając
+// kompozycji. https://en.wikipedia.org/wiki/Composition_over_inheritance
+
+public abstract class Zwierze
+{
+ private int wiek;
+
+ public abstract void dajGlos();
+
+ // Metody mogą mieć ciało
+ public void jedz()
+ {
+ System.out.println("Jestem zwierzeciem i jem.");
+ // Uwaga: Możliwy jest dostęp do zmiennych prywatnych.
+ wiek = 30;
+ }
+
+ public void wyswietlWiek()
+ {
+ System.out.println(wiek);
+ }
+
+ // Klasy abstrakcyjne mogą mieć metodę główną.
+ public static void main(String[] args)
+ {
+ System.out.println("Jestem abstrakcyjna");
+ }
+}
+
+class Pies extends Zwierze
+{
+ // Musimy przeciążyć wszystkie abstrakcyjne metody z klasy abstrakcyjnej
+ @Override
+ public void dajGlos()
+ {
+ System.out.println("Hau");
+ // wiek = 30; ==> BLAD! wiek jest typu private dla Zwierze
+ }
+
+ // NOTE: Wystąpi błąd jeżeli użyto annotacji @Override jako, że Java
+ // nie pozwala na przeciążanie metod statycznych.
+ // Występuje tutaj METHOD HIDING - ukrywanie metod.
+ // Więcej w poście na SO: http://stackoverflow.com/questions/16313649/
+ public static void main(String[] args)
+ {
+ Pies pluto = new Pies();
+ pluto.dajGLos();
+ pluto.jedz();
+ pluto.wyswietlWiek();
+ }
+}
+
+// Klasy finalne
+
+// Składnia deklaracji klasy finalnej
+// <dostępność> final <nazwa klasy finalnej> {
+// // Zmienne i stałe
+// // Deklaracje Metody
+// }
+
+// Klasy finalne są klasami, które nie mogą być użyte do dziedziczenia, są więc
+// z założenia ostatnim elementem dziedziczenia. W ten sposób są przeciwnością
+// klas abstrakcyjnych, które z założenia muszą być dziedziczone.
+public final class TygrysSzablozebny extends Zwierze
+{
+ // Nadal musimy przeciążyć metody abstrakcyjne klasy abstrakcyjnej Zwierze
+ @Override
+ public void dajGlos()
+ {
+ System.out.println("Roar");
+ }
+}
+
+// Metody finalne
+public abstract class Ssak
+{
+ // Składnia metody finalnej:
+ // <dostępność> final <zwracany rodzaj> <nazwa funkcji>(<argumenty>)
+
+ // Metody finalne, jak klasy finalne nie mogą być przeciążane
+ // i są w ten sposób ostatecznymi implementacjami danej metody.
+ public final boolean jestStalocieplny()
+ {
+ return true;
+ }
+}
+
+// Enumeratory
+//
+// Enumerator jest specjalnym tyme danej, która pozwala zmiennej na bycie
+// zestawem wcześniej zdefiniowanych stałych. Zmienna musi być równa jednej z
+// wartości wcześniej zdefiniowanych. Jako, że są to stałe, nazwy pól typu enum
+// są pisane wielkimi literami. W języku Java typ enum definiujemy przez użycie
+// słowa enum. Na przykład aby zdefiniować dni tygodnia:
+public enum Dzien {
+ PONIEDZIALEK, WTOREK, SRODA, CZWARTEK,
+ PIATEK, SOBOTA, NIEDZIELA
+}
+
+// We can use our enum Day like that:
+public class EnumTest {
+ // Zmienna typu enum
+ Dzien dzien;
+
+ public EnumTest(Dzien dzien) {
+ this.dzien = dzien;
+ }
+
+ public void opiszDzien() {
+ switch (dzien) {
+ case PONIEDZIALEK:
+ System.out.println("Nie lubię poniedziałku!");
+ break;
+ case PIATEK:
+ System.out.println("Piątki są dużo lepsze.");
+ break;
+ case SOBOTA:
+ case NIEDZIELA:
+ System.out.println("Weekendy są najlepsze.");
+ break;
+ default:
+ System.out.println("Środek tygodnia jest taki sobie.");
+ break;
+ }
+ }
+
+ public static void main(String[] args) {
+ EnumTest pierwszyDzien = new EnumTest(Dzien.PONIEDZIALEK);
+ pierwszyDzien.opiszDzien(); // => Nie lubię poniedziałku!
+ EnumTest trzeciDzien = new EnumTest(Dzien.SRODA);
+ trzeciDzien.opiszDzien(); // => Środek tygodnia jest taki sobie.
+ }
+}
+
+// Typ enum jest bardziej wszechstronny niż powyższa demostracja.
+// Ciało typu enum może zawierać metody i inne pola.
+// Rzuć okiem na (angielski) https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
+
+// Wprowadzenie do wyrażeń lambda
+//
+// Nowe w Javie 8 są wyrażenia lambda. Lambdy znajdujemy zwykle w funkcyjnych
+// językach programowania, co oznacza, że są metodami, które potrafią być
+// stowrzone bez klasy i przekazywane jak gdyby były obiektem oraz wykonywane
+// gdy zajdzie potrzeba.
+//
+// Ostatnia uwaga - lambdy muszą implementować funcjonalny interfejs.
+// Interfels funkcjonalny to taki, który ma jedynie jedną zadeklarowaną metodę
+// abstrakcyjną, ale może mieć dowolną ilość domyślnych metod. Wyrażenia lambda
+// mogą być używane jako instancje tego interfejsu. Każdy inteferjs, który
+// spełnia wymagania jest traktowany jako funkcjonalny. Więcej o interfejsach
+// znajdziesz powyżej, w odpowiedniej sekcji.
+//
+import java.util.Map;
+import java.util.HashMap;
+import java.util.function.*;
+import java.security.SecureRandom;
+
+public class Lambdas {
+ public static void main(String[] args) {
+ // Składnia deklaracji lambdy:
+ // <zero lub więcej parametrów> -> <ciało wyrażenia lub blok instrukcji>
+
+ // Poniżej w przykładzie użyjemy tablicy z hashowaniem.
+ Map<String, String> planety = new HashMap<>();
+ planety.put("Merkury", "87.969");
+ planety.put("Wenus", "224.7");
+ planety.put("Ziemia", "365.2564");
+ planety.put("Mars", "687");
+ planety.put("Jowisz", "4,332.59");
+ planety.put("Saturn", "10,759");
+ planety.put("Uran", "30,688.5");
+ planety.put("Neptun", "60,182");
+
+ // Lambda z zerową liczbą parametrów używając funkcjonalnego interfejsu
+ // Supplier z java.util.function.Supplier. Faktyczną lambdą jest częśc
+ // po numPlanets =.
+ Supplier<String> numPlanety = () -> Integer.toString(planety.size());
+ System.out.format("Liczba planet: %s\n\n", numPlanety.get());
+
+ // Lambda z jednym parametrem używająca funkcjonalnego interfejsu
+ // Consumer z java.util.function.Consumer.planety jest mapą, która
+ // wimplementuje Collection jak i Iterable. Użyty forEach pochodzi z
+ // Iterable i jest użyty w lambdzie na każdym elemencie kolekcji
+ // Domyślna implementacja forEach wygląda tak:
+ /*
+ for (T t : this)
+ action.accept(t);
+ */
+
+ // Faktyczna lambda jest parametrem przekazywanym do forEach.
+ planety.keySet().forEach((p) -> System.out.format("%s\n", p));
+
+ // Jeżeli przekazujemy tyklo pojedynczy argumentpowyższy zapis możemy
+ // przekształcić do (zauważ brak nawiasów dookoła p):
+ planety.keySet().forEach(p -> System.out.format("%s\n", p));
+
+ // Śledząc powyższe widzimy, że planety jest typu HashMap, a keySet()
+ // zwraca zestaw kluczy, forEach stosuje o każdego elementu lambdę:
+ // (parameter p) -> System.out.format("%s\n", p). Za każdym razem
+ // element jest uznawany jako "konsumowany" i wyrażenie (wyrażenia)
+ // w lambdzie są wykonywane. Pamiętaj, że ciało lambdy to część po
+ // symbolu ->.
+
+ // Powyższy przykład bez użycia lambdy wyglądałby tradycyjnie tak:
+ for (String planeta : planety.keySet()) {
+ System.out.format("%s\n", planeta);
+ }
+
+ // Poniższy przykład różni się od powyższego sposobem implementacji
+ // forEach: forEach użyty w klasie HashMap implementuje intefejs Map.
+ // Poniższy forEach przyjmuje BiConsumer, który ogólnie ujmując jest
+ // wymyślnym sposobem stwierdzenia, że zajmuje się zestawem par
+ // klucz-wartość Key -> Value dla każdego klucza. Ta domyślna
+ // implementacja działa jak:
+ /*
+ for (Map.Entry<K, V> entry : map.entrySet())
+ action.accept(entry.getKey(), entry.getValue());
+ */
+
+ // Faktyczna lambda jest parametrem przekazywanym do forEach.
+ String orbity = "%s okrąża Słońce w %s dni.\n";
+ planety.forEach((K, V) -> System.out.format(orbity, K, V));
+
+ // Powyższe bez użycia lambdy wyglądałoby tradycyjnie tak:
+ for (String planet : planety.keySet()) {
+ System.out.format(orbity, planet, planety.get(planet));
+ }
+
+ // Lub jeżeli postępujemy zgodnie ze specyfikacją domyślnej implementacji:
+ for (Map.Entry<String, String> planeta : planety.entrySet()) {
+ System.out.format(orbity, planeta.getKey(), planeta.getValue());
+ }
+
+ // Podane przykłady pokrywają jedynie podstawowe zastosowanie wyrażeń
+ // lambda. Być może wydają się one niezbyt przydatne, jednak należy
+ // pamiętać, że lambdy można stworzyć jako obiekty, które nastepnie mogą
+ // zostać przekazane jako parametry do innych metod.
+ }
+}
+```
+
+## Dalsze materiały
+
+Linki zamieszczone poniżej służą pomocą w zrozumieniu wybranego tematu, w razie braku rozwiązania wyszukanie w Google zwykle służy pomocą
+
+**Oficjalne poradniki Oracle po angielsku**:
+
+* [Tutorial w Javie od Sun / Oracle](https://docs.oracle.com/javase/tutorial/index.html)
+
+* [Modyfikacje poziomu dostępu w Java](https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html)
+
+* [Koncepty programowania obiektowego](https://docs.oracle.com/javase/tutorial/java/concepts/index.html):
+ * [Dziedziczenie](https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html)
+ * [Polimorfizm](https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html)
+ * [Abstrakcja](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)
+
+* [Wyjątki](https://docs.oracle.com/javase/tutorial/essential/exceptions/index.html)
+
+* [Interfejsy](https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html)
+
+* [Uogólnianie](https://docs.oracle.com/javase/tutorial/java/generics/index.html)
+
+* [Konwencja kodu Java](https://www.oracle.com/technetwork/java/codeconvtoc-136057.html)
+
+* Nowości z Java 8:
+ * [Funkcje Lambda (programowanie funkcyjne)](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)
+ * [Data y czas API (java.time package)](http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html)
+
+**Kursy po polsku**
+
+* [PJWSTK - Podstawy programowania w języku Java](http://edu.pjwstk.edu.pl/wyklady/ppj/scb/)
+
+* [PJWSTK - Programowanie obiektowe w języku Java](http://edu.pjwstk.edu.pl/wyklady/poj/scb/)
+
+**Tutoriale i ćwiczenia online po angielsku**
+
+* [Learneroo.com - Learn Java](http://www.learneroo.com)
+
+* [Codingbat.com](http://codingbat.com/java)
+
+* [Codewars - Java Katas](https://www.codewars.com/?language=java)
+
+**Książki po angielsku**:
+
+* [Head First Java](http://www.headfirstlabs.com/books/hfjava/)
+
+* [Thinking in Java](http://www.mindview.net/Books/TIJ/)
+
+* [Objects First with Java](https://www.amazon.com/Objects-First-Java-Practical-Introduction/dp/0132492660)
+
+* [Java The Complete Reference](https://www.amazon.com/gp/product/0071606300)
diff --git a/prolog.html.markdown b/prolog.html.markdown
index f7b55ac6..d4c28cba 100644
--- a/prolog.html.markdown
+++ b/prolog.html.markdown
@@ -75,7 +75,7 @@ magicNumber(42).
?- 2 = 3. % False - equality test
?- X = 3. % X = 3 - assignment
?- X = 2, X = Y. % X = Y = 2 - two assignments
- % Note Y is assigned to, even though it is
+ % Note Y is assigned too, even though it is
% on the right hand side, because it is free
?- X = 3, X = 2. % False
% First acts as assignment and binds X=3
diff --git a/protocol-buffer-3.html.markdown b/protocol-buffer-3.html.markdown
new file mode 100644
index 00000000..46065536
--- /dev/null
+++ b/protocol-buffer-3.html.markdown
@@ -0,0 +1,247 @@
+---
+language: protocol-buffers
+filename: protocol-buffers.proto
+contributors:
+ - ["Shankar Shastri", "https://github.com/shankarshastri"]
+---
+# Protocol Buffers
+
+## Why Protocol Buffers
+
+Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler.
+You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.
+Protocol Buffers are Schema Of Messages. They are language agnostic.
+They can be converted to binary and converted back to message formats using the code generated by the protoc compiler for various languages.
+
+```
+/*
+* Language Syntax
+*/
+
+/*
+* Specifying Syntax Of Protocol Buffer Version
+* Specifying Which Protocol Buffer Version To Use
+* It can be usually proto3 or proto2
+*/
+syntax = "proto3";
+
+/*
+* Declaring Message In Protocol Buffer:
+* As you can see, each field in the message definition has a unique number.
+* These field numbers are used to identify your fields in the message binary format,
+* and should not be changed once your message type is in use.
+* Note that field numbers in the range 1 through 15 take one byte to encode, including the field number and the field's type (you can find out more about this in Protocol Buffer Encoding).
+* Field numbers in the range 16 through 2047 take two bytes. So you should reserve the numbers 1 through 15 for very frequently occurring message elements.
+* Remember to leave some room for frequently occurring elements that might be added in the future.
+* The smallest field number you can specify is 1, and the largest is 2^29 - 1, or 536,870,911.
+* You also cannot use the numbers 19000 through 19999 (FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber),
+* as they are reserved for the Protocol Buffers implementation - the protocol buffer compiler will complain if you use one of these reserved numbers in your .proto.
+* Similarly, you cannot use any previously reserved field numbers.
+*
+*/
+
+/*
+Syntax For Declaring Message:
+ message ${MessageName} {
+ ${Scalar Value Type} ${FieldName1} = ${Tag Number1};
+ .
+ .
+ .
+ ${Scalar Value Type} ${FieldNameN} = ${Tag NumberN};
+ }
+
+Default Values Will be applied any case if the message doesn't contain a existing field defined
+in the message definition
+*/
+
+message MessageTypes {
+ /*
+ * Scalar Value Types
+ */
+ string stringType = 1; // A string must always contain UTF-8 encoded or 7-bit ASCII text. Default value = ""
+
+ // Number Types, Default Value = 0
+ int32 int32Type = 2; // Uses Variable Length Encoding. Inefficient For Negative Numbers, Instead Use sint32.
+ int64 int64Type = 3; // Uses Variable Length Encoding. Inefficient For Negative Numbers, Instead Use sint64.
+ uint32 uInt32Type = 4; // Uses Variable Length Encoding
+ uint64 uInt64Type = 5; // Uses Variable Length Encoding
+ sint32 sInt32Type = 6; // Uses Variable Length Encoding. They are efficient in encoding for negative numbers.
+ // Use this instead of int32 for negative numbers
+ sint64 sInt64Type = 7; // Uses Variable Length Encoding. They are efficient in encoding for negative numbers.
+ // Use this instead of int64 for negative numbers.
+
+ fixed32 fixed32Type = 8; // Always four bytes. More efficient than uint32 if values are often greater than 2^28.
+ fixed64 fixed64Type = 9; // Always eight bytes. More efficient than uint64 if values are often greater than 2^56
+
+ sfixed32 sfixed32Type = 10; // Always four bytes.
+ sfixed64 sfixed64Type = 11; // Always Eight bytes.
+
+ bool boolType = 12; // Boolean Type. Default Value = false
+
+ bytes bytesType = 13; // May contain any arbitrary sequence of bytes. Default Value = Empty Bytes
+
+ double doubleType = 14;
+ float floatType = 15;
+
+ enum Week {
+ UNDEFINED = 0; // Tag 0 is always used as default in case of enum
+ SUNDAY = 1;
+ MONDAY = 2;
+ TUESDAY = 3;
+ WEDNESDAY = 4;
+ THURSDAY = 5;
+ FRIDAY = 6;
+ SATURDAY = 7;
+ }
+ Week wkDayType = 16;
+
+ /*
+ * Defining Collection Of Scalar Value Type
+ * Syntax: repeated ${ScalarType} ${name} = TagValue
+ */
+ repeated string listOfString = 17; // List[String]
+}
+
+/*
+* Defining Defined Message Types In Other Message Definition
+*/
+message Person {
+ string fname = 1;
+ string sname = 2;
+}
+
+message City {
+ Person p = 1;
+}
+
+/*
+* Nested Message Definitions
+*/
+
+message NestedMessages {
+ message FirstLevelNestedMessage {
+ string firstString = 1;
+ message SecondLevelNestedMessage {
+ string secondString = 2;
+ }
+ }
+ FirstLevelNestedMessage msg = 1;
+ FirstLevelNestedMessage.SecondLevelNestedMessage msg2 = 2;
+}
+
+/*
+* Importing Message From A File
+*/
+
+// one.proto
+// message One {
+// string oneMsg = 1;
+// }
+
+// two.proto
+// import "myproject/one.proto"
+// message Two {
+// string twoMsg = 2;
+// }
+
+
+/*
+* Advanced Topics
+*/
+
+/*
+* Handling Message Type Changes:
+* Never Change/Use The TagNumber Of A Message Field Which Was Removed
+* We should use reserved in case of message definition update.
+* (https://developers.google.com/protocol-buffers/docs/proto3#updating)
+*/
+
+/*
+* Reserved Fields
+* It's used in case if we need to add/remove new fields into message.
+* Using Reserved Backward and Forward Compatibility Of Messages can be achieved
+*/
+
+
+message ReservedMessage {
+ reserved 0, 1, 2, 3 to 10; // Set Of Tag Numbers Which Can't be reused.
+ reserved "firstMsg", "secondMsg", "thirdMsg"; // Set Of Labels Which Can't Be reused.
+}
+
+/*
+* Any
+* The Any message type lets you use messages as embedded types without having their .proto definition.
+* An Any contains an arbitrary serialized message as bytes,
+* along with a URL that acts as a globally unique identifier for and resolves to that message's type.
+* For Any to work we need to import it as shown below.
+*/
+/*
+ import "google/protobuf/any.proto";
+ message AnySampleMessage {
+ repeated google.protobuf.Any.details = 1;
+ }
+
+*/
+
+
+/*
+* OneOf
+* There are cases, wherein only one field at-most might be present as part of the message.
+* Note: OneOf messages can't be repeated.
+*/
+
+message OneOfMessage {
+ oneof msg {
+ string fname = 1;
+ string sname = 2;
+ };
+}
+
+/*
+* Maps
+* Map fields cannot be repeated.
+* Ordering Of A Map Is Not Guaranteed.
+*/
+
+message MessageWithMaps {
+ map<string, string> mapOfMessages = 1;
+}
+
+
+/*
+* Packages
+* Used for preventing name clashes between protocol message types
+* Syntax:
+ package ${packageName};
+
+ To Access the package;
+ ${packageName}.${messageName} = ${tagNumber};
+*/
+
+/*
+* Services
+* Message Types Defined For Using In RPC system.
+* When protoc compiler generates for various languages it generates stub methods for the services.
+*/
+
+message SearchRequest {
+ string queryString = 1;
+}
+
+message SearchResponse {
+ string queryResponse = 1;
+}
+service SearchService {
+ rpc Search (SearchRequest) returns (SearchResponse);
+}
+```
+
+## Generating Classes In Various Languages For Protocol Buffers
+
+```shell
+protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto
+```
+
+## References
+
+[Google Protocol Buffers](https://developers.google.com/protocol-buffers/)
diff --git a/pt-br/bash-pt.html.markdown b/pt-br/bash-pt.html.markdown
index 3a48d994..86d1a8ea 100644
--- a/pt-br/bash-pt.html.markdown
+++ b/pt-br/bash-pt.html.markdown
@@ -33,7 +33,7 @@ diretamente no shell.
# Exemplo simples de hello world:
echo Hello World!
-# Cada comando começa com uma nova linha, ou após um ponto virgula:
+# Cada comando começa com uma nova linha, ou após um ponto e vírgula:
echo 'Essa é a primeira linha'; echo 'Essa é a segunda linha'
# A declaração de variáveis é mais ou menos assim
@@ -41,14 +41,14 @@ Variavel="Alguma string"
# Mas não assim:
Variavel = "Alguma string"
-# Bash interpretará Variavel como um comando e tentará executar e lhe retornar
+# Bash interpretará Variavel como um comando e tentará executar e lhe retornará
# um erro porque o comando não pode ser encontrado.
# Ou assim:
Variavel= 'Alguma string'
-# Bash interpretará 'Alguma string' como um comando e tentará executar e lhe retornar
+# Bash interpretará 'Alguma string' como um comando e tentará executar e lhe retornará
# um erro porque o comando não pode ser encontrado. (Nesse caso a a parte 'Variavel='
-# é vista com uma declaração de variável valida apenas para o escopo do comando 'Uma string').
+# é vista com uma declaração de variável válida apenas para o escopo do comando 'Uma string').
# Usando a variável:
echo $Variavel
@@ -65,12 +65,12 @@ echo ${Variavel/Alguma/Uma}
# Substring de uma variável
Tamanho=7
echo ${Variavel:0:Tamanho}
-# Isso retornará apenas os 7 primeiros caractéres da variável
+# Isso retornará apenas os 7 primeiros caracteres da variável
# Valor padrão de uma variável
echo ${Foo:-"ValorPadraoSeFooNaoExistirOuEstiverVazia"}
# Isso funciona para nulo (Foo=) e (Foo=""); zero (Foo=0) retorna 0.
-# Note que isso apenas retornar o valor padrão e não mudar o valor da variável.
+# Note que isso apenas retornará o valor padrão e não mudará o valor da variável.
# Variáveis internas
# Tem algumas variáveis internas bem uteis, como
@@ -86,7 +86,7 @@ read Nome # Note que nós não precisamos declarar a variável
echo Ola, $Nome
# Nós temos a estrutura if normal:
-# use 'man test' para mais infomações para as condicionais
+# use 'man test' para mais informações para as condicionais
if [ $Nome -ne $USER ]
then
echo "Seu nome não é o seu username"
@@ -109,7 +109,7 @@ then
echo "Isso vai rodar se $Nome é Daniela ou Jose."
fi
-# Expressões são denotadas com o seguinte formato
+# Expressões são escritas com o seguinte formato
echo $(( 10 + 5))
# Diferentemente das outras linguagens de programação, bash é um shell, então ele
@@ -118,9 +118,9 @@ echo $(( 10 + 5))
ls
#Esse comando tem opções que controlam sua execução
-ls -l # Lista todo arquivo e diretorio em linhas separadas
+ls -l # Lista todo arquivo e diretório em linhas separadas
-# Os resultados do comando anterior pode ser passado para outro comando como input.
+# Os resultados do comando anterior podem ser passados para outro comando como input.
# O comando grep filtra o input com o padrão passado. É assim que listamos apenas
# os arquivos .txt no diretório atual:
ls -l | grep "\.txt"
@@ -241,7 +241,7 @@ head -n 10 arquivo.txt
sort arquivo.txt
# reporta ou omite as linhas repetidas, com -d você as reporta
uniq -d arquivo.txt
-# exibe apenas a primeira coluna após o caráctere ','
+# exibe apenas a primeira coluna após o caractere ','
cut -d ',' -f 1 arquivo.txt
# substitui todas as ocorrencias de 'okay' por 'legal' em arquivo.txt (é compativel com regex)
sed -i 's/okay/legal/g' file.txt
diff --git a/pt-br/c-pt.html.markdown b/pt-br/c-pt.html.markdown
index e1c27958..4e55f068 100644
--- a/pt-br/c-pt.html.markdown
+++ b/pt-br/c-pt.html.markdown
@@ -8,6 +8,7 @@ translators:
- ["João Farias", "https://github.com/JoaoGFarias"]
- ["Elton Viana", "https://github.com/eltonvs"]
- ["Cássio Böck", "https://github.com/cassiobsilva"]
+ - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
lang: pt-br
filename: c-pt.el
---
@@ -641,7 +642,7 @@ typedef void (*minha_função_type)(char *);
Este é *o* livro sobre C, escrito pelos criadores da linguagem. Mas cuidado - ele é antigo e contém alguns erros (bem,
ideias que não são mais consideradas boas) ou práticas ultrapassadas.
-Outra boa referência é [Learn C the hard way](http://c.learncodethehardway.org/book/).
+Outra boa referência é [Learn C the hard way](http://learncodethehardway.org/c/).
Se você tem uma pergunta, leia [compl.lang.c Frequently Asked Questions](http://c-faq.com).
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 7e8b3f7b..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,367 +19,552 @@ 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
+
+; Para chamar métodos estáticos dentro de classes Java, use /
+(System/currentTimeMillis) ; => retorna um timestamp
-; Use . para chamar métodos. Ou, use o atalho ".method"
-(. (Date.) getTime) ; <a timestamp>
-(.getTime (Date.)) ; exatamente a mesma coisa.
+; Note que não é preciso importar o módulo System, pois ele está sempre presente
-; Use / para chamar métodos estáticos
-(System/currentTimeMillis) ; <a timestamp> (o módulo System 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.
-; O atom é o mais simples. Passe pra ele um valor inicial
-(def my-atom (atom {}))
+; 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 {}))
-; Atualize o atom com um swap!.
-; swap! pega uma funçnao and 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)
+; Para acessar o valor de um atom, você pode usar a função deref ou o operador @:
+@atom-mapa ; => {}
+(deref atom-mapa) ; => {}
-; Use '@' para desreferenciar um atom e acessar seu valor
-my-atom ;=> Atom<#...> (Retorna o objeto do Atom)
-@my-atom ; => {:a 1 :b 2}
+; 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)
-; Abaixo um contador simples usando um atom
-(def counter (atom 0))
-(defn inc-counter []
- (swap! counter inc))
+; Observe que essas chamadas alteraram de fato o valor de atom-mapa. Seu novo valor é:
+@atom-mapa ; => {:a 1 :b 2}
-(inc-counter)
-(inc-counter)
-(inc-counter)
-(inc-counter)
-(inc-counter)
+; Isso é diferente de fazer:
+(def atom-mapa-2 (atom {}))
+(def atom-mapa-3 (assoc @atom-mapa-2 :a 1))
-@counter ; => 5
+; 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}
-; Outras construção STM são refs e agents.
+(class atom-mapa-2) ; => clojure.lang.Atom
+(class atom-mapa-3) ; => clojure.lang.PersistentArrayMap
+
+; 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.
+
+; 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:
+[https://www.braveclojure.com/clojure-for-the-brave-and-true/](https://www.braveclojure.com/clojure-for-the-brave-and-true/)
diff --git a/pt-br/coffeescript-pt.html.markdown b/pt-br/coffeescript-pt.html.markdown
index 8b1094b1..7129a463 100644
--- a/pt-br/coffeescript-pt.html.markdown
+++ b/pt-br/coffeescript-pt.html.markdown
@@ -3,19 +3,20 @@ language: coffeescript
contributors:
- ["Tenor Biel", "http://github.com/L8D"]
- ["Xavier Yao", "http://github.com/xavieryao"]
+ - ["Claudio Busatto", "http://github.com/cjcbusatto"]
translators:
- ["Miguel Araújo", "https://github.com/miguelarauj1o"]
lang: pt-br
filename: learncoffeescript-pt.coffee
---
-CoffeeScript é uma pequena linguagem que compila um-para-um para o JavaScript
-equivalente, e não há interpretação em tempo de execução. Como um dos sucessores
-de JavaScript, CoffeeScript tenta o seu melhor para exibir uma saída legível,
-bem-impressa e bom funcionamento dos códigos JavaScript em todo o tempo de
+CoffeeScript é uma pequena linguagem que compila um-para-um para o JavaScript
+equivalente, e não há interpretação em tempo de execução. Como um dos sucessores
+de JavaScript, CoffeeScript tenta o seu melhor para exibir uma saída legível,
+bem-impressa e bom funcionamento dos códigos JavaScript em todo o tempo de
execução JavaScript.
-Veja também [site do CoffeeScript](http://coffeescript.org/), que tem um tutorial
+Veja também [site do CoffeeScript](http://coffeescript.org/), que tem um tutorial
completo sobre CoffeeScript.
``` coffeescript
@@ -23,35 +24,35 @@ completo sobre CoffeeScript.
#Segue as tendências de muitas linguagens modernas
#Assim, os comentários são iguais a Ruby e Python, eles usam símbolos numéricos.
-###
-Os comentários em bloco são como estes, e eles traduzem diretamente para '/ *'s e
+###
+Os comentários em bloco são como estes, e eles traduzem diretamente para '/ *'s e
'* /'s para o código JavaScript que resulta...
-Você deveria entender mais de semântica de JavaScript antes de continuar...
+Você deveria entender mais de semântica de JavaScript antes de continuar...
###
-# Tarefa:
-numero = 42 #=> número var = 42;
+# Tarefa:
+numero = 42 #=> var numero = 42;
oposto = true #=> var oposto = true;
-# Condições:
-numero = -42 if oposto #=> if (oposto) {número = -42;}
+# Condições:
+numero = -42 if oposto #=> if (oposto) {numero = -42;}
-# Funções:
+# Funções:
quadrado = (x) -> x * x #=> var quadrado = function (x) {return x * x;}
-preencher = (recipiente, líquido = "coffee") ->
- "Preenchendo o #{recipiente} with #{líquido}..."
+preencher = (recipiente, liquido = "coffee") ->
+ "Preenchendo o #{recipiente} with #{liquido}..."
#=>var preencher;
#
-#preencher = function(recipiente, líquido) {
-# if (líquido == null) {
-# líquido = "coffee";
+#preencher = function(recipiente, liquido) {
+# if (liquido == null) {
+# liquido = "coffee";
# }
-# return "Preenchendo o " + recipiente + " with " + líquido + "...";
+# return "Preenchendo o " + recipiente + " with " + liquido + "...";
#};
-# Alcances:
+# Alcances:
list = [1 .. 5] #=> lista var = [1, 2, 3, 4, 5];
# Objetos:
@@ -79,7 +80,7 @@ alert "Eu sabia!" if elvis?
#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("Eu sabia!"); }
# Compressão de Matrizes:
-cubes = (math.cube num for num in list)
+cubes = (math.cube num for num in list)
#=>cubes = (function() {
# var _i, _len, _results;
# _results = [];
@@ -99,8 +100,9 @@ eat alimento for alimento in comidas when alimento isnt 'chocolate'
# if (alimento !== 'chocolate') {
# eat(alimento);
# }
+```
## Recursos adicionais
- [Smooth CoffeeScript](http://autotelicum.github.io/Smooth-CoffeeScript/)
-- [CoffeeScript Ristretto](https://leanpub.com/coffeescript-ristretto/read) \ No newline at end of file
+- [CoffeeScript Ristretto](https://leanpub.com/coffeescript-ristretto/read)
diff --git a/pt-br/csharp-pt.html.markdown b/pt-br/csharp-pt.html.markdown
index 2ff59296..384ca325 100644
--- a/pt-br/csharp-pt.html.markdown
+++ b/pt-br/csharp-pt.html.markdown
@@ -78,15 +78,17 @@ namespace Learning.CSharp
short fooShort = 10000;
ushort fooUshort = 10000;
- // Integer - 32-bit integer
+ // Integer - inteiro de 32 bits
int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647)
uint fooUint = 1; // (0 <= uint <= 4,294,967,295)
-
+ //Números por padrão são int ou uint, dependendo do tamanho.
+
// Long - 64-bit integer
long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615)
- // Numbers default to being int or uint depending on size.
- // L is used to denote that this variable value is of type long or ulong
+
+ // Números por padrão são int ou uint dependendo do tamanho.
+ // L é usado para denotar que o valor da variável é do tipo long ou ulong.
// Double - Double-precision 64-bit IEEE 754 Floating Point
double fooDouble = 123.4; // Precision: 15-16 digits
@@ -308,25 +310,26 @@ on a new line! ""Wow!"", the masses cried";
}
///////////////////////////////////////
- // Converting Data Types And Typecasting
+ // Convertendo Data Types e Typecasting
///////////////////////////////////////
- // Converting data
+ // Convertendo dados
+
+ // Converter String para Integer
- // Convert String To Integer
- // this will throw a FormatException on failure
- int.Parse("123");//returns an integer version of "123"
+ // isso vai jogar um erro FormatException quando houver falha
+ int.Parse("123");//retorna uma verão em Integer da String "123"
- // try parse will default to type default on failure
- // in this case: 0
+ // try parse vai ir por padrão para o typo default quando houver uma falha
+ // nesse caso: 0
int tryInt;
- if (int.TryParse("123", out tryInt)) // Function is boolean
+ if (int.TryParse("123", out tryInt)) // Função booleana
Console.WriteLine(tryInt); // 123
- // Convert Integer To String
- // Convert class has a number of methods to facilitate conversions
+ // Converter Integer para String
+ // A classe Convert possuí métodos para facilitar as conversões
Convert.ToString(123);
- // or
+ // ou
tryInt.ToString();
// Casting
@@ -407,12 +410,12 @@ on a new line! ""Wow!"", the masses cried";
return result;
}
- // You can narrow down the objects that are passed in
+ // Você pode pode restringir os objetos que são passados
public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int>
{
- // We can iterate, since T is a IEnumerable
+ // Nos podemos iterar, desde que T seja um "IEnumerable"
foreach (var item in toPrint)
- // Item is an int
+ // Item é um inteiro
Console.WriteLine(item.ToString());
}
@@ -720,9 +723,9 @@ on a new line! ""Wow!"", the masses cried";
_speed -= decrement;
}
- // properties get/set values
- // when only data needs to be accessed, consider using properties.
- // properties may have either get or set, or both
+ // propriedade recupera e/ou atribui valores (get/set).
+ // quando os dados precisam apenas ser acessados, considere o uso de propriedades.
+ // uma propriedade pode ter "get" ou "set", ou ambos.
private bool _hasTassles; // private variable
public bool HasTassles // public accessor
{
diff --git a/pt-br/css-pt.html.markdown b/pt-br/css-pt.html.markdown
index c73669d0..38937894 100644
--- a/pt-br/css-pt.html.markdown
+++ b/pt-br/css-pt.html.markdown
@@ -14,15 +14,15 @@ translators:
lang: pt-br
---
-Nos primeiros dias da web não havia elementos visuais, apenas texto puro. Mas com maior desenvolvimento de navegadores da web, páginas web totalmente visuais também se tornou comum.
+No início da web não havia elementos visuais, apenas texto puro. Mas com maior desenvolvimento de navegadores da web, páginas web totalmente visuais também se tornara comum.
-CSS ajuda a manter a separação entre o conteúdo (HTML) e o look-and-feel de uma página web.
+CSS ajuda a manter a separação entre o conteúdo (HTML) e o visual de uma página web.
CSS permite atingir diferentes elementos em uma página HTML e atribuir diferentes propriedades visuais para eles.
-Este guia foi escrito para CSS2, embora CSS3 está rapidamente se tornando popular.
+Este guia foi escrito para CSS2, embora CSS3 esteja rapidamente se tornando popular.
-**NOTA:** Porque CSS produz resultados visuais, a fim de aprender, você precisa tentar de tudo em um playground CSS como [dabblet](http://dabblet.com/).
+**NOTA:** Porque CSS produz resultados visuais, a fim de aprender, você precisa treinar em um playground CSS como [dabblet](http://dabblet.com/).
O foco principal deste artigo é sobre a sintaxe e algumas dicas gerais.
```css
@@ -42,7 +42,7 @@ Abaixo um elemento de exemplo:
<div class='class1 class2' id='anID' attr='value' otherAttr='pt-br foo bar' />
*/
-/* Você pode direciona-lo usando uma das suas classes CSS */
+/* Você pode direcioná-lo usando uma das suas classes CSS */
.class1 { }
/* ou ambas as classes! */
@@ -82,9 +82,9 @@ classe div.some [attr $ = 'ue'] {}
/* Você pode selecionar um elemento que é filho de outro elemento */
div.some-parent> .class-name {}
-/* Ou um descendente de um outro elemento. As crianças são os descendentes diretos de
-   seu elemento pai, apenas um nível abaixo da árvore. Pode ser qualquer descendentes
-   nivelar por baixo da árvore. */
+/* Ou um descendente de um outro elemento. Os filhos são os descendentes diretos de
+   seu elemento pai, apenas um nível abaixo da árvore. Pode ser quaisquer descendentes
+   nivelados por baixo da árvore. */
div.some-parent class-name {}
/* Atenção: o mesmo seletor sem espaço tem um outro significado.
@@ -97,7 +97,7 @@ div.some-parent.class-name {}
/* Ou qualquer irmão que o precede */
.i am-qualquer-elemento antes ~ .Este elemento {}
-/* Existem alguns selectores chamado pseudo classes que podem ser usados para selecionar um
+/* Existem alguns seletores chamados pseudo classes que podem ser usados para selecionar um
   elemento quando ele está em um determinado estado */
/* Por exemplo, quando o cursor passa sobre um elemento */
@@ -118,7 +118,7 @@ seletor:first-child {}
/* Qualquer elemento que é o último filho de seu pai */
seletor:last-child {}
-/* Assim como pseudo classes, pseudo elementos permitem que você estilo certas partes de um documento */
+/* Assim como pseudo classes, pseudo elementos permitem que você estilize certas partes de um documento */
/* Corresponde a um primeiro filho virtual do elemento selecionado */
seletor::before {}
@@ -127,7 +127,7 @@ seletor::before {}
seletor::after {}
/* Nos locais apropriados, um asterisco pode ser utilizado como um curinga para selecionar todos
-   elemento */
+   os elementos */
* {} /* */ Todos os elementos
.parent * {} /* */ todos os descendentes
.parent> * {} /* */ todas as crianças
@@ -181,7 +181,7 @@ seletor {
## Uso
-Guardar uma folha de estilo CSS com a extensão `.css`.
+Salvar uma folha de estilo CSS com a extensão `.css`.
```xml
<!-- Você precisa incluir o arquivo css no da sua página <head>. Isto é o
diff --git a/pt-br/cypher-pt.html.markdown b/pt-br/cypher-pt.html.markdown
index 9b60f771..d4400148 100644
--- a/pt-br/cypher-pt.html.markdown
+++ b/pt-br/cypher-pt.html.markdown
@@ -101,7 +101,7 @@ path = shortestPath( (user)-[:KNOWS*..5]-(other) )
Crie consultas
---
-Create a new node
+Crie um novo nó
```
CREATE (a:Person {name:"Théo Gauchoux"})
RETURN a
diff --git a/pt-br/elisp-pt.html.markdown b/pt-br/elisp-pt.html.markdown
index fc2d1e40..aa611097 100644
--- a/pt-br/elisp-pt.html.markdown
+++ b/pt-br/elisp-pt.html.markdown
@@ -111,7 +111,7 @@ filename: learn-emacs-lisp-pt.el
(hello)
;; `C-xC-e' => Hello, I am Bastien
-;; Os parêntesis vazios na definição da função significam que ela
+;; Os parênteses vazios na definição da função significam que ela
;; não aceita argumentos. Mas sempre utilizar `my-name' é um tédio!
;; Vamos dizer à função para aceitar um argumento (o argumento é
;; chamado "name"):
diff --git a/pt-br/groovy-pt.html.markdown b/pt-br/groovy-pt.html.markdown
index aed23df1..1eab9cc3 100644
--- a/pt-br/groovy-pt.html.markdown
+++ b/pt-br/groovy-pt.html.markdown
@@ -17,7 +17,7 @@ Groovy - Uma linguagem dinâmica para a plataforma Java. [Leia mais aqui.](http:
Prepara-se:
1) Instale a máquina virtual de Groovy - http://gvmtool.net/
- 2) Intalse o Groovy: gvm install groovy
+ 2) Instale o Groovy: gvm install groovy
3) Inicie o console groovy digitando: groovyConsole
*/
diff --git a/pt-br/haskell-pt.html.markdown b/pt-br/haskell-pt.html.markdown
index 181aa471..c55a4c03 100644
--- a/pt-br/haskell-pt.html.markdown
+++ b/pt-br/haskell-pt.html.markdown
@@ -41,7 +41,7 @@ o desenvolvimento deste paradigma de programação.
7 * 7 -- 7 vezes 7
7 / 7 -- 7 dividido por 7
--- Divisões não são inteiras, são fracionádas por padrão da linguagem
+-- Divisões não são inteiras, são fracionadas por padrão da linguagem
28736 / 82374 -- 0.3488479374559934
@@ -67,7 +67,7 @@ not False -- Nega uma falácia
7 > 7 -- 7 é maior que 7 ?
-{- Haskell é uma linguagem que tem uma sintáxe bastante familiar na
+{- Haskell é uma linguagem que tem uma sintaxe bastante familiar na
matemática, por exemplo em chamadas de funções você tem:
NomeFunção ArgumentoA ArgumentoB ArgumentoC ...
diff --git a/pt-br/javascript-pt.html.markdown b/pt-br/javascript-pt.html.markdown
index ed4a6ff3..f12d275b 100644
--- a/pt-br/javascript-pt.html.markdown
+++ b/pt-br/javascript-pt.html.markdown
@@ -361,7 +361,7 @@ myObj.myFunc(); // = "Olá mundo!"
var myFunc = myObj.myFunc;
myFunc(); // = undefined
-// Inversamente, uma função pode ser atribuída a um objeto e ganhar a acesso
+// Inversamente, uma função pode ser atribuída à um objeto e ganhar a acesso
// através do `this`, até mesmo se ela não for chamada quando foi definida.
var myOtherFunc = function(){
return this.myString.toUpperCase();
@@ -416,7 +416,7 @@ myNewObj.myNumber; // = 5
// vai olhar imediatamente para o seu prototype.
// Algumas implementações em JS deixam você acessar o objeto prototype com a
-// propriedade mágica `__proto__`. Enquanto isso é util para explicar
+// propriedade mágica `__proto__`. Enquanto isso é útil para explicar
// prototypes, não é parte de um padrão; nós vamos falar de algumas formas de
// usar prototypes depois.
@@ -489,7 +489,7 @@ if (0){
}
// Entretanto, esses objetos encapsulados e as funções originais compartilham
-// um mesmo prototype, portanto você pode adicionar funcionalidades a uma string,
+// um mesmo prototype, portanto você pode adicionar funcionalidades à uma string,
// por exemplo.
String.prototype.firstCharacter = function(){
return this.charAt(0);
diff --git a/pt-br/julia-pt.html.markdown b/pt-br/julia-pt.html.markdown
index 48d97e58..11771d96 100644
--- a/pt-br/julia-pt.html.markdown
+++ b/pt-br/julia-pt.html.markdown
@@ -8,7 +8,7 @@ translators:
lang: pt-br
---
-Julia é uma linguagem homoiconic funcional focada na computação tecnica. Ao mesmo tempo que ela tem todo o poder dos homoiconic macros, funções de primeira classe, e controle de baixo nivel, Julia é tão facil para aprender e usar quanto Python.
+Julia é uma linguagem homoicônica funcional focada na computação técnica. Ao mesmo tempo que ela tem todo o poder dos macros homoicônicos, funções de primeira classe, e controle de baixo nível, Julia é tão fácil para aprender e usar quanto Python.
Este tutorial é baseado no Julia 0.3.
diff --git a/pt-br/latex-pt.html.markdown b/pt-br/latex-pt.html.markdown
index 103af28e..58586522 100644
--- a/pt-br/latex-pt.html.markdown
+++ b/pt-br/latex-pt.html.markdown
@@ -62,7 +62,7 @@ Svetlana Golubeva}
\newpage
-% Muitos artigos de pesquisa possuem um resumo, e pode-se isar comandos
+% Muitos artigos de pesquisa possuem um resumo, e pode-se usar comandos
% predefinidos para isso.
% Isso deve aparecer em sua ordem lógica, portanto, após o topo,
% mas antes das seções principais do corpo.
diff --git a/pt-br/markdown-pt.html.markdown b/pt-br/markdown-pt.html.markdown
index c2aa515d..63afffd5 100644
--- a/pt-br/markdown-pt.html.markdown
+++ b/pt-br/markdown-pt.html.markdown
@@ -4,6 +4,7 @@ contributors:
- ["Dan Turkel", "http://danturkel.com/"]
translators:
- ["Miguel Araújo", "https://github.com/miguelarauj1o"]
+ - ["Monique Baptista", "https://github.com/bfmonique"]
lang: pt-br
filename: learnmarkdown-pt.md
---
@@ -11,23 +12,23 @@ filename: learnmarkdown-pt.md
Markdown foi criado por John Gruber in 2004. Originado para ser fácil de ler e
escrever sintaxe que converte facilmente em HTML (hoje, suporta outros formatos também).
-Dê-me feedback tanto quanto você quiser! / Sinta-se livre para a garfar (fork) e
+Dê-me feedback tanto quanto você quiser! / Sinta-se livre para fazer uma bifurcação (fork) e
puxar o projeto (pull request)
```md
-<!-- Markdown é um superconjunto do HTML, de modo que qualquer arvquivo HTML é
-um arquivo Markdown válido, isso significa que nós podemos usar elementos HTML
+<!-- Markdown é um superconjunto do HTML, de modo que qualquer arquivo HTML é
+um arquivo Markdown válido. Isso significa que nós podemos usar elementos HTML
em Markdown, como o elemento de comentário, e eles não serão afetados pelo analisador
de remarcação. No entanto, se você criar um elemento HTML em seu arquivo Markdown, você
-não pode usar sintaxe remarcação dentro desse conteúdo do elemento.-->
+não pode usar sintaxe de remarcação dentro desse conteúdo do elemento.-->
-<!--Markdown também varia de implementação de um analisador para uma próxima.
+<!--A maneira como o Markdown é analisado varia de software para software.
Este guia vai tentar esclarecer quando as características são universais, ou quando eles são
-específico para um determinado parser -->
+específico para um determinado interpretador -->
<!-- Cabeçalhos -->
<!-- Você pode criar elementos HTML <h1> até <h6> facilmente antecedendo o texto
-que deseja estar nesse elemento por um número de hashes (#) -->
+que deseja estar nesse elemento por um número de cerquilhas (#) -->
# Isto é um cabeçalho <h1>
## Isto é um cabeçalho <h2>
### Isto é um cabeçalho <h3>
@@ -65,7 +66,7 @@ uma ou múltiplas linhas em branco. -->
Este é um parágrafo. Eu estou digitando em um parágrafo, não é legal?
-Agora, eu estou no parágrado 2.
+Agora, eu estou no parágrafo 2.
... Ainda continuo no parágrafo 2! :)
Eu estou no parágrafo três.
@@ -77,19 +78,20 @@ Termino com dois espaços (destacar-me para vê-los).
Há um <br /> acima de mim!
-<!-- Bloco de citações são fáceis e feito com o caractere >. -->
-
+<!-- Bloco de citações são fáceis e feitos com o caractere >. -->
+
> Este é um bloco de citação. Você pode
-> Enrolar manualmente suas linhas e colocar um `>` antes de cada linha ou você pode
-> deixar suas linhas ficarem muito longas e enrolar por conta própria. Não faz diferença,
+> Quebrar manualmente suas linhas e colocar um `>` antes de cada linha ou você pode
+> deixar suas linhas ficarem muito longas e quebrarem por conta própria. Não faz diferença,
> desde que eles começam com um `>`.
+
> Você também pode usar mais de um nível
>> De recuo?
> Como pura é isso?
<!-- Listas -->
-<!-- As listas não ordenadas podem ser feitas usando asteriscos, positivos ou hífens -->
+<!-- As listas não ordenadas podem ser feitas usando asteriscos, soma ou hífens -->
* Item
* Item
@@ -111,10 +113,10 @@ ou
1. Item um
2. Item dois
-3. Tem três
+3. Item três
-<!-- Você não tem poder para rotular os itens corretamente e a remarcação será ainda
-tornar os números em ordem, mas isso pode não ser uma boa idéia -->
+<!-- Você não tem poder para rotular os itens corretamente e a remarcação ainda deixará os
+itens em ordem, mas isso pode não ser uma boa idéia -->
1. Item um
1. Item dois
@@ -137,14 +139,14 @@ uma linha com quatro espaços ou uma guia -->
Isto é código
É assim, sacou?
-<!-- Você pode também re-guia (ou adicionar mais quatro espaços adicionais) para o recuo
+<!-- Você pode também tabular (ou adicionar mais quatro espaços adicionais) para o recuo
dentro do seu código -->
my_array.each do |item|
puts item
end
-<!-- Código embutido pode ser criada usando o caractere de crase ` -->
+<!-- Código embutido pode ser criado usando o caractere de crase ` -->
John não sabia nem o que o função 'goto()' fazia!
@@ -155,13 +157,13 @@ ruby! -->
def foobar
puts "Hello world!"
end
-\`\`\` <!-- Aqui também, não barras invertidas, apenas ``` -->
+\`\`\` <!-- Aqui também, não use barras invertidas, apenas ``` -->
<-- O texto acima não requer recuo, mas o GitHub vai usar a sintaxe
destacando do idioma que você especificar após a ``` -->
<!-- Regra Horizontal (<hr />) -->
-<!-- Regras horizontais são facilmente adicionados com três ou mais asteriscos ou hífens,
+<!-- Regras horizontais são facilmente adicionadas com três ou mais asteriscos ou hífens,
com ou sem espaços. -->
***
@@ -175,7 +177,7 @@ o texto a ser exibido entre parênteses rígidos [] seguido pela url em parênte
[Click aqui!](http://test.com/)
-<!-- Você também pode adicionar um título link usando aspas dentro dos parênteses -->
+<!-- Você também pode adicionar um título para o link usando aspas dentro dos parênteses -->
[Click aqui!](http://test.com/ "Link para Test.com")
diff --git a/pt-br/pascal-pt.html.markdown b/pt-br/pascal-pt.html.markdown
index 3a37271a..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
@@ -157,7 +158,7 @@ BEGIN
r := int; // um real pode receber um valor inteiro (mas não o contrário)
c := str[1]; //acessando elementos de um vetor: vetor[índice do elemento]
- str := 'hello' + 'world'; //concatenção de strings
+ str := 'hello' + 'world'; //concatenação de strings
my_str[0] := 'a'; { só se pode atribuir valores a vetores elemento
por elemento (não o vetor inteiro de uma vez) }
diff --git a/pt-br/php-pt.html.markdown b/pt-br/php-pt.html.markdown
index 8a1c956e..e55f1100 100644
--- a/pt-br/php-pt.html.markdown
+++ b/pt-br/php-pt.html.markdown
@@ -20,7 +20,7 @@ Este documento descreve PHP 5+.
// Duas barras iniciam o comentário de uma linha.
-# O hash (aka pound symbol) também inicia, mas // é mais comum.
+# O hash (conhecido como "pound symbol") também inicia, mas // é mais comum.
/*
O texto envolto por barra-asterisco e asterisco-barra
diff --git a/pt-br/python3-pt.html.markdown b/pt-br/python3-pt.html.markdown
index b72c732a..bc5f801c 100644
--- a/pt-br/python3-pt.html.markdown
+++ b/pt-br/python3-pt.html.markdown
@@ -7,15 +7,16 @@ contributors:
- ["Zachary Ferguson", "http://github.com/zfergus2"]
translators:
- ["Paulo Henrique Rodrigues Pinheiro", "http://www.sysincloud.it"]
+ - ["Monique Baptista", "https://github.com/bfmonique"]
lang: pt-br
filename: learnpython3-pt.py
---
-Python foi criado por Guido Van Rossum nos anos 1990. Ele é atualmente uma
-das mais populares linguagens em existência. Eu fiquei morrendo de amor
-pelo Python por sua clareza sintática. É praticamente pseudocódigo executável.
+Python foi criada por Guido Van Rossum nos anos 1990. Ela é atualmente uma
+das linguagens mais populares existentes. Eu me apaixonei por
+Python por sua clareza sintática. É praticamente pseudocódigo executável.
-Suas opiniões são grandemente apreciadas. Você pode encontrar-me em
+Opniões são muito bem vindas. Você pode encontrar-me em
[@louiedinh](http://twitter.com/louiedinh) ou louiedinh [em]
[serviço de e-mail do google].
@@ -44,7 +45,7 @@ aprender o velho Python 2.7.
8 - 1 # => 7
10 * 2 # => 20
-# Números inteiros por padrão, exceto na divisão, que retorna número
+# Números são inteiros por padrão, exceto na divisão, que retorna número
# de ponto flutuante (float).
35 / 5 # => 7.0
@@ -64,7 +65,7 @@ aprender o velho Python 2.7.
# Exponenciação (x**y, x elevado à potência y)
2**4 # => 16
-# Determine a precedência usando parêntesis
+# Determine a precedência usando parênteses
(1 + 3) * 2 # => 8
# Valores lógicos são primitivos (Atenção à primeira letra maiúscula)
@@ -105,9 +106,8 @@ False or True # => True
1 < 2 < 3 # => True
2 < 3 < 2 # => False
-# (operador 'is' e operador '==') is verifica se duas variáveis
-# referenciam um mesmo objeto, mas == verifica se as variáveis
-# apontam para o mesmo valor.
+# 'is' verifica se duas variáveis representam o mesmo endereço
+# na memória; '==' verifica se duas variáveis têm o mesmo valor
a = [1, 2, 3, 4] # Referência a uma nova lista, [1, 2, 3, 4]
b = a # b referencia o que está referenciado por a
b is a # => True, a e b referenciam o mesmo objeto
@@ -174,7 +174,7 @@ input_string_var = input("Digite alguma coisa: ") # Retorna o que foi digitado e
# Observação: Em versões antigas do Python, o método input() era chamado raw_input()
# Não é necessário declarar variáveis antes de iniciá-las
-# È uma convenção usar letras_minúsculas_com_sublinhados
+# É uma convenção usar letras_minúsculas_com_sublinhados
alguma_variavel = 5
alguma_variavel # => 5
@@ -182,31 +182,31 @@ alguma_variavel # => 5
# Veja Controle de Fluxo para aprender mais sobre tratamento de exceções.
alguma_variavel_nao_inicializada # Gera a exceção NameError
-# Listas armazenam sequencias
+# Listas armazenam sequências
li = []
-# Você pode iniciar com uma lista com alguns valores
+# Você pode iniciar uma lista com valores
outra_li = [4, 5, 6]
-# Adicionar conteúdo ao fim da lista com append
+# Adicione conteúdo ao fim da lista com append
li.append(1) # li agora é [1]
li.append(2) # li agora é [1, 2]
li.append(4) # li agora é [1, 2, 4]
li.append(3) # li agora é [1, 2, 4, 3]
-# Remover do final da lista com pop
+# Remova do final da lista com pop
li.pop() # => 3 e agora li é [1, 2, 4]
# Vamos colocá-lo lá novamente!
li.append(3) # li agora é [1, 2, 4, 3] novamente.
-# Acessar uma lista da mesma forma que você faz com um array
+# Acesse uma lista da mesma forma que você faz com um array
li[0] # => 1
-# Acessa o último elemento
+# Acessando o último elemento
li[-1] # => 3
-# Acessando além dos limites gera um IndexError
+# Acessar além dos limites gera um IndexError
li[4] # Gera o IndexError
# Você pode acessar vários elementos com a sintaxe de limites
-# (É um limite fechado, aberto pra você que gosta de matemática.)
+# Inclusivo para o primeiro termo, exclusivo para o segundo
li[1:3] # => [2, 4]
# Omitindo o final
li[2:] # => [4, 3]
diff --git a/pt-br/stylus-pt.html.markdown b/pt-br/stylus-pt.html.markdown
index 804fa806..40c3c02c 100755
--- a/pt-br/stylus-pt.html.markdown
+++ b/pt-br/stylus-pt.html.markdown
@@ -132,7 +132,7 @@ body {
background-color: $primary-color
}
-/* Apoś compilar ficaria assim: */
+/* Após compilar ficaria assim: */
div {
display: block;
margin-left: auto;
@@ -184,13 +184,13 @@ button
/* Funções
==============================*/
-/* Funções no Stylus permitem fazer uma variedade de tarefas, como por exemplo, menipular algum dado. */
+/* Funções no Stylus permitem fazer uma variedade de tarefas, como por exemplo, manipular algum dado. */
body {
background darken(#0088DD, 50%) // Escurece a cor #0088DD em 50%
}
-/** Criando sua própria função */
+/* Criando sua própria função */
somar(a, b)
a + b
@@ -221,7 +221,7 @@ for <val-name> [, <key-name>] in <expression>
for $item in (1..2) /* Repete o bloco 12 vezes */
.col-{$item}
- width ($item / 12) * 100% /* Calcula a largula pelo número da coluna*
+ width ($item / 12) * 100% /* Calcula a largura pelo número da coluna*
```
diff --git a/pt-br/typescript-pt.html.markdown b/pt-br/typescript-pt.html.markdown
index 077aa2cc..6ece02ff 100644
--- a/pt-br/typescript-pt.html.markdown
+++ b/pt-br/typescript-pt.html.markdown
@@ -10,7 +10,7 @@ lang: pt-br
Typescript é uma linguagem que visa facilitar o desenvolvimento de aplicações em grande escala escritos em JavaScript.
Typescript acrescenta conceitos comuns como classes, módulos, interfaces, genéricos e (opcional) tipagem estática para JavaScript.
-É um super conjunto de JavaScript: todo o código JavaScript é o código do texto dactilografado válido para que possa ser adicionados diretamente a qualquer projeto. O compilador emite typescript JavaScript.
+É um super conjunto de JavaScript: todo o código JavaScript é TypeScript válido então ele pode ser adicionado diretamente a qualquer projeto. O compilador emite typescript JavaScript.
Este artigo irá se concentrar apenas em texto datilografado sintaxe extra, ao contrário de [JavaScript](javascript-pt.html.markdown).
@@ -22,7 +22,7 @@ var isDone: boolean = false;
var lines: number = 42;
var name: string = "Anders";
-// Quando é impossível saber, há o "Qualquer" tipo
+// Quando é impossível saber, há o tipo "Qualquer"
var notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // Ok, definitivamente um boolean
@@ -65,7 +65,7 @@ interface Person {
move(): void;
}
-// Objeto que implementa a "Pessoa" Interface
+// Objeto que implementa a Interface "Pessoa"
// Pode ser tratado como uma pessoa desde que tem o nome e mover propriedades
var p: Person = { name: "Bobby", move: () => {} };
// Os objetos que têm a propriedade opcional:
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/pt-br/whip-pt.html.markdown b/pt-br/whip-pt.html.markdown
index 7bdeec25..b11faf28 100644
--- a/pt-br/whip-pt.html.markdown
+++ b/pt-br/whip-pt.html.markdown
@@ -71,7 +71,7 @@ false
(= 1 1) ; => true
(equal 2 1) ; => false
-; Por exemplo, inigualdade pode ser verificada combinando as funções
+; Por exemplo, desigualdade pode ser verificada combinando as funções
;`not` e `equal`.
(! (= 2 1)) ; => true
diff --git a/pt-br/yaml-pt.html.markdown b/pt-br/yaml-pt.html.markdown
index 0b71877e..07903325 100644
--- a/pt-br/yaml-pt.html.markdown
+++ b/pt-br/yaml-pt.html.markdown
@@ -11,10 +11,10 @@ lang: pt-br
YAML é uma linguagem de serialização de dados projetado para ser diretamente gravável e
legível por seres humanos.
-É um superconjunto de JSON, com a adição de indentação e quebras de linhas sintaticamente significativas, como Python. Ao contrário de Python, entretanto, YAML não permite o caracter literal tab para identação.
+É um superconjunto de JSON, com a adição de identação e quebras de linhas sintaticamente significativas, como Python. Ao contrário de Python, entretanto, YAML não permite o caracter literal tab para identação.
```yaml
-# Commentários em YAML são como este.
+# Comentários em YAML são como este.
###################
# TIPOS ESCALARES #
@@ -33,7 +33,7 @@ chave com espaco: valor
porem: "Uma string, entre aspas."
"Chaves podem estar entre aspas tambem.": "É útil se você quiser colocar um ':' na sua chave."
-# Seqüências de várias linhas podem ser escritos como um 'bloco literal' (utilizando |),
+# Seqüências de várias linhas podem ser escritas como um 'bloco literal' (utilizando |),
# ou em um 'bloco compacto' (utilizando '>').
bloco_literal: |
Todo esse bloco de texto será o valor da chave 'bloco_literal',
@@ -76,7 +76,7 @@ um_mapa_aninhado:
# também permite tipos de coleção de chaves, mas muitas linguagens de programação
# vão reclamar.
-# Sequências (equivalente a listas ou arrays) semelhante à isso:
+# Sequências (equivalente a listas ou arrays) semelhante a isso:
uma_sequencia:
- Item 1
- Item 2
@@ -118,7 +118,7 @@ datetime: 2001-12-15T02: 59: 43.1Z
datetime_com_espacos 2001/12/14: 21: 59: 43.10 -5
Data: 2002/12/14
-# A tag !!binary indica que a string é na verdade um base64-encoded (condificado)
+# A tag !!binary indica que a string é na verdade um base64-encoded (codificado)
# representação de um blob binário.
gif_file: !!binary |
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
diff --git a/pug.html.markdown b/pug.html.markdown
new file mode 100644
index 00000000..0187f1e0
--- /dev/null
+++ b/pug.html.markdown
@@ -0,0 +1,204 @@
+---
+language: Pug
+contributors:
+ - ["Michael Warner", "https://github.com/MichaelJGW"]
+filename: index.pug
+---
+
+## Getting Started with Pug
+
+Pug is a little language that compiles into the HTML. It has cleaner syntax
+with additional features like if statements and loops. It can also be used
+as a server side templating language for server languages like NodeJS.
+
+### The Language
+```pug
+
+//- Single Line Comment
+
+//- Multi Line
+ Comment
+
+//- ---TAGS---
+//- Basic
+div
+//- <div></div>
+h1
+//- <h1></h1>
+my-customTag
+//- <my-customTag></my-customTag>
+
+//- Sibling
+div
+div
+//- <div></div>
+ <div></div>
+
+//- Child
+div
+ div
+//- <div>
+ <div></div>
+ </div>
+
+//- Text
+h1 Hello there
+//- <h1>Hello there</h1>
+
+//- Multi Line Text
+div.
+ Hello
+ There
+//- <div>
+ Hello
+ There
+ </div>
+
+//- ---ATTRIBUTES---
+div(class="my-class" id="my-id" my-custom-attrs="data" enabled)
+//- <div class="my-class" id="my-id" my-custom-attrs="data" enabled></div>
+
+//- Short Hand
+span.my-class
+//- <span class="my-class"></span>
+.my-class
+//- <div class="my-class"></div>
+div#my-id
+//- <div id="my-id"></div>
+div#my-id.my-class
+//- <div class="my-class" id="my-id"></div>
+
+
+//- ---JS---
+- const lang = "pug";
+
+//- Multi Line JS
+-
+ const lang = "pug";
+ const awesome = true;
+
+//- JS Classes
+- const myClass = ['class1', 'class2', 'class3']
+div(class=myClass)
+//- <div class="class1 class2 class3"></div>
+
+//- JS Styles
+- const myStyles = {'color':'white', 'background-color':'blue'}
+div(styles=myStyles)
+//- <div styles="{&quot;color&quot;:&quot;white&quot;,&quot;background-color&quot;:&quot;blue&quot;}"></div>
+
+//- JS Attributes
+- const myAttributes = {"src": "photo.png", "alt": "My Photo"}
+img&attributes(myAttributes)
+//- <img src="photo.png" alt="My Photo">
+- let disabled = false
+input(type="text" disabled=disabled)
+//- <input type="text">
+- disabled = true
+input(type="text" disabled=disabled)
+//- <input type="text" disabled>
+
+//- JS Templating
+- const name = "Bob";
+h1 Hi #{name}
+h1= name
+//- <h1>Hi Bob</h1>
+//- <h1>Bob</h1>
+
+//- ---LOOPS---
+
+//- 'each' and 'for' do the same thing we will use 'each' only.
+
+each value, i in [1,2,3]
+ p=value
+//-
+ <p>1</p>
+ <p>2</p>
+ <p>3</p>
+
+each value, index in [1,2,3]
+ p=value + '-' + index
+//-
+ <p>1-0</p>
+ <p>2-1</p>
+ <p>3-2</p>
+
+each value in []
+ p=value
+//-
+
+each value in []
+ p=value
+else
+ p No Values are here
+
+//- <p>No Values are here</p>
+
+//- ---CONDITIONALS---
+
+- const number = 5
+if number < 5
+ p number is less then 5
+else if number > 5
+ p number is greater then 5
+else
+ p number is 5
+//- <p>number is 5</p>
+
+- const orderStatus = "Pending";
+case orderStatus
+ when "Pending"
+ p.warn Your order is pending
+ when "Completed"
+ p.success Order is Completed.
+ when -1
+ p.error Error Occurred
+ default
+ p No Order Record Found
+//- <p class="warn">Your order is pending</p>
+
+//- --INCLUDE--
+//- File path -> "includes/nav.png"
+h1 Company Name
+nav
+ a(href="index.html") Home
+ a(href="about.html") About Us
+
+//- File path -> "index.png"
+html
+ body
+ include includes/nav.pug
+//-
+ <html>
+ <body>
+ <h1>Company Name</h1>
+ <nav><a href="index.html">Home</a><a href="about.html">About Us</a></nav>
+ </body>
+ </html>
+
+//- Importing JS and CSS
+script
+ include scripts/index.js
+style
+ include styles/theme.css
+
+//- ---MIXIN---
+mixin basic()
+ div Hello
++basic("Bob")
+//- <div>Hello</div>
+
+mixin comment(name, comment)
+ div
+ span.comment-name= name
+ div.comment-text= comment
++comment("Bob", "This is Awesome")
+//- <div>Hello</div>
+
+```
+
+
+### Additional Resources
+- [The Site](https://pugjs.org/)
+- [The Docs](https://pugjs.org/api/getting-started.html)
+- [Github Repo](https://github.com/pugjs/pug)
diff --git a/python3.html.markdown b/python3.html.markdown
index c4f15867..20377801 100644
--- a/python3.html.markdown
+++ b/python3.html.markdown
@@ -8,6 +8,7 @@ contributors:
- ["evuez", "http://github.com/evuez"]
- ["Rommel Martinez", "https://ebzzry.io"]
- ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"]
+ - ["caminsha", "https://github.com/caminsha"]
filename: learnpython3.py
---
@@ -57,11 +58,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
@@ -155,7 +157,7 @@ len("This is a string") # => 16
name = "Reiko"
f"She said her name is {name}." # => "She said her name is Reiko"
# You can basically put any Python statement inside the braces and it will be output in the string.
-f"{name} is {len(name)} characters long."
+f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long."
# None is an object
@@ -228,15 +230,11 @@ li[4] # Raises an IndexError
# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
-li[1:3] # => [2, 4]
-# Omit the beginning and return the list
-li[2:] # => [4, 3]
-# Omit the end and return the list
-li[:3] # => [1, 2, 4]
-# Select every second entry
-li[::2] # =>[1, 4]
-# Return a reversed copy of the list
-li[::-1] # => [3, 4, 2, 1]
+li[1:3] # Return list from index 1 to 3 => [2, 4]
+li[2:] # Return list starting from index 2 => [4, 3]
+li[:3] # Return list from beginning until index 3 => [1, 2, 4]
+li[::2] # Return list selecting every second entry => [1, 4]
+li[::-1] # Return list in reverse order => [3, 4, 2, 1]
# Use any combination of these to make advanced slices
# li[start:end:step]
@@ -462,8 +460,19 @@ prints:
"""
for i in range(4, 8, 2):
print(i)
+
+"""
+To loop over a list, and retrieve both the index and the value of each item in the list
+prints:
+ 0 dog
+ 1 cat
+ 2 mouse
"""
+animals = ["dog", "cat", "mouse"]
+for i, value in enumerate(animals):
+ print(i, value)
+"""
While loops go until a condition is no longer met.
prints:
0
@@ -494,6 +503,26 @@ with open("myfile.txt") as f:
for line in f:
print(line)
+# Writing to a file
+contents = {"aa": 12, "bb": 21}
+with open("myfile1.txt", "w+") as file:
+ file.write(str(contents)) # writes a string to a file
+
+with open("myfile2.txt", "w+") as file:
+ file.write(json.dumps(contents)) # writes an object to a file
+
+# Reading from a file
+with open('myfile1.txt', "r+") as file:
+ contents = file.read() # reads a string from a file
+print(contents)
+# print: {"aa": 12, "bb": 21}
+
+with open('myfile2.txt', "r+") as file:
+ contents = json.load(file) # reads a json object from a file
+print(contents)
+# print: {"aa": 12, "bb": 21}
+
+
# Python offers a fundamental abstraction called the Iterable.
# An iterable is an object that can be treated as a sequence.
# The object returned by the range function, is an iterable.
@@ -523,8 +552,14 @@ next(our_iterator) # => "three"
# After the iterator has returned all of its data, it raises a StopIteration exception
next(our_iterator) # Raises StopIteration
-# You can grab all the elements of an iterator by calling list() on it.
-list(filled_dict.keys()) # => Returns ["one", "two", "three"]
+# We can also loop over it, in fact, "for" does this implicitly!
+our_iterator = iter(our_iterable)
+for i in our_iterator:
+ print(i) # Prints one, two, three
+
+# You can grab all the elements of an iterable or iterator by calling list() on it.
+list(our_iterable) # => Returns ["one", "two", "three"]
+list(our_iterator) # => Returns [] because state is saved
####################################################
diff --git a/raku.html.markdown b/raku.html.markdown
new file mode 100644
index 00000000..4f397589
--- /dev/null
+++ b/raku.html.markdown
@@ -0,0 +1,2412 @@
+---
+category: language
+language: Raku
+filename: learnraku.raku
+contributors:
+ - ["vendethiel", "http://github.com/vendethiel"]
+ - ["Samantha McVey", "https://cry.nu"]
+---
+
+Raku (formerly Perl 6) is a highly capable, feature-rich programming language
+made for at least the next hundred years.
+
+The primary Raku compiler is called [Rakudo](http://rakudo.org), which runs on
+the JVM and the [MoarVM](http://moarvm.com).
+
+Meta-note:
+
+* Although the pound sign (`#`) is used for sentences and notes, Pod-styled
+ comments (more below about them) are used whenever it's convenient.
+* `# OUTPUT:` is used to represent the output of a command to any standard
+ stream. If the output has a newline, it's represented by the `␤` symbol.
+ The output is always enclosed by angle brackets (`«` and `»`).
+* `#=>` represents the value of an expression, return value of a sub, etc.
+ In some cases, the value is accompanied by a comment.
+* Backticks are used to distinguish and highlight the language constructs
+ from the text.
+
+```perl6
+####################################################
+# 0. Comments
+####################################################
+
+# Single line comments start with a pound sign.
+
+#`( Multiline comments use #` and a quoting construct.
+ (), [], {}, 「」, etc, will work.
+)
+
+=for comment
+Use the same syntax for multiline comments to embed comments.
+for #`(each element in) @array {
+ put #`(or print element) $_ #`(with newline);
+}
+
+# You can also use Pod-styled comments. For example:
+
+=comment This is a comment that extends until an empty
+newline is found.
+
+=comment
+The comment doesn't need to start in the same line as the directive.
+
+=begin comment
+This comment is multiline.
+
+Empty newlines can exist here too!
+=end comment
+
+####################################################
+# 1. Variables
+####################################################
+
+# In Raku, you declare a lexical variable using the `my` keyword:
+my $variable;
+
+# Raku has 3 basic types of variables: scalars, arrays, and hashes.
+
+#
+# 1.1 Scalars
+#
+
+# Scalars represent a single value. They start with the `$` sigil:
+my $str = 'String';
+
+# Double quotes allow for interpolation (which we'll see later):
+my $str2 = "$str";
+
+# Variable names can contain but not end with simple quotes and dashes,
+# and can contain (and end with) underscores:
+my $person's-belongings = 'towel'; # this works!
+
+my $bool = True; # `True` and `False` are Raku's boolean values.
+my $inverse = !$bool; # Invert a bool with the prefix `!` operator.
+my $forced-bool = so $str; # And you can use the prefix `so` operator
+$forced-bool = ?$str; # to turn its operand into a Bool. Or use `?`.
+
+#
+# 1.2 Arrays and Lists
+#
+
+# Arrays represent multiple values. An array variable starts with the `@`
+# sigil. Unlike lists, from which arrays inherit, arrays are mutable.
+
+my @array = 'a', 'b', 'c';
+# equivalent to:
+my @letters = <a b c>;
+# In the previous statement, we use the quote-words (`<>`) term for array
+# of words, delimited by space. Similar to perl5's qw, or Ruby's %w.
+
+@array = 1, 2, 4;
+
+# Array indices start at 0. Here the third element is being accessed.
+say @array[2]; # OUTPUT: «4␤»
+
+say "Interpolate an array using []: @array[]";
+# OUTPUT: «Interpolate an array using []: 1 2 3␤»
+
+@array[0] = -1; # Assigning a new value to an array index
+@array[0, 1] = 5, 6; # Assigning multiple values
+
+my @keys = 0, 2;
+@array[@keys] = @letters; # Assignment using an array containing index values
+say @array; # OUTPUT: «a 6 b␤»
+
+#
+# 1.3 Hashes, or key-value Pairs.
+#
+
+=begin comment
+Hashes are pairs of keys and values. You can construct a `Pair` object
+using the syntax `key => value`. Hash tables are very fast for lookup,
+and are stored unordered. Keep in mind that keys get "flattened" in hash
+context, and any duplicated keys are deduplicated.
+=end comment
+my %hash = 'a' => 1, 'b' => 2;
+
+# Keys get auto-quoted when the fat comman (`=>`) is used. Trailing commas are
+# okay.
+%hash = a => 1, b => 2, ;
+
+# Even though hashes are internally stored differently than arrays,
+# Raku allows you to easily create a hash from an even numbered array:
+%hash = <key1 value1 key2 value2>; # Or:
+%hash = "key1", "value1", "key2", "value2";
+
+%hash = key1 => 'value1', key2 => 'value2'; # same result as above
+
+# You can also use the "colon pair" syntax. This syntax is especially
+# handy for named parameters that you'll see later.
+%hash = :n(2), # equivalent to `n => 2`
+ :is-even, # equivalent to `:is-even(True)` or `is-even => True`
+ :!is-odd, # equivalent to `:is-odd(False)` or `is-odd => False`
+;
+# The `:` (as in `:is-even`) and `:!` (as `:!is-odd`) constructs are known
+# as the `True` and `False` shortcuts respectively.
+
+=begin comment
+As demonstrated in the example below, you can use {} to get the value from a key.
+If it's a string without spaces, you can actually use the quote-words operator
+(`<>`). Since Raku doesn't have barewords, as Perl does, `{key1}` doesn't work
+though.
+=end comment
+say %hash{'n'}; # OUTPUT: «2␤», gets value associated to key 'n'
+say %hash<is-even>; # OUTPUT: «True␤», gets value associated to key 'is-even'
+
+####################################################
+# 2. Subroutines
+####################################################
+
+# Subroutines, or functions as most other languages call them, are
+# created with the `sub` keyword.
+sub say-hello { say "Hello, world" }
+
+# You can provide (typed) arguments. If specified, the type will be checked
+# at compile-time if possible, otherwise at runtime.
+sub say-hello-to( Str $name ) {
+ say "Hello, $name !";
+}
+
+# A sub returns the last value of the block. Similarly, the semicolon in
+# the last expression can be omitted.
+sub return-value { 5 }
+say return-value; # OUTPUT: «5␤»
+
+sub return-empty { }
+say return-empty; # OUTPUT: «Nil␤»
+
+# Some control flow structures produce a value, for instance `if`:
+sub return-if {
+ if True { "Truthy" }
+}
+say return-if; # OUTPUT: «Truthy␤»
+
+# Some don't, like `for`:
+sub return-for {
+ for 1, 2, 3 { 'Hi' }
+}
+say return-for; # OUTPUT: «Nil␤»
+
+=begin comment
+Positional arguments are required by default. To make them optional, use
+the `?` after the parameters' names.
+
+In the following example, the sub `with-optional` returns `(Any)` (Perl's
+null-like value) if no argument is passed. Otherwise, it returns its argument.
+=end comment
+sub with-optional( $arg? ) {
+ $arg;
+}
+with-optional; # returns Any
+with-optional(); # returns Any
+with-optional(1); # returns 1
+
+=begin comment
+You can also give provide a default value when they're not passed. Doing
+this make said parameter optional. Required parameters must come before
+optional ones.
+
+In the sub `greeting`, the parameter `$type` is optional.
+=end comment
+sub greeting( $name, $type = "Hello" ) {
+ say "$type, $name!";
+}
+
+greeting("Althea"); # OUTPUT: «Hello, Althea!␤»
+greeting("Arthur", "Good morning"); # OUTPUT: «Good morning, Arthur!␤»
+
+=begin comment
+You can also, by using a syntax akin to the one of hashes (yay unified syntax!),
+declared named parameters and thus pass named arguments to a subroutine.
+By default, named parameter are optional and will default to `Any`.
+=end comment
+sub with-named( $normal-arg, :$named ) {
+ say $normal-arg + $named;
+}
+with-named(1, named => 6); # OUTPUT: «7␤»
+
+=begin comment
+There's one gotcha to be aware of, here: If you quote your key, Raku
+won't be able to see it at compile time, and you'll have a single `Pair`
+object as a positional parameter, which means the function subroutine
+`with-named(1, 'named' => 6);` fails.
+=end comment
+with-named(2, :named(5)); # OUTPUT: «7␤»
+
+# Similar to positional parameters, you can provide your named arguments with
+# default values.
+sub named-def( :$def = 5 ) {
+ say $def;
+}
+named-def; # OUTPUT: «5»
+named-def(def => 15); # OUTPUT: «15»
+
+=begin comment
+In order to make a named parameter mandatory, you can append `!` to the
+parameter. This is the inverse of `?`, which makes a required parameter
+optional.
+=end comment
+
+sub with-mandatory-named( :$str! ) {
+ say "$str!";
+}
+with-mandatory-named(str => "My String"); # OUTPUT: «My String!␤»
+# with-mandatory-named; # runtime error: "Required named parameter not passed"
+# with-mandatory-named(3);# runtime error: "Too many positional parameters passed"
+
+=begin comment
+If a sub takes a named boolean argument, you can use the same "short boolean"
+hash syntax we discussed earlier.
+=end comment
+sub takes-a-bool( $name, :$bool ) {
+ say "$name takes $bool";
+}
+takes-a-bool('config', :bool); # OUTPUT: «config takes True␤»
+takes-a-bool('config', :!bool); # OUTPUT: «config takes False␤»
+
+=begin comment
+Since paranthesis can be omitted when calling a subroutine, you need to use
+`&` in order to distinguish between a call to a sub with no arguments and
+the code object.
+
+For instance, in this example we must use `&` to store the sub `say-hello`
+(i.e., the sub's code object) in a variable, not a subroutine call.
+=end comment
+my &s = &say-hello;
+my &other-s = sub { say "Anonymous function!" }
+
+=begin comment
+A sub can have a "slurpy" parameter, or what one'd call a
+"doesn't-matter-how-many" parameter. This is Raku's way of supporting variadic
+functions. For this, you must use `*@` (slurpy) which will "take everything
+else". You can have as many parameters *before* a slurpy one, but not *after*.
+=end comment
+sub as-many($head, *@rest) {
+ @rest.join(' / ') ~ " !";
+}
+say as-many('Happy', 'Happy', 'Birthday'); # OUTPUT: «Happy / Birthday !␤»
+say 'Happy', ['Happy', 'Birthday'], 'Day'; # OUTPUT: «Happy / Birthday / Day !␤»
+
+# Note that the splat (the *) did not consume the parameter before it.
+
+=begin comment
+There are other two variations of slurpy parameters in Raku. The previous one
+(namely, `*@`), known as flattened slurpy, flattens passed arguments. The other
+two are `**@` and `+@` known as unflattened slurpy and "single argument rule"
+slurpy respectively. The unflattened slurpy doesn't flatten its listy
+arguments (or Iterable ones).
+=end comment
+sub b(**@arr) { @arr.perl.say };
+b(['a', 'b', 'c']); # OUTPUT: «[["a", "b", "c"],]»
+b(1, $('d', 'e', 'f'), [2, 3]); # OUTPUT: «[1, ("d", "e", "f"), [2, 3]]»
+b(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, [1, 2], ([3, 4], 5)]␤»
+
+=begin comment
+On the other hand, the "single argument rule" slurpy follows the "single argument
+rule" which dictates how to handle the slurpy argument based upon context and
+roughly states that if only a single argument is passed and that argument is
+Iterable, that argument is used to fill the slurpy parameter array. In any
+other case, `+@` works like `**@`.
+=end comment
+sub c(+@arr) { @arr.perl.say };
+c(['a', 'b', 'c']); # OUTPUT: «["a", "b", "c"]␤»
+c(1, $('d', 'e', 'f'), [2, 3]); # OUTPUT: «[1, ("d", "e", "f"), [2, 3]]␤»
+c(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, [1, 2], ([3, 4], 5)]␤»
+
+=begin comment
+You can call a function with an array using the "argument list flattening"
+operator `|` (it's not actually the only role of this operator,
+but it's one of them).
+=end comment
+sub concat3($a, $b, $c) {
+ say "$a, $b, $c";
+}
+concat3(|@array); # OUTPUT: «a, b, c␤»
+ # `@array` got "flattened" as a part of the argument list
+
+####################################################
+# 3. Containers
+####################################################
+
+=begin comment
+In Raku, values are actually stored in "containers". The assignment
+operator asks the container on the left to store the value on its right.
+When passed around, containers are marked as immutable which means that,
+in a function, you'll get an error if you try to mutate one of your
+arguments. If you really need to, you can ask for a mutable container by
+using the `is rw` trait.
+=end comment
+sub mutate( $n is rw ) {
+ $n++; # postfix ++ operator increments its argument but returns its old value
+}
+my $m = 42;
+mutate $m; #=> 42, the value is incremented but the old value is returned
+say $m; # OUTPUT: «43␤»
+
+=begin comment
+This works because we are passing the container $m to the `mutate` sub.
+If we try to just pass a number instead of passing a variable, it won't work
+because there is no container being passed and integers are immutable by
+themselves:
+
+mutate 42; # Parameter '$n' expected a writable container, but got Int value
+=end comment
+
+=begin comment
+Similar error would be obtained, if a bound variable is passed to
+to the subroutine. In Raku, you bind a value to a variable using the binding
+operator `:=`.
+=end comment
+my $v := 50; # binding 50 to the variable $v
+# mutate $v; # Parameter '$n' expected a writable container, but got Int value
+
+=begin comment
+If what you want is a copy instead, use the `is copy` trait which will
+cause the argument to be copied and allow you to modify the argument
+inside the routine without modifying the passed argument.
+
+A sub itself returns a container, which means it can be marked as `rw`.
+Alternatively, you can explicitly mark the returned container as mutable
+by using `return-rw` instead of `return`.
+=end comment
+my $x = 42;
+my $y = 45;
+sub x-store is rw { $x }
+sub y-store { return-rw $y }
+
+# In this case, the parentheses are mandatory or else Raku thinks that
+# `x-store` and `y-store` are identifiers.
+x-store() = 52;
+y-store() *= 2;
+
+say $x; # OUTPUT: «52␤»
+say $y; # OUTPUT: «90␤»
+
+####################################################
+# 4.Control Flow Structures
+####################################################
+
+#
+# 4.1 if/if-else/if-elsif-else/unless
+#
+
+=begin comment
+Before talking about `if`, we need to know which values are "truthy"
+(represent `True`), and which are "falsey" (represent `False`). Only these
+values are falsey: 0, (), {}, "", Nil, a type (like `Str`, `Int`, etc.) and
+of course, `False` itself. Any other value is truthy.
+=end comment
+my $number = 5;
+if $number < 5 {
+ say "Number is less than 5"
+}
+elsif $number == 5 {
+ say "Number is equal to 5"
+}
+else {
+ say "Number is greater than 5"
+}
+
+unless False {
+ say "It's not false!";
+}
+
+# `unless` is the equivalent of `if not (X)` which inverts the sense of a
+# conditional statement. However, you cannot use `else` or `elsif` with it.
+
+# As you can see, you don't need parentheses around conditions. However, you
+# do need the curly braces around the "body" block. For example,
+# `if (True) say 'It's true';` doesn't work.
+
+# You can also use their statement modifier (postfix) versions:
+say "Quite truthy" if True; # OUTPUT: «Quite truthy␤»
+say "Quite falsey" unless False; # OUTPUT: «Quite falsey␤»
+
+=begin comment
+The ternary operator (`??..!!`) is structured as follows `condition ??
+expression1 !! expression2` and it returns expression1 if the condition is
+true. Otherwise, it returns expression2.
+=end comment
+my $age = 30;
+say $age > 18 ?? "You are an adult" !! "You are under 18";
+# OUTPUT: «You are an adult␤»
+
+#
+# 4.2 with/with-else/with-orwith-else/without
+#
+
+=begin comment
+The `with` statement is like `if`, but it tests for definedness rather than
+truth, and it topicalizes on the condition, much like `given` which will
+be discussed later.
+=end comment
+my $s = "raku";
+with $s.index("r") { say "Found a at $_" }
+orwith $s.index("k") { say "Found c at $_" }
+else { say "Didn't find r or k" }
+
+# Similar to `unless` that checks un-truthiness, you can use `without` to
+# check for undefined-ness.
+my $input01;
+without $input01 {
+ say "No input given."
+}
+# OUTPUT: «No input given.␤»
+
+# There are also statement modifier versions for both `with` and `without`.
+my $input02 = 'Hello';
+say $input02 with $input02; # OUTPUT: «Hello␤»
+say "No input given." without $input02;
+
+#
+# 4.3 given/when, or Raku's switch construct
+#
+
+=begin comment
+`given...when` looks like other languages' `switch`, but is much more
+powerful thanks to smart matching and Raku's "topic variable", `$_`.
+
+The topic variable `$_ `contains the default argument of a block, a loop's
+current iteration (unless explicitly named), etc.
+
+`given` simply puts its argument into `$_` (like a block would do),
+ and `when` compares it using the "smart matching" (`~~`) operator.
+
+Since other Raku constructs use this variable (as said before, like `for`,
+blocks, `with` statement etc), this means the powerful `when` is not only
+applicable along with a `given`, but instead anywhere a `$_` exists.
+=end comment
+
+given "foo bar" {
+ say $_; # OUTPUT: «foo bar␤»
+
+ # Don't worry about smart matching yet. Just know `when` uses it. This is
+ # equivalent to `if $_ ~~ /foo/`.
+ when /foo/ {
+ say "Yay !";
+ }
+
+ # smart matching anything with `True` is `True`, i.e. (`$a ~~ True`)
+ # so you can also put "normal" conditionals. For example, this `when` is
+ # equivalent to this `if`: `if $_ ~~ ($_.chars > 50) {...}`
+ # which means: `if $_.chars > 50 {...}`
+ when $_.chars > 50 {
+ say "Quite a long string !";
+ }
+
+ # same as `when *` (using the Whatever Star)
+ default {
+ say "Something else"
+ }
+}
+
+#
+# 4.4 Looping constructs
+#
+
+# The `loop` construct is an infinite loop if you don't pass it arguments, but
+# can also be a C-style `for` loop:
+loop {
+ say "This is an infinite loop !";
+ last;
+}
+# In the previous example, `last` breaks out of the loop very much
+# like the `break` keyword in other languages.
+
+# The `next` keyword skips to the next iteration, like `continue` in other
+# languages. Note that you can also use postfix conditionals, loops, etc.
+loop (my $i = 0; $i < 5; $i++) {
+ next if $i == 3;
+ say "This is a C-style for loop!";
+}
+
+# The `for` constructs iterates over a list of elements.
+my @odd-array = 1, 3, 5, 7, 9;
+
+# Accessing the array's elements with the topic variable $_.
+for @odd-array {
+ say "I've got $_ !";
+}
+
+# Accessing the array's elements with a "pointy block", `->`.
+# Here each element is read-only.
+for @odd-array -> $variable {
+ say "I've got $variable !";
+}
+
+# Accessing the array's elements with a "doubly pointy block", `<->`.
+# Here each element is read-write so mutating `$variable` mutates
+# that element in the array.
+for @odd-array <-> $variable {
+ say "I've got $variable !";
+}
+
+# As we saw with `given`, a `for` loop's default "current iteration" variable
+# is `$_`. That means you can use `when` in a `for`loop just like you were
+# able to in a `given`.
+for @odd-array {
+ say "I've got $_";
+
+ # This is also allowed. A dot call with no "topic" (receiver) is sent to
+ # `$_` (topic variable) by default.
+ .say;
+
+ # This is equivalent to the above statement.
+ $_.say;
+}
+
+for @odd-array {
+ # You can...
+ next if $_ == 3; # Skip to the next iteration (`continue` in C-like lang.)
+ redo if $_ == 4; # Re-do iteration, keeping the same topic variable (`$_`)
+ last if $_ == 5; # Or break out of loop (like `break` in C-like lang.)
+}
+
+# The "pointy block" syntax isn't specific to the `for` loop. It's just a way
+# to express a block in Raku.
+sub long-computation { "Finding factors of large primes" }
+if long-computation() -> $result {
+ say "The result is $result.";
+}
+
+####################################################
+# 5. Operators
+####################################################
+
+=begin comment
+Since Perl languages are very much operator-based languages, Raku
+operators are actually just funny-looking subroutines, in syntactic
+categories, like infix:<+> (addition) or prefix:<!> (bool not).
+
+The categories are:
+ - "prefix": before (like `!` in `!True`).
+ - "postfix": after (like `++` in `$a++`).
+ - "infix": in between (like `*` in `4 * 3`).
+ - "circumfix": around (like `[`-`]` in `[1, 2]`).
+ - "post-circumfix": around, after another term (like `{`-`}` in
+ `%hash{'key'}`)
+
+The associativity and precedence list are explained below.
+
+Alright, you're set to go!
+=end comment
+
+#
+# 5.1 Equality Checking
+#
+
+# `==` is numeric comparison
+say 3 == 4; # OUTPUT: «False␤»
+say 3 != 4; # OUTPUT: «True␤»
+
+# `eq` is string comparison
+say 'a' eq 'b'; # OUTPUT: «False␤»
+say 'a' ne 'b'; # OUTPUT: «True␤», not equal
+say 'a' !eq 'b'; # OUTPUT: «True␤», same as above
+
+# `eqv` is canonical equivalence (or "deep equality")
+say (1, 2) eqv (1, 3); # OUTPUT: «False␤»
+say (1, 2) eqv (1, 2); # OUTPUT: «True␤»
+say Int === Int; # OUTPUT: «True␤»
+
+# `~~` is the smart match operator which aliases the left hand side to $_ and
+# then evaluates the right hand side.
+# Here are some common comparison semantics:
+
+# String or numeric equality
+say 'Foo' ~~ 'Foo'; # OUTPU: «True␤», if strings are equal.
+say 12.5 ~~ 12.50; # OUTPU: «True␤», if numbers are equal.
+
+# Regex - For matching a regular expression against the left side.
+# Returns a `Match` object, which evaluates as True if regexp matches.
+my $obj = 'abc' ~~ /a/;
+say $obj; # OUTPUT: «「a」␤»
+say $obj.WHAT; # OUTPUT: «(Match)␤»
+
+# Hashes
+say 'key' ~~ %hash; # OUTPUT:«True␤», if key exists in hash.
+
+# Type - Checks if left side "is of type" (can check superclasses and roles).
+say 1 ~~ Int; # OUTPUT: «True␤»
+
+# Smart-matching against a boolean always returns that boolean (and will warn).
+say 1 ~~ True; # OUTPUT: «True␤», smartmatch against True always matches
+say False.so ~~ True; # OUTPUT: «True␤», use .so for truthiness
+
+# General syntax is `$arg ~~ &bool-returning-function;`. For a complete list
+# of combinations, refer to the table at:
+# https://docs.raku.org/language/operators#index-entry-smartmatch_operator
+
+# Of course, you also use `<`, `<=`, `>`, `>=` for numeric comparison.
+# Their string equivalent are also available: `lt`, `le`, `gt`, `ge`.
+say 3 > 4; # OUTPUT: «False␤»
+say 3 >= 4; # OUTPUT: «False␤»
+say 3 < 4; # OUTPUT: «True␤»
+say 3 <= 4; # OUTPUT: «True␤»
+say 'a' gt 'b'; # OUTPUT: «False␤»
+say 'a' ge 'b'; # OUTPUT: «False␤»
+say 'a' lt 'b'; # OUTPUT: «True␤»
+say 'a' le 'b'; # OUTPUT: «True␤»
+
+#
+# 5.2 Range constructor
+#
+
+say 3 .. 7; # OUTPUT: «3..7␤», both included.
+say 3 ..^ 7; # OUTPUT: «3..^7␤», exclude right endpoint.
+say 3 ^.. 7; # OUTPUT: «3^..7␤», exclude left endpoint.
+say 3 ^..^ 7; # OUTPUT: «3^..^7␤», exclude both endpoints.
+
+# The range 3 ^.. 7 is similar like 4 .. 7 when we only consider integers.
+# But when we consider decimals:
+
+say 3.5 ~~ 4 .. 7; # OUTPUT: «False␤»
+say 3.5 ~~ 3 ^.. 7; # OUTPUT: «True␤»,
+
+# This is because the range `3 ^.. 7` only excludes anything strictly
+# equal to 3. Hence, it contains decimals greater than 3. This could
+# mathematically be described as 3.5 ∈ (3,7] or in set notation,
+# 3.5 ∈ { x | 3 < x ≤ 7 }.
+
+say 3 ^.. 7 ~~ 4 .. 7; # OUTPUT: «False␤»
+
+# This also works as a shortcut for `0..^N`:
+say ^10; # OUTPUT: «^10␤», which means 0..^10
+
+# This also allows us to demonstrate that Raku has lazy/infinite arrays,
+# using the Whatever Star:
+my @natural = 1..*; # 1 to Infinite! Equivalent to `1..Inf`.
+
+# You can pass ranges as subscripts and it'll return an array of results.
+say @natural[^10]; # OUTPUT: «1 2 3 4 5 6 7 8 9 10␤», doesn't run out of memory!
+
+=begin comment
+NOTE: when reading an infinite list, Raku will "reify" the elements
+it needs, then keep them in memory. They won't be calculated more than once.
+It also will never calculate more elements that are needed.
+=end comment
+
+# An array subscript can also be a closure. It'll be called with the array's
+# length as the argument. The following two examples are equivalent:
+say join(' ', @array[15..*]); # OUTPUT: «15 16 17 18 19␤»
+say join(' ', @array[-> $n { 15..$n }]); # OUTPUT: «15 16 17 18 19␤»
+
+# NOTE: if you try to do either of those with an infinite array, you'll
+# trigger an infinite loop (your program won't finish).
+
+# You can use that in most places you'd expect, even when assigning to an array:
+my @numbers = ^20;
+
+# Here the numbers increase by 6, like an arithmetic sequence; more on the
+# sequence (`...`) operator later.
+my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99;
+
+# In this example, even though the sequence is infinite, only the 15
+# needed values will be calculated.
+@numbers[5..*] = 3, 9 ... *;
+say @numbers; # OUTPUT: «0 1 2 3 4 3 9 15 21 [...] 81 87␤», only 20 values
+
+#
+# 5.3 and (&&), or (||)
+#
+
+# Here `and` calls `.Bool` on both 3 and 4 and gets `True` so it returns
+# 4 since both are `True`.
+say (3 and 4); # OUTPUT: «4␤», which is truthy.
+say (3 and 0); # OUTPUT: «0␤»
+say (0 and 4); # OUTPUT: «0␤»
+
+# Here `or` calls `.Bool` on `0` and `False` which are both `False`
+# so it returns `False` since both are `False`.
+say (0 or False); # OUTPUT: «False␤».
+
+# Both `and` and `or` have tighter versions which also shortcut circuits.
+# They're `&&` and `||` respectively.
+
+# `&&` returns the first operand that evaluates to `False`. Otherwise,
+# it returns the last operand.
+my ($a, $b, $c, $d, $e) = 1, 0, False, True, 'pi';
+say $a && $b && $c; # OUTPUT: «0␤», the first falsey value
+say $a && $b && $c; # OUTPUT: «False␤», the first falsey value
+say $a && $d && $e; # OUTPUT: «pi␤», last operand since everthing before is truthy
+
+# `||` returns the first argument that evaluates to `True`.
+say $b || $a || $d; # OUTPUT: «1␤»
+say $e || $d || $a; # OUTPUT: «pi␤»
+
+# And because you're going to want them, you also have compound assignment
+# operators:
+$a *= 2; # multiply and assignment. Equivalent to $a = $a * 2;
+$b %%= 5; # divisible by and assignment. Equivalent to $b = $b %% 2;
+$c div= 3; # return divisor and assignment. Equivalent to $c = $c div 3;
+$d mod= 4; # return remainder and assignment. Equivalent to $d = $d mod 4;
+@array .= sort; # calls the `sort` method and assigns the result back
+
+####################################################
+# 6. More on subs!
+####################################################
+
+# As we said before, Raku has *really* powerful subs. We're going
+# to see a few more key concepts that make them better than in any
+# other language :-).
+
+#
+# 6.1 Unpacking!
+#
+
+# Unpacking is the ability to "extract" arrays and keys
+# (AKA "destructuring"). It'll work in `my`s and in parameter lists.
+my ($f, $g) = 1, 2;
+say $f; # OUTPUT: «1␤»
+my ($, $, $h) = 1, 2, 3; # keep the non-interesting values anonymous (`$`)
+say $h; # OUTPUT: «3␤»
+
+my ($head, *@tail) = 1, 2, 3; # Yes, it's the same as with "slurpy subs"
+my (*@small) = 1;
+
+sub unpack_array( @array [$fst, $snd] ) {
+ say "My first is $fst, my second is $snd! All in all, I'm @array[].";
+ # (^ remember the `[]` to interpolate the array)
+}
+unpack_array(@tail);
+# OUTPUT: «My first is 3, my second is 3! All in all, I'm 2 3.␤»
+
+# If you're not using the array itself, you can also keep it anonymous,
+# much like a scalar:
+sub first-of-array( @ [$fst] ) { $fst }
+first-of-array(@small); #=> 1
+
+# However calling `first-of-array(@tail);` will throw an error ("Too many
+# positional parameters passed"), which means the `@tail` has too many
+# elements.
+
+# You can also use a slurpy parameter. You could keep `*@rest` anonymous
+# Here, `@rest` is `(3,)`, since `$fst` holds the `2`. This results
+# since the length (.elems) of `@rest` is 1.
+sub slurp-in-array(@ [$fst, *@rest]) {
+ say $fst + @rest.elems;
+}
+slurp-in-array(@tail); # OUTPUT: «3␤»
+
+# You could even extract on a slurpy (but it's pretty useless ;-).)
+sub fst(*@ [$fst]) { # or simply: `sub fst($fst) { ... }`
+ say $fst;
+}
+fst(1); # OUTPUT: «1␤»
+
+# Calling `fst(1, 2);` will throw an error ("Too many positional parameters
+# passed") though. After all, the `fst` sub declares only a single positional
+# parameter.
+
+=begin comment
+You can also destructure hashes (and classes, which you'll learn about later).
+The syntax is basically the same as
+`%hash-name (:key($variable-to-store-value-in))`.
+The hash can stay anonymous if you only need the values you extracted.
+
+In order to call the function, you must supply a hash wither created with
+curly braces or with `%()` (recommended). Alternatively, you can pass
+a variable that contains a hash.
+=end comment
+
+sub key-of( % (:value($val), :qua($qua)) ) {
+ say "Got value $val, $qua time" ~~
+ $qua == 1 ?? '' !! 's';
+}
+
+my %foo-once = %(value => 'foo', qua => 1);
+key-of({value => 'foo', qua => 2}); # OUTPUT: «Got val foo, 2 times.␤»
+key-of(%(value => 'foo', qua => 0)); # OUTPUT: «Got val foo, 0 times.␤»
+key-of(%foo-once); # OUTPUT: «Got val foo, 1 time.␤»
+
+# The last expression of a sub is returned automatically (though you may
+# indicate explicitly by using the `return` keyword, of course):
+sub next-index( $n ) {
+ $n + 1;
+}
+my $new-n = next-index(3); # $new-n is now 4
+
+=begin comment
+This is true for everything, except for the looping constructs (due to
+performance reasons): there's no reason to build a list if we're just going to
+discard all the results. If you still want to build one, you can use the
+`do` statement prefix or the `gather` prefix, which we'll see later:
+=end comment
+
+sub list-of( $n ) {
+ do for ^$n { $_ }
+}
+my @list3 = list-of(3); #=> (0, 1, 2)
+
+#
+# 6.2 Lambdas (or anonymous subroutines)
+#
+
+# You can create a lambda by using a pointy block (`-> {}`), a
+# block (`{}`) or creating a `sub` without a name.
+
+my &lambda1 = -> $argument {
+ "The argument passed to this lambda is $argument"
+}
+
+my &lambda2 = {
+ "The argument passed to this lambda is $_"
+}
+
+my &lambda3 = sub ($argument) {
+ "The argument passed to this lambda is $argument"
+}
+
+=begin comment
+Both pointy blocks and blocks are pretty much the same thing, except that
+the former can take arguments, and that the latter can be mistaken as
+a hash by the parser. That being said, blocks can declare what's known
+as placeholders parameters through the twigils `$^` (for positional
+parameters) and `$:` (for named parameters). More on them latern on.
+=end comment
+
+my &mult = { $^numbers * $:times }
+say mult 4, :times(6); #=> «24␤»
+
+# Both pointy blocks and blocks are quite versatile when working with functions
+# that accepts other functions such as `map`, `grep`, etc. For example,
+# we add 3 to each value of an array using the `map` function with a lambda:
+my @nums = 1..4;
+my @res1 = map -> $v { $v + 3 }, @nums; # pointy block, explicit parameter
+my @res2 = map { $_ + 3 }, @nums; # block using an implicit parameter
+my @res3 = map { $^val + 3 }, @nums; # block with placeholder parameter
+
+=begin comment
+A sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`):
+A block doesn't have a "function context" (though it can have arguments),
+which means that if you return from it, you're going to return from the
+parent function.
+=end comment
+
+# Compare:
+sub is-in( @array, $elem ) {
+ say map({ return True if $_ == $elem }, @array);
+ say 'Hi';
+}
+
+# with:
+sub truthy-array( @array ) {
+ say map sub ($i) { $i ?? return True !! return False }, @array;
+ say 'Hi';
+}
+
+=begin comment
+In the `is-in` sub, the block will `return` out of the `is-in` sub once the
+condition evaluates to `True`, the loop won't be run anymore and the
+following statement won't be executed. The last statement is only executed
+if the block never returns.
+
+On the contrary, the `truthy-array` sub will produce an array of `True` and
+`False`, which will printed, and always execute the last execute statement.
+Thus, the `return` only returns from the anonymous `sub`
+=end comment
+
+=begin comment
+The `anon` declarator can be used to create an anonymous sub from a
+regular subroutine. The regular sub knows its name but its symbol is
+prevented from getting installed in the lexical scope, the method table
+and everywhere else.
+=end comment
+my $anon-sum = anon sub summation(*@a) { [+] @a }
+say $anon-sum.name; # OUTPUT: «summation␤»
+say $anon-sum(2, 3, 5); # OUTPUT: «10␤»
+#say summation; # Error: Undeclared routine: ...
+
+# You can also use the Whatever Star to create an anonymous subroutine.
+# (it'll stop at the furthest operator in the current expression).
+# The following is the same as `{$_ + 3 }`, `-> { $a + 3 }`,
+# `sub ($a) { $a + 3 }`, or even `{$^a + 3}` (more on this later).
+my @arrayplus3v0 = map * + 3, @nums;
+
+# The following is the same as `-> $a, $b { $a + $b + 3 }`,
+# `sub ($a, $b) { $a + $b + 3 }`, or `{ $^a + $^b + 3 }` (more on this later).
+my @arrayplus3v1 = map * + * + 3, @nums;
+
+say (*/2)(4); # OUTPUT: «2␤», immediately execute the Whatever function created.
+say ((*+3)/5)(5); # OUTPUT: «1.6␤», it works even in parens!
+
+# But if you need to have more than one argument (`$_`) in a block (without
+# wanting to resort to `-> {}`), you can also either `$^` and `$:` which
+# declared placeholder parameters or self-declared positional/named parameters.
+say map { $^a + $^b + 3 }, @nums;
+
+# which is equivalent to the following which uses a `sub`:
+map sub ($a, $b) { $a + $b + 3 }, @nums;
+
+# Placeholder parameters are sorted lexicographically so the following two
+# statements are equivalent:
+say sort { $^b <=> $^a }, @nums;
+say sort -> $a, $b { $b <=> $a }, @nums;
+
+#
+# 6.3 Multiple Dispatch
+#
+
+# Raku can decide which variant of a `sub` to call based on the type of the
+# arguments, or on arbitrary preconditions, like with a type or `where`:
+
+# with types:
+multi sub sayit( Int $n ) { # note the `multi` keyword here
+ say "Number: $n";
+}
+multi sayit( Str $s ) { # a multi is a `sub` by default
+ say "String: $s";
+}
+sayit "foo"; # OUTPUT: «String: foo␤»
+sayit 25; # OUTPUT: «Number: 25␤»
+sayit True; # fails at *compile time* with "calling 'sayit' will never
+ # work with arguments of types ..."
+
+# with arbitrary preconditions (remember subsets?):
+multi is-big(Int $n where * > 50) { "Yes!" } # using a closure
+multi is-big(Int $n where {$_ > 50}) { "Yes!" } # similar to above
+multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching
+multi is-big(Int $) { "No" }
+
+subset Even of Int where * %% 2;
+multi odd-or-even(Even) { "Even" } # Using the type. We don't name the argument.
+multi odd-or-even($) { "Odd" } # "everything else" hence the $ variable
+
+# You can even dispatch based on the presence of positional and named arguments:
+multi with-or-without-you($with) {
+ say "I wish I could but I can't";
+}
+multi with-or-without-you(:$with) {
+ say "I can live! Actually, I can't.";
+}
+multi with-or-without-you {
+ say "Definitely can't live.";
+}
+
+=begin comment
+This is very, very useful for many purposes, like `MAIN` subs (covered
+later), and even the language itself uses it in several places.
+
+For example, the `is` trait is actually a `multi sub` named `trait_mod:<is>`,
+and it works off that. Thus, `is rw`, is simply a dispatch to a function with
+this signature `sub trait_mod:<is>(Routine $r, :$rw!) {}`
+=end comment
+
+####################################################
+# 7. About types...
+####################################################
+
+=begin comment
+Raku is gradually typed. This means you can specify the type of your
+variables/arguments/return types, or you can omit the type annotations in
+in which case they'll default to `Any`. Obviously you get access to a few
+base types, like `Int` and `Str`. The constructs for declaring types are
+`subset`, `class`, `role`, etc. which you'll see later.
+
+For now, let us examine `subset` which is a "sub-type" with additional
+checks. For example, "a very big integer is an `Int` that's greater than 500".
+You can specify the type you're subtyping (by default, `Any`), and add
+additional checks with the `where` clause.
+=end comment
+subset VeryBigInteger of Int where * > 500;
+
+# Or the set of the whole numbers:
+subset WholeNumber of Int where * >= 0;
+my WholeNumber $whole-six = 6; # OK
+#my WholeNumber $nonwhole-one = -1; # Error: type check failed...
+
+# Or the set of Positive Even Numbers whose Mod 5 is 1. Notice we're
+# using the previously defined WholeNumber subset.
+subset PENFO of WholeNumber where { $_ %% 2 and $_ mod 5 == 1 };
+my PENFO $yes-penfo = 36; # OK
+#my PENFO $no-penfo = 2; # Error: type check failed...
+
+####################################################
+# 8. Scoping
+####################################################
+
+=begin comment
+In Raku, unlike many scripting languages, (such as Python, Ruby, PHP),
+you must declare your variables before using them. The `my` declarator
+we've used so far uses "lexical scoping". There are a few other declarators,
+(`our`, `state`, ..., ) which we'll see later. This is called
+"lexical scoping", where in inner blocks, you can access variables from
+outer blocks.
+=end comment
+
+my $file_scoped = 'Foo';
+sub outer {
+ my $outer_scoped = 'Bar';
+ sub inner {
+ say "$file_scoped $outer_scoped";
+ }
+ &inner; # return the function
+}
+outer()(); # OUTPUT: «Foo Bar␤»
+
+# As you can see, `$file_scoped` and `$outer_scoped` were captured.
+# But if we were to try and use `$outer_scoped` outside the `outer` sub,
+# the variable would be undefined (and you'd get a compile time error).
+
+####################################################
+# 9. Twigils
+####################################################
+
+=begin comment
+There are many special `twigils` (composed sigils) in Raku. Twigils
+define a variable's scope.
+The `*` and `?` twigils work on standard variables:
+ * for dynamic variables
+ ? for compile-time variables
+
+The `!` and the `.` twigils are used with Raku's objects:
+ ! for attributes (instance attribute)
+ . for methods (not really a variable)
+=end comment
+
+#
+# `*` twigil: Dynamic Scope
+#
+
+# These variables use the `*` twigil to mark dynamically-scoped variables.
+# Dynamically-scoped variables are looked up through the caller, not through
+# the outer scope.
+
+my $*dyn_scoped_1 = 1;
+my $*dyn_scoped_2 = 10;
+
+sub say_dyn {
+ say "$*dyn_scoped_1 $*dyn_scoped_2";
+}
+
+sub call_say_dyn {
+ # Defines $*dyn_scoped_1 only for this sub.
+ my $*dyn_scoped_1 = 25;
+
+ # Will change the value of the file scoped variable.
+ $*dyn_scoped_2 = 100;
+
+ # $*dyn_scoped 1 and 2 will be looked for in the call.
+ say_dyn(); # OUTPUT: «25 100␤»
+
+ # The call to `say_dyn` uses the value of $*dyn_scoped_1 from inside
+ # this sub's lexical scope even though the blocks aren't nested (they're
+ # call-nested).
+}
+say_dyn(); # OUTPUT: «1 10␤»
+
+# Uses $*dyn_scoped_1 as defined in `call_say_dyn` even though we are calling it
+# from outside.
+call_say_dyn(); # OUTPUT: «25 100␤»
+
+# We changed the value of $*dyn_scoped_2 in `call_say_dyn` so now its
+# value has changed.
+say_dyn(); # OUTPUT: «1 100␤»
+
+# TODO: Add information about remaining twigils
+
+####################################################
+# 10. Object Model
+####################################################
+
+=begin comment
+To call a method on an object, add a dot followed by the method name:
+`$object.method`
+
+Classes are declared with the `class` keyword. Attributes are declared
+with the `has` keyword, and methods declared with the `method` keyword.
+
+Every attribute that is private uses the `!` twigil. For example: `$!attr`.
+Immutable public attributes use the `.` twigil which creates a read-only
+method named after the attribute. In fact, declaring an attribute with `.`
+is equivalent to declaring the same attribute with `!` and then creating
+a read-only method with the attribute's name. However, this is done for us
+by Raku automatically. The easiest way to remember the `$.` twigil is
+by comparing it to how methods are called.
+
+Raku's object model ("SixModel") is very flexible, and allows you to
+dynamically add methods, change semantics, etc... Unfortunately, these will
+not all be covered here, and you should refer to:
+https://docs.raku.org/language/objects.html.
+=end comment
+
+class Human {
+ has Str $.name; # `$.name` is immutable but with an accessor method.
+ has Str $.bcountry; # Use `$!bcountry` to modify it inside the class.
+ has Str $.ccountry is rw; # This attribute can be modified from outside.
+ has Int $!age = 0; # A private attribute with default value.
+
+ method birthday {
+ $!age += 1; # Add a year to human's age
+ }
+
+ method get-age {
+ return $!age;
+ }
+
+ # This method is private to the class. Note the `!` before the
+ # method's name.
+ method !do-decoration {
+ return "$!name born in $!bcountry and now lives in $!ccountry."
+ }
+
+ # This method is public, just like `birthday` and `get-age`.
+ method get-info {
+ # Invoking a method on `self` inside the class.
+ # Use `self!priv-method` for private method.
+ say self!do-decoration;
+
+ # Use `self.public-method` for public method.
+ say "Age: ", self.get-age;
+ }
+};
+
+# Create a new instance of Human class.
+# NOTE: Only attributes declared with the `.` twigil can be set via the
+# default constructor (more later on). This constructor only accepts named
+# arguments.
+my $person1 = Human.new(
+ name => "Jord",
+ bcountry => "Togo",
+ ccountry => "Togo"
+);
+
+# Make human 10 years old.
+$person1.birthday for 1..10;
+
+say $person1.name; # OUTPUT: «Jord␤»
+say $person1.bcountry; # OUTPUT: «Togo␤»
+say $person1.ccountry; # OUTPUT: «Togo␤»
+say $person1.get-age; # OUTPUT: «10␤»
+
+# This fails, because the `has $.bcountry`is immutable. Jord can't change
+# his birthplace.
+# $person1.bcountry = "Mali";
+
+# This works because the `$.ccountry` is mutable (`is rw`). Now Jord's
+# current country is France.
+$person1.ccountry = "France";
+
+# Calling methods on the instance objects.
+$person1.birthday; #=> 1
+$person1.get-info; #=> Jord born in Togo and now lives in France. Age: 10
+# $person1.do-decoration; # This fails since the method `do-decoration` is private.
+
+#
+# 10.1 Object Inheritance
+#
+
+=begin comment
+Raku also has inheritance (along with multiple inheritance). While
+methods are inherited, submethods are not. Submethods are useful for
+object construction and destruction tasks, such as `BUILD`, or methods that
+must be overridden by subtypes. We will learn about `BUILD` later on.
+=end comment
+
+class Parent {
+ has $.age;
+ has $.name;
+
+ # This submethod won't be inherited by the Child class.
+ submethod favorite-color {
+ say "My favorite color is Blue";
+ }
+
+ # This method is inherited
+ method talk { say "Hi, my name is $!name" }
+}
+
+# Inheritance uses the `is` keyword
+class Child is Parent {
+ method talk { say "Goo goo ga ga" }
+ # This shadows Parent's `talk` method.
+ # This child hasn't learned to speak yet!
+}
+
+my Parent $Richard .= new(age => 40, name => 'Richard');
+$Richard.favorite-color; # OUTPUT: «My favorite color is Blue␤»
+$Richard.talk; # OUTPUT: «Hi, my name is Richard␤»
+# $Richard is able to access the submethod and he knows how to say his name.
+
+my Child $Madison .= new(age => 1, name => 'Madison');
+$Madison.talk; # OUTPUT: «Goo goo ga ga␤», due to the overridden method.
+# $Madison.favorite-color # does not work since it is not inherited.
+
+=begin comment
+When you use `my T $var`, `$var` starts off with `T` itself in it, so you can
+call `new` on it. (`.=` is just the dot-call and the assignment operator).
+Thus, `$a .= b` is the same as `$a = $a.b`. Also note that `BUILD` (the method
+called inside `new`) will set parent's properties too, so you can pass `val =>
+5`.
+=end comment
+
+#
+# 10.2 Roles, or Mixins
+#
+
+# Roles are supported too (which are called Mixins in other languages)
+role PrintableVal {
+ has $!counter = 0;
+ method print {
+ say $.val;
+ }
+}
+
+# you "apply" a role (or mixin) with the `does` keyword:
+class Item does PrintableVal {
+ has $.val;
+
+ =begin comment
+ When `does`-ed, a `role` literally "mixes in" the class:
+ the methods and attributes are put together, which means a class
+ can access the private attributes/methods of its roles (but
+ not the inverse!):
+ =end comment
+ method access {
+ say $!counter++;
+ }
+
+ =begin comment
+ However, this: method print {} is ONLY valid when `print` isn't a `multi`
+ with the same dispatch. This means a parent class can shadow a child class's
+ `multi print() {}`, but it's an error if a role does)
+
+ NOTE: You can use a role as a class (with `is ROLE`). In this case,
+ methods will be shadowed, since the compiler will consider `ROLE`
+ to be a class.
+ =end comment
+}
+
+####################################################
+# 11. Exceptions
+####################################################
+
+=begin comment
+Exceptions are built on top of classes, in the package `X` (like `X::IO`).
+In Raku, exceptions are automatically 'thrown':
+
+open 'foo'; # OUTPUT: «Failed to open file foo: no such file or directory␤»
+
+It will also print out what line the error was thrown at
+and other error info.
+=end comment
+
+# You can throw an exception using `die`. Here it's been commented out to
+# avoid stopping the program's execution:
+# die 'Error!'; # OUTPUT: «Error!␤»
+
+# Or more explicitly (commented out too):
+# X::AdHoc.new(payload => 'Error!').throw; # OUTPUT: «Error!␤»
+
+=begin comment
+In Raku, `orelse` is similar to the `or` operator, except it only matches
+undefined variables instead of anything evaluating as `False`.
+Undefined values include: `Nil`, `Mu` and `Failure` as well as `Int`, `Str`
+and other types that have not been initialized to any value yet.
+You can check if something is defined or not using the defined method:
+=end comment
+my $uninitialized;
+say $uninitialized.defined; # OUTPUT: «False␤»
+
+=begin comment
+When using `orelse` it will disarm the exception and alias $_ to that
+failure. This will prevent it to being automatically handled and printing
+lots of scary error messages to the screen. We can use the `exception`
+method on the `$_` variable to access the exception
+=end comment
+open 'foo' orelse say "Something happened {.exception}";
+
+# This also works:
+open 'foo' orelse say "Something happened $_";
+# OUTPUT: «Something happened Failed to open file foo: no such file or directory␤»
+
+=begin comment
+Both of those above work but in case we get an object from the left side
+that is not a failure we will probably get a warning. We see below how we
+can use try` and `CATCH` to be more specific with the exceptions we catch.
+=end comment
+
+#
+# 11.1 Using `try` and `CATCH`
+#
+
+=begin comment
+By using `try` and `CATCH` you can contain and handle exceptions without
+disrupting the rest of the program. The `try` block will set the last
+exception to the special variable `$!` (known as the error variable).
+NOTE: This has no relation to $!variables seen inside class definitions.
+=end comment
+
+try open 'foo';
+say "Well, I tried! $!" if defined $!;
+# OUTPUT: «Well, I tried! Failed to open file foo: no such file or directory␤»
+
+=begin comment
+Now, what if we want more control over handling the exception?
+Unlike many other languages, in Raku, you put the `CATCH` block *within*
+the block to `try`. Similar to how the `$_` variable was set when we
+'disarmed' the exception with `orelse`, we also use `$_` in the CATCH block.
+NOTE: The `$!` variable is only set *after* the `try` block has caught an
+exception. By default, a `try` block has a `CATCH` block of its own that
+catches any exception (`CATCH { default {} }`).
+=end comment
+
+try {
+ my $a = (0 %% 0);
+ CATCH {
+ default { say "Something happened: $_" }
+ }
+}
+# OUTPUT: «Something happened: Attempt to divide by zero using infix:<%%>␤»
+
+# You can redefine it using `when`s (and `default`) to handle the exceptions
+# you want to catch explicitly:
+
+try {
+ open 'foo';
+ CATCH {
+ # In the `CATCH` block, the exception is set to the $_ variable.
+ when X::AdHoc {
+ say "Error: $_"
+ }
+ when X::Numeric::DivideByZero {
+ say "Error: $_";
+ }
+
+ =begin comment
+ Any other exceptions will be re-raised, since we don't have a `default`.
+ Basically, if a `when` matches (or there's a `default`), the
+ exception is marked as "handled" so as to prevent its re-throw
+ from the `CATCH` block. You still can re-throw the exception
+ (see below) by hand.
+ =end comment
+ default {
+ say "Any other error: $_"
+ }
+ }
+}
+# OUTPUT: «Failed to open file /dir/foo: no such file or directory␤»
+
+=begin comment
+There are also some subtleties to exceptions. Some Raku subs return a
+`Failure`, which is a wrapper around an `Exception` object which is
+"unthrown". They're not thrown until you try to use the variables containing
+them unless you call `.Bool`/`.defined` on them - then they're handled.
+(the `.handled` method is `rw`, so you can mark it as `False` back yourself)
+You can throw a `Failure` using `fail`. Note that if the pragma `use fatal`
+is on, `fail` will throw an exception (like `die`).
+=end comment
+
+my $value = 0/0; # We're not trying to access the value, so no problem.
+try {
+ say 'Value: ', $value; # Trying to use the value
+ CATCH {
+ default {
+ say "It threw because we tried to get the fail's value!"
+ }
+ }
+}
+
+=begin comment
+There is also another kind of exception: Control exceptions. Those are "good"
+exceptions, which happen when you change your program's flow, using operators
+like `return`, `next` or `last`. You can "catch" those with `CONTROL` (not 100%
+working in Rakudo yet).
+=end comment
+
+####################################################
+# 12. Packages
+####################################################
+
+=begin comment
+Packages are a way to reuse code. Packages are like "namespaces", and any
+element of the six model (`module`, `role`, `class`, `grammar`, `subset` and
+`enum`) are actually packages. (Packages are the lowest common denominator)
+Packages are important - especially as Perl is well-known for CPAN,
+the Comprehensive Perl Archive Network.
+=end comment
+
+# You can use a module (bring its declarations into scope) with `use`:
+use JSON::Tiny; # if you installed Rakudo* or Panda, you'll have this module
+say from-json('[1]').perl; # OUTPUT: «[1]␤»
+
+=begin comment
+You should not declare packages using the `package` keyword (unlike Perl 5).
+Instead, use `class Package::Name::Here;` to declare a class, or if you only
+want to export variables/subs, you can use `module` instead.
+=end comment
+
+# If `Hello` doesn't exist yet, it'll just be a "stub", that can be redeclared
+# as something else later.
+module Hello::World { # bracketed form
+ # declarations here
+}
+
+# The file-scoped form which extends until the end of the file. For
+# instance, `unit module Parse::Text;` will extend until of the file.
+
+# A grammar is a package, which you could `use`. You will learn more about
+# grammars in the regex section.
+grammar Parse::Text::Grammar {
+}
+
+# As said before, any part of the six model is also a package.
+# Since `JSON::Tiny` uses its own `JSON::Tiny::Actions` class, you can use it:
+my $actions = JSON::Tiny::Actions.new;
+
+# We'll see how to export variables and subs in the next part.
+
+####################################################
+# 13. Declarators
+####################################################
+
+=begin comment
+In Raku, you get different behaviors based on how you declare a variable.
+You've already seen `my` and `has`, we'll now explore the others.
+
+`our` - these declarations happen at `INIT` time -- (see "Phasers" below).
+It's like `my`, but it also creates a package variable. All packagish
+things such as `class`, `role`, etc. are `our` by default.
+=end comment
+
+module Var::Increment {
+ # NOTE: `our`-declared variables cannot be typed.
+ our $our-var = 1;
+ my $my-var = 22;
+
+ our sub Inc {
+ our sub available { # If you try to make inner `sub`s `our`...
+ # ... Better know what you're doing (Don't !).
+ say "Don't do that. Seriously. You'll get burned.";
+ }
+
+ my sub unavailable { # `sub`s are `my`-declared by default
+ say "Can't access me from outside, I'm 'my'!";
+ }
+ say ++$our-var; # Increment the package variable and output its value
+ }
+
+}
+
+say $Var::Increment::our-var; # OUTPUT: «1␤», this works!
+say $Var::Increment::my-var; # OUTPUT: «(Any)␤», this will not work!
+
+say Var::Increment::Inc; # OUTPUT: «2␤»
+say Var::Increment::Inc; # OUTPUT: «3␤», notice how the value of $our-var was retained.
+
+# Var::Increment::unavailable; # OUTPUT: «Could not find symbol '&unavailable'␤»
+
+# `constant` - these declarations happen at `BEGIN` time. You can use
+# the `constant` keyword to declare a compile-time variable/symbol:
+constant Pi = 3.14;
+constant $var = 1;
+
+# And if you're wondering, yes, it can also contain infinite lists.
+constant why-not = 5, 15 ... *;
+say why-not[^5]; # OUTPUT: «5 15 25 35 45␤»
+
+# `state` - these declarations happen at run time, but only once. State
+# variables are only initialized one time. In other languages such as C
+# they exist as `static` variables.
+sub fixed-rand {
+ state $val = rand;
+ say $val;
+}
+fixed-rand for ^10; # will print the same number 10 times
+
+# Note, however, that they exist separately in different enclosing contexts.
+# If you declare a function with a `state` within a loop, it'll re-create the
+# variable for each iteration of the loop. See:
+for ^5 -> $a {
+ sub foo {
+ # This will be a different value for every value of `$a`
+ state $val = rand;
+ }
+ for ^5 -> $b {
+ # This will print the same value 5 times, but only 5. Next iteration
+ # will re-run `rand`.
+ say foo;
+ }
+}
+
+####################################################
+# 14. Phasers
+####################################################
+
+=begin comment
+Phasers in Raku are blocks that happen at determined points of time in
+your program. They are called phasers because they mark a change in the
+phase of a program. For example, when the program is compiled, a for loop
+runs, you leave a block, or an exception gets thrown (The `CATCH` block is
+actually a phaser!). Some of them can be used for their return values,
+some of them can't (those that can have a "[*]" in the beginning of their
+explanation text). Let's have a look!
+=end comment
+
+#
+# 14.1 Compile-time phasers
+#
+BEGIN { say "[*] Runs at compile time, as soon as possible, only once" }
+CHECK { say "[*] Runs at compile time, as late as possible, only once" }
+
+#
+# 14.2 Run-time phasers
+#
+INIT { say "[*] Runs at run time, as soon as possible, only once" }
+END { say "Runs at run time, as late as possible, only once" }
+
+#
+# 14.3 Block phasers
+#
+ENTER { say "[*] Runs everytime you enter a block, repeats on loop blocks" }
+LEAVE {
+ say "Runs everytime you leave a block, even when an exception
+ happened. Repeats on loop blocks."
+}
+
+PRE {
+ say "Asserts a precondition at every block entry,
+ before ENTER (especially useful for loops)";
+ say "If this block doesn't return a truthy value,
+ an exception of type X::Phaser::PrePost is thrown.";
+}
+
+# Example (commented out):
+for 0..2 {
+ # PRE { $_ > 1 } # OUTPUT: «Precondition '{ $_ > 1 }' failed
+}
+
+POST {
+ say "Asserts a postcondition at every block exit,
+ after LEAVE (especially useful for loops)";
+ say "If this block doesn't return a truthy value,
+ an exception of type X::Phaser::PrePost is thrown, like PRE.";
+}
+
+# Example (commented out):
+for 0..2 {
+ # POST { $_ < 1 } # OUTPUT: «Postcondition '{ $_ < 1 }' failed
+}
+
+#
+# 14.4 Block/exceptions phasers
+#
+{
+ KEEP { say "Runs when you exit a block successfully
+ (without throwing an exception)" }
+ UNDO { say "Runs when you exit a block unsuccessfully
+ (by throwing an exception)" }
+}
+
+#
+# 14.5 Loop phasers
+#
+for ^5 {
+ FIRST { say "[*] The first time the loop is run, before ENTER" }
+ NEXT { say "At loop continuation time, before LEAVE" }
+ LAST { say "At loop termination time, after LEAVE" }
+}
+
+#
+# 14.6 Role/class phasers
+#
+COMPOSE {
+ say "When a role is composed into a class. /!\ NOT YET IMPLEMENTED"
+}
+
+# They allow for cute tricks or clever code...:
+say "This code took " ~ (time - CHECK time) ~ "s to compile";
+
+# ... or clever organization:
+class DB {
+ method start-transaction { say "Starting transation!" }
+ method commit { say "Commiting transaction..." }
+ method rollback { say "Something went wrong. Rollingback!" }
+}
+
+sub do-db-stuff {
+ my DB $db .= new;
+ $db.start-transaction; # start a new transaction
+ KEEP $db.commit; # commit the transaction if all went well
+ UNDO $db.rollback; # or rollback if all hell broke loose
+}
+
+do-db-stuff();
+
+####################################################
+# 15. Statement prefixes
+####################################################
+
+=begin comment
+Those act a bit like phasers: they affect the behavior of the following
+code. Though, they run in-line with the executable code, so they're in
+lowercase. (`try` and `start` are theoretically in that list, but explained
+elsewhere) NOTE: all of these (except start) don't need explicit curly
+braces `{` and `}`.
+
+=end comment
+
+#
+# 15.1 `do` - It runs a block or a statement as a term.
+#
+
+# Normally you cannot use a statement as a value (or "term"). `do` helps
+# us do it. With `do`, an `if`, for example, becomes a term returning a value.
+=for comment :reason<this fails since `if` is a statement>
+my $value = if True { 1 }
+
+# this works!
+my $get-five = do if True { 5 }
+
+#
+# 15.1 `once` - makes sure a piece of code only runs once.
+#
+for ^5 {
+ once say 1
+};
+# OUTPUT: «1␤», only prints ... once
+
+# Similar to `state`, they're cloned per-scope.
+for ^5 {
+ sub { once say 1 }()
+};
+# OUTPUT: «1 1 1 1 1␤», prints once per lexical scope.
+
+#
+# 15.2 `gather` - co-routine thread.
+#
+
+# The `gather` constructs allows us to `take` several values from an array/list,
+# much like `do`.
+say gather for ^5 {
+ take $_ * 3 - 1;
+ take $_ * 3 + 1;
+}
+# OUTPUT: «-1 1 2 4 5 7 8 10 11 13␤»
+
+say join ',', gather if False {
+ take 1;
+ take 2;
+ take 3;
+}
+# Doesn't print anything.
+
+#
+# 15.3 `eager` - evaluates a statement eagerly (forces eager context).
+
+# Don't try this at home. This will probably hang for a while (and might crash)
+# so commented out.
+# eager 1..*;
+
+# But consider, this version which doesn't print anything
+constant thricev0 = gather for ^3 { say take $_ };
+# to:
+constant thricev1 = eager gather for ^3 { say take $_ }; # OUTPUT: «0 1 2␤»
+
+####################################################
+# 16. Iterables
+####################################################
+
+# Iterables are objects that can be iterated over for things such as
+# the `for` construct.
+
+#
+# 16.1 `flat` - flattens iterables.
+#
+say (1, 10, (20, 10) ); # OUTPUT: «(1 10 (20 10))␤», notice how nested
+ # lists are preserved
+say (1, 10, (20, 10) ).flat; # OUTPUT: «(1 10 20 10)␤», now the iterable is flat
+
+#
+# 16.2 `lazy` - defers actual evaluation until value is fetched by forcing lazy context.
+#
+my @lazy-array = (1..100).lazy;
+say @lazy-array.is-lazy; # OUTPUT: «True␤», check for laziness with the `is-lazy` method.
+
+say @lazy-array; # OUTPUT: «[...]␤», List has not been iterated on!
+
+# This works and will only do as much work as is needed.
+for @lazy-array { .print };
+
+# (**TODO** explain that gather/take and map are all lazy)
+
+#
+# 16.3 `sink` - an `eager` that discards the results by forcing sink context.
+#
+constant nilthingie = sink for ^3 { .say } #=> 0 1 2
+say nilthingie.perl; # OUTPUT: «Nil␤»
+
+#
+# 16.4 `quietly` - suppresses warnings in blocks.
+#
+quietly { warn 'This is a warning!' }; # No output
+
+####################################################
+# 17. More operators thingies!
+####################################################
+
+# Everybody loves operators! Let's get more of them.
+
+# The precedence list can be found here:
+# https://docs.raku.org/language/operators#Operator_Precedence
+# But first, we need a little explanation about associativity:
+
+#
+# 17.1 Binary operators
+#
+
+my ($p, $q, $r) = (1, 2, 3);
+
+=begin comment
+Given some binary operator § (not a Raku-supported operator), then:
+
+$p § $q § $r; # with a left-associative §, this is ($p § $q) § $r
+$p § $q § $r; # with a right-associative §, this is $p § ($q § $r)
+$p § $q § $r; # with a non-associative §, this is illegal
+$p § $q § $r; # with a chain-associative §, this is ($p § $q) and ($q § $r)§
+$p § $q § $r; # with a list-associative §, this is `infix:<>`
+=end comment
+
+#
+# 17.2 Unary operators
+#
+
+=begin comment
+Given some unary operator § (not a Raku-supported operator), then:
+§$p§ # with left-associative §, this is (§$p)§
+§$p§ # with right-associative §, this is §($p§)
+§$p§ # with non-associative §, this is illegal
+=end comment
+
+#
+# 17.3 Create your own operators!
+#
+
+=begin comment
+Okay, you've been reading all of that, so you might want to try something
+more exciting?! I'll tell you a little secret (or not-so-secret):
+In Raku, all operators are actually just funny-looking subroutines.
+
+You can declare an operator just like you declare a sub. In the following
+example, `prefix` refers to the operator categories (prefix, infix, postfix,
+circumfix, and post-circumfix).
+=end comment
+sub prefix:<win>( $winner ) {
+ say "$winner Won!";
+}
+win "The King"; # OUTPUT: «The King Won!␤»
+
+# you can still call the sub with its "full name":
+say prefix:<!>(True); # OUTPUT: «False␤»
+prefix:<win>("The Queen"); # OUTPUT: «The Queen Won!␤»
+
+sub postfix:<!>( Int $n ) {
+ [*] 2..$n; # using the reduce meta-operator... See below ;-)!
+}
+say 5!; # OUTPUT: «120␤»
+
+# Postfix operators ('after') have to come *directly* after the term.
+# No whitespace. You can use parentheses to disambiguate, i.e. `(5!)!`
+
+sub infix:<times>( Int $n, Block $r ) { # infix ('between')
+ for ^$n {
+ # You need the explicit parentheses to call the function in `$r`,
+ # else you'd be referring at the code object itself, like with `&r`.
+ $r();
+ }
+}
+3 times -> { say "hello" }; # OUTPUT: «hello␤hello␤hello␤»
+
+# It's recommended to put spaces around your infix operator calls.
+
+# For circumfix and post-circumfix ones
+multi circumfix:<[ ]>( Int $n ) {
+ $n ** $n
+}
+say [5]; # OUTPUT: «3125␤»
+
+# Circumfix means 'around'. Again, no whitespace.
+
+multi postcircumfix:<{ }>( Str $s, Int $idx ) {
+ $s.substr($idx, 1);
+}
+say "abc"{1}; # OUTPUT: «b␤», after the term `"abc"`, and around the index (1)
+
+# Post-circumfix is 'after a term, around something'
+
+=begin comment
+This really means a lot -- because everything in Raku uses this.
+For example, to delete a key from a hash, you use the `:delete` adverb
+(a simple named argument underneath). For instance, the following statements
+are equivalent.
+=end comment
+my %person-stans =
+ 'Giorno Giovanna' => 'Gold Experience',
+ 'Bruno Bucciarati' => 'Sticky Fingers';
+my $key = 'Bruno Bucciarati';
+%person-stans{$key}:delete;
+postcircumfix:<{ }>( %person-stans, 'Giorno Giovanna', :delete );
+# (you can call operators like this)
+
+=begin comment
+It's *all* using the same building blocks! Syntactic categories
+(prefix infix ...), named arguments (adverbs), ..., etc. used to build
+the language - are available to you. Obviously, you're advised against
+making an operator out of *everything* -- with great power comes great
+responsibility.
+=end comment
+
+#
+# 17.4 Meta operators!
+#
+
+=begin comment
+Oh boy, get ready!. Get ready, because we're delving deep into the rabbit's
+hole, and you probably won't want to go back to other languages after
+reading this. (I'm guessing you don't want to go back at this point but
+let's continue, for the journey is long and enjoyable!).
+
+Meta-operators, as their name suggests, are *composed* operators. Basically,
+they're operators that act on another operators.
+
+The reduce meta-operator is a prefix meta-operator that takes a binary
+function and one or many lists. If it doesn't get passed any argument,
+it either returns a "default value" for this operator (a meaningless value)
+or `Any` if there's none (examples below). Otherwise, it pops an element
+from the list(s) one at a time, and applies the binary function to the last
+result (or the first element of a list) and the popped element.
+=end comment
+
+# To sum a list, you could use the reduce meta-operator with `+`, i.e.:
+say [+] 1, 2, 3; # OUTPUT: «6␤», equivalent to (1+2)+3.
+
+# To multiply a list
+say [*] 1..5; # OUTPUT: «120␤», equivalent to ((((1*2)*3)*4)*5).
+
+# You can reduce with any operator, not just with mathematical ones.
+# For example, you could reduce with `//` to get first defined element
+# of a list:
+say [//] Nil, Any, False, 1, 5; # OUTPUT: «False␤»
+ # (Falsey, but still defined)
+# Or with relational operators, i.e., `>` to check elements of a list
+# are ordered accordingly:
+say [>] 234, 156, 6, 3, -20; # OUTPUT: «True␤»
+
+# Default value examples:
+say [*] (); # OUTPUT: «1␤», empty product
+say [+] (); # OUTPUT: «0␤», empty sum
+say [//]; # OUTPUT: «(Any)␤»
+ # There's no "default value" for `//`.
+
+# You can also use it with a function you made up,
+# You can also surround using double brackets:
+sub add($a, $b) { $a + $b }
+say [[&add]] 1, 2, 3; # OUTPUT: «6␤»
+
+=begin comment
+The zip meta-operator is an infix meta-operator that also can be used as a
+"normal" operator. It takes an optional binary function (by default, it
+just creates a pair), and will pop one value off of each array and call
+its binary function on these until it runs out of elements. It returns an
+array with all of these new elements.
+=end comment
+say (1, 2) Z (3, 4); # OUTPUT: «((1, 3), (2, 4))␤»
+say 1..3 Z+ 4..6; # OUTPUT: «(5, 7, 9)␤»
+
+# Since `Z` is list-associative (see the list above), you can use it on more
+# than one list.
+(True, False) Z|| (False, False) Z|| (False, False); # (True, False)
+
+# And, as it turns out, you can also use the reduce meta-operator with it:
+[Z||] (True, False), (False, False), (False, False); # (True, False)
+
+# And to end the operator list:
+
+=begin comment
+The sequence operator (`...`) is one of Raku's most powerful features:
+It's composed by the list (which might include a closure) you want Raku to
+deduce from on the left and a value (or either a predicate or a Whatever Star
+for a lazy infinite list) on the right that states when to stop.
+=end comment
+
+# Basic arithmetic sequence
+my @listv0 = 1, 2, 3...10;
+
+# This dies because Raku can't figure out the end
+# my @list = 1, 3, 6...10;
+
+# As with ranges, you can exclude the last element (the iteration ends when
+# the predicate matches).
+my @listv1 = 1, 2, 3...^10;
+
+# You can use a predicate (with the Whatever Star).
+my @listv2 = 1, 3, 9...* > 30;
+
+# Equivalent to the example above but using a block here.
+my @listv3 = 1, 3, 9 ... { $_ > 30 };
+
+# Lazy infinite list of fibonacci sequence, computed using a closure!
+my @fibv0 = 1, 1, *+* ... *;
+
+# Equivalent to the above example but using a pointy block.
+my @fibv1 = 1, 1, -> $a, $b { $a + $b } ... *;
+
+# Equivalent to the above example but using a block with placeholder parameters.
+my @fibv2 = 1, 1, { $^a + $^b } ... *;
+
+=begin comment
+In the examples with explicit parameters (i.e., $a and $b), $a and $b
+will always take the previous values, meaning that for the Fibonacci sequence,
+they'll start with $a = 1 and $b = 1 (values we set by hand), then $a = 1
+and $b = 2 (result from previous $a + $b), and so on.
+=end comment
+
+=begin comment
+# In the example we use a range as an index to access the sequence. However,
+# it's worth noting that for ranges, once reified, elements aren't re-calculated.
+# That's why, for instance, `@primes[^100]` will take a long time the first
+# time you print it but then it will be instateneous.
+=end comment
+say @fibv0[^10]; # OUTPUT: «1 1 2 3 5 8 13 21 34 55␤»
+
+####################################################
+# 18. Regular Expressions
+####################################################
+
+=begin comment
+I'm sure a lot of you have been waiting for this one. Well, now that you know
+a good deal of Raku already, we can get started. First off, you'll have to
+forget about "PCRE regexps" (perl-compatible regexps).
+
+IMPORTANT: Don't skip them because you know PCRE. They're different. Some
+things are the same (like `?`, `+`, and `*`), but sometimes the semantics
+change (`|`). Make sure you read carefully, because you might trip over a
+new behavior.
+
+Raku has many features related to RegExps. After all, Rakudo parses itself.
+We're first going to look at the syntax itself, then talk about grammars
+(PEG-like), differences between `token`, `regex` and `rule` declarators,
+and some more. Side note: you still have access to PCRE regexps using the
+`:P5` modifier which we won't be discussing this in this tutorial, though.
+
+In essence, Raku natively implements PEG ("Parsing Expression Grammars").
+The pecking order for ambiguous parses is determined by a multi-level
+tie-breaking test:
+ - Longest token matching: `foo\s+` beats `foo` (by 2 or more positions)
+ - Longest literal prefix: `food\w*` beats `foo\w*` (by 1)
+ - Declaration from most-derived to less derived grammars
+ (grammars are actually classes)
+ - Earliest declaration wins
+=end comment
+say so 'a' ~~ /a/; # OUTPUT: «True␤»
+say so 'a' ~~ / a /; # OUTPUT: «True␤», more readable with some spaces!
+
+=begin comment
+In all our examples, we're going to use the smart-matching operator against
+a regexp. We're converting the result using `so` to a Boolean value because,
+in fact, it's returning a `Match` object. They know how to respond to list
+indexing, hash indexing, and return the matched string. The results of the
+match are available in the `$/` variable (implicitly lexically-scoped). You
+can also use the capture variables which start at 0: `$0`, `$1', `$2`...
+
+You can also note that `~~` does not perform start/end checking, meaning
+the regexp can be matched with just one character of the string. We'll
+explain later how you can do it.
+
+In Raku, you can have any alphanumeric as a literal, everything else has
+to be escaped by using a backslash or quotes.
+=end comment
+say so 'a|b' ~~ / a '|' b /; # OUTPUT: «True␤», it wouldn't mean the same
+ # thing if `|` wasn't escaped.
+say so 'a|b' ~~ / a \| b /; # OUTPUT: «True␤», another way to escape it.
+
+# The whitespace in a regex is actually not significant, unless you use the
+# `:s` (`:sigspace`, significant space) adverb.
+say so 'a b c' ~~ / a b c /; #=> `False`, space is not significant here!
+say so 'a b c' ~~ /:s a b c /; #=> `True`, we added the modifier `:s` here.
+
+# If we use only one space between strings in a regex, Raku will warn us
+# about space being not signicant in the regex:
+say so 'a b c' ~~ / a b c /; # OUTPUT: «False␤»
+say so 'a b c' ~~ / a b c /; # OUTPUT: «False»
+
+=begin comment
+NOTE: Please use quotes or `:s` (`:sigspace`) modifier (or, to suppress this
+warning, omit the space, or otherwise change the spacing). To fix this and make
+the spaces less ambiguous, either use at least two spaces between strings
+or use the `:s` adverb.
+=end comment
+
+# As we saw before, we can embed the `:s` inside the slash delimiters, but we
+# can also put it outside of them if we specify `m` for 'match':
+say so 'a b c' ~~ m:s/a b c/; # OUTPUT: «True␤»
+
+# By using `m` to specify 'match', we can also use other delimiters:
+say so 'abc' ~~ m{a b c}; # OUTPUT: «True␤»
+say so 'abc' ~~ m[a b c]; # OUTPUT: «True␤»
+
+# `m/.../` is equivalent to `/.../`:
+say 'raku' ~~ m/raku/; # OUTPUT: «True␤»
+say 'raku' ~~ /raku/; # OUTPUT: «True␤»
+
+# Use the `:i` adverb to specify case insensitivity:
+say so 'ABC' ~~ m:i{a b c}; # OUTPUT: «True␤»
+
+# However, whitespace is important as for how modifiers are applied
+# (which you'll see just below) ...
+
+#
+# 18.1 Quantifiers - `?`, `+`, `*` and `**`.
+#
+
+# `?` - zero or one match
+say so 'ac' ~~ / a b c /; # OUTPUT: «False␤»
+say so 'ac' ~~ / a b? c /; # OUTPUT: «True␤», the "b" matched 0 times.
+say so 'abc' ~~ / a b? c /; # OUTPUT: «True␤», the "b" matched 1 time.
+
+# ... As you read before, whitespace is important because it determines which
+# part of the regex is the target of the modifier:
+say so 'def' ~~ / a b c? /; # OUTPUT: «False␤», only the "c" is optional
+say so 'def' ~~ / a b? c /; # OUTPUT: «False␤», whitespace is not significant
+say so 'def' ~~ / 'abc'? /; # OUTPUT: «True␤», the whole "abc" group is optional
+
+# Here (and below) the quantifier applies only to the "b"
+
+# `+` - one or more matches
+say so 'ac' ~~ / a b+ c /; # OUTPUT: «False␤», `+` wants at least one 'b'
+say so 'abc' ~~ / a b+ c /; # OUTPUT: «True␤», one is enough
+say so 'abbbbc' ~~ / a b+ c /; # OUTPUT: «True␤», matched 4 "b"s
+
+# `*` - zero or more matches
+say so 'ac' ~~ / a b* c /; # OUTPU: «True␤», they're all optional
+say so 'abc' ~~ / a b* c /; # OUTPU: «True␤»
+say so 'abbbbc' ~~ / a b* c /; # OUTPU: «True␤»
+say so 'aec' ~~ / a b* c /; # OUTPU: «False␤», "b"(s) are optional, not replaceable.
+
+# `**` - (Unbound) Quantifier
+# If you squint hard enough, you might understand why exponentation is used
+# for quantity.
+say so 'abc' ~~ / a b**1 c /; # OUTPU: «True␤», exactly one time
+say so 'abc' ~~ / a b**1..3 c /; # OUTPU: «True␤», one to three times
+say so 'abbbc' ~~ / a b**1..3 c /; # OUTPU: «True␤»
+say so 'abbbbbbc' ~~ / a b**1..3 c /; # OUTPU: «Fals␤», too much
+say so 'abbbbbbc' ~~ / a b**3..* c /; # OUTPU: «True␤», infinite ranges are ok
+
+#
+# 18.2 `<[]>` - Character classes
+#
+
+# Character classes are the equivalent of PCRE's `[]` classes, but they use a
+# more raku-ish syntax:
+say 'fooa' ~~ / f <[ o a ]>+ /; # OUTPUT: «fooa␤»
+
+# You can use ranges (`..`):
+say 'aeiou' ~~ / a <[ e..w ]> /; # OUTPUT: «ae␤»
+
+# Just like in normal regexes, if you want to use a special character, escape
+# it (the last one is escaping a space which would be equivalent to using
+# ' '):
+say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; # OUTPUT: «he-he !␤»
+
+# You'll get a warning if you put duplicate names (which has the nice effect
+# of catching the raw quoting):
+'he he' ~~ / <[ h e ' ' ]> /;
+# Warns "Repeated character (') unexpectedly found in character class"
+
+# You can also negate character classes... (`<-[]>` equivalent to `[^]` in PCRE)
+say so 'foo' ~~ / <-[ f o ]> + /; # OUTPUT: «False␤»
+
+# ... and compose them:
+# any letter except "f" and "o"
+say so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # OUTPUT: «False␤»
+
+# no letter except "f" and "o"
+say so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # OUTPUT: «True␤»
+
+# the + doesn't replace the left part
+say so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # OUTPUT: «True␤»
+
+#
+# 18.3 Grouping and capturing
+#
+
+# Group: you can group parts of your regexp with `[]`. Unlike PCRE's `(?:)`,
+# these groups are *not* captured.
+say so 'abc' ~~ / a [ b ] c /; # OUTPUT: «True␤», the grouping does nothing
+say so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; # OUTPUT: «True␤»
+
+# The previous line returns `True`. The regex matches "012" one or more time
+# (achieved by the the `+` applied to the group).
+
+# But this does not go far enough, because we can't actually get back what
+# we matched.
+
+# Capture: The results of a regexp can be *captured* by using parentheses.
+say so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # OUTPUT: «True␤»
+# (using `so` here, see `$/` below)
+
+# So, starting with the grouping explanations. As we said before, our `Match`
+# object is stored inside the `$/` variable:
+say $/; # Will either print the matched object or `Nil` if nothing matched.
+
+# As we also said before, it has array indexing:
+say $/[0]; # OUTPUT: «「ABC」 「ABC」␤»,
+
+# The corner brackets (「..」) represent (and are) `Match` objects. In the
+# previous example, we have an array of them.
+
+say $0; # The same as above.
+
+=begin comment
+Our capture is `$0` because it's the first and only one capture in the
+regexp. You might be wondering why it's an array, and the answer is simple:
+Some captures (indexed using `$0`, `$/[0]` or a named one) will be an array
+if and only if they can have more than one element. Thus any capture with
+`*`, `+` and `**` (whatever the operands), but not with `?`.
+Let's use examples to see that:
+
+NOTE: We quoted A B C to demonstrate that the whitespace between them isn't
+significant. If we want the whitespace to *be* significant there, we can use the
+`:sigspace` modifier.
+=end comment
+say so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # OUTPUT: «True␤»
+say $/[0]; # OUTPUT: «「ABC」␤»
+say $0.WHAT; # OUTPUT: «(Match)␤»
+ # There can't be more than one, so it's only a single match object.
+
+say so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; # OUTPUT: «True␤»
+say $0.WHAT; # OUTPUT: «(Any)␤», this capture did not match, so it's empty.
+
+say so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; #=> OUTPUT: «True␤»
+say $0.WHAT; # OUTPUT: «(Array)␤», A specific quantifier will always capture
+ # an Array, be a range or a specific value (even 1).
+
+# The captures are indexed per nesting. This means a group in a group will be
+# nested under its parent group: `$/[0][0]`, for this code:
+'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /;
+say $/[0].Str; # OUTPUT: «hello~␤»
+say $/[0][0].Str; # OUTPUT: «~␤»
+
+=begin comment
+This stems from a very simple fact: `$/` does not contain strings, integers
+or arrays, it only contains `Match` objects. These contain the `.list`, `.hash`
+and `.Str` methods but you can also just use `match<key>` for hash access
+and `match[idx]` for array access.
+
+In the following example, we can see `$_` is a list of `Match` objects.
+Each of them contain a wealth of information: where the match started/ended,
+the "ast" (see actions later), etc. You'll see named capture below with
+grammars.
+=end comment
+say $/[0].list.perl; # OUTPUT: «(Match.new(...),).list␤»
+
+# Alternation - the `or` of regexes
+# WARNING: They are DIFFERENT from PCRE regexps.
+say so 'abc' ~~ / a [ b | y ] c /; # OUTPU: «True␤», Either "b" or "y".
+say so 'ayc' ~~ / a [ b | y ] c /; # OUTPU: «True␤», Obviously enough...
+
+# The difference between this `|` and the one you're used to is
+# LTM ("Longest Token Matching") strategy. This means that the engine will
+# always try to match as much as possible in the string.
+say 'foo' ~~ / fo | foo /; # OUTPUT: «foo», instead of `fo`, because it's longer.
+
+=begin comment
+To decide which part is the "longest", it first splits the regex in two parts:
+
+ * The "declarative prefix" (the part that can be statically analyzed)
+ which includes alternations (`|`), conjunctions (`&`), sub-rule calls (not
+ yet introduced), literals, characters classes and quantifiers.
+
+ * The "procedural part" includes everything else: back-references,
+ code assertions, and other things that can't traditionnaly be represented
+ by normal regexps.
+
+Then, all the alternatives are tried at once, and the longest wins.
+=end comment
+
+# Examples:
+# DECLARATIVE | PROCEDURAL
+/ 'foo' \d+ [ <subrule1> || <subrule2> ] /;
+
+# DECLARATIVE (nested groups are not a problem)
+/ \s* [ \w & b ] [ c | d ] /;
+
+# However, closures and recursion (of named regexes) are procedural.
+# There are also more complicated rules, like specificity (literals win
+# over character classes).
+
+# NOTE: The alternation in which all the branches are tried in order
+# until the first one matches still exists, but is now spelled `||`.
+say 'foo' ~~ / fo || foo /; # OUTPUT: «fo␤», in this case.
+
+####################################################
+# 19. Extra: the MAIN subroutine
+####################################################
+
+=begin comment
+The `MAIN` subroutine is called when you run a Raku file directly. It's
+very powerful, because Raku actually parses the arguments and pass them
+as such to the sub. It also handles named argument (`--foo`) and will even
+go as far as to autogenerate a `--help` flag.
+=end comment
+
+sub MAIN($name) {
+ say "Hello, $name!";
+}
+=begin comment
+Supposing the code above is in file named cli.raku, then running in the command
+line (e.g., $ raku cli.raku) produces:
+Usage:
+ cli.raku <name>
+=end comment
+
+=begin comment
+And since MAIN is a regular Raku sub, you can have multi-dispatch:
+(using a `Bool` for the named argument so that we can do `--replace`
+instead of `--replace=1`. The presence of `--replace` indicates truthness
+while its absence falseness). For example:
+
+ # convert to IO object to check the file exists
+ subset File of Str where *.IO.d;
+
+ multi MAIN('add', $key, $value, Bool :$replace) { ... }
+ multi MAIN('remove', $key) { ... }
+ multi MAIN('import', File, Str :$as) { ... } # omitting parameter name
+
+Thus $ raku cli.raku produces:
+Usage:
+ cli.raku [--replace] add <key> <value>
+ cli.raku remove <key>
+ cli.raku [--as=<Str>] import <File>
+
+As you can see, this is *very* powerful. It even went as far as to show inline
+the constants (the type is only displayed if the argument is `$`/is named).
+=end comment
+
+####################################################
+# 20. APPENDIX A:
+####################################################
+
+=begin comment
+It's assumed by now you know the Raku basics. This section is just here to
+list some common operations, but which are not in the "main part" of the
+tutorial to avoid bloating it up.
+=end comment
+
+#
+# 20.1 Operators
+#
+
+# Sort comparison - they return one value of the `Order` enum: `Less`, `Same`
+# and `More` (which numerify to -1, 0 or +1 respectively).
+say 1 <=> 4; # OUTPUT: «More␤», sort comparison for numerics
+say 'a' leg 'b'; # OUTPUT: «Lessre␤», sort comparison for string
+say 1 eqv 1; # OUTPUT: «Truere␤», sort comparison using eqv semantics
+say 1 eqv 1.0; # OUTPUT: «False␤»
+
+# Generic ordering
+say 3 before 4; # OUTPUT: «True␤»
+say 'b' after 'a'; # OUTPUT: «True␤»
+
+# Short-circuit default operator - similar to `or` and `||`, but instead
+# returns the first *defined* value:
+say Any // Nil // 0 // 5; # OUTPUT: «0␤»
+
+# Short-circuit exclusive or (XOR) - returns `True` if one (and only one) of
+# its arguments is true
+say True ^^ False; # OUTPUT: «True␤»
+
+=begin comment
+Flip flops. These operators (`ff` and `fff`, equivalent to P5's `..`
+and `...`) are operators that take two predicates to test: They are `False`
+until their left side returns `True`, then are `True` until their right
+side returns `True`. Similar to ranges, you can exclude the iteration when
+it become `True`/`False` by using `^` on either side. Let's start with an
+example :
+=end comment
+
+for <well met young hero we shall meet later> {
+ # by default, `ff`/`fff` smart-match (`~~`) against `$_`:
+ if 'met' ^ff 'meet' { # Won't enter the if for "met"
+ .say # (explained in details below).
+ }
+
+ if rand == 0 ff rand == 1 { # compare variables other than `$_`
+ say "This ... probably will never run ...";
+ }
+}
+
+=begin comment
+This will print "young hero we shall meet" (excluding "met"): the flip-flop
+will start returning `True` when it first encounters "met" (but will still
+return `False` for "met" itself, due to the leading `^` on `ff`), until it
+sees "meet", which is when it'll start returning `False`.
+=end comment
+
+=begin comment
+The difference between `ff` (awk-style) and `fff` (sed-style) is that `ff`
+will test its right side right when its left side changes to `True`, and can
+get back to `False` right away (*except* it'll be `True` for the iteration
+that matched) while `fff` will wait for the next iteration to try its right
+side, once its left side changed:
+=end comment
+
+# The output is due to the right-hand-side being tested directly (and returning
+# `True`). "B"s are printed since it matched that time (it just went back to
+# `False` right away).
+.say if 'B' ff 'B' for <A B C B A>; # OUTPUT: «B B␤»,
+
+# In this case the right-hand-side wasn't tested until `$_` became "C"
+# (and thus did not match instantly).
+.say if 'B' fff 'B' for <A B C B A>; #=> «B C B␤»,
+
+# A flip-flop can change state as many times as needed:
+for <test start print it stop not printing start print again stop not anymore> {
+ # exclude both "start" and "stop",
+ .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # OUTPUT: «print it print again␤»
+}
+
+# You might also use a Whatever Star, which is equivalent to `True` for the
+# left side or `False` for the right, as shown in this example.
+# NOTE: the parenthesis are superfluous here (sometimes called "superstitious
+# parentheses"). Once the flip-flop reaches a number greater than 50, it'll
+# never go back to `False`.
+for (1, 3, 60, 3, 40, 60) {
+ .say if $_ > 50 ff *; # OUTPUT: «60␤3␤40␤60␤»
+}
+
+# You can also use this property to create an `if` that'll not go through the
+# first time. In this case, the flip-flop is `True` and never goes back to
+# `False`, but the `^` makes it *not run* on the first iteration
+for <a b c> { .say if * ^ff *; } # OUTPUT: «b␤c␤»
+
+# The `===` operator, which uses `.WHICH` on the objects to be compared, is
+# the value identity operator whereas the `=:=` operator, which uses `VAR()` on
+# the objects to compare them, is the container identity operator.
+```
+
+If you want to go further and learn more about Raku, you can:
+
+- Read the [Raku Docs](https://docs.raku.org/). This is a great
+resource on Raku. If you are looking for something, use the search bar.
+This will give you a dropdown menu of all the pages referencing your search
+term (Much better than using Google to find Raku documents!).
+
+- Read the [Raku Advent Calendar](http://perl6advent.wordpress.com/). This
+is a great source of Raku snippets and explanations. If the docs don't
+describe something well enough, you may find more detailed information here.
+This information may be a bit older but there are many great examples and
+explanations. Posts stopped at the end of 2015 when the language was declared
+stable and Raku 6.c was released.
+
+- Come along on `#raku` at `irc.freenode.net`. The folks here are
+always helpful.
+
+- Check the [source of Raku's functions and
+classes](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo is
+mainly written in Raku (with a lot of NQP, "Not Quite Perl", a Raku subset
+easier to implement and optimize).
+
+- Read [the language design documents](https://design.raku.org/). They explain
+Raku from an implementor point-of-view, but it's still very interesting.
+
diff --git a/reason.html.markdown b/reason.html.markdown
new file mode 100644
index 00000000..b8a2215d
--- /dev/null
+++ b/reason.html.markdown
@@ -0,0 +1,544 @@
+---
+language: reason
+filename: reason.re
+contributors:
+ - ["Seth Corker", "https://sethcorker.com"]
+---
+
+Reason is a syntax over OCaml that is easier to get started for programmers who are familiar with C-style syntax like JavaScript. BuckleScript is part of the toolchain which compiles Reason to JavaScript so you can write statically typed code for anywhere that JavaScript runs.
+
+```javascript
+/* Comments start with slash-star, and end with star-slash */
+
+/*----------------------------------------------
+ * Variable and function declaration
+ *----------------------------------------------
+ * Variables and functions use the let keyword and end with a semi-colon
+ * `let` bindings are immutable
+ */
+
+let x = 5;
+/* - Notice we didn't add a type, Reason will infer x is an int */
+
+/* A function like this, take two arguments and add them together */
+let add = (a, b) => a + b;
+/* - This doesn't need a type annotation either! */
+
+/*----------------------------------------------
+ * Type annotation
+ *----------------------------------------------
+ * Types don't need to be explicitly annotated in most cases but when you need
+ * to, you can add the type after the name
+ */
+
+/* A type can be explicitly written like so */
+let x: int = 5;
+
+/* The add function from before could be explicitly annotated too */
+let add2 = (a: int, b: int): int => a + b;
+
+/* A type can be aliased using the type keyword */
+type companyId = int;
+let myId: companyId = 101;
+
+/* Mutation is not encouraged in Reason but it's there if you need it
+ If you need to mutate a let binding, the value must be wrapped in a `ref()`*/
+let myMutableNumber = ref(120);
+
+/* To access the value (and not the ref container), use `^` */
+let copyOfMyMutableNumber = myMutableNumber^;
+
+/* To assign a new value, use the `:=` operator */
+myMutableNumber := 240;
+
+/*----------------------------------------------
+ * Basic types and operators
+ *----------------------------------------------
+ */
+
+/* > String */
+
+/* Use double quotes for strings */
+let greeting = "Hello world!";
+
+/* A string can span multiple lines */
+let aLongerGreeting = "Look at me,
+I'm a multi-line string
+";
+
+/* A quoted string can be used for string interpolation and special chars
+ Use the `js` annotation for unicode */
+let world = {js|🌍|js};
+
+/* The `j` annotation is used for string interpolation */
+let helloWorld = {j|hello, $world|j};
+
+/* Concatenate strings with ++ */
+let name = "John " ++ "Wayne";
+let emailSubject = "Hi " ++ name ++ ", you're a valued customer";
+
+/* > Char */
+
+/* Use a single character for the char type */
+let lastLetter = 'z';
+/* - Char doesn't support Unicode or UTF-8 */
+
+/* > Boolean */
+
+/* A boolean can be either true or false */
+let isLearning = true;
+
+true && false; /* - : bool = false; Logical and */
+true || true; /* - : bool = true; Logical or */
+!true; /* - : bool = false; Logical not */
+
+/* Greater than `>`, or greater than or equal to `>=` */
+'a' > 'b'; /* - bool : false */
+
+/* Less than `<`, or less than or equal to `<=` */
+1 < 5; /* - : bool = true */
+
+/* Structural equal */
+"hello" == "hello"; /* - : bool = true */
+
+/* Referential equal */
+"hello" === "hello"; /* - : bool = false */
+/* - This is false because they are two different "hello" string literals */
+
+/* Structural unequal */
+lastLetter != 'a'; /* -: bool = true */
+
+/* Referential unequal */
+lastLetter !== lastLetter; /* - : bool = false */
+
+/* > Integer */
+/* Perform math operations on integers */
+
+1 + 1; /* - : int = 2 */
+25 - 11; /* - : int = 11 */
+5 * 2 * 3; /* - : int = 30 */
+8 / 2; /* - : int = 4 */
+
+/* > Float */
+/* Operators on floats have a dot after them */
+
+1.1 +. 1.5; /* - : float = 2.6 */
+18.0 -. 24.5; /* - : float = -6.5 */
+2.5 *. 2.0; /* - : float = 5. */
+16.0 /. 4.0; /* - : float = 4. */
+
+/* > Tuple
+ * Tuples have the following attributes
+ - immutable
+ - ordered
+ - fix-sized at creation time
+ - heterogeneous (can contain different types of values)
+ A tuple is 2 or more values */
+
+let teamMember = ("John", 25);
+
+/* Type annotation matches the values */
+let position2d: (float, float) = (9.0, 12.0);
+
+/* Pattern matching is a great tool to retrieve just the values you care about
+ If we only want the y value, let's use `_` to ignore the value */
+let (_, y) = position2d;
+y +. 1.0; /* - : float = 13. */
+
+/* > Record */
+
+/* A record has to have an explicit type */
+type trainJourney = {
+ destination: string,
+ capacity: int,
+ averageSpeed: float,
+};
+
+/* Once the type is declared, Reason can infer it whenever it comes up */
+let firstTrip = {destination: "London", capacity: 45, averageSpeed: 120.0};
+
+/* Access a property using dot notation */
+let maxPassengers = firstTrip.capacity;
+
+/* If you define the record type in a different file, you have to reference the
+ filename, if trainJourney was in a file called Trips.re */
+let secondTrip: Trips.trainJourney = {
+ destination: "Paris",
+ capacity: 50,
+ averageSpeed: 150.0,
+};
+
+/* Records are immutable by default */
+/* But the contents of a record can be copied using the spread operator */
+let newTrip = {...secondTrip, averageSpeed: 120.0};
+
+/* A record property can be mutated explicitly with the `mutable` keyword */
+type breakfastCereal = {
+ name: string,
+ mutable amount: int,
+};
+
+let tastyMuesli = {name: "Tasty Muesli TM", amount: 500};
+
+tastyMuesli.amount = 200;
+/* - tastyMuesli now has an amount of 200 */
+
+/* Punning is used to avoid redundant typing */
+let name = "Just As Good Muesli";
+let justAsGoodMuesli = {name, amount: 500};
+/* - justAsGoodMuesli.name is now "Just As Good Muesli", it's equivalent
+ to { name: name, amount: 500 } */
+
+/* > Variant
+ Mutually exclusive states can be expressed with variants */
+
+type authType =
+ | GitHub
+ | Facebook
+ | Google
+ | Password;
+/* - The constructors must be capitalized like so */
+/* - Like records, variants should be named if declared in a different file */
+
+let userPreferredAuth = GitHub;
+
+/* Variants work great with a switch statement */
+let loginMessage =
+ switch (userPreferredAuth) {
+ | GitHub => "Login with GitHub credentials."
+ | Facebook => "Login with your Facebook account."
+ | Google => "Login with your Google account"
+ | Password => "Login with email and password."
+ };
+
+/* > Option
+ An option can be None or Some('a) where 'a is the type */
+
+let userId = Some(23);
+
+/* A switch handles the two cases */
+let alertMessage =
+ switch (userId) {
+ | Some(id) => "Welcome, your ID is" ++ string_of_int(id)
+ | None => "You don't have an account!"
+ };
+/* - Missing a case, `None` or `Some`, would cause an error */
+
+/* > List
+ * Lists have the following attributes
+ - immutable
+ - ordered
+ - fast at prepending items
+ - fast at splitting
+
+ * Lists in Reason are linked lists
+ */
+
+/* A list is declared with square brackets */
+let userIds = [1, 4, 8];
+
+/* The type can be explicitly set with list('a) where 'a is the type */
+type idList = list(int);
+type attendanceList = list(string);
+
+/* Lists are immutable */
+/* But the contents of a list can be copied using the spread operator */
+let newUserIds = [101, 102, ...userIds];
+
+/* > Array
+ * Arrays have the following attributes
+ - mutable
+ - fast at random access & updates */
+
+/* An array is declared with `[|` and ends with `|]` */
+let languages = [|"Reason", "JavaScript", "OCaml"|];
+
+/*----------------------------------------------
+ * Function
+ *----------------------------------------------
+ */
+
+/* Reason functions use the arrow syntax, the expression is returned */
+let signUpToNewsletter = email => "Thanks for signing up " ++ email;
+
+/* Call a function like this */
+signUpToNewsletter("hello@reason.org");
+
+/* For longer functions, use a block */
+let getEmailPrefs = email => {
+ let message = "Update settings for " ++ email;
+ let prefs = ["Weekly News", "Daily Notifications"];
+
+ (message, prefs);
+};
+/* - the final tuple is implicitly returned */
+
+/* > Labeled Arguments */
+
+/* Arguments can be labeled with the ~ symbol */
+let moveTo = (~x, ~y) => {/* Move to x,y */};
+
+moveTo(~x=7.0, ~y=3.5);
+
+/* Labeled arguments can also have a name used within the function */
+let getMessage = (~message as msg) => "==" ++ msg ++ "==";
+
+getMessage(~message="You have a message!");
+/* - The caller specifies ~message but internally the function can make use */
+
+/* The following function also has explicit types declared */
+let showDialog = (~message: string): unit => {
+ () /* Show the dialog */;
+};
+/* - The return type is `unit`, this is a special type that is equivalent to
+ specifying that this function doesn't return a value
+ the `unit` type can also be represented as `()` */
+
+/* > Currying
+ Functions can be curried and are partially called, allowing for easy reuse */
+
+let div = (denom, numr) => numr / denom;
+let divBySix = div(6);
+let divByTwo = div(2);
+
+div(3, 24); /* - : int = 8 */
+divBySix(128); /* - : int = 21 */
+divByTwo(10); /* - : int = 5 */
+
+/* > Optional Labeled Arguments */
+
+/* Use `=?` syntax for optional labeled arguments */
+let greetPerson = (~name, ~greeting=?, ()) => {
+ switch (greeting) {
+ | Some(greet) => greet ++ " " ++ name
+ | None => "Hi " ++ name
+ };
+};
+/* - The third argument, `unit` or `()` is required because if we omitted it,
+ the function would be curried so greetPerson(~name="Kate") would create
+ a partial function, to fix this we add `unit` when we declare and call it */
+
+/* Call greetPerson without the optional labeled argument */
+greetPerson(~name="Kate", ());
+
+/* Call greetPerson with all arguments */
+greetPerson(~name="Marco", ~greeting="How are you today,");
+
+/* > Pipe */
+/* Functions can be called with the pipeline operator */
+
+/* Use `->` to pass in the first argument (pipe-first) */
+3->div(24); /* - : int = 8 */
+/* - This is equivalent to div(3, 24); */
+
+36->divBySix; /* - : int = 6 */
+/* - This is equivalent to divBySix(36); */
+
+/* Use `|>` to pass in the last argument (pipe-last) */
+24 |> div(3); /* - : int = 8 */
+/* - This is equivalent to div(3, 24); */
+
+36 |> divBySix; /* - : int = 6 */
+/* - This is equivalent to divBySix(36); */
+
+/* Pipes make it easier to chain code together */
+let addOne = a => a + 1;
+let divByTwo = a => a / 2;
+let multByThree = a => a * 3;
+
+let pipedValue = 3->addOne->divByTwo->multByThree; /* - : int = 6 */
+
+/*----------------------------------------------
+ * Control Flow & Pattern Matching
+ *----------------------------------------------
+ */
+
+/* > If-else */
+/* In Reason, `If` is an expression when evaluate will return the result */
+
+/* greeting will be "Good morning!" */
+let greeting = if (true) {"Good morning!"} else {"Hello!"};
+
+/* Without an else branch the expression will return `unit` or `()` */
+if (false) {
+ showDialog(~message="Are you sure you want to leave?");
+};
+/* - Because the result will be of type `unit`, both return types should be of
+ the same type if you want to assign the result. */
+
+/* > Destructuring */
+/* Extract properties from data structures easily */
+
+let aTuple = ("Teacher", 101);
+
+/* We can extract the values of a tuple */
+let (name, classNum) = aTuple;
+
+/* The properties of a record can be extracted too */
+type person = {
+ firstName: string,
+ age: int,
+};
+let bjorn = {firstName: "Bjorn", age: 28};
+
+/* The variable names have to match with the record property names */
+let {firstName, age} = bjorn;
+
+/* But we can rename them like so */
+let {firstName: bName, age: bAge} = bjorn;
+
+let {firstName: cName, age: _} = bjorn;
+
+/* > Switch
+ Pattern matching with switches is an important tool in Reason
+ It can be used in combination with destructuring for an expressive and
+ concise tool */
+
+/* Lets take a simple list */
+let firstNames = ["James", "Jean", "Geoff"];
+
+/* We can pattern match on the names for each case we want to handle */
+switch (firstNames) {
+| [] => "No names"
+| [first] => "Only " ++ first
+| [first, second] => "A couple of names " ++ first ++ "," ++ second
+| [first, second, third] =>
+ "Three names, " ++ first ++ ", " ++ second ++ ", " ++ third
+| _ => "Lots of names"
+};
+/* - The `_` is a catch all at the end, it signifies that we don't care what
+ the value is so it will match every other case */
+
+/* > When clause */
+
+let isJohn = a => a == "John";
+let maybeName = Some("John");
+
+/* When can add more complex logic to a simple switch */
+let aGreeting =
+ switch (maybeName) {
+ | Some(name) when isJohn(name) => "Hi John! How's it going?"
+ | Some(name) => "Hi " ++ name ++ ", welcome."
+ | None => "No one to greet."
+ };
+
+/* > Exception */
+
+/* Define a custom exception */
+exception Under_Age;
+
+/* Raise an exception within a function */
+let driveToTown = (driver: person) =>
+ if (driver.age >= 15) {
+ "We're in town";
+ } else {
+ raise(Under_Age);
+ };
+
+let evan = {firstName: "Evan", age: 14};
+
+/* Pattern match on the exception Under_Age */
+switch (driveToTown(evan)) {
+| status => print_endline(status)
+| exception Under_Age =>
+ print_endline(evan.firstName ++ " is too young to drive!")
+};
+
+/* Alternatively, a try block can be used */
+/* - With Reason exceptions can be avoided with optionals and are seldom used */
+let messageToEvan =
+ try (driveToTown(evan)) {
+ | Under_Age => evan.firstName ++ " is too young to drive!"
+ };
+
+/*----------------------------------------------
+ * Object
+ *----------------------------------------------
+ * Objects are similar to Record types but aren't as rigid
+ * An object resembles a class
+ */
+
+/* An object may be typed like a record but contains a dot */
+type surfaceComputer = {
+ .
+ color: string,
+ capacity: int,
+};
+/* - A single dot signifies a closed object, an object that uses this type
+ must have the exact shape */
+
+let surfaceBook: surfaceComputer = {pub color = "blue"; pub capacity = 512};
+
+/* But an object doesn't require a type */
+let house = {
+ /* A private property */
+ val temp = ref(18.0);
+ /* Public properties */
+ pub temperature = temp;
+ /* A private method only accessible from within house */
+ pri setThermostat = v => temp := v;
+ /* A public method that calls the private setThermostat method */
+ pub arriveHome = () => this#setThermostat(22.0)
+};
+
+house#temperature; /* - : float = 18. */
+house#arriveHome();
+house#temperature; /* - : float = 22. */
+
+/*----------------------------------------------
+ * Module
+ *----------------------------------------------
+ * Modules are used to organize your code and provide namespacing.
+ * Each file is a module by default
+ */
+
+/* Create a module */
+module Staff = {
+ type role =
+ | Delivery
+ | Sales
+ | Other;
+ type member = {
+ name: string,
+ role,
+ };
+
+ let getRoleDirectionMessage = staff =>
+ switch (staff.role) {
+ | Delivery => "Deliver it like you mean it!"
+ | Sales => "Sell it like only you can!"
+ | Other => "You're an important part of the team!"
+ };
+};
+
+/* A module can be accessed with dot notation */
+let newEmployee: Staff.member = {name: "Laura", role: Staff.Delivery};
+
+/* Using the module name can be tiresome so the module's contents can be opened
+ into the current scope with `open` */
+open Staff;
+
+let otherNewEmployee: member = {name: "Fred", role: Other};
+
+/* A module can be extended using the `include` keyword, include copies
+ the contents of the module into the scope of the new module */
+module SpecializedStaff = {
+ include Staff;
+
+ /* `member` is included so there's no need to reference it explicitly */
+ let ceo: member = {name: "Reggie", role: Other};
+
+ let getMeetingTime = staff =>
+ switch (staff) {
+ | Other => 11_15 /* - : int = 1115; Underscores are for formatting only */
+ | _ => 9_30
+ };
+};
+```
+
+## Further Reading
+
+- [Official Reason Docs](https://reasonml.github.io/docs/en/what-and-why)
+- [Official BuckleScript Docs](https://bucklescript.github.io/docs/en/what-why)
+- [Try Reason](https://reasonml.github.io/en/try)
+- [Get Started with Reason by Nik Graf](https://egghead.io/courses/get-started-with-reason)
diff --git a/rst.html.markdown b/rst.html.markdown
index 01595fe4..2423622e 100644
--- a/rst.html.markdown
+++ b/rst.html.markdown
@@ -47,19 +47,27 @@ Title are underlined with equals signs too
Subtitles with dashes
---------------------
-You can put text in *italic* or in **bold**, you can "mark" text as code with double backquote ``print()``.
+You can put text in *italic* or in **bold**, you can "mark" text as code with double backquote ``print()``.
-Lists are as simple as in Markdown:
+Lists are similar to Markdown, but a little more involved.
+
+Remember to line up list symbols (like - or *) with the left edge of the previous text block, and remember to use blank lines to separate new lists from parent lists:
- First item
- Second item
- - Sub item
+
+ - Sub item
+
+- Third item
or
* First item
* Second item
- * Sub item
+
+ * Sub item
+
+* Third item
Tables are really easy to write:
diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown
index 35994749..3acfafa3 100644
--- a/ru-ru/c++-ru.html.markdown
+++ b/ru-ru/c++-ru.html.markdown
@@ -43,11 +43,11 @@ int main(int argc, char** argv)
// Аргументы командной строки, переданные в программу, хранятся в переменных
// argc и argv, так же, как и в C.
// argc указывает на количество аргументов,
- // а argv является массивом C-подобных строк (char*), который непосредсвенно
+ // а argv является массивом C-подобных строк (char*), который непосредственно
// содержит аргументы.
// Первым аргументом всегда передается имя программы.
- // argc и argv могут быть опущены, если вы не планируете работать с аругментами
- // коммандной строки.
+ // argc и argv могут быть опущены, если вы не планируете работать с аргументами
+ // командной строки.
// Тогда сигнатура функции будет иметь следующий вид: int main()
// Возвращаемое значение 0 указывает на успешное завершение программы.
@@ -162,7 +162,7 @@ void foo()
int main()
{
- // Включает все функци из пространства имен Second в текущую область видимости.
+ // Включает все функции из пространства имен Second в текущую область видимости.
// Обратите внимание, что простой вызов foo() больше не работает,
// так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или
// из глобальной области видимости.
@@ -471,6 +471,7 @@ int main() {
// членам\методам без открытых или защищенных методов для этого.
class OwnedDog : public Dog {
+public:
void setOwner(const std::string& dogsOwner);
// Переопределяем поведение функции печати для всех OwnedDog. Смотрите
@@ -582,10 +583,10 @@ public:
// Во время компиляции компилятор фактически генерирует копии каждого шаблона
// с замещенными параметрами, поэтому полное определение класса должно присутствовать
-// при каждом вызове. Именно поэтому классы шаблонов полностью определены в
+// при каждом вызове. Именно поэтому шаблоны классов полностью определены в
// заголовочных файлах.
-// Чтобы создать экземпляр класса шаблона на стеке:
+// Чтобы создать экземпляр шаблона класса на стеке:
Box<int> intBox;
// и вы можете использовать его, как и ожидалось:
@@ -605,7 +606,7 @@ boxOfBox.insert(intBox);
// http://en.wikipedia.org/wiki/Typename
// (да-да, это ключевое слово имеет собственную страничку на вики).
-// Аналогичным образом, шаблонная функция:
+// Аналогичным образом, шаблон функции:
template<class T>
void barkThreeTimes(const T& input)
{
@@ -622,7 +623,7 @@ Dog fluffy;
fluffy.setName("Fluffy");
barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза.
-//Параметры шаблона не должны быть классами:
+// Параметры шаблона не должны быть классами:
template<int Y>
void printMessage() {
cout << "Learn C++ in " << Y << " minutes!" << endl;
@@ -680,7 +681,7 @@ catch (...)
// некоторого ресурса неразрывно совмещается с инициализацией, а освобождение -
// с уничтожением объекта.
-// Чтобы понять, на сколько это полезно,
+// Чтобы понять, насколько это полезно,
// рассмотрим функцию, которая использует обработчик файлов в С:
void doSomethingWithAFile(const char* filename)
{
@@ -796,7 +797,7 @@ void doSomethingWithAFile(const std::string& filename)
// - Контейнеры - стандартная библиотека связанных списков, векторы
// (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически
// уничтожается сразу же, когда выходит за пределы области видимости.
-// - Ипользование мьютексов lock_guard и unique_lock
+// - Использование мьютексов lock_guard и unique_lock
// Контейнеры с пользовательскими классами в качестве ключей требуют
// сравнивающих функций в самом объекте или как указатель на функцию. Примитивы
diff --git a/ru-ru/c-ru.html.markdown b/ru-ru/c-ru.html.markdown
index 44e7ad3b..ba3c19ee 100644
--- a/ru-ru/c-ru.html.markdown
+++ b/ru-ru/c-ru.html.markdown
@@ -77,7 +77,7 @@ int main() {
// sizeof(obj) возвращает размер объекта obj в байтах.
printf("%zu\n", sizeof(int)); // => 4 (на большинстве машин int занимает 4 байта)
- // Если аргуметом sizeof будет выражение, то этот аргумент вычисляется
+ // Если аргументом sizeof будет выражение, то этот аргумент вычисляется
// ещё во время компиляции кода (кроме динамических массивов).
int a = 1;
// size_t это беззнаковый целый тип который использует как минимум 2 байта
@@ -308,7 +308,7 @@ int main() {
// Это работает, потому что при обращении к имени массива возвращается
// указатель на первый элемент.
// Например, когда массив передаётся в функцию или присваивается указателю, он
- // неяввно преобразуется в указатель.
+ // неявно преобразуется в указатель.
// Исключения: когда массив является аргументом для оператор '&':
int arr[10];
int (*ptr_to_arr)[10] = &arr; // &arr не является 'int *'!
@@ -335,7 +335,7 @@ int main() {
// Работа с памятью с помощью указателей может давать неожиданные и
// непредсказуемые результаты.
- printf("%d\n", *(my_ptr + 21)); // => Напечатает кто-нибудь-знает-что?
+ printf("%d\n", *(my_ptr + 21)); // => Напечатает кто-нибудь знает, что?
// Скорей всего программа вылетит.
// Когда вы закончили работать с памятью, которую ранее выделили, вам необходимо
@@ -426,7 +426,7 @@ void function_1() {
// Можно получить доступ к структуре и через указатель
(*my_rec_ptr).width = 30;
- // ... или ещё лучше: используйте оператор -> для лучшей читабельночти
+ // ... или ещё лучше: используйте оператор -> для лучшей читабельности
my_rec_ptr->height = 10; // то же что и "(*my_rec_ptr).height = 10;"
}
@@ -471,7 +471,7 @@ void str_reverse_through_pointer(char *str_in) {
Лучше всего найдите копию [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)
Это **книга** написанная создателями Си. Но будьте осторожны, она содержит идеи которые больше не считаются хорошими.
-Другой хороший ресурс: [Learn C the hard way](http://c.learncodethehardway.org/book/).
+Другой хороший ресурс: [Learn C the hard way](http://learncodethehardway.org/c/).
Если у вас появился вопрос, почитайте [compl.lang.c Frequently Asked Questions](http://c-faq.com).
diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown
index 6c8622cc..37592258 100644
--- a/ru-ru/go-ru.html.markdown
+++ b/ru-ru/go-ru.html.markdown
@@ -35,7 +35,7 @@ package main
// Import предназначен для указания зависимостей этого файла.
import (
"fmt" // Пакет в стандартной библиотеке Go
- "io/ioutil" // Реализация функций ввод/ввывода.
+ "io/ioutil" // Реализация функций ввод/вывода.
"net/http" // Да, это веб-сервер!
"strconv" // Конвертирование типов в строки и обратно
m "math" // Импортировать math под локальным именем m.
@@ -270,7 +270,7 @@ func learnErrorHandling() {
// c – это тип данных channel (канал), объект для конкурентного взаимодействия.
func inc(i int, c chan int) {
- c <- i + 1 // когда channel слева, <- являтся оператором "отправки".
+ c <- i + 1 // когда channel слева, <- является оператором "отправки".
}
// Будем использовать функцию inc для конкурентной инкрементации чисел.
diff --git a/ru-ru/kotlin-ru.html.markdown b/ru-ru/kotlin-ru.html.markdown
index 58dab4cd..85f44c96 100644
--- a/ru-ru/kotlin-ru.html.markdown
+++ b/ru-ru/kotlin-ru.html.markdown
@@ -8,7 +8,7 @@ translators:
- ["Vadim Toptunov", "https://github.com/VadimToptunov"]
---
-Kotlin - статистически типизированный язык для JVM, Android и браузера. Язык полностью совместим c Java.
+Kotlin - статически типизированный язык для JVM, Android и браузера. Язык полностью совместим c Java.
[Более детальная информация здесь.](https://kotlinlang.org/)
```kotlin
diff --git a/ru-ru/learnvisualbasic-ru.html.markdown b/ru-ru/learnvisualbasic-ru.html.markdown
new file mode 100644
index 00000000..72e1358c
--- /dev/null
+++ b/ru-ru/learnvisualbasic-ru.html.markdown
@@ -0,0 +1,284 @@
+---
+language: Visual Basic
+contributors:
+ - ["Brian Martin", "http://brianmartin.biz"]
+translators:
+ - ["satory-ra", "https://github.com/satory-ra"]
+filename: learnvisualbasic-ru.vb
+lang: ru-ru
+---
+
+```vbnet
+Module Module1
+
+ Sub Main()
+ 'Краткий обзор консольных приложений Visual Basic перед более
+ 'глубоким изучением.
+ 'Апостроф начинает строку комментария.
+ 'Чтобы изучить это руководство в компиляторе Visual Basic,
+ 'я создал систему навигации.
+ 'Эта система будет объяснена при прохождении этого урока.
+ 'Постепенно вы всё поймете.
+ Console.Title = ("Выучи Х за Y минут")
+ Console.WriteLine("НАВИГАЦИЯ") 'Display
+ Console.WriteLine("")
+ Console.ForegroundColor = ConsoleColor.Green
+ Console.WriteLine("1. Вывод данных")
+ Console.WriteLine("2. Ввод данных")
+ Console.WriteLine("3. Расчёт целых чисел")
+ Console.WriteLine("4. Расчёт десятичных дробей")
+ Console.WriteLine("5. Калькулятор")
+ Console.WriteLine("6. Использование циклов Do While")
+ Console.WriteLine("7. Использование циклов For")
+ Console.WriteLine("8. Условные выражения")
+ Console.WriteLine("9. Выберите напиток")
+ Console.WriteLine("50. О приложении")
+ Console.WriteLine("Выберите номер из списка")
+ Dim selection As String = Console.ReadLine
+ '«Case» в операторе Select не является обязательным.
+ 'Например, "Select selection" вместо "Select Case selection"
+ 'также будет работать.
+ Select Case selection
+ Case "1" 'Вывод данных
+ Console.Clear() 'Очищает окно консоли
+ HelloWorldOutput() 'Открывает приватную подпрограмму.
+ Case "2" 'Ввод данных
+ Console.Clear()
+ HelloWorldInput()
+ Case "3" 'Расчёт целых чисел
+ Console.Clear()
+ CalculatingWholeNumbers()
+ Case "4" 'Расчёт десятичных дробей
+ Console.Clear()
+ CalculatingDecimalNumbers()
+ Case "5" 'Калькулятор
+ Console.Clear()
+ WorkingCalculator()
+ Case "6" 'Использование циклов Do While
+ Console.Clear()
+ UsingDoWhileLoops()
+ Case "7" 'Использование циклов For
+ Console.Clear()
+ UsingForLoops()
+ Case "8" 'Условные выражения
+ Console.Clear()
+ ConditionalStatement()
+ Case "9" 'Выражения If/Else
+ Console.Clear()
+ IfElseStatement() 'Выберите напиток
+ Case "50" 'Окно сообщения «О приложении»
+ Console.Clear()
+ Console.Title = ("Выучи Х за Y минут :: О приложении")
+ MsgBox("Это руководство от Брайана Мартина (@BrianMartinn")
+ Console.Clear()
+ Main()
+ Console.ReadLine()
+
+ End Select
+ End Sub
+
+ 'Один - Я использую эти цифры для того, чтобы было проще
+ 'соотносить код с системой навигации.
+
+ 'Мы используем частные подпрограммы для разделения различных
+ 'разделов программы.
+ Private Sub HelloWorldOutput()
+ 'Название консольного приложения
+ Console.Title = "Вывод данных | Выучи Х за Y минут"
+ 'Используйте Console.Write ("") или Console.WriteLine ("")
+ 'для отображения результатов.
+ 'Затем следует Console.Read () или Console.Readline ()
+ 'Console.ReadLine () показывает вывод в консоли.
+ Console.WriteLine("Hello World")
+ Console.ReadLine()
+ End Sub
+
+ 'Два
+ Private Sub HelloWorldInput()
+ Console.Title = "Ввод данных | Выучи Х за Y минут"
+ 'Переменная
+ 'используется для хранения пользовательских данных.
+ 'Объявление переменных начинается с Dim и заканчиваются
+ 'As VariableType (тип переменной).
+
+ 'В этом уроке мы хотим узнать ваше имя и заставить программу
+ 'реагировать на это.
+ Dim username As String
+ 'Мы используем тип «string», так как ваше имя - это текстовая переменная.
+ Console.WriteLine("Привет, как тебя зовут? ") 'Просит ввести имя.
+ username = Console.ReadLine() 'Сохраняет имя в переменной username.
+ Console.WriteLine("Пирвет, " + username) 'Выводит: «Привет, 'имя'»
+ Console.ReadLine() 'Отображает вышеуказанный вывод.
+
+ 'Вышеуказанная программа спросит ваше имя и скажет вам привет.
+ 'Есть и другие типы переменных, такие как целые числа (Integer),
+ 'мы используем Integer для обработки целых чисел.
+ End Sub
+
+ 'Три
+ Private Sub CalculatingWholeNumbers()
+ Console.Title = "Расчёт целых чисел | Выучи Х за Y минут"
+ Console.Write("Первое число: ") 'Введите первое целое число: 1, 2, 50, 104 и т.д.
+ Dim a As Integer = Console.ReadLine()
+ Console.Write("Второе число: ") 'Введите второе целое число.
+ Dim b As Integer = Console.ReadLine()
+ Dim c As Integer = a + b
+ Console.WriteLine(c)
+ Console.ReadLine()
+ 'Приведенная программа сумирует два целых числа
+ End Sub
+
+ 'Четыре
+ Private Sub CalculatingDecimalNumbers()
+ Console.Title = "Расчёт десятичных дробей | Выучи Х за Y минут"
+ 'Мы также должны уметь обрабатывать десятичные дроби.
+ 'Просто измените тип переменной с Integer на Double.
+
+ 'Введите число с плавающей точкой: 1.2, 2.4, 50.1, 104.9 и т.д.
+ Console.Write("Первое число: ")
+ Dim a As Double = Console.ReadLine
+ Console.Write("Второе число: ") 'Введите второе число с плавающей точкой.
+ Dim b As Double = Console.ReadLine
+ Dim c As Double = a + b
+ Console.WriteLine(c)
+ Console.ReadLine()
+ 'Приведенный выше код может сложить две десятичных дроби.
+ End Sub
+
+ 'Пять
+ Private Sub WorkingCalculator()
+ Console.Title = "Калькулятор | Выучи Х за Y минут"
+ 'Но что, если вам нужен калькулятор, который может обрабатывать сложение,
+ 'вычитание, умножение и деление?
+ 'Просто скопируйте и вставьте приведенный код.
+ Console.Write("Первое число: ")
+ Dim a As Double = Console.ReadLine
+ Console.Write("Второе число: ")
+ Dim b As Double = Console.ReadLine
+ Dim c As Double = a + b
+ Dim d As Double = a * b
+ Dim e As Double = a - b
+ Dim f As Double = a / b
+
+ 'С помощью следующего кода мы можем вывести результат сложения,
+ 'вычитания, умножения и деления, рассчитанный выше, на экран.
+ Console.Write(a.ToString() + " + " + b.ToString())
+ 'Мы хотим, чтобы в начале ответа было 3 пробела, для этого
+ 'вы можете использовать метод String.PadLeft (3).
+ Console.WriteLine(" = " + c.ToString.PadLeft(3))
+ Console.Write(a.ToString() + " * " + b.ToString())
+ Console.WriteLine(" = " + d.ToString.PadLeft(3))
+ Console.Write(a.ToString() + " - " + b.ToString())
+ Console.WriteLine(" = " + e.ToString.PadLeft(3))
+ Console.Write(a.ToString() + " / " + b.ToString())
+ Console.WriteLine(" = " + f.ToString.PadLeft(3))
+ Console.ReadLine()
+
+ End Sub
+
+ 'Шесть
+ Private Sub UsingDoWhileLoops()
+ 'Код такой же, как и в предидущей подпрограмме
+ 'На этот раз мы спрашиваем, хочет ли пользователь продолжить (да или нет?)
+ 'Мы будем использовать цикл Do While, потому что не знаем,
+ 'понадобиться ли пользователю калькулятор болше одного раза.
+ Console.Title = "Использование циклов Do While | Выучи Х за Y минут"
+ Dim answer As String
+ 'Мы используем тип переменной "String", так как её значение текст.
+ Do 'Мы начаем программу с
+ Console.Write("Первое число: ")
+ Dim a As Double = Console.ReadLine
+ Console.Write("Второе число: ")
+ Dim b As Double = Console.ReadLine
+ Dim c As Double = a + b
+ Dim d As Double = a * b
+ Dim e As Double = a - b
+ Dim f As Double = a / b
+
+ Console.Write(a.ToString() + " + " + b.ToString())
+ Console.WriteLine(" = " + c.ToString.PadLeft(3))
+ Console.Write(a.ToString() + " * " + b.ToString())
+ Console.WriteLine(" = " + d.ToString.PadLeft(3))
+ Console.Write(a.ToString() + " - " + b.ToString())
+ Console.WriteLine(" = " + e.ToString.PadLeft(3))
+ Console.Write(a.ToString() + " / " + b.ToString())
+ Console.WriteLine(" = " + f.ToString.PadLeft(3))
+ Console.ReadLine()
+ 'Спросите пользователя, хочет ли он продолжить,
+ 'в ответе учитывается регистр букв.
+ Console.Write("Желаете ли вы продолжить? (да / нет)")
+ 'Программа берет значение и записывает в переменную answer.
+ answer = Console.ReadLine()
+ 'Когда пользователь вводит «да», программа переходит к Do и снова запускается.
+ Loop While answer = "yes"
+
+ End Sub
+
+ 'Семь
+ Private Sub UsingForLoops()
+ 'Иногда программу нужно запускать только один раз.
+ 'В этой программе мы осуществим обратный отсчет от 10.
+
+ Console.Title = "Использование циклов For | Выучи Х за Y минут"
+ 'Объявите переменные и Step (размер шага, то есть скорость уменьшения,
+ 'например, -1, -2, -3 и т.д.).
+ For i As Integer = 10 To 0 Step -1
+ Console.WriteLine(i.ToString) 'Показывает значение счетчика.
+ Next i 'Рассчитать новое значение i.
+ Console.WriteLine("Поехали")
+ Console.ReadLine()
+ End Sub
+
+ 'Восемь
+ Private Sub ConditionalStatement()
+ Console.Title = "Условные выражения | Выучи Х за Y минут"
+ Dim userName As String
+ Console.WriteLine("Привет, как тебя зовут? ") 'Спросите имя пользователя.
+ userName = Console.ReadLine() 'Записать имя в переменную userName.
+ If userName = "Адам" Then
+ Console.WriteLine("Привет, Адам")
+ Console.WriteLine("Спасибо за создание этого полезного сайта")
+ Console.ReadLine()
+ Else
+ Console.WriteLine("Привет " + userName)
+ Console.WriteLine("Вы заглянули на сайт www.learnxinyminutes.com")
+ Console.ReadLine() 'Программа останавливается и выводит вышеуказанный текст.
+ End If
+ End Sub
+
+ 'Девять
+ Private Sub IfElseStatement()
+ Console.Title = "Выражения If/Else | Выучи Х за Y минут"
+ 'Иногда важно рассмотреть более двух альтернатив.
+ 'Иногда некоторые из них лучше других.
+ 'Когда это произойдет, нам потребуется более одного утверждения «if» (если).
+ 'Оператор «if» подобен торговому автомату.
+ 'В котором пользователь пишет код (A1, A2, A3 и т.д.), чтобы выбрать элементы.
+ 'Все варианты могут быть объединены в одном утверждении «if».
+
+ Dim selection As String 'Объявить переменную для выбора
+ Console.WriteLine("Пожалуйста, выберите продукт из нашего прекрасного торгового автомата.")
+ Console.WriteLine("A1. для 7Up")
+ Console.WriteLine("A2. для Fanta")
+ Console.WriteLine("A3. для Dr. Pepper")
+ Console.WriteLine("A4. для Diet Coke")
+
+ selection = Console.ReadLine() 'Сохранить выбор пользователя
+ If selection = "A1" Then
+ Console.WriteLine("7up")
+ ElseIf selection = "A2" Then
+ Console.WriteLine("Fanta")
+ ElseIf selection = "A3" Then
+ Console.WriteLine("Dr. Pepper")
+ ElseIf selection = "A4" Then
+ Console.WriteLine("Diet Coke")
+ Else
+ Console.WriteLine("Извините, у меня нет " + selection)
+ End If
+ Console.ReadLine()
+
+ End Sub
+
+End Module
+
+```
diff --git a/ru-ru/linker-ru.html.markdown b/ru-ru/linker-ru.html.markdown
new file mode 100644
index 00000000..7df29c23
--- /dev/null
+++ b/ru-ru/linker-ru.html.markdown
@@ -0,0 +1,203 @@
+---
+category: tool
+tool: linker
+contributors:
+ - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
+translators:
+ - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"]
+lang: ru-ru
+---
+
+# Основные понятия и определения
+**Счетчик позиций** - у компоновщика есть специальная переменная
+"." (точка) всегда содержит текущую позицию вывода.
+
+# Функции
+**ADDR(section)** - возвращает абсолютный адрес указанной секции. Однако
+данная секция должна быть определенна до использования функции ADDR.
+
+**ALIGN(exp)** - возвращает значение счетчика позиций, выравненное на границу
+следующего за exp выражения.
+
+**SIZEOF(section)** - возвращает размер секции в байтах.
+
+**FILL(param)** - определяет образец заполнения для текущей секции. Все
+остальные неуказанные регионы внутри секции заполняются значением указанными
+в аргументе функции.
+
+**KEEP(param)** - используется чтобы помечать param как неустранимый.
+
+**ENTRY(func)** - определяет функцию, которая будет являться точкой входа
+в программу.
+
+```bash
+# Определяем точку входа в программу
+ENTRY(Reset_Handler)
+
+# Определяем перемнную которая содержит адрес вершины стека
+_estack = 0x20020000;
+# Определяем перемнную которая содержит значение размера кучи
+_Min_Heap_Size = 0x200;
+# Определяем перемнную которая содержит значение размера стека
+_Min_Stack_Size = 0x400;
+
+# Описание карты памяти доступной для данного процессора
+# MEMORY
+# {
+# ИМЯ_ОБЛАСТИ_ПАМЯТИ (права доступа) : ORIGIN = АДРЕС_НАЧАЛА, LENGTH = РАЗМЕР
+# }
+# В нашем примере контроллер содержит три области памяти:
+# RAM - начинается с адреса 0x20000000 и занимает 128 Кбайт;
+# CCMRAM - начинается с адреса 0x10000000и занимает 64 Кбайт;
+# FLASH - начинается с адреса 0x8000000 занимает 1024 Кбайт;
+# Причем RAM память доступка для чтения, записи и исполнения.
+# CCMRAM память доступна только на чтение и запись.
+# FLASH память доступна на чтение и исполнение.
+MEMORY
+{
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+ CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
+ FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
+}
+
+# Описываем выходные секции
+SECTIONS
+{
+ # Первая секция содержит таблицу векторов прерываний
+ .isr_vector :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Существует опция --gc-sections, которая позволяет собирать мусор из неиспользуемых
+ # входных разделов. И если есть разделы, которые сборщик муссора не должен трогать,
+ # то их необходимо указать в качестве аргумента функции KEEP() (аналог ключевого слова
+ # volatile).
+ # Запись (*(.isr_vector)) означает разделы .isr_vector во всех объектных файлах. Т.к.
+ # обращение к разделу в общем виде выглядит так: (ИМЯ_ФАЙЛА(ИМЯ_РАЗДЕЛА))
+ KEEP(*(.isr_vector))
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещенна
+ # данная секция. В нашем слущае секция .isr_vector будет размещена во FLASH памяти.
+ } >FLASH
+
+# ИТОГО: Секция .isr_vector, которая содержит таблицу векторов прерываний выравнивается
+# по границе 4-х байт, помечается как недоступная для сборщика мусора и размещается в начале
+# FLASH памяти микроконтроллера.
+
+ # Вторая секция содержит код программы.
+ .text :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Указываем, что в данной секции будут хранится области .text всех
+ # объектных файлов
+ *(.text)
+ *(.text*)
+
+ # Защищаем от сборщика мусора секции .init и .fini
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Определяется переменная _etext, которая хранит в себе адрес конца секции .text и которая
+ # может быть доступна в исходном тексте программы через объявление
+ # volaile unsigned int extern _etext;
+ _etext = .;
+ } >FLASH
+
+# ИТОГО: Секция .text, которая содержит код программы выравнивается по границе 4-х байт,
+# включает в себя: все секции с кодом программы во всех объектных файлах и защищенные
+от сборщика муссора секции .init и .fini во всех объектных файлах, распологается во FLASH
+памяти микроконтроллера сразу за таблицей векторов.
+Секции text, .init и .fini. располагаются в памяти в той последовательности в которой они
+объявлены в скрипте.
+
+ # Третья секция содержит константные данные.
+ .rodata :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Указываем, что в данной секции будут хранится области .rodataвсех
+ # объектных файлов
+ *(.rodata)
+ *(.rodata*)
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+ } >FLASH
+
+ # Сохраняем в переменной _sidata абсолютный адрес секции .data
+ _sidata = LOADADDR(.data);
+
+ # Четвертая секция содержит инициализированные переменные.
+ .data :
+ {
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Сохраняем в переменной _sdata адрес текущей позиции (начала секции)
+ _sdata = .;
+
+ # Указываем, что в данной секции будут хранится области .data всех
+ # объектных файлов
+ *(.data)
+ *(.data*)
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Сохраняем в переменной _sdata адрес текущей позиции (конец секции)
+ _edata = .;
+
+ # Функция AT указывает на то, что данный сектор хранится в одной области памяти
+ # (в нашем случае FLASH), а исполняться будет из другой обасти памяти (в нашем случае RAM).
+ # Есть два типа адрессов:
+ # * VMA (Virtual memory address) - это run-time адрес по которому уомпилятор ожидает
+ # видеть данные.
+ # * LMA (Load memory address) - это адрес по которому линкер хранит данные.
+
+ #Startup должен код скопировать секцию .data из адрессов LMA в адресса VMA.
+
+ } >RAM AT> FLASH
+
+ # Пятая секция содержит инициализированные нулем переменные.
+ .bss :
+ {
+ # Сохраняем в переменной _sbss и __bss_start__ адрес текущей позиции (начала секции)
+ _sbss = .;
+ __bss_start__ = _sbss;
+
+ # Указываем, что в данной секции будут хранится области .bss всех
+ # объектных файлов
+ *(.bss)
+ *(.bss*)
+
+ # Выравниваем текущую позицию на границу 4-х байт.
+ . = ALIGN(4);
+
+ # Сохраняем в переменной _ebss и __bss_end__ адрес текущей позиции (начала секции)
+ _ebss = .;
+ __bss_end__ = _ebss;
+ } >RAM
+
+ # Шестая секция содержит кучу и стек. Размещается в самом конце RAM.
+ ._user_heap_stack :
+ {
+ . = ALIGN(4);
+ PROVIDE ( end = . );
+ PROVIDE ( _end = . );
+ . = . + _Min_Heap_Size;
+ . = . + _Min_Stack_Size;
+ . = ALIGN(4);
+ } >RAM
+}
+```
+
diff --git a/ru-ru/ruby-ru.html.markdown b/ru-ru/ruby-ru.html.markdown
index e69c6d94..b1fd04e1 100644
--- a/ru-ru/ruby-ru.html.markdown
+++ b/ru-ru/ruby-ru.html.markdown
@@ -231,6 +231,7 @@ new_hash.value?(3) #=> true
# Управление ходом выполнения (Управляющие структуры)
+# Условия
if true
'Если истина'
elsif false
@@ -239,6 +240,15 @@ else
'Во всех других случаях (тоже опционально)'
end
+# Если условие контролирует выполнение не блока кода, а единственного выражения,
+# можно использовать постфиксную запись условного оператора
+warnings = ['Отсутствует отчество', 'Слишком короткий адрес']
+puts("Обратите внимание:\n" + warnings.join("\n")) if !warnings.empty?
+
+# Иногда условие лучше звучит с `unless`, чем с `if`
+puts("Обратите внимание:\n" + warnings.join("\n")) unless warnings.empty?
+
+# Циклы
for counter in 1..5
puts "итерация #{counter}"
end
diff --git a/ru-ru/rust-ru.html.markdown b/ru-ru/rust-ru.html.markdown
index 7bd2809a..9293a40e 100644
--- a/ru-ru/rust-ru.html.markdown
+++ b/ru-ru/rust-ru.html.markdown
@@ -6,36 +6,33 @@ contributors:
- ["P1start", "http://p1start.github.io/"]
translators:
- ["Anatolii Kosorukov", "https://github.com/java1cprog"]
+ - ["Vasily Starostin", "https://github.com/Basil22"]
lang: ru-ru
---
-Rust сочетает в себе низкоуровневый контроль над производительностью с удобством высокого уровня и предоставляет гарантии
-безопасности.
-Он достигает этих целей, не требуя сборщика мусора или времени выполнения, что позволяет использовать библиотеки Rust как замену
-для C-библиотек.
+Язык Rust разработан в Mozilla Research. Он сочетает низкоуровневую производительность с удобством языка высокого уровня и одновременно гарантирует безопасность памяти.
-Первый выпуск Rust, 0.1, произошел в январе 2012 года, и в течение 3 лет развитие продвигалось настолько быстро, что до
-недавнего времени использование стабильных выпусков было затруднено, и вместо этого общий совет заключался в том, чтобы
-использовать последние сборки.
+Он достигает этих целей без сборщика мусора или сложной среды выполнения, что позволяет использовать библиотеки Rust как прямую замену
+C-библиотек. И наоборот, Rust умеет использовать готовые С-библиотеки как есть, без накладных расходов.
-15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Усовершенствования времени компиляции и
-других аспектов компилятора в настоящее время доступны в ночных сборках. Rust приняла модель выпуска на поезде с регулярными выпусками каждые шесть недель. Rust 1.1 beta был доступен одновременно с выпуском Rust 1.0.
+Первый выпуск Rust, 0.1, произошел в январе 2012 года. В течение 3 лет развитие продвигалось настолько быстро, что язык серьезно менялся без сохранения совместимости. Это дало возможность обкатать и отполировать синтаксис и возможности языка.
-Хотя Rust является языком относительно низкого уровня, Rust имеет некоторые функциональные концепции, которые обычно
-встречаются на языках более высокого уровня. Это делает Rust не только быстрым, но и простым и эффективным для ввода кода.
+15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Сборка поставляется в трех вариантах: стабильная версия, бета-версия, ночная версия. Все нововведения языка сперва обкатываются на ночной и бета-версиях, и только потом попадают в стабильную. Выход очередной версии происходит раз в 6 недель. В 2018 году вышло второе большое обновление языка, добавившее ему новых возможностей.
+
+Хотя Rust является языком относительно низкого уровня, он имеет все возможности высокоуровневых языков: процедурное, объектное, функциональное, шаблонное и другие виды программирования. На данный момент Rust является одним из самых мощных (а может быть и самым) по возможностям среди статически типизированных языков. Это делает Rust не только быстрым, но и простым и эффективным для разработки сложного кода.
```rust
-// Это однострочный комментарии
+// Это однострочный комментарий
//
/// Так выглядит комментарий для документации
/// # Examples
///
-///
+/// ```
/// let seven = 7
-///
+/// ```
///////////////
// 1. Основы //
@@ -63,10 +60,9 @@ fn main() {
let y: i32 = 13i32;
let f: f64 = 1.3f64;
- // Автоматическое выявление типа данных
+ // Автоматическое выведение типа данных
// В большинстве случаев компилятор Rust может вычислить
- // тип переменной, поэтому
- // вам не нужно писать явные аннотации типа.
+ // тип переменной, поэтому вам не нужно явно указывать тип.
let implicit_x = 1;
let implicit_f = 1.3;
@@ -87,12 +83,11 @@ fn main() {
// Печать на консоль
println!("{} {}", f, x); // 1.3 hello world
- // `String` – изменяемя строка
+ // `String` – изменяемая строка
let s: String = "hello world".to_string();
- // Строковый срез - неизменяемый вид в строки
- // Это в основном неизменяемая пара указателей на строку -
- // Это указатель на начало и конец строкового буфера
+ // Строковый срез - неизменяемое представление части строки
+ // Представляет собой пару из указателя на начало фрагмента и его длины
let s_slice: &str = &s;
@@ -130,7 +125,7 @@ fn main() {
// 2. Типы //
//////////////
- // Struct
+ // Структура
struct Point {
x: i32,
y: i32,
@@ -154,6 +149,8 @@ fn main() {
let up = Direction::Up;
// Перечисление с полями
+ // В отличие от C и C++ компилятор автоматически следит за тем,
+ // какой именно тип хранится в перечислении.
enum OptionalI32 {
AnI32(i32),
Nothing,
@@ -175,7 +172,7 @@ fn main() {
// Методы //
impl<T> Foo<T> {
- fn get_bar(self) -> T {
+ fn get_bar(self) -> T {
self.bar
}
}
@@ -198,9 +195,9 @@ fn main() {
let another_foo = Foo { bar: 1 };
println!("{:?}", another_foo.frobnicate()); // Some(1)
- /////////////////////////
- // 3. Поиск по шаблону //
- /////////////////////////
+ /////////////////////////////////
+ // 3. Сопоставление по шаблону //
+ /////////////////////////////////
let foo = OptionalI32::AnI32(1);
match foo {
@@ -223,9 +220,9 @@ fn main() {
println!("The second number is Nothing!"),
}
- /////////////////////
+ //////////////////////////////////////////////
// 4. Управление ходом выполнения программы //
- /////////////////////
+ //////////////////////////////////////////////
// `for` loops/iteration
let array = [1, 2, 3];
@@ -233,7 +230,7 @@ fn main() {
println!("{}", i);
}
- // Отрезки
+ // Диапазоны
for i in 0u32..10 {
print!("{} ", i);
}
@@ -266,12 +263,12 @@ fn main() {
break;
}
- /////////////////////////////////
+ //////////////////////////////////
// 5. Защита памяти и указатели //
- /////////////////////////////////
+ //////////////////////////////////
// Владеющий указатель – такой указатель может быть только один
- // Это значит, что при вызоде из блока переменная автоматически становится недействительной.
+ // Это значит, что при выходе из блока переменная автоматически становится недействительной.
let mut mine: Box<i32> = Box::new(3);
*mine = 5; // dereference
// Здесь, `now_its_mine` получает во владение `mine`. Т.е. `mine` была перемещена.
diff --git a/ru-ru/sql-ru.html.markdown b/ru-ru/sql-ru.html.markdown
new file mode 100644
index 00000000..7353a175
--- /dev/null
+++ b/ru-ru/sql-ru.html.markdown
@@ -0,0 +1,120 @@
+---
+language: SQL
+filename: learnsql-ru.sql
+contributors:
+ - ["Bob DuCharme", "http://bobdc.com/"]
+translators:
+ - ["Shaltaev", "https://github.com/shaltaev"]
+ - ["Andre Polykanine", "https://github.com/Menelion"]
+lang: ru-ru
+---
+
+Язык структурированных запросов (SQL) — это стандартный язык ISO для создания
+и работы с базами данных, хранящимися в наборе таблиц. Реализации обычно
+добавляют свои собственные расширения к языку;
+[Сравнение различных реализаций SQL](http://troels.arvin.dk/db/rdbms/) — хороший справочник по различиям в продуктах.
+
+Реализации обычно предоставляют приглашение командной строки, где вы можете
+вводить команды, описанные ниже, в интерактивном режиме, также есть способ
+выполнить серию таких команд, сохранённых в файле скрипта.
+(Результат того, что вы сделали с помощью интерактивного режима, является
+хорошим примером того, что не стандартизировано, — большинство реализаций SQL
+поддерживают ключевые слова QUIT, EXIT или оба).
+
+Некоторые команды ниже предполагают использование
+[демонстрационного образца базы данных сотрудников от MySQL](https://dev.mysql.com/doc/employee/en/), доступного на [Github](https://github.com/datacharmer/test_db).
+Следовательно, для повторения команд в локальном окружении он должен быть загружен.
+Файлы на github — это скрипты с командами, которые схожи с командами ниже,
+которые создают и манипулируют таблицами и данными о сотрудниках вымышленной
+компании. Синтаксис для запуска этих скриптов будет зависеть от используемой
+вами реализации SQL. Обычно используется утилита, запускаемая из командной
+строки в вашей операционной системе.
+
+```sql
+-- Комментарии начинаются с двух дефисов. Завершайте каждую команду
+-- точкой с запятой.
+
+-- SQL не учитывает регистр букв для ключевых слов. Примеры команд здесь
+-- следуют соглашению о написании в верхнем регистре, потому что
+-- это позволяет легче отличить их от имён баз, таблиц и колонок.
+
+-- Создание и удаление базы данных. Имена базы и таблицы чувствительны
+-- к регистру букв.
+CREATE DATABASE someDatabase;
+DROP DATABASE someDatabase;
+
+-- Список доступных баз.
+SHOW DATABASES;
+
+-- Выбор базы для работы.
+USE employees;
+
+-- Выбрать все строки и колонки из таблицы «departments» (отделы) текущей базы.
+-- В интерактивном режиме обыч но результат будет выведен на экран.
+SELECT * FROM departments;
+
+-- Тот же запрос, что и выше, но выбор только колонок «dept_no» и «dept_name».
+-- Разбиение команд на несколько строк допустимо.
+SELECT dept_no,
+ dept_name FROM departments;
+
+-- В данном случае будут выбраны все колонки, но только первые 5 строк.
+SELECT * FROM departments LIMIT 5;
+
+-- Выбор названий отделов, содержащих подстроку «en».
+SELECT dept_name FROM departments WHERE dept_name LIKE '%en%';
+
+-- Выбор всех колонок, где названия отделов начинаются на «S»,
+-- после которой идёт ровно четыре символа.
+SELECT * FROM departments WHERE dept_name LIKE 'S____';
+
+-- Выбор всех должностей из таблицы «titles», но без повторений.
+SELECT DISTINCT title FROM titles;
+
+-- В дополнение к предыдущему запросу результат будет отсортирован
+-- в алфавитном порядке (с учётом регистра).
+SELECT DISTINCT title FROM titles ORDER BY title;
+
+-- Показать число строк в таблице отделов.
+SELECT COUNT(*) FROM departments;
+
+-- Показать число строк, где название отдела содержит подстроку «en»
+SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%';
+
+-- Объединение информации из нескольких таблиц:
+-- В таблице «titles» перечислены должности, кто их занимал по номеру сотрудника,
+-- а также с какой даты по какую. Получим эту информацию, но используем номера
+-- сотрудников как ссылку на таблицу «employees», чтобы получить имя и фамилию
+-- каждого сотрудника. Выводим только 10 строк.
+SELECT employees.first_name, employees.last_name,
+ titles.title, titles.from_date, titles.to_date
+FROM titles INNER JOIN employees ON
+ employees.emp_no = titles.emp_no LIMIT 10;
+
+-- Список всех таблиц во всех базах. Реализации обычно предоставляют
+-- собственные сокращения, чтобы показать все таблицы текущей базы.
+SELECT * FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_TYPE='BASE TABLE';
+
+-- Создать таблицу с именем tablename1 и двумя колонками в текущей базе.
+-- Для колонок имеется множество параметров, таких как тип данных.
+CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20));
+
+-- Вставляем строку данных в таблицу «tablename1». Предполагаем, что таблица
+-- настроена таким образом, чтобы принимать эти значения.
+INSERT INTO tablename1 VALUES('Richard','Mutt');
+
+-- В таблице «tablename1» изменить значение fname на «John»
+-- для каждой строки, где колонка lname равна «Mutt».
+UPDATE tablename1 SET fname='John' WHERE lname='Mutt';
+
+-- Удалить из таблицы «tablename1» строки,
+-- где значение колонки lname начинается с «M».
+DELETE FROM tablename1 WHERE lname like 'M%';
+
+-- Удалить все строки из таблицы «tablename1». В итоге получим пустую таблицу.
+DELETE FROM tablename1;
+
+-- Удалить таблицу «tablename1» полностью.
+DROP TABLE tablename1;
+```
diff --git a/ru-ru/yaml-ru.html.markdown b/ru-ru/yaml-ru.html.markdown
index 6eb580d9..0f805681 100644
--- a/ru-ru/yaml-ru.html.markdown
+++ b/ru-ru/yaml-ru.html.markdown
@@ -24,7 +24,7 @@ YAML как язык сериализации данных предназнач
# Скалярные величины #
######################
-# Наш корневой объект (который продолжается для всего документа) будет соответствовать
+# Наш корневой объект (который продолжается до конца документа) будет соответствовать
# типу map, который в свою очередь соответствует словарю, хешу или объекту в других языках.
key: value
another_key: Другое значение ключа.
diff --git a/ruby.html.markdown b/ruby.html.markdown
index 2595d1d5..3fc2ed2d 100644
--- a/ruby.html.markdown
+++ b/ruby.html.markdown
@@ -23,6 +23,15 @@ contributors:
```ruby
# This is a comment
+=begin
+This is a multi-line comment.
+The beginning line must start with "=begin"
+and the ending line must start with "=end".
+
+You can do this, or start each line in
+a multi-line comment with the # character.
+=end
+
# In Ruby, (almost) everything is an object.
# This includes numbers...
3.class #=> Integer
@@ -247,6 +256,14 @@ else
'else, also optional'
end
+# If a condition controls invokation 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?
+
+# Rephrase condition if `unless` sounds better than `if`
+puts("Some warnings occurred:\n" + warnings.join("\n")) unless warnings.empty?
+
# Loops
# In Ruby, traditional `for` loops aren't very common. Instead, these
# basic loops are implemented using enumerable, which hinges on `each`.
@@ -402,7 +419,7 @@ def guests(&block)
end
# The 'call' method on the Proc is similar to calling 'yield' when a block is
-# present. The arguments passed to 'call' will be forwarded to the block as arugments.
+# present. The arguments passed to 'call' will be forwarded to the block as arguments.
guests { |n| "You have #{n} guests." }
# => "You have 4 guests."
diff --git a/rust.html.markdown b/rust.html.markdown
index 71bc16b5..92794e69 100644
--- a/rust.html.markdown
+++ b/rust.html.markdown
@@ -92,10 +92,8 @@ fn main() {
let s: String = "hello world".to_string();
// A string slice – an immutable view into another string
- // This is basically an immutable pair of pointers to a string – it doesn’t
- // actually contain the contents of a string, just a pointer to
- // the begin and a pointer to the end of a string buffer,
- // statically allocated or contained in another object (in this case, `s`)
+ // The string buffer can be statically allocated like in a string literal
+ // or contained in another object (in this case, `s`)
let s_slice: &str = &s;
println!("{} {}", s, s_slice); // hello world hello world
@@ -290,7 +288,7 @@ fn main() {
// Reference – an immutable pointer that refers to other data
// When a reference is taken to a value, we say that the value has been ‘borrowed’.
// While a value is borrowed immutably, it cannot be mutated or moved.
- // A borrow lasts until the end of the scope it was created in.
+ // A borrow is active until the last use of the borrowing variable.
let mut var = 4;
var = 3;
let ref_var: &i32 = &var;
@@ -299,6 +297,8 @@ fn main() {
println!("{}", *ref_var);
// var = 5; // this would not compile because `var` is borrowed
// *ref_var = 6; // this would not either, because `ref_var` is an immutable reference
+ ref_var; // no-op, but counts as a use and keeps the borrow active
+ var = 2; // ref_var is no longer used after the line above, so the borrow has ended
// Mutable reference
// While a value is mutably borrowed, it cannot be accessed at all.
@@ -309,6 +309,7 @@ fn main() {
println!("{}", *ref_var2); // 6 , // var2 would not compile.
// ref_var2 is of type &mut i32, so stores a reference to an i32, not the value.
// var2 = 2; // this would not compile because `var2` is borrowed.
+ ref_var2; // no-op, but counts as a use and keeps the borrow active until here
}
```
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/scala.html.markdown b/scala.html.markdown
index 28424684..c7a8842e 100644
--- a/scala.html.markdown
+++ b/scala.html.markdown
@@ -345,7 +345,7 @@ s(0) // Boolean = false
s(1) // Boolean = true
/* Look up the documentation of map here -
- * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map
+ * https://www.scala-lang.org/api/current/scala/collection/immutable/Map.html
* and make sure you can read it
*/
diff --git a/smalltalk.html.markdown b/smalltalk.html.markdown
index ae7ecb0e..faf826f3 100644
--- a/smalltalk.html.markdown
+++ b/smalltalk.html.markdown
@@ -30,7 +30,7 @@ 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 +38,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 +96,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 +110,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 +140,7 @@ x := #('abc' 2 $a). "mixing of types allowed"
```
#### Booleans:
-```
+```smalltalk
| b x y |
x := 1. y := 2.
b := (x = y). "equals"
@@ -185,7 +178,7 @@ b := $A isLowercase. "test if lower case character"
```
#### Arithmetic expressions:
-```
+```smalltalk
| x |
x := 6 + 3. "addition"
x := 6 - 3. "subtraction"
@@ -241,7 +234,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 +250,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 +274,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 +297,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 +312,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 +352,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 +364,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 +384,7 @@ y := $A max: $B.
```
#### Symbol:
-```
+```smalltalk
| b x y |
x := #Hello. "symbol assignment"
y := 'String', 'Concatenation'. "symbol concatenation (result is string)"
@@ -413,7 +406,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 +440,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 +483,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 +530,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 +576,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 +612,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 +642,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 +672,7 @@ y := x asSet. "convert to set collection"
```
#### Associations:
-```
+```smalltalk
| x y |
x := #myVar->'hello'.
y := x key.
@@ -690,7 +683,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 +750,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 +778,7 @@ b := ios atEnd.
```
#### FileStream:
-```
+```smalltalk
| b x ios |
ios := FileStream newFileNamed: 'ios.txt'.
ios nextPut: $H; cr.
@@ -805,7 +798,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 +832,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 +852,7 @@ b := (x <= Time now). "comparison"
```
#### Point:
-```
+```smalltalk
| x y |
x := 200@100. "obtain a new point"
y := x x. "x coordinate"
@@ -884,12 +877,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 +910,7 @@ Display height. "get display height"
```
#### Dynamic Message Calling/Compiling:
-```
+```smalltalk
| receiver message result argument keyword1 keyword2 argument1 argument2 |
"unary message"
@@ -957,7 +950,7 @@ result := (Message
```
#### Class/Meta-Class:
-```
+```smalltalk
| b x |
x := String name. "class name"
x := String category. "organization category"
@@ -990,7 +983,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 +1006,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/solidity.html.markdown b/solidity.html.markdown
index d215180d..cc719ec7 100644
--- a/solidity.html.markdown
+++ b/solidity.html.markdown
@@ -483,7 +483,7 @@ for(uint x = 0; x < refundAddressList.length; x++) {
// A. Calling external contract
contract InfoFeed {
- function info() returns (uint ret) { return 42; }
+ function info() payable returns (uint ret) { return 42; }
}
contract Consumer {
diff --git a/sql.html.markdown b/sql.html.markdown
index 2bece208..5edf0f7c 100644
--- a/sql.html.markdown
+++ b/sql.html.markdown
@@ -9,14 +9,14 @@ Structured Query Language (SQL) is an ISO standard language for creating and wor
Implementations typically provide a command line prompt where you can enter the commands shown here interactively, and they also offer a way to execute a series of these commands stored in a script file. (Showing that you’re done with the interactive prompt is a good example of something that isn’t standardized--most SQL implementations support the keywords QUIT, EXIT, or both.)
-Several of these sample commands assume that the [MySQL employee sample database](https://dev.mysql.com/doc/employee/en/) available on [github](https://github.com/datacharmer/test_db) has already been loaded. The github files are scripts of commands, similar to the relevant commands below, that create and populate tables of data about a fictional company’s employees. The syntax for running these scripts will depend on the SQL implementation you are using. A utility that you run from the operating system prompt is typical.
+Several of these sample commands assume that the [MySQL employee sample database](https://dev.mysql.com/doc/employee/en/) available on [github](https://github.com/datacharmer/test_db) has already been loaded. The github files are scripts of commands, similar to the relevant commands below, that create and populate tables of data about a fictional company’s employees. The syntax for running these scripts will depend on the SQL implementation you are using. A utility that you run from the operating system prompt is typical.
```sql
-- Comments start with two hyphens. End each command with a semicolon.
-- SQL is not case-sensitive about keywords. The sample commands here
--- follow the convention of spelling them in upper-case because it makes
+-- follow the convention of spelling them in upper-case because it makes
-- it easier to distinguish them from database, table, and column names.
-- Create and delete a database. Database and table names are case-sensitive.
@@ -26,47 +26,47 @@ DROP DATABASE someDatabase;
-- List available databases.
SHOW DATABASES;
--- Use a particular existing database.
+-- Use a particular existing database.
USE employees;
-- Select all rows and columns from the current database's departments table.
--- Default activity is for the interpreter to scroll the results on your screen.
+-- Default activity is for the interpreter to scroll the results on your screen.
SELECT * FROM departments;
--- Retrieve all rows from the departments table,
--- but only the dept_no and dept_name columns.
+-- Retrieve all rows from the departments table,
+-- but only the dept_no and dept_name columns.
-- Splitting up commands across lines is OK.
SELECT dept_no,
dept_name FROM departments;
--- Retrieve all departments columns, but just 5 rows.
+-- Retrieve all departments columns, but just 5 rows.
SELECT * FROM departments LIMIT 5;
-- Retrieve dept_name column values from the departments
--- table where the dept_name value has the substring 'en'.
+-- table where the dept_name value has the substring 'en'.
SELECT dept_name FROM departments WHERE dept_name LIKE '%en%';
-- Retrieve all columns from the departments table where the dept_name
--- column starts with an 'S' and has exactly 4 characters after it.
+-- column starts with an 'S' and has exactly 4 characters after it.
SELECT * FROM departments WHERE dept_name LIKE 'S____';
-- Select title values from the titles table but don't show duplicates.
SELECT DISTINCT title FROM titles;
--- Same as above, but sorted (case-sensitive) by the title values.
+-- Same as above, but sorted (case-sensitive) by the title values.
SELECT DISTINCT title FROM titles ORDER BY title;
-- Show the number of rows in the departments table.
SELECT COUNT(*) FROM departments;
-- Show the number of rows in the departments table that
--- have 'en' as a substring of the dept_name value.
+-- have 'en' as a substring of the dept_name value.
SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%';
--- A JOIN of information from multiple tables: the titles table shows
--- who had what job titles, by their employee numbers, from what
+-- A JOIN of information from multiple tables: the titles table shows
+-- who had what job titles, by their employee numbers, from what
-- date to what date. Retrieve this information, but instead of the
--- employee number, use the employee number as a cross-reference to
+-- employee number, use the employee number as a cross-reference to
-- the employees table to get each employee's first and last name
-- instead. (And only get 10 rows.)
@@ -85,12 +85,12 @@ WHERE TABLE_TYPE='BASE TABLE';
-- for how you specify the columns, such as their datatypes.
CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20));
--- Insert a row of data into the table tablename1. This assumes that the
--- table has been defined to accept these values as appropriate for it.
+-- Insert a row of data into the table tablename1. This assumes that the
+-- table has been defined to accept these values as appropriate for it.
INSERT INTO tablename1 VALUES('Richard','Mutt');
-- In tablename1, change the fname value to 'John'
--- for all rows that have an lname value of 'Mutt'.
+-- for all rows that have an lname value of 'Mutt'.
UPDATE tablename1 SET fname='John' WHERE lname='Mutt';
-- Delete rows from the tablename1 table
@@ -100,6 +100,11 @@ DELETE FROM tablename1 WHERE lname like 'M%';
-- Delete all rows from the tablename1 table, leaving the empty table.
DELETE FROM tablename1;
--- Remove the entire tablename1 table.
+-- Remove the entire tablename1 table.
DROP TABLE tablename1;
```
+
+## Further Reading
+
+* [Codecademy - SQL](https://www.codecademy.com/learn/learn-sql) A good introduction to SQL in a "learn by doing it" format.
+* [Database System Concepts](https://www.db-book.com) book's Chapter 3 - Introduction to SQL has an in depth explanation of SQL concepts.
diff --git a/standard-ml.html.markdown b/standard-ml.html.markdown
index b34f1c08..0ba42f39 100644
--- a/standard-ml.html.markdown
+++ b/standard-ml.html.markdown
@@ -272,6 +272,9 @@ fun evenly_positioned_elems (odd::even::xs) = even::evenly_positioned_elems xs
datatype temp =
C of real
| F of real
+
+(* Declaring a new C temp value...
+ val t: temp = C 45.0 *)
fun temp_to_f t =
case t of
diff --git a/swift.html.markdown b/swift.html.markdown
index f834f373..689c5191 100644
--- a/swift.html.markdown
+++ b/swift.html.markdown
@@ -8,22 +8,26 @@ contributors:
- ["Clayton Walker", "https://github.com/cwalk"]
- ["Fernando Valverde", "http://visualcosita.xyz"]
- ["Alexey Nazaroff", "https://github.com/rogaven"]
+ - ["@Samasaur1", "https://github.com/Samasaur1"]
filename: learnswift.swift
---
Swift is a programming language for iOS and OS X development created by Apple. Designed to coexist with Objective-C and to be more resilient against erroneous code, Swift was introduced in 2014 at Apple's developer conference WWDC. It is built with the LLVM compiler included in Xcode 6+.
-The official _[Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329)_ book from Apple is now available via iBooks.
+The official _[Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329)_ book from Apple is now available via iBooks. It goes into much more detail than this guide, and if you have the time and patience to read it, it's recommended. Some of these examples are from that book.
Another great reference is _About Swift_ on Swift's [website](https://docs.swift.org/swift-book/).
```swift
// import a module
-import UIKit
+import Foundation
-//
-// MARK: Basics
-//
+// Single-line comments are prefixed with //
+// Multi-line comments start with /* and end with */
+/* Nested multiline comments
+ /* ARE */
+ allowed
+ */
// Xcode supports landmarks to annotate your code and lists them in the jump bar
// MARK: Section mark
@@ -31,220 +35,383 @@ import UIKit
// TODO: Do something soon
// FIXME: Fix this code
-// In Swift 2, println and print were combined into one print method. Print automatically appends a new line.
-print("Hello, world") // println is now print
-print("Hello, world", terminator: "") // printing without appending a newline
+//MARK: Hello, World
+// From Swift 3 on, to print, just use the `print` method.
+// It automatically appends a new line.
+print("Hello, world")
+
+//
+// MARK: - Variables
+//
+
+
+//Use `let` to declare a constant and `var` to declare a variable.
+let theAnswer = 42
+var theQuestion = "What is the Answer?"
+theQuestion = "How many roads must a man walk down?"
+theQuestion = "What is six by nine?"
+// Atttempting to reassign a constant throws a compile-time error
+//theAnswer = 54
+
+// Both variables and constants can be declared before they are given a value,
+// but must be given a value before they are used
+let someConstant: Int
+var someVariable: String
+// These lines will throw errors:
+//print(someConstant)
+//print(someVariable)
+someConstant = 0
+someVariable = "0"
+// These lines are now valid:
+print(someConstant)
+print(someVariable)
+
+// As you can see above, variable types are automatically inferred.
+// To explicitly declare the type, write it after the variable name,
+// separated by a colon.
+let aString: String = "A string"
+let aDouble: Double = 0
+
+// Values are never implicitly converted to another type.
+// Explicitly make instances of the desired type.
+let stringWithDouble = aString + String(aDouble)
+let intFromDouble = Int(aDouble)
+
+// For strings, use string interpolation
+let descriptionString = "The value of aDouble is \(aDouble)"
+// You can put any expression inside string interpolation.
+let equation = "Six by nine is \(6 * 9), not 42!"
+// To avoid escaping double quotes and backslashes, change the string delimiter
+let explanationString = #"The string I used was "The value of aDouble is \(aDouble)" and the result was \#(descriptionString)"#
+// You can put as many number signs as you want before the opening quote,
+// just match them at the ending quote. They also change the escape character
+// to a backslash followed by the same number of number signs.
+
+let multiLineString = """
+ This is a multi-line string.
+ It's called that because it takes up multiple lines (wow!)
+ Any indentation beyond the closing quotation marks is kept, the rest is discarded.
+ You can include " or "" in multi-line strings because the delimiter is three "s.
+ """
+
+// Arrays
+let shoppingList = ["catfish", "water", "tulips",] //commas are allowed after the last element
+let secondElement = shoppingList[1] // Arrays are 0-indexed
+
+// Arrays declared with let are immutable; the following line throws a compile-time error
+//shoppingList[2] = "mango"
+
+// Arrays are structs (more on that later), so this creates a copy instead of referencing the same object
+var mutableShoppingList = shoppingList
+mutableShoppingList[2] = "mango"
+
+// == is equality
+shoppingList == mutableShoppingList // false
+
+// Dictionaries declared with let are also immutable
+var occupations = [
+ "Malcolm": "Captain",
+ "Kaylee": "Mechanic"
+]
+occupations["Jayne"] = "Public Relations"
+// Dictionaries are also structs, so this also creates a copy
+let immutableOccupations = occupations
+
+immutableOccupations == occupations // true
-// variables (var) value can change after being set
-// constants (let) value can NOT be changed after being set
+// Arrays and dictionaries both automatically grow as you add elements
+mutableShoppingList.append("blue paint")
+occupations["Tim"] = "CEO"
-var myVariable = 42
+// They can both be set to empty
+mutableShoppingList = []
+occupations = [:]
+
+let emptyArray = [String]()
+let emptyArray2 = Array<String>() // same as above
+// [T] is shorthand for Array<T>
+let emptyArray3: [String] = [] // Declaring the type explicitly allows you to set it to an empty array
+let emptyArray4: Array<String> = [] // same as above
+
+// [Key: Value] is shorthand for Dictionary<Key, Value>
+let emptyDictionary = [String: Double]()
+let emptyDictionary2 = Dictionary<String, Double>() // same as above
+var emptyMutableDictionary: [String: Double] = [:]
+var explicitEmptyMutableDictionary: Dictionary<String, Double> = [:] // same as above
+
+// MARK: Other variables
let øπΩ = "value" // unicode variable names
-let π = 3.1415926
-let convenience = "keyword" // contextual variable name
-let weak = "keyword"; let override = "another keyword" // statements can be separated by a semi-colon
-let `class` = "keyword" // backticks allow keywords to be used as variable names
-let explicitDouble: Double = 70
-let intValue = 0007 // 7
-let largeIntValue = 77_000 // 77000
-let label = "some text " + String(myVariable) // String construction
-let piText = "Pi = \(π), Pi 2 = \(π * 2)" // String interpolation
-
-// Build Specific values
-// uses -D build configuration
-#if false
- print("Not printed")
- let buildValue = 3
-#else
- let buildValue = 7
-#endif
-print("Build value: \(buildValue)") // Build value: 7
+let 🤯 = "wow" // emoji variable names
+
+// Keywords can be used as variable names
+// These are contextual keywords that wouldn't be used now, so are allowed
+let convenience = "keyword"
+let weak = "another keyword"
+let override = "another keyword"
+
+// Using backticks allows keywords to be used as variable names even if they wouldn't be allowed normally
+let `class` = "keyword"
+
+// MARK: - Optionals
/*
-Optionals are a Swift language feature that either contains a value,
-or contains nil (no value) to indicate that a value is missing.
-A question mark (?) after the type marks the value as optional.
+ Optionals are a Swift language feature that either contains a value,
+ or contains nil (no value) to indicate that a value is missing.
+ Nil is roughly equivalent to `null` in other languages.
+ A question mark (?) after the type marks the value as optional of that type.
+
+ If a type is not optional, it is guaranteed to have a value.
-Because Swift requires every property to have a value, even nil must be
-explicitly stored as an Optional value.
+ Because Swift requires every property to have a type, even nil must be
+ explicitly stored as an Optional value.
+
+ Optional<T> is an enum, with the cases .none (nil) and .some(T) (the value)
+ */
-Optional<T> is an enum.
-*/
var someOptionalString: String? = "optional" // Can be nil
-// same as above, but ? is a postfix operator (syntax candy)
-var someOptionalString2: Optional<String> = "optional"
+// T? is shorthand for Optional<T> — ? is a postfix operator (syntax candy)
+let someOptionalString2: Optional<String> = nil
+let someOptionalString3 = String?.some("optional") // same as the first one
+let someOptionalString4 = String?.none //nil
+
+/*
+ To access the value of an optional that has a value, use the postfix
+ operator !, which force-unwraps it. Force-unwrapping is like saying, "I
+ know that this optional definitely has a value, please give it to me."
+
+ Trying to use ! to access a non-existent optional value triggers a
+ runtime error. Always make sure that an optional contains a non-nil
+ value before using ! to force-unwrap its value.
+ */
if someOptionalString != nil {
// I am not nil
if someOptionalString!.hasPrefix("opt") {
print("has the prefix")
}
-
- let empty = someOptionalString?.isEmpty
}
-someOptionalString = nil
-/*
-Trying to use ! to access a non-existent optional value triggers a runtime
-error. Always make sure that an optional contains a non-nil value before
-using ! to force-unwrap its value.
-*/
-
-// implicitly unwrapped optional
-var unwrappedString: String! = "Value is expected."
-// same as above, but ! is a postfix operator (more syntax candy)
-var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Value is expected."
-
-// If let structure -
-// If let is a special structure in Swift that allows you to check if an Optional rhs holds a value, and in case it does - unwraps and assigns it to the lhs.
-if let someOptionalStringConstant = someOptionalString {
+// Swift supports "optional chaining," which means that you can call functions
+// or get properties of optional values and they are optionals of the appropriate type.
+// You can even do this multiple times, hence the name "chaining."
+
+let empty = someOptionalString?.isEmpty // Bool?
+
+// if-let structure -
+// if-let is a special structure in Swift that allows you to check
+// if an Optional rhs holds a value, and if it does unwrap
+// and assign it to the lhs.
+if let someNonOptionalStringConstant = someOptionalString {
// has `Some` value, non-nil
- if !someOptionalStringConstant.hasPrefix("ok") {
+ // someOptionalStringConstant is of type String, not type String?
+ if !someNonOptionalStringConstant.hasPrefix("ok") {
// does not have the prefix
}
}
-// The nil-coalescing operator ?? unwraps an optional if it contains a non-nil value, or returns a default value.
-var someOptionalString: String?
-let someString = someOptionalString ?? "abc"
-print(someString) // abc
+//if-var is allowed too!
+if var someNonOptionalString = someOptionalString {
+ someNonOptionalString = "Non optional AND mutable"
+ print(someNonOptionalString)
+}
-// Swift has support for storing a value of any type.
-// For that purposes there is two keywords: `Any` and `AnyObject`
-// `AnyObject` == `id` from Objective-C
-// `Any` – also works with any scalar values (Class, Int, struct, etc.)
-var anyVar: Any = 7
-anyVar = "Changed value to a string, not good practice, but possible."
-let anyObjectVar: AnyObject = Int(1) as NSNumber
+// You can bind multiple optional values in one if-let statement.
+// If any of the bound values are nil, the if statement does not execute.
+if let first = someOptionalString, let second = someOptionalString2,
+ let third = someOptionalString3, let fourth = someOptionalString4 {
+ print("\(first), \(second), \(third), and \(fourth) are all not nil")
+}
-/*
- Comment here
+//if-let supports "," (comma) clauses, which can be used to
+// enforce conditions on newly-bound optional values.
+// Both the assignment and the "," clause must pass.
+let someNumber: Int? = 7
+if let num = someNumber, num > 3 {
+ print("num is not nil and is greater than 3")
+}
- /*
- Nested comments are also supported
- */
-*/
+// Implicitly unwrapped optional — An optional value that doesn't need to be unwrapped
+let unwrappedString: String! = "Value is expected."
-//
-// MARK: Collections
-//
+// Here's the difference:
+let forcedString = someOptionalString! // requires an exclamation mark
+let implicitString = unwrappedString // doesn't require an exclamation mark
/*
-Array and Dictionary types are structs. So `let` and `var` also indicate
-that they are mutable (var) or immutable (let) when declaring these types.
-*/
-
-// Array
-var shoppingList = ["catfish", "water", "lemons"]
-shoppingList[1] = "bottle of water"
-let emptyArray = [String]() // let == immutable
-let emptyArray2 = Array<String>() // same as above
-var emptyMutableArray = [String]() // var == mutable
-var explicitEmptyMutableStringArray: [String] = [] // same as above
-
+ You can think of an implicitly unwrapped optional as giving permission
+ for the optional to be unwrapped automatically whenever it's used.
+ Rather than placing an exclamation mark after the optional's name each time you use it,
+ you place an exclamation mark after the optional's type when you declare it.
+ */
-// Dictionary
-var occupations = [
- "Malcolm": "Captain",
- "kaylee": "Mechanic"
-]
-occupations["Jayne"] = "Public Relations"
-let emptyDictionary = [String: Float]() // let == immutable
-let emptyDictionary2 = Dictionary<String, Float>() // same as above
-var emptyMutableDictionary = [String: Float]() // var == mutable
-var explicitEmptyMutableDictionary: [String: Float] = [:] // same as above
+// Otherwise, you can treat an implicitly unwrapped optional the same way the you treat a normal optional
+// (i.e., if-let, != nil, etc.)
+// Pre-Swift 5, T! was shorthand for ImplicitlyUnwrappedOptional<T>
+// Swift 5 and later, using ImplicitlyUnwrappedOptional throws a compile-time error.
+//var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Value is expected." //error
-//
-// MARK: Control Flow
-//
+// The nil-coalescing operator ?? unwraps an optional if it contains a non-nil value, or returns a default value.
+someOptionalString = nil
+let someString = someOptionalString ?? "abc"
+print(someString) // abc
+// a ?? b is shorthand for a != nil ? a! : b
-// Condition statements support "," (comma) clauses, which can be used
-// to help provide conditions on optional values.
-// Both the assignment and the "," clause must pass.
-let someNumber = Optional<Int>(7)
-if let num = someNumber, num > 3 {
- print("num is greater than 3")
-}
+// MARK: - Control Flow
-// for loop (array)
-let myArray = [1, 1, 2, 3, 5]
-for value in myArray {
- if value == 1 {
- print("One!")
- } else {
- print("Not one!")
- }
-}
+let condition = true
+if condition { print("condition is true") } // can't omit the braces
-// for loop (dictionary)
-var dict = ["one": 1, "two": 2]
-for (key, value) in dict {
- print("\(key): \(value)")
+if theAnswer > 50 {
+ print("theAnswer > 50")
+} else if condition {
+ print("condition is true")
+} else {
+ print("Neither are true")
}
-// for loop (range)
-for i in -1...shoppingList.count {
- print(i)
-}
-shoppingList[1...2] = ["steak", "peacons"]
-// use ..< to exclude the last number
-
-// while loop
-var i = 1
-while i < 1000 {
- i *= 2
-}
-
-// repeat-while loop
-repeat {
- print("hello")
-} while 1 == 2
+// The condition in an `if` statement must be a `Bool`, so the following code is an error, not an implicit comparison to zero
+//if 5 {
+// print("5 is not zero")
+//}
// Switch
+// Must be exhaustive
+// Does not implicitly fall through, use the fallthrough keyword
// Very powerful, think `if` statements with syntax candy
// They support String, object instances, and primitives (Int, Double, etc)
let vegetable = "red pepper"
+let vegetableComment: String
switch vegetable {
case "celery":
- let vegetableComment = "Add some raisins and make ants on a log."
-case "cucumber", "watercress":
- let vegetableComment = "That would make a good tea sandwich."
+ vegetableComment = "Add some raisins and make ants on a log."
+case "cucumber", "watercress": // match multiple values
+ vegetableComment = "That would make a good tea sandwich."
case let localScopeValue where localScopeValue.hasSuffix("pepper"):
- let vegetableComment = "Is it a spicy \(localScopeValue)?"
+ vegetableComment = "Is it a spicy \(localScopeValue)?"
default: // required (in order to cover all possible input)
- let vegetableComment = "Everything tastes good in soup."
+ vegetableComment = "Everything tastes good in soup."
+}
+print(vegetableComment)
+
+// You use the `for-in` loop to iterate over a sequence, such as an array, dictionary, range, etc.
+for element in shoppingList {
+ print(element) // shoppingList is of type `[String]`, so element is of type `String`
+}
+//Iterating through a dictionary does not guarantee any specific order
+for (person, job) in immutableOccupations {
+ print("\(person)'s job is \(job)")
+}
+for i in 1...5 {
+ print(i, terminator: " ") // Prints "1 2 3 4 5"
+}
+for i in 0..<5 {
+ print(i, terminator: " ") // Prints "0 1 2 3 4"
+}
+//for index in range can replace a C-style for loop:
+// for (int i = 0; i < 10; i++) {
+// //code
+// }
+//becomes:
+// for i in 0..<10 {
+// //code
+// }
+//To step by more than one, use the stride(from:to:by:) or stride(from:through:by) functions
+//`for i in stride(from: 0, to: 10, by: 2)` is the same as `for (int i = 0; i < 10; i += 2)`
+//`for i in stride(from: 0, through: 10, by: 2)` is the same as `for (int i = 0; i <= 10; i += 2)
+
+// while loops are just like most languages
+var i = 0
+while i < 5 {
+ i += Bool.random() ? 1 : 0
+ print(i)
}
-//
-// MARK: Functions
-//
+// This is like a do-while loop in other languages — the body of the loop executes a minimum of once
+repeat {
+ i -= 1
+ i += Int.random(in: 0...3)
+} while i < 5
-// Functions are a first-class type, meaning they can be nested
-// in functions and can be passed around
+// The continue statement continues executing a loop at the next iteration
+// The break statement ends a swift or loop immediately
-// Function with Swift header docs (format as Swift-modified Markdown syntax)
+// MARK: - Functions
-/**
-A greet operation
+// Functions are a first-class type, meaning they can be nested in functions and can be passed around.
-- A bullet in docs
-- Another bullet in the docs
+// Function with Swift header docs (format as Swift-modified Markdown syntax)
-- Parameter name : A name
-- Parameter day : A day
-- Returns : A string containing the name and day value.
-*/
+/// A greet operation.
+///
+/// - Parameters:
+/// - name: A name.
+/// - day: A day.
+/// - Returns: A string containing the name and day value.
func greet(name: String, day: String) -> String {
return "Hello \(name), today is \(day)."
}
greet(name: "Bob", day: "Tuesday")
-// similar to above except for the function parameter behaviors
-func greet2(name: String, externalParamName localParamName: String) -> String {
- return "Hello \(name), the day is \(localParamName)"
+// Ideally, function names and parameter labels combine to make function calls similar to sentences.
+func sayHello(to name: String, onDay day: String) -> String {
+ return "Hello \(name), the day is \(day)"
+}
+sayHello(to: "John", onDay: "Sunday")
+
+//Functions that don't return anything can omit the return arrow; they don't need to say that they return Void (although they can).
+func helloWorld() {
+ print("Hello, World!")
+}
+
+// Argument labels can be blank
+func say(_ message: String) {
+ print(#"I say "\#(message)""#)
+}
+say("Hello")
+
+// Default parameters can be omitted when calling the function.
+func printParameters(requiredParameter r: Int, optionalParameter o: Int = 10) {
+ print("The required parameter was \(r) and the optional parameter was \(o)")
+}
+printParameters(requiredParameter: 3)
+printParameters(requiredParameter: 3, optionalParameter: 6)
+
+// Variadic args — only one set per function.
+func setup(numbers: Int...) {
+ // it's an array
+ let _ = numbers[0]
+ let _ = numbers.count
+}
+
+// pass by ref
+func swapTwoInts(a: inout Int, b: inout Int) {
+ let tempA = a
+ a = b
+ b = tempA
+}
+var someIntA = 7
+var someIntB = 3
+swapTwoInts(a: &someIntA, b: &someIntB) //must be called with an & before the variable name.
+print(someIntB) // 7
+
+type(of: greet) // (String, String) -> String
+type(of: helloWorld) // () -> Void
+
+// Passing and returning functions
+func makeIncrementer() -> ((Int) -> Int) {
+ func addOne(number: Int) -> Int {
+ return 1 + number
+ }
+ return addOne
+}
+var increment = makeIncrementer()
+increment(7)
+
+func performFunction(_ function: (String, String) -> String, on string1: String, and string2: String) {
+ let result = function(string1, string2)
+ print("The result of calling the function on \(string1) and \(string2) was \(result)")
}
-greet2(name: "John", externalParamName: "Sunday")
// Function that returns multiple items in a tuple
func getGasPrices() -> (Double, Double, Double) {
@@ -271,46 +438,24 @@ print("Highest gas price: \(pricesTuple2.highestPrice)")
func testGuard() {
// guards provide early exits or breaks, placing the error handler code near the conditions.
// it places variables it declares in the same scope as the guard statement.
+ // They make it easier to avoid the "pyramid of doom"
guard let aNumber = Optional<Int>(7) else {
- return
+ return // guard statements MUST exit the scope that they are in.
+ // They generally use `return` or `throw`.
}
print("number is \(aNumber)")
}
testGuard()
-// Variadic Args
-func setup(numbers: Int...) {
- // it's an array
- let _ = numbers[0]
- let _ = numbers.count
-}
-
-// Passing and returning functions
-func makeIncrementer() -> ((Int) -> Int) {
- func addOne(number: Int) -> Int {
- return 1 + number
- }
- return addOne
-}
-var increment = makeIncrementer()
-increment(7)
-
-// pass by ref
-func swapTwoInts(a: inout Int, b: inout Int) {
- let tempA = a
- a = b
- b = tempA
-}
-var someIntA = 7
-var someIntB = 3
-swapTwoInts(a: &someIntA, b: &someIntB)
-print(someIntB) // 7
+// Note that the print function is declared like so:
+// func print(_ input: Any..., separator: String = " ", terminator: String = "\n")
+// To print without a newline:
+print("No newline", terminator: "")
+print("!")
+// MARK: - Closures
-//
-// MARK: Closures
-//
var numbers = [1, 2, 6]
// Functions are special case closures ({})
@@ -336,85 +481,157 @@ numbers = numbers.sorted { $0 > $1 }
print(numbers) // [18, 6, 3]
-//
-// MARK: Structures
-//
+// MARK: - Enums
-// Structures and classes have very similar capabilities
-struct NamesTable {
- let names: [String]
+// Enums can optionally be of a specific type or on their own.
+// They can contain methods like classes.
- // Custom subscript
- subscript(index: Int) -> String {
- return names[index]
+enum Suit {
+ case spades, hearts, diamonds, clubs
+ var icon: Character {
+ switch self {
+ case .spades:
+ return "♤"
+ case .hearts:
+ return "♡"
+ case .diamonds:
+ return "♢"
+ case .clubs:
+ return "♧"
+ }
}
}
-// Structures have an auto-generated (implicit) designated initializer
-let namesTable = NamesTable(names: ["Me", "Them"])
-let name = namesTable[1]
-print("Name is \(name)") // Name is Them
-
-//
-// MARK: Error Handling
-//
+// Enum values allow short hand syntax, no need to type the enum type
+// when the variable is explicitly declared
+var suitValue: Suit = .hearts
-// The `Error` protocol is used when throwing errors to catch
-enum MyError: Error {
- case badValue(msg: String)
- case reallyBadValue(msg: String)
+// Conforming to the CaseIterable protocol automatically synthesizes the allCases property,
+// which contains all the values. It works on enums without associated values or @available attributes.
+enum Rank: CaseIterable {
+ case ace
+ case two, three, four, five, six, seven, eight, nine, ten
+ case jack, queen, king
+ var icon: String {
+ switch self {
+ case .ace:
+ return "A"
+ case .two:
+ return "2"
+ case .three:
+ return "3"
+ case .four:
+ return "4"
+ case .five:
+ return "5"
+ case .six:
+ return "6"
+ case .seven:
+ return "7"
+ case .eight:
+ return "8"
+ case .nine:
+ return "9"
+ case .ten:
+ return "10"
+ case .jack:
+ return "J"
+ case .queen:
+ return "Q"
+ case .king:
+ return "K"
+ }
+ }
}
-// functions marked with `throws` must be called using `try`
-func fakeFetch(value: Int) throws -> String {
- guard 7 == value else {
- throw MyError.reallyBadValue(msg: "Some really bad value")
+for suit in [Suit.clubs, .diamonds, .hearts, .spades] {
+ for rank in Rank.allCases {
+ print("\(rank.icon)\(suit.icon)")
}
+}
- return "test"
+// String enums can have direct raw value assignments
+// or their raw values will be derived from the Enum field
+enum BookName: String {
+ case john
+ case luke = "Luke"
}
+print("Name: \(BookName.john.rawValue)")
-func testTryStuff() {
- // assumes there will be no error thrown, otherwise a runtime exception is raised
- let _ = try! fakeFetch(value: 7)
+// Enum with associated Values
+enum Furniture {
+ // Associate with Int
+ case desk(height: Int)
+ // Associate with String and Int
+ case chair(String, Int)
- // if an error is thrown, then it proceeds, but if the value is nil
- // it also wraps every return value in an optional, even if its already optional
- let _ = try? fakeFetch(value: 7)
+ func description() -> String {
+ //either placement of let is acceptable
+ switch self {
+ case .desk(let height):
+ return "Desk with \(height) cm"
+ case let .chair(brand, height):
+ return "Chair of \(brand) with \(height) cm"
+ }
+ }
+}
- do {
- // normal try operation that provides error handling via `catch` block
- try fakeFetch(value: 1)
- } catch MyError.badValue(let msg) {
- print("Error message: \(msg)")
- } catch {
- // must be exhaustive
+var desk: Furniture = .desk(height: 80)
+print(desk.description()) // "Desk with 80 cm"
+var chair = Furniture.chair("Foo", 40)
+print(chair.description()) // "Chair of Foo with 40 cm"
+
+// MARK: - Structures & Classes
+
+/*
+ Structures and classes in Swift have many things in common. Both can:
+ - Define properties to store values
+ - Define methods to provide functionality
+ - Define subscripts to provide access to their values using subscript syntax
+ - Define initializers to set up their initial state
+ - Be extended to expand their functionality beyond a default implementation
+ - Conform to protocols to provide standard functionality of a certain kind
+
+ Classes have additional capabilities that structures don't have:
+ - Inheritance enables one class to inherit the characteristics of another.
+ - Type casting enables you to check and interpret the type of a class instance at runtime.
+ - Deinitializers enable an instance of a class to free up any resources it has assigned.
+ - Reference counting allows more than one reference to a class instance.
+
+ Unless you need to use a class for one of these reasons, use a struct.
+
+ Structures are value types, while classes are reference types.
+ */
+
+// MARK: Structures
+
+struct NamesTable {
+ let names: [String]
+
+ // Custom subscript
+ subscript(index: Int) -> String {
+ return names[index]
}
}
-testTryStuff()
-//
-// MARK: Classes
-//
+// Structures have an auto-generated (implicit) designated "memberwise" initializer
+let namesTable = NamesTable(names: ["Me", "Them"])
+let name = namesTable[1]
+print("Name is \(name)") // Name is Them
-// Classes, structures and its members have three levels of access control
-// They are: internal (default), public, private
+// MARK: Classes
-public class Shape {
- public func getArea() -> Int {
+class Shape {
+ func getArea() -> Int {
return 0
}
}
-// All methods and properties of a class are public.
-// If you just need to store data in a
-// structured object, you should use a `struct`
-
-internal class Rect: Shape {
+class Rect: Shape {
var sideLength: Int = 1
// Custom getter and setter property
- private var perimeter: Int {
+ var perimeter: Int {
get {
return 4 * sideLength
}
@@ -475,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")
@@ -509,104 +731,143 @@ if let circle = myEmptyCircle {
print("circle is not nil")
}
+// MARK: - Protocols
-//
-// MARK: Enums
-//
+// protocols are also known as interfaces in some other languages
-// Enums can optionally be of a specific type or on their own.
-// They can contain methods like classes.
+// `protocol`s can require that conforming types have specific
+// instance properties, instance methods, type methods,
+// operators, and subscripts.
-enum Suit {
- case spades, hearts, diamonds, clubs
- func getIcon() -> String {
- switch self {
- case .spades: return "♤"
- case .hearts: return "♡"
- case .diamonds: return "♢"
- case .clubs: return "♧"
- }
- }
+protocol ShapeGenerator {
+ var enabled: Bool { get set }
+ func buildShape() -> Shape
}
-// Enum values allow short hand syntax, no need to type the enum type
-// when the variable is explicitly declared
-var suitValue: Suit = .hearts
+// MARK: - Other
-// String enums can have direct raw value assignments
-// or their raw values will be derived from the Enum field
-enum BookName: String {
- case john
- case luke = "Luke"
-}
-print("Name: \(BookName.john.rawValue)")
+// MARK: Typealiases
-// Enum with associated Values
-enum Furniture {
- // Associate with Int
- case desk(height: Int)
- // Associate with String and Int
- case chair(String, Int)
+// Typealiases allow one type (or composition of types) to be referred to by another name
+typealias Integer = Int
+let myInteger: Integer = 0
- func description() -> String {
- switch self {
- case .desk(let height):
- return "Desk with \(height) cm"
- case .chair(let brand, let height):
- return "Chair of \(brand) with \(height) cm"
- }
- }
-}
+// MARK: = Operator
-var desk: Furniture = .desk(height: 80)
-print(desk.description()) // "Desk with 80 cm"
-var chair = Furniture.chair("Foo", 40)
-print(chair.description()) // "Chair of Foo with 40 cm"
+// Assignment does not return a value. This means it can't be used in conditional statements,
+// and the following statement is also illegal
+// let multipleAssignment = theQuestion = "No questions asked"
+//But you can do this:
+let multipleAssignment = "No questions asked", secondConstant = "No answers given"
+// MARK: Ranges
-//
-// MARK: Protocols
-//
+// The ..< and ... operators create ranges.
-// `protocol`s can require that conforming types have specific
-// instance properties, instance methods, type methods,
-// operators, and subscripts.
+// ... is inclusive on both ends (a "closed range") — mathematically, [0, 10]
+let _0to10 = 0...10
+// ..< is inclusive on the left, exclusive on the right (a "range") — mathematically, [0, 10)
+let singleDigitNumbers = 0..<10
+// You can omit one end (a "PartialRangeFrom") — mathematically, [0, ∞)
+let toInfinityAndBeyond = 0...
+// Or the other end (a "PartialRangeTo") — mathematically, (-∞, 0)
+let negativeInfinityToZero = ..<0
+// (a "PartialRangeThrough") — mathematically, (-∞, 0]
+let negativeInfinityThroughZero = ...0
-protocol ShapeGenerator {
- var enabled: Bool { get set }
- func buildShape() -> Shape
+// MARK: Wildcard operator
+
+// In Swift, _ (underscore) is the wildcard operator, which allows values to be ignored
+
+// It allows functions to be declared without argument labels:
+func function(_ labelLessParameter: Int, label labeledParameter: Int, labelAndParameterName: Int) {
+ print(labelLessParameter, labeledParameter, labelAndParameterName)
}
+function(0, label: 0, labelAndParameterName: 0)
-// Protocols declared with @objc allow optional functions,
-// which allow you to check for conformance. These functions must be
-// marked with @objc also.
-@objc protocol TransformShape {
- @objc optional func reshape()
- @objc optional func canReshape() -> Bool
+// You can ignore the return values of functions
+func printAndReturn(_ str: String) -> String {
+ print(str)
+ return str
}
+let _ = printAndReturn("Some String")
-class MyShape: Rect {
- var delegate: TransformShape?
+// You can ignore part of a tuple and keep part of it
+func returnsTuple() -> (Int, Int) {
+ return (1, 2)
+}
+let (_, two) = returnsTuple()
- func grow() {
- sideLength += 2
+// You can ignore closure parameters
+let closure: (Int, Int) -> String = { someInt, _ in
+ return "\(someInt)"
+}
+closure(1, 2) // returns 1
- // Place a question mark after an optional property, method, or
- // subscript to gracefully ignore a nil value and return nil
- // instead of throwing a runtime error ("optional chaining").
- if let reshape = self.delegate?.canReshape?(), reshape {
- // test for delegate then for method
- self.delegate?.reshape?()
- }
- }
+// You can ignore the value in a for loop
+for _ in 0..<10 {
+ // Code to execute 10 times
}
+// MARK: Access Control
-//
-// MARK: Other
-//
+/*
+ Swift has five levels of access control:
+ - Open: Accessible *and subclassible* in any module that imports it.
+ - Public: Accessible in any module that imports it, subclassible in the module it is declared in.
+ - Internal: Accessible and subclassible in the module it is declared in.
+ - Fileprivate: Accessible and subclassible in the file it is declared in.
+ - Private: Accessible and subclassible in the enclosing declaration (think inner classes/structs/enums)
+
+ See more here: https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html
+ */
+
+// MARK: Conditional Compilation, Compile-Time Diagnostics, & Availability Conditions
+
+// Conditional Compilation
+#if false
+print("This code will not be compiled")
+#else
+print("This code will be compiled")
+#endif
+/*
+ Options are:
+ os() macOS, iOS, watchOS, tvOS, Linux
+ arch() i386, x86_64, arm, arm64
+ swift() >= or < followed by a version number
+ compiler() >= or < followed by a version number
+ canImport() A module name
+ targetEnvironment() simulator
+ */
+#if swift(<3)
+println()
+#endif
+
+// Compile-Time Diagnostics
+// You can use #warning(message) and #error(message) to have the compiler emit warnings and/or errors
+#warning("This will be a compile-time warning")
+// #error("This would be a compile-time error")
+
+//Availability Conditions
+if #available(iOSMac 10.15, *) {
+ // macOS 10.15 is available, you can use it here
+} else {
+ // macOS 10.15 is not available, use alternate APIs
+}
+
+// MARK: Any and AnyObject
+
+// Swift has support for storing a value of any type.
+// For that purpose there are two keywords: `Any` and `AnyObject`
+// `AnyObject` == `id` from Objective-C
+// `Any` works with any values (class, Int, struct, etc.)
+var anyVar: Any = 7
+anyVar = "Changed value to a string, not good practice, but possible."
+let anyObjectVar: AnyObject = Int(1) as NSNumber
-// `extension`s: Add extra functionality to an already existing type
+// MARK: Extensions
+
+// Extensions allow you to add extra functionality to an already-declared type, even one that you don't have the source code for.
// Square now "conforms" to the `CustomStringConvertible` protocol
extension Square: CustomStringConvertible {
@@ -619,17 +880,23 @@ print("Square: \(mySquare)")
// You can also extend built-in types
extension Int {
- var customProperty: String {
- return "This is \(self)"
+ var doubled: Int {
+ return self * 2
}
- func multiplyBy(num: Int) -> Int {
+ func multipliedBy(num: Int) -> Int {
return num * self
}
+
+ mutating func multiplyBy(num: Int) {
+ self *= num
+ }
}
-print(7.customProperty) // "This is 7"
-print(14.multiplyBy(num: 3)) // 42
+print(7.doubled) // 14
+print(7.doubled.multipliedBy(num: 3)) // 42
+
+// MARK: Generics
// Generics: Similar to Java and C#. Use the `where` keyword to specify the
// requirements of the generics.
@@ -642,10 +909,21 @@ func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
}
return nil
}
-let foundAtIndex = findIndex(array: [1, 2, 3, 4], valueToFind: 3)
-print(foundAtIndex == 2) // true
+findIndex(array: [1, 2, 3, 4], valueToFind: 3) // Optional(2)
+
+// You can extend types with generics as well
+extension Array where Array.Element == Int {
+ var sum: Int {
+ var total = 0
+ for el in self {
+ total += el
+ }
+ return total
+ }
+}
+
+// MARK: Operators
-// Operators:
// Custom operators can start with the characters:
// / = - + * % < > ! & | ^ . ~
// or
@@ -678,4 +956,40 @@ var bar: Float = 20
foo <-> bar
print("foo is \(foo), bar is \(bar)") // "foo is 20.0, bar is 10.0"
+
+// MARK: - Error Handling
+
+// The `Error` protocol is used when throwing errors to catch
+enum MyError: Error {
+ case badValue(msg: String)
+ case reallyBadValue(msg: String)
+}
+
+// functions marked with `throws` must be called using `try`
+func fakeFetch(value: Int) throws -> String {
+ guard 7 == value else {
+ throw MyError.reallyBadValue(msg: "Some really bad value")
+ }
+
+ return "test"
+}
+
+func testTryStuff() {
+ // assumes there will be no error thrown, otherwise a runtime exception is raised
+ let _ = try! fakeFetch(value: 7)
+
+ // if an error is thrown, then it proceeds, but if the value is nil
+ // it also wraps every return value in an optional, even if its already optional
+ let _ = try? fakeFetch(value: 7)
+
+ do {
+ // normal try operation that provides error handling via `catch` block
+ try fakeFetch(value: 1)
+ } catch MyError.badValue(let msg) {
+ print("Error message: \(msg)")
+ } catch {
+ // must be exhaustive
+ }
+}
+testTryStuff()
```
diff --git a/ta_in/css-ta.html.markdown b/ta_in/css-ta.html.markdown
index cbe88f1e..4ea7f959 100644
--- a/ta_in/css-ta.html.markdown
+++ b/ta_in/css-ta.html.markdown
@@ -233,6 +233,48 @@ css முன்னுரிமை பின்வருமாறு
* `B` இது அடுத்தது.
* `D` இதுவே கடைசி .
+## Media Queries [மீடியா குரிஸ்]
+
+CSS மீடியா குரிஸ் CSS 3 அம்சங்கள். பயன்படுத்தும் கணினி, கைபேசி அல்லது சாதனத்தின் பிஸேல் டென்சிட்டிக்கு ஏற்றவாறு மீடியா குரிஸ் விதிகளை பயன்படுத்தலாம்.
+
+```css
+/* அனைத்து டேவிஸ்களுக்கும் பொதுவான விதி */
+h1 {
+ font-size: 2em;
+ color: white;
+ background-color: black;
+}
+
+/* பிரிண்ட் செய்யும்போது h1 கலர் மாற்ற */
+@media print {
+ h1 {
+ color: black;
+ background-color: white;
+ }
+}
+
+/* 480 பிஸேல்ளுக்கு மேல் சிகிரீன் அளவு உள்ள சாதனத்தில் எழுத்து அளவு மிகை படுத்த */
+@media screen and (min-width: 480px) {
+ h1 {
+ font-size: 3em;
+ font-weight: normal;
+ }
+}
+```
+
+மீடியா குரிஸ் வழங்கும் அம்சங்கள் :
+`width`, `height`, `device-width`, `device-height`, `orientation`, `aspect-ratio`, `device-aspect-ratio`, `color`, `color-index`, `monochrome`, `resolution`, `scan`, `grid`. இவையுள் பெரும்பான்மை `min-` அல்லது `max-` வுடன் பயன்படுத்தலாம் .
+
+`resolution` பழைய சாதனங்களில் பயன்படாது, எனவே `device-pixel-ratio` பயன்படுத்தவும்.
+
+பல கைபேசி மற்றும் கணினிகள், வீடு கணினி திரை அளவு காட்ட முற்படும். எனவே `viewport` மெட்டா டேக் பயன்படுத்தவும்.
+
+```html
+<head>
+ <meta name="viewport" content="width=device-width; initial-scale=1.0">
+</head>
+```
+
## css அம்சங்களின் பொருந்தகூடிய தன்மை
பெரும்பாலான css 2 வின் அம்சங்கள் எல்லா உலாவிகளிலும் , கருவிகளிலும் உள்ளன. ஆனால் முன்கூட்டியே அந்த அம்சங்களை பரிசோதிப்பது நல்லது.
diff --git a/ta_in/xml-ta.html.markdown b/ta_in/xml-ta.html.markdown
index d782399d..13aa9255 100644
--- a/ta_in/xml-ta.html.markdown
+++ b/ta_in/xml-ta.html.markdown
@@ -5,6 +5,7 @@ contributors:
- ["João Farias", "https://github.com/JoaoGFarias"]
translators:
- ["Rasendran Kirushan", "https://github.com/kirushanr"]
+ - ["Sridhar Easwaran", "https://github.com/sridhareaswaran"]
lang: in-ta
---
@@ -14,6 +15,57 @@ XML ஆனது ஒரு கட்டமைப்பு மொழி ஆகு
HTML போல் அன்றி , XML ஆனது தகவலை மட்டும் கொண்டு செல்ல்கிறது
+
+## சில வரையறை மற்றும் முன்னுரை
+
+பல கூறுகளால் அமைக்கப்பட்டது. ஒவொரு கூறுகளிலும் அட்ட்ரிபூட்க்கள் இருக்கும், அவை அந்தந்த கூறுகளை வரையறுக்க பயன்படும். மேலும் அந்த கூறுகளை தகவல் அல்லது கிளை கூறுகள் இருக்கலாம். அணைத்து கோப்புகளிலும் ரூட்/ஆரம்ப கூறு இருக்கும், அது தனக்குள் கிளை கூறுகளை கொண்டுருக்கும்.
+
+XML பாகுபடுத்தி மிகவும் கண்டிப்பான வீதிகளைக்கொண்டது. [XML தொடரியல் விதிகளை அறிய] (http://www.w3schools.com/xml/xml_syntax.asp).
+
+
+```xml
+<!-- இது ஒரு XML குறிப்ப -->
+<!-- குறிப்புக்கள்
+பலவரி இருக்கலாம் -->
+
+<!-- கூறுகள்/Elements -->
+<!-- Element எனப்படுவது அடிப்படை கூறு. அவை இருவகைப்பாடு. காலியான கூறு: -->
+<element1 attribute="value" /> <!-- காலியான கூறு - உள்ளடக்கம் இல்லாதது -->
+<!-- மற்றும் காலி-இல்லாத கூறு : -->
+<element2 attribute="value">Content</element2>
+<!-- கூற்றின் பெயர் எழுத்துக்கள் மற்றும் எண் கொண்டு மட்டுமே இருக்கவேண்டும்.. -->
+
+<empty /> <!-- காலியான கூறு - உள்ளடக்கம் இல்லாதது -->
+
+<notempty> <!-- காலி-இல்லாத கூற - துவக்கம் -->
+ <!-- உள்ளடக்கம் -->
+</notempty> <!-- முடிவு -->
+
+<!-- கூற்றின் பெயர்கள் எழுத்து வடிவுணர்வு கொண்டது-->
+<element />
+<!-- ஓட்றது அல்ல -->
+<eLEMENT />
+
+<!-- Attributes/பண்புகளை -->
+<!-- Attribute ஒரு மதிப்பு இணை -->
+<element attribute="value" another="anotherValue" many="space-separated list" />
+<!-- ஒரு கூற்றில் Attribute ஒருமுறைதான் தோன்றும். அது ஒரேயொரு பணப்பை கொண்டிருக்கும் -->
+
+<!-- கீழை கூறுகள் -->
+<!-- ஒரு கூரானது பல கீழை கூறுகளை கொண்டிருக்கலாம் : -->
+<parent>
+ <child>Text</child>
+ <emptysibling />
+</parent>
+
+<!-- XML இடைவெளி கான்கெடுக்கப்படும். -->
+<child>
+ Text
+</child>
+<!-- ஓட்றது அல்ல -->
+<child>Text</child>
+```
+
* XML வாக்கிய அமைப்பு
diff --git a/th-th/pascal.th.html.markdown b/th-th/pascal.th.html.markdown
new file mode 100644
index 00000000..bf1da958
--- /dev/null
+++ b/th-th/pascal.th.html.markdown
@@ -0,0 +1,236 @@
+---
+language: Pascal
+filename: learnpascal.pas
+contributors:
+ - ["Ganesha Danu", "http://github.com/blinfoldking"]
+ - ["Keith Miyake", "https://github.com/kaymmm"]
+translators:
+ - ["Worajedt Sitthidumrong", "https://bitbucket.org/wrj"]
+lang: th-th
+---
+
+> Pascal (ปาสกาล) เป็นภาษาโปรแกรมมิ่งทั้งแบบ imperative และ procedural ที่ออกแบบโดย Niklaus Wirth (นิเคล้า เวิร์ท) เมื่อปี 1968-69 และเผยแพร่ตอน 1970 โดยเน้นให้เป็นภาษาที่เล็ก มีประสิทธิภาพ เพื่อเสริมการเขียนโปรแกรมที่มีแนวปฏิบัติที่ดีด้วยการใช้โครงสร้างของตัวภาษา และโครงสร้างข้อมูลมากำกับ ชื่อของภาษานี้ตั้งเป็นเกียรติให้กับนักคณิตศาสตร์ชาวฝรั่งเศส, นักปรัชญา และนักฟิสิกส์ ชื่อ Blaise Pascal (เบลส ปาสกาล) ข้อมูลจาก : [วิกิพีเดีย][1]
+
+การคอมไพล์และรันโค้ดภาษาปาสกาลนี้ สามารถใช้ปาสกาลคอมไพลเลอร์ฟรีชื่อ Free Pascal ได้ โดย [ดาวน์โหลดที่นี่][2]
+
+ด้านล่างจะเป็นโครงสร้างภาษาหลัก ๆ ที่ต้องเข้าใจก่อน ปาสกาลจะเป็นภาษาที่เข้มงวดกับโครงสร้างโค้ดมาก
+
+```pascal
+//โปรแกรมปาสกาล
+//คอมเม้นต์เขียนแบบนี้ ใช้สแลชสองครั้ง
+{
+ แต่ถ้าต้องการคอมเม้นหลาย ๆ บรรทัด
+ ให้ใช้ วงเล็บปีกกา (curly brackets)
+ เนื้อหาอยู่บรรทัดเดียวกันกับปีกกาได้
+}
+
+//อย่างแรก ต้องประกาศ ชื่อโปรแกรม
+program learn_pascal; //<-- ห้ามลืม semicolon
+
+const
+ {
+ ประกาศค่าคงที่ (constant) ในบล็อคนี้
+ }
+type
+ {
+ ประกาศชนิดข้อมูลของเราเองที่นี่ ไม่ว่าจะเป็น ชนิดข้อมูลทั่วไป
+ หรือจะเป็นคลาส
+ }
+var
+ {
+ ตัวแปร ในภาษาปาสกาล ไม่เหมือนกับภาษาอื่น ๆ
+ เพราะต้องประกาศในบล็อค var ก่อนใช้งานเสมอ
+ }
+
+//มาถึงส่วนโปรแกรมหลัก หรือ main fucntion นั่นเอง
+begin
+ {
+ โค้ดเราทำงานอะไร อย่างไร ก็เริ่มรันจากตรงนี้
+ }
+end. // จบการทำงานของ _โปรแกรม_ เราจะจบด้วย จุลภาค "."
+```
+
+โค้ดต่อจากนี้ จะเป็นการอธิบายประกาศตัวแปรของปาสกาล
+
+```pascal
+//การประกาศตัวแปร ทำได้แบบนี้
+//var ชื่อตัวแปร : ชนิด ;
+var a:integer;
+var b:integer;
+
+//หรือแบบที่นิยมมากกว่า คือเอามาเก็บในบล็อค var ทั้งหมด
+var
+ a : integer;
+ b : integer;
+
+//ถ้าจะเอาแบบสั้น ๆ บรรทัดเดียว ก็ทำได้ ทำได้พร้อมกันหลาย ๆ ตัวแปรด้วย
+var a,b : integer;
+```
+
+โค้ดตัวอย่างนี้เป็นโปรแกรม Learn\_More ที่เป็นโครงสร้างโปรแกรมง่าย ๆ ที่จบสมบูรณ์หนึ่งโปรแกรม มีบล็อค program, const, type, main (Begin..End.)
+
+```pascal
+program Learn_More;
+// มาต่อเรื่อง ชนิดของข้อมูล (data types) และ ตัวดำเนินการ (operators)
+
+const
+ PI = 3.141592654;
+ GNU = 'GNU''s Not Unix';
+ // ค่าคงที่ ให้ตั้งชื่อเป็น ตัวพิมพ์ใหญ่ ทั้งหมด ใช้กับชนิดข้อมูลใดๆ ก็ได้
+ // ค่าคงที่ ก็ตามชื่อเลย กำหนดค่าแล้ว ไม่สามารถเปลี่ยนแปลงได้ขณะรัน
+
+// การประกาศชนิดข้อมูลของเราเอง
+// "ชนิด" ของตัวแปรสองแบบนี้ จะนำไปใช้ด้านล่าง
+type
+ ch_array : array [0..255] of char;
+ // อะเรย์ เป็นชนิดข้อมูลที่มี ความยาว/ช่องเก็บข้อมูล และ ชนิดข้อมูล
+ // โค้ดด้านบน เป็นการประกาศอะเรย์ของตัวอักษา 255 ตัวอักษา
+ // ซึ่งได้ ความยาว/ช่องเก็บข้อมูลในตัวแปรตัวนี้ 256 ช่องที่เป็นข้อความ
+ md_array : array of array of integer;
+ // ด้านบนนี้ เป็นตัวอย่าง อะเรย์สองมิติของเลขจำนวนเต็ม
+ // อะเรย์ ยังซ้อนกับอะเรย์ได้อีกด้วย ทำให้สร้าง อะเรย์หลายมิติได้
+ // เรายังสามารถสร้าง อะเรย์ที่มีความยาวช่องเท่ากับศูนย์ (0) ได้อีกด้วย
+ // ซึ่งทำให้เกิด อะเรย์ที่จำนวนช่องยืดหยุ่นได้ (dymaically sized array)
+
+// การประกาศตัวแปร : ชื่อตัวแปรเหล่านี้จะนำไปใช้ด้านล่างต่อไป
+var
+ int, c, d : integer;
+ // ประกาศในบล็อค var มีตัวแปรสามตัวเป็นอินทีเจอร์
+ // ชนิดจำนวนเต็ม แบบ 16 bit มีช่วงข้อมูล [-32,768.. 32,767]
+ // »int« ในที่นี้เป็น "ชื่อตัวแปร" ที่ต้นฉบับตั้งให้สอดคล้องกับชนิดข้อมูล
+ // อย่าสับสนกับบางภาษาที่มีชนิด int ประกาศหน้าชื่อตัวแปร
+ r : real;
+ // ตัวแปร r เป็นชนิดเรียล (real) หรือเลขทศนิยม
+ // real มีช่วงข้อมูล [3.4E-38..3.4E38]
+ bool : boolean;
+ // ข้อมูลชนิดบูเลียน (boolean) มีค่าได้สองแบบ คือ True/False
+ ch : char;
+ // ตัวแปร ch เป็นชนิดตัวอักษร (ชาร์? คาร์?) หรือคาแรกเตอร์
+ // ตัวอักษรเป็นแบบ ASCII 8 bit ดังนั้นจะไม่ใช่ UTF, Unicode
+ str : string;
+ // ตัวแปรสตริงจะเก็บข้อความ หรือ char หลาย ๆ ตัว
+ // ชนิดข้อมูลนี้ไม่เป็นมาตรฐานภาษาแต่คอมไพเลอร์ปาสกาลก็มักจะมีให้
+ // ทั่ว ๆ ไปแล้ว จะเป็นอะเรย์ของ char ความยาวตั้งต้น 255
+ s : string[50];
+ // แบบนี้คือ กำหนดความยาว string เอง ให้เก็บ char 50 ตัว
+ // แบบนี้ก็ทำให้ประหยัดหน่วยความจำมากขึ้นนั่นเอง
+ my_str: ch_array;
+ // ชนิดตัวแปร ใช้เป็นชนิดที่เรากำหนดเองก็ได้ อย่างตอนนี้
+ // ch_array เป็น "ชนิดข้อมูล" ที่เราสร้างขึ้นมาในบล็อค type
+ my_2d : md_array;
+ // ตัวแปรแบบอะเรย์ที่ไม่ประกาศขนาด (dynamically sized array)
+ // ก่อนเอาไปใช้จริงต้องระบุขนาดก่อนใช้เสมอ
+
+ // ชนิดข้อมูลแบบ integer เพิ่มเติม
+ b : byte; // มีช่วงข้อมูล [0..255]
+ shi : shortint; // มีช่วงข้อมูล [-128..127]
+ smi : smallint; // มีช่วงข้อมูล [-32,768..32,767] (standard Integer)
+ w : word; // มีช่วงข้อมูล [0..65,535]
+ li : longint; // มีช่วงข้อมูล [-2,147,483,648..2,147,483,647]
+ lw : longword; // มีช่วงข้อมูล [0..4,294,967,295]
+ c : cardinal; // ก็คือ longword
+ i64 : int64; // มีช่วงข้อมูล
+ // [-9223372036854775808..9223372036854775807]
+ qw : qword; // มีช่วงข้อมูล [0..18,446,744,073,709,551,615]
+
+ // ชนิดข้อมูลแบบ real เพิ่มเติม
+ rr : real; // มีช่วงข้อมูลที่ขึ้นกับระบบปฏิบัติการ
+ // (เช่นเป็นแบบ 8-bit, 16-bit, ฯลฯ)
+ rs : single; // มีช่วงข้อมูล [1.5E-45..3.4E38]
+ rd : double; // มีช่วงข้อมูล [5.0E-324 .. 1.7E308]
+ re : extended; // มีช่วงข้อมูล [1.9E-4932..1.1E4932]
+ rc : comp; // มีช่วงข้อมูล [-2E64+1 .. 2E63-1]
+
+Begin
+ // การกำหนดค่าตัวแปรให้ขณะประกาศ
+ int := 1;
+ r := 3.14;
+ ch := 'a'; // ใช้ single quote เหมือนกันทั้ง char และ string
+ str := 'apple';
+ bool := true;
+ // ภาษาปาสกาล มอง "ชื่อเฉพาะ" แบบไม่สนพิมพ์ใหญ่พิมพ์เล็ก
+ // (case-insensitive language)
+ // ตัวดำเนินการแบบคณิตศาสตร์ (arithmethic operation)
+ int := 1 + 1; // int = 2 ซึ่งจะกำหนดทับค่าเดิมด้านบนที่เคยประกาศ
+ int := int + 1; // int = 2 + 1 = 3 นำค่าตอนนี้ (2) มา +1 ได้ 3
+ int := 4 div 2; // int = 2 หารด้วย div จะได้ผลเป็น integer เสมอ
+ int := 3 div 2; // int = 1
+ int := 1 div 2; // int = 0
+
+ bool := true or false; // bool = true
+ bool := false and true; // bool = false
+ bool := true xor true; // bool = false
+
+ r := 3 / 2; // หารด้วย / จะได้ผลเป็น real เสมอ
+ r := int; // เรากำหนดค่า integer ให้ตัวแปร real ได้
+ // แต่ทำกลับกัน โดยกำหนด real ให้ integer ไม่ได้
+
+ c := str[1]; // กำหนดค่าแรกใน array str ให้ตัวแปร c ที่เป็น char
+ str := 'hello' + 'world'; // เรารวม string เข้าด้วยกันด้วย +
+
+ my_str[0] := 'a'; // กำหนดค่าให้ string เฉพาะตำแหน่งแบบอะเรย์ทั่วไป
+
+ setlength(my_2d,10,10); // ปรับขนาดอะเรย์ 2 มิติให้เป็นขนาด 10x10
+ // โดยตัวแปร my_2d นี้สร้างแล้วด้านบน
+ for c := 0 to 9 do // อะเรย์เริ่มจาก 0 และจบที่ ความยาว-1
+ for d := 0 to 9 do // ตัวนับ (counter) จำเป็นต้องประกาศก่อนใช้
+ my_2d[c,d] := c * d;
+ // กำหนดอะเรย์หลายมิติ ด้วยการใช้วงเล็บก้ามปู (square brackets)
+
+End.
+// จบโปรแกรมบริบูรณ์ ด้วย "."
+```
+
+ด้านล่าง เป็นตัวอย่างการเขียนโปรแกรมปาสกาลชื่อ Functional\_Programming
+
+```pascal
+program Functional_Programming;
+
+Var
+ i, dummy : integer;
+
+function factorial_recursion(const a: integer) : integer;
+{ ทำการคำนวณแฟคทอเรียลซ้ำ ๆ ของเลขจำนวนเต็ม โดยผ่านพารามิเตอร์ a
+ ถ้าจะประกาศตัวแปรโลคอลในฟังก์ชั่น ก็ทำได้ โดยการใช้บล็อค var ภายในฟังก์ชั่น
+ เช่น :
+ var
+ local_a : integer;
+}
+Begin
+ If a >= 1 Then
+ { ฟังก์ชั่นนี้คืนค่ากลับ โดยการกำหนดค่าที่ผ่านทางพารามิเตอร์ a
+ นำมาคูณกับฟังก์ชั่นที่ผ่าน a-1 สุดท้ายก็กำหนดค่าลงไปให้กับฟังก์ชั่นตรงๆ }
+ factorial_recursion := a * factorial_recursion(a-1)
+ Else
+ factorial_recursion := 1;
+End; // จบ ฟังก์ชั่น ด้วย ";" หลัง End ไม่เหมือนกับจบ โปรแกรม ที่จะใช้ "."
+
+procedure get_integer(var i : integer; dummy : integer);
+{ เรารับ input จากผู้ใช้มาเก็บใน parameter i ที่เป็น integer ที่ตั้งขึ้นใน
+ พารามิเตอร์ โดยใช้ var ประกาศ ทำให้ค่าที่รับเข้ามาจะเปลี่ยนปรับได้จาก
+ ภายนอกการประกาศพารามิเตอร์นี้ ส่วน dummy เป็นตัวแปรที่ปรับเปลี่ยนได้
+ "เฉพาะจากภายในฟังก์ชั่น,โพรซีเยอร์นั้น ๆ }
+Begin
+ write('Enter an integer: ');
+ readln(i);
+ dummy := 4; // dummy จะไม่ทำให้ค่าที่ได้รับมาครั้งแรกใน main block เปลี่ยน
+End;
+
+//--------------------//
+// main program block
+//--------------------//
+Begin
+ dummy := 3;
+ get_integer(i, dummy);
+ writeln(i, '! = ', factorial_recursion(i));
+ // พิมพ์ค่า i!
+ writeln('dummy = ', dummy); // จะให้ค่าเป็น '3' เสมอ
+ // เพราะจะไม่เปลี่ยนเนื่องด้วย
+ // การประกาศพารามิเตอร์ใน
+ // โพรซีเยอร์ get_integer ด้านบน
+End.
+
+```
+
+[1]: https://en.wikipedia.org/wiki/Pascal_(programming_language)
+[2]: https://www.freepascal.org/
diff --git a/th-th/typescript.th.html.markdown b/th-th/typescript.th.html.markdown
new file mode 100644
index 00000000..5395c2a7
--- /dev/null
+++ b/th-th/typescript.th.html.markdown
@@ -0,0 +1,259 @@
+---
+language: TypeScript
+contributors:
+ - ["Philippe Vlérick", "https://github.com/pvlerick"]
+ - ["Worajedt Sitthidumrong", "https://bitbucket.org/wrj"]
+filename: learntypescript-th.ts
+lang: th-th
+---
+
+TypeScript เป็นภาษาที่มีเป้าหมายเพื่อทำให้การพัฒนาซอฟต์แวร์ขนาดใหญ่ด้วย JavaScript ทำได้ง่ายขึ้น โดยที่ TypeScript ได้เพิ่มแนวคิดที่พบทั่วไป อาทิ classes, modules, interfaces, generics และ static typing (ไม่บังคับ) เข้าไปในภาษา JavaScript ดังนั้น TypeScript ก็เลยเป็น Super Set ของ JavaScript อีกที โค้ด JavaScript ทุกส่วน ก็คือโค้ดที่ทำงานได้ถูกต้องใน TypeScript ทำให้เราเพิ่ม TypeScript เข้าไปใช้ในโปรเจคการพัฒนาของเราได้ไม่ยากเลย เพราะ TypeScript คอมไพล์ผลลัพธ์ออกมาเป็น JavaScript ในท้ายสุดอยู่ดี
+
+บทความนี้จะเน้นเฉพาะ syntax ส่วนขยายของ TypeScript ซึ่งจะไม่รวมกับที่มีใน [JavaScript](/docs/javascript)
+
+การทดสอบเขียน TypeScript เริ่มได้ง่าย ๆ โดยเข้าไปที่
+[Playground](http://www.typescriptlang.org/Playground) ซึ่งคุณจะเขียนโค้ดพร้อม autocomplete และเห็นเลยว่ามันจะแปลงมาเป็นผลลัพธ์แบบ JavaScript อย่างไร
+
+```ts
+// TypeScript มี data type พื้นฐาน 3 แบบ
+let isDone: boolean = false;
+let lines: number = 42;
+let name: string = "Anders";
+
+// แต่เราก็สามารถละการบอกชนิดได้ โดยชนิดตัวแปรก็จะปรับชนิดของเขาจากข้อมูลที่กำหนดให้โดยตรง
+let isDone = false;
+let lines = 42;
+let name = "Anders";
+
+// ถ้าไม่รู้ ก็กำหนดเป็นชนิด "Any" ได้
+let notSure: any = 4;
+notSure = "maybe a string instead";
+notSure = false; // โอเค ตอนนี้เป็น Boolean แน่ ๆ
+
+// ใช้ const สำหรับสร้าง ค่าคงที่
+const numLivesForCat = 9;
+numLivesForCat = 1; // Error
+
+// สำหรับ collections มี typed arrays และ generic arrays
+// ก็คือ อะเรย์บอกชนิด และ อะเรย์เจเนอริก ตามลำดับ
+let list: number[] = [1, 2, 3];
+// ในอีกทางหนึ่ง สร้างเป็นอะเรย์ชนิด generic array
+let list: Array<number> = [1, 2, 3];
+
+// และสำหรับ enumerations:
+enum Color { Red, Green, Blue };
+let c: Color = Color.Green;
+
+// สุดท้าย, "void" ใช้เมื่อเป็นกรณีพิเศษที่ฟังก์ชันไม่ส่งค่ากลับ
+function bigHorribleAlert(): void {
+ alert("I'm a little annoying box!");
+}
+
+// ฟังก์ชั่น (Functions) เป็นสิ่งที่มีความสำคัญมาเป็นอันดับหนึ่ง รองรับการใช้ "fat arrow" ในการสร้าง lambda function และ type inference
+
+// สไตล์ต่อไปนี้มีค่าเท่ากันกับบรรทัดที่ยกตัวอย่างด้านล่าง เพราะคอมไพเลอร์จะมองเหมือนกัน และได้ JavaScript แบบเดียวกัน
+let f1 = function (i: number): number { return i * i; }
+// อนุมานชนิดที่ส่งกลับ หรือ type inferred
+let f2 = function (i: number) { return i * i; }
+// เขียนแบบ "Fat arrow" แต่บอกชนิดส่งกลับ
+let f3 = (i: number): number => { return i * i; }
+// เขียนแบบ "Fat arrow" แต่อนุมานชนิดส่งกลับ
+let f4 = (i: number) => { return i * i; }
+// เขียนแบบ "Fat arrow" อนุมานชนิดส่งกลับ พร้อมกับไม่มีวงเล็บ แปลว่าไม่ต้องมี return keyword ด้วย
+let f5 = (i: number) => i * i;
+
+// Interfaces นั้นเป็นเหมือนเราออกแบบโครงสร้าง คุณสมบัติต่าง ๆ ตอนเอาไปใช้ จะต้องเป็นไปตาม interface นั้น ๆ เหมือนกับเป็นการกำหนดสเป็คของ "ชนิดข้อมูล"
+interface Person {
+ name: string;
+ // Optional properties กำหนดด้วย "?"
+ age?: number;
+ // และมี function พร้อมชนิดได้ใน interface
+ move(): void;
+}
+
+// Object นี้ implements "Person" interface ทำให้มันเป็นชนิด Person และมันก็มี property name และ function move()
+let p: Person = { name: "Bobby", move: () => { } };
+// Objects นี้เป็นชนิด Person ด้วย และมี optional property หรือ age?: นั่นเอง
+let validPerson: Person = { name: "Bobby", age: 42, move: () => { } };
+// ไม่ใช่ Person เพราะ age: ต้องเป็น number เท่านั้น ตามข้อกำหนดใน interface Person
+let invalidPerson: Person = { name: "Bobby", age: true };
+
+// Interfaces ยังนำมาใช้ในลักษณะของ function ได้อีกด้วย
+interface SearchFunc {
+ (source: string, subString: string): boolean;
+}
+// เฉพาะชนิด parameters เท่านั้นที่สำคัญ ชื่อของมันไม่จำเป็นต้องเหมือน
+let mySearch: SearchFunc;
+mySearch = function (src: string, sub: string) {
+ return src.search(sub) != -1;
+}
+
+// สมาชิกใน class จะเข้าถึงได้แบบ public เป็นค่าปริยาย
+class Point {
+ // Properties
+ // ตั้งค่า Properties ของ class นี้
+ x: number;
+
+ // Constructor
+ // เราใส่ public/private keywords ตรงนี้ได้ มีผลเหมือนกันกับกำหนด x ด้านบน
+ // ในตัวอย่าง y มีการกำหนดเช่นเดียวกับ x แต่พิมพ์สั้นกว่า
+ // สังเกตว่า มีการกำหนดค่าปริยายให้ parameters ได้ด้วย
+
+ constructor(x: number, public y: number = 0) {
+ this.x = x;
+ }
+
+ // Functions
+ dist() { return Math.sqrt(this.x*this.x + this.y*this.y); }
+
+ // Static members
+ static origin = new Point(0, 0);
+}
+
+// Classes สามารถระบุชนิด interface ที่ต้องการได้ตรง ๆ ด้วยเช่นโค้ดด้านล่าง
+// แต่อะไรที่จะ implement มานั้น ถ้าไม่ได้กำหนดไว้ใน constructor ก็จะเกิดข้อผิดพลาดตอนคอมไพล์
+class PointPerson implements Person {
+ name: string // ตรงนี้จะผิด แก้ไขโดยการไปสร้างตัวรับค่าเข้ามาผ่านทาง constructor
+ move() {}
+}
+
+let p1 = new Point(10, 20);
+let p2 = new Point(25); //y เป็น 0 เพราะกำหนดค่าปริยายไว้ให้แล้ว
+
+// Inheritance การสืบทอดคุณสมบัติ
+class Point3D extends Point {
+ constructor(x: number, y: number, public z: number = 0) {
+ super(x, y); // เราจะต้องเรียกใช้ super class constructor โดยตรง
+ }
+
+ // Overwrite ฟังก์ชั่นที่มีอยู่เดิมใน Point
+ dist() {
+ let d = super.dist();
+ return Math.sqrt(d * d + this.z * this.z);
+ }
+}
+
+// Modules ใช้เป็นกลุ่มของ class เราใช้ "." เป็นตัวแบ่ง sub modules
+// อย่างกรณีนี้จะเป็น Module.Class เช่น Geometry.Square
+module Geometry {
+ export class Square {
+ constructor(public sideLength: number = 0) {
+ }
+ area() {
+ return Math.pow(this.sideLength, 2);
+ }
+ }
+}
+
+let s1 = new Geometry.Square(5);
+
+// เราทำให้เรียกใช้ง่ายขึ้นโดยการใช้ alias มาอ้างชื่อ module แบบเดียวกับบางภาษา เช่น Python
+import G = Geometry;
+
+let s2 = new G.Square(10);
+
+// Generics
+// Classes
+class Tuple<T1, T2> {
+ constructor(public item1: T1, public item2: T2) {
+ }
+}
+
+// Interfaces
+interface Pair<T> {
+ item1: T;
+ item2: T;
+}
+
+// และ functions
+let pairToTuple = function <T>(p: Pair<T>) {
+ return new Tuple(p.item1, p.item2);
+};
+
+let tuple = pairToTuple({ item1: "hello", item2: "world" });
+
+// เราเรียกใช้ไฟล์ definition แบบนี้:
+/// <reference path="jquery.d.ts" />
+
+// Template Strings ( คือ strings ที่ใช้ backticks ครอบ — "`" ปุ่มบนซ้ายคีย์บอร์ด )
+// แทรกข้อความใน String ด้วย Template Strings
+let name = 'Tyrone';
+let greeting = `Hi ${name}, how are you?`
+// Strings หลายบรรทัดก็ทำได้ใน Template Strings
+let multiline = `This is an example
+of a multiline string`;
+
+// READONLY: ความสามารถใหม่ใน TypeScript 3.1
+interface Person {
+ readonly name: string;
+ readonly age: number;
+}
+
+var p1: Person = { name: "Tyrone", age: 42 };
+p1.age = 25; // Error แน่นอน เพราะ p1.age ถูกกำหนดเป็น read-only
+
+var p2 = { name: "John", age: 60 }; // สังเกตว่า p2 ไม่ได้กำหนดเป็น Person
+var p3: Person = p2; // ทำได้ เป็น read-only alias ของ p2 และกำหนดเป็น Person
+p3.x = 35; // Error p3.x ก็เป็น read-only
+p2.x = 45; // Ok ทำได้แต่ก็จะเปลี่ยนค่า p3.x ด้วย เพราะ p3 เป็น alias ของ p2
+
+class Car {
+ readonly make: string;
+ readonly model: string;
+ readonly year = 2018;
+
+ constructor() {
+ this.make = "Unknown Make"; // อนุญาตให้กำหนดค่าได้ใน constructor แม้ว่าจะ read-only
+ this.model = "Unknown Model"; // อนุญาตให้กำหนดค่าได้ใน constructor แม้ว่าจะ read-only
+ }
+}
+
+let numbers: Array<number> = [0, 1, 2, 3, 4];
+let moreNumbers: ReadonlyArray<number> = numbers;
+moreNumbers[5] = 5; // Error, สมาชิกอะเรย์เป็น read-only แปลว่า ห้ามแก้ไข
+moreNumbers.push(5); // Error, push method ใช้ไม่ได้ เพราะมันจะไปแก้ไข read-only array
+moreNumbers.length = 3; // Error, เพราะ length ก็ต้อง read-only
+numbers = moreNumbers; // Error, method ที่ทำให้อะเรย์เปลี่ยนได้จะไม่อนุญาต
+
+// Tagged Union Types สำหรับโมเดลสเตท ที่อาจจะมีได้หลายๆ สเตท
+type State =
+ | { type: "loading" }
+ | { type: "success", value: number }
+ | { type: "error", message: string };
+
+ประกาศ const state: State;
+if (state.type === "success") {
+ console.log(state.value);
+} else if (state.type === "error") {
+ console.error(state.message);
+}
+
+// Iterators และ Generators
+
+// ประโยคแบบ for..of
+// การทำซ้ำกับ ลิสต์ของค่าในออปเจ็คต์
+let arrayOfAnyType = [1, "string", false];
+for (const val of arrayOfAnyType) {
+ console.log(val); // 1, "string", false
+}
+
+let list = [4, 5, 6];
+for (const i of list) {
+ console.log(i); // 4, 5, 6
+}
+
+// ประโยคแบบ for..in
+// การทำซ้ำกับ ลิสต์ของคีย์ในออปเจ็คต์
+for (const i in list) {
+ console.log(i); // 0, 1, 2
+}
+
+
+```
+
+## อ่านเพิ่มเติมที่
+ * [TypeScript Official website] (http://www.typescriptlang.org/)
+ * [TypeScript language specifications] (https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)
+ * [Anders Hejlsberg - Introducing TypeScript on Channel 9] (http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript)
+ * [Source Code on GitHub] (https://github.com/Microsoft/TypeScript)
+ * [Definitely Typed - repository for type definitions] (http://definitelytyped.org/)
diff --git a/tmux.html.markdown b/tmux.html.markdown
index b28a4f59..1c2c2da3 100644
--- a/tmux.html.markdown
+++ b/tmux.html.markdown
@@ -78,7 +78,7 @@ combinations called 'Prefix' keys.
p # Change to the previous window
{ # Swap the current pane with the previous pane
} # Swap the current pane with the next pane
- ] # Enter Copy Mode to copy text or view history.
+ [ # Enter Copy Mode to copy text or view history.
s # Select a new session for the attached client
interactively
diff --git a/toml.html.markdown b/toml.html.markdown
index 814e57e7..385a2437 100755
--- a/toml.html.markdown
+++ b/toml.html.markdown
@@ -32,7 +32,7 @@ boolean = true
dateTime = 1979-05-27T07:32:00-08:00
scientificNotation = 1e+12
"key can be quoted" = true # Both " and ' are fine
-"key may contains" = "letters, numbers, underscores, and dashes"
+"key may contain" = "letters, numbers, underscores, and dashes"
# A bare key must be non-empty, but an empty quoted key is allowed
"" = "blank" # VALID but discouraged
@@ -225,26 +225,26 @@ color = "gray"
# sub-table will belong to the nearest table element above it.
[[fruit]]
- name = "apple"
+ name = "apple" # I am a property in fruit table/map
- [fruit.Geometry]
+ [fruit.geometry]
shape = "round"
- note = "I am an fruit's property"
+ note = "I am a property in geometry table/map"
[[fruit.color]]
name = "red"
- note = "I am an array's item in apple"
+ note = "I am an array item in apple fruit's table/map"
[[fruit.color]]
name = "green"
- note = "I am in the same array than red"
+ note = "I am in the same array as red"
[[fruit]]
name = "banana"
[[fruit.color]]
name = "yellow"
- note = "I am an array's item too but banana's one"
+ note = "I am an array item in banana fruit's table/map"
```
In JSON land, this code will be:
diff --git a/tr-tr/c-tr.html.markdown b/tr-tr/c-tr.html.markdown
index 6042a609..4ef12527 100644
--- a/tr-tr/c-tr.html.markdown
+++ b/tr-tr/c-tr.html.markdown
@@ -477,7 +477,7 @@ typedef void (*my_fnp_type)(char *);
[K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)'in bir kopyasını bulundurmak mükemmel olabilir
-Diğer bir iyi kaynak ise [Learn C the hard way](http://c.learncodethehardway.org/book/)
+Diğer bir iyi kaynak ise [Learn C the hard way](http://learncodethehardway.org/c/)
It's very important to use proper spacing, indentation and to be consistent with your coding style in general.
Readable code is better than clever code and fast code. For a good, sane coding style to adopt, see the
diff --git a/tr-tr/clojure-tr.html.markdown b/tr-tr/clojure-tr.html.markdown
index 64970945..5ebe5ce6 100644
--- a/tr-tr/clojure-tr.html.markdown
+++ b/tr-tr/clojure-tr.html.markdown
@@ -4,6 +4,7 @@ lang: tr-tr
filename: learnclojure-tr.clj
contributors:
- ["Adam Bard", "http://adambard.com/"]
+ - ["Seçkin KÜKRER", "https://leavenha.github.io"]
translators:
- ["Seçkin KÜKRER", "https://leavenha.github.io"]
---
diff --git a/tr-tr/edn-tr.html.markdown b/tr-tr/edn-tr.html.markdown
new file mode 100644
index 00000000..9a2ac1ff
--- /dev/null
+++ b/tr-tr/edn-tr.html.markdown
@@ -0,0 +1,157 @@
+---
+language: edn
+filename: learnedn-tr.edn
+lang: tr-tr
+contributors:
+ - ["Seçkin KÜKRER", "https://github.com/LeaveNhA"]
+---
+
+# Y = 20 Dakika.
+
+### Genişletilebilir Veri Notasyonu (EDN, Extensible Data Notation).
+
+### Okunuşu: (Türkçe: ey-di-en), (English: eed-n)
+
+### Kodlama Türü: UTF-8
+
+EDN Clojure sözdiziminin bir alt kümesidir. Bu alt küme, amacı gereği kod barındırmaz. Ve kendisi bir tip sistemi değildir. Bir şeması da yoktur. En basit tabirle; Genişletilebilir Veri Notasyonu kabul edilebilir elemanların bir kümesidir.
+
+EDN elementleri, akışları ve dosyaları UTF-8 kullanılarak kodlanmalıdır. Üstelik, dökümanı çevreleyen işaretçiler de olmadığı için akış, dağıtık programlama mesaj arayüzü ve diğer dinamik sistemler için idealdir.
+
+
+```clojure
+; Yorumlar, yorumlarımız, noktalı virgül ile başlıyor.
+;; Genellikle ikili olarak kullanılıyorlar.
+
+;; |--------------------------------|
+; |--------- Genel Yapısı ---------|
+;; |--------------------------------|
+
+;; Boşluklar --whitespaces--, elementler için en yaygın ayıraçtır.
+"Mustafa" "Kemal" "ATATÜRK"
+;; Fakat okunuşu arttırdığı gerekçesiyle "," (virgüller --commas--) EDN yorumlayıcısı tarafından görmezden gelinir ve boşluk olarak nitelendirilir.
+"Mustafa","Kemal","PAŞA"
+;; Üstelik bu yenilikçi sözdizimsel kurala rağmen, {}, [] () gibi koleksiyon karakterlerini ayırmak için boşluğa ya da boşluğa çözümlenen virgüle ihtiyacınız yoktur.
+[["MUSTAFA"] ["KEMAL"] [[{"ATA" "ATATÜRK"}]]]
+;; Üst düzey vektör elemanlarını birbirinden ayıran boşlukları da kaldırabilirsiniz.
+;; Fakat bu size, okunması zor bir vektör dışında hiç bir şey vermeyecektir.
+
+;; |--------------------------------|
+; |-------- Atomik Yapılar --------|
+;; |--------------------------------|
+
+; Mantıksal Değerler
+;; Mantıksal Doğru, çoğu teknolojide aynı gösterimi var.
+true
+;; Mantıksal Yanlış.
+false
+
+; Karakter Katarları
+;; Karakter katarları, --SADECE-- çift tırnak ile belirtilebilir.
+"İzmirin dağlarında çiçekler açar!"
+;; C, C++, Java v.b. gibi dillerin desteklediği kaçış sekanslarını da destekler.
+"Altın güneş orda sırmalar saçar.\nBozulmuş düşmanlar yel gibi kaçar."
+;; Kaçış sekansları için bknz: $!$
+
+; Karakter Sabitleri
+;; Karakter sabitleri önlerinde bir ters eğik çizgi ile temsil edilirler.
+\T \Ü \R \K
+;; Üstelik, belirli kaçıl sekanslarının da karşılığı Karakter Sabiti olarak var.
+\newline \return
+
+; Anahtar Kelimeler
+;; Anahtar Kelimeler, önlerinde bir ":" iki nokta --colon--
+:yımırta
+:kaşar
+:bıngıl
+
+; Semboller
+;; Semboller tanımlayıcıları temsil etmek için kullanılır.
+;; "/" karakteri, Sembol Sabitlerinde isim-uzayı ayıracı olarak kullanılıyor.
+izmir/kızları
+;; "mutfak" isim uzayındaki "ekmek-bıçağı" isimli sembole çözümlenir.
+
+banyo/fayans
+parke
+laminat
+
+; Sayısal Değerler
+;; Tam Sayı sabiti.
+1991
+;; Kayan Noktalı Sabiti.
+19.67
+
+; Listeler
+;; Listeler, yukarıdaki temel tiplerin ardışıklanmasıdır.
+(bomba :bomba nokta \c \o \m)
+
+; Vektörler
+;; Vektörler bir bakıma Listelere benzeseler de, bir çok açıdan farklıdırlar.
+;; Mesela Listenin aksine Vektörler, Rastgele Erişime imkan verir.
+[[] "şimdi" "asker"]
+
+; Eşlemeler
+;; Sıfır veya daha fazla Anahtar-Değer çifti kabul eder.
+;; Not: Clojure Veri Yapıları Soyutlaması ile Eşlemeler de, teknik olarak ardışık olarak işlenebilir.
+{:canı :neler-ister?
+ :uykuda "mevlam"}
+;; Bu ve diğer tüm Veri Yapıları Homojendir, birbirilerini barındırabilir, kapsayabilir, içerebilirler.
+;; Ayrıca okunurluk gibi farklı sebeplerle virgül kullanımında özgürsünüz.
+{{:id_ "129u391824981237981237" :kim "BEN"}, göster!}
+
+; Kümeler
+;; Kümeler eşsiz eleman barındıran bir yapıdır.
+;; Matematikteki karşılığını veriyor dersek yanlış olmaz.
+#{:sen 3 milyar 750 milyon}
+
+;; |--------------------------------|
+; |------ Etiketli Elemanlar ------|
+;; |--------------------------------|
+
+;; EDN (Genişletilebilir Veri Notasyonu), # sembolü ile genişletilebilir.
+
+#benimuygulamam/bağlantı {:içerik "Y dakikada EDN Öğren" :url "https://learnxinyminutes.com/docs/tr-tr/edn-tr" :tıhlama-aksiyonu yırrttılll!}
+
+;; Ve bu yapıyı yorumlayacak bir de yapı gerekiyor.
+(defn ->bağlantı [props]
+ (str "<a href='" (:url props) "'" ">"
+ (:içerik props)
+ "</a>"))
+
+;; Bu örnekte yorumlayıcıya, basit bir fonksiyon veriyoruz.
+;; `clojure.edn/read-string` aslında bir ayarlar Eşlemesi kabul ediyor.
+;; (Bu tür fonksiyon genişlemeleri, Clojure ekosisteminde yaygındır.)
+
+(clojure.edn/read-string
+ {:readers {'benimuygulamam/bağlantı ->bağlantı}}
+ "#benimuygulamam/bağlantı {:içerik \"Y dakikada EDN Öğren\" :url \"https://learnxinyminutes.com/docs/tr-tr/edn-tr\" :tıhlama-aksiyonu yırrttılll!}")
+;=> "<a href='https://learnxinyminutes.com/docs/tr-tr/edn-tr'>Y dakikada EDN Öğren</a>"
+
+;; |--------------------------------|
+; |--- Ön Tanımlı Genişletmeler ---|
+;; |--------------------------------|
+
+; Tarih Etiketi
+;; Bu etiket `inst` ön-ekinden sonra bir RFC-3339 formatında bir karakter katarı beklemektedir.
+#inst "2013-10-21T14:50:00+00:00" ; => Formatlanmış bir şekilde: 21/10/2013 14:50:00
+
+; UUID Etiketi
+;; Bu etiket `uuid` ön-ekinden sonra bir UUID karşılığını karakter katarı olarak kabul eder.
+#uuid "11k12fae-7d3c-11k0-a765-0010ckke6hgk"
+
+```
+
+# Son Ek
+Bu içerik, EDN'i tanıtmakta kısıtlı bir açıyla, özet bilgiler sunmaktadır.
+Fakat, Clojure ve diğer Veri Odaklı dillerde, Verinin yolculuğunu anlamak için önemli bir rol oynamaktadır.
+EDN'in var olan probleme çözümü ve artı/eksilerinin doğru şekilde kavranması mühimdir.
+Ben bu dökümanı hazırlarken, EDN ve gerçek dünya kullanımını anlatan yoktu. Fakat ümidim, Clojure ve diğer teknolojiler üzerinde kullanımının artmasından sonra birinin bu ihtiyacı giderecek özgün kaynak çıkarmasıdır.
+
+Başarılar!
+
+# Referanslar
+
+- [EDN Formatı Standardı](https://github.com/edn-format/edn)
+- [Gerçeklemeler](https://github.com/edn-format/edn/wiki/Implementations)
+- [Etiketlenmiş Elementler](http://www.compoundtheory.com/clojure-edn-walkthrough/)
+- [Clojure.Docs EDN İçeriği](https://clojuredocs.org/clojure.edn)
diff --git a/tr-tr/sql-tr.html.markdown b/tr-tr/sql-tr.html.markdown
new file mode 100644
index 00000000..54007d32
--- /dev/null
+++ b/tr-tr/sql-tr.html.markdown
@@ -0,0 +1,125 @@
+---
+language: SQL
+contributors:
+ - ["Metin Yalçınkaya", "https://github.com/mtnylnky"]
+lang: tr-tr
+filename: learnsql-tr.sql
+---
+
+
+```sql
+-- Yorumlar iki tire ile başlar
+
+-- KISITLAR
+Not null -- Bir kolon asla boş olamaz
+default -- Boş olan yerlere varsayılan bir değer atar
+unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması
+primary key -- Bir tablodaki her veri için kimlik bilgisi niteliğindedir
+check -- Bir kolondaki değerlerin belli bir kısıtlamayı sağlamasını sağlar
+
+-- Tablo oluşturulur
+CREATE TABLE tablo1 ();
+
+-- Tabloyu içerisinde kolonlar ile oluşturma
+CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER);
+
+-- TABLO varlığını kontrol eder
+.table
+
+-- Veri tabanında olan bütün tabloları görüntüler.
+.schema
+
+-- Satır ekle
+INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2");
+
+-- Veritabanında tablo üzerindeki verileri görüntüle
+-- Sadece 'ad' gibi sınırlı bir veri için
+SELECT ad FROM tablo1;
+-- Bütün veriler için
+SELECT * FROM tablo1;
+
+-- Veri güncelleme
+UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1";
+
+-- Satır sil
+DELETE FROM tablo1 WHERE id = 1;
+DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2";
+
+-- Tabloya sonradan kolon ekleme
+ALTER TABLE tablo1 ADD COLUMN email TEXT;
+
+-- Tablodaki kolon adı değiştirme
+EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN';
+
+-- Tablo adı değiştirme
+ALTER TABLE table1 RENAME TO Table1;
+
+-- Tabloyu silme
+DROP TABLE Table1;
+
+-- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK
+INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1;
+
+-- LIKE KOMUTU
+-- Belirli bir kritere göre arama yaparken kullanılır
+-- Adı 'A' ile başlayan veriler
+SELECT * FROM tablo1 WHERE adi LIKE "A%";
+-- İçinde 'A' olan veriler
+SELECT * FROM tablo1 WHERE adi LIKE "%A%";
+
+-- LIMIT KOMUTU
+-- Gösterilen satır sayısını sınırlamak için
+SELECT * FROM Tablo1 LIMIT 6;
+-- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için
+SELECT * FROM Tablo1 LIMIT 6 OFFSET 3;
+
+-- ORDER BY KOMUTU
+-- Herhangi bir kolona göre gösterilen değerleri azalan veya artan şekilde sıralamak için
+SELECT kolon FROM tablo1 WHERE yas ORDER BY column1, column2, .. columnN] [ASC | DESC];
+SELECT * FROM Tablo1 ORDER BY yas ASC
+SELECT * FROM Tablo1 ORDER BY yas DESC
+
+-- DISTINCT ANAHTAR SÖZCÜĞÜ
+-- Bu anahtar sözcükle sadece farklı değerler gösterilir.
+SELECT DISTINCT yas FROM tablo1;
+
+-- JOIN KOMUTU
+-- CROSS JOIN
+-- Cross join bir tablodaki her satırı ikinci tablodaki bir satır ile eşleştirmek için kulanılır.
+-- Eğer birinci tabloda x satır ikinci tabloda y satır varsa sonuçta x*y satır olur.
+SELECT ... FROM table1 CROSS JOIN table2 …
+SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2;
+
+-- INNER JOIN
+-- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir.
+SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression …
+SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad;
+
+-- OUTER JOIN
+-- Outer join iki tablodaki ortak kolon değerlerinin dışında kalanları kullanarak bir sonuç üretir.
+SELECT isci_num, isim, dept FROM Tablo1 LEFT OUTER JOIN Tablo2 ON Tablo1.id = Tablo2.isci_num;
+
+-- ÇEKİRDEK FONKSİYONLAR
+COUNT -- Sayma
+AVG -- Ortalama
+ABS -- Mutlak değer
+SUM -- Toplam
+RANDOM -- Rastgele
+ROUND -- Yuvarlama
+MAX -- Maksimim
+MIN -- Minimum
+UPPER -- Büyük Harf
+LOWER -- Küçük Harf
+LENGTH -- Uzunluk
+CURRENT_TIMESTAMP -- Zaman
+
+SELECT max(yas) FROM Table1;
+SELECT min(yas) FROM Table1;
+SELECT avg(yas) FROM Table1;
+SELECT * From Table1 WHERE yas ==18;
+SELECT sum(yas) FROM Table1;
+SELECT random() AS Random;
+SELECT upper(ad) FROM Table1;
+SELECT lower(ad) FROM Table1;
+SELECT ad, length(ad) FROM Table1;
+``` \ No newline at end of file
diff --git a/typescript.html.markdown b/typescript.html.markdown
index ba4a9e71..7e857cc0 100644
--- a/typescript.html.markdown
+++ b/typescript.html.markdown
@@ -16,7 +16,7 @@ This article will focus only on TypeScript extra syntax, as opposed to
[JavaScript](/docs/javascript).
To test TypeScript's compiler, head to the
-[Playground] (http://www.typescriptlang.org/Playground) where you will be able
+[Playground](https://www.typescriptlang.org/play) where you will be able
to type code, have auto completion and directly see the emitted JavaScript.
```ts
@@ -199,7 +199,7 @@ interface Person {
}
var p1: Person = { name: "Tyrone", age: 42 };
-p1.age = 25; // Error, p1.x is read-only
+p1.age = 25; // Error, p1.age is read-only
var p2 = { name: "John", age: 60 };
var p3: Person = p2; // Ok, read-only alias for p2
@@ -223,6 +223,59 @@ moreNumbers[5] = 5; // Error, elements are read-only
moreNumbers.push(5); // Error, no push method (because it mutates array)
moreNumbers.length = 3; // Error, length is read-only
numbers = moreNumbers; // Error, mutating methods are missing
+
+// Tagged Union Types for modelling state that can be in one of many shapes
+type State =
+ | { type: "loading" }
+ | { type: "success", value: number }
+ | { type: "error", message: string };
+
+declare const state: State;
+if (state.type === "success") {
+ console.log(state.value);
+} else if (state.type === "error") {
+ console.error(state.message);
+}
+
+// Iterators and Generators
+
+// for..of statement
+// iterate over the list of values on the object being iterated
+let arrayOfAnyType = [1, "string", false];
+for (const val of arrayOfAnyType) {
+ console.log(val); // 1, "string", false
+}
+
+let list = [4, 5, 6];
+for (const i of list) {
+ console.log(i); // 4, 5, 6
+}
+
+// for..in statement
+// iterate over the list of keys on the object being iterated
+for (const i in list) {
+ console.log(i); // 0, 1, 2
+}
+
+// Type Assertion
+
+let foo = {} // Creating foo as an empty object
+foo.bar = 123 // Error: property 'bar' does not exist on `{}`
+foo.baz = 'hello world' // Error: property 'baz' does not exist on `{}`
+
+// Because the inferred type of foo is `{}` (an object with 0 properties), you
+// are not allowed to add bar and baz to it. However with type assertion,
+// the following will pass:
+
+interface Foo {
+ bar: number;
+ baz: string;
+}
+
+let foo = {} as Foo; // Type assertion here
+foo.bar = 123;
+foo.baz = 'hello world'
+
```
## Further Reading
diff --git a/uk-ua/cypher-ua.html.markdown b/uk-ua/cypher-ua.html.markdown
new file mode 100644
index 00000000..0911793b
--- /dev/null
+++ b/uk-ua/cypher-ua.html.markdown
@@ -0,0 +1,254 @@
+---
+language: cypher
+filename: LearnCypher-ua.cql
+contributors:
+ - ["Théo Gauchoux", "https://github.com/TheoGauchoux"]
+translators:
+ - ["AstiaSun", "https://github.com/AstiaSun"]
+lang: uk-ua
+---
+
+Cypher - це мова запитів Neo4j для спрощення роботи з графами. Вона повторює синтаксис SQL та перемішує його з таким собі ascii стилем для відображення структури графа.
+Цей навчальний матеріал передбачає, що ви вже знайомі із концепцією графів, зобрема що таке вершини та зв'язки між ними.
+
+[Деталі тут](https://neo4j.com/developer/cypher-query-language/)
+
+
+Вершини
+---
+
+**Відображує запис у графі.**
+
+`()`
+Таким чином у запиті позначається пуста *вершина*. Використовується зазвичай для того, щоб позначити, що вона є, проте це не так вже й важливо для запиту.
+
+`(n)`
+Це вершина, яка має назву **n**, до неї можна повторно звертатись у запиті. Звернення до вершини **n** починається з нижнього підкреслення та використовує camelCase (верблюжий регіст).
+
+`(p:Person)`
+Можна також додати *ярлик* до вершини, в данному випадку - **Person**. Це як тип / клас / категорія. Назва *ярлика* починається з великої літери та використовує верблюжу нотацію.
+
+`(p:Person:Manager)`
+Вершина може мати кілька *ярликів*.
+
+`(p:Person {name : 'Théo Gauchoux', age : 22})`
+Вершина також може мати різні *властивості*, в данному випадку - **name** та **age**. Також мають починатися з великої літери та використовувати верблюжу нотацію.
+
+Наступні типи дозволяється використовувати у властивостях:
+
+ - Чиселиний
+ - Булевий
+ - Рядок
+ - Списки попередніх примітивних типів
+
+*Увага! В Cypher не існує типу, що відображає час. Замість нього можна використовувати рядок із визначеним шаблоном або чисельне відображення певної дати.*
+
+`p.name`
+За допомогою крапки можна звернутись до властивості вершини.
+
+
+Зв'язки (або ребра)
+---
+
+**Сполучають дві вершини**
+
+`[:KNOWS]`
+Це *зв'язок* з *ярликом* **KNOWS**. Це такий же самий *ярлик* як і у вершини. Починається з великої літери та використовує ВЕРХНІЙ\_РЕГІСТР\_ІЗ\_ЗМІЇНОЮ\_НОТАЦІЄЮ.
+
+`[k:KNOWS]`
+Це той же самий *зв'язок*, до якого можна звертатись через змінну **k**. Можна подалі використовувати у запиті, хоч це і не обов'язково.
+
+`[k:KNOWS {since:2017}]`
+Той же *зв'язок*, але вже із *властивостями* (як у *вершини*), в данному випадку властивість - це **since**.
+
+`[k:KNOWS*..4]`
+Це структурна інформація, яку використовують *шляхи*, які розглянуті нижче. В данному випадку, **\*..4** говорить: "Сумістити шаблон із зв'язком **k**, що повторюватиметься від одного до чотирьох разів."
+
+
+Шляхи
+---
+
+**Спосіб поєднувати вершини та зв'язки.**
+
+`(a:Person)-[:KNOWS]-(b:Person)`
+Шлях описує, що вершини **a** та **b** знають (knows) один одного.
+
+`(a:Person)-[:MANAGES]->(b:Person)`
+Шлях може бути направленим. Цей описує, що **а** є менеджером **b**.
+
+`(a:Person)-[:KNOWS]-(b:Person)-[:KNOWS]-(c:Person)`
+Можна створювати ланцюги зі зв'язків. Цей шлях описує друга друга (**a** знає **b**, який в свою чергу знає **c**).
+
+`(a:Person)-[:MANAGES]->(b:Person)-[:MANAGES]->(c:Person)`
+Ланцюг, аналогічно, також може бути направленим. Шлях описує, що **a** - бос **b** і супер бос для **c**.
+
+Шаблони, які часто використовуються (з документації Neo4j):
+
+```
+// Друг-мого-друга
+(user)-[:KNOWS]-(friend)-[:KNOWS]-(foaf)
+
+// Найкоротший шлях
+path = shortestPath( (user)-[:KNOWS*..5]-(other) )
+
+// Спільна фільтрація
+(user)-[:PURCHASED]->(product)<-[:PURCHASED]-()-[:PURCHASED]->(otherProduct)
+
+// Навігація по дереву
+(root)<-[:PARENT*]-(leaf:Category)-[:ITEM]->(data:Product)
+
+```
+
+
+Запити на створення
+---
+
+Створити нову вершину:
+```
+CREATE (a:Person {name:"Théo Gauchoux"})
+RETURN a
+```
+*`RETURN` дозволяє повернути результат після виконання запиту. Можна повертати кілька значень, наприклад, `RETURN a, b`.*
+
+Створити новий зв'язок (із двома вершинами):
+```
+CREATE (a:Person)-[k:KNOWS]-(b:Person)
+RETURN a,k,b
+```
+
+Запити на знаходження
+---
+
+Знайти всі вершини:
+```
+MATCH (n)
+RETURN n
+```
+
+Знайти вершини за ярликом:
+```
+MATCH (a:Person)
+RETURN a
+```
+
+Знайти вершини за ярликом та властивістю:
+```
+MATCH (a:Person {name:"Théo Gauchoux"})
+RETURN a
+```
+
+Знайти вершини відповідно до зв'язків (ненаправлених):
+```
+MATCH (a)-[:KNOWS]-(b)
+RETURN a,b
+```
+
+Знайти вершини відповідно до зв'язків (направлених):
+```
+MATCH (a)-[:MANAGES]->(b)
+RETURN a,b
+```
+
+Знайти вершини за допомогою `WHERE`:
+```
+MATCH (p:Person {name:"Théo Gauchoux"})-[s:LIVES_IN]->(city:City)
+WHERE s.since = 2015
+RETURN p,state
+```
+
+Можна використовувати вираз `MATCH WHERE` разом із операцією `CREATE`:
+```
+MATCH (a), (b)
+WHERE a.name = "Jacquie" AND b.name = "Michel"
+CREATE (a)-[:KNOWS]-(b)
+```
+
+
+Запити на оновлення
+---
+
+Оновити окрему властивість вершини:
+```
+MATCH (p:Person)
+WHERE p.name = "Théo Gauchoux"
+SET p.age = 23
+```
+
+Оновити всі властивості вершини:
+```
+MATCH (p:Person)
+WHERE p.name = "Théo Gauchoux"
+SET p = {name: "Michel", age: 23}
+```
+
+Додати нову властивіcть до вершини:
+```
+MATCH (p:Person)
+WHERE p.name = "Théo Gauchoux"
+SET p + = {studies: "IT Engineering"}
+```
+
+Повісити ярлик на вершину:
+```
+MATCH (p:Person)
+WHERE p.name = "Théo Gauchoux"
+SET p:Internship
+```
+
+
+Запити на видалення
+---
+
+Видалити окрему вершину (пов'язані ребра повинні бути видалені перед цим):
+```
+MATCH (p:Person)-[relationship]-()
+WHERE p.name = "Théo Gauchoux"
+DELETE relationship, p
+```
+
+Видалити властивість певної вершини:
+```
+MATCH (p:Person)
+WHERE p.name = "Théo Gauchoux"
+REMOVE p.age
+```
+
+*Зверніть увагу, що ключове слово `REMOVE` це не те саме, що й `DELETE`!*
+
+Видалити ярлик певної вершини:
+```
+MATCH (p:Person)
+WHERE p.name = "Théo Gauchoux"
+DELETE p:Person
+```
+
+Видалити всю базу даних:
+```
+MATCH (n)
+OPTIONAL MATCH (n)-[r]-()
+DELETE n, r
+```
+
+*Так, це `rm -rf /` на мові Cypher !*
+
+
+Інші корисні запити
+---
+
+`PROFILE`
+Перед виконанням, показати план виконання запитів.
+
+`COUNT(e)`
+Порахувати елементи (вершини та зв'язки), що відповідають **e**.
+
+`LIMIT x`
+Обмежити результат до x перших результатів.
+
+
+Особливі підказки
+---
+
+- У мові Cypher існують лише однорядкові коментарі, що позначаються двійним слешем : // Коментар
+- Можна виконати скрипт Cypher, збережений у файлі **.cql** прямо в Neo4j (прямо як імпорт). Проте, не можна мати мати кілька виразів в цьому файлі (розділених **;**).
+- Використовуйте командний рядок Neo4j для написання запитів Cypher, це легко і швидко.
+- Cypher планує бути стандартною мовою запитів для всіх графових баз даних (більш відома як **OpenCypher**).
diff --git a/uk-ua/go-ua.html.markdown b/uk-ua/go-ua.html.markdown
new file mode 100644
index 00000000..f980f7b1
--- /dev/null
+++ b/uk-ua/go-ua.html.markdown
@@ -0,0 +1,449 @@
+---
+name: Go
+category: language
+language: Go
+filename: learngo-ua.go
+contributors:
+ - ["Sonia Keys", "https://github.com/soniakeys"]
+ - ["Christopher Bess", "https://github.com/cbess"]
+ - ["Jesse Johnson", "https://github.com/holocronweaver"]
+ - ["Quint Guvernator", "https://github.com/qguv"]
+ - ["Jose Donizetti", "https://github.com/josedonizetti"]
+ - ["Alexej Friesen", "https://github.com/heyalexej"]
+ - ["Clayton Walker", "https://github.com/cwalk"]
+ - ["Leonid Shevtsov", "https://github.com/leonid-shevtsov"]
+translators:
+ - ["AstiaSun", "https://github.com/AstiaSun"]
+lang: uk-ua
+---
+
+Go був створений для того, щоб виконати задачу. Це не останній тренд в теорії мов програмування, а спосіб вирішення реальних проблем.
+
+Він увібрав принципи з імперативних мов зі статичною типізацією.
+Go швидко компілюється та виконується, а його багатопоточність легка для
+вивчення, оскільки багатоядерні CPU стали буденністю. Ця мова програмування успішно використовується у кодах великих продуктів (~100 мільйонів в Google, Inc.)
+
+Go має чудову стандартну бібліотеку та чимале ком'юніті.
+
+```go
+// Однорядковий коментар
+/* Багато-
+ рядковий коментар */
+
+// Кожен файл вихідного коду має починатись із ключового слова package.
+// main - це спеціальна назва, що оголошує виконуваний код, а не бібліотеку.
+package main
+
+// import оголошує бібліотеки, що використовуються в даному файлі.
+import (
+ "fmt" // Пакет стандартної бібліотеки Go.
+ "io/ioutil" // Цей пакет реалізує деякі I/O функції утиліт.
+ m "math" // Бібліотека математичних операцій з локальним псевдонімом m.
+ "net/http" // Так, веб сервер!
+ "os" // Функції операційної системи, такі як робота з файловою системою.
+ "strconv" // Перетворення текстових змінних.
+)
+
+// Оголошення функції.
+// Функція main - особлива. Це вхідна точка для виконуваних програм.
+// Ви можете любити це, або ж ненавидіти, але Go використовує фігурні дужки.
+func main() {
+ // Println виводить рядок в stdout.
+ // Ця функція входить у пакет fmt.
+ fmt.Println("Hello world!")
+
+ // Викликати іншу функцію з цього файлу.
+ beyondHello()
+}
+
+// Аргументи функцій описуються у круглих дужках.
+// Навіть якщо ніякі аргументи не передаються, пусті круглі дужки - обов`язкові.
+func beyondHello() {
+ var x int // Оголошення змінної. Перед використанням змінні обов'язково мають бути оголошені.
+ x = 3 // Присвоєння значення.
+ // "Короткі" оголошення використовують := щоб окреслити тип, оголосити та присвоїти значення.
+ y := 4
+ sum, prod := learnMultiple(x, y) // Функція повертає два значення.
+ fmt.Println("sum:", sum, "prod:", prod) // Просто вивід.
+ learnTypes() // < y хвилин, потрібно вивчити більше!
+}
+
+/* <- багаторядковий коментар
+Функції можуть мати параметри та повертати довільну кількість значень.
+В цьому прикладі `x`, `y` - це аргументи, а `sum`, `prod` - це змінні, що повертаються.
+Зверніть увагу, що `x` та `sum` мають тип `int`.
+*/
+func learnMultiple(x, y int) (sum, prod int) {
+ return x + y, x * y // Повернути два значення.
+}
+
+// Кілька вбудованих типів та літералів.
+func learnTypes() {
+ // Короткі оголошення зазвичай виконують все, що необхідно.
+ str := "Вчи Go!" // рядок (string).
+
+ s2 := `"Необроблений" текст
+може містити переноси рядків.` // Також має тип рядок.
+
+ // Не ASCII символи. Go використовує UTF-8.
+ g := 'Σ' // руничний тип, псевдонім для int32, містить позицію юнікод кода.
+
+ f := 3.14195 // float64, IEEE-754 64-бітне число з плаваючою крапкою.
+ c := 3 + 4i // complex128, комплексні числа, що являють собою два float64.
+
+ // Синтаксис ініціалізації з var.
+ var u uint = 7 // Беззнаковий цілочисельний тип, проте розмір залежить від імплементації, так само як і int.
+ var pi float32 = 22. / 7
+
+ // Синтаксис перетворення типів з коротким оголошенням.
+ n := byte('\n') // Байт - це переіменований uint8.
+
+ // Розмір масива фіксований протягом часу виконання.
+ var a4 [4]int // Масив з 4 чисел, всі проініціалізовані 0.
+ a5 := [...]int{3, 1, 5, 10, 100} // Масив проініціалізованих чисел з фіксованим розміром у
+ // п'ять елементів, що мають значення 3, 1, 5, 10, та 100.
+
+ // Зрізи мають динамічний розмір. Переваги є і у масивів, й у зрізів, проте
+ // останні використовуються частіше.
+ s3 := []int{4, 5, 9} // Порівняйте з a5. Тут немає трьокрапки.
+ s4 := make([]int, 4) // Виділяє пам'ять для зрізу з 4 чисел, проініціалізованих 0.
+ var d2 [][]float64 // Декларація, нічого не виділяється.
+ bs := []byte("a slice") // Синтаксис переведення у інший тип.
+
+ // Оскільки зрізи динамічні, до них можна додавати елементи за необхідністю.
+ // Для цієї операції використовується вбудована функція append().
+ // Перший аргумент - це зріз, до якого додається елемент. Зазвичай
+ // змінна масиву оновлюється на місці, як у прикладі нижче.
+ s := []int{1, 2, 3} // В результаті отримуємо зріз із 3 чисел.
+ s = append(s, 4, 5, 6) // додаємо 3 елементи. Зріз тепер довжини 6.
+ fmt.Println(s) // Оновлений зріз тепер має значення [1 2 3 4 5 6]
+
+ // Щоб об'єднати два зрізи, замість того, щоб проходитись по всім елементам,
+ // можна передати посилання на зріз із трьокрапкою, як у прикладі нижче. Таким чином,
+ // зріз розпакується і його елементи додадуться до зріза s.
+ s = append(s, []int{7, 8, 9}...)
+ fmt.Println(s) // Оновлений зріз тепер дорівнює [1 2 3 4 5 6 7 8 9]
+
+ p, q := learnMemory() // Оголошує змінні p, q, що є вказівниками на числа.
+ fmt.Println(*p, *q) // * іде попереду вказівника. Таким чином, виводяться числа.
+
+ // Асоціативний масив (map) - це динамічно розширюваний тип даних, як хеш
+ // або словник в інших мовах програмування
+ m := map[string]int{"three": 3, "four": 4}
+ m["one"] = 1
+
+ // В Go змінні, які не використовуються, вважаються помилкою.
+ // Нижнє підкреслення дозволяє "використати" змінну, але проігнорувати значення.
+ _, _, _, _, _, _, _, _, _, _ = str, s2, g, f, u, pi, n, a5, s4, bs
+ // Зазвичай це використовується, щоб проігнорувати значення, що повертає функція.
+ // Наприклад, в скрипті нашвидкоруч можна проігнорувати помилку, яку повертає
+ // функція os.Create, вважаючи, що файл буде створений за будь-яких умов.
+ file, _ := os.Create("output.txt")
+ fmt.Fprint(file, "Приклад, як відбувається запис у файл.")
+ file.Close()
+
+ // Вивід значень змінних.
+ fmt.Println(s, c, a4, s3, d2, m)
+
+ learnFlowControl() // Рухаємось далі.
+}
+
+// Навідміну від більшості інших мов програмування, функції в Go підтримують
+// іменоване значення, що повертається.
+// Змінні, значення яких повертається функцією, вказуються із зазначенням типу при
+// оголошенні функції. Таким чином, можна з легкістю повернути їхні значення в різних
+// точках коду, не перелічуючи їх після ключового слова return.
+func learnNamedReturns(x, y int) (z int) {
+ z = x * y
+ return // z не потрібно вказувати, при оголошенні описано змінну для повернення.
+}
+
+// Go використовує сміттєзбірник. В ньому використовуються вказівники, проте немає
+// операцій з вказівниками. Можлива помилка при використовуванні вказівника nil, але не
+// при збільшенні значення вказівника (перехід по адресам пам'яті).
+func learnMemory() (p, q *int) {
+ // Іменовані змінні, що повертаються, p та q, мають тип вказівника на чисельне значення.
+ p = new(int) // Вбудована функція виділяє нову пам'ять.
+ // Виділена адреса пам'яті чисельного типу int ініціалізовується 0, p більше не nil.
+ s := make([]int, 20) // Виділити пам'ять для 20 чисел у вигляді суцільного блоку в пам'яті.
+ s[3] = 7 // Присвоїти значення одному з них.
+ r := -2 // Оголосити нову локальну змінну.
+ return &s[3], &r // Оператор & повертає адресу в пам'яті об'єкта.
+}
+
+func expensiveComputation() float64 {
+ return m.Exp(10)
+}
+
+func learnFlowControl() {
+ // if твердження вимагає фігурні дужки, але не вимагає округлих.
+ if true {
+ fmt.Println("Кажу ж")
+ }
+ // Форматування стандартизовано командою командного рядка "go fmt".
+ if false {
+ // Pout.
+ } else {
+ // Gloat.
+ }
+ // Використання перемикача (switch) замість ланцюга if-тверджень.
+ x := 42.0
+ switch x {
+ case 0:
+ case 1:
+ case 42:
+ // Кейси не "провалюються". Натомість, є ключове слово `fallthrough`:
+ // https://github.com/golang/go/wiki/Switch#fall-through (англ)
+ case 43:
+ // Недоступний.
+ default:
+ // Кейс за замовчуванням не обов'язковий.
+ }
+ // Як і if, формат оголошення циклу for не вимагає круглих дужок:
+ // Змінні, оголошені всередині if та for - належать цій області видимості.
+ for x := 0; x < 3; x++ { // ++ - це твердження.
+ fmt.Println("iteration", x)
+ }
+ // Тут x == 42.
+
+ // For - це єдиний цикл в Go, проте він має кілька різних форм.
+ for { // Ініціалізація циклу.
+ break // Упс, помилково зайшли.
+ continue // Недоступне твердження.
+ }
+
+ // Можна використовувати діапазони, зрізи, рядки, асоціативні масиви, або ж
+ // канал для ітерації в циклі. Діапазон (range) повертає один (канал) або два
+ // значення (масив, зріз, рядок та асоціативний масив).
+ for key, value := range map[string]int{"one": 1, "two": 2, "three": 3} {
+ // для кожної пари в асоціативному масиві, надрукувати ключ та значення
+ fmt.Printf("key=%s, value=%d\n", key, value)
+ }
+ // якщо потрібне тільки значення, можна застосувати нижнє підкреслення як ключ
+ for _, name := range []string{"Bob", "Bill", "Joe"} {
+ fmt.Printf("Hello, %s\n", name)
+ }
+
+ // так само, як і з циклом for, оператор := в розгалуженні означає оголосити
+ // локальну змінну в області видимості if та присвоїти значення. Далі
+ // значення змінної проходить перевірку y > x.
+ if y := expensiveComputation(); y > x {
+ x = y
+ }
+ // Літерали функцій - це замикання
+ xBig := func() bool {
+ return x > 10000 // Посилання на x, що був оголошений раніше, перед switch.
+ }
+ x = 99999
+ fmt.Println("xBig:", xBig()) // true
+ x = 1.3e3 // Тобто, тепер x == 1300
+ fmt.Println("xBig:", xBig()) // false тепер.
+
+ // Функція може бути оголошена та викликана в одному рядку, поводячи себе
+ // як аргумент функції, але за наступних умов:
+ // 1) літерал функції негайно викликається за допомогою ()
+ // 2) тип значення, що повертається, точно відповідає очікуваному типу аргументу
+ fmt.Println("Add + double two numbers: ",
+ func(a, b int) int {
+ return (a + b) * 2
+ }(10, 2)) // Викликаємо з аргументами 10 та 2
+ // => Додати + подвоїти два числа: 24
+
+ // Коли вам це знадобиться, ви полюбите це
+ goto love
+love:
+
+ learnFunctionFactory() // функція, що повертає функцію - це весело(3)(3)
+ learnDefer() // Швидкий обхід до важливого ключового слова.
+ learnInterfaces() // Тут на вас чекає крута штука!
+}
+
+func learnFunctionFactory() {
+ // Два наступних твердження роблять однакові дії, але другий приклад частіше
+ // застосовується
+ fmt.Println(sentenceFactory("summer")("A beautiful", "day!"))
+
+ d := sentenceFactory("summer")
+ fmt.Println(d("A beautiful", "day!"))
+ fmt.Println(d("A lazy", "afternoon!"))
+}
+
+// Декоратори звична річ для багатьох мов програмування. В Go їх можна реалізувати
+// за допомогою літералів функцій, що приймають аргументи.
+func sentenceFactory(mystring string) func(before, after string) string {
+ return func(before, after string) string {
+ return fmt.Sprintf("%s %s %s", before, mystring, after) // новий рядок
+ }
+}
+
+func learnDefer() (ok bool) {
+ // твердження defer змушує функцію посилатись на список. Список
+ // збережених викликів виконується ПІСЛЯ того, як оточуюча функція закінчує
+ // виконання.
+ defer fmt.Println("відкладені твердження виконуються у зворотньому порядку (LIFO).")
+ defer fmt.Println("\nЦей рядок надрукується першим, тому що")
+ // Відкладення зазвичай використовується для того, щоб закрити файл. Таким чином,
+ // функція, що закриває файл, залишається близькою до функції, що відкриває файл.
+ return true
+}
+
+// Оголошує Stringer як тип інтерфейсу з одним методом, String.
+type Stringer interface {
+ String() string
+}
+
+// Оголошує pair як структуру з двома полями, цілими числами x та y.
+type pair struct {
+ x, y int
+}
+
+// Оголошує метод для типу pair. pair тепер реалізує Stringer, оскільки pair оголосив
+// всі методи в цьому інтерфейсі.
+func (p pair) String() string { // p тепер називається "приймачем"
+ // Sprintf - ще одна функція з пакету fmt.
+ // Крапка використовується, щоб звернутись до полів об'єкту p.
+ return fmt.Sprintf("(%d, %d)", p.x, p.y)
+}
+
+func learnInterfaces() {
+ // Синтаксис з використанням фігурних дужок називається "літералом структури".
+ // Він застосовується до ініціалізованої структури. Оператор := оголошує
+ // та ініціалізує p цією структурою.
+ p := pair{3, 4}
+ fmt.Println(p.String()) // Викликає метод String об'єкта p типу pair.
+ var i Stringer // Оголошує і інтерфейсного типу Stringer.
+ i = p // Допустиме, оскільки pair реалізує Stringer
+ // Викликає метод String об'єкта і, що має тип Stringer. Виводить те ж саме, що й
+ // аналогічний метод вище.
+ fmt.Println(i.String())
+
+ // Функції з бібліотеки fmt викликають метод String, щоб запросити у об'єкта
+ // своє представлення, яке можна надрукувати.
+ fmt.Println(p) // Виводить те ж саме, що й раніше.
+ fmt.Println(i) // Виводить те ж саме, що й раніше.
+
+ learnVariadicParams("great", "learning", "here!")
+}
+
+// Кількість аргументів функції може бути змінною.
+func learnVariadicParams(myStrings ...interface{}) {
+ // Пройтись по значенням всіх аргументів.
+ // _ - це ігнорування порядкового номеру аргумента в масиві.
+ for _, param := range myStrings {
+ fmt.Println("param:", param)
+ }
+
+ // Передати значення аргументів як параметр змінної величини.
+ fmt.Println("params:", fmt.Sprintln(myStrings...))
+
+ learnErrorHandling()
+}
+
+func learnErrorHandling() {
+ // Ідіома ", ok"використовується, щоб перевірити виконання команди без помилок.
+ m := map[int]string{3: "three", 4: "four"}
+ if x, ok := m[1]; !ok { // ok буде мати значення false, тому що 1 не знаходиться
+ // в асоціативному масиві.
+ fmt.Println("немає таких")
+ } else {
+ fmt.Print(x) // x буде мати значення 1, якщо 1 знаходиться в m.
+ }
+ // Значення помилки повідомляє не тільки, що все добре, але й може розповісти
+ // більше про проблему.
+ if _, err := strconv.Atoi("non-int"); err != nil { // _ ігнорує значення
+ // виводить помилку 'strconv.ParseInt: parsing "non-int": invalid syntax'
+ fmt.Println(err)
+ }
+ // Ми розглянемо інтерфейси дещо пізніше. А поки, розглянемо багатопоточність.
+ learnConcurrency()
+}
+
+// Канал с - це потокозохищений об'єкт для спілкування між потоками.
+func inc(i int, c chan int) {
+ c <- i + 1 // Оператор <- виконує операцію "надіслати",якщо змінна каналу
+ // знаходиться зліва від нього.
+}
+
+// inc виконує збільшення значення на 1. Ми використаємо його, щоб збільшувати
+// числа рівночасно.
+func learnConcurrency() {
+ // вже знайома функція make, яка раніше використовувалась для виділення пам'яті,
+ // тут використовується для створення каналу. Make виділяє пам'ять та ініціалізує
+ // зрізи, асоційовані масиви та канали. Новостворений канал буде передавати
+ // цілочисельні значення.
+ c := make(chan int)
+ // Запустити три одночасні ґорутини. Числа будуть збільшуватись рівночасно, імовірно
+ // паралельно якщо пристрій здатний до цього та правильно сконфігурований.
+ // Всі три ґорутини надсилають значення в один канал.
+ go inc(0, c) // Твердження go запускає нову ґорутину.
+ go inc(10, c)
+ go inc(-805, c)
+ // Читаємо три результати з каналу та друкуємо їх.
+ // Порядок результатів - невідомий!
+ fmt.Println(<-c, <-c, <-c) // якщо канал знаходиться справа від оператора <-,
+ // він виконує функцію "приймача".
+
+ cs := make(chan string) // Ще один канал, який примає рядки.
+ ccs := make(chan chan string) // Канал каналів рядків.
+ go func() { c <- 84 }() // Запустимо нову ґорутину, щоб надіслати значення в канал с.
+ go func() { cs <- "wordy" }() // Надсилаємо "wordy" в канал cs.
+ // Ключове слово select має синтаксис, подібний до switch, проте кожен кейс
+ // включає в себе операцію з каналом. Він обирає довільний кейс з наявних, які готові
+ // комунікувати (передавати дані).
+ select {
+ case i := <-c: // Отримане значення може бути присвоєно змінній,
+ fmt.Printf("it's a %T", i)
+ case <-cs: // або значення може бути проігнороване.
+ fmt.Println("it's a string")
+ case <-ccs: // Пустий канал, не готовий комунікувати.
+ fmt.Println("Не відбудеться.")
+ }
+ // На цьому етапі, значення було прочитане або з с або з cs. Одна з двох
+ // ґорутин завершилась, але інша все ще заблокована.
+
+ learnWebProgramming() // Go вміє й у веб. Так, ти хочеш зробити це.
+}
+
+// Лиш одна функція з пакету http запускає веб сервер.
+func learnWebProgramming() {
+
+ // перший аргумент ListenAndServe - це TCP адреса, який сервер буде слухати.
+ // Другий аргумент - це інтерфейс, а точніше http.Handler.
+ go func() {
+ err := http.ListenAndServe(":8080", pair{})
+ fmt.Println(err) // не ігноруйте помилки
+ }()
+
+ requestServer()
+}
+
+// pair матиме тип http.Handler, якщо реалізувати один його метод, ServeHTTP.
+func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // Відповідати на запити можна методом, що належить http.ResponseWriter.
+ w.Write([]byte("Ти вивчив Go за Y хвилин!"))
+}
+
+func requestServer() {
+ resp, err := http.Get("http://localhost:8080")
+ fmt.Println(err)
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ fmt.Printf("\nWebserver said: `%s`", string(body))
+}
+```
+
+## Подальше вивчення
+
+Основним джерелом всієї інформації про Go залишається [офіційна веб-сторінка](http://golang.org/). Там можна знайти уроки, інтерактивно пограти та багато про що почитати.
+Окрім туру, у [документації](https://golang.org/doc/) міститься інформація як писати чистий та ефективний код на Go, документація пакетів та окремих команд, а також історія релізів.
+
+Надзвичайно рекомендується ознайомитись із визначенням мови. Вона легко читається та на диво коротка (в порівнянні з іншими сучасними мовами).
+
+Можна погратись з кодом вище на [Go playground](https://play.golang.org/p/tnWMjr16Mm). Спробуй змінити його та запустити із свого браузера. Поміть, що можна використовувати [https://play.golang.org](https://play.golang.org) як [REPL](https://uk.wikipedia.org/wiki/REPL) до тестів та коду в твоєму браузері, без встановлення Go.
+
+В списку для прочитання новачкам в Go - [вихідний код стандартної бібліотеки](http://golang.org/src/pkg/). Код всеосяжно задокоментований, тому є найкращим прикладом з боку зручного для прочитання та швидкості розуміння коду на цій мові програмування. Приведений стиль та ідіоми Go.
+Крім того, можна просто натиснути на назву функції в [документації](http://golang.org/pkg/), щоб перейти до її реалізації.
+
+Іншим прекрасним посиланням для вивчення Go є [Go by example](https://gobyexample.com/).
+
+Go Mobile додає підтримку мобільних платформ (Android та iOS). Можна написати нативний код на Go для мобільних застосунків або написати бібліотеку, що міститиме прив'язки (bindings) з пакету Go, які можуть бути викликані з Java (Android) та Objective-C (iOS). Деталі можна дізнатись на [веб-сторінці Go Mobile](https://github.com/golang/go/wiki/Mobile).
diff --git a/uk-ua/kotlin-ua.html.markdown b/uk-ua/kotlin-ua.html.markdown
new file mode 100644
index 00000000..5e79cc48
--- /dev/null
+++ b/uk-ua/kotlin-ua.html.markdown
@@ -0,0 +1,464 @@
+---
+language: kotlin
+filename: LearnKotlin-uk.kt
+lang: uk-ua
+contributors:
+ - ["S Webber", "https://github.com/s-webber"]
+translators:
+ - ["AstiaSun", "https://github.com/AstiaSun"]
+---
+
+Kotlin - це мова програмування зі статичною типізацією для JVM, Android та браузера.
+Вона має 100% сумісність із Java.
+
+[Детальніше](https://kotlinlang.org/)
+
+```kotlin
+// Однорядкові коментарі починаються з //
+/*
+Такий вигляд мають багаторядкові коментарі
+*/
+
+// Ключове слово package працює так само, як і в Java.
+package com.learnxinyminutes.kotlin
+
+/*
+Точкою входу для програм на Kotlin є функція під назвою main.
+Вона приймає масив із аргументів, що були передані через командний рядок.
+Починаючи з Kotlin 1.3, функція main може бути оголошена без параметрів взагалі.
+*/
+fun main(args: Array<String>) {
+ /*
+ Оголошення змінних відбувається за допомогою ключових слів var або val.
+ Відмінність між ними полягає в тому, що значення змінних, оголошених через
+ val, не можна змінювати. Водночас, змінній "var" можна переприсвоїти нове
+ значення в подальшому.
+ */
+ val fooVal = 10 // більше ми не можемо змінити значення fooVal на інше
+ var fooVar = 10
+ fooVar = 20 // fooVar може змінювати значення
+
+ /*
+ В більшості випадків Kotlin може визначати, якого типу змінна, тому не
+ потрібно щоразу точно вказувати її тип.
+ Тип змінної вказується наступним чином:
+ */
+ val foo: Int = 7
+
+ /*
+ Рядки мають аналогічне з Java представлення. Спеціальні символи
+ позначаються за допомогою зворотнього слеша.
+ */
+ val fooString = "My String Is Here!"
+ val barString = "Printing on a new line?\nNo Problem!"
+ val bazString = "Do you want to add a tab?\tNo Problem!"
+ println(fooString)
+ println(barString)
+ println(bazString)
+
+ /*
+ Необроблений рядок розмежовується за допомогою потрійних лапок (""").
+ Необроблені рядки можуть містити переніс рядка (не спеціальний символ \n) та
+ будь-які інші символи.
+ */
+ val fooRawString = """
+fun helloWorld(val name : String) {
+ println("Hello, world!")
+}
+"""
+ println(fooRawString)
+
+ /*
+ Рядки можуть містити шаблонні вирази.
+ Шаблонний вираз починається із символа доллара "$".
+ */
+ val fooTemplateString = "$fooString has ${fooString.length} characters"
+ println(fooTemplateString) // => My String Is Here! has 18 characters
+
+ /*
+ Щоб змінна могла мати значення null, потрібно це додатково вказати.
+ Для цього після оголошеного типу змінної додається спеціальний символ "?".
+ Отримати значення такої змінної можна використавши оператор "?.".
+ Оператор "?:" застосовується, щоб оголосити альтернативне значення змінної
+ у випадку, якщо вона буде рівна null.
+ */
+ var fooNullable: String? = "abc"
+ println(fooNullable?.length) // => 3
+ println(fooNullable?.length ?: -1) // => 3
+ fooNullable = null
+ println(fooNullable?.length) // => null
+ println(fooNullable?.length ?: -1) // => -1
+
+ /*
+ Функції оголошуються з використанням ключового слова fun.
+ Аргументи функції перелічуються у круглих дужках після назви функції.
+ Аргументи можуть мати значення за замовчуванням. Тип значення, що повертатиметься
+ функцією, вказується після оголошення аргументів за необхідністю.
+ */
+ fun hello(name: String = "world"): String {
+ return "Hello, $name!"
+ }
+ println(hello("foo")) // => Hello, foo!
+ println(hello(name = "bar")) // => Hello, bar!
+ println(hello()) // => Hello, world!
+
+ /*
+ Аргументи функції можуть бути помічені ключовим словом vararg. Це дозволяє
+ приймати довільну кількість аргументів функції зазначеного типу.
+ */
+ fun varargExample(vararg names: Int) {
+ println("Argument has ${names.size} elements")
+ }
+ varargExample() // => Argument has 0 elements
+ varargExample(1) // => Argument has 1 elements
+ varargExample(1, 2, 3) // => Argument has 3 elements
+
+ /*
+ Коли функція складається з одного виразу, фігурні дужки не є обов'язковими.
+ Тіло функції вказується після оператора "=".
+ */
+ fun odd(x: Int): Boolean = x % 2 == 1
+ println(odd(6)) // => false
+ println(odd(7)) // => true
+
+ // Якщо тип значення, що повертається функцією, може бути однозначно визначено,
+ // його непотрібно вказувати.
+ fun even(x: Int) = x % 2 == 0
+ println(even(6)) // => true
+ println(even(7)) // => false
+
+ // Функції можуть приймати інші функції як аргументи, а також повертати інші функції.
+ fun not(f: (Int) -> Boolean): (Int) -> Boolean {
+ return {n -> !f.invoke(n)}
+ }
+ // Іменовані функції можуть бути вказані як аргументи за допомогою оператора "::".
+ val notOdd = not(::odd)
+ val notEven = not(::even)
+ // Лямбда-вирази також можуть бути аргументами функції.
+ val notZero = not {n -> n == 0}
+ /*
+ Якщо лямбда-вираз приймає лише один параметр, його оголошення може бути пропущене
+ (разом із ->). Всередині виразу до цього параметра можна звернутись через
+ змінну "it".
+ */
+ val notPositive = not {it > 0}
+ for (i in 0..4) {
+ println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}")
+ }
+
+ // Ключове слово class використовується для оголошення класів.
+ class ExampleClass(val x: Int) {
+ fun memberFunction(y: Int): Int {
+ return x + y
+ }
+
+ infix fun infixMemberFunction(y: Int): Int {
+ return x * y
+ }
+ }
+ /*
+ Щоб створити новий об'єкт, потрібно викликати конструктор класу.
+ Зазначте, що в Kotlin немає ключового слова new.
+ */
+ val fooExampleClass = ExampleClass(7)
+ // Методи класу викликаються через крапку.
+ println(fooExampleClass.memberFunction(4)) // => 11
+ /*
+ Якщо функція була позначена ключовим словом infix, тоді її можна викликати через
+ інфіксну нотацію.
+ */
+ println(fooExampleClass infixMemberFunction 4) // => 28
+
+ /*
+ Класи даних - це лаконічний спосіб створювати класи, що містимуть тільки дані.
+ Методи "hashCode"/"equals" та "toString" автоматично генеруються.
+ */
+ data class DataClassExample (val x: Int, val y: Int, val z: Int)
+ val fooData = DataClassExample(1, 2, 4)
+ println(fooData) // => DataClassExample(x=1, y=2, z=4)
+
+ // Класи даних також мають функцію "copy".
+ val fooCopy = fooData.copy(y = 100)
+ println(fooCopy) // => DataClassExample(x=1, y=100, z=4)
+
+ // Об'єкти можуть бути деструктурувані кількома способами.
+ val (a, b, c) = fooCopy
+ println("$a $b $c") // => 1 100 4
+
+ // деструктурування у циклі for
+ for ((a, b, c) in listOf(fooData)) {
+ println("$a $b $c") // => 1 100 4
+ }
+
+ val mapData = mapOf("a" to 1, "b" to 2)
+ // Map.Entry також деструктурувуються
+ for ((key, value) in mapData) {
+ println("$key -> $value")
+ }
+
+ // Функція із "with" працює майже так само як це ж твердження у JavaScript.
+ data class MutableDataClassExample (var x: Int, var y: Int, var z: Int)
+ val fooMutableData = MutableDataClassExample(7, 4, 9)
+ with (fooMutableData) {
+ x -= 2
+ y += 2
+ z--
+ }
+ println(fooMutableData) // => MutableDataClassExample(x=5, y=6, z=8)
+
+ /*
+ Список можна створити використовуючи функцію listOf.
+ Список буде незмінним, тобто елементи не можна буде додавати або видаляти.
+ */
+ val fooList = listOf("a", "b", "c")
+ println(fooList.size) // => 3
+ println(fooList.first()) // => a
+ println(fooList.last()) // => c
+ // доступ до елементів здійснюється через їхні порядковий номер.
+ println(fooList[1]) // => b
+
+ // Змінні списки можна створити використовуючи функцію mutableListOf.
+ val fooMutableList = mutableListOf("a", "b", "c")
+ fooMutableList.add("d")
+ println(fooMutableList.last()) // => d
+ println(fooMutableList.size) // => 4
+
+ // Функція setOf створює об'єкт типу множина.
+ val fooSet = setOf("a", "b", "c")
+ println(fooSet.contains("a")) // => true
+ println(fooSet.contains("z")) // => false
+
+ // mapOf створює асоціативний масив.
+ val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9)
+ // Доступ до значень в асоціативних масивах здійснюється через їхні ключі.
+ println(fooMap["a"]) // => 8
+
+ /*
+ Послідовності представлені як колекції лінивих обчислень. Функція generateSequence
+ створює послідовність.
+ */
+ val fooSequence = generateSequence(1, { it + 1 })
+ val x = fooSequence.take(10).toList()
+ println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+ // Приклад використання послідовностей, генерація чисел Фібоначчі:
+ fun fibonacciSequence(): Sequence<Long> {
+ var a = 0L
+ var b = 1L
+
+ fun next(): Long {
+ val result = a + b
+ a = b
+ b = result
+ return a
+ }
+
+ return generateSequence(::next)
+ }
+ val y = fibonacciSequence().take(10).toList()
+ println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
+
+ // Kotlin має функції вищого порядку для роботи з колекціями.
+ val z = (1..9).map {it * 3}
+ .filter {it < 20}
+ .groupBy {it % 2 == 0}
+ .mapKeys {if (it.key) "even" else "odd"}
+ println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]}
+
+ // Цикл for може використовуватись з будь-чим, що має ітератор.
+ for (c in "hello") {
+ println(c)
+ }
+
+ // Принцип роботи циклів "while" не відрізняється від інших мов програмування.
+ var ctr = 0
+ while (ctr < 5) {
+ println(ctr)
+ ctr++
+ }
+ do {
+ println(ctr)
+ ctr++
+ } while (ctr < 10)
+
+ /*
+ if може бути використаний як вираз, що повертає значення. Тому тернарний
+ оператор ?: не потрібний в Kotlin.
+ */
+ val num = 5
+ val message = if (num % 2 == 0) "even" else "odd"
+ println("$num is $message") // => 5 is odd
+
+ // "when" використовується як альтернатива ланцюгам "if-else if".
+ val i = 10
+ when {
+ i < 7 -> println("first block")
+ fooString.startsWith("hello") -> println("second block")
+ else -> println("else block")
+ }
+
+ // "when" може приймати аргумент.
+ when (i) {
+ 0, 21 -> println("0 or 21")
+ in 1..20 -> println("in the range 1 to 20")
+ else -> println("none of the above")
+ }
+
+ // "when" також може використовуватись як функція, що повертає значення.
+ var result = when (i) {
+ 0, 21 -> "0 or 21"
+ in 1..20 -> "in the range 1 to 20"
+ else -> "none of the above"
+ }
+ println(result)
+
+ /*
+ Тип об'єкта можна перевірити використавши оператор is. Якщо перевірка проходить
+ успішно, тоді можна використовувати об'єкт як данний тип не приводячи до нього
+ додатково.
+ */
+ fun smartCastExample(x: Any) : Boolean {
+ if (x is Boolean) {
+ // x тепер має тип Boolean
+ return x
+ } else if (x is Int) {
+ // x тепер має тип Int
+ return x > 0
+ } else if (x is String) {
+ // x тепер має тип String
+ return x.isNotEmpty()
+ } else {
+ return false
+ }
+ }
+ println(smartCastExample("Hello, world!")) // => true
+ println(smartCastExample("")) // => false
+ println(smartCastExample(5)) // => true
+ println(smartCastExample(0)) // => false
+ println(smartCastExample(true)) // => true
+
+ // Smartcast (розумне приведення) також працює з блоком when
+ fun smartCastWhenExample(x: Any) = when (x) {
+ is Boolean -> x
+ is Int -> x > 0
+ is String -> x.isNotEmpty()
+ else -> false
+ }
+
+ /*
+ Розширення - це ще один спосіб розширити функціонал класу.
+ Подібні методи розширення реалізовані у С#.
+ */
+ fun String.remove(c: Char): String {
+ return this.filter {it != c}
+ }
+ println("Hello, world!".remove('l')) // => Heo, word!
+}
+
+// Класи перелічення також подібні до тих типів, що і в Java.
+enum class EnumExample {
+ A, B, C // Константи перелічення розділені комами.
+}
+fun printEnum() = println(EnumExample.A) // => A
+
+// Оскільки кожне перелічення - це об'єкт класу enum, воно може бути
+// проініціалізоване наступним чином:
+enum class EnumExample(val value: Int) {
+ A(value = 1),
+ B(value = 2),
+ C(value = 3)
+}
+fun printProperty() = println(EnumExample.A.value) // => 1
+
+// Кожне перелічення має властивості, які дозволяють отримати його ім'я
+// та порядок (позицію) в класі enum:
+fun printName() = println(EnumExample.A.name) // => A
+fun printPosition() = println(EnumExample.A.ordinal) // => 0
+
+/*
+Ключове слово object можна використати для створення об'єкту сінглтону. Об'єкт не
+можна інстанціювати, проте на його унікальний екземпляр можна посилатись за іменем.
+Подібна можливість є в сінглтон об'єктах у Scala.
+*/
+object ObjectExample {
+ fun hello(): String {
+ return "hello"
+ }
+
+ override fun toString(): String {
+ return "Hello, it's me, ${ObjectExample::class.simpleName}"
+ }
+}
+
+
+fun useSingletonObject() {
+ println(ObjectExample.hello()) // => hello
+ // В Kotlin, "Any" - це корінь ієрархії класів, так само, як і "Object" у Java.
+ val someRef: Any = ObjectExample
+ println(someRef) // => Hello, it's me, ObjectExample
+}
+
+
+/*
+Оператор перевірки на те, що об'єкт не рівний null, (!!) перетворює будь-яке значення в ненульовий тип і кидає виняток, якщо значення рівне null.
+*/
+var b: String? = "abc"
+val l = b!!.length
+
+// Далі - приклади перевизначення методів класу Any в класі-насліднику
+data class Counter(var value: Int) {
+ // перевизначити Counter += Int
+ operator fun plusAssign(increment: Int) {
+ this.value += increment
+ }
+
+ // перевизначити Counter++ та ++Counter
+ operator fun inc() = Counter(value + 1)
+
+ // перевизначити Counter + Counter
+ operator fun plus(other: Counter) = Counter(this.value + other.value)
+
+ // перевизначити Counter * Counter
+ operator fun times(other: Counter) = Counter(this.value * other.value)
+
+ // перевизначити Counter * Int
+ operator fun times(value: Int) = Counter(this.value * value)
+
+ // перевизначити Counter in Counter
+ operator fun contains(other: Counter) = other.value == this.value
+
+ // перевизначити Counter[Int] = Int
+ operator fun set(index: Int, value: Int) {
+ this.value = index + value
+ }
+
+ // перевизначити виклик екземпляру Counter
+ operator fun invoke() = println("The value of the counter is $value")
+
+}
+// Можна також перевизначити оператори через методи розширення.
+// перевизначити -Counter
+operator fun Counter.unaryMinus() = Counter(-this.value)
+
+fun operatorOverloadingDemo() {
+ var counter1 = Counter(0)
+ var counter2 = Counter(5)
+ counter1 += 7
+ println(counter1) // => Counter(value=7)
+ println(counter1 + counter2) // => Counter(value=12)
+ println(counter1 * counter2) // => Counter(value=35)
+ println(counter2 * 2) // => Counter(value=10)
+ println(counter1 in Counter(5)) // => false
+ println(counter1 in Counter(7)) // => true
+ counter1[26] = 10
+ println(counter1) // => Counter(value=36)
+ counter1() // => The value of the counter is 36
+ println(-counter2) // => Counter(value=-5)
+}
+```
+
+### Подальше вивчення
+
+* [Уроки Kotlin](https://kotlinlang.org/docs/tutorials/)
+* [Спробувати попрацювати з Kotlin в браузері](https://play.kotlinlang.org/)
+* [Список корисних посилань](http://kotlin.link/)
diff --git a/uk-ua/mips-ua.html.markdown b/uk-ua/mips-ua.html.markdown
new file mode 100644
index 00000000..8d4517fe
--- /dev/null
+++ b/uk-ua/mips-ua.html.markdown
@@ -0,0 +1,366 @@
+---
+language: "MIPS Assembly"
+filename: MIPS.asm
+contributors:
+ - ["Stanley Lim", "https://github.com/Spiderpig86"]
+translators:
+ - ["AstiaSun", "https://github.com/AstiaSun"]
+lang: uk-ua
+---
+
+Мова ассемблера MIPS (англ. Microprocessor without Interlocked Pipeline Stages) була написана для роботи з мікропроцесорами MIPS, парадигма яких була описана в 1981 році [Джоном Геннессі](https://uk.wikipedia.org/wiki/Джон_Лерой_Геннессі). Ці RISC процесори використовуються у таких вбудованих системах, як маршрутизатори та мережеві шлюзи.
+
+[Детальніше](https://en.wikipedia.org/wiki/MIPS_architecture)
+
+```asm
+# Коментарі позначені як'#'
+
+# Всі символи після '#' ігноруються лексичним аналізатором асемблера.
+
+# Зазвичай програми поділяються на .data та .text частини
+
+.data # У цьому розділі дані зберігаються у пам'яті, виділеній в RAM, подібно до змінних
+ # в мовах програмування вищого рівня
+
+ # Змінна оголошується наступним чином: [назва]: .[тип] [значення]
+ # Наприклад:
+ hello_world: .asciiz "Hello World\n" # Оголосити текстову змінну
+ num1: .word 42 # word - це чисельний тип 32-бітного розряду
+
+ arr1: .word 1, 2, 3, 4, 5 # Масив чисел
+ arr2: .byte 'a', 'b' # Масив буквених символів (розмір кожного - 1 байт)
+ buffer: .space 60 # Виділити місце в RAM
+ # (не очищується, тобто не заповнюється 0)
+
+ # Розміри типів даних
+ _byte: .byte 'a' # 1 байт
+ _halfword: .half 53 # 2 байти
+ _word: .word 3 # 4 байти
+ _float: .float 3.14 # 4 байти
+ _double: .double 7.0 # 8 байтів
+
+ .align 2 # Вирівнювання пам'яті даних, де число
+ # показує кількість байтів, вирівнених
+ # у степені 2. (.align 2 означає
+ # чисельне (word) вирівнювання оскільки
+ # 2^2 = 4 байти)
+
+.text # Розділ, що містить інструкції та
+ # логіку програми
+
+.globl _main # Оголошує назву інструкції як
+ # глобальну, тобто, яка є доступною для
+ # всіх інших файлів
+
+ _main: # програми MIPS виконують інструкції
+ # послідовно, тобто першочергово код
+ # буде виконуватись після цієї позначки
+
+ # Виведемо на екран "hello world"
+ la $a0, hello_world # Завантажує адресу тексту у пам'яті
+ li $v0, 4 # Завантажує значення системної
+ # команди (вказуючи тип функціоналу)
+ syscall # Виконує зазначену системну команду
+ # з обраним аргументом ($a0)
+
+ # Регістри (використовуються, щоб тримати дані протягом виконання програми)
+ # $t0 - $t9 # Тимчасові регістри використовуються
+ # для проміжних обчислень всередині
+ # підпрограм (не зберігаються між
+ # викликами функцій)
+
+ # $s0 - $s7 # Збережені регістри, у яких значення
+ # зберігаються між викликами підпрограм.
+ # Зазвичай зберігаються у стеку.
+
+ # $a0 - $a3 # Регістри для передачі аргументів для
+ # підпрограм
+ # $v0 - $v1 # Регістри для значень, що повертаються
+ # від викликаної функції
+
+ # Типи інструкції завантаження / збереження
+ la $t0, label # Скопіювати адресу в пам'яті, де
+ # зберігається значення змінної label
+ # в регістр $t0
+ lw $t0, label # Скопіювати чисельне значення з пам'яті
+ lw $t1, 4($s0) # Скопіювати чисельне значення з адреси
+ # пам'яті регістра зі зміщенням в
+ # 4 байти (адреса + 4)
+ lb $t2, label # Скопіювати буквений символ в частину
+ # нижчого порядку регістра $t2
+ lb $t2, 0($s0) # Скопіювати буквений символ з адреси
+ # в $s0 із зсувом 0
+ # Подібне використання і 'lh' для halfwords
+
+ sw $t0, label # Зберегти чисельне значення в адресу в
+ # пам'яті, що відповідає змінній label
+ sw $t0, 8($s0) # Зберегти чисельне значення в адресу,
+ # що зазначена у $s0, та зі зсувом у 8 байтів
+ # Така ж ідея використання 'sb' та 'sh' для буквених символів та halfwords.
+ # 'sa' не існує
+
+
+### Математичні операції ###
+ _math:
+ # Пам'ятаємо, що попередньо потрібно завантажити дані в пам'ять
+ lw $t0, num # Із розділа з даними
+ li $t0, 5 # Або безпосередньо з константи
+ li $t1, 6
+ add $t2, $t0, $t1 # $t2 = $t0 + $t1
+ sub $t2, $t0, $t1 # $t2 = $t0 - $t1
+ mul $t2, $t0, $t1 # $t2 = $t0 * $t1
+ div $t2, $t0, $t1 # $t2 = $t0 / $t1 (Може не підтримуватись
+ # деякими версіями MARS)
+ div $t0, $t1 # Виконує $t0 / $t1. Отримати частку можна
+ # за допомогою команди 'mflo', остаток - 'mfhi'
+
+ # Бітовий зсув
+ sll $t0, $t0, 2 # Побітовий зсув вліво на 2. Біти вищого порядку
+ # не зберігаються, нищого - заповнюються 0
+ sllv $t0, $t1, $t2 # Зсув вліво зі змінною кількістю у
+ # регістрі
+ srl $t0, $t0, 5 # Побітовий зсув вправо на 5 (не зберігає
+ # біти, біти зліва заповнюються 0)
+ srlv $t0, $t1, $t2 # Зсув вправо зі змінною кількістю у
+ # регістрі
+ sra $t0, $t0, 7 # Побітовий арифметичний зсув вправо
+ # (зберігає біти)
+ srav $t0, $t1, $t2 # Зсув вправо зі змінною кількістю у
+ # регістрі зі збереження значеннь бітів
+
+ # Побітові операції
+ and $t0, $t1, $t2 # Побітове І (AND)
+ andi $t0, $t1, 0xFFF # Побітове І з безпосереднім значенням
+ or $t0, $t1, $t2 # Побітове АБО (OR)
+ ori $t0, $t1, 0xFFF # Побітове АБО з безпосереднім значенням
+ xor $t0, $t1, $t2 # Побітова виключна диз'юнкція (XOR)
+ xori $t0, $t1, 0xFFF # Побітове XOR з безпосереднім значенням
+ nor $t0, $t1, $t2 # Побітова стрілка Пірса (NOR)
+
+## Розгалуження ##
+ _branching:
+ # В основному інструкції розгалуження мають наступну форму:
+ # <instr> <reg1> <reg2> <label>
+ # де label - це назва змінної, в яку ми хочемо перейти, якщо зазначене твердження
+ # правдиве
+
+ beq $t0, $t1, reg_eq # Перейдемо у розгалуження reg_eq
+ # якщо $t0 == $t1, інакше -
+ # виконати наступний рядок
+ bne $t0, $t1, reg_neq # Розгалужується, якщо $t0 != $t1
+ b branch_target # Розгалуження без умови завжди виконується
+ beqz $t0, req_eq_zero # Розгалужується, якщо $t0 == 0
+ bnez $t0, req_neq_zero # Розгалужується, якщо $t0 != 0
+ bgt $t0, $t1, t0_gt_t1 # Розгалужується, якщо $t0 > $t1
+ bge $t0, $t1, t0_gte_t1 # Розгалужується, якщо $t0 >= $t1
+ bgtz $t0, t0_gt0 # Розгалужується, якщо $t0 > 0
+ blt $t0, $t1, t0_gt_t1 # Розгалужується, якщо $t0 < $t1
+ ble $t0, $t1, t0_gte_t1 # Розгалужується, якщо $t0 <= $t1
+ bltz $t0, t0_lt0 # Розгалужується, якщо $t0 < 0
+ slt $s0, $t0, $t1 # Інструкція, що посилає сигнал коли
+ # $t0 < $t1, результат зберігається в $s0
+ # (1 - правдиве твердження)
+
+ # Просте твердження якщо (if)
+ # if (i == j)
+ # f = g + h;
+ # f = f - i;
+
+ # Нехай $s0 = f, $s1 = g, $s2 = h, $s3 = i, $s4 = j
+ bne $s3, $s4, L1 # if (i !=j)
+ add $s0, $s1, $s2 # f = g + h
+
+ L1:
+ sub $s0, $s0, $s3 # f = f - i
+
+ # Нижче наведений приклад знаходження максимального значення з 3 чисел
+ # Пряма трансляція в Java з логіки MIPS:
+ # if (a > b)
+ # if (a > c)
+ # max = a;
+ # else
+ # max = c;
+ # else
+ # max = b;
+ # else
+ # max = c;
+
+ # Нехай $s0 = a, $s1 = b, $s2 = c, $v0 = повернути регістр
+ ble $s0, $s1, a_LTE_b # якщо (a <= b) розгалуження(a_LTE_b)
+ ble $s0, $s2, max_C # якщо (a > b && a <=c) розгалуження(max_C)
+ move $v0, $s1 # інакше [a > b && a > c] max = a
+ j done # Перейти в кінець програми
+
+ a_LTE_b: # Мітка розгалуження, коли a <= b
+ ble $s1, $s2, max_C # якщо (a <= b && b <= c) розгалуження(max_C)
+ move $v0, $s1 # якщо (a <= b && b > c) max = b
+ j done # Перейти в кінець програми
+
+ max_C:
+ move $v0, $s2 # max = c
+
+ done: # Кінець програми
+
+## Цикли ##
+ _loops:
+ # Цикл складається з умови виходу та з інструкції переходу після його завершення
+ li $t0, 0
+ while:
+ bgt $t0, 10, end_while # Коли $t0 менше 10, продовжувати ітерації
+ addi $t0, $t0, 1 # Збільшити значення
+ j while # Перейти на початок циклу
+ end_while:
+
+ # Транспонування 2D матриці
+ # Припустимо, що $a0 зберігає адресу цілочисельної матриці розмірністю 3 x 3
+ li $t0, 0 # Лічильник для i
+ li $t1, 0 # Лічильник для j
+ matrix_row:
+ bgt $t0, 3, matrix_row_end
+
+ matrix_col:
+ bgt $t1, 3, matrix_col_end
+
+ # ...
+
+ addi $t1, $t1, 1 # Збільшити лічильник стовпця (col)
+ matrix_col_end:
+
+ # ...
+
+ addi $t0, $t0, 1
+ matrix_row_end:
+
+## Функції ##
+ _functions:
+ # Функції - це процедури, що викликаються, приймають аргументи та повертають значення
+
+ main: # Програма починається з головної функції
+ jal return_1 # jal збереже поточний ПЦ (програмний центр) в $ra,
+ # а потім перейде до return_1
+
+ # Як передати аргументи?
+ # По-перше, ми маємо передати значення аргументів у регістри аргументів
+ li $a0, 1
+ li $a1, 2
+ jal sum # Тепер ми можемо викликати функцію
+
+ # Як щодо рекурсії?
+ # Тут потрібно дещо більше роботи оскільки ми маємо впевнитись, що ми збережемо
+ # та зчитаємо попередній ПЦ в $ra, оскільки jal автоматично перепише її при виклику
+ li $a0, 3
+ jal fact
+
+ li $v0, 10
+ syscall
+
+ # Ця функція повертає 1
+ return_1:
+ li $v0, 1 # Завантажити val в регіст $v0
+ jr $ra # Повернутись до попереднього ПЦ і продовжити виконання
+
+
+ # Функція з двома аргументами
+ sum:
+ add $v0, $a0, $a1
+ jr $ra # Повернутись
+
+ # Рекурсивна функція, яка знаходить факторіал
+ fact:
+ addi $sp, $sp, -8 # Виділити місце в стеку
+ sw $s0, ($sp) # Зберегти регістр, що містить поточне число
+ sw $ra, 4($sp) # Зберегти попередній ПЦ
+
+ li $v0, 1 # Проініціалізувати значення, що повертатиметься
+ beq $a0, 0, fact_done # Закінчити, якщо параметр 0
+
+ # Інакше, продовжити рекурсію
+ move $s0, $a0 # Скопіювати $a0 в $s0
+ sub $a0, $a0, 1
+ jal fact
+
+ mul $v0, $s0, $v0 # Множення
+
+ fact_done:
+ lw $s0, ($sp)
+ lw $ra, ($sp) # Відновити ПЦ
+ addi $sp, $sp, 8
+
+ jr $ra
+
+## Макроси ##
+ _macros:
+ # Макроси надзвичайно корисні для заміни блоків коду, що повторюються, за допомогою
+ # однієї змінної, для покращення читабельності
+ # Це не заміна функцій.
+ # Вони мають бути оголошені перед використанням
+
+ # Макрос для виведення нових рядків (оскільки операція досить часто виконується)
+ .macro println()
+ la $a0, newline # Значення нового рядка зберігатиметься тут
+ li $v0, 4
+ syscall
+ .end_macro
+
+ println() # Асемблер скопіює цей блок коду сюди
+ # перед тим, як виконувати його
+
+ # Можна передавати параметри у макроси.
+ # Параметри позначаються знаком '%' з довільною назвою
+ .macro print_int(%num)
+ li $v0, 1
+ lw $a0, %num
+ syscall
+ .end_macro
+
+ li $t0, 1
+ print_int($t0)
+
+ # Значення також можна передавати безпосередньо в макроси
+ .macro immediates(%a, %b)
+ add $t0, %a, %b
+ .end_macro
+
+ immediates(3, 5)
+
+ # Одночасно із назвами змінних
+ .macro print(%string)
+ la $a0, %string
+ li $v0, 4
+ syscall
+ .end_macro
+
+ print(hello_world)
+
+## Масиви ##
+.data
+ list: .word 3, 0, 1, 2, 6 # Це масив чисел
+ char_arr: .asciiz "hello" # Це текстовий масив
+ buffer: .space 128 # Виділяє блок пам'яті, що
+ # автоматично не очищується
+ # Ці блоки пам'яті вирівнені
+ # вирівнені поруч один з одним
+
+.text
+ la $s0, list # Завантажити адресу списку
+ li $t0, 0 # Лічильник
+ li $t1, 5 # Довжина списку
+
+ loop:
+ bgt $t0, $t1, end_loop
+
+ lw $a0, ($s0)
+ li $v0, 1
+ syscall # Вивести число
+
+ addi $s0, $s0, 4 # Розмір числа - 4 байти
+ addi $t0, $t0, 1 # Збільшити
+ j loop
+ end_loop:
+
+## Включення ##
+# Потрібно для імпорту сторонніх файлів у програму (насправді, код з цього файлу
+# копіюється та вставляється в місце, де оголошений імпорт)
+.include "somefile.asm"
+
+```
diff --git a/uk-ua/python-ua.html.markdown b/uk-ua/python-ua.html.markdown
index 23bc1796..4091e433 100644
--- a/uk-ua/python-ua.html.markdown
+++ b/uk-ua/python-ua.html.markdown
@@ -9,7 +9,7 @@ contributors:
- ["asyne", "https://github.com/justblah"]
- ["habi", "http://github.com/habi"]
translators:
- - ["Oleg Gromyak", "https://github.com/ogroleg"]
+ - ["Oleh Hromiak", "https://github.com/ogroleg"]
filename: learnpython-ua.py
---
diff --git a/uk-ua/rust-ua.html.markdown b/uk-ua/rust-ua.html.markdown
new file mode 100644
index 00000000..4ec2b7c9
--- /dev/null
+++ b/uk-ua/rust-ua.html.markdown
@@ -0,0 +1,331 @@
+---
+language: rust
+contributors:
+ - ["P1start", "http://p1start.github.io/"]
+translators:
+ - ["Volodymyr Korniichuk", "https://github.com/ezhikus"]
+filename: learnrust-uk.rs
+lang: uk-ua
+---
+
+Rust - це мова програмування, що розрабляється спільнотою Mozilla Research
+Rust поєднує в собі низькорівневий контроль швидкодії з високорівневими
+інструментами забезпечення гарантій цілісності та безпеки.
+
+Rust досягає своїх цілей без автоматичного збирання сміття і не вимагає
+наявності певного середовища виконання, що робить можливим пряму заміну
+бібліотек, написаних на мові С на бібліотеки, написані на Rust.
+
+Перший реліз Rust (версія 0.1) вийшла в січні 2012 року і з тих пір оновлення
+виходили так часто, що загальною порадою розробникам було не чекати якоїсь
+стабільної версії, а використовувати нічні збірки компілятора.
+
+15 травня 2015 року вийшла версія Rust 1.0. Для цієї версії була дана гарантія
+зворотної сумісності. Подальші нічні збірки покращили швидкість компіляції та
+деякі інші аспекти. На даний момент оновлення Rust виходять кожні 6 тижнів.
+Бета-версія Rust 1.1 вийшла одночасно з релізом Rust 1.0.
+
+Не зважаючи на те, що Rust є відносно низькорівневою мовою програмування, в
+ній є деякі концепти, притаманні високорівневим мовам. Це робить Rust не лише
+швидким, але й досить зручним та ефективним інструментом розробки.
+
+```rust
+// Це коментар. Він починається в цьому рядку...
+// і продовжується в цьому
+
+/// Цей коментар включає в себе документацію і підтримує markdown.
+/// # Приклади
+///
+/// ```
+/// let five = 5
+/// ```
+
+///////////////
+// 1. Основи //
+///////////////
+
+#[allow(dead_code)]
+// Функції
+// `i32` - це 32-бітний цілочислений знаковий тип даних
+fn add2(x: i32, y: i32) -> i32 {
+ // неявне повернення результату (в кінці рядку немає крапки з комою)
+ x + y
+}
+
+#[allow(unused_variables)]
+#[allow(unused_assignments)]
+#[allow(dead_code)]
+// Головна функція
+fn main() {
+ // Числа //
+
+ // Незмінне число
+ let x: i32 = 1;
+
+ // суфікси для позначення цілого числа та числа з плаваючою змінною
+ let y: i32 = 13i32;
+ let f: f64 = 1.3f64;
+
+ // Вивід типів
+ // Як правило, Rust може самостійно визначити тип змінної, отож
+ // ви можете не прописувати його явно
+ // В даному документі типи явно прописані в багатьох місцях, це зроблено
+ // виключно в навчальних цілях. В реальному коді вивід типів спрацює
+ // в більшості випадків
+ let implicit_x = 1;
+ let implicit_f = 1.3;
+
+ // арифметика
+ let sum = x + y + 13;
+
+ // Змінні
+ let mut mutable = 1;
+ mutable = 4;
+ mutable += 2;
+
+ // Строки //
+
+ // Строкові літерали
+ let x: &str = "Привіт, світ!";
+
+ // Друк на екран
+ println!("{} {}", f, x); // 1.3 Привіт, світ!
+
+ // `String` – строка, що розміщується в "купі"
+ let s: String = "hello world".to_string();
+
+ // Строковий зріз - це незмінне відображення якоїсь строки (або її частини)
+ // Зріз можна розглядати як константну пару покажчиків (на початок та кінець
+ // якоїсь строки)
+ let s_slice: &str = &s;
+
+ println!("{} {}", s, s_slice); // Привіт, світ! Привіт, світ!
+
+ // Вектори/масиви //
+
+ // Масив фіксованого розміру
+ let four_ints: [i32; 4] = [1, 2, 3, 4];
+
+ // Масив змінного розміру (вектор)
+ let mut vector: Vec<i32> = vec![1, 2, 3, 4];
+ vector.push(5);
+
+ // Зріз - незмінне відображення масиву
+ // Це схоже на строковий зріз, але в даному випадку мова йде про вектори
+ let slice: &[i32] = &vector;
+
+ // Використовуйте `{:?}` щоб вивести щось в цілях відлагодження
+ println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
+
+ // Кортеж //
+
+ // Кортеж - це набір фіксованого розміру, що включає значення кількох типів
+ let x: (i32, &str, f64) = (1, "привіт", 3.4);
+
+ // розбираємо кортеж "х" на окремі змінні "a", "b" та "с"
+ let (a, b, c) = x;
+ println!("{} {} {}", a, b, c); // 1 привіт 3.4
+
+ // доступ по індексу
+ println!("{}", x.1); // привіт
+
+ //////////////
+ // 2. Типи //
+ //////////////
+
+ // Структура
+ struct Point {
+ x: i32,
+ y: i32,
+ }
+
+ let origin: Point = Point { x: 0, y: 0 };
+
+ // Структура з безіменними полями, "кортежна структура"
+ struct Point2(i32, i32);
+
+ let origin2 = Point2(0, 0);
+
+ // перелічуваний тип даних
+ enum Direction {
+ Left,
+ Right,
+ Up,
+ Down,
+ }
+
+ let up = Direction::Up;
+
+ // перелічуваний тип даних з полями
+ enum OptionalI32 {
+ AnI32(i32),
+ Nothing,
+ }
+
+ let two: OptionalI32 = OptionalI32::AnI32(2);
+ let nothing = OptionalI32::Nothing;
+
+ // Узагальнене програмування //
+
+ struct Foo<T> { bar: T }
+
+ // Ось так стандартна бібліотека Rust оголошує `Option`
+ enum Optional<T> {
+ SomeVal(T),
+ NoVal,
+ }
+
+ // Методи //
+
+ impl<T> Foo<T> {
+ // Методи приймають неявний параметр `self`
+ fn get_bar(self) -> T {
+ self.bar
+ }
+ }
+
+ let a_foo = Foo { bar: 1 };
+ println!("{}", a_foo.get_bar()); // 1
+
+ // Типажі (в інших мовах програмування схожою сутністю є інтерфейси) //
+
+ trait Frobnicate<T> {
+ fn frobnicate(self) -> Option<T>;
+ }
+
+ impl<T> Frobnicate<T> for Foo<T> {
+ fn frobnicate(self) -> Option<T> {
+ Some(self.bar)
+ }
+ }
+
+ let another_foo = Foo { bar: 1 };
+ println!("{:?}", another_foo.frobnicate()); // Some(1)
+
+ /////////////////////////
+ // 3. Відповідність шаблону //
+ /////////////////////////
+
+ let foo = OptionalI32::AnI32(1);
+ match foo {
+ OptionalI32::AnI32(n) => println!("Це тип i32: {}", n),
+ OptionalI32::Nothing => println!("Це ніщо!"),
+ }
+
+ // Складніший приклад
+ struct FooBar { x: i32, y: OptionalI32 }
+ let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) };
+
+ match bar {
+ FooBar { x: 0, y: OptionalI32::AnI32(0) } =>
+ println!("Числа рівні нулю!"),
+ FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m =>
+ println!("Числа однакові"),
+ FooBar { x: n, y: OptionalI32::AnI32(m) } =>
+ println!("Числа різні: {} {}", n, m),
+ FooBar { x: _, y: OptionalI32::Nothing } =>
+ println!("Друге число - ніщо!"),
+ }
+
+ /////////////////////
+ // 4. Потік керування //
+ /////////////////////
+
+ // Цикл `for`
+ let array = [1, 2, 3];
+ for i in array.iter() {
+ println!("{}", i);
+ }
+
+ // Діапазони
+ for i in 0u32..10 {
+ print!("{} ", i);
+ }
+ println!("");
+ // друкує `0 1 2 3 4 5 6 7 8 9 `
+
+ // `if`
+ if 1 == 1 {
+ println!("Математика працює!");
+ } else {
+ println!("Ой, лишенько...");
+ }
+
+ // `if` як вираз
+ let value = if true {
+ "добре"
+ } else {
+ "погано"
+ };
+
+ // Цикл `while`
+ while 1 == 1 {
+ println!("Всесвіт функціонує стабільно.");
+ // Вираз break перериває цикл
+ break
+ }
+
+ // Нескінченний цикл
+ loop {
+ println!("Привіт!");
+ // Вираз break перериває цикл
+ break
+ }
+
+ /////////////////////////////////
+ // 5. Вказівники і безпека пам'яті //
+ /////////////////////////////////
+
+ // Володіючий вказівник - тільки хтось один може "володіти" вказівником в
+ // будь-який момент. Це означає, що коли "Box" вийде за межі області
+ // видимості - його можна безпечно звільнити
+ let mut mine: Box<i32> = Box::new(3);
+ *mine = 5; // розіменування `mine` з присвоєнням йому нового значення
+ // `now_its_mine` перебирає на себе володіння над `mine`. Іншими словами,
+ // `mine` переміщується.
+ let mut now_its_mine = mine;
+ *now_its_mine += 2;
+
+ println!("{}", now_its_mine); // 7
+ // println!("{}", mine); // цей код не скомпілюється, оскільки тепер
+ // покажчиком на дані володіє `now_its_mine`
+
+ // Посилання – незмінний вказівник на дані
+ // При створенні посилання на якесь значення, ми говоримо, що значення
+ // було "запозичене". Поки значення є запозиченим - воно не може бути
+ // змінене або переміщене. Запозичення пропадає, як тільки стається вихід з
+ // області видимості, де було створене посилання
+ let mut var = 4;
+ var = 3;
+ let ref_var: &i32 = &var;
+
+ println!("{}", var); // На відміну від `mine`, `var` можна використати
+ println!("{}", *ref_var);
+ // var = 5; // цей код не скомпілюється, оскільки `var` зараз є запозиченим
+ // *ref_var = 6; // цей код також не зкомпілюється, оскільки `ref_var`
+ // є незмінним посиланням
+
+ // Змінне посилання
+ // Значення можна запозичити з можливістю зміни. У цьому випадку доступ до
+ // оригінального значення втрачається.
+ let mut var2 = 4;
+ let ref_var2: &mut i32 = &mut var2;
+ *ref_var2 += 2; // '*' використовується для доступу до змінного посилання
+
+ println!("{}", *ref_var2); // 6 , // при заміні на var2 код не зкомпілюється
+ // ref_var2 має тип &mut i32, отож зберігає посилання на i32, а не значення
+ // var2 = 2; // цей рядок не зкомпілюється, оскільки `var2` є запозиченим.
+}
+```
+
+## Матеріали для самовдосконалення
+
+В даному матеріалі ми оглянули лише основи Rust. Більше матеріалу ви можете
+знайти на сайті
+[The Rust Programming Language](http://doc.rust-lang.org/book/index.html)
+Також існує Reddit-розділ [/r/rust](http://reddit.com/r/rust). Люди на каналі
+irc.mozilla.org також завжди раді допомогти новачкам.
+
+Ви можете спробувати можливості Rust за допомогою онлайн-компілятора на сторінці
+[Rust playpen](http://play.rust-lang.org) або
+[Rust website](http://rust-lang.org).
diff --git a/uk-ua/wasm-ua.html.markdown b/uk-ua/wasm-ua.html.markdown
new file mode 100644
index 00000000..34f8cef8
--- /dev/null
+++ b/uk-ua/wasm-ua.html.markdown
@@ -0,0 +1,226 @@
+---
+language: WebAssembly
+lang: uk-ua
+filename: learnwasm-ua.wast
+contributors:
+ - ["Dean Shaff", "http://dean-shaff.github.io"]
+translators:
+ - ["Oleh Hromiak", "https://github.com/ogroleg"]
+---
+
+```
+;; learnwasm-ua.wast
+
+(module
+ ;; У WebAssembly весь код знаходиться в модулях. Будь-яка операція
+ ;; може бути записана за допомогою s-виразу. Також існує синтаксис "стек машини",
+ ;; втім, він не сумісний з проміжним бінарним представленням коду.
+
+ ;; Формат бінарного проміжного представлення майже повністю сумісний
+ ;; з текстовим форматом WebAssembly.
+ ;; Деякі відмінності:
+ ;; local_set -> local.set
+ ;; local_get -> local.get
+
+ ;; Код розміщується у функціях
+
+ ;; Типи даних
+ (func $data_types
+ ;; WebAssembly має чотири типи даних:
+ ;; i32 - ціле число, 32 біти
+ ;; i64 - ціле число, 64 біти (не підтримується у JavaScript)
+ ;; f32 - число з плаваючою комою, 32 біти
+ ;; f64 - число з плаваючою комою, 64 біти
+
+ ;; Створити локальну змінну можна за допомогою ключового слова "local".
+ ;; Змінні потрібно оголошувати на початку функції.
+
+ (local $int_32 i32)
+ (local $int_64 i64)
+ (local $float_32 f32)
+ (local $float_64 f64)
+
+ ;; Змінні, оголошені вище, ще не ініціалізовані, себто, не мають значення.
+ ;; Давайте присвоїмо їм значення за допомогою <тип даних>.const:
+
+ (local.set $int_32 (i32.const 16))
+ (local.set $int_32 (i64.const 128))
+ (local.set $float_32 (f32.const 3.14))
+ (local.set $float_64 (f64.const 1.28))
+ )
+
+ ;; Базові операції
+ (func $basic_operations
+
+ ;; Нагадаємо, у WebAssembly будь-що є s-виразом, включно
+ ;; з математичними виразами або зчитуванням значень змінних
+
+ (local $add_result i32)
+ (local $mult_result f64)
+
+ (local.set $add_result (i32.add (i32.const 2) (i32.const 4)))
+ ;; тепер add_result дорівнює 6!
+
+ ;; Для кожної операції потрібно використовувати правильний тип:
+ ;; (local.set $mult_result (f32.mul (f32.const 2.0) (f32.const 4.0))) ;; Ніт! mult_result має тип f64!
+ (local.set $mult_result (f64.mul (f64.const 2.0) (f64.const 4.0))) ;; Ніт! mult_result має тип f64!
+
+ ;; У WebAssembly є вбудовані функції накшталт математики та побітових операцій.
+ ;; Варто зазначити, що тут відсутні вбудовані тригонометричні функції.
+ ;; Тож нам потрібно:
+ ;; - написати їх самостійно (не найкраща ідея)
+ ;; - звідкись їх імпортувати (як саме - побачимо згодом)
+ )
+
+ ;; Функції
+ ;; Параметри вказуються ключовим словом `param`, значення, що повертається - `result`
+ ;; Поточне значення стеку і є значенням функції, що повертається
+
+ ;; Ми можемо викликати інші функції за допомогою `call`
+
+ (func $get_16 (result i32)
+ (i32.const 16)
+ )
+
+ (func $add (param $param0 i32) (param $param1 i32) (result i32)
+ (i32.add
+ (local.get $param0)
+ (local.get $param1)
+ )
+ )
+
+ (func $double_16 (result i32)
+ (i32.mul
+ (i32.const 2)
+ (call $get_16))
+ )
+
+ ;; Досі ми не могли що-небудь вивести на консоль і не мали доступу
+ ;; до високорівневої математики (степеневі функції, обрахунок експоненти або тригонометрія).
+ ;; Більше того, ми навіть не могли викликати WASM функції у Javascript!
+ ;; Виклик цих функцій у WebAssembly залежить від того,
+ ;; де ми знаходимось - чи це Node.js, чи середовище браузера.
+
+ ;; Якщо ми у Node.js, то потрібно виконати два кроки. По-перше, ми маємо сконвертувати
+ ;; текстове представлення WASM у справжній код webassembly.
+ ;; Наприклад, ось так (Binaryen):
+
+ ;; wasm-as learn-wasm.wast -o learn-wasm.wasm
+
+ ;; Давай також застосуємо оптимізації:
+
+ ;; wasm-opt learn-wasm.wasm -o learn-wasm.opt.wasm -O3 --rse
+
+ ;; Тепер наш скомпільований WebAssembly можна завантажити у Node.js:
+ ;; const fs = require('fs')
+ ;; const instantiate = async function (inFilePath, _importObject) {
+ ;; var importObject = {
+ ;; console: {
+ ;; log: (x) => console.log(x),
+ ;; },
+ ;; math: {
+ ;; cos: (x) => Math.cos(x),
+ ;; }
+ ;; }
+ ;; importObject = Object.assign(importObject, _importObject)
+ ;;
+ ;; var buffer = fs.readFileSync(inFilePath)
+ ;; var module = await WebAssembly.compile(buffer)
+ ;; var instance = await WebAssembly.instantiate(module, importObject)
+ ;; return instance.exports
+ ;; }
+ ;;
+ ;; const main = function () {
+ ;; var wasmExports = await instantiate('learn-wasm.wasm')
+ ;; wasmExports.print_args(1, 0)
+ ;; }
+
+ ;; Цей код зчитує функції з importObject
+ ;; (вказано у асинхронній JavaScript функції instantiate), а потім експортує функцію
+ ;; "print_args", яку ми викликаємо у Node.js
+
+ (import "console" "log" (func $print_i32 (param i32)))
+ (import "math" "cos" (func $cos (param f64) (result f64)))
+
+ (func $print_args (param $arg0 i32) (param $arg1 i32)
+ (call $print_i32 (local.get $arg0))
+ (call $print_i32 (local.get $arg1))
+ )
+ (export "print_args" (func $print_args))
+
+ ;; Завантаження даних з пам'яті WebAssembly.
+ ;; Наприклад, ми хочемо порахувати cos для елементів Javascript масиву.
+ ;; Нам потрібно отримати доступ до масиву і можливість ітерувати по ньому.
+ ;; У прикладі нижче ми змінимо існуючий масив.
+ ;; f64.load і f64.store приймають адресу числа у пам'яті *у байтах*.
+ ;; Для того, щоб отримати доступ до 3-го елементу масиву, ми маємо передати щось
+ ;; накшталт (i32.mul (i32.const 8) (i32.const 2)) у функцію f64.store.
+
+ ;; У JavaScript ми викличемо `apply_cos64` таким чином
+ ;; (використаємо функцію instantiate з попереднього прикладу):
+ ;;
+ ;; const main = function () {
+ ;; var wasm = await instantiate('learn-wasm.wasm')
+ ;; var n = 100
+ ;; const memory = new Float64Array(wasm.memory.buffer, 0, n)
+ ;; for (var i=0; i<n; i++) {
+ ;; memory[i] = i;
+ ;; }
+ ;; wasm.apply_cos64(n)
+ ;; }
+ ;;
+ ;; Ця функція не буде працювати, якщо ми виділимо пам'ять для (створимо) Float32Array у JavaScript.
+
+ (memory (export "memory") 100)
+
+ (func $apply_cos64 (param $array_length i32)
+ ;; визначаємо змінну циклу або лічильник
+ (local $idx i32)
+ ;; визначаємо змінну для доступу до пам'яті
+ (local $idx_bytes i32)
+ ;; константа - кількість байтів у числі типу f64.
+ (local $bytes_per_double i32)
+
+ ;; визначаємо змінну, яка зберігатиме значення з пам'яті
+ (local $temp_f64 f64)
+
+ (local.set $idx (i32.const 0))
+ (local.set $idx_bytes (i32.const 0)) ;; не обов'язково
+ (local.set $bytes_per_double (i32.const 8))
+
+ (block
+ (loop
+ ;; записуємо у idx_bytes необхідне зміщення в пам'яті - для поточного числа.
+ (local.set $idx_bytes (i32.mul (local.get $idx) (local.get $bytes_per_double)))
+
+ ;; отримуємо число з пам'яті (за зміщенням):
+ (local.set $temp_f64 (f64.load (local.get $idx_bytes)))
+
+ ;; рахуємо cos:
+ (local.set $temp_64 (call $cos (local.get $temp_64)))
+
+ ;; тепер зберігаємо результат обчислень у пам'ять:
+ (f64.store
+ (local.get $idx_bytes)
+ (local.get $temp_64))
+
+ ;; або робимо все за один крок (альтернативний код)
+ (f64.store
+ (local.get $idx_bytes)
+ (call $cos
+ (f64.load
+ (local.get $idx_bytes))))
+
+ ;; збільшуємо лічильник на одиницю (інкремент)
+ (local.set $idx (i32.add (local.get $idx) (i32.const 1)))
+
+ ;; якщо лічильник дорівнює довжині масиву, то завершуємо цикл
+ (br_if 1 (i32.eq (local.get $idx) (local.get $array_length)))
+ (br 0)
+ )
+ )
+ )
+ (export "apply_cos64" (func $apply_cos64))
+)
+
+```
diff --git a/vyper.html.markdown b/vyper.html.markdown
new file mode 100644
index 00000000..fec1a79f
--- /dev/null
+++ b/vyper.html.markdown
@@ -0,0 +1,872 @@
+---
+language: Vyper
+filename: learnVyper.vy
+contributors:
+ - ["Kenny Peluso", "kennyp.herokuapp.com"]
+---
+
+> The content of this document is largely inspired by ["Learn Solidity in Y Minutes"](https:#github.com/adambard/learnxinyminutes-docs/blob/master/solidity.html.markdown)
+
+Vyper lets you program on [Ethereum](https:#www.ethereum.org/), a
+blockchain-based virtual machine that allows the creation and
+execution of smart contracts, without requiring centralized or trusted parties. It was
+designed to improve upon Solidity, another smart contract language for Ethereum, by
+limiting unsafe practices and enhancing readability; Vyper seeks to optimize the
+security and auditability of smart contracts.
+
+Vyper is an experimental, statically typed, contract programming language meant to
+resemble Python. Like objects in OOP, each contract contains state variables, functions,
+and common data types. Contract-specific features include event notifiers for listeners,
+and custom global variables, global constants.
+
+Some Ethereum contract examples include crowdfunding, voting, and blind auctions.
+
+---
+
+## Table of Contents
+
+- Intro
+- Example
+1. Data types and associated methods
+2. Data structures
+3. Simple operators
+4. Global variables of note
+5. Functions and more
+ a. functions
+ b. events
+6. Branching and loops
+7. Objects/contracts
+ a. calling external contracts
+ b. ERC20 built-in
+ c. following an interface
+8. Other keywords
+ a. selfdestruct
+9. Contract design notes
+ a. obfuscation
+ b. storage optimization
+ c. data access in blockchain
+ d. cron job
+ e. observer pattern
+10. Security
+11. Style notes
+12. Natspec comments
+- Other documents
+
+---
+
+## Intro
+
+From [the docs](https://media.readthedocs.org/pdf/vyper/latest/vyper.pdf)
+the foundational tenants of Vyper are:
+
+1. *Security*
+2. *Language and compiler simplicity*
+3. *Auditability*
+
+This allows for the following features:
+
+1. *Bounds and overflow checking*
+ - On the arithmetic and array level
+ - There are no dynamic arrays in Vyper
+2. *Support for signed integers and decimal fixed point numbers*
+3. *Decidability* - You can always compute precise upper bound on gas cost
+4. *Strong typing* - for built-in and custom types
+5. *Small and understandable compiler code*
+6. *Limited support for pure functions*
+ - Anything marked `@constant` is not allowed to change the state
+
+Following the principles and goals, Vyper does not provide the following features:
+
+1. *Modifiers* (defining parts of functions elsewhere)
+2. *Class inheritance*
+3. *Inline assembly*
+4. *Function overloading*
+5. *Operator overloading*
+6. *Recursive calling*
+7. *Infinite-length loops*
+8. *Binary fixed point* (decimal fixed point is used for its exactness)
+
+WITH THE RAPID CHANGES IN ETHEREUM, THIS DOCUMENT IS UNLIKELY TO STAY UP TO
+DATE, SO YOU SHOULD FOLLOW THE LATEST VYPER DOCS AND ETHEREUM BLOG FOR THE LATEST.
+ALL CODE HERE IS PROVIDED AS IS, WITH SUBSTANTIAL RISK OF ERRORS OR DEPRECATED CODE
+PATTERNS.
+
+This document primarily discusses syntax, and so excludes many
+popular design patterns.
+
+As Vyper and Ethereum are under active development, experimental or beta
+features are typically marked, and subject to change. Pull requests welcome.
+
+This document describes Vyper version `0.1.0-beta.8`.
+
+*All of the following code exists for educational purposes only!*
+*None of the following code should be used in production as-is!*
+
+## Example
+
+```python
+# First, a simple todo list contract
+# Implements CRUD operations for tasks
+
+# todo.vy (note .vy extension)
+### **** START EXAMPLE **** ###
+
+# Start with Natspec comment
+# used for documentation
+
+# @title SimpleBank v1
+# @author kennyp
+# @notice This is a simple bank.
+
+# Vyper contracts must obey a particular order:
+# struct -> interface -> events -> globals and constants -> functions
+# Additionally, like Python, Vyper functions must be defined in the file
+# before they're called.
+
+# Structs
+
+struct Task:
+ done: bool
+ deleted: bool
+ task: string[100]
+ metadata: bytes32
+
+# Interfaces
+
+contract AnotherContract():
+ def fetch() -> bytes32: constant
+ def inform(_taskId: uint256, _status: uint256) -> bool: modifying
+
+# Events
+
+# Events - publicize actions to external listeners
+# `indexed` means that it's easier to search/filter on this field
+TaskStatus: event({_taskId: indexed(uint256), _status: uint256})
+
+# Global Variables
+
+# State variables are values which are permanently stored in contract storage
+# State vars consist of any value persisting beyond any function's scope
+# and are permanently stored in contract storage
+
+# You can define your own, custom, unmutable constants
+CREATED: constant(uint256) = 0
+COMPLETED: constant(uint256) = 1
+DELETED: constant(uint256) = 2
+
+# The `public` built-in allows for this address to be read externally
+# without defining a `get()` constant function
+owner: public(address)
+other: public(address)
+
+# uint256 means "unsigned positive integer between 0 and 2^256 - 1"
+# Overflow protection is built-in to Vyper
+taskCount: uint256
+tasks: map(uint256, Task) # dictionary: key=uint256, value: Task struct
+
+# Private Functions
+
+# Start each function with Pythonic decorators
+# These decorators resemble Natspec but are actually enforced by Vyper's compiler
+# These decorators are:
+# @public XOR @private (either one or the other)
+# @public (if any contract/user can call it)
+# @private (if only internal functions can call it)
+# @payable (if the function is payable i.e. accepting ETH)
+# @constant (if the function is not modifying anything on-chain)
+@private
+def _changeTaskStatus( \
+ _sender: address, \
+ _taskId: uint256, \
+ _status: uint256, \
+ ):
+ # backslashes (\) allow for multi-line code
+ # Natspec comments are particularly helpful for documentation and readibility
+ # Natspec can be included using familiar Pythonic docstring syntax
+ """
+ @notice
+ @dev `_sender` MUST be `self.owner`
+ @param _sender Who is triggering this function
+ @param _task The description of the task (only useful when task added)
+ """
+ # NOTE: Private functions do not have access to `msg.sender`
+ # SIDE NOTE: `msg.sender` refers to whoever immediately called the function of
+ # immediate scope. In other words, if I call a function that calls another
+ # in-contract, public function, then `msg.sender` turns from my address to
+ # the address of the current contract.
+ assert _sender == self.owner # failed assertions cause calls/transactions to fail
+ # Note that unlike Solidity, `self.` is required to query the contract's state
+ # Control flow is Pythonic, as is much of Vyper:
+ _task: string[100] # initialized to default value
+ _data: bytes32 = sha3(convert(_sender, bytes32)) # owner is obfuscated (but still visible in logs)
+ if _status == CREATED: # control flow mimics python
+ # How a new struct is instantiated:
+ self.tasks[_taskId] = Task({ \
+ done: False, deleted: False, task: _task, metadata: _data \
+ })
+ elif _status == COMPLETED:
+ # Modifying an existing struct:
+ self.tasks[_taskId].done = True
+ elif _status == DELETED:
+ self.tasks[_taskId].deleted = True
+ AnotherContract(self.other).inform(_taskId, _status) # modifying external call
+ log.TaskStatus(_taskId, _status) # emit an event
+
+# Public Functions
+
+# Pythonic constructor - can receive none or many arguments
+@public
+def __init__(_owner: address, _other_contract: address):
+ """
+ @dev Called once and only upon contract depoyment
+ """
+ self.owner = _owner
+ self.other = _other_contract
+
+# NOTE: Pythonic whitespace rules are mandated in Vyper
+
+@public
+def addTask(_task: string[100]) -> uint256:
+ """
+ @notice Adds a task to contract
+ @param _task Description of task
+ @return Id of newly minted task
+ """
+ # msg.sender gives the address of who/what contract is calling this function
+ self._changeTaskStatus(msg.sender, self.taskCount, CREATED)
+ self.tasks[self.taskCount].task = _task
+ self.taskCount += 1
+ return self.taskCount - 1
+
+@public
+def addSpecialTask(_task: string[100]) -> uint256:
+ """
+ @notice Adds a task with metadata pulled from elsewhere
+ @param _task Description of task
+ @return Id of newly minted task
+ """
+ self._changeTaskStatus(msg.sender, self.taskCount, CREATED)
+ self.tasks[self.taskCount].task = _task
+ self.tasks[self.taskCount].metadata = AnotherContract(self.other).fetch()
+ self.taskCount += 1
+ return self.taskCount - 1
+
+@public
+def completeTask(_taskId: uint256):
+ """
+ @notice Marks a task as "completed"
+ @param _taskId Id of task to complete
+ """
+ self._changeTaskStatus(msg.sender, _taskId, COMPLETED)
+
+@public
+def deleteTask(_taskId: uint256):
+ """
+ @notice Adds a task to contract
+ @param _taskId Id of task to delete
+ """
+ self._changeTaskStatus(msg.sender, _taskId, DELETED)
+
+@public
+@constant # allows function to run locally/off blockchain
+def getTask(_taskId: uint256) -> string[100]:
+ """
+ @notice Getter for a task's description
+ @param _taskId Id of task with desired description
+ @return Description of task
+ """
+ return self.tasks[_taskId].task
+
+### **** END EXAMPLE **** ###
+
+
+# Now, the basics of Vyper
+
+
+# ---
+
+
+# 1. DATA TYPES AND ASSOCIATED METHODS
+# uint256 used for currency amount and for dates (in unix time)
+x: uint256
+
+# int of 128 bits, cannot be changed after contract deployment
+# with 'constant', compiler replaces each occurrence with actual value
+a: constant(int128) = 5
+
+# All state variables (those outside a function)
+# are by default 'internal' and accessible inside contract
+# Need to explicitly set to 'public' to allow external contracts to access
+# A getter is automatically created, but NOT a setter
+# Can only be called in the contract's scope (not within functions)
+# Add 'public' field to indicate publicly/externally accessible
+a: public(int128)
+
+# No random functions built in, use other contracts for randomness
+
+# Type casting is limited but exists
+b: int128 = 5
+x: uint256 = convert(b, uint256)
+
+# Types of accounts:
+# Contract Account: f(creator_addr, num_transactions)=address set on contract creation
+# External Account: (person/external entity): f(public_key)=address
+
+# Addresses - An address type can hold an Ethereum address which
+# equates to 20 bytes or 160 bits. It returns in hexadecimal notation
+# with a leading 0x. No arithmetic allowed
+owner: public(address)
+
+# Members can be invoked on all addresses:
+owner.balance # returns balance of address as `wei_value`
+owner.codesize # returns code size of address as `int128`
+owner.is_contract # `True` if Contract Account
+
+# All addresses can be sent ether via `send()` built-in
+@public
+@payable
+def sendWei(any_addr: address):
+ send(any_addr, msg.value)
+
+# Bytes available
+a: bytes[2]
+b: bytes[32]
+c: bytes32
+# `b` and `c` are 2 different types
+
+# Bytes are preferable to strings since Vyper currently offers better
+# support for bytes i.e. more built-ins to deal with `bytes32`, `bytes32`
+# can be returned from functions and strings[] can't be, UTF8 (string encoding)
+# uses more storage, etc.
+
+# There are no dynamically sized bytes, similar to how there are no
+# dynamic arrays
+
+# Fixed-size byte arrays (Strings)
+a: string[100]
+b: string[8]
+c: string[108] = concat(a, b) # check the latest docs for more built-ins
+
+# Time
+t1: timedelta
+t2: timestamp
+# Both types are built-in "custom type" variants of `uint256`
+# `timedelta` values can be added but not `timestamp` values
+
+# Money
+m: wei_value
+# Also has the base type `uint256` like `timestamp` and `timedelta`
+# 1 unit of WEI (a small amount of ETH i.e. ether)
+
+# Custom types
+# specify units used in the contract:
+units: {
+ cm: "centimeter",
+ km: "kilometer"
+}
+# usage:
+a: int128(cm)
+b: uint256(km)
+
+# BY DEFAULT: all values are set to 0 on instantiation
+
+# `clear()` can be called on most types
+# Does NOT destroy value, but sets value to 0, the initial value
+
+
+# ---
+
+
+# 2. DATA STRUCTURES
+# Arrays
+bytes32[5] nicknames; # static array
+bytes32[] names; # dynamic array
+uint newLength = names.push("John"); # adding returns new length of the array
+# Length
+names.length; # get length
+names.length = 1; # lengths can be set (for dynamic arrays in storage only)
+
+# Multidimensional Arrays
+# At initialization, array dimensions must be hard-coded or constants
+# Initialize a 10-column by 3-row, multidimensional fixed array
+ls: (uint256[10])[3] # parentheses are optional
+@public
+def setToThree():
+ # Multidimensional Array Access and Write
+ # access indices are reversed
+ # set element in row 2 (3rd row) column 5 (6th column) to 3
+ self.ls[2][5] = 3
+
+# Dictionaries (any simple type to any other type including structs)
+theMap: map(uint256, bytes32)
+theMap[5] = sha3("charles")
+# theMap[255] result is 0, all non-set key values return zeroes
+# To make read public, make a getter that accesses the mapping
+@public
+def getMap(_idx: uint256) -> bytes32:
+ """
+ @notice Get the value of `theMap` at `_idx`
+ """
+ return self.theMap[_idx]
+
+self.getMap(5) # returns sha3("charles") in bytes32
+
+# Nested mappings
+aMap: map(address, map(address, uint256))
+# NOTE: Mappings are only allowed as state variables
+# NOTE: Mappings are not iterable; can only be accessed
+
+# To delete (reset the mapping's value to default at a key)
+clear(balances["John"])
+clear(balances); # sets all elements to 0
+
+# Unlike other languages, CANNOT iterate through all elements in
+# mapping, without knowing source keys - can build data structure
+# on top to do this
+
+# Structs
+struct Struct:
+ owner: address
+ _balance: uint256 # balance is a reserved keyword, is a member for addresses
+
+exampleStuct: Struct
+
+@public
+def foo() -> uint256:
+ self.exampleStuct = Struct({owner: msg.sender, _balance: 5})
+ self.exampleStuct._balance = 10
+ self.exampleStuct._balance = 5 # set to new value
+ clear(self.exampleStuct._balance)
+ clear(self.exampleStuct)
+ return self.exampleStuct._balance
+
+
+# Data locations: Memory vs. storage vs. calldata - all complex types (arrays,
+# structs) have a data location
+# 'memory' does not persist, 'storage' does
+# Default is 'storage' for local and state variables; 'memory' for func params
+# stack holds small local variables
+
+# for most types, can explicitly set which data location to use
+
+
+# ---
+
+
+# 3. SIMPLE OPERATORS
+# Comparisons, bit operators and arithmetic operators are provided
+# exponentiation: **
+# modulo: %
+# maximum: max(x, y)
+# AND: bitwise_and(x, y)
+# bitwise shift: shift(x, _shift)
+# where x,y are uint256
+# _shift is int128
+
+# 4. GLOBAL VARIABLES OF NOTE
+# ** self **
+self # address of contract
+# often used at end of contract life to transfer remaining balance to party:
+self.balance # balance of current contract
+self.someFunction() # calls func externally via call, not via internal jump
+
+# ** msg - Current message received by the contract **
+# Ethereum programmers take NOTE: this `msg` object is smaller than elsewhere
+msg.sender # address of sender
+msg.value # amount of ether provided to this contract in wei, the function should be marked `@payable`
+msg.gas # remaining gas
+
+# ** tx - This transaction **
+# Ethereum programmers take NOTE: this `tx` object is smaller than elsewhere
+tx.origin # address of sender of the transaction
+
+# ** block - Information about current block **
+block.timestamp # time at current block (uses Unix time)
+# Note that `block.timestamp` can be manipulated by miners, so be careful
+block.number # current block number
+block.difficulty # current block difficulty
+
+# ** storage - Persistent storage hash **
+storage['abc'] = 'def'; # maps 256 bit words to 256 bit words
+
+
+# ---
+
+
+# 5. FUNCTIONS AND MORE
+
+# A. FUNCTIONS
+# Simple function
+function increment(uint x) returns (uint) {
+ x += 1;
+ return x;
+}
+
+# Functions can return many arguments
+@public
+@constant
+def increment(x: uint256, y: uint256) -> (uint256, uint256):
+ x += 1
+ y += 1
+ return (x, y)
+
+# Call previous functon
+@public
+@constant
+def willCall() -> (uint256, uint256):
+ return self.increment(1,1)
+
+# One should never have to call a function / hold any logic outside
+# outside the scope of a function in Vyper
+
+# '@constant'
+# indicates that function does not/cannot change persistent vars
+# Constant function execute locally, not on blockchain
+y: uint256
+@public
+@constant
+def increment(x: uint256) -> uint256:
+ x += 1
+ y += 1 # this line would fail
+ # y is a state variable => can't be changed in a constant function
+
+
+# 'Function Decorators'
+# Used like python decorators but are REQUIRED by Vyper
+# @public - visible externally and internally (default for function)
+# @private - only visible in the current contract
+# @constant - doesn't change state
+# @payable - receive ether/ETH
+# @nonrentant(<unique_key>) - Function can only be called once, both externally
+# and internally. Used to prevent reentrancy attacks
+
+# Functions hare not hoisted
+# Functions cannot be assigned to a variable
+# Functions cannot be recursive
+
+# All functions that receive ether must be marked 'payable'
+@public
+@payable
+def depositEther():
+ self.balances[msg.sender] += msg.value
+
+
+# B. EVENTS
+# Events are notify external parties; easy to search and
+# access events from outside blockchain (with lightweight clients)
+# typically declare after contract parameters
+
+# Declare
+LogSent: event({_from: indexed(address), address: indexed(_to), _amount: uint256})
+# Call
+log.LogSent(from, to, amount)
+
+/**
+For an external party (a contract or external entity), to watch using
+the Web3 Javascript library:
+
+# The following is Javascript code, not Vyper code
+Coin.LogSent().watch({}, '', function(error, result) {
+ if (!error) {
+ console.log("Coin transfer: " + result.args.amount +
+ " coins were sent from " + result.args.from +
+ " to " + result.args.to + ".");
+ console.log("Balances now:\n" +
+ "Sender: " + Coin.balances.call(result.args.from) +
+ "Receiver: " + Coin.balances.call(result.args.to));
+ }
+}
+**/
+
+# Common paradigm for one contract to depend on another (e.g., a
+# contract that depends on current exchange rate provided by another)
+
+
+# ---
+
+
+# 6. BRANCHING AND LOOPS
+
+# All basic logic blocks from Python work - including if/elif/else, for,
+# while, break, continue, return - but no switch
+
+# Syntax same as Python, but no type conversion from non-boolean
+# to boolean (comparison operators must be used to get the boolean val)
+
+# REMEMBER: Vyper does not allow resursive calls or infinite loops
+
+
+# ---
+
+
+# 7. OBJECTS/CONTRACTS
+# REMEMBER: Vyper does not allow for inheritance or imports
+
+# A. CALLING EXTERNAL CONTRACTS
+# You must define an interface to an external contract in the current contract
+
+contract InfoFeed():
+ def getInfo() -> uint256: constant
+
+info: uint256
+
+@public
+def __init__(_source: address):
+ self.info = InfoFeed(_source).getInfo()
+
+
+# B. ERC20 BUILT-IN
+# Using the `ERC20` keyword implies that the contract at the address
+# follows the ERC20 token standard, allowing you to safely call
+# functions like `transfer()`, etc.
+
+tokenAddress: address(ERC20)
+
+@public
+def transferIt(_to: address, _amt: uint256(wei)):
+ self.tokenAddress.transfer(_to, _amt)
+
+
+# C. FOLLOWING AN INTERFACE
+# Vyper is experimenting with using the following syntax at the top of
+# a `.vy` file to specify what interfaces are followed by the contract
+# This allows interfaces to be better organized, registered, and recognized
+
+import interfaces.some_interface as SomeInterface
+implements: SomeInterface
+# <rest of contract>
+
+
+# ---
+
+
+# 8. OTHER KEYWORDS
+
+# A. selfdestruct()
+# selfdestruct current contract, sending funds to address (often creator)
+selfdestruct(SOME_ADDRESS);
+
+# removes storage/code from current/future blocks
+# helps thin clients, but previous data persists in blockchain
+
+# Common pattern, lets owner end the contract and receive remaining funds
+@public
+def endItAll() {
+ assert msg.sender == self.creator # Only let the contract creator do this
+ selfdestruct(self.creator) # Makes contract inactive, returns funds
+
+# May want to deactivate contract manually, rather than selfdestruct
+# (ether sent to selfdestructed contract is lost)
+
+
+# B. sha3()
+# Encrypts strings and other data
+# Very important on the blockchain
+# Takes 1 argument, `concat()` can be called beforehand
+# All strings passed are concatenated before hash action
+sha3(concat("ab", "cd")) # returns bytes32
+
+
+# ---
+
+
+# 9. CONTRACT DESIGN NOTES
+
+# A. Obfuscation
+# All variables are publicly viewable on blockchain, so anything
+# that is private needs to be obfuscated (e.g., hashed w/secret)
+# Oftentimes, a "commit-reveal" scheme is employed
+
+# Step 1. Commit
+# Place a commitment by sending output of `sha3()`
+sha3("a secret"); # btyes32 commit
+sha3(concat("secret", "other secret", "salt")); # commit multiple things
+# The `sha3()` calculation should occur off-chain, only the bytes32
+# output should be inputted into some `commit()` function
+commits: map(address, bytes32)
+@public
+def commit(commitment: bytes32):
+ self.commits[msg.sender] = commitment
+
+# Step 2. Reveal
+# Send your previously committed data so the contract can check
+# if your commitment was honest
+@public
+def reveal(_secret: string[100], _salt: string[100]) -> bool:
+ return sha3(concat(_secret, _salt)) == self.commits[msg.sender]
+
+
+# B. Storage optimization
+# Writing to blockchain can be expensive, as data stored forever; encourages
+# smart ways to use memory (eventually, compilation will be better, but for now
+# benefits to planning data structures - and storing min amount in blockchain)
+
+# Cost can often be high for items like multidimensional arrays
+# (cost is for storing data - not declaring unfilled variables)
+
+
+# C. Data access in blockchain
+# Cannot restrict human or computer from reading contents of
+# transaction or transaction's state
+
+# While 'private' prevents other *contracts* from reading data
+# directly - any other party can still read data in blockchain
+
+# All data to start of time is stored in blockchain, so
+# anyone can observe all previous data and changes
+
+
+# D. Cron Job
+# Contracts must be manually called to handle time-based scheduling;
+# can create external code to regularly ping or provide incentives
+# (ether) for others to ping
+
+
+# E. Observer Pattern
+# An Observer Pattern lets you register as a subscriber and
+# register a function which is called by the oracle (note, the oracle
+# pays for this action to be run)
+# Some similarities to subscription in Pub/sub
+
+# This is an abstract contract, both client and server classes import,
+# the client should implement
+
+### **** START EXAMPLE **** ###
+
+contract SomeOracleCallback():
+ def oracleCallback(_value: uint256, _time: timestamp, _info: bytes32): modifying
+
+MAX_SUBS: constant(uint256) = 100
+numSubs: public(uint256) # number of subscribers
+subs: map(uint256, address) # enumerates subscribers
+
+@public
+def addSub(_sub: address) -> uint256:
+ """
+ @notice Add subscriber
+ @param _sub Address to add
+ @return Id of newly added subscriber
+ """
+ self.subs[self.numSubs] = _sub
+ self.numSubs += 1
+ return self.numSubs - 1
+
+@private
+def notify(_value: uint256, _time: timestamp, _info: bytes32) -> bool:
+ """
+ @notice Notify all subscribers
+ @dev Check `numSubs` first; Watch out for gas costs!
+ @param _value whatever
+ @param _time what have you
+ @param _info what else
+ @return True upon successful completion
+ """
+ j: uint256
+ for i in range(MAX_SUBS):
+ j = convert(i, uint256) # `i` is int128 by default
+ if j == self.numSubs:
+ return True
+ SomeOracleCallback(self.subs[j]).oracleCallback(_value, _time, _info)
+
+@public
+def doSomething():
+ """
+ @notice Do something and notify subscribers
+ """
+ # ...something...
+ whatever: uint256 = 6
+ what_have_you: timestamp
+ what_else: bytes32 = sha3("6")
+ self.notify(whatever, what_have_you, what_else)
+
+# Now, your client contract can addSubscriber by importing SomeOracleCallback
+# and registering with Some Oracle
+
+### **** END EXAMPLE **** ###
+
+
+# ---
+
+
+# 10. SECURITY
+# Bugs can be disastrous in Ethereum contracts - and even popular patterns in
+# Vyper may be found to be antipatterns
+
+# See security links at the end of this doc
+
+
+# ---
+
+
+# 11. STYLE NOTES
+# Based on Python's PEP8 style guide
+# Full Style guide: http:#solidity.readthedocs.io/en/develop/style-guide.html
+
+# Quick summary:
+# 4 spaces for indentation
+# Two lines separate contract declarations (and other top level declarations)
+# Avoid extraneous spaces in parentheses
+# Can omit curly braces for one line statement (if, for, etc)
+# else should be placed on own line
+
+# Specific to Vyper:
+# arguments: snake_case
+# events, interfaces, structs: PascalCase
+# public functions: camelCase
+# private functions: _prefaceWithUnderscore
+
+
+# ---
+
+
+# 12. NATSPEC COMMENTS
+# used for documentation, commenting, and external UIs
+
+# Contract natspec - always above contract definition
+# @title Contract title
+# @author Author name
+
+# Function natspec
+# Should include in docstring of functions in typical Pythonic fashion
+# @notice Information about what function does; shown when function to execute
+# @dev Function documentation for developer
+
+# Function parameter/return value natspec
+# @param someParam Some description of what the param does
+# @return Description of the return value
+
+```
+
+## Additional resources
+- [Installation](https://vyper.readthedocs.io/en/latest/installing-vyper.html)
+- [Vyper Docs](https://media.readthedocs.org/pdf/vyper/latest/vyper.pdf)
+- [Vyper GitHub (under active dev)](https://github.com/ethereum/vyper)
+- [Tools and Resources](https://github.com/ethereum/vyper/wiki/Vyper-tools-and-resources)
+- [Online Compiler](https://vyper.online/)
+
+## Sample contracts
+- [Uniswap](https://github.com/Uniswap/contracts-vyper)
+- [Generalized Governance](https://github.com/kpeluso/gdg)
+- [Dynamic Arrays](https://github.com/kpeluso/vyper-dynamic-array)
+
+## Security
+Vyper is secure by design, but it may be helpful to understand what Vyper is
+protecting you from.
+- [Thinking About Smart Contract Security](https:#blog.ethereum.org/2016/06/19/thinking-smart-contract-security/)
+- [Smart Contract Security](https:#blog.ethereum.org/2016/06/10/smart-contract-security/)
+- [Hacking Distributed Blog](http:#hackingdistributed.com/)
+
+## Style
+- [Vyper Style Guide WIP](https://github.com/ethereum/vyper/issues/905)
+ - Heavily derived from [Solidity's style guide](http:#solidity.readthedocs.io/en/latest/style-guide.html) ...
+ - ... which, in turn, is heavily derived from Python's [PEP 8](https:#www.python.org/dev/peps/pep-0008/) style guide.
+
+## Editors
+- [Vyper for VS Code (alpha)](https://github.com/p-/vscode-vyper)
+
+## Future To Dos
+- Update to current Vyper release
+- List of common design patterns
+
+*Feel free to send a pull request with any edits - or email* `pelusoken -/at-/ gmail`
+
diff --git a/wasm.html.markdown b/wasm.html.markdown
new file mode 100644
index 00000000..aba2084f
--- /dev/null
+++ b/wasm.html.markdown
@@ -0,0 +1,312 @@
+---
+language: WebAssembly
+filename: learn-wasm.wast
+contributors:
+ - ["Dean Shaff", "http://dean-shaff.github.io"]
+---
+
+```
+;; learn-wasm.wast
+
+(module
+ ;; In WebAssembly, everything is included in a module. Moreover, everything
+ ;; can be expressed as an s-expression. Alternatively, there is the
+ ;; "stack machine" syntax, but that is not compatible with Binaryen
+ ;; intermediate representation (IR) syntax.
+
+ ;; The Binaryen IR format is *mostly* compatible with WebAssembly text format.
+ ;; There are some small differences:
+ ;; local_set -> local.set
+ ;; local_get -> local.get
+
+ ;; We have to enclose code in functions
+
+ ;; Data Types
+ (func $data_types
+ ;; WebAssembly has only four types:
+ ;; i32 - 32 bit integer
+ ;; i64 - 64 bit integer (not supported in JavaScript)
+ ;; f32 - 32 bit floating point
+ ;; f64 - 64 bit floating point
+
+ ;; We can declare local variables with the "local" keyword
+ ;; We have to declare all variables before we start doing anything
+ ;; inside the function
+
+ (local $int_32 i32)
+ (local $int_64 i64)
+ (local $float_32 f32)
+ (local $float_64 f64)
+
+ ;; These values remain uninitialized.
+ ;; To set them to a value, we can use <type>.const:
+
+ (local.set $int_32 (i32.const 16))
+ (local.set $int_32 (i64.const 128))
+ (local.set $float_32 (f32.const 3.14))
+ (local.set $float_64 (f64.const 1.28))
+ )
+
+ ;; Basic operations
+ (func $basic_operations
+
+ ;; In WebAssembly, everything is an s-expression, including
+ ;; doing math, or getting the value of some variable
+
+ (local $add_result i32)
+ (local $mult_result f64)
+
+ (local.set $add_result (i32.add (i32.const 2) (i32.const 4)))
+ ;; the value of add_result is now 6!
+
+ ;; We have to use the right data type for each operation:
+ ;; (local.set $mult_result (f32.mul (f32.const 2.0) (f32.const 4.0))) ;; WRONG! mult_result is f64!
+ (local.set $mult_result (f64.mul (f64.const 2.0) (f64.const 4.0))) ;; WRONG! mult_result is f64!
+
+ ;; WebAssembly has some builtin operations, like basic math and bitshifting.
+ ;; Notably, it does not have built in trigonometric functions.
+ ;; In order to get access to these functions, we have to either
+ ;; - implement them ourselves (not recommended)
+ ;; - import them from elsewhere (later on)
+ )
+
+ ;; Functions
+ ;; We specify arguments with the `param` keyword, and specify return values
+ ;; with the `result` keyword
+ ;; The current value on the stack is the return value of a function
+
+ ;; We can call other functions we've defined with the `call` keyword
+
+ (func $get_16 (result i32)
+ (i32.const 16)
+ )
+
+ (func $add (param $param0 i32) (param $param1 i32) (result i32)
+ (i32.add
+ (local.get $param0)
+ (local.get $param1)
+ )
+ )
+
+ (func $double_16 (result i32)
+ (i32.mul
+ (i32.const 2)
+ (call $get_16))
+ )
+
+ ;; Up until now, we haven't be able to print anything out, nor do we have
+ ;; access to higher level math functions (pow, exp, or trig functions).
+ ;; Moreover, we haven't been able to use any of the WASM functions in Javascript!
+ ;; The way we get those functions into WebAssembly
+ ;; looks different whether we're in a Node.js or browser environment.
+
+ ;; If we're in Node.js we have to do two steps. First we have to convert the
+ ;; WASM text representation into actual webassembly. If we're using Binyaren,
+ ;; we can do that with a command like the following:
+
+ ;; wasm-as learn-wasm.wast -o learn-wasm.wasm
+
+ ;; We can apply Binaryen optimizations to that file with a command like the
+ ;; following:
+
+ ;; wasm-opt learn-wasm.wasm -o learn-wasm.opt.wasm -O3 --rse
+
+ ;; With our compiled WebAssembly, we can now load it into Node.js:
+ ;; const fs = require('fs')
+ ;; const instantiate = async function (inFilePath, _importObject) {
+ ;; var importObject = {
+ ;; console: {
+ ;; log: (x) => console.log(x),
+ ;; },
+ ;; math: {
+ ;; cos: (x) => Math.cos(x),
+ ;; }
+ ;; }
+ ;; importObject = Object.assign(importObject, _importObject)
+ ;;
+ ;; var buffer = fs.readFileSync(inFilePath)
+ ;; var module = await WebAssembly.compile(buffer)
+ ;; var instance = await WebAssembly.instantiate(module, importObject)
+ ;; return instance.exports
+ ;; }
+ ;;
+ ;; const main = function () {
+ ;; var wasmExports = await instantiate('learn-wasm.wasm')
+ ;; wasmExports.print_args(1, 0)
+ ;; }
+
+ ;; The following snippet gets the functions from the importObject we defined
+ ;; in the JavaScript instantiate async function, and then exports a function
+ ;; "print_args" that we can call from Node.js
+
+ (import "console" "log" (func $print_i32 (param i32)))
+ (import "math" "cos" (func $cos (param f64) (result f64)))
+
+ (func $print_args (param $arg0 i32) (param $arg1 i32)
+ (call $print_i32 (local.get $arg0))
+ (call $print_i32 (local.get $arg1))
+ )
+ (export "print_args" (func $print_args))
+
+ ;; Loading in data from WebAssembly memory.
+ ;; Say that we want to apply the cosine function to a Javascript array.
+ ;; We need to be able to access the allocated array, and iterate through it.
+ ;; This example will modify the input array inplace.
+ ;; f64.load and f64.store expect the location of a number in memory *in bytes*.
+ ;; If we want to access the 3rd element of an array, we have to pass something
+ ;; like (i32.mul (i32.const 8) (i32.const 2)) to the f64.store function.
+
+ ;; In JavaScript, we would call `apply_cos64` as follows
+ ;; (using the instantiate function from earlier):
+ ;;
+ ;; const main = function () {
+ ;; var wasm = await instantiate('learn-wasm.wasm')
+ ;; var n = 100
+ ;; const memory = new Float64Array(wasm.memory.buffer, 0, n)
+ ;; for (var i=0; i<n; i++) {
+ ;; memory[i] = i;
+ ;; }
+ ;; wasm.apply_cos64(n)
+ ;; }
+ ;;
+ ;; This function will not work if we allocate a Float32Array on the JavaScript
+ ;; side.
+
+ (memory (export "memory") 100)
+
+ (func $apply_cos64 (param $array_length i32)
+ ;; declare the loop counter
+ (local $idx i32)
+ ;; declare the counter that will allow us to access memory
+ (local $idx_bytes i32)
+ ;; constant expressing the number of bytes in a f64 number.
+ (local $bytes_per_double i32)
+
+ ;; declare a variable for storing the value loaded from memory
+ (local $temp_f64 f64)
+
+ (local.set $idx (i32.const 0))
+ (local.set $idx_bytes (i32.const 0)) ;; not entirely necessary
+ (local.set $bytes_per_double (i32.const 8))
+
+ (block
+ (loop
+ ;; this sets idx_bytes to bytes offset of the value we're interested in.
+ (local.set $idx_bytes (i32.mul (local.get $idx) (local.get $bytes_per_double)))
+
+ ;; get the value of the array from memory:
+ (local.set $temp_f64 (f64.load (local.get $idx_bytes)))
+
+ ;; now apply the cosine function:
+ (local.set $temp_64 (call $cos (local.get $temp_64)))
+
+ ;; now store the result at the same location in memory:
+ (f64.store
+ (local.get $idx_bytes)
+ (local.get $temp_64))
+
+ ;; do it all in one step instead
+ (f64.store
+ (local.get $idx_bytes)
+ (call $cos
+ (f64.load
+ (local.get $idx_bytes))))
+
+ ;; increment the loop counter
+ (local.set $idx (i32.add (local.get $idx) (i32.const 1)))
+
+ ;; stop the loop if the loop counter is equal the array length
+ (br_if 1 (i32.eq (local.get $idx) (local.get $array_length)))
+ (br 0)
+ )
+ )
+ )
+ (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/wolfram.html.markdown b/wolfram.html.markdown
index 4514006d..5fddbc82 100644
--- a/wolfram.html.markdown
+++ b/wolfram.html.markdown
@@ -123,8 +123,8 @@ myHash[["Green"]] (* 2, use it *)
myHash[["Green"]] := 5 (* 5, update it *)
myHash[["Puce"]] := 3.5 (* 3.5, extend it *)
KeyDropFrom[myHash, "Green"] (* Wipes out key Green *)
-Keys[myHash] (* {Red} *)
-Values[myHash] (* {1} *)
+Keys[myHash] (* {Red, Puce} *)
+Values[myHash] (* {1, 3.5} *)
(* And you can't do any demo of Wolfram without showing this off *)
Manipulate[y^2, {y, 0, 20}] (* Return a reactive user interface that displays y^2
diff --git a/yaml.html.markdown b/yaml.html.markdown
index 09c5dfc5..f1393c09 100644
--- a/yaml.html.markdown
+++ b/yaml.html.markdown
@@ -38,6 +38,8 @@ however: 'A string, enclosed in quotes.'
'Keys can be quoted too.': "Useful if you want to put a ':' in your key."
single quotes: 'have ''one'' escape pattern'
double quotes: "have many: \", \0, \t, \u263A, \x0d\x0a == \r\n, and more."
+# UTF-8/16/32 characters need to be encoded
+Superscript two: \u00B2
# Multiple-line strings can be written either as a 'literal block' (using |),
# or a 'folded block' (using '>').
diff --git a/zfs.html.markdown b/zfs.html.markdown
index fad6b62d..6795b1fa 100644
--- a/zfs.html.markdown
+++ b/zfs.html.markdown
@@ -221,7 +221,7 @@ Delete dataset
```bash
# Datasets cannot be deleted if they have any snapshots
-zfs destroy tank/root/home
+$ zfs destroy tank/root/home
```
Get / set properties of a dataset
@@ -294,6 +294,7 @@ tank/home/sarlalian@now 0 - 259M -
tank/home/alice@now 0 - 156M -
tank/home/bob@now 0 - 156M -
...
+```
Destroy snapshots
@@ -313,13 +314,13 @@ Renaming Snapshots
$ zfs rename tank/home/sarlalian@now tank/home/sarlalian@today
$ zfs rename tank/home/sarlalian@now today
-# zfs rename -r tank/home@now @yesterday
+$ zfs rename -r tank/home@now @yesterday
```
Accessing snapshots
```bash
-# CD Into a snapshot directory
+# CD into a snapshot directory
$ cd /home/.zfs/snapshot/
```
@@ -335,11 +336,11 @@ $ zfs send tank/home/sarlalian@now | zfs recv backups/home/sarlalian
# Send a snapshot to a remote host
$ zfs send tank/home/sarlalian@now | ssh root@backup_server 'zfs recv tank/home/sarlalian'
-# Send full dataset with snapshos to new host
+# Send full dataset with snapshots to new host
$ zfs send -v -R tank/home@now | ssh root@backup_server 'zfs recv tank/home'
```
-Cloneing Snapshots
+Cloning Snapshots
```bash
# Clone a snapshot
diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown
index 8566e811..8eecc56e 100644
--- a/zh-cn/c-cn.html.markdown
+++ b/zh-cn/c-cn.html.markdown
@@ -612,7 +612,7 @@ typedef void (*my_fnp_type)(char *);
最好找一本 [K&R, aka "The C Programming Language", “C程序设计语言”](https://en.wikipedia.org/wiki/The_C_Programming_Language)。它是关于C最重要的一本书,由C的创作者撰写。不过需要留意的是它比较古老了,因此有些不准确的地方。
-另一个比较好的资源是 [Learn C the hard way](http://c.learncodethehardway.org/book/)
+另一个比较好的资源是 [Learn C the hard way](http://learncodethehardway.org/c/)
如果你有问题,请阅读[compl.lang.c Frequently Asked Questions](http://c-faq.com/)。
diff --git a/zh-cn/lambda-calculus-cn.html.markdown b/zh-cn/lambda-calculus-cn.html.markdown
new file mode 100644
index 00000000..7719ee71
--- /dev/null
+++ b/zh-cn/lambda-calculus-cn.html.markdown
@@ -0,0 +1,223 @@
+---
+category: Algorithms & Data Structures
+name: Lambda Calculus
+lang: zh-cn
+contributors:
+ - ["Max Sun", "http://github.com/maxsun"]
+ - ["Yan Hui Hang", "http://github.com/yanhh0"]
+translators:
+ - ["Maoyin Sun", "https://github.com/simonmysun"]
+---
+
+# Lambda 演算
+
+Lambda 演算(lambda calculus, λ-calculus),
+最初由[阿隆佐·邱奇][]([Alonzo Church][])提出,
+是世界上最小的编程语言.
+尽管没有数字, 字符串, 布尔或者任何非函数的数据类型,
+lambda 演算仍可以表示任何图灵机.
+
+[阿隆佐·邱奇]: https://zh.wikipedia.org/wiki/%E9%98%BF%E9%9A%86%E4%BD%90%C2%B7%E9%82%B1%E5%A5%87
+[Alonzo Church]: https://en.wikipedia.org/wiki/Alonzo_Church
+
+Lambda 演算由三种元素组成: **变量**(variables)、**函数**(functions)和**应用**(applications)。
+
+| 名称 | 语法 | 示例 | 解释 |
+|------|----------------------|-----------|--------------------------------------------------|
+| 变量 | `<变量名>` | `x` | 一个名为"x"的变量 |
+| 函数 | `λ<参数>.<函数体>` | `λx.x` | 一个以"x"(前者)为参数、以"x"(后者)为函数体的函数 |
+| 应用 | `<函数><变量或函数>` | `(λx.x)a` | 以"a"为参数调用函数"λx.x" |
+
+最基本的函数为恒等函数: `λx.x`, 它等价于`f(x) = x`.
+第一个"x"为函数的参数, 第二个为函数体.
+
+## 自由变量和约束变量:
+
+- 在函数`λx.x`中, "x"被称作约束变量因为它同时出现在函数体和函数参数中.
+- 在`λx.y`中, "y"被称作自由变量因为它没有被预先声明.
+
+## 求值:
+
+求值操作是通过[β-归约][]([β-Reduction][])完成的,
+它本质上是词法层面上的替换.
+
+[β-归约]: https://zh.wikipedia.org/wiki/%CE%9B%E6%BC%94%E7%AE%97#'%22%60UNIQ--postMath-0000006F-QINU%60%22'-%E6%AD%B8%E7%B4%84
+[β-Reduction]: https://en.wikipedia.org/wiki/Lambda_calculus#Beta_reduction
+
+当对表达式`(λx.x)a`求值时, 我们将函数体中所有出现的"x"替换为"a".
+
+- `(λx.x)a`计算结果为: `a`
+- `(λx.y)a`计算结果为: `y`
+
+你甚至可以创建高阶函数:
+
+- `(λx.(λy.x))a`计算结果为: `λy.a`
+
+尽管 lambda 演算传统上仅支持单个参数的函数,
+但我们可以通过一种叫作[柯里化][]([Currying][])的技巧创建多个参数的函数.
+
+[柯里化]: https://zh.wikipedia.org/wiki/%E6%9F%AF%E9%87%8C%E5%8C%96
+[Currying]: https://en.wikipedia.org/wiki/Currying
+
+- `(λx.λy.λz.xyz)`等价于`f(x, y, z) = ((x y) z)`
+
+有时`λxy.<body>`与`λx.λy.<body>`可以互换使用.
+
+----
+
+认识到传统的 **lambda 演算没有数字, 字符或者任何非函数的数据类型**很重要.
+
+## 布尔逻辑:
+
+在 lambda 演算中没有"真"或"假". 甚至没有 1 或 0.
+
+作为替换:
+
+`T`表示为: `λx.λy.x`
+
+`F`表示为: `λx.λy.y`
+
+首先, 我们可以定义一个"if"函数`λbtf`, 它当`b`为真时返回`t`,
+`b`为假时返回`f`
+
+`IF`等价于: `λb.λt.λf.b t f`
+
+通过`IF`, 我们可以定义基本的布尔逻辑运算符:
+
+`a AND b`等价于: `λab.IF a b F`
+
+`a OR b`等价于: `λab.IF a T b`
+
+`NOT a`等价于: `λa.IF a F T`
+
+*注意: `IF a b c`本质上指: `IF((a b) c)`*
+
+## 数字:
+
+尽管 lambda 演算中没有数字,
+我们还可以用[邱奇编码][]([Church numerals][])将数字嵌入到 lambda 演算中.
+
+[邱奇编码]: https://zh.wikipedia.org/wiki/%E9%82%B1%E5%A5%87%E7%BC%96%E7%A0%81
+[Church numerals]: https://en.wikipedia.org/wiki/Church_encoding
+
+对于任意数字 n: <code>n = λf.f<sup>n</sup></code> 所以:
+
+`0 = λf.λx.x`
+
+`1 = λf.λx.f x`
+
+`2 = λf.λx.f(f x)`
+
+`3 = λf.λx.f(f(f x))`
+
+要增加一个邱奇数, 我们使用后继函数`S(n) = n + 1`:
+
+`S = λn.λf.λx.f((n f) x)`
+
+使用后继函数, 我们可以定义加法:
+
+`ADD = λab.(a S)b`
+
+**挑战**: 试定义乘法函数!
+
+## 变得更小: SKI, SK 和 Iota
+
+### SKI 组合子演算
+
+令 S, K, I 为下列函数:
+
+`I x = x`
+
+`K x y = x`
+
+`S x y z = x z (y z)`
+
+我们可以将 lambda 演算中的表达式转换为 SKI 组合子演算中的表达式:
+
+1. `λx.x = I`
+2. `λx.c = Kc`
+3. `λx.(y z) = S (λx.y) (λx.z)`
+
+以邱奇数 2 为例:
+
+`2 = λf.λx.f(f x)`
+
+对于里面的部分 `λx.f(f x)`:
+
+```
+ λx.f(f x)
+= S (λx.f) (λx.(f x)) (case 3)
+= S (K f) (S (λx.f) (λx.x)) (case 2, 3)
+= S (K f) (S (K f) I) (case 2, 1)
+```
+
+所以:
+
+```
+ 2
+= λf.λx.f(f x)
+= λf.(S (K f) (S (K f) I))
+= λf.((S (K f)) (S (K f) I))
+= S (λf.(S (K f))) (λf.(S (K f) I)) (case 3)
+```
+
+对于第一个参数`λf.(S (K f))`有:
+
+```
+ λf.(S (K f))
+= S (λf.S) (λf.(K f)) (case 3)
+= S (K S) (S (λf.K) (λf.f)) (case 2, 3)
+= S (K S) (S (K K) I) (case 2, 3)
+```
+
+对于第二个参数`λf.(S (K f) I)`有:
+
+```
+ λf.(S (K f) I)
+= λf.((S (K f)) I)
+= S (λf.(S (K f))) (λf.I) (case 3)
+= S (S (λf.S) (λf.(K f))) (K I) (case 2, 3)
+= S (S (K S) (S (λf.K) (λf.f))) (K I) (case 1, 3)
+= S (S (K S) (S (K K) I)) (K I) (case 1, 2)
+```
+
+综上:
+
+```
+ 2
+= S (λf.(S (K f))) (λf.(S (K f) I))
+= S (S (K S) (S (K K) I)) (S (S (K S) (S (K K) I)) (K I))
+```
+
+如果展开这个表达式, 我们最终又会得到邱奇数 2 的相同的表达式.
+
+### SK 组合子演算
+
+SKI 组合子演算还可以进一步简化. 我们可以通过`I = SKK`移除 I 组合子.
+我们可以将所有的 `I` 替换为 `SKK`.
+
+### ι 组合子
+
+SK 组合子仍不是最简的. 定义:
+
+```
+ι = λf.((f S) K)
+```
+
+我们有:
+
+```
+I = ιι
+K = ι(ιI) = ι(ι(ιι))
+S = ι(K) = ι(ι(ι(ιι)))
+```
+
+## 更多阅读:
+
+1. [A Tutorial Introduction to the Lambda Calculus](http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf)(英文)
+2. [Cornell CS 312 Recitation 26: The Lambda Calculus](https://courses.cs.cornell.edu/cs312/2008sp/recitations/rec26.html)(英文)
+3. [Wikipedia - Lambda Calculus](https://en.wikipedia.org/wiki/Lambda_calculus)(英文)
+4. [Wikipedia - SKI combinator calculus](https://en.wikipedia.org/wiki/SKI_combinator_calculus)(英文)
+5. [Wikipedia - Iota and Jot](https://en.wikipedia.org/wiki/Iota_and_Jot)(英文)
+6. [λ演算 - 维基百科,自由的百科全书](https://zh.wikipedia.org/wiki/SKI%E7%BB%84%E5%90%88%E5%AD%90%E6%BC%94%E7%AE%97)
+7. [SKI组合子演算 - 维基百科,自由的百科全书](https://zh.wikipedia.org/wiki/SKI%E7%BB%84%E5%90%88%E5%AD%90%E6%BC%94%E7%AE%97)
diff --git a/zh-cn/make-cn.html.markdown b/zh-cn/make-cn.html.markdown
index 281537d6..76dde941 100644
--- a/zh-cn/make-cn.html.markdown
+++ b/zh-cn/make-cn.html.markdown
@@ -39,7 +39,7 @@ Makefile 用于定义如何创建目标文件, 比如如何从源码到可执行
# …
# prerequisites(依赖) 是可选的, recipe(做法) 也可以多个或者不给.
-# 下面这个任务没有给 prerequisites, 只会在目标文件 file0.txt 文件不存在是跑
+# 下面这个任务没有给 prerequisites, 只会在目标文件 file0.txt 文件不存在时执行
file0.txt:
echo "foo" > file0.txt
# 试试 `make file0.txt`
@@ -47,12 +47,12 @@ file0.txt:
# 注意: 即使是这些注释, 如果前面有 TAB, 也会发送给 shell, 注意看 `make file0.txt` 输出
# 如果提供 prerequisites, 则只有 prerequisites 比 target 新时会执行
-# 比如下面这个任务只有当 file1.txt 比 file0.txt 新时才会执行.
+# 比如下面这个任务只有当 file0.txt 比 file1.txt 新时才会执行.
file1.txt: file0.txt
cat file0.txt > file1.txt
- # 这里跟shell里的命令式一毛一样的.
+ # 这里跟shell里的命令式一模一样.
@cat file0.txt >> file1.txt
- # @ 不会把命令往 stdout 打印.
+ # @ 不会把命令打印到 stdout.
-@echo 'hello'
# - 意思是发生错误了也没关系.
# 试试 `make file1.txt` 吧.
@@ -235,7 +235,7 @@ ls: *
# include foo.mk
sport = tennis
-# 一些逻辑语句 if else 什么的, 顶个写
+# 流程控制语句 (如if else 等等) 顶格写
report:
ifeq ($(sport),tennis)
@echo 'game, set, match'
diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown
index 2bd8d11a..9b3d96ab 100644
--- a/zh-cn/markdown-cn.html.markdown
+++ b/zh-cn/markdown-cn.html.markdown
@@ -5,6 +5,7 @@ contributors:
translators:
- ["Fangzhou Chen","https://github.com/FZSS"]
- ["Luffy Zhong", "https://github.com/mengzhongshi"]
+ - ["Yuchen Liu", "https://github.com/smallg0at"]
filename: learnmarkdown-cn.md
lang: zh-cn
---
@@ -46,6 +47,16 @@ Markdown 是 HTML 的父集,所以任何 HTML 文件都是有效的 Markdown
##### 这是一个 <h5>
###### 这是一个 <h6>
```
+
+实际效果(最终显示时会因设置而看起来不同):
+# 这是一个
+## 这也是一个
+### 这还是一个
+#### 这依旧是一个
+##### 这真的是一个
+###### 这...是一个
+
+
对于 `<h1>` 和 `<h2>` 元素,Markdown 额外提供了两种添加方式。
```md
@@ -58,7 +69,7 @@ Markdown 是 HTML 的父集,所以任何 HTML 文件都是有效的 Markdown
## 文本样式
-文本的斜体,粗体在 Markdown 中可以轻易实现。
+文本的*斜体*,**粗体**在 Markdown 中可以轻易实现。
```md
*此文本为斜体。*
@@ -72,7 +83,7 @@ __此文本也是__
*__这个也是!__*
```
-GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以使用删除线:
+GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以使用~~删除线~~:
```md
~~此文本为删除线效果。~~
@@ -80,6 +91,7 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以
## 段落
段落由一个句子或是多个中间没有空行的句子组成,每个段落由一个或是多个空行分隔开来。
+(注:部分解析器有无需空行就能换行的设置,这个主要看个人喜好)
```md
这是第一段落. 这句话在同一个段落里,好玩么?
@@ -92,7 +104,9 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以
```
如果你想插入一个 `<br />` 标签,你可以在段末加入两个以上的空格,然后另起一
-段。(译者注:试了一下,很多解析器,并不需要空两个空格,直接换行就会添加一个`<br />`)
+段。
+
+(译者注:试了一下,很多解析器,并不需要空两个空格,直接换行就会添加一个`<br />`)
```md
此段落结尾有两个空格(选中以显示)。
@@ -102,6 +116,8 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以
段落引用可由 `>` 字符轻松实现。
+> 对的很轻松
+
```md
> 这是一个段落引用。 你可以
> 手动断开你的句子,然后在每句句子前面添加 `>` 字符。或者让你的句子变得很长,以至于他们自动得换行。
@@ -113,7 +129,7 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以
```
## 列表
-无序列表可由星号,加号或者减号来创建
+- 无序列表可由星号,加号或者减号来创建
```md
* 项目
@@ -172,6 +188,7 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以
下面这个选择框将会是选中状态
- [x] 这个任务已经完成
```
+- [ ] 你看完了这个任务(注:此选择框是无法直接更改的,即禁用状态。)
## 代码块
@@ -217,7 +234,10 @@ end
---
- - -
****************
+
+下面这个就是示例
```
+---
## 链接
@@ -294,33 +314,45 @@ Markdown同样支持引用形式的链接
我希望 *将这段文字置于星号之间* 但是我不希望它被
斜体化, 这么做: \*这段置文字于星号之间\*。
```
+对比一下:*将这段文字置于星号之间* 和 \*将这段文字置于星号之间\*
### 键盘上的功能键
-在 GitHub 的 Markdown中,你可以使用 `<kbd>` 标签来表示功能键。
+在 GitHub 的 Markdown 中,你可以使用 `<kbd>` 标签来表示功能键。
```md
你的电脑死机了?试试
<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd>
```
<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd>
+
+(译注:可能由于网站本身样式问题,效果不明显)
+
### 表格
-表格只被 GitHub 的 Markdown 支持,并且有一点笨重,但如果你真的要用的话: (译者注:其实现在大部分markdown都已经支持)
+下面示例的表格长这样:
+
+| 第一列 | 第二列 | 第三列 |
+| :----------- | :-------: | ----------: |
+| 我是左对齐 | 居个中 | 右对齐 |
+| 注意 | 冒 | 号 |
+
+工整一点的写法是这样的:
```md
| 第一列 | 第二列 | 第三列 |
-| :--------- | :------: | ----------: |
-| 左对齐 | 居个中 | 右对齐 |
-| 某某某 | 某某某 | 某某某 |
+| :----------- | :-------: | ----------: |
+| 我是左对齐 | 居个中 | 右对齐 |
+| 注意 | 冒 | 号 |
```
-
-或者, 同样的
+好吧,强行对齐字符是很难的。但是,至少比下面这种写法好一点——
```md
-第一列 | 第二列 | 第三列
+我是超级超级长的第一列 | 第二列 | 第三列
:-- | :-: | --:
-这太丑了 | 药不能 | 停
+这真的太丑了 | 药不能 | 停!!!!
```
+真的是*看着令人头晕*
+
更多信息, 请于[此处](http://daringfireball.net/projects/Markdown/syntax)参见 John Gruber 关于语法的官方帖子,及于[此处](https://github.com/adam-p/Markdown-here/wiki/Markdown-Cheatsheet) 参见 Adam Pritchard 的摘要笔记。
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/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown
index 657a913d..9918c022 100644
--- a/zh-cn/ruby-cn.html.markdown
+++ b/zh-cn/ruby-cn.html.markdown
@@ -6,11 +6,25 @@ contributors:
- ["David Underwood", "http://theflyingdeveloper.com"]
- ["Joel Walden", "http://joelwalden.net"]
- ["Luke Holder", "http://twitter.com/lukeholder"]
+ - ["Tristan Hume", "http://thume.ca/"]
+ - ["Nick LaMuro", "https://github.com/NickLaMuro"]
+ - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"]
+ - ["Ariel Krakowski", "http://www.learneroo.com"]
+ - ["Dzianis Dashkevich", "https://github.com/dskecse"]
+ - ["Levi Bostian", "https://github.com/levibostian"]
+ - ["Rahil Momin", "https://github.com/iamrahil"]
+ - ["Gabriel Halley", "https://github.com/ghalley"]
+ - ["Persa Zula", "http://persazula.com"]
+ - ["Jake Faris", "https://github.com/farisj"]
+ - ["Corey Ward", "https://github.com/coreyward"]
+ - ["Jannik Siebert", "https://github.com/janniks"]
+ - ["Keith Miyake", "https://github.com/kaymmm"]
- ["lidashuang", "https://github.com/lidashuang"]
- ["ftwbzhao", "https://github.com/ftwbzhao"]
translators:
- ["Lin Xiangyu", "https://github.com/oa414"]
- ["Jiang Haiyun", "https://github.com/haiiiiiyun"]
+ - ["woclass", "https://github.com/inkydragon"]
---
```ruby
@@ -18,26 +32,27 @@ translators:
=begin
这是多行注释
-没人用这个
-你也不该用
=end
-# 首先,也是最重要的,所有东西都是对象
+# 在 Ruby 中,(几乎)所有东西都是对象
# 数字是对象
-
-3.class #=> Fixnum
-
+3.class #=> Integer
3.to_s #=> "3"
+# 字符串是对象
+"Hello".class #=> String
+
+# 甚至方法也是对象
+"Hello".method(:class).class #=> Method
-# 一些基本的算术符号
-1 + 1 #=> 2
-8 - 1 #=> 7
-10 * 2 #=> 20
-35 / 5 #=> 7
-2**5 #=> 32
-5 % 3 #=> 2
+# 一些基本的算术操作
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+35 / 5 #=> 7
+2 ** 5 #=> 32
+5 % 3 #=> 2
# 位运算符
3 & 5 #=> 1
@@ -48,6 +63,7 @@ translators:
# 实际上是调用对象的方法
1.+(3) #=> 4
10.* 5 #=> 50
+100.methods.include?(:/) #=> true
# 特殊的值也是对象
nil # 相当于其它语言中的 null
@@ -66,11 +82,11 @@ false.class #=> FalseClass
1 != 1 #=> false
2 != 1 #=> true
-# 除了false自己,nil是唯一的另一个值为false的对象
-
-!nil #=> true
-!false #=> true
-!0 #=> false
+# 除了 false 自己,nil 是唯一的另一个值为 false 的对象
+!!nil #=> false
+!!false #=> false
+!!0 #=> true
+!!"" #=> true
# 更多比较
1 < 10 #=> true
@@ -90,11 +106,11 @@ true || false #=> true
!true #=> false
# 也有优先级更低的逻辑运算符
-# 它们用于控制流结构中,用来串接语句,直到返回true或false。
+# 它们用于控制流结构中,用来串接语句,直到返回 true 或 false。
-# `do_something_else` 只当 `do_something` 返回true时才会被调用
+# `do_something_else` 只当 `do_something` 返回 true 时才会被调用
do_something() and do_something_else()
-# `log_error` 只当 `do_something` 返回false时才会被调用
+# `log_error` 只当 `do_something` 返回 false 时才会被调用
do_something() or log_error()
@@ -114,6 +130,7 @@ placeholder = "use string interpolation"
'hello ' + 'world' #=> "hello world"
'hello ' + 3 #=> TypeError: can't convert Fixnum into String
'hello ' + 3.to_s #=> "hello 3"
+"hello #{3}" #=> "hello 3"
# 合并字符串及其运算符
'hello ' * 3 #=> "hello hello hello "
@@ -141,7 +158,7 @@ x = y = 10 #=> 10
x #=> 10
y #=> 10
-# 按照惯例,使用类似snake_case风格的变量名
+# 按照惯例,使用类似 snake_case 风格的变量名
snake_case = true
# 使用有意义的变量名
@@ -174,6 +191,7 @@ array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# 数组可以被索引
# 从前面开始
array[0] #=> 1
+array.first #=> 1
array[12] #=> nil
# 像运算符一样,[var] 形式的访问
@@ -189,13 +207,13 @@ array.last #=> 5
# 同时指定开始的位置和长度
array[2, 3] #=> [3, 4, 5]
+# 或者指定一个区间
+array[1..3] #=> [2, 3, 4]
+
# 将数组逆序
a=[1,2,3]
a.reverse! #=> [3,2,1]
-# 或者指定一个区间
-array[1..3] #=> [2, 3, 4]
-
# 像这样往数组增加一个元素
array << 6 #=> [1, 2, 3, 4, 5, 6]
# 或者像这样
@@ -217,14 +235,18 @@ hash['number'] #=> 5
# 查询一个不存在的键将会返回nil
hash['nothing here'] #=> nil
-# 从Ruby 1.9开始,用符号作为键的时候有特别的记号表示:
+# 从 Ruby 1.9 开始,用符号作为键的时候有特别的记号表示:
new_hash = { defcon: 3, action: true }
new_hash.keys #=> [:defcon, :action]
+# 检查键值是否存在
+hash.key?(:defcon) #=> true
+hash.value?(3) #=> true
+
# 小贴士:数组和哈希表都是可枚举的
-# 它们共享一些有用的方法,比如each,map,count等等
+# 它们共享一些有用的方法,比如 each, map, count 等等
# 控制流
@@ -236,6 +258,8 @@ else
"else, also optional"
end
+# 循环
+
for counter in 1..5
puts "iteration #{counter}"
end
@@ -246,14 +270,14 @@ end
#=> iteration 5
-# 但是,没有人用for循环。
-# 你应该使用"each"方法,然后再传给它一个块。
-# 所谓块就是可以传给像"each"这样的方法的代码段。
-# 它类似于其它语言中的lambdas, 匿名函数或闭包。
+# 但是,没有人用 for 循环。
+# 你应该使用 "each" 方法,然后再传给它一个块。
+# 所谓块就是可以传给像 "each" 这样的方法的代码段。
+# 它类似于其它语言中的 lambdas, 匿名函数或闭包。
#
-# 区间上的"each"方法会对区间中的每个元素运行一次块代码。
-# 我们将counter作为一个参数传给了块。
-# 调用带有块的"each"方法看起来如下:
+# 区间上的 "each" 方法会对区间中的每个元素运行一次块代码。
+# 我们将 counter 作为一个参数传给了块。
+# 调用带有块的 "each" 方法看起来如下:
(1..5).each do |counter|
puts "iteration #{counter}"
@@ -275,7 +299,7 @@ hash.each do |key, value|
puts "#{key} is #{value}"
end
-# 如果你还需要索引值,可以使用"each_with_index",并且定义
+# 如果你还需要索引值,可以使用 "each_with_index",并且定义
# 一个索引变量
array.each_with_index do |element, index|
puts "#{element} is number #{index} in the array"
@@ -293,7 +317,7 @@ end
#=> iteration 5
# Ruby 中还有很多有用的循环遍历函数,
-# 如"map","reduce","inject"等等。
+# 如 "map", "reduce", "inject" 等等。
# 以map为例,它会遍历数组,并根据你在
# 块中定义的逻辑对它进行处理,然后返回
# 一个全新的数组。
@@ -388,19 +412,26 @@ surround { puts 'hello world' }
# {
# hello world
# }
+# => nil
# 可以向函数传递一个块
# "&"标记传递的块是一个引用
def guests(&block)
- block.call 'some_argument'
+ block.class #=> Proc
+ block.call(4)
end
+guests { |n| "You have #{n} guests." }
+# => "You have 4 guests."
+
# 可以传递多个参数,这些参数会转成一个数组,
# 这也是使用星号符 ("*") 的原因:
def guests(*array)
array.each { |guest| puts guest }
end
+# 结构
+
# 如果函数返回一个数组,在赋值时可以进行拆分:
def foods
['pancake', 'sandwich', 'quesadilla']
@@ -409,21 +440,42 @@ breakfast, lunch, dinner = foods
breakfast #=> 'pancake'
dinner #=> 'quesadilla'
-# 按照惯例,所有返回布尔值的方法都以?结尾
+# 有些情况下,你会想使用解构操作符 `*` 来解构数组
+ranked_competitors = ["John", "Sally", "Dingus", "Moe", "Marcy"]
+
+def best(first, second, third)
+ puts "Winners are #{first}, #{second}, and #{third}."
+end
+
+best *ranked_competitors.first(3) #=> Winners are John, Sally, and Dingus.
+
+# 结构操作符也可放在参数里面
+def best(first, second, third, *others)
+ puts "Winners are #{first}, #{second}, and #{third}."
+ puts "There were #{others.count} other participants."
+end
+
+best *ranked_competitors
+#=> Winners are John, Sally, and Dingus.
+#=> There were 2 other participants.
+
+# 按照惯例,所有返回布尔值的方法都以 ? 结尾
5.even? # false
5.odd? # true
-# 如果方法名末尾有!,表示会做一些破坏性的操作,比如修改调用者自身。
-# 很多方法都会有一个!的版本来进行修改,和一个非!的版本
-# 只用来返回更新了的结果
+# 如果方法名末尾有感叹号 !,表示会做一些破坏性的操作,比如修改调用者自身。
+# 很多方法都会有一个 ! 的版本来进行修改,
+# 和一个只返回更新结果的非 ! 版本
company_name = "Dunder Mifflin"
company_name.upcase #=> "DUNDER MIFFLIN"
company_name #=> "Dunder Mifflin"
-company_name.upcase! # we're mutating company_name this time!
+# 这次我们修改了 company_name
+company_name.upcase! #=> "DUNDER MIFFLIN"
company_name #=> "DUNDER MIFFLIN"
+# 类
-# 用class关键字定义一个类
+# 用 class 关键字定义一个类
class Human
# 一个类变量,它被这个类的所有实例变量共享
@@ -431,30 +483,30 @@ class Human
# 基本构造函数
def initialize(name, age = 0)
- # 将参数值赋给实例变量"name"
+ # 将参数值赋给实例变量 "name"
@name = name
- # 如果没有给出age,那么会采用参数列表中的默认值
+ # 如果没有给出 age,那么会采用参数列表中的默认值
@age = age
end
- # 基本的setter方法
+ # 基本的 setter 方法
def name=(name)
@name = name
end
- # 基本地getter方法
+ # 基本地 getter 方法
def name
@name
end
- # 以上的功能也可以用下面的attr_accessor来封装
+ # 以上的功能也可以用下面的 attr_accessor 来封装
attr_accessor :name
- # Getter/setter方法也可以像这样单独创建
+ # Getter/setter 方法也可以像这样单独创建
attr_reader :name
attr_writer :name
- # 类方法通过使用self与实例方法区别开来。
+ # 类方法通过使用 self 与实例方法区别开来。
# 它只能通过类来调用,不能通过实例调用。
def self.say(msg)
puts "#{msg}"
@@ -468,7 +520,6 @@ end
# 初始化一个类
jim = Human.new("Jim Halpert")
-
dwight = Human.new("Dwight K. Schrute")
# 让我们来调用一些方法
@@ -483,15 +534,15 @@ dwight.name #=> "Dwight K. Schrute"
Human.say('Hi') #=> "Hi"
# 变量的作用域由它们的名字格式定义
-# 以$开头的变量具有全局域
+# 以 $ 开头的变量具有全局域
$var = "I'm a global var"
defined? $var #=> "global-variable"
-# 以@开头的变量具有实例作用域
+# 以 @ 开头的变量具有实例作用域
@var = "I'm an instance var"
defined? @var #=> "instance-variable"
-# 以@@开头的变量具有类作用域
+# 以 @@ 开头的变量具有类作用域
@@var = "I'm a class var"
defined? @@var #=> "class variable"
@@ -568,7 +619,6 @@ Book.foo # => 'foo'
Book.new.foo # => NoMethodError: undefined method `foo'
# 当包含或扩展一个模块时,相应的回调代码会被执行。
-
module ConcernExample
def self.included(base)
base.extend(ClassMethods)
diff --git a/zh-cn/sql.html.markdown b/zh-cn/sql.html.markdown
new file mode 100644
index 00000000..9d430bd1
--- /dev/null
+++ b/zh-cn/sql.html.markdown
@@ -0,0 +1,105 @@
+---
+language: SQL
+filename: learnsql.sql
+contributors:
+ - ["Bob DuCharme", "http://bobdc.com/"]
+translators:
+ - ["Shuxin Shu", "https://github.com/NamelessAshone"]
+lang: zh-cn
+---
+
+结构化查询语言(SQL)是一个ISO标准语言,用于创建和管理数据库,
+这种数据库存储一系列表。不同的实现通常会添加特有的语言扩展;
+[不同SQL实现的比较(Comparison of different SQL implementat-
+ions)](http://troels.arvin.dk/db/rdbms/)是一份很好的产品差
+异参考文档。
+
+不同的实现通常会提供一个命令行用于交互式键入命令和显示输出,
+同时这些实现也会提供一种执行脚本文件的方法。(如何退出命令行
+就是就是SQL中尚未被标准化部分的一个典型例子,绝大多数SQL实
+现支持关键字QUIT、EXIT或者两者。)
+
+本文的实例命令假设你已经加载了[github](https://github.com/datacharmer/test_db)上的[MySQL示例员工数据库](https://dev.mysql.com/doc/employee/en/)。
+运行脚本的语法取决于你使用的SQL实现。通常是一个命令行工具。
+
+```sql
+
+-- 注释以两个连字符开始。命令以分号结束。
+
+-- SQL关键字大小写不敏感。在下文的示例命令中关键字大写,
+-- 因为大写更容易区分数据库、表和列名。
+
+-- 创建和删除一个数据库。数据库名和表名是大小写敏感的。
+CREATE DATABASE someDatabase;
+DROP DATABASE someDatabase;
+
+-- 列出可用的数据库。
+SHOW DATABASES;
+
+-- 使用某个已经存在的数据库
+USE employees;
+
+-- 从当前的departments表,选择所有的行和列
+-- 解释器的默认行为是将结果打印在屏幕上。
+SELECT * FROM departments;
+
+-- 检索departments表中所有的行,但只取dept_no和dept_name列。
+-- 一条命令可以跨越多行
+SELECT dept_no,
+ dept_name FROM departments;
+
+-- 检索departments表中所有的行,但是只输出5行。
+SELECT * FROM departments LIMIT 5;
+
+-- 检索departments表中dept_name列包含子串'en'的行。
+SELECT dept_name FROM departments WHERE dept_name LIKE '%en%';
+
+-- 检索departmnets表中所有dept_name列值为'S'开头并且'S'后接4个字符的行。
+SELECT * FROM departments WHERE dept_name LIKE 'S____';
+
+-- 检索title表中所有行,不显示重复的行。
+SELECT DISTINCT title FROM titles;
+
+-- 和上面的查询相同,但是以title的值排序(大小写敏感)。
+SELECT DISTINCT title FROM titles ORDER BY title;
+
+-- 计算departments表的总行数。
+SELECT COUNT(*) FROM departments;
+
+-- 计算departments表中dept_name列以'en'字段开头的行的数量。
+SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%';
+
+-- 不同表中信息的JOIN: titles表显示谁有什么工作,员工编号,
+-- 入职离职时间。检索这些信息,但是使用员工编号作为employees表
+-- 的交叉引用,而不是直接使用员工编号,来获得每个员工的名和姓。
+-- (同时只取10行)
+
+SELECT employees.first_name, employees.last_name,
+ titles.title, titles.from_date, titles.to_date
+FROM titles INNER JOIN employees ON
+ employees.emp_no = titles.emp_no LIMIT 10;
+
+-- 列出所有数据库中所有的表。不同实现通常提供各自的快捷命令
+-- 来列出当前使用数据库的所有表。
+SELECT * FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_TYPE='BASE TABLE';
+
+-- 在当前使用的数据库中,创建一个名为tablename1的表,包含下
+-- 述两列。许多其它选项可用于定制列,比如列的数据类型。
+CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20));
+
+-- 向tablename1表插入一行数据。假设该表已经定义并且接受这些值。
+INSERT INTO tablename1 VALUES('Richard','Mutt');
+
+-- 更新tablename1表中lname为'Mutt'的行fname的值改为'John'。
+UPDATE tablename1 SET fname='John' WHERE lname='Mutt';
+
+-- 删除tablename1表lname列以'M'开头的行。
+DELETE FROM tablename1 WHERE lname like 'M%';
+
+-- 删除tablename1表的所有行,留下空表。
+DELETE FROM tablename1;
+
+-- 删除整个tablename1表。
+DROP TABLE tablename1;
+```
diff --git a/zh-cn/yaml-cn.html.markdown b/zh-cn/yaml-cn.html.markdown
index bbda20e9..3ba2afd8 100644
--- a/zh-cn/yaml-cn.html.markdown
+++ b/zh-cn/yaml-cn.html.markdown
@@ -23,18 +23,23 @@ YAML 根本不容许文字制表符。
################
# 我们的根对象 (它们在整个文件里延续) 将会是一个映射,
-# 它等价于在别的语言里的一个字典,哈西表或对象。
+# 它等价于在别的语言里的一个字典,哈希表或对象。
key: value
another_key: Another value goes here.
a_number_value: 100
-# 如果你想将数字 1 作为值,你必须要将它括在引号中。
-# 不然 YAML 解析器会假定它是一个布尔值 true。
+# 数字 1 会被解释为数值,而不是一个布尔值。
+# 如果你想要的是一个布尔值,使用 true。
scientific_notation: 1e+12
boolean: true
null_value: null
key with spaces: value
-# 注意到字符串不需要被括在引号中。但是,它们可以被括起来。
-"Keys can be quoted too.": "Useful if you want to put a ':' in your key."
+# 注意,字符串不必被括在引号中,但也可以被括起来。
+however: 'A string, enclosed in quotes.'
+'Keys can be quoted too.': "Useful if you want to put a ':' in your key."
+single quotes: 'have ''one'' escape pattern'
+double quotes: "have many: \", \0, \t, \u263A, \x0d\x0a == \r\n, and more."
+# UTF-8/16/32 字符需要被转义(encoded)
+Superscript two: \u00B2
# 多行字符串既可以写成像一个'文字块'(使用 |),
# 或像一个'折叠块'(使用 '>')。
@@ -60,21 +65,21 @@ folded_style: >
# 集合类型 #
####################
-# 嵌套是通过缩进完成的。
+# 嵌套是通过缩进完成的。推荐使用 2 个空格的缩进(但非必须)
a_nested_map:
- key: value
- another_key: Another Value
- another_nested_map:
- hello: hello
+ key: value
+ another_key: Another Value
+ another_nested_map:
+ hello: hello
-# 映射的键值不必是字符串。
+# 映射的键不必是字符串。
0.25: a float key
-# 键值也可以是复合型的,比如多行对象
+# 键也可以是复合型的,比如多行对象
# 我们用 ? 后跟一个空格来表示一个复合键的开始。
? |
- This is a key
- that has multiple lines
+ This is a key
+ that has multiple lines
: and this is its value
# YAML 也允许使用复杂键语法表示序列间的映射关系。
@@ -85,20 +90,24 @@ a_nested_map:
: [ 2001-01-01, 2002-02-02 ]
# 序列 (等价于列表或数组) 看起来像这样:
+# 注意 '-' 算作缩进
a_sequence:
- - Item 1
- - Item 2
- - 0.5 # 序列可以包含不同类型。
- - Item 4
- - key: value
- another_key: another_value
- -
- - This is a sequence
- - inside another sequence
+ - Item 1
+ - Item 2
+ - 0.5 # 序列可以包含不同类型。
+ - Item 4
+ - key: value
+ another_key: another_value
+ -
+ - This is a sequence
+ - inside another sequence
+ - - - Nested sequence indicators
+ - can be collapsed
# 因为 YAML 是 JSON 的超集,你也可以写 JSON 风格的映射和序列:
json_map: {"key": "value"}
json_seq: [3, 2, 1, "takeoff"]
+and quotes are optional: {key: [3, 2, 1, takeoff]}
#######################
# 其余的 YAML 特性 #
@@ -111,15 +120,18 @@ other_anchor: *anchor_name
# 锚也可被用来复制/继承属性
base: &base
- name: Everyone has same name
+ name: Everyone has same name
+
+# The regexp << is called Merge Key Language-Independent Type.
+# 它表明指定映射的所有键值会插入到当前的映射中。
foo: &foo
- <<: *base
- age: 10
+ <<: *base
+ age: 10
bar: &bar
- <<: *base
- age: 20
+ <<: *base
+ age: 20
# foo 和 bar 将都含有 name: Everyone has same name
@@ -146,22 +158,25 @@ date: 2002-12-14
# 这个 !!binary 标签表明这个字符串实际上
# 是一个用 base64 编码表示的二进制 blob。
gif_file: !!binary |
- R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
- OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
- +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
- AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
+ R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
+ OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
+ +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
+ AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
# YAML 还有一个集合类型,它看起来像这样:
set:
- ? item1
- ? item2
- ? item3
+ ? item1
+ ? item2
+ ? item3
+or: {item1, item2, item3}
-# 像 Python 一样,集合仅是值为 null 的映射;上面的集合等价于:
+# 集合只是值为 null 的映射;上面的集合等价于:
set2:
- item1: null
- item2: null
- item3: null
+ item1: null
+ item2: null
+ item3: null
+
+... # document end
```
### 更多资源
diff --git a/zh-tw/pcre-tw.html.markdown b/zh-tw/pcre-tw.html.markdown
index c9cdc537..5f681d46 100644
--- a/zh-tw/pcre-tw.html.markdown
+++ b/zh-tw/pcre-tw.html.markdown
@@ -13,7 +13,9 @@ lang: zh-tw
相容Perl正規表達式(Perl Compatible Regular Expressions, PCRE)是一個實作正規表達式的C語言函式庫。此函式庫在1997年被開發出來,在當時面對複雜字串處理時大多會選擇使用Perl。也因為如此,PCRE大多的正規表達式語法都很酷似Perl。PCRE語法被廣泛運用在許多大專案中,包括PHP、Apache、R等。
PCRE中的超字元(metacharacter)主要可以分為以下兩類:
+
* 在中括號外會被辨識的字元
+
```
\ 通用跳脫字元
^ 字串開頭 或 行首
@@ -33,18 +35,17 @@ PCRE中的超字元(metacharacter)主要可以分為以下兩類:
```
* 在中括號內會被辨識的超字元,在中括號外會被視為字元集合使用
-
+
```
-
\ 通用跳脫字元
^ 非字元集合的字,但只會抓到第一個符合的字元
- 字元範圍
[ POSIX字元集合(若後面接POSIX格式)
] 字元集合定義結束
-
-```
+```
PCRE提供了一些通用的字元類型,可被當作字元集合使用
+
```
\d 任何數字字元
\D 任何非數字字元