mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 09:41:36 +00:00
Merge branch 'master' into patch-2
This commit is contained in:
commit
4d59048f0d
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -46,13 +46,13 @@ json*.html.markdown linguist-language=JSON
|
||||
julia*.html.markdown linguist-language=Julia
|
||||
kotlin*.html.markdown linguist-language=Kotlin
|
||||
latex*.html.markdown linguist-language=latex
|
||||
less*.html.markdown linguist-language=less
|
||||
less*.html.markdown linguist-language=Less
|
||||
livescript*.html.markdown linguist-language=LiveScript
|
||||
logtalk*.html.markdown linguist-language=Logtalk
|
||||
lua*.html.markdown linguist-language=Lua
|
||||
make*.html.markdown linguist-language=Makefile
|
||||
markdown*.html.markdown linguist-language=Markdown
|
||||
matlab*.html.markdown linguist-language=Matlab
|
||||
matlab*.html.markdown linguist-language=MATLAB
|
||||
nim*.html.markdown linguist-language=Nimrod
|
||||
nix*.html.markdown linguist-language=Nix
|
||||
objective-c*.html.markdown linguist-language=Objective-C
|
||||
|
7
.github/CODEOWNERS
vendored
7
.github/CODEOWNERS
vendored
@ -1,5 +1,8 @@
|
||||
/fr-fr/ @vendethiel
|
||||
/ru-ru/ @Menelion
|
||||
/uk-ua/ @Menelion
|
||||
/zh-cn/ @geoffliu
|
||||
/zh-tw/ @geoffliu
|
||||
/zh-cn/ @geoffliu @imba-tjd
|
||||
/zh-tw/ @geoffliu @imba-tjd
|
||||
/ko-kr/ @justin-themedium
|
||||
/pt-pt/ @mribeirodantas
|
||||
/pt-br/ @mribeirodantas
|
||||
|
607
ATS.html.markdown
Normal file
607
ATS.html.markdown
Normal file
@ -0,0 +1,607 @@
|
||||
---
|
||||
language: 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
|
||||
|
||||
// explicity 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 compile
|
||||
|
||||
// this takes a proof int n @ l, but returns a proof int (n+1) @ l
|
||||
// since they're different types, we can't use !int @ l like before
|
||||
fn refined_inc_at_ptr {n:int}{l:addr} (
|
||||
pf: int n @ l | p: ptr l
|
||||
): (int (n+1) @ l | void) =
|
||||
let
|
||||
val () = !p := !p + 1
|
||||
in (pf | ()) end
|
||||
|
||||
// special syntactic sugar for returning a proof at a different type
|
||||
fn refined_dec_at_ptr {n:int}{l:addr} (
|
||||
pf: !int n @ l >> int (n-1) @ l | p: ptr l
|
||||
): void =
|
||||
!p := !p - 1
|
||||
|
||||
// legal but very bad code
|
||||
prfn swap_proofs {v1,v2:view} (a: !v1 >> v2, b: !v2 >> v1): void =
|
||||
let
|
||||
prval tmp = a
|
||||
prval () = a := b
|
||||
prval () = b := tmp
|
||||
in () end
|
||||
|
||||
// also works with references
|
||||
fn refined_square {n:int} (x: &int n >> int (n*n)): void =
|
||||
x := x * x
|
||||
|
||||
fn replace {a,b:vtype} (dest: &a >> b, src: b): a =
|
||||
let
|
||||
val old = dest
|
||||
val () = dest := src
|
||||
in old end
|
||||
|
||||
// values can be uninitialized
|
||||
fn {a:vt@ype} write (place: &a? >> a, value: a): void =
|
||||
place := value
|
||||
|
||||
val forty: int = let
|
||||
var res: int
|
||||
val () = write (res, 40)
|
||||
in res end
|
||||
|
||||
// viewtype: a view and a type
|
||||
viewtypedef MaybeNullPtr(a:t@ype) = [l:addr] (MaybeNull(a, l) | ptr l)
|
||||
// MaybeNullPtr has type 'viewtype' (aka 'vtype')
|
||||
// type is a subtype of vtype and t@ype is a subtype of vt@ype
|
||||
|
||||
// The most general identity function:
|
||||
fn {a:vt@ype} id7 (x: a) = x
|
||||
|
||||
// since they contain views, viewtypes must be used linearly
|
||||
// fn {a:vt@ype} duplicate (x: a) = (x, x) // doesn't compile
|
||||
// fn {a:vt@ype} ignore (x: a) = () // doesn't compile
|
||||
|
||||
// arrayptr(a,l,n) is a convenient built-in viewtype
|
||||
fn easier_sum_array {l:addr}{n:nat} (p: !arrayptr(int,l,n), n: int n): int =
|
||||
let
|
||||
fun loop {i:nat | i <= n} (
|
||||
p: !arrayptr(int,l,n), n: int n, i: int i, acc: int
|
||||
): int =
|
||||
if i = n
|
||||
then acc
|
||||
else loop(p, n, i+1, acc + p[i])
|
||||
in loop(p, n, 0, 0) end
|
||||
|
||||
|
||||
/*************** Part 5: dataviewtypes ****************/
|
||||
|
||||
// a dataviewtype is a heap-allocated non-shared inductive type
|
||||
|
||||
// in the stdlib:
|
||||
// dataviewtype list_vt(a:vt@ype, int) =
|
||||
// | list_vt_nil(a, 0)
|
||||
// | {n:nat} list_vt_cons(a, n+1) of (a, list_vt(a, n))
|
||||
|
||||
fn {a:vt@ype} length {n:int} (l: !list_vt(a, n)): int n =
|
||||
let // ^ since we're not consuming it
|
||||
fun loop {acc:int} (l: !list_vt(a, n-acc), acc: int acc): int n =
|
||||
case l of
|
||||
| list_vt_nil() => acc
|
||||
| list_vt_cons(head, tail) => loop(tail, acc + 1)
|
||||
in loop (l, 0) end
|
||||
|
||||
// vvvvv not vt@ype, because you can't easily get rid of a vt@ype
|
||||
fun {a:t@ype} destroy_list {n:nat} (l: list_vt(a,n)): void =
|
||||
case l of
|
||||
// ~ pattern match consumes and frees that node
|
||||
| ~list_vt_nil() => ()
|
||||
| ~list_vt_cons(_, tail) => destroy_list tail
|
||||
|
||||
// unlike a datatype, a dataviewtype can be modified:
|
||||
fun {a:vt@ype} push_back {n:nat} (
|
||||
x: a,
|
||||
l: &list_vt(a,n) >> list_vt(a,n+1)
|
||||
): void =
|
||||
case l of
|
||||
| ~list_vt_nil() => l := list_vt_cons(x, list_vt_nil)
|
||||
// @ pattern match disassembles/"unfolds" the datavtype's view, so you can
|
||||
// modify its components
|
||||
| @list_vt_cons(head, tail) => let
|
||||
val () = push_back (x, tail)
|
||||
// reassemble it with fold@
|
||||
prval () = fold@ l
|
||||
in () end
|
||||
|
||||
fun {a:vt@ype} pop_last {n:pos} (l: &list_vt(a,n) >> list_vt(a,n-1)): a =
|
||||
let
|
||||
val+ @list_vt_cons(head, tail) = l
|
||||
in case tail of
|
||||
| list_vt_cons _ => let
|
||||
val res = pop_last tail
|
||||
prval () = fold@ l
|
||||
in res end
|
||||
| ~list_vt_nil() => let
|
||||
val head = head
|
||||
// Deallocate empty datavtype nodes with free@
|
||||
val () = free@{..}{0} l
|
||||
val () = l := list_vt_nil()
|
||||
in head end
|
||||
/** Equivalently:
|
||||
* | ~list_vt_nil() => let
|
||||
* prval () = fold@ l
|
||||
* val+ ~list_vt_cons(head, ~list_vt_nil()) = l
|
||||
* val () = l := list_vt_nil()
|
||||
* in head end
|
||||
*/
|
||||
end
|
||||
|
||||
// "holes" (ie uninitialized memory) can be created with _ on the RHS
|
||||
// This function uses destination-passing-style to copy the list in a single
|
||||
// tail-recursive pass.
|
||||
fn {a:t@ype} copy_list {n:nat} (l: !list_vt(a, n)): list_vt(a, n) =
|
||||
let
|
||||
var res: ptr
|
||||
fun loop {k:nat} (l: !list_vt(a, k), hole: &ptr? >> list_vt(a, k)): void =
|
||||
case l of
|
||||
| list_vt_nil() => hole := list_vt_nil
|
||||
| list_vt_cons(first, rest) => let
|
||||
val () = hole := list_vt_cons{..}{k-1}(first, _)
|
||||
// ^ on RHS: a hole
|
||||
val+list_vt_cons(_, new_hole) = hole
|
||||
// ^ on LHS: wildcard pattern (not a hole)
|
||||
val () = loop (rest, new_hole)
|
||||
prval () = fold@ hole
|
||||
in () end
|
||||
val () = loop (l, res)
|
||||
in res end
|
||||
|
||||
// Reverse a linked-list *in place* -- no allocations or frees
|
||||
fn {a:vt@ype} in_place_reverse {n:nat} (l: list_vt(a, n)): list_vt(a, n) =
|
||||
let
|
||||
fun loop {k:nat} (l: list_vt(a, n-k), acc: list_vt(a, k)): list_vt(a, n) =
|
||||
case l of
|
||||
| ~list_vt_nil() => acc
|
||||
| @list_vt_cons(x, tail) => let
|
||||
val rest = replace(tail, acc)
|
||||
// the node 'l' is now part of acc instead of the original list
|
||||
prval () = fold@ l
|
||||
in loop (rest, l) end
|
||||
in loop (l, list_vt_nil) end
|
||||
|
||||
|
||||
/*************** Part 6: miscellaneous extras ****************/
|
||||
|
||||
// a record
|
||||
// Point has type 't@ype'
|
||||
typedef Point = @{ x= int, y= int }
|
||||
val origin: Point = @{ x= 0, y= 0 }
|
||||
|
||||
// tuples and records are normally unboxed, but there are boxed variants
|
||||
// BoxedPoint has type 'type'
|
||||
typedef BoxedPoint = '{ x= int, y= int }
|
||||
val boxed_pair: '(int,int) = '(5, 3)
|
||||
|
||||
// When passing a pair as the single argument to a function, it needs to be
|
||||
// written @(a,b) to avoid ambiguity with multi-argument functions
|
||||
val six_plus_seven = let
|
||||
fun sum_of_pair (pair: (int,int)) = pair.0 + pair.1
|
||||
in sum_of_pair @(6, 7) end
|
||||
|
||||
// When a constructor has no associated data, such as None(), the parentheses
|
||||
// are optional in expressions. However, they are mandatory in patterns
|
||||
fn inc_option (opt: Option int) =
|
||||
case opt of
|
||||
| Some(x) => Some(x+1)
|
||||
| None() => None
|
||||
|
||||
// ATS has a simple FFI, since it compiles to C and (mostly) uses the C ABI
|
||||
%{
|
||||
// Inline C code
|
||||
int scanf_wrapper(void *format, void *value) {
|
||||
return scanf((char *) format, (int *) value);
|
||||
}
|
||||
%}
|
||||
// If you wanted to, you could define a custom dataviewtype more accurately
|
||||
// describing the result of scanf
|
||||
extern fn scanf (format: string, value: &int): int = "scanf_wrapper"
|
||||
|
||||
fn get_input_number (): Option int =
|
||||
let
|
||||
var x: int = 0
|
||||
in
|
||||
if scanf("%d\n", x) = 1
|
||||
then Some(x)
|
||||
else None
|
||||
end
|
||||
|
||||
// extern is also used for separate declarations and definitions
|
||||
extern fn say_hi (): void
|
||||
// later on, or in another file:
|
||||
implement say_hi () = print "hi\n"
|
||||
|
||||
// if you implement main0, it will run as the main function
|
||||
// implmnt is an alias for implement
|
||||
implmnt main0 () = ()
|
||||
|
||||
// as well as for axioms:
|
||||
extern praxi view_id {a:view} (x: a): a
|
||||
// you don't need to actually implement the axioms, but you could
|
||||
primplmnt view_id x = x
|
||||
// primplmnt is an alias for primplement
|
||||
|
||||
// Some standard aliases are:
|
||||
// List0(a) = [n:nat] list(a,n) and List0_vt(a) = [n:nat] list_vt(a,n)
|
||||
// t0p = t@ype and vt0p = vt@ype
|
||||
fun {a:t0p} append (xs: List0 a, ys: List0 a): List0 a =
|
||||
case xs of
|
||||
| list_nil() => ys
|
||||
| list_cons(x, xs) => list_cons(x, append(xs, ys))
|
||||
|
||||
// there are many ways of doing things after one another
|
||||
val let_in_example = let
|
||||
val () = print "thing one\n"
|
||||
val () = print "thing two\n"
|
||||
in () end
|
||||
|
||||
val parens_example = (print "thing one\n"; print "thing two\n")
|
||||
|
||||
val begin_end_example = begin
|
||||
print "thing one\n";
|
||||
print "thing two\n"; // optional trailing semicolon
|
||||
end
|
||||
|
||||
// and many ways to use local variables
|
||||
fun times_four_let x =
|
||||
let
|
||||
fun times_two (x: int) = x * 2
|
||||
in times_two (times_two x) end
|
||||
|
||||
local
|
||||
fun times_two (x: int) = x * 2
|
||||
in
|
||||
fun times_four_local x = times_two (times_two x)
|
||||
end
|
||||
|
||||
fun times_four_where x = times_two (times_two x)
|
||||
where {
|
||||
fun times_two (x: int) = x * 2
|
||||
}
|
||||
|
||||
//// The last kind of comment in ATS is an end-of-file comment.
|
||||
|
||||
Anything between the four slashes and the end of the file is ignored.
|
||||
|
||||
Have fun with ATS!
|
||||
```
|
||||
|
||||
## Learn more
|
||||
|
||||
This isn't all there is to ATS -- notably, some core features like closures and
|
||||
the effect system are left out, as well as other less type-y stuff like modules
|
||||
and the build system. If you'd like to write these sections yourself,
|
||||
contributions would be welcome!
|
||||
|
||||
To learn more about ATS, visit the [ATS website](http://www.ats-lang.org/), in
|
||||
particular the [documentation page](http://www.ats-lang.org/Documents.html).
|
||||
|
@ -362,8 +362,6 @@ sqr ;; => #<procedure (sqr x)>
|
||||
;; The CHICKEN core is very minimal, but additional features are provided by library extensions known as Eggs.
|
||||
;; You can install Eggs with 'chicken-install <eggname>' command.
|
||||
|
||||
;; 'numbers' egg provides support for full numeric tower.
|
||||
(require-extension numbers)
|
||||
;; complex numbers
|
||||
3+4i ;; => 3+2i
|
||||
;; Supports fractions without falling back to inexact flonums
|
||||
@ -375,12 +373,12 @@ sqr ;; => #<procedure (sqr x)>
|
||||
(numerator 2/3) ;; => 2
|
||||
|
||||
;; 'utf8' provides unicode support
|
||||
(require-extension utf8)
|
||||
(import utf8)
|
||||
"\u03BBx:(\u03BC\u0251.\u0251\u2192\u0251).xx" ;; => "λx:(μɑ.ɑ→ɑ).xx"
|
||||
|
||||
;; 'posix' provides file I/O and lots of other services for unix-like operating systems
|
||||
;; Some of the functions are not available in Windows system,
|
||||
;; See http://wiki.call-cc.org/man/4/Unit%20posix for more details
|
||||
;; See http://wiki.call-cc.org/man/5/Module%20(chicken%20file%20posix) for more details
|
||||
|
||||
;; Open a file to append, open "write only" and create file if it does not exist
|
||||
(define outfn (file-open "chicken-hen.txt" (+ open/append open/wronly open/creat)))
|
||||
@ -396,14 +394,14 @@ sqr ;; => #<procedure (sqr x)>
|
||||
|
||||
;; CHICKEN also supports SRFI (Scheme Requests For Implementation) extensions
|
||||
;; See 'http://srfi.schemers.org/srfi-implementers.html" to see srfi's supported by CHICKEN
|
||||
(require-extension srfi-1) ;; list library
|
||||
(import srfi-1) ;; list library
|
||||
(filter odd? '(1 2 3 4 5 6 7)) ;; => (1 3 5 7)
|
||||
(count even? '(1 2 3 4 5)) ;; => 2
|
||||
(take '(12 24 36 48 60) 3) ;; => (12 24 36)
|
||||
(drop '(12 24 36 48 60) 2) ;; => (36 48 60)
|
||||
(circular-list 'z 'q) ;; => z q z q ...
|
||||
|
||||
(require-extension srfi-13) ;; string library
|
||||
(import srfi-13) ;; string library
|
||||
(string-reverse "pan") ;; => "nap"
|
||||
(string-index "Turkey" #\k) ;; => 3
|
||||
(string-every char-upper-case? "CHICKEN") ;; => #t
|
||||
@ -448,7 +446,7 @@ sqr ;; => #<procedure (sqr x)>
|
||||
; 9. Modules
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Also See http://wiki.call-cc.org/man/4/Modules
|
||||
;; Also See http://wiki.call-cc.org/man/5/Modules
|
||||
|
||||
;; The 'test' module exports a value named 'hello' and a macro named 'greet'
|
||||
(module test (hello greet)
|
||||
@ -509,11 +507,11 @@ sqr ;; => #<procedure (sqr x)>
|
||||
|
||||
```
|
||||
## Further Reading
|
||||
* [CHICKEN User's Manual](http://wiki.call-cc.org/man/4/The%20User%27s%20Manual).
|
||||
* [CHICKEN User's Manual](https://wiki.call-cc.org/manual).
|
||||
* [R5RS standards](http://www.schemers.org/Documents/Standards/R5RS)
|
||||
|
||||
|
||||
## Extra Info
|
||||
|
||||
* [For programmers of other languages](http://wiki.call-cc.org/chicken-for-programmers-of-other-languages)
|
||||
* [For programmers of other languages](https://wiki.call-cc.org/chicken-for-programmers-of-other-languages)
|
||||
* [Compare CHICKEN syntax with other languages](http://plr.sourceforge.net/cgi-bin/plr/launch.py)
|
||||
|
@ -16,27 +16,29 @@ review them more effectively and/or individually.
|
||||
|
||||
## Style Guidelines
|
||||
|
||||
- **Keep lines of under 80 chars**
|
||||
+ Try to keep **line length in code blocks to 80 characters or fewer**.
|
||||
+ Otherwise, the text will overflow and look odd.
|
||||
- **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**
|
||||
+ For translations (or EN articles with non-ASCII characters) please make sure
|
||||
your file is UTF-8 encoded.
|
||||
+ Try to leave out the byte-order-mark at the start of the file. (`:set nobomb`
|
||||
in Vim)
|
||||
+ You can check if the file contains a BOM on Linux/Unix systems by running
|
||||
* **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 the freely available
|
||||
[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**
|
||||
* For translations (or EN articles with non-ASCII characters) please ensure
|
||||
your file is UTF-8 encoded.
|
||||
* Leave out the byte-order-mark (BOM) at the start of the file (in Vim, use
|
||||
`:set nobomb`).
|
||||
* You can check if the file contains a BOM on Linux/Unix systems by running
|
||||
`file language.html.markdown` You will see this if it uses a BOM:
|
||||
`UTF-8 Unicode (with BOM) text`.
|
||||
|
||||
`UTF-8 Unicode (with BOM) text`.
|
||||
|
||||
### Header configuration
|
||||
|
||||
@ -47,59 +49,67 @@ some key information be defined in the header.
|
||||
The following fields are necessary for English articles about programming
|
||||
languages:
|
||||
|
||||
- **language** The *programming language* in question
|
||||
- **contributors** A list of [author, URL] lists to credit
|
||||
* **language** The *programming language* in question
|
||||
* **contributors** A list of [author, URL] lists to credit
|
||||
|
||||
Other fields:
|
||||
|
||||
- **category**: The category of the article. So far, can be one of *language*,
|
||||
* **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
|
||||
* **filename**: The filename for this article's code. It will be fetched, mashed
|
||||
together, and made downloadable.
|
||||
+ For non-English articles, *filename* should have a language-specific
|
||||
suffix.
|
||||
- **lang**: For translations, the human language this article is in. For
|
||||
* For non-English articles, *filename* should have a language-specific
|
||||
suffix.
|
||||
* **lang**: For translations, the human language this article is in. For
|
||||
categorization, mostly.
|
||||
|
||||
Here's an example header for an Esperanto translation of Ruby:
|
||||
|
||||
```yaml
|
||||
---
|
||||
*--
|
||||
language: ruby
|
||||
filename: learnruby-epo.ruby
|
||||
contributors:
|
||||
- ["Doktor Esperanto", "http://example.com/"]
|
||||
- ["Someone else", "http://someoneelseswebsite.com/"]
|
||||
lang: ep-ep
|
||||
---
|
||||
*--
|
||||
```
|
||||
|
||||
### Should I add myself as a Contributor?
|
||||
### Syntax highlighter
|
||||
|
||||
[Rouge](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) 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 judgement when deciding if your contribution constitutes a substantial
|
||||
use your judgment when deciding if your contribution constitutes a substantial
|
||||
addition or not.
|
||||
|
||||
## Building the site locally
|
||||
|
||||
You can build the site locally to test your changes. Follow the steps below.
|
||||
|
||||
* Install Ruby language runtime and RubyGems. See [here](https://middlemanapp.com/basics/install/) for more details.
|
||||
* Clone or zip download the [learnxinyminutes-site](https://github.com/adambard/learnxinyminutes-site) repo.
|
||||
* `git clone https://github.com/adambard/learnxinyminutes-site`
|
||||
* Install Ruby language runtime and RubyGems. See
|
||||
[here](https://middlemanapp.com/basics/install/)
|
||||
for more details.
|
||||
* Clone or zip download the
|
||||
[learnxinyminutes-site](https://github.com/adambard/learnxinyminutes-site)
|
||||
repository.
|
||||
* `git clone https://github.com/adambard/learnxinyminutes-site`
|
||||
* Install Middleman and other required dependencies using Bundler.
|
||||
* `cd learnxinyminutes-site/`
|
||||
* `bundle install`
|
||||
* `cd learnxinyminutes-site/`
|
||||
* `bundle install`
|
||||
* Get the source in place
|
||||
* Copy the contents of your clone of the fork of learnxinyminutes-docs repo
|
||||
into the `source/docs` folder. There shouldn't be a `learnxinyminutes-docs`
|
||||
folder inside the `docs` folder, it should just contain all the repo
|
||||
contents.
|
||||
* Checkout your fork of the learnxinyminutes-docs repo as `source/docs`.
|
||||
* `cd source/docs/`
|
||||
* `git clone https://github.com/YOUR-USERNAME/learnxinyminutes-docs ./source/docs/`
|
||||
* Copy the contents of your clone of the fork of learnxinyminutes-docs repo
|
||||
into the `source/docs` folder. There shouldn't be a `learnxinyminutes-docs`
|
||||
folder inside the `docs` folder, it should just contain all the repo
|
||||
contents.
|
||||
* Checkout your fork of the learnxinyminutes-docs repo as `source/docs`.
|
||||
* `cd source/docs/`
|
||||
* `git clone https://github.com/YOUR-USERNAME/learnxinyminutes-docs ./source/docs/`
|
||||
* Build the site or run a development server to test your changes (NOTE: run
|
||||
these commands at `learnxinyminutes-site/`).
|
||||
* Build - `bundle exec middleman build`
|
||||
* Dev server - `bundle exec middleman --force-polling --verbose`
|
||||
these commands at `learnxinyminutes-site/`).
|
||||
* Build - `bundle exec middleman build`
|
||||
* Dev server - `bundle exec middleman --force-polling --verbose`
|
||||
|
359
LICENSE.txt
Normal file
359
LICENSE.txt
Normal file
@ -0,0 +1,359 @@
|
||||
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/.
|
416
ada.html.markdown
Normal file
416
ada.html.markdown
Normal file
@ -0,0 +1,416 @@
|
||||
---
|
||||
language: 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)
|
||||
|
@ -1,212 +1,212 @@
|
||||
---
|
||||
category: tool
|
||||
tool: 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)
|
||||
---
|
||||
category: tool
|
||||
tool: 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)
|
||||
|
@ -44,7 +44,7 @@ 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 noticable amount.
|
||||
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)
|
||||
@ -691,7 +691,7 @@ to specify the username.
|
||||
|
||||
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'
|
||||
privilages.
|
||||
privileges.
|
||||
|
||||
[Read more](http://docs.ansible.com/ansible/latest/become.html)
|
||||
|
||||
@ -753,3 +753,4 @@ the `register` command.
|
||||
* [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)
|
||||
|
135
ar-ar/sql-ar.html.markdown
Normal file
135
ar-ar/sql-ar.html.markdown
Normal file
@ -0,0 +1,135 @@
|
||||
---
|
||||
language: SQL
|
||||
filename: learnsql-ar.sql
|
||||
contributors:
|
||||
- ["Bob DuCharme", "http://bobdc.com/"]
|
||||
translators:
|
||||
- ["Ahmed Omar Eissa", "https://twitter.com/AhmedOmarEissa"]
|
||||
lang: ar-ar
|
||||
---
|
||||
<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>
|
432
arturo.html.markdown
Normal file
432
arturo.html.markdown
Normal file
@ -0,0 +1,432 @@
|
||||
---
|
||||
language: 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.
|
@ -3,7 +3,7 @@ language: asciidoc
|
||||
contributors:
|
||||
- ["Ryan Mavilia", "http://unoriginality.rocks/"]
|
||||
- ["Abel Salgado Romero", "https://twitter.com/abelsromero"]
|
||||
filename: asciidoc.md
|
||||
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.
|
||||
|
202
assemblyscript.html.markdown
Normal file
202
assemblyscript.html.markdown
Normal file
@ -0,0 +1,202 @@
|
||||
---
|
||||
language: 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](/docs/typescript) and [JavaScript](/docs/javascript).
|
||||
|
||||
To test AssemblyScript's compiler, head to the
|
||||
[Playground](https://bit.ly/asplayground) 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)
|
@ -135,7 +135,7 @@ 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 > <sub>0</sub>?
|
||||
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
|
||||
|
@ -48,7 +48,7 @@ BEGIN {
|
||||
# the preliminary set-up code, before you process any text files. If you
|
||||
# have no text files, then think of BEGIN as the main entry point.
|
||||
|
||||
# Variables are global. Just set them or use them, no need to declare..
|
||||
# Variables are global. Just set them or use them, no need to declare.
|
||||
count = 0;
|
||||
|
||||
# Operators just like in C and friends
|
||||
@ -118,12 +118,12 @@ BEGIN {
|
||||
# Arrays
|
||||
arr[0] = "foo";
|
||||
arr[1] = "bar";
|
||||
|
||||
|
||||
# You can also initialize an array with the built-in function split()
|
||||
|
||||
|
||||
n = split("foo:bar:baz", arr, ":");
|
||||
|
||||
# You also have associative arrays (actually, they're all associative arrays)
|
||||
|
||||
# You also have associative arrays (indeed, they're all associative arrays)
|
||||
assoc["foo"] = "bar";
|
||||
assoc["bar"] = "baz";
|
||||
|
||||
@ -178,26 +178,26 @@ function arithmetic_functions(a, b, c, d) {
|
||||
# Now, to demonstrate the arithmetic functions
|
||||
|
||||
# Most AWK implementations have some standard trig functions
|
||||
localvar = sin(a);
|
||||
localvar = cos(a);
|
||||
localvar = atan2(b, a); # arc tangent of b / a
|
||||
d = sin(a);
|
||||
d = cos(a);
|
||||
d = atan2(b, a); # arc tangent of b / a
|
||||
|
||||
# And logarithmic stuff
|
||||
localvar = exp(a);
|
||||
localvar = log(a);
|
||||
d = exp(a);
|
||||
d = log(a);
|
||||
|
||||
# Square root
|
||||
localvar = sqrt(a);
|
||||
d = sqrt(a);
|
||||
|
||||
# Truncate floating point to integer
|
||||
localvar = int(5.34); # localvar => 5
|
||||
d = int(5.34); # d => 5
|
||||
|
||||
# Random numbers
|
||||
srand(); # Supply a seed as an argument. By default, it uses the time of day
|
||||
localvar = rand(); # Random number between 0 and 1.
|
||||
d = rand(); # Random number between 0 and 1.
|
||||
|
||||
# Here's how to return a value
|
||||
return localvar;
|
||||
return d;
|
||||
}
|
||||
|
||||
function string_functions( localvar, arr) {
|
||||
@ -209,14 +209,15 @@ function string_functions( localvar, arr) {
|
||||
# Both return number of matches replaced
|
||||
localvar = "fooooobar";
|
||||
sub("fo+", "Meet me at the ", localvar); # localvar => "Meet me at the bar"
|
||||
gsub("e+", ".", localvar); # localvar => "m..t m. at th. bar"
|
||||
gsub("e", ".", localvar); # localvar => "M..t m. at th. bar"
|
||||
|
||||
# Search for a string that matches a regular expression
|
||||
# index() does the same thing, but doesn't allow a regular expression
|
||||
match(localvar, "t"); # => 4, since the 't' is the fourth character
|
||||
|
||||
# Split on a delimiter
|
||||
n = split("foo-bar-baz", arr, "-"); # a[1] = "foo"; a[2] = "bar"; a[3] = "baz"; n = 3
|
||||
n = split("foo-bar-baz", arr, "-");
|
||||
# result: a[1] = "foo"; a[2] = "bar"; a[3] = "baz"; n = 3
|
||||
|
||||
# Other useful stuff
|
||||
sprintf("%s %d %d %d", "Testing", 1, 2, 3); # => "Testing 1 2 3"
|
||||
@ -238,9 +239,9 @@ function io_functions( localvar) {
|
||||
# AWK doesn't have file handles, per se. It will automatically open a file
|
||||
# handle for you when you use something that needs one. The string you used
|
||||
# for this can be treated as a file handle, for purposes of I/O. This makes
|
||||
# it feel sort of like shell scripting, but to get the same output, the string
|
||||
# must match exactly, so use a variable:
|
||||
|
||||
# it feel sort of like shell scripting, but to get the same output, the
|
||||
# string must match exactly, so use a variable:
|
||||
|
||||
outfile = "/tmp/foobar.txt";
|
||||
|
||||
print "foobar" > outfile;
|
||||
@ -261,7 +262,7 @@ function io_functions( localvar) {
|
||||
|
||||
# Reads a line from a file and stores in localvar
|
||||
infile = "/tmp/foobar.txt";
|
||||
getline localvar < infile;
|
||||
getline localvar < infile;
|
||||
close(infile);
|
||||
}
|
||||
|
||||
@ -273,10 +274,10 @@ function io_functions( localvar) {
|
||||
# When you pass arguments to AWK, they are treated as file names to process.
|
||||
# It will process them all, in order. Think of it like an implicit for loop,
|
||||
# iterating over the lines in these files. these patterns and actions are like
|
||||
# switch statements inside the loop.
|
||||
# switch statements inside the loop.
|
||||
|
||||
/^fo+bar$/ {
|
||||
|
||||
|
||||
# This action will execute for every line that matches the regular
|
||||
# expression, /^fo+bar$/, and will be skipped for any line that fails to
|
||||
# match it. Let's just print the line:
|
||||
@ -376,11 +377,15 @@ END {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Further Reading:
|
||||
|
||||
* [Awk tutorial](http://www.grymoire.com/Unix/Awk.html)
|
||||
* [Awk man page](https://linux.die.net/man/1/awk)
|
||||
* [The GNU Awk User's Guide](https://www.gnu.org/software/gawk/manual/gawk.html) GNU Awk is found on most Linux systems.
|
||||
* [The GNU Awk User's Guide](https://www.gnu.org/software/gawk/manual/gawk.html)
|
||||
GNU Awk is found on most Linux systems.
|
||||
* [AWK one-liner collection](http://tuxgraphics.org/~guido/scripts/awk-one-liner.html)
|
||||
* [Awk alpinelinux wiki](https://wiki.alpinelinux.org/wiki/Awk) a technical summary and list of "gotchas" (places where different implementations may behave in different or unexpected ways).
|
||||
* [Awk alpinelinux wiki](https://wiki.alpinelinux.org/wiki/Awk) a technical
|
||||
summary and list of "gotchas" (places where different implementations may
|
||||
behave in different or unexpected ways).
|
||||
* [basic libraries for awk](https://github.com/dubiousjim/awkenough)
|
||||
|
432
ballerina.html.markdown
Normal file
432
ballerina.html.markdown
Normal file
@ -0,0 +1,432 @@
|
||||
---
|
||||
language: Ballerina
|
||||
contributors:
|
||||
- ["Anjana Fernando", "https://github.com/lafernando"]
|
||||
filename: learn_ballerina.bal
|
||||
---
|
||||
|
||||
[Ballerina](https://ballerina.io/) is a statically-typed programming language for making development for the cloud an enjoyable experience.
|
||||
|
||||
```java
|
||||
// Single-line comment
|
||||
|
||||
// Import modules into the current source file
|
||||
import ballerina/io;
|
||||
import ballerina/time;
|
||||
import ballerina/http;
|
||||
import ballerinax/java.jdbc;
|
||||
import ballerina/lang.'int as ints;
|
||||
import ballerinax/awslambda;
|
||||
// Module alias "af" used in code in place of the full module name
|
||||
import ballerinax/azure.functions as af;
|
||||
|
||||
http:Client clientEP = new ("https://freegeoip.app/");
|
||||
jdbc:Client accountsDB = new ({url: "jdbc:mysql://localhost:3306/AccountsDB",
|
||||
username: "test", password: "test"});
|
||||
|
||||
// A service is a first-class concept in Ballerina, and is one of the
|
||||
// entrypoints to a Ballerina program.
|
||||
// The Ballerina platform also provides support for easy deployment to
|
||||
// environments such as Kubernetes (https://ballerina.io/learn/deployment/kubernetes/).
|
||||
service geoservice on new http:Listener(8080) {
|
||||
|
||||
@http:ResourceConfig {
|
||||
path: "/geoip/{ip}"
|
||||
}
|
||||
resource function geoip(http:Caller caller, http:Request request,
|
||||
string ip) returns @tainted error? {
|
||||
http:Response resp = check clientEP->get("/json/" + <@untainted>ip);
|
||||
check caller->respond(<@untainted> check resp.getTextPayload());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Serverless Function-as-a-Service support with AWS Lambda.
|
||||
// The Ballerina compiler automatically generates the final deployment
|
||||
// artifact to be deployed.
|
||||
@awslambda:Function
|
||||
public function echo(awslambda:Context ctx, json input) returns json {
|
||||
return input;
|
||||
}
|
||||
|
||||
@awslambda:Function
|
||||
public function notifyS3(awslambda:Context ctx,
|
||||
awslambda:S3Event event) returns json {
|
||||
return event.Records[0].s3.'object.key;
|
||||
}
|
||||
|
||||
// Serverless Function-as-a-Service support with Azure Functions.
|
||||
// Similar to AWS Lambda, the compiler generates the deployment artifacts.
|
||||
@af:Function
|
||||
public function fromQueueToQueue(af:Context ctx,
|
||||
@af:QueueTrigger { queueName: "queue1" } string inMsg,
|
||||
@af:QueueOutput { queueName: "queue2" } af:StringOutputBinding outMsg) {
|
||||
outMsg.value = inMsg;
|
||||
}
|
||||
|
||||
// A custom record type
|
||||
public type Person record {
|
||||
string id; // required field
|
||||
string name;
|
||||
int age?; // optional field
|
||||
string country = "N/A"; // default value
|
||||
};
|
||||
|
||||
@af:Function
|
||||
public function fromHttpTriggerCosmosDBInput(
|
||||
@af:HTTPTrigger { route: "c1/{country}" } af:HTTPRequest httpReq,
|
||||
@af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection",
|
||||
databaseName: "db1", collectionName: "c1",
|
||||
sqlQuery: "select * from c1 where c1.country = {country}" }
|
||||
Person[] dbReq)
|
||||
returns @af:HTTPOutput string|error {
|
||||
return dbReq.toString();
|
||||
}
|
||||
|
||||
public function main() returns @tainted error? {
|
||||
int a = 10; // 64-bit signed integer
|
||||
float b = 1.56; // 64-bit IEEE 754-2008 binary floating point number
|
||||
string c = "hello"; // a unicode string
|
||||
boolean d = true; // true, false
|
||||
decimal e = 15.335; // decimal floating point number
|
||||
|
||||
var f = 20; // type inference with 'var' - 'f' is an int
|
||||
|
||||
int[] intArray = [1, 2, 3, 4, 5, 6];
|
||||
int x = intArray.shift(); // similar to a dequeue operation
|
||||
x = intArray.pop(); // removes the last element
|
||||
intArray.push(10); // add to the end
|
||||
|
||||
// Tuples - similar to a fixed length array with a distinct type for each slot
|
||||
[string, int] p1 = ["Jack", 1990];
|
||||
[string, int] p2 = ["Tom", 1986];
|
||||
io:println("Name: ", p1[0], " Birth Year: ", p1[1]);
|
||||
|
||||
string name1;
|
||||
int birthYear1;
|
||||
[name1, birthYear1] = p1; // tuple destructuring
|
||||
|
||||
var [name2, birthYear2] = p2; // declare and assign values in the same statement
|
||||
|
||||
// If statements
|
||||
int ix = 10;
|
||||
if ix < 10 {
|
||||
io:println("value is less than 10");
|
||||
} else if ix == 10 {
|
||||
io:println("value equals to 10");
|
||||
} else {
|
||||
io:println("value is greater than 10");
|
||||
}
|
||||
|
||||
// Loops
|
||||
int count = 10;
|
||||
int i = 0;
|
||||
while i < 10 {
|
||||
io:println(i);
|
||||
}
|
||||
// Loop from 0 to count (inclusive)
|
||||
foreach var j in 0...count {
|
||||
io:println(j);
|
||||
}
|
||||
// Loop from 0 to count (non-inclusive)
|
||||
foreach var j in 0..<count {
|
||||
io:println(j);
|
||||
}
|
||||
// Loop a list
|
||||
foreach var j in intArray {
|
||||
io:println(j);
|
||||
}
|
||||
|
||||
json j1 = { "name" : name1, "birthYear" : birthYear1, "zipcode" : 90210 };
|
||||
io:println(j1.name, " - ", j1.zipcode);
|
||||
// New fields are added to a JSON value through "mergeJson"
|
||||
var j2 = j1.mergeJson({ "id" : "90400593053"});
|
||||
|
||||
// XML namespace declaration
|
||||
xmlns "http://example.com/ns1" as ns1;
|
||||
xmlns "http://example.com/default";
|
||||
|
||||
// XML variable from a literal value
|
||||
xml x1 = xml `<ns1:entry><name>{{name1}}</name><birthYear>{{birthYear1}}</birthYear></ns1:entry>`;
|
||||
io:println(x1);
|
||||
// Access specific elements in the XML value
|
||||
io:println(x1/<name>);
|
||||
// List all child items in the XML value
|
||||
io:println(x1/*);
|
||||
|
||||
// Function invocations
|
||||
x = add(1, 2);
|
||||
io:println(multiply(2, 4));
|
||||
// Invocation providing value for the defaultable parameter
|
||||
io:println(multiply(3, 4, true));
|
||||
// Invocation with values to a rest parameter (multi-valued)
|
||||
io:println(addAll(1, 2, 3));
|
||||
io:println(addAll(1, 2, 3, 4, 5));
|
||||
|
||||
// Function pointers
|
||||
(function (int, int) returns int) op1 = getOperation("add");
|
||||
(function (int, int) returns int) op2 = getOperation("mod");
|
||||
io:println(op1(5, 10));
|
||||
io:println(op2(13, 10));
|
||||
|
||||
// Closures
|
||||
(function (int x) returns int) add5 = getAdder(5);
|
||||
(function (int x) returns int) add10 = getAdder(10);
|
||||
io:println(add5(10));
|
||||
io:println(add10(10));
|
||||
|
||||
int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
// Functional iteration
|
||||
int[] evenNumbers = numbers.filter(function (int x) returns boolean { return x % 2 == 0; });
|
||||
|
||||
// Union types - "input" is of type either string or byte[]
|
||||
string|byte[] uval = "XXX";
|
||||
|
||||
// A type test expression ("uval is string") can be used to check the
|
||||
// runtime type of a variable.
|
||||
if uval is string {
|
||||
// In the current scope, "uval" is a string value
|
||||
string data = "data:" + uval;
|
||||
} else {
|
||||
// Since the expression in the "if" statement ruled out that it's not a string,
|
||||
// the only type left is "byte[]"; so in the current scope, "uval" will always
|
||||
// be a "byte[]".
|
||||
int inputLength = uval.length();
|
||||
}
|
||||
|
||||
// Error handling
|
||||
string input = io:readln("Enter number: ");
|
||||
int|error result = ints:fromString(input);
|
||||
if result is int {
|
||||
io:println("Number: ", result);
|
||||
} else {
|
||||
io:println("Invalid number: ", input);
|
||||
}
|
||||
|
||||
// A check expression can be used to directly return the error from
|
||||
// the current function if its subexpression evaluated to an error
|
||||
// value in the runtime.
|
||||
int number = check ints:fromString(input);
|
||||
|
||||
// Concurrent execution using workers in a function
|
||||
doWorkers();
|
||||
|
||||
// Asynchronous execution with futures
|
||||
future<int> f10 = start fib(10);
|
||||
var webresult = clientEP->get("/");
|
||||
int fresult = wait f10;
|
||||
if webresult is http:Response {
|
||||
io:println(webresult.getTextPayload());
|
||||
io:println(fresult);
|
||||
}
|
||||
|
||||
// Mapping types
|
||||
map<int> ageMap = {};
|
||||
ageMap["Peter"] = 25;
|
||||
ageMap["John"] = 30;
|
||||
|
||||
int? agePeter = ageMap["Peter"]; // int? is the union type int|() - int or nill
|
||||
if agePeter is int {
|
||||
io:println("Peter's age is ", agePeter);
|
||||
} else {
|
||||
io:println("Peter's age is not found");
|
||||
}
|
||||
|
||||
Person person1 = { id: "p1", name : "Anne", age: 28, country: "Sri Lanka" };
|
||||
Scores score1 = { physics : 80, mathematics: 95 };
|
||||
score1["chemistry"] = 75;
|
||||
io:println(score1["chemistry"]);
|
||||
|
||||
Student student1 = { id: "s1", name: "Jack", age: 25, country: "Japan" };
|
||||
student1.college = "Stanford";
|
||||
string? jacksCollege = student1?.college; // optional field access
|
||||
if jacksCollege is string {
|
||||
io:println("Jack's college is ", jacksCollege);
|
||||
}
|
||||
|
||||
// Due to the structural type system, "student1" can be assigned to "person2",
|
||||
// since the student1's structure is compatible with person2's,
|
||||
// where we can say, a "Student" is a "Person" as well.
|
||||
Person person2 = student1;
|
||||
|
||||
map<int> grades = {"Jack": 95, "Anne": 90, "John": 80, "Bill": 55};
|
||||
Person px1 = {id: "px1", name: "Jack", age: 30, country: "Canada"};
|
||||
Person px2 = {id: "px2", name: "John", age: 25};
|
||||
Person px3 = {id: "px3", name: "Anne", age: 17, country: "UK"};
|
||||
Person px4 = {id: "px4", name: "Bill", age: 15, country: "USA"};
|
||||
Person[] persons = [];
|
||||
persons.push(px1);
|
||||
persons.push(px2);
|
||||
persons.push(px3);
|
||||
persons.push(px4);
|
||||
|
||||
// Query expressions used to execute complex queries for list data
|
||||
Result[] results = from var person in persons
|
||||
let int lgrade = (grades[person.name] ?: 0)
|
||||
where lgrade > 75
|
||||
let string targetCollege = "Stanford"
|
||||
select {
|
||||
name: person.name,
|
||||
college: targetCollege,
|
||||
grade: lgrade
|
||||
};
|
||||
|
||||
// Compile-time taint checking for handling untrusted data
|
||||
string s1 = "abc";
|
||||
mySecureFunction(s1);
|
||||
// Explicitely make "s2" a tainted value. External input to a Ballerina
|
||||
// program such as command-line arguments and network input are by-default
|
||||
// marked as tainted data.
|
||||
string s2 = <@tainted> s1;
|
||||
// "s2x" is now a tainted value, since its value is derived using a
|
||||
// tainted value (s1).
|
||||
string s2x = s2 + "abc";
|
||||
// The following line uncommented will result in a compilation error,
|
||||
// since we are passing a tainted value (s2x) to a function which
|
||||
// exepects an untainted value.
|
||||
// mySecureFunction(s2x);
|
||||
|
||||
// Instantiating objects
|
||||
Employee emp1 = new("E0001", "Jack Smith", "Sales", 2009);
|
||||
io:println("The company service duration of ", emp1.name,
|
||||
" is ", emp1.serviceDuration());
|
||||
|
||||
// Supported operations can be executed in a transaction by enclosing the actions
|
||||
// in a "transaction" block.
|
||||
transaction {
|
||||
// Executes the below database operations in a single local transactions
|
||||
var r1 = accountsDB->update("UPDATE Employee SET balance = balance + ? WHERE id = ?", 5500.0, "ID001");
|
||||
var r2 = accountsDB->update("UPDATE Employee SET balance = balance + ? WHERE id = ?", 5500.0, "ID001");
|
||||
}
|
||||
}
|
||||
|
||||
// An object is a behavioural type, which encapsulates both data and functionality.
|
||||
type Employee object {
|
||||
|
||||
// Private fields are only visible within the object and its methods
|
||||
private string empId;
|
||||
// Public fields can be accessed by anyone
|
||||
public string name;
|
||||
public string department;
|
||||
// The default qualifier is a "protected" field,
|
||||
// which are accessible only within the module.
|
||||
int yearJoined;
|
||||
|
||||
// The object initialization function; automatically called when an object is instantiated.
|
||||
public function __init(string empId, string name, string department, int yearJoined) {
|
||||
self.empId = empId;
|
||||
self.name = name;
|
||||
self.department = department;
|
||||
self.yearJoined = yearJoined;
|
||||
}
|
||||
|
||||
// An object method
|
||||
public function serviceDuration() returns int {
|
||||
time:Time ct = time:currentTime();
|
||||
return time:getYear(ct) - self.yearJoined;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Student is a subtype of Person
|
||||
type Student record {
|
||||
string id;
|
||||
string name;
|
||||
int age;
|
||||
string college?;
|
||||
string country;
|
||||
};
|
||||
|
||||
type Scores record {
|
||||
int physics;
|
||||
int mathematics;
|
||||
};
|
||||
|
||||
type Result record {
|
||||
string name;
|
||||
string college;
|
||||
int grade;
|
||||
};
|
||||
|
||||
public function getOperation(string op) returns (function (int, int) returns int) {
|
||||
if op == "add" {
|
||||
return add;
|
||||
} else if op == "mod" {
|
||||
return function (int a, int b) returns int { // anonymous function
|
||||
return a % b;
|
||||
};
|
||||
} else {
|
||||
return (x, y) => 0; // single expression anonymous no-op function
|
||||
}
|
||||
}
|
||||
|
||||
// Two required parameters
|
||||
public function add(int a, int b) returns int {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
// 'log' is a defaultable parameter
|
||||
public function multiply(int a, int b, boolean log = false) returns int {
|
||||
if log {
|
||||
io:println("Multiplying ", a, " with ", b);
|
||||
}
|
||||
return a * b;
|
||||
}
|
||||
|
||||
// 'numbers' is a rest parameter - it can have multiple values,
|
||||
// similar to an array.
|
||||
public function addAll(int... numbers) returns int {
|
||||
int result = 0;
|
||||
foreach int number in numbers {
|
||||
result += number;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public function getAdder(int n) returns (function (int x) returns int) {
|
||||
return function (int x) returns int { // returns closure
|
||||
return x + n;
|
||||
};
|
||||
}
|
||||
|
||||
function fib(int n) returns int {
|
||||
if n <= 2 {
|
||||
return 1;
|
||||
} else {
|
||||
return fib(n - 1) + fib(n - 2);
|
||||
}
|
||||
}
|
||||
|
||||
// The code in worker blocks "w1" and "w2" are executed concurrency
|
||||
// when this function is invoked. The "wait" expressions waits for
|
||||
// the given workers to finish to retrieve their results.
|
||||
public function doWorkers() {
|
||||
worker w1 returns int {
|
||||
int j = 10;
|
||||
j -> w2;
|
||||
int b;
|
||||
b = <- w2;
|
||||
return b * b;
|
||||
}
|
||||
worker w2 returns int {
|
||||
int a;
|
||||
a = <- w1;
|
||||
a * 2 -> w1;
|
||||
return a + 2;
|
||||
}
|
||||
record {int w1; int w2;} x = wait {w1, w2};
|
||||
io:println(x);
|
||||
}
|
||||
|
||||
// A function which takes in only an untainted string value.
|
||||
public function mySecureFunction(@untainted string input) {
|
||||
io:println(input);
|
||||
}
|
||||
```
|
||||
|
||||
### Further Reading
|
||||
|
||||
* [Ballerina by Example](https://ballerina.io/learn/by-example/)
|
||||
* [User Guide](https://ballerina.io/learn/installing-ballerina/)
|
||||
* [API Documentation](https://ballerina.io/learn/api-docs/ballerina/)
|
||||
* [Language Specification](https://ballerina.io/spec/)
|
@ -17,6 +17,8 @@ contributors:
|
||||
- ["John Detter", "https://github.com/jdetter"]
|
||||
- ["Harry Mumford-Turner", "https://github.com/harrymt"]
|
||||
- ["Martin Nicholson", "https://github.com/mn113"]
|
||||
- ["Mark Grimwood", "https://github.com/MarkGrimwood"]
|
||||
- ["Emily Grace Seville", "https://github.com/EmilySeville7cfg"]
|
||||
filename: LearnBash.sh
|
||||
translators:
|
||||
- ["Dimitri Kokkonis", "https://github.com/kokkonisd"]
|
||||
@ -36,104 +38,107 @@ or executed directly in the shell.
|
||||
# As you already figured, comments start with #. Shebang is also a comment.
|
||||
|
||||
# Simple hello world example:
|
||||
echo Hello world! # => Hello world!
|
||||
echo "Hello world!" # => Hello world!
|
||||
|
||||
# Each command starts on a new line, or after a semicolon:
|
||||
echo 'This is the first line'; echo 'This is the second line'
|
||||
# => This is the first line
|
||||
# => This is the second line
|
||||
echo "This is the first command"; echo "This is the second command"
|
||||
# => This is the first command
|
||||
# => This is the second command
|
||||
|
||||
# Declaring a variable looks like this:
|
||||
Variable="Some string"
|
||||
variable="Some string"
|
||||
|
||||
# But not like this:
|
||||
Variable = "Some string" # => returns error "Variable: command not found"
|
||||
# Bash will decide that Variable is a command it must execute and give an error
|
||||
variable = "Some string" # => returns error "variable: command not found"
|
||||
# Bash will decide that `variable` is a command it must execute and give an error
|
||||
# because it can't be found.
|
||||
|
||||
# Nor like this:
|
||||
Variable= 'Some string' # => returns error: "Some string: command not found"
|
||||
# Bash will decide that 'Some string' is a command it must execute and give an
|
||||
# error because it can't be found. (In this case the 'Variable=' part is seen
|
||||
# as a variable assignment valid only for the scope of the 'Some string'
|
||||
# command.)
|
||||
variable= "Some string" # => returns error: "Some string: command not found"
|
||||
# Bash will decide that "Some string" is a command it must execute and give an
|
||||
# error because it can't be found. In this case the "variable=" part is seen
|
||||
# as a variable assignment valid only for the scope of the "Some string"
|
||||
# command.
|
||||
|
||||
# Using the variable:
|
||||
echo $Variable # => Some string
|
||||
echo "$Variable" # => Some string
|
||||
echo '$Variable' # => $Variable
|
||||
# When you use the variable itself — assign it, export it, or else — you write
|
||||
echo "$variable" # => Some string
|
||||
echo '$variable' # => $variable
|
||||
# When you use a variable itself — assign it, export it, or else — you write
|
||||
# its name without $. If you want to use the variable's value, you should use $.
|
||||
# Note that ' (single quote) won't expand the variables!
|
||||
# You can write variable without surrounding quotes but it's not recommended.
|
||||
|
||||
# Parameter expansion ${ }:
|
||||
echo ${Variable} # => Some string
|
||||
# This is a simple usage of parameter expansion
|
||||
# Parameter Expansion gets a value from a variable.
|
||||
# It "expands" or prints the value
|
||||
# During the expansion time the value or parameter can be modified
|
||||
# Below are other modifications that add onto this expansion
|
||||
# Parameter expansion ${...}:
|
||||
echo "${variable}" # => Some string
|
||||
# This is a simple usage of parameter expansion such as two examples above.
|
||||
# Parameter expansion gets a value from a variable.
|
||||
# It "expands" or prints the value.
|
||||
# During the expansion time the value or parameter can be modified.
|
||||
# Below are other modifications that add onto this expansion.
|
||||
|
||||
# String substitution in variables
|
||||
echo ${Variable/Some/A} # => A string
|
||||
# This will substitute the first occurrence of "Some" with "A"
|
||||
# String substitution in variables:
|
||||
echo "${variable/Some/A}" # => A string
|
||||
# This will substitute the first occurrence of "Some" with "A".
|
||||
|
||||
# Substring from a variable
|
||||
Length=7
|
||||
echo ${Variable:0:Length} # => Some st
|
||||
# Substring from a variable:
|
||||
length=7
|
||||
echo "${variable:0:length}" # => Some st
|
||||
# This will return only the first 7 characters of the value
|
||||
echo ${Variable: -5} # => tring
|
||||
# This will return the last 5 characters (note the space before -5)
|
||||
echo "${variable: -5}" # => tring
|
||||
# This will return the last 5 characters (note the space before -5).
|
||||
# The space before minus is mandatory here.
|
||||
|
||||
# String length
|
||||
echo ${#Variable} # => 11
|
||||
# String length:
|
||||
echo "${#variable}" # => 11
|
||||
|
||||
# Indirect expansion
|
||||
OtherVariable="Variable"
|
||||
echo ${!OtherVariable} # => Some String
|
||||
# This will expand the value of OtherVariable
|
||||
# Indirect expansion:
|
||||
other_variable="variable"
|
||||
echo ${!other_variable} # => Some string
|
||||
# This will expand the value of `other_variable`.
|
||||
|
||||
# Default value for variable
|
||||
echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"}
|
||||
# The default value for variable:
|
||||
echo "${foo:-"DefaultValueIfFooIsMissingOrEmpty"}"
|
||||
# => DefaultValueIfFooIsMissingOrEmpty
|
||||
# This works for null (Foo=) and empty string (Foo=""); zero (Foo=0) returns 0.
|
||||
# This works for null (foo=) and empty string (foo=""); zero (foo=0) returns 0.
|
||||
# Note that it only returns default value and doesn't change variable value.
|
||||
|
||||
# Declare an array with 6 elements
|
||||
array0=(one two three four five six)
|
||||
# Print first element
|
||||
echo $array0 # => "one"
|
||||
# Print first element
|
||||
echo ${array0[0]} # => "one"
|
||||
# Print all elements
|
||||
echo ${array0[@]} # => "one two three four five six"
|
||||
# Print number of elements
|
||||
echo ${#array0[@]} # => "6"
|
||||
# Print number of characters in third element
|
||||
echo ${#array0[2]} # => "5"
|
||||
# Print 2 elements starting from forth
|
||||
echo ${array0[@]:3:2} # => "four five"
|
||||
# Print all elements. Each of them on new line.
|
||||
for i in "${array0[@]}"; do
|
||||
echo "$i"
|
||||
# Declare an array with 6 elements:
|
||||
array=(one two three four five six)
|
||||
# Print the first element:
|
||||
echo "${array[0]}" # => "one"
|
||||
# Print all elements:
|
||||
echo "${array[@]}" # => "one two three four five six"
|
||||
# Print the number of elements:
|
||||
echo "${#array[@]}" # => "6"
|
||||
# Print the number of characters in third element
|
||||
echo "${#array[2]}" # => "5"
|
||||
# Print 2 elements starting from fourth:
|
||||
echo "${array[@]:3:2}" # => "four five"
|
||||
# Print all elements each of them on new line.
|
||||
for item in "${array[@]}"; do
|
||||
echo "$item"
|
||||
done
|
||||
|
||||
# Brace Expansion { }
|
||||
# Used to generate arbitrary strings
|
||||
echo {1..10} # => 1 2 3 4 5 6 7 8 9 10
|
||||
echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z
|
||||
# This will output the range from the start value to the end value
|
||||
|
||||
# Built-in variables:
|
||||
# There are some useful built-in variables, like
|
||||
# There are some useful built-in variables, like:
|
||||
echo "Last program's return value: $?"
|
||||
echo "Script's PID: $$"
|
||||
echo "Number of arguments passed to script: $#"
|
||||
echo "All arguments passed to script: $@"
|
||||
echo "Script's arguments separated into different variables: $1 $2..."
|
||||
|
||||
# Brace Expansion {...}
|
||||
# used to generate arbitrary strings:
|
||||
echo {1..10} # => 1 2 3 4 5 6 7 8 9 10
|
||||
echo {a..z} # => a b c d e f g h i j k l m n o p q r s t u v w x y z
|
||||
# This will output the range from the start value to the end value.
|
||||
# Note that you can't use variables here:
|
||||
from=1
|
||||
to=10
|
||||
echo {$from..$to} # => {$from..$to}
|
||||
|
||||
# Now that we know how to echo and use variables,
|
||||
# let's learn some of the other basics of bash!
|
||||
# let's learn some of the other basics of Bash!
|
||||
|
||||
# Our current directory is available through the command `pwd`.
|
||||
# `pwd` stands for "print working directory".
|
||||
@ -143,33 +148,46 @@ echo "I'm in $(pwd)" # execs `pwd` and interpolates output
|
||||
echo "I'm in $PWD" # interpolates the variable
|
||||
|
||||
# If you get too much output in your terminal, or from a script, the command
|
||||
# `clear` clears your screen
|
||||
# `clear` clears your screen:
|
||||
clear
|
||||
# Ctrl-L also works for clearing output
|
||||
# Ctrl-L also works for clearing output.
|
||||
|
||||
# Reading a value from input:
|
||||
echo "What's your name?"
|
||||
read Name # Note that we didn't need to declare a new variable
|
||||
echo Hello, $Name!
|
||||
read name
|
||||
# Note that we didn't need to declare a new variable.
|
||||
echo "Hello, $name!"
|
||||
|
||||
# We have the usual if structure:
|
||||
# use `man test` for more info about conditionals
|
||||
if [ $Name != $USER ]
|
||||
then
|
||||
# We have the usual if structure.
|
||||
# Condition is true if the value of $name is not equal to the current user's login username:
|
||||
if [[ "$name" != "$USER" ]]; then
|
||||
echo "Your name isn't your username"
|
||||
else
|
||||
echo "Your name is your username"
|
||||
fi
|
||||
# True if the value of $Name is not equal to the current user's login username
|
||||
|
||||
# NOTE: if $Name is empty, bash sees the above condition as:
|
||||
if [ != $USER ]
|
||||
# which is invalid syntax
|
||||
# so the "safe" way to use potentially empty variables in bash is:
|
||||
if [ "$Name" != $USER ] ...
|
||||
# which, when $Name is empty, is seen by bash as:
|
||||
if [ "" != $USER ] ...
|
||||
# which works as expected
|
||||
# To use && and || with if statements, you need multiple pairs of square brackets:
|
||||
read age
|
||||
if [[ "$name" == "Steve" ]] && [[ "$age" -eq 15 ]]; then
|
||||
echo "This will run if $name is Steve AND $age is 15."
|
||||
fi
|
||||
|
||||
if [[ "$name" == "Daniya" ]] || [[ "$name" == "Zach" ]]; then
|
||||
echo "This will run if $name is Daniya OR Zach."
|
||||
fi
|
||||
# There are other comparison operators for numbers listed below:
|
||||
# -ne - not equal
|
||||
# -lt - less than
|
||||
# -gt - greater than
|
||||
# -le - less than or equal to
|
||||
# -ge - greater than or equal to
|
||||
|
||||
# There is also the `=~` operator, which tests a string against the Regex pattern:
|
||||
email=me@example.com
|
||||
if [[ "$email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]]
|
||||
then
|
||||
echo "Valid email!"
|
||||
fi
|
||||
|
||||
# There is also conditional execution
|
||||
echo "Always executed" || echo "Only executed if first command fails"
|
||||
@ -178,27 +196,19 @@ echo "Always executed" && echo "Only executed if first command does NOT fail"
|
||||
# => Always executed
|
||||
# => Only executed if first command does NOT fail
|
||||
|
||||
|
||||
# To use && and || with if statements, you need multiple pairs of square brackets:
|
||||
if [ "$Name" == "Steve" ] && [ "$Age" -eq 15 ]
|
||||
then
|
||||
echo "This will run if $Name is Steve AND $Age is 15."
|
||||
fi
|
||||
|
||||
if [ "$Name" == "Daniya" ] || [ "$Name" == "Zach" ]
|
||||
then
|
||||
echo "This will run if $Name is Daniya OR Zach."
|
||||
fi
|
||||
|
||||
# There is also the `=~` operator, which tests a string against a Regex pattern:
|
||||
Email=me@example.com
|
||||
if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]]
|
||||
then
|
||||
echo "Valid email!"
|
||||
fi
|
||||
# Note that =~ only works within double [[ ]] square brackets,
|
||||
# which are subtly different from single [ ].
|
||||
# See https://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs for more on this.
|
||||
# A single ampersand & after a command runs it in the background. A background command's
|
||||
# output is printed to the terminal, but it cannot read from the input.
|
||||
sleep 30 &
|
||||
# List background jobs
|
||||
jobs # => [1]+ Running sleep 30 &
|
||||
# Bring the background job to the foreground
|
||||
fg
|
||||
# Ctrl-C to kill the process, or Ctrl-Z to pause it
|
||||
# Resume a background process after it has been paused with Ctrl-Z
|
||||
bg
|
||||
# Kill job number 2
|
||||
kill %2
|
||||
# %1, %2, etc. can be used for fg and bg as well
|
||||
|
||||
# Redefine command `ping` as alias to send only 5 packets
|
||||
alias ping='ping -c 5'
|
||||
@ -220,7 +230,8 @@ ls -l # Lists every file and directory on a separate line
|
||||
ls -t # Sorts the directory contents by last-modified date (descending)
|
||||
ls -R # Recursively `ls` this directory and all of its subdirectories
|
||||
|
||||
# Results of the previous command can be passed to the next command as input.
|
||||
# Results (stdout) of the previous command can be passed as input (stdin) to the next command
|
||||
# using a pipe |. Commands chained in this way are called a "pipeline", and are run concurrently.
|
||||
# The `grep` command filters the input with provided patterns.
|
||||
# That's how we can list .txt files in the current directory:
|
||||
ls -l | grep "\.txt"
|
||||
@ -260,7 +271,7 @@ cd # also goes to home directory
|
||||
cd .. # go up one directory
|
||||
# (^^say, from /home/username/Downloads to /home/username)
|
||||
cd /home/username/Documents # change to specified directory
|
||||
cd ~/Documents/.. # still in home directory..isn't it??
|
||||
cd ~/Documents/.. # now in home directory (if ~/Documents exists)
|
||||
cd - # change to last directory
|
||||
# => /home/username/Documents
|
||||
|
||||
@ -275,9 +286,13 @@ mkdir -p myNewDir/with/intermediate/directories
|
||||
# if the intermediate directories didn't already exist, running the above
|
||||
# command without the `-p` flag would return an error
|
||||
|
||||
# You can redirect command input and output (stdin, stdout, and stderr).
|
||||
# You can redirect command input and output (stdin, stdout, and stderr)
|
||||
# using "redirection operators". Unlike a pipe, which passes output to a command,
|
||||
# a redirection operator has a command's input come from a file or stream, or
|
||||
# sends its output to a file or stream.
|
||||
|
||||
# Read from stdin until ^EOF$ and overwrite hello.py with the lines
|
||||
# between "EOF":
|
||||
# between "EOF" (which are called a "here document"):
|
||||
cat > hello.py << EOF
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
@ -299,6 +314,8 @@ python hello.py 2> "error.err" # redirect error output to error.err
|
||||
|
||||
python hello.py > "output-and-error.log" 2>&1
|
||||
# redirect both output and errors to output-and-error.log
|
||||
# &1 means file descriptor 1 (stdout), so 2>&1 redirects stderr (2) to the current
|
||||
# destination of stdout (1), which has been redirected to output-and-error.log.
|
||||
|
||||
python hello.py > /dev/null 2>&1
|
||||
# redirect all output and errors to the black hole, /dev/null, i.e., no output
|
||||
@ -402,13 +419,17 @@ function foo ()
|
||||
echo "Arguments work just like script arguments: $@"
|
||||
echo "And: $1 $2..."
|
||||
echo "This is a function"
|
||||
return 0
|
||||
returnValue=0 # Variable values can be returned
|
||||
return $returnValue
|
||||
}
|
||||
# Call the function `foo` with two arguments, arg1 and arg2:
|
||||
foo arg1 arg2
|
||||
# => Arguments work just like script arguments: arg1 arg2
|
||||
# => And: arg1 arg2...
|
||||
# => This is a function
|
||||
# Return values can be obtained with $?
|
||||
resultValue=$?
|
||||
# More than 9 arguments are also possible by using braces, e.g. ${10}, ${11}, ...
|
||||
|
||||
# or simply
|
||||
bar ()
|
||||
@ -429,7 +450,7 @@ tail -n 10 file.txt
|
||||
# prints first 10 lines of file.txt
|
||||
head -n 10 file.txt
|
||||
|
||||
# sort file.txt's lines
|
||||
# print file.txt's lines in sorted order
|
||||
sort file.txt
|
||||
|
||||
# report or omit repeated lines, with -d it reports them
|
||||
|
@ -4,12 +4,13 @@ filename: bf.bf
|
||||
contributors:
|
||||
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
|
||||
- ["Mathias Bynens", "http://mathiasbynens.be/"]
|
||||
- ["rilysh", "https://github.com/rilysh"]
|
||||
---
|
||||
|
||||
Brainfuck (not capitalized except at the start of a sentence) is an extremely
|
||||
minimal Turing-complete programming language with just 8 commands.
|
||||
|
||||
You can try brainfuck on your browser with [brainfuck-visualizer](http://fatiherikli.github.io/brainfuck-visualizer/).
|
||||
You can try brainfuck on your browser with [brainfuck-online](https://copy.sh/brainfuck/).
|
||||
|
||||
```bf
|
||||
Any character not "><+-.,[]" (excluding quotation marks) is ignored.
|
||||
@ -80,3 +81,8 @@ And that's brainfuck. Not that hard, eh? For fun, you can write your own
|
||||
brainfuck programs, or you can write a brainfuck interpreter in another
|
||||
language. The interpreter is fairly simple to implement, but if you're a
|
||||
masochist, try writing a brainfuck interpreter… in brainfuck.
|
||||
|
||||
## Further Reading
|
||||
* [esolang-wiki](https://esolangs.org/wiki/Brainfuck)
|
||||
* [learn brainfuck](http://cydathria.com/bf/brainfuck.html)
|
||||
* [other resources](http://www.muppetlabs.com/~breadbox/bf/)
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: c++
|
||||
language: C++
|
||||
filename: learncpp.cpp
|
||||
contributors:
|
||||
- ["Steven Basart", "https://github.com/xksteven"]
|
||||
@ -158,6 +158,10 @@ namespace Second {
|
||||
{
|
||||
printf("This is Second::foo\n");
|
||||
}
|
||||
void bar()
|
||||
{
|
||||
printf("This is Second::bar\n");
|
||||
}
|
||||
}
|
||||
|
||||
void foo()
|
||||
@ -168,10 +172,12 @@ void foo()
|
||||
int main()
|
||||
{
|
||||
// Includes all symbols from namespace Second into the current scope. Note
|
||||
// that simply foo() no longer works, since it is now ambiguous whether
|
||||
// we're calling the foo in namespace Second or the top level.
|
||||
// that while bar() works, simply using foo() no longer works, since it is
|
||||
// now ambiguous whether we're calling the foo in namespace Second or the
|
||||
// top level.
|
||||
using namespace Second;
|
||||
|
||||
bar(); // prints "This is Second::bar"
|
||||
Second::foo(); // prints "This is Second::foo"
|
||||
First::Nested::foo(); // prints "This is First::Nested::foo"
|
||||
::foo(); // prints "This is global foo"
|
||||
@ -946,7 +952,7 @@ mymap.insert(pair<char,int>('Z',26));
|
||||
// To iterate
|
||||
map<char,int>::iterator it;
|
||||
for (it=mymap.begin(); it!=mymap.end(); ++it)
|
||||
std::cout << it->first << "->" << it->second << std::cout;
|
||||
std::cout << it->first << "->" << it->second << std::endl;
|
||||
// Output:
|
||||
// A->1
|
||||
// Z->26
|
||||
@ -1196,5 +1202,6 @@ compl 4 // Performs a bitwise not
|
||||
Further Reading:
|
||||
|
||||
* An up-to-date language reference can be found at [CPP Reference](http://cppreference.com/w/cpp).
|
||||
* Additional resources may be found at [CPlusPlus](http://cplusplus.com).
|
||||
* A tutorial for beginners or experts, covering many modern features and good practices: [LearnCpp.com](https://www.learncpp.com/)
|
||||
* A tutorial covering basics of language and setting up coding environment is available at [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).
|
||||
* Additional resources may be found at [CPlusPlus](http://cplusplus.com).
|
||||
|
169
c.html.markdown
169
c.html.markdown
@ -1,16 +1,16 @@
|
||||
---
|
||||
language: c
|
||||
language: C
|
||||
filename: learnc.c
|
||||
contributors:
|
||||
- ["Adam Bard", "http://adambard.com/"]
|
||||
- ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
|
||||
- ["Jakub Trzebiatowski", "http://cbs.stgn.pl"]
|
||||
- ["Marco Scannadinari", "https://marcoms.github.io"]
|
||||
- ["Zachary Ferguson", "https://github.io/zfergus2"]
|
||||
- ["himanshu", "https://github.com/himanshu81494"]
|
||||
- ["Joshua Li", "https://github.com/JoshuaRLi"]
|
||||
- ["Dragos B. Chirila", "https://github.com/dchirila"]
|
||||
- ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
|
||||
- ["Adam Bard", "http://adambard.com/"]
|
||||
- ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"]
|
||||
- ["Jakub Trzebiatowski", "http://cbs.stgn.pl"]
|
||||
- ["Marco Scannadinari", "https://marcoms.github.io"]
|
||||
- ["Zachary Ferguson", "https://github.io/zfergus2"]
|
||||
- ["himanshu", "https://github.com/himanshu81494"]
|
||||
- ["Joshua Li", "https://github.com/JoshuaRLi"]
|
||||
- ["Dragos B. Chirila", "https://github.com/dchirila"]
|
||||
- ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"]
|
||||
---
|
||||
|
||||
Ah, C. Still **the** language of modern high-performance computing.
|
||||
@ -46,31 +46,47 @@ Multi-line comments don't nest /* Be careful */ // comment ends on this line...
|
||||
|
||||
// Enumeration constants are also ways to declare constants.
|
||||
// All statements must end with a semicolon
|
||||
enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT};
|
||||
enum days {SUN, MON, TUE, WED, THU, FRI, SAT};
|
||||
// SUN gets 0, MON gets 1, TUE gets 2, etc.
|
||||
|
||||
// Enumeration values can also be specified
|
||||
enum days {SUN = 1, MON, TUE, WED = 99, THU, FRI, SAT};
|
||||
// MON gets 2 automatically, TUE gets 3, etc.
|
||||
// WED get 99, THU gets 100, FRI gets 101, etc.
|
||||
|
||||
// Import headers with #include
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// (File names between <angle brackets> are headers from the C standard library.)
|
||||
// For your own headers, use double quotes instead of angle brackets:
|
||||
//#include "my_header.h"
|
||||
// File names between <angle brackets> tell the compiler to look in your system
|
||||
// libraries for the headers.
|
||||
// For your own headers, use double quotes instead of angle brackets, and
|
||||
// provide the path:
|
||||
#include "my_header.h" // local file
|
||||
#include "../my_lib/my_lib_header.h" //relative path
|
||||
|
||||
// Declare function signatures in advance in a .h file, or at the top of
|
||||
// your .c file.
|
||||
void function_1();
|
||||
int function_2(void);
|
||||
|
||||
// Must declare a 'function prototype' before main() when functions occur after
|
||||
// your main() function.
|
||||
// At a minimum, you must declare a 'function prototype' before its use in any function.
|
||||
// Normally, prototypes are placed at the top of a file before any function definition.
|
||||
int add_two_ints(int x1, int x2); // function prototype
|
||||
// although `int add_two_ints(int, int);` is also valid (no need to name the args),
|
||||
// it is recommended to name arguments in the prototype as well for easier inspection
|
||||
|
||||
// Your program's entry point is a function called
|
||||
// main with an integer return type.
|
||||
// Function prototypes are not necessary if the function definition comes before
|
||||
// any other function that calls that function. However, it's standard practice to
|
||||
// always add the function prototype to a header file (*.h) and then #include that
|
||||
// file at the top. This prevents any issues where a function might be called
|
||||
// before the compiler knows of its existence, while also giving the developer a
|
||||
// clean header file to share with the rest of the project.
|
||||
|
||||
// Your program's entry point is a function called "main". The return type can
|
||||
// be anything, however most operating systems expect a return type of `int` for
|
||||
// error code processing.
|
||||
int main(void) {
|
||||
// your program
|
||||
}
|
||||
@ -85,6 +101,12 @@ int main (int argc, char** argv)
|
||||
// %d is an integer, \n is a newline
|
||||
printf("%d\n", 0); // => Prints 0
|
||||
|
||||
// take input using scanf
|
||||
// '&' is used to define the location
|
||||
// where we want to store the input value
|
||||
int input;
|
||||
scanf("%d", &input);
|
||||
|
||||
///////////////////////////////////////
|
||||
// Types
|
||||
///////////////////////////////////////
|
||||
@ -96,13 +118,14 @@ int main (int argc, char** argv)
|
||||
// For the sake of the tutorial, variables are declared dynamically under
|
||||
// C99-compliant standards.
|
||||
|
||||
// ints are usually 4 bytes
|
||||
// ints are usually 4 bytes (use the `sizeof` operator to check)
|
||||
int x_int = 0;
|
||||
|
||||
// shorts are usually 2 bytes
|
||||
// shorts are usually 2 bytes (use the `sizeof` operator to check)
|
||||
short x_short = 0;
|
||||
|
||||
// chars are guaranteed to be 1 byte
|
||||
// chars are defined as the smallest addressable unit for a processor.
|
||||
// This is usually 1 byte, but for some systems it can be more (ex. for TMS320 from TI it's 2 bytes).
|
||||
char x_char = 0;
|
||||
char y_char = 'y'; // Char literals are quoted with ''
|
||||
|
||||
@ -145,19 +168,25 @@ int main (int argc, char** argv)
|
||||
int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes
|
||||
// (assuming 4-byte words)
|
||||
|
||||
// You can initialize an array to 0 thusly:
|
||||
char my_array[20] = {0};
|
||||
// You can initialize an array of twenty ints that all equal 0 thusly:
|
||||
int my_array[20] = {0};
|
||||
// where the "{0}" part is called an "array initializer".
|
||||
// NOTE that you get away without explicitly declaring the size of the array,
|
||||
// IF you initialize the array on the same line. So, the following declaration
|
||||
// is equivalent:
|
||||
char my_array[] = {0};
|
||||
// BUT, then you have to evaluate the size of the array at run-time, like this:
|
||||
// All elements (if any) past the ones in the initializer are initialized to 0:
|
||||
int my_array[5] = {1, 2};
|
||||
// So my_array now has five elements, all but the first two of which are 0:
|
||||
// [1, 2, 0, 0, 0]
|
||||
// NOTE that you get away without explicitly declaring the size
|
||||
// of the array IF you initialize the array on the same line:
|
||||
int my_array[] = {0};
|
||||
// NOTE that, when not declaring the size, the size of the array is the number
|
||||
// of elements in the initializer. With "{0}", my_array is now of size one: [0]
|
||||
// To evaluate the size of the array at run-time, divide its byte size by the
|
||||
// byte size of its element type:
|
||||
size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]);
|
||||
// WARNING If you adopt this approach, you should evaluate the size *before*
|
||||
// you begin passing the array to function (see later discussion), because
|
||||
// arrays get "downgraded" to raw pointers when they are passed to functions
|
||||
// (so the statement above will produce the wrong result inside the function).
|
||||
// WARNING You should evaluate the size *before* you begin passing the array
|
||||
// to functions (see later discussion) because arrays get "downgraded" to
|
||||
// raw pointers when they are passed to functions (so the statement above
|
||||
// will produce the wrong result inside the function).
|
||||
|
||||
// Indexing an array is like other languages -- or,
|
||||
// rather, other languages are like C
|
||||
@ -224,14 +253,23 @@ int main (int argc, char** argv)
|
||||
(float)i1 / i2; // => 0.5f
|
||||
i1 / (double)i2; // => 0.5 // Same with double
|
||||
f1 / f2; // => 0.5, plus or minus epsilon
|
||||
|
||||
// Floating-point numbers and calculations are not exact
|
||||
// for instance it is not giving mathematically correct results
|
||||
|
||||
// Floating-point numbers are defined by IEEE 754, thus cannot store perfectly
|
||||
// exact values. For instance, the following does not produce expected results
|
||||
// because 0.1 might actually be 0.099999999999 inside the computer, and 0.3
|
||||
// might be stored as 0.300000000001.
|
||||
(0.1 + 0.1 + 0.1) != 0.3; // => 1 (true)
|
||||
// and it is NOT associative
|
||||
// and it is NOT associative due to reasons mentioned above.
|
||||
1 + (1e123 - 1e123) != (1 + 1e123) - 1e123; // => 1 (true)
|
||||
// this notation is scientific notations for numbers: 1e123 = 1*10^123
|
||||
|
||||
// It is important to note that most all systems have used IEEE 754 to
|
||||
// represent floating points. Even python, used for scientific computing,
|
||||
// eventually calls C which uses IEEE 754. It is mentioned this way not to
|
||||
// indicate that this is a poor implementation, but instead as a warning
|
||||
// that when doing floating point comparisons, a little bit of error (epsilon)
|
||||
// needs to be considered.
|
||||
|
||||
// Modulo is there as well, but be careful if arguments are negative
|
||||
11 % 3; // => 2 as 11 = 2 + 3*x (x=3)
|
||||
(-11) % 3; // => -2, as one would expect
|
||||
@ -239,7 +277,7 @@ int main (int argc, char** argv)
|
||||
|
||||
// Comparison operators are probably familiar, but
|
||||
// there is no Boolean type in C. We use ints instead.
|
||||
// (Or _Bool or bool in C99.)
|
||||
// (C99 introduced the _Bool type provided in stdbool.h)
|
||||
// 0 is false, anything else is true. (The comparison
|
||||
// operators always yield 0 or 1.)
|
||||
3 == 2; // => 0 (false)
|
||||
@ -379,7 +417,7 @@ int main (int argc, char** argv)
|
||||
*/
|
||||
/*
|
||||
it is generally considered bad practice to do so, except if
|
||||
you really know what you are doing. See
|
||||
you really know what you are doing. See
|
||||
https://en.wikipedia.org/wiki/Spaghetti_code#Meaning
|
||||
*/
|
||||
|
||||
@ -391,13 +429,16 @@ int main (int argc, char** argv)
|
||||
// if you want (with some constraints).
|
||||
|
||||
int x_hex = 0x01; // You can assign vars with hex literals
|
||||
// binary is not in the standard, but allowed by some
|
||||
// compilers (x_bin = 0b0010010110)
|
||||
|
||||
// Casting between types will attempt to preserve their numeric values
|
||||
printf("%d\n", x_hex); // => Prints 1
|
||||
printf("%d\n", (short) x_hex); // => Prints 1
|
||||
printf("%d\n", (char) x_hex); // => Prints 1
|
||||
|
||||
// Types will overflow without warning
|
||||
// If you assign a value greater than a types max val, it will rollover
|
||||
// without warning.
|
||||
printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long)
|
||||
|
||||
// For determining the max value of a `char`, a `signed char` and an `unsigned char`,
|
||||
@ -543,7 +584,8 @@ the function are copies of the original arguments (except arrays). Anything you
|
||||
do to the arguments in the function do not change the value of the original
|
||||
argument where the function was called.
|
||||
|
||||
Use pointers if you need to edit the original argument values.
|
||||
Use pointers if you need to edit the original argument values (arrays are always
|
||||
passed in as pointers).
|
||||
|
||||
Example: in-place string reversal
|
||||
*/
|
||||
@ -554,9 +596,11 @@ void str_reverse(char *str_in)
|
||||
char tmp;
|
||||
size_t ii = 0;
|
||||
size_t len = strlen(str_in); // `strlen()` is part of the c standard library
|
||||
// NOTE: length returned by `strlen` DOESN'T include the
|
||||
// terminating NULL byte ('\0')
|
||||
for (ii = 0; ii < len / 2; ii++) { // in C99 you can directly declare type of `ii` here
|
||||
// NOTE: length returned by `strlen` DOESN'T
|
||||
// include the terminating NULL byte ('\0')
|
||||
// in C99 and newer versions, you can directly declare loop control variables
|
||||
// in the loop's parentheses. e.g., `for (size_t ii = 0; ...`
|
||||
for (ii = 0; ii < len / 2; ii++) {
|
||||
tmp = str_in[ii];
|
||||
str_in[ii] = str_in[len - ii - 1]; // ii-th char from end
|
||||
str_in[len - ii - 1] = tmp;
|
||||
@ -588,6 +632,24 @@ printf("first: %d\nsecond: %d\n", first, second);
|
||||
// values will be swapped
|
||||
*/
|
||||
|
||||
// Return multiple values.
|
||||
// C does not allow for returning multiple values with the return statement. If
|
||||
// you would like to return multiple values, then the caller must pass in the
|
||||
// variables where they would like the returned values to go. These variables must
|
||||
// be passed in as pointers such that the function can modify them.
|
||||
int return_multiple( int *array_of_3, int *ret1, int *ret2, int *ret3)
|
||||
{
|
||||
if(array_of_3 == NULL)
|
||||
return 0; //return error code (false)
|
||||
|
||||
//de-reference the pointer so we modify its value
|
||||
*ret1 = array_of_3[0];
|
||||
*ret2 = array_of_3[1];
|
||||
*ret3 = array_of_3[2];
|
||||
|
||||
return 1; //return error code (true)
|
||||
}
|
||||
|
||||
/*
|
||||
With regards to arrays, they will always be passed to functions
|
||||
as pointers. Even if you statically allocate an array like `arr[10]`,
|
||||
@ -653,7 +715,7 @@ struct rectangle {
|
||||
|
||||
void function_1()
|
||||
{
|
||||
struct rectangle my_rec;
|
||||
struct rectangle my_rec = { 1, 2 }; // Fields can be initialized immediately
|
||||
|
||||
// Access struct members with .
|
||||
my_rec.width = 10;
|
||||
@ -677,6 +739,16 @@ int area(rect r)
|
||||
return r.width * r.height;
|
||||
}
|
||||
|
||||
// Typedefs can also be defined right during struct definition
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
} rect;
|
||||
// Like before, doing this means one can type
|
||||
rect r;
|
||||
// instead of having to type
|
||||
struct rectangle r;
|
||||
|
||||
// if you have large structs, you can pass them "by pointer" to avoid copying
|
||||
// the whole struct:
|
||||
int areaptr(const rect *r)
|
||||
@ -716,6 +788,10 @@ typedef void (*my_fnp_type)(char *);
|
||||
// my_fnp_type f;
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// Printing characters with printf()
|
||||
/////////////////////////////
|
||||
|
||||
//Special characters:
|
||||
/*
|
||||
'\a'; // alert (bell) character
|
||||
@ -825,16 +901,17 @@ enum traffic_light_state {GREEN, YELLOW, RED};
|
||||
Node createLinkedList(int *vals, int len);
|
||||
|
||||
/* Beyond the above elements, other definitions should be left to a C source */
|
||||
/* file. Excessive includes or definitions should, also not be contained in */
|
||||
/* file. Excessive includes or definitions should also not be contained in */
|
||||
/* a header file but instead put into separate headers or a C file. */
|
||||
|
||||
#endif /* End of the if precompiler directive. */
|
||||
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)
|
||||
It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some
|
||||
It is _the_ book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some
|
||||
inaccuracies (well, ideas that are not considered good anymore) or now-changed practices.
|
||||
|
||||
Another good resource is [Learn C The Hard Way](http://learncodethehardway.org/c/) (not free).
|
||||
|
@ -5,7 +5,7 @@ contributors:
|
||||
translators:
|
||||
- ["Abel Salgado Romero", "https://twitter.com/abelsromero"]
|
||||
lang: ca-es
|
||||
filename: asciidoc-ca.md
|
||||
filename: asciidoc-ca.adoc
|
||||
---
|
||||
|
||||
AsciiDoc és un llenguatge de marques similar a Markdown i que pot ser usat per qualsevol ús, des de llibres fins a blogs.
|
||||
|
@ -95,7 +95,7 @@ salts de línia.` // El mateix tipus
|
||||
// literals Non-ASCII literal. El tipus de Go és UTF-8.
|
||||
g := 'Σ' // El tipus rune, és un àlies de int32 conté un caràcter unicode.
|
||||
|
||||
f := 3.14195 // float64, un número de 64 bits amb coma flotant IEEE-754.
|
||||
f := 3.14159 // float64, un número de 64 bits amb coma flotant IEEE-754.
|
||||
c := 3 + 4i // complex128, representat internament amb dos float64.
|
||||
|
||||
// Sintaxi amb var i inicialitzadors.
|
||||
@ -433,25 +433,25 @@ func requestServer() {
|
||||
## Més informació
|
||||
|
||||
L'arrel de tot en Go és la web oficial [official Go web site]
|
||||
(http://golang.org/). Allà es pot seguir el tutorial, jugar interactivament
|
||||
(https://go.dev/). Allà es pot seguir el tutorial, jugar interactivament
|
||||
i llegir molt més del que hem vist aquí.En el "tour",
|
||||
[the docs](https://golang.org/doc/) conté informació sobre com escriure codi
|
||||
[the docs](https://go.dev/doc/) conté informació sobre com escriure codi
|
||||
net i efectiu en Go, comandes per empaquetar i generar documentació, i
|
||||
història de les versions.
|
||||
|
||||
És altament recomanable llegir La definició del llenguatge. És fàcil de llegir
|
||||
i sorprenentment curta (com la definició del llenguatge en aquests dies).
|
||||
|
||||
Es pot jugar amb codi a [Go playground](https://play.golang.org/p/tnWMjr16Mm).
|
||||
Es pot jugar amb codi a [Go playground](https://go.dev/play/p/tnWMjr16Mm).
|
||||
Prova de fer canvis en el codi i executar-lo des del navegador! Es pot fer
|
||||
servir [https://play.golang.org](https://play.golang.org) com a [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) per provar coses i codi
|
||||
servir [https://go.dev/play/](https://go.dev/play/) com a [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) per provar coses i codi
|
||||
en el navegador sense haver d'instal·lar Go.
|
||||
|
||||
En la llista de lectures pels estudiants de Go hi ha
|
||||
[el codi font de la llibreria estàndard](http://golang.org/src/pkg/).
|
||||
[el codi font de la llibreria estàndard](https://go.dev/src/).
|
||||
Ampliament comentada, que demostra el fàcil que és de llegir i entendre els
|
||||
programes en Go, l'estil de programació, i les formes de treballar-hi. O es
|
||||
pot clicar en un nom de funció en [la documentació](http://golang.org/pkg/)
|
||||
pot clicar en un nom de funció en [la documentació](https://go.dev/pkg/)
|
||||
i veure'n el codi!
|
||||
|
||||
Un altre gran recurs per aprendre Go és
|
||||
|
864
cairo.html.markdown
Normal file
864
cairo.html.markdown
Normal file
@ -0,0 +1,864 @@
|
||||
---
|
||||
language: Cairo
|
||||
filename: learnCairo.sol
|
||||
contributors:
|
||||
- ["Darlington Nnam", "https://github.com/Darlington02"]
|
||||
---
|
||||
|
||||
# Cairo
|
||||
|
||||
Cairo is a Turing-complete language that allows you write provable programs
|
||||
(where one party can prove to another that a certain computation was executed
|
||||
correctly) on StarkNet.
|
||||
|
||||
## StarkNet
|
||||
|
||||
StarkNet is a decentralized ZK-rollup that operates as an Ethereum layer 2
|
||||
chain.
|
||||
|
||||
In this document, we are going to be going in-depth into understanding Cairo's
|
||||
syntax and how you could create and deploy a Cairo smart contract on StarkNet.
|
||||
|
||||
**NB: As at the time of this writing, StarkNet is still at v0.10.3, with Cairo
|
||||
1.0 coming soon. The ecosystem is young and evolving very fast, so you might
|
||||
want to check the [official docs](https://www.cairo-lang.org/docs) to confirm
|
||||
this document is still up-to-date. Pull requests are welcome!**
|
||||
|
||||
## Setting Up A Development Environment
|
||||
|
||||
Before we get started writing codes, we will need to setup a Cairo development
|
||||
environment, for writing, compiling and deploying our contracts to StarkNet.
|
||||
For the purpose of this tutorial we are going to be using the
|
||||
[Protostar Framework](https://github.com/software-mansion/protostar).
|
||||
Installation steps can be found in the docs
|
||||
[here](https://docs.swmansion.com/protostar/docs/tutorials/installation).
|
||||
Note that Protostar supports just Mac and Linux OS, Windows users might need to
|
||||
use WSL, or go for other alternatives such as the Official
|
||||
[StarkNet CLI](https://www.cairo-lang.org/docs/quickstart.html) or
|
||||
[Nile from Openzeppelin](https://github.com/OpenZeppelin/nile)
|
||||
|
||||
Once you're done with the installations, run the command `protostar -v` to
|
||||
confirm your installation was successful. If successful, you should see your
|
||||
Protostar version displayed on the screen.
|
||||
|
||||
## Initializing a new project
|
||||
|
||||
Protostar similar to Truffle for solidity development can be installed once and
|
||||
used for multiple projects. To initialize a new Protostar project, run the
|
||||
following command:
|
||||
|
||||
```
|
||||
protostar init
|
||||
```
|
||||
|
||||
It would then request the project's name and the library's directory name,
|
||||
you'd need to fill in this, and a new project will be initialized successfully.
|
||||
|
||||
## Compiling, Declaring, Deploying and Interacting with StarkNet Contracts
|
||||
|
||||
Within the `src` folder you'll find a boilerplate contract that comes with
|
||||
initializing a new Protostar project, `main.cairo`. We are going to be
|
||||
compiling, declaring and deploying this contract.
|
||||
|
||||
### Compiling Contracts
|
||||
|
||||
To compile a Cairo contract using Protostar, ensure a path to the contract is
|
||||
specified in the `[contracts]` section of the `protostar.toml` file. Once
|
||||
you've done that, open your terminal and run the command:
|
||||
|
||||
```
|
||||
protostar build
|
||||
```
|
||||
|
||||
And you should get an output similar to what you see below, with a `main.json`
|
||||
and `main_abi.json` files created in the `build` folder.
|
||||
<img src="./images/cairo/build.png" alt="building your contract">
|
||||
|
||||
### Declaring Contracts
|
||||
|
||||
With the recent StarkNet update to 0.10.3, the DEPLOY transaction was
|
||||
deprecated and no longer works. To deploy a transaction, you must first declare
|
||||
a Contract to obtain the class hash, then deploy the declared contract using the
|
||||
[Universal Deployer Contract](https://community.starknet.io/t/universal-deployer-contract-proposal/1864).
|
||||
|
||||
Before declaring or deploying your contract using Protostar, you should set the
|
||||
private key associated with the specified account address in a file, or in the
|
||||
terminal. To set your private key in the terminal, run the command:
|
||||
|
||||
```
|
||||
export PROTOSTAR_ACCOUNT_PRIVATE_KEY=[YOUR PRIVATE KEY HERE]
|
||||
```
|
||||
|
||||
Then to declare our contract using Protostar run the following command (for
|
||||
visual clarity, the backslash sign symbolizes the continuing line):
|
||||
|
||||
```
|
||||
protostar declare ./build/main.json \
|
||||
--network testnet \
|
||||
--account 0x0691622bBFD29e835bA4004e7425A4e9630840EbD11c5269DE51C16774585b16 \
|
||||
--max-fee auto
|
||||
```
|
||||
|
||||
where `network` specifies the network we are deploying to, `account` specifies
|
||||
account whose private key we are using, `max-fee` specifies the maximum fee to
|
||||
be paid for the transaction. You should get the class hash outputted as seen
|
||||
below:
|
||||
<img src="./images/cairo/declare.png" alt="declaring your contract">
|
||||
|
||||
### Deploying Contracts
|
||||
|
||||
After obtaining our class hash from declaring, we can now deploy using the
|
||||
command below:
|
||||
|
||||
```
|
||||
protostar \
|
||||
deploy 0x02a5de1b145e18dfeb31c7cd7ff403714ededf5f3fdf75f8b0ac96f2017541bc \
|
||||
--network testnet \
|
||||
--account 0x0691622bBFD29e835bA4004e7425A4e9630840EbD11c5269DE51C16774585b16 \
|
||||
--max-fee auto
|
||||
```
|
||||
|
||||
where `0x02a5de1b145e18dfeb31c7cd7ff403714ededf5f3fdf75f8b0ac96f2017541bc` is
|
||||
the class hash of our contract.
|
||||
<img src="./images/cairo/deploy.png" alt="deploying your contract">
|
||||
|
||||
### Interacting with Contracts
|
||||
|
||||
To interact with your deployed contract, we will be using `Argent X`
|
||||
(alternative: `Braavos`), and `Starkscan` (alternative: `Voyager`). To install
|
||||
and setup `Argent X`, see this
|
||||
[guide](https://www.argent.xyz/learn/how-to-create-an-argent-x-wallet/).
|
||||
|
||||
Copy your contract address, displayed on screen from the previous step, and
|
||||
head over to [Starkscan](https://testnet.starkscan.co/) to search for the
|
||||
contract. Once found, you can make write calls to the contract in the following
|
||||
sequence:
|
||||
|
||||
+ click on the "connect wallet" button,
|
||||
<img src="./images/cairo/connect.png" alt="connect wallet">
|
||||
+ select `Argent X` and approve the connection
|
||||
<img src="./images/cairo/connect2.png" alt="connect to argentX">
|
||||
+ you can now make read and write calls easily.
|
||||
|
||||
## Let's learn Cairo
|
||||
|
||||
First let's look at a default contract that comes with Protostar which allows
|
||||
you to set balance on deployment, increase, and get the balance.
|
||||
|
||||
```
|
||||
// Language directive - instructs compiler its a StarkNet contract
|
||||
%lang starknet
|
||||
|
||||
// Library imports from the Cairo-lang library
|
||||
from starkware.cairo.common.math import assert_nn
|
||||
from starkware.cairo.common.cairo_builtins import HashBuiltin
|
||||
|
||||
// @dev Storage variable that stores the balance of a user.
|
||||
// @storage_var is a decorator that instructs the compiler the function
|
||||
// below it is a storage variable.
|
||||
@storage_var
|
||||
func balance() -> (res: felt) {}
|
||||
|
||||
// @dev Constructor writes the balance variable to 0 on deployment
|
||||
// Constructors sets storage variables on deployment. Can accept arguments too.
|
||||
@constructor
|
||||
func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() {
|
||||
balance.write(0);
|
||||
return();
|
||||
}
|
||||
|
||||
// @dev increase_balance updates the balance variable
|
||||
// @param amount the amount you want to add to balance
|
||||
// @external is a decorator that specifies the func below it is an external
|
||||
// function.
|
||||
@external
|
||||
func increase_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(amount: felt){
|
||||
with_attr error_message("Amount must be positive. Got: {amount}.") {
|
||||
assert_nn(amount);
|
||||
}
|
||||
|
||||
let (res) = balance.read();
|
||||
balance.write(res + amount);
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev returns the balance variable
|
||||
// @view is a decorator that specifies the func below it is a view function.
|
||||
@view
|
||||
func get_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
let (res) = balance.read();
|
||||
return (res,);
|
||||
}
|
||||
```
|
||||
|
||||
Before proceeding to the main lessons, try to build, deploy and interact with
|
||||
this contract.
|
||||
NB: You should be at `main.cairo` if you are using Protostar.
|
||||
|
||||
### 1. The Felt data type
|
||||
|
||||
Unlike solidity, where you have access to various data types, Cairo comes with
|
||||
just a single data type `..felts`. Felts stands for Field elements, and are a
|
||||
252 bit integer in the range `0<=x<=P` where `P` is a prime number. You can
|
||||
create a `Uint256` in Cairo by utlizing a struct of two 128 bits felts.
|
||||
|
||||
```
|
||||
struct Uint256 {
|
||||
low: felt, // The low 128 bits of the value.
|
||||
high: felt, // The high 128 bits of the value.
|
||||
}
|
||||
```
|
||||
|
||||
To avoid running into issues with divisions, it's safer to work with the
|
||||
`unsigned_div_rem` method from Cairo-lang's library.
|
||||
|
||||
### 2. Lang Directive and Imports
|
||||
|
||||
To get started with writing a StarkNet contract, you must specify the directive:
|
||||
|
||||
```
|
||||
%lang starknet
|
||||
```
|
||||
|
||||
This directive informs the compiler you are writing a contract and not a
|
||||
program. The difference between both is contracts have access to StarkNet's
|
||||
storage, programs don't and as such are stateless.
|
||||
|
||||
There are important functions you might need to import from the official
|
||||
Cairo-lang library or Openzeppelin's, e.g.
|
||||
|
||||
```
|
||||
from starkware.cairo.common.cairo_builtins import HashBuiltin
|
||||
from cairo_contracts.src.openzeppelin.token.erc20.library import ERC20
|
||||
from starkware.cairo.common.uint256 import Uint256
|
||||
from starkware.cairo.common.bool import TRUE
|
||||
```
|
||||
|
||||
### 3. Data Structures
|
||||
|
||||
+ Storage variables: Cairo's storage is a map with `2^251` slots, where each
|
||||
slot is a felt which is initialized to `0`. You create one using the
|
||||
`@storage_var` decorator.
|
||||
|
||||
```
|
||||
@storage_var
|
||||
func names() -> (name: felt) {}
|
||||
```
|
||||
|
||||
+ Storage mappings: Unlike Solidity where mappings have a separate keyword, in
|
||||
Cairo you create mappings using storage variables.
|
||||
|
||||
```
|
||||
@storage_var
|
||||
func names(address: felt) -> (name: felt) {}
|
||||
```
|
||||
|
||||
+ Structs: are a means to create custom data types in Cairo. A `struct` has a
|
||||
size, which is the sum of the sizes of its members. The size can be
|
||||
retrieved using `MyStruct.SIZE`. You create a struct in Cairo using the
|
||||
`struct` keyword.
|
||||
|
||||
```
|
||||
struct Person {
|
||||
name: felt,
|
||||
age: felt,
|
||||
address: felt,
|
||||
}
|
||||
```
|
||||
|
||||
+ Constants: Constants are fixed and as such can't be altered after being set.
|
||||
They evaluate to an integer (field element) at compile time. To create a
|
||||
constant in Cairo, you use the `const` keyword. It's proper practice to
|
||||
capitalize constant names.
|
||||
|
||||
```
|
||||
const USER = 0x01C6cfC1DB2ae90dACEA243F0a8C2F4e32560F7cDD398e4dA2Cc56B733774E9b
|
||||
```
|
||||
|
||||
+ Arrays: Arrays can be defined as a `pointer(felt*)` to the first element of
|
||||
the array. As an array is populated, its elements take up contigous memory
|
||||
cells. The `alloc` keyword can be used to dynamically allocate a new memory
|
||||
segment, which can be used to store an array:
|
||||
|
||||
```
|
||||
let (myArray: felt*) = alloc ();
|
||||
assert myArray[0] = 1;
|
||||
assert myArray[1] = 2;
|
||||
assert myArray[3] = 3;
|
||||
```
|
||||
|
||||
You can also use the `new` operator to create fixed-size arrays using
|
||||
tuples. The new operator is useful as it enables you allocate memory and
|
||||
initialize the object in one instruction
|
||||
|
||||
```
|
||||
func foo() {
|
||||
tempvar arr: felt* = new (1, 1, 2, 3, 5);
|
||||
assert arr[4] = 5;
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
+ Tuples: A tuple is a finite, ordered, unchangeable list of elements. It is
|
||||
represented as a comma-separated list of elements enclosed by parentheses.
|
||||
Their elements may be of any combination of valid types.
|
||||
|
||||
```
|
||||
local tuple0: (felt, felt, felt) = (7, 9, 13);
|
||||
```
|
||||
|
||||
+ Events: Events allows a contract emit information during the course of its
|
||||
execution, that can be used outside of StarkNet. An event can be created,
|
||||
subsequently emitted:
|
||||
|
||||
```
|
||||
@event
|
||||
func name_stored(address, name) {}
|
||||
|
||||
name_stored.emit(address, name);
|
||||
```
|
||||
|
||||
### 4. Constructors, External and View functions
|
||||
|
||||
+ Constructors: Constructors are a way to intialize state variables on
|
||||
contract deployment. You create a constructor using the `@constructor`
|
||||
decorator.
|
||||
|
||||
```
|
||||
@constructor
|
||||
func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_name: felt) {
|
||||
let (caller) = get_caller_address();
|
||||
names.write(caller, _name);
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
+ External functions: External functions are functions that modifies the state
|
||||
of the network. You create an external function using the `@external`
|
||||
decorator:
|
||||
|
||||
```
|
||||
@external
|
||||
func store_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_name: felt){
|
||||
let (caller) = get_caller_address();
|
||||
names.write(caller, _name);
|
||||
stored_name.emit(caller, _name);
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
+ View functions: View functions do not modify the state of the blockchain.
|
||||
You can create a view function using the `@view` decorator.
|
||||
|
||||
```
|
||||
@view
|
||||
func get_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_address: felt) -> (name: felt){
|
||||
let (name) = names.read(_address);
|
||||
return (name,);
|
||||
}
|
||||
```
|
||||
|
||||
NB: Unlike Solidity, Cairo supports just External and View function types.
|
||||
You can alternatively also create an internal function by not adding any
|
||||
decorator to the function.
|
||||
|
||||
### 5. Decorators
|
||||
|
||||
All functions in Cairo are specified by the `func` keyword, which can be
|
||||
confusing. Decorators are used by the compiler to distinguish between these
|
||||
functions.
|
||||
|
||||
Here are the most common decorators you'll encounter in Cairo:
|
||||
|
||||
+ `@storage_var` — used for specifying state variables.
|
||||
+ `@constructor` — used for specifying constructors.
|
||||
+ `@external` — used for specifying functions that write to a state variable.
|
||||
+ `@event` — used for specifying events
|
||||
+ `@view` — used to specify functions reading from a state variable
|
||||
+ `@contract_interface` — used for specifying function interfaces.
|
||||
+ `@l1_handler` — used for specifying functions that processes message sent from
|
||||
an L1 contract in a messaging bridge.
|
||||
|
||||
### 6. BUILTINS, HINTS & IMPLICIT Arguments
|
||||
|
||||
+ `BUILTINS` are predefined optimized low-level execution units, which are
|
||||
added to Cairo’s CPU board. They help perform predefined computations like
|
||||
pedersen hashing, bitwise operations etc, which are expensive to perform in
|
||||
Vanilla Cairo. Each builtin in Cairo is assigned a separate memory location,
|
||||
accessible through regular Cairo memory calls using implicit parameters. You
|
||||
specify them using the `%builtins` directive
|
||||
|
||||
Here is a list of available builtins in Cairo:
|
||||
|
||||
+ `output` — the output builtin is used for writing program outputs
|
||||
+ `pedersen` — the pedersen builtin is used for pedersen hashing
|
||||
computations
|
||||
+ `range_check` — This builtin is mostly used for integer comparisons,
|
||||
and facilitates check to confirm that a field element is within a range
|
||||
`[0, 2^128)`
|
||||
+ `ecdsa` — the ecdsa builtin is used for verifying ECDSA signatures
|
||||
+ `bitwise` — the bitwise builtin is used for carrying out bitwise
|
||||
operations on felts
|
||||
|
||||
+ `HINTS` are pieces of Python codes, which contains instructions that only
|
||||
the prover sees and executes. From the point of view of the verifier these
|
||||
hints do not exist. To specify a hint in Cairo, you need to encapsulate it
|
||||
within `%{` and `%}`. It is good practice to avoid using hints as much as
|
||||
you can in your contracts, as hints are not added to the bytecode, and thus
|
||||
do not count in the total number of execution steps.
|
||||
|
||||
```
|
||||
%{
|
||||
# Python hint goes here
|
||||
%}
|
||||
```
|
||||
|
||||
+ `IMPLICIT ARGUMENTS` are not restricted to the function body, but can be
|
||||
inherited by other functions calls that require them. Implicit arguments are
|
||||
passed in between curly bracelets, like you can see below:
|
||||
|
||||
```
|
||||
func store_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_name: felt){
|
||||
let (caller) = get_caller_address();
|
||||
names.write(caller, _name);
|
||||
stored_name.emit(caller, _name);
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Error Messages and Access Controls
|
||||
|
||||
You can create custom errors in Cairo which is outputted to the user upon failed
|
||||
execution. This can be very useful for implementing checks and proper access
|
||||
control mechanisms. An example is preventing a user to call a function except
|
||||
user is `admin`.
|
||||
|
||||
```
|
||||
// imports
|
||||
from starkware.starknet.common.syscalls import get_caller_address
|
||||
|
||||
// create an admin constant
|
||||
const ADMIN = 0x01C6cfC1DB2ae90dACEA243F0a8C2F4e32560F7cDD398e4dA2Cc56B733774E9b
|
||||
|
||||
// implement access control
|
||||
with_attr error_message("You do not have access to make this action!"){
|
||||
let (caller) = get_caller_address();
|
||||
assert ADMIN = caller;
|
||||
}
|
||||
|
||||
// using an assert statement throws if condition is not true, thus
|
||||
// returning the specified error.
|
||||
```
|
||||
|
||||
### 8. Contract Interfaces
|
||||
|
||||
Contract interfaces provide a means for one contract to invoke or call the
|
||||
external function of another contract. To create a contract interface, you use
|
||||
the `@contract_interface` keyword:
|
||||
|
||||
```
|
||||
@contract_interface
|
||||
namespace IENS {
|
||||
func store_name(_name: felt) {
|
||||
}
|
||||
|
||||
func get_name(_address: felt) -> (name: felt) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Once a contract interface is specified, any contract can make calls to that
|
||||
contract passing in the contract address as the first parameter like this:
|
||||
|
||||
```
|
||||
IENS.store_name(contract_address, _name);
|
||||
```
|
||||
|
||||
Note that Interfaces exclude the function body/logic and the implicit
|
||||
arguments.
|
||||
|
||||
### 9. Recursions
|
||||
|
||||
Due to the unavailability of loops, Recursion is the go-to for similar
|
||||
operations. In simple terms, a recursive function is one which calls itself
|
||||
repeatedly.
|
||||
|
||||
A good example to demonstrate this is writing a function for getting the nth
|
||||
fibonacci number:
|
||||
|
||||
```
|
||||
@external
|
||||
func fibonacci{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(n : felt) -> (result : felt){
|
||||
alloc_locals;
|
||||
if (n == 0){
|
||||
return (0);
|
||||
}
|
||||
if (n == 1){
|
||||
return (1);
|
||||
}
|
||||
let (local x) = fibonacci(n - 1);
|
||||
let (local y) = fibonacci(n - 2);
|
||||
return (result=(x + y));
|
||||
}
|
||||
```
|
||||
|
||||
The nth fibonacci term is the sum of the `nth - 1` and the `nth - 2` numbers,
|
||||
that's why we get these two as `(x,y)` using recursion.
|
||||
|
||||
NB: when implementing recursive functions, always remember to implement a base
|
||||
case (`n==0`, `n==1` in our case), to prevent stack overflows.
|
||||
|
||||
### 10. Registers
|
||||
|
||||
Registers holds values that may change over time. There are 3 major types of
|
||||
registers:
|
||||
|
||||
+ `ap` (allocation pointer) points to a yet unused memory. Temporary variables
|
||||
created using `let`, `tempvar` are held here, and thus susceptible to being
|
||||
revoked.
|
||||
+ `fp` (frame pointer) points to the frame of the current function. The address
|
||||
of all the function arguments and local variables are relative to this
|
||||
register and as such can never be revoked.
|
||||
+ `pc` (program counter) points to the current instruction.
|
||||
|
||||
### 11. Revoked References
|
||||
|
||||
Revoked references occur when there is a call instruction to another function,
|
||||
between the definition of a reference variable that depends on `ap` (temp
|
||||
variables) and its usage. This occurs as the compiler may not be able to compute
|
||||
the change of `ap` (as one may jump to the label from another place in the
|
||||
program, or call a function that might change ap in an unknown way).
|
||||
|
||||
Here is an example to demonstrate what I mean:
|
||||
|
||||
```
|
||||
@external
|
||||
func get_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
return (res=100);
|
||||
}
|
||||
|
||||
@external
|
||||
func double_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
let multiplier = 2;
|
||||
let (balance) = get_balance();
|
||||
let new_balance = balance * multiplier;
|
||||
return (res=new_balance);
|
||||
}
|
||||
```
|
||||
|
||||
If you run that code, you'll run into the revoked reference error as we are
|
||||
trying to access the `multiplier` variable after calling the `get_balance`
|
||||
function.
|
||||
|
||||
In simple cases you can resolve revoked references by adding the keyword
|
||||
`alloc_locals` within function scopes. In more complex cases you might need to
|
||||
create a local variable to resolve it.
|
||||
|
||||
```
|
||||
// resolving the `double_balance` function:
|
||||
@external
|
||||
func double_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
alloc_locals;
|
||||
let multiplier = 2;
|
||||
let (balance) = get_balance();
|
||||
let new_balance = balance * multiplier;
|
||||
return (res=new_balance);
|
||||
}
|
||||
```
|
||||
|
||||
### 12. Understanding Cairo's Punctuations
|
||||
|
||||
+ `;` (semicolon). Used at the end of each instruction
|
||||
+ `()` (parentheses). Used in a function declaration, if statements, and in a
|
||||
tuple declaration
|
||||
+ `{}` (curly braces). Used in a declaration of implicit arguments and to define
|
||||
code blocks.
|
||||
+ `[]` (square brackets). Standalone brackets represent the value at a
|
||||
particular address location (such as the allocation pointer, `[ap]`). Brackets
|
||||
following a pointer or a tuple act as a subscript operator, where `x[2]`
|
||||
represents the element with index `2` in `x`.
|
||||
+ `*` (single asterisk). Refers to the pointer of an expression.
|
||||
+ `%` (percent sign). Appears at the start of a directive, such as `%builtins`
|
||||
or `%lang`.
|
||||
+ `%{` and `%}` represent Python hints.
|
||||
+ `_` (underscore). A placeholder to handle values that are not used, such as an
|
||||
unused function return value.
|
||||
|
||||
## Full Contract Example
|
||||
|
||||
Below is a simple automated market maker contract example that implements most
|
||||
of what we just learnt! Re-write, deploy, have fun!
|
||||
|
||||
```
|
||||
%lang starknet
|
||||
|
||||
from starkware.cairo.common.cairo_builtins import HashBuiltin
|
||||
from starkware.cairo.common.hash import hash2
|
||||
from starkware.cairo.common.alloc import alloc
|
||||
from starkware.cairo.common.math import (assert_le, assert_nn_le,
|
||||
unsigned_div_rem)
|
||||
from starkware.starknet.common.syscalls import (get_caller_address,
|
||||
storage_read, storage_write)
|
||||
|
||||
|
||||
// CONSTANTS
|
||||
//
|
||||
// @dev the maximum amount of each token that belongs to the AMM
|
||||
const BALANCE_UPPER_BOUND = 2 ** 64;
|
||||
|
||||
const TOKEN_TYPE_A = 1;
|
||||
const TOKEN_TYPE_B = 2;
|
||||
|
||||
// @dev Ensure the user's balances are much smaller than the pool's balance
|
||||
const POOL_UPPER_BOUND = 2 ** 30;
|
||||
const ACCOUNT_BALANCE_BOUND = 1073741; // (2 ** 30 / 1000)
|
||||
|
||||
|
||||
// STORAGE VARIABLES
|
||||
//
|
||||
// @dev A map from account and token type to corresponding balance
|
||||
@storage_var
|
||||
func account_balance(account_id: felt, token_type: felt) -> (balance: felt) {}
|
||||
|
||||
// @dev a map from token type to corresponding pool balance
|
||||
@storage_var
|
||||
func pool_balance(token_type: felt) -> (balance: felt) {}
|
||||
|
||||
|
||||
// GETTERS
|
||||
//
|
||||
// @dev returns account balance for a given token
|
||||
// @param account_id Account to be queried
|
||||
// @param token_type Token to be queried
|
||||
@view
|
||||
func get_account_token_balance{syscall_ptr: felt*, pedersen_ptr:
|
||||
HashBuiltin*, range_check_ptr}(
|
||||
account_id: felt, token_type: felt
|
||||
) -> (balance: felt) {
|
||||
return account_balance.read(account_id, token_type);
|
||||
}
|
||||
|
||||
// @dev return the pool's balance
|
||||
// @param token_type Token type to get pool balance
|
||||
@view
|
||||
func get_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_type: felt
|
||||
) -> (balance: felt) {
|
||||
return pool_balance.read(token_type);
|
||||
}
|
||||
|
||||
|
||||
// EXTERNALS
|
||||
//
|
||||
// @dev set pool balance for a given token
|
||||
// @param token_type Token whose balance is to be set
|
||||
// @param balance Amount to be set as balance
|
||||
@external
|
||||
func set_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_type: felt, balance: felt
|
||||
) {
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(balance, BALANCE_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
pool_balance.write(token_type, balance);
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev add demo token to the given account
|
||||
// @param token_a_amount amount of token a to be added
|
||||
// @param token_b_amount amount of token b to be added
|
||||
@external
|
||||
func add_demo_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_a_amount: felt, token_b_amount: felt
|
||||
) {
|
||||
alloc_locals;
|
||||
let (account_id) = get_caller_address();
|
||||
|
||||
modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_A,
|
||||
amount=token_a_amount);
|
||||
modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_B,
|
||||
amount=token_b_amount);
|
||||
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev intialize AMM
|
||||
// @param token_a amount of token a to be set in pool
|
||||
// @param token_b amount of token b to be set in pool
|
||||
@external
|
||||
func init_pool{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_a: felt, token_b: felt
|
||||
) {
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(token_a, POOL_UPPER_BOUND - 1);
|
||||
assert_nn_le(token_b, POOL_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
set_pool_token_balance(token_type=TOKEN_TYPE_A, balance=token_a);
|
||||
set_pool_token_balance(token_type=TOKEN_TYPE_B, balance=token_b);
|
||||
|
||||
return ();
|
||||
}
|
||||
|
||||
|
||||
// @dev swaps token between the given account and the pool
|
||||
// @param token_from token to be swapped
|
||||
// @param amount_from amount of token to be swapped
|
||||
// @return amount_to the token swapped to
|
||||
@external
|
||||
func swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
|
||||
token_from: felt, amount_from: felt
|
||||
) -> (amount_to: felt) {
|
||||
alloc_locals;
|
||||
let (account_id) = get_caller_address();
|
||||
|
||||
// verify token_from is TOKEN_TYPE_A or TOKEN_TYPE_B
|
||||
with_attr error_message("token not allowed in pool!"){
|
||||
assert (token_from - TOKEN_TYPE_A) * (token_from - TOKEN_TYPE_B) = 0;
|
||||
}
|
||||
|
||||
// check requested amount_from is valid
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(amount_from, BALANCE_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
// check user has enough funds
|
||||
let (account_from_balance) =
|
||||
get_account_token_balance(account_id=account_id, token_type=token_from);
|
||||
with_attr error_message("insufficient balance!"){
|
||||
assert_le(amount_from, account_from_balance);
|
||||
}
|
||||
|
||||
let (token_to) = get_opposite_token(token_type=token_from);
|
||||
let (amount_to) = do_swap(account_id=account_id, token_from=token_from,
|
||||
token_to=token_to, amount_from=amount_from);
|
||||
|
||||
return (amount_to=amount_to);
|
||||
}
|
||||
|
||||
|
||||
// INTERNALS
|
||||
//
|
||||
// @dev internal function that updates account balance for a given token
|
||||
// @param account_id Account whose balance is to be modified
|
||||
// @param token_type Token type to be modified
|
||||
// @param amount Amount Amount to be added
|
||||
func modify_account_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
account_id: felt, token_type: felt, amount: felt
|
||||
) {
|
||||
let (current_balance) = account_balance.read(account_id, token_type);
|
||||
tempvar new_balance = current_balance + amount;
|
||||
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(new_balance, BALANCE_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
account_balance.write(account_id=account_id, token_type=token_type,
|
||||
value=new_balance);
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev internal function that swaps tokens between the given account and
|
||||
// the pool
|
||||
// @param account_id Account whose tokens are to be swapped
|
||||
// @param token_from Token type to be swapped from
|
||||
// @param token_to Token type to be swapped to
|
||||
// @param amount_from Amount to be swapped
|
||||
func do_swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
account_id: felt, token_from: felt, token_to: felt, amount_from: felt
|
||||
) -> (amount_to: felt) {
|
||||
alloc_locals;
|
||||
|
||||
// get pool balance
|
||||
let (local amm_from_balance) = get_pool_token_balance(token_type =
|
||||
token_from);
|
||||
let (local amm_to_balance) = get_pool_token_balance(token_type=token_to);
|
||||
|
||||
// calculate swap amount
|
||||
let (local amount_to, _) = unsigned_div_rem((amm_to_balance *
|
||||
amount_from), (amm_from_balance + amount_from));
|
||||
|
||||
// update token_from balances
|
||||
modify_account_balance(account_id=account_id, token_type=token_from,
|
||||
amount=-amount_from);
|
||||
set_pool_token_balance(token_type=token_from, balance=(amm_from_balance
|
||||
+ amount_from));
|
||||
|
||||
// update token_to balances
|
||||
modify_account_balance(account_id=account_id, token_type=token_to,
|
||||
amount=amount_to);
|
||||
set_pool_token_balance(token_type=token_to, balance=(amm_to_balance -
|
||||
amount_to));
|
||||
|
||||
return (amount_to=amount_to);
|
||||
}
|
||||
|
||||
|
||||
// @dev internal function to get the opposite token type
|
||||
// @param token_type Token whose opposite pair needs to be gotten
|
||||
func get_opposite_token(token_type: felt) -> (t: felt) {
|
||||
if(token_type == TOKEN_TYPE_A) {
|
||||
return (t=TOKEN_TYPE_B);
|
||||
} else {
|
||||
return (t=TOKEN_TYPE_A);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
+ [Official documentation](https://www.cairo-lang.org/docs/)
|
||||
+ [Starknet EDU](https://medium.com/starknet-edu)
|
||||
+ [Journey through Cairo](https://medium.com/@darlingtonnnam/journey-through-cairo-i-setting-up-protostar-and-argentx-for-local-development-ba40ae6c5524)
|
||||
+ [Demystifying Cairo whitepaper](https://medium.com/@pban/demystifying-cairo-white-paper-part-i-b71976ad0108)
|
||||
+ [Learn about StarkNet with Argent](https://www.argent.xyz/learn/tag/starknet/)
|
||||
|
||||
## Development Frameworks
|
||||
|
||||
+ [Protostar](https://docs.swmansion.com/protostar/docs/tutorials/installation)
|
||||
+ [Nile](https://github.com/OpenZeppelin/nile)
|
||||
+ [StarkNet CLI](https://www.cairo-lang.org/docs/quickstart.html)
|
||||
|
||||
## Helpful Libraries
|
||||
|
||||
+ [Cairo-lang](https://github.com/starkware-libs/cairo-lang)
|
||||
+ [Openzeppelin](https://github.com/OpenZeppelin/cairo-contracts)
|
||||
|
||||
## Educational Repos
|
||||
|
||||
+ [StarkNet Cairo 101](https://github.com/starknet-edu/starknet-cairo-101)
|
||||
+ [StarkNet ERC721](https://github.com/starknet-edu/starknet-erc721)
|
||||
+ [StarkNet ERC20](https://github.com/starknet-edu/starknet-erc20)
|
||||
+ [L1 -> L2 Messaging](https://github.com/starknet-edu/starknet-messaging-bridge)
|
||||
+ [StarkNet Debug](https://github.com/starknet-edu/starknet-debug)
|
||||
+ [StarkNet Accounts](https://github.com/starknet-edu/starknet-accounts)
|
||||
+ [Min-Starknet](https://github.com/Darlington02/min-starknet)
|
||||
|
||||
## Security
|
||||
|
||||
+ [Amarna static analysis for Cairo programs](https://blog.trailofbits.com/2022/04/20/amarna-static-analysis-for-cairo-programs/)
|
||||
+ [Cairo and StarkNet security by Ctrl03](https://ctrlc03.github.io/)
|
||||
+ [How to hack almost any Cairo smart contract](https://medium.com/ginger-security/how-to-hack-almost-any-starknet-cairo-smart-contract-67b4681ac0f6)
|
||||
+ [Analyzing Cairo code using Armana](https://dic0de.substack.com/p/analyzing-cairo-code-using-amarna?sd=pf)
|
||||
|
||||
## Future TO-DOs
|
||||
|
||||
Update tutorial to fit Cairo 1.0
|
@ -68,7 +68,7 @@ False not. # True
|
||||
###########################################
|
||||
|
||||
# You may assign values to the current scope:
|
||||
var name is value. # assignes `value` into `name`
|
||||
var name is value. # assigns `value` into `name`
|
||||
|
||||
# You may also assign values into the current object's namespace
|
||||
my name is value. # assigns `value` into the current object's `name` property
|
||||
@ -146,7 +146,7 @@ add(3, 5). # 8
|
||||
|
||||
3 `add` 5. # 8
|
||||
# This call binds as such: add[(3), 5]
|
||||
# because the default fixity is left, and the default precedance is 1
|
||||
# because the default fixity is left, and the default precedence is 1
|
||||
|
||||
# You may change the precedence/fixity of this operator with a pragma
|
||||
#:declare infixr 1 add
|
||||
|
@ -412,7 +412,7 @@ Clojuredocs.org has documentation with examples for most core functions:
|
||||
[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
|
||||
|
||||
4Clojure is a great way to build your clojure/FP skills:
|
||||
[http://www.4clojure.com/](http://www.4clojure.com/)
|
||||
[https://4clojure.oxal.org/](https://4clojure.oxal.org/)
|
||||
|
||||
Clojure-doc.org (yes, really) has a number of getting started articles:
|
||||
[http://clojure-doc.org/](http://clojure-doc.org/)
|
||||
|
@ -14,7 +14,7 @@ organizations.
|
||||
*COBOL has significant differences between legacy (COBOL-85)
|
||||
*and modern (COBOL-2002 and COBOL-2014) versions.
|
||||
*Legacy versions require columns 1-6 to be blank (they are used
|
||||
*to store the index number of the punched card..)
|
||||
*to store the index number of the punched card).
|
||||
*A '*' in column 7 means a comment.
|
||||
*In legacy COBOL, a comment can only be a full line.
|
||||
*Modern COBOL doesn't require fixed columns and uses *> for
|
||||
@ -106,7 +106,7 @@ organizations.
|
||||
PROCEDURE DIVISION.
|
||||
FIRST-PARA.
|
||||
DISPLAY 'THIS IS IN FIRST-PARA'.
|
||||
PERFORM THIRD-PARA THRU FOURTH-PARA. *>skip second-para and perfrom 3rd & 4th
|
||||
PERFORM THIRD-PARA THRU FOURTH-PARA. *>skip second-para and perform 3rd & 4th
|
||||
*> then after performing third and fourth,
|
||||
*> return here and continue the program until STOP RUN.
|
||||
|
||||
@ -132,7 +132,7 @@ organizations.
|
||||
|
||||
*Now it is time to learn about two related COBOL verbs: string and unstring.
|
||||
|
||||
*The string verb is used to concatenate, or put together, two or more stings.
|
||||
*The string verb is used to concatenate, or put together, two or more strings.
|
||||
*Unstring is used, not surprisingly, to separate a
|
||||
*string into two or more smaller strings.
|
||||
*It is important that you remember to use ‘delimited by’ when you
|
||||
|
@ -4,6 +4,7 @@ filename: learncrystal.cr
|
||||
contributors:
|
||||
- ["Vitalii Elenhaupt", "http://veelenga.com"]
|
||||
- ["Arnaud Fernandés", "https://github.com/TechMagister/"]
|
||||
- ["Valentin Baca", "https://github.com/valbaca/"]
|
||||
|
||||
---
|
||||
|
||||
@ -64,24 +65,25 @@ true.class #=> Bool
|
||||
1.5e10.class #=> Float64
|
||||
1.5e-7.class #=> Float64
|
||||
|
||||
# Chars
|
||||
# Chars use 'a' pair of single quotes
|
||||
|
||||
'a'.class #=> Char
|
||||
|
||||
# Octal codepoint
|
||||
'\101' #=> 'A' : Char
|
||||
# Chars are 32-bit unicode
|
||||
'あ' #=> 'あ' : Char
|
||||
|
||||
# Unicode codepoint
|
||||
'\u0041' #=> 'A' : Char
|
||||
|
||||
# Strings
|
||||
# Strings use a "pair" of double quotes
|
||||
|
||||
"s".class #=> String
|
||||
|
||||
# Strings are immutable
|
||||
s = "hello, " #=> "hello, " : String
|
||||
s.object_id #=> 134667712 : UInt64
|
||||
s += "Crystal" #=> "hello, Crystal" : String
|
||||
s += "Crystal"
|
||||
s #=> "hello, Crystal" : String
|
||||
s.object_id #=> 142528472 : UInt64
|
||||
|
||||
# Supports interpolation
|
||||
@ -89,7 +91,8 @@ s.object_id #=> 142528472 : UInt64
|
||||
|
||||
# Multiline string
|
||||
"This is
|
||||
multiline string"
|
||||
multiline string" #=> "This is\n multiline string"
|
||||
|
||||
|
||||
# String with double quotes
|
||||
%(hello "world") #=> "hello \"world\""
|
||||
@ -110,7 +113,7 @@ sentence == "question?" #=> false : Bool
|
||||
# Arrays
|
||||
|
||||
[1, 2, 3].class #=> Array(Int32)
|
||||
[1, "hello", 'x'].class #=> Array(Int32 | String | Char)
|
||||
[1, "hello", 'x'].class #=> Array(Char | Int32 | String)
|
||||
|
||||
# Empty arrays should specify a type
|
||||
[] # Syntax error: for empty arrays use '[] of ElementType'
|
||||
@ -154,24 +157,24 @@ array.includes? 3 #=> true
|
||||
|
||||
# There is a special array syntax with other types too, as long as
|
||||
# they define a .new and a #<< method
|
||||
set = Set{1, 2, 3} #=> [1, 2, 3]
|
||||
set = Set{1, 2, 3} #=> Set{1, 2, 3}
|
||||
set.class #=> Set(Int32)
|
||||
|
||||
# The above is equivalent to
|
||||
set = Set(typeof(1, 2, 3)).new
|
||||
set << 1
|
||||
set << 2
|
||||
set << 3
|
||||
set = Set(typeof(1, 2, 3)).new #=> Set{} : Set(Int32)
|
||||
set << 1 #=> Set{1} : Set(Int32)
|
||||
set << 2 #=> Set{1, 2} : Set(Int32)
|
||||
set << 3 #=> Set{1, 2, 3} : Set(Int32)
|
||||
|
||||
# Hashes
|
||||
|
||||
{1 => 2, 3 => 4}.class #=> Hash(Int32, Int32)
|
||||
{1 => 2, 'a' => 3}.class #=> Hash(Int32 | Char, Int32)
|
||||
{1 => 2, 'a' => 3}.class #=> Hash(Char| Int32, Int32)
|
||||
|
||||
# Empty hashes should specify a type
|
||||
{} # Syntax error
|
||||
{} of Int32 => Int32 # {}
|
||||
Hash(Int32, Int32).new # {}
|
||||
# Empty hashes must specify a type
|
||||
{} # Syntax Error: for empty hashes use '{} of KeyType => ValueType'
|
||||
{} of Int32 => Int32 # {} : Hash(Int32, Int32)
|
||||
Hash(Int32, Int32).new # {} : Hash(Int32, Int32)
|
||||
|
||||
# Hashes can be quickly looked up by key
|
||||
hash = {"color" => "green", "number" => 5}
|
||||
@ -179,6 +182,9 @@ hash["color"] #=> "green"
|
||||
hash["no_such_key"] #=> Missing hash key: "no_such_key" (KeyError)
|
||||
hash["no_such_key"]? #=> nil
|
||||
|
||||
# The type of the returned value is based on all key types
|
||||
hash["number"] #=> 5 : (Int32 | String)
|
||||
|
||||
# Check existence of keys hash
|
||||
hash.has_key? "color" #=> true
|
||||
|
||||
@ -220,7 +226,7 @@ Range.new(1, 10).class #=> Range(Int32, Int32)
|
||||
# Access tuple's value by its index
|
||||
tuple = {:key1, :key2}
|
||||
tuple[1] #=> :key2
|
||||
tuple[2] #=> syntax error : Index out of bound
|
||||
tuple[2] #=> Error: index out of bounds for Tuple(Symbol, Symbol) (2 not in -2..1)
|
||||
|
||||
# Can be expanded into multiple variables
|
||||
a, b, c = {:a, 'b', "c"}
|
||||
@ -246,7 +252,7 @@ elsif false
|
||||
"else-if, optional"
|
||||
else
|
||||
"else, also optional"
|
||||
end
|
||||
end
|
||||
|
||||
puts "if as a suffix" if true
|
||||
|
||||
@ -314,7 +320,7 @@ if a < 3
|
||||
else
|
||||
a = true
|
||||
end
|
||||
typeof a #=> (Bool | String)
|
||||
typeof(a) #=> (Bool | String)
|
||||
|
||||
if a && b
|
||||
# here both a and b are guaranteed not to be Nil
|
||||
@ -388,15 +394,19 @@ dinner #=> "quesadilla"
|
||||
5.even? # false
|
||||
5.odd? # true
|
||||
|
||||
# And if a method ends with an exclamation mark, it does something destructive
|
||||
# like mutate the receiver. Some methods have a ! version to make a change, and
|
||||
# Also by convention, if a method ends with an exclamation mark, it does
|
||||
# something destructive like mutate the receiver.
|
||||
# Some methods have a ! version to make a change, and
|
||||
# a non-! version to just return a new changed version
|
||||
company_name = "Dunder Mifflin"
|
||||
company_name.gsub "Dunder", "Donald" #=> "Donald Mifflin"
|
||||
company_name #=> "Dunder Mifflin"
|
||||
company_name.gsub! "Dunder", "Donald"
|
||||
company_name #=> "Donald Mifflin"
|
||||
fruits = ["grapes", "apples", "bananas"]
|
||||
fruits.sort #=> ["apples", "bananas", "grapes"]
|
||||
fruits #=> ["grapes", "apples", "bananas"]
|
||||
fruits.sort! #=> ["apples", "bananas", "grapes"]
|
||||
fruits #=> ["apples", "bananas", "grapes"]
|
||||
|
||||
# However, some mutating methods do not end in !
|
||||
fruits.shift #=> "apples"
|
||||
fruits #=> ["bananas", "grapes"]
|
||||
|
||||
# Define a class with the class keyword
|
||||
class Human
|
||||
@ -404,7 +414,7 @@ class Human
|
||||
# A class variable. It is shared by all instances of this class.
|
||||
@@species = "H. sapiens"
|
||||
|
||||
# type of name is String
|
||||
# An instance variable. Type of name is String
|
||||
@name : String
|
||||
|
||||
# Basic initializer
|
||||
@ -469,9 +479,9 @@ class TestClass
|
||||
end
|
||||
# Variables that start with a capital letter are constants
|
||||
Var = "I'm a constant"
|
||||
Var = "can't be updated" # Already initialized constant Var
|
||||
Var = "can't be updated" # Error: already initialized constant Var
|
||||
|
||||
# Class is also an object in crystal. So class can have instance variables.
|
||||
# Class is also an object in Crystal. So a class can have instance variables.
|
||||
# Class variable is shared among the class and all of its descendants.
|
||||
|
||||
# base class
|
||||
|
@ -220,9 +220,11 @@ p { vlastnost: hodnota !important; }
|
||||
```
|
||||
|
||||
a tento element
|
||||
|
||||
```xml
|
||||
<p style='/*F*/ vlastnost:hodnota;' trida='trida1 trida2' attr='hodnota' />
|
||||
```
|
||||
|
||||
Priorita stylu je následující. Pamatujte, priorita pro každou **vlastnost**, ne pro celý blok.
|
||||
|
||||
* `E` má nejvyšší prioritu kvůli slůvku `!important`. Je doporučováno se úplně vyhnout jeho použití.
|
||||
|
@ -33,7 +33,7 @@ Go má již v základu vynikající knihovnu a je s ním spojená nadšená komu
|
||||
řádkový komentář */
|
||||
|
||||
// Každý zdroják začíná deklarací balíčku (package)
|
||||
// Main je vyhrazené jméno, které označuje spustitelný soubor,
|
||||
// main je vyhrazené jméno, které označuje spustitelný soubor,
|
||||
// narozdíl od knihovny
|
||||
package main
|
||||
|
||||
@ -90,7 +90,7 @@ může obsahovat nové řádky` // Opět typ řetězec.
|
||||
// Můžeme použít ne ASCII znaky, Go používá UTF-8.
|
||||
g := 'Σ' // type runa, což je alias na int32 a ukládá se do něj znak UTF-8
|
||||
|
||||
f := 3.14195 // float64, je IEEE-754 64-bit číslem s plovoucí čárkou.
|
||||
f := 3.14159 // float64, je IEEE-754 64-bit číslem s plovoucí čárkou.
|
||||
c := 3 + 4i // complex128, interně uložené jako dva float64.
|
||||
|
||||
// takhle vypadá var s inicializací
|
||||
@ -408,20 +408,20 @@ func requestServer() {
|
||||
|
||||
## Kam dále
|
||||
|
||||
Vše hlavní o Go se nachází na [oficiálních stránkách go](http://golang.org/).
|
||||
Vše hlavní o Go se nachází na [oficiálních stránkách go](https://go.dev/).
|
||||
Tam najdete tutoriály, interaktivní konzolu a mnoho materiálu ke čtení.
|
||||
Kromě úvodu, [dokumenty](https://golang.org/doc/) tam obsahují jak psát čistý kód v Go
|
||||
Kromě úvodu, [dokumenty](https://go.dev/doc/) tam obsahují jak psát čistý kód v Go
|
||||
popis balíčků (package), dokumentaci příkazové řádky a historii releasů.
|
||||
|
||||
Také doporučujeme přečíst si definici jazyka. Je čtivá a překvapivě krátká. Tedy alespoň proti
|
||||
jiným současným jazyků.
|
||||
|
||||
Pokud si chcete pohrát s Go, tak navštivte [hřiště Go](https://play.golang.org/p/r46YvCu-XX).
|
||||
Můžete tam spouštět programy s prohlížeče. Také můžete [https://play.golang.org](https://play.golang.org) použít jako
|
||||
Pokud si chcete pohrát s Go, tak navštivte [hřiště Go](https://go.dev/play/p/r46YvCu-XX).
|
||||
Můžete tam spouštět programy s prohlížeče. Také můžete [https://go.dev/play/](https://go.dev/play/) použít jako
|
||||
[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop), kde si v rychlosti vyzkoušíte věci, bez instalace Go.
|
||||
|
||||
Na vašem knižním seznamu, by neměly chybět [zdrojáky stadardní knihovny](http://golang.org/src/pkg/).
|
||||
Důkladně popisuje a dokumentuje Go, styl zápisu Go a Go idiomy. Pokud kliknete na [dokumentaci](http://golang.org/pkg/)
|
||||
Na vašem knižním seznamu, by neměly chybět [zdrojáky stadardní knihovny](https://go.dev/src/).
|
||||
Důkladně popisuje a dokumentuje Go, styl zápisu Go a Go idiomy. Pokud kliknete na [dokumentaci](https://go.dev/pkg/)
|
||||
tak se podíváte na dokumentaci.
|
||||
|
||||
Dalším dobrým zdrojem informací je [Go v ukázkách](https://gobyexample.com/).
|
||||
|
@ -5,44 +5,87 @@ contributors:
|
||||
- ["Dan Turkel", "http://danturkel.com/"]
|
||||
translators:
|
||||
- ["Michal Martinek", "https://github.com/MichalMartinek"]
|
||||
- ["Tomáš Hartman", "https://github.com/tomas-hartman"]
|
||||
filename: markdown-cz.md
|
||||
lang: cs-cz
|
||||
---
|
||||
|
||||
Markdown byl vytvořen Johnem Gruberem v roce 2004. Je zamýšlen jako lehce čitelná
|
||||
a psatelná syntaxe, která je jednoduše převeditelná do HTML (a dnes i do mnoha
|
||||
dalších formátů)
|
||||
Markdown byl vytvořen Johnem Gruberem v roce 2004 jako značkovací jazyk, který
|
||||
lze snadno číst a psát a který je možné jednoduše převést do HTML (a dnes i do
|
||||
mnoha dalších formátů).
|
||||
|
||||
Implementace markdownu se v různých parserech (syntaktických analyzátorech,
|
||||
které markdown dále zpracovávají) mírně odlišuje. V této příručce se snažíme
|
||||
upozorňovat, kdy se jedná o obecnou vlastnost markdownu a kdy se jedná o
|
||||
specifickou vlastnost daného parseru.
|
||||
|
||||
## Obsah
|
||||
|
||||
- [Obsah](#obsah)
|
||||
- [HTML Elementy](#html-elementy)
|
||||
- [Nadpisy](#nadpisy)
|
||||
- [Jednoduché stylování textu](#jednoduché-stylování-textu)
|
||||
- [Odstavce](#odstavce)
|
||||
- [Blokové citace](#blokové-citace)
|
||||
- [Seznamy](#seznamy)
|
||||
- [Bloky kódu](#bloky-kódu)
|
||||
- [Vodorovná čára (`<hr />`)](#vodorovná-čára-hr-)
|
||||
- [Odkazy](#odkazy)
|
||||
- [Obsahy](#obsahy)
|
||||
- [Obrázky](#obrázky)
|
||||
- [Ostatní](#ostatní)
|
||||
- [Automatické odkazy](#automatické-odkazy)
|
||||
- [Automatické odkazy z emailů](#automatické-odkazy-z-emailů)
|
||||
- [Escapování znaků](#escapování-znaků)
|
||||
- [Klávesové zkratky](#klávesové-zkratky)
|
||||
- [Tabulky](#tabulky)
|
||||
- [Markdownlint](#markdownlint)
|
||||
- [Reference](#reference)
|
||||
|
||||
## HTML Elementy
|
||||
|
||||
Markdown je nadstavba HTML. To znamená, že každý HTML kód je zároveň validním
|
||||
kódem v Markdownu.
|
||||
|
||||
```md
|
||||
<!-- Markdown je nadstavba nad HTML, takže jakýkoliv kód HTML je validní
|
||||
Markdown, to znamená, že můžeme používat HTML elementy, třeba jako komentář, a
|
||||
nebudou ovlivněny parserem Markdownu. Avšak, pokud vytvoříte HTML element v
|
||||
Markdownu, tak nemůžete používat syntaxi Markdownu uvnitř tohoto elementu. -->
|
||||
<!-- To znamená, že v Markdownu můžeme používat HTML elementy jako například
|
||||
komentáře, které nebudou ovlivněny parserem Markdownu. Na druhou stranu to také
|
||||
znamená, že pokud ve svém Markdown kódu vytvoříte HTML element, už v rámci
|
||||
tohoto elementu nelze použít Markdown.
|
||||
|
||||
<!-- Markdown se také mírně liší v jednotlivých interpretacích parseru. Tento
|
||||
návod vás bude upozorňovat, které vlastnosti jsou obecné a které specifické pro
|
||||
konkrétní parser. -->
|
||||
Markdown využívá i tato stránka, a tak by tento text, kdyby nebyl obalen v bloku
|
||||
kódu (viz níže), jako validní HTML komentář vůbec nebyl vidět. -->
|
||||
```
|
||||
|
||||
<!-- Nadpisy -->
|
||||
<!-- Můžete vytvořit HTML elementy <h1> až <h6> jednoduše tak, že text předsadíte
|
||||
počtem křížků (#), podle toho jaké úrovně to má být nadpis -->
|
||||
## Nadpisy
|
||||
|
||||
HTML elementy `<h1>` až `<h6>` vytvoříte jednoduše tak, že nadpisu předsadíte
|
||||
takový počet křížků (#), jaký odpovídá úrovni nadpisu.
|
||||
|
||||
```md
|
||||
# Toto je <h1>
|
||||
## Toto je <h2>
|
||||
### Toto je <h3>
|
||||
#### Toto je <h4>
|
||||
##### Toto je <h5>
|
||||
###### Toto je <h6>
|
||||
```
|
||||
|
||||
<!-- Markdown obsahuje taky dvě další cesty, jak udělat h1 a h2 -->
|
||||
Markdown obsahuje ještě dva další způsoby, jak vytvořit h1 a h2:
|
||||
|
||||
```md
|
||||
Toto je h1
|
||||
==========
|
||||
|
||||
Toto je h2
|
||||
----------
|
||||
```
|
||||
|
||||
<!-- Jednoduché stylování textu -->
|
||||
<!-- Pomocí markdownu můžete text jednoduše označit jako kurzívu či tučný -->
|
||||
## Jednoduché stylování textu
|
||||
|
||||
Pomocí markdownu můžete text jednoduše označit jako kurzívu či tučný text.
|
||||
|
||||
```md
|
||||
*Tento text je kurzívou;*
|
||||
_Stejně jako tento._
|
||||
|
||||
@ -50,47 +93,62 @@ _Stejně jako tento._
|
||||
__Stejně jako tento.__
|
||||
|
||||
***Tento text je obojí***
|
||||
**_Jako tento!_**
|
||||
*__A tento!__*
|
||||
**_Tak jako tento!_**
|
||||
*__Nebo tento!__*
|
||||
```
|
||||
|
||||
<!-- Ve verzi Markdownu od GitHubu, máme k dispozici taky prošktrnutí: -->
|
||||
Ve verzi Markdownu od GitHubu máme k dispozici také přeškrtnutí:
|
||||
|
||||
~~Tento text je prošktrnutý.~~
|
||||
```md
|
||||
~~Tento text je přeškrtnutý.~~
|
||||
```
|
||||
|
||||
<!-- Odstavce jsou jedna nebo více řádek textu, oddělených jednou nebo více prázdnými řádky. -->
|
||||
## Odstavce
|
||||
|
||||
Toto je odstavec. Píši odstavec, není to zábava?
|
||||
Odstavce tvoří jeden nebo více řádků textu, oddělených jedním nebo více
|
||||
prázdnými řádky.
|
||||
|
||||
```md
|
||||
Toto je odstavec. Zde jsem napsal odstavec a je to bezva!
|
||||
|
||||
Teď jsem v odstavci 2.
|
||||
Jsem pořád v odstavci 2!
|
||||
A tady jsem pořád v odstavci 2!
|
||||
|
||||
Ale tady už je odstavec 3.
|
||||
```
|
||||
|
||||
Toto je odstavec 3.
|
||||
|
||||
<!-- Chtěli jste někdy vložit znak <br /> tag? Můžete napsat na konec odstavce
|
||||
dvě nebo více mezer a potom začít nový odstavec. -->
|
||||
Pokud byste chtěli vložit HTML element `<br />`, můžete na konec odstavce napsat
|
||||
dvě nebo více mezer a potom začít nový odstavec.
|
||||
|
||||
```md
|
||||
Tento odstavec končí dvěma mezerami.
|
||||
|
||||
Nad tímto odstavcem je <br />!
|
||||
Nad tímto odstavcem je <br />!
|
||||
```
|
||||
|
||||
<!-- Blokové citace se dělají jednoduše pomocí znaku >. -->
|
||||
### Blokové citace
|
||||
|
||||
Blokové citace se dělají jednoduše uvozením řádku znakem >.
|
||||
|
||||
```md
|
||||
> Toto je bloková citace. Můžete dokonce
|
||||
> manuálně rozdělit řádky, a před každý vložit >, nebo nechat vaše řádky jakkoliv dlouhé, ať se zarovnají sami.
|
||||
> Nedělá to rozdíl, dokud začínáte vždy znakem >.
|
||||
> manuálně rozdělit řádky, a před každý vložit >, nebo nechat vaše řádky
|
||||
> jakkoli dlouhé, ať se zarovnají samy.
|
||||
> Je to jedno, pokud vždy začínají symbolem `>`.
|
||||
|
||||
> Můžu použít více než jednu
|
||||
>> odsazení?
|
||||
> Jak je to úhledné, že?
|
||||
> Použít můžu i více než jednu úroveň
|
||||
>> odsazení.
|
||||
> Co vy na to?
|
||||
```
|
||||
|
||||
<!-- Seznamy -->
|
||||
<!-- Nečíslovaný seznam můžete jednoduše udělat pomocí hvězdiček, plusů, nebo
|
||||
pomlček -->
|
||||
## Seznamy
|
||||
|
||||
Nečíslovaný seznam můžete jednoduše udělat pomocí hvězdiček, plusů nebo pomlček:
|
||||
|
||||
```md
|
||||
* Položka
|
||||
* Položka
|
||||
* Jinná položka
|
||||
* Jiná položka
|
||||
|
||||
nebo
|
||||
|
||||
@ -103,158 +161,248 @@ nebo
|
||||
- Položka
|
||||
- Položka
|
||||
- Další položka
|
||||
```
|
||||
|
||||
<!-- Číslovaný seznam se dělají pomocí čísla a . -->
|
||||
Číslované seznamy se dělají pomocí číslice a `.`.
|
||||
|
||||
```md
|
||||
1. Položka jedna
|
||||
2. Položka dvě
|
||||
3. Položka tři
|
||||
|
||||
<!-- Nemusíte dokonce psát čísla správně a markdown je zobrazi správně,
|
||||
ale nemusí to být vždy dobrý nápad -->
|
||||
<!-- Čísla ani nemusíte psát popořadě. Markdown je umí zobrazit správně, jenom
|
||||
je třeba vždy překontrolovat, že číslování funguje správně. -->
|
||||
|
||||
1. Položka jedna
|
||||
1. Položka dvě
|
||||
1. Položka tři
|
||||
<!-- (Toto zobrazí to samě, jako příklad nadtím.) -->
|
||||
|
||||
<!-- Můžete také tvořit podseznamy -->
|
||||
<!-- (Toto zobrazí to samé, jako příklad nad tím.) -->
|
||||
```
|
||||
|
||||
Můžete také tvořit podseznamy:
|
||||
|
||||
```md
|
||||
1. Položka jedna
|
||||
2. Položka dvě
|
||||
3. Položka tři
|
||||
* Podpoložka
|
||||
* Podpoložka
|
||||
- Podpoložka
|
||||
- Podpoložka
|
||||
4. Položka čtyři
|
||||
```
|
||||
|
||||
<!-- Existují i zašktávací seznamy. Toto vytvoří HTML checkboxy. -->
|
||||
Vytvořit lze i zaškrtávací seznamy. Takto lze vytvořit seznam s HTML checkboxy.
|
||||
(Boxy níže bez 'x' jsou nezaškrtnuté checkboxy.)
|
||||
|
||||
Boxy níže bez 'x' jsou nezašktrnuté checkboxy.
|
||||
- [ ] První úkol
|
||||
- [ ] Druhý úkol
|
||||
Tento box bude zašktrnutý
|
||||
```md
|
||||
- [ ] První úkol, který je třeba dokončit
|
||||
- [ ] Druhý úkol na dodělání
|
||||
Tento box bude zaškrtnutý
|
||||
- [x] Tento úkol byl dokončen
|
||||
```
|
||||
|
||||
<!-- Bloky ködu -->
|
||||
<!-- Můžete označit kód bloku (který používá <code> element) odsazením pomocí 4
|
||||
mezer, nebo tabu -->
|
||||
## Bloky kódu
|
||||
|
||||
Bloky kódu můžete označit tak, že řádek odsadíte čtyřmi mezerami nebo pomocí
|
||||
tabu. Pro interpretaci kódu parser používá `<code>` element.
|
||||
|
||||
```md
|
||||
Toto je kód
|
||||
Stejně jako toto
|
||||
```
|
||||
|
||||
<!-- Můžete dokonce přidat další 4 mezery nebo tab pro další odsazení -->
|
||||
Pro ještě hlubší odsazení můžete přidat další 4 mezery nebo další tab:
|
||||
|
||||
```md
|
||||
moje_pole.each do |i|
|
||||
puts i
|
||||
puts i
|
||||
end
|
||||
```
|
||||
|
||||
<!-- Kód na řádku může být označen pomocí zpětných apostrofů ` -->
|
||||
Jednořádkový kód můžete zabalit do dvou zpětných apostrofů (`) tak, jako
|
||||
kdybyste text normálně stylovali:
|
||||
|
||||
Jan nevědel, jak se dělá `go_to()` funkce!
|
||||
```md
|
||||
Honza neměl tušení, co dělá funkce `go_to()`!
|
||||
```
|
||||
|
||||
<!-- V Markdownu od GitHubu , můžete použít speciální syntaxi pro kód -->
|
||||
V Markdownu od GitHubu, můžete použít speciální syntaxi pro kód:
|
||||
|
||||
\`\`\`ruby <!-- vyjma zpětných lomítek, jenom ```ruby ! -->
|
||||
````md
|
||||
```ruby
|
||||
def neco
|
||||
puts "Ahoj světe!"
|
||||
puts "Ahoj světe!"
|
||||
end
|
||||
\`\`\` <!-- zde taky, žádné zpětná lomítka, pouze ``` -->
|
||||
```
|
||||
````
|
||||
|
||||
<!-- Text výše nepotřebuje odsazení a navíc GitHub použije zvýraznění označeného
|
||||
jazyka. -->
|
||||
Text výše nepotřebuje čtyřmezerové odsazení a parser navíc použije zvýraznění
|
||||
syntaxe pro zvolený jazyk.
|
||||
|
||||
<!-- Horizontální čára (<hr />) -->
|
||||
<!-- Horizontální čára se jednoduše přidá pomocí 3 nebo více hvězdiček nebo pomlček
|
||||
s nebo bez mezer. -->
|
||||
## Vodorovná čára (`<hr />`)
|
||||
|
||||
Vodorovnou oddělovací čáru lze snadno přidat pomocí 3 nebo více hvězdiček (nebo
|
||||
pomlček), a to buď s mezerami mezi jednotlivými znaky, nebo bez nich.
|
||||
|
||||
```md
|
||||
***
|
||||
---
|
||||
- - -
|
||||
****************
|
||||
```
|
||||
|
||||
<!-- Odkazy -->
|
||||
<!-- Jedna z nejlepších věcí na Markdownu je, jak jednoduše se dělají odkazy.
|
||||
Dejte text, který chcete zobrazit, do [] následovaný url v závorkách () a je to. -->
|
||||
## Odkazy
|
||||
|
||||
```md
|
||||
<!-- Jedna z nejlepších vlastností Markdownu je, jak snadno lze s jeho pomocí
|
||||
vytvářet odkazy. Text odkazu, který chcete zobrazit vložte do [] a hned za něj
|
||||
v kulatých závorkách () připojte url adresu. -->
|
||||
|
||||
[Klikni na mě!](http://test.com/)
|
||||
|
||||
<!-- Můžete také přidat jméno linku pomocí uvozovek -->
|
||||
|
||||
<!-- V uvozovkách za url můžete přidat název odkazu -->
|
||||
|
||||
[Klikni na mě!](http://test.com/ "Odkaz na Test.com")
|
||||
|
||||
<!-- Relativní cesty fungují taky -->
|
||||
|
||||
<!-- Relativní cesty fungují také -->
|
||||
|
||||
[Jdi na hudbu](/hudba/).
|
||||
|
||||
<!-- Markdown taktéž podporuje reference odkazů. -->
|
||||
|
||||
<!-- Markdown taktéž podporuje referenční odkazy -->
|
||||
|
||||
[Klikni na tento odkaz][link1] pro více informací!
|
||||
[Taky zkontrolujte tento odkaz][neco], když chcete.
|
||||
[Taky zkontrolujte tento odkaz][neco], jestli tedy chcete.
|
||||
|
||||
[link1]: http://test.com/ "Cool!"
|
||||
[neco]: http://neco.czz/ "Dobře!"
|
||||
|
||||
<!-- Titulek může být v apostrofech nebo závorkách, nebo vyjmutý úplně. Reference
|
||||
může být kdekoliv ve vašem dokumentu a identifikátor může být jakýkoliv, dokud
|
||||
je unikátní.-->
|
||||
<!-- Titulek v tomto případě může být v jednoduchých uvozovkách, závorkách, nebo
|
||||
zcela vynechaný. Reference může být kdekoliv ve vašem dokumentu a identifikátory
|
||||
mohou být jakékoli, pokud jsou unikátní. -->
|
||||
|
||||
<!-- Také existuje "implicitní pojmenování", které použije text jako id -->
|
||||
|
||||
<!-- V markdownu existuje rovněž "implicitní pojmenování", které použije text
|
||||
odkazu jako své id -->
|
||||
|
||||
[Toto][] je odkaz..
|
||||
|
||||
[toto]: http://totojelink.cz/
|
||||
|
||||
<!-- Ale toto není zrovna běžné užívané. -->
|
||||
<!-- Ale tento způsob se obvykle nepoužívá. -->
|
||||
```
|
||||
|
||||
<!-- Obrázky -->
|
||||
<!-- Obrázky se dělají stejně jako odkazy, ale s vykřičníkem na začátku -->
|
||||
### Obsahy
|
||||
|
||||
Kombinace seznamů, odkazů a nadpisů využívají také některé parsery pro
|
||||
generování obsahu Markdown souborů. Jako identifikátory slouží jména nadpisů
|
||||
psané malými písmeny, které jsou uvozené křížkem (`#`). Víceslovné nadpisy
|
||||
bývají propojeny pomlčkou (`-`), která někdy nahrazuje i speciální znaky. Jiné
|
||||
speciální znaky mohou být vynechány.
|
||||
|
||||
```md
|
||||
- [Nadpis](#nadpis)
|
||||
- [Víceslovný text](#víceslovný-text)
|
||||
- [Odstavce](#odstavce)
|
||||
- [Podkapitola <h3 />](#podkapitola-h3-)
|
||||
```
|
||||
|
||||
V případě obsahů se v každém případě jedná o nadstavbu, která nemusí všude
|
||||
fungovat stejně.
|
||||
|
||||
## Obrázky
|
||||
|
||||
```md
|
||||
<!-- Obrázky se vytváří stejně jako odkazy, ale s vykřičníkem na začátku -->
|
||||
|
||||
![Toto je atribut alt pro obrázek](http://imgur.com/myimage.jpg "Nepovinný titulek")
|
||||
|
||||
<!-- Reference fungují, jak bychom čekali-->
|
||||
<!-- Reference fungují tak, jak bychom čekali -->
|
||||
|
||||
![Toto je atribut alt][mujobrazek]
|
||||
|
||||
[mujobrazek]: relativni/cesta/obrazek.jpg "a toto by byl titulek"
|
||||
```
|
||||
|
||||
<!-- Ostatní -->
|
||||
<!-- Automatické odkazy -->
|
||||
## Ostatní
|
||||
|
||||
### Automatické odkazy
|
||||
|
||||
```md
|
||||
<http://stranka.cz/>
|
||||
|
||||
je stejné jako
|
||||
|
||||
<http://stranka.cz/> je stejná jako
|
||||
[http://stranka.cz/](http://stranka.cz/)
|
||||
```
|
||||
|
||||
<!-- Automatické odkazy pro emaily-->
|
||||
### Automatické odkazy z emailů
|
||||
|
||||
```md
|
||||
<jmeno@prijmeni.cz>
|
||||
```
|
||||
|
||||
<!-- Escapování znaků -->
|
||||
### Escapování znaků
|
||||
|
||||
Chci napsat *tento text obklopený hvězdičkami*, ale nechci aby to bylo kurzívou, tak udělám: \*tento text obklopený hvězdičkami\*.
|
||||
```md
|
||||
Chci napsat *tento text obklopený hvězdičkami*, ale protože nechci, aby to bylo
|
||||
kurzívou, tak hvězdičky vyescapuji `\`: \*tento text bude obklopený hvězdičkami\*.
|
||||
```
|
||||
|
||||
<!-- Klávesové zkratky -->
|
||||
<!-- V Markdownu od GitHubu, můžete použít tag <kbd> k reprezentování klaves na počítači -->
|
||||
### Klávesové zkratky
|
||||
|
||||
```md
|
||||
<!-- V Markdownu od GitHubu můžete použít tag <kbd> k označení kláves na
|
||||
počítači -->
|
||||
|
||||
Váš počítač přestal pracovat? Zkuste
|
||||
<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd>
|
||||
```
|
||||
|
||||
<!-- Tabulky -->
|
||||
<!-- Tabulky jsou povolené pouze v Markdownu od GitHubu a jsou trochu podivně,
|
||||
ale když je opravdu chcete: -->
|
||||
### Tabulky
|
||||
|
||||
Tabulky lze využít pouze v Markdownu od GitHubu a jejich syntax je trošku
|
||||
zvláštní. Kdybyste je chtěli použít, vytváří se takto:
|
||||
|
||||
```md
|
||||
| Sloupec1 | Sloupec2 | Sloupec3 |
|
||||
| :----------- | :------: | ------------: |
|
||||
| Vlevo zarovn.| Na střed | Vpravo zarovn.|
|
||||
| blah | blah | blah |
|
||||
|
||||
<!-- nebo, to jde i taky: -->
|
||||
<!-- nebo je jde taky zapsat takto: -->
|
||||
|
||||
Sloupec 1 | Sloupec2 | Sloupec3
|
||||
:-- | :-: | --:
|
||||
Ohh toto je tak ošklivé | radši to | nedělejte
|
||||
|
||||
<!-- Konec -->
|
||||
|
||||
Že se to nedá číst? | No tak to takhle | radši nedělejte.
|
||||
```
|
||||
|
||||
Pro více informací, prozkoumejte oficiální článek o syntaxi od Johna Grubera
|
||||
[zde](http://daringfireball.net/projects/markdown/syntax) a skvělý tahák od Adama Pritcharda [zde](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
|
||||
## Markdownlint
|
||||
|
||||
Pro usnadnění práce s Markdownem a s cílem sjednotit styl psaní jeho kódu vznikl
|
||||
nástroj `Markdownlint`. Tento nástroj je dostupný i jako plugin pro některé
|
||||
editory kódu (IDE) a lze jej použít jako nástroj pro vytváření a ověřování
|
||||
validity a čitelnosti Markdownu kódu.
|
||||
|
||||
---
|
||||
|
||||
## Reference
|
||||
|
||||
Pro více informací doporučujeme oficiální článek o syntaxi od Johna Grubera
|
||||
[zde](http://daringfireball.net/projects/markdown/syntax) a skvělý tahák od
|
||||
Adama Pritcharda [zde](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
|
||||
|
||||
---
|
||||
|
||||
> _Pozn. překladatele:_ Tento text vznikl jako překlad původního článku, který
|
||||
> pochází z roku 2013 a kombinace původního českého překladu z roku 2015.
|
||||
> Některé informace v tomto článku, zejména ty, týkající se specifických
|
||||
> vlastností parserů markdownu tak již dnes mohou být zastaralé.
|
||||
|
||||
Aktuální informace o specifických vlastnostech různých implementací Markdownu
|
||||
můžete nalézt zde (v angličtině):
|
||||
|
||||
- [Markdown pro GitHub](https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)
|
||||
- [Markdown pro GitLab](https://docs.gitlab.com/ee/user/markdown.html)
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: c#
|
||||
language: C#
|
||||
contributors:
|
||||
- ["Irfan Charania", "https://github.com/irfancharania"]
|
||||
- ["Max Yankov", "https://github.com/golergka"]
|
||||
@ -12,9 +12,9 @@ contributors:
|
||||
filename: LearnCSharp.cs
|
||||
---
|
||||
|
||||
C# is an elegant and type-safe object-oriented language that enables developers to build a variety of secure and robust applications that run on the .NET Framework.
|
||||
C# is an elegant and type-safe object-oriented language that enables developers to build a variety of secure and robust applications that run on the cross-platform .NET framework.
|
||||
|
||||
[Read more here.](https://docs.microsoft.com/dotnet/csharp/getting-started/introduction-to-the-csharp-language-and-the-net-framework)
|
||||
[Read more here.](https://docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/)
|
||||
|
||||
```c#
|
||||
// Single-line comments start with //
|
||||
@ -29,7 +29,7 @@ Multi-line comments look like this
|
||||
/// </summary>
|
||||
/// <param name="firstParam">This is some parameter documentation for firstParam</param>
|
||||
/// <returns>Information on the returned value of a function</returns>
|
||||
public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {}
|
||||
public void MethodOrClassOrOtherWithParsableHelp(string firstParam) { }
|
||||
|
||||
// Specify the namespaces this source code will be using
|
||||
// The namespaces below are all part of the standard .NET Framework Class Library
|
||||
@ -48,6 +48,10 @@ using System.Data.Entity;
|
||||
|
||||
// Namespaces define scope to organize code into "packages" or "modules"
|
||||
// Using this code from another source file: using Learning.CSharp;
|
||||
|
||||
// You can also do this in C# 10, it is called file-scoped namespaces.
|
||||
// namespace Learning.CSharp;
|
||||
|
||||
namespace Learning.CSharp
|
||||
{
|
||||
// Each .cs file should at least contain a class with the same name as the file.
|
||||
@ -154,7 +158,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
|
||||
// Arrays - zero indexed
|
||||
// The array size must be decided upon declaration
|
||||
// The format for declaring an array is follows:
|
||||
// The format for declaring an array is
|
||||
// <datatype>[] <var name> = new <datatype>[<array size>];
|
||||
int[] intArray = new int[10];
|
||||
|
||||
@ -168,7 +172,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
|
||||
// Lists
|
||||
// Lists are used more frequently than arrays as they are more flexible
|
||||
// The format for declaring a list is follows:
|
||||
// The format for declaring a list is
|
||||
// List<datatype> <var name> = new List<datatype>();
|
||||
List<int> intList = new List<int>();
|
||||
List<string> stringList = new List<string>();
|
||||
@ -178,14 +182,14 @@ on a new line! ""Wow!"", the masses cried";
|
||||
// Lists don't default to a value;
|
||||
// A value must be added before accessing the index
|
||||
intList.Add(1);
|
||||
Console.WriteLine("intList @ 0: " + intList[0]);
|
||||
Console.WriteLine("intList at 0: " + intList[0]);
|
||||
|
||||
// Others data structures to check out:
|
||||
// Other data structures to check out:
|
||||
// Stack/Queue
|
||||
// Dictionary (an implementation of a hash map)
|
||||
// HashSet
|
||||
// Read-only Collections
|
||||
// Tuple (.Net 4+)
|
||||
// Tuple (.NET 4+)
|
||||
|
||||
///////////////////////////////////////
|
||||
// Operators
|
||||
@ -218,20 +222,20 @@ on a new line! ""Wow!"", the masses cried";
|
||||
| Bitwise inclusive OR
|
||||
*/
|
||||
|
||||
// Incrementations
|
||||
// Incrementing
|
||||
int i = 0;
|
||||
Console.WriteLine("\n->Inc/Dec-rementation");
|
||||
Console.WriteLine(i++); //Prints "0", i = 1. Post-Incrementation
|
||||
Console.WriteLine(++i); //Prints "2", i = 2. Pre-Incrementation
|
||||
Console.WriteLine(i--); //Prints "2", i = 1. Post-Decrementation
|
||||
Console.WriteLine(--i); //Prints "0", i = 0. Pre-Decrementation
|
||||
Console.WriteLine("\n->Inc/Dec-rement");
|
||||
Console.WriteLine(i++); //Prints "0", i = 1. Post-Increment
|
||||
Console.WriteLine(++i); //Prints "2", i = 2. Pre-Increment
|
||||
Console.WriteLine(i--); //Prints "2", i = 1. Post-Decrement
|
||||
Console.WriteLine(--i); //Prints "0", i = 0. Pre-Decrement
|
||||
|
||||
///////////////////////////////////////
|
||||
// Control Structures
|
||||
///////////////////////////////////////
|
||||
Console.WriteLine("\n->Control Structures");
|
||||
|
||||
// If statements are c-like
|
||||
// If statements are C-like
|
||||
int j = 10;
|
||||
if (j == 10)
|
||||
{
|
||||
@ -284,7 +288,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
// For Each Loop
|
||||
// foreach loop structure => foreach(<iteratorType> <iteratorName> in <enumerable>)
|
||||
// The foreach loop loops over any object implementing IEnumerable or IEnumerable<T>
|
||||
// All the collection types (Array, List, Dictionary...) in the .Net framework
|
||||
// All the collection types (Array, List, Dictionary...) in the .NET framework
|
||||
// implement one or both of these interfaces.
|
||||
// (The ToCharArray() could be removed, because a string also implements IEnumerable)
|
||||
foreach (char character in "Hello World".ToCharArray())
|
||||
@ -293,7 +297,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
}
|
||||
|
||||
// Switch Case
|
||||
// A switch works with the byte, short, char, and int data types.
|
||||
// A switch works with byte, short, char, and int data types.
|
||||
// It also works with enumerated types (discussed in Enum Types),
|
||||
// the String class, and a few special classes that wrap
|
||||
// primitive types: Character, Byte, Short, and Integer.
|
||||
@ -312,7 +316,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
break;
|
||||
// You can assign more than one case to an action
|
||||
// But you can't add an action without a break before another case
|
||||
// (if you want to do this, you would have to explicitly add a goto case x
|
||||
// (if you want to do this, you would have to explicitly add a goto case x)
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
@ -333,16 +337,25 @@ on a new line! ""Wow!"", the masses cried";
|
||||
// this will throw a FormatException on failure
|
||||
int.Parse("123"); // returns an integer version of "123"
|
||||
|
||||
// try parse will default to type default on failure
|
||||
// in this case: 0
|
||||
// TryParse will default to the type's default value on failure
|
||||
// in this case 0
|
||||
int tryInt;
|
||||
if (int.TryParse("123", out tryInt)) // Function is boolean
|
||||
Console.WriteLine(tryInt); // 123
|
||||
|
||||
// Convert Integer To String
|
||||
// Convert class has a number of methods to facilitate conversions
|
||||
// The Convert class has a number of methods to facilitate conversions
|
||||
|
||||
// String to int
|
||||
|
||||
// Better
|
||||
bool result = int.TryParse(string, out var integer)
|
||||
int.Parse(string);
|
||||
|
||||
// Not recommended
|
||||
Convert.ToString(123);
|
||||
// or
|
||||
|
||||
// Int to string
|
||||
tryInt.ToString();
|
||||
|
||||
// Casting
|
||||
@ -375,6 +388,9 @@ on a new line! ""Wow!"", the masses cried";
|
||||
Console.Read();
|
||||
} // End main method
|
||||
|
||||
// Available in C# 9 and later, this is basically syntactic sugar for a class. Records are immutable*.
|
||||
public record ARecord(string Csharp);
|
||||
|
||||
// CONSOLE ENTRY - A console application must have a main method as an entry point
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
@ -412,7 +428,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
|
||||
// GENERICS
|
||||
// The classes for TKey and TValue is specified by the user calling this function.
|
||||
// This method emulates the SetDefault of Python
|
||||
// This method emulates Python's dict.setdefault()
|
||||
public static TValue SetDefault<TKey, TValue>(
|
||||
IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
@ -744,7 +760,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
Gitane // 43
|
||||
}
|
||||
// We defined this type inside a Bicycle class, so it is a nested type
|
||||
// Code outside of this class should reference this type as Bicycle.Brand
|
||||
// Code outside of this class should reference this type as Bicycle.BikeBrand
|
||||
|
||||
public BikeBrand Brand; // After declaring an enum type, we can declare the field of this type
|
||||
|
||||
@ -1299,16 +1315,27 @@ namespace Csharp7
|
||||
```
|
||||
|
||||
## Topics Not Covered
|
||||
✨ New, 👍 Old, 🎈 LTS, 🔥 Cross-platform, 🎁 Windows-only
|
||||
|
||||
* Attributes
|
||||
* async/await
|
||||
|
||||
* Asynchronous Programming
|
||||
|
||||
* Web Development
|
||||
* ASP.NET MVC & WebApi (new)
|
||||
* ASP.NET Web Forms (old)
|
||||
* WebMatrix (tool)
|
||||
* ASP.NET Core ✨
|
||||
|
||||
* Desktop Development
|
||||
* Windows Presentation Foundation (WPF) (new)
|
||||
* Winforms (old)
|
||||
* Windows Presentation Foundation 👍 🎈 🎁
|
||||
* Universal Windows Platform ✨ 🎁
|
||||
* Uno Platform 🔥 ✨
|
||||
* WinForms 👍 🎈 🎁
|
||||
* Avalonia 🔥 ✨
|
||||
* WinUI ✨ 🎁
|
||||
|
||||
* Cross-platform Development
|
||||
* Xamarin.Forms 👍
|
||||
* MAUI ✨
|
||||
|
||||
|
||||
## Further Reading
|
||||
|
||||
@ -1321,4 +1348,4 @@ namespace Csharp7
|
||||
* [LINQ Pocket Reference](http://shop.oreilly.com/product/9780596519254.do)
|
||||
* [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208)
|
||||
* [freeCodeCamp - C# Tutorial for Beginners](https://www.youtube.com/watch?v=GhQdlIFylQ8)
|
||||
|
||||
|
||||
|
@ -102,19 +102,24 @@ div.some-parent.class-name { }
|
||||
/* There are some selectors called pseudo classes that can be used to select an
|
||||
element only when it is in a particular state */
|
||||
|
||||
/* for example, when the cursor hovers over an element */
|
||||
selector:hover { }
|
||||
/* for example, when a link hasn't been visited */
|
||||
selected:link { }
|
||||
|
||||
/* or a link has been visited */
|
||||
selector:visited { }
|
||||
|
||||
/* or hasn't been visited */
|
||||
selected:link { }
|
||||
|
||||
/* or an element is in focus */
|
||||
selected:focus { }
|
||||
|
||||
/* any element that is the first child of its parent */
|
||||
/* or when the cursor hovers over an element */
|
||||
selector:hover { }
|
||||
|
||||
/* or when a link is clicked on */
|
||||
selector:active { }
|
||||
|
||||
/* These pseudo classes regarding links should always be written in the above order or the code might not work as expected */
|
||||
|
||||
/* Any element that is the first child of its parent */
|
||||
selector:first-child {}
|
||||
|
||||
/* any element that is the last child of its parent */
|
||||
|
551
cue.html.markdown
Normal file
551
cue.html.markdown
Normal file
@ -0,0 +1,551 @@
|
||||
---
|
||||
name: CUE
|
||||
category: language
|
||||
language: CUE
|
||||
filename: learncue.cue
|
||||
contributors:
|
||||
- ["Daniel Cox", "https://github.com/danielpcox"]
|
||||
- ["Coleman McFarland", "https://github.com/dontlaugh"]
|
||||
---
|
||||
|
||||
CUE is an expressive (but not Turing-complete) JSON superset, exportable to JSON or YAML. It supports optional types and many other conveniences for working with large configuration sets. The unification engine has roots in logic programming, and as such it provides a ready solution to modern configuration management problems.
|
||||
|
||||
When CUE is exported to JSON, values from every processed file are unified into one giant object. Consider these two files:
|
||||
|
||||
```yaml
|
||||
//name.cue
|
||||
name: "Daniel"
|
||||
```
|
||||
|
||||
```yaml
|
||||
//disposition.cue
|
||||
disposition: "oblivious"
|
||||
```
|
||||
|
||||
Now we can unify and export to JSON:
|
||||
```bash
|
||||
% cue export name.cue disposition.cue
|
||||
{
|
||||
"name": "Daniel",
|
||||
"disposition": "oblivious"
|
||||
}
|
||||
```
|
||||
|
||||
Or YAML:
|
||||
```bash
|
||||
% cue export --out yaml name.cue disposition.cue
|
||||
name: Daniel
|
||||
disposition: oblivious
|
||||
```
|
||||
|
||||
Notice the C-style comments are not in the output. Also notice that the keys in CUE syntax did not require quotes. Some special characters do require quotes:
|
||||
|
||||
```yaml
|
||||
works_fine: true
|
||||
"needs-quotes": true
|
||||
```
|
||||
|
||||
Unification doesn't just unify across files, it is also a *global merge* of all types and values. The following fails, because the *types* are different.
|
||||
|
||||
```yaml
|
||||
//string_value.cue
|
||||
foo: "baz"
|
||||
```
|
||||
|
||||
```yaml
|
||||
//integer_value.cue
|
||||
foo: 100
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export string_value.cue integer_value.cue
|
||||
foo: conflicting values "baz" and 100 (mismatched types string and int):
|
||||
integer_value.cue:1:6
|
||||
string_value.cue:1:6
|
||||
```
|
||||
|
||||
But even if we quote the integer, it still fails, because the *values* conflict and there is no way to unify everything into a top-level object.
|
||||
|
||||
```yaml
|
||||
//string_value.cue
|
||||
foo: "baz"
|
||||
```
|
||||
|
||||
```yaml
|
||||
//integer_value.cue
|
||||
foo: "100" // a string now
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export string_value.cue integer_value.cue
|
||||
foo: conflicting values "100" and "baz":
|
||||
integer_value.cue:1:6
|
||||
string_value.cue:1:6
|
||||
```
|
||||
|
||||
Types in CUE *are* values; special ones that the unification engine knows have certain behavior relative to other values. During unification it requires that values match the specified types, and when concrete values are required, you will get an error if there's only a type. So this is fine:
|
||||
|
||||
```yaml
|
||||
street: "1 Infinite Loop"
|
||||
street: string
|
||||
```
|
||||
|
||||
While `cue export` produces YAML or JSON, `cue eval` produces CUE. This is useful for converting YAML or JSON to CUE, or for inspecting the unified output in CUE itself. It's fine to be missing concrete values in CUE (though it prefers concrete values when emitting CUE when both are available and match),
|
||||
|
||||
```yaml
|
||||
//type-only.cue
|
||||
amount: float
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue eval type-only.cue
|
||||
amount: float
|
||||
```
|
||||
|
||||
but you *need* concrete values if you want to export (or if you tell `eval` to require them with `-c`):
|
||||
|
||||
```bash
|
||||
% cue export type-only.cue
|
||||
amount: incomplete value float
|
||||
```
|
||||
|
||||
Give it a value that unifies with the type, and all is well.
|
||||
|
||||
```yaml
|
||||
//concrete-value.cue
|
||||
amount: 3.14
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export type-only.cue concrete-value.cue
|
||||
{
|
||||
"amount": 3.14
|
||||
}
|
||||
```
|
||||
|
||||
The method of unifying concrete values with types that share a common syntax is very powerful, and much more compact than, e.g., JSON Schema. This way, schema, defaults, and data are all expressible in CUE.
|
||||
|
||||
Default values may be supplied with a type using an asterisk:
|
||||
|
||||
```yaml
|
||||
// default-port.cue
|
||||
port: int | *8080
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue eval default-port.cue
|
||||
port: 8080
|
||||
```
|
||||
|
||||
Enum-style options ("disjunctions" in CUE) may be specified with an `|` separator:
|
||||
|
||||
```yaml
|
||||
//severity-enum.cue
|
||||
severity: "high" | "medium" | "low"
|
||||
severity: "unknown"
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue eval severity-enum.cue
|
||||
severity: 3 errors in empty disjunction:
|
||||
severity: conflicting values "high" and "unknown":
|
||||
./severity-enum.cue:1:11
|
||||
./severity-enum.cue:1:48
|
||||
severity: conflicting values "low" and "unknown":
|
||||
./severity-enum.cue:1:31
|
||||
./severity-enum.cue:1:48
|
||||
severity: conflicting values "medium" and "unknown":
|
||||
./severity-enum.cue:1:20
|
||||
./severity-enum.cue:1:48
|
||||
```
|
||||
|
||||
You can even have disjunctions of structs (not shown, but it works like you'd expect).
|
||||
|
||||
CUE has "definitions", and you can use them like you would variable declarations in other languages. They are also for defining struct types. You can apply a struct of type definitions to some concrete value(s) with `&`. Also notice you can say "a list with type #Whatever" using `[...#Whatever]`.
|
||||
|
||||
```yaml
|
||||
// definitions.cue
|
||||
|
||||
#DashboardPort: 1337
|
||||
|
||||
configs: {
|
||||
host: "localhost"
|
||||
port: #DashboardPort
|
||||
}
|
||||
|
||||
#Address: {
|
||||
street: string
|
||||
city: string
|
||||
zip?: int // ? makes zip optional
|
||||
}
|
||||
|
||||
some_address: #Address & {
|
||||
street: "1 Rocket Rd"
|
||||
city: "Hawthorne"
|
||||
}
|
||||
|
||||
more_addresses: [...#Address] & [
|
||||
{street: "1600 Amphitheatre Parkway", city: "Mountain View", zip: "94043"},
|
||||
{street: "1 Hacker Way", city: "Menlo Park"}
|
||||
]
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export --out yaml definitions.cue
|
||||
configs:
|
||||
host: localhost
|
||||
port: 1337
|
||||
some_address:
|
||||
street: 1 Rocket Rd
|
||||
city: Hawthorne
|
||||
more_addresses:
|
||||
- street: 1600 Amphitheatre Parkway
|
||||
city: Mountain View
|
||||
zip: "94043"
|
||||
- street: 1 Hacker Way
|
||||
city: Menlo Park
|
||||
```
|
||||
|
||||
CUE supports more complex values and validation:
|
||||
|
||||
```yaml
|
||||
#Country: {
|
||||
name: =~"^\\p{Lu}" // Must start with an upper-case letter
|
||||
pop: >800 & <9_000_000_000 // More than 800, fewer than 9 billion
|
||||
}
|
||||
|
||||
vatican_city: #Country & {
|
||||
name: "Vatican City"
|
||||
pop: 825
|
||||
}
|
||||
```
|
||||
|
||||
CUE may save you quite a bit of time with all the sugar it provides on top of mere JSON. Here we're defining, "modifying", and validating a nested structure in three lines: (Notice the `[]` syntax used around `string` to signal to the engine that `string` is a constraint, not a string in this case.)
|
||||
|
||||
```yaml
|
||||
//paths.cue
|
||||
|
||||
// path-value pairs
|
||||
outer: middle1: inner: 3
|
||||
outer: middle2: inner: 7
|
||||
|
||||
// collection-constraint pair
|
||||
outer: [string]: inner: int
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export paths.cue
|
||||
{
|
||||
"outer": {
|
||||
"middle1": {
|
||||
"inner": 3
|
||||
},
|
||||
"middle2": {
|
||||
"inner": 7
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In the same vein, CUE supports "templates", which are a bit like functions of a single argument. Here `Name` is bound to each string key immediately under `container` while the struct underneath *that* is evaluated.
|
||||
|
||||
```yaml
|
||||
//templates.cue
|
||||
|
||||
container: [Name=_]: {
|
||||
name: Name
|
||||
replicas: uint | *1
|
||||
command: string
|
||||
}
|
||||
|
||||
container: sidecar: command: "envoy"
|
||||
|
||||
container: service: {
|
||||
command: "fibonacci"
|
||||
replicas: 2
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue eval templates.cue
|
||||
container: {
|
||||
sidecar: {
|
||||
name: "sidecar"
|
||||
replicas: 1
|
||||
command: "envoy"
|
||||
}
|
||||
service: {
|
||||
name: "service"
|
||||
command: "fibonacci"
|
||||
replicas: 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And while we're talking about references like that, CUE supports scoped references.
|
||||
|
||||
```yaml
|
||||
//scopes-and-references.cue
|
||||
v: "top-level v"
|
||||
b: v // a reference
|
||||
a: {
|
||||
b: v // matches the top-level v
|
||||
}
|
||||
|
||||
let V = v
|
||||
a: {
|
||||
v: "a's inner v"
|
||||
c: v // matches the inner v
|
||||
d: V // matches the top-level v now shadowed by a.v
|
||||
}
|
||||
av: a.v // matches a's v
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue eval --out yaml scopes-and-references.cue
|
||||
```
|
||||
|
||||
```yaml
|
||||
v: top-level v
|
||||
b: top-level v
|
||||
a:
|
||||
b: top-level v
|
||||
v: a's inner v
|
||||
c: a's inner v
|
||||
d: top-level v
|
||||
av: a's inner v
|
||||
```
|
||||
|
||||
I changed the order of the keys in the output for clarity. Order doesn't actually matter, and notice that duplicate keys at a given level are *all* unified.
|
||||
|
||||
You can hide fields be prefixing them with `_` (quote the field if you need a `_` prefix in an emitted field)
|
||||
|
||||
```yaml
|
||||
//hiddens.cue
|
||||
"_foo": 2
|
||||
_foo: 3
|
||||
foo: 4
|
||||
_#foo: 5
|
||||
#foo : 6
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue eval hiddens.cue
|
||||
"_foo": 2
|
||||
foo: 4
|
||||
#foo: 6
|
||||
|
||||
% cue export hiddens.cue
|
||||
{
|
||||
"_foo": 2,
|
||||
"foo": 4
|
||||
}
|
||||
```
|
||||
|
||||
Notice the difference between `eval` and `export` with respect to definitions. If you want to hide a definition in CUE, you can prefix *that* with `_`.
|
||||
|
||||
Interpolation of values and fields:
|
||||
|
||||
```yaml
|
||||
//interpolation.cue
|
||||
|
||||
#expense: 90
|
||||
#revenue: 100
|
||||
message: "Your profit was $\( #revenue - #expense)"
|
||||
|
||||
cat: {
|
||||
type: "Cuddly"
|
||||
"is\(type)": true
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export interpolation.cue
|
||||
{
|
||||
"message": "Your profit was $10",
|
||||
"cat": {
|
||||
"type": "Cuddly",
|
||||
"isCuddly": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Operators, list comprehensions, conditionals, imports...:
|
||||
|
||||
```yaml
|
||||
//getting-out-of-hand-now.cue
|
||||
import "strings" // we'll come back to this
|
||||
|
||||
// operators are nice
|
||||
g: 5 / 3 // CUE can do math
|
||||
h: 3 * "blah" // and Python-like string repetition
|
||||
i: 3 * [1, 2, 3] // with lists too
|
||||
j: 8 < 10 // and supports boolean ops
|
||||
|
||||
// conditionals are also nice
|
||||
price: number
|
||||
// Require a justification if price is too high
|
||||
if price > 100 {
|
||||
justification: string
|
||||
}
|
||||
price: 200
|
||||
justification: "impulse buy"
|
||||
|
||||
// list comprehensions are powerful and compact
|
||||
#items: [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
comp: [ for x in #items if x rem 2 == 0 {x*x}]
|
||||
|
||||
// and... well you can do this too
|
||||
#a: [ "Apple", "Google", "SpaceX"]
|
||||
for k, v in #a {
|
||||
"\( strings.ToLower(v) )": {
|
||||
pos: k + 1
|
||||
name: v
|
||||
nameLen: len(v)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export getting-out-of-hand-now.cue
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"g": 1.66666666666666666666667,
|
||||
"h": "blahblahblah",
|
||||
"i": [1, 2, 3, 1, 2, 3, 1, 2, 3],
|
||||
"j": true,
|
||||
"apple": {
|
||||
"pos": 1,
|
||||
"name": "Apple",
|
||||
"nameLen": 5
|
||||
},
|
||||
"google": {
|
||||
"pos": 2,
|
||||
"name": "Google",
|
||||
"nameLen": 6
|
||||
},
|
||||
"price": 200,
|
||||
"justification": "impulse buy",
|
||||
"comp": [
|
||||
4,
|
||||
16,
|
||||
36,
|
||||
64
|
||||
],
|
||||
"spacex": {
|
||||
"pos": 3,
|
||||
"name": "SpaceX",
|
||||
"nameLen": 6
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
At this point it's worth mentioning that CUE may not be Turing-complete, but it *is* powerful enough for you to shoot yourself in the foot, so do try to keep it clear. It's easy to go off the deep end and make your config *harder* to work with if you're not careful. Make use of those comments, at least, and/or...
|
||||
|
||||
To that end, CUE supports packages and modules. CUE files are standalone by default, but if you put a package clause at the top, you're saying that file is unifiable with other files "in" the same package.
|
||||
|
||||
```yaml
|
||||
//a.cue
|
||||
package config
|
||||
|
||||
foo: 100
|
||||
bar: int
|
||||
```
|
||||
|
||||
```yaml
|
||||
//b.cue
|
||||
package config
|
||||
|
||||
bar: 200
|
||||
```
|
||||
|
||||
If you create these two files in a new directory and run `cue eval` (no arguments), it will unify them like you'd expect. It searches the current directory for .cue files, and if they all have the same package, they will be unified.
|
||||
|
||||
Packages are more clear in the context of "modules". Modules are the *largest* unit of organization. Basically every time you have a project that spans multiple files, you should create a module and name it with something that looks like the domain and path of a URL, e.g., `example.com/something`. When you import anything from this module, even from *within* the module, you must do so using the fully-qualified module path which will be prefixed with this module name.
|
||||
|
||||
You can create a new module like so:
|
||||
|
||||
```bash
|
||||
mkdir mymodule && cd mymodule
|
||||
cue mod init example.com/mymodule
|
||||
```
|
||||
|
||||
This creates a `cue.mod/` subdirectory within that `mymodule` directory, and `cue.mod/` contains the following file and subdirectories:
|
||||
|
||||
- `module.cue` (which defines your module name, in this case with `module: "example.com/mymodule"`)
|
||||
- pkg/
|
||||
- gen/
|
||||
- usr/
|
||||
|
||||
For a different perspective on this and details about what's in there, see https://cuelang.org/docs/concepts/packages/. For my purposes here, I'll say you don't need to think about the contents of this directory *at all*, except that your module name will be the prefix for all imports within your module.
|
||||
|
||||
Where will your module file hierarchy go? All files and directories for your module are rooted in `mymodule/`, the directory that also contains `cue.mod/`. If you want to import a package, you'll prefix it with `example.com/mymodule`, followed by a relative path rooted in `mymodule/`.
|
||||
|
||||
To make it concrete, consider the following:
|
||||
|
||||
```
|
||||
mymodule
|
||||
├── config
|
||||
│ ├── a.cue
|
||||
│ └── b.cue
|
||||
├── cue.mod
|
||||
│ ├── module.cue
|
||||
│ ├── pkg
|
||||
│ └── usr
|
||||
└── main.cue
|
||||
```
|
||||
|
||||
`cue.mod/` and the files underneath it were created by `cue mod init example.com/mymodule`. I then created the `config/` subdirectory with `a.cue` and `b.cue` inside. Then I created `main.cue` to act as my top-level file to rule them all.
|
||||
|
||||
Running `eval` (no arguments) checks to see if there's only one package in all .cue files in the current directory, and if so, it unifies them and outputs the result. In this case, there's only main.cue with package `main` (nothing special about "main" there, it just seemed appropriate), so that's the one.
|
||||
|
||||
```bash
|
||||
% cue eval
|
||||
configuredBar: 200
|
||||
```
|
||||
|
||||
The contents of `main.cue` is:
|
||||
|
||||
```yaml
|
||||
//main.cue
|
||||
|
||||
package main
|
||||
import "example.com/mymodule/config"
|
||||
|
||||
configuredBar: config.bar
|
||||
```
|
||||
|
||||
`config/a.cue` and `config/b.cue` are files from earlier, except now they've both got `package config` at the top:
|
||||
|
||||
```yaml
|
||||
//a.cue
|
||||
package config
|
||||
|
||||
foo: 100
|
||||
bar: int
|
||||
```
|
||||
|
||||
```yaml
|
||||
//b.cue
|
||||
package config
|
||||
|
||||
bar: 200
|
||||
```
|
||||
|
||||
So there you go. If you want to verify that it's actually unifying both files under `config/`, you can change `bar: int` to `bar: string` in `a.cue` and re-run `cue eval` to get a nice type error:
|
||||
|
||||
```
|
||||
cue eval 2022-01-06 17:51:24
|
||||
configuredBar: conflicting values string and 200 (mismatched types string and int):
|
||||
./config/a.cue:4:6
|
||||
./config/b.cue:3:6
|
||||
./main.cue:5:16
|
||||
```
|
||||
|
||||
That's it for now. I understand there are more package management features coming in the future and the design decisions around `cue.mod` are looking ahead to that.
|
||||
|
||||
Finally, CUE has built-in modules with powerful functionality. We saw one of these earlier, when we imported "strings" and used `strings.ToLower`. Imports without fully-qualified module names are assumed to be built-ins. The full list and documentation for each is here: https://pkg.go.dev/cuelang.org/go/pkg
|
||||
|
||||
This has been a condensation of the official docs and tutorials, so go give the source material some love: https://cuelang.org/docs/tutorials/
|
@ -45,7 +45,7 @@ const CONSTANT_VALUE = "I CANNOT CHANGE";
|
||||
CONSTANT_VALUE = "DID I?"; //Error
|
||||
/// Final is another variable declaration that cannot be change once it has been instantiated. Commonly used in classes and functions
|
||||
/// `final` can be declared in pascalCase.
|
||||
final finalValue = "value cannot be change once instantiated";
|
||||
final finalValue = "value cannot be changed once instantiated";
|
||||
finalValue = "Seems not"; //Error
|
||||
|
||||
/// `var` is another variable declaration that is mutable and can change its value. Dart will infer types and will not change its data type
|
||||
@ -77,13 +77,12 @@ example1() {
|
||||
nested1();
|
||||
}
|
||||
|
||||
/// Anonymous functions don't include a name but can take number of arguments
|
||||
/// Anonymous functions don't include a name
|
||||
example2() {
|
||||
//// Explicit return type.
|
||||
nested1(Function<void> fn) {
|
||||
nested1(void Function() fn) {
|
||||
fn();
|
||||
}
|
||||
|
||||
nested1(() => print("Example2 nested 1"));
|
||||
}
|
||||
|
||||
@ -717,6 +716,6 @@ main() {
|
||||
## Further Reading
|
||||
|
||||
Dart has a comprehensive web-site. It covers API reference, tutorials, articles and more, including a
|
||||
useful Try Dart online.
|
||||
[https://www.dartlang.org](https://www.dartlang.org)
|
||||
[https://try.dartlang.org](https://try.dartlang.org)
|
||||
useful DartPad (a cloud-based Dart coding playground).
|
||||
[https://dart.dev/](https://dart.dev)
|
||||
[https://dartpad.dev/](https://dartpad.dev)
|
||||
|
@ -4,15 +4,19 @@ contributors:
|
||||
- ["Ryan Mavilia", "http://unoriginality.rocks/"]
|
||||
translators:
|
||||
- ["Dennis Keller", "https://github.com/denniskeller"]
|
||||
filename: asciidoc-de.md
|
||||
filename: asciidoc-de.adoc
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
AsciiDoc ist eine Auszeichnungssprache ähnlich zu Markdown. Sie kann für alles verwendet werden von Büchern zu Blogs. Erfunden wurde sie 2002 von Stuart Rackham. Die Sprache ist simpel aber sie ermöglicht eine große Anzahl an Anpassungen.
|
||||
AsciiDoc ist eine Auszeichnungssprache ähnlich zu Markdown. Sie kann für alles
|
||||
verwendet werden von Büchern zu Blogs. Erfunden wurde sie 2002 von Stuart
|
||||
Rackham. Die Sprache ist simpel aber sie ermöglicht eine große Anzahl an
|
||||
Anpassungen.
|
||||
|
||||
Kopfzeile des Dokuments
|
||||
|
||||
Kopfzeilen sind optional und dürfen keine Leerzeilen besitzen. Sie müssen mindestens eine Leerzeile vom Inhalt versetzt sein.
|
||||
Kopfzeilen sind optional und dürfen keine Leerzeilen besitzen. Sie müssen
|
||||
mindestens eine Leerzeile vom Inhalt versetzt sein.
|
||||
|
||||
Nur Titel
|
||||
|
||||
@ -104,7 +108,8 @@ Um eine nummerierte Liste zu erstellen, verwendest du Punkte.
|
||||
. item 3
|
||||
```
|
||||
|
||||
Um Listen zu verschachteln, musst du zusätzliche Sternchen beziehungsweise Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
|
||||
Um Listen zu verschachteln, musst du zusätzliche Sternchen beziehungsweise
|
||||
Punkte hinzufügen. Dies ist bis zu fünf Mal möglich.
|
||||
|
||||
```
|
||||
* foo 1
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
language: brainfuck
|
||||
language: bf
|
||||
contributors:
|
||||
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
|
||||
- ["Mathias Bynens", "http://mathiasbynens.be/"]
|
||||
translators:
|
||||
- ["urfuchs", "https://github.com/urfuchs"]
|
||||
filename: brainfuck-de
|
||||
filename: brainfuck-de.bf
|
||||
lang: de-de
|
||||
|
||||
---
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: c++
|
||||
language: C++
|
||||
filename: learncpp-de.cpp
|
||||
contributors:
|
||||
- ["Steven Basart", "http://github.com/xksteven"]
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: c
|
||||
language: C
|
||||
filename: learnc-de.c
|
||||
contributors:
|
||||
- ["caminsha", "https://github.com/caminsha"]
|
||||
|
561
de-de/crystal-de.html.markdown
Normal file
561
de-de/crystal-de.html.markdown
Normal file
@ -0,0 +1,561 @@
|
||||
---
|
||||
language: crystal
|
||||
contributors:
|
||||
- ["Vitalii Elenhaupt", "http://veelenga.com"]
|
||||
- ["Arnaud Fernandés", "https://github.com/TechMagister/"]
|
||||
translators:
|
||||
- ["caminsha", "https://github.com/caminsha"]
|
||||
filename: learncrystal-de.cr
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
```crystal
|
||||
|
||||
# Das ist ein Kommentar
|
||||
|
||||
# Alles ist ein Objekt
|
||||
nil.class # => Nil
|
||||
100.class # => Int32
|
||||
true.class # => Bool
|
||||
|
||||
# Falschwerte sind: nil, false und Nullpointer
|
||||
!nil # => true : Bool
|
||||
!false # => true : Bool
|
||||
!0 # => false : Bool
|
||||
|
||||
# Integer
|
||||
|
||||
1.class # => Int32
|
||||
|
||||
# Fünf vorzeichenbehaftete Ganzzahlen
|
||||
1_i8.class # => Int8
|
||||
1_i16.class # => Int16
|
||||
1_i32.class # => Int32
|
||||
1_i64.class # => Int64
|
||||
1_i128.class # => Int128
|
||||
|
||||
# Fünf vorzeichenlose Ganzzahlen
|
||||
1_u8.class # => UInt8
|
||||
1_u16.class # => UInt16
|
||||
1_u32.class # => UInt32
|
||||
1_u64.class # => UInt64
|
||||
1_u128.class # => UInt128
|
||||
|
||||
|
||||
2147483648.class # => Int64
|
||||
9223372036854775808.class # => UInt64
|
||||
|
||||
# Binäre Zahlen
|
||||
0b1101 # => 13 : Int32
|
||||
|
||||
# Oktalzahlen
|
||||
0o123 # => 83 : Int32
|
||||
|
||||
# Hexadezimalzahlen
|
||||
0xFE012D # => 16646445 : Int32
|
||||
0xfe012d # => 16646445 : Int32
|
||||
|
||||
# Gleitkommazahlen (floats)
|
||||
|
||||
1.0.class # => Float64
|
||||
|
||||
# Es gibt zwei Typen von Gleitkommazahlen
|
||||
|
||||
1.0_f32.class # => Float32
|
||||
1_f32.class # => Float32
|
||||
|
||||
1e10.class # => Float64
|
||||
1.5e10.class # => Float64
|
||||
1.5e-7.class # => Float64
|
||||
|
||||
|
||||
# Chars (einzelne Zeichen)
|
||||
|
||||
'a'.class # => Char
|
||||
|
||||
# Oktale Schreibweise
|
||||
'\101' # => 'A' : Char
|
||||
|
||||
# Unicode Schreibweise
|
||||
'\u0041' # => 'A' : Char
|
||||
|
||||
# Strings (Zeichenketten)
|
||||
"s".class # => String
|
||||
|
||||
# Strings sind unveränderlich
|
||||
s = 'hello, " # => "hello, " : String
|
||||
s.object_id # => 1234667712 : UInt64
|
||||
s += "Crystal" # => "hello, Crystal" : String
|
||||
s.object_id # => 142528472 : UInt64
|
||||
|
||||
# Interpolation wird unterstützt
|
||||
"sum = #{1 + 2}" # => "sum = 3" : String
|
||||
|
||||
# Mehrzeilige Strings
|
||||
" Dies ist ein
|
||||
mehrzeiliger String."
|
||||
|
||||
# String mit doppeltem Anführungszeichen
|
||||
%(hello "world") # => "hello \"world\""
|
||||
|
||||
# Symbole
|
||||
# Unveränderbare, wiederverwendbare Konstanten, welche intern als Int32 Integer
|
||||
# Werte repräsentiert werden.
|
||||
# Symbole werden oft anstelle von Strings verwendet, um bestimmte Werte zu bestimmen.
|
||||
|
||||
:symbol.class # => Symbol
|
||||
|
||||
sentence = :question? # :"question?" : Symbol
|
||||
|
||||
sentence = :question? # => true : Bool
|
||||
sentence = :exclamation! # => false : Bool
|
||||
sentence = "question?" # => false : Bool
|
||||
|
||||
# Arrays
|
||||
[1, 2, 3].class # => Array(Int32)
|
||||
[1, "hello", 'x'].class # => Array(Int32 | String | Char)
|
||||
|
||||
# Leere Arrays sollten einen Typen definieren
|
||||
[] # => Syntaxfehler: für leere Arrays,
|
||||
# verwende `[] of ElementType`
|
||||
[] of Int32 # => [] : Array(Int32)
|
||||
Array(Int32).new # => [] : Array(Int32)
|
||||
|
||||
# Arrays können indiziert werden
|
||||
array = [1, 2, 3, 4, 5] # => [1, 2, 3, 4, 5] : Array(Int32)
|
||||
array[0] # => 1 : Int32
|
||||
array[10] # führt zu einem IndexError
|
||||
array[-6] # führt zu einem IndexError
|
||||
array[10]? # => nil : (Int32 | Nil)
|
||||
array[-6]? # => nil : (Int32 | Nil)
|
||||
|
||||
# Starte am Ende des Arrays
|
||||
array[-1] # => 5
|
||||
|
||||
# Mit einem Startindex und einer Länge
|
||||
array[2, 4] # => [3, 4, 5]
|
||||
|
||||
# oder mit einem Bereich
|
||||
array[1..3] # => [2, 3, 4]
|
||||
|
||||
# Füge etwas zu einem Array hinzu
|
||||
array << 6 # => [1, 2, 3, 4, 5, 6]
|
||||
|
||||
# Entferne Einträge am Ende des Arrays
|
||||
array.pop # => 6
|
||||
array # => [1, 2, 3, 4, 5]
|
||||
|
||||
# Entferne ersten Eintrag im Array
|
||||
array.shift # => 1
|
||||
array # => [2, 3, 4, 5]
|
||||
|
||||
# Überprüfe, ob ein Element in einem Array existiert
|
||||
array.includes? 3 # => true
|
||||
|
||||
# Spezielle Syntax für String-Arrays und Symbol-Arrays
|
||||
%w(one two three) # => ["one", "two", "three"] : Array(String)
|
||||
%i(one two three) # 0> [:one, :two, :three] : Array(Symbol)
|
||||
|
||||
# Es gibt auch für andere Arrays eine spezielle Syntax, wenn die Methoden
|
||||
# `.new` und `#<<` definiert werden.
|
||||
set = Set{1, 2, 3} # => [1, 2, 3]
|
||||
set.class # => Set(Int32)
|
||||
|
||||
# Das obere ist äquivalent zu:
|
||||
set = Set(typeof(1, 2, 3)).new
|
||||
set << 1
|
||||
set << 2
|
||||
set << 3
|
||||
|
||||
# Hashes
|
||||
{1 => 2, 3 => 4}.class # => Hash(Int32, Int32)
|
||||
{1 => 2, 'a' => 3}.class # => Hash (Int32 | Char, Int32)
|
||||
|
||||
# Leere Hashes sollten einen Typen spezifieren
|
||||
{} # Syntaxfehler
|
||||
{} of Int32 => Int32 # {}
|
||||
Hash(Int32, Int32).new # {}
|
||||
|
||||
# Hashes können schnell mit dem Key nachgeschaut werden
|
||||
hash = {"color" => "green", "number" => 5}
|
||||
hash["color"] # => "green"
|
||||
hash["no_such_key"] # => Fehlender hash key: "no_such_key" (KeyError)
|
||||
hash["no_such_key"]? # => nil
|
||||
|
||||
# Überprüfe die Existenz eines Hashkeys
|
||||
hash.has_key? "color" # => true
|
||||
|
||||
# Spezielle Schreibweise für Symbol- und Stringkeys
|
||||
{key1: 'a', key2: 'b'} # {:key1 => 'a', :key2 => 'b'}
|
||||
{"key1": 'a', "key2": 'b'} # {"key1" => 'a', "key2" => 'b'}
|
||||
|
||||
# Die spezielle Syntax für Hash-Literale gibt es auch für andere Typen, sofern
|
||||
# diese die Methoden `.new` und `#[]=` Methoden definieren.
|
||||
class MyType
|
||||
def []=(key, value)
|
||||
puts "do stuff"
|
||||
end
|
||||
end
|
||||
|
||||
MyType{"foo" => "bar"}
|
||||
|
||||
# Das obere ist äquivalent zu:
|
||||
tmp = MyType.new
|
||||
tmp["foo"] = "bar"
|
||||
tmp
|
||||
|
||||
# Ranges (Bereiche)
|
||||
1..10 # => Range(Int32, Int32)
|
||||
Range.new(1,10).class # => Range(Int32, Int32)
|
||||
|
||||
# Ranges können inklusiv oder exklusiv sein.
|
||||
(3..5).to_a # => [3, 4, 5]
|
||||
(3...5).to_a # => [3, 4]
|
||||
|
||||
# Überprüfe, ob ein Range einen Wert enthält oder nicht.
|
||||
(1..8).includes? 2 # => true
|
||||
|
||||
# Tupel sind unveränderliche, Stack-zugewiese Folgen von Werten mit fester
|
||||
# Größe und möglicherweise unterschiedlichen Typen
|
||||
{1, "hello", 'x'}.class # => Tuple(Int32, String, Char)
|
||||
|
||||
# Erhalte den Wert eines Tupels über den Index
|
||||
tuple = {:key1, :key2}
|
||||
tuple[1] # => :key2
|
||||
tuple[2] # syntax error: Index out of bound
|
||||
|
||||
# Können auf mehrere Variablen erweitert werden
|
||||
a, b, c = {:a, 'b', "c"}
|
||||
a # => :a
|
||||
b # => 'b'
|
||||
c # => "c"
|
||||
|
||||
# Procs repräsentieren ein Funktionspointer mit einem optionalen Kontext.
|
||||
# Normalerweise wird ein Proc mit einem proc-Literal erstellt.
|
||||
proc = ->(x : Int32) { x.to_s }
|
||||
proc.class # => Print(Int32, String)
|
||||
# Außerdem kann man auch mit der Methode `new` ein Proc erstellen.
|
||||
Proc(Int32, String).new { |x| x.to_s }
|
||||
|
||||
# Rufe ein Proc auf mit der Methode `call`
|
||||
proc.call 10 # => "10"
|
||||
|
||||
# Kontrollstatements
|
||||
|
||||
if true
|
||||
"if statement"
|
||||
elsif false
|
||||
"else-f, optional"
|
||||
else
|
||||
"else, auch optional"
|
||||
end
|
||||
|
||||
puts "if as a suffix" if true # => if as a suffix
|
||||
|
||||
# If als Ausdruck
|
||||
a = if 2 > 1
|
||||
3
|
||||
else
|
||||
4
|
||||
end
|
||||
|
||||
a # => 3
|
||||
|
||||
# Bedingter ternärer Ausdruck
|
||||
a = 1 > 2 ? 3 : 4 # => 4
|
||||
|
||||
# Case-Statement
|
||||
cmd = "move"
|
||||
|
||||
action = case cmd
|
||||
when "create"
|
||||
"Creating..."
|
||||
when "copy"
|
||||
"Copying..."
|
||||
when "move"
|
||||
"Moving..."
|
||||
when "delete"
|
||||
"Deleting..."
|
||||
end
|
||||
|
||||
action # => "Moving..."
|
||||
|
||||
# Schleifen
|
||||
index = 0
|
||||
while index <= 3
|
||||
puts "Index: #{index}"
|
||||
index += 1
|
||||
end
|
||||
# Index: 0
|
||||
# Index: 1
|
||||
# Index: 2
|
||||
# Index: 3
|
||||
|
||||
index = 0
|
||||
until index > 3
|
||||
puts "Index: #{index}"
|
||||
index += 1
|
||||
end
|
||||
# Index: 0
|
||||
# Index: 1
|
||||
# Index: 2
|
||||
# Index: 3
|
||||
|
||||
# Der bevorzugte Weg, ist `each` zu verwenden.
|
||||
(1..3).each do |index|
|
||||
puts "Index: #{index}"
|
||||
end
|
||||
# Index: 1
|
||||
# Index: 2
|
||||
# Index: 3
|
||||
|
||||
# Der Typ der Variablen hängt vom Typen innerhalb der Kontrollanweisung ab
|
||||
if a < 3
|
||||
a = "hello"
|
||||
else
|
||||
a = true
|
||||
end
|
||||
typeof a # => (Bool | String)
|
||||
|
||||
if a && b
|
||||
# Hier wird garantiert, dass weder a noch b vom Typ Nil sind
|
||||
end
|
||||
|
||||
if a.is_a? String
|
||||
a.class # => String
|
||||
end
|
||||
|
||||
# Funktionen
|
||||
def double(x)
|
||||
x * 2
|
||||
end
|
||||
|
||||
# Funktionen geben implizit den Wert der letzten Anweisung zurück
|
||||
# Dies ist auch bei anderen Blöcken der Fall.
|
||||
double(2) # => 4
|
||||
|
||||
# Klammern müssen nicht gesetzt werden, wenn der Aufruf eindeutig ist
|
||||
double 3 # => 6
|
||||
double double 3 # => 12
|
||||
|
||||
def sum(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
# Funktionsargumente werden mit einem Komma separiert.
|
||||
sum 3, 4 # => 7
|
||||
|
||||
sum sum(3, 4), 5 # => 12
|
||||
|
||||
# yield
|
||||
# Alle Methoden haben einen impliziten, optionalen Blockparameter.
|
||||
# Dieser kann mit dem Schlüsselwort `yield` aufgerufen werden.
|
||||
|
||||
def surround
|
||||
puts '{'
|
||||
yield
|
||||
puts '}'
|
||||
end
|
||||
|
||||
surround { puts "Hallo Welt" }
|
||||
|
||||
# {
|
||||
# Hallo Welt
|
||||
# }
|
||||
|
||||
# Du kannst ein Block einer Funktion übergeben.
|
||||
# "&" kennzeichnet eine Referenz zu einem übergebenen Block
|
||||
def guests(&block)
|
||||
block.call "some_argument"
|
||||
end
|
||||
|
||||
# Du kannst eine Liste von Argumenten mitgeben, welche zu einem Array
|
||||
# umgewandelt werden.
|
||||
# Hierfür ist der Splat-Operator ("*")
|
||||
def guests(*array)
|
||||
array.each { |guest| puts guest }
|
||||
end
|
||||
|
||||
# Wenn eine Methode ein Array zurückgibt, kann destrukturiende Zuordnung
|
||||
# verwendet werden.
|
||||
def foods
|
||||
["pancake", "sandwich", "quesadilla"]
|
||||
end
|
||||
breakfast, lunch, dinner = foods
|
||||
breakfast # => "pancake"
|
||||
dinner # => "quesadilla"
|
||||
|
||||
# Gemäß der Konvention enden alle Methoden, welchen einen Boolean zurückgeben
|
||||
# mit einem Fragezeichen.
|
||||
5.even? # false
|
||||
5.odd? # true
|
||||
|
||||
# Und wenn eine Methode mit einem Ausrufezeichen endet, macht sie etwas
|
||||
# destruktives. Zum Beispiel wird der Aufrufer verändert. Einige Methoden haben
|
||||
# eine !-Version, um eine Änderung zu machen und eine Nicht-!-Version, welche
|
||||
# lediglich eine neue veränderte Version zurückgibt.
|
||||
|
||||
company_name = "Dunder Mifflin"
|
||||
company_name.gsub "Dunder", "Donald" # => "Donald Mifflin"
|
||||
company_name # => "Dunder Mifflin"
|
||||
company_name.gsub! "Dunder", "Donald"
|
||||
company_name # => "Donald Mifflin"
|
||||
|
||||
# definiere eine Klasse mit dem Schlüsselwort `class`.
|
||||
class Human
|
||||
|
||||
# eine Klassenvariable. Diese wird mit allen Instanzen dieser Klasse geteilt.
|
||||
@@species = "H. sapiens"
|
||||
|
||||
# type of name is String
|
||||
@name: String
|
||||
|
||||
# Grundlegender Intialisierer
|
||||
# Weise das Argument der Instanz-Variable "name" zu
|
||||
# Wenn kein Alter angegeben wird, wird der Default (hier 0) genommen.
|
||||
def initialize(@name, @age = 0)
|
||||
end
|
||||
|
||||
# Einfache Setter-Methode
|
||||
def name=(name)
|
||||
@name = name
|
||||
end
|
||||
|
||||
# einfache Getter-Methode
|
||||
def name
|
||||
@name
|
||||
end
|
||||
|
||||
# Die obere Funktionalität kann mit der property-Methode gekapselt werden:
|
||||
property :name
|
||||
|
||||
# Getter/Setter-Methoden können auch individuell erstellt werden:
|
||||
getter :name
|
||||
setter :name
|
||||
|
||||
# eine Klassenmethode verwendet `self` um sich von Instanzmethoden zu
|
||||
# unterscheiden. Diese kann lediglich von einer Klasse aufgerufen werden,
|
||||
# nicht von einer Instanz.
|
||||
def self.say(msg)
|
||||
puts msg
|
||||
end
|
||||
|
||||
def species
|
||||
@@species
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Eine Klasse instanzieren
|
||||
jim = Human.new("Jim Halpert")
|
||||
|
||||
dwight = Human.new("Dwight K. Schrute")
|
||||
|
||||
# Lass uns ein paar Methoden aufrufen
|
||||
jim.species # => "H. sapiens"
|
||||
jim.name # => "Jim Halpert"
|
||||
jim.name = "Jim Halpert II" # => "Jim Halpert II"
|
||||
jim.name # => "Jim Halpert II"
|
||||
dwight.species # => "H. sapiens"
|
||||
dwight.name # => "Dwight K. Schrute"
|
||||
|
||||
# Rufe die Klassenmethode auf
|
||||
Human.say("Hi") # => gibt Hi aus und gibt `nil` zurück
|
||||
|
||||
# Variablen, welche mit @ starten, sind im Scope der Instanz
|
||||
class TestClass
|
||||
@var = "Ich bin eine Instanzvariable"
|
||||
end
|
||||
|
||||
# Variablen, welche mit @@ starten, sind im Scope der Klasse
|
||||
class TestClass
|
||||
@@var = "Ich bin eine Klassenvariable"
|
||||
end
|
||||
|
||||
# Variablen, welche mit einem Großbuchstaben starten, sind Konstanten.
|
||||
Var = "Ich bin eine Konstante"
|
||||
Var = "Ich kann nicht aktualisiert werden." # Die Konstante Var wurde bereits
|
||||
# initialisiert.
|
||||
|
||||
# In Crystal ist Class auch ein Objekt. Dadurch können Klassen Instanzvariablen
|
||||
# haben. Klassenvariablen werden mit der Klasse und allen Subklassen geteilt.
|
||||
|
||||
# Basisklasse
|
||||
class Human
|
||||
@@foo = 0
|
||||
|
||||
def self.foo
|
||||
@@foo
|
||||
end
|
||||
|
||||
def self.foo=(value)
|
||||
@@foo = value
|
||||
end
|
||||
end
|
||||
|
||||
# abgeleitete Klasse
|
||||
class Worker < Human
|
||||
end
|
||||
|
||||
Human.foo # => 0
|
||||
Worker.foo # => 0
|
||||
|
||||
Human.foo = 2 # => 2
|
||||
Worker.foo # => 0
|
||||
|
||||
Worker.foo = 3 # => 3
|
||||
Human.foo # => 2
|
||||
Worker.foo # => 3
|
||||
|
||||
module ModuleExample
|
||||
def foo
|
||||
"foo"
|
||||
end
|
||||
end
|
||||
|
||||
# Wenn ein Modul mit include eingeschlossen wird, so werden die Methoden an die
|
||||
# Instanzen gebunden.
|
||||
# Wenn eine Klasse mit einem Modul erweitert wird, so werden die Methoden an die
|
||||
# Klasse selbst gebunden.
|
||||
|
||||
class Person
|
||||
include ModuleExample
|
||||
end
|
||||
|
||||
class Book
|
||||
extend ModuleExample
|
||||
end
|
||||
|
||||
Person.foo # => undefinierte Methode 'foo' für Person:Class
|
||||
Person.new.foo # => 'foo'
|
||||
Book.foo # => 'foo'
|
||||
Book.new.foo # => undefinierte Methode für Book
|
||||
|
||||
# Ausnahmebehandlung
|
||||
|
||||
# Definiere eine neue Ausnahme
|
||||
class MyException < Exception
|
||||
end
|
||||
|
||||
# Definiere eine weitere Ausnahme
|
||||
class MyAnotherException < Exception; end
|
||||
|
||||
ex = begin
|
||||
raise MyException.new
|
||||
rescue ex1 : IndexError
|
||||
"ex1"
|
||||
rescue ex2 : MyException | MyAnotherException
|
||||
"ex2"
|
||||
rescue ex3 : Exception
|
||||
"ex3"
|
||||
rescue ex4 # fange alle Ausnahmen ab
|
||||
"ex4"
|
||||
end
|
||||
|
||||
ex # => "ex2"
|
||||
```
|
||||
|
||||
|
||||
## Weitere Unterlagen
|
||||
|
||||
- [offizielle Dokumentation, englisch](https://crystal-lang.org/)
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,7 @@ wie `largest_sequences_so_far` und dessen Index würde eine Menge Zeit sparen.
|
||||
|
||||
Ein ähnliches Konzept könnte auch bei der Suche nach dem längsten Weg
|
||||
in gerichteten azyklischen Graphen angewandt werden.
|
||||
|
||||
```python
|
||||
for i=0 to n-1
|
||||
LS[i]=1
|
||||
|
@ -1,423 +1,423 @@
|
||||
---
|
||||
language: elixir
|
||||
contributors:
|
||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||
translators:
|
||||
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
|
||||
filename: learnelixir-de.ex
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
|
||||
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
|
||||
viele Features mit.
|
||||
|
||||
```ruby
|
||||
|
||||
# Einzeilige Kommentare werden mit der Raute gesetzt.
|
||||
|
||||
# Es gibt keine mehrzeiligen Kommentare;
|
||||
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
|
||||
# zu setzen (so wie hier).
|
||||
|
||||
# Mit 'iex' ruft man die Elixir-Shell auf.
|
||||
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
|
||||
|
||||
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
|
||||
# installiert wurde.
|
||||
|
||||
## ---------------------------
|
||||
## -- Basistypen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt Nummern:
|
||||
3 # Integer
|
||||
0x1F # Integer
|
||||
3.0 # Float
|
||||
|
||||
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
|
||||
1_000_000 == 1000000 # Integer
|
||||
1_000.567 == 1000.567 # Float
|
||||
|
||||
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
|
||||
# ':'.
|
||||
:hello # Atom
|
||||
|
||||
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
|
||||
{1,2,3} # Tupel
|
||||
|
||||
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
|
||||
# werden:
|
||||
elem({1, 2, 3}, 0) # => 1
|
||||
|
||||
# Listen sind als verkettete Listen implementiert.
|
||||
[1, 2, 3] # list
|
||||
|
||||
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
|
||||
[ kopf | rest ] = [1,2,3]
|
||||
kopf # => 1
|
||||
rest # => [2, 3]
|
||||
|
||||
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
|
||||
# (Musterabgleich) und keine Zuweisung.
|
||||
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
|
||||
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
|
||||
# werden.
|
||||
|
||||
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
|
||||
# zusammenpassen.
|
||||
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
|
||||
# Elementen:
|
||||
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
|
||||
|
||||
# Es gibt außerdem 'binaries',
|
||||
<<1,2,3>> # binary.
|
||||
|
||||
# Strings und 'char lists'
|
||||
"hello" # String
|
||||
'hello' # Char-Liste
|
||||
|
||||
# ... und mehrzeilige Strings
|
||||
"""
|
||||
Ich bin ein
|
||||
mehrzeiliger String.
|
||||
"""
|
||||
#=> "Ich bin ein\nmehrzeiliger String.\n"
|
||||
|
||||
# Alles Strings werden in UTF-8 enkodiert:
|
||||
"héllò" #=> "héllò"
|
||||
|
||||
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
|
||||
# Listen.
|
||||
<<?a, ?b, ?c>> #=> "abc"
|
||||
[?a, ?b, ?c] #=> 'abc'
|
||||
|
||||
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
|
||||
?a #=> 97
|
||||
|
||||
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
|
||||
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
|
||||
'hello ' ++ 'world' #=> 'hello world'
|
||||
|
||||
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
|
||||
"hello " <> "world" #=> "hello world"
|
||||
|
||||
## ---------------------------
|
||||
## -- Operatoren
|
||||
## ---------------------------
|
||||
|
||||
# Einfache Arithmetik
|
||||
1 + 1 #=> 2
|
||||
10 - 5 #=> 5
|
||||
5 * 2 #=> 10
|
||||
10 / 2 #=> 5.0
|
||||
|
||||
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
|
||||
|
||||
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
|
||||
div(10, 2) #=> 5
|
||||
|
||||
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
|
||||
rem(10, 3) #=> 1
|
||||
|
||||
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
|
||||
# Operatoren erwarten einen Boolean als erstes Argument.
|
||||
true and true #=> true
|
||||
false or true #=> true
|
||||
# 1 and true #=> ** (ArgumentError) argument error
|
||||
|
||||
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
|
||||
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
|
||||
1 || true #=> 1
|
||||
false && 1 #=> false
|
||||
nil && 20 #=> nil
|
||||
|
||||
!true #=> false
|
||||
|
||||
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
|
||||
# `<` und `>`
|
||||
1 == 1 #=> true
|
||||
1 != 1 #=> false
|
||||
1 < 2 #=> true
|
||||
|
||||
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
|
||||
1 == 1.0 #=> true
|
||||
1 === 1.0 #=> false
|
||||
|
||||
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
|
||||
1 < :hello #=> true
|
||||
|
||||
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
|
||||
# number < atom < reference < functions < port < pid < tuple < list < bitstring
|
||||
|
||||
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
|
||||
# total ordering is well defined is important."
|
||||
|
||||
## ---------------------------
|
||||
## -- Kontrollstrukturen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt die `if`-Verzweigung
|
||||
if false do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# ...und ebenso `unless`
|
||||
unless true do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
|
||||
# arbeiten damit.
|
||||
|
||||
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
|
||||
case {:one, :two} do
|
||||
{:four, :five} ->
|
||||
"Das wird nicht passen"
|
||||
{:one, x} ->
|
||||
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
|
||||
_ ->
|
||||
"Dieser Fall greift immer."
|
||||
end
|
||||
|
||||
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
|
||||
# nicht weiter verwendet wird.
|
||||
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
|
||||
[kopf | _] = [1,2,3]
|
||||
kopf #=> 1
|
||||
|
||||
# Für bessere Lesbarkeit können wir auch das Folgende machen:
|
||||
[kopf | _rest] = [:a, :b, :c]
|
||||
kopf #=> :a
|
||||
|
||||
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
|
||||
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
1 + 2 == 3 ->
|
||||
"Aber ich!"
|
||||
end
|
||||
|
||||
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
true ->
|
||||
"Aber ich! (dies ist im Grunde ein 'else')"
|
||||
end
|
||||
|
||||
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
|
||||
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
|
||||
# egal ob zuvor ein Wert gefangen wurde.
|
||||
try do
|
||||
throw(:hello)
|
||||
catch
|
||||
nachricht -> "#{nachricht} gefangen."
|
||||
after
|
||||
IO.puts("Ich bin die 'after'-Klausel.")
|
||||
end
|
||||
#=> Ich bin die 'after'-Klausel.
|
||||
# ":hello gefangen"
|
||||
|
||||
## ---------------------------
|
||||
## -- Module und Funktionen
|
||||
## ---------------------------
|
||||
|
||||
# Anonyme Funktionen (man beachte den Punkt)
|
||||
square = fn(x) -> x * x end
|
||||
square.(5) #=> 25
|
||||
|
||||
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
|
||||
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
|
||||
# eingeführt:
|
||||
f = fn
|
||||
x, y when x > 0 -> x + y
|
||||
x, y -> x * y
|
||||
end
|
||||
|
||||
f.(1, 3) #=> 4
|
||||
f.(-1, 3) #=> -3
|
||||
|
||||
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
|
||||
# Geltungsbereich ('scope') verfügbar.
|
||||
is_number(10) #=> true
|
||||
is_list("hello") #=> false
|
||||
elem({1,2,3}, 0) #=> 1
|
||||
|
||||
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
|
||||
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
|
||||
# definieren.
|
||||
defmodule Math do
|
||||
def sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
|
||||
def square(x) do
|
||||
x * x
|
||||
end
|
||||
end
|
||||
|
||||
Math.sum(1, 2) #=> 3
|
||||
Math.square(3) #=> 9
|
||||
|
||||
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
|
||||
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
|
||||
# werden: elixirc math.ex
|
||||
|
||||
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
|
||||
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
|
||||
# werden; eine private Funktion kann nur lokal angesprochen werden.
|
||||
defmodule PrivateMath do
|
||||
def sum(a, b) do
|
||||
do_sum(a, b)
|
||||
end
|
||||
|
||||
defp do_sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
end
|
||||
|
||||
PrivateMath.sum(1, 2) #=> 3
|
||||
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
||||
|
||||
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
|
||||
defmodule Geometry do
|
||||
def area({:rectangle, w, h}) do
|
||||
w * h
|
||||
end
|
||||
|
||||
def area({:circle, r}) when is_number(r) do
|
||||
3.14 * r * r
|
||||
end
|
||||
end
|
||||
|
||||
Geometry.area({:rectangle, 2, 3}) #=> 6
|
||||
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||
# Geometry.area({:circle, "not_a_number"})
|
||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||
|
||||
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
|
||||
# Bestandteil von Elixir.
|
||||
defmodule Recursion do
|
||||
def sum_list([head | tail], acc) do
|
||||
sum_list(tail, acc + head)
|
||||
end
|
||||
|
||||
def sum_list([], acc) do
|
||||
acc
|
||||
end
|
||||
end
|
||||
|
||||
Recursion.sum_list([1,2,3], 0) #=> 6
|
||||
|
||||
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
|
||||
# ist es möglich eigene Attribute hinzuzufügen.
|
||||
defmodule MyMod do
|
||||
@moduledoc """
|
||||
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
|
||||
"""
|
||||
|
||||
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
|
||||
IO.inspect(@my_data) #=> 100
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- 'Records' und Ausnahmebehandlung
|
||||
## ---------------------------
|
||||
|
||||
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
|
||||
# Namen zuzuweisen.
|
||||
defrecord Person, name: nil, age: 0, height: 0
|
||||
|
||||
joe_info = Person.new(name: "Joe", age: 30, height: 180)
|
||||
#=> Person[name: "Joe", age: 30, height: 180]
|
||||
|
||||
# Zugriff auf den Wert von 'name'
|
||||
joe_info.name #=> "Joe"
|
||||
|
||||
# Den Wert von 'age' überschreiben
|
||||
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
|
||||
|
||||
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
|
||||
# um Ausnahmen beziehungsweise Fehler zu behandeln.
|
||||
try do
|
||||
raise "Irgendein Fehler."
|
||||
rescue
|
||||
RuntimeError -> "Laufzeit-Fehler gefangen."
|
||||
_error -> "Und dies fängt jeden Fehler."
|
||||
end
|
||||
|
||||
# Alle Ausnahmen haben das Attribut 'message'
|
||||
try do
|
||||
raise "ein Fehler"
|
||||
rescue
|
||||
x in [RuntimeError] ->
|
||||
x.message
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- Nebenläufigkeit
|
||||
## ---------------------------
|
||||
|
||||
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
|
||||
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
|
||||
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
|
||||
|
||||
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
|
||||
# wiederum eine Funktion als Argument entgegen nimmt.
|
||||
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
|
||||
spawn(f) #=> #PID<0.40.0>
|
||||
|
||||
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
|
||||
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
|
||||
# zu senden nutzen wir den '<-' Operator. Damit das alles Sinn macht müssen wir
|
||||
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
|
||||
# 'receive'-Mechanismus sichergestellt:
|
||||
defmodule Geometry do
|
||||
def area_loop do
|
||||
receive do
|
||||
{:rectangle, w, h} ->
|
||||
IO.puts("Area = #{w * h}")
|
||||
area_loop()
|
||||
{:circle, r} ->
|
||||
IO.puts("Area = #{3.14 * r * r}")
|
||||
area_loop()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
|
||||
# in der Shell mit, etwa so:
|
||||
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
|
||||
|
||||
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
|
||||
# erfüllt:
|
||||
pid <- {:rectangle, 2, 3}
|
||||
#=> Area = 6
|
||||
# {:rectangle,2,3}
|
||||
|
||||
pid <- {:circle, 2}
|
||||
#=> Area = 12.56000000000000049738
|
||||
# {:circle,2}
|
||||
|
||||
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
|
||||
# die aktuelle pid herausfinden.
|
||||
self() #=> #PID<0.27.0>
|
||||
|
||||
```
|
||||
|
||||
## Referenzen und weitere Lektüre
|
||||
|
||||
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
|
||||
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
|
||||
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
|
||||
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
|
||||
---
|
||||
language: Elixir
|
||||
contributors:
|
||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||
translators:
|
||||
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
|
||||
filename: learnelixir-de.ex
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
|
||||
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
|
||||
viele Features mit.
|
||||
|
||||
```ruby
|
||||
|
||||
# Einzeilige Kommentare werden mit der Raute gesetzt.
|
||||
|
||||
# Es gibt keine mehrzeiligen Kommentare;
|
||||
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
|
||||
# zu setzen (so wie hier).
|
||||
|
||||
# Mit 'iex' ruft man die Elixir-Shell auf.
|
||||
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
|
||||
|
||||
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
|
||||
# installiert wurde.
|
||||
|
||||
## ---------------------------
|
||||
## -- Basistypen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt Nummern:
|
||||
3 # Integer
|
||||
0x1F # Integer
|
||||
3.0 # Float
|
||||
|
||||
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
|
||||
1_000_000 == 1000000 # Integer
|
||||
1_000.567 == 1000.567 # Float
|
||||
|
||||
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
|
||||
# ':'.
|
||||
:hello # Atom
|
||||
|
||||
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
|
||||
{1,2,3} # Tupel
|
||||
|
||||
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
|
||||
# werden:
|
||||
elem({1, 2, 3}, 0) # => 1
|
||||
|
||||
# Listen sind als verkettete Listen implementiert.
|
||||
[1, 2, 3] # list
|
||||
|
||||
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
|
||||
[ kopf | rest ] = [1,2,3]
|
||||
kopf # => 1
|
||||
rest # => [2, 3]
|
||||
|
||||
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
|
||||
# (Musterabgleich) und keine Zuweisung.
|
||||
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
|
||||
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
|
||||
# werden.
|
||||
|
||||
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
|
||||
# zusammenpassen.
|
||||
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
|
||||
# Elementen:
|
||||
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
|
||||
|
||||
# Es gibt außerdem 'binaries',
|
||||
<<1,2,3>> # binary.
|
||||
|
||||
# Strings und 'char lists'
|
||||
"hello" # String
|
||||
'hello' # Char-Liste
|
||||
|
||||
# ... und mehrzeilige Strings
|
||||
"""
|
||||
Ich bin ein
|
||||
mehrzeiliger String.
|
||||
"""
|
||||
#=> "Ich bin ein\nmehrzeiliger String.\n"
|
||||
|
||||
# Alles Strings werden in UTF-8 enkodiert:
|
||||
"héllò" #=> "héllò"
|
||||
|
||||
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
|
||||
# Listen.
|
||||
<<?a, ?b, ?c>> #=> "abc"
|
||||
[?a, ?b, ?c] #=> 'abc'
|
||||
|
||||
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
|
||||
?a #=> 97
|
||||
|
||||
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
|
||||
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
|
||||
'hello ' ++ 'world' #=> 'hello world'
|
||||
|
||||
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
|
||||
"hello " <> "world" #=> "hello world"
|
||||
|
||||
## ---------------------------
|
||||
## -- Operatoren
|
||||
## ---------------------------
|
||||
|
||||
# Einfache Arithmetik
|
||||
1 + 1 #=> 2
|
||||
10 - 5 #=> 5
|
||||
5 * 2 #=> 10
|
||||
10 / 2 #=> 5.0
|
||||
|
||||
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
|
||||
|
||||
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
|
||||
div(10, 2) #=> 5
|
||||
|
||||
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
|
||||
rem(10, 3) #=> 1
|
||||
|
||||
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
|
||||
# Operatoren erwarten einen Boolean als erstes Argument.
|
||||
true and true #=> true
|
||||
false or true #=> true
|
||||
# 1 and true #=> ** (ArgumentError) argument error
|
||||
|
||||
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
|
||||
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
|
||||
1 || true #=> 1
|
||||
false && 1 #=> false
|
||||
nil && 20 #=> nil
|
||||
|
||||
!true #=> false
|
||||
|
||||
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
|
||||
# `<` und `>`
|
||||
1 == 1 #=> true
|
||||
1 != 1 #=> false
|
||||
1 < 2 #=> true
|
||||
|
||||
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
|
||||
1 == 1.0 #=> true
|
||||
1 === 1.0 #=> false
|
||||
|
||||
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
|
||||
1 < :hello #=> true
|
||||
|
||||
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
|
||||
# number < atom < reference < functions < port < pid < tuple < list < bitstring
|
||||
|
||||
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
|
||||
# total ordering is well defined is important."
|
||||
|
||||
## ---------------------------
|
||||
## -- Kontrollstrukturen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt die `if`-Verzweigung
|
||||
if false do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# ...und ebenso `unless`
|
||||
unless true do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
|
||||
# arbeiten damit.
|
||||
|
||||
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
|
||||
case {:one, :two} do
|
||||
{:four, :five} ->
|
||||
"Das wird nicht passen"
|
||||
{:one, x} ->
|
||||
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
|
||||
_ ->
|
||||
"Dieser Fall greift immer."
|
||||
end
|
||||
|
||||
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
|
||||
# nicht weiter verwendet wird.
|
||||
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
|
||||
[kopf | _] = [1,2,3]
|
||||
kopf #=> 1
|
||||
|
||||
# Für bessere Lesbarkeit können wir auch das Folgende machen:
|
||||
[kopf | _rest] = [:a, :b, :c]
|
||||
kopf #=> :a
|
||||
|
||||
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
|
||||
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
1 + 2 == 3 ->
|
||||
"Aber ich!"
|
||||
end
|
||||
|
||||
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
true ->
|
||||
"Aber ich! (dies ist im Grunde ein 'else')"
|
||||
end
|
||||
|
||||
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
|
||||
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
|
||||
# egal ob zuvor ein Wert gefangen wurde.
|
||||
try do
|
||||
throw(:hello)
|
||||
catch
|
||||
nachricht -> "#{nachricht} gefangen."
|
||||
after
|
||||
IO.puts("Ich bin die 'after'-Klausel.")
|
||||
end
|
||||
#=> Ich bin die 'after'-Klausel.
|
||||
# ":hello gefangen"
|
||||
|
||||
## ---------------------------
|
||||
## -- Module und Funktionen
|
||||
## ---------------------------
|
||||
|
||||
# Anonyme Funktionen (man beachte den Punkt)
|
||||
square = fn(x) -> x * x end
|
||||
square.(5) #=> 25
|
||||
|
||||
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
|
||||
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
|
||||
# eingeführt:
|
||||
f = fn
|
||||
x, y when x > 0 -> x + y
|
||||
x, y -> x * y
|
||||
end
|
||||
|
||||
f.(1, 3) #=> 4
|
||||
f.(-1, 3) #=> -3
|
||||
|
||||
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
|
||||
# Geltungsbereich ('scope') verfügbar.
|
||||
is_number(10) #=> true
|
||||
is_list("hello") #=> false
|
||||
elem({1,2,3}, 0) #=> 1
|
||||
|
||||
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
|
||||
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
|
||||
# definieren.
|
||||
defmodule Math do
|
||||
def sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
|
||||
def square(x) do
|
||||
x * x
|
||||
end
|
||||
end
|
||||
|
||||
Math.sum(1, 2) #=> 3
|
||||
Math.square(3) #=> 9
|
||||
|
||||
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
|
||||
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
|
||||
# werden: elixirc math.ex
|
||||
|
||||
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
|
||||
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
|
||||
# werden; eine private Funktion kann nur lokal angesprochen werden.
|
||||
defmodule PrivateMath do
|
||||
def sum(a, b) do
|
||||
do_sum(a, b)
|
||||
end
|
||||
|
||||
defp do_sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
end
|
||||
|
||||
PrivateMath.sum(1, 2) #=> 3
|
||||
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
||||
|
||||
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
|
||||
defmodule Geometry do
|
||||
def area({:rectangle, w, h}) do
|
||||
w * h
|
||||
end
|
||||
|
||||
def area({:circle, r}) when is_number(r) do
|
||||
3.14 * r * r
|
||||
end
|
||||
end
|
||||
|
||||
Geometry.area({:rectangle, 2, 3}) #=> 6
|
||||
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||
# Geometry.area({:circle, "not_a_number"})
|
||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||
|
||||
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
|
||||
# Bestandteil von Elixir.
|
||||
defmodule Recursion do
|
||||
def sum_list([head | tail], acc) do
|
||||
sum_list(tail, acc + head)
|
||||
end
|
||||
|
||||
def sum_list([], acc) do
|
||||
acc
|
||||
end
|
||||
end
|
||||
|
||||
Recursion.sum_list([1,2,3], 0) #=> 6
|
||||
|
||||
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
|
||||
# ist es möglich eigene Attribute hinzuzufügen.
|
||||
defmodule MyMod do
|
||||
@moduledoc """
|
||||
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
|
||||
"""
|
||||
|
||||
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
|
||||
IO.inspect(@my_data) #=> 100
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- 'Records' und Ausnahmebehandlung
|
||||
## ---------------------------
|
||||
|
||||
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
|
||||
# Namen zuzuweisen.
|
||||
defrecord Person, name: nil, age: 0, height: 0
|
||||
|
||||
joe_info = Person.new(name: "Joe", age: 30, height: 180)
|
||||
#=> Person[name: "Joe", age: 30, height: 180]
|
||||
|
||||
# Zugriff auf den Wert von 'name'
|
||||
joe_info.name #=> "Joe"
|
||||
|
||||
# Den Wert von 'age' überschreiben
|
||||
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
|
||||
|
||||
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
|
||||
# um Ausnahmen beziehungsweise Fehler zu behandeln.
|
||||
try do
|
||||
raise "Irgendein Fehler."
|
||||
rescue
|
||||
RuntimeError -> "Laufzeit-Fehler gefangen."
|
||||
_error -> "Und dies fängt jeden Fehler."
|
||||
end
|
||||
|
||||
# Alle Ausnahmen haben das Attribut 'message'
|
||||
try do
|
||||
raise "ein Fehler"
|
||||
rescue
|
||||
x in [RuntimeError] ->
|
||||
x.message
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- Nebenläufigkeit
|
||||
## ---------------------------
|
||||
|
||||
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
|
||||
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
|
||||
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
|
||||
|
||||
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
|
||||
# wiederum eine Funktion als Argument entgegen nimmt.
|
||||
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
|
||||
spawn(f) #=> #PID<0.40.0>
|
||||
|
||||
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
|
||||
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
|
||||
# zu senden nutzen wir den '<-' Operator. Damit das alles Sinn macht müssen wir
|
||||
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
|
||||
# 'receive'-Mechanismus sichergestellt:
|
||||
defmodule Geometry do
|
||||
def area_loop do
|
||||
receive do
|
||||
{:rectangle, w, h} ->
|
||||
IO.puts("Area = #{w * h}")
|
||||
area_loop()
|
||||
{:circle, r} ->
|
||||
IO.puts("Area = #{3.14 * r * r}")
|
||||
area_loop()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
|
||||
# in der Shell mit, etwa so:
|
||||
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
|
||||
|
||||
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
|
||||
# erfüllt:
|
||||
pid <- {:rectangle, 2, 3}
|
||||
#=> Area = 6
|
||||
# {:rectangle,2,3}
|
||||
|
||||
pid <- {:circle, 2}
|
||||
#=> Area = 12.56000000000000049738
|
||||
# {:circle,2}
|
||||
|
||||
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
|
||||
# die aktuelle pid herausfinden.
|
||||
self() #=> #PID<0.27.0>
|
||||
|
||||
```
|
||||
|
||||
## Referenzen und weitere Lektüre
|
||||
|
||||
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
|
||||
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
|
||||
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
|
||||
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
|
||||
|
@ -343,7 +343,7 @@ $ elm reactor
|
||||
-- Starte das REPL (read-eval-print-loop).
|
||||
$ elm repl
|
||||
|
||||
-- Bibliotheken werden durch den Github-Nutzernamen und ein Repository identifiziert.
|
||||
-- Bibliotheken werden durch den GitHub-Nutzernamen und ein Repository identifiziert.
|
||||
-- Installieren einer neuen Bibliothek.
|
||||
$ elm package install elm-lang/html
|
||||
-- Diese wird der elm-package.json Datei hinzugefügt.
|
||||
|
@ -385,6 +385,4 @@ $ git rm /pather/to/the/file/HelloWorld.c
|
||||
|
||||
* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf)
|
||||
|
||||
* [GitGuys](http://www.gitguys.com/)
|
||||
|
||||
* [gitflow - Ein Modell um mit Branches zu arbeiten](http://nvie.com/posts/a-successful-git-branching-model/)
|
||||
|
@ -82,7 +82,7 @@ Zeilenumbrüche beinhalten.` // Selber Zeichenketten-Typ
|
||||
// nicht-ASCII Literal. Go Quelltext ist UTF-8 kompatibel.
|
||||
g := 'Σ' // Ein Runen-Typ, alias int32, gebraucht für unicode code points.
|
||||
|
||||
f := 3.14195 // float64, eine IEEE-754 64-bit Dezimalzahl
|
||||
f := 3.14159 // float64, eine IEEE-754 64-bit Dezimalzahl
|
||||
c := 3 + 4i // complex128, besteht intern aus zwei float64-er
|
||||
|
||||
// "var"-Syntax mit Initalwert
|
||||
@ -308,13 +308,13 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
```
|
||||
|
||||
## Weitere Resourcen
|
||||
Informationen zu Go findet man auf der [offiziellen Go Webseite](http://golang.org/).
|
||||
Informationen zu Go findet man auf der [offiziellen Go Webseite](https://go.dev/).
|
||||
Dort gibt es unter anderem ein Tutorial und interaktive Quelltext-Beispiele, vor
|
||||
allem aber Dokumentation zur Sprache und den Paketen.
|
||||
|
||||
Auch zu empfehlen ist die Spezifikation von Go, die nach heutigen Standards sehr
|
||||
kurz und gut verständlich formuliert ist. Auf der Leseliste von Go-Neulingen
|
||||
ist außerdem der Quelltext der [Go standard Bibliothek](http://golang.org/src/pkg/)
|
||||
ist außerdem der Quelltext der [Go standard Bibliothek](https://go.dev/src/)
|
||||
einzusehen. Dieser kann als Referenz für leicht zu verstehendes und im idiomatischen Stil
|
||||
verfasstes Go dienen. Erreichbar ist der Quelltext auch durch das Klicken der Funktionsnamen
|
||||
in der [offiziellen Dokumentation von Go](http://golang.org/pkg/).
|
||||
in der [offiziellen Dokumentation von Go](https://go.dev/pkg/).
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,263 +1,263 @@
|
||||
---
|
||||
category: tool
|
||||
tool: make
|
||||
contributors:
|
||||
- ["Robert Steed", "https://github.com/robochat"]
|
||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||
translators:
|
||||
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
|
||||
filename: Makefile-de
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
|
||||
zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
|
||||
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
|
||||
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
|
||||
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
|
||||
Konkurrenz und Kritik zu Make gibt.
|
||||
|
||||
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
|
||||
mit der Version GNU Make. Diese Version ist Standard auf Linux.
|
||||
|
||||
```make
|
||||
|
||||
# Kommentare können so geschrieben werden.
|
||||
|
||||
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
|
||||
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
|
||||
# werden.
|
||||
|
||||
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
|
||||
# werden. Niemals Leerzeichen!
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Grundlagen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
|
||||
# nicht existiert.
|
||||
file0.txt:
|
||||
echo "foo" > file0.txt
|
||||
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
|
||||
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
|
||||
# die erste Regel ist die Standard-Regel.
|
||||
|
||||
|
||||
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
|
||||
file1.txt: file0.txt
|
||||
cat file0.txt > file1.txt
|
||||
# Verwende die selben Quoting-Regeln wie die Shell
|
||||
@cat file0.txt >> file1.txt
|
||||
# @ unterdrückt die Ausgabe des Befehls an stdout.
|
||||
-@echo 'hello'
|
||||
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
|
||||
# passieren.
|
||||
# Versuche `make file1.txt` auf der Kommandozeile.
|
||||
|
||||
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
|
||||
file2.txt file3.txt: file0.txt file1.txt
|
||||
touch file2.txt
|
||||
touch file3.txt
|
||||
|
||||
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
|
||||
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
|
||||
# Voraussetzungen hinzuzufügen.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Phony-Ziele
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
|
||||
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
|
||||
all: maker process
|
||||
|
||||
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
|
||||
maker:
|
||||
touch ex0.txt ex1.txt
|
||||
|
||||
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
|
||||
# selben namen wie ein Phony-Ziel hat:
|
||||
.PHONY: all maker process
|
||||
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
|
||||
|
||||
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
|
||||
ex0.txt ex1.txt: maker
|
||||
|
||||
# Häufige Phony-Ziele sind: all make clean install ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Automatische Variablen & Wildcards
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
|
||||
@echo $^ # $^ ist eine Variable die eine Liste aller
|
||||
# Voraussetzungen enthält.
|
||||
@echo $@ # Namen des Ziels ausgeben.
|
||||
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
|
||||
#der Regel.)
|
||||
@echo $< # Die erste Voraussetzung aus der Liste
|
||||
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
|
||||
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
|
||||
#@echo $| # Alle 'order only' Voraussetzungen
|
||||
|
||||
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
|
||||
process: ex1.txt file0.txt
|
||||
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Muster
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
|
||||
# umgewandelt werden.
|
||||
|
||||
%.png: %.svg
|
||||
inkscape --export-png $^
|
||||
|
||||
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
|
||||
# Ziel zu erzeugen
|
||||
|
||||
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
|
||||
# Aber make wird versuchen die am besten passende Regel zu verwenden.
|
||||
small/%.png: %.svg
|
||||
inkscape --export-png --export-dpi 30 $^
|
||||
|
||||
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
|
||||
# findet.
|
||||
%.png: %.svg
|
||||
@echo this rule is chosen
|
||||
|
||||
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
|
||||
# Ziel erzeugen kann.
|
||||
%.png: %.ps
|
||||
@echo this rule is not chosen if *.svg and *.ps are both present
|
||||
|
||||
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
|
||||
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
|
||||
|
||||
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
|
||||
# Muster-Vergleichs-Regeln.
|
||||
.png.ps:
|
||||
@echo this rule is similar to a pattern rule.
|
||||
|
||||
# Aktivieren der Suffix-Regel
|
||||
.SUFFIXES: .png
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen
|
||||
#-----------------------------------------------------------------------
|
||||
# auch Makros genannt.
|
||||
|
||||
# Variablen sind im Grunde genommen Zeichenketten-Typen.
|
||||
|
||||
name = Ted
|
||||
name2="Sarah"
|
||||
|
||||
echo:
|
||||
@echo $(name)
|
||||
@echo ${name2}
|
||||
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
|
||||
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
|
||||
|
||||
# Es git 4 Stellen um Variablen zu setzen.
|
||||
# In Reihenfolge der Priorität von höchster zu niedrigster:
|
||||
# 1: Befehls-Zeilen Argumente
|
||||
# 2: Makefile
|
||||
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
|
||||
# 3: MAke hat einige vordefinierte Variablen.
|
||||
|
||||
name4 ?= Jean
|
||||
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
|
||||
# nicht gibt.
|
||||
|
||||
override name5 = David
|
||||
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
|
||||
|
||||
name4 +=grey
|
||||
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
|
||||
|
||||
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
|
||||
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
|
||||
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
|
||||
# kann, wenn es zu kompilizert wird!)
|
||||
|
||||
# Ein paar Variablen, die von Make automatisch definiert werden.
|
||||
echo_inbuilt:
|
||||
echo $(CC)
|
||||
echo ${CXX}
|
||||
echo $(FC)
|
||||
echo ${CFLAGS}
|
||||
echo $(CPPFLAGS)
|
||||
echo ${CXXFLAGS}
|
||||
echo $(LDFLAGS)
|
||||
echo ${LDLIBS}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen 2
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
|
||||
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
|
||||
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
|
||||
|
||||
var := hello
|
||||
var2 ::= $(var) hello
|
||||
#:= und ::= sind äquivalent.
|
||||
|
||||
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
|
||||
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
|
||||
|
||||
# Das funktioniert nicht
|
||||
var3 ::= $(var4) and good luck
|
||||
var4 ::= good night
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Funktionen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Make verfügt über eine Vielzahl von Funktionen.
|
||||
|
||||
sourcefiles = $(wildcard *.c */*.c)
|
||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||
|
||||
# Das Format ist $(func arg0,arg1,arg2...)
|
||||
|
||||
# Ein paar Beispiele
|
||||
ls: * src/*
|
||||
@echo $(filter %.txt, $^)
|
||||
@echo $(notdir $^)
|
||||
@echo $(join $(dir $^),$(notdir $^))
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Direktiven
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
|
||||
include foo.mk
|
||||
|
||||
sport = tennis
|
||||
# Konditionale kompiliereung
|
||||
report:
|
||||
ifeq ($(sport),tennis)
|
||||
@echo 'game, set, match'
|
||||
else
|
||||
@echo "They think it's all over; it is now"
|
||||
endif
|
||||
|
||||
# Es gibt auch ifneq, ifdef, ifndef
|
||||
|
||||
foo = true
|
||||
|
||||
ifdef $(foo)
|
||||
bar = 'hello'
|
||||
endif
|
||||
```
|
||||
|
||||
|
||||
### Mehr Resourcen
|
||||
|
||||
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
||||
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
|
||||
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||
|
||||
---
|
||||
category: tool
|
||||
tool: make
|
||||
contributors:
|
||||
- ["Robert Steed", "https://github.com/robochat"]
|
||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||
translators:
|
||||
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
|
||||
filename: Makefile-de
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
|
||||
zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
|
||||
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
|
||||
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
|
||||
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
|
||||
Konkurrenz und Kritik zu Make gibt.
|
||||
|
||||
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
|
||||
mit der Version GNU Make. Diese Version ist Standard auf Linux.
|
||||
|
||||
```make
|
||||
|
||||
# Kommentare können so geschrieben werden.
|
||||
|
||||
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
|
||||
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
|
||||
# werden.
|
||||
|
||||
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
|
||||
# werden. Niemals Leerzeichen!
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Grundlagen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
|
||||
# nicht existiert.
|
||||
file0.txt:
|
||||
echo "foo" > file0.txt
|
||||
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
|
||||
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
|
||||
# die erste Regel ist die Standard-Regel.
|
||||
|
||||
|
||||
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
|
||||
file1.txt: file0.txt
|
||||
cat file0.txt > file1.txt
|
||||
# Verwende die selben Quoting-Regeln wie die Shell
|
||||
@cat file0.txt >> file1.txt
|
||||
# @ unterdrückt die Ausgabe des Befehls an stdout.
|
||||
-@echo 'hello'
|
||||
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
|
||||
# passieren.
|
||||
# Versuche `make file1.txt` auf der Kommandozeile.
|
||||
|
||||
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
|
||||
file2.txt file3.txt: file0.txt file1.txt
|
||||
touch file2.txt
|
||||
touch file3.txt
|
||||
|
||||
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
|
||||
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
|
||||
# Voraussetzungen hinzuzufügen.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Phony-Ziele
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
|
||||
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
|
||||
all: maker process
|
||||
|
||||
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
|
||||
maker:
|
||||
touch ex0.txt ex1.txt
|
||||
|
||||
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
|
||||
# selben namen wie ein Phony-Ziel hat:
|
||||
.PHONY: all maker process
|
||||
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
|
||||
|
||||
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
|
||||
ex0.txt ex1.txt: maker
|
||||
|
||||
# Häufige Phony-Ziele sind: all make clean install ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Automatische Variablen & Wildcards
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
|
||||
@echo $^ # $^ ist eine Variable die eine Liste aller
|
||||
# Voraussetzungen enthält.
|
||||
@echo $@ # Namen des Ziels ausgeben.
|
||||
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
|
||||
#der Regel.)
|
||||
@echo $< # Die erste Voraussetzung aus der Liste
|
||||
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
|
||||
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
|
||||
#@echo $| # Alle 'order only' Voraussetzungen
|
||||
|
||||
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
|
||||
process: ex1.txt file0.txt
|
||||
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Muster
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
|
||||
# umgewandelt werden.
|
||||
|
||||
%.png: %.svg
|
||||
inkscape --export-png $^
|
||||
|
||||
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
|
||||
# Ziel zu erzeugen
|
||||
|
||||
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
|
||||
# Aber make wird versuchen die am besten passende Regel zu verwenden.
|
||||
small/%.png: %.svg
|
||||
inkscape --export-png --export-dpi 30 $^
|
||||
|
||||
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
|
||||
# findet.
|
||||
%.png: %.svg
|
||||
@echo this rule is chosen
|
||||
|
||||
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
|
||||
# Ziel erzeugen kann.
|
||||
%.png: %.ps
|
||||
@echo this rule is not chosen if *.svg and *.ps are both present
|
||||
|
||||
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
|
||||
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
|
||||
|
||||
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
|
||||
# Muster-Vergleichs-Regeln.
|
||||
.png.ps:
|
||||
@echo this rule is similar to a pattern rule.
|
||||
|
||||
# Aktivieren der Suffix-Regel
|
||||
.SUFFIXES: .png
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen
|
||||
#-----------------------------------------------------------------------
|
||||
# auch Makros genannt.
|
||||
|
||||
# Variablen sind im Grunde genommen Zeichenketten-Typen.
|
||||
|
||||
name = Ted
|
||||
name2="Sarah"
|
||||
|
||||
echo:
|
||||
@echo $(name)
|
||||
@echo ${name2}
|
||||
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
|
||||
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
|
||||
|
||||
# Es git 4 Stellen um Variablen zu setzen.
|
||||
# In Reihenfolge der Priorität von höchster zu niedrigster:
|
||||
# 1: Befehls-Zeilen Argumente
|
||||
# 2: Makefile
|
||||
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
|
||||
# 3: MAke hat einige vordefinierte Variablen.
|
||||
|
||||
name4 ?= Jean
|
||||
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
|
||||
# nicht gibt.
|
||||
|
||||
override name5 = David
|
||||
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
|
||||
|
||||
name4 +=grey
|
||||
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
|
||||
|
||||
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
|
||||
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
|
||||
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
|
||||
# kann, wenn es zu kompilizert wird!)
|
||||
|
||||
# Ein paar Variablen, die von Make automatisch definiert werden.
|
||||
echo_inbuilt:
|
||||
echo $(CC)
|
||||
echo ${CXX}
|
||||
echo $(FC)
|
||||
echo ${CFLAGS}
|
||||
echo $(CPPFLAGS)
|
||||
echo ${CXXFLAGS}
|
||||
echo $(LDFLAGS)
|
||||
echo ${LDLIBS}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen 2
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
|
||||
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
|
||||
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
|
||||
|
||||
var := hello
|
||||
var2 ::= $(var) hello
|
||||
#:= und ::= sind äquivalent.
|
||||
|
||||
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
|
||||
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
|
||||
|
||||
# Das funktioniert nicht
|
||||
var3 ::= $(var4) and good luck
|
||||
var4 ::= good night
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Funktionen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Make verfügt über eine Vielzahl von Funktionen.
|
||||
|
||||
sourcefiles = $(wildcard *.c */*.c)
|
||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||
|
||||
# Das Format ist $(func arg0,arg1,arg2...)
|
||||
|
||||
# Ein paar Beispiele
|
||||
ls: * src/*
|
||||
@echo $(filter %.txt, $^)
|
||||
@echo $(notdir $^)
|
||||
@echo $(join $(dir $^),$(notdir $^))
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Direktiven
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
|
||||
include foo.mk
|
||||
|
||||
sport = tennis
|
||||
# Konditionale kompiliereung
|
||||
report:
|
||||
ifeq ($(sport),tennis)
|
||||
@echo 'game, set, match'
|
||||
else
|
||||
@echo "They think it's all over; it is now"
|
||||
endif
|
||||
|
||||
# Es gibt auch ifneq, ifdef, ifndef
|
||||
|
||||
foo = true
|
||||
|
||||
ifdef $(foo)
|
||||
bar = 'hello'
|
||||
endif
|
||||
```
|
||||
|
||||
|
||||
### Mehr Resourcen
|
||||
|
||||
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
||||
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
|
||||
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||
|
||||
|
@ -356,6 +356,9 @@ with builtins; [
|
||||
|
||||
* [Susan Potter - Nix Cookbook - Nix By Example]
|
||||
(https://ops.functionalalgebra.com/nix-by-example/)
|
||||
|
||||
|
||||
* [Zero to Nix - Nix Tutorial]
|
||||
(https://zero-to-nix.com/)
|
||||
|
||||
* [Rommel Martinez - A Gentle Introduction to the Nix Family]
|
||||
(https://web.archive.org/web/20210121042658/https://ebzzry.io/en/nix/#nix)
|
||||
|
@ -162,13 +162,13 @@ case bestellungsStatus
|
||||
//- <p class="warn">Deine Bestellung steht noch aus</p>
|
||||
|
||||
//- --INCLUDE--
|
||||
//- File path -> "includes/nav.png"
|
||||
//- File path -> "includes/nav.pug"
|
||||
h1 Firmenname
|
||||
nav
|
||||
a(href="index.html") Home
|
||||
a(href="about.html") Über uns
|
||||
|
||||
//- Dateipfad -> "index.png"
|
||||
//- Dateipfad -> "index.pug"
|
||||
html
|
||||
body
|
||||
include includes/nav.pug
|
||||
@ -205,4 +205,4 @@ mixin comment(name, kommentar)
|
||||
### Zusätzliche Ressourcen
|
||||
- [The Site](https://pugjs.org/)
|
||||
- [The Docs](https://pugjs.org/api/getting-started.html)
|
||||
- [Github Repo](https://github.com/pugjs/pug)
|
||||
- [GitHub Repo](https://github.com/pugjs/pug)
|
||||
|
@ -21,7 +21,7 @@ Diese Version wurde in pyqt erstellt.
|
||||
```python
|
||||
import sys
|
||||
from PyQt4 import QtGui
|
||||
|
||||
|
||||
def window():
|
||||
# Erschafft ein Anwendungsobjekt.
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
@ -48,10 +48,10 @@ if __name__ == '__main__':
|
||||
|
||||
Damit wir weitere fortgeschrittene Funktionen in **pyqt** verwenden können,
|
||||
müssen wir anfangen zusätzliche Elemente zu bauen.
|
||||
Hier zeigen wir wie man eine Dialog Popup Box einführt.
|
||||
Hier zeigen wir wie man eine Dialog Popup Box einführt.
|
||||
Diese ist nützlich, um den Benutzer eine Entscheidung zu bestätigen oder um Informationen anzuzeigen.
|
||||
|
||||
```Python
|
||||
```python
|
||||
import sys
|
||||
from PyQt4.QtGui import *
|
||||
from PyQt4.QtCore import *
|
||||
@ -70,7 +70,7 @@ def window():
|
||||
w.setWindowTitle("PyQt Dialog")
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
# Diese Funktion soll ein Dialogfenster mit einem Knopf erschaffen.
|
||||
# Der Knopf wartet bis er geklickt wird und beendet das Programm
|
||||
def showdialog():
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
category: tool
|
||||
tool: Qt Framework
|
||||
language: c++
|
||||
language: C++
|
||||
filename: learnqt-de.cpp
|
||||
contributors:
|
||||
- ["Aleksey Kholovchuk", "https://github.com/vortexxx192"]
|
||||
|
@ -86,14 +86,14 @@ erstellt werden, aber ich empfehle dir dafür die komplette Dokumentation zu les
|
||||
|
||||
Es gibt mehrere Möglichkeiten um Links zu machen:
|
||||
|
||||
- Wenn man einen Unterstrich hinter einem Wort hinzufügt: Github_ Zusätzlich
|
||||
- Wenn man einen Unterstrich hinter einem Wort hinzufügt: GitHub_ Zusätzlich
|
||||
muss man die Zielurl nach dem Text hinzufügen.
|
||||
(Dies hat den Vorteil, dass man keine unnötigen Urls in lesbaren Text einfügt.
|
||||
- Wenn man die vollständige Url eingibt : https://github.com/
|
||||
(Dies wird automatisch in ein Link konvertiert.)
|
||||
- Wenn man es mehr Markdown ähnlich eingibt: `Github <https://github.com/>`_ .
|
||||
- Wenn man es mehr Markdown ähnlich eingibt: `GitHub <https://github.com/>`_ .
|
||||
|
||||
.. _Github https://github.com/
|
||||
.. _GitHub https://github.com/
|
||||
|
||||
```
|
||||
|
||||
|
@ -685,4 +685,4 @@ _(z.T. auf Englisch)_
|
||||
- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
|
||||
- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - Eine ältere [freie Ausgabe](http://ruby-doc.com/docs/ProgrammingRuby/) ist online verfügbar.
|
||||
- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - Ein von der Community erstellter Ruby coding style guide.
|
||||
- [Try Ruby](http://tryruby.org) - Lerne die Grundlagen der Ruby Programmiersprache, interaktiv im Browser.
|
||||
- [Try Ruby](https://try.ruby-lang.org/) - Lerne die Grundlagen der Ruby Programmiersprache, interaktiv im Browser.
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: rust
|
||||
language: Rust
|
||||
contributors:
|
||||
- ["P1start", "http://p1start.github.io/"]
|
||||
translators:
|
||||
@ -255,7 +255,7 @@ fn main() {
|
||||
|
||||
// `for` Schleife/Iterationen
|
||||
let array = [1, 2, 3];
|
||||
for i in array.iter() {
|
||||
for i in array {
|
||||
println!("{}", i);
|
||||
}
|
||||
|
||||
|
@ -3,95 +3,92 @@ category: tool
|
||||
tool: vim
|
||||
lang: de-de
|
||||
contributors:
|
||||
- ["RadhikaG", "https://github.com/RadhikaG"]
|
||||
- ["RadhikaG", "https://github.com/RadhikaG"]
|
||||
translators:
|
||||
- ["caminsha", "https://github.com/caminsha"]
|
||||
- ["caminsha", "https://github.com/caminsha"]
|
||||
filename: LearnVim-de.txt
|
||||
---
|
||||
|
||||
|
||||
[Vim](http://www.vim.org)
|
||||
(Vi IMproved) ist ein Klon von vi, dem bekannten Editor für Unix. Es ist ein
|
||||
Texteditor, welcher mit Fokus auf Geschwindigkeit und Prouktivität entwickelt
|
||||
wurde.
|
||||
Vim hat viele Keybindings für ein schnelles navigieren und schnelles bearbeiten
|
||||
einer Datei.
|
||||
Texteditor, welcher mit Fokus auf Geschwindigkeit und Produktivität entwickelt
|
||||
wurde. Vim hat viele Keybindings für ein schnelles navigieren und schnelles
|
||||
bearbeiten einer Datei.
|
||||
|
||||
## Grundlagen, um in Vim zu navigieren
|
||||
|
||||
```
|
||||
vim <filename> # Öffne <filename> in Vim
|
||||
:help <topic> # Open up built-in help docs about <topic> if any exists
|
||||
:help <topic> # Öffne die eingebaute Hilfe zum Thema <topic>, wenn
|
||||
# es existiert
|
||||
:q # Schließe vim
|
||||
:w # Speichere diese Datei
|
||||
:wq # Speichere diese Datei und schließe vim
|
||||
ZZ # Speichere diese Datei und schließe vim
|
||||
:q! # Schließe vim ohne die Datei zu speichern
|
||||
# ! *zwingt* die Ausführung von :q,
|
||||
# daher wird die Datei nicht gespeichert.
|
||||
ZQ # Beende vim ohne die Datei zu speichern
|
||||
:x # Speichere die Datei und beende vim
|
||||
# Dies ist eine kürzere Version von :wq
|
||||
vim <filename> # Öffne <filename> in Vim
|
||||
:help <topic> # Öffne die eingebaute Hilfe zum Thema <topic>, wenn
|
||||
# es existiert
|
||||
:q # Schließe vim
|
||||
:w # Speichere diese Datei
|
||||
:wq # Speichere diese Datei und schließe vim
|
||||
ZZ # Speichere diese Datei und schließe vim
|
||||
:q! # Schließe vim ohne die Datei zu speichern
|
||||
# ! *zwingt* die Ausführung von :q,
|
||||
# daher wird die Datei nicht gespeichert.
|
||||
ZQ # Beende vim ohne die Datei zu speichern
|
||||
:x # Speichere die Datei und beende vim
|
||||
# Dies ist eine kürzere Version von :wq
|
||||
|
||||
u # Änderung rückgängig machen
|
||||
CTRL+R # Änderung wiederherstellen
|
||||
u # Änderung rückgängig machen
|
||||
CTRL+R # Änderung wiederherstellen
|
||||
|
||||
h # Den Cursor um ein Zeichen nach links bewegen
|
||||
j # Den Cursor eine Zeile nach unten bewegen
|
||||
k # Den Cursor eine Zeile nach oben bewegen
|
||||
l # Den Cursor um ein Zeichen nach rechts bewegen
|
||||
h # Den Cursor um ein Zeichen nach links bewegen
|
||||
j # Den Cursor eine Zeile nach unten bewegen
|
||||
k # Den Cursor eine Zeile nach oben bewegen
|
||||
l # Den Cursor um ein Zeichen nach rechts bewegen
|
||||
|
||||
Ctrl+B # Gehe eine Bildschirmanzeige zurück
|
||||
Ctrl+F # Gehe eine Bildschirmanzeige vorwärts
|
||||
Ctrl+D # Gehe eine halbe Bildschirmanzeige vorwärts
|
||||
Ctrl+U # Gehe eine halbe Bildschirmanzeige zurück
|
||||
Ctrl+B # Gehe eine Bildschirmanzeige zurück
|
||||
Ctrl+F # Gehe eine Bildschirmanzeige vorwärts
|
||||
Ctrl+D # Gehe eine halbe Bildschirmanzeige vorwärts
|
||||
Ctrl+U # Gehe eine halbe Bildschirmanzeige zurück
|
||||
|
||||
# Navigieren innerhalb einer Zeile
|
||||
# Navigieren innerhalb einer Zeile
|
||||
|
||||
0 # Navigiere zum Anfang der Zeile
|
||||
$ # Navigiere zum Ende der Zeile
|
||||
^ # Navigiere zum ersten Zeichen, welches kein Leerzeichen ist
|
||||
0 # Navigiere zum Anfang der Zeile
|
||||
$ # Navigiere zum Ende der Zeile
|
||||
^ # Navigiere zum ersten Zeichen, welches kein Leerzeichen ist
|
||||
|
||||
# Im Text suchen
|
||||
# Im Text suchen
|
||||
|
||||
/word # Hebt alle Ergebnisse nach dem Cursor hervor
|
||||
?word # Hebt alle Ergebnisse vor dem Cursor hervor
|
||||
n # Bewegt den Cursor zum nächsten Ergebnis nach der Suche
|
||||
N # Bewegt den Cursor zum vorherigen Ergebnis der Suche
|
||||
/word # Hebt alle Ergebnisse nach dem Cursor hervor
|
||||
?word # Hebt alle Ergebnisse vor dem Cursor hervor
|
||||
n # Bewegt den Cursor zum nächsten Ergebnis nach der Suche
|
||||
N # Bewegt den Cursor zum vorherigen Ergebnis der Suche
|
||||
|
||||
:%s/foo/bar/g # Ersetze "foo" durch "bar" in allen Zeilen
|
||||
:s/foo/bar/g # Ersetze "foo" durch "bar" in der aktuellen Zeile
|
||||
:%s/\n/\r/g # Ersetze das newline-Zeichen bei allen Zeilen durch
|
||||
# ein carriage return
|
||||
:%s/foo/bar/g # Ersetze "foo" durch "bar" in allen Zeilen
|
||||
:s/foo/bar/g # Ersetze "foo" durch "bar" in der aktuellen Zeile
|
||||
:%s/\n/\r/g # Ersetze das newline-Zeichen bei allen Zeilen durch
|
||||
# ein carriage return
|
||||
|
||||
# Zu einzelnen Zeichen springen
|
||||
# Zu einzelnen Zeichen springen
|
||||
|
||||
f<character> # Springe vorwärts und auf dem Zeichen <character>
|
||||
t<character> # Springe vorwärts und lande vor dem Zeichen <character>
|
||||
f<character> # Springe vorwärts und auf dem Zeichen <character>
|
||||
t<character> # Springe vorwärts und lande vor dem Zeichen <character>
|
||||
|
||||
# Zum Beispiel,
|
||||
f< # Springe vorwärts und lande auf <
|
||||
t< # Springe vorwärts und lande vor <
|
||||
# Zum Beispiel,
|
||||
f< # Springe vorwärts und lande auf <
|
||||
t< # Springe vorwärts und lande vor <
|
||||
|
||||
# Wortweise navigieren
|
||||
# Wortweise navigieren
|
||||
|
||||
w # Springe um ein Wort vorwärts
|
||||
b # Gehe ein Wort zurück
|
||||
e # Springe zum Ende des aktuellen Wortes
|
||||
w # Springe um ein Wort vorwärts
|
||||
b # Gehe ein Wort zurück
|
||||
e # Springe zum Ende des aktuellen Wortes
|
||||
|
||||
# Weitere Befehle, um zu navigieren
|
||||
# Weitere Befehle, um zu navigieren
|
||||
|
||||
gg # Gehe an den Start der Datei
|
||||
G # Gehe an das Ende der Datei
|
||||
:NUM # Springe zur Zeile NUM (NUM kann eine beliebige Zahl sein)
|
||||
H # Navigiere zum Start der aktuellen Bildschirmanzeige
|
||||
M # Navigiere in die Mitte der aktuellen Bildschirmanzeige
|
||||
L # Navigiere an das Ende der aktuellen Bildschirmanzeige
|
||||
gg # Gehe an den Start der Datei
|
||||
G # Gehe an das Ende der Datei
|
||||
:NUM # Springe zur Zeile NUM (NUM kann eine beliebige Zahl sein)
|
||||
H # Navigiere zum Start der aktuellen Bildschirmanzeige
|
||||
M # Navigiere in die Mitte der aktuellen Bildschirmanzeige
|
||||
L # Navigiere an das Ende der aktuellen Bildschirmanzeige
|
||||
```
|
||||
|
||||
## Hilfsdokumente:
|
||||
## Hilfsdokumente
|
||||
|
||||
Vim hat eine eingebaute Dokumentation, welche mit `:help <topic>` aufgerufen
|
||||
werden kann.
|
||||
@ -99,34 +96,33 @@ Zum Beispiel öffnet `:help navigation` die Dokumentation über das Navigieren
|
||||
|
||||
`:help` kann auch ohne ein Argument verwendet werden. Dies zeigt den Standard-
|
||||
Hilfsdialog an, welcher den Start mit vim einfacher macht.
|
||||
that aims to make getting started with vim more approachable!
|
||||
|
||||
## Modi:
|
||||
## Modi
|
||||
|
||||
Vim basiert auf dem Konzept von **modes**.
|
||||
|
||||
- Command Mode - Vim startet in diesem Modus, hier kann man navigieren und Befehle eingeben
|
||||
- Command Mode - Vims erster Modus, hier kann man navigieren und Befehle eingeben
|
||||
- Insert Mode - Wird verwendet, um Änderungen in der Datei zu machen.
|
||||
- Visual Mode - Wird verwendet, um Text zu markieren und Operationen durchzuführen
|
||||
- Visual Mode - Wird verwendet, um Text zu markieren und diesen zu verändern
|
||||
- Ex Mode - Wird verwendet, um im ':'-Prompt Befehle einzugeben
|
||||
|
||||
```
|
||||
i # Führt vim in den Insert Mode, vor der Cursorposition
|
||||
a # Führt vim in den Insert Mode, nach der Cursorposition
|
||||
v # Führt vim in den Visual Mode
|
||||
: # Führt vim in den Ex Mode
|
||||
<esc> # Führt zurück in den Command Mode, egal in welchem Mode
|
||||
# man sich gerade befindet.
|
||||
i # Führt vim in den Insert Mode, vor der Cursorposition
|
||||
a # Führt vim in den Insert Mode, nach der Cursorposition
|
||||
v # Führt vim in den Visual Mode
|
||||
: # Führt vim in den Ex Mode
|
||||
<esc> # Führt zurück in den Command Mode, egal in welchem Mode
|
||||
# man sich gerade befindet.
|
||||
|
||||
# Kopieren und einfügen von Text
|
||||
# Kopieren und einfügen von Text
|
||||
|
||||
y # Kopiere alles, was im Moment ausgewählt ist
|
||||
yy # Kopiert die aktuelle Zeile
|
||||
d # Löscht alles, was im Moment ausgewählt ist
|
||||
dd # Löscht die aktuelle Zeile
|
||||
p # Fügt den kopierten Text nach dem Cursor ein
|
||||
P # Fügt den kopierten Text vor dem Cursor ein
|
||||
x # Löscht das Zeichen unter dem Cursor
|
||||
y # Kopiere alles, was im Moment ausgewählt ist
|
||||
yy # Kopiert die aktuelle Zeile
|
||||
d # Löscht alles, was im Moment ausgewählt ist
|
||||
dd # Löscht die aktuelle Zeile
|
||||
p # Fügt den kopierten Text nach dem Cursor ein
|
||||
P # Fügt den kopierten Text vor dem Cursor ein
|
||||
x # Löscht das Zeichen unter dem Cursor
|
||||
```
|
||||
|
||||
## Die 'Grammatik' von Vim
|
||||
@ -141,68 +137,67 @@ Vim kann als Satz von Kommandos angesehen werden, welche im Format
|
||||
Einige wichtige Beispiele von 'Verb', 'Modifier' und 'Nouns':
|
||||
|
||||
```
|
||||
# 'Verb'
|
||||
# 'Verb'
|
||||
|
||||
d # löschen
|
||||
c # ändern
|
||||
y # kopieren
|
||||
v # visuelles auswählen
|
||||
d # löschen
|
||||
c # ändern
|
||||
y # kopieren
|
||||
v # visuelles auswählen
|
||||
|
||||
# 'Modifiers'
|
||||
# 'Modifiers'
|
||||
|
||||
i # innerhalb
|
||||
a # außerhalb
|
||||
NUM # Nummer (NUM kann irgendeine Zahl sein)
|
||||
f # Sucht nach etwas und landet darauf
|
||||
t # Sucht nach etwas und stoppt davor
|
||||
/ # Suche eine Zeichenfolge ab dem Cursor
|
||||
? # Suche eine Zeichenfolge vor dem Cursor
|
||||
i # innerhalb
|
||||
a # außerhalb
|
||||
NUM # Nummer (NUM kann irgendeine Zahl sein)
|
||||
f # Sucht nach etwas und landet darauf
|
||||
t # Sucht nach etwas und stoppt davor
|
||||
/ # Suche eine Zeichenfolge ab dem Cursor
|
||||
? # Suche eine Zeichenfolge vor dem Cursor
|
||||
|
||||
# 'Nouns'
|
||||
# 'Nouns'
|
||||
|
||||
w # Wort
|
||||
s # Satz
|
||||
p # Abschnitt
|
||||
b # Block
|
||||
w # Wort
|
||||
s # Satz
|
||||
p # Abschnitt
|
||||
b # Block
|
||||
|
||||
# Beispielsätze resp. Kommandos
|
||||
# Beispielsätze resp. Kommandos
|
||||
|
||||
d2w # lösche zwei Wörter
|
||||
cis # Ändere innerhalb des Satzes.
|
||||
yip # Kopiere innerhalb des Abschnitts (kopiere den Abschnitt,
|
||||
# in welchem du bist)
|
||||
ct< # Ändere bis zur spitzen Klammer
|
||||
# Ändere den Text von deiner aktuellen Cursorposition bis
|
||||
# zur nächsten spitzen Klammer
|
||||
d$ # Lösche bis zum Ende der Zeile
|
||||
d2w # lösche zwei Wörter
|
||||
cis # Ändere innerhalb des Satzes.
|
||||
yip # Kopiere innerhalb des Abschnitts (kopiere den Abschnitt,
|
||||
# in welchem du bist)
|
||||
ct< # Ändere bis zur spitzen Klammer
|
||||
# Ändere den Text von deiner aktuellen Cursorposition bis
|
||||
# zur nächsten spitzen Klammer
|
||||
d$ # Lösche bis zum Ende der Zeile
|
||||
```
|
||||
|
||||
## Einige Shortcuts und Tricks
|
||||
|
||||
```
|
||||
> # Rücke die Auswahl um einen Block ein
|
||||
< # Lösche eine Einrückung der Auswahl
|
||||
:earlier 15m # Stellt das Dokument so wieder her, wie es vor 15
|
||||
# Minuten war
|
||||
:later 15m # den oberen Befehl rückgängig machen
|
||||
ddp # Vertauschen zweier aufeinanderfolgenden Zeilen
|
||||
# Zuerst dd, dann p
|
||||
. # Wiederhole die vorherige Aktion
|
||||
:w !sudo tee % # Speichere die Datei als Root
|
||||
:set syntax=c # Stelle das Syntax-Highlighting für 'C' ein
|
||||
:sort # Alle Zeilen sortieren
|
||||
:sort! # Alle Zeilen rückwärts sortieren
|
||||
:sort u # Alle Zeilen sortieren und Duplikate entfernen
|
||||
~ # Umschalten der Groß-/Kleinschreibung des ausgewählten Textes
|
||||
u # Ausgewählten Text zu Kleinschreibung ändern
|
||||
U # Ausgewählten Text zu Großschreibung ändern
|
||||
|
||||
# Text-Folding (Textfaltung)
|
||||
zf # Erstelle eine Faltung des ausgewählten Textes
|
||||
zo # Öffne die aktuelle Faltung
|
||||
zc # Schließe die aktuelle Faltung
|
||||
zR # Öffne alle Faltungen
|
||||
zM # Schließe alle Faltungen
|
||||
> # Rücke die Auswahl um einen Block ein
|
||||
< # Lösche eine Einrückung der Auswahl
|
||||
:earlier 15m # Stellt das Dokument so wieder her, wie es vor 15 Minuten war
|
||||
:later 15m # den oberen Befehl rückgängig machen
|
||||
ddp # Vertauschen zweier aufeinanderfolgenden Zeilen
|
||||
# Zuerst dd, dann p
|
||||
. # Wiederhole die vorherige Aktion
|
||||
:w !sudo tee % # Speichere die Datei als Root
|
||||
:set syntax=c # Stelle das Syntax-Highlighting für 'C' ein
|
||||
:sort # Alle Zeilen sortieren
|
||||
:sort! # Alle Zeilen rückwärts sortieren
|
||||
:sort u # Alle Zeilen sortieren und Duplikate entfernen
|
||||
~ # Umschalten der Groß-/Kleinschreibung des ausgewählten Textes
|
||||
u # Ausgewählten Text zu Kleinschreibung ändern
|
||||
U # Ausgewählten Text zu Großschreibung ändern
|
||||
|
||||
# Text-Folding (Textfaltung)
|
||||
zf # Erstelle eine Faltung des ausgewählten Textes
|
||||
zo # Öffne die aktuelle Faltung
|
||||
zc # Schließe die aktuelle Faltung
|
||||
zR # Öffne alle Faltungen
|
||||
zM # Schließe alle Faltungen
|
||||
```
|
||||
|
||||
## Makros
|
||||
@ -213,9 +208,9 @@ Kommandos, welche du braucht, aufgenommen bis die Aufnahme gestoppt wird.
|
||||
Wenn du ein Makro ausführst, werden exakt die gleichen Schritte gemacht.
|
||||
|
||||
```
|
||||
qa # Starte das Aufnehmen des Makros 'a'
|
||||
q # Beende das Aufnehmen
|
||||
@a # Führe das Makro 'a' aus
|
||||
qa # Starte das Aufnehmen des Makros 'a'
|
||||
q # Beende das Aufnehmen
|
||||
@a # Führe das Makro 'a' aus
|
||||
```
|
||||
|
||||
### Konfigurieren mit ~/.vimrc
|
||||
|
290
de-de/visualbasic-de.html.markdown
Normal file
290
de-de/visualbasic-de.html.markdown
Normal file
@ -0,0 +1,290 @@
|
||||
---
|
||||
language: Visual Basic
|
||||
contributors:
|
||||
- ["Brian Martin", "http://brianmartin.biz"]
|
||||
translators:
|
||||
- ["Enno Nagel", "https://github.com/konfekt"]
|
||||
filename: learnvisualbasic-de.vb
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
```visualbasic
|
||||
Module Modul1
|
||||
|
||||
Sub Main()
|
||||
' Ein kurzer Blick auf Visual Basic-Konsolenanwendungen
|
||||
' bevor wir tiefer in das Thema eintauchen.
|
||||
' Das Hochkomma leitet eine Kommentarzeile ein.
|
||||
' Um dieses Tutorial innerhalb des Visual Basic Compilers zu erkunden,
|
||||
' habe ich ein Navigationssystem erstellt.
|
||||
' Dieses System wird im weiteren Verlauf des Tutorials erklärt;
|
||||
' Sie werden nach und nach verstehen, was das alles bedeutet.
|
||||
Console.Title = ("Lerne X in Y Minuten")
|
||||
Console.WriteLine ("NAVIGATION") 'Anzeige
|
||||
Console.WriteLine ("")
|
||||
Console.ForegroundColor = ConsoleColor.Green
|
||||
Console.WriteLine ("1. Ausgabe von 'Hallo, Welt'")
|
||||
Console.WriteLine ("2. Eingabe 'Hallo, Welt'")
|
||||
Console.WriteLine ("3. ganze Zahlen berechnen")
|
||||
Console.WriteLine ("4. Berechne Dezimalzahlen")
|
||||
Console.WriteLine ("5. ein funktionaler Taschenrechner")
|
||||
Console.WriteLine ("6. 'Do While'-Schleifen verwenden")
|
||||
Console.WriteLine ("7. Verwendung von 'For While'-Schleifen")
|
||||
Console.WriteLine ("8. Bedingte Anweisungen")
|
||||
Console.WriteLine ("9. Ein Getränk auswählen")
|
||||
Console.WriteLine ("50. Über")
|
||||
Console.WriteLine ("Wählen Sie eine Zahl aus der obigen Liste")
|
||||
Dim selection As String = Console.Readline()
|
||||
Select Case auswahl
|
||||
Case "1" 'Ausgabe "Hallo, Welt"
|
||||
Console.Clear() 'Löscht die Konsole und öffnet die private Subroutine
|
||||
AusgabeHalloWelt() 'Öffnet die genannte private Subroutine
|
||||
Case "2" 'Eingabe "hallo, Welt"
|
||||
Console.Clear()
|
||||
EingabeHalloWelt()
|
||||
Case "3" 'Berechne ganze Zahlen
|
||||
Console.Clear()
|
||||
BerechneGanzeZahlen()
|
||||
Case "4" 'Dezimalzahlen berechnen
|
||||
Console.Clear()
|
||||
BerechneDezimalZahlen()
|
||||
Case "5" 'Ein funktionaler Taschenrechner
|
||||
Console.Clear()
|
||||
Taschenrechner()
|
||||
Case "6" 'Verwendung von "Do While"-Schleifen
|
||||
Console.Clear()
|
||||
WhileSchleife()
|
||||
Case "7" 'Verwendung von "For While"-Schleifen
|
||||
Console.Clear()
|
||||
ForSchleife()
|
||||
Case "8" 'Bedingte Anweisungen
|
||||
Console.Clear()
|
||||
BedingteAnweisung()
|
||||
Case "9" 'If/Else-Anweisung
|
||||
Console.Clear()
|
||||
IfElseAnweisung() 'Ein Getränk auswählen
|
||||
Case "50" '"Über" Infobox
|
||||
Console.Clear()
|
||||
Console.Title = ("Lernen Sie X in Y Minuten :: Über")
|
||||
MsgBox ("Tutorial geschrieben von Brian Martin (@BrianMartinn)")
|
||||
Console.Clear()
|
||||
Main()
|
||||
Console.ReadLine()
|
||||
|
||||
End Select
|
||||
End Sub
|
||||
|
||||
'Eins - Ich habe Zahlen verwendet, um mich durch das obige Navigationssystem zu
|
||||
'führen auf das ich später zurückkomme, um es zu implementieren.
|
||||
|
||||
'wir verwenden private Unterprogramme, um verschiedene Abschnitte des Programms
|
||||
'zu trennen.
|
||||
Private Sub AusgabeHalloWelt()
|
||||
'Titel der Konsolenanwendung
|
||||
Console.Title = "Ausgabe 'Hallo, Welt' | Lerne X in Y Minuten"
|
||||
'Verwenden Sie Console.Write("") oder Console.WriteLine(""), um die Ausgabe
|
||||
'anzuzeigen, gefolgt von Console.Read(), oder Console.Readline()
|
||||
'Console.ReadLine() zeigt die Ausgabe auf der Konsole an.
|
||||
Console.WriteLine ("Hallo, Welt")
|
||||
Console.ReadLine()
|
||||
End Sub
|
||||
|
||||
'Zwei
|
||||
Private Sub EingabeHalloWelt()
|
||||
Console.Title = "Hallo, Welt, ich bin.. | Lerne X in Y Minuten"
|
||||
'Variablen
|
||||
'Vom Benutzer eingegebene Daten müssen gespeichert werden.
|
||||
'Variablen beginnen ebenfalls mit Dim und enden mit As VariableType.
|
||||
|
||||
'In diesem Lernprogramm wollen wir Ihren Namen wissen und das Programm
|
||||
'auf ihn antworten.
|
||||
Dim nutzername As String
|
||||
' Wir verwenden "String", weil es sich um eine textbasierte Variable handelt.
|
||||
Console.WriteLine ("Hallo, wie ist Ihr Name?") 'Frage nach dem Benutzernamen.
|
||||
nutzername = Console.ReadLine() 'Benutzernamen speichern.
|
||||
Console.WriteLine ("Hallo, " + nutzername) 'Ausgabe ist Hallo, Name
|
||||
Console.ReadLine() 'Die obige Ausgabe anzeigen.
|
||||
'Der obige Code stellt Ihnen eine Frage und zeigt die Antwort an.
|
||||
'Neben anderen Variablentypen gibt es Integer, den wir für ganze Zahlen
|
||||
'verwenden werden.
|
||||
End Sub
|
||||
|
||||
'Drei
|
||||
Private Sub BerechneGanzeZahlen()
|
||||
Console.Title = "Berechne ganze Zahlen | Lerne X in Y Minuten"
|
||||
Console.Write ("Erste Zahl: ") 'Schreiben Sie eine ganze Zahl, 1, 2, 104, usw
|
||||
Dim a As Integer = Console.ReadLine()
|
||||
Console.Write ("Zweite Zahl: ") 'Schreiben Sie eine weitere ganze Zahl.
|
||||
Dim b As Integer = Console.ReadLine()
|
||||
Dim c As Integer = a + b
|
||||
Console.WriteLine (c)
|
||||
Console.ReadLine()
|
||||
'Dies ist ein einfacher Taschenrechner
|
||||
End Sub
|
||||
|
||||
'Vier
|
||||
Private Sub BerechneDezimalZahlen()
|
||||
Console.Title = "Berechne mit dem Typ Double | Lerne X in Y Minuten"
|
||||
'Natürlich würden wir gerne Dezimalzahlen addieren.
|
||||
'Also könnten wir von Integer auf Double umstellen.
|
||||
|
||||
'Schreiben Sie eine Bruchzahl, 1.2, 2.4, 50.1, 104.9 usw
|
||||
Console.Write ("Erste Zahl: ")
|
||||
Dim a As Double = Console.Readline()
|
||||
Console.Write ("Zweite Zahl: ") 'Schreiben Sie die zweite Zahl.
|
||||
Dim b As Double = Console.Readline()
|
||||
Dim c As Double = a + b
|
||||
Console.WriteLine (c)
|
||||
Console.ReadLine()
|
||||
'Dieses Programm kann 1.1 und 2.2 addieren
|
||||
End Sub
|
||||
|
||||
'Fünf
|
||||
Private Sub Taschenrechner()
|
||||
Console.Title = "Der Funktionsrechner | Lerne X in Y Minuten"
|
||||
'Wenn Sie aber wollen, dass der Rechner subtrahiert, dividiert,
|
||||
'multipliziert und addiert.
|
||||
'Kopieren Sie den obigen Text und fügen Sie ihn ein.
|
||||
Console.Write ("Erste Zahl: ")
|
||||
Dim a As Double = Console.Readline()
|
||||
Console.Write ("Zweite Zahl: ")
|
||||
Dim b As Integer = Console.Readline()
|
||||
Dim c As Integer = a + b
|
||||
Dim d As Integer = a * b
|
||||
Dim e As Integer = a - b
|
||||
Dim f As Integer = a / b
|
||||
|
||||
'Mit den folgenden Zeilen können wir die Werte a und b
|
||||
'subtrahieren, multiplizieren und dividieren
|
||||
Console.Write (a.ToString() + " + " + b.ToString())
|
||||
'Wir wollen den Ergebnissen einen linken Rand von 3 Leerzeichen geben.
|
||||
Console.WriteLine (" = " + c.ToString.PadLeft(3))
|
||||
Console.Write (a.ToString() + " * " + b.ToString())
|
||||
Console.WriteLine (" = " + d.ToString.PadLeft(3))
|
||||
Console.Write (a.ToString() + " - " + b.ToString())
|
||||
Console.WriteLine (" = " + e.ToString.PadLeft(3))
|
||||
Console.Write (a.ToString() + " / " + b.ToString())
|
||||
Console.WriteLine (" = " + f.ToString.PadLeft(3))
|
||||
Console.ReadLine()
|
||||
|
||||
End Sub
|
||||
|
||||
'Sechs
|
||||
Private Sub WhileSchleife()
|
||||
'Gleich zur vorherigen privaten Subroutine.
|
||||
'Diesmal fragen wir den Benutzer, ob er fortfahren möchte (ja oder nein?).
|
||||
'Wir verwenden die Do While-Schleife, weil wir nicht wissen, ob der Benutzer
|
||||
'das Programm mehr als einmal verwenden möchte.
|
||||
Console.Title = "Do While-Schleifen verwenden | X in Y Minuten lernen"
|
||||
Dim antwort As String 'Wir verwenden "String", weil die Antwort ein Text ist
|
||||
Do 'Wir beginnen das Programm mit
|
||||
Console.Write ("Erste Zahl: ")
|
||||
Dim a As Double = Console.Readline()
|
||||
Console.Write ("Zweite Zahl: ")
|
||||
Dim b As Integer = Console.Readline()
|
||||
Dim c As Integer = a + b
|
||||
Dim d As Integer = a * b
|
||||
Dim e As Integer = a - b
|
||||
Dim f As Integer = a / b
|
||||
|
||||
Console.Write (a.ToString() + " + " + b.ToString())
|
||||
Console.WriteLine (" = " + c.ToString.PadLeft(3))
|
||||
Console.Write (a.ToString() + " * " + b.ToString())
|
||||
Console.WriteLine (" = " + d.ToString.PadLeft(3))
|
||||
Console.Write (a.ToString() + " - " + b.ToString())
|
||||
Console.WriteLine (" = " + e.ToString.PadLeft(3))
|
||||
Console.Write (a.ToString() + " / " + b.ToString())
|
||||
Console.WriteLine (" = " + f.ToString.PadLeft(3))
|
||||
Console.ReadLine()
|
||||
'Fragen Sie den Benutzer, ob er fortfahren möchte. Unglücklicherweise
|
||||
'werden Groß- und Kleinschreibung unterschieden.
|
||||
Console.Write ("Möchten Sie fortfahren? (j / n)")
|
||||
'Das Programm nimmt die Variable, zeigt sie an und beginnt von vorne.
|
||||
antwort = Console.Readline()
|
||||
'Der Befehl, der diese Variable zum Laufen bringt, ist in diesem Fall "j"
|
||||
Loop While antwort = "j"
|
||||
|
||||
End Sub
|
||||
|
||||
'Sieben
|
||||
Private Sub ForSchleife()
|
||||
'Manchmal muss das Programm nur einmal ausgeführt werden.
|
||||
'In diesem Programm werden wir von 10 loszählen.
|
||||
|
||||
Console.Title = "Mit "For"-Schleifen | X in Y Minuten lernen"
|
||||
'Deklarieren Sie die Variable und ab welcher Zahl in Schritt -1 gezählt
|
||||
'werden soll, Schritt -2, Schritt -3, usw.
|
||||
For i As Integer = 10 To 0 Schritt -1
|
||||
Console.WriteLine (i.ToString) 'Zählerwert anzeigen
|
||||
Next i 'Berechne den neuen Wert
|
||||
Console.WriteLine ("Start") 'Starten wir das Programm, baby!!!!
|
||||
Console.ReadLine() 'BANG!!!! - Vielleicht war ich zu aufgeregt :)
|
||||
End Sub
|
||||
|
||||
'Acht
|
||||
Private Sub BedingteAnweisung()
|
||||
Console.Title = "Bedingte Anweisungen | X in Y Minuten lernen"
|
||||
Dim username As String = Console.Readline()
|
||||
'Aufforderung zur Eingabe des Benutzernamens.
|
||||
Console.WriteLine ("Hallo, wie ist Ihr Name?")
|
||||
username = Console.ReadLine() 'Benutzernamen speichern.
|
||||
If username = "Adam" Then
|
||||
Console.WriteLine ("Hallo, Adam")
|
||||
Console.WriteLine ("Danke, dass Sie diese nützliche Website erstellt haben")
|
||||
Console.ReadLine()
|
||||
Else
|
||||
Console.WriteLine ("Hallo, " + Benutzername)
|
||||
Console.WriteLine ("Haben Sie www.learnxinyminutes.com besucht?")
|
||||
Console.ReadLine() 'Beendet und zeigt die obige Anweisung an.
|
||||
End If
|
||||
End Sub
|
||||
|
||||
'Neun
|
||||
Private Sub IfElseAnweisung()
|
||||
Console.Title = "If / Else-Anweisung | X in Y Minuten lernen"
|
||||
'Manchmal ist es wichtig, mehr als zwei Alternativen in Betracht zu ziehen.
|
||||
'Manchmal sind einige von ihnen besser.
|
||||
'In diesem Fall brauchen wir mehr als eine "if"-Anweisung.
|
||||
'Eine "if"-Anweisung ist für Verkaufsautomaten geeignet.
|
||||
'Der Benutzer gibt einen Code ein (A1, A2, A3), aus dem er wählen kann.
|
||||
'Alle Auswahlmöglichkeiten können in einer einzigen "if"-Anweisung
|
||||
'kombiniert werden.
|
||||
|
||||
Dim auswahl As String = Console.ReadLine 'Der Wert der Auswahl
|
||||
Console.WriteLine ("A1. für 7Up")
|
||||
Console.WriteLine ("A2. für Fanta")
|
||||
Console.WriteLine ("A3. für Dr. Pepper")
|
||||
Console.WriteLine ("A4. für Coca-Cola")
|
||||
Console.ReadLine()
|
||||
If auswahl = "A1" Dann
|
||||
Console.WriteLine ("7up")
|
||||
Console.ReadLine()
|
||||
ElseIf auswahl = "A2" Then
|
||||
Console.WriteLine ("fanta")
|
||||
Console.ReadLine()
|
||||
ElseIf auswahl = "A3" Then
|
||||
Console.WriteLine ("Dr. Pfeffer")
|
||||
Console.ReadLine()
|
||||
ElseIf auswahl = "A4" Then
|
||||
Console.WriteLine ("Coca-Cola")
|
||||
Console.ReadLine()
|
||||
Else
|
||||
Console.WriteLine ("Ein Produkt auswählen")
|
||||
Console.ReadLine()
|
||||
End If
|
||||
|
||||
End Sub
|
||||
|
||||
End Module
|
||||
```
|
||||
|
||||
## Referenzen
|
||||
|
||||
Für diejenigen, die mehr wissen wollen, hat Brian Martin ein umfassenderes
|
||||
[Visual Basic Tutorial](http://www.vbbootcamp.co.uk/ "Visual Basic Tutorial")
|
||||
erstellt.
|
||||
|
||||
Die gesamte Syntax sollte gültig sein.
|
||||
Kopieren Sie den Code und fügen Sie ihn in den Visual Basic Compiler ein und
|
||||
führen Sie das Programm aus (F5).
|
||||
|
@ -112,7 +112,7 @@ python_komplexe_Zahlen: !!python/komplex 1+2j
|
||||
####################
|
||||
|
||||
# Strings und Zahlen sind nicht die einzigen Skalare, welche YAML versteht.
|
||||
# ISO-formatierte Datumsangaben and Zeiangaben können ebenso geparsed werden.
|
||||
# ISO-formatierte Datumsangaben and Zeitangaben können ebenso geparsed werden.
|
||||
DatumZeit: 2001-12-15T02:59:43.1Z
|
||||
DatumZeit_mit_Leerzeichen: 2001-12-14 21:59:43.10 -5
|
||||
Datum: 2002-12-14
|
||||
|
@ -12,7 +12,7 @@ all began with Direct, such as Direct3D, DirectDraw, DirectMusic, DirectPlay, Di
|
||||
Direct3D (the 3D graphics API within DirectX) is widely used in the development of video games for Microsoft
|
||||
Windows and the Xbox line of consoles.<sup>[1]</sup>
|
||||
|
||||
In this tutorial we will be focusing on DirectX 9, which is not as low-level as it's sucessors, which are aimed at programmers very familiar with how graphics hardware works. It makes a great starting point for learning Direct3D. In this tutorial I will be using the Win32-API for window handling and the DirectX 2010 SDK.
|
||||
In this tutorial we will be focusing on DirectX 9, which is not as low-level as it's successors, which are aimed at programmers very familiar with how graphics hardware works. It makes a great starting point for learning Direct3D. In this tutorial I will be using the Win32-API for window handling and the DirectX 2010 SDK.
|
||||
|
||||
## Window creation
|
||||
|
||||
@ -125,7 +125,7 @@ bool InitD3D(HWND hWnd) {
|
||||
pp.hDeviceWindow = hWnd; // associated window handle
|
||||
pp.Windowed = true; // display in window mode
|
||||
pp.Flags = 0; // no special flags
|
||||
// Variable to store results of methods to check if everything succeded.
|
||||
// Variable to store results of methods to check if everything succeeded.
|
||||
HRESULT result{ };
|
||||
result = _d3d->CreateDevice(D3DADAPTER_DEFAULT, // use default graphics card
|
||||
D3DDEVTYPE_HAL, // use hardware acceleration
|
||||
@ -144,7 +144,7 @@ bool InitD3D(HWND hWnd) {
|
||||
viewport.Y = 0; // ..
|
||||
viewport.Width = clientRect.right; // use the entire window
|
||||
viewport.Height = clientRect.bottom; // ..
|
||||
viewport.MinZ = 0.0f; // minimun view distance
|
||||
viewport.MinZ = 0.0f; // minimum view distance
|
||||
viewport.MaxZ = 100.0f; // maximum view distance
|
||||
// Apply the created viewport.
|
||||
result = _device->SetViewport(&viewport);
|
||||
@ -157,7 +157,7 @@ bool InitD3D(HWND hWnd) {
|
||||
// ...
|
||||
// Back in our WinMain function we call our initialization function.
|
||||
// ...
|
||||
// Check if Direct3D initialization succeded, else exit the application.
|
||||
// Check if Direct3D initialization succeeded, else exit the application.
|
||||
if (!InitD3D(hWnd))
|
||||
return -1;
|
||||
|
||||
@ -197,7 +197,7 @@ Let's create a vertex buffer to store the vertices for our triangle
|
||||
#include <vector>
|
||||
// First we declare a new ComPtr holding a vertex buffer.
|
||||
ComPtr<IDirect3DVertexBuffer9> _vertexBuffer{ };
|
||||
// Lets define a funtion to calculate the byte size of a std::vector
|
||||
// Lets define a function to calculate the byte size of a std::vector
|
||||
template <typename T>
|
||||
unsigned int GetByteSize(const std::vector<T>& vec) {
|
||||
return sizeof(vec[0]) * vec.size();
|
||||
@ -253,7 +253,7 @@ if (!InitD3D(hWnd))
|
||||
return -1;
|
||||
// Define the vertices we need to draw a triangle.
|
||||
// Values are declared in a clockwise direction else Direct3D would cull them.
|
||||
// If you want to diable culling just call:
|
||||
// If you want to disable culling just call:
|
||||
// _device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
std::vector<VStruct> vertices {
|
||||
// Bottom left
|
||||
@ -274,7 +274,7 @@ if (!(_vertexBuffer = CreateBuffer(vertices)))
|
||||
Before we can use the vertex buffer to draw our primitives, we first need to set up the matrices.
|
||||
|
||||
```cpp
|
||||
// Lets create a new funtions for the matrix transformations.
|
||||
// Lets create a new functions for the matrix transformations.
|
||||
bool SetupTransform() {
|
||||
// Create a view matrix that transforms world space to
|
||||
// view space.
|
||||
@ -338,7 +338,7 @@ if (FAILED(result))
|
||||
// Create a world transformation matrix and set it to an identity matrix.
|
||||
D3DXMATRIX world{ };
|
||||
D3DXMatrixIdentity(&world);
|
||||
// Create a scalation matrix scaling our primitve by 10 in the x,
|
||||
// Create a scalation matrix scaling our primitive by 10 in the x,
|
||||
// 10 in the y and keeping the z direction.
|
||||
D3DXMATRIX scaling{ };
|
||||
D3DXMatrixScaling(&scaling, // matrix to scale
|
||||
@ -499,7 +499,7 @@ std::vector<D3DVERTEXELEMENT9> vertexDeclDesc {
|
||||
0, // byte offset from the struct beginning
|
||||
D3DDECLTYPE_FLOAT3, // data type (3d float vector)
|
||||
D3DDECLMETHOD_DEFAULT, // tessellator operation
|
||||
D3DDECLUSAGE_POSTION, // usage of the data
|
||||
D3DDECLUSAGE_POSITION, // usage of the data
|
||||
0 }, // index (multiples usage of the same type)
|
||||
{ 0,
|
||||
12, // byte offset (3 * sizeof(float) bytes)
|
||||
|
@ -1,147 +1,281 @@
|
||||
---
|
||||
language: docker
|
||||
filename: docker.bat
|
||||
contributors:
|
||||
- ["Ruslan López", "http://javapro.org/"]
|
||||
- ["Michael Chen", "https://github.com/ML-Chen"]
|
||||
---
|
||||
|
||||
```bat
|
||||
:: download, install and run hello-world image
|
||||
docker run hello-world
|
||||
|
||||
:: if this is the first time you should be able to see the message
|
||||
:: Unable to find image 'hello-world:latest' locally
|
||||
:: latest: Pulling from library/hello-world
|
||||
:: 1b930d010525: Pull complete
|
||||
:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
|
||||
:: Status: Downloaded newer image for hello-world:latest
|
||||
::
|
||||
:: Hello from Docker!
|
||||
:: This message shows that your installation appears to be working correctly.
|
||||
::
|
||||
:: To generate this message, Docker took the following steps:
|
||||
:: 1. The Docker client contacted the Docker daemon.
|
||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. The Docker daemon created a new container from that image which runs the
|
||||
:: executable that produces the output you are currently reading.
|
||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
:: to your terminal.
|
||||
::
|
||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Share images, automate workflows, and more with a free Docker ID:
|
||||
:: https://hub.docker.com/
|
||||
::
|
||||
:: For more examples and ideas, visit:
|
||||
:: https://docs.docker.com/get-started/
|
||||
|
||||
:: now let's see currently running images
|
||||
docker ps
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
|
||||
:: let's see the images we have ran previously
|
||||
docker ps -a
|
||||
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
|
||||
:: happy_poincare
|
||||
:: the name part is generated automatically so it probably will be different for you
|
||||
|
||||
:: let's remove our previously generated image
|
||||
docker rm happy_poincare
|
||||
|
||||
:: let's test if it was really deleted
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
|
||||
:: specify a custom name for the container
|
||||
docker run --name test_container hello-world
|
||||
:: Hello from Docker!
|
||||
:: This message shows that your installation appears to be working correctly.
|
||||
::
|
||||
:: To generate this message, Docker took the following steps:
|
||||
:: 1. The Docker client contacted the Docker daemon.
|
||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. The Docker daemon created a new container from that image which runs the
|
||||
:: executable that produces the output you are currently reading.
|
||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
:: to your terminal.
|
||||
::
|
||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Share images, automate workflows, and more with a free Docker ID:
|
||||
:: https://hub.docker.com/
|
||||
::
|
||||
:: For more examples and ideas, visit:
|
||||
:: https://docs.docker.com/get-started/
|
||||
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
|
||||
:: test_container
|
||||
:: as you can see the name is now what we have specified
|
||||
|
||||
:: retrieve logs from a named container
|
||||
docker logs test_container
|
||||
:: Hello from Docker!
|
||||
:: This message shows that your installation appears to be working correctly.
|
||||
::
|
||||
:: To generate this message, Docker took the following steps:
|
||||
:: 1. The Docker client contacted the Docker daemon.
|
||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. The Docker daemon created a new container from that image which runs the
|
||||
:: executable that produces the output you are currently reading.
|
||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
:: to your terminal.
|
||||
::
|
||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Share images, automate workflows, and more with a free Docker ID:
|
||||
:: https://hub.docker.com/
|
||||
::
|
||||
:: For more examples and ideas, visit:
|
||||
:: https://docs.docker.com/get-started/
|
||||
|
||||
docker rm test_container
|
||||
|
||||
docker run ubuntu
|
||||
:: Unable to find image 'ubuntu:latest' locally
|
||||
:: latest: Pulling from library/ubuntu
|
||||
:: 2746a4a261c9: Pull complete
|
||||
:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
|
||||
:: Status: Downloaded newer image for ubuntu:latest
|
||||
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
|
||||
:: relaxed_nobel
|
||||
|
||||
:: running a container in an interactive mode
|
||||
docker run -it ubuntu
|
||||
:: root@e2cac48323d2:/# uname
|
||||
:: Linux
|
||||
:: root@e2cac48323d2:/# exit
|
||||
:: exit
|
||||
|
||||
docker rm relaxed_nobel
|
||||
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
|
||||
:: nifty_goldwasser
|
||||
|
||||
docker rm nifty_goldwasser
|
||||
```
|
||||
---
|
||||
category: tool
|
||||
tool: docker
|
||||
filename: docker.bat
|
||||
contributors:
|
||||
- ["Ruslan López", "http://javapro.org/"]
|
||||
- ["Michael Chen", "https://github.com/ML-Chen"]
|
||||
- ["Akshita Dixit", "https://github.com/akshitadixit"]
|
||||
- ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"]
|
||||
---
|
||||
|
||||
Docker is a tool that helps you build, test, ship and run applications
|
||||
seamlessly across various machines. It replicates the environment our software
|
||||
needs on any machine. You can get Docker for your machine from
|
||||
https://docs.docker.com/get-docker/
|
||||
|
||||
It has grown in popularity over the last decade due to being lightweight and
|
||||
fast as compared to virtual-machines that are bulky and slow. Unlike VMs, docker
|
||||
does not need a full blown OS of its own to be loaded to start and does not
|
||||
compete for resources other than what the application it is running will use.
|
||||
VMs on the other hand are pretty resource intensive on our processors, disks and
|
||||
memory hence running multiple VMs for various applications becomes a challenge
|
||||
in a limited capacity architecture.
|
||||
|
||||
<pre>
|
||||
┌────────────────────────┐ ┌───────────────────────┐
|
||||
│ ┌───────────┐ │ │ ┌───────────┐ │
|
||||
│ │ App │ │ │ │ App │ │
|
||||
│ └───────────┘ │ │ └───────────┘ │
|
||||
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
|
||||
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
|
||||
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
|
||||
│ ┌───────────────────┐ │ │ ┌──────────────────┐ │
|
||||
│ │ Guest OS │ │ │ │ Guest OS │ │
|
||||
│ └───────────────────┘ │ │ └──────────────────┘ │
|
||||
│ VM1 │ │ VM2 │
|
||||
└────────────────────────┘ └───────────────────────┘
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Hypervisor │
|
||||
└──────────────────────────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Host OS │
|
||||
└──────────────────────────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Hardware Infrastructure │
|
||||
└──────────────────────────────────────────────────┘
|
||||
(VM based architecture)
|
||||
|
||||
┌────────────────────────┐ ┌───────────────────────┐
|
||||
│ ┌───────────┐ │ │ ┌───────────┐ │
|
||||
│ │ App │ │ │ │ App │ │
|
||||
│ └───────────┘ │ │ └───────────┘ │
|
||||
│ ┌────────┐ ┌────────┐ │ │ ┌────────┐ ┌───────┐ │
|
||||
│ │ Libs │ │ Deps │ │ │ │ Libs │ │ Deps │ │
|
||||
│ └────────┘ └────────┘ │ │ └────────┘ └───────┘ │
|
||||
│ Container1 │ │ Container2 │
|
||||
└────────────────────────┘ └───────────────────────┘
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Docker │
|
||||
└──────────────────────────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ OS │
|
||||
└──────────────────────────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Hardware Infrastructure │
|
||||
└──────────────────────────────────────────────────┘
|
||||
(Docker based architecture)
|
||||
|
||||
</pre>
|
||||
|
||||
Couple of terms we will encounter frequently are Docker Images and Docker
|
||||
Containers. Images are packages or templates of containers all stored in a
|
||||
container registry such as [Docker Hub](https://hub.docker.com/). Containers
|
||||
are standalone, executable instances of these images which include code,
|
||||
runtime, system tools, system libraries and settings - everything required to
|
||||
get the software up and running. Coming to Docker, it follows a client-server
|
||||
architecture wherein the CLI client communicates with the server component,
|
||||
which here is, the Docker Engine using RESTful API to issue commands.
|
||||
|
||||
## The Docker CLI
|
||||
```bash
|
||||
# after installing Docker from https://docs.docker.com/get-docker/
|
||||
# To list available commands, either run `docker` with no parameters or execute
|
||||
# `docker help`
|
||||
$ docker
|
||||
|
||||
>>> docker [OPTIONS] COMMAND [ARG...]
|
||||
docker [ --help | -v | --version ]
|
||||
|
||||
A self-sufficient runtime for containers.
|
||||
|
||||
Options:
|
||||
--config string Location of client config files (default "/root/.docker")
|
||||
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
|
||||
-D, --debug Enable debug mode
|
||||
--help Print usage
|
||||
-H, --host value Daemon socket(s) to connect to (default [])
|
||||
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
|
||||
--tls Use TLS; implied by --tlsverify
|
||||
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
|
||||
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
|
||||
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
|
||||
--tlsverify Use TLS and verify the remote
|
||||
-v, --version Print version information and quit
|
||||
|
||||
Commands:
|
||||
attach Attach to a running container
|
||||
# […]
|
||||
|
||||
$ docker run hello-world
|
||||
# `docker run <container-name>` is used to run a container, it will pull the
|
||||
# images from Docker Hub if they don't already exist in your system. Here the
|
||||
# docker client connects to the daemon which in turn pulls the "hello-world"
|
||||
# image from the Docker Hub. The daemon then builds a new container from the
|
||||
# image which runs the executable that produces the output streamed back to the
|
||||
# client that we see on our terminals.
|
||||
|
||||
$ docker run -d ubuntu sleep 60s
|
||||
# The -d (or --detach) flag is when we want to run a container in the background
|
||||
# and return back to the terminal. Here we detach an ubuntu container from the
|
||||
# terminal, the output should be the id and the command exits. If we check
|
||||
# running containers, we should still see ours there:
|
||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
# 133261b4894a ubuntu "sleep 60s" 3 seconds ago Up 2 seconds vigorous_gould
|
||||
|
||||
$ docker run <container-id> -p 3000:8000
|
||||
# The -p (or --publish) flag is used to expose port 8000 inside the container to
|
||||
# port 3000 outside the container. This is because the app inside the container
|
||||
# runs in isolation, hence the port 8000 where the app runs is private to the
|
||||
# container.
|
||||
|
||||
$ docker run -i
|
||||
# or
|
||||
$ docker run -it
|
||||
# Docker runs our containers in a non-interactive mode i.e. they do not accept
|
||||
# inputs or work dynamically while running. The -i flag keeps input open to the
|
||||
# container, and the -t flag creates a pseudo-terminal that the shell can attach
|
||||
# to (can be combined as -it)
|
||||
|
||||
$ docker ps -a
|
||||
# The `docker ps` command only shows running containers by default. To see all
|
||||
# containers, use the -a (or --all) flag
|
||||
# Running the above command should output something similar in the terminal:
|
||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
# 82f84bf6912b hello-world "/hello" 9 minutes ago Exited (0) 9 minutes ago eloquent_sammet
|
||||
|
||||
|
||||
$ docker stop hello-world
|
||||
# or
|
||||
$ docker start hello-world
|
||||
# The stop command simply stops one or more containers, and the start command
|
||||
# starts the container(s) up again! `docker start -a ubuntu` will attach our
|
||||
# detached container back to the terminal i.e. runs in the foreground
|
||||
|
||||
$ docker create alpine
|
||||
# `docker create` creates a new container for us with the image specified (here,
|
||||
# alpine), the container does not auto-start unlike `docker run`. This command
|
||||
# is used to set up a container configuration and then `docker start` to shoot
|
||||
# it up when required. Note that the status is "Created":
|
||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
# 4c71c727c73d alpine "/bin/sh" 29 seconds ago Created naughty_ritchie
|
||||
|
||||
$ docker rm 82f84
|
||||
# Removes one or more containers using their container ID.
|
||||
# P.S.: we can use only the first few characters of the entire ID to identify
|
||||
# containers
|
||||
|
||||
$ docker images
|
||||
# Displays all images and their information, created here means the latest image
|
||||
# tag updated on Docker Hub:
|
||||
# REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
# ubuntu latest a8780b506fa4 9 days ago 77.8MB
|
||||
# alpine latest 9c6f07244728 3 months ago 5.54MB
|
||||
# hello-world latest feb5d9fea6a5 13 months ago 13.3kB
|
||||
|
||||
$ docker rmi
|
||||
# Removes one or more images from your system which do not have their instances
|
||||
# (or containers as we know them) running. If the image has an attached
|
||||
# container, either delete the container first or use the -f (or --force) flag
|
||||
# to forcefully delete both the container and image.
|
||||
|
||||
$ docker pull busybox
|
||||
# The pull command downloads the specified image on our system from Docker Hub.
|
||||
|
||||
$ docker exec -it 7b272 bash
|
||||
# This command is used to run a command in the running container's default
|
||||
# directory. Here 7b272 was our ubuntu container and the above command would
|
||||
# help us interact with the container by opening a bash session.
|
||||
|
||||
$ docker logs <container-id>
|
||||
# Displays the information logged by the specified container
|
||||
# root@7b27222e4bb7:/# whoami
|
||||
# root
|
||||
# root@7b27222e4bb7:/# pwd
|
||||
# /
|
||||
# root@7b27222e4bb7:/# ls
|
||||
# bin boot dev etc home lib lib32 lib64 libx3 srv sys tmp usr var
|
||||
# root@7b27222e4bb7:/# exit
|
||||
# exit
|
||||
|
||||
# More commands can be found at https://docs.docker.com/engine/reference/commandline/docker/
|
||||
```
|
||||
## The Dockerfile
|
||||
The Dockerfile is a blueprint of a Docker image. We can mention the artifacts
|
||||
from our application along with their configurations into this file in the
|
||||
specific syntax to let anyone create a Docker image of our application.
|
||||
|
||||
### A few things to keep in mind:
|
||||
* It is always strictly named `Dockerfile` without any extensions
|
||||
* We have to build our custom image on top of some already available Docker base
|
||||
image. (there is an empty image called `scratch` which literally lets you build
|
||||
an image from scratch)
|
||||
* All capitalised commands are part of the syntax, they are not case-sensitive
|
||||
but used like a convention
|
||||
* Below is a sample Dockerfile but you can read in depth from the [official docs](https://docs.docker.com/engine/reference/builder/).
|
||||
|
||||
```Dockerfile
|
||||
FROM <base-image>
|
||||
# define base image
|
||||
|
||||
ENV USERNAME='admin'\
|
||||
PWD='****'
|
||||
# optionally define environmental variables
|
||||
|
||||
RUN apt-get update
|
||||
# run linux commands inside container env, does not affect host env
|
||||
# This executes during the time of image creation
|
||||
|
||||
COPY <src> <target>
|
||||
# executes on the host, copies files from src (usually on the host) to target
|
||||
# on the container
|
||||
|
||||
ENTRYPOINT ["some-script.sh"]
|
||||
# executes an entire script as an entrypoint
|
||||
|
||||
CMD [<args>,...]
|
||||
# always part of dockerfile, introduces entry point linux command e.g.
|
||||
# `CMD node server.js`
|
||||
# This executes after image creation only when the container from the image
|
||||
# is running.
|
||||
```
|
||||
### Build your images
|
||||
Use the `docker build` command after wrapping your application into a Docker
|
||||
image to run ( or build) it.
|
||||
|
||||
```bash
|
||||
|
||||
$ docker build <path-to-dockerfile>
|
||||
# used to build an image from the specified Dockerfile
|
||||
# instead of path we could also specify a URL
|
||||
# -t tag is optional and used to name and tag your images for e.g.
|
||||
# `$ docker build -t my-image:0.1 ./home/app`
|
||||
# rebuild images everytime you make changes in the dockerfile
|
||||
```
|
||||
|
||||
## Push your image to DockerHub
|
||||
If you want your application's Docker image to be made publicly available for
|
||||
any Docker user, you might wanna push it to the [Docker Hub](https://hub.docker.com/) which is a
|
||||
registry of Docker images. Make sure you have an account with a username and
|
||||
password on Docker Hub.
|
||||
|
||||
When pushing an image to Docker Hub, we must specify our Docker Hub username
|
||||
as part of the source image name. We need to create the target image with the
|
||||
tag name of username/image-name much like GitHub repositories.
|
||||
|
||||
```bash
|
||||
$ docker login
|
||||
# to login to Docker Hub using your username and password
|
||||
|
||||
$ docker tag <src-image>[:<src-tag>] <target-image>[:<target-tag>]
|
||||
# this tags a local src-image to a public target-image
|
||||
# e.g. `docker tag my-sample-app:1.0.0 akshitadixit/my-sample-app`
|
||||
# if tags are not specified, they're defaulted to `latest`
|
||||
|
||||
$ docker push <target-image>[:<target-tag>]
|
||||
# uploads our image to Docker Hub
|
||||
# e.g. `docker push akshitadixit/my-sample-app`
|
||||
# this image will be accessible under your profile's repositories as
|
||||
# `https://hub.docker.com/r/username/image-name`
|
||||
|
||||
```
|
||||
|
@ -59,5 +59,3 @@ for i=0 to n-1
|
||||
* [Optimal Substructure Property](https://www.geeksforgeeks.org/dynamic-programming-set-2-optimal-substructure-property/)
|
||||
* [How to solve a DP problem](https://www.geeksforgeeks.org/solve-dynamic-programming-problem/)
|
||||
* [How to write DP solutions](https://www.quora.com/Are-there-any-good-resources-or-tutorials-for-dynamic-programming-DP-besides-the-TopCoder-tutorial/answer/Michal-Danilák)
|
||||
|
||||
And a [quiz](https://www.commonlounge.com/discussion/cdbbfe83bcd64281964b788969247253) to test your knowledge.
|
||||
|
221
easylang.html.markdown
Normal file
221
easylang.html.markdown
Normal file
@ -0,0 +1,221 @@
|
||||
---
|
||||
language: Easylang
|
||||
contributors:
|
||||
- ["chkas", "https://github.com/chkas"]
|
||||
filename: easylang.el
|
||||
---
|
||||
|
||||
**Easylang** is a simple programming language with built-in graphical functions and an easy-to-use and offline usable browser IDE. Its simple syntax and semantics make it well suited as a teaching and learning programming language. You can also use it to write graphical applications that you can embed in a web page.
|
||||
|
||||
*Easylang* is statically typed and has as data types only strings and numbers (floating point), resizeable arrays of strings and numbers and arrays of arrays.
|
||||
|
||||
[The browser IDE](https://easylang.online/ide/) includes various tutorials, including one for beginners.
|
||||
|
||||
```
|
||||
print "Hello world"
|
||||
#
|
||||
# number variable (64 bit floating point)
|
||||
#
|
||||
h = 3.14
|
||||
print h
|
||||
#
|
||||
# string variable
|
||||
#
|
||||
str$ = "monkey"
|
||||
# strings can grow
|
||||
str$ &= " circus"
|
||||
print str$
|
||||
#
|
||||
# blocks end with 'end' or a dot, a newline has no
|
||||
# other meaning than a space
|
||||
#
|
||||
for i = 1 to 5
|
||||
sum += i * i
|
||||
.
|
||||
print sum
|
||||
#
|
||||
# functions have value and reference
|
||||
# parameters, no return values
|
||||
#
|
||||
func gcd a b . res .
|
||||
# a and b are value parameters
|
||||
# res is a reference parameter
|
||||
while b <> 0
|
||||
# h is a local variable, because
|
||||
# it is first used in the function
|
||||
h = b
|
||||
b = a mod b
|
||||
a = h
|
||||
.
|
||||
res = a
|
||||
.
|
||||
call gcd 120 35 r
|
||||
print r
|
||||
#
|
||||
# strings can be concatenated and numbers are
|
||||
# automatically converted to strings
|
||||
#
|
||||
print "1 + 2 = " & 1 + 2
|
||||
#
|
||||
# array of numbers
|
||||
#
|
||||
a[] = [ 2.1 3.14 3 ]
|
||||
#
|
||||
# arrays can grow
|
||||
a[] &= 4
|
||||
print a[]
|
||||
#
|
||||
# arrays, strings and numbers are copied by value
|
||||
#
|
||||
b[] = a[]
|
||||
a[] &= 4
|
||||
print a[] ; print b[]
|
||||
#
|
||||
# array swapping ist fast
|
||||
#
|
||||
swap a[] b[]
|
||||
print a[] ; print b[]
|
||||
#
|
||||
# array of strings
|
||||
#
|
||||
fruits$[] = [ "apple" "banana" "orange" ]
|
||||
#
|
||||
# for-in iterates over the elements of an array
|
||||
#
|
||||
for fruit$ in fruits$[]
|
||||
print fruit$
|
||||
.
|
||||
#
|
||||
# strings are also used for single characters
|
||||
#
|
||||
letters$[] = str_chars "ping"
|
||||
print letters$[]
|
||||
letters$[1] = "o"
|
||||
print str_join letters$[]
|
||||
#
|
||||
# 2-dimensional arrays are arrays of arrays
|
||||
# this defines 3 arrays with length 4
|
||||
#
|
||||
len a[][] 3
|
||||
for i range len a[][]
|
||||
len a[i][] 4
|
||||
.
|
||||
a[1][2] = 99
|
||||
print a[][]
|
||||
#
|
||||
# builtin functions
|
||||
if sin 90 = 1
|
||||
print "angles are in degree"
|
||||
.
|
||||
print pow 2 8
|
||||
# seconds since 1970
|
||||
print floor sys_time
|
||||
# random numbers
|
||||
print randomf
|
||||
print random 6 + 1
|
||||
#
|
||||
# hour and minutes
|
||||
print substr time_str sys_time 11 5
|
||||
#
|
||||
print str_ord "A"
|
||||
print str_chr 65
|
||||
#
|
||||
# set number format
|
||||
numfmt 0 4
|
||||
print sqrt 2
|
||||
print pi
|
||||
print logn 10
|
||||
#
|
||||
a$[] = str_split "10,15,22" ","
|
||||
print a$[]
|
||||
print 2 * number a$[0]
|
||||
print len a$[]
|
||||
print len "Hello"
|
||||
#
|
||||
# With 'break n' you can leave nested loops and a function
|
||||
#
|
||||
names$[] = [ ]
|
||||
func name2id name$ . id .
|
||||
for id range len names$[]
|
||||
if names$[id] = name$
|
||||
# leave loop and function
|
||||
break 2
|
||||
.
|
||||
.
|
||||
names$[] &= name$
|
||||
.
|
||||
call name2id "alice" id ; print id
|
||||
call name2id "bob" id ; print id
|
||||
call name2id "alice" id ; print i
|
||||
#
|
||||
# with 'repeat' you can make loops, which you can leave
|
||||
# in the loop body using 'until'
|
||||
#
|
||||
sum = 0
|
||||
repeat
|
||||
s$ = input
|
||||
until s$ = ""
|
||||
sum += number s$
|
||||
.
|
||||
print "sum: " & sum
|
||||
#
|
||||
# "input" reads a string from the "input_data" section,
|
||||
# if it exists, otherwise via a prompt.
|
||||
#
|
||||
input_data
|
||||
10
|
||||
-2
|
||||
6
|
||||
```
|
||||
|
||||
Built-in graphic primitives and event-driven programming
|
||||
|
||||
```
|
||||
# simple drawing with the mouse
|
||||
#
|
||||
set_linewidth 4
|
||||
set_color 900
|
||||
# the colors are coded from 0 to 999, with
|
||||
# the left digit specifying the red component,
|
||||
# the middle digit the green component and
|
||||
# the right digit the blue component.
|
||||
#
|
||||
on mouse_down
|
||||
down = 1
|
||||
move_pen mouse_x mouse_y
|
||||
# moves the drawing pen to the actual mouse position
|
||||
draw_circle 2
|
||||
.
|
||||
on mouse_up
|
||||
down = 0
|
||||
.
|
||||
on mouse_move
|
||||
if down = 1
|
||||
draw_line mouse_x mouse_y
|
||||
.
|
||||
.
|
||||
```
|
||||
|
||||
```
|
||||
# an animated pendulum
|
||||
#
|
||||
on animate
|
||||
# The animate event occurs after each screen refresh.
|
||||
#
|
||||
clear_screen
|
||||
move_pen 50 50
|
||||
draw_circle 1
|
||||
x = 50 + 40 * sin ang
|
||||
y = 50 - 40 * cos ang
|
||||
draw_line x y
|
||||
draw_circle 5
|
||||
vel += sin ang / 5
|
||||
ang += vel
|
||||
.
|
||||
ang = 10
|
||||
```
|
||||
|
||||
* [More about Easylang](https://easylang.online/)
|
||||
|
||||
* [Source code](https://github.com/chkas/easylang)
|
||||
|
381
el-gr/ocaml-gr.html.markdown
Normal file
381
el-gr/ocaml-gr.html.markdown
Normal file
@ -0,0 +1,381 @@
|
||||
---
|
||||
language: OCaml
|
||||
filename: learnocaml-gr.ml
|
||||
contributors:
|
||||
- ["Daniil Baturin", "http://baturin.org/"]
|
||||
translators:
|
||||
- ["Chariton Charitonidis", "https://github.com/haritonch"]
|
||||
lang: el-gr
|
||||
---
|
||||
|
||||
Η OCaml είναι μία strictly evaluated συναρτησιακή γλώσσα με κάποια στοιχεία
|
||||
προστακτικού προγραμματισμού.
|
||||
|
||||
Μαζί με την StandardML και τις διαλέκτους της, ανήκει στην οικογένεια ML γλωσσών.
|
||||
Η F# είναι επίσης αρκετά επιρρεασμένη από την OCaml.
|
||||
|
||||
Ακριβώς όπως η StandardML, η OCaml διαθέτει έναν interpreter, που μπορεί να
|
||||
χρησιμοποιηθεί διαδραστικά, αλλά και έναν compiler.
|
||||
Το εκτελέσιμο αρχείο του interpreter κανονικά έχει το όνομα "ocaml" και ο compiler
|
||||
έχει το όνομα "ocamlopt".
|
||||
Υπάρχει και ένας bytecode compiler "ocamlc", αλλά δεν υπάρχουν πολλοί λόγοι να το
|
||||
χρησιμοποιήσει κάποιος.
|
||||
|
||||
Είναι ισχυρά και στατικά τυποποιημένη. Παρ'όλα αυτά , δεν χρειάζεται ο
|
||||
προγραμματιστής να δηλώνει τους τύπους, καθώς συμπερασμός τύπων γίνεται με τον
|
||||
αλγόριθμο του συστήματος τύπων Hindley-Milner. Αυτό κάνει τις δηλώσεις τύπων μη
|
||||
αναγκαίες στις περισσότερες περιπτώσεις, αλλά μπορεί να είναι δύσκολο στην αρχή.
|
||||
|
||||
Όταν είμαστε στο toplevel της OCaml (read-eval-print-loop), η OCaml τυπώνει τον
|
||||
τύπο που συμπεραίνει όταν εισάγουμε μια έκφραση.
|
||||
|
||||
```
|
||||
# let inc x = x + 1 ;;
|
||||
val inc : int -> int = <fun>
|
||||
# let a = 99 ;;
|
||||
val a : int = 99
|
||||
```
|
||||
Για ένα source αρχείο μπορούμε να χρησιμοποιούμε την εντολή
|
||||
"ocamlc -i /path/to/file.ml" στο terminal για να τυπώσει όλα τα ονόματα και
|
||||
τους τύπους.
|
||||
|
||||
```
|
||||
$ cat sigtest.ml
|
||||
let inc x = x + 1
|
||||
let add x y = x + y
|
||||
|
||||
let a = 1
|
||||
|
||||
$ ocamlc -i ./sigtest.ml
|
||||
val inc : int -> int
|
||||
val add : int -> int -> int
|
||||
val a : int
|
||||
```
|
||||
|
||||
Σημειώστε ότι τα type signatures των συναρτήσεων με πολλά ορίσματα είναι
|
||||
γραμμένα σε curried form. Μια συνάρτηση με πολλά ορίσματα μπορεί να
|
||||
αναπαρασταθεί ως σύνθεση συναρτήσεων με μόνο ένα όρισμα.
|
||||
Η "f(x,y) = x + y" από το παράδειγμα, όταν εφαρμόζεται στα ορίσματα 2 και 3
|
||||
είναι ισοδύναμη με την εφαρμογή της "f0(y) = 2 + y" στο 3. Γι' αυτό έχει τύπο
|
||||
"int -> int -> int".
|
||||
|
||||
|
||||
```ocaml
|
||||
(*** Comments ***)
|
||||
|
||||
(* Τα σχόλια περικλείονται σε (* και *). Μπορούν να είναι και εμφωλευμένα *)
|
||||
|
||||
(* Δεν υπάρχει ειδικό σύμβολο για σχόλια μιας γραμμής *)
|
||||
|
||||
|
||||
(*** Μεταβλητές και Συναρτήσεις ***)
|
||||
|
||||
(* Οι εκφράσεις διαχωρίζονται από διπλό semicolon, ";;".
|
||||
Σε πολλές περιπτώσεις είναι περιττό, αλλά εδώ θα το χρησιμοποιούμε σε
|
||||
κάθε έκφραση για ευκολότερο copy-paste στο interpreter shell.
|
||||
Το να χρησιμοποιούμε περιττά ;; σε αρχεία κώδικα θεωρείται συνήθως
|
||||
κακό στυλιστικά. *)
|
||||
|
||||
(* Οι δηλώσεις μεταβλητών και συναρτήσεων χρησιμοποιούν το keyword "let" *)
|
||||
let x = 10 ;;
|
||||
|
||||
(* Η OCaml επιτρέπει χαρακτήρες μονών εισαγωγικών σε identifiers.
|
||||
το μονό εισαγωγικό δεν έχει κάποια σημασία σε αυτή την περίπτωση,
|
||||
χρησιμοποιείται συνήθως σε περιπτώσεις που σε άλλες γλώσσες χρησιμοποιούμε
|
||||
ονόματα όπως "foo_tmp". *)
|
||||
let foo = 1 ;;
|
||||
let foo' = foo * 2 ;;
|
||||
|
||||
(* Από τη στιγμή που ο compiler της OCaml συμπεραίνει τους τύπους αυτόματα,
|
||||
κανονικά δεν χρειάζεται να δηλώνουμε ρητά τον τύπο ορισμάτων. Παρ'όλα αυτά
|
||||
μπορούμε να το κάνουμε αν θέλουμε ή χρειάζεται *)
|
||||
let inc_int (x: int) : int = x + 1 ;;
|
||||
|
||||
(* Μία από αυτές τις περιπτώσεις που είναι αναγκαίο να δηλώσουμε ρητά τύπους
|
||||
είναι για να λύσουμε την αμφισημία μεταξύ δύο record types που έχουν πεδία με
|
||||
όμοια ονόματα. Η εναλλακτική είναι να βάλουμε αυτούς τους τύπους σε modules,
|
||||
αλλά και τα δύο αυτά θέματα είναι εκτός του σκοπού αυτού το μαθήματος. *)
|
||||
|
||||
(* Πρέπει να δηλώνουμε ότι μία συνάρτηση είναι αναδρομική με "rec". *)
|
||||
let rec factorial n =
|
||||
if n = 0 then 1
|
||||
else n * factorial (n-1)
|
||||
;;
|
||||
|
||||
(* H εφαρμογή συναρτήσεων συνήθως δεν χρειάζεται παρενθέσεις γύρω από ορίσματα *)
|
||||
let fact_5 = factorial 5 ;;
|
||||
|
||||
(* ...εκτός αν τα ορίσματα είναι εκφράσεις *)
|
||||
let fact_4 = factorial (5-1) ;;
|
||||
let sqr2 = sqr (-2) ;;
|
||||
|
||||
(* Κάθε συνάρητση πρέπει να έχει τουλάχιστον ένα όρισμα.
|
||||
Από τη στιγμή που κάποιες συναρτήσεις, από τη φύση τους, δεν παίρνουν κάποιο
|
||||
όρισμα, υπάρχει ο τύπος "unit" που έχει μόνο μία τιμή,
|
||||
την οποία γράφουμε ως "()". *)
|
||||
let print_hello () = print_endline "hello world" ;;
|
||||
|
||||
(* Προσέχετε ότι πρέπει να γράφουμε το "()" ως όρισμα και όταν την καλούμε. *)
|
||||
print_hello () ;;
|
||||
|
||||
(* Το να καλούμε μια συνάρτηση με λιγότερα ορίσματα από όσα δέχεται
|
||||
δεν προκαλεί πρόβλημα, απλά παράγει μια νέα συνάρτηση. *)
|
||||
let make_inc x y = x + y ;; (* make_inc is int -> int -> int *)
|
||||
let inc_2 = make_inc 2 ;; (* inc_2 is int -> int *)
|
||||
inc_2 3 ;; (* Αποτιμάται σε 5 *)
|
||||
|
||||
(* Μπορούμε να χρησιμοποιούμε πολλές εκφράσεις στο σώμα μιας συνάρτησης.
|
||||
Η αποτίμηση της τελευταίας έκφρασης είναι η τιμή που επιστρέφει η συνάρτηση.
|
||||
Όλες οι ενδιάμεσες εκφράσεις πρέπει να είναι τύπου "unit".
|
||||
Αυτό είναι ιδιαίτερα χρήσιμο όταν γράφουμε σε προστακτικό στυλ, η απλούστερη
|
||||
μορφή αυτού είναι η εισαγωγή ενός debug print. *)
|
||||
let print_and_return x =
|
||||
print_endline (string_of_int x);
|
||||
x
|
||||
;;
|
||||
|
||||
(* Ως συναρτησιακή γλώσσα η OCaml δεν έχει "procedures" (διαδικασίες).
|
||||
Κάθε συνάρτηση πρέπει να επιστρέφει κάτι. Οπότε, συναρτήσεις που δεν
|
||||
επιστρέφουν κάτι και καλούνται μόνο για τις παρενέργειες τους,
|
||||
όπως η print_endline, επιστρέφουν τιμή τύπου "unit". *)
|
||||
|
||||
|
||||
(* Οι ορισμοί μπορούν να γίνουν αλυσιδωτά με τη δομή "let ... in".
|
||||
Αυτό είναι περίπου το ίδιο με το να αναθέτουμε τιμές σε πολλές μεταβλητές
|
||||
πριν τις χρησιμοποιήσουμε σε εκφράσεις σε προστακτικές γλώσσες. *)
|
||||
let x = 10 in
|
||||
let y = 20 in
|
||||
x + y ;;
|
||||
|
||||
(* Εναλλακτικά μπορούμε να χρησιμποιούμε τη δομή "let ... and ... in".
|
||||
Αυτό είναι εξαιρετικά χρήσιμο για αμοιβαία αποκλειόμενες συναρτήσεις,
|
||||
όπυ με "let .. in", ο compiler θα παραπονιόταν για unbound values *)
|
||||
let rec
|
||||
is_even = function
|
||||
| 0 -> true
|
||||
| n -> is_odd (n-1)
|
||||
and
|
||||
is_odd = function
|
||||
| 0 -> false
|
||||
| n -> is_even (n-1)
|
||||
;;
|
||||
|
||||
(* Οι ανώνυμες συναρτήσεις χρησιμοποιούν την εξής σύνταξη: *)
|
||||
let my_lambda = fun x -> x * x ;;
|
||||
|
||||
(*** Τελεστές ***)
|
||||
|
||||
(* Δεν υπάρχει ιδιαίτερη διάκριση ανάμεσα σε τελεστές και συναρτήσεις.
|
||||
Κάθε τελεστής μπορεί να κληθεί ως συνάρτηση. *)
|
||||
|
||||
(+) 3 4 (* Same as 3 + 4 *)
|
||||
|
||||
(* Υπάρχει ένας αριθμός built-in τελεστών. Ένα ασυνήθιστο χαρακτηριστικό είναι
|
||||
ότι η OCaml δεν μπορεί να κάνει έμμεση μετατροπή τύπων
|
||||
ανάμεσα σε ακεραίους και floats, επίσης, χρησιμοποιεί διαφορετικούς τελεστές
|
||||
για τους floats (αριθμούς κινητής υποδιαστολής) *)
|
||||
12 + 3 ;; (* Πρόσθεση ακεραίων. *)
|
||||
12.0 +. 3.0 ;; (* Πρόσθεση κινητής υποδιαστολής. *)
|
||||
|
||||
12 / 3 ;; (* Διαίρεση ακεραίων. *)
|
||||
12.0 /. 3.0 ;; (* Διαίρεση κινητής υποδιαστολής. *)
|
||||
5 mod 2 ;; (* Υπόλοιπο. *)
|
||||
|
||||
(* Το ενός-ορίσματος μείον είναι αξιοσημείωτη εξαίρεση, είναι πολυμορφικό.
|
||||
Ωστόσο, έχει καθαρές μορφές ακεραίων και float. *)
|
||||
- 3 ;; (* Πολυμορφικό, ακέραιοι *)
|
||||
- 4.5 ;; (* Πολυμορφικό, float *)
|
||||
~- 3 (* Μόνο για integer *)
|
||||
~- 3.4 (* Type error *)
|
||||
~-. 3.4 (* Μόνο για float *)
|
||||
|
||||
(* Μπορούμε να ορίζουμε δικούς μας τελεστές ή να ξανα-ορίσουμε υπάρχοντες.
|
||||
Σε αντίθεση με την SML ή τη Haskell, μόνο ορισμένα σύμβολα μπορούν να
|
||||
χρησιμοποιηθούν για ονόματα τελεστών και το πρώτο σύμβολο ορίζει την
|
||||
επιμεριστικότητα και προτεραιότητα πράξεων. *)
|
||||
let (+) a b = a - b ;; (* και καλή τύχη στον επόμενο... *)
|
||||
|
||||
(* Πιο χρήσιμο: ένας τελεστής αντιστρόφου για floats.
|
||||
οι τελεστές ενός-ορίσματος πρέπει να ξεκινούν με "~". *)
|
||||
let (~/) x = 1.0 /. x ;;
|
||||
~/4.0 (* = 0.25 *)
|
||||
|
||||
|
||||
(*** Built-in δομές δεδομένων ***)
|
||||
|
||||
(* Οι λίστες περικλείονται από αγκύλες και τα στοιχεία τους
|
||||
διαχωρίζονται με semicolons. *)
|
||||
let my_list = [1; 2; 3] ;;
|
||||
|
||||
(* Οι tuples (προαιρετικά) περικλείονται από παρενθέσεις, τα στοιχεία τους
|
||||
διαχωρίζονται με κόμματα. *)
|
||||
let first_tuple = 3, 4 ;; (* Έχει τύπο "int * int". *)
|
||||
let second_tuple = (4, 5) ;;
|
||||
|
||||
(* Συνέπεια: αν προσπαθήσεουμε να διαχωρίσουμε τα στοιχεία μιας λίστας
|
||||
με κόμματα, θα πάρουμε μια λίστα με ένα tuple ως στοιχείο.
|
||||
Μπορεί να την πατήσουμε εύκολα έτσι. *)
|
||||
let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *)
|
||||
|
||||
(* Μπρούμε να προσπελάσουμε στοιχεία μιας λίστας με τη συνάρτηση List.nth. *)
|
||||
List.nth my_list 1 ;;
|
||||
|
||||
(* Yπάρχουν συναρτήσεις ανώτερης τάξης για λίστες, όπως οι map και filter. *)
|
||||
List.map (fun x -> x * 2) [1; 2; 3] ;;
|
||||
List.filter (fun x -> x mod 2 = 0) [1; 2; 3; 4] ;;
|
||||
|
||||
(* Μπορούμε να προσθέτουμε στοιχεία στην αρχή μιας λίστας με τον
|
||||
constructor "::", συνήθως αναφέρεται ως "cons". *)
|
||||
1 :: [2; 3] ;; (* Αποτέλεσμα: [1; 2; 3] *)
|
||||
|
||||
(* Οι πίνακες Arrays περικλείονται από [| |] *)
|
||||
let my_array = [| 1; 2; 3 |] ;;
|
||||
|
||||
(* Προσπελαύνουμε στοιχεία ενός πίνακα ως εξής: *)
|
||||
my_array.(0) ;;
|
||||
|
||||
|
||||
(*** Strings και Χαρακτήρες ***)
|
||||
|
||||
(* Χρησιμοποιούμε διπλά εισαγωγικά για τα string literals. *)
|
||||
let my_str = "Hello world" ;;
|
||||
|
||||
(* Μονά εισαγωγικά για τα literals χαρακτήρων. *)
|
||||
let my_char = 'a' ;;
|
||||
|
||||
(* Τα μονά και τα διπλά εισαγωγικά δεν είναι ισοδύναμα. *)
|
||||
let bad_str = 'syntax error' ;; (* Syntax error. *)
|
||||
|
||||
(* Αυτό μας δίνει ένα string με έναν χαρακτήρα και όχι εναν χαρακτήρα. *)
|
||||
let single_char_str = "w" ;;
|
||||
|
||||
(* Τα strings παρατίθενται με τον τελεστή "^". *)
|
||||
let some_str = "hello" ^ "world" ;;
|
||||
|
||||
(* Τα strings δεν είναι πίνακες από χαρακτήρες όπως στην C.
|
||||
Δεν μπορούμε να ανακατεύουμε strings με χαρακτήρες σε εκφράσεις.
|
||||
Μπορούμε να μετατρέπουμε χαρακτήρες σε strings με "String.make 1 my_char".
|
||||
Υπάρχουν πιο βολικές συναρτήσεις για αυτό το σκοπό σε πρόσθετες βιβλιοθήκες,
|
||||
όπως η Core.Std που μπορεί να μην έχουν εγκατασταθεί/φορτωθεί by default. *)
|
||||
let ocaml = (String.make 1 'O') ^ "Caml" ;;
|
||||
|
||||
(* Υπάρχει και μια συνάρτηση printf. *)
|
||||
Printf.printf "%d %s" 99 "bottles of beer" ;;
|
||||
|
||||
(* Υπάρχουν και συναρτήσεις read/write χωρίς μορφοποίηση. *)
|
||||
print_string "hello world\n" ;;
|
||||
print_endline "hello world" ;;
|
||||
let line = read_line () ;;
|
||||
|
||||
|
||||
(*** User-defined τύποι δεδομένων ***)
|
||||
|
||||
(* Μπορούμε να ορίζουμε τύπους δεδομένων με τη δομή "type some_type".
|
||||
Όπως σε αυτό τον άχρηστο τύπο που αντιγράφει τους ακεραίους: *)
|
||||
type my_int = int ;;
|
||||
|
||||
(* Πιο ενδιαφέροντες τύποι περιλαμβάνουν τους λεγόμενους type constructors.
|
||||
Αυτοί πρέπει να ξεκινούν με κεφαλαίο γράμμα. *)
|
||||
type ml = OCaml | StandardML ;;
|
||||
let lang = OCaml ;; (* Έχει τύπο "ml". *)
|
||||
|
||||
(* Οι type constructors δε χρειάζεται να είναι κενοί. *)
|
||||
type my_number = PlusInfinity | MinusInfinity | Real of float ;;
|
||||
let r0 = Real (-3.4) ;; (* Έχει τύπο "my_number". *)
|
||||
|
||||
(* Μπορούν να χρησιμοποιηθούν για πολυμορφική αριθμιτική *)
|
||||
type number = Int of int | Float of float ;;
|
||||
|
||||
(* Σημείο στο επίπεδο, βασικά ένα tuple περιορισμένου συγκεκριμένου τύπου *)
|
||||
type point2d = Point of float * float ;;
|
||||
let my_point = Point (2.0, 3.0) ;;
|
||||
|
||||
(* Οι τύποι μπορούν να είναι παραμετροποιημένοι, όπως σε αυτόν τον τύπο για
|
||||
λίστες λίστών με οτιδήποτε τύπου στοιχεία. Το 'a μπορεί να αντικατασταθεί από
|
||||
οποιονδήποτε τύπο. *)
|
||||
type 'a list_of_lists = 'a list list ;;
|
||||
type int_list_list = int list_of_lists ;;
|
||||
|
||||
(* Οι τύποι μπορούν επίσης να ορίζονται αναδρομικά. Σαν αυτόν εδώ τον τύπο που
|
||||
είναι ανάλογος της built in λίστας από ακεραίους. *)
|
||||
type my_int_list = EmptyList | IntList of int * my_int_list ;;
|
||||
let l = IntList (1, EmptyList) ;;
|
||||
|
||||
|
||||
(*** Ταίριασμα Προτύπων - Pattern Matching ***)
|
||||
|
||||
(* Το ταίριασμα προτύπων είναι κάπως σαν το switch statement σε προστακτικές
|
||||
γλώσσες προγραμματισμού, αλλά παρέχει πολύ μεγαλύτερη εκφραστική ισχύ.
|
||||
|
||||
Παρόλο που φαίνεται περίπλοκο, στην πραγματικότητα είναι απλώς ταίριασμα
|
||||
ενός ορίσματος με μια συγκεκριμένη τιμή, ένα κατηγόρημα ή έναν type constructor
|
||||
Το σύστημα τύπων είναι αυτό που το κάνει τόσο ισχυρό. *)
|
||||
|
||||
(** Ταίριασμα με ακριβείς τιμές. **)
|
||||
|
||||
let is_zero x =
|
||||
match x with
|
||||
| 0 -> true
|
||||
| _ -> false (* Το "_" σημαίνει "οτιδήποτε άλλο". *)
|
||||
;;
|
||||
|
||||
(* Εναλλακτικά μπορούμε να χρησιμοποιούμε το keyword "function". *)
|
||||
let is_one = function
|
||||
| 1 -> true
|
||||
| _ -> false
|
||||
;;
|
||||
|
||||
(* Ταίριασμα με κατηγορήματα, γνωστό και ως "guarded pattern matching". *)
|
||||
let abs x =
|
||||
match x with
|
||||
| x when x < 0 -> -x
|
||||
| _ -> x
|
||||
;;
|
||||
|
||||
abs 5 ;; (* 5 *)
|
||||
abs (-5) ;; (* 5 πάλι *)
|
||||
|
||||
(** Ταίριασμα με type constructors **)
|
||||
|
||||
type animal = Dog of string | Cat of string ;;
|
||||
|
||||
let say x =
|
||||
match x with
|
||||
| Dog x -> x ^ " says woof"
|
||||
| Cat x -> x ^ " says meow"
|
||||
;;
|
||||
|
||||
say (Cat "Fluffy") ;; (* "Fluffy says meow". *)
|
||||
|
||||
(** Διάσχιση δομών δεδομένων με ταίριασμα προτύπων **)
|
||||
|
||||
(* Οι αναδρομικοί τύποι μπορούν να διασχιστούν εύκολα με ταίριασμα προτύπων.
|
||||
Ας δούμε πώς μπορούμε να διασχίσουμε μια λίστα.
|
||||
Παρόλο που το built-in cons ("::") μοιάζει με infix τελεστή,
|
||||
στην πραγματικότητα είναι ένας type constructor και μπορεί να
|
||||
ταιριαστεί όπως όλοι οι type constructors. *)
|
||||
let rec sum_list l =
|
||||
match l with
|
||||
| [] -> 0
|
||||
| head :: tail -> head + (sum_list tail)
|
||||
;;
|
||||
|
||||
sum_list [1; 2; 3] ;; (* Αποτιμάται σε 6 *)
|
||||
|
||||
(* Η built-in συνταξη των cons εμποδίζει τη δομή λίγο, γι αυτό θα φτιάξουμε
|
||||
το δικό μας τύπο λίστας για την παρουσίαση. *)
|
||||
type int_list = Nil | Cons of int * int_list ;;
|
||||
let rec sum_int_list l =
|
||||
match l with
|
||||
| Nil -> 0
|
||||
| Cons (head, tail) -> head + (sum_int_list tail)
|
||||
;;
|
||||
|
||||
let t = Cons (1, Cons (2, Cons (3, Nil))) ;;
|
||||
sum_int_list t ;;
|
||||
```
|
||||
|
||||
## Περισσότερα για την OCaml
|
||||
|
||||
* Επισκεφθείτε την επίσημη σελίδα της OCaml για να κατεβάσετε τον compiler και να διαβάσετε το documentation: <http://ocaml.org/>
|
||||
* Δοκιμάστε διαδραστικά μαθήματα και έναν web-based interpreter από την OCaml Pro: <http://try.ocamlpro.com/>
|
@ -62,7 +62,7 @@ fn add2(x: i32, y: i32) -> i32 {
|
||||
fn main() {
|
||||
// Αριθμοί //
|
||||
|
||||
// Αμετάβλητη σύνδεση
|
||||
// Αμετάβλητη δέσμευση (η τιμή που αντιστοιχεί στο όνομα "x" δεν μπορεί να αλλάξει)
|
||||
let x: i32 = 1;
|
||||
|
||||
// Καταλήξεις integer/float
|
||||
@ -80,7 +80,8 @@ fn main() {
|
||||
// Πράξεις
|
||||
let sum = x + y + 13;
|
||||
|
||||
// Μη-αμετάβλητη αξία (με την έννοια ότι μπορεί να αλλάξει)
|
||||
// Μεταβλητές (με την έννοια των προστακτικών γλωσσών προγραμματισμού).
|
||||
// Στη Rust η αμετάβλητη δέσμευση είναι στάνταρ. Το mut δηλώνει μεταβλητότητα.
|
||||
let mut mutable = 1;
|
||||
mutable = 4;
|
||||
mutable += 2;
|
||||
@ -96,7 +97,7 @@ fn main() {
|
||||
// A `String` – a heap-allocated string
|
||||
let s: String = "καλημέρα κόσμε".to_string();
|
||||
|
||||
// Ένα κομμάτι αλφαριθμητικού (string slice) – μια μη-μεταβλητή οπτική γωνία προς ένα άλλο αλφαριθμητικό
|
||||
// Ένα κομμάτι αλφαριθμητικού (string slice) – μια αμετάβλητη οπτική γωνία προς ένα άλλο αλφαριθμητικό
|
||||
// Το αλφαριθμητικό μπορεί να είναι στατικό όπως τα σταθερά αλφαριθμητικά, ή να περιλαμβάνεται σε ένα άλλο,
|
||||
// δυναμικό αντικείμενο (σε αυτή την περίπτωση τη μεταβλητή `s`)
|
||||
let s_slice: &str = &s;
|
||||
@ -112,7 +113,7 @@ fn main() {
|
||||
let mut vector: Vec<i32> = vec![1, 2, 3, 4];
|
||||
vector.push(5);
|
||||
|
||||
// Ένα κομμάτι – μια μη-μεταβλητή οπτική γωνία προς ένα διάνυσμα ή πίνακα
|
||||
// Ένα κομμάτι – μια αμετάβλητη οπτική γωνία προς ένα διάνυσμα ή πίνακα
|
||||
// Είναι παρόμοιο με το κομμάτι αλφαριθμητικού που είδαμε προηγουμένως
|
||||
let slice: &[i32] = &vector;
|
||||
|
||||
@ -121,10 +122,10 @@ fn main() {
|
||||
|
||||
// Tuples (πλειάδες) //
|
||||
|
||||
// Ένα tuple είναι μια σταθερού μεγέθους σειρά από αξίες (πιθανά διαφορετικού τύπου)
|
||||
// Ένα tuple είναι μια σταθερού μεγέθους σειρά από τιμές (πιθανά διαφορετικού τύπου)
|
||||
let x: (i32, &str, f64) = (1, "καλημέρα", 3.4);
|
||||
|
||||
// Μπορούμε να χρησιμοποιήσουμε το `let` και ένα tuple για να δώσουμε πολλές αξίες σε πολλές μεταβλητές ταυτόχρονα
|
||||
// Μπορούμε να χρησιμοποιήσουμε το `let` και ένα tuple για να δώσουμε πολλές τιμές σε πολλές μεταβλητές ταυτόχρονα
|
||||
// (destructuring `let`)
|
||||
let (a, b, c) = x;
|
||||
println!("{} {} {}", a, b, c); // 1 καλημέρα 3.4
|
||||
@ -185,7 +186,7 @@ fn main() {
|
||||
fn bar(&self) -> &T { // Δανειζόμαστε το self
|
||||
&self.bar
|
||||
}
|
||||
fn bar_mut(&mut self) -> &mut T { // Δανειζόμαστε το self ως μη-αμετάβλητη αξία
|
||||
fn bar_mut(&mut self) -> &mut T { // Γίνεται "μεταβλητός δανεισμός" του self (μπορούμε να το τροποποιήσουμε)
|
||||
&mut self.bar
|
||||
}
|
||||
fn into_bar(self) -> T { // Εδώ το self καταναλώνεται
|
||||
@ -240,9 +241,9 @@ fn main() {
|
||||
// 4. Έλεγχος ροής //
|
||||
/////////////////////
|
||||
|
||||
// Βρόγχοι `for`
|
||||
// Βρόχοι `for`
|
||||
let array = [1, 2, 3];
|
||||
for i in array.iter() {
|
||||
for i in array {
|
||||
println!("{}", i);
|
||||
}
|
||||
|
||||
@ -253,7 +254,7 @@ fn main() {
|
||||
println!("");
|
||||
// Τυπώνει `0 1 2 3 4 5 6 7 8 9 `
|
||||
|
||||
// Βρόγχοι `if`
|
||||
// `if` (υπό συνθήκη διακλάδωση)
|
||||
if 1 == 1 {
|
||||
println!("Τα μαθηματικά δουλεύουν!");
|
||||
} else {
|
||||
@ -267,17 +268,17 @@ fn main() {
|
||||
"κακό"
|
||||
};
|
||||
|
||||
// Βρόγχοι `while`
|
||||
// Βρόχοι `while`
|
||||
while 1 == 1 {
|
||||
println!("Το σύμπαν λειτουργεί κανονικά.");
|
||||
// Μπορούμε να βγούμε από το βρόγχο με το `break`
|
||||
// Μπορούμε να βγούμε από το βρόχο με το `break`
|
||||
break
|
||||
}
|
||||
|
||||
// Ατέρμονος βρόχγος
|
||||
// Ατέρμονος βρόχος
|
||||
loop {
|
||||
println!("Καλημέρα!");
|
||||
// Μπορούμε να βγούμε από το βρόγχο με το `break`
|
||||
// Μπορούμε να βγούμε από το βρόχο με το `break`
|
||||
break
|
||||
}
|
||||
|
||||
@ -294,11 +295,11 @@ fn main() {
|
||||
*now_its_mine += 2;
|
||||
|
||||
println!("{}", now_its_mine); // 7
|
||||
// println!("{}", mine); // Αυτό παράγει λάθος κατά τη μεταγλώττιση διότι τώρα ο δείκτης ανοίκει στο `now_its_mine`
|
||||
// println!("{}", mine); // Αυτό παράγει λάθος κατά τη μεταγλώττιση διότι τώρα ο δείκτης ανήκει στο `now_its_mine`
|
||||
|
||||
// Reference (αναφορά) – ένας αμετάβλητος δείκτης που αναφέρεται σε άλλα δεδομένα
|
||||
// Όταν μια αναφορά δίνεται σε μια αξία, λέμε πως η αξία έχει "δανειστεί".
|
||||
// Όταν μια αξία δανείζεται αμετάβλητα, δεν μπορεί να είναι mutated (να μεταβληθεί) ή να μετακινηθεί.
|
||||
// Όταν μια αναφορά δίνεται σε μια τιμή, λέμε πως η τιμή έχει "δανειστεί".
|
||||
// Όταν μια τιμή δανείζεται αμετάβλητα, δεν μπορεί να είναι mutated (να μεταβληθεί) ή να μετακινηθεί.
|
||||
// Ένας "δανεισμός" παραμένει ενεργός μέχρι την τελευταία χρήση της μεταβλητής που δανείζεται.
|
||||
let mut var = 4;
|
||||
var = 3;
|
||||
@ -313,13 +314,13 @@ fn main() {
|
||||
var = 2; // Η `ref_var` δεν χρησιμοποιείται από εδώ και στο εξής, άρα ο "δανεισμός" τελειώνει
|
||||
|
||||
// Μεταβλητή αναφορά
|
||||
// Όσο μια αξία είναι μεταβλητά δανεισμένη, παραμένει τελείως απροσβάσιμη.
|
||||
// Όσο μια τιμή είναι μεταβλητά δανεισμένη, παραμένει τελείως απροσβάσιμη.
|
||||
let mut var2 = 4;
|
||||
let ref_var2: &mut i32 = &mut var2;
|
||||
*ref_var2 += 2; // Ο αστερίσκος (*) χρησιμοποιείται ως δείκτης προς την μεταβλητά δανεισμένη `var2`
|
||||
|
||||
println!("{}", *ref_var2); // 6 , // Αν είχαμε `var2` εδώ θα προκαλούνταν λάθος μεταγλώττισης.
|
||||
// O τύπος της `ref_var2` είναι &mut i32, άρα αποθηκεύει μια αναφορά προς μια αξία i32, όχι την αξία την ίδια.
|
||||
// O τύπος της `ref_var2` είναι &mut i32, άρα αποθηκεύει μια αναφορά προς μια τιμή i32, όχι την τιμή την ίδια.
|
||||
// var2 = 2; // Λάθος μεταγλώττισης, γιατί η `var2` είναι δανεισμένη.
|
||||
ref_var2; // Εντολή no-op (τίποτα δεν εκτελείται από τον επεξεργαστή), η οποία όμως μετράει ως χρήση και κρατά τον
|
||||
// "δανεισμό" ενεργό
|
||||
|
@ -3,7 +3,7 @@ category: tool
|
||||
tool: vim
|
||||
contributors:
|
||||
- ["RadhikaG", "https://github.com/RadhikaG"]
|
||||
filename: LearnVim.txt
|
||||
filename: LearnVim-gr.txt
|
||||
lang: el-gr
|
||||
---
|
||||
|
||||
|
@ -3,6 +3,7 @@ language: elisp
|
||||
contributors:
|
||||
- ["Bastien Guerry", "https://bzg.fr"]
|
||||
- ["Saurabh Sandav", "http://github.com/SaurabhSandav"]
|
||||
- ["rilysh", "https://github.com/rilysh"]
|
||||
filename: learn-emacs-lisp.el
|
||||
---
|
||||
|
||||
@ -12,11 +13,11 @@ filename: learn-emacs-lisp.el
|
||||
;; First make sure you read this text by Peter Norvig:
|
||||
;; http://norvig.com/21-days.html
|
||||
;;
|
||||
;; Then install GNU Emacs 24.3:
|
||||
;; Then install latest version of GNU Emacs:
|
||||
;;
|
||||
;; Debian: apt-get install emacs (or see your distro instructions)
|
||||
;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg
|
||||
;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip
|
||||
;; OSX: https://emacsformacosx.com/
|
||||
;; Windows: https://ftp.gnu.org/gnu/emacs/windows/
|
||||
;;
|
||||
;; More general information can be found at:
|
||||
;; http://www.gnu.org/software/emacs/#Obtaining
|
||||
@ -76,12 +77,12 @@ filename: learn-emacs-lisp.el
|
||||
;; `C-j' inserts the result of the evaluation in the buffer.
|
||||
|
||||
;; `C-xC-e' displays the same result in Emacs bottom line,
|
||||
;; called the "minibuffer". We will generally use `C-xC-e',
|
||||
;; called the "echo area". We will generally use `C-xC-e',
|
||||
;; as we don't want to clutter the buffer with useless text.
|
||||
|
||||
;; `setq' stores a value into a variable:
|
||||
(setq my-name "Bastien")
|
||||
;; `C-xC-e' => "Bastien" (displayed in the mini-buffer)
|
||||
;; `C-xC-e' => "Bastien" (displayed in the echo area)
|
||||
|
||||
;; `insert' will insert "Hello!" where the cursor is:
|
||||
(insert "Hello!")
|
||||
@ -343,3 +344,9 @@ filename: learn-emacs-lisp.el
|
||||
;; To read an online introduction to Emacs Lisp:
|
||||
;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
|
||||
```
|
||||
|
||||
### Further Reading
|
||||
- [GNU Elisp Manual](https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html)
|
||||
- [Emacs Wiki](https://www.emacswiki.org/emacs/LearningEmacs)
|
||||
- [Emacs Docs](https://emacsdocs.org/docs/elisp/Emacs-Lisp)
|
||||
- [Mpre Elisp Docs](https://www.math.utah.edu/docs/info/elisp_22.html)
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: elixir
|
||||
language: Elixir
|
||||
contributors:
|
||||
- ["Joao Marques", "https://github.com/mrshankly"]
|
||||
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
||||
@ -13,16 +13,15 @@ It's fully compatible with Erlang, but features a more standard syntax
|
||||
and many more features.
|
||||
|
||||
```elixir
|
||||
|
||||
# Single line comments start with a number symbol.
|
||||
|
||||
# There's no multi-line comment,
|
||||
# but you can stack multiple comments.
|
||||
|
||||
# To use the elixir shell use the `iex` command.
|
||||
# To use the Elixir shell use the `iex` command.
|
||||
# Compile your modules with the `elixirc` command.
|
||||
|
||||
# Both should be in your path if you installed elixir correctly.
|
||||
# Both should be in your path if you installed Elixir correctly.
|
||||
|
||||
## ---------------------------
|
||||
## -- Basic types
|
||||
@ -33,7 +32,7 @@ and many more features.
|
||||
0x1F # integer
|
||||
3.0 # float
|
||||
|
||||
# Atoms, that are literals, a constant with name. They start with `:`.
|
||||
# Atoms are constants whose values are their own name. They start with `:`.
|
||||
:hello # atom
|
||||
|
||||
# Tuples that are stored contiguously in memory.
|
||||
@ -50,7 +49,7 @@ elem({1, 2, 3}, 0) #=> 1
|
||||
head #=> 1
|
||||
tail #=> [2,3]
|
||||
|
||||
# In elixir, just like in Erlang, the `=` denotes pattern matching and
|
||||
# In Elixir, just like in Erlang, the `=` denotes pattern matching and
|
||||
# not an assignment.
|
||||
#
|
||||
# This means that the left-hand side (pattern) is matched against a
|
||||
@ -83,7 +82,7 @@ string.
|
||||
<<?a, ?b, ?c>> #=> "abc"
|
||||
[?a, ?b, ?c] #=> 'abc'
|
||||
|
||||
# `?a` in elixir returns the ASCII integer for the letter `a`
|
||||
# `?a` in Elixir returns the ASCII integer for the letter `a`
|
||||
?a #=> 97
|
||||
|
||||
# To concatenate lists use `++`, for binaries use `<>`
|
||||
@ -116,7 +115,7 @@ genders.gillian #=> "female"
|
||||
5 * 2 #=> 10
|
||||
10 / 2 #=> 5.0
|
||||
|
||||
# In elixir the operator `/` always returns a float.
|
||||
# In Elixir the operator `/` always returns a float.
|
||||
|
||||
# To do integer division use `div`
|
||||
div(10, 2) #=> 5
|
||||
@ -174,7 +173,7 @@ else
|
||||
"This will"
|
||||
end
|
||||
|
||||
# Remember pattern matching? Many control-flow structures in elixir rely on it.
|
||||
# Remember pattern matching? Many control-flow structures in Elixir rely on it.
|
||||
|
||||
# `case` allows us to compare a value against many patterns:
|
||||
case {:one, :two} do
|
||||
@ -307,7 +306,7 @@ Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||
# Geometry.area({:circle, "not_a_number"})
|
||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||
|
||||
# Due to immutability, recursion is a big part of elixir
|
||||
# Due to immutability, recursion is a big part of Elixir
|
||||
defmodule Recursion do
|
||||
def sum_list([head | tail], acc) do
|
||||
sum_list(tail, acc + head)
|
||||
@ -382,7 +381,7 @@ end
|
||||
## ---------------------------
|
||||
|
||||
# Elixir relies on the actor model for concurrency. All we need to write
|
||||
# concurrent programs in elixir are three primitives: spawning processes,
|
||||
# concurrent programs in Elixir are three primitives: spawning processes,
|
||||
# sending messages and receiving messages.
|
||||
|
||||
# To start a new process we use the `spawn` function, which takes a function
|
||||
|
@ -224,7 +224,7 @@ List.map : (a -> b) -> List a -> List b
|
||||
-- Comparable allows you to order numbers and strings, like a < b.
|
||||
-- Appendable things can be combined with a ++ b.
|
||||
|
||||
{-- Type Aliases and Union Types --}
|
||||
{-- Type Aliases and Custom Types --}
|
||||
|
||||
-- When you write a record or tuple, its type already exists.
|
||||
-- (Notice that record types use colon and record values use equals.)
|
||||
@ -244,28 +244,28 @@ otherOrigin =
|
||||
-- But it's still the same type, so you can equate them.
|
||||
origin == otherOrigin -- True
|
||||
|
||||
-- By contrast, defining a union type creates a type that didn't exist before.
|
||||
-- A union type is so called because it can be one of many possibilities.
|
||||
-- Each of the possibilities is represented as a "tag".
|
||||
-- By contrast, defining a custom type creates a type that didn't exist before.
|
||||
-- A custom type is so called because it can be one of many possibilities.
|
||||
-- Each of the possibilities is represented as a "type variant".
|
||||
type Direction =
|
||||
North | South | East | West
|
||||
|
||||
-- Tags can carry other values of known type. This can work recursively.
|
||||
-- Type variants can carry other values of known type. This can work recursively.
|
||||
type IntTree =
|
||||
Leaf | Node Int IntTree IntTree
|
||||
-- "Leaf" and "Node" are the tags. Everything following a tag is a type.
|
||||
-- "Leaf" and "Node" are the type variants. Everything following a type variant is a type.
|
||||
|
||||
-- Tags can be used as values or functions.
|
||||
-- Type variants can be used as values or functions.
|
||||
root : IntTree
|
||||
root =
|
||||
Node 7 Leaf Leaf
|
||||
|
||||
-- Union types (and type aliases) can use type variables.
|
||||
-- Custom types (and type aliases) can use type variables.
|
||||
type Tree a =
|
||||
Leaf | Node a (Tree a) (Tree a)
|
||||
-- "The type tree-of-a is a leaf, or a node of a, tree-of-a, and tree-of-a."
|
||||
|
||||
-- Pattern match union tags. The uppercase tags will be matched exactly. The
|
||||
-- Pattern match variants in a custom type. The uppercase variants will be matched exactly. The
|
||||
-- lowercase variables will match anything. Underscore also matches anything,
|
||||
-- but signifies that you aren't using it.
|
||||
leftmostElement : Tree a -> Maybe a
|
||||
@ -289,7 +289,7 @@ module Name where
|
||||
-- By default, everything is exported. You can specify exports explicitly.
|
||||
module Name (MyType, myValue) where
|
||||
|
||||
-- One common pattern is to export a union type but not its tags. This is known
|
||||
-- One common pattern is to export a custom type but not its type variants. This is known
|
||||
-- as an "opaque type", and is frequently used in libraries.
|
||||
|
||||
-- Import code from other modules to use it in this one.
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
language: erlang
|
||||
contributors:
|
||||
- ["Giovanni Cappellotto", "http://www.focustheweb.com/"]
|
||||
- ["Giovanni Cappellotto", "http://giovanni.curlybrackets.it/"]
|
||||
filename: learnerlang.erl
|
||||
---
|
||||
|
||||
|
@ -16,6 +16,7 @@ lang: es-es
|
||||
El API del **Módulo de Definición Asíncrono** especifica un mecanismo para definir módulos JavaScript de manera tal que tanto el módulo como sus dependencias puedan ser cargadas de manera asíncrona. Esto es particularmente adecuado para el entorno del navegador donde la carga sincronizada de los módulos genera problemas de rendimiento, usabilidad, depuración y acceso de multi-dominios.
|
||||
|
||||
### Conceptos básicos
|
||||
|
||||
```javascript
|
||||
// El API básico de AMD consiste en tan solo dos métodos: `define` y `require`
|
||||
// y se basa en la definición y consumo de los módulos:
|
||||
@ -137,6 +138,7 @@ require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolL
|
||||
coolLib.doFancyStuffWith(helpers.transform($('#foo')));
|
||||
});
|
||||
```
|
||||
|
||||
Las aplicaciones basadas en `require.js` usualmente tendrán un solo punto de entrada (`main.js`) que se pasa a la etiqueta del script `require.js` como un atributo de datos. Será cargado y ejecutado automáticamente al cargar la página:
|
||||
|
||||
```html
|
||||
@ -158,16 +160,19 @@ Muchas personas prefieren usar AMD para la organización del código durante el
|
||||
`require.js` incluye un script llamado `r.js` (el que probablemente correrás en node.js, aunque Rhino también es soportado) que puede analizar el gráfico de dependencias de tu proyecto, y armar un solo fichero que contenga todos tus módulos (adecuadamente nombrados), minificado y listo para consumo.
|
||||
|
||||
Instálalo usando `npm`:
|
||||
|
||||
```shell
|
||||
$ npm install requirejs -g
|
||||
```
|
||||
|
||||
Ahora puedes alimentarlo con un fichero de configuración:
|
||||
|
||||
```shell
|
||||
$ r.js -o app.build.js
|
||||
```
|
||||
|
||||
Para nuestro ejemplo anterior el archivo de configuración luciría así:
|
||||
|
||||
```javascript
|
||||
/* file : app.build.js */
|
||||
({
|
||||
@ -184,6 +189,7 @@ Para nuestro ejemplo anterior el archivo de configuración luciría así:
|
||||
```
|
||||
|
||||
Para usar el fichero creado en producción, simplemente intercambia `data-main`:
|
||||
|
||||
```html
|
||||
<script src="require.js" data-main="app/main-built"></script>
|
||||
```
|
||||
|
@ -5,7 +5,7 @@ contributors:
|
||||
translators:
|
||||
- ["Abel Salgado Romero", "https://twitter.com/abelsromero"]
|
||||
lang: es-es
|
||||
filename: asciidoc-es.md
|
||||
filename: asciidoc-es.adoc
|
||||
---
|
||||
|
||||
AsciiDoc es un lenguaje de marcas similar a Markdown que puede ser usado para cualquier uso, desde libros a blogs.
|
||||
|
@ -11,8 +11,8 @@ lang: es-es
|
||||
|
||||
AWK es una herramienta estándar en cada sistema UNIX compatible con POSIX.
|
||||
Es como un Perl restringido, perfecto para tareas de procesamiento de texto y
|
||||
otras necesidades de scripting. Tiene una sintaxis similar a C, pero sin
|
||||
puntos y comas, manejo manual de memoria y tipado estático. Puedes llamarlo
|
||||
otras necesidades de scripting. Tiene una sintaxis similar a C, pero sin
|
||||
puntos y comas, manejo manual de memoria y tipado estático. Puedes llamarlo
|
||||
desde un script de shell o usarlo como un lenguaje stand-alone para scripting.
|
||||
|
||||
¿Por qué elegir AWK sobre Perl? Principalmente, porque AWK es parte de UNIX.
|
||||
@ -74,8 +74,8 @@ BEGIN {
|
||||
|
||||
# Bloques formados por múltiples líneas usan llaves
|
||||
while (a < 10) {
|
||||
print "La concatenación de strings se hace " " con series "
|
||||
print " de" " strings separados por espacios"
|
||||
print "La concatenación de strings se hace " " con series "
|
||||
print " de" " strings separados por espacios"
|
||||
print a
|
||||
|
||||
a++
|
||||
@ -153,13 +153,13 @@ function arithmetic_functions(a, b, c, localvar) {
|
||||
# Todo es global. No es problema en scripts pequeños, pero sí para
|
||||
# scripts más grandes.
|
||||
|
||||
# Hay un work-around (mmm... hack). Los argumentos de las funciones son
|
||||
# Hay un work-around (mmm... hack). Los argumentos de las funciones son
|
||||
# locales para la función, y AWK permite definir más argumentos de función
|
||||
# de los que necesita, por lo que define las variables locales en la
|
||||
# de los que necesita, por lo que define las variables locales en la
|
||||
# declaración como en la función de arriba. Como convención, agrega
|
||||
# espacios en blanco para distinguir los parámetros de la función de las
|
||||
# variables locales. En este ejemplo, a, b y c son parámetros y localvar es una
|
||||
# variable local.
|
||||
# espacios en blanco para distinguir los parámetros de la función de las
|
||||
# variables locales. En este ejemplo, a, b y c son parámetros y localvar es
|
||||
# una variable local.
|
||||
|
||||
# Ahora, a demostrar las funciones aritméticas
|
||||
|
||||
@ -196,7 +196,7 @@ function string_functions( localvar, arr) {
|
||||
# Ambas regresan el número de matches remplazados.
|
||||
localvar = "fooooobar"
|
||||
sub("fo+", "Meet me at the ", localvar) # localvar => "Meet me at the bar"
|
||||
gsub("e+", ".", localvar) # localvar => "m..t m. at th. bar"
|
||||
gsub("e", ".", localvar) # localvar => "M..t m. at th. bar"
|
||||
|
||||
# Buscar una cadena que haga match con una expresión regular
|
||||
# index() hace lo mismo, pero no permite expresiones regulares
|
||||
@ -222,10 +222,10 @@ function io_functions( localvar) {
|
||||
# También hay printf
|
||||
printf("%s %d %d %d\n", "Testing", 1, 2, 3)
|
||||
|
||||
# AWK no tiene handles de archivos en sí mismo. Automáticamente abrirá un
|
||||
# handle de archivo cuando use algo que necesite uno. El string que usaste
|
||||
# para esto puede ser tratada como un handle de archivo para propósitos de I/O.
|
||||
# Esto lo hace similar al scripting de shell:
|
||||
# AWK no tiene handles de archivos en sí mismo. Automáticamente abrirá un
|
||||
# handle de archivo cuando use algo que necesite uno. El string que usaste
|
||||
# para esto puede ser tratada como un handle de archivo para propósitos
|
||||
# de I/O. Esto lo hace similar al scripting de shell:
|
||||
|
||||
print "foobar" >"/tmp/foobar.txt"
|
||||
|
||||
@ -247,17 +247,17 @@ function io_functions( localvar) {
|
||||
close("/tmp/foobar.txt")
|
||||
}
|
||||
|
||||
# Como dije al inicio, los programas en AWK son una colección de patrones y
|
||||
# Como dije al inicio, los programas en AWK son una colección de patrones y
|
||||
# acciones. Ya conociste el patrón BEGIN. otros patrones sólo se usan si estás
|
||||
# procesando líneas desde archivos o stdin.
|
||||
|
||||
# Cuando pasas argumentos a AWK, son tratados como nombres de archivos a
|
||||
# procesar. Los va a procesar todos, en orden. Imagínalos como un ciclo for
|
||||
# Cuando pasas argumentos a AWK, son tratados como nombres de archivos a
|
||||
# procesar. Los va a procesar todos, en orden. Imagínalos como un ciclo for
|
||||
# implícito, iterando sobre las líneas de estos archivos. Estos patrones y
|
||||
# acciones son como instrucciones switch dentro del ciclo.
|
||||
|
||||
/^fo+bar$/ {
|
||||
|
||||
|
||||
# Esta acción se ejecutará por cada línea que haga match con la expresión
|
||||
# regular /^fo+bar$/, y será saltada por cualquier línea que no haga match.
|
||||
# Vamos a sólo mostrar la línea:
|
||||
@ -268,7 +268,7 @@ function io_functions( localvar) {
|
||||
# $0 es el nombre de la línea actual que se está procesando.
|
||||
# Se crea automáticamente para ti.
|
||||
|
||||
# Probablemente puedas adivinar que hay otras variables $. Cada línea es
|
||||
# Probablemente puedas adivinar que hay otras variables $. Cada línea es
|
||||
# separada implícitamente antes de que se llame cada acción, justo como lo
|
||||
# hace shell. Y, como shell, cada campo puede ser accesado con $.
|
||||
|
||||
@ -301,7 +301,7 @@ a > 0 {
|
||||
# Y ya te das una idea. Procesar archivos de texto, leyendo una línea a la vez,
|
||||
# y haciendo algo con ella, particularmente separando en un deliminator, es tan
|
||||
# común en UNIX que AWK es un lenguaje de scripting que hace todo eso por ti
|
||||
# sin que tengas que pedirlo. Basta con escribir los patrones y acciones
|
||||
# sin que tengas que pedirlo. Basta con escribir los patrones y acciones
|
||||
# basados en lo que esperas de la entrada y lo quieras quieras hacer con ella.
|
||||
|
||||
# Aquí está un ejemplo de un script simple, para lo que AWK es perfecto.
|
||||
@ -343,7 +343,7 @@ $1 == name {
|
||||
nlines++
|
||||
}
|
||||
|
||||
# Otro patrón especial es END. Va a ejecutarse después de procesar todos los
|
||||
# Otro patrón especial es END. Va a ejecutarse después de procesar todos los
|
||||
# archivos de texto. A diferencia de BEGIN, sólo se ejecuta si le das dado una
|
||||
# entrada a procesar. Se ejecutará después de que todos los archivos hayan sido
|
||||
# leídos y procesados según las reglas y acciones que programaste. El propósito
|
||||
@ -356,8 +356,10 @@ END {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Más información:
|
||||
|
||||
* [Tutorial de AWK](http://www.grymoire.com/Unix/Awk.html)
|
||||
* [Página man de AWK](https://linux.die.net/man/1/awk)
|
||||
* [La guía del usuario de GNU Awk](https://www.gnu.org/software/gawk/manual/gawk.html): GNU Awk se encuentra en la mayoría de los sistemas Linux.
|
||||
* [La guía del usuario de GNU Awk](https://www.gnu.org/software/gawk/manual/gawk.html):
|
||||
GNU Awk se encuentra en la mayoría de los sistemas Linux.
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: c++
|
||||
language: C++
|
||||
filename: learncpp-es.cpp
|
||||
contributors:
|
||||
- ["Steven Basart", "http://github.com/xksteven"]
|
||||
@ -8,6 +8,7 @@ contributors:
|
||||
- ["Connor Waters", "http://github.com/connorwaters"]
|
||||
translators:
|
||||
- ["Gerson Lázaro", "https://gersonlazaro.com"]
|
||||
- ["Diego Ramirez", "https://DiddiLeija.github.io"]
|
||||
lang: es-es
|
||||
---
|
||||
|
||||
@ -101,8 +102,8 @@ void print(int myInt)
|
||||
|
||||
int main()
|
||||
{
|
||||
print("Hello"); // Resolves to void print(const char*)
|
||||
print(15); // Resolves to void print(int)
|
||||
print("Hello"); // Corresponde a void print(const char*)
|
||||
print(15); // Corresponde a void print(int)
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
@ -114,7 +115,7 @@ int main()
|
||||
|
||||
void doSomethingWithInts(int a = 1, int b = 4)
|
||||
{
|
||||
// Hacer algo con los enteros aqui
|
||||
// Hacer algo con los enteros aquí
|
||||
}
|
||||
|
||||
int main()
|
||||
@ -134,7 +135,7 @@ void invalidDeclaration(int a = 1, int b) // Error!
|
||||
// Espacios de nombre
|
||||
/////////////////////
|
||||
|
||||
// Espacios de nombres proporcionan ámbitos separados para variable, función y
|
||||
// Los espacios de nombres proporcionan ámbitos separados para variable, función y
|
||||
// otras declaraciones.
|
||||
// Los espacios de nombres se pueden anidar.
|
||||
|
||||
@ -184,7 +185,7 @@ int main()
|
||||
|
||||
#include <iostream> // Incluir para el flujo de entrada/salida
|
||||
|
||||
using namespace std; // Los streams estan en std namespace (libreria estandar)
|
||||
using namespace std; // Los streams estan en el espacio de nombre std (libreria estandar)
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -208,7 +209,7 @@ int main()
|
||||
// Las cadenas en C++ son objetos y tienen muchas funciones
|
||||
#include <string>
|
||||
|
||||
using namespace std; // Strings también estan en namespace std
|
||||
using namespace std; // Las cadenas también estan en el nombre de espacio std
|
||||
|
||||
string myString = "Hola";
|
||||
string myOtherString = " Mundo";
|
||||
@ -252,7 +253,7 @@ fooRef = bar;
|
||||
const string& barRef = bar; // Crea una referencia constante a bar.
|
||||
// Como en C, los valores constantes (y punteros y referencias) no pueden ser
|
||||
// modificados.
|
||||
barRef += ". Hola!"; // Error, referencia constante no puede ser modificada.
|
||||
barRef += ". Hola!"; // Error, una referencia constante no puede ser modificada.
|
||||
|
||||
// Sidetrack: Antes de hablar más sobre referencias, hay que introducir un
|
||||
// concepto llamado objeto temporal. Supongamos que tenemos el siguiente código:
|
||||
@ -264,7 +265,7 @@ string retVal = tempObjectFun();
|
||||
// - Una nueva cadena se construye con el objeto devuelto como argumento al
|
||||
// constructor
|
||||
// - El objeto devuelto es destruido
|
||||
// El objeto devuelto se llama objeto temporal. Objetos temporales son
|
||||
// El objeto devuelto se llama objeto temporal. Los objetos temporales son
|
||||
// creados cada vez que una función devuelve un objeto, y es destruido en el
|
||||
// fin de la evaluación de la expresión que encierra (Bueno, esto es lo que la
|
||||
// norma dice, pero los compiladores están autorizados a cambiar este
|
||||
@ -295,7 +296,7 @@ void someFun(string&& s) { ... } // Referencia a objeto temporal
|
||||
|
||||
string foo;
|
||||
someFun(foo); // Llama la función con referencia regular
|
||||
someFun(tempObjectFun()); // Llama la versión con referencia temporal
|
||||
someFun(tempObjectFun()); // Llama la función con referencia temporal
|
||||
|
||||
// Por ejemplo, puedes ver estas dos versiones de constructores para
|
||||
// std::basic_string:
|
||||
@ -305,7 +306,7 @@ basic_string(basic_string&& other);
|
||||
// La idea es que si estamos construyendo una nueva cadena de un objeto temporal
|
||||
// (que va a ser destruido pronto de todos modos), podemos tener un constructor
|
||||
// mas eficiente que "rescata" partes de esa cadena temporal. Usted verá este
|
||||
// Concepto denominado "movimiento semántico".
|
||||
// concepto denominado "movimiento semántico".
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Clases y programación orientada a objetos
|
||||
@ -322,9 +323,7 @@ class Dog {
|
||||
int weight;
|
||||
|
||||
// Todos los miembros siguientes de este son públicos
|
||||
// Hasta que se encuentre "private" o "protected".
|
||||
// All members following this are public
|
||||
// until "private:" or "protected:" is found.
|
||||
// hasta que se encuentre "private" o "protected".
|
||||
public:
|
||||
|
||||
// Constructor por defecto
|
||||
@ -339,8 +338,8 @@ public:
|
||||
|
||||
void setWeight(int dogsWeight);
|
||||
// Funciones que no modifican el estado del objeto
|
||||
// Deben marcarse como const.
|
||||
// Esto le permite llamarlas si se envia una referencia constante al objeto.
|
||||
// deben marcarse como const.
|
||||
// Esto le permite llamarlas si se envía una referencia constante al objeto.
|
||||
// También tenga en cuenta que las funciones deben ser declaradas
|
||||
// explícitamente como _virtual_ para que sea reemplazada en las clases
|
||||
// derivadas.
|
||||
@ -357,8 +356,8 @@ public:
|
||||
// Esto permite paradigmas potentes como RAII
|
||||
// (mira abajo)
|
||||
// El destructor debe ser virtual si una clase es dervada desde el;
|
||||
// Si no es virtual, entonces la clase derivada destructor
|
||||
// No será llamada si el objeto se destruye a través de una referencia de
|
||||
// Si no es virtual, entonces la clase destructora derivada
|
||||
// no será llamada si el objeto se destruye a través de una referencia de
|
||||
// la clase base o puntero.
|
||||
virtual ~Dog();
|
||||
|
||||
@ -373,7 +372,7 @@ Dog::Dog()
|
||||
}
|
||||
|
||||
// Objetos (tales como cadenas) deben ser pasados por referencia
|
||||
// Si los estas modificando o referencia constante en caso contrario.
|
||||
// si los estás modificando, o referencia constante en caso contrario.
|
||||
void Dog::setName(const std::string& dogsName)
|
||||
{
|
||||
name = dogsName;
|
||||
@ -413,9 +412,9 @@ class OwnedDog : public Dog {
|
||||
// Reemplaza el comportamiento de la función de impresión
|
||||
// de todos los OwnedDogs. Mira
|
||||
// http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping
|
||||
// Para una introducción más general si no está familiarizado con el
|
||||
// para una introducción más general si no está familiarizado con el
|
||||
// polimorfismo de subtipo.
|
||||
// La palabra clave override es opcional, pero asegura que estás
|
||||
// La palabra clave override es opcional, pero asegúrate de que estás
|
||||
// reemplazando el método de una clase base.
|
||||
void print() const override;
|
||||
|
||||
@ -460,8 +459,8 @@ public:
|
||||
// pero inicializa el punto al valor por defecto (0, 0)
|
||||
Point() { };
|
||||
|
||||
// The following syntax is known as an initialization list
|
||||
// and is the proper way to initialize class member values
|
||||
// La siguiente sintaxis se conoce como lista de inicialización
|
||||
// y es la forma correcta de inicializar los valores de los miembros de la clase
|
||||
Point (double a, double b) :
|
||||
x(a),
|
||||
y(b)
|
||||
@ -474,7 +473,7 @@ public:
|
||||
Point& operator+=(const Point& rhs);
|
||||
|
||||
// También tendría sentido añadir los operadores - y -=,
|
||||
// Pero vamos a omitirlos por razones de brevedad.
|
||||
// pero vamos a omitirlos por razones de brevedad.
|
||||
};
|
||||
|
||||
Point Point::operator+(const Point& rhs) const
|
||||
@ -496,7 +495,7 @@ int main () {
|
||||
// Llama al operador + de Point
|
||||
// Point llama la función + con right como parámetro
|
||||
Point result = up + right;
|
||||
// Prints "Result is upright (1,1)"
|
||||
// Imprime "Result is upright (1,1)"
|
||||
cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
|
||||
return 0;
|
||||
}
|
||||
@ -525,7 +524,7 @@ public:
|
||||
// plantilla con parámetros sustituidos, por lo que la definición completa
|
||||
// de la clase debe estar presente en cada invocación.
|
||||
// Es por esto que usted verá clases de plantilla definidas
|
||||
// Enteramente en archivos de cabecera.
|
||||
// enteramente en archivos de cabecera.
|
||||
|
||||
//Para crear una instancia de una clase de plantilla en la pila:
|
||||
Box<int> intBox;
|
||||
@ -544,7 +543,7 @@ boxOfBox.insert(intBox);
|
||||
|
||||
// A veces verás
|
||||
// template<typename T>
|
||||
// en su lugar. La palabra clave "class" y las palabras clave "typename" son
|
||||
// en su lugar. La palabra clave "class" y la palabra clave "typename" son
|
||||
// mayormente intercambiables en este caso. Para la explicación completa, mira
|
||||
// http://en.wikipedia.org/wiki/Typename
|
||||
// (sí, esa palabra clave tiene su propia página de Wikipedia).
|
||||
@ -568,7 +567,7 @@ Dog fluffy;
|
||||
fluffy.setName("Fluffy")
|
||||
barkThreeTimes(fluffy); // Imprime "Fluffy barks" 3 veces.
|
||||
|
||||
Los parámetros de la plantilla no tienen que ser las clases:
|
||||
// Los parámetros de la plantilla no tienen que ser las clases:
|
||||
template<int Y>
|
||||
void printMessage() {
|
||||
cout << "Aprende C++ en " << Y << " minutos!" << endl;
|
||||
@ -604,7 +603,7 @@ printMessage<10>(); // Prints "Aprende C++ rapido en solo 10 minutos!"
|
||||
//Todas las excepciones lanzadas dentro del bloque _try_ pueden ser
|
||||
// capturados por los siguientes manejadores _catch_.
|
||||
try {
|
||||
// No asignar excepciones en el heap usando _new_.
|
||||
// No asigne excepciones en el heap usando _new_.
|
||||
throw std::runtime_error("Ocurrió un problema");
|
||||
}
|
||||
|
||||
@ -629,10 +628,10 @@ catch (...)
|
||||
// (Adquisición de recursos es inicialización).
|
||||
// A menudo se considera el paradigma más poderoso en C++
|
||||
// Y el concepto es simple: un constructor de un objeto
|
||||
// Adquiere recursos de ese objeto y el destructor les libera.
|
||||
// adquiere recursos de ese objeto y el destructor les libera.
|
||||
|
||||
// Para entender cómo esto es útil,
|
||||
// Considere una función que utiliza un identificador de archivo C:
|
||||
// considere una función que utiliza un identificador de archivo C:
|
||||
void doSomethingWithAFile(const char* filename)
|
||||
{
|
||||
// Para empezar, asuma que nada puede fallar.
|
||||
@ -691,11 +690,11 @@ bool doSomethingWithAFile(const char* filename)
|
||||
|
||||
failure:
|
||||
fclose(fh);
|
||||
return false; // Propagate el error
|
||||
return false; // Propaga el error
|
||||
}
|
||||
|
||||
// Si las funciones indican errores mediante excepciones,
|
||||
// Las cosas son un poco más claras, pero pueden optimizarse mas.
|
||||
// las cosas son un poco más claras, pero pueden optimizarse más.
|
||||
void doSomethingWithAFile(const char* filename)
|
||||
{
|
||||
FILE* fh = fopen(filename, "r"); // Abrir el archivo en modo lectura
|
||||
@ -732,9 +731,9 @@ void doSomethingWithAFile(const std::string& filename)
|
||||
|
||||
// Esto tiene ventajas _enormes_:
|
||||
// 1. No importa lo que pase,
|
||||
// El recurso (en este caso el manejador de archivo) será limpiado.
|
||||
// el recurso (en este caso el manejador de archivo) será limpiado.
|
||||
// Una vez que escribes el destructor correctamente,
|
||||
// Es _imposible_ olvidar cerrar el identificador y permitir
|
||||
// es _imposible_ olvidar cerrar el identificador y permitir
|
||||
// fugas del recurso.
|
||||
// 2. Tenga en cuenta que el código es mucho más limpio.
|
||||
// El destructor se encarga de cerrar el archivo detrás de cámaras
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: c
|
||||
language: C
|
||||
filename: learnc-es.c
|
||||
contributors:
|
||||
- ["Adam Bard", "http://adambard.com/"]
|
||||
|
1219
es-es/chapel-es.html.markdown
Normal file
1219
es-es/chapel-es.html.markdown
Normal file
File diff suppressed because it is too large
Load Diff
@ -431,7 +431,7 @@ funciones principales (pertenecientes al core):
|
||||
[http://clojuredocs.org/quickref](http://clojuredocs.org/quickref)
|
||||
|
||||
4Clojure es una genial forma de mejorar tus habilidades con clojure/FP:
|
||||
[http://www.4clojure.com/](http://www.4clojure.com/)
|
||||
[https://4clojure.oxal.org/](https://4clojure.oxal.org/)
|
||||
|
||||
Clojure-doc.org (sí, de verdad) tiene un buen número de artículos con los que
|
||||
iniciarse en Clojure: [http://clojure-doc.org](http://clojure-doc.org)
|
||||
|
@ -1,327 +0,0 @@
|
||||
---
|
||||
language: css
|
||||
contributors:
|
||||
- ["Mohammad Valipour", "https://github.com/mvalipour"]
|
||||
- ["Marco Scannadinari", "https://github.com/marcoms"]
|
||||
- ["Geoffrey Liu", "https://github.com/g-liu"]
|
||||
- ["Connor Shea", "https://github.com/connorshea"]
|
||||
- ["Deepanshu Utkarsh", "https://github.com/duci9y"]
|
||||
- ["Brett Taylor", "https://github.com/glutnix"]
|
||||
- ["Tyler Mumford", "https://tylermumford.com"]
|
||||
translators:
|
||||
- ["miky ackerman", "https://github.com/mikyackerman"]
|
||||
lang: es-es
|
||||
filename: learncss-es.css
|
||||
---
|
||||
|
||||
Paginas web estan contruidas en HTML, lo cual especifica el contenido de una pagina
|
||||
CSS(Hoja de Estilos en Cascada) es un lenguaje separado el cual especifica
|
||||
la **apariencia** de una pagina.
|
||||
|
||||
codigo CSS esta hecho de *reglas* estaticas. Cada regla toma uno o mas *selectores* y da *valores* especificos a un numero de *propiedades* visuales. Esas propiedades estan entonces aplicadas a los elementos indicados en una pagina por los selectores
|
||||
|
||||
Esta guia ha sido escrita con CSS 2 en mente, la cual es extendida por una nueva caracterica de CSS 3.
|
||||
|
||||
**NOTA:** Debido a que CSS produce resultados visuales, para aprenderlo, necesitas
|
||||
Probar todo en un patio de juegos CSS como [dabblet] (http://dabblet.com/).
|
||||
El objetivo principal de este artículo es la sintaxis y algunos consejos generales.
|
||||
|
||||
## Sintaxis
|
||||
|
||||
```css
|
||||
/* Los comentarios aparecen dentro de un diagonal-asterisco, justo como esta linea
|
||||
no hay "comentarios en una linea"; este es el unico estilo de comentario.*/
|
||||
|
||||
|
||||
/* ####################
|
||||
## SELECTORS
|
||||
#################### */
|
||||
|
||||
/* el selector es usado para apuntar a un elemento de la pagina. */
|
||||
selector { property: value; /* more properties...*/ }
|
||||
|
||||
/*
|
||||
Here is an example element:
|
||||
|
||||
<div class='class1 class2' id='anID' attr='value' otherAttr='en-us foo bar' />
|
||||
*/
|
||||
|
||||
/* You can target it using one of its CSS classes */
|
||||
.class1 { }
|
||||
|
||||
/* or both classes! */
|
||||
.class1.class2 { }
|
||||
|
||||
/* or its name */
|
||||
div { }
|
||||
|
||||
/* or its id */
|
||||
#anID { }
|
||||
|
||||
/* or using the fact that it has an attribute! */
|
||||
[attr] { font-size:smaller; }
|
||||
|
||||
/* or that the attribute has a specific value */
|
||||
[attr='value'] { font-size:smaller; }
|
||||
|
||||
/* starts with a value (CSS 3) */
|
||||
[attr^='val'] { font-size:smaller; }
|
||||
|
||||
/* or ends with a value (CSS 3) */
|
||||
[attr$='ue'] { font-size:smaller; }
|
||||
|
||||
/* or contains a value in a space-separated list */
|
||||
[otherAttr~='foo'] { }
|
||||
[otherAttr~='bar'] { }
|
||||
|
||||
/* or contains a value in a dash-separated list, e.g., "-" (U+002D) */
|
||||
[otherAttr|='en'] { font-size:smaller; }
|
||||
|
||||
|
||||
/* You can combine different selectors to create a more focused selector. Don't
|
||||
put spaces between them. */
|
||||
div.some-class[attr$='ue'] { }
|
||||
|
||||
/* You can select an element which is a child of another element */
|
||||
div.some-parent > .class-name { }
|
||||
|
||||
/* or a descendant of another element. Children are the direct descendants of
|
||||
their parent element, only one level down the tree. Descendants can be any
|
||||
level down the tree. */
|
||||
div.some-parent .class-name { }
|
||||
|
||||
/* Warning: the same selector without a space has another meaning.
|
||||
Can you guess what? */
|
||||
div.some-parent.class-name { }
|
||||
|
||||
/* You may also select an element based on its adjacent sibling */
|
||||
.i-am-just-before + .this-element { }
|
||||
|
||||
/* or any sibling preceding it */
|
||||
.i-am-any-element-before ~ .this-element { }
|
||||
|
||||
/* There are some selectors called pseudo classes that can be used to select an
|
||||
element only when it is in a particular state */
|
||||
|
||||
/* for example, when the cursor hovers over an element */
|
||||
selector:hover { }
|
||||
|
||||
/* or a link has been visited */
|
||||
selector:visited { }
|
||||
|
||||
/* or hasn't been visited */
|
||||
selected:link { }
|
||||
|
||||
/* or an element is in focus */
|
||||
selected:focus { }
|
||||
|
||||
/* any element that is the first child of its parent */
|
||||
selector:first-child {}
|
||||
|
||||
/* any element that is the last child of its parent */
|
||||
selector:last-child {}
|
||||
|
||||
/* Just like pseudo classes, pseudo elements allow you to style certain parts of
|
||||
a document */
|
||||
|
||||
/* matches a virtual first child of the selected element */
|
||||
selector::before {}
|
||||
|
||||
/* matches a virtual last child of the selected element */
|
||||
selector::after {}
|
||||
|
||||
/* At appropriate places, an asterisk may be used as a wildcard to select every
|
||||
element */
|
||||
* { } /* all elements */
|
||||
.parent * { } /* all descendants */
|
||||
.parent > * { } /* all children */
|
||||
|
||||
/* ####################
|
||||
## PROPERTIES
|
||||
#################### */
|
||||
|
||||
selector {
|
||||
|
||||
/* Units of length can be absolute or relative. */
|
||||
|
||||
/* Relative units */
|
||||
width: 50%; /* percentage of parent element width */
|
||||
font-size: 2em; /* multiples of element's original font-size */
|
||||
font-size: 2rem; /* or the root element's font-size */
|
||||
font-size: 2vw; /* multiples of 1% of the viewport's width (CSS 3) */
|
||||
font-size: 2vh; /* or its height */
|
||||
font-size: 2vmin; /* whichever of a vh or a vw is smaller */
|
||||
font-size: 2vmax; /* or greater */
|
||||
|
||||
/* Absolute units */
|
||||
width: 200px; /* pixels */
|
||||
font-size: 20pt; /* points */
|
||||
width: 5cm; /* centimeters */
|
||||
min-width: 50mm; /* millimeters */
|
||||
max-width: 5in; /* inches */
|
||||
|
||||
/* Colors */
|
||||
color: #F6E; /* short hex format */
|
||||
color: #FF66EE; /* long hex format */
|
||||
color: tomato; /* a named color */
|
||||
color: rgb(255, 255, 255); /* as rgb values */
|
||||
color: rgb(10%, 20%, 50%); /* as rgb percentages */
|
||||
color: rgba(255, 0, 0, 0.3); /* as rgba values (CSS 3) Note: 0 <= a <= 1 */
|
||||
color: transparent; /* equivalent to setting the alpha to 0 */
|
||||
color: hsl(0, 100%, 50%); /* as hsl percentages (CSS 3) */
|
||||
color: hsla(0, 100%, 50%, 0.3); /* as hsl percentages with alpha */
|
||||
|
||||
/* Borders */
|
||||
border-width:5px;
|
||||
border-style:solid;
|
||||
border-color:red; /* similar to how background-color is set */
|
||||
border: 5px solid red; /* this is a short hand approach for the same */
|
||||
border-radius:20px; /* this is a CSS3 property */
|
||||
|
||||
/* Images as backgrounds of elements */
|
||||
background-image: url(/img-path/img.jpg); /* quotes inside url() optional */
|
||||
|
||||
/* Fonts */
|
||||
font-family: Arial;
|
||||
/* if the font family name has a space, it must be quoted */
|
||||
font-family: "Courier New";
|
||||
/* if the first one is not found, the browser uses the next, and so on */
|
||||
font-family: "Courier New", Trebuchet, Arial, sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Save a CSS stylesheet with the extension `.css`.
|
||||
|
||||
```html
|
||||
<!-- You need to include the css file in your page's <head>. This is the
|
||||
recommended method. Refer to http://stackoverflow.com/questions/8284365 -->
|
||||
<link rel='stylesheet' type='text/css' href='path/to/style.css'>
|
||||
|
||||
<!-- You can also include some CSS inline in your markup. -->
|
||||
<style>
|
||||
a { color: purple; }
|
||||
</style>
|
||||
|
||||
<!-- Or directly set CSS properties on the element. -->
|
||||
<div style="border: 1px solid red;">
|
||||
</div>
|
||||
```
|
||||
|
||||
## Precedence or Cascade
|
||||
|
||||
An element may be targeted by multiple selectors and may have a property set on
|
||||
it in more than once. In these cases, one of the rules takes precedence over
|
||||
others. Rules with a more specific selector take precedence over a less specific
|
||||
one, and a rule occurring later in the stylesheet overwrites a previous one
|
||||
(which also means that if two different linked stylesheets contain rules for an
|
||||
element and if the rules are of the same specificity, then order of linking
|
||||
would take precedence and the sheet linked latest would govern styling) .
|
||||
|
||||
This process is called cascading, hence the name Cascading Style Sheets.
|
||||
|
||||
Given the following CSS:
|
||||
|
||||
```css
|
||||
/* A */
|
||||
p.class1[attr='value']
|
||||
|
||||
/* B */
|
||||
p.class1 { }
|
||||
|
||||
/* C */
|
||||
p.class2 { }
|
||||
|
||||
/* D */
|
||||
p { }
|
||||
|
||||
/* E */
|
||||
p { property: value !important; }
|
||||
```
|
||||
|
||||
and the following markup:
|
||||
|
||||
```html
|
||||
<p style='/*F*/ property:value;' class='class1 class2' attr='value'>
|
||||
```
|
||||
|
||||
The precedence of style is as follows. Remember, the precedence is for each
|
||||
**property**, not for the entire block.
|
||||
|
||||
* `E` has the highest precedence because of the keyword `!important`. It is
|
||||
recommended that you avoid its usage.
|
||||
* `F` is next, because it is an inline style.
|
||||
* `A` is next, because it is more "specific" than anything else. It has 3
|
||||
specifiers: The name of the element `p`, its class `class1`, an attribute
|
||||
`attr='value'`.
|
||||
* `C` is next, even though it has the same specificity as `B`.
|
||||
This is because it appears after `B`.
|
||||
* `B` is next.
|
||||
* `D` is the last one.
|
||||
|
||||
## Media Queries
|
||||
|
||||
CSS Media Queries are a feature in CSS 3 which allows you to specify when certain CSS rules should be applied, such as when printed, or when on a screen with certain dimensions or pixel density. They do not add to the selector's specificity.
|
||||
|
||||
```css
|
||||
/* A rule that will be used on all devices */
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
/* change the h1 to use less ink on a printer */
|
||||
@media print {
|
||||
h1 {
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
/* make the font bigger when shown on a screen at least 480px wide */
|
||||
@media screen and (min-width: 480px) {
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Media queries can include these features:
|
||||
`width`, `height`, `device-width`, `device-height`, `orientation`, `aspect-ratio`, `device-aspect-ratio`, `color`, `color-index`, `monochrome`, `resolution`, `scan`, `grid`. Most of these features can be prefixed with `min-` or `max-`.
|
||||
|
||||
The `resolution` feature is not supported by older devices, instead use `device-pixel-ratio`.
|
||||
|
||||
Many smartphones and tablets will attempt to render the page as if it were on a desktop unless you provide a `viewport` meta-tag.
|
||||
|
||||
```html
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
</head>
|
||||
```
|
||||
|
||||
## Compatibility
|
||||
|
||||
Most of the features in CSS 2 (and many in CSS 3) are available across all
|
||||
browsers and devices. But it's always good practice to check before using
|
||||
a new feature.
|
||||
|
||||
## Resources
|
||||
|
||||
* [CanIUse](http://caniuse.com) (Detailed compatibility info)
|
||||
* [Dabblet](http://dabblet.com/) (CSS playground)
|
||||
* [Mozilla Developer Network's CSS documentation](https://developer.mozilla.org/en-US/docs/Web/CSS) (Tutorials and reference)
|
||||
* [Codrops' CSS Reference](http://tympanus.net/codrops/css_reference/) (Reference)
|
||||
|
||||
## Further Reading
|
||||
|
||||
* [Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/)
|
||||
* [Selecting elements using attributes](https://css-tricks.com/almanac/selectors/a/attribute/)
|
||||
* [QuirksMode CSS](http://www.quirksmode.org/css/)
|
||||
* [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context)
|
||||
* [SASS](http://sass-lang.com/) and [LESS](http://lesscss.org/) for CSS pre-processing
|
||||
* [CSS-Tricks](https://css-tricks.com)
|
||||
|
||||
|
@ -1,253 +1,327 @@
|
||||
---
|
||||
language: css
|
||||
filename: learncss-es.css
|
||||
contributors:
|
||||
- ["Mohammad Valipour", "https://github.com/mvalipour"]
|
||||
- ["Marco Scannadinari", "https://github.com/marcoms"]
|
||||
- ["Geoffrey Liu", "https://github.com/g-liu"]
|
||||
- ["Connor Shea", "https://github.com/connorshea"]
|
||||
- ["Deepanshu Utkarsh", "https://github.com/duci9y"]
|
||||
- ["Brett Taylor", "https://github.com/glutnix"]
|
||||
- ["Tyler Mumford", "https://tylermumford.com"]
|
||||
translators:
|
||||
- ["Daniel Zendejas","https://github.com/DanielZendejas"]
|
||||
- ["miky ackerman", "https://github.com/mikyackerman"]
|
||||
lang: es-es
|
||||
filename: learncss-es.css
|
||||
---
|
||||
|
||||
Tutorial de CSS en español
|
||||
Paginas web estan contruidas en HTML, lo cual especifica el contenido de una pagina
|
||||
CSS(Hoja de Estilos en Cascada) es un lenguaje separado el cual especifica
|
||||
la **apariencia** de una pagina.
|
||||
|
||||
En los primeros días de la web no había elementos visuales, todo
|
||||
era texto plano. Pero después, con el desarrollo de los navegadores,
|
||||
las páginas con contenido visual empezaron a ser más comunes.
|
||||
CSS es el lenguaje estándar que existe para separar el contenido
|
||||
(HTML) y el aspecto visual de las páginas web.
|
||||
codigo CSS esta hecho de *reglas* estaticas. Cada regla toma uno o mas *selectores* y da *valores* especificos a un numero de *propiedades* visuales. Esas propiedades estan entonces aplicadas a los elementos indicados en una pagina por los selectores
|
||||
|
||||
Lo que CSS hace es proveer con una sintaxis que te permite apuntar a distintos
|
||||
elementos HTML y asignarles diferentes propiedades visuales.
|
||||
Esta guia ha sido escrita con CSS 2 en mente, la cual es extendida por una nueva caracterica de CSS 3.
|
||||
|
||||
CSS, como cualquier otro lenguaje, tiene múltiples versiones. Aquí nos enfocamos
|
||||
en CSS 2.0. No es la versión más reciente pero sí la más soportada y compatible.
|
||||
**NOTA:** Debido a que CSS produce resultados visuales, para aprenderlo, necesitas
|
||||
Probar todo en un patio de juegos CSS como [dabblet] (http://dabblet.com/).
|
||||
El objetivo principal de este artículo es la sintaxis y algunos consejos generales.
|
||||
|
||||
**NOTA:** Como los resultados de CSS son efectos visuales, para aprenderlo,
|
||||
necesitarás probar todo tipo de cosas en ambientes como
|
||||
[dabblet](http://dabblet.com/). Este artículo se enfoca, principalmente, en
|
||||
la sintaxis y consejos generales.
|
||||
## Sintaxis
|
||||
|
||||
```css
|
||||
/* ¡Los comentarios aparecen dentro de diagonal-asterisco, justo como esta línea! */
|
||||
/* Los comentarios aparecen dentro de un diagonal-asterisco, justo como esta linea
|
||||
no hay "comentarios en una linea"; este es el unico estilo de comentario.*/
|
||||
|
||||
|
||||
/* ####################
|
||||
## SELECTORES
|
||||
####################*/
|
||||
## SELECTORS
|
||||
#################### */
|
||||
|
||||
/* Generalmente, la sentencia principal en CSS es muy simple. */
|
||||
selector { propiedad: valor; /* más propiedades separados por punto y coma...*/ }
|
||||
|
||||
/* El selector es usado para apuntar a (seleccionar) un elemento en la página.
|
||||
|
||||
¡Puedes apuntar a todos los elementos en la página con el asterisco! */
|
||||
* { color:red; }
|
||||
/* el selector es usado para apuntar a un elemento de la pagina. */
|
||||
selector { property: value; /* more properties...*/ }
|
||||
|
||||
/*
|
||||
Dado un elemento como este en la página:
|
||||
Here is an example element:
|
||||
|
||||
<div class='una-clase clase2' id='unaId' attr='valor' />
|
||||
<div class='class1 class2' id='anID' attr='value' otherAttr='en-us foo bar' />
|
||||
*/
|
||||
|
||||
/* puedes seleccionar el <div> por el nombre de su clase */
|
||||
.una-clase { }
|
||||
/* You can target it using one of its CSS classes */
|
||||
.class1 { }
|
||||
|
||||
/*¡O por sus dos clases! */
|
||||
.una-clase.clase2 { }
|
||||
/* or both classes! */
|
||||
.class1.class2 { }
|
||||
|
||||
/* O por el nombre de su elemento */
|
||||
/* or its name */
|
||||
div { }
|
||||
|
||||
/* O por su Id */
|
||||
#unaId { }
|
||||
/* or its id */
|
||||
#anID { }
|
||||
|
||||
/* ¡O por el hecho de que tiene un atributo! */
|
||||
/* or using the fact that it has an attribute! */
|
||||
[attr] { font-size:smaller; }
|
||||
|
||||
/* O por el hecho de que el atributo tiene un valor determinado */
|
||||
[attr='valor'] { font-size:smaller; }
|
||||
/* or that the attribute has a specific value */
|
||||
[attr='value'] { font-size:smaller; }
|
||||
|
||||
/* Empieza con un valor ('val' en este caso)*/
|
||||
/* starts with a value (CSS 3) */
|
||||
[attr^='val'] { font-size:smaller; }
|
||||
|
||||
/* O termina con un valor ('or' en este caso) */
|
||||
[attr$='or'] { font-size:smaller; }
|
||||
/* or ends with a value (CSS 3) */
|
||||
[attr$='ue'] { font-size:smaller; }
|
||||
|
||||
/* O incluso contiene un valor ('lo' en este caso) */
|
||||
[attr~='lo'] { font-size:smaller; }
|
||||
/* or contains a value in a space-separated list */
|
||||
[otherAttr~='foo'] { }
|
||||
[otherAttr~='bar'] { }
|
||||
|
||||
/*Más importante, puedes combinar estos criterios de búsqueda entre sí.
|
||||
No debe existir ningún espacio entre estas partes porque hace que el
|
||||
significado cambie.*/
|
||||
div.una-clase[attr$='or'] { }
|
||||
/* or contains a value in a dash-separated list, e.g., "-" (U+002D) */
|
||||
[otherAttr|='en'] { font-size:smaller; }
|
||||
|
||||
/* También puedes seleccionar un elemento HTML basándote en sus padres*/
|
||||
|
||||
/* Un elemento que es hijo directo de otro elemento (Seleccionado de la forma que
|
||||
vimos anteriormente) */
|
||||
/* You can combine different selectors to create a more focused selector. Don't
|
||||
put spaces between them. */
|
||||
div.some-class[attr$='ue'] { }
|
||||
|
||||
div.un-padre > .nombre-clase {}
|
||||
/* You can select an element which is a child of another element */
|
||||
div.some-parent > .class-name { }
|
||||
|
||||
/* O cualquiera de sus ancestros en la jerarquía*/
|
||||
/* La siguiente sentencia selecciona a cualquier elemento que tenga una clase
|
||||
"nombre-clase" y sea hijo de un div con clase "un-padre" EN CUALQUIER PROFUNDIDAD*/
|
||||
div.un-padre .nombre-clase {}
|
||||
/* or a descendant of another element. Children are the direct descendants of
|
||||
their parent element, only one level down the tree. Descendants can be any
|
||||
level down the tree. */
|
||||
div.some-parent .class-name { }
|
||||
|
||||
/* advertencia: el mismo selector sin espacio tiene otro significado. ¿Puedes
|
||||
identificar la diferencia?*/
|
||||
/* Warning: the same selector without a space has another meaning.
|
||||
Can you guess what? */
|
||||
div.some-parent.class-name { }
|
||||
|
||||
/* También puedes seleccionar un elemento basado en su hermano inmediato previo*/
|
||||
.yo-estoy-antes + .este-elemento { }
|
||||
/* You may also select an element based on its adjacent sibling */
|
||||
.i-am-just-before + .this-element { }
|
||||
|
||||
/*o cualquier hermano previo */
|
||||
.yo-soy-cualquiera-antes ~ .estes-elemento {}
|
||||
/* or any sibling preceding it */
|
||||
.i-am-any-element-before ~ .this-element { }
|
||||
|
||||
/* Existen algunas pseudo-clases que permiten seleccionar un elemento
|
||||
basado en el comportamiendo de la página (a diferencia de la estructura de
|
||||
la página) */
|
||||
/* There are some selectors called pseudo classes that can be used to select an
|
||||
element only when it is in a particular state */
|
||||
|
||||
/* Por ejemplo, para cuando pasas el mouse por encima de un elemento */
|
||||
:hover {}
|
||||
/* for example, when the cursor hovers over an element */
|
||||
selector:hover { }
|
||||
|
||||
/* o una liga visitada*/
|
||||
:visited {}
|
||||
/* or a link has been visited */
|
||||
selector:visited { }
|
||||
|
||||
/* o una liga no visitada aún*/
|
||||
:link {}
|
||||
/* or hasn't been visited */
|
||||
selected:link { }
|
||||
|
||||
/* o un elemento de un formulario que esté seleccionado */
|
||||
:focus {}
|
||||
/* or an element is in focus */
|
||||
selected:focus { }
|
||||
|
||||
/* any element that is the first child of its parent */
|
||||
selector:first-child {}
|
||||
|
||||
/* any element that is the last child of its parent */
|
||||
selector:last-child {}
|
||||
|
||||
/* Just like pseudo classes, pseudo elements allow you to style certain parts of
|
||||
a document */
|
||||
|
||||
/* matches a virtual first child of the selected element */
|
||||
selector::before {}
|
||||
|
||||
/* matches a virtual last child of the selected element */
|
||||
selector::after {}
|
||||
|
||||
/* At appropriate places, an asterisk may be used as a wildcard to select every
|
||||
element */
|
||||
* { } /* all elements */
|
||||
.parent * { } /* all descendants */
|
||||
.parent > * { } /* all children */
|
||||
|
||||
/* ####################
|
||||
## PROPIEDADES
|
||||
####################*/
|
||||
## PROPERTIES
|
||||
#################### */
|
||||
|
||||
selector {
|
||||
|
||||
/* Unidades */
|
||||
width: 50%; /* en porcentaje */
|
||||
font-size: 2em; /* dos veces el tamaño de la fuente actual */
|
||||
width: 200px; /* en pixeles */
|
||||
font-size: 20pt; /* en puntos */
|
||||
width: 5cm; /* en centimetros */
|
||||
width: 50mm; /* en milimetros */
|
||||
width: 5in; /* en pulgadas */
|
||||
|
||||
/* Colores */
|
||||
background-color: #F6E; /* en hexadecimal corto */
|
||||
background-color: #F262E2; /* en hexadecimal largo */
|
||||
background-color: tomato; /* puede ser un color con nombre */
|
||||
background-color: rgb(255, 255, 255); /* en rgb */
|
||||
background-color: rgb(10%, 20%, 50%); /* en rgb percent */
|
||||
background-color: rgba(255, 0, 0, 0.3); /* en rgb semi-transparente (con valor alfa)*/
|
||||
|
||||
/* Imagenes */
|
||||
background-image: url(/ruta-a-la-imagen/imagen.jpg);
|
||||
|
||||
/* Fuentes */
|
||||
font-family: Arial;
|
||||
font-family: "Courier New"; /* si el nombre contiene espacios, debe ir entre comillas */
|
||||
font-family: "Courier New", Trebuchet, Arial; /* si la primera fuente no se encontró
|
||||
entonces se busca la seguna, o la tercera, así recursivamente*/
|
||||
}
|
||||
|
||||
/* Units of length can be absolute or relative. */
|
||||
|
||||
/* Relative units */
|
||||
width: 50%; /* percentage of parent element width */
|
||||
font-size: 2em; /* multiples of element's original font-size */
|
||||
font-size: 2rem; /* or the root element's font-size */
|
||||
font-size: 2vw; /* multiples of 1% of the viewport's width (CSS 3) */
|
||||
font-size: 2vh; /* or its height */
|
||||
font-size: 2vmin; /* whichever of a vh or a vw is smaller */
|
||||
font-size: 2vmax; /* or greater */
|
||||
|
||||
/* Absolute units */
|
||||
width: 200px; /* pixels */
|
||||
font-size: 20pt; /* points */
|
||||
width: 5cm; /* centimeters */
|
||||
min-width: 50mm; /* millimeters */
|
||||
max-width: 5in; /* inches */
|
||||
|
||||
/* Colors */
|
||||
color: #F6E; /* short hex format */
|
||||
color: #FF66EE; /* long hex format */
|
||||
color: tomato; /* a named color */
|
||||
color: rgb(255, 255, 255); /* as rgb values */
|
||||
color: rgb(10%, 20%, 50%); /* as rgb percentages */
|
||||
color: rgba(255, 0, 0, 0.3); /* as rgba values (CSS 3) Note: 0 <= a <= 1 */
|
||||
color: transparent; /* equivalent to setting the alpha to 0 */
|
||||
color: hsl(0, 100%, 50%); /* as hsl percentages (CSS 3) */
|
||||
color: hsla(0, 100%, 50%, 0.3); /* as hsl percentages with alpha */
|
||||
|
||||
/* Borders */
|
||||
border-width:5px;
|
||||
border-style:solid;
|
||||
border-color:red; /* similar to how background-color is set */
|
||||
border: 5px solid red; /* this is a short hand approach for the same */
|
||||
border-radius:20px; /* this is a CSS3 property */
|
||||
|
||||
/* Images as backgrounds of elements */
|
||||
background-image: url(/img-path/img.jpg); /* quotes inside url() optional */
|
||||
|
||||
/* Fonts */
|
||||
font-family: Arial;
|
||||
/* if the font family name has a space, it must be quoted */
|
||||
font-family: "Courier New";
|
||||
/* if the first one is not found, the browser uses the next, and so on */
|
||||
font-family: "Courier New", Trebuchet, Arial, sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
## Uso
|
||||
## Usage
|
||||
|
||||
Guarda cualquier CSS que quieras en un archivo con extensión `.css`.
|
||||
Save a CSS stylesheet with the extension `.css`.
|
||||
|
||||
```xml
|
||||
<!-- Necesitas incluir tu archivo CSS en el elemento <head> de tu HTML: -->
|
||||
<link rel='stylesheet' type='text/css' href='ruta/archivoDeEstilos.css' />
|
||||
```html
|
||||
<!-- You need to include the css file in your page's <head>. This is the
|
||||
recommended method. Refer to http://stackoverflow.com/questions/8284365 -->
|
||||
<link rel='stylesheet' type='text/css' href='path/to/style.css'>
|
||||
|
||||
<!--
|
||||
también puedes incluir CSS dentro del archivo HTML. Esta no es una buena práctica
|
||||
y debe ser evitada.
|
||||
-->
|
||||
<!-- You can also include some CSS inline in your markup. -->
|
||||
<style>
|
||||
selector { propiedad:valor; }
|
||||
a { color: purple; }
|
||||
</style>
|
||||
|
||||
<!--
|
||||
También se pueden aplicar propiedades al elemento directamente.
|
||||
Esta práctica también debe ser evitada a toda costa
|
||||
-->
|
||||
<div style='propiedad:valor;'>
|
||||
<!-- Or directly set CSS properties on the element. -->
|
||||
<div style="border: 1px solid red;">
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
## Preferencia y orden
|
||||
## Precedence or Cascade
|
||||
|
||||
Como te habrás dado cuenta un elemento puede ser seleccionado por más
|
||||
de un selector. En este caso alguna de las reglas cobra preferencia
|
||||
sobre las otras:
|
||||
An element may be targeted by multiple selectors and may have a property set on
|
||||
it in more than once. In these cases, one of the rules takes precedence over
|
||||
others. Rules with a more specific selector take precedence over a less specific
|
||||
one, and a rule occurring later in the stylesheet overwrites a previous one
|
||||
(which also means that if two different linked stylesheets contain rules for an
|
||||
element and if the rules are of the same specificity, then order of linking
|
||||
would take precedence and the sheet linked latest would govern styling) .
|
||||
|
||||
Dado el siguiente CSS:
|
||||
This process is called cascading, hence the name Cascading Style Sheets.
|
||||
|
||||
Given the following CSS:
|
||||
|
||||
```css
|
||||
/*A*/
|
||||
p.clase1[attr='valor']
|
||||
/* A */
|
||||
p.class1[attr='value']
|
||||
|
||||
/*B*/
|
||||
p.clase1 {}
|
||||
/* B */
|
||||
p.class1 { }
|
||||
|
||||
/*C*/
|
||||
p.clase2 {}
|
||||
/* C */
|
||||
p.class2 { }
|
||||
|
||||
/*D*/
|
||||
p {}
|
||||
|
||||
/*E*/
|
||||
p { propiedad: valor !important; }
|
||||
/* D */
|
||||
p { }
|
||||
|
||||
/* E */
|
||||
p { property: value !important; }
|
||||
```
|
||||
|
||||
Y el siguiente HTML:
|
||||
and the following markup:
|
||||
|
||||
```xml
|
||||
<p style='/*F*/ propiedad:valor;' class='clase1 clase2' attr='valor'>
|
||||
</p>
|
||||
```html
|
||||
<p style='/*F*/ property:value;' class='class1 class2' attr='value'>
|
||||
```
|
||||
|
||||
El orden respetado es el siguiente:
|
||||
Recuerda, la preferencia es por cada **property**, no para el bloque completo.
|
||||
The precedence of style is as follows. Remember, the precedence is for each
|
||||
**property**, not for the entire block.
|
||||
|
||||
* `E` tiene la preferencia más elevada gracias a la palabra `!important`.
|
||||
Es recomendado evitar esto a menos que sea estrictamente necesario incluirlo.
|
||||
* `F` le sigue, porque es estilo incrustado directamente en el HTML.
|
||||
* `A` le sigue, porque es más específico que cualquier otra opción.
|
||||
más específico = más especificadores. Aquí hay tres especificadores: elemento `p` +
|
||||
nombre de la clase `clase1` + un atributo `attr='valor'`
|
||||
* `C` le sigue. Aunque tiene el mismo número de especificadores como `B`
|
||||
pero aparece después.
|
||||
* Luego va `B`
|
||||
* y al final `D`.
|
||||
* `E` has the highest precedence because of the keyword `!important`. It is
|
||||
recommended that you avoid its usage.
|
||||
* `F` is next, because it is an inline style.
|
||||
* `A` is next, because it is more "specific" than anything else. It has 3
|
||||
specifiers: The name of the element `p`, its class `class1`, an attribute
|
||||
`attr='value'`.
|
||||
* `C` is next, even though it has the same specificity as `B`.
|
||||
This is because it appears after `B`.
|
||||
* `B` is next.
|
||||
* `D` is the last one.
|
||||
|
||||
## Compatibilidad
|
||||
## Media Queries
|
||||
|
||||
La mayoría de las funcionalidades de CSS2 (y gradualmente de CSS3) son compatibles
|
||||
en todos los navegadores y dispositivos. Pero siempre es vital tener en mente la
|
||||
compatibilidad y disponibilidad del CSS que uses con respecto a los navegadores
|
||||
y dispositivos para los que desarrolles.
|
||||
CSS Media Queries are a feature in CSS 3 which allows you to specify when certain CSS rules should be applied, such as when printed, or when on a screen with certain dimensions or pixel density. They do not add to the selector's specificity.
|
||||
|
||||
[QuirksMode CSS](http://www.quirksmode.org/css/) es una excelente referencia para esto.
|
||||
```css
|
||||
/* A rule that will be used on all devices */
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
## Recursos
|
||||
/* change the h1 to use less ink on a printer */
|
||||
@media print {
|
||||
h1 {
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
* Para ejecutar un test de compatibilidad, revisa [CanIUse](http://caniuse.com).
|
||||
* CSS Playground [Dabblet](http://dabblet.com/).
|
||||
* [Mozilla Developer Network's CSS documentation](https://developer.mozilla.org/en-US/docs/Web/CSS).
|
||||
* [Codrops' CSS Reference](http://tympanus.net/codrops/css_reference/).
|
||||
/* make the font bigger when shown on a screen at least 480px wide */
|
||||
@media screen and (min-width: 480px) {
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Otras lecturas
|
||||
Media queries can include these features:
|
||||
`width`, `height`, `device-width`, `device-height`, `orientation`, `aspect-ratio`, `device-aspect-ratio`, `color`, `color-index`, `monochrome`, `resolution`, `scan`, `grid`. Most of these features can be prefixed with `min-` or `max-`.
|
||||
|
||||
* [Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/).
|
||||
* [Selecting elements using attributes](https://css-tricks.com/almanac/selectors/a/attribute/).
|
||||
* [QuirksMode CSS](http://www.quirksmode.org/css/).
|
||||
The `resolution` feature is not supported by older devices, instead use `device-pixel-ratio`.
|
||||
|
||||
Many smartphones and tablets will attempt to render the page as if it were on a desktop unless you provide a `viewport` meta-tag.
|
||||
|
||||
```html
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
</head>
|
||||
```
|
||||
|
||||
## Compatibility
|
||||
|
||||
Most of the features in CSS 2 (and many in CSS 3) are available across all
|
||||
browsers and devices. But it's always good practice to check before using
|
||||
a new feature.
|
||||
|
||||
## Resources
|
||||
|
||||
* [CanIUse](http://caniuse.com) (Detailed compatibility info)
|
||||
* [Dabblet](http://dabblet.com/) (CSS playground)
|
||||
* [Mozilla Developer Network's CSS documentation](https://developer.mozilla.org/en-US/docs/Web/CSS) (Tutorials and reference)
|
||||
* [Codrops' CSS Reference](http://tympanus.net/codrops/css_reference/) (Reference)
|
||||
|
||||
## Further Reading
|
||||
|
||||
* [Understanding Style Precedence in CSS: Specificity, Inheritance, and the Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/)
|
||||
* [Selecting elements using attributes](https://css-tricks.com/almanac/selectors/a/attribute/)
|
||||
* [QuirksMode CSS](http://www.quirksmode.org/css/)
|
||||
* [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context)
|
||||
* [SASS](http://sass-lang.com/) y [LESS](http://lesscss.org/) para preprocesamiento CSS.
|
||||
* [CSS-Tricks](https://css-tricks.com).
|
||||
* [SASS](http://sass-lang.com/) and [LESS](http://lesscss.org/) for CSS pre-processing
|
||||
* [CSS-Tricks](https://css-tricks.com)
|
||||
|
||||
|
||||
|
167
es-es/docker-es.html.markdown
Normal file
167
es-es/docker-es.html.markdown
Normal file
@ -0,0 +1,167 @@
|
||||
---
|
||||
language: docker
|
||||
filename: docker-es.bat
|
||||
contributors:
|
||||
- ["Ruslan López", "http://javapro.org/"]
|
||||
- ["Michael Chen", "https://github.com/ML-Chen"]
|
||||
lang: es-es
|
||||
---
|
||||
|
||||
```bat
|
||||
:: descargar, instalar y ejecutar la imágen del hola mundo
|
||||
docker run hello-world
|
||||
|
||||
:: Si esta es la primera vez, deberíais de poder ver el mensaje
|
||||
:: Unable to find image 'hello-world:latest' locally
|
||||
:: latest: Pulling from library/hello-world
|
||||
:: 1b930d010525: Pull complete
|
||||
:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
|
||||
:: Status: Downloaded newer image for hello-world:latest
|
||||
::
|
||||
:: Hello from Docker!
|
||||
:: This message shows that your installation appears to be working correctly.
|
||||
::
|
||||
:: To generate this message, Docker took the following steps:
|
||||
:: 1. The Docker client contacted the Docker daemon.
|
||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. The Docker daemon created a new container from that image which runs the
|
||||
:: executable that produces the output you are currently reading.
|
||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
:: to your terminal.
|
||||
::
|
||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Share images, automate workflows, and more with a free Docker ID:
|
||||
:: https://hub.docker.com/
|
||||
::
|
||||
:: For more examples and ideas, visit:
|
||||
:: https://docs.docker.com/get-started/
|
||||
:: El susodicho mensaje se podría traducir como:
|
||||
::
|
||||
:: Hola desde Docker!
|
||||
:: Este mensaje muestra que su instalación parece estar funcionando crrectamente.
|
||||
::
|
||||
:: Para generar este mensaje, Docker realizó los siguientes pasos:
|
||||
:: 1. El cliente de Docker contactó a Docker daemon.
|
||||
:: 2. El Docker daemon obtubo la imágen "hello-world" desde Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. El Docker daemon creó un nuevo contenedor a partir de esa imagen con la cual ejecuta el
|
||||
:: ejecutable que produce la salida que estás leyendo.
|
||||
:: 4. El Docker daemon transmitió dicha salida el cliente Docker, el cual
|
||||
:: la envió a tu terminal.
|
||||
::
|
||||
:: Para intentar algo más ambicioso, puede correr un contenedor Ubuntu mediante:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Comparte imágenes, automatice flujos y más con un Docker ID gratuito:
|
||||
:: https://hub.docker.com/
|
||||
|
||||
:: ahora veamos las imágenes que se están ejecutando actualmente
|
||||
docker ps
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
|
||||
:: veamos las imágenes que hemos ejecutado previamente
|
||||
docker ps -a
|
||||
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
|
||||
:: happy_poincare
|
||||
:: la parte del nombre se genera automáticamente, así que probablemente sea diferente para vos
|
||||
|
||||
:: eliminemos nuestra imagen previamente generada
|
||||
docker rm happy_poincare
|
||||
|
||||
:: verifiquemos si realmente fue borrada
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
|
||||
:: especifiquemos un nombre personalizado para el contenedor
|
||||
docker run --name test_container hello-world
|
||||
:: Hello from Docker!
|
||||
:: This message shows that your installation appears to be working correctly.
|
||||
::
|
||||
:: To generate this message, Docker took the following steps:
|
||||
:: 1. The Docker client contacted the Docker daemon.
|
||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. The Docker daemon created a new container from that image which runs the
|
||||
:: executable that produces the output you are currently reading.
|
||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
:: to your terminal.
|
||||
::
|
||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Share images, automate workflows, and more with a free Docker ID:
|
||||
:: https://hub.docker.com/
|
||||
::
|
||||
:: For more examples and ideas, visit:
|
||||
:: https://docs.docker.com/get-started/
|
||||
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
|
||||
:: test_container
|
||||
:: tal como podeis ver el nombre es el que especificamos
|
||||
|
||||
:: obtener los registros de un contenedor nombrado
|
||||
docker logs test_container
|
||||
:: Hello from Docker!
|
||||
:: This message shows that your installation appears to be working correctly.
|
||||
::
|
||||
:: To generate this message, Docker took the following steps:
|
||||
:: 1. The Docker client contacted the Docker daemon.
|
||||
:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
:: (amd64)
|
||||
:: 3. The Docker daemon created a new container from that image which runs the
|
||||
:: executable that produces the output you are currently reading.
|
||||
:: 4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
:: to your terminal.
|
||||
::
|
||||
:: To try something more ambitious, you can run an Ubuntu container with:
|
||||
:: $ docker run -it ubuntu bash
|
||||
::
|
||||
:: Share images, automate workflows, and more with a free Docker ID:
|
||||
:: https://hub.docker.com/
|
||||
::
|
||||
:: For more examples and ideas, visit:
|
||||
:: https://docs.docker.com/get-started/
|
||||
|
||||
docker rm test_container
|
||||
|
||||
docker run ubuntu
|
||||
:: Unable to find image 'ubuntu:latest' locally
|
||||
:: latest: Pulling from library/ubuntu
|
||||
:: 2746a4a261c9: Pull complete
|
||||
:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
|
||||
:: Status: Downloaded newer image for ubuntu:latest
|
||||
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
|
||||
:: relaxed_nobel
|
||||
|
||||
:: ejecutando un contenedor en modo interactivo
|
||||
docker run -it ubuntu
|
||||
:: root@e2cac48323d2:/# uname
|
||||
:: Linux
|
||||
:: root@e2cac48323d2:/# exit
|
||||
:: exit
|
||||
|
||||
docker rm relaxed_nobel
|
||||
|
||||
docker ps -a
|
||||
:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
|
||||
:: NAMES
|
||||
:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
|
||||
:: nifty_goldwasser
|
||||
|
||||
docker rm nifty_goldwasser
|
||||
```
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: elixir
|
||||
language: Elixir
|
||||
contributors:
|
||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
||||
@ -23,10 +23,10 @@ y otras características más.
|
||||
# No hay comentarios multilinea,
|
||||
# pero se pueden apilar varios comentarios.
|
||||
|
||||
# Para usar el shell de elixir se usa el comando `iex`.
|
||||
# Para usar el shell de Elixir se usa el comando `iex`.
|
||||
# Los módulos se compilan con el comando `elixirc`.
|
||||
|
||||
# Ambos deberían estar en la ruta si elixir se instaló correctamente.
|
||||
# Ambos deberían estar en la ruta si Elixir se instaló correctamente.
|
||||
|
||||
## ---------------------------
|
||||
## -- Tipos básicos
|
||||
@ -55,7 +55,7 @@ elem({1, 2, 3}, 0) #=> 1
|
||||
head #=> 1
|
||||
tail #=> [2,3]
|
||||
|
||||
# En elixir, solo como Erlang, el `=` denota la coincidencia de patrones y
|
||||
# En Elixir, solo como Erlang, el `=` denota la coincidencia de patrones y
|
||||
# no una asignación.
|
||||
#
|
||||
# This is how the above example of accessing the head and tail of a list works.
|
||||
@ -87,7 +87,7 @@ string.
|
||||
<<?a, ?b, ?c>> #=> "abc"
|
||||
[?a, ?b, ?c] #=> 'abc'
|
||||
|
||||
# `?a` en elixir devuelve el valor ASCII para el caracter `a`
|
||||
# `?a` en Elixir devuelve el valor ASCII para el caracter `a`
|
||||
?a #=> 97
|
||||
|
||||
# Para concatenar listas se usa `++`, para binarios `<>`
|
||||
@ -120,7 +120,7 @@ genders.gillian #=> "female"
|
||||
5 * 2 #=> 10
|
||||
10 / 2 #=> 5.0
|
||||
|
||||
# En elixir el operador `/` siempre devuelve un número flotante
|
||||
# En Elixir el operador `/` siempre devuelve un número flotante
|
||||
|
||||
# Para hacer la división de número entero se debe usar `div`
|
||||
div(10, 2) #=> 5
|
||||
@ -175,7 +175,7 @@ else
|
||||
end
|
||||
|
||||
# Se acuerda de la coincidencia de patrones?
|
||||
# Muchas estructuras de control de flujo en elixir confían en ella.
|
||||
# Muchas estructuras de control de flujo en Elixir confían en ella.
|
||||
|
||||
# `case` permite comparar un valor con muchos patrones:
|
||||
case {:one, :two} do
|
||||
@ -305,7 +305,7 @@ Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||
# Geometry.area({:circle, "not_a_number"})
|
||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||
|
||||
# Debido a la inmutabilidad, la recursión es una gran parte de elixir
|
||||
# Debido a la inmutabilidad, la recursión es una gran parte de Elixir
|
||||
defmodule Recursion do
|
||||
def sum_list([head | tail], acc) do
|
||||
sum_list(tail, acc + head)
|
||||
@ -380,7 +380,7 @@ end
|
||||
## ---------------------------
|
||||
|
||||
# Elixir confía en el modelo actor para la concurrencia. Todo lo que se necesita para escribir
|
||||
# programas concurrentes en elixir son tres primitivas: procesos de desove,
|
||||
# programas concurrentes en Elixir son tres primitivas: procesos de desove,
|
||||
# envío de mensajes y recepción de mensajes.
|
||||
|
||||
# Para empezar un nuevo proceso se usa la función `spawn`,
|
||||
|
@ -13,7 +13,7 @@ Forth fue criado por Charles H. Moore en los 70s. Forth es un lenguaje imperativ
|
||||
Nota: Este articulo enfoca predominantemente en la Gforth implementación de Forth, pero casi todo
|
||||
de lo que esta escrito aquí debe funcionar en otro sitio.
|
||||
|
||||
```
|
||||
```forth
|
||||
\ Este es un comentario
|
||||
( Este es un comentario también pero solo esta usado cuando definiendo palabras. )
|
||||
|
||||
|
@ -410,10 +410,8 @@ $ git rm /directorio/del/archivo/FooBar.c
|
||||
|
||||
* [SalesForce Chuleta](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf)
|
||||
|
||||
* [GitGuys](http://www.gitguys.com/)
|
||||
|
||||
* [Git - La guía simple](http://rogerdudler.github.io/git-guide/index.html)
|
||||
|
||||
* [Pro Git](http://www.git-scm.com/book/en/v2)
|
||||
|
||||
* [Una introducción a Git y Github para principiantes (Tutorial)](http://product.hubspot.com/blog/git-and-github-tutorial-for-beginners)
|
||||
* [Una introducción a Git y GitHub para principiantes (Tutorial)](http://product.hubspot.com/blog/git-and-github-tutorial-for-beginners)
|
||||
|
@ -88,7 +88,7 @@ saltos de línea.` // mismo tipo cadena
|
||||
|
||||
// Literal no ASCII. Los ficheros fuente de Go son UTF-8.
|
||||
g := 'Σ' // Tipo rune, un alias de int32, alberga un carácter unicode.
|
||||
f := 3.14195 // float64, el estándar IEEE-754 de coma flotante 64-bit.
|
||||
f := 3.14159 // float64, el estándar IEEE-754 de coma flotante 64-bit.
|
||||
c := 3 + 4i // complex128, representado internamente por dos float64.
|
||||
// Sintaxis var con iniciadores.
|
||||
var u uint = 7 // Sin signo, pero la implementación depende del tamaño
|
||||
@ -425,7 +425,7 @@ func consultaAlServidor() {
|
||||
## Más información
|
||||
|
||||
La raíz de todas las cosas sobre Go es el
|
||||
[sitio web oficial de Go](http://golang.org/).
|
||||
[sitio web oficial de Go](https://go.dev/).
|
||||
Allí puedes seguir el tutorial, jugar interactivamente y leer mucho más.
|
||||
|
||||
La definición del lenguaje es altamente recomendada. Es fácil de leer y
|
||||
@ -433,17 +433,17 @@ sorprendentemente corta (como la definición del lenguaje Go en estos
|
||||
días).
|
||||
|
||||
Puedes jugar con el código en el
|
||||
[parque de diversiones Go](https://play.golang.org/p/ncRC2Zevag). ¡Trata
|
||||
[parque de diversiones Go](https://go.dev/play/p/ncRC2Zevag). ¡Trata
|
||||
de cambiarlo y ejecutarlo desde tu navegador! Ten en cuenta que puedes
|
||||
utilizar [https://play.golang.org]( https://play.golang.org) como un
|
||||
utilizar [https://go.dev/play/]( https://go.dev/play/) como un
|
||||
[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) para probar
|
||||
cosas y el código en el navegador, sin ni siquiera instalar Go.
|
||||
|
||||
En la lista de lecturas para estudiantes de Go está el
|
||||
[código fuente de la biblioteca estándar](http://golang.org/src/pkg/).
|
||||
[código fuente de la biblioteca estándar](https://go.dev/src/).
|
||||
Ampliamente documentado, que demuestra lo mejor del legible y comprensible
|
||||
Go, con su característico estilo y modismos. ¡O puedes hacer clic en un
|
||||
nombre de función en [la documentación](http://golang.org/pkg/) y
|
||||
nombre de función en [la documentación](https://go.dev/pkg/) y
|
||||
aparecerá el código fuente!
|
||||
|
||||
Otro gran recurso para aprender Go está en
|
||||
|
@ -28,7 +28,7 @@ En Julia los programas están organizados entorno al [despacho múltiple](http:/
|
||||
* [Buen desempeño](http://julialang.org/benchmarks), comparado al de lenguajes **estáticamente compilados** como C.
|
||||
* [Gestor de paquetes](http://docs.julialang.org/en/release-0.3/stdlib/pkg) integrado.
|
||||
* [Macros tipo Lisp](http://docs.julialang.org/en/release-0.3/manual/metaprogramming/#macros) y otras comodidades para la [meta programación](http://docs.julialang.org/en/release-0.3/manual/metaprogramming).
|
||||
* Llamar funciones de otros lenguajes, mediante paquetes como: **Python** ([PyCall](https://github.com/stevengj/PyCall.jl)), [Mathematica](http://github.com/one-more-minute/Mathematica.jl), **Java** ([JavaCall](http://github.com/aviks/JavaCall.jl)), **R** ([Rif](http://github.com/lgautier/Rif.jl) y [RCall](http://github.com/JuliaStats/RCall.jl)) y **Matlab** ([MATLAB](http://github.com/JuliaLang/MATLAB.jl)).
|
||||
* Llamar funciones de otros lenguajes, mediante paquetes como: **Python** ([PyCall](https://github.com/stevengj/PyCall.jl)), [Mathematica](http://github.com/one-more-minute/Mathematica.jl), **Java** ([JavaCall](http://github.com/aviks/JavaCall.jl)), **R** ([Rif](http://github.com/lgautier/Rif.jl) y [RCall](http://github.com/JuliaStats/RCall.jl)) y **MATLAB** ([MATLAB](http://github.com/JuliaLang/MATLAB.jl)).
|
||||
* [Llamar funciones de C y Fortran](http://docs.julialang.org/en/release-0.3/manual/calling-c-and-fortran-code) **directamente**: sin necesidad de usar envoltorios u APIs especiales.
|
||||
* Poderosas características de **línea de comandos** para [gestionar otros procesos](http://docs.julialang.org/en/release-0.3/manual/running-external-programs).
|
||||
* Diseñado para la [computación paralela y distribuida](http://docs.julialang.org/en/release-0.3/manual/parallel-computing) **desde el principio**.
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: Matlab
|
||||
language: MATLAB
|
||||
filename: learnmatlab-es.mat
|
||||
contributors:
|
||||
- ["mendozao", "http://github.com/mendozao"]
|
||||
@ -139,7 +139,7 @@ A.d.e = false;
|
||||
|
||||
% Vectores
|
||||
x = [4 32 53 7 1]
|
||||
x(2) % ans = 32, los índices en Matlab comienzan 1, no 0
|
||||
x(2) % ans = 32, los índices en MATLAB comienzan 1, no 0
|
||||
x(2:3) % ans = 32 53
|
||||
x(2:end) % ans = 32 53 7 1
|
||||
|
||||
@ -506,7 +506,7 @@ find(x) % Encuentra todos los elementos distintos de cero de x y devuelve sus í
|
||||
|
||||
|
||||
% Clases
|
||||
% Matlab puede soportar programación orientada a objetos.
|
||||
% MATLAB puede soportar programación orientada a objetos.
|
||||
% Las clases deben colocarse en un archivo del nombre de la clase con la extensión .m.
|
||||
% Para comenzar, creamos una clase simple para almacenar puntos de referencia de GPS.
|
||||
% Comience WaypointClass.m
|
||||
@ -528,7 +528,7 @@ classdef WaypointClass % El nombre de la clase.
|
||||
end
|
||||
|
||||
% Si queremos agregar dos objetos Waypoint juntos sin llamar
|
||||
% a una función especial, podemos sobrecargar la aritmética de Matlab así:
|
||||
% a una función especial, podemos sobrecargar la aritmética de MATLAB así:
|
||||
function r = plus(o1,o2)
|
||||
r = WaypointClass([o1.latitude] +[o2.latitude], ...
|
||||
[o1.longitude]+[o2.longitude]);
|
||||
@ -540,7 +540,7 @@ end
|
||||
% Podemos crear un objeto de la clase usando el constructor
|
||||
a = WaypointClass(45.0, 45.0)
|
||||
|
||||
% Las propiedades de clase se comportan exactamente como estructuras de Matlab.
|
||||
% Las propiedades de clase se comportan exactamente como estructuras de MATLAB.
|
||||
a.latitude = 70.0
|
||||
a.longitude = 25.0
|
||||
|
||||
@ -551,15 +551,15 @@ ans = multiplyLatBy(a,3)
|
||||
% no necesita ser pasado al método.
|
||||
ans = a.multiplyLatBy(a,1/3)
|
||||
|
||||
% Las funciones de Matlab pueden sobrecargarse para manejar objetos.
|
||||
% En el método anterior, hemos sobrecargado cómo maneja Matlab
|
||||
% Las funciones de MATLAB pueden sobrecargarse para manejar objetos.
|
||||
% En el método anterior, hemos sobrecargado cómo maneja MATLAB
|
||||
% la adición de dos objetos Waypoint.
|
||||
b = WaypointClass(15.0, 32.0)
|
||||
c = a + b
|
||||
|
||||
```
|
||||
|
||||
## Más sobre Matlab
|
||||
## Más sobre MATLAB
|
||||
|
||||
* [The official website (EN)](http://www.mathworks.com/products/matlab/)
|
||||
* [The official MATLAB Answers forum (EN)](http://www.mathworks.com/matlabcentral/answers/)
|
||||
|
@ -34,7 +34,7 @@ $PSVersionTable
|
||||
|
||||
Para obtener ayuda:
|
||||
|
||||
```
|
||||
```powershell
|
||||
# Si necesita encontrar algún comando
|
||||
Get-Command about_* # tiene por abreviación (o alias): gcm
|
||||
Get-Command -Verb Add # lista todos los comandos que tienen por verbo 'Add'
|
||||
@ -51,7 +51,7 @@ Update-Help # Actualiza la ayuda (debe ser ejecutado en una consola elevada como
|
||||
|
||||
Acá inicia el tutorial:
|
||||
|
||||
```
|
||||
```powershell
|
||||
# Como ya lo notó, los comentarios empiezan con #
|
||||
|
||||
# Ejemplo de un simple hola mundo:
|
||||
@ -299,7 +299,7 @@ $Shortcut.Save()
|
||||
|
||||
Configurando el shell
|
||||
|
||||
```
|
||||
```powershell
|
||||
# $Profile es la ruta completa para su `Microsoft.PowerShell_profile.ps1`
|
||||
# Todo el código alojado allí será ejecutado cuando se ejecuta una nueva sesión de PS
|
||||
if (-not (Test-Path $Profile)) {
|
||||
|
@ -16,7 +16,7 @@ Esta es una adaptación de la introducción a QT con C++ por [Aleksey Kholovchuk
|
||||
```python
|
||||
import sys
|
||||
from PyQt4 import QtGui
|
||||
|
||||
|
||||
def window():
|
||||
# Crear el objeto de la aplicación
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
@ -44,7 +44,7 @@ if __name__ == '__main__':
|
||||
Para poder hacer uso de las funciones más avanzades en **pyqt** necesitamos agregar elementos adicionales.
|
||||
Aquí mostramos cómo introducir una caja de diálogo popup, útil para permitir al usuario confirmar su decisión o para brindarnos información.
|
||||
|
||||
```Python
|
||||
```python
|
||||
import sys
|
||||
from PyQt4.QtGui import *
|
||||
from PyQt4.QtCore import *
|
||||
@ -63,7 +63,7 @@ def window():
|
||||
w.setWindowTitle("PyQt Dialog")
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
# Esta función debería crear una ventana de diálogo con un botón
|
||||
# que espera a recibir un click y luego sale del programa
|
||||
def showdialog():
|
||||
|
@ -328,7 +328,7 @@ dicc_lleno = {"uno": 1, "dos": 2, "tres": 3}
|
||||
nuestro_iterable = dicc_lleno.keys()
|
||||
print(nuestro_iterable) #=> dict_keys(['uno', 'dos', 'tres']). Este es un objeto que implementa nuestra interfaz Iterable
|
||||
|
||||
Podemos recorrerla.
|
||||
# Podemos recorrerla.
|
||||
for i in nuestro_iterable:
|
||||
print(i) # Imprime uno, dos, tres
|
||||
|
||||
@ -388,8 +388,8 @@ keyword_args(pie="grande", lago="ness") #=> {"pie": "grande", "lago": "ness"}
|
||||
|
||||
# Puedes hacer ambas a la vez si quieres
|
||||
def todos_los_argumentos(*args, **kwargs):
|
||||
print args
|
||||
print kwargs
|
||||
print(args)
|
||||
print(kwargs)
|
||||
"""
|
||||
todos_los_argumentos(1, 2, a=3, b=4) imprime:
|
||||
(1, 2)
|
||||
@ -462,10 +462,10 @@ class Humano(object):
|
||||
|
||||
# Instancia una clase
|
||||
i = Humano(nombre="Ian")
|
||||
print i.decir("hi") # imprime "Ian: hi"
|
||||
print(i.decir("hi")) # imprime "Ian: hi"
|
||||
|
||||
j = Humano("Joel")
|
||||
print j.decir("hello") #imprime "Joel: hello"
|
||||
print(j.decir("hello")) #imprime "Joel: hello"
|
||||
|
||||
# Llama nuestro método de clase
|
||||
i.get_especie() #=> "H. sapiens"
|
||||
@ -548,7 +548,7 @@ def pedir(_decir):
|
||||
|
||||
|
||||
@pedir
|
||||
def say(decir_por_favor=False):
|
||||
def decir(decir_por_favor=False):
|
||||
mensaje = "¿Puedes comprarme una cerveza?"
|
||||
return mensaje, decir_por_favor
|
||||
|
||||
|
@ -16,7 +16,7 @@ LaTeX.
|
||||
|
||||
```r
|
||||
|
||||
# Los comentariso inician con símbolos numéricos.
|
||||
# Los comentarios inician con símbolos numéricos.
|
||||
|
||||
# No puedes hacer comentarios de múltiples líneas
|
||||
# pero puedes agrupar múltiples comentarios de esta manera.
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: perl6
|
||||
name: Raku
|
||||
category: language
|
||||
language: Raku
|
||||
filename: learnraku-es.raku
|
||||
|
@ -89,10 +89,10 @@ true || false #=> true
|
||||
# Estos son usados como constructores controladores de flujo que encadenan
|
||||
# sentencias hasta que una de ellas retorne verdadero o falso
|
||||
|
||||
# `has_otra_cosa` solo se llama si `has_algo` retorna verdadero.
|
||||
has_algo() and has_otra_cosa()
|
||||
# `registra_error` solo se llama si `has_algo` falla
|
||||
has_algo() or registra_error()
|
||||
# `haz_otra_cosa` solo se llama si `haz_algo` retorna verdadero.
|
||||
haz_algo() and haz_otra_cosa()
|
||||
# `registra_error` solo se llama si `haz_algo` falla
|
||||
haz_algo() or registra_error()
|
||||
|
||||
|
||||
# Los strings son objetos
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: rust
|
||||
language: Rust
|
||||
contributors:
|
||||
- ["P1start", "http://p1start.github.io/"]
|
||||
translators:
|
||||
@ -225,7 +225,7 @@ fn main() {
|
||||
|
||||
// bucles `for`
|
||||
let array = [1, 2, 3];
|
||||
for i in array.iter() {
|
||||
for i in array {
|
||||
println!("{}", i);
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,7 @@ Las expresiones múltiples son separadas por un punto. ^ retorna inmediatamente.
|
||||
```
|
||||
|
||||
Los bloques son ejecutados al enviales el mensaje 'value' y son inherentes (delegados a) sus contextos:
|
||||
|
||||
```
|
||||
"returns 0"
|
||||
[|x|
|
||||
|
@ -8,7 +8,7 @@ filename: learnvisualbasic-es.vb
|
||||
lang: es-es
|
||||
---
|
||||
|
||||
```
|
||||
```visualbasic
|
||||
Module Module1
|
||||
|
||||
Sub Main()
|
||||
|
@ -15,7 +15,7 @@ El lenguaje de Wolfram tiene varias interfaces:
|
||||
|
||||
El código de este ejemplo se puede escribir en cualquier interfaz y editarlo con Wolfram Workbench. Cargar directamente en Matematica puede resultar incómodo porque el archivo no contiene información de formato de celda (lo que haría que el archivo sea un desastre enorme para ser leído como texto) - puede ser visto / editado pero tal vez requerira algún ajuste.
|
||||
|
||||
```
|
||||
```mathematica
|
||||
(* Esto es un comentario *)
|
||||
|
||||
(* En Mathematica en lugar de utilizar estos comentarios, puede crear una celda de texto
|
||||
|
@ -29,21 +29,21 @@ filename: learncss-fa.css
|
||||
|
||||
<p dir='rtl'>در CSS همه توضیحات داخل ستاره-بروم نوشته میشوند زیرا CSS دستوری برای توضیحات تک خطی مثل C ندارد</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
/* comments appear inside slash-asterisk, just like this line!
|
||||
there are no "one-line comments"; this is the only comment style */
|
||||
```
|
||||
|
||||
<p dir='rtl'>به طور کلی دستورات CSS بسیار ساده هستند که در آن یک انتخابگر (selector) عنصری را در روی صفحه هدف قرار میدهد.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
selector { property: value; /* more properties...*/ }
|
||||
```
|
||||
|
||||
<p dir='rtl'>با استفاده از ستاره می توان برای همه عناصر روی صفحه استایل تعریف کرد</p>
|
||||
|
||||
|
||||
```CSS
|
||||
```css
|
||||
* { color:red; }
|
||||
```
|
||||
|
||||
@ -55,129 +55,129 @@ selector { property: value; /* more properties...*/ }
|
||||
<p dir='rtl'>شما میتوانید با استفاده از نام کلاس آنرا انتخاب کنید</p>
|
||||
|
||||
|
||||
```CSS
|
||||
```css
|
||||
.some-class { }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا با استفاده از نام دو کلاس</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
.some-class.class2 { }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا با استفاده از نام id</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
#someId { }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا با استفاده از نام خود عنصر</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
div { }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا با استفاده از `attr`</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
[attr] { font-size:smaller; }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا با استفاده از ارزشی که برای `attr` مشخص شده</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
[attr='value'] { font-size:smaller; }
|
||||
```
|
||||
|
||||
<p dir='rtl'>با استفاده از ارزشی که برای `attr` مشخص شده و آن ارزش با `val` شروع میشود در CSS3</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
[attr^='val'] { font-size:smaller; }
|
||||
```
|
||||
|
||||
<p dir='rtl'>با استفاده از ارزشی که برای `attr` مشخص شده و آن ارزش با `ue` به پایان میرسد در CSS3</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
[attr$='ue'] { font-size:smaller; }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا با انتخاب بوسیله یکی از ارزشهایی که در لیست `otherAttr` بوسیله فاصله از هم جدا شده اند در CSS3</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
[attr$='ue'] { font-size:smaller; }
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا ارزش(`value`) دقیقاً خود ارزش(`value`) یا بوسیله `-` که یونیکد (U+002D) از حرف بعدی جدا شود</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
[otherAttr|='en'] { font-size:smaller; }
|
||||
```
|
||||
|
||||
<p dir='rtl'>و مهمتر از همه اینکه میتوان آنها را ترکیب کرد. نکته مهمی که در اینجا باید مد نظر داشته باشید این است که هنگام ترکیب نباید هیچگونه فاصله ای بین آنها قرار گیرد زیرا در این حالت معنای دستور تغییر میکند</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
div.some-class[attr$='ue'] { }
|
||||
```
|
||||
|
||||
<p dir='rtl'>CSS این امکان را به شما میدهد که یک عنصر را بوسیله والدین آن انتخاب کنید</p>
|
||||
<p dir='rtl'>برای مثال دستور زیر همه عناصری را که نام کلاس آنها <span dir="ltr">`.class-name`</span> و دارای پدر و مادری با این مشخصه <span dir="ltr">`div.some-parent`</span> هستند را انتخاب میکند.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
div.some-parent > .class-name {}
|
||||
```
|
||||
|
||||
|
||||
<p dir='rtl'>یا دستور زیر که همه عناصری را که نام کلاس آنها <span dir="ltr">`.class-name`</span> و داخل عنصری با مشخصه <span dir="ltr">`div.some-parent`</span> هستند را در هر عمقی که باشند (یعنی فرزندی از فرزندان <span dir="ltr">`div.some-parent`</span><span dir="ltr"> باشند) انتخاب میکند.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
div.some-parent .class-name {}
|
||||
```
|
||||
|
||||
<p dir='rtl'>نکته ای که در اینجا باید به آن توجه کنید این است که این رستور با فاصله ای بین نام دو کلاس همراه است و با مثال زیر که در بالا هم ذکر شد تفاوت دارد.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
div.some-parent.class-name {}
|
||||
```
|
||||
|
||||
<p dir='rtl'>دستور زیر همه عناصری را که نام کلاس آنها <span dir="ltr">`.this-element`</span> و بلافاصله بعد از عنصری با مشخصه <span dir="ltr">`.i-am-before`</span> قرار دارد را انتخاب میکند.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
.i-am-before + .this-element { }
|
||||
```
|
||||
|
||||
<p dir='rtl'>هر خواهر یا برادری که بعد از <span dir="ltr">`.i-am-before`</span> بیاید در اینجا لازم نیست بلافاصله بعد از هم قرار بگیرند ولی باید دارای پدر و مادری یکسان باشند.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
.i-am-any-before ~ .this-element {}
|
||||
```
|
||||
<p dir='rtl'>در زیر چند نمونه از شبه کلاسها را معرفی میکنیم که به شما اجازه میدهد عناصر را بر اساس رفتار آنها در صفحه انتخاب کنید.</p>
|
||||
<p dir='rtl'>برای مثال زمانی که اشاره گر ماوس روی عنصری بر روی صفحه قرار دارد.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
selector:hover {}
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا زمانی از یک لینک بازید کردید.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
selected:visited {}
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا زمانی از لینکی بازید نشده است.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
selected:link {}
|
||||
```
|
||||
|
||||
<p dir='rtl'>یا زمانی که روی یک عنصر ورودی متمرکز شده.</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
selected:focus {}
|
||||
```
|
||||
|
||||
<h3 dir='rtl'>واحدها</h3>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
selector {
|
||||
|
||||
/* واحدها اندازه */
|
||||
@ -247,7 +247,7 @@ selector {
|
||||
|
||||
<p dir='rtl'>به مثال زیر توجه کنید:</p>
|
||||
|
||||
```CSS
|
||||
```css
|
||||
/*A*/
|
||||
p.class1[attr='value']
|
||||
|
||||
|
469
fa-ir/vim-fa.html.markdown
Normal file
469
fa-ir/vim-fa.html.markdown
Normal file
@ -0,0 +1,469 @@
|
||||
---
|
||||
category: tool
|
||||
tool: vim
|
||||
contributors:
|
||||
- ["RadhikaG", "https://github.com/RadhikaG"]
|
||||
translators:
|
||||
- ["Moein Halvaei", "https://github.com/mo1ein"]
|
||||
lang: fa-ir
|
||||
filename: LearnVim-fa.txt
|
||||
---
|
||||
|
||||
<p dir="rtl">
|
||||
[Vim](http://www.vim.org) (Vi رشدیافته) یک کلون از ادیتور مشهور vi است برای unix. ادیتورمتنیست که برای سرعت و افزایش بهرهوری طراحی شده و در همه جا به ویژه در سیستم های unix-based دیده میشود. شورتکات کلید های بیشماری برای سرعت جهتیابی به نقاط ویژهي فایل ها و تغییر سریع، دارد.
|
||||
<br />
|
||||
`vimtutor` یک برنامهي عالیست که به شما چگونگی استفاده از `vim` را آموزش میدهد.
|
||||
این به همراه پکیج های vim هنگام نصب کردن، نصب میشود. شما باید بتوانید با ران کردن `vimtutor` در کامندلاین از آموزش ها استفاده کنید. این همهی ویژگی های عمدهی `vim` را به شما راهنمایی میکند.
|
||||
</p>
|
||||
<h3>
|
||||
<p dir="rtl">
|
||||
مکانیابی اولیه vim
|
||||
</p>
|
||||
</h3>
|
||||
|
||||
|
||||
<p dir="rtl">
|
||||
باز کردن `<filename>` در ویم
|
||||
</p>
|
||||
|
||||
```
|
||||
vim <filename> # Open <filename> in vim
|
||||
```
|
||||
<p dir="rtl">
|
||||
باز کردن help docs های `<topic>` اگر وجود داشته باشد
|
||||
</p>
|
||||
|
||||
```
|
||||
:help <topic> # Open up built-in help docs about <topic> if any exists
|
||||
```
|
||||
```
|
||||
:q # خروج از ویم
|
||||
|
||||
:w # ذخیره کردن فایل فعلی
|
||||
|
||||
:wq # ذخیره کردن و خارج شدن از ویم
|
||||
|
||||
ZZ # ذخیره کردن و خارج شدن از ویم
|
||||
|
||||
:q! # خارج شدن بدون ذخیره کردن فایل
|
||||
|
||||
! *forces* :q to execute, hence quiting vim without saving
|
||||
|
||||
ZQ # خارج شدن بدون ذخیره کردن فایل
|
||||
```
|
||||
|
||||
<p dir="rtl">ذخیره کردن و خارج شدن از vim ورژن خلاصه شدهی wq:</p>
|
||||
|
||||
```
|
||||
:x # Save file and quit vim, shorter version of :wq
|
||||
```
|
||||
|
||||
<p dir="rtl">برگشت به عقب</p>
|
||||
|
||||
```
|
||||
u # Undo
|
||||
```
|
||||
|
||||
<p dir="rtl">رفتن به جلو</p>
|
||||
|
||||
```
|
||||
CTRL+R # Redo
|
||||
```
|
||||
|
||||
<p dir="rtl">راه رفتن در صفحه</p>
|
||||
|
||||
```
|
||||
h # رفتن یک کاراکتر به چپ
|
||||
|
||||
j # رفتن یک کاراکتر به پایین
|
||||
|
||||
k # رفتن یک کاراکتر به بالا
|
||||
|
||||
l # رفتن یک کاراکتر به راست
|
||||
|
||||
Ctrl+B # جابهجا شدن به عقب به اندازه یک صفحه
|
||||
|
||||
Ctrl+F # جابهجا شدن به جلو به اندازه یک صفحه
|
||||
|
||||
Ctrl+D # جابهجا شدن به جلو به اندازه نصف صفحه
|
||||
|
||||
Ctrl+U # جابهجا شدن به عقب به اندازه نصف صفحه
|
||||
```
|
||||
|
||||
<p dir="rtl"><strong>جابهجا شدن در خط</strong></p>
|
||||
|
||||
```
|
||||
0 # رفتن به اول خط
|
||||
$ # رفتن به آخر خط
|
||||
^ # رفتن به اولین کاراکتر غیرخالی در خط
|
||||
```
|
||||
|
||||
<p dir="rtl"><strong>جست و جو در متن</strong></p>
|
||||
|
||||
```
|
||||
/word # هایلایت کردن همهی کلمه های بعد کِرسر
|
||||
|
||||
?word # هایلایت کردن همهی کلمه های قبل کِرسر
|
||||
|
||||
n # جابهجایی کِرسر به کلمه های بعدی پیدا شده
|
||||
|
||||
N # جابهجایی کِرسر به کلمه های قبلی پیدا شده
|
||||
```
|
||||
|
||||
<p dir="rtl">عوض کردن 'foo' به 'bar' در هر خط از فایل</p>
|
||||
|
||||
```
|
||||
:%s/foo/bar/g # Change 'foo' to 'bar' on every line in the file
|
||||
```
|
||||
|
||||
<p dir="rtl">عوض کردن 'foo' به 'bar' در خط فعلی</p>
|
||||
|
||||
```
|
||||
:s/foo/bar/g # Change 'foo' to 'bar' on the current line
|
||||
```
|
||||
|
||||
<p dir="rtl">جایگزینی کاراکتر های خط جدید با کاراکتر های خط جدید</p>
|
||||
|
||||
```
|
||||
:%s/\n/\r/g # Replace new line characters with new line characters
|
||||
```
|
||||
|
||||
<p dir="rtl"><strong>پرش به کاراکتر ها</strong></p>
|
||||
<p dir="rtl">پرش به جلو و قرار گرفتن روی کاراکتر مورد نظر</p>
|
||||
|
||||
```
|
||||
f<character> # Jump forward and land on <character>
|
||||
```
|
||||
|
||||
<p dir="rtl">پرش به جلو و قرار گرفتن قبل کاراکتر مورد نظر</p>
|
||||
|
||||
```
|
||||
t<character> # Jump forward and land right before <character>
|
||||
```
|
||||
|
||||
<p dir="rtl"><strong>برای مثال:</strong></p>
|
||||
|
||||
<p dir="rtl">پرش به جلو و قرار گرفتن روی ></p>
|
||||
|
||||
```
|
||||
f< # Jump forward and land on <
|
||||
```
|
||||
|
||||
<p dir="rtl">پرش به جلو و قرار گرفتن قبل از ></p>
|
||||
|
||||
```
|
||||
t< # Jump forward and land right before <
|
||||
```
|
||||
<p dir="rtl"><strong>جابهجا شدن با کلمه ها</strong></p>
|
||||
|
||||
```
|
||||
w # رفتن به جلو به اندازهی یک کلمه
|
||||
b # رفتن به عقب به اندازهی یک کلم
|
||||
e # رفتن به آخر کلمهی فعلی
|
||||
```
|
||||
<p dir="rtl"><strong>سایر کاراکتر ها برای جابهجایی</strong></p>
|
||||
<p dir="rtl">رفتن به اول فایل</p>
|
||||
|
||||
```
|
||||
gg # Go to the top of the file
|
||||
```
|
||||
<p dir="rtl">رفتن به آخر فایل</p>
|
||||
|
||||
```
|
||||
G # Go to the bottom of the file
|
||||
```
|
||||
<p dir="rtl">رفتن به شمارهی خط مورد نظر (NUM شماره است)</p>
|
||||
|
||||
```
|
||||
:NUM # Go to line number NUM (NUM is any number)
|
||||
```
|
||||
<p dir="rtl">رفتن به اول صفحه</p>
|
||||
|
||||
```
|
||||
H # Move to the top of the screen
|
||||
```
|
||||
<p dir="rtl">رفتن به وسط صفحه</p>
|
||||
|
||||
```
|
||||
M # Move to the middle of the screen
|
||||
```
|
||||
<p dir="rtl">رفتن به آخر صفحه</p>
|
||||
|
||||
```
|
||||
L # Move to the bottom of the screen
|
||||
```
|
||||
|
||||
<h3>
|
||||
<p dir="rtl"><strong>
|
||||
داک های help
|
||||
</strong></p>
|
||||
</h3>
|
||||
|
||||
<p dir="rtl">
|
||||
Vim دارای یک help doc داخلی است که میتوان با help: <topic> به آن دسترسی داشت. برای مثال help navigation: داک مربوط به مکانیابی در فضای کار را به شما نشان میدهد! <br /><br />
|
||||
help: همچنین میتواند بدون option مورد استفاده قرار گیرد.
|
||||
این یه صورت یک help پیشفرض بالا میآید که شروع vim را قابل دسترس تر میکند!
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
<p dir="rtl"><strong>Modes:</strong></p>
|
||||
</h3>
|
||||
|
||||
<div dir="rtl">
|
||||
Vim بر پایهی مفهومیست به نام <strong>modes</strong>
|
||||
<br /><br />
|
||||
<ul>
|
||||
<li>
|
||||
Command Mode - ویم در این حالت بالا میآید، برای مکانیابی و نوشتن دستورات استفاده میشود
|
||||
</li>
|
||||
<li>
|
||||
Insert Mode - برای ایجاد تغییر در فایل شما استفاده میشود
|
||||
</li>
|
||||
<li>
|
||||
Visual Mode - برای هایلایت کردن متن و انجام عملی روی آن ها استفاده میشود
|
||||
</li>
|
||||
<li>
|
||||
Ex Mode - برای وارد کردن دستورات توسط ":" در قسمت پایین استفاده میشود
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<p dir="rtl">رفتن به حالت insert, پیش از جایگاه cursor</p>
|
||||
|
||||
```
|
||||
i # Puts vim into insert mode, before the cursor position
|
||||
```
|
||||
<p dir="rtl">رفتن به حالت insert, پس از جایگاه cursor</p>
|
||||
|
||||
```
|
||||
a # Puts vim into insert mode, after the cursor position
|
||||
```
|
||||
|
||||
<p dir="rtl">رفتن به حالت visual</p>
|
||||
|
||||
```
|
||||
v # Puts vim into visual mode
|
||||
```
|
||||
<p dir="rtl">رفتن به حالت ex</p>
|
||||
|
||||
```
|
||||
: # Puts vim into ex mode
|
||||
```
|
||||
<p dir="rtl">خروج از همهی حالت ها و رفتن به حالت command</p>
|
||||
|
||||
```
|
||||
<esc> # 'Escapes' from whichever mode you're in, into Command mode
|
||||
```
|
||||
<p dir="rtl">کپی و پیست در متن</p>
|
||||
|
||||
```
|
||||
y # کپی کردن متن انتخاب شده
|
||||
|
||||
yy # کپی کردن خط فعلی
|
||||
|
||||
d # حذف کردن متن انتخاب شده
|
||||
|
||||
dd # حذف کردن خط فعلی
|
||||
|
||||
p # پیست کردن متن کپی شده پس از جایگاه فعلی کِرسر
|
||||
|
||||
P # پیست کردن متن کپی شده پیش از جایگاه فعلی کِرسر
|
||||
|
||||
x # حذف کردن یک کاراکتر از جایگاه کِرسر
|
||||
```
|
||||
|
||||
<h3>
|
||||
<p dir="rtl"><strong>گرامر (Grammer) </strong></p>
|
||||
</h3>
|
||||
|
||||
<div dir="rtl">
|
||||
Vim را می توان به عنوان مجموعه ای از دستورات در قالب (Verb - Modifier - Noun) تصور کرد ، جایی که:
|
||||
<br /><br />
|
||||
<ul>
|
||||
<li>
|
||||
Verb - عمل شما
|
||||
</li>
|
||||
<li>
|
||||
Modifier - چگونگی انجام عمل شما
|
||||
</li>
|
||||
<li>
|
||||
Noun - شیئی که عمل شما بر اساس آن عمل می کند
|
||||
</li>
|
||||
</ul>
|
||||
اندکی از مثال های مهم Verbs ,Modifiers, Nouns:
|
||||
<br /><br />
|
||||
</div>
|
||||
|
||||
<p dir="rtl"><strong>فعل ها (Verbs)</strong></p>
|
||||
|
||||
```
|
||||
d # حذف
|
||||
c # تغییر
|
||||
y # کپی
|
||||
v # انتخاب
|
||||
```
|
||||
<p dir="rtl"><strong>تغییردهنده ها (Modifiers)</strong></p>
|
||||
|
||||
```
|
||||
i # داخل
|
||||
a # اطراف
|
||||
NUM # شماره (NUM هر شمارهای است)
|
||||
f # جست و جو کردن چیزی و متوقف شدن روی آن
|
||||
t # جست و جو کردن چیزی و متوقف شدن قبل از آن
|
||||
/ # جست و جو کردن رشتهای پس از کِرسر
|
||||
? # جست و جو کردن رشتهای پیش از کِرسر
|
||||
```
|
||||
<p dir="rtl"><strong>اسم ها (Nouns)</strong></p>
|
||||
|
||||
```
|
||||
w # کلمه
|
||||
s # جمله
|
||||
p # پاراگراف
|
||||
b # بلوک
|
||||
```
|
||||
<p dir="rtl"><strong>جمله ها و کامند های نمونه</strong></p>
|
||||
|
||||
```
|
||||
d2w # حذف دو کلمه
|
||||
cis # تغییر داخل جمله
|
||||
yip # کپی داخل پاراگراف (از پاراگرافی که داخل آن هستید کپی کنید)
|
||||
ct< # متن را از جایی که قرار دارید به براکت باز بعدی تغییر دهید
|
||||
d$ # حذف تا پایان
|
||||
```
|
||||
|
||||
<h3>
|
||||
<p dir="rtl">بعضی از شورتکات ها و ترفند ها</p>
|
||||
</h3>
|
||||
|
||||
```
|
||||
<!--TODO: Add more!-->
|
||||
|
||||
> # ایجاد دندانه به اندازه یک بلوک
|
||||
|
||||
< # حذف دندانه به اندازه یک بلوک
|
||||
|
||||
:earlier 15m # برگرداندن همه چیز به ۱۵ دقیقه قبل
|
||||
|
||||
:later 15m # برعکس کامند قبلی
|
||||
|
||||
ddp # تغییر مکان خطوط متوالی(dd, then p)
|
||||
|
||||
. # تکرار دستور قبلی
|
||||
|
||||
:w !sudo tee % # ذخیره کردن فایل فعلی به عنوان روت
|
||||
|
||||
:set syntax=c # تنظیم سینتکس هایلایتینگ روی 'c'
|
||||
|
||||
:sort # مرتب کردن همهی خطوط
|
||||
|
||||
:sort! # مرتب کردن همهی خطوط به صورت برعکس
|
||||
|
||||
:sort u # مرتب کردن همهی خطوط و پاک کردن تکراری ها
|
||||
|
||||
~ # تبدیل متن انتخاب شده به حروف (اگر بزرگ است، کوچک و اگر کوچک است، بزرگ)
|
||||
|
||||
u # تبدیل متن انتخاب شده به حروف کوچک
|
||||
|
||||
U # تبدیل متن انتخاب شده به حروف بزرگ
|
||||
|
||||
J # اتصال خط فعلی به خط بعدی
|
||||
```
|
||||
<h4>
|
||||
<p dir="rtl">
|
||||
فولد (Fold)
|
||||
</p>
|
||||
</h4>
|
||||
|
||||
```
|
||||
zf # ایجاد فولد برای متن انتخاب شده
|
||||
zo # باز کردن فولد فعلی
|
||||
zc # بستن فولد فعلی
|
||||
zR # باز کردن همهی فولد ها
|
||||
zM # بستن همهی فولد ها
|
||||
```
|
||||
|
||||
<h3>
|
||||
<p dir="rtl">
|
||||
ماکرو ها (Macros)
|
||||
</p>
|
||||
</h3>
|
||||
|
||||
<p dir="rtl">
|
||||
ماکرو ها اساسا عمل های قابل ضبط هستند. زمانی که شما شروع میکنید به ضبط ماکرو، هر عمل و دستوری را که استفاده میکنید، تا زمانی که ضبط را متوقف کنید، ضبط میشود. با فراخوانی ماکرو، دقیقاً همان توالی اعمال و دستورات، دوباره روی متن انتخاب شده اعمال میشود.
|
||||
</p>
|
||||
|
||||
```
|
||||
qa # Start recording a macro named 'a'
|
||||
q # Stop recording
|
||||
@a # Play back the macro
|
||||
```
|
||||
<h3>
|
||||
<p dir="rtl">
|
||||
کانفیگ vimrc./~
|
||||
<p>
|
||||
</h3>
|
||||
|
||||
<p dir="rtl">
|
||||
vimrc. فایلیست که استفاده میشود برای کانفیگ vim هنگام بالا آمدن
|
||||
<br />
|
||||
اینجا یک نمونه فایل vimrc. آورده شده:
|
||||
</p>
|
||||
|
||||
```
|
||||
" Example ~/.vimrc
|
||||
" 2015.10
|
||||
|
||||
" Required for vim to be iMproved
|
||||
set nocompatible
|
||||
|
||||
" Determines filetype from name to allow intelligent auto-indenting, etc.
|
||||
filetype indent plugin on
|
||||
|
||||
" Enable syntax highlighting
|
||||
syntax on
|
||||
|
||||
" Better command-line completion
|
||||
set wildmenu
|
||||
|
||||
" Use case insensitive search except when using capital letters
|
||||
set ignorecase
|
||||
set smartcase
|
||||
|
||||
" When opening a new line and no file-specific indenting is enabled,
|
||||
" keep same indent as the line you're currently on
|
||||
set autoindent
|
||||
|
||||
" Display line numbers on the left
|
||||
set number
|
||||
|
||||
" Indentation options, change according to personal preference
|
||||
|
||||
" Number of visual spaces per TAB
|
||||
set tabstop=4
|
||||
|
||||
" Number of spaces in TAB when editing
|
||||
set softtabstop=4
|
||||
|
||||
" Number of spaces indented when reindent operations (>> and <<) are used
|
||||
set shiftwidth=4
|
||||
" Convert TABs to spaces
|
||||
set expandtab
|
||||
|
||||
" Enable intelligent tabbing and spacing for indentation and alignment
|
||||
set smarttab
|
||||
```
|
||||
|
||||
<h3>
|
||||
<p dir="rtl">رفرنس ها</p>
|
||||
</h3>
|
||||
|
||||
[Vim | Home](http://www.vim.org/index.php)
|
||||
|
||||
`$ vimtutor`
|
||||
|
||||
[A vim Tutorial and Primer](https://danielmiessler.com/study/vim/)
|
||||
|
||||
[What are the dark corners of Vim your mom never told you about? (St
|
||||
|
||||
[Arch Linux Wiki](https://wiki.archlinux.org/index.php/Vim)
|
@ -33,7 +33,7 @@ Go tuo mukanaan loistavan oletuskirjaston sekä innokkaan yhteisön.
|
||||
rivin kommentti */
|
||||
|
||||
// Package -lausekkeella aloitetaan jokainen lähdekooditiedosto.
|
||||
// Main on erityinen nimi joka ilmoittaa
|
||||
// main on erityinen nimi joka ilmoittaa
|
||||
// suoritettavan tiedoston kirjaston sijasta.
|
||||
package main
|
||||
|
||||
@ -90,7 +90,7 @@ voi sisältää rivinvaihtoja.` // Sama merkkijonotyyppi.
|
||||
// Ei-ASCII todellisarvo. Go-lähdekoodi on UTF-8.
|
||||
g := 'Σ' // riimutyyppi, lempinimi int32:lle, sisältää unicode-koodipisteen.
|
||||
|
||||
f := 3.14195 //float64, IEEE-754 64-bittinen liukuluku.
|
||||
f := 3.14159 //float64, IEEE-754 64-bittinen liukuluku.
|
||||
c := 3 + 4i // complex128, sisäisesti ilmaistu kahdella float64:lla.
|
||||
|
||||
// var -syntaksi alkuarvoilla.
|
||||
@ -418,21 +418,21 @@ func requestServer() {
|
||||
|
||||
## Lisää luettavaa
|
||||
|
||||
Go-tietämyksen alku ja juuri on sen [virallinen verkkosivu]()(http://golang.org/).
|
||||
Go-tietämyksen alku ja juuri on sen [virallinen verkkosivu]()(https://go.dev/).
|
||||
Siellä voit seurata oppitunteja, askarrella vuorovaikutteisesti sekä lukea paljon.
|
||||
Kierroksen lisäksi [dokumentaatio](https://golang.org/doc/) pitää sisällään tietoa
|
||||
Kierroksen lisäksi [dokumentaatio](https://go.dev/doc/) pitää sisällään tietoa
|
||||
siistin Go-koodin kirjoittamisesta, pakettien ja komentojen käytöstä sekä julkaisuhistoriasta.
|
||||
|
||||
Kielen määritelmä itsessään on suuresti suositeltavissa. Se on helppolukuinen ja
|
||||
yllättävän lyhyt (niissä määrin kuin kielimääritelmät nykypäivänä ovat.)
|
||||
|
||||
Voit askarrella parissa kanssa [Go playgroundissa](https://play.golang.org/p/tnWMjr16Mm).
|
||||
Muuttele sitä ja aja se selaimestasi! Huomaa, että voit käyttää [https://play.golang.org](https://play.golang.org)
|
||||
Voit askarrella parissa kanssa [Go playgroundissa](https://go.dev/play/p/tnWMjr16Mm).
|
||||
Muuttele sitä ja aja se selaimestasi! Huomaa, että voit käyttää [https://go.dev/play/](https://go.dev/play/)
|
||||
[REPL:na](https://en.wikipedia.org/wiki/Read-eval-print_loop) testataksesi ja koodataksesi selaimessasi, ilman Go:n asentamista.
|
||||
|
||||
Go:n opiskelijoiden lukulistalla on [oletuskirjaston lähdekoodi](http://golang.org/src/pkg/).
|
||||
Go:n opiskelijoiden lukulistalla on [oletuskirjaston lähdekoodi](https://go.dev/src/).
|
||||
Kattavasti dokumentoituna se antaa parhaan kuvan helppolukuisesta ja ymmärrettävästä Go-koodista,
|
||||
-tyylistä ja -tavoista. Voit klikata funktion nimeä [doukumentaatiossa](http://golang.org/pkg/) ja
|
||||
-tyylistä ja -tavoista. Voit klikata funktion nimeä [doukumentaatiossa](https://go.dev/pkg/) ja
|
||||
lähdekoodi tulee esille!
|
||||
|
||||
Toinen loistava paikka oppia on [Go by example](https://gobyexample.com/).
|
||||
|
@ -605,4 +605,4 @@ Something.new.qux # => 'qux'
|
||||
- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
|
||||
- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - Vanhempi, mutta [ilmainen painos](http://ruby-doc.com/docs/ProgrammingRuby/) on luettavissa netissä
|
||||
- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - Yhteisön luoma Ruby-tyyliopas
|
||||
- [Try Ruby](http://tryruby.org) - Rubyn perusteet interaktiivisesti
|
||||
- [Try Ruby](https://try.ruby-lang.org/) - Rubyn perusteet interaktiivisesti
|
||||
|
342
fish.html.markdown
Normal file
342
fish.html.markdown
Normal file
@ -0,0 +1,342 @@
|
||||
---
|
||||
category: tool
|
||||
tool: fish
|
||||
contributors:
|
||||
- ["MySurmise", "https://github.com/MySurmise"]
|
||||
- ["Geo Maciolek", "https://github.com/GeoffMaciolek"]
|
||||
filename: learn.fish
|
||||
---
|
||||
|
||||
Fish (**f**riendly **i**nteractive **sh**ell) is the name of an exotic shell. That is a shell with a syntax that is derived from neither the Bourne-Shell nor the C-Shell.
|
||||
|
||||
The advantage of fish is that many features that you want in a modern shell come out-of-the-box, so you don't have to install additional software like zsh and oh-my-zsh.
|
||||
|
||||
Examples of these features are autosuggestions, 24-bit colors, Man Page Completions (meaning fish automatically parses your man pages and suggests additional options for your commands) or the ability to make options through a web page (when a GUI is installed).
|
||||
|
||||
It was released in February 2005.
|
||||
|
||||
- [Read more](https://fishshell.com/docs/current/language.html)
|
||||
- [Installation guide](https://github.com/fish-shell/fish-shell#getting-fish)
|
||||
|
||||
|
||||
## Guide
|
||||
|
||||
Be sure you have the newest fish shell. This was made with version 3.3.0. To test, type:
|
||||
|
||||
```
|
||||
> fish -v
|
||||
```
|
||||
|
||||
To start the fish shell, type:
|
||||
|
||||
```
|
||||
> fish
|
||||
```
|
||||
|
||||
to exit, type:
|
||||
|
||||
```
|
||||
> exit
|
||||
```
|
||||
|
||||
or press <kbd>Ctrl + D</kbd>
|
||||
|
||||
Now, right out of the gate, there's one annoying thing in fish. It's the welcome message. Who needs that, right? When your shell is started, just type:
|
||||
|
||||
```
|
||||
> set -U fish_greeting ""
|
||||
```
|
||||
|
||||
If you want to execute a single command written in bash, without switching to that shell, you can type:
|
||||
|
||||
```
|
||||
> bash -c 'echo "fish is better than bash"'
|
||||
```
|
||||
|
||||
In fish, you can use single or double quotes.
|
||||
The escape character is a `\`
|
||||
|
||||
You can change your configuration of fish either by editing the config file
|
||||
|
||||
```
|
||||
> vim ~/.config/fish/config.fish
|
||||
```
|
||||
|
||||
or by opening the aforementioned web settings:
|
||||
|
||||
```
|
||||
> fish_config
|
||||
```
|
||||
|
||||
Adding something to your fish PATH Variable is easy:
|
||||
|
||||
```
|
||||
> fish_path_add ~/cowsay
|
||||
```
|
||||
|
||||
Can you do that with bash, huh? No, you always have to look it up... It's just that easy!
|
||||
|
||||
But there's more. Most fish-specific commands start, you guessed it, with 'fish'. Just type in `fish` and press <kbd>TAB</kbd>. And there you have one of the many cool features of fish: The autocompletion that **just works.**
|
||||
Now you can navigate with <kbd>TAB</kbd>, <kbd>Shift + TAB</kbd> and your Arrow-Keys <kbd>←</kbd><kbd>↑</kbd><kbd>→</kbd><kbd>↓</kbd>.
|
||||
|
||||
To get help, contact your local psychiatrist or type `man`. That will bring up the manual for that command, for example:
|
||||
|
||||
```
|
||||
> man set
|
||||
```
|
||||
|
||||
If you finally tried fish, you can see something other in fish that's really cool. Everything has cool colors, if you type in something wrong, it is red, without even executing, if you put something in quotes, you see where it ends and why that quote doesn't work, because there's another qoutation mark in the quote at position 26.
|
||||
|
||||
fish has even more cool things, like wildcards.
|
||||
For example, type
|
||||
|
||||
```
|
||||
> ls *.fish
|
||||
```
|
||||
|
||||
That will list all fish files in your current directory.
|
||||
|
||||
You can have multiple wildcards per command or even a recursive wildcard, `**`, which basically means it includes files and directories, that fit.
|
||||
For example the following command would return (in your case):
|
||||
|
||||
```
|
||||
> ls ~/images/**.jpg
|
||||
|
||||
~/images/nudes/pewdiepie.jpg
|
||||
~/images/nudes/peppa.jpg
|
||||
~/images/screenshots/2020-42-69.jpg
|
||||
~/images/omegalul.jpg
|
||||
```
|
||||
|
||||
Of course, you can also pipe the output of a command to another command
|
||||
|
||||
```
|
||||
>echo sick egg, nadia. no u do really goofy shit. | grep [udense]
|
||||
```
|
||||
|
||||
write to a file:
|
||||
|
||||
```
|
||||
>echo This\ is\ text > file.txt
|
||||
```
|
||||
|
||||
(noticed the escape character?)
|
||||
Add to a file:
|
||||
|
||||
```
|
||||
>echo This\ is\ a\ line >> file.txt
|
||||
>echo This\ is\ a\ second\ line >> file.txt
|
||||
```
|
||||
|
||||
For Autocompletion, just always press <kbd>TAB</kbd>. You will be surprised how many things fish knows.
|
||||
|
||||
To use variables, just type `$VAR`, like in bash.
|
||||
|
||||
```
|
||||
> echo "My home is $HOME"
|
||||
My home is /home/myuser
|
||||
```
|
||||
|
||||
Here comes a difference between single and double quotes. If you use a variable in single quotes, it will not substitute it.
|
||||
|
||||
```
|
||||
> echo 'My home is $HOME'
|
||||
My home is $HOME
|
||||
```
|
||||
|
||||
More on variables later.
|
||||
|
||||
To execute two commands, separate them with `;`
|
||||
|
||||
```
|
||||
> echo Lol; echo this is fun
|
||||
```
|
||||
|
||||
The status code of the last command is stored in `$status`
|
||||
|
||||
You can use && for two commands that depend on each other.
|
||||
|
||||
```
|
||||
> set var lol && echo $var
|
||||
```
|
||||
|
||||
You can also use `and` which executes if the previous command was successful,
|
||||
`or` which executes if the previous command was not successful, and `not`
|
||||
which inverts the exit status of a command.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
> if not echo It's very late I should not waste my time with this
|
||||
echo Nobody heard you
|
||||
end
|
||||
```
|
||||
|
||||
(You can of course do all of that in the shell)
|
||||
|
||||
---
|
||||
Now let's start with the scripting part of fish.
|
||||
|
||||
As with every shell, you can not only execute commands in the shell, but also as files, saved as a `.fish` file.
|
||||
(You can also execute `.sh` files with fish syntax, but I always use `.fish` for fish-syntax scripts to distinguish them from bash script files)
|
||||
|
||||
```fish
|
||||
# This is a comment in fish.
|
||||
#
|
||||
# If you execute a file without specifying an interpreter,
|
||||
# meaning the software that runs your script, you need to tell the shell,
|
||||
# where that interpreter is.
|
||||
# For fish you just add the following comment as the first line in your script:
|
||||
|
||||
#!/bin/fish
|
||||
|
||||
# When executing via e.g. fish /path/to/script.fish
|
||||
# you don't need that, because you specified fish as an interpreter
|
||||
|
||||
# Let's start with variables.
|
||||
# for use inside a program, you can use the syntax
|
||||
set name = 'My Variable'
|
||||
|
||||
# Use...
|
||||
set -x name value
|
||||
# to eXport, or
|
||||
set -e name
|
||||
# to Erase
|
||||
|
||||
# a variable set with a space doesn't get sent as two arguments, but as one, as you would expect it.
|
||||
set turtlefolder 'Turtle Folder'
|
||||
mkdir $turtlefolder
|
||||
|
||||
# This will create one folder, as expected, not two, like in bash...
|
||||
# Who would even want that? tHiS iS a fEaTurE, nOt a bUg...
|
||||
|
||||
# you can even have lists as variables. This actually makes sense, because if you want to have a variable that would create two folders, you just give mkdir a list of your foldernames.
|
||||
|
||||
# you can then count the entries in that list with:
|
||||
count $PATH
|
||||
|
||||
# Not only is everything awesome, but in fish, everything is also a list.
|
||||
# So $PWD for example is a list of length 1.
|
||||
# To make a list, just give the set command multiple arguments:
|
||||
set list entry1 entry2 entry3
|
||||
|
||||
# that way you can also append something to an existing variable:
|
||||
set PATH $PATH ~/cowsay/
|
||||
|
||||
# But, as previously mentioned, we also have a simpler way to do that specifically in fish.
|
||||
# As with every Array/List, you can access it with
|
||||
$listvar[2]
|
||||
|
||||
# there's also ranges with
|
||||
$listvar[1..5]
|
||||
|
||||
# and you can use negative numbers like
|
||||
$listvar[-1]
|
||||
# e.g to access the last element.
|
||||
|
||||
# You can also do fancy cartesian products when you combine two list variables:
|
||||
set a 1 2 3
|
||||
set 1 a b c
|
||||
echo $a$1
|
||||
# Will output : 1a 2a 3a 1b 2b 3b 1c 2c 3c
|
||||
|
||||
# Of course, if you separate them, it will see them as two separate arguments and echo them one after the other. THAT is expected behavior @bash.
|
||||
|
||||
# There are also other useful things, like command substitutions. For example, when you want to output the returns of two commands in one line. In bash you would do that with
|
||||
echo "`ls` is in $PWD"
|
||||
# or
|
||||
echo "$(ls) is in $PWD"
|
||||
|
||||
# if you ask me, that's unnecessary. I always type in the wrong apostrophe. Why not just use two parenthesis, like in fish?
|
||||
echo (ls) is in $PWD
|
||||
|
||||
# Yep, that easy. And thanks to fish's highlighting you can instantly see, if you typed it in correctly.
|
||||
|
||||
# And, as you would expect, if you ask me, your commands don't work in quotes. I mean why bash? Ok I'll stop now. But in fish, just do:
|
||||
echo (ls)" is in $PWD"
|
||||
# or
|
||||
set myvar "The file"(ls -a)" is in the directory $PWD"
|
||||
# will make a List with the string and all files. Try it out. Isn't that cool?
|
||||
|
||||
# And to separate these variables in separate arguments, just put a space between them:
|
||||
|
||||
set myvar "The files" (ls -a) " are in the directory $PWD"
|
||||
|
||||
# There's also if, else if, else
|
||||
if grep fish /etc/shells
|
||||
echo Found fish
|
||||
else if grep bash /etc/shells
|
||||
echo Found bash
|
||||
else
|
||||
echo Got nothing
|
||||
end
|
||||
|
||||
# A little weird is that you compare stuff with one = sign, of course because we don't need it to set variables, but still... and the keyword "test":
|
||||
if test $var = "test"
|
||||
echo yes
|
||||
else
|
||||
echo no
|
||||
end
|
||||
|
||||
# Of course, there's also switch case with
|
||||
switch $OS
|
||||
case Linux
|
||||
echo "you're good"
|
||||
case Windows
|
||||
echo "install Gentoo"
|
||||
case Arch
|
||||
echo "I use arch btw"
|
||||
case '*'
|
||||
echo "what OS is $OS, please?"
|
||||
end
|
||||
|
||||
|
||||
# functions in fish get their arguments through the $argv variable. The syntax is following:
|
||||
|
||||
function print
|
||||
echo $argv
|
||||
end
|
||||
|
||||
# There are also events, like the "fish_exit"-event (What may that be, hmm?).
|
||||
|
||||
# You can use them by adding them to the function definition:
|
||||
|
||||
function on_exit --on-event fish_exit
|
||||
echo fish is now exiting
|
||||
end
|
||||
|
||||
# find events with the command
|
||||
functions --handlers
|
||||
|
||||
|
||||
# You can use the functions command to learn more about, well, functions.
|
||||
# For example you can print the source code of every function:
|
||||
functions cd
|
||||
functions print
|
||||
# or get the names of all functions:
|
||||
functions
|
||||
|
||||
# There's while Loops, of course
|
||||
while test $var = lol
|
||||
echo lol
|
||||
end
|
||||
|
||||
# for Loops (with wildcards, they are even cooler):
|
||||
for image in *.jpg
|
||||
echo $image
|
||||
end
|
||||
|
||||
# there's an equivalent to the range(0, 5) in Python, so you can also do the standard for loops with numbers:
|
||||
|
||||
set files (ls)
|
||||
for number in (seq 10)
|
||||
echo "$files[$number] is file number $number"
|
||||
end
|
||||
|
||||
# Cool!
|
||||
|
||||
# The bashrc equivalent is not fishrc, but the previously mentioned config.fish file in ~/.config/fish/
|
||||
# To add a function to fish, though, you should create a simple .fish file in that directory. Don't just paste that function in the config.fish. That's ugly.
|
||||
# If you have more, just add it, but those are the most important basics.
|
||||
|
||||
```
|
@ -93,8 +93,8 @@ see square \ : square dup * ; ok
|
||||
|
||||
\ ------------------------------------ Loops -----------------------------------
|
||||
|
||||
\ `do` is also a compile-only word.
|
||||
: myloop ( -- ) 5 0 do cr ." Hello!" loop ; \ ok
|
||||
\ `?do` is also a compile-only word.
|
||||
: myloop ( -- ) 5 0 ?do cr ." Hello!" loop ; \ ok
|
||||
myloop
|
||||
\ Hello!
|
||||
\ Hello!
|
||||
@ -102,16 +102,17 @@ myloop
|
||||
\ Hello!
|
||||
\ Hello! ok
|
||||
|
||||
\ `do` expects two numbers on the stack: the end number and the start number.
|
||||
\ `?do` expects two numbers on the stack: the end number (exclusive) and the
|
||||
\ start number (inclusive).
|
||||
|
||||
\ We can get the value of the index as we loop with `i`:
|
||||
: one-to-12 ( -- ) 12 0 do i . loop ; \ ok
|
||||
one-to-12 \ 0 1 2 3 4 5 6 7 8 9 10 11 12 ok
|
||||
one-to-12 \ 0 1 2 3 4 5 6 7 8 9 10 11 ok
|
||||
|
||||
\ `?do` works similarly, except it will skip the loop if the end and start
|
||||
\ numbers are equal.
|
||||
: squares ( n -- ) 0 ?do i square . loop ; \ ok
|
||||
10 squares \ 0 1 4 9 16 25 36 49 64 81 ok
|
||||
\ `do` works similarly, except if start and end are exactly the same it will
|
||||
\ loop forever (until arithmetic underflow).
|
||||
: loop-forever 1 1 do i square . loop ; \ ok
|
||||
loop-forever \ 1 4 9 16 25 36 49 64 81 100 ...
|
||||
|
||||
\ Change the "step" with `+loop`:
|
||||
: threes ( n n -- ) ?do i . 3 +loop ; \ ok
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user