master 1c6ba6f68851 cached
886 files
9.6 MB
2.5M tokens
5 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (10,167K chars total). Download the full file to get everything.
Repository: adambard/learnxinyminutes-docs
Branch: master
Commit: 1c6ba6f68851
Files: 886
Total size: 9.6 MB

Directory structure:
gitextract_7ub_b4qw/

├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── build.yml
│       └── lint.yml
├── .gitignore
├── .mailmap
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── ada.md
├── agda.md
├── amd.md
├── angularjs.md
├── ansible.md
├── apl.md
├── ar/
│   ├── html.md
│   ├── python.md
│   └── sql.md
├── arturo.md
├── asciidoc.md
├── assemblyscript.md
├── asymptotic-notation.md
├── ats.md
├── awk.md
├── ballerina.md
├── bash.md
├── bc.md
├── be/
│   ├── python.md
│   └── r.md
├── bf.md
├── bg/
│   ├── logtalk.md
│   └── perl.md
├── bqn.md
├── c++.md
├── c.md
├── ca/
│   ├── asciidoc.md
│   ├── go.md
│   ├── groovy.md
│   ├── html.md
│   └── kotlin.md
├── chapel.md
├── chicken.md
├── citron.md
├── clojure-macros.md
├── clojure.md
├── cmake.md
├── cobol.md
├── coffeescript.md
├── coldfusion.md
├── common-lisp.md
├── compojure.md
├── coq.md
├── crystal.md
├── cs/
│   ├── bf.md
│   ├── css.md
│   ├── elm.md
│   ├── go.md
│   ├── hack.md
│   ├── javascript.md
│   ├── json.md
│   ├── markdown.md
│   ├── python.md
│   └── sass.md
├── csharp.md
├── css.md
├── csv.md
├── cue.md
├── cypher.md
├── d.md
├── da/
│   └── javascript.md
├── dart.md
├── de/
│   ├── apl.md
│   ├── asciidoc.md
│   ├── bash.md
│   ├── bc.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── crystal.md
│   ├── csharp.md
│   ├── css.md
│   ├── d.md
│   ├── dhall.md
│   ├── dynamic-programming.md
│   ├── edn.md
│   ├── elixir.md
│   ├── elm.md
│   ├── git.md
│   ├── go.md
│   ├── hack.md
│   ├── haml.md
│   ├── haskell.md
│   ├── hq9+.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── json.md
│   ├── latex.md
│   ├── lolcode.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── nix.md
│   ├── opencv.md
│   ├── paren.md
│   ├── perl.md
│   ├── processing.md
│   ├── pug.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── rst.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── shutit.md
│   ├── sql.md
│   ├── swift.md
│   ├── tcl.md
│   ├── vim.md
│   ├── visualbasic.md
│   └── yaml.md
├── dhall.md
├── directx9.md
├── djot.md
├── docker.md
├── dynamic-programming.md
├── easylang.md
├── edn.md
├── el/
│   ├── bash.md
│   ├── css.md
│   ├── haskell.md
│   ├── html.md
│   ├── java.md
│   ├── json.md
│   ├── ocaml.md
│   ├── python.md
│   ├── racket.md
│   ├── rust.md
│   ├── scala.md
│   └── vim.md
├── elisp.md
├── elixir.md
├── elm.md
├── emacs.md
├── erlang.md
├── es/
│   ├── amd.md
│   ├── asciidoc.md
│   ├── asymptotic-notation.md
│   ├── awk.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── chapel.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── coldfusion.md
│   ├── common-lisp.md
│   ├── csharp.md
│   ├── css.md
│   ├── csv.md
│   ├── curto.md
│   ├── dart.md
│   ├── docker.md
│   ├── dynamic-programming.md
│   ├── edn.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── factor.md
│   ├── forth.md
│   ├── fsharp.md
│   ├── git.md
│   ├── go.md
│   ├── groovy.md
│   ├── hack.md
│   ├── haml.md
│   ├── haskell.md
│   ├── hq9+.md
│   ├── html.md
│   ├── hy.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── latex.md
│   ├── less.md
│   ├── livescript.md
│   ├── logtalk.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── objective-c.md
│   ├── pascal.md
│   ├── pcre.md
│   ├── perl.md
│   ├── php-composer.md
│   ├── php.md
│   ├── powershell.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── pythonstatcomp.md
│   ├── r.md
│   ├── racket.md
│   ├── raku.md
│   ├── rst.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── self.md
│   ├── smallbasic.md
│   ├── sql.md
│   ├── swift.md
│   ├── tcl.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── wolfram.md
│   ├── xml.md
│   └── yaml.md
├── fa/
│   ├── bf.md
│   ├── css.md
│   ├── html.md
│   ├── javascript.md
│   └── vim.md
├── factor.md
├── fi/
│   ├── go.md
│   ├── markdown.md
│   └── ruby.md
├── fish.md
├── forth.md
├── fortran.md
├── fr/
│   ├── asymptotic-notation.md
│   ├── awk.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── crystal.md
│   ├── csharp.md
│   ├── css.md
│   ├── d.md
│   ├── dynamic-programming.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── erlang.md
│   ├── fsharp.md
│   ├── git.md
│   ├── go.md
│   ├── haml.md
│   ├── haskell.md
│   ├── html.md
│   ├── hy.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── livescript.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── nix.md
│   ├── objective-c.md
│   ├── pcre.md
│   ├── perl.md
│   ├── php.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── r.md
│   ├── racket.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── scala.md
│   ├── set-theory.md
│   ├── sql.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── wolfram.md
│   ├── xml.md
│   └── yaml.md
├── fsharp.md
├── gdscript.md
├── git.md
├── gleam.md
├── go.md
├── golfscript.md
├── groovy.md
├── hack.md
├── haml.md
├── haskell.md
├── haxe.md
├── hcl.md
├── hdl.md
├── he/
│   ├── html.md
│   └── uxntal.md
├── hi/
│   ├── amd.md
│   ├── c++.md
│   ├── d.md
│   └── json.md
├── hjson.md
├── hocon.md
├── hq9+.md
├── hre.csv
├── html.md
├── httpie.md
├── hu/
│   ├── coffeescript.md
│   ├── go.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── typescript.md
│   └── yaml.md
├── hy.md
├── id/
│   ├── asciidoc.md
│   ├── bf.md
│   ├── coffeescript.md
│   ├── css.md
│   ├── hq9+.md
│   ├── java.md
│   ├── json.md
│   ├── markdown.md
│   ├── php.md
│   ├── pyqt.md
│   ├── rst.md
│   ├── ruby.md
│   ├── smallbasic.md
│   └── xml.md
├── inform7.md
├── it/
│   ├── asciidoc.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── cmake.md
│   ├── coffeescript.md
│   ├── dynamic-programming.md
│   ├── elixir.md
│   ├── fish.md
│   ├── gdscript.md
│   ├── git.md
│   ├── go.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── logtalk.md
│   ├── lua.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── pcre.md
│   ├── php-composer.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── rst.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── solidity.md
│   ├── sql.md
│   ├── toml.md
│   ├── typescript.md
│   ├── vim.md
│   └── zfs.md
├── ja/
│   ├── asciidoc.md
│   ├── bash.md
│   ├── c.md
│   ├── css.md
│   ├── elixir.md
│   ├── julia.md
│   ├── markdown.md
│   ├── nim.md
│   ├── php.md
│   ├── python.md
│   ├── r.md
│   ├── rust.md
│   ├── vim.md
│   └── yaml.md
├── janet.md
├── java.md
├── javascript.md
├── jinja.md
├── jq.md
├── jquery.md
├── json.md
├── jsonnet.md
├── julia.md
├── kdb+.md
├── ko/
│   ├── bash.md
│   ├── bf.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── erlang.md
│   ├── go.md
│   ├── java.md
│   ├── javascript.md
│   ├── json.md
│   ├── kotlin.md
│   ├── lua.md
│   ├── markdown.md
│   ├── php.md
│   ├── pythonlegacy.md
│   ├── racket.md
│   ├── vim.md
│   ├── xml.md
│   └── yaml.md
├── kotlin.md
├── lambda-calculus.md
├── latex.md
├── lbstanza.md
├── ldpl.md
├── lean4.md
├── less.md
├── lfe.md
├── linker.md
├── lint/
│   ├── encoding.sh
│   ├── frontmatter.py
│   └── requirements.txt
├── livescript.md
├── logtalk.md
├── lolcode.md
├── lt/
│   ├── json.md
│   └── tmux.md
├── lua.md
├── m.md
├── make.md
├── markdown.md
├── matlab.md
├── mercurial.md
├── mercury.md
├── messagepack.md
├── miniscript.md
├── mips.md
├── mongodb.md
├── moonscript.md
├── ms/
│   ├── bash.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── elisp.md
│   ├── javascript.md
│   ├── json.md
│   ├── sass.md
│   └── xml.md
├── nim.md
├── niva.md
├── nix.md
├── nl/
│   ├── amd.md
│   ├── bash.md
│   ├── bf.md
│   ├── coffeescript.md
│   ├── dynamic-programming.md
│   ├── html.md
│   ├── json.md
│   ├── markdown.md
│   ├── typescript.md
│   ├── vim.md
│   ├── xml.md
│   └── yaml.md
├── nmap.md
├── no/
│   ├── bash.md
│   └── json.md
├── objective-c.md
├── ocaml.md
├── odin.md
├── opencv.md
├── opengl.md
├── openmp.md
├── openscad.md
├── osl.md
├── p5.md
├── paren.md
├── pascal.md
├── pcre.md
├── perl.md
├── pets.csv
├── phel.md
├── phix.md
├── php-composer.md
├── php.md
├── pl/
│   ├── bf.md
│   ├── haskell.md
│   ├── java.md
│   ├── json.md
│   ├── perl.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── vim.md
│   └── xml.md
├── powershell.md
├── processing.md
├── prolog.md
├── protocol-buffer-3.md
├── pt-br/
│   ├── amd.md
│   ├── asciidoc.md
│   ├── asymptotic-notation.md
│   ├── awk.md
│   ├── bash.md
│   ├── bc.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── cmake.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── csharp.md
│   ├── css.md
│   ├── cypher.md
│   ├── d.md
│   ├── dart.md
│   ├── dynamic-programming.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── elm.md
│   ├── emacs.md
│   ├── erlang.md
│   ├── factor.md
│   ├── fsharp.md
│   ├── git.md
│   ├── go.md
│   ├── groovy.md
│   ├── hack.md
│   ├── haskell.md
│   ├── haxe.md
│   ├── html.md
│   ├── httpie.md
│   ├── hy.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── latex.md
│   ├── less.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── p5.md
│   ├── paren.md
│   ├── pascal.md
│   ├── perl.md
│   ├── php-composer.md
│   ├── php.md
│   ├── processing.md
│   ├── pug.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── pythonstatcomp.md
│   ├── qt.md
│   ├── r.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── self.md
│   ├── set-theory.md
│   ├── solidity.md
│   ├── sql.md
│   ├── stylus.md
│   ├── swift.md
│   ├── tmux.md
│   ├── toml.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── xml.md
│   └── yaml.md
├── pt-pt/
│   ├── bf.md
│   ├── git.md
│   ├── kotlin.md
│   ├── scala.md
│   └── swift.md
├── pug.md
├── purescript.md
├── pyqt.md
├── python.md
├── pythonlegacy.md
├── pythonstatcomp.md
├── qml.md
├── qsharp.md
├── qt.md
├── r.md
├── racket.md
├── raku-pod.md
├── raku.md
├── raylib.md
├── rdf.md
├── reason.md
├── red.md
├── rescript.md
├── rink.md
├── ro/
│   ├── bash.md
│   ├── bf.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── elixir.md
│   ├── haskell.md
│   ├── json.md
│   ├── latex.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   └── xml.md
├── rst.md
├── ru/
│   ├── asymptotic-notation.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── crystal.md
│   ├── css.md
│   ├── d.md
│   ├── dynamic-programming.md
│   ├── elixir.md
│   ├── erlang.md
│   ├── forth.md
│   ├── go.md
│   ├── haml.md
│   ├── haskell.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── linker.md
│   ├── lua.md
│   ├── markdown.md
│   ├── nim.md
│   ├── objective-c.md
│   ├── paren.md
│   ├── pascal.md
│   ├── perl.md
│   ├── php-composer.md
│   ├── php.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sql.md
│   ├── swift.md
│   ├── tcl.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── xml.md
│   ├── yaml.md
│   └── zfs.md
├── ruby-ecosystem.md
├── ruby.md
├── rust.md
├── sass.md
├── scala.md
├── sed.md
├── self.md
├── set-theory.md
├── shutit.md
├── sing.md
├── sk/
│   ├── bash.md
│   ├── coffeescript.md
│   ├── elixir.md
│   ├── git.md
│   ├── json.md
│   ├── latex.md
│   └── ruby.md
├── sl/
│   └── asciidoc.md
├── smallbasic.md
├── smalltalk.md
├── snobol.md
├── solidity.md
├── sorbet.md
├── sql.md
├── standard-ml.md
├── stylus.md
├── sv/
│   ├── bf.md
│   ├── haskell.md
│   ├── json.md
│   └── nix.md
├── swift.md
├── ta/
│   ├── css.md
│   ├── javascript.md
│   ├── json.md
│   └── xml.md
├── tailspin.md
├── tcl.md
├── tcsh.md
├── texinfo.md
├── textile.md
├── th/
│   ├── pascal.md
│   └── typescript.md
├── tmux.md
├── toml.md
├── tr/
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure.md
│   ├── csharp.md
│   ├── css.md
│   ├── dynamic-programming.md
│   ├── edn.md
│   ├── fsharp.md
│   ├── gdscript.md
│   ├── git.md
│   ├── html.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── kotlin.md
│   ├── markdown.md
│   ├── objective-c.md
│   ├── php.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── sql.md
│   ├── swift.md
│   └── typescript.md
├── typescript.md
├── uk/
│   ├── awk.md
│   ├── bash.md
│   ├── c.md
│   ├── cypher.md
│   ├── go.md
│   ├── java.md
│   ├── javascript.md
│   ├── json.md
│   ├── kotlin.md
│   ├── mips.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sql.md
│   ├── typescript.md
│   └── wasm.md
├── uxntal.md
├── v.md
├── vala.md
├── vi/
│   ├── git.md
│   ├── html.md
│   ├── json.md
│   ├── less.md
│   ├── markdown.md
│   ├── objective-c.md
│   ├── python.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── sass.md
│   ├── typescript.md
│   └── xml.md
├── vim.md
├── vim9script.md
├── vimscript.md
├── visualbasic.md
├── wasm.md
├── wikitext.md
├── wolfram.md
├── xml.md
├── yaml.md
├── zfs.md
├── zh-cn/
│   ├── angularjs.md
│   ├── asciidoc.md
│   ├── awk.md
│   ├── bash.md
│   ├── bc.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── cmake.md
│   ├── cobol.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── crystal.md
│   ├── csharp.md
│   ├── css.md
│   ├── dart.md
│   ├── docker.md
│   ├── dynamic-programming.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── erlang.md
│   ├── fortran.md
│   ├── fsharp.md
│   ├── gdscript.md
│   ├── git.md
│   ├── go.md
│   ├── groovy.md
│   ├── haskell.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── latex.md
│   ├── less.md
│   ├── livescript.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── mips.md
│   ├── nim.md
│   ├── nix.md
│   ├── objective-c.md
│   ├── opencv.md
│   ├── perl.md
│   ├── php.md
│   ├── powershell.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── r.md
│   ├── racket.md
│   ├── raylib.md
│   ├── red.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── set-theory.md
│   ├── solidity.md
│   ├── sql.md
│   ├── standard-ml.md
│   ├── swift.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── wolfram.md
│   ├── xml.md
│   ├── yaml.md
│   └── zfs.md
├── zh-tw/
│   ├── bash.md
│   ├── dart.md
│   ├── elixir.md
│   ├── javascript.md
│   ├── pcre.md
│   ├── perl.md
│   ├── pythonlegacy.md
│   └── typescript.md
└── zig.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
*.md linguist-language=Markdown linguist-detectable


================================================
FILE: .github/CODEOWNERS
================================================
/fr-fr/ @vendethiel
/ru-ru/ @Menelion
/uk-ua/ @Menelion
/zh-cn/ @geoffliu @imba-tjd
/zh-tw/ @geoffliu @imba-tjd
/ko-kr/ @justin-themedium
/pt-pt/ @mribeirodantas
/pt-br/ @mribeirodantas


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
## Is this a major issue that you cannot fix?

**Being a community driven documents of languages and tools,"YOUR" contributions
are also important.
If the issue you're reporting is trivial to report to maintainers why not contribute
to fix it. In that way, you will have contributed to an awesome open-source project.
The changes can be typo fix, fixing of data in examples or grammar fix. If you found it,
why not do it and take full credit for it?**

Make sure the issue title is prepended with '[language/lang-code]' if the language is
already on the site.
If it's a request for a new language, use: '[Request] [language/lang-code]'

Issues are always welcome. If you are able and willing, we welcome any pull requests
as this is a community powered project.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
- [ ] I solemnly swear that this is all original content of which I am the original author
- [ ] Pull request title is prepended with `[language/lang-code]` (example `[python/fr]` for Python in French or `[java]` for multiple Java translations)
- [ ] Pull request touches only one file (or a set of logically related files with similar changes made)
- [ ] Content changes are aimed at *intermediate to experienced programmers* (this is a poor format for explaining fundamental programming concepts)
- [ ] If you've changed any part of the YAML Frontmatter, make sure it is formatted according to [CONTRIBUTING.md](https://github.com/adambard/learnxinyminutes-docs/blob/master/CONTRIBUTING.md)


================================================
FILE: .github/workflows/build.yml
================================================
name: Trigger site build

on:
  push:
    branches: [main, master]

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.repository_owner == 'adambard'
    steps:
      - name: Trigger site build
        uses: peter-evans/repository-dispatch@v3
        with:
          token: ${{ secrets.PAT_LEARNXINYMINUTES_SITE }}
          repository: adambard/learnxinyminutes-site
          event-type: doc-update


================================================
FILE: .github/workflows/lint.yml
================================================
name: CI

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.13'
      - run: pip install -r lint/requirements.txt
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
      - run: gem install mdl

      - name: Files are UTF-8
        run: ./lint/encoding.sh .
      - name: "No non-breaking spaces"
        run: |
          if grep -rI --include='*.md' $'\u00A0' .; then
            exit 1
          fi
      - name: "No zero-width spaces"
        run: |
          if grep -rI --include='*.md' $'\u200B' .; then
            exit 1
          fi
      - name: "No carriage return"
        run: |
          if grep -rI --include='*.md' $'\u000D' .; then
            exit 1
          fi
      - name: "GitHub/JavaScript/TypeScript capitalized properly"
        run: |
          if grep -rI --include='*.md' -E "Github|Javascript|Typescript" .; then
            exit 1
          fi

      - name: Lint Markdown
        run: mdl . --ignore-front-matter -r MD003,MD005,MD011,MD018,MD019,MD023,MD025,MD027,MD028,MD030,MD035,MD037,MD038,MD039,MD046,MD047
      - name: Lint frontmatter
        run: ./lint/frontmatter.py .


================================================
FILE: .gitignore
================================================
**/*~
**/*#
**/#*#
**/*.swp
**/*.swo
**/*.bak
**/*.log*
**/*.sublime-workspace
**/.DS_Store
**/.DS_Store?
**/._*
**/.Spotlight-V100
**/.Trashes
**/ehthumbs.db
**/Thumbs.db
**/desktop.ini 

================================================
FILE: .mailmap
================================================
Leigh Brenecki <l@leigh.net.au> <adam@brenecki.id.au>

Adam Bard <github@adambard.com> Adam <adam@adambard.com>
Adam Bard <github@adambard.com> Adam Bard <adam@adambard.com>

ven <vendethiel@hotmail.fr> Nami-Doc <vendethiel@hotmail.fr>

Andre Polykanine <ap@oire.me> <andre@oire.org>
Andre Polykanine <ap@oire.me> <andre.polykanine@internations.org>

Divay Prakash <divayprakash3@gmail.com> <divayprakash@users.noreply.github.com>
Divay Prakash <divayprakash3@gmail.com> <divayprakash0@gmail.com>

Levi Bostian <levi.bostian@gmail.com> <levi.bostian@banno.com>

Pratik Karki <predatoramigo@gmail.com> <prertik@outlook.com>

Marcel Ribeiro-Dantas <ribeirodantasdm@gmail.com> <ribeirodantasdm@gmail.com>
Marcel Ribeiro-Dantas <ribeirodantasdm@gmail.com> <mribeirodantas@hey.com>
Marcel Ribeiro-Dantas <ribeirodantasdm@gmail.com> <marcel.ribeiro-dantas@curie.fr>
Marcel Ribeiro-Dantas <ribeirodantasdm@gmail.com> <mribeirodantas@seqera.io>
Marcel Ribeiro-Dantas <ribeirodantasdm@gmail.com> <marcel.ribeirodantas@seqera.io>

Geoff Liu <cangming.liu@gmail.com> <g@geoffliu.me>
Geoff Liu <cangming.liu@gmail.com> <hi@geoffliu.me>

sirkubax <muszynski@so1.net> <jakubxmuszynski@gmail.com>

caminsha <c.96marco@hotmail.com> <31421093+caminsha@users.noreply.github.com>

Samantha McVey <samantham@posteo.net>

Ian Bertolacci <ian.bertolacci@gmail.com> ian.bertolacci <ibertolacci@cray.com>

Boris Verkhovskiy <boris.verk@gmail.com>

Louie Dinh <LouieDinh@gmail.com> lodin <LouieDinh@gmail.com>

Milo Gilad <milogaccnts@gmail.com> Milo Gilad <Myl0g@users.noreply.github.com>

Yannick Loriot <yannick.loriot@gmail.com> Yannick <yannick.loriot@gmail.com>


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

All contributions are welcome, from the tiniest typo to a brand new article.
Translations in all languages are welcome (or, for that matter, original
articles in any language). Send a pull request or open an issue any time of day
or night.

**Please prepend the tag `[language/lang-code]` to your issues and pull
requests.** For example, `[python/en]` for English Python. This will help
everyone pick out things they care about.

We're happy for any contribution in any form, but if you're making more than one
major change (i.e. translations for two different languages) it would be super
cool of you to make a separate pull request for each one so that someone can
review them more effectively and/or individually.

## Style Guidelines

* **Keep lines under 80 chars**
   * Try to keep line length in code blocks to 80 characters or fewer.
   * Otherwise, the text will overflow and look odd.
   * This and other potential pitfalls to format the content consistently are
     identified by [markdownlint](https://github.com/markdownlint/markdownlint).
* **Prefer example to exposition**
   * Try to use as few words as possible.
   * Code examples are preferred over exposition in all cases.
* **Eschew surplusage**
   * We welcome newcomers, but the target audience for this site is programmers
     with some experience.
   * Try to avoid explaining basic concepts except for those specific to the
     language in question.
   * Keep articles succinct and scannable. We all know how to use Google here.
* **Use UTF-8**

### Header configuration

The actual site generates HTML files from these Markdown ones.
The markdown files can contain extra metadata before the actual markdown,
called frontmatter.

The following fields are necessary for English articles about programming
languages:

* `name`: The human-readable name of the programming language
* `contributors`: A list of [*author*, *URL*] lists to credit, *URL* is optional

Other fields:

* `category`: The category of the article. So far, can be one of *language*,
  *tool* or *Algorithms & Data Structures*. Defaults to *language* if omitted.
* `filename`: The filename for this article's code. It will be fetched, mashed
  together, and made downloadable.

Translations should also include:
* `translators`: A list of [*translator*, *URL*] lists to credit, *URL* is optional

Non-English articles inherit frontmatter values from the English article (if it exists)
but you can overwrite them.

Here's an example header for Ruby:

```yaml
---
name: Ruby
filename: learnruby.rb
contributors:
    - ["Doktor Esperanto", "http://example.com/"]
    - ["Someone else", "http://someoneelseswebsite.com/"]
---
```

### Syntax highlighter

[Pygments](https://pygments.org/languages/) is used for syntax highlighting.

### Should I add myself as a contributor?

If you want to add yourself to contributors, keep in mind that contributors get
equal billing, and the first contributor usually wrote the whole article. Please
use your judgment when deciding if your contribution constitutes a substantial
addition or not.

## Building the site locally

Install Python. On macOS this can be done with [Homebrew](https://brew.sh/).

```sh
brew install python
```

Then clone two repos, install dependencies and run.

```sh
# Clone website
git clone https://github.com/adambard/learnxinyminutes-site
# Clone docs (this repo) nested in website
git clone https://github.com/<YOUR-USERNAME>/learnxinyminutes-docs ./learnxinyminutes-site/source/docs/

# Install dependencies
cd learnxinyminutes-site
pip install -r requirements.txt

# Run
python build.py
cd build
python -m http.server

# open http://localhost:8000/ in your browser of choice
```


================================================
FILE: LICENSE.txt
================================================
Creative Commons Legal Code

Attribution-ShareAlike 3.0 Unported

    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
    LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
    INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
    REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
    DAMAGES RESULTING FROM ITS USE.

License

THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.

1. Definitions

 a. "Adaptation" means a work based upon the Work, or upon the Work and
    other pre-existing works, such as a translation, adaptation,
    derivative work, arrangement of music or other alterations of a
    literary or artistic work, or phonogram or performance and includes
    cinematographic adaptations or any other form in which the Work may be
    recast, transformed, or adapted including in any form recognizably
    derived from the original, except that a work that constitutes a
    Collection will not be considered an Adaptation for the purpose of
    this License. For the avoidance of doubt, where the Work is a musical
    work, performance or phonogram, the synchronization of the Work in
    timed-relation with a moving image ("synching") will be considered an
    Adaptation for the purpose of this License.
 b. "Collection" means a collection of literary or artistic works, such as
    encyclopedias and anthologies, or performances, phonograms or
    broadcasts, or other works or subject matter other than works listed
    in Section 1(f) below, which, by reason of the selection and
    arrangement of their contents, constitute intellectual creations, in
    which the Work is included in its entirety in unmodified form along
    with one or more other contributions, each constituting separate and
    independent works in themselves, which together are assembled into a
    collective whole. A work that constitutes a Collection will not be
    considered an Adaptation (as defined below) for the purposes of this
    License.
 c. "Creative Commons Compatible License" means a license that is listed
    at https://creativecommons.org/compatiblelicenses that has been
    approved by Creative Commons as being essentially equivalent to this
    License, including, at a minimum, because that license: (i) contains
    terms that have the same purpose, meaning and effect as the License
    Elements of this License; and, (ii) explicitly permits the relicensing
    of adaptations of works made available under that license under this
    License or a Creative Commons jurisdiction license with the same
    License Elements as this License.
 d. "Distribute" means to make available to the public the original and
    copies of the Work or Adaptation, as appropriate, through sale or
    other transfer of ownership.
 e. "License Elements" means the following high-level license attributes
    as selected by Licensor and indicated in the title of this License:
    Attribution, ShareAlike.
 f. "Licensor" means the individual, individuals, entity or entities that
    offer(s) the Work under the terms of this License.
 g. "Original Author" means, in the case of a literary or artistic work,
    the individual, individuals, entity or entities who created the Work
    or if no individual or entity can be identified, the publisher; and in
    addition (i) in the case of a performance the actors, singers,
    musicians, dancers, and other persons who act, sing, deliver, declaim,
    play in, interpret or otherwise perform literary or artistic works or
    expressions of folklore; (ii) in the case of a phonogram the producer
    being the person or legal entity who first fixes the sounds of a
    performance or other sounds; and, (iii) in the case of broadcasts, the
    organization that transmits the broadcast.
 h. "Work" means the literary and/or artistic work offered under the terms
    of this License including without limitation any production in the
    literary, scientific and artistic domain, whatever may be the mode or
    form of its expression including digital form, such as a book,
    pamphlet and other writing; a lecture, address, sermon or other work
    of the same nature; a dramatic or dramatico-musical work; a
    choreographic work or entertainment in dumb show; a musical
    composition with or without words; a cinematographic work to which are
    assimilated works expressed by a process analogous to cinematography;
    a work of drawing, painting, architecture, sculpture, engraving or
    lithography; a photographic work to which are assimilated works
    expressed by a process analogous to photography; a work of applied
    art; an illustration, map, plan, sketch or three-dimensional work
    relative to geography, topography, architecture or science; a
    performance; a broadcast; a phonogram; a compilation of data to the
    extent it is protected as a copyrightable work; or a work performed by
    a variety or circus performer to the extent it is not otherwise
    considered a literary or artistic work.
 i. "You" means an individual or entity exercising rights under this
    License who has not previously violated the terms of this License with
    respect to the Work, or who has received express permission from the
    Licensor to exercise rights under this License despite a previous
    violation.
 j. "Publicly Perform" means to perform public recitations of the Work and
    to communicate to the public those public recitations, by any means or
    process, including by wire or wireless means or public digital
    performances; to make available to the public Works in such a way that
    members of the public may access these Works from a place and at a
    place individually chosen by them; to perform the Work to the public
    by any means or process and the communication to the public of the
    performances of the Work, including by public digital performance; to
    broadcast and rebroadcast the Work by any means including signs,
    sounds or images.
 k. "Reproduce" means to make copies of the Work by any means including
    without limitation by sound or visual recordings and the right of
    fixation and reproducing fixations of the Work, including storage of a
    protected performance or phonogram in digital form or other electronic
    medium.

2. Fair Dealing Rights. Nothing in this License is intended to reduce,
limit, or restrict any uses free from copyright or rights arising from
limitations or exceptions that are provided for in connection with the
copyright protection under copyright law or other applicable laws.

3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:

 a. to Reproduce the Work, to incorporate the Work into one or more
    Collections, and to Reproduce the Work as incorporated in the
    Collections;
 b. to create and Reproduce Adaptations provided that any such Adaptation,
    including any translation in any medium, takes reasonable steps to
    clearly label, demarcate or otherwise identify that changes were made
    to the original Work. For example, a translation could be marked "The
    original work was translated from English to Spanish," or a
    modification could indicate "The original work has been modified.";
 c. to Distribute and Publicly Perform the Work including as incorporated
    in Collections; and,
 d. to Distribute and Publicly Perform Adaptations.
 e. For the avoidance of doubt:

     i. Non-waivable Compulsory License Schemes. In those jurisdictions in
        which the right to collect royalties through any statutory or
        compulsory licensing scheme cannot be waived, the Licensor
        reserves the exclusive right to collect such royalties for any
        exercise by You of the rights granted under this License;
    ii. Waivable Compulsory License Schemes. In those jurisdictions in
        which the right to collect royalties through any statutory or
        compulsory licensing scheme can be waived, the Licensor waives the
        exclusive right to collect such royalties for any exercise by You
        of the rights granted under this License; and,
   iii. Voluntary License Schemes. The Licensor waives the right to
        collect royalties, whether individually or, in the event that the
        Licensor is a member of a collecting society that administers
        voluntary licensing schemes, via that society, from any exercise
        by You of the rights granted under this License.

The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights in
other media and formats. Subject to Section 8(f), all rights not expressly
granted by Licensor are hereby reserved.

4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:

 a. You may Distribute or Publicly Perform the Work only under the terms
    of this License. You must include a copy of, or the Uniform Resource
    Identifier (URI) for, this License with every copy of the Work You
    Distribute or Publicly Perform. You may not offer or impose any terms
    on the Work that restrict the terms of this License or the ability of
    the recipient of the Work to exercise the rights granted to that
    recipient under the terms of the License. You may not sublicense the
    Work. You must keep intact all notices that refer to this License and
    to the disclaimer of warranties with every copy of the Work You
    Distribute or Publicly Perform. When You Distribute or Publicly
    Perform the Work, You may not impose any effective technological
    measures on the Work that restrict the ability of a recipient of the
    Work from You to exercise the rights granted to that recipient under
    the terms of the License. This Section 4(a) applies to the Work as
    incorporated in a Collection, but this does not require the Collection
    apart from the Work itself to be made subject to the terms of this
    License. If You create a Collection, upon notice from any Licensor You
    must, to the extent practicable, remove from the Collection any credit
    as required by Section 4(c), as requested. If You create an
    Adaptation, upon notice from any Licensor You must, to the extent
    practicable, remove from the Adaptation any credit as required by
    Section 4(c), as requested.
 b. You may Distribute or Publicly Perform an Adaptation only under the
    terms of: (i) this License; (ii) a later version of this License with
    the same License Elements as this License; (iii) a Creative Commons
    jurisdiction license (either this or a later license version) that
    contains the same License Elements as this License (e.g.,
    Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible
    License. If you license the Adaptation under one of the licenses
    mentioned in (iv), you must comply with the terms of that license. If
    you license the Adaptation under the terms of any of the licenses
    mentioned in (i), (ii) or (iii) (the "Applicable License"), you must
    comply with the terms of the Applicable License generally and the
    following provisions: (I) You must include a copy of, or the URI for,
    the Applicable License with every copy of each Adaptation You
    Distribute or Publicly Perform; (II) You may not offer or impose any
    terms on the Adaptation that restrict the terms of the Applicable
    License or the ability of the recipient of the Adaptation to exercise
    the rights granted to that recipient under the terms of the Applicable
    License; (III) You must keep intact all notices that refer to the
    Applicable License and to the disclaimer of warranties with every copy
    of the Work as included in the Adaptation You Distribute or Publicly
    Perform; (IV) when You Distribute or Publicly Perform the Adaptation,
    You may not impose any effective technological measures on the
    Adaptation that restrict the ability of a recipient of the Adaptation
    from You to exercise the rights granted to that recipient under the
    terms of the Applicable License. This Section 4(b) applies to the
    Adaptation as incorporated in a Collection, but this does not require
    the Collection apart from the Adaptation itself to be made subject to
    the terms of the Applicable License.
 c. If You Distribute, or Publicly Perform the Work or any Adaptations or
    Collections, You must, unless a request has been made pursuant to
    Section 4(a), keep intact all copyright notices for the Work and
    provide, reasonable to the medium or means You are utilizing: (i) the
    name of the Original Author (or pseudonym, if applicable) if supplied,
    and/or if the Original Author and/or Licensor designate another party
    or parties (e.g., a sponsor institute, publishing entity, journal) for
    attribution ("Attribution Parties") in Licensor's copyright notice,
    terms of service or by other reasonable means, the name of such party
    or parties; (ii) the title of the Work if supplied; (iii) to the
    extent reasonably practicable, the URI, if any, that Licensor
    specifies to be associated with the Work, unless such URI does not
    refer to the copyright notice or licensing information for the Work;
    and (iv) , consistent with Ssection 3(b), in the case of an
    Adaptation, a credit identifying the use of the Work in the Adaptation
    (e.g., "French translation of the Work by Original Author," or
    "Screenplay based on original Work by Original Author"). The credit
    required by this Section 4(c) may be implemented in any reasonable
    manner; provided, however, that in the case of a Adaptation or
    Collection, at a minimum such credit will appear, if a credit for all
    contributing authors of the Adaptation or Collection appears, then as
    part of these credits and in a manner at least as prominent as the
    credits for the other contributing authors. For the avoidance of
    doubt, You may only use the credit required by this Section for the
    purpose of attribution in the manner set out above and, by exercising
    Your rights under this License, You may not implicitly or explicitly
    assert or imply any connection with, sponsorship or endorsement by the
    Original Author, Licensor and/or Attribution Parties, as appropriate,
    of You or Your use of the Work, without the separate, express prior
    written permission of the Original Author, Licensor and/or Attribution
    Parties.
 d. Except as otherwise agreed in writing by the Licensor or as may be
    otherwise permitted by applicable law, if You Reproduce, Distribute or
    Publicly Perform the Work either by itself or as part of any
    Adaptations or Collections, You must not distort, mutilate, modify or
    take other derogatory action in relation to the Work which would be
    prejudicial to the Original Author's honor or reputation. Licensor
    agrees that in those jurisdictions (e.g. Japan), in which any exercise
    of the right granted in Section 3(b) of this License (the right to
    make Adaptations) would be deemed to be a distortion, mutilation,
    modification or other derogatory action prejudicial to the Original
    Author's honor and reputation, the Licensor will waive or not assert,
    as appropriate, this Section, to the fullest extent permitted by the
    applicable national law, to enable You to reasonably exercise Your
    right under Section 3(b) of this License (right to make Adaptations)
    but not otherwise.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

 a. This License and the rights granted hereunder will terminate
    automatically upon any breach by You of the terms of this License.
    Individuals or entities who have received Adaptations or Collections
    from You under this License, however, will not have their licenses
    terminated provided such individuals or entities remain in full
    compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
    survive any termination of this License.
 b. Subject to the above terms and conditions, the license granted here is
    perpetual (for the duration of the applicable copyright in the Work).
    Notwithstanding the above, Licensor reserves the right to release the
    Work under different license terms or to stop distributing the Work at
    any time; provided, however that any such election will not serve to
    withdraw this License (or any other license that has been, or is
    required to be, granted under the terms of this License), and this
    License will continue in full force and effect unless terminated as
    stated above.

8. Miscellaneous

 a. Each time You Distribute or Publicly Perform the Work or a Collection,
    the Licensor offers to the recipient a license to the Work on the same
    terms and conditions as the license granted to You under this License.
 b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
    offers to the recipient a license to the original Work on the same
    terms and conditions as the license granted to You under this License.
 c. If any provision of this License is invalid or unenforceable under
    applicable law, it shall not affect the validity or enforceability of
    the remainder of the terms of this License, and without further action
    by the parties to this agreement, such provision shall be reformed to
    the minimum extent necessary to make such provision valid and
    enforceable.
 d. No term or provision of this License shall be deemed waived and no
    breach consented to unless such waiver or consent shall be in writing
    and signed by the party to be charged with such waiver or consent.
 e. This License constitutes the entire agreement between the parties with
    respect to the Work licensed here. There are no understandings,
    agreements or representations with respect to the Work not specified
    here. Licensor shall not be bound by any additional provisions that
    may appear in any communication from You. This License may not be
    modified without the mutual written agreement of the Licensor and You.
 f. The rights granted under, and the subject matter referenced, in this
    License were drafted utilizing the terminology of the Berne Convention
    for the Protection of Literary and Artistic Works (as amended on
    September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
    Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
    and the Universal Copyright Convention (as revised on July 24, 1971).
    These rights and subject matter take effect in the relevant
    jurisdiction in which the License terms are sought to be enforced
    according to the corresponding provisions of the implementation of
    those treaty provisions in the applicable national law. If the
    standard suite of rights granted under applicable copyright law
    includes additional rights not granted under this License, such
    additional rights are deemed to be included in the License; this
    License is not intended to restrict the license of any rights under
    applicable law.


Creative Commons Notice

    Creative Commons is not a party to this License, and makes no warranty
    whatsoever in connection with the Work. Creative Commons will not be
    liable to You or any party on any legal theory for any damages
    whatsoever, including without limitation any general, special,
    incidental or consequential damages arising in connection to this
    license. Notwithstanding the foregoing two (2) sentences, if Creative
    Commons has expressly identified itself as the Licensor hereunder, it
    shall have all rights and obligations of Licensor.

    Except for the limited purpose of indicating to the public that the
    Work is licensed under the CCPL, Creative Commons does not authorize
    the use by either party of the trademark "Creative Commons" or any
    related trademark or logo of Creative Commons without the prior
    written consent of Creative Commons. Any permitted use will be in
    compliance with Creative Commons' then-current trademark usage
    guidelines, as may be published on its website or otherwise made
    available upon request from time to time. For the avoidance of doubt,
    this trademark restriction does not form part of the License.

    Creative Commons may be contacted at https://creativecommons.org/.


================================================
FILE: README.md
================================================
# [Learn X in Y minutes][1]

Whirlwind tours of (several, hopefully many someday) popular and
ought-to-be-more-popular programming languages, presented as valid, commented
code and explained as they go.

## We need YOU!...

... to write more inline code tutorials. Just grab an existing file from this
repo and copy the formatting (don't worry, it's all very simple). Make a new
file, send a pull request, and if it passes muster I'll get it up pronto.
Remember to fill in the "contributors" fields so you get credited properly!

## Contributing

All contributions are welcome, from the tiniest typo to a brand new article.
Translations in all languages are welcome (or, for that matter, original
articles in any language). Send a pull request or open an issue any time of day
or night.

**Please prepend the tag `[language/lang-code]` to your issues and pull
requests.** For example, `[python/en]` for English Python. This will help
everyone pick out things they care about.

We're happy for any contribution in any form, but if you're making more than one
major change (i.e. translations for two different languages) it would be super
cool of you to make a separate pull request for each one so that someone can
review them more effectively and/or individually.

For a detailed style guide, please review the full [CONTRIBUTING][2] guidelines.

## License

Contributors retain copyright to their work, and can request removal at any
time. By uploading a doc here, you agree to publish your work under the default
[Creative Commons Attribution-ShareAlike 3.0 Unported][3] licensing included on
each doc page.

Anything not covered by the above -- basically, this README -- you can use as
you wish, I guess.


[1]: https://learnxinyminutes.com
[2]: /CONTRIBUTING.md
[3]: http://creativecommons.org/licenses/by-sa/3.0/deed.en_US


================================================
FILE: ada.md
================================================
---
name: Ada
filename: learn.ada
contributors:
    - ["Luke A. Guest", "https://github.com/Lucretia"]
    - ["Fernando Oleo Blanco", "https://github.com/Irvise"]
    - ["Fabien Chouteau", "https://github.com/Fabien-Chouteau"]
    - ["Manuel", "https://github.com/mgrojo"]
---

Ada is a strong statically typed imperative, [object-oriented](https://ada-lang.io/docs/arm/AA-3/AA-3.9), [real-time](https://ada-lang.io/docs/arm/AA-D), [parallel](https://ada-lang.io/docs/arm/AA-9) and [distributed](https://ada-lang.io/docs/arm/AA-9) programming language from the Pascal/Algol family of languages, but nowadays, it only has a passing resemblance to Pascal, with the only remnants left being the ```begin/end``` keyword pair, the ```:=``` assignment symbol, records and ```if/case``` control statement structures.

Ada was originally designed to be an [object-based](https://ada-lang.io/docs/arm/AA-3/AA-3.3) language and to replace 100's of languages in use by the US government. This means that all entities are objects, not in the object-oriented sense. The language became [Object-Oriented](https://ada-lang.io/docs/arm/AA-3/AA-3.9) in 1995, and added [interfaces](https://ada-lang.io/docs/arm/AA-3/AA-3.9#Subclause_3.9.4) derived from Java in 2005. [Contract based](https://ada-lang.io/docs/arm/AA-13/AA-13.1#Subclause_13.1.1) programming was introduced with Ada 2012.

Ada was designed to be easy to read and learn, even for non-programmers, e.g. management within an organisation, therefore programs written in the language tend to be a bit more verbose.

Ada is a modern programming language, and now has a package manager like other modern languages, Alire, see below.

```ada
--  Comments are written with a double hyphen and exist until the end of
--  the line.

--  You do not need to call the entry point "Main" or "main," you should
--  name it based on what the program does.
procedure Empty is
   --  This is a declarative part.
begin
   --  Statements go here.
   null;  --  Do nothing here.
end Empty;

--  Ada compilers accept compilation units which can be library packages,
--  tasks, sub-programs, generics, etc.

--  This is where "context clauses" go, these can be pragmas or "with"
--  statements. "with" is equivalent to "include" or "import" in other
--  languages.
with Ada.Text_IO;  --  Get access to a library package.

procedure Hello is
begin
   Ada.Text_IO.Put_Line ("Hello, world");

   Ada.Text_IO.Put ("Hello again, world");
   Ada.Text_IO.New_Line;
end Hello;


--  Ada has a real module system. Modules are called packages and are split into
--  two component parts, the specification and a body.
--  It is important to introduce packages early, as you will be using them from
--  the start.
package Stuff is
   --  We could add the following line in order to tell the compiler that this
   --  package does not have to run any code before the "main" procedure starts.
   --  pragma Preelaborate;

   --  Packages can be nested within the same file or externally.
   --  Nested packages are accessed via dot notation, e.g. Stuff.Things.My.
   package Things is
      My : constant Integer := 100;
   end Things;

   --  If there are sub-programs declared within the specification, the body
   --  of the sub-program must be declared within the package body.
   procedure Do_Something;  --  If a subprogram takes no parameters, empty
                            --  parentheses are not required, unlike other
                            --  languages.

   --  We can also make generic sub-programs.
   generic
      type Element is (<>);  --  The "(<>)" notation specifies that only
                             --  discrete types can be passed into the generic.
   procedure Swap (Left, Right : in out Element);

   --  Sometimes we want to hide how a type is defined from the outside world
   --  so that nobody can mess with it directly. The full type must be defined
   --  within the private section below.
   type Blobs is private;

   --  We can also make types "limited" by putting this keyword after the "is"
   --  keyword, this means that the user cannot copy objects of that type
   --  around, like they normally could.
private
   type Blobs is new Integer range -25 .. 25;
end Stuff;


package body Stuff is
   --  Sub-program body.
   procedure Do_Something is
      --  We can nest sub-programs too.
      --  Parameters are defined with the direction of travel, in, in out, out.
      --  If the direction of travel is not specified, they are in by default.
      function Times_4 (Value : in Integer) return Integer is
      begin
         return Value * 4;
      end Times_4;

      I : Integer := 4;
   begin
      I := Times_4 (I);
   end Do_Something;


   --  Generic procedure body.
   procedure Swap (Left, Right : in out Element) is
      Temp : Element := Left;
   begin
      Left  := Right;
      Right := Temp;
   end Swap;
begin
   --  If we need to initialise something within the package, we can do it
   --  here.
   Do_Something;
end Stuff;


with Ada.Unchecked_Conversion;
with Ada.Text_IO;
with Stuff;

procedure LearnAdaInY is
   --  Indentation is 3 spaces.

   --  The most important feature in Ada is the type. Objects have types and an
   --  object of one type cannot be assigned to an object of another type.

   --  You can, and should, define your own types for the domain you are
   --  modelling. But you can use the standard types to start with and then
   --  replace them later with your own types, this could be called a form of
   --  gradual typing.

   --  The standard types would only really be a good starting point for binding
   --  to other languages, like C. Ada is the only language with a standardised
   --  way to bind with C, Fortran and COBOL! See the links in the References
   --  section with more information on binding to these languages.

   type Degrees is range 0 .. 360;  --  This is a type. Its underlying
                                    --  representation is an Integer.

   type Hues is (Red, Green, Blue, Purple, Yellow);  --  So is this. Here, we
                                                     --  are declaring an
                                                     --  Enumeration.

   --  This is a modular type. They behave like Integers that automatically
   --  wrap around. In this specific case, the range would be 0 .. 359.
   --  If we added 1 to a variable containing the value 359, we would receive
   --  back 0. They are very useful for arrays.
   type Degrees_Wrap is mod 360;

   --  You can restrict a type's range using a subtype, this makes them
   --  compatible with each other, i.e. the subtype can be assigned to an
   --  object of the type, as can be seen below.
   subtype Primaries is Hues range Red .. Blue;  --  This is a range.

   --  You can define variables or constants like this:
   --  Var_Name : Type := Value;

   --  10 is a universal integer. These universal numerics can be used with
   --  any type which matches the base type.
   Angle : Degrees := 10;
   Value : Integer := 20;
   --  New_Angle : Degrees := Value;  --  Incompatible types won't compile.
   --  New_Value : Integer := Angle;

   Blue_Hue   :          Primaries := Blue;  --  A variable.
   Red_Hue    : constant Primaries := Red;   --  A constant.
   Yellow_Hue : constant Hues      := Yellow;
   Colour_1   : constant Hues      := Red_Hue;
   --  Colour_2   : constant Primaries := Yellow_Hue;  --  uncomment to compile.

   --  You can force conversions, but then you are warned by the name of the
   --  package that you may be doing something unsafe.
   function Degrees_To_Int is new Ada.Unchecked_Conversion
     (Source => Degrees,   --  Line continuations are indented by 2 spaces.
      Target => Integer);

   New_Value_2 : Integer := Degrees_To_Int (Angle);  --  Note, space before (.

   --  GNAT is the GNU Ada Translator (compiler).
   --  Ada has a style guide and GNAT will warn you to adhere to it, and has
   --  option to check your style so that you can correct it so that all Ada
   --  source looks consistent. However, the style can be customized.

   --  Yes, you can even define your own floating and fixed point types, this
   --  is a very rare and unique ability. "digits" refers to the minimum
   --  digit precision that the type should support. "delta" is for fixed
   --  point types and refers to the smallest change that the type will support.
   type Real_Angles is digits 3 range 0.0 .. 360.0;
   type Fixed_Angles is delta 0.01 digits 5 range 0.0 .. 360.0;

   RA : constant Real_Angles  := 36.45;
   FA : constant Fixed_Angles := 360.0;  --  ".0" in order to make it a Float.

   --  You can have normal Latin 1 based strings by default.
   Str  : constant String    := "This is a constant string";
   --  When initialising from a string literal, the compiler knows the bounds,
   --  so we don't have to define them.

   --  Strings are arrays. Note how parentheses are used to access elements of
   --  an array? This is mathematical notation and was used because square
   --  brackets were not available on all keyboards at the time Ada was
   --  created. Also, because an array can be seen as a function from a
   --  mathematical perspective, so it made converting between arrays and
   --  functions easier.
   Char : constant Character := Str (Str'First);  --  "'First" is a type
                                                  --  attribute.

   --  Ada 2022 includes the use of [] for array initialisation when using
   --  containers, which were added in Ada 2012.

   --  Arrays are usually always defined as a type.
   --  They can be any dimension.
   type My_Array_1 is array (1 .. 4, 3 .. 7, -20 .. 20) of Integer;

   --  Yes, unlike other languages, you can index arrays with other discrete
   --  types such as enumerations and modular types or arbitrary ranges.
   type Axes is (X, Y, Z);

   --  You can define the array's range using the 'Range attribute from
   --  another type.
   type Vector is array (Axes'Range) of Float;

   V1 : constant Vector := (0.0, 0.0, 1.0);

   --  A record is the same as a structure in C, C++.
   type Entities is record
      Name     : String (1 .. 10);  --  Always starts at a positive value,
                                    --  inclusive range.
      Position : Vector;
   end record;

   --  In Ada, array bounds are immutable. You therefore have to provide a
   --  string literal with a value for every character.
   E1 : constant Entities := ("Blob      ", (0.0, 0.0, 0.0));

   --  An alternative is to use an array aggregate and assign a default value
   --  to every element that wasn't previously assigned in this aggregate.
   --  "others" is used to indicate anything else that has not been
   --  explicitly initialized.
   E2 : constant Entities := (('B', 'l', 'o', 'b', others => ' '),
                              (0.0, 0.0, 0.0));

   --  There are dynamic length strings (see references section) available in
   --  the standard library.

   --  We can make an object be initialised to its default values with the box
   --  notation, "<>". "others" is used to indicate anything else that has not
   --  been explicitly initialized.
   Null_Entity : constant Entities := (others => <>);

   --  Object-orientation is accomplished via an extension of record syntax,
   --  tagged records, see link above in first paragraph.

   --  We can rename objects (aliases) to make readability a bit better.
   package IO renames Ada.Text_IO;
begin
   --  We can output enumerations as names.
   IO.Put_Line ("Blue_Hue   = " &  --  & is the string concatenation operator.
                Blue'Image);       --  ' accesses attributes on objects.
                  --  The Image attribute converts a value to a string.
                  --  Ada 2022 has extended Image to custom types too.
                  --  Access this with -gnat2022 compiler flag.
   IO.Put_Line ("Yellow_Hue = " &
                --  We can use the type's attribute.
                Primaries'Image (Yellow_Hue));

   --  We can define local variables within a declare block, this can be made
   --  more readable by giving it a label.
   Enum_IO : declare
      package Hue_IO is new IO.Enumeration_IO (Hues);

      --  Using a package makes everything inside that package visible within
      --  this block, it is good practice to only do this locally and not on
      --  a whole package within the context clause.
      use Hue_IO;
   begin
      --  We can print out the enumeration values too.
      Put (Purple); --  Note we don't have to prefix the Put procedure with
                    --  Hue_IO.
      IO.New_Line;  --  We still need to prefix with IO here.
      Put (Red_Hue);
      IO.New_Line;
   end Enum_IO;

   --  Loops have a consistent form. "<form> loop ... end loop".
   --  Where "form" can be "while" or "for" or missing as below, if
   --  you place the "loop ... end loop;" construct on their own lines,
   --  you can comment out or experiment with different loop constructs more
   --  easily.
   declare
      Counter : Positive := Positive'First;  --  This is 1.
   begin
      --  We can label loops so we can exit from them more easily if we need to.
      Infinite :
      loop
         IO.Put_Line ("[Infinite loop] Counter = " & Counter'Image);

         Counter := Counter + 1;

         --  This next line implements a repeat ... until or do ... while loop construct.
         --  Comment it out for an infinite loop.
         exit Infinite when Counter = 5;  --  Equality tests use a single "=".
      end loop Infinite;  --  Useful when implementing state machines.
   end;

   declare  --  We don't have to have a label.
      Counter : Positive := Positive'First;  --  This is 1.
   begin
      while Counter < 10
      loop
         IO.Put_Line ("Counter = " & Counter'Image);

         Counter := Counter + 1;  --  There is no explicit inc/decrement.

         --  Ada 2022 introduced @ for LHS, so the above would be written as
         --  Counter := @ + 1;  --  Try it, -gnat2022.
      end loop;
   end;

   declare
      package Hue_IO is new IO.Enumeration_IO (Hues);

      --  We can have multiple packages on one line, but I tend to use one
      --  package per line for readability.
      use IO, Hue_IO;
   begin
      Put ("Hues : ");  --  Note, no prefix.

      --  Because we are using the 'Range attribute, the compiler knows it is
      --  safe and can omit run-time checks here.
      for Hue in Hues'Range
      loop
         Put (Hue);

         --  Types and objects know about their bounds, their First .. Last
         --  values. These can be specified as range types.
         if Hue /= Hues'Last then  --  The /= means "not equal to" like the
                                   --  maths symbol ≠.
            Put (", ");
         end if;
      end loop;

      IO.New_Line;
   end;

   --  All objects know their bounds, including strings.
   declare
      C : Character := Str (50);  --  Warning caused and exception raised at
                                  --  runtime.
      --  The exception raised above can only be handled by an outer scope,
      --  see wikibook link below.
   begin
      null;  --  We will never get to this point because of the above.
   end;
exception
   when Constraint_Error =>
      IO.Put_Line ("Caught the exception");
end LearnAdaInY;
```

Now, that's a lot of information for a basic intro to Ada, and I've only touched the surface, there's much more to look at in the references section below. I haven't even touched on dynamic memory allocation which includes [pools](https://ada-lang.io/docs/arm/AA-13/AA-13.11), this is because for the most part, Ada programs don't need it, you can do a lot without it.

As I stated above, Ada barely looks like Pascal and if you look at the original [Green specification](https://apps.dtic.mil/sti/trecms/pdf/ADB950587.pdf) (Warning: Huge 4575 page scanned PDF - starting on page 460), it looks nothing like it at all (page 505 of that PDF).

The above source code will compile, but also will give warnings showing the power of the strong static type system.

## Download this source

If you already have the GNAT toolchain installed, you can cut and paste the above into a new file, e.g. ```learn-ada-in-y.ada``` and then run the following:

```bash
$ gnatchop learn-ada-in-y.ada # This breaks the program into its specification ".ads" and body ".adb".
$ gnatmake empty.adb # gnatmake takes care of compilation of all units and linking.
$ gnatmake hello.adb
$ gnatmake learnadainy.adb
```

Or, download [Alire](https://alire.ada.dev), copy it to somewhere in your PATH and then do the following:

**N.B.** Alire will automatically install the toolchain for you if you don't have one installed and will ask you to select which you want to use.

```bash
$ alr search learnadainy
$ alr get learnadainy
$ cd learnadainy
$ alr run empty
$ alr run hello
$ alr run learnadainy
```

## Further Reading

* [Ada Programming Language](https://ada-lang.io)
* [Ada 2022 Reference Manual](https://ada-lang.io/docs/arm)
* [Ada Style Guide](https://ada-lang.io/docs/style-guide/Ada_Style_Guide)
* [Learn more Ada/Spark at AdaCore's site](https://learn.adacore.com)

## References from the source above

1. [wikibook](https://en.wikibooks.org/wiki/Ada_Programming/Exceptions#Exception_handlers)
2. [C](https://ada-lang.io/docs/arm/AA-B/AA-B.3)
3. [Fortran](https://ada-lang.io/docs/arm/AA-B/AA-B.5/)
4. [COBOL](https://ada-lang.io/docs/arm/AA-B/AA-B.4/)
5. [dynamic length strings](https://ada-lang.io/docs/arm/AA-A/AA-A.4#Subclause_A.4.5)

### Multi-line comments

Multi-line comments are not allowed as they are error prone.

> Such comments would require a closing comment delimiter and this would again raise the dangers associated with the (unintentional) omission of the closing delimiter: entire sections of a program could be ignored by the compiler without the programmer realizing it
>
> [Ada 83 Rationale](http://archive.adaic.com/standards/83rat/html/ratl-02-01.html#2.1)



================================================
FILE: agda.md
================================================
---
name: Agda
filename: learnagda.agda
contributors:
    - ["pe200012", "https://github.com/pe200012"]
---

Agda is a dependently typed functional programming language. It is an
extension of Martin-Löf's Type Theory. In Agda, programs and proofs are
written in the same language. In Agda, there is no separation between types
and values: types can depend on values, and values can act as types. This
allows you to encode logical invariants (like the length of a vector)
directly into the type system, making Agda a powerful tool for both
programming and theorem proving.

Agda is heavily reliant on Unicode characters. Most editors (like Emacs or VS Code) support entering these via LaTeX-like abbreviations (e.g., `\to` for `→`, `\all` for `∀`, `\bN` for `ℕ`).

To install Agda, you typically use Haskell's cabal or stack. See the [wiki](https://wiki.portal.chalmers.se/agda/pmwiki.php) for details.

```agda
-- A module must have the same name as the file (excluding .agda)
module learnagda where

-- We can import other modules.
-- Agda's standard library is commonly used, but here we will define
-- the basics from scratch for educational purposes.

-- Agda is a dependently typed functional programming language.
-- It is strictly total:
--   all programs must terminate, and all patterns must be matched.
-- Agda logic relies heavily on the Curry-Howard correspondence:
--   Propositions are Types
--   Proofs are Programs

-- Comments use double dashes for single lines.
{- Multi-line comments are enclosed in braces and hyphens. -}

-- Agda uses Unicode extensively.
-- In the Emacs mode (or VS Code), you type these using LaTeX-like shortcuts:
-- \to      →
-- \bN      ℕ
-- \==      ≡
-- \all     ∀
-- \::      ∷

--------------------------------------------------------------------------------
-- Datatypes and Pattern Matching
--------------------------------------------------------------------------------

-- 'Set' is the type of types (similar to 'Type' in other languages).
-- We define Booleans as an inductive data type.
data Bool : Set where
  true  : Bool
  false : Bool

-- We can define functions using pattern matching.
-- 'not' takes a Bool and returns a Bool.
not : Bool → Bool  -- The type signature is mandatory.
not true  = false
not false = true

-- Natural numbers (Peano encoding).
-- This defines an infinite set of terms: zero, suc zero,
-- suc (suc zero), ...
data ℕ : Set where
  zero : ℕ
  suc  : ℕ → ℕ

-- We can tell Agda to treat ℕ as normal numbers for literals
-- by using a pragma.
{-# BUILTIN NATURAL ℕ #-}

-- Addition defined recursively.
-- Underscores denote where the arguments go for infix operators.
-- This is Agda's "Mixfix" notation. You can put underscores anywhere!
_+_ : ℕ → ℕ → ℕ
zero  + n = n
suc m + n = suc (m + n)

-- We can define precedence for operators.
infixl 6 _+_

-- Example evaluation:
-- 2 + 3 = 5
-- To verify this in an editor:
-- Type "2 + 3", select it, and press C-c C-n (Compute Normal Form).

-- Mixfix examples:
-- if_then_else_ : Bool → A → A → A
-- if true then x else y

--------------------------------------------------------------------------------
-- Interaction and Holes
--------------------------------------------------------------------------------

-- Before introducing other concepts, we need to introduce 'holes'.

-- Agda development is interactive.
-- You write types, and the system helps fill terms.
-- A question mark ? or {! !} creates a "hole".

-- example : 2 + 2 ≡ 4
-- example = ?

-- While in Emacs/VS Code:
-- C-c C-l : Load file (type checks).
-- C-c C-space : Given a hole, ask Agda to fill it (Auto).
-- C-c C-r : Refine. If the hole is for a data type,
-- splits constructors.
-- C-c C-, : Goal type and context. Tells you what you need to prove.

-- POP QUIZ: Define multiplication for natural numbers.
-- Hint: split cases, and then do induction.
_*_ : ℕ → ℕ → ℕ
x * y = ?

--------------------------------------------------------------------------------
-- Polymorphism and Variables
--------------------------------------------------------------------------------

-- In modern Agda, we can declare generalizable variables to avoid
-- repetitive `forall` syntax in type signatures.
variable
  A B : Set
  n m : ℕ

-- Lists are parameterized by a type A.
infixr 5 _::_
data List (A : Set) : Set where
  []   : List A                -- Empty list
  _::_ : A → List A → List A   -- Cons constructor

-- A list of numbers: 1 :: 2 :: 3 :: []
nums : List ℕ
nums = 1 :: 2 :: 3 :: []

-- Map function showing explicit universe polymorphism (optional)
-- Here we use implicit arguments (denoted by { }).
-- Agda infers them from context.
-- ∀ {A B} makes A and B implicit type variables.
map : ∀ {A B : Set} → (A → B) → List A → List B
map f []        = []
map f (x :: xs) = f x :: map f xs

-- Anonymous functions (lambdas)
-- We can write `λ x → x + 1`
plus1 : ℕ → ℕ
plus1 = λ x → x + 1

--------------------------------------------------------------------------------
-- Dependent Types
--------------------------------------------------------------------------------

-- Dependent types allow types to depend on values.
-- A classic example is a Vector: a list with a fixed length
-- encoded in its type.

data Vec (A : Set) : ℕ → Set where
  []   : Vec A zero
  _::_ : ∀ {n} → A → Vec A n → Vec A (suc n)

-- If we try to create a vector with the wrong length, it's a type error.
vec3 : Vec ℕ 3
vec3 = 1 :: 2 :: 3 :: []

-- Because the length is known, we can define 'safe' operations.
-- This function cannot be called on an empty vector.
head : Vec A (suc n) → A
head (x :: xs) = x

-- We can calculate the exact type of a concatenation.
_++_ : Vec A n → Vec A m → Vec A (n + m)
[]       ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)

--------------------------------------------------------------------------------
-- Equality and Proofs
--------------------------------------------------------------------------------

-- The identity type (equality) is the heart of proving in Agda.
-- x ≡ y is a type that has a value only if x and y are the same normal form.
infix 4 _≡_
data _≡_ {A : Set} (x : A) : A → Set where
  refl : x ≡ x
{-# BUILTIN EQUALITY _≡_ #-}

-- PROOFS ARE PROGRAMS
-- To prove a property, we write a function that produces a value of that type.

-- Proving 1 + 1 equals 2.
1+1≡2 : 1 + 1 ≡ 2
1+1≡2 = refl

-- Congruence: applying a function to equal values yields equal results.
cong : ∀ {A B : Set} (f : A → B) {x y : A}
  → x ≡ y → f x ≡ f y
cong f refl = refl

-- Symmetry
sym : ∀ {A : Set} {x y : A} → x ≡ y → y ≡ x
sym refl = refl

-- Transitivity
trans : ∀ {A : Set} {x y z : A} → x ≡ y → y ≡ z → x ≡ z
trans refl refl = refl

-- Proving associativity of addition.
-- This requires induction on x.
-- We split cases on x.
-- If x is zero: zero + (y + z) ≡ zero + y + z
-- reduces to y + z ≡ y + z.
-- If x is suc x: we use the inductive hypothesis (recursion).
+-assoc : ∀ (x y z : ℕ) → (x + y) + z ≡ x + (y + z)
+-assoc zero    y z = refl
+-assoc (suc x) y z =
  let
    -- The inductive hypothesis
    ih = +-assoc x y z
  in
    -- We need to prove: suc (x + y) + z ≡ suc (x + (y + z))
    -- Using congruence on the IH gives us exactly that.
    cong suc ih

-- Agda provides a 'rewrite' keyword to simplify this.
-- It pattern matches on the equality proof effectively replacing x with y.
+-identity : (n : ℕ) → n + zero ≡ n
+-identity zero    = refl
+-identity (suc n) rewrite +-identity n = refl

--------------------------------------------------------------------------------
-- Equational Reasoning
--------------------------------------------------------------------------------

-- Agda allows defining custom syntax to write proofs
-- that look like calculations.
-- This is similar to Lean's `calc` mode but defined within the language.

module Reasoning {A : Set} where
  infix  1 begin_
  infixr 2 _≡⟨⟩_ _≡⟨_⟩_
  infix  3 _∎

  begin_ : ∀ {x y : A} → x ≡ y → x ≡ y
  begin p = p

  _≡⟨⟩_ : ∀ (x : A) {y : A} → x ≡ y → x ≡ y
  x ≡⟨⟩ p = p

  _≡⟨_⟩_ : ∀ (x : A) {y z : A} → x ≡ y → y ≡ z → x ≡ z
  x ≡⟨ x≡y ⟩ y≡z = trans x≡y y≡z

  _∎ : ∀ (x : A) → x ≡ x
  x ∎ = refl

open Reasoning

-- Proof of associativity using reasoning syntax
+-assoc' : ∀ (x y z : ℕ) → (x + y) + z ≡ x + (y + z)
+-assoc' zero    y z = refl
+-assoc' (suc x) y z =
  begin
    (suc x + y) + z
  ≡⟨⟩               -- Definition of +
    suc (x + y) + z
  ≡⟨⟩               -- Definition of +
    suc ((x + y) + z)
  ≡⟨ cong suc (+-assoc' x y z) ⟩
    suc (x + (y + z))
  ≡⟨⟩
    suc x + (y + z)
  ∎

--------------------------------------------------------------------------------
-- Inductive Relations
--------------------------------------------------------------------------------

-- Relations can also be defined as inductive types.
-- Here we define "less than or equal to" for natural numbers.

data _≤_ : ℕ → ℕ → Set where
  z≤n : ∀ {n} → zero ≤ n
  s≤s : ∀ {m n} → m ≤ n → suc m ≤ suc n

-- Proof that 2 ≤ 4
2≤4 : 2 ≤ 4
2≤4 = s≤s (s≤s z≤n)

--------------------------------------------------------------------------------
-- Mutual Recursion: Even and Odd
--------------------------------------------------------------------------------

-- We can define types that depend on each other using `mutual`.

mutual
  data Even : ℕ → Set where
    zero : Even zero
    suc  : ∀ {n} → Odd n → Even (suc n)

  data Odd : ℕ → Set where
    suc  : ∀ {n} → Even n → Odd (suc n)

mutual
  e+e≡e : ∀ {m n} → Even m → Even n → Even (m + n)
  e+e≡e zero    en = en
  e+e≡e (suc om) en = suc (o+e≡o om en)

  o+e≡o : ∀ {m n} → Odd m → Even n → Odd (m + n)
  o+e≡o (suc em) en = suc (e+e≡e em en)

--------------------------------------------------------------------------------
-- Records and Type Classes
--------------------------------------------------------------------------------

-- Records are similar to structs.
record Isomorphism (A B : Set) : Set where
  field
    to   : A → B
    from : B → A
    from∘to : ∀ (x : A) → from (to x) ≡ x
    to∘from : ∀ (y : B) → to (from y) ≡ y

-- Agda supports "Instance Arguments" via {{ }}.
-- This works like Type Classes in Haskell or Lean.

record Monoid (A : Set) : Set where
  field
    mempty : A
    _<>_   : A → A → A

-- A function using the type class
concat : ∀ {A : Set} {{m : Monoid A}} → List A → A
concat {{m}} [] = Monoid.mempty m
concat {{m}} (x :: xs) = Monoid._<>_ m x (concat {{m}} xs)

-- Instances are defined like normal values but marked 'instance'
instance
  natPlusMonoid : Monoid ℕ
  natPlusMonoid = record { mempty = 0 ; _<>_ = _+_ }

-- Now we can use it implicitly
sumList : ℕ
sumList = concat (1 :: 2 :: 3 :: []) -- Result: 6

--------------------------------------------------------------------------------
-- Propositions as Types
--------------------------------------------------------------------------------

data _×_ (A B : Set) : Set where   -- AND
  _,_ : A → B → A × B

data _⊎_ (A B : Set) : Set where   -- OR
  inj₁ : A → A ⊎ B
  inj₂ : B → A ⊎ B

data ⊥ : Set where                 -- FALSE
  -- No constructors

-- Ex Falso Quodlibet: From falsehood, anything follows.
-- We use an absurd pattern () to indicate this case is impossible.
⊥-elim : ∀ {A : Set} → ⊥ → A
⊥-elim ()

-- Negation is defined as "implies False".
¬_ : Set → Set
¬ A = A → ⊥

-- Example: Proving 1 is not equal to 0.
-- We assume 1 ≡ 0 is true (argument eq), and show it leads to
-- a contradiction.
1≢0 : ¬ (1 ≡ 0)
1≢0 ()
-- The pattern () automatically realizes that 1 ≡ 0 is an impossible match
-- because the constructors 'suc' and 'zero' do not clash
-- in the definition of ≡.

-- Decidable Propositions
-- A property P is decidable if we can compute whether it holds
-- or not.
data Dec (P : Set) : Set where
  yes : P → Dec P
  no  : (P → ⊥) → Dec P

-- Computable equality for Naturals
_==_ : (n m : ℕ) → Dec (n ≡ m)
zero  == zero  = yes refl
zero  == suc m = no λ()
suc n == zero  = no λ()
suc n == suc m with n == m
... | yes p = yes (cong suc p)
... | no ¬p = no (λ { refl → ¬p refl })

```

## Further Reading

* [PLFA (Programming Language Foundations in Agda)](https://plfa.github.io/) - Highly recommended deep dive.
* [The Agda Wiki](https://wiki.portal.chalmers.se/agda/pmwiki.php)
* [Agda Documentation](https://agda.readthedocs.io/en/latest/)
* [Standard Library](https://github.com/agda/agda-stdlib) - The official standard library.


================================================
FILE: amd.md
================================================
---
category: tool
name: AMD
contributors:
    - ["Frederik Ring", "https://github.com/m90"]
filename: learnamd.js
---

## Getting Started with AMD

The **Asynchronous Module Definition** API specifies a mechanism for defining
JavaScript modules such that the module and its dependencies can be asynchronously
loaded. This is particularly well suited for the browser environment where
synchronous loading of modules incurs performance, usability, debugging, and
cross-domain access problems.

### Basic concept

```javascript
// The basic AMD API consists of nothing but two methods: `define` and `require`
// and is all about module definition and consumption:
// `define(id?, dependencies?, factory)` defines a module
// `require(dependencies, callback)` imports a set of dependencies and
// consumes them in the passed callback

// Let's start by using define to define a new named module
// that has no dependencies. We'll do so by passing a name
// and a factory function to define:
define('awesomeAMD', function(){
  var isAMDAwesome = function(){
    return true;
  };
  // The return value of a module's factory function is
  // what other modules or require calls will receive when
  // requiring our `awesomeAMD` module.
  // The exported value can be anything, (constructor) functions,
  // objects, primitives, even undefined (although that won't help too much).
  return isAMDAwesome;
});

// Now, let's define another module that depends upon our `awesomeAMD` module.
// Notice that there's an additional argument defining our
// module's dependencies now:
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
  // dependencies will be passed to the factory's arguments
  // in the order they are specified
  var tellEveryone = function(){
    if (awesomeAMD()){
      alert('This is sOoOo rad!');
    } else {
      alert('Pretty dull, isn\'t it?');
    }
  };
  return tellEveryone;
});

// As we do know how to use define now, let's use `require` to
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
require(['loudmouth'], function(loudmouth){
  loudmouth();
});

// To make this tutorial run code, let's implement a very basic
// (non-asynchronous) version of AMD right here on the spot:
function define(name, deps, factory){
  // notice how modules without dependencies are handled
  define[name] = require(factory ? deps : [], factory || deps);
}

function require(deps, callback){
  var args = [];
  // first let's retrieve all the dependencies needed
  // by the require call
  for (var i = 0; i < deps.length; i++){
    args[i] = define[deps[i]];
  }
  // satisfy all the callback's dependencies
  return callback.apply(null, args);
}
// you can see this code in action here: http://jsfiddle.net/qap949pd/
```

### Real-world usage with require.js

In contrast to the introductory example, `require.js` (the most popular AMD library) actually implements the **A** in **AMD**, enabling you to load modules and their dependencies asynchronously via XHR:

```javascript
/* file: app/main.js */
require(['modules/someClass'], function(SomeClass){
  // the callback is deferred until the dependency is loaded
  var thing = new SomeClass();
});
console.log('So here we are, waiting!'); // this will run first
```

By convention, you usually store one module in one file. `require.js` can resolve module names based on file paths, so you don't have to name your modules, but can simply reference them using their location. In the example `someClass` is assumed to be in the `modules` folder, relative to your configuration's `baseUrl`:

* app/
  * main.js
  * modules/
    * someClass.js
    * someHelpers.js
    * ...
  * daos/
    * things.js
    * ...

This means we can define `someClass` without specifying a module id:

```javascript
/* file: app/modules/someClass.js */
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
  // module definition, of course, will also happen asynchronously
  function SomeClass(){
    this.method = function(){/**/};
    // ...
  }
  return SomeClass;
});
```

To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:

```javascript
/* file: main.js */
requirejs.config({
  baseUrl : 'app',
  paths : {
    // you can also load modules from other locations
    jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
    coolLibFromBower : '../bower_components/cool-lib/coollib'
  }
});
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
  // a `main` file needs to call require at least once,
  // otherwise no code will ever run
  coolLib.doFancyStuffWith(helpers.transform($('#foo')));
});
```

`require.js`-based apps will usually have a single entry point (`main.js`) that is passed to the `require.js` script tag as a data-attribute. It will be automatically loaded and executed on pageload:

```html
<!DOCTYPE html>
<html>
<head>
  <title>A hundred script tags? Never again!</title>
</head>
<body>
  <script src="require.js" data-main="app/main"></script>
</body>
</html>
```

### Optimizing a whole project using r.js

Many people prefer using AMD for sane code organization during development, but still want to ship a single script file in production instead of performing hundreds of XHRs on page load.

`require.js` comes with a script called `r.js` (that you will probably run in node.js, although Rhino is supported too) that can analyse your project's dependency graph, and build a single file containing all your modules (properly named), minified and ready for consumption.

Install it using `npm`:

```shell
$ npm install requirejs -g
```

Now you can feed it with a configuration file:

```shell
$ r.js -o app.build.js
```

For our above example the configuration might look like:

```javascript
/* file : app.build.js */
({
  name : 'main', // name of the entry point
  out : 'main-built.js', // name of the file to write the output to
  baseUrl : 'app',
  paths : {
    // `empty:` tells r.js that this should still be loaded from the CDN, using
    // the location specified in `main.js`
    jquery : 'empty:',
    coolLibFromBower : '../bower_components/cool-lib/coollib'
  }
})
```

To use the built file in production, simply swap `data-main`:

```html
<script src="require.js" data-main="app/main-built"></script>
```

An incredibly detailed [overview of build options](https://github.com/jrburke/r.js/blob/master/build/example.build.js) is available in the GitHub repo.

### Topics not covered in this tutorial
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
* [Shim configuration (loading non-AMD modules)](http://requirejs.org/docs/api.html#config-shim)
* [CSS loading and optimizing with require.js](http://requirejs.org/docs/optimization.html#onecss)
* [Using almond.js for builds](https://github.com/jrburke/almond)

### Further reading:

* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
* [Universal Module Definition](https://github.com/umdjs/umd)

### Implementations:

* [require.js](http://requirejs.org)
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
* [cujo.js](http://cujojs.com/)
* [curl.js](https://github.com/cujojs/curl)
* [lsjs](https://github.com/zazl/lsjs)
* [mmd](https://github.com/alexlawrence/mmd)


================================================
FILE: angularjs.md
================================================
---
category: framework
name: AngularJS
contributors:
    - ["Walter Cordero", "http://waltercordero.com"]
filename: learnangular.txt
---

## AngularJS Tutorial.

AngularJS version 1.0 was released in 2012.
Miško Hevery, a Google employee, started to work with AngularJS in 2009.
The idea turned out very well, and the project is now officially supported by Google.

AngularJS is a JavaScript framework. It can be added to an HTML page with a "script" tag.
AngularJS extends HTML attributes with Directives, and binds data to HTML with Expressions.

## What You Should Already Know

Before you study AngularJS, you should have a basic understanding of:

- HTML
- CSS
- JavaScript

```html
// AngularJS is a JavaScript framework. It is a library written in JavaScript.
// AngularJS is distributed as a JavaScript file, and can be added to a web page with a script tag:
// <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>

///////////////////////////////////
// AngularJS Extends HTML

//AngularJS extends HTML with ng-directives.
//The ng-app directive defines an AngularJS application.
//The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.
//The ng-bind directive binds application data to the HTML view.
<!DOCTYPE html>
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
  <body>
    <div ng-app="">
      <p>Name: <input type="text" ng-model="name"></p>
      <p ng-bind="name"></p>
    </div>
  </body>
</html>

/*
  * Example explained:
  * AngularJS starts automatically when the web page has loaded.
  * The ng-app directive tells AngularJS that the <div> element is the "owner" of an AngularJS application.
  * The ng-model directive binds the value of the input field to the application variable name.
  * The ng-bind directive binds the innerHTML of the <p> element to the application variable name.
*/
<tag> Here are content to be interpreted </tag>

///////////////////////////////////
// AngularJS Expressions

// AngularJS expressions are written inside double braces: {{ expression }}.
// AngularJS expressions binds data to HTML the same way as the ng-bind directive.
// AngularJS will "output" data exactly where the expression is written.
// AngularJS expressions are much like JavaScript expressions: They can contain literals, operators, and variables.
// Example {{ 5 + 5 }} or {{ firstName + " " + lastName }}
<!DOCTYPE html>
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
  <body>
    <div ng-app="">
      <p>My first expression: {{ 5 + 5 }}</p>
    </div>
  </body>
</html>

//If you remove the ng-app directive, HTML will display the expression as it is, without solving it:
<!DOCTYPE html>
<html>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
  <body>
    <div>
      <p>My first expression: {{ 5 + 5 }}</p>
    </div>
  </body>
</html>

// AngularJS expressions bind AngularJS data to HTML the same way as the ng-bind directive.
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
  <body>
    <div ng-app="">
      <p>Name: <input type="text" ng-model="name"></p>
      <p>{{name}}</p>
    </div>
  </body>
</html>

// AngularJS numbers are like JavaScript numbers:
<div ng-app="" ng-init="quantity=1;cost=5">
  <p>Total in dollar: {{ quantity * cost }}</p>
</div>

//AngularJS strings are like JavaScript strings:
<div ng-app="" ng-init="firstName='John';lastName='Doe'">
  <p>The name is <span ng-bind="firstName + ' ' + lastName"></span></p>
</div>

//AngularJS objects are like JavaScript objects:
<div ng-app="" ng-init="person={firstName:'John',lastName:'Doe'}">
  <p>The name is {{ person.lastName }}</p>
</div>

//AngularJS arrays are like JavaScript arrays:
<div ng-app="" ng-init="points=[1,15,19,2,40]">
  <p>The third result is {{ points[2] }}</p>
</div>

// Like JavaScript expressions, AngularJS expressions can contain literals, operators, and variables.
// Unlike JavaScript expressions, AngularJS expressions can be written inside HTML.
// AngularJS expressions do not support conditionals, loops, and exceptions, while JavaScript expressions do.
// AngularJS expressions support filters, while JavaScript expressions do not.

///////////////////////////////////
// AngularJS Directives


//AngularJS directives are extended HTML attributes with the prefix ng-.
//The ng-app directive initializes an AngularJS application.
//The ng-init directive initializes application data.
//The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.
<div ng-app="" ng-init="firstName='John'">
  <p>Name: <input type="text" ng-model="firstName"></p>
  <p>You wrote: {{ firstName }}</p>
</div>

//Using ng-init is not very common. You will learn how to initialize data in the chapter about controllers.

//The ng-repeat directive repeats an HTML element:
<div ng-app="" ng-init="names=['Jani','Hege','Kai']">
  <ul>
    <li ng-repeat="x in names">
      {{ x }}
    </li>
  </ul>
</div>

//The ng-repeat directive used on an array of objects:
<div ng-app="" ng-init="names=[
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}]">
  <ul>
    <li ng-repeat="x  in names">
      {{ x.name + ', ' + x.country }}
    </li>
  </ul>
</div>

// AngularJS is perfect for database CRUD (Create Read Update Delete) applications.
// Just imagine if these objects were records from a database.

// The ng-app directive defines the root element of an AngularJS application.
// The ng-app directive will auto-bootstrap (automatically initialize) the application when a web page is loaded.
// Later you will learn how ng-app can have a value (like ng-app="myModule"), to connect code modules.

// The ng-init directive defines initial values for an AngularJS application.
// Normally, you will not use ng-init. You will use a controller or module instead.
// You will learn more about controllers and modules later.

//The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.
//The ng-model directive can also:
//Provide type validation for application data (number, email, required).
//Provide status for application data (invalid, dirty, touched, error).
//Provide CSS classes for HTML elements.
//Bind HTML elements to HTML forms.

//The ng-repeat directive clones HTML elements once for each item in a collection (in an array).

///////////////////////////////////
// AngularJS Controllers

// AngularJS controllers control the data of AngularJS applications.
// AngularJS controllers are regular JavaScript Objects.

// AngularJS applications are controlled by controllers.
// The ng-controller directive defines the application controller.
// A controller is a JavaScript Object, created by a standard JavaScript object constructor.

<div ng-app="myApp" ng-controller="myCtrl">

First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}

</div>

<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.firstName = "John";
    $scope.lastName = "Doe";
});
</script>

//Application explained:

//The AngularJS application is defined by  ng-app="myApp". The application runs inside the <div>.
//The ng-controller="myCtrl" attribute is an AngularJS directive. It defines a controller.
//The myCtrl function is a JavaScript function.
//AngularJS will invoke the controller with a $scope object.
//In AngularJS, $scope is the application object (the owner of application variables and functions).
//The controller creates two properties (variables) in the scope (firstName and lastName).
//The ng-model directives bind the input fields to the controller properties (firstName and lastName).

//The example above demonstrated a controller object with two properties: lastName and firstName.
//A controller can also have methods (variables as functions):
<div ng-app="myApp" ng-controller="personCtrl">

First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{fullName()}}

</div>

<script>
var app = angular.module('myApp', []);
app.controller('personCtrl', function($scope) {
    $scope.firstName = "John";
    $scope.lastName = "Doe";
    $scope.fullName = function() {
        return $scope.firstName + " " + $scope.lastName;
    }
});
</script>

//In larger applications, it is common to store controllers in external files.
//Just copy the code between the <script> </script> tags into an external file named personController.js:

<div ng-app="myApp" ng-controller="personCtrl">

First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}

</div>

<script src="personController.js"></script>

// For the next example we will create a new controller file:
angular.module('myApp', []).controller('namesCtrl', function($scope) {
    $scope.names = [
        {name:'Jani',country:'Norway'},
        {name:'Hege',country:'Sweden'},
        {name:'Kai',country:'Denmark'}
    ];
});

//Save the file as  namesController.js:
//And then use the controller file in an application:

<div ng-app="myApp" ng-controller="namesCtrl">

<ul>
  <li ng-repeat="x in names">
    {{ x.name + ', ' + x.country }}
  </li>
</ul>

</div>

<script src="namesController.js"></script>

///////////////////////////////////
// AngularJS Filters

// Filters can be added to expressions and directives using a pipe character.
// AngularJS filters can be used to transform data:

- **currency**:  Format a number to a currency format.
- **filter**:  Select a subset of items from an array.
- **lowercase**: Format a string to lower case.
- **orderBy**: Orders an array by an expression.
- **uppercase**: Format a string to upper case.

//A filter can be added to an expression with a pipe character (|) and a filter.
//(For the next two examples we will use the person controller from the previous chapter)
//The uppercase filter format strings to upper case:
<div ng-app="myApp" ng-controller="personCtrl">

<p>The name is {{ lastName | uppercase }}</p>

</div>

//The lowercase filter format strings to lower case:
<div ng-app="myApp" ng-controller="personCtrl">

<p>The name is {{ lastName | lowercase }}</p>

</div>

//The currency filter formats a number as currency:
<div ng-app="myApp" ng-controller="costCtrl">

<input type="number" ng-model="quantity">
<input type="number" ng-model="price">

<p>Total = {{ (quantity * price) | currency }}</p>

</div> 

//A filter can be added to a directive with a pipe character (|) and a filter.
//The orderBy filter orders an array by an expression:
<div ng-app="myApp" ng-controller="namesCtrl">

<ul>
  <li ng-repeat="x in names | orderBy:'country'">
    {{ x.name + ', ' + x.country }}
  </li>
</ul>

<div>

//An input filter can be added to a directive with a pipe character (|) 
//and filter followed by a colon and a model name.
//The filter selects a subset of an array:

<div ng-app="myApp" ng-controller="namesCtrl">

<p><input type="text" ng-model="test"></p>

<ul>
  <li ng-repeat="x in names | filter:test | orderBy:'country'">
    {{ (x.name | uppercase) + ', ' + x.country }}
  </li>
</ul>

</div>

///////////////////////////////////
// AngularJS AJAX - $http

//$http is an AngularJS service for reading data from remote servers.

// The following data can be provided by a web server:
// http://www.w3schools.com/angular/customers.php
// **Check the URL to see the data format**

// AngularJS $http is a core service for reading data from web servers.
// $http.get(url) is the function to use for reading server data.
<div ng-app="myApp" ng-controller="customersCtrl"> 

<ul>
  <li ng-repeat="x in names">
    {{ x.Name + ', ' + x.Country }}
  </li>
</ul>

</div>

<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
    $http.get("http://www.w3schools.com/angular/customers.php")
    .success(function(response) {$scope.names = response.records;});
});
</script>

Application explained:

// The AngularJS application is defined by ng-app. The application runs inside a <div>.
// The ng-controller directive names the controller object.
// The customersCtrl function is a standard JavaScript object constructor.
// AngularJS will invoke customersCtrl with a $scope and $http object.
// $scope is the application object (the owner of application variables and functions).
// $http is an XMLHttpRequest object for requesting external data.
// $http.get() reads JSON data from http://www.w3schools.com/angular/customers.php.
// If success, the controller creates a property (names) in the scope, with JSON data from the server.


// Requests for data from a different server (than the requesting page), are called cross-site HTTP requests.
// Cross-site requests are common on the web. Many pages load CSS, images, and scripts from different servers.
// In modern browsers, cross-site HTTP requests from scripts are restricted to same site for security reasons.
// The following line, in our PHP examples, has been added to allow cross-site access.
header("Access-Control-Allow-Origin: *");


///////////////////////////////////
// AngularJS Tables

// Displaying tables with angular is very simple:
<div ng-app="myApp" ng-controller="customersCtrl"> 

<table>
  <tr ng-repeat="x in names">
    <td>{{ x.Name }}</td>
    <td>{{ x.Country }}</td>
  </tr>
</table>

</div>

<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
    $http.get("http://www.w3schools.com/angular/customers.php")
    .success(function (response) {$scope.names = response.records;});
});
</script>

// To sort the table, add an orderBy filter: 
<table>
  <tr ng-repeat="x in names | orderBy : 'Country'">
    <td>{{ x.Name }}</td>
    <td>{{ x.Country }}</td>
  </tr>
</table>

// To display the table index, add a <td> with $index: 
<table>
  <tr ng-repeat="x in names">
    <td>{{ $index + 1 }}</td>
    <td>{{ x.Name }}</td>
    <td>{{ x.Country }}</td>
  </tr>
</table>

// Using $even and $odd
<table>
  <tr ng-repeat="x in names">
    <td ng-if="$odd" style="background-color:#f1f1f1">{{ x.Name }}</td>
    <td ng-if="$even">{{ x.Name }}</td>
    <td ng-if="$odd" style="background-color:#f1f1f1">{{ x.Country }}</td>
    <td ng-if="$even">{{ x.Country }}</td>
  </tr>
</table>

///////////////////////////////////
// AngularJS HTML DOM

//AngularJS has directives for binding application data to the attributes of HTML DOM elements.

// The ng-disabled directive binds AngularJS application data to the disabled attribute of HTML elements.

<div ng-app="" ng-init="mySwitch=true">

<p>
<button ng-disabled="mySwitch">Click Me!</button>
</p>

<p>
<input type="checkbox" ng-model="mySwitch">Button
</p>

</div>

//Application explained:

// The ng-disabled directive binds the application data mySwitch to the HTML button's disabled attribute.
// The ng-model directive binds the value of the HTML checkbox element to the value of mySwitch.
// If the value of mySwitch evaluates to true, the button will be disabled: 
<p>
<button disabled>Click Me!</button>
</p>

// If the value of mySwitch evaluates to false, the button will not be disabled: 
<p>
  <button>Click Me!</button>
</p>

// The ng-show directive shows or hides an HTML element.

<div ng-app="">

<p ng-show="true">I am visible.</p>

<p ng-show="false">I am not visible.</p>

</div>

// The ng-show directive shows (or hides) an HTML element based on the value of ng-show.
// You can use any expression that evaluates to true or false:
<div ng-app="">
<p ng-show="hour > 12">I am visible.</p>
</div>

///////////////////////////////////
// AngularJS Events

// AngularJS has its own HTML events directives.

// The ng-click directive defines an AngularJS click event.
<div ng-app="myApp" ng-controller="myCtrl">

<button ng-click="count = count + 1">Click me!</button>

<p>{{ count }}</p>

</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
    $scope.count = 0;
});
</script>

// The ng-hide directive can be used to set the visibility of a part of an application.
// The value ng-hide="true" makes an HTML element invisible.
// The value ng-hide="false" makes the element visible.
<div ng-app="myApp" ng-controller="personCtrl">

<button ng-click="toggle()">Toggle</button>

<p ng-hide="myVar">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</p>

</div>

<script>
var app = angular.module('myApp', []);
app.controller('personCtrl', function($scope) {
    $scope.firstName = "John",
    $scope.lastName = "Doe"
    $scope.myVar = false;
    $scope.toggle = function() {
        $scope.myVar = !$scope.myVar;
    };
});
</script>

//Application explained:

// The first part of the personController is the same as in the chapter about controllers.
// The application has a default property (a variable): $scope.myVar = false;
// The ng-hide directive sets the visibility, of a <p> element with two input fields, 
// according to the value (true or false) of myVar.
// The function toggle() toggles myVar between true and false.
// The value ng-hide="true" makes the element invisible.


// The ng-show directive can also be used to set the visibility of a part of an application.
// The value ng-show="false" makes an HTML element invisible.
// The value ng-show="true" makes the element visible.
// Here is the same example as above, using ng-show instead of ng-hide:
<div ng-app="myApp" ng-controller="personCtrl">

<button ng-click="toggle()">Toggle</button>

<p ng-show="myVar">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</p>

</div>

<script>
var app = angular.module('myApp', []);
app.controller('personCtrl', function($scope) {
    $scope.firstName = "John",
    $scope.lastName = "Doe"
    $scope.myVar = true;
    $scope.toggle = function() {
        $scope.myVar = !$scope.myVar;
    }
});
</script>

///////////////////////////////////
// AngularJS Modules

// An AngularJS module defines an application.
// The module is a container for the different parts of an application.
// The module is a container for the application controllers.
// Controllers always belong to a module.

// This application ("myApp") has one controller ("myCtrl"):

<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>

<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
    $scope.firstName = "John";
    $scope.lastName = "Doe";
});
</script>

</body>
</html>

// It is common in AngularJS applications to put the module and the controllers in JavaScript files.
// In this example, "myApp.js" contains an application module definition, while "myCtrl.js" contains the controller:

<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>

<script src="myApp.js"></script>
<script src="myCtrl.js"></script>

</body>
</html>

//myApp.js
var app = angular.module("myApp", []); 

// The [] parameter in the module definition can be used to define dependent modules.

// myCtrl.js
app.controller("myCtrl", function($scope) {
    $scope.firstName  = "John";
    $scope.lastName= "Doe";
});

// Global functions should be avoided in JavaScript. They can easily be overwritten 
// or destroyed by other scripts.

// AngularJS modules reduces this problem, by keeping all functions local to the module.

// While it is common in HTML applications to place scripts at the end of the 
// <body> element, it is recommended that you load the AngularJS library either
// in the <head> or at the start of the <body>.

// This is because calls to angular.module can only be compiled after the library has been loaded.

<!DOCTYPE html>
<html>
<body>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>

<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
    $scope.firstName = "John";
    $scope.lastName = "Doe";
});
</script>

</body>
</html>


///////////////////////////////////
// AngularJS Applications

// AngularJS modules define AngularJS applications.
// AngularJS controllers control AngularJS applications.
// The ng-app directive defines the application, the ng-controller directive defines the controller.
<div ng-app="myApp" ng-controller="myCtrl">
  First Name: <input type="text" ng-model="firstName"><br>
  Last Name: <input type="text" ng-model="lastName"><br>
  <br>
  Full Name: {{firstName + " " + lastName}}
</div>
<script>
  var app = angular.module('myApp', []);
  app.controller('myCtrl', function($scope) {
      $scope.firstName= "John";
      $scope.lastName= "Doe";
  });
</script>

// AngularJS modules define applications:
var app = angular.module('myApp', []);

// AngularJS controllers control applications:
app.controller('myCtrl', function($scope) {
    $scope.firstName= "John";
    $scope.lastName= "Doe";
});
```

## Source & References

**Examples**

- [http://www.w3schools.com/angular/angular_examples.asp](http://www.w3schools.com/angular/angular_examples.asp)

**References**

- [http://www.w3schools.com/angular/angular_ref_directives.asp](http://www.w3schools.com/angular/angular_ref_directives.asp)
- [http://www.w3schools.com/angular/default.asp](http://www.w3schools.com/angular/default.asp)
- [https://teamtreehouse.com/library/angular-basics/](https://teamtreehouse.com/library/angular-basics/)


================================================
FILE: ansible.md
================================================
---
category: tool
name: Ansible
contributors:
    - ["Jakub Muszynski" , "http://github.com/sirkubax"]
    - ["Pat Myron" , "https://github.com/patmyron"]
    - ["Divay Prakash", "https://github.com/divayprakash"]
filename: LearnAnsible.txt
---

## Introduction

```yaml
---
"{{ Ansible }}" is an orchestration tool written in Python.
...
```

Ansible is (one of many) orchestration tools. It allows you to control your
environment (infrastructure and code) and automate the manual tasks.

Ansible has great integration with multiple operating systems (even Windows)
and some hardware (switches, Firewalls, etc). It has multiple tools that
integrate with the cloud providers. Almost every noteworthy cloud provider is
present in the ecosystem (AWS, Azure, Google, DigitalOcean, OVH, etc...).

But ansible is way more! It provides execution plans, an API, library, and callbacks.

### Main pros and cons

#### Pros

* 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 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)
* Documentation is at the world-class standard!
* Writing your own modules and extensions is fairly easy.
* Ansible AWX is the open source version of Ansible Tower we have been waiting
for, which provides an excellent UI.

#### Cons

* It is an agent-less tool - every agent consumes up to 16MB ram - in some
environments, it may be noticeable amount.
* It is agent-less - you have to verify your environment consistency
'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 enterprise' payment plan, however Ansible AWX is the free
open source version we were all waiting for.

#### Neutral

Migration - Ansible <-> Salt is fairly easy - so if you would need an
event-driven agent environment - it would be a good choice to start quick with
Ansible, and convert to Salt when needed.

#### Some concepts

Ansible uses ssh or paramiko as a transport layer. In a way you can imagine
that you are using a ssh with API to perform your action. The simplest way is
to execute remote command in more controlled way (still using ssh).
On the other hand - in advanced scope - you can wrap Ansible (use python Ansible
code as a library) with your own Python scripts! It would act a
bit like Fabric then.

## Example

An example playbook to install apache and configure log level

```yaml
---
- hosts: apache

  vars:
      apache2_log_level: "warn"

  handlers:
  - name: restart apache
    service:
      name: apache2
      state: restarted
      enabled: True
    notify:
      - Wait for instances to listen on port 80
    become: True

  - name: reload apache
    service:
      name: apache2
      state: reloaded
    notify:
      - Wait for instances to listen on port 80
    become: True

  - name: Wait for instances to listen on port 80
    wait_for:
      state: started
      host: localhost
      port: 80
      timeout: 15
      delay: 5

  tasks:
  - name: Update cache
    apt:
      update_cache: yes
      cache_valid_time: 7200
    become: True

  - name: Install packages
    apt:
      name={{ item }}
    with_items:
      - apache2
      - logrotate
    notify:
      - restart apache
    become: True

  - name: Configure apache2 log level
    lineinfile:
      dest: /etc/apache2/apache2.conf
      line: "LogLevel {{ apache2_log_level }}"
      regexp: "^LogLevel"
    notify:
      - reload apache
    become: True
...
```

## Installation

```bash
# Universal way
$ pip install ansible

# Debian, Ubuntu
$ apt-get install ansible
```

* [Appendix A - How do I install ansible](#infrastructure-as-a-code)
* [Additional Reading.](http://docs.ansible.com/ansible/latest/intro_installation.html)

### Your first ansible command (shell execution)

```bash
# Command pings localhost (defined in default inventory: /etc/ansible/hosts)
$ ansible -m ping localhost
# You should see this output
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
```

### Shell Commands

There are few commands you should know about

* `ansible` (to run modules in CLI)
* `ansible-playbook` (to run playbooks)
* `ansible-vault` (to manage secrets)
* `ansible-galaxy` (to install roles from github/galaxy)

### Module

A program (usually python) that executes, does some work and returns proper
JSON output. This program performs specialized task/action (like manage
instances in the cloud, execute shell command). The simplest module is called
`ping` - it just returns a JSON with `pong` message.

Example of modules:

* Module: `ping` - the simplest module that is useful to verify host connectivity
* Module: `shell` - a module that executes a shell command on a specified host(s).


```bash
$ ansible -m ping all
$ ansible -m shell -a 'date; whoami' localhost #hostname_or_a_group_name
```

* Module: `command` - executes a single command that will not be processed
through the shell, so variables like `$HOME` or operands like ``|` `;`` will not
work. The command module is more secure, because it will not be affected by the
user’s environment. For more complex commands - use shell module.

```bash
$ ansible -m command -a 'date; whoami' # FAILURE
$ ansible -m command -a 'date' all
$ ansible -m command -a 'whoami' all
```

* Module: `file` - performs file operations (stat, link, dir, ...)
* Module: `raw` - executes a low-down and dirty SSH command, not going through
the module subsystem (useful to install python2.7)

### Task

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 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**.
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)

Playbook script language is YAML. You can think that playbook is very advanced
CLI script that you are executing.

#### Example of the playbook

This example-playbook would execute (on all hosts defined in inventory) two tasks:
* `ping` that would return message *pong*
* `shell` that execute three commands and return the output to our terminal

```yaml
- hosts: all

  tasks:
    - name: "ping all"
      ping:

    - name: "execute a shell command"
      shell: "date; whoami; df -h;"
```

Run the playbook with the command:

```bash
$ ansible-playbook path/name_of_the_playbook.yml
```

Note: Example playbook is explained in the next chapter: 'Roles'

### More on ansible concept

### Inventory

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`).

```
localhost

[some_group]
hostA.mydomain.com
hostB.localdomain
1.2.3.4

[a_group_of_a_groups:children]
some_group
some_other_group
```

* [Additional Reading.](http://docs.ansible.com/ansible/latest/intro_inventory.html)

### ansible-roles (a 'template-playbooks' with right structure)

You already know that the tasks (modules) can be run via CLI. You also know the
playbooks - the execution plans of multiple tasks (with variables and logic).

A concept called `role` was introduced for parts of the code (playbooks) that
should be reusable.

**Role** is a structured way to manage your set of tasks, variables, handlers,
default settings, and way more (meta, files, templates). Roles allow reusing
the same parts of code in multiple playbooks (you can parametrize the role
'further' during its execution). Its a great way to introduce `object oriented`
management for your applications.

Role can be included in your playbook (executed via your playbook).


```yaml
- hosts: all

  tasks:
      - name: "ping all"
        ping:
      - name: "execute a shell command"
        shell: "date; whoami; df -h;"

  roles:
      - some_role
      - { role: another_role, some_variable: 'learnxiny', tags: ['my_tag'] }

  pre_tasks:
      - name: some pre-task
        shell: echo 'this task is the last, but would be executed before roles, and before tasks'
```

#### For remaining examples we would use additional repository
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](https://github.com/sirkubax/ansible-for-learnXinYminutes)

```bash
$ # The following example contains a shell-prompt to indicate the venv and relative path
$ git clone git@github.com:sirkubax/ansible-for-learnXinYminutes.git
user@host:~/$ cd ansible-for-learnXinYminutes
user@host:~/ansible-for-learnXinYminutes$ source environment.sh
$
$ # First lets execute the simple_playbook.yml
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/simple_playbook.yml
```

Run the playbook with roles example

```bash
$ source environment.sh
$ # Now we would run the above playbook with roles
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/simple_role.yml
```

#### Role directory structure

```
roles/
   some_role/
     defaults/      # contains default variables
     files/         # for static files
     templates/     # for jinja templates
     tasks/         # tasks
     handlers/      # handlers
     vars/          # more variables (higher priority)
     meta/          # meta - package (role) info
```

#### Role Handlers
Handlers are tasks that can be triggered (notified) during execution of a
playbook, but they execute at the very end of a playbook. It is the best way to
restart a service, check if the application port is active (successful
deployment criteria), etc.

Get familiar with how you can use roles in the simple_apache_role example

```
playbooks/roles/simple_apache_role/
├── tasks
│   └── main.yml
└── templates
    └── main.yml
```

### ansible - variables

Ansible is flexible - it has 21 levels of variable precedence.
[read more](http://docs.ansible.com/ansible/latest/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable)
For now you should know that CLI variables have the top priority.
You should also know, that a nice way to pool some data is a **lookup**

### Lookups
Awesome tool to query data from various sources!!! Awesome!
query from:
* pipe  (load shell command output into variable!)
* file
* stream
* etcd
* password management tools
* url

```bash
# read playbooks/lookup.yml
# then run
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/lookup.yml
```

You can use them in CLI too

```yaml
ansible -m shell -a 'echo "{{ my_variable }}"' -e 'my_variable="{{ lookup("pipe", "date") }}"' localhost
ansible -m shell -a 'echo "{{ my_variable }}"' -e 'my_variable="{{ lookup("pipe", "hostname") }}"' all

# Or use in playbook

(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/lookup.yml
```

### Register and Conditional

#### Register

Another way to dynamically generate the variable content is the `register` command.
`Register` is also useful to store an output of a task and use its value
for executing further tasks.

```
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/register_and_when.yml
```

```yaml
---
- hosts: localhost
  tasks:
   - name: check the system capacity
     shell: df -h /
     register: root_size

   - name: debug root_size
     debug:
        msg: "{{ root_size }}"

   - name: debug root_size return code
     debug:
       msg:  "{{ root_size.rc }}"

# when: example

   - name: Print this message when return code of 'check the system capacity' was ok
     debug:
       msg:  "{{ root_size.rc }}"
     when: root_size.rc == 0
...
```

#### Conditionals - when:

You can define complex logic with Ansible and Jinja functions. Most common is
usage of `when:`, with some variable (often dynamically generated in previous
playbook steps with `register` or `lookup`)

```yaml
---
- hosts: localhost
  tasks:
   - name: check the system capacity
     shell: df -h /
     when: some_variable in 'a string'
  roles:
   - { role: mid_nagios_probe, when: allow_nagios_probes }
...
```

### ansible - tags, limit

You should know about a way to increase efficiency by this simple functionality

#### TAGS

You can tag a task, role (and its tasks), include, etc, and then run only the
tagged resources

```
ansible-playbook playbooks/simple_playbook.yml --tags=tagA,tag_other
ansible-playbook playbooks/simple_playbook.yml -t tagA,tag_other

There are special tags:
    always

--skip-tags can be used to exclude a block of code
--list-tags to list available tags
```

[Read more](http://docs.ansible.com/ansible/latest/playbooks_tags.html)

#### LIMIT

You can limit an execution of your tasks to defined hosts

```
ansible-playbook playbooks/simple_playbook.yml --limit localhost

--limit my_hostname
--limit groupname
--limit some_prefix*
--limit hostname:group #JM
```

### Templates

Templates are a powerful way to deliver some (partially) dynamic content.
Ansible uses **Jinja2** language to describe the template.

```
Some static content

{{ a_variable }}

{% for item in loop_items %}
    this line item is {{ item }}
{% endfor %}
```

Jinja may have some limitations, but it is a powerful tool that you might like.

Please examine this simple example that installs apache2 and generates
index.html from the template
"playbooks/roles/simple_apache_role/templates/index.html"

```bash
$ source environment.sh
$ # Now we would run the above playbook with roles
(venv) user@host:~/ansible-for-learnXinYminutes$ ansible-playbook playbooks/simple_role.yml --tags apache2
```

#### Jinja2 CLI

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
```

In fact - jinja is used to template parts of the playbooks too

```yaml
# check part of this playbook: playbooks/roles/sys_debug/tasks/debug_time.yml
- local_action: shell date +'%F %T'
  register: ts
  become: False
  changed_when: False

- name: Timestamp
  debug: msg="{{ ts.stdout }}"
  when: ts is defined and ts.stdout is defined
  become: False
```

#### Jinja2 filters

Jinja is powerful. It has many built-in useful functions.

```
# get first item of the list
{{ some_list | first() }}
# if variable is undefined - use default value
{{ some_variable | default('default_value') }}
```

[Read More](http://docs.ansible.com/ansible/latest/playbooks_filters.html)

### ansible-vault

To maintain **infrastructure as code** you need to store secrets. Ansible
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 them during runtime.

```bash
# Try (this would fail)
$ ansible-playbook playbooks/vault_example.yml

$ echo some_very_very_long_secret > ~/.ssh/secure_located_file

# in ansible.cfg set the path to your secret file
$ vi ansible.cfg
  ansible_vault_password_file = ~/.ssh/secure_located_file

#or use env
$ export ANSIBLE_VAULT_PASSWORD_FILE=~/.ssh/secure_located_file

$ ansible-playbook playbooks/vault_example.yml

  # encrypt the file
$ ansible-vault encrypt path/somefile

  # view the file
$ ansible-vault view path/somefile

  # check the file content:
$ cat path/somefile

  # decrypt the file
$ ansible-vault decrypt path/somefile
```

### dynamic inventory

You might like to know, that you can build your inventory dynamically.
(For Ansible) inventory is just JSON with proper structure - if you can
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 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)

```bash
$ etc/inv/ec2.py --refresh
$ ansible -m ping all -i etc/inv/ec2.py
```

[Read more](http://docs.ansible.com/ansible/latest/intro_dynamic_inventory.html)

### ansible profiling - callback

Playbook execution takes some time. It is OK. First make it run, then you may
like to speed things up. Since ansible 2.x there is built-in callback for task
execution profiling.

```
vi ansible.cfg
# set this to:
callback_whitelist = profile_tasks
```

### facts-cache and ansible-cmdb

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.

```
vi ansible.cfg

# if set to a persistent type (not 'memory', for example 'redis') fact values
# from previous runs in Ansible will be stored.  This may be useful when
# wanting to use, for example, IP information from one group of servers
# without having to talk to them in the same playbook run to get their
# current IP information.
fact_caching = jsonfile
fact_caching_connection = ~/facts_cache
fact_caching_timeout = 86400
```

I like to use `jsonfile` as my backend. It allows to use another project
`ansible-cmdb` [(project on GitHub)](https://github.com/fboender/ansible-cmdb) that generates a HTML page of your inventory
resources. A nice 'free' addition!

### Debugging ansible [chapter in progress]

When your job fails - it is good to be effective with debugging.

1. Increase verbosity by using multiple -v **[ -vvvvv]**
2. If variable is undefined -
`grep -R path_of_your_inventory -e missing_variable`
3. If variable (dictionary or a list) is undefined -
`grep -R path_of_your_inventory -e missing_variable`
4. Jinja template debug
5. Strange behaviour - try to run the code 'at the destination'

### Infrastructure as code

You already know, that ansible-vault allows you to store your confidential data
along with your code. You can go further - and define your
ansible installation and configuration as code.
See `environment.sh` to learn how to install the ansible itself inside a
`virtualenv` that is not attached to your operating system (can be changed by
non-privileged user), and as additional benefit - upgrading version of ansible
is as easy as installing new version in new virtualenv. What is more, you can
have multiple versions of Ansible present at the same time.

```bash
# recreate ansible 2.x venv
$ rm -rf venv2
$ source environment2.sh

# execute playbook
(venv2)$ ansible-playbook playbooks/ansible1.9_playbook.yml # would fail - deprecated syntax

# now lets install ansible 1.9.x next to ansible 2.x
(venv2)$ deactivate
$ source environment.1.9.sh

# execute playbook
(venv1.9)$ ansible-playbook playbooks/ansible1.9_playbook.yml # works!

# please note that you have both venv1.9 and venv2 present - you need to (de)activate one - that is all
```

#### become-user, become

In Ansible - to become `sudo` - use the `become` parameter. Use `become_user`
to specify the username.

```
- name: Ensure the httpd service is running
  service:
    name: httpd
    state: started
  become: true
```

Note: You may like to execute Ansible with `--ask-sudo-pass` or add the user to
sudoers file in order to allow non-supervised execution if you require 'admin'
privileges.

[Read more](http://docs.ansible.com/ansible/latest/become.html)

## Tips and tricks

#### --check -C

Always make sure that your playbook can execute in 'dry run' mode (--check),
and its execution is not declaring 'Changed' objects.

#### --diff -D

Diff is useful to see nice detail of the files changed.
It compare 'in memory' the files like `diff -BbruN fileA fileB`.


#### Execute hosts with 'regex'

```bash
ansible -m ping web*
```

#### Host groups can be joined, negated, etc

```bash
ansible -m ping web*:!backend:monitoring:&allow_change
```

#### Tagging

You should tag some (not all) objects - a task in a playbook, all tasks
included form a role, etc. It allows you to execute the chosen parts of the
playbook.

#### no_logs: True

You may see, that some roles print a lot of output in verbose mode. There is
also a debug module. This is the place where credentials may leak. Use `no_log`
to hide the output.

#### Debug module

allows to print a value to the screen - use it!

#### Register the output of a task

You can register the output (stdout), rc (return code), stderr of a task with
the `register` command.

#### Conditionals: when:

#### Loop: with, with\_items, with\_dict, with\_together

[Read more](http://docs.ansible.com/ansible/latest/playbooks_conditionals.html)

## Additional Resources

* [Servers For Hackers: An Ansible Tutorial](https://serversforhackers.com/c/an-ansible-tutorial)
* [A system administrator's guide to getting started with Ansible - FAST!](https://www.redhat.com/en/blog/system-administrators-guide-getting-started-ansible-fast)
* [Ansible Tower](https://www.ansible.com/products/tower) - Ansible Tower provides a web UI, dashboard and rest interface to ansible.
* [Ansible AWX](https://github.com/ansible/awx) - The Open Source version of Ansible Tower.
* [Ansible Tutorial for Beginners: Ultimate Playbook & Examples](https://spacelift.io/blog/ansible-tutorial)


================================================
FILE: apl.md
================================================
---
name: APL
contributors:
    - ["nooodl", "https://github.com/nooodl"]
filename: learnapl.apl
---

```apl
⍝ Comments in APL are prefixed by ⍝.

⍝ A list of numbers. (¯ is negative)
2 3e7 ¯4 50.3

⍝ An expression, showing some functions. In APL, there's
⍝ no order of operations: everything is parsed right-to-
⍝ left. This is equal to 5 + (4 × (2 ÷ (5 - 3))) = 9:
5 + 4 × 2 ÷ 5 - 3        ⍝ 9

⍝ These functions work on lists, too:
1 2 3 4 × 5              ⍝ 5 10 15 20
1 2 3 4 × 5 6 7 8        ⍝ 5 12 21 32

⍝ All functions have single-argument and dual-argument
⍝ meanings. For example, "×" applied to two arguments
⍝ means multiply, but when applied to only a right-hand
⍝ side, it returns the sign:

× ¯4 ¯2 0 2 4            ⍝ ¯1 ¯1 0 1 1

⍝ Values can be compared using these operators (1 means
⍝ "true", 0 means "false"):

10 20 30 = 10 20 99      ⍝ 1 1 0

10 20 30 < 10 20 99      ⍝ 0 0 1

⍝ "⍳n" returns a vector containing the first n naturals.
⍝ Matrices can be constructed using ⍴ (reshape):
4 3 ⍴ ⍳5                 ⍝ 0 1 2
                         ⍝ 3 4 0
                         ⍝ 1 2 3
                         ⍝ 4 0 1

⍝ Single-argument ⍴ gives you the dimensions back:
⍴ 4 3 ⍴ ⍳5               ⍝ 4 3

⍝ Values can be stored using ←. Let's calculate the mean
⍝ value of a vector of numbers:
A ← 10 60 55 23

⍝ Sum of elements of A (/ is reduce):
+/A                      ⍝ 148

⍝ Length of A:
⍴A                       ⍝ 4

⍝ Mean:
(+/A) ÷ (⍴A)             ⍝ 37

⍝ We can define this as a function using {} and ⍵:
mean ← {(+/⍵)÷⍴⍵}
mean A                   ⍝ 37
```

## Further Reading

- [APL Wiki](https://aplwiki.com/)
- An older version of APL book by the creator: [Kenneth Iverson - A Programming Language](https://archive.org/details/aprogramminglanguage1962)
- Additional Books: [APL Books](https://aplwiki.com/wiki/Books)


================================================
FILE: ar/html.md
================================================
---
contributors:
    - ["Christophe THOMAS", "https://github.com/WinChris"]
translators:
    - ["Ader", "https://github.com/y1n0"]
---

HTML اختصار ل HyperText Markup Language، أي "لغة ترميز النص التشعبي". 
هي لغة تمكننا من كتابة صفحات موجهة لشبكة الويب العالمي. 
هي لغة توصيف للنص، تسمح بكتابة صفحات ويب عن طريق تحديد كيفية عرض النصوص والمعلومات. 
في الحقيقة، ملفات html هي ملفات تحتوي على نصوص بسيطة. 
ما هو توصيف النص هذا؟ هو طريقة لتنظيم معلومات النص عن طريق إحاطته بوُسوم فتح ووسوم غلق. 
هذه الوسوم تعطي معاني محددة للنص الذي تحيطه. 
كباقي لغات الحاسوب، هناك الكثير من إصدارات HTML. سنتحدث هنا عن HTLM5. 

**ملاحظة:** يمكنك تجريب مختلف الوسوم والعناصر بينما تقرأ الدرس عبر موقع كـ [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>هذا عنصر من لائحة غير مرقمة. (لائحة بالعرائض)</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> خاص بالعناوين الكبيرة. -->
	<!-- هناك أيضا وسوم خاصة بالعناوين الفرعية من h1، الأكثر أهمية h2 والذي يليه حتى h6 الذي هو آخر عنوان داخلي. -->
	<a href = "http://codepen.io/anon/pen/xwjLbZ">ألق نظرة كيف يبدو هذا من هنا</a> <!-- يظهر رابطا للصفحة التي داخل السمة href="" -->
	<p>هذه فقرة.</p> <!-- يمكن من اضافة نصوص للصفحة. يميز الفقرات -->
	<p>هذه فقرة أخرى.</p>
	<ul> <!-- الوسم <ul> يخلق لائحة بالعرائض -->
	<!-- إذا أردت لائحة مرقمة، هناك الوسم <ol>. ويكون الترتيب فيه حسب تموضع العناصر داخله، الأول فالأول. -->
		<li>هذا عنصر من لائحة غير مرقمة. (لائحة بالعرائض)</li>
		<li>هذا عنصر آخر</li>
		<li>وهذا آخر عنصر في اللائحة</li>
	</ul>
</body>

<!-- وهكذا، كتابة ملفات HTML جد بسيطة -->

<!-- يمكنك كذلك إضافة أنواع أخرى من الوسوم -->

<!-- لادخال صورة: -->
<img src="http://i.imgur.com/XWG0O.gif"/> <!-- مصدر الصورة يحدد داخل السمة: src="" -->
<!-- مصدرها يمكن أن يكون رابطا أو مسارا لصورة في حاسوبك -->

<!-- يمكنك كذلك تشكيل جداول. -->

<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`.

## لمعرفة المزيد 

* [wikipedia](https://en.wikipedia.org/wiki/HTML)
* [HTML tutorial](https://developer.mozilla.org/en-US/docs/Web/HTML)
* [W3School](http://www.w3schools.com/html/html_intro.asp)


================================================
FILE: ar/python.md
================================================
---
contributors:
    - ["Louie Dinh", "http://pythonpracticeprojects.com"]
    - ["Steven Basart", "http://github.com/xksteven"]
    - ["Andre Polykanine", "https://github.com/Oire"]
    - ["Zachary Ferguson", "http://github.com/zfergus2"]
    - ["evuez", "http://github.com/evuez"]
    - ["Rommel Martinez", "https://ebzzry.io"]
    - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"]
translators:
    - ["Ahmad Hegazy", "https://github.com/ahegazy"]
---

لقد أُنشئت لغة البايثون بواسطة جايدو ڤان روسم في بداية التسعينات. هي الأن أحد أشهر اللغات الموجودة. 
لقد أحببت لغة البايثون بسبب وضوحها. هي في الأساس عبارة عن سودوكود قابل للتنفيذ.

ملحوظة: هذا المقال يُطبق على بايثون 3 فقط. راجع المقال [هنا](../pythonlegacy/) إذا أردت تعلم لغة البايثون نسخة 2.7 الأقدم

```python
# تعليق من سطر واحد يبدأ برمز الرقم.

""" يمكن كتابة تعليق يتكون من أكثر من سطر
    باستخدام ثلاثة علامات "
    ، وعادة يُستخدم في كتابة التوثيقات.
"""

####################################################
## 1. أنواع البيانات البدائية والعمليات
####################################################

# لديك أرقام
3  # => 3

# العمليات الحسابية هي ما تتوقعه
1 + 1   # => 2
8 - 1   # => 7
10 * 2  # => 20
35 / 5  # => 7.0

# نتائج قسمة الأرقام الصحيحية تُقرب للأصغر سواءًا كانت الأرقام موجبة أو سالبة.
5 // 3       # => 1
5.0 // 3.0   # => 1.0 # يعمل في حالة الكسور أيضا
-5 // 3      # => -2
-5.0 // 3.0  # => -2.0

# ناتج القسمة هو دائما كسر
10.0 / 3  # => 3.3333333333333335

# عملية باقي القسمة
7 % 3  # => 1

# الأُس  (س ** ص، رفع س لقوى ص)
2**3  # => 8

# أفرض ترتيب العمليات الحسابية بالأقواس
(1 + 3) * 2  # => 8

# القيم الثنائية هي المعروفة عموما (ﻻحظ: تكبير أول حرف)
True
False

# أنفي بـ (not)
not True   # => False
not False  # => True

# العمليات على القيم الثنائية
# ﻻحظ ﻻيهم حالة الحرف (كبير أو صغير) في "and" و "or"
True and False  # => False
False or True   # => True

# True و False هما في الواقع 1 و 0 لكن بمسميات مختلفة
True + True # => 2
True * 8    # => 8
False - 5   # => -5

# عمليات المقارنة تنظر الي القيمة الرقمية لل True وال False
0 == False  # => True
1 == True   # => True
2 == True   # => False
-5 != False # => True

# عند استخدام المنطق الثنائي على القيم الصحيحة يتم تحويلهم الي قيم ثنائية لإجرات العمليات عليهم، لكن قيمهم الأصلية تعود
# ﻻ تخلط بين bool(قيمة صحيحة) و العمليات المنطقية الثناية and/or (&,|)
bool(0)     # => False
bool(4)     # => True
bool(-6)    # => True
0 and 2     # => 0
-5 or 0     # => -5

# مقارنة التساوي ب ==
1 == 1  # => True
2 == 1  # => False

# مقارنة الاختلاف ب !=
1 != 1  # => False
2 != 1  # => True

# مقارنات أخرى
1 < 10  # => True
1 > 10  # => False
2 <= 2  # => True
2 >= 2  # => True

# لمعرفة هل القيمة في نطاق معين 
1 < 2 and 2 < 3  # => True
2 < 3 and 3 < 2  # => False

# التسلسل يجعلها تبدو أجمل
1 < 2 < 3  # => True
2 < 3 < 2  # => False

# (is مقابل ==) is تتحق من أن المتغيرين يشيران إلي نفس العنصر,
# لكن == تتحقق من أن العنصرين المُشار اليهما بالمتغيرين لهما نفس القيمة.
a = [1, 2, 3, 4]  # اجعل a تشير إلي قائمة جديدة, [1, 2, 3, 4]
b = a             # اجعل a تُشير الي ما تُشير إليه b
b is a            # => True, a و b يُشيران إلي نفس العنصر
b == a            # => True, قيمة عنصر a و b متساوية
b = [1, 2, 3, 4]  # اجعل b تشير الي قائمة جديدة , [1, 2, 3, 4]
b is a            # => False, a و b do ﻻ يشيران إلي نفس العنصر
b == a            # => True,  قيمة عنصر a و b متساوية

# يمكنك إنشاء الكلمات (تسلسلات الحروف) عن طريق " أو '
"This is a string."
'This is also a string.'

# يمكنك جمع هذا النوع أيضا! لكن حاول ألا تفعل هذا.
"Hello " + "world!"  # => "Hello world!"
# يمكنك الربط بين الكلمات بدون استخدام '+' (لكن ليس المتغيرات)
"Hello " "world!"    # => "Hello world!"

# يمكنك معاملة الكلمات كقائمة من الحروف
"This is a string"[0]  # => 'T'

# يمكنك معرفة طول الكلمة
len("This is a string")  # => 16

# .format يمكنك استخدامها لبناء الجمل بشكل معين, مثل هذا:
"{} can be {}".format("Strings", "interpolated")  # => "Strings can be interpolated"

# يمكنك تكرار معاملات بناء الجملة لتقليل الكتابة.
"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick")
# => "Jack be nimble, Jack be quick, Jack jump over the candle stick"

# يمكنك استخدام الكلمات المفتاحية إذا لم تُرد العد.
"{name} wants to eat {food}".format(name="Bob", food="lasagna")  # => "Bob wants to eat lasagna"

# إذا كان كود بايثون 3 الخاص بك يحتاج لبايثون 2.5 أو نسخة أقدم
# يمكنك استخدام أسلوب بناء الجمل القديم:
"%s can be %s the %s way" % ("Strings", "interpolated", "old")  # => "Strings can be interpolated the old way"

# يمكنك أبضا بناء الجمل باستخدام f-strings أو حروف بناء الجمل (في بايثون 3.6 فما فوق)
name = "Reiko"
f"She said her name is {name}." # => "She said her name is Reiko"
# يمكنك ببساطة وضع أي كود بايثون داخل أقواس وستقوم بإخراج الجملة.
f"{name} is {len(name)} characters long."


# None عبارة عن كائن
None  # => None

# ﻻ تستخدم رمز المساواة "==" لمقارنة العناصر ب None
# استخدم is بدلا منه. يقوم بالتحقق من مساواة هوية العنصر
"etc" is None  # => False
None is None   # => True

# None, 0, قوائم/جمل/قواميس/صفوف فارغة كلها تُترجم إلي False.
# كل القيم الأخرى True.
bool(0)   # => False
bool("")  # => False
bool([])  # => False
bool({})  # => False
bool(())  # => False

####################################################
## 2. المتغيرات والمجموعات
####################################################

# بايثون لديها دالة عرض "print"
print("I'm Python. Nice to meet you!")  # => I'm Python. Nice to meet you!

# الافتراضي دالة print تطبع سطر جديد في النهاية.
# استخدم المعامل end لتغيير أخر الجملة المعروضة.
print("Hello, World", end="!")  # => Hello, World!

# طريقة بسيطة لطلب مدخل من الطرفية
input_string_var = input("Enter some data: ") # يقوم بإعادة البيانات ك "string"
# لاحظ: في النسخ القديمة من بايثون، دالة input() كان اسمها raw_input()

# ﻻ يوجد تعريفات للمتغيرات، يتم تعيين قيمة المتغير مباشرة.
# العٌرف تسمية المتغيرات حروف_صغيرة_مع_خطوط_سُفلية
some_var = 5
some_var  # => 5

# محاولة استخدام متغير غير مُعين يعتبر خطأ
# إقرأ جزء 3.مسار التحكم لمعرفة المزيد عن التحكم في الأخطاء
some_unknown_var  # يعرض خطأ NameError

# يمكن استخدام if كتعبير واحد
# مساوِ للتعبير الأتي في لغة السي '?:' عملية ثلاثية
"yahoo!" if 3 > 2 else 2  # => "yahoo!"

# القوائم تحفظ المتسلسلات
li = []
# يمكنك البدأ بقائمة مليئة
other_li = [4, 5, 6]

# إضافة بيانات لأخر القائمة عن طريق append
li.append(1)    # li is now [1]
li.append(2)    # li is now [1, 2]
li.append(4)    # li is now [1, 2, 4]
li.append(3)    # li is now [1, 2, 4, 3]
# حذف أخر عنصر في القائمة عن طريق pop
li.pop()        # => 3 and li is now [1, 2, 4]
# هيا نعيده ثانية
li.append(3)    # li is now [1, 2, 4, 3] again.

# يمكنك الوصول لعناصر القائمة كما تفعل في ال array
# Access a list like you would any array
li[0]   # => 1
# للوصول لأخر عنصر
li[-1]  # => 3

# محاولة الوصول لعنصر خارج نطاق القائمة يعتبر خطأ: IndexError
li[4]  # يعرض خطأ IndexError

# يمكنك النظر للنطاقات باستخدام تركيب التقطيع
# مؤشر/رقم/فهرس البداية مُضمن، مؤشر النهاية ﻻ
# (لمحبي الرياضيات هو نطاق مفتوح/مغلق)
li[1:3]   # => [2, 4]
# إحذف أول عنصر ثم إعرض القائمة
li[2:]    # => [4, 3]
# إحذف أخر عنصر ثم إعرض القائمة
li[:3]    # => [1, 2, 4]
# حدد عنصر ثم إحذف الذي يليه ثم حدد عنصر وهكذا
li[::2]   # =>[1, 4]
# اعرض نسخة معكوسة من القائمة
li[::-1]  # => [3, 4, 2, 1]
# إستخدم أي تجميعة من الطرق المذكورة لعمل تقطيعات متقدمة
# li[start:end:step]

# عمل نسخة من طبقة واحدة باستخدم التقطيع
li2 = li[:]  # => li2 = [1, 2, 4, 3] لكن عند عمل(li2 is li) سينتج False.

# إمسح أي عنصر من القائمة باستخدام "del"
del li[2]  # li is now [1, 2, 3]

# إمسح أول ظهور لقيمة.
li.remove(2)  # li is now [1, 3]
li.remove(2)  # يعرض خطأ ValueError لأن 2 غير موجود في القائمة

# أضف عنصر في خانة معينة
li.insert(1, 2)  # li is now [1, 2, 3] مرة أخرى

# أحصل على مؤشر/رقم لأول ظهور للقيمة
li.index(2)  # => 1
li.index(4)  # يعرض خطأ ValueError لأن 4 غير موجودة في القائمة

# يمكنك جمع قوائم
# لاحظ: لا يتم تعديل قيمة li و other_li
li + other_li  # => [1, 2, 3, 4, 5, 6]

# إستخدم دالة "extend()" لربط القوائم
li.extend(other_li)  # Now li is [1, 2, 3, 4, 5, 6]

# راجع وجود قيمة في القائمة باستخدام "in"
1 in li  # => True

# إحصل على طول القائمة باستخدام دالة "len()"
len(li)  # => 6


# الصفوف تشبه القوائم لكنها غير قابلة للتغيير.
tup = (1, 2, 3)
tup[0]      # => 1
tup[0] = 3  # يعرض خطأ TypeError

# لاحظ أن صف طوله عنصر واحد يحتاج لإضافة فاصلة "," بعد أخر عنصر
# لكن الصفوف من أي طول أخر، حتى صفر لا تحتاج.
type((1))   # => <class 'int'>
type((1,))  # => <class 'tuple'>
type(())    # => <class 'tuple'>

# يمكنك عمل معظم عمليات القوائم على الصفوف.
len(tup)         # => 3
tup + (4, 5, 6)  # => (1, 2, 3, 4, 5, 6)
tup[:2]          # => (1, 2)
2 in tup         # => True

# يمكنك تفريغ الصفوف (أو القوائم) في متغيرات
a, b, c = (1, 2, 3)  # a is now 1, b is now 2 and c is now 3
# يمكنك أيضا عمل تفريغ واسع
a, *b, c = (1, 2, 3, 4)  # a is now 1, b is now [2, 3] and c is now 4
# الصفوف تُنشأ تلقائيا إذا تركت الأقواس
d, e, f = 4, 5, 6  # تم توسعة الصف 4, 5 ,6 في المتغيرات d, e, f
# بالترتيب حيث d = 4, e = 5 و f = 6
# الأن إنظر إلي مدى سهولة التبديل بين قيم متغيرين
e, d = d, e  # d is now 5 and e is now 4


# القواميس تُخزن خرائط من المفتاح للقيمة
empty_dict = {}
# هذا قاموس مملوء
filled_dict = {"one": 1, "two": 2, "three": 3}

# لاحظ أن القواميس يجب أن تكون أنواع غير قابلة للتغيير.
# هذا للتأكد من أن المفتاح يمكن تحويله لقيمة ثابتة للوصول السريع.
# الأنواع الغير قابلة للتغير تتضمن: الأرقام الصحيحة، الكسور، الكلمات، الصفوف.
invalid_dict = {[1,2,3]: "123"}  # =>يعرض خطأ TypeError: unhashable type: 'list'
valid_dict = {(1,2,3):[1,2,3]}   # القيم يمكن أن تكون من أي نوع.

# يمكنك البحث عن قيمة باستخدام []
filled_dict["one"]  # => 1

# يمكنك الحصول على كل المفاتيح باستخدام "keys()".
# نحتاج لإرسالها لدالة list() لتحويلها لقائمة. سنتعلم هذا لاحقًا
# لاحظ - لنسخ بايثون قبل 3.7، ترتيب مفاتيح القاموس غير مضمون. نتائجك
# يمكن ألا تساوي المثال بالأسفل. مع ذلك، من أول بايثون 3.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() للحصول عليها كقائمة.
# نفس الكلام السابق بخصوص ترتيب المفاتيح
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
1 in filled_dict      # => False

# البحث عن مفتاح غير موجود يعرض خطأ KeyError
filled_dict["four"]  # KeyError

# استخدم "get()" لتجنب الخطأ KeyError
filled_dict.get("one")      # => 1
filled_dict.get("four")     # => None
# دالة get تدعم إدخال قيمة افتراضية عند عدم وجود البحث
filled_dict.get("one", 4)   # => 1
filled_dict.get("four", 4)  # => 4

# "setdefault()" تقوم بإدخال قيمة جديدة في القاموس في حالة عدم وجود المفتاح فقط.
filled_dict.setdefault("five", 5)  # filled_dict["five"] is set to 5
filled_dict.setdefault("five", 6)  # filled_dict["five"] is still 5

# إضافة عنصر للقاموس
filled_dict.update({"four":4})  # => {"one": 1, "two": 2, "three": 3, "four": 4}
filled_dict["four"] = 4         # طريقة أخرى للإضافة

# مسح المفاتيح من القاموس باستخدام del
del filled_dict["one"]  # Removes the key "one" from filled dict

# من بايثون 3.5 فما فوق يمكنك أيضا استخدام خيارات تفريغ إضافية
{'a': 1, **{'b': 2}}  # => {'a': 1, 'b': 2}
{'a': 1, **{'a': 2}}  # => {'a': 2}


# المجموعات تُخزن .. مجموعات
empty_set = set()
# .تهيئة مجموعة بمجموعة قيم. نعم، تشبه قليلا تهيئة القاموس. أسف
some_set = {1, 1, 2, 2, 3, 4}  # some_set is now {1, 2, 3, 4}

# مثل مفتاح القاموس، عناصر المجموعة يجب أن تكون غير قابلة للتغيير.
invalid_set = {[1], 1}  # => يعرض خطأ TypeError: unhashable type: 'list'
valid_set = {(1,), 1}

# إضافة عنصر أخر للمجموعة
filled_set = some_set
filled_set.add(5)  # filled_set is now {1, 2, 3, 4, 5}
# المجموعات لا يمكن أن تحتوي على عناصر مكررة
filled_set.add(5)  # it remains as before {1, 2, 3, 4, 5}

# تقاطع مجموعتين باستخدام &
other_set = {3, 4, 5, 6}
filled_set & other_set  # => {3, 4, 5}

# اتحاد مجموعتين باستخدام | 
filled_set | other_set  # => {1, 2, 3, 4, 5, 6}

# الفرق بين مجموعتين باستخدام -
{1, 2, 3, 4} - {2, 3, 5}  # => {1, 4}

# الفروق بين مجموعتين باستخدام ^
{1, 2, 3, 4} ^ {2, 3, 5}  # => {1, 4, 5}

# لفحص هل المجموعة على اليسار مجموعة عُليا للمجموعة على اليمين (تحتوي على كل عناصرها)
{1, 2} >= {1, 2, 3} # => False

# لفحص هل المجموعة على اليسار مجموعة فرعية من المجموعة على اليمين
{1, 2} <= {1, 2, 3} # => True

# للتأكد من وجود عن في مجموعة استخدم in 
2 in filled_set   # => True
10 in filled_set  # => False



####################################################
## 3. مسار التحكم والعمليات التكرارية #Control Flow and Iterables
####################################################

# هيا ننشيء متغير
some_var = 5

# الأن الأمر if. الفجوات (المسافات قبل الأوامر) مهمة في البايثون!
# العُرف استخدام أربع مسافات. ليس تبويب.
# هذا السطر البرمجي يطبع "some_var is smaller than 10"
if some_var > 10:
    print("some_var is totally bigger than 10.")
elif some_var < 10:    # This elif clause is optional.
    print("some_var is smaller than 10.")
else:                  # This is optional too.
    print("some_var is indeed 10.")


"""
For عبارة عن حلقات تدور حول عناصر قوائم 
:ثم تطبع
    dog is a mammal
    cat is a mammal
    mouse is a mammal
"""
for animal in ["dog", "cat", "mouse"]:
    # يمكنك استخدام format() لترجمة كلمات بشكل معين.
    print("{} is a mammal".format(animal))

"""
"range(number)" يقوم بإعادة مجموعة من الأرقام يمكن الدوران حولها
من الصفر إلي رقم معين 
ثم يطبع: 
    0
    1
    2
    3
"""

for i in range(4):
    print(i)

"""
"range(lower, upper)" يقوم بإعادة مجموعة من الأرقام يمكن الدوران حولها من القيمة السُفلى
lower حتى القيمة العُليا upper
ثم يطبع:
    4
    5
    6
    7
"""
for i in range(4, 8):
    print(i)

"""
"range(lower, upper, step)" يقوم بإعادة مجموعة من الأرقام يمكن الدوران حولها من القيمة السُفلى
lower حتى القيمة العُليا upper، ثم يقوم بالزيادة قيمة الstep.
إذا لم تُحدد ال step, القيمة الأفتراضية 1.
ثم يطبع:
    4
    6
"""
for i in range(4, 8, 2):
    print(i)

"""
While هي عبارة عن حلقات تدور حتى عدم تحقق شرط معين.
وتطبع: 
    0
    1
    2
    3
"""
x = 0 for
while x < 4:
    print(x)
    x += 1  # اختصار ل x = x + 1

# يمكنك التحكم في الأخطاء والاستثناءات باستخدام مجموعة try/except 
try:
    # استخدم "raise" لرفع خطأ.
    raise IndexError("This is an index error")
except IndexError as e:
    pass                 # Pass: هو مجرد أمر ﻻ تفعل شيء. عادة تقوم بتصحيح الخطأ هنا.
except (TypeError, NameError):
    pass                 # يمكنك التحكم في أكثر من خطأ في نفس الوقت، إذا أقتضت الضرورة
else:                    # فقرة اختيارية في مجموعة try/except. يجب أن يتبع جميع مجموعات معارضة الأخطاء
    print("All good!")   # تُنفذ في حالة أن السطور البرمجية داخل ال try لم ترفع أي خطأ
finally:                 #  تُنفذ في كل الحالات
    print("We can clean up resources here")

# بدلا من مجموعة try/finally لتنظيف الموارد يمكنك استخدام سطر with 
with open("myfile.txt") as f:
    for line in f:
        print(line)

# يتيح البايثون تجريد أساسي يسمى المُكرَر.
# المُكرٍَر عبارة عن متغير يمكن التعامل معه كسلسلة.
# الكائن الذي يعود من دالة نطاق، يسمى المُكرَر.

filled_dict = {"one": 1, "two": 2, "three": 3}
our_iterable = filled_dict.keys()
print(our_iterable)  # => dict_keys(['one', 'two', 'three'])
# هذا عبارة عن متغير يعرض عناصر مفاتيح المُكرَر.

# يمكننا الدوران حوله.
for i in our_iterable:
    print(i)  # Prints one, two, three

# مع ذلك ﻻ يمكننا الوصول للعناصر بالمؤشر.
our_iterable[1]  # يرفع خطأ TypeError

# المُكرَر هو عبارة عن عنصر يعلم كيفية إنشاء مُكرِر
our_iterator = iter(our_iterable)

# المُكرِر هو عبارة عن عنصر يمكنه تذكر الحالة أثناء مرورنا بعناصره.
# يمكننا الحصول على العنصر التالي عن طريق "next()"
next(our_iterator)  # => "one"

# يحفظ الحالة أثناء الدوران.
next(our_iterator)  # => "two"
next(our_iterator)  # => "three"

# بعد عرض المُكرِر كل عناصره، يرفع استثناء StopIteration
next(our_iterator)  # يرفع StopIteration

# يمكنك الحصول على كل عناصر المُكرر بمناداة دالة list() عليه.
list(filled_dict.keys())  # => Returns ["one", "two", "three"]


####################################################
## 4. الدوال
####################################################

# إستخدم "def" لإنشاء دوال جديدة.
def add(x, y):
    print("x is {} and y is {}".format(x, y))
    return x + y  # يمكنك إرجاع قيمة من الدالة بسطر return

# مناداة دوال بمعطيات
add(5, 6)  # => prints out "x is 5 and y is 6" and returns 11

# طريقة أخرى لمناداة دوال باستخدام كلمات مفتاحية.
add(y=6, x=5)  # الكلمة المفتاحية يمكن أن تُعطى بأي ترتيب.

# يمكنك تعريف دوال تأخذ عدد متغير من المُعطيات

def varargs(*args):
    return args

varargs(1, 2, 3)  # => (1, 2, 3)

# يمكنك تعريف دوال تأخذ عدد متغير من الكلمات المفتاحية كمعطيات أيضا.
def keyword_args(**kwargs):
    return kwargs

# هيا ننادي على الدالة لنرى ماذا سيحدث 
keyword_args(big="foot", loch="ness")  # => {"big": "foot", "loch": "ness"}


# يمكنك فعل الأثنين معًا في نفس الوقت، إذا أردت
def all_the_args(*args, **kwargs):
    print(args)
    print(kwargs)
"""
all_the_args(1, 2, a=3, b=4) prints:
    (1, 2)
    {"a": 3, "b": 4}
"""

# عندما تنادي على دوال، يمكنك عمل عكس المعطيات/المفاتيح!
# استخدم * لتوسعة الصفوف، واستخدم ** لتوسعة المفاتيح.
args = (1, 2, 3, 4)
kwargs = {"a": 3, "b": 4}
all_the_args(*args)            # مساوٍ ل all_the_args(1, 2, 3, 4)
all_the_args(**kwargs)         # مساوٍ ل to all_the_args(a=3, b=4)
all_the_args(*args, **kwargs)  # مساوٍ ل to all_the_args(1, 2, 3, 4, a=3, b=4)

# يقوم بإعادة مجموعة من القيم (بتعيين الصفوف)
def swap(x, y):
    return y, x  # يقوم بإعادة مجموعة من القيم على شكل صفوف بدون الأقواس
                 # (لاحظ: الأقواس حُذفت لكن يمكن إضافتها)

x = 1
y = 2
x, y = swap(x, y)     # => x = 2, y = 1
# (x, y) = swap(x,y)  # مرة أخرى الأقواس حُذفت لكن يمكن إضافتها.

# مجال الدالة
x = 5

def set_x(num):
    # المتغير المحلي x ليس هو المتغير العام x
    x = num    # => 43
    print(x)   # => 43

def set_global_x(num):
    global x
    print(x)   # => 5
    x = num    #المتغير العام x الأن مساوٍ ل 6
    print(x)   # => 6

set_x(43)
set_global_x(6)


# بايثون تدعم دوال الفئة أولية [first class functions] (أي أنه يمكن إرسال الدوال كمعطيات لدوال أخرى)
def create_adder(x):
    def adder(y):
        return x + y
    return adder

add_10 = create_adder(10)
add_10(3)   # => 13

# يوجد أيضا دوال مجهولة
(lambda x: x > 2)(3)                  # => True
(lambda x, y: x ** 2 + y ** 2)(2, 1)  # => 5

# يوجد دوال مدمجة من درجة أعلى
list(map(add_10, [1, 2, 3]))          # => [11, 12, 13]
list(map(max, [1, 2, 3], [4, 2, 1]))  # => [4, 2, 3]

list(filter(lambda x: x > 5, [3, 4, 5, 6, 7]))  # => [6, 7]

# يمكن إشتمال القوائم على خرائط وفلاتر حسنة الشكل
# هذه القوائم تحفظ المُخرج كقائمة والتي بدورها يمكن أن تكون قائمة مداخلة
[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]

# يمكنك بناء مجموعات وقواميس على هذا المنوال أيضا
{x for x in 'abcddeef' if x not in 'abc'}  # => {'d', 'e', 'f'}
{x: x**2 for x in range(5)}  # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}


####################################################
## 5. الوحدات البرمجية (الموديولات)
####################################################

# يمكنك استدعاء موديولات
import math
print(math.sqrt(16))  # => 4.0

# يمكنك استدعاء دالة معينة من موديول
from math import ceil, floor
print(ceil(3.7))   # => 4.0
print(floor(3.7))  # => 3.0

# يمكنك استدعاء كل الدوال من مديول.
# تحذير: هذا الفعل غير موصى به
from math import *

# يمكنك تصغير اسم موديول
import math as m
math.sqrt(16) == m.sqrt(16)  # => True

# موديولات البايثون عبارة عن ملفات بايثون عادية.
# يمكنك كتابة الموديولات الخاصة بك, واستدعاها.
# اسم الموديول يكون نفس اسم الملف.

# يمكنك معرفة أي الدوال والصفات مُعرفة في الموديول.
import math
dir(math)

# إذا كان لديك سكربت بايثون يسمى math.py
# في نفس المجلد الموجود به السكربت الخاص بك، الملف الخاص بك math.py
# سَيُستدعى بدلا من موديول البايثون بنفس الاسم
# هذا يحدث لأن المجلدات المحلية لديها أولوية عن مكتبات البايثون المُدمجة


####################################################
## 6. الفئات/القوالب (الكلاسات)
####################################################

# نستخدم السطر البرمجي "class" لإنشاء قالب
class Human:

    # صفة القالب. مشتركة بين كل نسخ القالب
    species = "H. sapiens"

    # مُهيئ إبتدائي، يُنادى عليه عندما يتم استدعاء القالب.
    # لاحظ أن الشرطة السٌفلية المُكررة مرتين __ قبل وبعد الاسم تُعبر عن الكائنات
    # أو الصفات المُستخدمة عن طريق  بايثون لكنها تعيش في مساحة تحكم المُستخدم.
    # العمليات -الدوال- (أو الكائنات أو الصفات) مثل: __init__, __str__,__repr__ ألخ.
    # تُسمى عمليات خاصة (أو أحيانا تسمى عمليات سحرية أو dunder methods)
    # يجب عليك ألا تُسمي مثل هذه الاسماء بنفسك.
    def __init__(self, name):
        # ساوِ المُعطى بالصفة name الخاصة بهذه النسخة من القالب.
        self.name = name
        
        # هيئ الصفة
        self._age = 0

    # عملية/دالة خاصة بنسخة القالب. كل العمليات تأخذ "self" كأول مُعطى
    # An instance method. All methods take "self" as the first argument
    def say(self, msg):
        print("{name}: {message}".format(name=self.name, message=msg))

    # عملية أخرى خاصة بنسخة القالب.
    def sing(self):
        return 'yo... yo... microphone check... one two... one two...'

    # عمليات القالب مشتركة بين كل أجزاء القالب
    # يتم مناداتهم عن طريق جعل القالب المُنادي أول معطى
    # They are called with the calling class as the first argument
    @classmethod
    def get_species(cls):
        return cls.species

    # تُنادى العملية الثابتة بدون قالب أو نسخة قالب
    @staticmethod
    def grunt():
        return "*grunt*"

    # الخاصية تشبه تماما إمر الطلب
    # تُحَوِل العملية age() إلي صفة مقروءة فقط بنفس الاسم.
    # ﻻ حاجة لكتابة أوامر طلب أو تهيئة
    @property
    def age(self):
        return self._age

    # هذا يتيح تهيئة الخاصية 
    @age.setter
    def age(self, age):
        self._age = age

    # هذا يتيح حذف الخاصية
    @age.deleter
    def age(self):
        del self._age


# عندما يقرأ مُترجم البايثون ملف مصدري يقوم بتنفيذ كل الكود.
# فحص ال __name__ يجعل هذا الجزء من الكود يُنَفَذ فقط 
# في حالة أن هذا الموديول هو البرنامج الرئيسي
if __name__ == '__main__':
    # Instantiate a class
    i = Human(name="Ian")
    i.say("hi")                     # "Ian: hi"
    j = Human("Joel")
    j.say("hello")                  # "Joel: hello"
    # i و j نُسخ من النوع Human, أول بكلمات أخرى: هما كائنات للقالب Human

    # نادي على عملية القالب
    i.say(i.get_species())          # "Ian: H. sapiens"
    # عدل الخاصية المُشتركة
    Human.species = "H. neanderthalensis"
    i.say(i.get_species())          # => "Ian: H. neanderthalensis"
    j.say(j.get_species())          # => "Joel: H. neanderthalensis"

    # نادي على العملية الثابتة
    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)                    # => "Ian: 42"
    j.say(j.age)                    # => "Joel: 0"
    # إحذف الخاصية
    del i.age
    # i.age                         # => سوف يرفع استثناء AttributeError


####################################################
## 6.1 الإرث
####################################################

# الإرث يتيح لقالب ابن أن يُعَرف ويرث بعض عمليات/دوال ومتغيرات القالب الأب.

# باستخدام القالب Human المُعَرف بالأعلى كأساس أو كقالب أب،
# يمكننا تعريف قالب ابن،Superhero ، يرث متغيرات القالب مثل "species", "name", و "age"، 
# وأيضا العمليات، مثل "sing", "grunt"
# من القالب Human، لكنه أيضا لديه خواصه الفريدة

# للاستفادة من التقطيع بالملف يمكنك وضع القوالب بالأعلى في ملفاتهم الخاصة،
# مثلا، human.py

# لاستيراد دالة من ملف أخر استخدم الطريقة التالية
# from "اسم الملف بدون مُلحق" import "اسم الدالة أو القالب"

from human import Human

# حدد القالب/ات الأب كمُعطى أثناء تعريف القالب.
class Superhero(Human):

    # إذا أردت أن يرث القالب الابن كل تعريفات القالب الأب بدون تعديل
    # يمكنك استخدام الكلمة المفتاحية "pass" (بدون شيء أخر)
    # لكن في هذه الحالة تم أهمالها لإنشاء قالب ابن فريد:
    # pass

    # القوالب الابن يمكنها تعديل صفات القوالب الأب
    species = 'Superhuman'

    # القوالب الابن ترث تلقائيا عمليات الإنشاء الخاصة بالقالب الأب بالإضافة إلي مُعطياتهم
    # لكن يمكن أيضا تعريف مُعطيات إضافية أو تعريفات
    # وتعديل العمليات مثل منشيء القالب.
    # هذا المُنشيء يرث المُعطى "name" من القالب "Human" 
    # ويضيف المعطيات"superpower" و "movies":
    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')

    # إحصل على ترتيب قرار البحث للعملية (Method Resolution search Order) المُستخدمة بواسطة العمليات 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 الإرث المُتعدد
####################################################

# تعريف قالب أخرA
# bat.py
class Bat:

    species = 'Baty'

    def __init__(self, can_fly=True):
        self.fly = can_fly

    # هذا القالب لديه عملية تسمى say
    def say(self, msg):
        msg = '... ... ...'
        return msg

    # ولديه عمليته الخاصة به أيضا
    def sonar(self):
        return '))) ... ((('

if __name__ == '__main__':
    b = Bat()
    print(b.say('hello'))
    print(b.fly)

# تعريف قالب أخر يرث من Superhero و Bat
# superhero.py
from superhero import Superhero
from bat import Bat

# عَرٍف Batman كقالب ابن يرث من كلا من Superhero و Bat
class Batman(Superhero, Bat):

    def __init__(self, *args, **kwargs):
        # عادة لكي ترث صفة يجد أن تنادي على super:
        # super(Batman, self).__init__(*args, **kwargs)      
        # لكننا في هذه الحالة نتعامل مع إرث متعدد هنا، و super()
        # تعمل فقط مع القالب التالي في قائمة ال MRO.
        # لذا بدلا من ذلك ننادي على __init__ صراحة لكل الأباء.
        # استخدام *args و **kwargs يتيح طريقة نظيفة لتمرير المعطيات.
        # لكل أب "تقشير طبقة من البصل".
        Superhero.__init__(self, 'anonymous', movie=True, 
                           superpowers=['Wealthy'], *args, **kwargs)
        Bat.__init__(self, *args, can_fly=False, **kwargs)
        # تعديل قيمة الصفة name
        self.name = 'Sad Affleck'

    def sing(self):
        return 'nan nan nan nan nan batman!'


if __name__ == '__main__':
    sup = Batman()

    # إحصل على ترتيب قرار البحث للعملية (Method Resolution search Order) المُستخدمة بواسطة العمليات getattr() و super()
    # هذه الصفة ديناميكية ويمكن أن تُحَدًث.
    print(Batman.__mro__)       # => (<class '__main__.Batman'>, 
                                # => <class 'superhero.Superhero'>, 
                                # => <class 'human.Human'>, 
                                # => <class 'bat.Bat'>, <class 'object'>)

    # نادي على العملية الخاصة بالأب لكن استخدم الصفات الخاصة بالقالب الابن
    print(sup.get_species())    # => Superhuman

    # نادي على العملية المُعدلة
    print(sup.sing())           # => nan nan nan nan nan batman!

    # نادي على العملية من القالب Human, لأن الترتيب في الأرث مهم.
    sup.say('I agree')          # => Sad Affleck: I agree

    # نادي على العملية الموجودة فقط في القالب الأب الثاني
    print(sup.sonar())          # => ))) ... (((

    # الصفة الموروثة من القالب الأب
    sup.age = 100
    print(sup.age)              # => 100

    # الصفة الموروثة من القالب الأب الثاني، الذي تم تعديل قيمته الافتراضية
    print('Can I fly? ' + str(sup.fly)) # => Can I fly? False



####################################################
## 7. مُتَقدم
####################################################

# المولدات تُساعدك على كتابة كود كسول.
def double_numbers(iterable):
    for i in iterable:
        yield i + i

# المولدات فعالة من حيث الذاكرة، لأنها تُحمٍل الذاكرة بالبيانات التي تحتاج
# لإجراء العملية عليها في الخطوة التالية في المُكَرِر.
# هذا يتيح إجراء عمليات على قيم كبيرة ممنوعة في حالات أخرى.
# ﻻحظ: `range` بديل ل `xrange` في بايثون 3.
for i in double_numbers(range(1, 900000000)):  # `range` is a generator.
    print(i)
    if i >= 30:
        break

# كما يمكنك إنشاء قوائم اشتمال، يمكنك إنشاء مولدات اشتمال أيضا
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

# يمكنك أيضا تغيير نوع مولد الاشتمال مباشرة إلي قائمة
values = (-x for x in [1,2,3,4,5])
gen_to_list = list(values)
print(gen_to_list)  # => [-1, -2, -3, -4, -5]


# المُحسنات
# في هذا المثال الدالة`beg` تُغلف الدالة `say`. 
# إذا كانت say_please تساوي True 
# إذا ستُغير الرسالة الراجعة من الدالة
from functools import wraps

def beg(target_function):
    @wraps(target_function)
    def wrapper(*args, **kwargs):
        msg, say_please = target_function(*args, **kwargs)
        if say_please:
            return "{} {}".format(msg, "Please! I am poor :(")
        return msg

    return wrapper


@beg
def say(say_please=False):
    msg = "Can you buy me a beer?"
    return msg, say_please


print(say())                 # Can you buy me a beer?
print(say(say_please=True))  # Can you buy me a beer? Please! I am poor :(
```

## جاهز للمزيد?

### مجانا عبر الانترنت

* [أتمتتة المهمات المُملة عبر بايثون](https://automatetheboringstuff.com)
* [التوثيقات الرسمية](http://docs.python.org/3/)
* [دليل المُسافر لبايثون](http://docs.python-guide.org/en/latest/)
* [دورة بايثون](http://www.python-course.eu/index.php)
* [أولى الخطوات مع بايثون](https://realpython.com/learn/python-first-steps/)
* [قائمة مُختارة من إطارات عمل بايثون الرائعة, المكتبات والبرمجيات](https://github.com/vinta/awesome-python)
* [الدليل الرسمي لنمط البايثون](https://peps.python.org/pep-0008/)
* [بايثون 3 دوائر علوم الحاسب](http://cscircles.cemc.uwaterloo.ca/)
* [غُص في بايثون 3](http://www.diveintopython3.net/index.html)


================================================
FILE: ar/sql.md
================================================
---
contributors:
  - ["Bob DuCharme", "http://bobdc.com/"]
translators:
    - ["Ahmed Omar Eissa", "https://twitter.com/AhmedOmarEissa"]
---
<div dir="rtl">

لغة الاستعلام الهيكلية 
(SQL) 
هي لغة قياسية
[ISO/IEC 9075](https://www.iso.org/standard/63555.html)
لإنشاء قواعد البيانات المخزنة في مجموعة من الجداول التعامل معها. عادةً ما تضيف التطبيقات 
امتدادات خاصة بها إلى اللغة ؛ تعد 
[مقارنة نسخ SQL المختلفة](http://troels.arvin.dk/db/rdbms/) 
مرجعًا جيدًا لاختلافات النسخ.

توفر النسخ عادةً موجه سطر أوامر
command line prompt
حيث يمكنك إدخال الأوامر المعروضة هنا بشكل تفاعلي، كما أنها توفر طريقة لتنفيذ سلسلة من هذه الأوامر المخزنة في ملف نصي. إظهار رسالة الانتهاء من العمل مع الموجه التفاعلي مثال جيد على امكانية اضافة أوامر غير قياسية، معظم النسخ تدعم أحد أوامر
QUIT , EXIT
.أو كليهما

في الامثلة بالأسفل تعتمدالعديد من الأوامرأن قاعدة بيانات الموظفين
[MySQL employee sample database](https://dev.mysql.com/doc/employee/en/) 
الموجودة على
[GitHub](https://github.com/datacharmer/test_db)
قد تم تحميلها مسبقا. الملفات على
GitHub 
هي مجموعة من الاوامر تشبه الموجودة بالاسفل و تقوم الأوامر بإنشاء الجدوال وإدخال بيانات مجموعة من الموظفين المتخيلين في شركة. تعتمد الأوامر المستخدمة في هذا البرنامج على نسخة 
SQL 
التي تستخدمها، 
</div>




```sql
-- تبدأ التعليقات بشرطتين. قم بإنهاء كل أمر بفاصلة منقوطة

-- حساسة لحالة الاحرف SQL لا تعتبر
-- فقط ليسهل تمييزها عن أسماه الأعمدة والجداول وقواعد البيانات UPPER-CASE  الاوامر الموجودة هنا تستخدم الحالة العليا للاحرف 

-- إنشاء ومسح قاعدة بيانات، أسماء قواعد البيانات والجداول حساسة لحالة الأحرف
CREATE DATABASE someDatabase;
DROP DATABASE someDatabase;

-- عرض قواعد البيانات الموجودة
SHOW DATABASES;

--استخدام قاعدة بيانات محددة
USE employees;

-- في قاعدة البيانات المستخدمة departments ارجاع كل السطور والاعمدة في جدول 
-- ستظهر النتائج على الشاشة بشكل تلقائي لتتصفحها.
SELECT * FROM departments;

-- فقط dept_name و dept_no لكن سنسترجع عمودي departments استرجاع كل أسطر من جدول 
-- لا مانع من تقسيم الاوامر بين السطور

SELECT dept_no,
       dept_name FROM departments;

-- لكن هذه المرة سنسترجع ٥ أسطر فقط departments استرجاع كل الاعمدة من جدول
SELECT * FROM departments LIMIT 5;

--en يحتوي علي dept_name في حالة أن عمود  departments من جدول  dept_name استرجاع عمود 

SELECT dept_name FROM departments WHERE dept_name LIKE '%en%';

-- S استرجاع كل أعمدة جدول الاقسام في حالة أن اسم القسم يبدأ بحرف  
-- متبوعا بأربعة حروف 

SELECT * FROM departments WHERE dept_name LIKE 'S____';

-- استرجاع قيم العناوين من جدول العناوين بدون تكرار 
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%';


-- ربط المعلومات بين الجداول، جدول العناوين يظهر رقم كل موظف ومسماه الوظيفي 
-- ومتي حصل على هذا المسمى وإلي متى ولكن بدلا من اظهار رقم الموظف سنستخدم هذا الرقم
-- للحصول على اسم الموظف الاول والأخير من جدول الموظفين مع إظهار ١٠ سطور فقط
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');

--John إلى fname سنغير قيمة عمود tablename1  في 
-- Mutt هي lname  في حالة أن قيمة العمود
UPDATE tablename1 SET fname='John' WHERE lname='Mutt';


-- 'M' تبدأ ب  lname في حالة أن قيمة عمود  tablename1 مسح السطور من جدول 
DELETE FROM tablename1 WHERE lname like 'M%';

-- مع ترك الجدول فارغ tablename1 مسح جميع السطور من جدول 
DELETE FROM tablename1;

-- تماما tablename1 إزالة جدول 
DROP TABLE tablename1;
```

<div dir="rtl">

## اقرأ أكثر

* [Codecademy - SQL](https://www.codecademy.com/learn/learn-sql)مقدمة جيدة للتعلم عن طريق التطبيق.
* [Database System Concepts](https://www.db-book.com) الفصل رقم ٣ من الكتاب مقدمة في (SQL) تحتوى علي شرح مفصل لمفاهيم (SQL)

</div>


================================================
FILE: arturo.md
================================================
---
name: Arturo
filename: learnarturo.art
contributors:
  - ["Dr.Kameleon", "https://github.com/drkameleon"]
---

```red
; this is a comment
; this is another comment

;---------------------------------
; VARIABLES & VALUES
;---------------------------------

; numbers
a1: 2
a2: 3.14
a3: to :complex [1 2.0]     ; 1.0+2.0i

; strings
c1: "this is a string"
c2: {
    this is a multiline string
    that is indentation-agnostic
}
c3: {:
    this is 
        a verbatim
            multiline string
                which will remain exactly
                    as the original
:}

; characters
ch: `c`

; blocks/arrays
d: [1 2 3]

; dictionaries
e: #[
    name: "John"
    surname: "Doe"
    age: 34
    likes: [pizza spaghetti]
]

; yes, functions are values too
f: function [x][
    2 * x
]

; dates
g: now              ; 2021-05-03T17:10:48+02:00

; booleans
h1: true
h2: false

;---------------------------------
; BASIC OPERATORS
;---------------------------------

; simple arithmetic
1 + 1       ; => 2
8 - 1       ; => 7
4.2 - 1.1   ; => 3.1
10 * 2      ; => 20
35 / 4      ; => 8
35 // 4     ; => 8.75
2 ^ 5       ; => 32
5 % 3       ; => 2

; bitwise operators
and 3 5     ; => 1
or 3 5      ; => 7
xor 3 5     ; => 6

; pre-defined constants
pi          ; => 3.141592653589793
epsilon     ; => 2.718281828459045
null        ; => null
true        ; => true
false       ; => false

;---------------------------------
; COMPARISON OPERATORS
;---------------------------------

; equality
1 = 1       ; => true
2 = 1       ; => false

; inequality
1 <> 1      ; => false
2 <> 1      ; => true

; more comparisons
1 < 10      ; => true
1 =< 10     ; => true
10 =< 10    ; => true
1 > 10      ; => false
1 >= 10     ; => false
11 >= 10    ; => true

;---------------------------------
; CONDITIONALS
;---------------------------------

; logical operators
and? true true      ; => true
and? true false     ; => false
or? true false      ; => true
or? false false     ; => false

and? [1=2][2<3]     ; => false 
                    ; (the second block will not be evaluated)

; simple if statements
if 2 > 1 [ print "yes!"]    ; yes!
if 3 <> 2 -> print "true!"  ; true!

; if/else statements
if? 2 > 3 -> print "2 is greater than 3"
else -> print "2 is not greater than 3"         ; 2 is not greater than 3

; switch statements
switch 2 > 3 -> print "2 is greater than 3"
             -> print "2 is not greater than 3" ; 2 is not greater than 3

a: (2 > 3)["yes"]["no"]         ; a: "no"
a: (2 > 3)? -> "yes" -> "no"    ; a: "no" (exactly the same as above)

; case/when statements
case [1]
    when? [>2] -> print "1 is greater than 2. what?!"
    when? [<0] -> print "1 is less than 0. nope..."
    else -> print "here we are!"                ; here we are!

;---------------------------------
; LOOPS
;---------------------------------

; with `loop`
arr: [1 4 5 3]
loop arr 'x [
    print ["x =" x]
]
; x = 1
; x = 4
; x = 5
; x = 3

; with loop and custom index
loop.with:'i arr 'x [
    print ["item at position" i "=>" x]
]
; item at position 0 => 1
; item at position 1 => 4
; item at position 2 => 5
; item at position 3 => 3

; using ranges
loop 1..3 'x ->         ; since it's a single statement
    print x             ; there's no need for [block] notation
                        ; we can wrap it up using the `->` syntactic sugar

loop `a`..`c` 'ch ->
    print ch
; a
; b
; c

; picking multiple items
loop 1..10 [x y] ->
    print ["x =" x ", y =" y]
; x = 1 , y = 2 
; x = 3 , y = 4 
; x = 5 , y = 6 
; x = 7 , y = 8 
; x = 9 , y = 10 

; looping through a dictionary
dict: #[name: "John", surname: "Doe", age: 34]
loop dict [key value][
    print [key "->" value]
]
; name -> John 
; surname -> Doe 
; age -> 34 
                    
; while loops
i: new 0
while [i<3][
    print ["i =" i]
    inc 'i
]
; i = 0
; i = 1
; i = 2
 
;---------------------------------
; STRINGS
;---------------------------------

; case
a: "tHis Is a stRinG"
print upper a               ; THIS IS A STRING
print lower a               ; this is a string
print capitalize a          ; tHis Is a stRinG

; concatenation
a: "Hello " ++ "World!"     ; a: "Hello World!"

; strings as an array
split "hello"               ; => [h e l l o]
split.words "hello world"   ; => [hello world]

print first "hello"         ; h
print last "hello"          ; o

; conversion
to :string 123              ; => "123"
to :integer "123"           ; => 123

; joining strings together
join ["hello" "world"]              ; => "helloworld"
join.with:"-" ["hello" "world"]     ; => "hello-world"

; string interpolation
x: 2
print ~"x = |x|"            ; x = 2

; interpolation with `print`
print ["x =" x]             ; x = 2
                            ; (`print` works by calculating the given block
                            ;  and joining the different values as strings
                            ;  with a single space between them)

; templates
print render.template {
    <||= switch x=2 [ ||>
        Yes, x = 2
    <||][||>
        No, x is not 2
    <||]||> 
} ; Yes, x = 2

; matching
prefix? "hello" "he"        ; => true
suffix? "hello" "he"        ; => false

contains? "hello" "ll"      ; => true
contains? "hello" "he"      ; => true
contains? "hello" "x"       ; => false

in? "ll" "hello"            ; => true 
in? "x" "hello"             ; => false

;---------------------------------
; BLOCKS
;---------------------------------

; calculate a block
arr: [1 1+1 1+1+1]
@arr                        ; => [1 2 3]

; execute a block
sth: [print "Hello world"]  ; this is perfectly valid,
                            ; could contain *anything*
                            ; and will not be executed...

do sth                      ; Hello world
                            ; (...until we tell it to)

; array indexing
arr: ["zero" "one" "two" "three"]
print first arr             ; zero
print arr\0                 ; zero
print last arr              ; three
print arr\3                 ; three

x: 2
print get arr x             ; two
print arr \ 2               ; two
                            ; (using the `\` infix alias for get -
                            ;  notice space between the operands! 
                            ;  otherwise, it'll be parsed as a path)

; setting an array element
arr\0: "nada"
set arr 2 "dos"
print arr                   ; nada one dos three

; adding elements to an array
arr: new []
'arr ++ "one"
'arr ++ "two"
print arr                   ; one two

; remove elements from an array
arr: new ["one" "two" "three" "four"]
'arr -- "two"               ; arr: ["one" "three" "four"]
remove 'arr .index 0        ; arr: ["three" "four"]

; getting the size of an array
arr: ["one" 2 "three" 4]
print size arr              ; 4

; getting a slice of an array
print slice ["one" "two" "three" "four"] 0 1        ; one two

; check if array contains a specific element
print contains? arr "one"   ; true
print contains? arr "five"  ; false

; sorting array
arr: [1 5 3 2 4]
sort arr                    ; => [1 2 3 4 5]
sort.descending arr         ; => [5 4 3 2 1]

; mapping values
map 1..10 [x][2*x]          ; => [2 4 6 8 10 12 14 16 18 20]
map 1..10 'x -> 2*x         ; same as above
map 1..10 => [2*&]          ; same as above
map 1..10 => [2*]           ; same as above

; selecting/filtering array values
select 1..10 [x][odd? x]    ; => [1 3 5 7 9]
select 1..10 => odd?        ; same as above

filter 1..10 => odd?        ; => [2 4 6 8 10]
                            ; (now, we leave out all odd numbers - 
                            ;  while select keeps them)

; misc operations
arr: ["one" 2 "three" 4]
reverse arr                 ; => [4 "three" 2 "one"]
shuffle arr                 ; => [2 4 "three" "one"]
unique [1 2 3 2 3 1]        ; => [1 2 3]
permutate [1 2 3]           ; => [[1 2 3] [1 3 2] [3 1 2] [2 1 3] [2 3 1] [3 2 1]]
take 1..10 3                ; => [1 2 3]
repeat [1 2] 3              ; => [1 2 1 2 1 2]

;---------------------------------
; FUNCTIONS
;---------------------------------

; declaring a function
f: function [x][ 2*x ]
f: function [x]-> 2*x       ; same as above
f: $[x]->2*x                ; same as above (only using the `$` alias 
                            ;  for the `function`... function)

; calling a function
f 10                        ; => 20

; returning a value
g: function [x][
    if x < 2 -> return 0

    res: 0
    loop 0..x 'z [
        res: res + z
    ]
    return res
]

;---------------------------------
; CUSTOM TYPES
;---------------------------------

; defining a custom type
define :person [                            ; define a new custom type "Person"
    name                                    ; with fields: name, surname, age
    surname
    age 
][ 
    ; with custom post-construction initializer
    init: [
        this\name: capitalize this\name
    ]

    ; custom print function
    print: [
        render "NAME: |this\name|, SURNAME: |this\surname|, AGE: |this\age|"
    ]

    ; custom comparison operator
    compare: 'age
]

; create a method for our custom type
sayHello: function [this][
    ensure -> is? :person this

    print ["Hello" this\name]
]

; create new objects of our custom type
a: to :person ["John" "Doe" 34]                 ; let's create 2 "Person"s
b: to :person ["jane" "Doe" 33]                 ; and another one

; call pseudo-inner method
sayHello a                                      ; Hello John                       
sayHello b                                      ; Hello Jane

; access object fields
print ["The first person's name is:" a\name]    ; The first person's name is: John
print ["The second person's name is:" b\name]   ; The second person's name is: Jane

; changing object fields
a\name: "Bob"                                   
sayHello a                                      ; Hello Bob

; verifying object type
print type a                                    ; :person
print is? :person a                             ; true

; printing objects
print a                                         ; NAME: John, SURNAME: Doe, AGE: 34

; sorting user objects (using custom comparator)
sort @[a b]                                     ; Jane..., John...
sort.descending @[a b]                          ; John..., Jane...       
```

## Additional resources

- [Official documentation](https://arturo-lang.io/documentation/) - Arturo official documentation & reference.
- [Online playground](https://arturo-lang.io/playground/) - Online REPL for the Arturo programming language.


================================================
FILE: asciidoc.md
================================================
---
name: AsciiDoc
contributors:
    - ["Ryan Mavilia", "http://unoriginality.rocks/"]
    - ["Abel Salgado Romero", "https://twitter.com/abelsromero"]
filename: asciidoc.adoc
---

AsciiDoc is a markup language similar to Markdown and it can be used for anything from books to blogs. Created in 2002 by Stuart Rackham the language is simple but it allows for a great amount of customization.

Document Header

Headers are optional and can't contain blank lines. It must be offset from content by at least one blank line.

Title Only

```
= Document Title

First sentence of document.
```

Title and Author

```
= Document Title
First Last <first.last@learnxinyminutes.com>

Start of this document.
```

Multiple Authors

```
= Document Title
John Doe <john@go.com>; Jane Doe<jane@yo.com>; Black Beard <beardy@pirate.com>

Start of a doc with multiple authors.
```

Revision Line (requires an author line)

```
= Doc Title V1
Potato Man <chip@crunchy.com>
v1.0, 2016-01-13

This article about chips is going to be fun.
```

Paragraphs

```
You don't need anything special for paragraphs.

Add a blank line between paragraphs to separate them.

To create a line blank add a +
and you will receive a line break!
```

Formatting Text

```
_underscore creates italics_
*asterisks for bold*
*_combine for extra fun_*
`use ticks to signify monospace`
`*bolded monospace*`
```

Section Titles

```
= Level 0 (may only be used in document's header)

== Level 1 <h2>

=== Level 2 <h3>

==== Level 3 <h4>

===== Level 4 <h5>
```

Lists

To create a bulleted list use asterisks.

```
* foo
* bar
* baz
```

To create a numbered list use periods.

```
. item 1
. item 2
. item 3
```

You can nest lists by adding extra asterisks or periods up to five times.

```
* foo 1
** foo 2
*** foo 3
**** foo 4
***** foo 5

. foo 1
.. foo 2
... foo 3
.... foo 4
..... foo 5
```

## Further Reading

There are two tools to process AsciiDoc documents:

1. [AsciiDoc](http://asciidoc.org/): original Python implementation available in the main Linux distributions. Stable and currently in maintenance mode.
2. [Asciidoctor](http://asciidoctor.org/): alternative Ruby implementation, usable also from Java and JavaScript. Under active development, it aims to extend the AsciiDoc syntax with new features and output formats.

Following links are related to `Asciidoctor` implementation:

* [Markdown - AsciiDoc syntax comparison](http://asciidoctor.org/docs/user-manual/#comparison-by-example): side-by-side comparison of common Markdown and AsciiDoc elements.
* [Getting started](http://asciidoctor.org/docs/#get-started-with-asciidoctor): installation and quick start guides to render simple documents.
* [Asciidoctor User Manual](http://asciidoctor.org/docs/user-manual/): complete single-document manual with syntax reference, examples, rendering tools, amongst others.


================================================
FILE: assemblyscript.md
================================================
---
name: AssemblyScript
contributors:
    - ["Philippe Vlérick", "https://github.com/pvlerick"]
    - ["Steve Huguenin-Elie", "https://github.com/StEvUgnIn"]
    - ["Sebastian Speitel", "https://github.com/SebastianSpeitel"]
    - ["Max Graey", "https://github.com/MaxGraey"]
filename: learnassemblyscript.ts
---

__AssemblyScript__ compiles a variant of __TypeScript__ (basically JavaScript with types) to __WebAssembly__ using __Binaryen__. It generates lean and mean WebAssembly modules while being just an `npm install` away.

This article will focus only on AssemblyScript extra syntax, as opposed to [TypeScript](../typescript/) and [JavaScript](../javascript/).

To test AssemblyScript's compiler, head to the
[Playground](https://www.assemblyscript.org/editor.html#IyFydW50aW1lPXN0dWIKLyoqIENhbGN1bGF0ZXMgdGhlIG4tdGggRmlib25hY2NpIG51bWJlci4gKi8KZXhwb3J0IGZ1bmN0aW9uIGZpYihuOiBpMzIpOiBpMzIgewogIHZhciBhID0gMCwgYiA9IDEKICBpZiAobiA+IDApIHsKICAgIHdoaWxlICgtLW4pIHsKICAgICAgbGV0IHQgPSBhICsgYgogICAgICBhID0gYgogICAgICBiID0gdAogICAgfQogICAgcmV0dXJuIGIKICB9CiAgcmV0dXJuIGEKfQoKIyFodG1sCjx0ZXh0YXJlYSBpZD0ib3V0cHV0IiBzdHlsZT0iaGVpZ2h0OiAxMDAlOyB3aWR0aDogMTAwJSIgcmVhZG9ubHk+PC90ZXh0YXJlYT4KPHNjcmlwdD4KbG9hZGVyLmluc3RhbnRpYXRlKG1vZHVsZV93YXNtLCB7IC8qIGltcG9ydHMgKi8gfSkKICAudGhlbigoeyBleHBvcnRzIH0pID0+IHsKICAgIGNvbnN0IG91dHB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdvdXRwdXQnKQogICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMTA7ICsraSkgewogICAgICBvdXRwdXQudmFsdWUgKz0gYGZpYigke2l9KSA9ICR7ZXhwb3J0cy5maWIoaSl9XG5gCiAgICB9CiAgfSkKPC9zY3JpcHQ+Cg==) where you will be able
to type code, have auto completion and directly see the emitted WebAssembly.

```ts
// There are many basic types in AssemblyScript,
let isDone: boolean = false;
let name: string = "Anders";

// but integer type come as signed (sized from 8 to 64 bits)
let lines8: i8 = 42;
let lines16: i16 = 42;
let lines32: i32 = 42;
let lines64: i64 = 42;

// and unsigned (sized from 8 to 64 bits),
let ulines8: u8 = 42;
let ulines16: u16 = 42;
let ulines32: u32 = 42;
let ulines64: u64 = 42;

// and float has two sizes possible (32/64).
let rate32: f32 = 1.0
let rate64: f64 = 1.0

// But you can omit the type annotation if the variables are derived
// from explicit literals
let _isDone = false;
let _lines = 42;
let _name = "Anders";

// Use const keyword for constants
const numLivesForCat = 9;
numLivesForCat = 1; // Error

// For collections, there are typed arrays and generic arrays
let list1: i8[] = [1, 2, 3];
// Alternatively, using the generic array type
let list2: Array<i8> = [1, 2, 3];

// For enumerations:
enum Color { Red, Green, Blue };
let c: Color = Color.Green;

// Functions imported from JavaScript need to be declared as external
// @ts-ignore decorator
@external("alert")
declare function alert(message: string): void;

// and you can also import JS functions in a namespace
declare namespace window {
  // @ts-ignore decorator
  @external("window", "alert")
  function alert(message: string): void;
}

// Lastly, "void" is used in the special case of a function returning nothing
export function bigHorribleAlert(): void {
  alert("I'm a little annoying box!"); // calling JS function here
}

// Functions are first class citizens, support the lambda "fat arrow" syntax

// The following are equivalent, the compiler does not offer any type
// inference for functions yet, and same WebAssembly will be emitted.
export function f1 (i: i32): i32 { return i * i; }
// "Fat arrow" syntax
let f2 = (i: i32): i32 => { return i * i; }
// "Fat arrow" syntax, braceless means no return keyword needed
let f3 = (i: i32): i32 => i * i;

// Classes - members are public by default
export class Point {
  // Properties
  x: f64;

  // Constructor - the public/private keywords in this context will generate
  // the boiler plate code for the property and the initialization in the
  // constructor.
  // In this example, "y" will be defined just like "x" is, but with less code
  // Default values are also supported

  constructor(x: f64, public y: f64 = 0) {
    this.x = x;
  }

  // Functions
  dist(): f64 { return Math.sqrt(this.x * this.x + this.y * this.y); }

  // Static members
  static origin: Point = new Point(0, 0);
}

// Classes can be explicitly marked as extending a parent class.
// Any missing properties will then cause an error at compile-time.
export class PointPerson extends Point {
  constructor(x: f64, y: f64, public name: string) {
    super(x, y);
  }
  move(): void {}
}

let p1 = new Point(10, 20);
let p2 = new Point(25); //y will be 0

// Inheritance
export class Point3D extends Point {
  constructor(x: f64, y: f64, public z: f64 = 0) {
    super(x, y); // Explicit call to the super class constructor is mandatory
  }

  // Overwrite
  dist(): f64 {
    let d = super.dist();
    return Math.sqrt(d * d + this.z * this.z);
  }
}

// Namespaces, "." can be used as separator for sub namespaces
export namespace Geometry {
  class Square {
    constructor(public sideLength: f64 = 0) {
    }
    area(): f64 {
      return Math.pow(this.sideLength, 2);
    }
  }
}

let s1 = new Geometry.Square(5);

// Generics
// AssemblyScript compiles generics to one concrete method or function per set
// of unique contextual type arguments, also known as [monomorphisation].
// Implications are that a module only includes and exports concrete functions
// for sets of type arguments actually used and that concrete functions can be
// shortcutted with [static type checks] at compile time, which turned out to
// be quite useful.
// Classes
export class Tuple<T1, T2> {
  constructor(public item1: T1, public item2: T2) {
  }
}

export class Pair<T> {
  item1: T;
  item2: T;
}

// And functions
export function pairToTuple <T>(p: Pair<T>): Tuple<T, T> {
  return new Tuple(p.item1, p.item2);
};

let tuple = pairToTuple<string>({ item1: "hello", item2: "world" });

// Including references to a TypeScript-only definition file:
/// <reference path="jquery.d.ts" />

// Template Strings (strings that use backticks)
// String Interpolation with Template Strings
let name = 'Tyrone';
let greeting = `Hi ${name}, how are you?`
// Multiline Strings with Template Strings
let multiline = `This is an example
of a multiline string`;

let numbers: Array<i8> = [0, 1, 2, 3, 4];
let moreNumbers: Array<i8> = numbers;
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

// Type inference in Arrays
let ints = [0, 1, 2, 3, 4]  // will infer as Array<i32>
let floats: f32[] = [0, 1, 2, 3, 4]  // will infer as Array<f32>
let doubles = [0.0, 1.0, 2, 3, 4]  // will infer as Array<f64>
let bytes1 = [0 as u8, 1, 2, 3, 4]  // will infer as Array<u8>
let bytes2 = [0, 1, 2, 3, 4]  as u8[] // will infer as Array<u8>
let bytes3: u8[] = [0, 1, 2, 3, 4] // will infer as Array<u8>
```

## Further Reading

 * [AssemblyScript Official website](https://www.assemblyscript.org/)
 * [AssemblyScript source documentation](https://github.com/AssemblyScript/website/tree/main/src)
 * [Source Code on GitHub](https://github.com/AssemblyScript/assemblyscript)


================================================
FILE: asymptotic-notation.md
================================================
---
category: Algorithms & Data Structures
name: Asymptotic Notation
contributors:
    - ["Jake Prather", "http://github.com/JakeHP"]
    - ["Divay Prakash", "http://github.com/divayprakash"]
---

# Asymptotic Notations

## What are they?

Asymptotic Notations are languages that allow us to analyze an algorithm's 
running time by identifying its behavior as the input size for the algorithm 
increases. This is also known as an algorithm's growth rate. Does the 
algorithm suddenly become incredibly slow when the input size grows? Does it 
mostly maintain its quick run time as the input size increases? Asymptotic 
Notation gives us the ability to answer these questions.

## Are there alternatives to answering these questions?

One way would be to count the number of primitive operations at different 
input sizes. Though this is a valid solution, the amount of work this takes 
for even simple algorithms does not justify its use.

Another way is to physically measure the amount of time an algorithm takes to 
complete given different input sizes. However, the accuracy and relativity 
(times obtained would only be relative to the machine they were computed on) 
of this method is bound to environmental variables such as computer hardware 
specifications, processing power, etc.

## Types of Asymptotic Notation

In the first section of this doc, we described how an Asymptotic Notation 
identifies the behavior of an algorithm as the input size changes. Let us 
imagine an algorithm as a function f, n as the input size, and f(n) being 
the running time. So for a given algorithm f, with input size n you get 
some resultant run time f(n). This results in a graph where the Y-axis is 
the runtime, the X-axis is the input size, and plot points are the resultants 
of the amount of time for a given input size.

You can label a function, or algorithm, with an Asymptotic Notation in many 
different ways. Some examples are, you can describe an algorithm by its best 
case, worst case, or average case. The most common is to analyze an algorithm 
by its worst case. You typically don’t evaluate by best case because those 
conditions aren’t what you’re planning for. An excellent example of this is 
sorting algorithms; particularly, adding elements to a tree structure. The 
best case for most algorithms could be as low as a single operation. However, 
in most cases, the element you’re adding needs to be sorted appropriately 
through the tree, which could mean examining an entire branch. This is 
the worst case, and this is what we plan for.

### Types of functions, limits, and simplification

```
Logarithmic Function - log n
Linear Function - an + b
Quadratic Function - an^2 + bn + c
Polynomial Function - an^z + . . . + an^2 + a*n^1 + a*n^0, where z is some 
constant
Exponential Function - a^n, where a is some constant
```

These are some fundamental function growth classifications used in 
various notations. The list starts at the slowest growing function 
(logarithmic, fastest execution time) and goes on to the fastest 
growing (exponential, slowest execution time). Notice that as ‘n’ 
or the input, increases in each of those functions, the result 
increases much quicker in quadratic, polynomial, and exponential, 
compared to logarithmic and linear.

It is worth noting that for the notations about to be discussed, 
you should do your best to use the simplest terms. This means to 
disregard constants, and lower order terms, because as the input 
size (or n in our f(n) example) increases to infinity (mathematical 
limits), the lower order terms and constants are of little to no 
importance. That being said, if you have constants that are 2^9001, 
or some other ridiculous, unimaginable amount, realize that 
simplifying skew your notation accuracy.

Since we want simplest form, lets modify our table a bit...

```
Logarithmic - log n
Linear - n
Quadratic - n^2
Polynomial - n^z, where z is some constant
Exponential - a^n, where a is some constant
```

### Big-O
Big-O, commonly written as **O**, is an Asymptotic Notation for the worst 
case, or ceiling of growth for a given function. It provides us with an 
_**asymptotic upper bound**_ for the growth rate of the runtime of an algorithm.
Say `f(n)` is your algorithm runtime, and `g(n)` is an arbitrary time 
complexity you are trying to relate to your algorithm. `f(n)` is O(g(n)), if 
for some real constants c (c > 0) and n<sub>0</sub>, `f(n)` <= `c g(n)` for every input size 
n (n > n<sub>0</sub>).

*Example 1*

```
f(n) = 3log n + 100
g(n) = log n
```

Is `f(n)` O(g(n))?
Is `3 log n + 100` O(log n)?
Let's look to the definition of Big-O.

```
3log n + 100 <= c * log n
```

Is there some pair of constants c, n<sub>0</sub> that satisfies this for all n > n<sub>0</sub>?

```
3log n + 100 <= 150 * log n, n > 2 (undefined at n = 1)
```

Yes! The definition of Big-O has been met therefore `f(n)` is O(g(n)).

*Example 2*

```
f(n) = 3*n^2
g(n) = n
```

Is `f(n)` O(g(n))?
Is `3 * n^2` O(n)?
Let's look at the definition of Big-O.

```
3 * n^2 <= c * n
```

Is there some pair of constants c, n<sub>0</sub> that satisfies this for all n > n<sub>0</sub>?
No, there isn't. `f(n)` is NOT O(g(n)).

### Big-Omega
Big-Omega, commonly written as **Ω**, is an Asymptotic Notation for the best 
case, or a floor growth rate for a given function. It provides us with an 
_**asymptotic lower bound**_ for the growth rate of the runtime of an algorithm.

`f(n)` is Ω(g(n)), if for some real constants c (c > 0) and n<sub>0</sub> (n<sub>0</sub> > 0), `f(n)` is >= `c g(n)` 
for every input size n (n > n<sub>0</sub>).

### Note

The asymptotic growth rates provided by big-O and big-omega notation may or 
may not be asymptotically tight. Thus we use small-o and small-omega notation 
to denote bounds that are not asymptotically tight. 

### Small-o
Small-o, commonly written as **o**, is an Asymptotic Notation to denote the 
upper bound (that is not asymptotically tight) on the growth rate of runtime 
of an algorithm.

`f(n)` is o(g(n)), if for all real constants c (c > 0) and n<sub>0</sub> (n<sub>0</sub> > 0), `f(n)` is < `c g(n)` 
for every input size n (n > n<sub>0</sub>).

The definitions of O-notation and o-notation are similar. The main difference 
is that in f(n) = O(g(n)), the bound f(n) <= g(n) holds for _**some**_ 
constant c > 0, but in f(n) = o(g(n)), the bound f(n) < c g(n) holds for 
_**all**_ constants c > 0.

### Small-omega
Small-omega, commonly written as **ω**, is an Asymptotic Notation to denote 
the lower bound (that is not asymptotically tight) on the growth rate of 
runtime of an algorithm.

`f(n)` is ω(g(n)), if for all real constants c (c > 0) and n<sub>0</sub> (n<sub>0</sub> > 0), `f(n)` is > `c g(n)` 
for every input size n (n > n<sub>0</sub>).

The definitions of Ω-notation and ω-notation are similar. The main difference 
is that in f(n) = Ω(g(n)), the bound f(n) >= g(n) holds for _**some**_ 
constant c > 0, but in f(n) = ω(g(n)), the bound f(n) > c g(n) holds for 
_**all**_ constants c > 0.

### Theta
Theta, commonly written as **Θ**, is an Asymptotic Notation to denote the 
_**asymptotically tight bound**_ on the growth rate of runtime of an algorithm. 

`f(n)` is Θ(g(n)), if for some real constants c1, c2 and n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0), 
`c1 g(n)` is < `f(n)` is < `c2 g(n)` for every input size n (n > n<sub>0</sub>).

∴ `f(n)` is Θ(g(n)) implies `f(n)` is O(g(n)) as well as `f(n)` is Ω(g(n)).

Feel free to head over to additional resources for examples on this. Big-O 
is the primary notation use for general algorithm time complexity.

### Endnotes
It's hard to keep this kind of topic short, and you should go 
through the books and online resources listed. They go into much greater depth 
with definitions and examples. More where x='Algorithms & Data Structures' is 
on its way; we'll have a doc up on analyzing actual code examples soon.

## Books

* [Algorithms](http://www.amazon.com/Algorithms-4th-Robert-Sedgewick/dp/032157351X)
* [Algorithm Design](http://www.amazon.com/Algorithm-Design-Foundations-Analysis-Internet/dp/0471383651)

## Online Resources

* [MIT](http://web.mit.edu/16.070/www/lecture/big_o.pdf)
* [KhanAcademy](https://www.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/asymptotic-notation)
* [Big-O Cheatsheet](http://bigocheatsheet.com/) - common structures, operations, and algorithms, ranked by complexity.


================================================
FILE: ats.md
================================================
---
name: ATS
contributors:
  - ["Mark Barbone", "https://github.com/mb64"]
filename: learnats.dats
---

ATS is a low-level functional programming language.  It has a powerful type
system which lets you write programs with the same level of control and
efficiency as C, but in a memory safe and type safe way.

The ATS type system supports:

* Full type erasure: ATS compiles to efficient C
* Dependent types, including [LF](http://twelf.org/wiki/LF) and proving
  metatheorems
* Refinement types
* Linearity for resource tracking
* An effect system that tracks exceptions, mutation, termination, and other
  side effects

This tutorial is not an introduction to functional programming, dependent types,
or linear types, but rather to how they all fit together in ATS.  That said, ATS
is a very complex language, and this tutorial doesn't cover it all.  Not only
does ATS's type system boast a wide array of confusing features, its
idiosyncratic syntax can make even "simple" examples hard to understand.  In the
interest of keeping it a reasonable length, this document is meant to give a
taste of ATS, giving a high-level overview of what's possible and how, rather
than attempting to fully explain how everything works.

You can [try ATS in your browser](http://www.ats-lang.org/SERVER/MYCODE/Patsoptaas_serve.php),
or install it from [http://www.ats-lang.org/](http://www.ats-lang.org/).


```ocaml
// Include the standard library
#include "share/atspre_define.hats"
#include "share/atspre_staload.hats"

// To compile, either use
//   $ patscc -DATS_MEMALLOC_LIBC program.dats -o program
// or install the ats-acc wrapper https://github.com/sparverius/ats-acc and use
//   $ acc pc program.dats

// C-style line comments
/* and C-style block comments */
(* as well as ML-style block comments *)

/*************** Part 1: the ML fragment ****************/

val () = print "Hello, World!\n"

// No currying
fn add (x: int, y: int) = x + y

// fn vs fun is like the difference between let and let rec in OCaml/F#
fun fact (n: int): int = if n = 0 then 1 else n * fact (n-1)

// Multi-argument functions need parentheses when you call them; single-argument
// functions can omit parentheses
val forty_three = add (fact 4, 19)

// let is like let in SML
fn sum_and_prod (x: int, y: int): (int, int) =
  let
    val sum = x + y
    val prod = x * y
  in (sum, prod) end

// 'type' is the type of all heap-allocated, non-linear types
// Polymorphic parameters go in {} after the function name
fn id {a:type} (x: a) = x

// ints aren't heap-allocated, so we can't pass them to 'id'
// val y: int = id 7 // doesn't compile

// 't@ype' is the type of all non-linear potentially unboxed types. It is a
// supertype of 'type'.
// Templated parameters go in {} before the function name
fn {a:t@ype} id2 (x: a) = x

val y: int = id2 7 // works

// can't have polymorphic t@ype parameters
// fn id3 {a:t@ype} (x: a) = x // doesn't compile

// explicitly specifying type parameters:
fn id4 {a:type} (x: a) = id {a} x // {} for non-template parameters
fn id5 {a:type} (x: a) = id2<a> x // <> for template parameters
fn id6 {a:type} (x: a) = id {..} x // {..} to explicitly infer it

// Heap allocated shareable datatypes
// using datatypes leaks memory
datatype These (a:t@ype, b:t@ype) = This of a
                                  | That of b
                                  | These of (a, b)

// Pattern matching using 'case'
fn {a,b: t@ype} from_these (x: a, y: b, these: These(a,b)): (a, b) =
  case these of
  | This(x) => (x, y) // Shadowing of variable names is fine; here, x shadows
                      // the parameter x
  | That(y) => (x, y)
  | These(x, y) => (x, y)

// Partial pattern match using 'case-'
// Will throw an exception if passed This
fn {a,b:t@ype} unwrap_that (these: These(a,b)): b =
  case- these of
  | That(y) => y
  | These(_, y) => y


/*************** Part 2: refinements ****************/

// Parameterize functions by what values they take and return
fn cool_add {n:int} {m:int} (x: int n, y: int m): int (n+m) = x + y

// list(a, n) is a list of n a's
fun square_all {n:int} (xs: list(int, n)): list(int, n) =
  case xs of
  | list_nil() => list_nil()
  | list_cons(x, rest) => list_cons(x * x, square_all rest)

fn {a:t@ype} get_first {n:int | n >= 1} (xs: list(a, n)): a =
  case+ xs of // '+' asks ATS to prove it's total
  | list_cons(x, _) => x

// Can't run get_first on lists of length 0
// val x: int = get_first (list_nil()) // doesn't compile

// in the stdlib:
// sortdef nat = {n:int | n >= 0}
// sortdef pos = {n:int | n >= 1}

fn {a:t@ype} also_get_first {n:pos} (xs: list(a, n)): a =
  let
    val+ list_cons(x, _) = xs // val+ also works
  in x end

// tail-recursive reverse
fun {a:t@ype} reverse {n:int} (xs: list(a, n)): list(a, n) =
  let
    // local functions can use type variables from their enclosing scope
    // this one uses both 'a' and 'n'
    fun rev_helper {i:nat} (xs: list(a, n-i), acc: list(a, i)): list(a, n) =
      case xs of
      | list_nil() => acc
      | list_cons(x, rest) => rev_helper(rest, list_cons(x, acc))
  in rev_helper(xs, list_nil) end

// ATS has three context-dependent namespaces
// the two 'int's mean different things in this example, as do the two 'n's
fn namespace_example {n:int} (n: int n): int n = n
//                      ^^^                         sort namespace
//                    ^          ^^^ ^   ^^^ ^      statics namespace
// ^^^^^^^^^^^^^^^^^          ^                  ^  value namespace

// a termination metric can go in .< >.
// it must decrease on each recursive call
// then ATS will prove it doesn't infinitely recurse
fun terminating_factorial {n:nat} .<n>. (n: int n): int =
  if n = 0 then 1 else n * terminating_factorial (n-1)


/*************** Part 3: the LF fragment ****************/

// ATS supports proving theorems in LF (http://twelf.org/wiki/LF)

// Relations are represented by inductive types

// Proofs that the nth fibonacci number is f
dataprop Fib(n:int, m:int) =
  | FibZero(0, 0)
  | FibOne(1, 1)
  | {n, f1, f2: int} FibInd(n, f1 + f2) of (Fib(n-1,f1), Fib(n-2,f2))

// Proved-correct fibonacci implementation
// [A] B is an existential type: "there exists A such that B"
// (proof | value)
fun fib {n:nat} .<n>. (n: int n): [f:int] (Fib(n,f) | int f) =
  if n = 0 then (FibZero | 0) else
  if n = 1 then (FibOne | 1) else
  let
    val (proof1 | val1) = fib (n-1)
    val (proof2 | val2) = fib (n-2)
  // the existential type is inferred
  in (FibInd(proof1, proof2) | val1 + val2) end

// Faster proved-correct fibonacci implementation
fn fib_tail {n:nat} (n: int n): [f:int] (Fib(n,f) | int f) =
  let
    fun loop {i:int | i < n} {f1, f2: int} .<n - i>.
          (p1: Fib(i,f1), p2: Fib(i+1,f2)
          | i: int i, f1: int f1, f2: int f2, n: int n
          ): [f:int] (Fib(n,f) | int f) =
      if i = n - 1
      then (p2 | f2)
      else loop (p2, FibInd(p2,p1) | i+1, f2, f1+f2, n)
  in if n = 0 then (FibZero | 0) else loop (FibZero, FibOne | 0, 0, 1, n) end

// Proof-level lists of ints, of type 'sort'
datasort IntList = ILNil of ()
                 | ILCons of (int, IntList)

// ILAppend(x,y,z) iff x ++ y = z
dataprop ILAppend(IntList, IntList, IntList) =
  | {y:IntList} AppendNil(ILNil, y, y)
  | {a:int} {x,y,z: IntList}
    AppendCons(ILCons(a,x), y, ILCons(a,z)) of ILAppend(x,y,z)

// prfuns/prfns are compile-time functions acting on proofs

// metatheorem: append is total
prfun append_total {x,y: IntList} .<x>. (): [z:IntList] ILAppend(x,y,z)
  = scase x of // scase lets you inspect static arguments (only in prfuns)
  | ILNil() => AppendNil
  | ILCons(a,rest) => AppendCons(append_total())


/*************** Part 4: views ****************/

// views are like props, but linear; ie they must be consumed exactly once
// prop is a subtype of view

// 'type @ address' is the most basic view

fn {a:t@ype} read_ptr {l:addr} (pf: a@l | p: ptr l): (a@l | a) =
  let
    // !p searches for usable proofs that say something is at that address
    val x = !p
  in (pf | x) end

// oops, tried to dereference a potentially invalid pointer
// fn {a:t@ype} bad {l:addr} (p: ptr l): a = !p // doesn't compile

// oops, dropped the proof (leaked the memory)
// fn {a:t@ype} bad {l:addr} (pf: a@l | p: ptr l): a = !p // doesn't compile

fn inc_at_ptr {l:addr} (pf: int@l | p: ptr l): (int@l | void) =
  let
    // !p := value writes value to the location at p
    // like !p, it implicitly searches for usable proofs that are in scope
    val () = !p := !p + 1
  in (pf | ()) end

// threading proofs through gets annoying
fn inc_three_times {l:addr} (pf: int@l | p: ptr l): (int@l | void) =
  let
    val (pf2 | ()) = inc_at_ptr (pf | p)
    val (pf3 | ()) = inc_at_ptr (pf2 | p)
    val (pf4 | ()) = inc_at_ptr (pf3 | p)
  in (pf4 | ()) end

// so there's special syntactic sugar for when you don't consume a proof
fn dec_at_ptr {l:addr} (pf: !int@l | p: ptr l): void =
  !p := !p - 1           // ^ note the exclamation point

fn dec_three_times {l:addr} (pf: !int@l | p: ptr l): void =
  let
    val () = dec_at_ptr (pf | p)
    val () = dec_at_ptr (pf | p)
    val () = dec_at_ptr (pf | p)
  in () end

// dataview is like dataprop, but linear
// A proof that either the address is null, or there is a value there
dataview MaybeNull(a:t@ype, addr) =
  | NullPtr(a, null)
  | {l:addr | l > null} NonNullPtr(a, l) of (a @ l)

fn maybe_inc {l:addr} (pf: !MaybeNull(int, l) | p: ptr l): void =
  if ptr1_is_null p
  then ()
  else let
    // Deconstruct the proof to access the proof of a @ l
    prval NonNullPtr(value_exists) = pf
    val () = !p := !p + 1
    // Reconstruct it again for the caller
    prval () = pf := NonNullPtr(value_exists)
  in () end

// array_v(a,l,n) represents and array of n a's at location l
// this gets compiled into an efficient for loop, since all proofs are erased
fn sum_array {l:addr}{n:nat} (pf: !array_v(int,l,n) | p: ptr l, n: int n): int =
  let
    fun loop {l:addr}{n:nat} .<n>. (
      pf: !array_v(int,l,n)
    | ptr: ptr l,
      length: int n,
      acc: int
    ): int = if length = 0
      then acc
      else let
        prval (head, rest) = array_v_uncons(pf)
        val result = loop(rest | ptr_add<int>(ptr, 1), length - 1, acc + !ptr)
        prval () = pf := array_v_cons(head, rest)
      in result end
  in loop (pf | p, n, 0) end

// 'var' is used to create stack-allocated (lvalue) variables
val seven: int = let
    var res: int = 3
    // they can be modified
    val () = res := res + 1
    // addr@ res is a pointer to it, and view@ res is the associated proof
    val (pf | ()) = inc_three_times(view@ res | addr@ res)
    // need to give back the view before the variable goes out of scope
    prval () = view@ res := pf
  in res end

// References let you pass lvalues, like in C++
fn square (x: &int): void =
  x := x * x // they can be modified

val sixteen: int = let
    var res: int = 4
    val () = square res
  in res end

fn inc_at_ref (x: &int): void =
  let
    // like vars, references have views and addresses
    val (pf | ()) = inc_at_ptr(view@ x | addr@ x)
    prval () = view@ x := pf
  in () end

// Like ! for views, & references are only legal as argument types
// fn bad (x: &int): &int = x // doesn't 
Download .txt
gitextract_7ub_b4qw/

├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── build.yml
│       └── lint.yml
├── .gitignore
├── .mailmap
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── ada.md
├── agda.md
├── amd.md
├── angularjs.md
├── ansible.md
├── apl.md
├── ar/
│   ├── html.md
│   ├── python.md
│   └── sql.md
├── arturo.md
├── asciidoc.md
├── assemblyscript.md
├── asymptotic-notation.md
├── ats.md
├── awk.md
├── ballerina.md
├── bash.md
├── bc.md
├── be/
│   ├── python.md
│   └── r.md
├── bf.md
├── bg/
│   ├── logtalk.md
│   └── perl.md
├── bqn.md
├── c++.md
├── c.md
├── ca/
│   ├── asciidoc.md
│   ├── go.md
│   ├── groovy.md
│   ├── html.md
│   └── kotlin.md
├── chapel.md
├── chicken.md
├── citron.md
├── clojure-macros.md
├── clojure.md
├── cmake.md
├── cobol.md
├── coffeescript.md
├── coldfusion.md
├── common-lisp.md
├── compojure.md
├── coq.md
├── crystal.md
├── cs/
│   ├── bf.md
│   ├── css.md
│   ├── elm.md
│   ├── go.md
│   ├── hack.md
│   ├── javascript.md
│   ├── json.md
│   ├── markdown.md
│   ├── python.md
│   └── sass.md
├── csharp.md
├── css.md
├── csv.md
├── cue.md
├── cypher.md
├── d.md
├── da/
│   └── javascript.md
├── dart.md
├── de/
│   ├── apl.md
│   ├── asciidoc.md
│   ├── bash.md
│   ├── bc.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── crystal.md
│   ├── csharp.md
│   ├── css.md
│   ├── d.md
│   ├── dhall.md
│   ├── dynamic-programming.md
│   ├── edn.md
│   ├── elixir.md
│   ├── elm.md
│   ├── git.md
│   ├── go.md
│   ├── hack.md
│   ├── haml.md
│   ├── haskell.md
│   ├── hq9+.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── json.md
│   ├── latex.md
│   ├── lolcode.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── nix.md
│   ├── opencv.md
│   ├── paren.md
│   ├── perl.md
│   ├── processing.md
│   ├── pug.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── rst.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── shutit.md
│   ├── sql.md
│   ├── swift.md
│   ├── tcl.md
│   ├── vim.md
│   ├── visualbasic.md
│   └── yaml.md
├── dhall.md
├── directx9.md
├── djot.md
├── docker.md
├── dynamic-programming.md
├── easylang.md
├── edn.md
├── el/
│   ├── bash.md
│   ├── css.md
│   ├── haskell.md
│   ├── html.md
│   ├── java.md
│   ├── json.md
│   ├── ocaml.md
│   ├── python.md
│   ├── racket.md
│   ├── rust.md
│   ├── scala.md
│   └── vim.md
├── elisp.md
├── elixir.md
├── elm.md
├── emacs.md
├── erlang.md
├── es/
│   ├── amd.md
│   ├── asciidoc.md
│   ├── asymptotic-notation.md
│   ├── awk.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── chapel.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── coldfusion.md
│   ├── common-lisp.md
│   ├── csharp.md
│   ├── css.md
│   ├── csv.md
│   ├── curto.md
│   ├── dart.md
│   ├── docker.md
│   ├── dynamic-programming.md
│   ├── edn.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── factor.md
│   ├── forth.md
│   ├── fsharp.md
│   ├── git.md
│   ├── go.md
│   ├── groovy.md
│   ├── hack.md
│   ├── haml.md
│   ├── haskell.md
│   ├── hq9+.md
│   ├── html.md
│   ├── hy.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── latex.md
│   ├── less.md
│   ├── livescript.md
│   ├── logtalk.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── objective-c.md
│   ├── pascal.md
│   ├── pcre.md
│   ├── perl.md
│   ├── php-composer.md
│   ├── php.md
│   ├── powershell.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── pythonstatcomp.md
│   ├── r.md
│   ├── racket.md
│   ├── raku.md
│   ├── rst.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── self.md
│   ├── smallbasic.md
│   ├── sql.md
│   ├── swift.md
│   ├── tcl.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── wolfram.md
│   ├── xml.md
│   └── yaml.md
├── fa/
│   ├── bf.md
│   ├── css.md
│   ├── html.md
│   ├── javascript.md
│   └── vim.md
├── factor.md
├── fi/
│   ├── go.md
│   ├── markdown.md
│   └── ruby.md
├── fish.md
├── forth.md
├── fortran.md
├── fr/
│   ├── asymptotic-notation.md
│   ├── awk.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── crystal.md
│   ├── csharp.md
│   ├── css.md
│   ├── d.md
│   ├── dynamic-programming.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── erlang.md
│   ├── fsharp.md
│   ├── git.md
│   ├── go.md
│   ├── haml.md
│   ├── haskell.md
│   ├── html.md
│   ├── hy.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── livescript.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── nix.md
│   ├── objective-c.md
│   ├── pcre.md
│   ├── perl.md
│   ├── php.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── r.md
│   ├── racket.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── scala.md
│   ├── set-theory.md
│   ├── sql.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── wolfram.md
│   ├── xml.md
│   └── yaml.md
├── fsharp.md
├── gdscript.md
├── git.md
├── gleam.md
├── go.md
├── golfscript.md
├── groovy.md
├── hack.md
├── haml.md
├── haskell.md
├── haxe.md
├── hcl.md
├── hdl.md
├── he/
│   ├── html.md
│   └── uxntal.md
├── hi/
│   ├── amd.md
│   ├── c++.md
│   ├── d.md
│   └── json.md
├── hjson.md
├── hocon.md
├── hq9+.md
├── hre.csv
├── html.md
├── httpie.md
├── hu/
│   ├── coffeescript.md
│   ├── go.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── typescript.md
│   └── yaml.md
├── hy.md
├── id/
│   ├── asciidoc.md
│   ├── bf.md
│   ├── coffeescript.md
│   ├── css.md
│   ├── hq9+.md
│   ├── java.md
│   ├── json.md
│   ├── markdown.md
│   ├── php.md
│   ├── pyqt.md
│   ├── rst.md
│   ├── ruby.md
│   ├── smallbasic.md
│   └── xml.md
├── inform7.md
├── it/
│   ├── asciidoc.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── cmake.md
│   ├── coffeescript.md
│   ├── dynamic-programming.md
│   ├── elixir.md
│   ├── fish.md
│   ├── gdscript.md
│   ├── git.md
│   ├── go.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── logtalk.md
│   ├── lua.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── pcre.md
│   ├── php-composer.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── rst.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── solidity.md
│   ├── sql.md
│   ├── toml.md
│   ├── typescript.md
│   ├── vim.md
│   └── zfs.md
├── ja/
│   ├── asciidoc.md
│   ├── bash.md
│   ├── c.md
│   ├── css.md
│   ├── elixir.md
│   ├── julia.md
│   ├── markdown.md
│   ├── nim.md
│   ├── php.md
│   ├── python.md
│   ├── r.md
│   ├── rust.md
│   ├── vim.md
│   └── yaml.md
├── janet.md
├── java.md
├── javascript.md
├── jinja.md
├── jq.md
├── jquery.md
├── json.md
├── jsonnet.md
├── julia.md
├── kdb+.md
├── ko/
│   ├── bash.md
│   ├── bf.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── erlang.md
│   ├── go.md
│   ├── java.md
│   ├── javascript.md
│   ├── json.md
│   ├── kotlin.md
│   ├── lua.md
│   ├── markdown.md
│   ├── php.md
│   ├── pythonlegacy.md
│   ├── racket.md
│   ├── vim.md
│   ├── xml.md
│   └── yaml.md
├── kotlin.md
├── lambda-calculus.md
├── latex.md
├── lbstanza.md
├── ldpl.md
├── lean4.md
├── less.md
├── lfe.md
├── linker.md
├── lint/
│   ├── encoding.sh
│   ├── frontmatter.py
│   └── requirements.txt
├── livescript.md
├── logtalk.md
├── lolcode.md
├── lt/
│   ├── json.md
│   └── tmux.md
├── lua.md
├── m.md
├── make.md
├── markdown.md
├── matlab.md
├── mercurial.md
├── mercury.md
├── messagepack.md
├── miniscript.md
├── mips.md
├── mongodb.md
├── moonscript.md
├── ms/
│   ├── bash.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── elisp.md
│   ├── javascript.md
│   ├── json.md
│   ├── sass.md
│   └── xml.md
├── nim.md
├── niva.md
├── nix.md
├── nl/
│   ├── amd.md
│   ├── bash.md
│   ├── bf.md
│   ├── coffeescript.md
│   ├── dynamic-programming.md
│   ├── html.md
│   ├── json.md
│   ├── markdown.md
│   ├── typescript.md
│   ├── vim.md
│   ├── xml.md
│   └── yaml.md
├── nmap.md
├── no/
│   ├── bash.md
│   └── json.md
├── objective-c.md
├── ocaml.md
├── odin.md
├── opencv.md
├── opengl.md
├── openmp.md
├── openscad.md
├── osl.md
├── p5.md
├── paren.md
├── pascal.md
├── pcre.md
├── perl.md
├── pets.csv
├── phel.md
├── phix.md
├── php-composer.md
├── php.md
├── pl/
│   ├── bf.md
│   ├── haskell.md
│   ├── java.md
│   ├── json.md
│   ├── perl.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── vim.md
│   └── xml.md
├── powershell.md
├── processing.md
├── prolog.md
├── protocol-buffer-3.md
├── pt-br/
│   ├── amd.md
│   ├── asciidoc.md
│   ├── asymptotic-notation.md
│   ├── awk.md
│   ├── bash.md
│   ├── bc.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── cmake.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── csharp.md
│   ├── css.md
│   ├── cypher.md
│   ├── d.md
│   ├── dart.md
│   ├── dynamic-programming.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── elm.md
│   ├── emacs.md
│   ├── erlang.md
│   ├── factor.md
│   ├── fsharp.md
│   ├── git.md
│   ├── go.md
│   ├── groovy.md
│   ├── hack.md
│   ├── haskell.md
│   ├── haxe.md
│   ├── html.md
│   ├── httpie.md
│   ├── hy.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── latex.md
│   ├── less.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── p5.md
│   ├── paren.md
│   ├── pascal.md
│   ├── perl.md
│   ├── php-composer.md
│   ├── php.md
│   ├── processing.md
│   ├── pug.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── pythonstatcomp.md
│   ├── qt.md
│   ├── r.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── self.md
│   ├── set-theory.md
│   ├── solidity.md
│   ├── sql.md
│   ├── stylus.md
│   ├── swift.md
│   ├── tmux.md
│   ├── toml.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── xml.md
│   └── yaml.md
├── pt-pt/
│   ├── bf.md
│   ├── git.md
│   ├── kotlin.md
│   ├── scala.md
│   └── swift.md
├── pug.md
├── purescript.md
├── pyqt.md
├── python.md
├── pythonlegacy.md
├── pythonstatcomp.md
├── qml.md
├── qsharp.md
├── qt.md
├── r.md
├── racket.md
├── raku-pod.md
├── raku.md
├── raylib.md
├── rdf.md
├── reason.md
├── red.md
├── rescript.md
├── rink.md
├── ro/
│   ├── bash.md
│   ├── bf.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── elixir.md
│   ├── haskell.md
│   ├── json.md
│   ├── latex.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   └── xml.md
├── rst.md
├── ru/
│   ├── asymptotic-notation.md
│   ├── bash.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── crystal.md
│   ├── css.md
│   ├── d.md
│   ├── dynamic-programming.md
│   ├── elixir.md
│   ├── erlang.md
│   ├── forth.md
│   ├── go.md
│   ├── haml.md
│   ├── haskell.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── linker.md
│   ├── lua.md
│   ├── markdown.md
│   ├── nim.md
│   ├── objective-c.md
│   ├── paren.md
│   ├── pascal.md
│   ├── perl.md
│   ├── php-composer.md
│   ├── php.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sql.md
│   ├── swift.md
│   ├── tcl.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── xml.md
│   ├── yaml.md
│   └── zfs.md
├── ruby-ecosystem.md
├── ruby.md
├── rust.md
├── sass.md
├── scala.md
├── sed.md
├── self.md
├── set-theory.md
├── shutit.md
├── sing.md
├── sk/
│   ├── bash.md
│   ├── coffeescript.md
│   ├── elixir.md
│   ├── git.md
│   ├── json.md
│   ├── latex.md
│   └── ruby.md
├── sl/
│   └── asciidoc.md
├── smallbasic.md
├── smalltalk.md
├── snobol.md
├── solidity.md
├── sorbet.md
├── sql.md
├── standard-ml.md
├── stylus.md
├── sv/
│   ├── bf.md
│   ├── haskell.md
│   ├── json.md
│   └── nix.md
├── swift.md
├── ta/
│   ├── css.md
│   ├── javascript.md
│   ├── json.md
│   └── xml.md
├── tailspin.md
├── tcl.md
├── tcsh.md
├── texinfo.md
├── textile.md
├── th/
│   ├── pascal.md
│   └── typescript.md
├── tmux.md
├── toml.md
├── tr/
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure.md
│   ├── csharp.md
│   ├── css.md
│   ├── dynamic-programming.md
│   ├── edn.md
│   ├── fsharp.md
│   ├── gdscript.md
│   ├── git.md
│   ├── html.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── kotlin.md
│   ├── markdown.md
│   ├── objective-c.md
│   ├── php.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── sql.md
│   ├── swift.md
│   └── typescript.md
├── typescript.md
├── uk/
│   ├── awk.md
│   ├── bash.md
│   ├── c.md
│   ├── cypher.md
│   ├── go.md
│   ├── java.md
│   ├── javascript.md
│   ├── json.md
│   ├── kotlin.md
│   ├── mips.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sql.md
│   ├── typescript.md
│   └── wasm.md
├── uxntal.md
├── v.md
├── vala.md
├── vi/
│   ├── git.md
│   ├── html.md
│   ├── json.md
│   ├── less.md
│   ├── markdown.md
│   ├── objective-c.md
│   ├── python.md
│   ├── ruby-ecosystem.md
│   ├── ruby.md
│   ├── sass.md
│   ├── typescript.md
│   └── xml.md
├── vim.md
├── vim9script.md
├── vimscript.md
├── visualbasic.md
├── wasm.md
├── wikitext.md
├── wolfram.md
├── xml.md
├── yaml.md
├── zfs.md
├── zh-cn/
│   ├── angularjs.md
│   ├── asciidoc.md
│   ├── awk.md
│   ├── bash.md
│   ├── bc.md
│   ├── bf.md
│   ├── c++.md
│   ├── c.md
│   ├── clojure-macros.md
│   ├── clojure.md
│   ├── cmake.md
│   ├── cobol.md
│   ├── coffeescript.md
│   ├── common-lisp.md
│   ├── crystal.md
│   ├── csharp.md
│   ├── css.md
│   ├── dart.md
│   ├── docker.md
│   ├── dynamic-programming.md
│   ├── elisp.md
│   ├── elixir.md
│   ├── erlang.md
│   ├── fortran.md
│   ├── fsharp.md
│   ├── gdscript.md
│   ├── git.md
│   ├── go.md
│   ├── groovy.md
│   ├── haskell.md
│   ├── html.md
│   ├── java.md
│   ├── javascript.md
│   ├── jquery.md
│   ├── json.md
│   ├── julia.md
│   ├── kotlin.md
│   ├── lambda-calculus.md
│   ├── latex.md
│   ├── less.md
│   ├── livescript.md
│   ├── lua.md
│   ├── make.md
│   ├── markdown.md
│   ├── matlab.md
│   ├── mips.md
│   ├── nim.md
│   ├── nix.md
│   ├── objective-c.md
│   ├── opencv.md
│   ├── perl.md
│   ├── php.md
│   ├── powershell.md
│   ├── pyqt.md
│   ├── python.md
│   ├── pythonlegacy.md
│   ├── qt.md
│   ├── r.md
│   ├── racket.md
│   ├── raylib.md
│   ├── red.md
│   ├── ruby.md
│   ├── rust.md
│   ├── sass.md
│   ├── scala.md
│   ├── set-theory.md
│   ├── solidity.md
│   ├── sql.md
│   ├── standard-ml.md
│   ├── swift.md
│   ├── tmux.md
│   ├── typescript.md
│   ├── vim.md
│   ├── visualbasic.md
│   ├── wolfram.md
│   ├── xml.md
│   ├── yaml.md
│   └── zfs.md
├── zh-tw/
│   ├── bash.md
│   ├── dart.md
│   ├── elixir.md
│   ├── javascript.md
│   ├── pcre.md
│   ├── perl.md
│   ├── pythonlegacy.md
│   └── typescript.md
└── zig.md
Download .txt
SYMBOL INDEX (5 symbols across 1 files)

FILE: lint/frontmatter.py
  function extract_yaml_frontmatter (line 10) | def extract_yaml_frontmatter(file_path):
  function lint_yaml (line 34) | def lint_yaml(yaml_content):
  function validate_yaml_keys (line 42) | def validate_yaml_keys(yaml_content, allowed_keys):
  function process_files (line 72) | def process_files(path):
  function main (line 105) | def main(path_input):
Copy disabled (too large) Download .json
Condensed preview — 886 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,511K chars).
[
  {
    "path": ".gitattributes",
    "chars": 52,
    "preview": "*.md linguist-language=Markdown linguist-detectable\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 194,
    "preview": "/fr-fr/ @vendethiel\r\n/ru-ru/ @Menelion\r\n/uk-ua/ @Menelion\r\n/zh-cn/ @geoffliu @imba-tjd\r\n/zh-tw/ @geoffliu @imba-tjd\r\n/ko"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 762,
    "preview": "## Is this a major issue that you cannot fix?\n\n**Being a community driven documents of languages and tools,\"YOUR\" contri"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 693,
    "preview": "- [ ] I solemnly swear that this is all original content of which I am the original author\n- [ ] Pull request title is p"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 439,
    "preview": "name: Trigger site build\n\non:\n  push:\n    branches: [main, master]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    if: g"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 1331,
    "preview": "name: CI\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    branches: [master]\n\njobs:\n  lint:\n    runs-on: ubuntu-l"
  },
  {
    "path": ".gitignore",
    "chars": 187,
    "preview": "**/*~\n**/*#\n**/#*#\n**/*.swp\n**/*.swo\n**/*.bak\n**/*.log*\n**/*.sublime-workspace\n**/.DS_Store\n**/.DS_Store?\n**/._*\n**/.Spo"
  },
  {
    "path": ".mailmap",
    "chars": 1643,
    "preview": "Leigh Brenecki <l@leigh.net.au> <adam@brenecki.id.au>\n\nAdam Bard <github@adambard.com> Adam <adam@adambard.com>\nAdam Bar"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3710,
    "preview": "# Contributing\n\nAll contributions are welcome, from the tiniest typo to a brand new article.\nTranslations in all languag"
  },
  {
    "path": "LICENSE.txt",
    "chars": 22240,
    "preview": "Creative Commons Legal Code\n\nAttribution-ShareAlike 3.0 Unported\n\n    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND"
  },
  {
    "path": "README.md",
    "chars": 1828,
    "preview": "# [Learn X in Y minutes][1]\n\nWhirlwind tours of (several, hopefully many someday) popular and\nought-to-be-more-popular p"
  },
  {
    "path": "ada.md",
    "chars": 18042,
    "preview": "---\nname: Ada\nfilename: learn.ada\ncontributors:\n    - [\"Luke A. Guest\", \"https://github.com/Lucretia\"]\n    - [\"Fernando "
  },
  {
    "path": "agda.md",
    "chars": 12345,
    "preview": "---\nname: Agda\nfilename: learnagda.agda\ncontributors:\n    - [\"pe200012\", \"https://github.com/pe200012\"]\n---\n\nAgda is a d"
  },
  {
    "path": "amd.md",
    "chars": 7537,
    "preview": "---\ncategory: tool\nname: AMD\ncontributors:\n    - [\"Frederik Ring\", \"https://github.com/m90\"]\nfilename: learnamd.js\n---\n\n"
  },
  {
    "path": "angularjs.md",
    "chars": 22278,
    "preview": "---\ncategory: framework\nname: AngularJS\ncontributors:\n    - [\"Walter Cordero\", \"http://waltercordero.com\"]\nfilename: lea"
  },
  {
    "path": "ansible.md",
    "chars": 21904,
    "preview": "---\ncategory: tool\nname: Ansible\ncontributors:\n    - [\"Jakub Muszynski\" , \"http://github.com/sirkubax\"]\n    - [\"Pat Myro"
  },
  {
    "path": "apl.md",
    "chars": 1849,
    "preview": "---\nname: APL\ncontributors:\n    - [\"nooodl\", \"https://github.com/nooodl\"]\nfilename: learnapl.apl\n---\n\n```apl\n⍝ Comments "
  },
  {
    "path": "ar/html.md",
    "chars": 3836,
    "preview": "---\ncontributors:\n    - [\"Christophe THOMAS\", \"https://github.com/WinChris\"]\ntranslators:\n    - [\"Ader\", \"https://github"
  },
  {
    "path": "ar/python.md",
    "chars": 31375,
    "preview": "---\ncontributors:\n    - [\"Louie Dinh\", \"http://pythonpracticeprojects.com\"]\n    - [\"Steven Basart\", \"http://github.com/x"
  },
  {
    "path": "ar/sql.md",
    "chars": 4460,
    "preview": "---\ncontributors:\n  - [\"Bob DuCharme\", \"http://bobdc.com/\"]\ntranslators:\n    - [\"Ahmed Omar Eissa\", \"https://twitter.com"
  },
  {
    "path": "arturo.md",
    "chars": 10537,
    "preview": "---\nname: Arturo\nfilename: learnarturo.art\ncontributors:\n  - [\"Dr.Kameleon\", \"https://github.com/drkameleon\"]\n---\n\n```re"
  },
  {
    "path": "asciidoc.md",
    "chars": 2846,
    "preview": "---\nname: AsciiDoc\ncontributors:\n    - [\"Ryan Mavilia\", \"http://unoriginality.rocks/\"]\n    - [\"Abel Salgado Romero\", \"ht"
  },
  {
    "path": "assemblyscript.md",
    "chars": 7209,
    "preview": "---\nname: AssemblyScript\ncontributors:\n    - [\"Philippe Vlérick\", \"https://github.com/pvlerick\"]\n    - [\"Steve Huguenin-"
  },
  {
    "path": "asymptotic-notation.md",
    "chars": 8444,
    "preview": "---\ncategory: Algorithms & Data Structures\nname: Asymptotic Notation\ncontributors:\n    - [\"Jake Prather\", \"http://github"
  },
  {
    "path": "ats.md",
    "chars": 19772,
    "preview": "---\nname: ATS\ncontributors:\n  - [\"Mark Barbone\", \"https://github.com/mb64\"]\nfilename: learnats.dats\n---\n\nATS is a low-le"
  },
  {
    "path": "awk.md",
    "chars": 13037,
    "preview": "---\ncategory: tool\nname: AWK\nfilename: learnawk.awk\ncontributors:\n     - [\"Marshall Mason\", \"http://github.com/marshallm"
  },
  {
    "path": "ballerina.md",
    "chars": 14366,
    "preview": "---\nname: Ballerina\ncontributors:\n    - [\"Anjana Fernando\", \"https://github.com/lafernando\"]\nfilename: learn_ballerina.b"
  },
  {
    "path": "bash.md",
    "chars": 18144,
    "preview": "---\nname: Bash\ncontributors:\n    - [\"Max Yankov\", \"https://github.com/golergka\"]\n    - [\"Darren Lin\", \"https://github.co"
  },
  {
    "path": "bc.md",
    "chars": 2543,
    "preview": "---\nname: bc\ncontributors:\n    - [\"Btup\"]\nfilename: learnbc.bc\n---\n```bc\n/*This is a multi-\nline comment.*/\n# This is al"
  },
  {
    "path": "be/python.md",
    "chars": 37034,
    "preview": "---\ncontributors:\n    - [\"Louie Dinh\", \"http://pythonpracticeprojects.com\"]\n    - [\"Steven Basart\", \"http://github.com/x"
  },
  {
    "path": "be/r.md",
    "chars": 25300,
    "preview": "---\nname: R\ncontributors:\n    - [\"e99n09\", \"http://github.com/e99n09\"]\n    - [\"isomorphismes\", \"http://twitter.com/isomo"
  },
  {
    "path": "bf.md",
    "chars": 3729,
    "preview": "---\nname: BF\nwhere_x_eq_name: brainfuck\nfilename: bf.bf\ncontributors:\n    - [\"Prajit Ramachandran\", \"http://prajitr.gith"
  },
  {
    "path": "bg/logtalk.md",
    "chars": 14646,
    "preview": "---\ncontributors:\n    - [\"Paulo Moura\", \"http://github.com/pmoura\"]\ntranslators:\n    - [\"vsraptor\", \"https://github.com/"
  },
  {
    "path": "bg/perl.md",
    "chars": 9133,
    "preview": "---\ncontributors:\n    - [\"Korjavin Ivan\", \"http://github.com/korjavin\"]\n    - [\"Dan Book\", \"http://github.com/Grinnz\"]\nt"
  },
  {
    "path": "bqn.md",
    "chars": 10377,
    "preview": "---\nname: BQN\nfilename: learnbqn.bqn\ncontributors:\n    - [\"Raghu Ranganathan\", \"https://github.com/razetime\"]\n---\n\nBQN i"
  },
  {
    "path": "c++.md",
    "chars": 37870,
    "preview": "---\nname: C++\nfilename: learncpp.cpp\ncontributors:\n    - [\"Steven Basart\", \"https://github.com/xksteven\"]\n    - [\"Matt K"
  },
  {
    "path": "c.md",
    "chars": 34403,
    "preview": "---\nname: C\nfilename: learnc.c\ncontributors:\n  - [\"Adam Bard\", \"http://adambard.com/\"]\n  - [\"Árpád Goretity\", \"http://tw"
  },
  {
    "path": "ca/asciidoc.md",
    "chars": 2972,
    "preview": "---\ncontributors:\n    - [\"Ryan Mavilia\", \"http://unoriginality.rocks/\"]\ntranslators:\n    - [\"Abel Salgado Romero\", \"http"
  },
  {
    "path": "ca/go.md",
    "chars": 16897,
    "preview": "---\ncontributors:\n    - [\"Sonia Keys\", \"https://github.com/soniakeys\"]\n    - [\"Christopher Bess\", \"https://github.com/cb"
  },
  {
    "path": "ca/groovy.md",
    "chars": 9389,
    "preview": "---\ncontributors:\n    - [\"Roberto Pérez Alcolea\", \"http://github.com/rpalcolea\"]\ntranslators:\n    - [\"Xavier Sala Pujola"
  },
  {
    "path": "ca/html.md",
    "chars": 5091,
    "preview": "---\ncontributors:\n    - [\"Christophe THOMAS\", \"https://github.com/WinChris\"]\ntranslators:\n    - [\"Marc Auledas\", \"https:"
  },
  {
    "path": "ca/kotlin.md",
    "chars": 12082,
    "preview": "---\ncontributors:\n    - [\"S Webber\", \"https://github.com/s-webber\"]\ntranslators:\n    - [\"Xavier Sala\", \"https://github.c"
  },
  {
    "path": "chapel.md",
    "chars": 40539,
    "preview": "---\nname: Chapel\nfilename: learnchapel.chpl\ncontributors:\n    - [\"Ian J. Bertolacci\", \"https://www.cs.arizona.edu/~ianbe"
  },
  {
    "path": "chicken.md",
    "chars": 17617,
    "preview": "---\nname: \"CHICKEN\"\nfilename: CHICKEN.scm\ncontributors:\n  - [\"Diwakar Wagle\", \"https://github.com/deewakar\"]\n---\n\n\nCHICK"
  },
  {
    "path": "citron.md",
    "chars": 6003,
    "preview": "---\nname: citron\nfilename: learncitron.ctr\ncontributors:\n    - [\"AnotherTest\", \"\"]\n---\n```ruby\n# Comments start with a '"
  },
  {
    "path": "clojure-macros.md",
    "chars": 4375,
    "preview": "---\nname: Clojure macros\nfilename: learnclojuremacros.clj\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\n---\n"
  },
  {
    "path": "clojure.md",
    "chars": 12343,
    "preview": "---\nname: Clojure\nfilename: learnclojure.clj\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\n---\n\nClojure is a"
  },
  {
    "path": "cmake.md",
    "chars": 5327,
    "preview": "---\ncategory: tool\nname: CMake\ncontributors:\n    - [\"Bruno Alano\", \"https://github.com/brunoalano\"]\nfilename: CMake\n---\n"
  },
  {
    "path": "cobol.md",
    "chars": 6984,
    "preview": "---\nname: COBOL\ncontributors:\n    - [\"Hyphz\", \"http://github.com/hyphz/\"]\nfilename: learn.cob\n---\n\nCOBOL is a business-o"
  },
  {
    "path": "coffeescript.md",
    "chars": 2879,
    "preview": "---\nname: CoffeeScript\ncontributors:\n  - [\"Tenor Biel\", \"http://github.com/L8D\"]\n  - [\"Xavier Yao\", \"http://github.com/x"
  },
  {
    "path": "coldfusion.md",
    "chars": 9104,
    "preview": "---\nname: ColdFusion\nfilename: learncoldfusion.cfm\ncontributors:\n    - [\"Wayne Boka\", \"http://wboka.github.io\"]\n    - [\""
  },
  {
    "path": "common-lisp.md",
    "chars": 20167,
    "preview": "---\n\nname: \"Common Lisp\"\nfilename: commonlisp.lisp\ncontributors:\n  - [\"Paul Nathan\", \"https://github.com/pnathan\"]\n  - ["
  },
  {
    "path": "compojure.md",
    "chars": 6917,
    "preview": "---\ncategory: tool\nname: Compojure\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\nfilename: learncompojure.cl"
  },
  {
    "path": "coq.md",
    "chars": 17311,
    "preview": "---\nname: Coq\nfilename: learncoq.v\ncontributors:\n    - [\"Philip Zucker\", \"http://www.philipzucker.com/\"]\n---\n\nThe Coq sy"
  },
  {
    "path": "crystal.md",
    "chars": 12011,
    "preview": "---\nname: Crystal\nfilename: learncrystal.cr\ncontributors:\n    - [\"Vitalii Elenhaupt\", \"http://veelenga.com\"]\n    - [\"Arn"
  },
  {
    "path": "cs/bf.md",
    "chars": 3608,
    "preview": "---\ncontributors:\n    - [\"Prajit Ramachandran\", \"http://prajitr.github.io/\"]\n    - [\"Mathias Bynens\", \"http://mathiasbyn"
  },
  {
    "path": "cs/css.md",
    "chars": 8248,
    "preview": "---\ncontributors:\n    - [\"Mohammad Valipour\", \"https://github.com/mvalipour\"]\n    - [\"Marco Scannadinari\", \"https://gith"
  },
  {
    "path": "cs/elm.md",
    "chars": 13095,
    "preview": "---\ncontributors:\n    - [\"Max Goldstein\", \"http://maxgoldste.in/\"]\ntranslators:\n    - [\"Robin Pokorný\", \"http://robinpok"
  },
  {
    "path": "cs/go.md",
    "chars": 15837,
    "preview": "---\ncontributors:\n    - [\"Sonia Keys\", \"https://github.com/soniakeys\"]\n    - [\"Christopher Bess\", \"https://github.com/cb"
  },
  {
    "path": "cs/hack.md",
    "chars": 7313,
    "preview": "---\ncontributors:\n    - [\"Stephen Holdaway\", \"https://github.com/stecman\"]\ntranslators:\n    - [\"Vojta Svoboda\", \"https:/"
  },
  {
    "path": "cs/javascript.md",
    "chars": 20007,
    "preview": "---\ncontributors:\n    - [\"Leigh Brenecki\", \"https://leigh.net.au\"]\n    - [\"Ariel Krakowski\", \"http://www.learneroo.com\"]"
  },
  {
    "path": "cs/json.md",
    "chars": 1586,
    "preview": "---\ncontributors:\n  - [\"Anna Harren\", \"https://github.com/iirelu\"]\n  - [\"Marco Scannadinari\", \"https://github.com/marcom"
  },
  {
    "path": "cs/markdown.md",
    "chars": 9024,
    "preview": "---\ncontributors:\n    - [\"Dan Turkel\", \"http://danturkel.com/\"]\ntranslators:\n    - [\"Michal Martinek\", \"https://github.c"
  },
  {
    "path": "cs/python.md",
    "chars": 19398,
    "preview": "---\ncontributors:\n    - [\"Louie Dinh\", \"http://pythonpracticeprojects.com\"]\n    - [\"Steven Basart\", \"http://github.com/x"
  },
  {
    "path": "cs/sass.md",
    "chars": 8712,
    "preview": "---\ncontributors:\n  - [\"Laura Kyle\", \"https://github.com/LauraNK\"]\n  - [\"Sean Corrales\", \"https://github.com/droidenator"
  },
  {
    "path": "csharp.md",
    "chars": 48415,
    "preview": "---\nname: C#\ncontributors:\n    - [\"Irfan Charania\", \"https://github.com/irfancharania\"]\n    - [\"Max Yankov\", \"https://gi"
  },
  {
    "path": "css.md",
    "chars": 12139,
    "preview": "---\nname: CSS\ncontributors:\n    - [\"Mohammad Valipour\", \"https://github.com/mvalipour\"]\n    - [\"Marco Scannadinari\", \"ht"
  },
  {
    "path": "csv.md",
    "chars": 3330,
    "preview": "---\nname: CSV\ncontributors:\n- [Timon Erhart, 'https://github.com/turbotimon/']\n---\n\nCSV (Comma-Separated Values) is a li"
  },
  {
    "path": "cue.md",
    "chars": 14331,
    "preview": "---\nname: CUE\nfilename: learncue.cue\ncontributors:\n    - [\"Daniel Cox\", \"https://github.com/danielpcox\"]\n    - [\"Coleman"
  },
  {
    "path": "cypher.md",
    "chars": 5656,
    "preview": "---\nname: Cypher\nfilename: LearnCypher.cql\ncontributors:\n    - [\"Théo Gauchoux\", \"https://github.com/TheoGauchoux\"]\n---\n"
  },
  {
    "path": "d.md",
    "chars": 6977,
    "preview": "---\nname: D\nfilename: learnd.d\ncontributors:\n    - [\"Nick Papanastasiou\", \"www.nickpapanastasiou.github.io\"]\n---\n\n```d\n/"
  },
  {
    "path": "da/javascript.md",
    "chars": 19747,
    "preview": "---\ncontributors:\n  - [\"Leigh Brenecki\", \"https://leigh.net.au\"]\n  - [\"Ariel Krakowski\", \"http://www.learneroo.com\"]\ntra"
  },
  {
    "path": "dart.md",
    "chars": 22470,
    "preview": "---\nname: Dart\nfilename: learndart.dart\ncontributors:\n  - [\"Joao Pedrosa\", \"https://github.com/jpedrosa/\"]\n  - [\"Vince R"
  },
  {
    "path": "de/apl.md",
    "chars": 2049,
    "preview": "---\nname: APL\ncontributors:\n    - [\"nooodl\", \"https://github.com/nooodl\"]\ntranslators:\n    - [\"antonkesy\", \"https://gith"
  },
  {
    "path": "de/asciidoc.md",
    "chars": 2070,
    "preview": "---\ncontributors:\n    - [\"Ryan Mavilia\", \"http://unoriginality.rocks/\"]\ntranslators:\n  - [\"Dennis Keller\", \"https://gith"
  },
  {
    "path": "de/bash.md",
    "chars": 8997,
    "preview": "---\ncontributors:\n    - [\"Max Yankov\", \"https://github.com/golergka\"]\n    - [\"Darren Lin\", \"https://github.com/CogBear\"]"
  },
  {
    "path": "de/bc.md",
    "chars": 3019,
    "preview": "---\ncontributors:\n    - [\"caminsha\", \"https://github.com/caminsha\"]\n---\n\n```bc\n/* Das ist ein mehr-\nzeiliger Kommentar *"
  },
  {
    "path": "de/bf.md",
    "chars": 4034,
    "preview": "---\ncontributors:\n    - [\"Prajit Ramachandran\", \"http://prajitr.github.io/\"]\n    - [\"Mathias Bynens\", \"http://mathiasbyn"
  },
  {
    "path": "de/c++.md",
    "chars": 35892,
    "preview": "---\ncontributors:\n    - [\"Steven Basart\", \"http://github.com/xksteven\"]\n    - [\"Matt Kline\", \"https://github.com/mrkline"
  },
  {
    "path": "de/c.md",
    "chars": 35114,
    "preview": "---\ncontributors:\n    - [\"caminsha\", \"https://github.com/caminsha\"]\n---\n\nAch, C. Immer noch **die** Sprache für modernes"
  },
  {
    "path": "de/clojure-macros.md",
    "chars": 4917,
    "preview": "---\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\ntranslators:\n    - [\"Dennis Keller\", \"https://github.com/d"
  },
  {
    "path": "de/clojure.md",
    "chars": 13539,
    "preview": "---\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\ntranslators:\n    - [\"Dennis Keller\", \"https://github.com/d"
  },
  {
    "path": "de/coffeescript.md",
    "chars": 3049,
    "preview": "---\ncontributors:\n  - [\"Tenor Biel\", \"http://github.com/L8D\"]\n  - [\"Xavier Yao\", \"http://github.com/xavieryao\"]\ntranslat"
  },
  {
    "path": "de/crystal.md",
    "chars": 13140,
    "preview": "---\ncontributors:\n    - [\"Vitalii Elenhaupt\", \"http://veelenga.com\"]\n    - [\"Arnaud Fernandés\", \"https://github.com/Tech"
  },
  {
    "path": "de/csharp.md",
    "chars": 35248,
    "preview": "---\ncontributors:\n    - [\"Irfan Charania\", \"https://github.com/irfancharania\"]\n    - [\"Max Yankov\", \"https://github.com/"
  },
  {
    "path": "de/css.md",
    "chars": 7063,
    "preview": "---\ncontributors:\n    - [\"Mohammad Valipour\", \"https://github.com/mvalipour\"]\ntranslators:\n    - [\"Kyr\", \"http://github."
  },
  {
    "path": "de/d.md",
    "chars": 6358,
    "preview": "---\ncontributors:\n    - [\"Nick Papanastasiou\", \"www.nickpapanastasiou.github.io\"]\ntranslators:\n    - [\"Dominik Süß\", \"ww"
  },
  {
    "path": "de/dhall.md",
    "chars": 12355,
    "preview": "---\ncontributors:\n    - [\"Gabriel Gonzalez\", \"http://www.haskellforall.com/\"]\ntranslators:\n    - [\"Profpatsch\", \"http://"
  },
  {
    "path": "de/dynamic-programming.md",
    "chars": 3511,
    "preview": "---\ncontributors:\n    - [\"Akashdeep Goel\", \"http://github.com/akashdeepgoel\"]\ntranslators:\n    - [\"Henrik Jürges\", \"http"
  },
  {
    "path": "de/edn.md",
    "chars": 3553,
    "preview": "---\ncontributors:\n  - [\"Jason Yeo\", \"https://github.com/jsyeo\"]\n  - [\"Jonathan D Johnston\", \"https://github.com/jdjohnst"
  },
  {
    "path": "de/elixir.md",
    "chars": 11569,
    "preview": "---\ncontributors:\n    - [\"Joao Marques\", \"http://github.com/mrshankly\"]\ntranslators:\n    - [\"Gregor Große-Bölting\", \"htt"
  },
  {
    "path": "de/elm.md",
    "chars": 13152,
    "preview": "---\ncontributors:\n  - [\"Max Goldstein\", \"http://maxgoldste.in/\"]\ntranslators:\n  - [\"waynee95\", \"https://waynee95.me\"]\n--"
  },
  {
    "path": "de/git.md",
    "chars": 11959,
    "preview": "---\ncontributors:\n    - [\"Jake Prather\", \"http://github.com/JakeHP\"]\ntranslators:\n    - [\"kultprok\", \"http://www.kulturp"
  },
  {
    "path": "de/go.md",
    "chars": 12608,
    "preview": "---\ncontributors:\n    - [\"Joseph Adams\", \"https://github.com/jcla1\"]\n    - [\"Dennis Keller\", \"https://github.com/dennisk"
  },
  {
    "path": "de/hack.md",
    "chars": 8058,
    "preview": "---\ncontributors:\n    - [\"Stephen Holdaway\", \"https://github.com/stecman\"]\n    - [\"David Lima\", \"https://github.com/dave"
  },
  {
    "path": "de/haml.md",
    "chars": 4065,
    "preview": "---\ncontributors:\n  - [\"Simon Neveu\", \"https://github.com/sneveu\"]\n  - [\"Sol Bekic\", \"https://github.com/S0lll0s\"]\n---\n\n"
  },
  {
    "path": "de/haskell.md",
    "chars": 12805,
    "preview": "---\ncontributors:\n    - [\"Adit Bhargava\", \"http://adit.io\"]\ntranslators:\n    - [\"Henrik Jürges\", \"https://github.com/san"
  },
  {
    "path": "de/hq9+.md",
    "chars": 1203,
    "preview": "---\ncontributors:\n    - [\"Alexey Nazaroff\", \"https://github.com/rogaven\"]\ntranslators:\n    - [\"Dennis Keller\", \"https://"
  },
  {
    "path": "de/html.md",
    "chars": 4862,
    "preview": "---\ncontributors:\n    - [\"Christophe THOMAS\", \"https://github.com/WinChris\"]\ntranslators:\n    - [\"Dennis Keller\", \"https"
  },
  {
    "path": "de/java.md",
    "chars": 19077,
    "preview": "---\ncontributors:\n    - [\"Jake Prather\", \"http://github.com/JakeHP\"]\n    - [\"Jakukyo Friel\", \"http://weakish.github.io\"]"
  },
  {
    "path": "de/javascript.md",
    "chars": 18873,
    "preview": "---\ncontributors:\n    - [\"Leigh Brenecki\", \"https://leigh.net.au\"]\ntranslators:\n    - [\"ggb\", \"http://www.ideen-und-soeh"
  },
  {
    "path": "de/json.md",
    "chars": 1814,
    "preview": "---\ncontributors:\n  - [\"Anna Harren\", \"https://github.com/iirelu\"]\n  - [\"Marco Scannadinari\", \"https://github.com/marcom"
  },
  {
    "path": "de/latex.md",
    "chars": 9393,
    "preview": "---\ncontributors:\n    - [\"Chaitanya Krishna Ande\", \"http://icymist.github.io\"]\n    - [\"Colton Kohnke\", \"http://github.co"
  },
  {
    "path": "de/lolcode.md",
    "chars": 5383,
    "preview": "---\ncontributors:\n    - [\"abactel\", \"https://github.com/abactel\"]\ntranslators:\n    - [\"Henrik Jürges\", \"http://github.co"
  },
  {
    "path": "de/lua.md",
    "chars": 15128,
    "preview": "---\ncontributors:\n    - [\"Tyler Neylon\", \"http://tylerneylon.com/\"]\ntranslators:\n    - [\"Martin Schimandl\", \"https://git"
  },
  {
    "path": "de/make.md",
    "chars": 8524,
    "preview": "---\ncontributors:\n    - [\"Robert Steed\", \"https://github.com/robochat\"]\n    - [\"Stephan Fuhrmann\", \"https://github.com/s"
  },
  {
    "path": "de/markdown.md",
    "chars": 7688,
    "preview": "---\ncontributors:\n    - [\"Dan Turkel\", \"http://danturkel.com/\"]\ntranslators:\n    - [\"Frederik Ring\", \"https://github.com"
  },
  {
    "path": "de/nix.md",
    "chars": 9496,
    "preview": "---\nfilename: learnnix.nix\ncontributors:\n    - [\"Chris Martin\", \"http://chris-martin.org/\"]\ntranslators:\n    - [\"Dennis "
  },
  {
    "path": "de/opencv.md",
    "chars": 6103,
    "preview": "---\ncontributors:\n    - [\"Yogesh Ojha\", \"http://github.com/yogeshojha\"]\ntranslators:\n    - [\"Dennis Keller\", \"https://gi"
  },
  {
    "path": "de/paren.md",
    "chars": 5890,
    "preview": "---\n\ncontributors:\n  - [\"KIM Taegyoon\", \"https://github.com/kimtg\"]\n  - [\"Claudson Martins\", \"https://github.com/claudso"
  },
  {
    "path": "de/perl.md",
    "chars": 4721,
    "preview": "---\ncontributors:\n    - [\"Korjavin Ivan\", \"http://github.com/korjavin\"]\ntranslators:\n    - [\"Martin Schimandl\", \"http://"
  },
  {
    "path": "de/processing.md",
    "chars": 18948,
    "preview": "---\ncontributors:\n    - [\"Phone Thant Ko\", \"http://github.com/phonethantko\"]\n    - [\"Divay Prakash\", \"https://github.com"
  },
  {
    "path": "de/pug.md",
    "chars": 3930,
    "preview": "---\ncontributors:\n  - [\"Michael Warner\", \"https://github.com/MichaelJGW\"]\nfilename: lernepug.pug\ntranslators:\n    - [\"de"
  },
  {
    "path": "de/pyqt.md",
    "chars": 2740,
    "preview": "---\ncontributors:\n    - [\"Nathan Hughes\", \"https://github.com/sirsharpest\"]\ntranslators:\n    - [\"Dennis Keller\", \"https:"
  },
  {
    "path": "de/python.md",
    "chars": 37966,
    "preview": "---\ncontributors:\n    - [\"Louie Dinh\", \"http://ldinh.ca\"]\ntranslators:\n    - [\"kultprok\", \"http:/www.kulturproktologie.d"
  },
  {
    "path": "de/pythonlegacy.md",
    "chars": 25715,
    "preview": "---\ncontributors:\n    - [\"Louie Dinh\", \"http://ldinh.ca\"]\ntranslators:\n    - [\"kultprok\", \"http:/www.kulturproktologie.d"
  },
  {
    "path": "de/qt.md",
    "chars": 4779,
    "preview": "---\ncontributors:\n    - [\"Aleksey Kholovchuk\", \"https://github.com/vortexxx192\"]\ntranslators:\n    - [\"Dennis Keller\", \"h"
  },
  {
    "path": "de/rst.md",
    "chars": 3339,
    "preview": "---\ncontributors:\n    - [\"DamienVGN\", \"https://github.com/martin-damien\"]\n    - [\"Andre Polykanine\", \"https://github.com"
  },
  {
    "path": "de/ruby-ecosystem.md",
    "chars": 6551,
    "preview": "---\ncontributors:\n    - [\"Jon Smock\", \"http://github.com/jonsmock\"]\n    - [\"Rafal Chmiel\", \"http://github.com/rafalchmie"
  },
  {
    "path": "de/ruby.md",
    "chars": 17969,
    "preview": "---\ncontributors:\n  - [\"David Underwood\", \"http://theflyingdeveloper.com\"]\n  - [\"Joel Walden\", \"http://joelwalden.net\"]\n"
  },
  {
    "path": "de/rust.md",
    "chars": 10667,
    "preview": "---\ncontributors:\n    - [\"P1start\", \"http://p1start.github.io/\"]\ntranslators:\n    - [\"Christian Albrecht\", \"https://gith"
  },
  {
    "path": "de/sass.md",
    "chars": 9760,
    "preview": "---\ncontributors:\n  - [\"Laura Kyle\", \"https://github.com/LauraNK\"]\n  - [\"Sean Corrales\", \"https://github.com/droidenator"
  },
  {
    "path": "de/scala.md",
    "chars": 23029,
    "preview": "---\ncontributors:\n    - [\"George Petrov\", \"http://github.com/petrovg\"]\n    - [\"Dominic Bou-Samra\", \"http://dbousamra.git"
  },
  {
    "path": "de/shutit.md",
    "chars": 9516,
    "preview": "---\ncontributors:\n    - [\"Ian Miell\", \"http://ian.meirionconsulting.tk\"]\ntranslators:\n    - [\"Dennis Keller\", \"https://g"
  },
  {
    "path": "de/sql.md",
    "chars": 5568,
    "preview": "---\ncontributors:\n  - [\"Bob DuCharme\", \"http://bobdc.com/\"]\ntranslators:\n    - [\"denniskeller\", \"https://github.com/denn"
  },
  {
    "path": "de/swift.md",
    "chars": 16081,
    "preview": "---\ncontributors:\n  - [\"Grant Timmerman\", \"http://github.com/grant\"]\n  - [\"Christopher Bess\", \"http://github.com/cbess\"]"
  },
  {
    "path": "de/tcl.md",
    "chars": 14927,
    "preview": "---\ncontributors:\n    - [\"Poor Yorick\", \"http://pooryorick.com/\"]\ntranslators:\n    - [\"Martin Schimandl\", \"https://githu"
  },
  {
    "path": "de/vim.md",
    "chars": 9744,
    "preview": "---\ncontributors:\n- [\"RadhikaG\", \"https://github.com/RadhikaG\"]\ntranslators:\n- [\"caminsha\", \"https://github.com/caminsha"
  },
  {
    "path": "de/visualbasic.md",
    "chars": 10708,
    "preview": "---\ncontributors:\n    - [\"Brian Martin\", \"http://brianmartin.biz\"]\ntranslators:\n    - [\"Enno Nagel\", \"https://github.com"
  },
  {
    "path": "de/yaml.md",
    "chars": 4728,
    "preview": "---\ncontributors:\n  - [\"Leigh Brenecki\", \"https://github.com/adambrenecki\"]\ntranslators:\n  - [\"Ruben M.\", \"https://githu"
  },
  {
    "path": "dhall.md",
    "chars": 11849,
    "preview": "---\nname: Dhall\nfilename: learndhall.dhall\ncontributors:\n    - [\"Gabriel Gonzalez\", \"http://www.haskellforall.com/\"]\n---"
  },
  {
    "path": "directx9.md",
    "chars": 33572,
    "preview": "---\ncategory: framework\nname: DirectX 9\nfilename: learndirectx9.cpp\ncontributors:\n    - [\"Simon Deitermann\", \"s.f.deiter"
  },
  {
    "path": "djot.md",
    "chars": 5530,
    "preview": "---\nname: Djot\ncontributors:\n    - [\"stag\", \"http://github.com/stag-enterprises/\"]\nfilename: learndjot.dj\n---\n\n[Djot](ht"
  },
  {
    "path": "docker.md",
    "chars": 12720,
    "preview": "---\ncategory: tool\nname: Docker\nfilename: docker.bat\ncontributors:\n    - [\"Ruslan López\", \"http://javapro.org/\"]\n    - ["
  },
  {
    "path": "dynamic-programming.md",
    "chars": 4160,
    "preview": "---\ncategory: Algorithms & Data Structures\nname: Dynamic Programming\ncontributors:\n    - [\"Akashdeep Goel\", \"http://gith"
  },
  {
    "path": "easylang.md",
    "chars": 4122,
    "preview": "---\nname: Easylang\ncontributors:\n    - [\"chkas\", \"https://github.com/chkas\"]\nfilename: easylang.el\n---\n\n**Easylang** is "
  },
  {
    "path": "edn.md",
    "chars": 3236,
    "preview": "---\nname: EDN\nfilename: learnedn.edn\ncontributors:\n  - [\"Jason Yeo\", \"https://github.com/jsyeo\"]\n  - [\"Jonathan D Johnst"
  },
  {
    "path": "el/bash.md",
    "chars": 20005,
    "preview": "---\ncontributors:\n    - [\"Dimitri Kokkonis\", \"https://github.com/kokkonisd\"]\n---\n\nΗ λέξη «bash» είναι ένα από τα ονόματα"
  },
  {
    "path": "el/css.md",
    "chars": 7830,
    "preview": "---\ncontributors:\n    - [\"Kostas Bariotis\", \"http://kostasbariotis.com\"]\nfilename: css.css\n---\n\nΗ αρχική μορφή του Παγκό"
  },
  {
    "path": "el/haskell.md",
    "chars": 15948,
    "preview": "---\ncontributors:\n    - [\"Miltiadis Stouras\", \"https://github.com/mstou\"]\n---\n\nΗ Haskell σχεδιάστηκε για να είναι μια πρ"
  },
  {
    "path": "el/html.md",
    "chars": 5653,
    "preview": "---\ncontributors:\n    - [\"Dimitri Kokkonis\", \"https://github.com/kokkonisd\"]\n---\n\nΤο ακρώνυμο HTML σημαίνει HyperText Ma"
  },
  {
    "path": "el/java.md",
    "chars": 31776,
    "preview": "---\ncontributors:\n    - [\"Jake Prather\", \"http://github.com/JakeHP\"]\n    - [\"Jakukyo Friel\", \"http://weakish.github.io\"]"
  },
  {
    "path": "el/json.md",
    "chars": 2883,
    "preview": "---\nfilename: json.json\ncontributors:\n  - [\"Anna Harren\", \"https://github.com/iirelu\"]\n  - [\"Marco Scannadinari\", \"https"
  },
  {
    "path": "el/ocaml.md",
    "chars": 13107,
    "preview": "---\ncontributors:\n    - [\"Daniil Baturin\", \"http://baturin.org/\"]\ntranslators:\n    - [\"Chariton Charitonidis\", \"https://"
  },
  {
    "path": "el/python.md",
    "chars": 35944,
    "preview": "---\ncontributors:\n    - [\"Louie Dinh\", \"http://pythonpracticeprojects.com\"]\n    - [\"Steven Basart\", \"http://github.com/x"
  },
  {
    "path": "el/racket.md",
    "chars": 22970,
    "preview": "---\ncontributors:\n  - [\"th3rac25\", \"https://github.com/voila\"]\n  - [\"Eli Barzilay\", \"https://github.com/elibarzilay\"]\n  "
  },
  {
    "path": "el/rust.md",
    "chars": 11923,
    "preview": "---\ncontributors:\n    - [\"P1start\", \"http://p1start.github.io/\"]\n    - [\"Dimitri Kokkonis\", \"https://github.com/kokkonis"
  },
  {
    "path": "el/scala.md",
    "chars": 23728,
    "preview": "---\ncontributors:\n    - [\"George Petrov\", \"http://github.com/petrovg\"]\n    - [\"Dominic Bou-Samra\", \"http://dbousamra.git"
  },
  {
    "path": "el/vim.md",
    "chars": 9418,
    "preview": "---\ncontributors:\n    - [\"RadhikaG\", \"https://github.com/RadhikaG\"]\n---\n\n\n[Vim](http://www.vim.org)\nTo (Vi IMproved) είν"
  },
  {
    "path": "elisp.md",
    "chars": 10946,
    "preview": "---\nname: Emacs Lisp\ncontributors:\n    - [\"Bastien Guerry\", \"https://bzg.fr\"]\n    - [\"Saurabh Sandav\", \"http://github.co"
  },
  {
    "path": "elixir.md",
    "chars": 12490,
    "preview": "---\nname: Elixir\ncontributors:\n    - [\"Joao Marques\", \"https://github.com/mrshankly\"]\n    - [\"Dzianis Dashkevich\", \"http"
  },
  {
    "path": "elm.md",
    "chars": 12899,
    "preview": "---\nname: Elm\ncontributors:\n    - [\"Max Goldstein\", \"http://maxgoldste.in/\"]\nfilename: learnelm.elm\n---\n\nElm is a functi"
  },
  {
    "path": "emacs.md",
    "chars": 12726,
    "preview": "---\ncategory: tool\nname: Emacs\nfilename: emacs.txt\ncontributors:\n    - [\"Joseph Riad\", \"https://github.com/Joseph-Riad\"]"
  },
  {
    "path": "erlang.md",
    "chars": 13097,
    "preview": "---\nname: Erlang\ncontributors:\n    - [\"Giovanni Cappellotto\", \"http://giovanni.curlybrackets.it/\"]\nfilename: learnerlang"
  },
  {
    "path": "es/amd.md",
    "chars": 7971,
    "preview": "---\n\ncontributors:\n    - [\"Frederik Ring\", \"https://github.com/m90\"]\n\ntranslators:\n    - [\"Damaso Sanoja\", \"https://gith"
  },
  {
    "path": "es/asciidoc.md",
    "chars": 3037,
    "preview": "---\ncontributors:\n    - [\"Ryan Mavilia\", \"http://unoriginality.rocks/\"]\ntranslators:\n    - [\"Abel Salgado Romero\", \"http"
  },
  {
    "path": "es/asymptotic-notation.md",
    "chars": 6761,
    "preview": "---\ncontributors:\n    - [\"Jake Prather\", \"http://github.com/JakeHP\"]\ntranslators:\n    - [\"Gerson Lázaro\", \"https://gerso"
  },
  {
    "path": "es/awk.md",
    "chars": 11908,
    "preview": "---\ncontributors:\n    - [\"Marshall Mason\", \"http://github.com/marshallmason\"]\ntranslators:\n    - [\"Hugo Guillén-Ramírez\""
  },
  {
    "path": "es/bash.md",
    "chars": 5984,
    "preview": "---\ncontributors:\n    - [\"Max Yankov\", \"https://github.com/golergka\"]\n    - [\"Darren Lin\", \"https://github.com/CogBear\"]"
  },
  {
    "path": "es/bf.md",
    "chars": 3742,
    "preview": "---\ncontributors:\n    - [\"Prajit Ramachandran\", \"http://prajitr.github.io/\"]\n    - [\"Mathias Bynens\", \"http://mathiasbyn"
  },
  {
    "path": "es/c++.md",
    "chars": 26231,
    "preview": "---\ncontributors:\n    - [\"Steven Basart\", \"http://github.com/xksteven\"]\n    - [\"Matt Kline\", \"https://github.com/mrkline"
  },
  {
    "path": "es/c.md",
    "chars": 13404,
    "preview": "---\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\ntranslators:\n    - [\"Francisco García\", \"http://flaskbreak"
  },
  {
    "path": "es/chapel.md",
    "chars": 42121,
    "preview": "---\ncontributors:\n    - [\"Ian J. Bertolacci\", \"https://www.cs.arizona.edu/~ianbertolacci/\"]\n    - [\"Ben Harshbarger\", \"h"
  },
  {
    "path": "es/clojure.md",
    "chars": 13661,
    "preview": "---\ncontributors:\n    - [\"Adam Bard\", \"http://adambard.com/\"]\ntranslators:\n    - [\"Antonio Hernández Blas\", \"https://twi"
  },
  {
    "path": "es/coffeescript.md",
    "chars": 1300,
    "preview": "---\ncontributors:\n  - [\"Tenor Biel\", \"http://github.com/L8D\"]\ntranslators:\n  - [\"Pablo Elices\", \"http://github.com/pablo"
  },
  {
    "path": "es/coldfusion.md",
    "chars": 9225,
    "preview": "---\ncontributors:\n    - [\"Wayne Boka\", \"http://wboka.github.io\"]\n    - [\"Kevin Morris\", \"https://twitter.com/kevinmorris"
  },
  {
    "path": "es/common-lisp.md",
    "chars": 21012,
    "preview": "---\ncontributors:\n  - [\"Paul Nathan\", \"https://github.com/pnathan\"]\n  - [\"Paul Khuong\", \"https://github.com/pkhuong\"]\n  "
  },
  {
    "path": "es/csharp.md",
    "chars": 22694,
    "preview": "---\ncontributors:\n    - [\"Irfan Charania\", \"https://github.com/irfancharania\"]\n    - [\"Max Yankov\", \"https://github.com/"
  },
  {
    "path": "es/css.md",
    "chars": 10663,
    "preview": "---\ncontributors:\n    - [\"Mohammad Valipour\", \"https://github.com/mvalipour\"]\n    - [\"Marco Scannadinari\", \"https://gith"
  },
  {
    "path": "es/csv.md",
    "chars": 3965,
    "preview": "---\nname: CSV\ncontributors:\n- [Timon Erhart, 'https://github.com/turbotimon/']\ntranslators:\n- [Luis Morales, 'https://gi"
  },
  {
    "path": "es/curto.md",
    "chars": 7051,
    "preview": "---\nname: curto\ncontributors:\n    - [\"Maleza\", \"https://maleza.srht.site/\"]\nfilename: learncurto.fs\n---\n\nCurto es una tr"
  },
  {
    "path": "es/dart.md",
    "chars": 16752,
    "preview": "---\ncontributors:\n    - [\"Joao Pedrosa\", \"https://github.com/jpedrosa/\"]\ntranslators:\n    - [\"Jorge Antonio Atempa\", \"ht"
  },
  {
    "path": "es/docker.md",
    "chars": 7341,
    "preview": "---\ncontributors:\n    - [\"Ruslan López\", \"http://javapro.org/\"]\n    - [\"Michael Chen\", \"https://github.com/ML-Chen\"]\n---"
  },
  {
    "path": "es/dynamic-programming.md",
    "chars": 3512,
    "preview": "---\ncontributors:\n    - [\"Akashdeep Goel\", \"http://github.com/akashdeepgoel\"]\ntranslators:\n    - [\"Gino Amaury\", \"https:"
  },
  {
    "path": "es/edn.md",
    "chars": 3416,
    "preview": "---\ncontributors:\n  - [\"Jason Yeo\", \"https://github.com/jsyeo\"]\ntranslators:\n    - [\"Gino Amaury\", \"https://github.com/g"
  },
  {
    "path": "es/elisp.md",
    "chars": 12215,
    "preview": "---\ncontributors:\n    - [\"Bastien Guerry\", \"http://bzg.fr\"]\ntranslators:\n    - [\"Guillermo Vayá\", \"http://willyfrog.es\"]"
  },
  {
    "path": "es/elixir.md",
    "chars": 12684,
    "preview": "---\ncontributors:\n    - [\"Joao Marques\", \"http://github.com/mrshankly\"]\n    - [\"Dzianis Dashkevich\", \"https://github.com"
  },
  {
    "path": "es/factor.md",
    "chars": 8429,
    "preview": "---\ncontributors:\n    - [\"hyphz\", \"http://github.com/hyphz/\"]\ntranslators:\n    - [\"Roberto R\", \"https://github.com/rrodr"
  },
  {
    "path": "es/forth.md",
    "chars": 7761,
    "preview": "---\ncontributors:\n    - [\"Horse M.D.\", \"http://github.com/HorseMD/\"]\ntranslators:\n    - [\"Zach Larsen\", \"http://zacharia"
  },
  {
    "path": "es/fsharp.md",
    "chars": 22806,
    "preview": "---\ncontributors:\n  - ['Scott Wlaschin', 'http://fsharpforfunandprofit.com/']\ntranslators:\n  - ['Angel Arciniega', 'http"
  },
  {
    "path": "es/git.md",
    "chars": 11465,
    "preview": "---\ncontributors:\n    - [\"Jake Prather\", \"http://github.com/JakeHP\"]\ntranslators:\n    - [\"Raúl Ascencio\", \"http://rscnt."
  },
  {
    "path": "es/go.md",
    "chars": 17424,
    "preview": "---\ncontributors:\n    - [\"Sonia Keys\", \"https://github.com/soniakeys\"]\n    - [\"Christopher Bess\", \"https://github.com/cb"
  },
  {
    "path": "es/groovy.md",
    "chars": 9704,
    "preview": "---\ncontributors:\n    - [\"Roberto Pérez Alcolea\", \"http://github.com/rpalcolea\"]\ntranslators:\n    - [\"Jhoon Saravia\", \"h"
  },
  {
    "path": "es/hack.md",
    "chars": 7592,
    "preview": "---\ncontributors:\n    - [\"Stephen Holdaway\", \"https://github.com/stecman\"]\n    - [\"David Lima\", \"https://github.com/dave"
  },
  {
    "path": "es/haml.md",
    "chars": 4863,
    "preview": "---\ncontributors:\n  - [\"Simon Neveu\", \"https://github.com/sneveu\"]\ntranslators:\n    - [\"Camilo Garrido\", \"http://www.twi"
  },
  {
    "path": "es/haskell.md",
    "chars": 13367,
    "preview": "---\ncontributors:\n    - [\"Adit Bhargava\", \"http://adit.io\"]\ntranslators:\n    - [\"Jorge Antonio Atempa\", \"http://www.twit"
  },
  {
    "path": "es/hq9+.md",
    "chars": 1141,
    "preview": "---\ncontributors:\n    - [\"Alexey Nazaroff\", \"https://github.com/rogaven\"]\ntranslators:\n    - [\"Roberto R\", \"https://gith"
  },
  {
    "path": "es/html.md",
    "chars": 4884,
    "preview": "---\ncontributors:\n    - [\"Christophe THOMAS\", \"https://github.com/WinChris\"]\ntranslators:\n    - [\"Gino Amaury\", \"https:/"
  },
  {
    "path": "es/hy.md",
    "chars": 5434,
    "preview": "---\ncontributors:\n    - [\"Abhishek L\", \"http://twitter.com/abhishekl\"]\ntranslators:\n    - [\"Roberto R\", \"https://github."
  },
  {
    "path": "es/java.md",
    "chars": 14820,
    "preview": "---\ncontributors:\n    - [\"Jake Prather\", \"http://github.com/JakeHP\"]\ntranslators:\n    - [\"Camilo Garrido\", \"http://www.t"
  },
  {
    "path": "es/javascript.md",
    "chars": 18080,
    "preview": "---\ncontributors:\n    - [\"Leigh Brenecki\", \"https://leigh.net.au\"]\n    - [\"Ariel Krakowski\", \"http://www.learneroo.com\"]"
  },
  {
    "path": "es/jquery.md",
    "chars": 5553,
    "preview": "---\ncontributors:\n    - [\"Sawyer Charles\", \"https://github.com/xssc\"]\ntranslators:\n    - [\"Ivan Alburquerque\", \"https://"
  },
  {
    "path": "es/json.md",
    "chars": 1568,
    "preview": "---\ncontributors:\n  - [\"Anna Harren\", \"https://github.com/iirelu\"]\n  - [\"Marco Scannadinari\", \"https://github.com/marcom"
  },
  {
    "path": "es/julia.md",
    "chars": 31656,
    "preview": "---\ncontributors:\n    - [\"Leah Hanson\", \"http://leahhanson.us\"]\ntranslators:\n    - [\"Guillermo Garza\", \"http://github.co"
  },
  {
    "path": "es/kotlin.md",
    "chars": 13355,
    "preview": "---\ncontributors:\n- [\"S Webber\", \"https://github.com/s-webber\"]\n- [\"Aitor Escolar\", \"https://github.com/aiescola\"]\ntrans"
  },
  {
    "path": "es/lambda-calculus.md",
    "chars": 6069,
    "preview": "---\ncontributors:\n    - [\"Max Sun\", \"http://github.com/maxsun\"]\n    - [\"Yan Hui Hang\", \"http://github.com/yanhh0\"]\ntrans"
  },
  {
    "path": "es/latex.md",
    "chars": 8547,
    "preview": "---\ncontributors:\n    - [\"Chaitanya Krishna Ande\", \"http://icymist.github.io\"]\n    - [\"Colton Kohnke\", \"http://github.co"
  },
  {
    "path": "es/less.md",
    "chars": 7492,
    "preview": "---\ncontributors:\n  - [\"Saravanan Ganesh\", \"http://srrvnn.me\"]\ntranslators:\n  - [\"César Suárez\", \"https://github.com/csu"
  },
  {
    "path": "es/livescript.md",
    "chars": 11502,
    "preview": "---\ncontributors:\n    - [\"Christina Whyte\", \"http://github.com/kurisuwhyte/\"]\ntranslators:\n    - [\"Daniel Zendejas\", \"ht"
  },
  {
    "path": "es/logtalk.md",
    "chars": 9300,
    "preview": "---\ncontributors:\n    - [\"Paulo Moura\", \"http://github.com/pmoura\"]\n    - [\"Adrián Arroyo Calle\", \"https://adrianistan.e"
  }
]

// ... and 686 more files (download for full content)

About this extraction

This page contains the full source code of the adambard/learnxinyminutes-docs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 886 files (9.6 MB), approximately 2.5M tokens, and a symbol index with 5 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!