diff options
550 files changed, 68294 insertions, 24088 deletions
diff --git a/.gitattributes b/.gitattributes index 183b7cdb..da8c9d63 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 @@ -61,5 +61,5 @@ paren*.html.markdown linguist-language=lisp pcre*.html.markdown linguist-language=Perl perl.html.markdown linguist-language=Perl perl-*.html.markdown linguist-language=Perl -perl6*.html.markdown linguist-language=Perl6 +raku*.html.markdown linguist-language=Perl6 ruby*.html.markdown linguist-language=Ruby diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..7bc421a7 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,8 @@ +/fr-fr/ @vendethiel
+/ru-ru/ @Menelion
+/uk-ua/ @Menelion
+/zh-cn/ @geoffliu @imba-tjd
+/zh-tw/ @geoffliu @imba-tjd
+/ko-kr/ @justin-themedium
+/pt-pt/ @mribeirodantas
+/pt-br/ @mribeirodantas
diff --git a/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 96278da9..96278da9 100644 --- a/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md diff --git a/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fd9d1b31..6a496409 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,5 @@ - [ ] I solemnly swear that this is all original content of which I am the original author -- [ ] Pull request title is prepended with `[language/lang-code]` +- [ ] Pull request title is prepended with `[language/lang-code]` (example `[python/fr-fr]` or `[java/en]`) - [ ] Pull request touches only one file (or a set of logically related files with similar changes made) - [ ] Content changes are aimed at *intermediate to experienced programmers* (this is a poor format for explaining fundamental programming concepts) - [ ] If you've changed any part of the YAML Frontmatter, make sure it is formatted according to [CONTRIBUTING.md](https://github.com/adambard/learnxinyminutes-docs/blob/master/CONTRIBUTING.markdown) diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..b69f76fe --- /dev/null +++ b/.mailmap @@ -0,0 +1 @@ +Leigh Brenecki <l@leigh.net.au> <adam@brenecki.id.au> diff --git a/ATS.html.markdown b/ATS.html.markdown new file mode 100644 index 00000000..f290ac0f --- /dev/null +++ b/ATS.html.markdown @@ -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). + diff --git a/CHICKEN.html.markdown b/CHICKEN.html.markdown index 3f7cc2db..4ae45cac 100644 --- a/CHICKEN.html.markdown +++ b/CHICKEN.html.markdown @@ -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) diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown index 79d6838a..f3556efa 100644 --- a/CONTRIBUTING.markdown +++ b/CONTRIBUTING.markdown @@ -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,67 +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 buid the site locally to test your changes. Follow the steps below. +You can build the site locally to test your changes. Follow the steps below. -* Install Ruby language runtime and RubyGems. See [here](https://middlemanapp.com/basics/install/) for more details. -* Clone or zip download the [learnxinyminutes-site](https://github.com/adambard/learnxinyminutes-site) repo. - * `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` - -## Building the site locally, for Nix users - -You can buid the site locally to test your changes too: - -* Clone or zip download the [learnxinyminutes-site](https://github.com/adambard/learnxinyminutes-site) repo. -* Get the source in place following the instructions above -* Install all site dependencies and start a dev server by running `nix-shell` at the `learnxinyminutes-site/` root directory. + these commands at `learnxinyminutes-site/`). + * Build - `bundle exec middleman build` + * Dev server - `bundle exec middleman --force-polling --verbose` diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..604209a8 --- /dev/null +++ b/LICENSE.txt @@ -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/. diff --git a/ada.html.markdown b/ada.html.markdown new file mode 100644 index 00000000..7191c5dc --- /dev/null +++ b/ada.html.markdown @@ -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) + diff --git a/amd.html.markdown b/amd.html.markdown index d7fb41ba..fc8f20a4 100644 --- a/amd.html.markdown +++ b/amd.html.markdown @@ -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) diff --git a/ansible.html.markdown b/ansible.html.markdown index 41a8c9b5..847505c1 100644 --- a/ansible.html.markdown +++ b/ansible.html.markdown @@ -30,9 +30,9 @@ But ansible is way more! It provides execution plans, an API, library, and callb #### Pros -* It is an agent-less tools In most scenarios, it use ssh as a transport layer. +* It is an agent-less tool. In most scenarios, it uses ssh as a transport layer. In some way you can use it as 'bash on steroids'. -* It is very easy to start. If you are familiar with ssh concept - you already +* It is very easy to start. If you are familiar with the concept of ssh - you already know Ansible (ALMOST). * It executes 'as is' - other tools (salt, puppet, chef - might execute in different scenario than you would expect) @@ -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) @@ -176,7 +176,7 @@ instances in the cloud, execute shell command). The simplest module is called Example of modules: * Module: `ping` - the simplest module that is useful to verify host connectivity -* Module: `shell` - a module that executes shell command on a specified host(s). +* Module: `shell` - a module that executes a shell command on a specified host(s). ```bash @@ -204,13 +204,13 @@ the module subsystem (useful to install python2.7) Execution of a single Ansible **module** is called a **task**. The simplest module is called `ping` as you could see above. -Another example of the module that allow you to execute command remotly on +Another example of the module that allows you to execute a command remotely on multiple resources is called `shell`. See above how you were using them already. ### Playbook **Execution plan** written in a form of script file(s) is called **playbook**. -Playbook consist of multiple elements - +Playbooks consist of multiple elements - * a list (or group) of hosts that 'the play' is executed against * `task(s)` or `role(s)` that are going to be executed * multiple optional settings (like default variables, and way more) @@ -247,7 +247,7 @@ Note: Example playbook is explained in the next chapter: 'Roles' ### Inventory -Inventory is a set of objects or hosts, against which we are executing our +An inventory is a set of objects or hosts, against which we are executing our playbooks or single tasks via shell commands. For these few minutes, let's assume that we are using the default ansible inventory (which in Debian based system is placed in `/etc/ansible/hosts`). @@ -303,11 +303,11 @@ Role can be included in your playbook (executed via your playbook). ``` #### For remaining examples we would use additional repository -This example install ansible in `virtualenv` so it is independend from a system. -You need to initialize it into your shell-context with `source environment.sh` +This example installs ansible in `virtualenv` so it is independent from the system. +You need to initialize it into your shell-context with the `source environment.sh` command. -We are going to use this repository with examples: [https://github.com/sirkubax/ansible-for-learnXinYminutes]() +We are going to use this repository with examples: [https://github.com/sirkubax/ansible-for-learnXinYminutes](https://github.com/sirkubax/ansible-for-learnXinYminutes) ```bash $ # The following example contains a shell-prompt to indicate the venv and relative path @@ -513,7 +513,7 @@ $ # Now we would run the above playbook with roles You can use the jinja in the CLI too ```bash -ansible -m shell -a 'echo {{ my_variable }}` -e 'my_variable=something, playbook_parameter=twentytwo" localhost +ansible -m shell -a 'echo {{ my_variable }}' -e 'my_variable=something, playbook_parameter=twentytwo' localhost ``` In fact - jinja is used to template parts of the playbooks too @@ -551,7 +551,7 @@ provides a way to encrypt confidential files so you can store them in the repository, yet the files are decrypted on-the-fly during ansible execution. The best way to use it is to store the secret in some secure location, and -configure ansible to use during runtime. +configure ansible to use them during runtime. ```bash # Try (this would fail) @@ -588,7 +588,7 @@ You might like to know, that you can build your inventory dynamically. deliver that to ansible - anything is possible. You do not need to reinvent the wheel - there are plenty of ready to use -inventory scripts for most popular Cloud providers and a lot of in-house +inventory scripts for the most popular Cloud providers and a lot of in-house popular usecases. [AWS example](http://docs.ansible.com/ansible/latest/intro_dynamic_inventory.html#example-aws-ec2-external-inventory-script) @@ -614,7 +614,7 @@ callback_whitelist = profile_tasks ### facts-cache and ansible-cmdb -You can pull some information about your environment from another hosts. +You can pull some information about your environment from another host. If the information does not change - you may consider using a facts_cache to speed things up. @@ -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) diff --git a/ar-ar/python3-ar.html.markdown b/ar-ar/python-ar.html.markdown index e1a12690..f89c2f25 100644 --- a/ar-ar/python3-ar.html.markdown +++ b/ar-ar/python-ar.html.markdown @@ -1,5 +1,5 @@ --- -language: python3 +language: Python contributors: - ["Louie Dinh", "http://pythonpracticeprojects.com"] - ["Steven Basart", "http://github.com/xksteven"] @@ -11,7 +11,7 @@ contributors: translators: - ["Ahmad Hegazy", "https://github.com/ahegazy"] lang: ar-ar -filename: learnpython3-ar.py +filename: learnpython-ar.py --- لقد أُنشئت لغة البايثون بواسطة جايدو ڤان روسم في بداية التسعينات. هي الأن أحد أشهر اللغات الموجودة. @@ -19,7 +19,7 @@ filename: learnpython3-ar.py ردود أفعالكم عن المقال مُقدرة بشدة. يمكنكم التواصل مع الكاتب الاساسي من خلال [@louiedinh](http://twitter.com/louiedinh) أو louiedinh [at] [google's email service] -ملحوظة: هذا المقال يُطبق على بايثون 3 فقط. راجع المقال [هنا](http://learnxinyminutes.com/docs/python/) إذا أردت تعلم لغة البايثون نسخة 2.7 الأقدم +ملحوظة: هذا المقال يُطبق على بايثون 3 فقط. راجع المقال [هنا](http://learnxinyminutes.com/docs/pythonlegacy/) إذا أردت تعلم لغة البايثون نسخة 2.7 الأقدم ```python diff --git a/ar-ar/sql-ar.html.markdown b/ar-ar/sql-ar.html.markdown new file mode 100644 index 00000000..dea20c1f --- /dev/null +++ b/ar-ar/sql-ar.html.markdown @@ -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> diff --git a/arturo.html.markdown b/arturo.html.markdown new file mode 100644 index 00000000..c3c4dc43 --- /dev/null +++ b/arturo.html.markdown @@ -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. diff --git a/asciidoc.html.markdown b/asciidoc.html.markdown index 51d0d7c9..557ed294 100644 --- a/asciidoc.html.markdown +++ b/asciidoc.html.markdown @@ -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. diff --git a/assemblyscript.html.markdown b/assemblyscript.html.markdown new file mode 100644 index 00000000..4433b41e --- /dev/null +++ b/assemblyscript.html.markdown @@ -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) diff --git a/asymptotic-notation.html.markdown b/asymptotic-notation.html.markdown index 7a7989d3..0739c02d 100644 --- a/asymptotic-notation.html.markdown +++ b/asymptotic-notation.html.markdown @@ -31,24 +31,24 @@ specifications, processing power, etc. ## Types of Asymptotic Notation -In the first section of this doc we described how an Asymptotic Notation +In the first section of this doc, we described how an Asymptotic Notation identifies the behavior of an algorithm as the input size changes. Let us imagine an algorithm as a function f, n as the input size, and f(n) being the running time. So for a given algorithm f, with input size n you get -some resultant run time f(n). This results in a graph where the Y axis is the -runtime, X axis is the input size, and plot points are the resultants of the -amount of time for a given input size. +some resultant run time f(n). This results in a graph where the Y-axis is +the runtime, the X-axis is the input size, and plot points are the resultants +of the amount of time for a given input size. You can label a function, or algorithm, with an Asymptotic Notation in many different ways. Some examples are, you can describe an algorithm by its best -case, worse case, or equivalent case. The most common is to analyze an -algorithm by its worst case. You typically don't evaluate by best case because -those conditions aren't what you're planning for. A very good example of this -is sorting algorithms; specifically, adding elements to a tree structure. Best -case for most algorithms could be as low as a single operation. However, in -most cases, the element you're adding will need to be sorted appropriately -through the tree, which could mean examining an entire branch. This is the -worst case, and this is what we plan for. +case, worst case, or average case. The most common is to analyze an algorithm +by its worst case. You typically don’t evaluate by best case because those +conditions aren’t what you’re planning for. An excellent example of this is +sorting algorithms; particularly, adding elements to a tree structure. The +best case for most algorithms could be as low as a single operation. However, +in most cases, the element you’re adding needs to be sorted appropriately +through the tree, which could mean examining an entire branch. This is +the worst case, and this is what we plan for. ### Types of functions, limits, and simplification @@ -61,20 +61,22 @@ constant Exponential Function - a^n, where a is some constant ``` -These are some basic function growth classifications used in various -notations. The list starts at the slowest growing function (logarithmic, -fastest execution time) and goes on to the fastest growing (exponential, -slowest execution time). Notice that as 'n', or the input, increases in each -of those functions, the result clearly increases much quicker in quadratic, -polynomial, and exponential, compared to logarithmic and linear. - -One extremely important note is that for the notations about to be discussed -you should do your best to use simplest terms. This means to disregard -constants, and lower order terms, because as the input size (or n in our f(n) -example) increases to infinity (mathematical limits), the lower order terms -and constants are of little to no importance. That being said, if you have -constants that are 2^9001, or some other ridiculous, unimaginable amount, -realize that simplifying will skew your notation accuracy. +These are some fundamental function growth classifications used in +various notations. The list starts at the slowest growing function +(logarithmic, fastest execution time) and goes on to the fastest +growing (exponential, slowest execution time). Notice that as ‘n’ +or the input, increases in each of those functions, the result +increases much quicker in quadratic, polynomial, and exponential, +compared to logarithmic and linear. + +It is worth noting that for the notations about to be discussed, +you should do your best to use the simplest terms. This means to +disregard constants, and lower order terms, because as the input +size (or n in our f(n) example) increases to infinity (mathematical +limits), the lower order terms and constants are of little to no +importance. That being said, if you have constants that are 2^9001, +or some other ridiculous, unimaginable amount, realize that +simplifying skew your notation accuracy. Since we want simplest form, lets modify our table a bit... @@ -89,7 +91,7 @@ Exponential - a^n, where a is some constant ### Big-O Big-O, commonly written as **O**, is an Asymptotic Notation for the worst case, or ceiling of growth for a given function. It provides us with an -_**asymptotic upper bound**_ for the growth rate of runtime of an algorithm. +_**asymptotic upper bound**_ for the growth rate of the runtime of an algorithm. Say `f(n)` is your algorithm runtime, and `g(n)` is an arbitrary time complexity you are trying to relate to your algorithm. `f(n)` is O(g(n)), if for some real constants c (c > 0) and n<sub>0</sub>, `f(n)` <= `c g(n)` for every input size @@ -133,13 +135,13 @@ 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 Big-Omega, commonly written as **Ω**, is an Asymptotic Notation for the best case, or a floor growth rate for a given function. It provides us with an -_**asymptotic lower bound**_ for the growth rate of runtime of an algorithm. +_**asymptotic lower bound**_ for the growth rate of the runtime of an algorithm. `f(n)` is Ω(g(n)), if for some real constants c (c > 0) and n<sub>0</sub> (n<sub>0</sub> > 0), `f(n)` is >= `c g(n)` for every input size n (n > n<sub>0</sub>). @@ -188,8 +190,8 @@ _**asymptotically tight bound**_ on the growth rate of runtime of an algorithm. Feel free to head over to additional resources for examples on this. Big-O is the primary notation use for general algorithm time complexity. -### Ending Notes -It's hard to keep this kind of topic short, and you should definitely go +### Endnotes +It's hard to keep this kind of topic short, and you should go through the books and online resources listed. They go into much greater depth with definitions and examples. More where x='Algorithms & Data Structures' is on its way; we'll have a doc up on analyzing actual code examples soon. diff --git a/awk.html.markdown b/awk.html.markdown index 3ff3f937..e1d4a0a3 100644 --- a/awk.html.markdown +++ b/awk.html.markdown @@ -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) diff --git a/ballerina.html.markdown b/ballerina.html.markdown new file mode 100644 index 00000000..7f055343 --- /dev/null +++ b/ballerina.html.markdown @@ -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/) diff --git a/bash.html.markdown b/bash.html.markdown index 856db706..e0e4f88a 100644 --- a/bash.html.markdown +++ b/bash.html.markdown @@ -17,118 +17,128 @@ 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"] --- Bash is a name of the unix shell, which was also distributed as the shell -for the GNU operating system and as default shell on Linux and Mac OS X. +for the GNU operating system and as the default shell on most Linux distros. Nearly all examples below can be a part of a shell script or executed directly in the shell. -[Read more here.](http://www.gnu.org/software/bash/manual/bashref.html) +[Read more here.](https://www.gnu.org/software/bash/manual/bashref.html) ```bash #!/usr/bin/env bash # First line of the script is the shebang which tells the system how to execute -# the script: http://en.wikipedia.org/wiki/Shebang_(Unix) +# the script: https://en.wikipedia.org/wiki/Shebang_(Unix) # 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! - -# 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 - -# 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 +# 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 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". + +# 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: +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". @@ -138,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" @@ -173,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 http://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' @@ -215,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" @@ -225,7 +241,9 @@ cat file.txt # We can also read the file using `cat`: Contents=$(cat file.txt) -echo "START OF FILE\n$Contents\nEND OF FILE" # "\n" prints a new line character +# "\n" prints a new line character +# "-e" to interpret the newline escape characters as escape characters +echo -e "START OF FILE\n$Contents\nEND OF FILE" # => START OF FILE # => [contents of file.txt] # => END OF FILE @@ -253,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 @@ -268,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 @@ -292,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 @@ -318,6 +342,9 @@ echo "#helloworld" | tee output.out >/dev/null # WARNING: `rm` commands cannot be undone rm -v output.out error.err output-and-error.log rm -r tempDir/ # recursively delete +# You can install the `trash-cli` Python package to have `trash` +# which puts files in the system trash and doesn't delete them directly +# see https://pypi.org/project/trash-cli/ if you want to be careful # Commands can be substituted within other commands using $( ): # The following command displays the number of files and directories in the @@ -325,15 +352,15 @@ rm -r tempDir/ # recursively delete echo "There are $(ls | wc -l) items here." # The same can be done using backticks `` but they can't be nested - -#the preferred way is to use $( ). +# the preferred way is to use $( ). echo "There are `ls | wc -l` items here." # Bash uses a `case` statement that works similarly to switch in Java and C++: case "$Variable" in - #List patterns for the conditions you want to meet + # List patterns for the conditions you want to meet 0) echo "There is a zero.";; 1) echo "There is a one.";; - *) echo "It is not null.";; + *) echo "It is not null.";; # match everything esac # `for` loops iterate for as many arguments given: @@ -370,6 +397,13 @@ do cat "$Output" done +# Bash can also accept patterns, like this to `cat` +# all the Markdown files in current directory +for Output in ./*.markdown +do + cat "$Output" +done + # while loop: while [ true ] do @@ -385,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 () @@ -412,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 @@ -424,6 +462,8 @@ cut -d ',' -f 1 file.txt # replaces every occurrence of 'okay' with 'great' in file.txt # (regex compatible) sed -i 's/okay/great/g' file.txt +# be aware that this -i flag means that file.txt will be changed +# -i or --in-place erase the input file (use --in-place=.backup to keep a back-up) # print to stdout all lines of file.txt which match some regex # The example prints lines which begin with "foo" and end in "bar" @@ -441,7 +481,7 @@ grep -rI "^foo.*bar$" someDir/ # recursively `grep`, but ignore binary files grep "^foo.*bar$" file.txt | grep -v "baz" # if you literally want to search for the string, -# and not the regex, use fgrep (or grep -F) +# and not the regex, use `fgrep` (or `grep -F`) fgrep "foobar" file.txt # The `trap` command allows you to execute a command whenever your script @@ -450,6 +490,7 @@ fgrep "foobar" file.txt trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM # `sudo` is used to perform commands as the superuser +# usually it will ask interactively the password of superuser NAME1=$(whoami) NAME2=$(sudo whoami) echo "Was $NAME1, then became more powerful $NAME2" diff --git a/bf.html.markdown b/bf.html.markdown index 1e415a4d..adc58f02 100644 --- a/bf.html.markdown +++ b/bf.html.markdown @@ -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/) diff --git a/bg-bg/perl-bg.html.markdown b/bg-bg/perl-bg.html.markdown index 2ae7a8fd..e6da8965 100644 --- a/bg-bg/perl-bg.html.markdown +++ b/bg-bg/perl-bg.html.markdown @@ -11,10 +11,10 @@ translators: lang: bg-bg --- -Perl 5 е изключително мощен език за програмиране с широка област на приложение +Perl е изключително мощен език за програмиране с широка област на приложение и над 25 годишна история. -Perl 5 работи на повече от 100 операционни системи от мини до супер-компютри и е +Perl работи на повече от 100 операционни системи от мини до супер-компютри и е подходящ както за бърза разработка на скриптове така и за огромни приложения. ```perl @@ -281,7 +281,7 @@ sub increment { 1; -# Методите могат да се извикват на клас или на обект като се използва оператора +# Методите могат да се извикват на клас или на обект като се използва оператора # стрелка (->). use MyCounter; @@ -323,4 +323,3 @@ sub increment { - [Learn at www.perl.com](http://www.perl.org/learn.html) - [perldoc](http://perldoc.perl.org/) - и идващото с perl: `perldoc perlintro` - diff --git a/c++.html.markdown b/c++.html.markdown index f3dc8e20..499eb669 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -1,17 +1,17 @@ --- -language: c++ +language: C++ filename: learncpp.cpp contributors: - - ["Steven Basart", "http://github.com/xksteven"] + - ["Steven Basart", "https://github.com/xksteven"] - ["Matt Kline", "https://github.com/mrkline"] - ["Geoff Liu", "http://geoffliu.me"] - - ["Connor Waters", "http://github.com/connorwaters"] - - ["Ankush Goyal", "http://github.com/ankushg07"] + - ["Connor Waters", "https://github.com/connorwaters"] + - ["Ankush Goyal", "https://github.com/ankushg07"] - ["Jatin Dhankhar", "https://github.com/jatindhankhar"] --- C++ is a systems programming language that, -[according to its inventor Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), +[according to its inventor Bjarne Stroustrup](https://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote), was designed to - be a "better C" @@ -37,7 +37,7 @@ one of the most widely-used programming languages. // Just like in C, your program's entry point is a function called // main with an integer return type. // This value serves as the program's exit status. -// See http://en.wikipedia.org/wiki/Exit_status for more information. +// See https://en.wikipedia.org/wiki/Exit_status for more information. int main(int argc, char** argv) { // Command line arguments are passed in by argc and argv in the same way @@ -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" @@ -199,10 +205,10 @@ int main() cin >> myInt; // cout can also be formatted - cout << "Your favorite number is " << myInt << "\n"; + cout << "Your favorite number is " << myInt << '\n'; // prints "Your favorite number is <myInt>" - cerr << "Used for error messages"; + cerr << "Used for error messages"; } ////////// @@ -461,7 +467,7 @@ void Dog::print() const Dog::~Dog() { - std::cout << "Goodbye " << name << "\n"; + std::cout << "Goodbye " << name << '\n'; } int main() { @@ -483,7 +489,7 @@ public: void setOwner(const std::string& dogsOwner); // Override the behavior of the print function for all OwnedDogs. See - // http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping + // https://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping // for a more general introduction if you are unfamiliar with // subtype polymorphism. // The override keyword is optional but makes sure you are actually @@ -504,7 +510,7 @@ void OwnedDog::setOwner(const std::string& dogsOwner) void OwnedDog::print() const { Dog::print(); // Call the print function in the base Dog class - std::cout << "Dog is owned by " << owner << "\n"; + std::cout << "Dog is owned by " << owner << '\n'; // Prints "Dog is <name> and weights <weight>" // "Dog is owned by <owner>" } @@ -616,7 +622,7 @@ boxOfBox.insert(intBox); // template<typename T> // instead. The 'class' keyword and 'typename' keywords are _mostly_ // interchangeable in this case. For the full explanation, see -// http://en.wikipedia.org/wiki/Typename +// https://en.wikipedia.org/wiki/Typename // (yes, that keyword has its own Wikipedia page). // Similarly, a template function: @@ -660,7 +666,7 @@ printMessage<10>(); // Prints "Learn C++ faster in only 10 minutes!" ///////////////////// // The standard library provides a few exception types -// (see http://en.cppreference.com/w/cpp/error/exception) +// (see https://en.cppreference.com/w/cpp/error/exception) // but any type can be thrown as an exception #include <exception> #include <stdexcept> @@ -915,7 +921,7 @@ ST.erase(20); // Will erase element with value 20 // Set ST: 10 30 // To iterate through Set we use iterators set<int>::iterator it; -for(it=ST.begin();it<ST.end();it++) { +for(it=ST.begin();it!=ST.end();it++) { cout << *it << endl; } // Output: @@ -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 << '\n'; + std::cout << it->first << "->" << it->second << std::endl; // Output: // A->1 // Z->26 @@ -1030,7 +1036,7 @@ sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs) { return weight[lhs] < weight[rhs]; }); // Note we captured "weight" by reference in the above example. -// More on Lambdas in C++ : http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11 +// More on Lambdas in C++ : https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11 /////////////////////////////// // Range For (C++11 and above) @@ -1106,7 +1112,8 @@ f1 = f2; #include<tuple> -// Conceptually, Tuples are similar to old data structures (C-like structs) but instead of having named data members, +// Conceptually, Tuples are similar to old data structures (C-like structs) +// but instead of having named data members, // its elements are accessed by their order in the tuple. // We start with constructing a tuple. @@ -1117,33 +1124,33 @@ const int maxL = 15; auto second = make_tuple(maxN, maxL); // Printing elements of 'first' tuple -cout << get<0>(first) << " " << get<1>(first) << "\n"; //prints : 10 A +cout << get<0>(first) << " " << get<1>(first) << '\n'; //prints : 10 A // Printing elements of 'second' tuple -cout << get<0>(second) << " " << get<1>(second) << "\n"; // prints: 1000000000 15 +cout << get<0>(second) << " " << get<1>(second) << '\n'; // prints: 1000000000 15 // Unpacking tuple into variables int first_int; char first_char; tie(first_int, first_char) = first; -cout << first_int << " " << first_char << "\n"; // prints : 10 A +cout << first_int << " " << first_char << '\n'; // prints : 10 A // We can also create tuple like this. tuple<int, char, double> third(11, 'A', 3.14141); // tuple_size returns number of elements in a tuple (as a constexpr) -cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3 +cout << tuple_size<decltype(third)>::value << '\n'; // prints: 3 // tuple_cat concatenates the elements of all the tuples in the same order. auto concatenated_tuple = tuple_cat(first, second, third); // concatenated_tuple becomes = (10, 'A', 1e9, 15, 11, 'A', 3.14141) -cout << get<0>(concatenated_tuple) << "\n"; // prints: 10 -cout << get<3>(concatenated_tuple) << "\n"; // prints: 15 -cout << get<5>(concatenated_tuple) << "\n"; // prints: 'A' +cout << get<0>(concatenated_tuple) << '\n'; // prints: 10 +cout << get<3>(concatenated_tuple) << '\n'; // prints: 15 +cout << get<5>(concatenated_tuple) << '\n'; // prints: 'A' /////////////////////////////////// @@ -1195,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). diff --git a/c.html.markdown b/c.html.markdown index 7975a1c2..ef341abf 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,15 +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"] + - ["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. @@ -45,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 } @@ -84,22 +101,31 @@ 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 /////////////////////////////////////// - // All variables MUST be declared at the top of the current block scope - // we declare them dynamically along the code for the sake of the tutorial - // (however, C99-compliant compilers allow declarations near the point where - // the value is used) + // Compilers that are not C99-compliant require that variables MUST be + // declared at the top of the current block scope. + // Compilers that ARE C99-compliant allow declarations near the point where + // the value is used. + // 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 '' @@ -142,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 @@ -221,24 +253,41 @@ 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 - // Modulo is there as well - 11 % 3; // => 2 + // 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 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 + 11 % (-3); // => 2 and not -2, and it's quite counter intuitive // 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) 3 != 2; // => 1 (true) - 3 > 2; // => 1 - 3 < 2; // => 0 + 3 > 2; // => 1 + 3 < 2; // => 0 2 <= 2; // => 1 2 >= 2; // => 1 - // C is not Python - comparisons don't chain. + // C is not Python - comparisons do NOT chain. // Warning: The line below will compile, but it means `(0 < a) < 2`. // This expression is always true, because (0 < a) could be either 1 or 0. // In this case it's 1, because (0 < 1). @@ -346,25 +395,30 @@ int main (int argc, char** argv) break; } /* - using "goto" in C + Using "goto" in C */ typedef enum { false, true } bool; // for C don't have bool as data type before C99 :( bool disaster = false; int i, j; - for(i=0;i<100;++i) - for(j=0;j<100;++j) + for(i=0; i<100; ++i) + for(j=0; j<100; ++j) { if((i + j) >= 150) disaster = true; if(disaster) - goto error; + goto error; // exit both for loops } - error : + error: // this is a label that you can "jump" to with "goto error;" printf("Error occurred at i = %d & j = %d.\n", i, j); /* - https://ideone.com/GuPhd6 - this will print out "Error occurred at i = 51 & j = 99." + https://ideone.com/GuPhd6 + this will print out "Error occurred at i = 51 & j = 99." + */ + /* + it is generally considered bad practice to do so, except if + you really know what you are doing. See + https://en.wikipedia.org/wiki/Spaghetti_code#Meaning */ /////////////////////////////////////// @@ -375,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`, @@ -527,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 */ @@ -538,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; @@ -572,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]`, @@ -637,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; @@ -661,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) @@ -700,6 +788,10 @@ typedef void (*my_fnp_type)(char *); // my_fnp_type f; +///////////////////////////// +// Printing characters with printf() +///////////////////////////// + //Special characters: /* '\a'; // alert (bell) character @@ -738,11 +830,12 @@ typedef void (*my_fnp_type)(char *); // Order of Evaluation /////////////////////////////////////// +// From top to bottom, top has higher precedence //---------------------------------------------------// // Operators | Associativity // //---------------------------------------------------// // () [] -> . | left to right // -// ! ~ ++ -- + = *(type)sizeof | right to left // +// ! ~ ++ -- + = *(type) sizeof | right to left // // * / % | left to right // // + - | left to right // // << >> | left to right // @@ -780,8 +873,8 @@ as the C file. /* included into files that include this header. */ #include <string.h> -/* Like c source files macros can be defined in headers and used in files */ -/* that include this header file. */ +/* Like for c source files, macros can be defined in headers */ +/* and used in files that include this header file. */ #define EXAMPLE_NAME "Dennis Ritchie" /* Function macros can also be defined. */ @@ -808,19 +901,20 @@ 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://c.learncodethehardway.org/book/). +Another good resource is [Learn C The Hard Way](http://learncodethehardway.org/c/) (not free). If you have a question, read the [compl.lang.c Frequently Asked Questions](http://c-faq.com). @@ -830,4 +924,4 @@ Readable code is better than clever code and fast code. For a good, sane coding Other than that, Google is your friend. -[1] [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) +[1] [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) diff --git a/ca-es/asciidoc-ca.html.markdown b/ca-es/asciidoc-ca.html.markdown index a88aba52..6d387213 100644 --- a/ca-es/asciidoc-ca.html.markdown +++ b/ca-es/asciidoc-ca.html.markdown @@ -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. diff --git a/ca-es/go-ca.html.markdown b/ca-es/go-ca.html.markdown index 99f0d393..7bec4ba4 100644 --- a/ca-es/go-ca.html.markdown +++ b/ca-es/go-ca.html.markdown @@ -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 diff --git a/cairo.html.markdown b/cairo.html.markdown new file mode 100644 index 00000000..dd3ca036 --- /dev/null +++ b/cairo.html.markdown @@ -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 diff --git a/chapel.html.markdown b/chapel.html.markdown index 7e8fc41a..cfab6f34 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -1171,7 +1171,7 @@ You will need to `source util/setchplenv.EXT` from within the Chapel directory (`$CHPL_HOME`) every time your terminal starts so it's suggested that you drop that command in a script that will get executed on startup (like .bashrc). -Chapel is easily installed with Brew for OS X +Chapel is easily installed with Brew for macOS 1. `brew update` 2. `brew install chapel` diff --git a/citron.html.markdown b/citron.html.markdown index bd3c398c..ce607ca1 100644 --- a/citron.html.markdown +++ b/citron.html.markdown @@ -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 diff --git a/clojure.html.markdown b/clojure.html.markdown index c94625d6..21d5a088 100644 --- a/clojure.html.markdown +++ b/clojure.html.markdown @@ -298,8 +298,8 @@ keymap ; => {:a 1, :b 2, :c 3} (as-> [1 2 3] input (map inc input);=> You can use last transform's output at the last position (nth input 2) ;=> and at the second position, in the same expression - (conj [4 5 6] input [8 9 10])) ;=> or in the middle ! - + (conj [4 5 6] input 8 9 10)) ;=> or in the middle ! + ; Result: [4 5 6 4 8 9 10] ; Modules @@ -412,7 +412,10 @@ 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/) + +Clojure for the Brave and True has a great introduction to Clojure and a free online version: +[https://www.braveclojure.com/clojure-for-the-brave-and-true/](https://www.braveclojure.com/clojure-for-the-brave-and-true/) diff --git a/cmake.html.markdown b/cmake.html.markdown index 32a7b758..9ea68a42 100644 --- a/cmake.html.markdown +++ b/cmake.html.markdown @@ -6,25 +6,25 @@ contributors: filename: CMake --- -CMake is a cross-platform, open-source build system. This tool will allow you -to test, compile and create packages of your source code. +CMake is a cross-platform, open-source build system. This tool allows you to test, +compile, and create packages of your source code. -The problem that CMake tries to solve is the problem of Makefiles and -Autoconfigure on cross-platforms (different make interpreters have different -command) and the ease-of-use on linking 3rd party libraries. +The problem that CMake tries to solve is the problem of Makefiles and +Autoconfigure on cross-platforms (different make interpreters have different +commands) and the ease-of-use on linking 3rd party libraries. -CMake is an extensible, open-source system that manages the build process in -an operating system and compiler-independent manner. Unlike many -cross-platform systems, CMake is designed to be used in conjunction with the +CMake is an extensible, open-source system that manages the build process in +an operating system and compiler-agnostic manner. Unlike many +cross-platform systems, CMake is designed to be used in conjunction with the native build environment. Simple configuration files placed in each source -directory (called CMakeLists.txt files) are used to generate standard build -files (e.g., makefiles on Unix and projects/workspaces in Windows MSVC) which +directory (called CMakeLists.txt files) are used to generate standard build +files (e.g., makefiles on Unix and projects/workspaces in Windows MSVC) which are used in the usual way. ```cmake # In CMake, this is a comment -# To run our code, we will use these steps: +# To run our code, please perform the following commands: # - mkdir build && cd build # - cmake .. # - make @@ -45,22 +45,22 @@ cmake_minimum_required (VERSION 2.8) # Raises a FATAL_ERROR if version < 2.8 cmake_minimum_required (VERSION 2.8 FATAL_ERROR) -# We setup the name for our project. After we do that, this will change some -# directories naming convention generated by CMake. We can send the LANG of -# code as second param +# We define the name of our project, and this changes some directories +# naming convention generated by CMake. We can send the LANG of code +# as the second param project (learncmake C) # Set the project source dir (just convention) set( LEARN_CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) set( LEARN_CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) -# It's useful to setup the current version of our code in the build system +# It's useful to set up the current version of our code in the build system # using a `semver` style set (LEARN_CMAKE_VERSION_MAJOR 1) set (LEARN_CMAKE_VERSION_MINOR 0) set (LEARN_CMAKE_VERSION_PATCH 0) -# Send the variables (version number) to source code header +# Send the variables (version number) to the source code header configure_file ( "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" "${PROJECT_BINARY_DIR}/TutorialConfig.h" @@ -127,14 +127,14 @@ if(FALSE AND (FALSE OR TRUE)) message("Don't display!") endif() -# Set a normal, cache, or environment variable to a given value. -# If the PARENT_SCOPE option is given the variable will be set in the scope +# Set a regular, cache, or environment variable to a given value. +# If the PARENT_SCOPE option is given, the variable will be set in the scope # above the current scope. # `set(<variable> <value>... [PARENT_SCOPE])` -# How to reference variables inside quoted and unquoted arguments -# A variable reference is replaced by the value of the variable, or by the -# empty string if the variable is not set +# How to reference variables inside quoted and unquoted arguments? +# A variable reference is replaced by either the variable value or by the +# empty string if the variable is not set. ${variable_name} # Lists @@ -172,6 +172,7 @@ endif() ### More Resources -+ [cmake tutorial](https://cmake.org/cmake-tutorial/) -+ [cmake documentation](https://cmake.org/documentation/) -+ [mastering cmake](http://amzn.com/1930934319/) ++ [CMake tutorial](https://cmake.org/cmake-tutorial/) ++ [CMake documentation](https://cmake.org/documentation/) ++ [Mastering CMake](http://amzn.com/1930934319/) ++ [An Introduction to Modern CMake](https://cliutils.gitlab.io/modern-cmake/) diff --git a/cobol.html.markdown b/cobol.html.markdown new file mode 100644 index 00000000..1350c66f --- /dev/null +++ b/cobol.html.markdown @@ -0,0 +1,198 @@ +--- +language: COBOL +contributors: + - ["Hyphz", "http://github.com/hyphz/"] +filename: learn.COB +--- +COBOL is a business-oriented language revised multiple times since its original design in 1960. It is claimed to still be used in over 80% of +organizations. + +```cobol + *COBOL. Coding like it's 1985. + *Compiles with GnuCOBOL in OpenCobolIDE 4.7.6. + + *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). + *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 + *a comment, which can appear in the middle of a line. + *Legacy COBOL also imposes a limit on maximum line length. + *Keywords have to be in capitals in legacy COBOL, + *but are case insensitive in modern. + *Although modern COBOL allows you to use mixed-case characters + *it is still common to use all caps when writing COBOL code. + *This is what most professional COBOL developers do. + *COBOL statements end with a period. + + *COBOL code is broken up into 4 divisions. + *Those divisions, in order, are: + *IDENTIFICATION DIVISION. + *ENVIRONMENT DIVISION. + *DATA DIVISION. + *PROCEDURE DIVISION. + + *First, we must give our program an ID. + *Identification division can include other values too, + *but they are comments only. Program-id is the only one that is mandatory. + IDENTIFICATION DIVISION. + PROGRAM-ID. LEARN. + AUTHOR. JOHN DOE. + DATE-WRITTEN. 05/02/2020. + + *Let's declare some variables. + *We do this in the WORKING-STORAGE section within the DATA DIVISION. + *Each data item (aka variable) starts with a level number, + *then the name of the item, followed by a picture clause + *describing the type of data that the variable will contain. + *Almost every COBOL programmer will abbreviate PICTURE as PIC. + *A is for alphabetic, X is for alphanumeric, and 9 is for numeric. + + *example: + 01 MYNAME PIC xxxxxxxxxx. *> A 10 character string. + + *But counting all those x's can lead to errors, + *so the above code can, and should + *be re-written as: + 01 MYNAME PIC X(10). + + *Here are some more examples: + 01 AGE PIC 9(3). *> A number up to 3 digits. + 01 LAST_NAME PIC X(10). *> A string up to 10 characters. + + *In COBOL, multiple spaces are the same as a single space, so it is common + *to use multiple spaces to line up your code so that it is easier for other + *coders to read. + 01 inyear picture s9(7). *> S makes number signed. + *> Brackets indicate 7 repeats of 9, + *> ie a 6 digit number (not an array). + + *Now let's write some code. Here is a simple, Hello World program. + IDENTIFICATION DIVISION. + PROGRAM-ID. HELLO. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 THE-MESSAGE PIC X(20). + PROCEDURE DIVISION. + DISPLAY "STARTING PROGRAM". + MOVE "HELLO WORLD" TO THE-MESSAGE. + DISPLAY THE-MESSAGE. + STOP RUN. + + *The above code will output: + *STARTING PROGRAM + *HELLO WORLD + + + + ********COBOL can perform math*************** + ADD 1 TO AGE GIVING NEW-AGE. + SUBTRACT 1 FROM COUNT. + DIVIDE VAR-1 INTO VAR-2 GIVING VAR-3. + COMPUTE TOTAL-COUNT = COUNT1 PLUS COUNT2. + + + *********PERFORM******************** + *The PERFORM keyword allows you to jump to another specified section of the code, + *and then to return to the next executable + *statement once the specified section of code is completed. + *You must write the full word, PERFORM, you cannot abbreviate it. + + IDENTIFICATION DIVISION. + PROGRAM-ID. HELLOCOBOL. + + PROCEDURE DIVISION. + FIRST-PARA. + DISPLAY 'THIS IS IN FIRST-PARA'. + 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. + + SECOND-PARA. + DISPLAY 'THIS IS IN SECOND-PARA'. + STOP RUN. + + THIRD-PARA. + DISPLAY 'THIS IS IN THIRD-PARA'. + + FOURTH-PARA. + DISPLAY 'THIS IS IN FOURTH-PARA'. + + + *When you compile and execute the above program, it produces the following result: + THIS IS IN FIRST-PARA + THIS IS IN THIRD-PARA + THIS IS IN FOURTH-PARA + THIS IS IN SECOND-PARA + + + **********Combining variables together using STRING *********** + + *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 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 + *are using string or unstring in your program. + + IDENTIFICATION DIVISION. + PROGRAM-ID. LEARNING. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 FULL-NAME PIC X(20). + 01 FIRST-NAME PIC X(13) VALUE "BOB GIBBERISH". + 01 LAST-NAME PIC X(5) VALUE "COBB". + PROCEDURE DIVISION. + STRING FIRST-NAME DELIMITED BY SPACE + " " + LAST-NAME DELIMITED BY SIZE + INTO FULL-NAME + END-STRING. + DISPLAY "THE FULL NAME IS: "FULL-NAME. + STOP RUN. + + + *The above code will output: + THE FULL NAME IS: BOB COBB + + + *Let’s examine it to see why. + + *First, we declared all of our variables, including the one that we are creating + *by the string command, in the DATA DIVISION. + + *The action takes place down in the PROCEDURE DIVISION. + *We start with the STRING keyword and end with END-STRING. In between we + *list what we want to combine together into the larger, master variable. + *Here, we are combining FIRST-NAME, a space, and LAST-NAME. + + *The DELIMITED BY phrase that follows FIRST-NAME and + *LAST-NAME tells the program how much of each variable we want to capture. + *DELIMITED BY SPACE tells the program to start at the beginning, + *and capture the variable until it runs into a space. + *DELIMITED BY SIZE tells the program to capture the full size of the variable. + *Since we have DELIMITED BY SPACE after FIRST-NAME, the GIBBERISH part is ignored. + + *To make this clearer, change line 10 in the above code to: + + STRING FIRST-NAME DELIMITED BY SIZE + + *and then re-run the program. This time the output is: + + THE FULL NAME IS: BOB GIBBERISH COBB + + + + + + +``` + +##Ready For More? + +* [GnuCOBOL](https://sourceforge.net/projects/open-cobol/) + diff --git a/common-lisp.html.markdown b/common-lisp.html.markdown index b12e50ca..1f2bb366 100644 --- a/common-lisp.html.markdown +++ b/common-lisp.html.markdown @@ -69,7 +69,7 @@ t ; another atom, denoting true ;;; is a good starting point. Third party libraries can be easily installed with ;;; Quicklisp -;;; CL is usually developed with a text editor and a Real Eval Print +;;; CL is usually developed with a text editor and a Read Eval Print ;;; Loop (REPL) running at the same time. The REPL allows for interactive ;;; exploration of the program while it is running "live". diff --git a/coq.html.markdown b/coq.html.markdown new file mode 100644 index 00000000..3a924a19 --- /dev/null +++ b/coq.html.markdown @@ -0,0 +1,510 @@ +--- +language: Coq +filename: learncoq.v +contributors: + - ["Philip Zucker", "http://www.philipzucker.com/"] +--- + +The Coq system is a proof assistant. It is designed to build and verify mathematical proofs. The Coq system contains the functional programming language Gallina and is capable of proving properties about programs written in this language. + +Coq is a dependently typed language. This means that the types of the language may depend on the values of variables. In this respect, it is similar to other related languages such as Agda, Idris, F*, Lean, and others. Via the Curry-Howard correspondence, programs, properties and proofs are formalized in the same language. + +Coq is developed in OCaml and shares some syntactic and conceptual similarity with it. Coq is a language containing many fascinating but difficult topics. This tutorial will focus on the programming aspects of Coq, rather than the proving. It may be helpful, but not necessary to learn some OCaml first, especially if you are unfamiliar with functional programming. This tutorial is based upon its OCaml equivalent + +The standard usage model of Coq is to write it with interactive tool assistance, which operates like a high powered REPL. Two common such editors are the CoqIDE and Proof General Emacs mode. + +Inside Proof General `Ctrl+C Ctrl+<Enter>` will evaluate up to your cursor. + + +```coq +(*** Comments ***) + +(* Comments are enclosed in (* and *). It's fine to nest comments. *) + +(* There are no single-line comments. *) + +(*** Variables and functions ***) + +(* The Coq proof assistant can be controlled and queried by a command + language called the vernacular. Vernacular keywords are capitalized and + the commands end with a period. Variable and function declarations are + formed with the Definition vernacular. *) + +Definition x := 10. + +(* Coq can sometimes infer the types of arguments, but it is common practice + to annotate with types. *) + +Definition inc_nat (x : nat) : nat := x + 1. + +(* There exists a large number of vernacular commands for querying + information. These can be very useful. *) + +Compute (1 + 1). (* 2 : nat *) (* Compute a result. *) + +Check tt. (* tt : unit *) (* Check the type of an expressions *) + +About plus. (* Prints information about an object *) + +(* Print information including the definition *) +Print true. (* Inductive bool : Set := true : Bool | false : Bool *) + +Search nat. (* Returns a large list of nat related values *) +Search "_ + _". (* You can also search on patterns *) +Search (?a -> ?a -> bool). (* Patterns can have named parameters *) +Search (?a * ?a). + +(* Locate tells you where notation is coming from. Very helpful when you + encounter new notation. *) + +Locate "+". + +(* Calling a function with insufficient number of arguments does not cause + an error, it produces a new function. *) +Definition make_inc x y := x + y. (* make_inc is nat -> nat -> nat *) +Definition inc_2 := make_inc 2. (* inc_2 is nat -> nat *) +Compute inc_2 3. (* Evaluates to 5 *) + + +(* Definitions can be chained with "let ... in" construct. This is roughly + the same to assigning values to multiple variables before using them in + expressions in imperative languages. *) + +Definition add_xy : nat := let x := 10 in + let y := 20 in + x + y. + +(* Pattern matching is somewhat similar to switch statement in imperative + languages, but offers a lot more expressive power. *) + +Definition is_zero (x : nat) := + match x with + | 0 => true + | _ => false (* The "_" pattern means "anything else". *) + end. + +(* You can define recursive function definition using the Fixpoint + vernacular.*) + +Fixpoint factorial n := match n with + | 0 => 1 + | (S n') => n * factorial n' + end. + +(* Function application usually doesn't need parentheses around arguments *) +Compute factorial 5. (* 120 : nat *) + +(* ...unless the argument is an expression. *) +Compute factorial (5-1). (* 24 : nat *) + +(* You can define mutually recursive functions using "with" *) +Fixpoint is_even (n : nat) : bool := match n with + | 0 => true + | (S n) => is_odd n +end with + is_odd n := match n with + | 0 => false + | (S n) => is_even n + end. + +(* As Coq is a total programming language, it will only accept programs when + it can understand they terminate. It can be most easily seen when the + recursive call is on a pattern matched out subpiece of the input, as then + the input is always decreasing in size. Getting Coq to understand that + functions terminate is not always easy. See the references at the end of + the article for more on this topic. *) + +(* Anonymous functions use the following syntax: *) + +Definition my_square : nat -> nat := fun x => x * x. + +Definition my_id (A : Type) (x : A) : A := x. +Definition my_id2 : forall A : Type, A -> A := fun A x => x. +Compute my_id nat 3. (* 3 : nat *) + +(* You can ask Coq to infer terms with an underscore *) +Compute my_id _ 3. + +(* An implicit argument of a function is an argument which can be inferred + from contextual knowledge. Parameters enclosed in {} are implicit by + default *) + +Definition my_id3 {A : Type} (x : A) : A := x. +Compute my_id3 3. (* 3 : nat *) + +(* Sometimes it may be necessary to turn this off. You can make all + arguments explicit again with @ *) + +Compute @my_id3 nat 3. + +(* Or give arguments by name *) +Compute my_id3 (A:=nat) 3. + +(* Coq has the ability to extract code to OCaml, Haskell, and Scheme *) +Require Extraction. +Extraction Language OCaml. +Extraction "factorial.ml" factorial. +(* The above produces a file factorial.ml and factorial.mli that holds: + +type nat = +| O +| S of nat + +(** val add : nat -> nat -> nat **) + +let rec add n m = + match n with + | O -> m + | S p -> S (add p m) + +(** val mul : nat -> nat -> nat **) + +let rec mul n m = + match n with + | O -> O + | S p -> add m (mul p m) + +(** val factorial : nat -> nat **) + +let rec factorial n = match n with +| O -> S O +| S n' -> mul n (factorial n') +*) + + +(*** Notation ***) + +(* Coq has a very powerful Notation system that can be used to write + expressions in more natural forms. *) + +Compute Nat.add 3 4. (* 7 : nat *) +Compute 3 + 4. (* 7 : nat *) + +(* Notation is a syntactic transformation applied to the text of the program + before being evaluated. Notation is organized into notation scopes. Using + different notation scopes allows for a weak notion of overloading. *) + +(* Imports the Zarith module holding definitions related to the integers Z *) + +Require Import ZArith. + +(* Notation scopes can be opened *) +Open Scope Z_scope. + +(* Now numerals and addition are defined on the integers. *) +Compute 1 + 7. (* 8 : Z *) + +(* Integer equality checking *) +Compute 1 =? 2. (* false : bool *) + +(* Locate is useful for finding the origin and definition of notations *) +Locate "_ =? _". (* Z.eqb x y : Z_scope *) +Close Scope Z_scope. + +(* We're back to nat being the default interpretation of "+" *) +Compute 1 + 7. (* 8 : nat *) + +(* Scopes can also be opened inline with the shorthand % *) +Compute (3 * -7)%Z. (* -21%Z : Z *) + +(* Coq declares by default the following interpretation scopes: core_scope, + type_scope, function_scope, nat_scope, bool_scope, list_scope, int_scope, + uint_scope. You may also want the numerical scopes Z_scope (integers) and + Q_scope (fractions) held in the ZArith and QArith module respectively. *) + +(* You can print the contents of scopes *) +Print Scope nat_scope. +(* +Scope nat_scope +Delimiting key is nat +Bound to classes nat Nat.t +"x 'mod' y" := Nat.modulo x y +"x ^ y" := Nat.pow x y +"x ?= y" := Nat.compare x y +"x >= y" := ge x y +"x > y" := gt x y +"x =? y" := Nat.eqb x y +"x <? y" := Nat.ltb x y +"x <=? y" := Nat.leb x y +"x <= y <= z" := and (le x y) (le y z) +"x <= y < z" := and (le x y) (lt y z) +"n <= m" := le n m +"x < y <= z" := and (lt x y) (le y z) +"x < y < z" := and (lt x y) (lt y z) +"x < y" := lt x y +"x / y" := Nat.div x y +"x - y" := Init.Nat.sub x y +"x + y" := Init.Nat.add x y +"x * y" := Init.Nat.mul x y +*) + +(* Coq has exact fractions available as the type Q in the QArith module. + Floating point numbers and real numbers are also available but are a more + advanced topic, as proving properties about them is rather tricky. *) + +Require Import QArith. + +Open Scope Q_scope. +Compute 1. (* 1 : Q *) + +(* Only 1 and 0 are interpreted as fractions by Q_scope *) +Compute 2. (* 2 : nat *) +Compute (2 # 3). (* The fraction 2/3 *) +Compute (1 # 3) ?= (2 # 6). (* Eq : comparison *) +Close Scope Q_scope. + +Compute ( (2 # 3) / (1 # 5) )%Q. (* 10 # 3 : Q *) + + +(*** Common data structures ***) + +(* Many common data types are included in the standard library *) + +(* The unit type has exactly one value, tt *) +Check tt. (* tt : unit *) + +(* The option type is useful for expressing computations that might fail *) +Compute None. (* None : option ?A *) +Check Some 3. (* Some 3 : option nat *) + +(* The type sum A B allows for values of either type A or type B *) +Print sum. +Check inl 3. (* inl 3 : nat + ?B *) +Check inr true. (* inr true : ?A + bool *) +Check sum bool nat. (* (bool + nat)%type : Set *) +Check (bool + nat)%type. (* Notation for sum *) + +(* Tuples are (optionally) enclosed in parentheses, items are separated + by commas. *) +Check (1, true). (* (1, true) : nat * bool *) +Compute prod nat bool. (* (nat * bool)%type : Set *) + +Definition my_fst {A B : Type} (x : A * B) : A := match x with + | (a,b) => a + end. + +(* A destructuring let is available if a pattern match is irrefutable *) +Definition my_fst2 {A B : Type} (x : A * B) : A := let (a,b) := x in + a. + +(*** Lists ***) + +(* Lists are built by using cons and nil or by using notation available in + list_scope. *) +Compute cons 1 (cons 2 (cons 3 nil)). (* (1 :: 2 :: 3 :: nil)%list : list nat *) +Compute (1 :: 2 :: 3 :: nil)%list. + +(* There is also list notation available in the ListNotations modules *) +Require Import List. +Import ListNotations. +Compute [1 ; 2 ; 3]. (* [1; 2; 3] : list nat *) + + +(* There is a large number of list manipulation functions available, + including: + +• length +• head : first element (with default) +• tail : all but first element +• app : appending +• rev : reverse +• nth : accessing n-th element (with default) +• map : applying a function +• flat_map : applying a function returning lists +• fold_left : iterator (from head to tail) +• fold_right : iterator (from tail to head) + + *) + +Definition my_list : list nat := [47; 18; 34]. + +Compute List.length my_list. (* 3 : nat *) + +(* All functions in coq must be total, so indexing requires a default value *) +Compute List.nth 1 my_list 0. (* 18 : nat *) +Compute List.map (fun x => x * 2) my_list. (* [94; 36; 68] : list nat *) +Compute List.filter (fun x => Nat.eqb (Nat.modulo x 2) 0) my_list. + (* [18; 34] : list nat *) +Compute (my_list ++ my_list)%list. (* [47; 18; 34; 47; 18; 34] : list nat *) + +(*** Strings ***) + +Require Import Strings.String. + +(* Use double quotes for string literals. *) +Compute "hi"%string. + +Open Scope string_scope. + +(* Strings can be concatenated with the "++" operator. *) +Compute String.append "Hello " "World". (* "Hello World" : string *) +Compute "Hello " ++ "World". (* "Hello World" : string *) + +(* Strings can be compared for equality *) +Compute String.eqb "Coq is fun!" "Coq is fun!". (* true : bool *) +Compute "no" =? "way". (* false : bool *) + +Close Scope string_scope. + +(*** Other Modules ***) + +(* Other Modules in the standard library that may be of interest: + +• Logic : Classical logic and dependent equality +• Arith : Basic Peano arithmetic +• PArith : Basic positive integer arithmetic +• NArith : Basic binary natural number arithmetic +• ZArith : Basic relative integer arithmetic + +• Numbers : Various approaches to natural, integer and cyclic numbers + (currently axiomatically and on top of 2^31 binary words) +• Bool : Booleans (basic functions and results) + +• Lists : Monomorphic and polymorphic lists (basic functions and results), + Streams (infinite sequences defined with co-inductive types) +• Sets : Sets (classical, constructive, finite, infinite, power set, etc.) +• FSets : Specification and implementations of finite sets and finite maps + (by lists and by AVL trees) +• Reals : Axiomatization of real numbers (classical, basic functions, + integer part, fractional part, limit, derivative, Cauchy series, + power series and results,...) +• Relations : Relations (definitions and basic results) +• Sorting : Sorted list (basic definitions and heapsort correctness) +• Strings : 8-bit characters and strings +• Wellfounded : Well-founded relations (basic results) + *) + +(*** User-defined data types ***) + +(* Because Coq is dependently typed, defining type aliases is no different + than defining an alias for a value. *) + +Definition my_three : nat := 3. +Definition my_nat : Type := nat. + +(* More interesting types can be defined using the Inductive vernacular. + Simple enumeration can be defined like so *) + +Inductive ml := OCaml | StandardML | Coq. +Definition lang := Coq. (* Has type "ml". *) + +(* For more complicated types, you will need to specify the types of the + constructors. *) + +(* Type constructors don't need to be empty. *) +Inductive my_number := plus_infinity + | nat_value : nat -> my_number. +Compute nat_value 3. (* nat_value 3 : my_number *) + + +(* Record syntax is sugar for tuple-like types. It defines named accessor + functions for the components. Record types are defined with the notation + {...} *) + +Record Point2d (A : Set) := mkPoint2d { x2 : A ; y2 : A }. +(* Record values are constructed with the notation {|...|} *) +Definition mypoint : Point2d nat := {| x2 := 2 ; y2 := 3 |}. +Compute x2 nat mypoint. (* 2 : nat *) +Compute mypoint.(x2 nat). (* 2 : nat *) + +(* Types can be parameterized, like in this type for "list of lists of + anything". 'a can be substituted with any type. *) + +Definition list_of_lists a := list (list a). +Definition list_list_nat := list_of_lists nat. + +(* Types can also be recursive. Like in this type analogous to + built-in list of naturals. *) + +Inductive my_nat_list := + EmptyList | NatList : nat -> my_nat_list -> my_nat_list. + +Compute NatList 1 EmptyList. (* NatList 1 EmptyList : my_nat_list *) + +(** Matching type constructors **) + +Inductive animal := Dog : string -> animal | Cat : string -> animal. + +Definition say x := + match x with + | Dog x => (x ++ " says woof")%string + | Cat x => (x ++ " says meow")%string + end. + +Compute say (Cat "Fluffy"). (* "Fluffy says meow". *) + +(** Traversing data structures with pattern matching **) + +(* Recursive types can be traversed with pattern matching easily. + Let's see how we can traverse a data structure of the built-in list type. + Even though the built-in cons ("::") looks like an infix operator, + it's actually a type constructor and can be matched like any other. *) +Fixpoint sum_list l := + match l with + | [] => 0 + | head :: tail => head + (sum_list tail) + end. + +Compute sum_list [1; 2; 3]. (* Evaluates to 6 *) + + +(*** A Taste of Proving ***) + +(* Explaining the proof language is out of scope for this tutorial, but here + is a taste to whet your appetite. Check the resources below for more. *) + +(* A fascinating feature of dependently type based theorem provers is that + the same primitive constructs underly the proof language as the + programming features. For example, we can write and prove the + proposition A and B implies A in raw Gallina *) + +Definition my_theorem : forall A B, A /\ B -> A := + fun A B ab => match ab with + | (conj a b) => a + end. + +(* Or we can prove it using tactics. Tactics are a macro language to help + build proof terms in a more natural style and automate away some + drudgery. *) + +Theorem my_theorem2 : forall A B, A /\ B -> A. +Proof. + intros A B ab. destruct ab as [ a b ]. apply a. +Qed. + +(* We can easily prove simple polynomial equalities using the + automated tactic ring. *) + +Require Import Ring. +Require Import Arith. +Theorem simple_poly : forall (x : nat), (x + 1) * (x + 2) = x * x + 3 * x + 2. + Proof. intros. ring. Qed. + +(* Here we prove the closed form for the sum of all numbers 1 to n using + induction *) + +Fixpoint sumn (n : nat) : nat := + match n with + | 0 => 0 + | (S n') => n + (sumn n') + end. + +Theorem sum_formula : forall n, 2 * (sumn n) = (n + 1) * n. +Proof. intros n. induction n. + - reflexivity. (* 0 = 0 base case *) + - simpl. ring [IHn]. (* induction step *) +Qed. +``` + +With this we have only scratched the surface of Coq. It is a massive +ecosystem with many interesting and peculiar topics leading all the way up +to modern research. + +## Further reading + +* [The Coq reference manual](https://coq.inria.fr/refman/) +* [Software Foundations](https://softwarefoundations.cis.upenn.edu/) +* [Certified Programming with Dependent Types](http://adam.chlipala.net/cpdt/) +* [Mathematical Components](https://math-comp.github.io/mcb/) +* [Coq'Art: The Calculus of Inductive Constructions](http://www.cse.chalmers.se/research/group/logic/TypesSS05/resources/coq/CoqArt/) +* [FRAP](http://adam.chlipala.net/frap/) diff --git a/crystal.html.markdown b/crystal.html.markdown index 9fae9da3..d32712ce 100644 --- a/crystal.html.markdown +++ b/crystal.html.markdown @@ -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"} @@ -229,7 +235,7 @@ b #=> 'b' c #=> "c" # Procs represent a function pointer with an optional context (the closure data) -# It is typically created with a proc litteral +# It is typically created with a proc literal proc = ->(x : Int32) { x.to_s } proc.class # Proc(Int32, String) # Or using the new method @@ -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 @@ -551,4 +561,4 @@ ex #=> "ex2" ## Additional resources -- [Official Documentation](http://crystal-lang.org/) +- [Official Documentation](https://crystal-lang.org/) diff --git a/cs-cz/css.html.markdown b/cs-cz/css.html.markdown index 54a0a08e..ed69c73a 100644 --- a/cs-cz/css.html.markdown +++ b/cs-cz/css.html.markdown @@ -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í. diff --git a/cs-cz/go.html.markdown b/cs-cz/go.html.markdown index 36217414..18880a3b 100644 --- a/cs-cz/go.html.markdown +++ b/cs-cz/go.html.markdown @@ -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/). diff --git a/cs-cz/javascript.html.markdown b/cs-cz/javascript.html.markdown index c05a9138..408ddde0 100644 --- a/cs-cz/javascript.html.markdown +++ b/cs-cz/javascript.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["Michal Martinek", "https://github.com/MichalMartinek"] diff --git a/cs-cz/markdown.html.markdown b/cs-cz/markdown.html.markdown index 35becf94..e1a96f32 100644 --- a/cs-cz/markdown.html.markdown +++ b/cs-cz/markdown.html.markdown @@ -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 +<!-- 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 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 + +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 -<!-- 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. --> - -<!-- 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. --> - -<!-- 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 --> # Toto je <h1> ## Toto je <h2> ### Toto je <h3> #### Toto je <h4> ##### Toto je <h5> ###### Toto je <h6> +``` + +Markdown obsahuje ještě dva další způsoby, jak vytvořit h1 a h2: -<!-- Markdown obsahuje taky dvě další cesty, jak udělat h1 a h2 --> +```md Toto je h1 ========== Toto je h2 ---------- +``` + +## Jednoduché stylování textu -<!-- Jednoduché stylování textu --> -<!-- Pomocí markdownu můžete text jednoduše označit jako kurzívu či tučný --> +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. -Teď jsem v odstavci 2. -Jsem pořád v odstavci 2! +```md +Toto je odstavec. Zde jsem napsal odstavec a je to bezva! +Teď jsem v odstavci 2. +A tady jsem pořád v odstavci 2! -Toto je odstavec 3. +Ale tady už 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 -<!-- Blokové citace se dělají jednoduše pomocí znaku >. --> +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 `>`. + +> Použít můžu i více než jednu úroveň +>> odsazení. +> Co vy na to? +``` -> Můžu použít více než jednu ->> odsazení? -> Jak je to úhledné, že? +## Seznamy -<!-- Seznamy --> -<!-- Nečíslovaný seznam můžete jednoduše udělat pomocí hvězdiček, plusů, nebo - pomlček --> +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 -<!-- 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 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 čtyřmezerové odsazení a parser navíc použije zvýraznění +syntaxe pro zvolený jazyk. -<!-- Text výše nepotřebuje odsazení a navíc GitHub použije zvýraznění označeného - jazyka. --> +## Vodorovná čára (`<hr />`) -<!-- 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. --> +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 -<!-- 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. --> +```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 -->  -<!-- 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 + +```md +<http://stranka.cz/> -<!-- Ostatní --> -<!-- Automatické odkazy --> +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 +Že se to nedá číst? | No tak to takhle | radši nedělejte. +``` -<!-- Konec --> +## 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ě): -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). +- [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) diff --git a/cs-cz/python3.html.markdown b/cs-cz/python.html.markdown index bd3690a8..71509460 100644 --- a/cs-cz/python3.html.markdown +++ b/cs-cz/python.html.markdown @@ -1,5 +1,5 @@ --- -language: python3 +language: Python contributors: - ["Louie Dinh", "http://pythonpracticeprojects.com"] - ["Steven Basart", "http://github.com/xksteven"] @@ -7,7 +7,7 @@ contributors: - ["Tomáš Bedřich", "http://tbedrich.cz"] translators: - ["Tomáš Bedřich", "http://tbedrich.cz"] -filename: learnpython3-cz.py +filename: learnpython-cz.py lang: cs-cz --- @@ -17,7 +17,7 @@ Zamiloval jsem si Python pro jeho syntaktickou čistotu - je to vlastně spustit Vaše zpětná vazba je vítána! Můžete mě zastihnout na [@louiedinh](http://twitter.com/louiedinh) nebo louiedinh [at] [email od googlu] anglicky, autora českého překladu pak na [@tbedrich](http://twitter.com/tbedrich) nebo ja [at] tbedrich.cz -Poznámka: Tento článek je zaměřen na Python 3. Zde se můžete [naučit starší Python 2.7](http://learnxinyminutes.com/docs/python/). +Poznámka: Tento článek je zaměřen na Python 3. Zde se můžete [naučit starší Python 2.7](http://learnxinyminutes.com/docs/pythonlegacy/). ```python @@ -42,7 +42,8 @@ Poznámka: Tento článek je zaměřen na Python 3. Zde se můžete [naučit sta # Až na dělení, které vrací desetinné číslo 35 / 5 # => 7.0 -# Při celočíselném dělení je desetinná část oříznuta (pro kladná i záporná čísla) +# Při celočíselném dělení je na výsledek aplikována funkce floor(), +# což znamená zaokrouhlení směrem k mínus nekonečnu (pro kladná i záporná čísla). 5 // 3 # => 1 5.0 // 3.0 # => 1.0 # celočíselně dělit lze i desetinným číslem -5 // 3 # => -2 diff --git a/csharp.html.markdown b/csharp.html.markdown index df6544d3..1d7d0881 100644 --- a/csharp.html.markdown +++ b/csharp.html.markdown @@ -1,5 +1,5 @@ --- -language: c# +language: C# contributors: - ["Irfan Charania", "https://github.com/irfancharania"] - ["Max Yankov", "https://github.com/golergka"] @@ -12,22 +12,24 @@ 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.](http://msdn.microsoft.com/en-us/library/vstudio/z1zx9t92.aspx) +[Read more here.](https://docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/) ```c# // Single-line comments start with // + /* Multi-line comments look like this */ + /// <summary> /// This is an XML documentation comment which can be used to generate external /// documentation or provide context help within an IDE /// </summary> /// <param name="firstParam">This is some parameter documentation for firstParam</param> /// <returns>Information on the returned value of a function</returns> -//public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {} +public void MethodOrClassOrOtherWithParsableHelp(string firstParam) { } // Specify the namespaces this source code will be using // The namespaces below are all part of the standard .NET Framework Class Library @@ -46,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. @@ -152,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]; @@ -166,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>(); @@ -176,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 @@ -216,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) { @@ -254,7 +260,7 @@ on a new line! ""Wow!"", the masses cried"; int fooWhile = 0; while (fooWhile < 100) { - //Iterated 100 times, fooWhile 0->99 + // Iterated 100 times, fooWhile 0->99 fooWhile++; } @@ -273,25 +279,25 @@ on a new line! ""Wow!"", the masses cried"; } while (fooDoWhile < 100); - //for loop structure => for(<start_statement>; <conditional>; <step>) + // for loop structure => for(<start_statement>; <conditional>; <step>) for (int fooFor = 0; fooFor < 10; fooFor++) { - //Iterated 10 times, fooFor 0->9 + // Iterated 10 times, fooFor 0->9 } // For Each Loop // 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()) { - //Iterated over all the characters in the string + // Iterated over all the characters in the string } // 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. @@ -310,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: @@ -329,18 +335,27 @@ on a new line! ""Wow!"", the masses cried"; // Convert String To Integer // this will throw a FormatException on failure - int.Parse("123");//returns an integer version of "123" + int.Parse("123"); // returns an integer version of "123" - // try parse will default to type default on failure - // in this case: 0 + // 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 @@ -373,7 +388,10 @@ on a new line! ""Wow!"", the masses cried"; Console.Read(); } // End main method - // CONSOLE ENTRY A console application must have a main method as an entry point + // 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) { OtherInterestingFeatures(); @@ -404,13 +422,13 @@ on a new line! ""Wow!"", the masses cried"; ref int maxCount, // Pass by reference out int count) { - //the argument passed in as 'count' will hold the value of 15 outside of this function + // the argument passed in as 'count' will hold the value of 15 outside of this function count = 15; // out param must be assigned before control leaves the method } // 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, @@ -552,7 +570,7 @@ on a new line! ""Wow!"", the masses cried"; } // PARALLEL FRAMEWORK - // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx + // https://devblogs.microsoft.com/csharpfaq/parallel-programming-in-net-framework-4-getting-started/ var words = new List<string> {"dog", "cat", "horse", "pony"}; @@ -564,11 +582,11 @@ on a new line! ""Wow!"", the masses cried"; } ); - //Running this will produce different outputs - //since each thread finishes at different times. - //Some example outputs are: - //cat dog horse pony - //dog horse pony cat + // Running this will produce different outputs + // since each thread finishes at different times. + // Some example outputs are: + // cat dog horse pony + // dog horse pony cat // DYNAMIC OBJECTS (great for working with other languages) dynamic student = new ExpandoObject(); @@ -651,10 +669,10 @@ on a new line! ""Wow!"", the masses cried"; return ++count; } - // A delegate is a reference to a method + // A delegate is a reference to a method. // To reference the Increment method, - // first declare a delegate with the same signature - // ie. takes no arguments and returns an int + // first declare a delegate with the same signature, + // i.e. takes no arguments and returns an int public delegate int IncrementDelegate(); // An event can also be used to trigger delegates @@ -725,10 +743,10 @@ on a new line! ""Wow!"", the masses cried"; int _speed; // Everything is private by default: Only accessible from within this class. // can also use keyword private public string Name { get; set; } - + // Properties also have a special syntax for when you want a readonly property // that simply returns the result of an expression - public string LongName => Name + " " + _speed + " speed"; + public string LongName => Name + " " + _speed + " speed"; // Enum is a value type that consists of a set of named constants // It is really just mapping a name to a value (an int, unless specified otherwise). @@ -742,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 @@ -865,7 +883,7 @@ on a new line! ""Wow!"", the masses cried"; } } - //Method to display the attribute values of this Object. + // Method to display the attribute values of this Object. public virtual string Info() { return "Gear: " + Gear + @@ -960,7 +978,7 @@ on a new line! ""Wow!"", the masses cried"; /// <summary> /// Used to connect to DB for LinqToSql example. /// EntityFramework Code First is awesome (similar to Ruby's ActiveRecord, but bidirectional) - /// http://msdn.microsoft.com/en-us/data/jj193542.aspx + /// https://docs.microsoft.com/ef/ef6/modeling/code-first/workflows/new-database /// </summary> public class BikeRepository : DbContext { @@ -1069,7 +1087,7 @@ on a new line! ""Wow!"", the masses cried"; { private static bool LogException(Exception ex) { - /* log exception somewhere */ + // log exception somewhere return false; } @@ -1089,7 +1107,7 @@ on a new line! ""Wow!"", the masses cried"; // Spell failed return false; } - // Other exceptions, or MagicServiceException where Code is not 42 + // Other exceptions, or MagicServiceException where Code is not 42 catch(Exception ex) when (LogException(ex)) { // Execution never reaches this block @@ -1117,12 +1135,12 @@ on a new line! ""Wow!"", the masses cried"; [Obsolete("Use NewMethod instead", false)] public static void ObsoleteMethod() { - /* obsolete code */ + // obsolete code } public static void NewMethod() { - /* new code */ + // new code } public static void Main() @@ -1154,9 +1172,9 @@ namespace Learning.More.CSharp } } -//New C# 7 Feature -//Install Microsoft.Net.Compilers Latest from Nuget -//Install System.ValueTuple Latest from Nuget +// New C# 7 Feature +// Install Microsoft.Net.Compilers Latest from Nuget +// Install System.ValueTuple Latest from Nuget using System; namespace Csharp7 { @@ -1213,7 +1231,7 @@ namespace Csharp7 Console.WriteLine(tt.GetLastName()); } } - + // PATTERN MATCHING class PatternMatchingTest { @@ -1297,26 +1315,37 @@ 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 + * [C# language reference](https://docs.microsoft.com/dotnet/csharp/language-reference/) + * [Learn .NET](https://dotnet.microsoft.com/learn) + * [C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions) * [DotNetPerls](http://www.dotnetperls.com) * [C# in Depth](http://manning.com/skeet2) - * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) - * [LINQ](http://shop.oreilly.com/product/9780596519254.do) - * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx) - * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) - * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials) - * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Programming C# 5.0](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ Pocket Reference](http://shop.oreilly.com/product/9780596519254.do) * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) - * [C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx) + * [freeCodeCamp - C# Tutorial for Beginners](https://www.youtube.com/watch?v=GhQdlIFylQ8) + diff --git a/css.html.markdown b/css.html.markdown index 64dc097c..948b70ac 100644 --- a/css.html.markdown +++ b/css.html.markdown @@ -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 */ @@ -164,14 +169,14 @@ selector { max-width: 5in; /* inches */ /* Colors */ - color: #F6E; /* short hex format */ - color: #FF66EE; /* long hex format */ - color: tomato; /* a named color */ - color: rgb(255, 255, 255); /* as rgb values */ - color: rgb(10%, 20%, 50%); /* as rgb percentages */ - color: rgba(255, 0, 0, 0.3); /* as rgba values (CSS 3) Note: 0 <= a <= 1 */ - color: transparent; /* equivalent to setting the alpha to 0 */ - color: hsl(0, 100%, 50%); /* as hsl percentages (CSS 3) */ + color: #F6E; /* short hex format */ + color: #FF66EE; /* long hex format */ + color: tomato; /* a named color */ + color: rgb(255, 255, 255); /* as rgb values */ + color: rgb(10%, 20%, 50%); /* as rgb percentages */ + color: rgba(255, 0, 0, 0.3); /* as rgba values (CSS 3) Note: 0 <= a <= 1 */ + color: transparent; /* equivalent to setting the alpha to 0 */ + color: hsl(0, 100%, 50%); /* as hsl percentages (CSS 3) */ color: hsla(0, 100%, 50%, 0.3); /* as hsl percentages with alpha */ /* Borders */ @@ -179,7 +184,7 @@ selector { border-style:solid; border-color:red; /* similar to how background-color is set */ border: 5px solid red; /* this is a short hand approach for the same */ - border-radius:20px; /* this is a CSS3 property */ + border-radius:20px; /* this is a CSS3 property */ /* Images as backgrounds of elements */ background-image: url(/img-path/img.jpg); /* quotes inside url() optional */ @@ -317,6 +322,7 @@ a new feature. * [Dabblet](http://dabblet.com/) (CSS playground) * [Mozilla Developer Network's CSS documentation](https://developer.mozilla.org/en-US/docs/Web/CSS) (Tutorials and reference) * [Codrops' CSS Reference](http://tympanus.net/codrops/css_reference/) (Reference) +* [DevTips' CSS Basics](https://www.youtube.com/playlist?list=PLqGj3iMvMa4IOmy04kDxh_hqODMqoeeCy) (Tutorials) ## Further Reading diff --git a/cue.html.markdown b/cue.html.markdown new file mode 100644 index 00000000..a1ff0822 --- /dev/null +++ b/cue.html.markdown @@ -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/ diff --git a/d.html.markdown b/d.html.markdown index d2a57cae..93c08da2 100644 --- a/d.html.markdown +++ b/d.html.markdown @@ -212,6 +212,7 @@ found in the wonderful `std.algorithm` module! ```d import std.algorithm : map, filter, reduce; import std.range : iota; // builds an end-exclusive range +import std.stdio; void main() { // We want to print the sum of a list of squares of even ints diff --git a/dart.html.markdown b/dart.html.markdown index 07f755f7..ab3c07d2 100644 --- a/dart.html.markdown +++ b/dart.html.markdown @@ -2,127 +2,227 @@ language: dart filename: learndart.dart contributors: - - ["Joao Pedrosa", "https://github.com/jpedrosa/"] + - ["Joao Pedrosa", "https://github.com/jpedrosa/"] + - ["Vince Ramces Oliveros", "https://github.com/ram231"] --- -Dart is a newcomer into the realm of programming languages. -It borrows a lot from other mainstream languages, having as a goal not to deviate too much from -its JavaScript sibling. Like JavaScript, Dart aims for great browser integration. +**Dart** is a single threaded, general purpose programming language. +It borrows a lot from other mainstream languages. +It supports Streams, Futures(known as Promises in JavaScript), Generics, First-class functions(closures) and static type checking. +Dart can run in any platform such as Web, CLI, Desktop, Mobile and IoT devices. -Dart's most controversial feature must be its Optional Typing. +Dart's most controversial feature is its ~~Optional Typing~~ Static Type safety and [Sound Type checks](https://dart.dev/guides/language/sound-dart). ```dart import "dart:collection"; -import "dart:math" as DM; - -// Welcome to Learn Dart in 15 minutes. http://www.dartlang.org/ -// This is an executable tutorial. You can run it with Dart or on -// the Try Dart! site if you copy/paste it there. http://try.dartlang.org/ - -// Function declaration and method declaration look the same. Function -// declarations can be nested. The declaration takes the form of -// name() {} or name() => singleLineExpression; -// The fat arrow function declaration has an implicit return for the result of -// the expression. +import "dart:math" as math; + +/// Welcome to Learn Dart in 15 minutes. http://dart.dev/ +/// This is an executable tutorial. You can run it with Dart or on +/// the Try Dart! site if you copy/paste it there. http://dartpad.dev/ +/// You can also run Flutter in DartPad by click the `< > New Pad ` and choose Flutter + + +/// In Dart, Everything is an Object. +/// Every declaration of an object is an instance of Null and +/// Null is also an object. + + +/// 3 Types of comments in dart +// Single line comment +/** +* Multi-line comment +* Can comment more than 2 lines +*/ +/// Code doc comment +/// It uses markdown syntax to generate code docs when making an API. +/// Code doc comment is the recommended choice when documenting your APIs, classes and methods. + +/// 4 types of variable declaration. +/// Constants are variables that are immutable cannot be change or altered. +/// `const` in dart should practice SCREAMING_SNAKE_CASE name declaration. +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 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 +var mutableValue = "Variable string"; +mutableValue = "this is valid"; +mutableValue = false; // Error. + +/// `dynamic` is another variable declaration in which the type is not evaluated by the dart static type checking. +/// It can change its value and data type. +/// Some dartisans uses dynamic cautiously as it cannot keep track of its data type. so use it at your own risk +dynamic dynamicValue = "I'm a string"; +dynamicValue = false; // false + + +/// Functions can be declared in a global space +/// Function declaration and method declaration look the same. Function +/// declarations can be nested. The declaration takes the form of +/// name() {} or name() => singleLineExpression; +/// The fat arrow function declaration can be an implicit or +/// explicit return for the result of the expression. +/// Dart will execute a function called `main()` anywhere in the dart project. +/// example1() { nested1() { nested2() => print("Example1 nested 1 nested 2"); nested2(); } + nested1(); } -// Anonymous functions don't include a name. +/// Anonymous functions don't include a name example2() { - nested1(fn) { + //// Explicit return type. + nested1(void Function() fn) { fn(); } nested1(() => print("Example2 nested 1")); } -// When a function parameter is declared, the declaration can include the -// number of parameters the function takes by specifying the names of the -// parameters it takes. +/// When a function parameter is declared, the declaration can include the +/// number of parameters the function takes by explicitly specifying the names of the +/// parameters it takes. example3() { - planA(fn(informSomething)) { + planA(fn(String informSomething)) { fn("Example3 plan A"); } - planB(fn) { // Or don't declare number of parameters. + planB(fn) { + // Or don't declare number of parameters. fn("Example3 plan B"); } + planA((s) => print(s)); planB((s) => print(s)); } -// Functions have closure access to outer variables. +/// Functions have closure access to outer variables. +/// Dart will infer types when the variable has a value of something. +/// In this example dart knows that this variable is a String. var example4Something = "Example4 nested 1"; example4() { nested1(fn(informSomething)) { fn(example4Something); } + nested1((s) => print(s)); } -// Class declaration with a sayIt method, which also has closure access -// to the outer variable as though it were a function as seen before. +/// Class declaration with a sayIt method, which also has closure access +/// to the outer variable as though it were a function as seen before. var example5method = "Example5 sayIt"; + class Example5Class { sayIt() { print(example5method); } } + example5() { - // Create an anonymous instance of the Example5Class and call the sayIt - // method on it. + /// Create an anonymous instance of the Example5Class and call the sayIt + /// method on it. + /// the `new` keyword is optional in Dart. new Example5Class().sayIt(); } -// Class declaration takes the form of class name { [classBody] }. -// Where classBody can include instance methods and variables, but also -// class methods and variables. +/// Class declaration takes the form of class name { [classBody] }. +/// Where classBody can include instance methods and variables, but also +/// class methods and variables. class Example6Class { var instanceVariable = "Example6 instance variable"; sayIt() { print(instanceVariable); } } + example6() { - new Example6Class().sayIt(); + Example6Class().sayIt(); } -// Class methods and variables are declared with "static" terms. +/// Class methods and variables are declared with "static" terms. class Example7Class { static var classVariable = "Example7 class variable"; static sayItFromClass() { print(classVariable); } + sayItFromInstance() { print(classVariable); } } + example7() { Example7Class.sayItFromClass(); new Example7Class().sayItFromInstance(); } -// Literals are great, but there's a restriction for what literals can be -// outside of function/method bodies. Literals on the outer scope of class -// or outside of class have to be constant. Strings and numbers are constant -// by default. But arrays and maps are not. They can be made constant by -// declaring them "const". -var example8Array = const ["Example8 const array"], - example8Map = const {"someKey": "Example8 const map"}; +/// Dart supports Generics. +/// Generics refers to the technique of writing the code for a class +/// without specifying the data type(s) that the class works on. +/// Source: https://stackoverflow.com/questions/4560890/what-are-generics-in-c + +/// Type `T` refers to any type that has been instantiated +/// you can call whatever you want +/// Programmers uses the convention in the following +/// T - Type(used for class and primitype types) +/// E - Element(used for List, Set, or Iterable) +/// K,V - Key Value(used for Map) +class GenericExample<T>{ + void printType(){ + print("$T") + } + // methods can also have generics + genericMethod<M>(){ + print("class:$T, method: $M"); + } +} + + +/// List are similar to arrays but list is a child of Iterable<E> +/// Therefore Maps, List, LinkedList are all child of Iterable<E> to be able to loop using the keyword `for` +/// Important things to remember: +/// () - Iterable<E> +/// [] - List<E> +/// {} - Map<K,V> + + +/// List are great, but there's a restriction for what List can be +/// outside of function/method bodies. List on the outer scope of class +/// or outside of class have to be constant. Strings and numbers are constant +/// by default. But arrays and maps are not. They can be made constant by +/// declaring them "const". Kind of similar to Javascript's Object.freeze() +const example8List = ["Example8 const array"]; +const example8Map = {"someKey": "Example8 const map"}; +/// Declare List or Maps as Objects. + List<String> explicitList = new List<String>(); + Map<String,dynamic> explicitMaps = new Map<String,dynamic>(); + + explicitList.add("SomeArray"); example8() { - print(example8Array[0]); print(example8Map["someKey"]); + print(explicitList[0]); } -// Loops in Dart take the form of standard for () {} or while () {} loops, -// slightly more modern for (.. in ..) {}, or functional callbacks with many -// supported features, starting with forEach. +/// Assigning a list from one variable to another will not be the same result. +/// Because dart is pass-reference-by-value. +/// So when you assign an existing list to a new variable. +/// Instead of List, it becomes an Iterable +var iterableExplicitList = explicitList; +print(iterableExplicitList) // ("SomeArray"); "[]" becomes "()" +var newExplicitLists = explicitList.toList() // Converts Iterable<E> to List<E> + +/// Loops in Dart take the form of standard for () {} or while () {} loops, +/// slightly more modern for (.. in ..) {}, or functional callbacks with many +/// supported features, starting with forEach,map and where. var example9Array = const ["a", "b"]; example9() { - for (var i = 0; i < example9Array.length; i++) { + for (int i = 0; i < example9Array.length; i++) { print("Example9 for loop '${example9Array[i]}'"); } var i = 0; @@ -130,13 +230,15 @@ example9() { print("Example9 while loop '${example9Array[i]}'"); i++; } - for (var e in example9Array) { + for (final e in example9Array) { print("Example9 for-in loop '${e}'"); } + example9Array.forEach((e) => print("Example9 forEach loop '${e}'")); + } -// To loop over the characters of a string or to extract a substring. +/// To loop over the characters of a string or to extract a substring. var example10String = "ab"; example10() { for (var i = 0; i < example10String.length; i++) { @@ -147,14 +249,37 @@ example10() { } } -// Int and double are the two supported number formats. +/// `int`, `double` and `num` are the three supported number formats. +/// `num` can be either `int` or `double`. +/// `int` and `double` are children of type `num` example11() { var i = 1 + 320, d = 3.2 + 0.01; + num myNumDouble = 2.2; + num myNumInt = 2; + int myInt = 1; + double myDouble = 0; // Dart will add decimal prefix, becomes 0.0; + myNumDouble = myInt; // valid + myNumDouble = myDouble; //valid + myNumDouble = myNumInt; //valid + + myNumInt = myInt; // valid + myNumInt = myDouble; // valid + myNumInt = myNumDouble; // valid + + myInt = myNumDouble; //Error + myInt = myDouble; //Error + myInt = myNumInt; //valid + + myDouble = myInt; //error + myDouble = myNumInt; //valid + myDouble = myNumDouble; //valid + print("Example11 int ${i}"); print("Example11 double ${d}"); + } -// DateTime provides date/time arithmetic. +/// DateTime provides date/time arithmetic. example12() { var now = new DateTime.now(); print("Example12 now '${now}'"); @@ -162,7 +287,7 @@ example12() { print("Example12 tomorrow '${now}'"); } -// Regular expressions are supported. +/// Regular expressions are supported. example13() { var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$"); match(s) { @@ -172,11 +297,12 @@ example13() { print("Example13 regexp doesn't match '${s}'"); } } + match(s1); match(s2); } -// Boolean expressions support implicit conversions and dynamic type +/// Boolean expressions support implicit conversions and dynamic type example14() { var a = true; if (a) { @@ -186,11 +312,11 @@ example14() { if (a) { print("true, a is $a"); } else { - print("false, a is $a"); // runs here + print("false, a is $a"); /// runs here } - // dynamic typed null can be convert to bool - var b;// b is dynamic type + /// dynamic typed null can be convert to bool + var b;/// b is dynamic type b = "abc"; try { if (b) { @@ -199,35 +325,35 @@ example14() { print("false, b is $b"); } } catch (e) { - print("error, b is $b"); // this could be run but got error + print("error, b is $b"); /// this could be run but got error } b = null; if (b) { print("true, b is $b"); } else { - print("false, b is $b"); // runs here + print("false, b is $b"); /// runs here } - // statically typed null can not be convert to bool + /// statically typed null can not be convert to bool var c = "abc"; c = null; - // complie failed - // if (c) { - // print("true, c is $c"); - // } else { - // print("false, c is $c"); - // } + /// complie failed + /// if (c) { + /// print("true, c is $c"); + /// } else { + /// print("false, c is $c"); + /// } } -// try/catch/finally and throw are used for exception handling. -// throw takes any object as parameter; +/// try/catch/finally and throw are used for exception handling. +/// throw takes any object as parameter; example15() { try { try { throw "Some unexpected error."; } catch (e) { print("Example15 an exception: '${e}'"); - throw e; // Re-throw + throw e; /// Re-throw } } catch (e) { print("Example15 catch exception being re-thrown: '${e}'"); @@ -236,18 +362,21 @@ example15() { } } -// To be efficient when creating a long string dynamically, use -// StringBuffer. Or you could join a string array. +/// To be efficient when creating a long string dynamically, use +/// StringBuffer. Or you could join a string array. example16() { var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e; - for (e in a) { sb.write(e); } + for (e in a) { + sb.write(e); + } print("Example16 dynamic string created with " - "StringBuffer '${sb.toString()}'"); + "StringBuffer '${sb.toString()}'"); print("Example16 join string array '${a.join()}'"); } -// Strings can be concatenated by just having string literals next to -// one another with no further operator needed. +/// Strings can be concatenated by just having string List next to +/// one another with no further operator needed. + example17() { print("Example17 " "concatenate " @@ -255,44 +384,44 @@ example17() { "just like that"); } -// Strings have single-quote or double-quote for delimiters with no -// actual difference between the two. The given flexibility can be good -// to avoid the need to escape content that matches the delimiter being -// used. For example, double-quotes of HTML attributes if the string -// contains HTML content. +/// Strings have single-quote or double-quote for delimiters with no +/// actual difference between the two. The given flexibility can be good +/// to avoid the need to escape content that matches the delimiter being +/// used. For example, double-quotes of HTML attributes if the string +/// contains HTML content. example18() { print('Example18 <a href="etc">' "Don't can't I'm Etc" '</a>'); } -// Strings with triple single-quotes or triple double-quotes span -// multiple lines and include line delimiters. +/// Strings with triple single-quotes or triple double-quotes span +/// multiple lines and include line delimiters. example19() { print('''Example19 <a href="etc"> Example19 Don't can't I'm Etc Example19 </a>'''); } -// Strings have the nice interpolation feature with the $ character. -// With $ { [expression] }, the return of the expression is interpolated. -// $ followed by a variable name interpolates the content of that variable. -// $ can be escaped like so \$ to just add it to the string instead. +/// Strings have the nice interpolation feature with the $ character. +/// With $ { [expression] }, the return of the expression is interpolated. +/// $ followed by a variable name interpolates the content of that variable. +/// $ can be escaped like so \$ to just add it to the string instead. example20() { var s1 = "'\${s}'", s2 = "'\$s'"; print("Example20 \$ interpolation ${s1} or $s2 works."); } -// Optional types allow for the annotation of APIs and come to the aid of -// IDEs so the IDEs can better refactor, auto-complete and check for -// errors. So far we haven't declared any types and the programs have -// worked just fine. In fact, types are disregarded during runtime. -// Types can even be wrong and the program will still be given the -// benefit of the doubt and be run as though the types didn't matter. -// There's a runtime parameter that checks for type errors which is -// the checked mode, which is said to be useful during development time, -// but which is also slower because of the extra checking and is thus -// avoided during deployment runtime. +/// Optional types allow for the annotation of APIs and come to the aid of +/// IDEs so the IDEs can better refactor, auto-complete and check for +/// errors. So far we haven't declared any types and the programs have +/// worked just fine. In fact, types are disregarded during runtime. +/// Types can even be wrong and the program will still be given the +/// benefit of the doubt and be run as though the types didn't matter. +/// There's a runtime parameter that checks for type errors which is +/// the checked mode, which is said to be useful during development time, +/// but which is also slower because of the extra checking and is thus +/// avoided during deployment runtime. class Example21 { List<String> _names; Example21() { @@ -302,11 +431,13 @@ class Example21 { set names(List<String> list) { _names = list; } + int get length => _names.length; void add(String name) { _names.add(name); } } + void example21() { Example21 o = new Example21(); o.add("c"); @@ -315,46 +446,50 @@ void example21() { print("Example21 names '${o.names}' and length '${o.length}'"); } -// Class inheritance takes the form of class name extends AnotherClassName {}. +/// Class inheritance takes the form of class name extends AnotherClassName {}. class Example22A { var _name = "Some Name!"; get name => _name; } + class Example22B extends Example22A {} + example22() { var o = new Example22B(); print("Example22 class inheritance '${o.name}'"); } -// Class mixin is also available, and takes the form of -// class name extends SomeClass with AnotherClassName {}. -// It's necessary to extend some class to be able to mixin another one. -// The template class of mixin cannot at the moment have a constructor. -// Mixin is mostly used to share methods with distant classes, so the -// single inheritance doesn't get in the way of reusable code. -// Mixins follow the "with" statement during the class declaration. +/// Class mixin is also available, and takes the form of +/// class name extends SomeClass with AnotherClassName {}. +/// It's necessary to extend some class to be able to mixin another one. +/// The template class of mixin cannot at the moment have a constructor. +/// Mixin is mostly used to share methods with distant classes, so the +/// single inheritance doesn't get in the way of reusable code. +/// Mixins follow the "with" statement during the class declaration. class Example23A {} + class Example23Utils { addTwo(n1, n2) { return n1 + n2; } } + class Example23B extends Example23A with Example23Utils { addThree(n1, n2, n3) { return addTwo(n1, n2) + n3; } } + example23() { - var o = new Example23B(), r1 = o.addThree(1, 2, 3), - r2 = o.addTwo(1, 2); + var o = new Example23B(), r1 = o.addThree(1, 2, 3), r2 = o.addTwo(1, 2); print("Example23 addThree(1, 2, 3) results in '${r1}'"); print("Example23 addTwo(1, 2) results in '${r2}'"); } -// The Class constructor method uses the same name of the class and -// takes the form of SomeClass() : super() {}, where the ": super()" -// part is optional and it's used to delegate constant parameters to the -// super-parent's constructor. +/// The Class constructor method uses the same name of the class and +/// takes the form of SomeClass() : super() {}, where the ": super()" +/// part is optional and it's used to delegate constant parameters to the +/// super-parent's constructor. class Example24A { var _value; Example24A({value: "someValue"}) { @@ -362,71 +497,76 @@ class Example24A { } get value => _value; } + class Example24B extends Example24A { Example24B({value: "someOtherValue"}) : super(value: value); } + example24() { - var o1 = new Example24B(), - o2 = new Example24B(value: "evenMore"); + var o1 = new Example24B(), o2 = new Example24B(value: "evenMore"); print("Example24 calling super during constructor '${o1.value}'"); print("Example24 calling super during constructor '${o2.value}'"); } -// There's a shortcut to set constructor parameters in case of simpler classes. -// Just use the this.parameterName prefix and it will set the parameter on -// an instance variable of same name. +/// There's a shortcut to set constructor parameters in case of simpler classes. +/// Just use the this.parameterName prefix and it will set the parameter on +/// an instance variable of same name. class Example25 { var value, anotherValue; Example25({this.value, this.anotherValue}); } + example25() { var o = new Example25(value: "a", anotherValue: "b"); print("Example25 shortcut for constructor '${o.value}' and " - "'${o.anotherValue}'"); + "'${o.anotherValue}'"); } -// Named parameters are available when declared between {}. -// Parameter order can be optional when declared between {}. -// Parameters can be made optional when declared between []. +/// Named parameters are available when declared between {}. +/// Parameter order can be optional when declared between {}. +/// Parameters can be made optional when declared between []. example26() { var _name, _surname, _email; setConfig1({name, surname}) { _name = name; _surname = surname; } + setConfig2(name, [surname, email]) { _name = name; _surname = surname; _email = email; } + setConfig1(surname: "Doe", name: "John"); print("Example26 name '${_name}', surname '${_surname}', " - "email '${_email}'"); + "email '${_email}'"); setConfig2("Mary", "Jane"); print("Example26 name '${_name}', surname '${_surname}', " - "email '${_email}'"); + "email '${_email}'"); } -// Variables declared with final can only be set once. -// In case of classes, final instance variables can be set via constant -// constructor parameter. +/// Variables declared with final can only be set once. +/// In case of classes, final instance variables can be set via constant +/// constructor parameter. class Example27 { final color1, color2; - // A little flexibility to set final instance variables with syntax - // that follows the : + /// A little flexibility to set final instance variables with syntax + /// that follows the : Example27({this.color1, color2}) : color2 = color2; } + example27() { final color = "orange", o = new Example27(color1: "lilac", color2: "white"); print("Example27 color is '${color}'"); print("Example27 color is '${o.color1}' and '${o.color2}'"); } -// To import a library, use import "libraryPath" or if it's a core library, -// import "dart:libraryName". There's also the "pub" package management with -// its own convention of import "package:packageName". -// See import "dart:collection"; at the top. Imports must come before -// other code declarations. IterableBase comes from dart:collection. +/// To import a library, use import "libraryPath" or if it's a core library, +/// import "dart:libraryName". There's also the "pub" package management with +/// its own convention of import "package:packageName". +/// See import "dart:collection"; at the top. Imports must come before +/// other code declarations. IterableBase comes from dart:collection. class Example28 extends IterableBase { var names; Example28() { @@ -434,16 +574,17 @@ class Example28 extends IterableBase { } get iterator => names.iterator; } + example28() { var o = new Example28(); o.forEach((name) => print("Example28 '${name}'")); } -// For control flow we have: -// * standard switch with must break statements -// * if-else if-else and ternary ..?..:.. operator -// * closures and anonymous functions -// * break, continue and return statements +/// For control flow we have: +/// * standard switch with must break statements +/// * if-else if-else and ternary ..?..:.. operator +/// * closures and anonymous functions +/// * break, continue and return statements example29() { var v = true ? 30 : 60; switch (v) { @@ -459,10 +600,12 @@ example29() { callItForMe(fn()) { return fn(); } + rand() { v = new DM.Random().nextInt(50); return v; } + while (true) { print("Example29 callItForMe(rand) '${callItForMe(rand)}'"); if (v != 30) { @@ -470,17 +613,21 @@ example29() { } else { continue; } - // Never gets here. + /// Never gets here. } } -// Parse int, convert double to int, or just keep int when dividing numbers -// by using the ~/ operation. Let's play a guess game too. +/// Parse int, convert double to int, or just keep int when dividing numbers +/// by using the ~/ operation. Let's play a guess game too. example30() { - var gn, tooHigh = false, - n, n2 = (2.0).toInt(), top = int.parse("123") ~/ n2, bottom = 0; + var gn, + tooHigh = false, + n, + n2 = (2.0).toInt(), + top = int.parse("123") ~/ n2, + bottom = 0; top = top ~/ 6; - gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive + gn = new DM.Random().nextInt(top + 1); /// +1 because nextInt top is exclusive print("Example30 Guess a number between 0 and ${top}"); guessNumber(i) { if (n == gn) { @@ -488,10 +635,11 @@ example30() { } else { tooHigh = n > gn; print("Example30 Number ${n} is too " - "${tooHigh ? 'high' : 'low'}. Try again"); + "${tooHigh ? 'high' : 'low'}. Try again"); } return n == gn; } + n = (top - bottom) ~/ 2; while (!guessNumber(n)) { if (tooHigh) { @@ -503,19 +651,64 @@ example30() { } } -// Programs have only one entry point in the main function. -// Nothing is expected to be executed on the outer scope before a program -// starts running with what's in its main function. -// This helps with faster loading and even lazily loading of just what -// the program needs to startup with. +/// Optional Positional Parameter: +/// parameter will be disclosed with square bracket [ ] & square bracketed parameter are optional. +example31() { + findVolume31(int length, int breath, [int height]) { + print('length = $length, breath = $breath, height = $height'); + } + + findVolume31(10,20,30); //valid + findVolume31(10,20); //also valid +} + +/// Optional Named Parameter: +/// parameter will be disclosed with curly bracket { } +/// curly bracketed parameter are optional. +/// have to use parameter name to assign a value which separated with colan : +/// in curly bracketed parameter order does not matter +/// these type parameter help us to avoid confusion while passing value for a function which has many parameter. +example32() { + findVolume32(int length, int breath, {int height}) { + print('length = $length, breath = $breath, height = $height'); + } + + findVolume32(10,20,height:30);//valid & we can see the parameter name is mentioned here. + findVolume32(10,20);//also valid +} + +/// Optional Default Parameter: +/// same like optional named parameter in addition we can assign default value for this parameter. +/// which means no value is passed this default value will be taken. +example33() { + findVolume33(int length, int breath, {int height=10}) { + print('length = $length, breath = $breath, height = $height'); + } + + findVolume33(10,20,height:30);//valid + findVolume33(10,20);//valid +} + +/// Dart has also added feature such as Null aware operators +var isBool = true; +var hasString = isBool ?? "default String"; + +/// Programs have only one entry point in the main function. +/// Nothing is expected to be executed on the outer scope before a program +/// starts running with what's in its main function. +/// This helps with faster loading and even lazily loading of just what +/// the program needs to startup with. main() { print("Learn Dart in 15 minutes!"); - [example1, example2, example3, example4, example5, example6, example7, - example8, example9, example10, example11, example12, example13, example14, - example15, example16, example17, example18, example19, example20, - example21, example22, example23, example24, example25, example26, - example27, example28, example29, example30 - ].forEach((ef) => ef()); + [ + example1, example2, example3, example4, example5, + example6, example7, example8, example9, example10, + example11, example12, example13, example14, example15, + example16, example17, example18, example19, example20, + example21, example22, example23, example24, example25, + example26, example27, example28, example29, + example30 // Adding this comment stops the dart formatter from putting all items on a new line + ].forEach((ef) => ef()); } ``` @@ -523,9 +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) diff --git a/de-de/asciidoc-de.html.markdown b/de-de/asciidoc-de.html.markdown index e3f64a00..d0a62c66 100644 --- a/de-de/asciidoc-de.html.markdown +++ b/de-de/asciidoc-de.html.markdown @@ -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 diff --git a/de-de/bash-de.html.markdown b/de-de/bash-de.html.markdown index 7a0db157..12da1df8 100644 --- a/de-de/bash-de.html.markdown +++ b/de-de/bash-de.html.markdown @@ -10,7 +10,7 @@ translators: filename: LearnBash-de.sh --- -Bash ist der Name der Unix-Shell, die als Shell des GNU-Betriebssystems und auch als Standard-Shell von Linux und Mac OS X ausgeliefert wurde. +Bash ist der Name der Unix-Shell, die als Shell des GNU-Betriebssystems und auch als Standard-Shell von Linux und macOS ausgeliefert wurde. Beinahe alle der folgenden Beispiele können als Teile eines Shell-Skripts oder direkt in der Shell ausgeführt werden. [Weitere Informationen \(Englisch\)](http://www.gnu.org/software/bash/manual/bashref.html) @@ -157,7 +157,7 @@ echo "#helloworld" | cat > output.out echo "#helloworld" | tee output.out >/dev/null # Löschen der Hilfsdateien von oberhalb, mit Anzeige der Dateinamen -# (mit '-i' für "interactive" erfolgt für jede Date eine Rückfrage) +# (mit '-i' für "interactive" erfolgt für jede Datei eine Rückfrage) rm -v output.out error.err output-and-error.log # Die Ausgabe von Befehlen kann mit Hilfe von $( ) in anderen Befehlen verwendet weden: @@ -217,7 +217,7 @@ done function foo () { echo "Argumente funktionieren wie bei skripts: $@" - echo Und: $1 $2..." + echo "Und: $1 $2..." echo "Dies ist eine Funktion" return 0 } diff --git a/de-de/bc.html.markdown b/de-de/bc.html.markdown new file mode 100644 index 00000000..49a2878d --- /dev/null +++ b/de-de/bc.html.markdown @@ -0,0 +1,102 @@ +--- +language: bc +contributors: + - ["caminsha", "https://github.com/caminsha"] +filename: learnbc-de.bc +lang: de-de +--- +```c +/* Das is ein mehr- +zeiliger Kommentar */ +# Das ist ein (einzeiliger) Kommentar (in GNU bc). + + /*1. Variablen und Kontrollstrukturen*/ +num = 45 /* Alle Variablen speichern nur Doubles und es ist + nicht möglich String-Konstanten direkt zu speichern */ +num = 45; /* Es kann nach jedem Statement ein optionales Semikolon + hinzugefügt werden */ +/* Blöcke werden mit den Operatoren {} (ähnlich wie in C) bezeichnet */ +while(num < 50) { + num += 1 /* äquivalent zu num=num+1. + a = a Op b ist äquivalent zu a Op= b*/ +} +/* Ausserdem gibt es ++ (Inkrement) und -- (Dekrement) Operatoren */ +/* Es gibt 3 spezielle Variablen: +scale: definiert die Anzahl Nachkommastellen +ibase: definiert die Basis der Eingabe +obase: definiert die Basis der Ausgabe*/ +/*Wenn-Bedingungen:*/ +hour = read() /*Eingabe einer Zahl*/ + +if(hour < 12) { /*Operatoren sind genau wie in C*/ + print "Guten Morgen\n" /*"print" Gibt Strings oder Variablen + mit einem Komma separiert aus.*/ +} else if(hour == 12) { + print "Hallo\n" + /* Escape-Sequenzen starten mite einem \ in einem String. + Um Escape-Sequenzen klarer zu machen, ist hier eine vereinfachte + Liste, welche in bc funktioneren.: + \b: Backspace + \c: carriage return + \n: Zeilenumbruch + \t: Tab + \\: Backslash*/ +} else { + /* Standardmässig sind Variablen global. */ + thisIsGlobal = 5 + /*Variablen können lokal gemacht werden. Benutze das Schlüsselwort "auto" + in einer Funktion.*/ +} + +/* Jede Variable hat als Voreinstellung den Wert 0. */ +num = blankVariable /*num wurde auf 0 gesetzt.*/ + +/*Wie in C ist nur 0 falsch.*/ +if(!num) {print "false\n"} + +/*Im Gegensatz zu C hat bc den Ternäroperator ?: nicht. Zum Beispiel +führt dieser Codeblok zu einem Fehler: +a = (num) ? 1 : 0 +Jedoch kann dies simuliert werden:*/ +a = (num) && (1) || (0) /*&& ist das UND, || ist das ODER*/ + +/*For-Schleifen*/ +num = 0 +for(i = 1; i <= 100; i++) {/*Gleich wie die For-Schleife in C*/ + num += i +} + + /*2.Funktionen und Arrays*/ +define fac(n) { /*Definiere eine Funktion mit define*/ + if(n == 1 || n == 0) { + return 1 /*Gebe einen Wert zurück*/ + } + return n * fac(n - 1) /*Rekursion ist möglich*/ +} + +/*Closures und anonyme Funktionen sind nicht möglich */ + +num = fac(4) /*24*/ + +/*Dies ist ein Beispiel von lokalen Variabeln.*/ +define x(n) { + auto x + x = 1 + return n + x +} +x(3) /*4*/ +print x /*Es stellt sich heraus, dass x ausserhalb der Funktion nicht + zugänglich ist.*/ +/*Arrays sind äquivalent zu C Arrays.*/ +for(i = 0; i <= 3; i++) { + a[i] = 1 +} +/*Greife wie folgt darauf zu:*/ +print a[0], " ", a[1], " ", a[2], " ", a[3], "\n" +quit /* Füge diese Codezeile hinzu, um sicherzustellen, dass +das Programm beendet. Diese Codezeile ist optional.*/ +``` +Viel Spass mit diesem einfachen Rechner! (Oder dieser Programmiersprache, um exakt zu sein.) + +Das ganze Programm wurde in GNU bc geschrieben. Um es auszuführen, benutze ```bc learnbc.bc```. + diff --git a/de-de/brainfuck-de.html.markdown b/de-de/brainfuck-de.html.markdown index dd62dd67..09f01cd2 100644 --- a/de-de/brainfuck-de.html.markdown +++ b/de-de/brainfuck-de.html.markdown @@ -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 --- diff --git a/de-de/c++-de.html.markdown b/de-de/c++-de.html.markdown index cef7514b..cca54c30 100644 --- a/de-de/c++-de.html.markdown +++ b/de-de/c++-de.html.markdown @@ -1,5 +1,5 @@ --- -language: c++ +language: C++ filename: learncpp-de.cpp contributors: - ["Steven Basart", "http://github.com/xksteven"] @@ -9,6 +9,7 @@ contributors: - ["Ankush Goyal", "http://github.com/ankushg07"] - ["Jatin Dhankhar", "https://github.com/jatindhankhar"] - ["Maximilian Sonnenburg", "https://github.com/LamdaLamdaLamda"] + - ["caminsha", "https://github.com/caminsha"] lang: de-de --- @@ -22,9 +23,9 @@ entworfen wurde um, - Objektorientierung zu unterstützen - generische Programmierung zu unterstützen -Durch seinen Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein. +Durch seine Syntax kann sie durchaus schwieriger und komplexer als neuere Sprachen sein. -Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welches direkt vom Prozessor ausgeführt +Sie ist weit verbreitet, weil sie in Maschinen-Code kompiliert, welcher direkt vom Prozessor ausgeführt werden kann und somit eine strikte Kontrolle über die Hardware bietet und gleichzeitig High-Level-Features wie generics, exceptions und Klassen enthält. @@ -36,7 +37,7 @@ weitverbreitesten Programmiersprachen. // Vergleich zu C ////////////////// -// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich den +// C ist fast eine Untermenge von C++ und teilt sich grundsätzlich die // Syntax für Variablen Deklarationen, primitiven Typen und Funktionen. // Wie in C ist der Programmeinsprungpunkt eine Funktion, welche "main" genannt wird und @@ -137,7 +138,7 @@ void invalidDeclaration(int a = 1, int b) // Fehler! ///////////// -// Namespaces (Namesräume) +// Namespaces (Namensräume) ///////////// // Namespaces stellen einen getrennten Gültigkeitsbereich für Variablen, @@ -169,7 +170,7 @@ void foo() int main() { - // Fügt all Symbole aus dem namespace Second in den aktuellen Gültigkeitsbereich (scope). + // Fügt alle Symbole aus dem namespace Second in den aktuellen Gültigkeitsbereich (scope). // "foo()" wird nun nicht länger funktionieren, da es nun doppeldeutig ist, ob foo aus // dem namespace foo oder darüberliegenden aufgerufen wird. using namespace Second; @@ -283,7 +284,7 @@ string retVal = tempObjectFun(); // für Details). Wie in diesem Code: foo(bar(tempObjectFun())) -// Nehmen wir an foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben, +// Nehmen wir an, foo und bar existieren. Das Objekt wird von "tempObjectFun" zurückgegeben, // wird an bar übergeben und ist zerstört bevor foo aufgerufen wird. // Zurück zu Referenzen. Die Annahme, dass die "am Ende des Ausdrucks" Regel gültig ist, @@ -335,7 +336,7 @@ ECarTypes GetPreferredCarType() return ECarTypes::Hatchback; } -// Mit C++11 existiert eine einfache Möglichkeit einem Typ dem Enum zu zuweisen. Dies +// Mit C++11 existiert eine einfache Möglichkeit einem Typ dem Enum zuzuweisen. Dies // kann durchaus sinnvoll bei der Serialisierung von Daten sein, oder bei der Konvertierung // zwischen Typen bzw. Konstanten. enum ECarTypes : uint8_t @@ -574,7 +575,7 @@ int main () // Templates in C++ werden in erster Linie dafür verwendet generisch zu programmieren. // Sie unterstützen explizite und partielle Spezialisierung und darüber hinaus können // sie für funktionale Klassen verwendet werden. -// Tatsächlich bilden templates die Turing-Vollständigkeit +// Tatsächlich bilden Templates die Turing-Vollständigkeit // (universelle Programmierbarkeit) ab. @@ -588,12 +589,12 @@ public: void insert(const T&) { ... } }; -// Während der Kompilierung generiert der Compiler Kopien für jedes template, wobei +// Während der Kompilierung generiert der Compiler Kopien für jedes Template, wobei // hierbei die Parameter substituiert werden. Somit muss bei jedem Aufruf die gesamte // Definition der Klasse zur Verfügung stehen. Aus diesem Grund wird ein Template // komplett im header definiert. -// Erzeugung einer Template-Klasse auf dem stack: +// Erzeugung einer Template-Klasse auf dem Stack: Box<int> intBox; // eine der zu erwartenden Verwendungen: @@ -612,7 +613,7 @@ boxOfBox.insert(intBox); // sind fast identisch hinsichtlich der Funktionalität. Weitere // Informationen auf: http://en.wikipedia.org/wiki/Typename -// Eine template-Funktion: +// Eine Template-Funktion: template<class T> void barkThreeTimes(const T& input) { @@ -622,7 +623,7 @@ void barkThreeTimes(const T& input) } // Hierbei ist zu beachten, dass an dieser Stelle nichts über den Typen des Parameters -// definiert wurde. Der Kompiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen +// definiert wurde. Der Compiler wird bei jedem Aufruf bzw. jeder Erzeugung den Typen // prüfen. Somit funktioniert die zuvor definierte Funktion für jeden Typ 'T', die die // const Methode 'bark' implementiert hat. @@ -637,10 +638,10 @@ void printMessage() cout << "Learn C++ in " << Y << " minutes!" << endl; } -// Des Weiteren können templates aus Effizienzgründen genauer spezifiziert werden. -// Selbstverständlich sind reale-Problemen, welche genauer spezifiziert werden nicht +// Des Weiteren können Templates aus Effizienzgründen genauer spezifiziert werden. +// Selbstverständlich sind reale Probleme, welche genauer spezifiziert werden, nicht // derart trivial. Auch wenn alle Parameter explizit definiert wurden, muss die -// Funktion oder Klasse als template deklariert werden. +// Funktion oder Klasse als Template deklariert werden. template<> void printMessage<10>() { @@ -818,9 +819,9 @@ void doSomethingWithAFile(const std::string& filename) // Container ///////////////////// -// Die Container der Standard template Bibliothek beinhaltet einige vordefinierter templates. +// Die Container der Standard template Bibliothek beinhaltet einige vordefinierte Templates. // Diese verwalten die Speicherbereiche für die eigenen Elemente und stellen Member-Funktionen -// für den Zugriff und die Maniplulation bereit. +// für den Zugriff und die Manipulation bereit. // Beispielhafte Container: @@ -876,7 +877,7 @@ for(it=ST.begin();it<ST.end();it++) // 10 // 30 -// Zum leeren des gesamten Container wird die Methode +// Zum leeren des gesamten Containers wird die Methode // Container._name.clear() verwendet. ST.clear(); cout << ST.size(); // Ausgabe der Set-Größe @@ -948,11 +949,11 @@ fooMap.find(Foo(1)); // Wahr // Lambda Ausdrücke (C++11 und höher) /////////////////////////////////////// -// Lambdas sind eine gängige Methodik um anonyme Funktionen an dem +// Lambdas sind eine gängige Methodik, um anonyme Funktionen an dem // Ort der Verwendung zu definieren. Darüber hinaus auch bei der // Verwendung von Funktionen als Argument einer Funktion. -// Nehmen wir an es soll ein Vektor von "pairs" (Paaren) mithilfe +// Nehmen wir an, es soll ein Vektor von "pairs" (Paaren) mithilfe // des zweiten Werts des "pairs" sortiert werden. vector<pair<int, int> > tester; @@ -966,7 +967,7 @@ sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, return lhs.second < rhs.second; }); -// Beachte den Syntax von Lambda-Ausdrücken. +// Beachte die Syntax von Lambda-Ausdrücken. // Die [] im Lambda Ausdruck werden für die Variablen verwendet. // Diese so genannte "capture list" definiert, was außerhalb des Lambdas, // innerhalb der Funktion verfügbar sein soll und in welcher Form. @@ -1025,7 +1026,7 @@ for(auto elem: arr) // Einige Aspekte von C++ sind für Neueinsteiger häufig überraschend (aber auch für // C++ Veteranen). // Der nachfolgende Abschnitt ist leider nicht vollständig: -// C++ ist eine der Sprachen, bei der es ein leichtes ist sich selbst ins Bein zu schießen. +// C++ ist eine der Sprachen, bei der es ein Leichtes ist, sich selbst ins Bein zu schießen. // Private-Methoden können überschrieben werden class Foo @@ -1074,10 +1075,10 @@ f1 = f2; #include<tuple> -// Konzeptionell sind Tuple´s alten Datenstrukturen sehr ähnlich, allerdings haben diese keine +// Konzeptionell sind Tupel alten Datenstrukturen sehr ähnlich, allerdings haben diese keine // bezeichneten Daten-Member, sondern werden durch die Reihenfolge angesprochen. -// Erstellen des Tuples und das Einfügen eines Werts. +// Erstellen des Tupels und das Einfügen eines Werts. auto first = make_tuple(10, 'A'); const int maxN = 1e9; const int maxL = 15; @@ -1102,7 +1103,7 @@ tuple<int, char, double> third(11, 'A', 3.14141); cout << tuple_size<decltype(third)>::value << "\n"; // prints: 3 -// tuple_cat fügt die Elemente eines Tuples aneinander (in der selben Reihenfolge). +// tuple_cat fügt die Elemente eines Tupels aneinander (in der selben Reihenfolge). auto concatenated_tuple = tuple_cat(first, second, third); // concatenated_tuple wird zu = (10, 'A', 1e9, 15, 11, 'A', 3.14141) diff --git a/de-de/c-de.html.markdown b/de-de/c-de.html.markdown new file mode 100644 index 00000000..3a726b83 --- /dev/null +++ b/de-de/c-de.html.markdown @@ -0,0 +1,869 @@ +--- +language: C +filename: learnc-de.c +contributors: + - ["caminsha", "https://github.com/caminsha"] +lang: de-de +--- + +Ach, C. Immer noch **die** Sprache für modernes High-Performance Computing. + +C ist wahrscheinlich die Programmiersprache mit dem niedrigsten Abstraktionsnvieau, +welche die meisten Programmierer je brauchen werden. +Die Geschwindigkeit von C ist enorm, allerdings muss man sich stets der +manuellen Speicherverwaltung bewusst sein. + + +> **Über Compiler Optionen** +> +> Standardmäßig sind `gcc` und `clang` ziemlich ruhig bezüglich Warnungen und +> Fehlern, obwohl dies sehr nützliche Informationen sein können. Es wird +> empfohlen, strengere Compiler Optionen zu verwenden. Hier sind einige empfohlene +> Standards: +> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic` +> +> Da gewisse Optionen (inbesondere der C-Standard) sehr stark vom Projekt +> abhängen, lohnt es sich, wenn die unterschiedlichen Optionen genauer +> angeschaut werden. Eine Übersicht über die Compiler-Optionen findet man unter +> [diesem](https://stackoverflow.com/questions/3375697/useful-gcc-flags-for-c) Stackoverflow-Beitrag. +> +> Für weitere Informationen, was diese und weitere Optionen genau machen, +> sollte die Man-Page des C-Compilers aufgerufen werden (z.B. `man 1 gcc`). +> Alternativ kann auch online nach den unterschiedlichen Optionen gesucht werden. + +```c +// einzeilige Kommentare starten mit // - nur in C99 und später vorhanden. + +/* +mehrzeilige Kommentare sehen so aus. Diese funktionieren auch in C89 +*/ + +/* +mehrzeilige Kommentare können nicht verschachtelt werden /* Sei Vorsichtig! */ // Kommentar endet auf dieser Linie ... +*/ // ... nicht bei dieser! + +// Konstanten: #define <keyword> +// Konstanten werden laut der Konvention immer in GROSSBUCHSTABEN geschrieben +#define DAYS_IN_YEAR 365 + +// Konstanten können auch als Aufzählungskonstanten (Enums) definiert werden. +// Alle Anweisungen müssen mit einem Semikolon beendet werden. +enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +// MON wird automatisch zu 2, TUE zu 3 etc. + +// Importiere Header-Dateien mit #include +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// Dateien, welche zwischen <spitzen Klammern> stehen, sind Header-Dateien aus +// der C-Standard-Bibliothek. +// Für deine eigenen Header müssen Anführungszeichen verwendet werden, z.B.: +// #include "mein_header.h" + +// Funktionssignaturen werden entweder vorher in einer .h-Datei deklariert oder +// am Anfang der .c-Datei. +void function_1(); +int funkcion_2(void); + +// Es muss ein Funktionsprototyp deklariert werden vor der `main()` Funktion, +// wenn die Funktion nach der `main()` Funktion gebraucht wird. +int add_two_ints(int x1, int x2); // Funktionsprototyp +// Auch wenn der Ausdrck `int add_two_ints(int, int)` auch valid wäre, +// ist es empfohlen, dass man die Namen der Argumente hinschreibt für eine +// einfachere Analyse. + +// Der Einstiegspunkt deines Programms ist eine Funktion mit dem Namen main und +// einem Integer als Rückgabewert. +int main(void) { + // dein Programm +} + +// Die Kommandozeilenargumente, welche gebraucht werden, damit dein Programm +// läuft, werden als Argumente der `main`-Funktion mitgegeben. +// argc (argument counter) steht für die Anzahl von Argumenten. +// Der Programmname ist das erste Argument. +// argv (argument vector) ist ein Array von Zeichenarrays, welche die +// Argumente beinhaltet. +// argv[0] = Name des Programms +// argv[1] = erstes Argument usw. +int main (int argc, char** argv) { + // Ausgabe mit Hilfe von printf (print formatted) + // %d ist ein Integer. + // \n steht für eine neue Zeile + printf("%d\n",0); // => Gibt 0 aus. + + //////////////////////////////////////////////// + // Operatoren + //////////////////////////////////////////////// + + // Kurzschreibweise für mehrere Deklarationen + int i1 = 1, i2 = 2; + flaot f1 = 1.0, f2 = 2.0; + + int b,c; + b = c = 0; + + // Arithmetik ist unkompliziert + 1 + 2; // => 3 + 2 - 1; // => 1 + 2 * 1; // => 2 + 1 / 2; // 0 (0.5, aber abgeschnitten, da es int sind.) + + // Man muss mindestens ein Integer zu einen float konvertieren, damit man als + // Resultat eine Gleitkommazahl erhält. + (float)1 / 2; // => 0.5f + 1 / (double)2; // => 0.5 // das gleiche mit dem Typ `double` + 1.0 / 2.0; // => 0.5, plus oder minus Epsilon + // Gleitkommazahlen und deren Berechnungen sind nicht exakt. + + // Es gibt auch die Möglichkeit, Modulo zu rechnen + 11 % 3; // => 2 + + // Vergleichsoperatoren sind vielleicht schon bekannt, aber in C gibt es + // keinen Boolean-Typ. In C verwenden wir `int`. (Oder _Bool oder bool in C99) + // 0 ist falsch, alles andere ist wahr (Die Vergleichsoperatoren ergeben + // immer 1 oder 0. + 3 == 2; // => 0 (falsch) + 3 != 2; // => 1 (wahr) + 3 > 2; // => 1 + 3 < 2; // => 0 + 2 <= 2; // => 1 + 2 >= 2; // => 1 + + // C ist nicht Python - Vergleiche können nicht einfach verkettet werden. + // Warnung: die folgende Zeile wird kompilieren, aber es bedeutet `(0 < a) < 2`. + // Dieser Ausdruck ist immer wahr, weil (0 < a) kann entweder 1 oder 0 sein. + // In diesem Falle ist es 1, weil (0 < 1). + int zwischen_0_und_2 = 0 < a < 2; + // Benutze stattdessen folgende Schreibweise: + int zwischen_0_und_2 = 0 < a && a < 2; + + // Logik funktioniert auch mit ints + !3; // => 0 (logisches Nicht) + !0; // => 1 + 1 && 1; // => 1 (logisches Und) + 0 && 1; // => 0 + 0 || 1; // => 1 (logisches Oder) + 0 || 0; // => 0 + + // Bedingter ternärer Ausdruck ( ? : ) + int e = 5; + int f = 10; + int z; + z = ( e > f ) ? e : f; // => // => 10 "wenn e > f ist, gib e zurück, sonst f." + + // Inkrementierungs- und Dekrementierungsoperatoren + int j = 0; + int s = j++; // gib j zurück und erhöhe danach j. (s = 0, j = 1) + s = ++j; // erhöhe zuerst j und gib dann j zurück (s = 2, j = 2) + // das gleiche gilt für j-- und --j + + // Bitweise Operatoren + ~0x0F; // => 0xFFFFFFF0 (Bitweise Negation, "Einer-Komplement", + // Beispielresultat für 32-Bit int) + 0x0F & 0xF0; // => 0x00 (Bitweises UND) + 0x0F | 0xF0; // => 0xFF (Bitweises ODER) + 0x04 ^ 0x0F; // => 0x0B (Bitweises XOR) + 0x01 << 1; // => 0x02 (Bitweises Linksverschiebung (left shift) (um 1)) + 0x02 >> 1; // => 0x01 (Bitweises Rechtsverschiebung (right shift) (um 1)) + + // Sei vorsichtig beim Shift mit vorzeichenbehafteten Integern + // folgende Ausdrücke sind nicht definiert: + // - Verschiebung in das Vorzeichenbit (int a = 1 << 31) + // - Linksshift einer negativen Zahl (int a = -1 << 2) + // - Shift um einen Offset, welcher >= die Breite des linken Ausdrucks ist. + // int a = 1 << 32; // undefiniertes Verhalten, wenn int 32-Bit ist. + + + //////////////////////////////////////////////// + // Typen + //////////////////////////////////////////////// + + // Compiler, welche nicht C99-kompatibel sind, verlangen, dass sämtliche + // Variablen zu Beginn des Blocks deklariert werden. + // C99-Konforme Compiler erlauben die Variablendeklaration an dem Punkt, an + // welchem die Variable verwendet wird. + // Wir deklarieren die Variablen dynamisch im Code um die Lesbarkeit im + // Tutorial zu verbessern. + + // integer sind normalerweise 4 Bytes groß + int x_int = 0; + + // shorts sind normalerweise 2 Bytes groß + short x_short = 0; + + // chars sind garantiert 1 Byte groß + char x_char = 0; + char y_char = 'y'; // Charakterliterale werden mit '' gekennzeichnet. + + // longs sind oft 4 bis 8 Bytes groß. long long sind garantiert mindestens + // 8 Bytes groß. + long x_long = 0; + long long x_long_long = 0; + + // floats sind normalerweise 32-Bit Gleitkommazahlen + float x_float = 0.0f; // 'f'-Suffix beschreibt eine Gleitkommazahl. + + // doubles sind normalerweise 64-Bit Gleitkommazahlen + double x_double = 0.0; // echte Zahlen ohne Suffix sind vom Typ double + + // integer-Typen können vorzeichenlos (unsigned) sein + // (größer oder kleiner als 0) + unsigned short ux_short; + unsigned int ux_int; + unsigned long long ux_long_long; + + // Zeichen innerhalb von einfachen Anführungszeichen sind Integers im + // Maschinenzeichensatz + '0'; // => 48 im ASCII-Zeichensatz + 'A'; // => 65 im ASCII-Zeichensatz + + // sizeof(T) gibt die Größe einer Variablen des Typen T in Bytes zurück. + // sizeof(obj) ergibt die Größe des Ausdrucks (Variable, Literal usw.) + + printf("%zu\n", sizeof(int)); // => 4 (auf den Rechnern mit einem 4-Byte-Wort) + + // Wenn das Argument des `sizeof`-Operator ein Ausdruck ist, dann wird das + // Argument nicht ausgewertet (außer Arrays mit variabler Länge) + // Der Wert, der in diesem Fall zurückgegeben wird, ist eine Konstante zur + // Kompillierzeit. + + int a = 1; + //size_t ist ein vorzeichenloser Integer Typ mit mindestens 2 Byte um die + // Größe eines Objekts zu repräsentieren. + size_t size = sizeof(a++); // a++ wird nicht ausgewertet + printf("sizeof(a++) = %zu, wobei a=%d ist\n", size, a); + // Gibt "sizeof(a++) = 4, wobei a=1 ist" aus (mit einer 32-Bit-Architektur) + + // Arrays müssen mit einer Größe initialisiert werden. + char my_char_array[20]; // Dieses Array beinhaltet 1 * 20 = 20 Bytes + int my_int_array[20]; // Dieses Array beinhaltet 4 * 20 = 80 Bytes. + // unter der Voraussetzung eines 4-Byte-Worts. + + // Ein Array kann auf diese Weise mit 0 initialisiert werden. + char my_array[20] = {0}; + // Hierbei ist der Teil "{0}" der "Array Initialisierer". + // Beachte, dass die Länge des Arrays nicht explizit definiert werden muss, + // wenn er auf derselben Linie initialisiert wird. + // Folgende Deklaration ist gleichwertig: + char my_array[] = {0}; + // Allerdings muss die Länge des Arrays dann zur Laufzeit ausgewertet werden: + size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]); + // WARNUNG: Wenn dieser Ansatz gewählt wird, muss man sicherstellen, dass die + // Größe des Arrays ermittelt werden *bevor* dieser einer Funktion als + // Argument weitergegeben wird (siehe Diskussion weiter unten), weil Arrays + // einer Funktion nur als Zeiger übergeben werden. => Das obere Statement + // würde innerhalb einer Funktion ein falsches Resultat liefern. + + // Das Indexieren eines Arrays funktioniert wie in anderen Sprache - resp. + // in anderen Sprachen funktioniert es gleich wie in C. + my_array[0]; // => 0 + + // Arrays sind veränderbar; es ist nur Arbeitsspeicher! + my_array[1] = 2; + printf("%d\n", my_array[1]); // => 2 + + // In C99 (und als optionales Feature in C11) können Arrays mit variabler + // Länge deklariert werden. Die Größe eines solchen Array muss eine Konstante + // zur Kompilierzeit sein. + printf("Geben Sie die Arraygröße an: "); //Frag den Benutzer nach + // der Arraygröße + int array_size; + fcsanf(stdin, "%d", &array_size); + int var_length_array[array_size]; // deklariere Array mit variabler Länge + printf("sizeof array =%zu\n", sizeof var_length_array); + + // Zum Beispiel: + // > Geben Sie die Arraygröße an: 10 + // > sizeof array = 40 + + // Strings sind lediglich Arrays von `chars`, welche mit einem Null-Byte + // (0x00) beendet werden. In Strings wird das Nullbyte durch das Zeichen \0 + // repräsentiert. Wir müssen das Null-Byte nicht angeben in String-Literalen; + // der Compiler fügt es am Ende des Array automatisch hinzu. + char a_string[20] = "Das ist ein String"; + printf("%s\n", a_string); // %s formattiert einen String + + printf("%d\n", a_string[18]); // => 0 + // Hier ist das Byte #19 0 (wie auch Byte #20) + + // Wenn wir Zeichen zwischen einfachen Anführungszeichen haben, ist es ein + // Zeichenliteral vom Typ int und *nicht* char. (aus historischen Gründen) + int cha = 'a'; // Ok + char chb = 'a'; // auch ok (implizite Umwandlung von int zu char) + + // Mehrdimensionale Arrays: + int multi_array[2][5] = { + {1,2,3,4,5}, + {6,7,8,9,0} + }; + // Auf Elemente zugreifen: + int array_int = multi_array[0][2]; // => 3 + + //////////////////////////////////////////////// + // Kontrollstrukturen + //////////////////////////////////////////////// + if (0) { + printf("Ich werde nie ausgeführt."); + } + else if (0) { + printf("Ich werde auch nie ausgeführt."); + } + else { + printf("Ich gebe etwas aus."); + } + + // While-Schleifen existieren auch + int ii = 0; + while (ii < 10) { // JEDER Wert unter zehn ist wahr + printf("%d, " ii++); //i++ inkrementiert ii NACHDEM der Wert gebraucht + // wurde. + } // => gibt folgendes aus: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + int kk = 0; + do { + printf("%d, ", kk); + } while(++kk < 10); //++kk inkrementiert kk BEVOR der Wert gebraucht wurde. + // => gibt folgendes aus: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // In C gibt es auch for-Schleifen + int jj; + for (jj = 0; jj < 10; jj++) { + printf("%d, ", jj); + } // => gibt folgendes aus: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // **Merke** + // Schleifen und Funktionen müssen einen Rumpf haben. Wenn kein Rumpf gebraucht + // wird, kann folgendes gemacht werden: + int i; + for (i = 0; i <= 5; i++) { + ; // Semikolon wird als Rumpf behandelt (Null-Anweisung) + } + // Alternativ kann auch folgendes geschrieben werden: + for (i = 0; i <= 5; i++); + + // Verzweigungen mit mehreren Möglichkeiten: `switch()` + switch (a) { + case 0: // Labels müssen integrale *konstante* Ausdrücke sein (z.B. Enums) + printf("Hey, 'a' ist gleich 0!\n"); + break; //Wenn du kein break einsetzt, so geht der Kontrollfluss + // durch die Labels + case 1: + printf("Huh, 'a' ist gleich 1!\n"); + break; + // Sei vorsichtig - wenn man das `break` vergisst, werden alle + // Anweisungen ausgeführt bis das nächste `break` erscheint. + case 3: + case 4: + printf("Schau mal ... 'a' ist entweder 3 oder 4.\n"); + break; + default: + // wenn der Ausdruck `a` auf kein Label zutrifft. + fputs("Fehler!\n", stderr); + exit(-1); + break; + } + + //////////////////////////////////////////////// + // Typenumwandlung + //////////////////////////////////////////////// + + // Jeder Wert in C hat einen bestimmten Typen, aber es ist möglich, ein + // Wert in einen anderen Typ umzuwandeln (mit einigen Einschränkungen). + + int x_hex = 0x01; // Es ist möglich, Variablen Hexadezimalwerten zuzuweisen. + + // Bei der Umwandlung zwischen Typen wird versucht, den numerischen Wert + // beizubehalten. + printf("%d\n", x_hex); // => 1 + printf("%d\n", (short) x_hex); // => 1 + printf("%d\n", (char) x_hex); // => 1 + + // Typen werden überlaufen (overflow) ohne jegliche Warnung + printf("%d\n", (unsigned char) 257); // => 1 (Max char=255 wenn char 8 Bit ist) + + // Um den maximalen Wert eines `char`, `signed char` oder `unsigned char` + // herauszufinden, können die Makros `CHAR_MAX`, `SCHAR_MAX` und `UCHAR_MAX` + // aus der Header-Datei `<limits.h>` verwendet werden. + + // Integer-Typen können zu Gleitkommazahlen und umgekehrt umgewandelt werden. + printf("%f\n", (double) 100); // %f formattiert immer zu einem `double`... + printf("%f\n", (flaot) 100); // ... auch mit einem `float` + printf("%d\n", (char)100.0); + + //////////////////////////////////////////////// + // Zeiger (aka Pointer) + //////////////////////////////////////////////// + + // In diesem Tutorial wird das deutsche Wort Zeiger nicht verwendet, da es + // bei einer weiteren Recherche einfacher ist, wenn man von Pointern ausgeht. + // Außerdem ist der Begriff Pointer auch im deutschen Sprachgebrauch zu finden. + + // Ein Pointer ist eine Variable, welche deklariert wurde, um eine Speicher- + // adresse zu speichern. Die Deklaration eines Pointers wird auch zeigen, + // auf welche Art von Daten der Pointer zeigt. Man kann die Speicheradresse + // von Variablen abrufen und dann mit diesen herumspielen. + + int x = 0; + printf("%p\n", (void *)&x); // verwende & um die Adresse der Variable + // zu erhalten + // %p formattiert einen Objektpointer des Typen void*) + // => Gibt eine Adresse im Speicher aus + + // Pointer starten mit einem * zu Beginn der Deklaration. + int *px, not_a_pointer; // px ist ein Pointer zu einem int. + px = &x; // Speichert die Adresse von x in px + printf("%p\n", (void *)px); // => Gibt eine Adresse im Speicher aus + printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); + // Gibt auf einem typischen 64-Bit-System folgendes aus: "8, 4" + + // Um den Wert einer Adresse, auf welche ein Pointer zeigt, herauszufinden, + // muss man vor die Variable ein * setzen, um sie zu dereferenzieren. + // Notiz: Ja, es kann verwirrend sein, dass '*' sowohl für das Deklarieren + // als auch das Derefenzieren verwendet werden kann. + printf("%d\n", *px); // => 0, der Wert von x + + // Man kann den Wert, auf welchen ein Pointer zeigt, auch verändern. + // Man muss die Dereferenzierung in Klammern setzen, weil ++ eine höhere + // Priorität als * hat. + (*px)++; // Inkrementiere den Wert, auf welchen px zeigt, um 1 + printf("%d\n", *px); // => 1 + printf("%d\n", x); // => 1 + + // Arrays sind eine gute Möglichekit, einen zusammenhängenden Block von + // Speicher zu allozieren. + int x_array[20]; // deklariert einen Array der Größe 20 (Größe kann + // nicht geändert werden.) + int xx; + for (xx =0; xx < 20; xx++) { + x_array[xx] 20 -xx; + } // Initialisiere x_array zu 20, 19, 18, ... 2, 1 + + // Deklariere ein Pointer des Typs int und initalisiere ihn, um auf `x_array` + // zu zeigen. + int *x_ptr = x_array; + // x_ptr zeigt jetzt auf den ersten Wert innerhalb des Arrays (int 20) + // Das funktioniert, weil Arrays oft zu Pointern reduziert werden, welche + // auf das erste Element zeigen. + // Zum Beispiel: Wenn ein Array einer Funktion mitgegeben wird oder einem + // Pointer zugewiesen wird, wird es zu einem Pointer reduziert (implizites Casting) + // Ausnahme: Wenn das Array das Argument des Operators `&` ist. + int arr[10]; + int (*ptr_to_arr)[10] = &arr; //`&arr` ist nicht vom Typ `int *`! + // Es ist vom Typem "Pointer auf Array" (aus zehn `int`s) + // oder wenn das Array ein Stringliteral ist, welches gebraucht wird um ein + // `char`-Array zu initialisieren. + char other_arr[] = "foobarbazquirk"; + // oder wenn es das Argument des `sizeof` oder `alignof` Operators ist. + int third_array[10]; + int *ptr = third_array; // gleich wie: `int *ptr = &arr[0]` + printf("%zu, %zu\n", sizeof(third_array), sizeof(ptr)); + // Gibt wahrscheinlich "40, 4" oder "40, 8" aus + + // Pointer werden basierend auf dem Typ in- und dekrementiert + // Dies wird Pointer-Arithmetik genannt. + printf("%d\n", *(x_ptr + 1)); // => 19 + printf("%d\n", x_array[1]); // => 19 + + // Man kann zusammenhängende Speicherblöcke auch mit der Funktion `malloc` + // aus der Standardbibliothek dynamisch allozieren. Der Funktion `malloc` + // muss ein Argument des Typs `size_t` übergeben werden, welches bestimmt, + // wie viele Bytes alloziert werden sollen. (Normalerweise geschieht dies + // aus dem Heap - dies kann auf eingebetteten Systemen unterschiedlichen sein. + // Der C Standard sagt nichts darüber.) + int *my_ptr = malloc(sizeof(*my_ptr) * 20); + for (xx = 0; xx < 20; xx++) { + *(my_ptr + xx) = 20 -xx; //my_ptr[xx] = 20-xx + } // initialisiere Speicher zu 20, 19, 18, 17, ... 2, 1 (als `int`) + + // Sei vorsichtig beim Übergeben von Benutzerdefinierten Werten an `malloc`. + // Wenn du sicher sein willst, kannst du die Funktion `calloc` nutzen, welche + // (nicht wie `malloc`) auch den Speicher nullt. + int *my_other_ptr = calloc(20, sizeof(int)); + + // Merke, dass es in C keinen Standard-Weg gibt, um die Länge eines dynamisch + // allozierten Arrays zu bestimmen. Auf Grund dessen sollte eine Variable + // erstellt werden, welche sich die Anzahl der Elemente im Array merkt, wenn + // die Arrays mehrmals im Programm gebraucht werden. + // Weitere Informationen stehen im Abschnitt Funktionen. + size_t size = 10; + int *my_array = calloc(size, sizeof(int)); + // Füge dem Array ein Element hinzu + size++; + my_array = realloc(my_array, sizeof(int) *size); + if (my_array == NULL) { + // Denke daran, realloc-Fehler zu prüfen + return + } + my_array[10] = 5; + + // Das Dereferenzieren von nicht alloziertem Speicher führt zu einem + // Undefinierten Verhalten. + printf("%d\n", *(my_ptr + 21)); // Gibt irgendwas aus. + // Das Programm kann auch abstürzen + + // Nachdem du fertig mit einem Block bist, welcher `malloc` verwendet hat, + // muss der Speicher befreit werden. Ansonsten kann dieser Speicherbereich + // niemand nutzen bis dein Programm beendet wird. + // Dies wird auch als "Speicherleck" (engl: memory leak) bezeichnet. + free(my_ptr); + + // Obwohl Strings normalerweise als Pointer-to-Char (Pointer zum ersten + // Zeichen des Arrays) repräsentiert werden, sind Strings Arrays aus `char`s. + // Es ist eine gute Praxis, `const char *` zu verwenden, wenn man ein + // String-Literal referenziert, da String-Literale nicht modifiziert werden + // sollten (z.B. "foo"[0] = 'a' ist ILLEGAL) + const char *my_str = "Das ist mein eigener String"; + printf("%c\n", *my_str); // => D + + // Dies ist nicht der Fall, wenn der String ein Array (möglicherweise mit + // einem String-Literal initialisiert) ist, welcher im beschreibbaren Speicher + // bleibt, wie zum Beispiel in: + char foo[] = "foo"; + foo[0] = 'a'; // Dies ist legal, foo enthält jetzt "aoo" + + function_1(); +} // Ende der `main`-Funktion + +//////////////////////////////////////////////// +// Funktionen +//////////////////////////////////////////////// + +// Syntax einer Funktionsdeklaration +// <rueckgabe_wert> <funktions_name>(<args>) + +int add_two_ints(int x1, int x2) { + return x1 + x2; // verwendet return, um einen Wert zurückzugeben +} + +/* +Funktionen werden auf Grund des Wertes aufgerufen (call-by-value). Wenn eine +Funktion aufgerufen wird, sind die Argumente Kopien der ursprünglichen Werte +(ausgenommen Arrays). Alles, was man innerhalb einer Funktion mit den Werten +macht, hat keinen Einfluss auf die Originalwerte als die Funktion aufgerufen +wurde. + +Verwende Pointer, um den Originalinhalt zu bearbeiten. + +Beispiel: +*/ + +// Eine `void`-Funktion gibt keinen Wert zurück +void str_reverse(char *str_in) { + char tmp; + size_t ii = 0; + size_t size = strlen(str_in); + // `strlen()` ist ein Teil der C Standard-Bibliothek. + // Merke: Die Länge, welche von `strlen` zurückgegeben wird, ist ohne den + // Null-Byte Terminator. + for (ii = 0; i < size /2; ii++) { // in C99 kann man `ii` hier deklarieren. + tmp = str_in[ii]; + str_in[ii] = str_in[size - ii - 1]; //#ii'tes Zeichen vom Ende her + str_in[size - ii- 1] = tmp; + } +} +// Merke: Die `string.h`-Headerdatei muss inkludiert werden, bevor `strlen()` +// verwendet werden kann. + +/* +char c[] = "Das ist ein Test"; +str_reverse(c); +printf("%s\n", c), => "tseT nie tsi saD" +*/ + +// Weil wir lediglich eine Variable zurückgeben können, kann zum Ändern mehrerer +// Variablen das Konzept call-by-reference verwendet werden. +void swap_two_numbers(int *a, int *b) { + int temp = *a; + *a = *b; + *b = temp; +} +int first = 10; +int seconde = 20; +printf("Erste Zahl: %d\n Zweite Zahl: %d\n", first, second); +swap_two_numbers(&first, &second); +printf("Erste Zahl: %d\n Zweite Zahl: %d\n", first, second); +// Werte sind vertauscht. + +/* +Wenn man Arrays betrachtet, so werden diese immer als Pointer übergeben. Auch +wenn die Arrays statisch alloziert werden (wie zum Beispiel `arr[10]`), werden +diese als Pointer zum ersten Element des Arrays übergeben. +Auch hier soll noch einmal erwähnt werden, dass es keinen Standard gibt, wie die +Größe eines dynamischen Arrays herausgefunden werden kann. +*/ +// Die Größe des Arrays muss unbedingt mitgegeben werden. +// Sonst hat die Funktion keine Ahnung wie groß das Array ist. +void print_int_arrray(int *arr, size_t size) { + int i; + for (i = 0; i < size; i++) { + printf("arr[%d] ist %d\n", i, arr[i]); + } +} + +int my_array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +int size = 10; +print_int_array(my_array, size); +// Wird folgendes ausgeben: "arr[0] ist 1" usw. + +// Wenn man auf externe Variable (außerhalb der Funktion) referenziert, sollte +// man das Schlüsselwort `extern` verwenden. +int i = 0; +void test_function() { + extern int i; // i braucht nun die externe Variable i +} + +// Das Schlüsselwort `static` macht, dass eine Variable außerhalb der Kompilier- +// einheit nicht zugreifbar ist. (Auf den meisten Systemen ist eine Kompiliereinheit +// eine `.c`-Datei.) Das Schlüsselwort `static` kann sowohl bei globalen +// (zur Kompiliereinheit gehörende) Variablen, Funktionen und Funktionslokale +// Variablen angewendet werden. +// Wenn man `static` bei lokalen Variablen verwendet, so ist diese Variable global +// erreichbar und behält dessen Wert über Funktionsaufrufe hinweg, aber sie ist +// nur innerhalb der deklarierten Funktion verfügbar. Außerdem werden statische +// Variablen mit 0 initialisiert, wenn sie nicht mit einem anderen Startwert +// initialisiert werden. +// Es ist auch möglich, Funktionen als statisch zu deklarieren, damit diese +// `private` sind. Privat heißt, dass sie nur in diesem Kontekt sichtbar sind. + + +//////////////////////////////////////////////// +// Benutzerdefinierte Typen und Strukturen (Structs) +//////////////////////////////////////////////// + +// `typedef`s können verwendet werden, um Typenaliase zu erstellen. +typedef int my_type; +my_type my_type_var = 0; + +// Structs sind lediglich Sammlungen von Daten, die Inhalte werden +// (in der Reihenfolge wie sie geschrieben wurden) sequentiell alloziert. +struct rectangle { + int width; + int height; +}; + +// Allgemein ist es nicht so, dass folgender Ausdruck wahr ist. +// sizeof(struct rectangle) == sizeof(int) + sizeof(int) +// Dies ist so, weil potentiell ein Padding zwischen den Struktur-Inhalten +// möglich ist). (siehe [1, Englisch]) + +void function_1() { + struct rectangle my_rectangle; + + // Greife auf Struct-Inhalte mit `.` zu. + my_rectangle.width = 10; + my_rectangle.height = 20; + + // Du kannst Pointer zu Structs deklarieren. + struct rectangle *my_rectangle_ptr = &my_rectangle; + + // Verwende Dereferenzierung, um Struct-Inhalte zu bearbeiten + (*my_rectangle_ptr).width = 30; + + //Noch besser: Verwende die Kurzschreibweise ->, um die Lesbarkeit zu + // verbessern. + my_rectangle_ptr->height = 10; // Gleich wie: (*my_rectangle_ptr).height = 10; +} + +// Aus Bequemlichkeitsgründen ist es möglich einem `struct` ein `typedef` hinzuzufügen. +typedef struct rectangle rect; + +int area(rect r) { + return r.width * r.height; +} + +// Wenn du große Structs hast, kannst du diese mit dem Pointer kopieren, +// damit große Kopiervorgänge vermieden werden. +int area_ptr(const rect *r) { + return r->width * r->height; +} + +//////////////////////////////////////////////// +// Funktionspointer +//////////////////////////////////////////////// + +/* +Zur Laufzeit sind Funktionen in einer Speicheradresse gespeichert. +Funktionspointer sind wie normale Pointer (es wird einfach eine Speicheradresse +gespeichert). Funktionspointer können verwendet werden, um Funktionen und +Handler (oder Callback-Funktionen) direkt aufzurufen. +Wie auch immer, die Syntax kann zu Beginn verwirrend wirken. + +Zum Beispiel: Verwende str_reverse von einem Pointer +*/ +void str_reverse_through_pointer(char *str_in) { + // Definiere eine Funktionspointer-Variable, welche f genannt wird. + void (*f)(char *); // Signatur sollte genau der Funktion entsprechen. + f = &str_reverse; // weise die Adresse der wirklichen Funktion zu + // (zur Laufzeit bestimmt) + // `f = str_reverse;` würde auch funktionieren, da Funktionen zu Pointern + // reduziert werden (ähnlich wie Arrays) + (*f)(str_in); // Die Funktion einfach mit dem Pointer aufrufen + // f(str_in); // Dies ist eine weitere gültige Alternative um eine Funktion + // auzurufen. +} + +/* +Solange die Signaturen der Funktionen übereinstimmen, kann man sämtliche Funktionen +demselben Pointer zuweisen. Funktionspointer sind auf Grund der Einfacheit und +Leserlichkeit normalerweise wie folgt `typedef`d +*/ +typedef void (*my_fnp_type)(char *); +// Danach werden diese genutzt, um die wirkliche Pointervariable zu deklarieren. +// .. +// my_fnp_type f; + +// Spezialzeichen +// Im folgenden sin die englischen Begriffe jeweils in Klammern geschrieben, +// da diese Begriffe auch im deutschten Sprachgebrauch verwendet werden. +'\a'; // Alarmzeichen (alert (bell) character) +'\n'; // Zeichen für neue Linie (newline character) +'\t'; // Tab (tab character (left justifies text)) +'\v'; // Vertikaler Tab (vertical tab) +'\f'; // Neue Seite (new page (form feed)) +'\r'; // Wagenrücklauf (carriage return) +'\b'; // Backspace-Zeichen (backspace character) +'\0'; // Null-Byte (NULL character). In C wird dieses Zeichen normalerweise am +// Ende eines Strings gesetzt. +// Beispiel: Hallo\n\0. "\0" wird per Konvention verwendet, um das Ende +// eines Strings zu kennzeichnen. +'\\'; // Backslash (backslash) +'\?'; // Fragezeichen (question mark) +'\''; // einfaches Anführungszeichen (single quote) +'\"'; // doppeltes Anführungszeichen (double quote) +'\xhh'; // Hexadezimale Zahl (hexadecimal number.) Beispiel: + // '\xb' = Zeichen für vertikalen Tab +'\0oo'; // Oktalzahl (octal number). Beispiel \013 = Zeichen für vertikalen Tab + +//Ausgabeformatierung +"%d"; // Integer +"%3d"; // Integer mit einer minimalen Länge von drei Zeichen. +"%s"; // String +"%f"; // Gleitkommazahl (float) +"%ld"; // genauere Gleitkommazahl (long) +"%3.2f"; // Mindestens drei Zeichen vor und drei nach dem Komma. +"%7.4s"; // (Kann auch mit Strings gemacht werden) +"%c"; // einzelnes Zeichen (char) +"%p"; // Pointer. Merke: man muss den Pointer zu void umwandeln, + // bevor `printf` funktioniert. +"%x"; // Hexadezimal +"%o"; // Oktalzahl +"%%"; // Gibt % aus + +//////////////////////////////////////////////// +// Reihenfolge der Auswertung von Operatoren +//////////////////////////////////////////////// + +//-------------------------------------------------------// +// Operatoren | Assoziativität // +//-------------------------------------------------------// +// () [] -> . | linksassoziativ // +// ! ~ ++ -- + = *(type)sizeof | rechtsassoziativ // +// * / % | linksassoziativ // +// + - | linksassoziativ // +// << >> | linksassoziativ // +// < <= > >= | linksassoziativ // +// == != | linksassoziativ // +// & | linksassoziativ // +// ^ | linksassoziativ // +// | | linksassoziativ // +// && | linksassoziativ // +// || | linksassoziativ // +// ?: | rechtsassoziativ // +// = += -= *= /= %= &= ^= |= <<= >>= | rechtsassoziativ // +// , | linksassoziativ // +//-------------------------------------------------------// + + +//////////////////////////////////////////////// +// Header-Dateien +//////////////////////////////////////////////// + +/* +Header-Dateien sind ein wichtiger Teil von C, da sie eine Verbindung zwischen +unterschiedlichen C-Quelldateien herstellen. Außerdem vereinfachen Header-Dateien +den Code und Definitionen, da diese in separaten Dateien geschrieben werden können. + +Header-Dateien sind von der Syntax her ähnlich zu C-Quelldateien, allerdings haben +die Header-Dateien die Dateiendung `.h`. Header-Dateien können im Quellcode mit +der `#include`-Anweisung eingebunden werden z.B. `#include "beispiel.h". Die +vorherige Anweisung geht davon aus, dass sich die Header-Datei im selben Ordner +befindet wie die C-Quelldatei. +*/ + +// Eine sichere Möglichkeit, einen Header mehrere Male zu definieren bietet, das +// folgende Statement. Die mehrfache Definition geschieht, wenn Kreisabhängigkeiten +// bestehen. +#ifndef EXAMPLE_H /* Wenn EXAMPLE_H noch nicht definiert wurde */ +#define EXAMPLE_H /* definiere das Makro EXAMPLE_H */ + +// Es könenn weitere Header innerhalb eines Headers eingebunden werden, was dazu +// führt, dass diese bereits in anderen Dateien eingebunden wurden. So kann eine +// Header-Datei in mehreren Dateien eingebunden werden. zum Beispiel: +#include <string.h> + +// Wie in den Quelldateien können auch in den Header-Dateien Makros definiert +// werden und in anderen Dateien verwendet werden, welche diesen Header einbinden. +#define EXAMPLE_NAME "Dennis Ritchie" + +// Funktionsmakros können auch definiert werden. +#define ADD(a, b) ((a) + (b)) + +// Beachte die Klammern, welche um die Argumente geschrieben wurden - diese sind +// wichtig, damit sichergestellt werden kann, dass a und b nicht unerwartet +// erweitert werden. Zum Beispiel: `MUL (x,y) (x * y)`; Bei der Verwendung von +// `MUL(1 + 2, 3)` würde dies wie folgt erweitert werden: `(1 + 2 * 3)`, was zu +// einem falschen Resultat führt. + +// Strukturen und Typendefinitionen können verwendet werden, um die Konsistenz +// zwischen unterschiedlichen Dateien beizubehalten. +typedef struct Node { + int value; + struct Node *next; +}Node; + +// Dies kann auch mit Aufzählungen gemacht werden. +enum traffic_light_state {GREEN, YELLOW, RED}; + +// Funktionsprototypen könenn auch in Header-Dateien definiert werden, um die +// Funktion in unterschiedlichen Dateien zu verwenden, aber dies wird als schlechte +// Praxis angesehen. Definitionen sollten in einer C-Datei erstellt werden. +Node create_linked_list(int *value, int length); + +// Außer den oben genannten Elementen, sollten weitere Definitionen in einer +// C-Datei gemacht werden. Übermäßige Includes und Definitionen sollten auch +// nicht einer Header-Datei gemacht werden. Stattdessen wird es empfohlen, diese +// in eine separate Header-Datei oder in eine C-Quelldatei zu schreiben. + +#endif /* Ende der Präprozessordirektive */ +``` +## Weiterführende Literatur + +Das Beste wird es sein, wenn man sich ein Exemplar des Buches +["The C Programming Language"](https://de.wikipedia.org/wiki/The_C_Programming_Language) besorgt. +Dieses Buch gilt als **das** Buch über die Programmiersprache C und wurde +von Dennis Ritchie, dem Erfinder der Programmiersprache C, und Brian Kernighan +geschrieben. +Sei vorsichtig, da dieses Buch mittlerweile schon etwas älter ist und gewisse +Unkorrektheiten (d.h. Ideen, welche nicht mehr als gut empfunden werden.) oder +mittlerweile geänderte Praktiken enthält. [Hinweis: Das Buch wurde auf Englisch +geschrieben, es gibt aber auch eine Übersetzung davon] + +Eine weitere gute Ressource ist [Learn C The Hard Way](http://learncodethehardway.org/c/). +[Englisch] + +Solltest du Fragen zu C haben, so lies die FAQ [compl.lang.c Frequently Asked Questions](http://c-faq.com).[Englisch] + +Außerdem ist es wichtig, eine saubere Einrückung zu verwenden. Des weiteren ist +es wichtig, dass der Codestil möglichst konsistent ist. Es ist wichtiger, lesbaren +Code zu schreiben als Code, welcher clever und schnell ist. Es lohnt sich ein +Blick auf den [Codestil des Linuxkernel](https://www.kernel.org/doc/Documentation/process/coding-style.rst) zu werfen. [Englisch] + +[1] [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) diff --git a/de-de/clojure-macros-de.html.markdown b/de-de/clojure-macros-de.html.markdown new file mode 100644 index 00000000..088a29a8 --- /dev/null +++ b/de-de/clojure-macros-de.html.markdown @@ -0,0 +1,161 @@ +--- +language: "clojure macros" +filename: learnclojuremacros-de.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Dennis Keller", "https://github.com/denniskeller"] +lang: de-de +--- + +Wie mit allen Lisps besitzt auch Clojure die inhärente [Homoikonizität](https://en.wikipedia.org/wiki/Homoiconic), +die dir den vollen Zugang der Sprache gibt, um + Code-Generierungsroutinen zu schreiben. Diese werden "Macros" genannt. +Macros geben dir eine leistungsarke Möglichkeit, die Sprache +an deine Bedürfnisse anzupassen. + +Sei aber vorsichtig, es wird als schlechter Stil angesehen, wenn du +ein Macro schreibst, obwohl eine Funktion genausogut funktionieren würde. +Verwende nur dann ein Macro, wenn du Kontrolle darüber brauchst, wann oder ob Argumente in einer Form evaluiert werden. + +Wenn du mit Clojure vertraut sein möchtest, stelle sicher, dass du alles in [Clojure in Y Minutes](/docs/clojure/) verstehst. + +```clojure +;; Definiere ein Macro mit defmacro. Dein Macro sollte eine Liste zurückgeben, +;; die als Clojure Code evaluiert werden kann. +;; +;; Dieses Macro ist das Gleiche, als ob du (reverse "Hallo Welt") geschrieben +;; hättest +(defmacro my-first-macro [] + (list reverse "Hallo Welt")) + +;; Inspiziere das Ergebnis eines Macros mit macroexpand oder macroexpand-1. +;; +;; Beachte, dass der Aufruf zitiert sein muss. +(macroexpand '(my-first-macro)) +;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hallo Welt") + +;; Du kannst das Ergebnis von macroexpand direkt auswerten. +(eval (macroexpand '(my-first-macro))) +; -> (\t \l \e \W \space \o \l \l \a \H) + +;; Aber du solltest diese prägnante und funktionsähnliche Syntax verwenden: +(my-first-macro) ; -> (\t \l \e \W \space \o \l \l \a \H) + +;; Du kannst es dir leichter machen, indem du die Zitiersyntax verwendest +;; um Listen in ihren Makros zu erstellen: +(defmacro my-first-quoted-macro [] + '(reverse "Hallo Welt")) + +(macroexpand '(my-first-quoted-macro)) +;; -> (reverse "Hallo Welt") +;; Beachte, dass reverse nicht mehr ein Funktionsobjekt ist, sondern ein Symbol + +;; Macros können Argumente haben. +(defmacro inc2 [arg] + (list + 2 arg)) + +(inc2 2) ; -> 4 + +;; Aber wenn du versuchst das mit einer zitierten Liste zu machen wirst du +;; einen Fehler bekommen, weil das Argument auch zitiert sein wird. +;; Um dies zu umgehen, bietet Clojure einee Art und Weise Macros zu zitieren: ` +;; In ` kannst du ~ verwenden um in den äußeren Bereich zu kommen. +(defmacro inc2-quoted [arg] + `(+ 2 ~arg)) + +(inc2-quoted 2) + +;; Du kannst die normalen destruktuierungs Argumente verwenden. Expandiere +;; Listenvariablen mit ~@. +(defmacro unless [arg & body] + `(if (not ~arg) + (do ~@body))) ; Erinnere dich an das do! + +(macroexpand '(unless true (reverse "Hallo Welt"))) +;; -> +;; (if (clojure.core/not true) (do (reverse "Hallo Welt"))) + +;; (unless) evaluiert und gibt body zurück, wenn das erste Argument falsch ist. +;; Andernfalls gibt es nil zurück + +(unless true "Hallo") ; -> nil +(unless false "Hallo") ; -> "Hallo" + +;; Die Verwendung Macros ohne Sorgfalt kann viel Böses auslösen, indem es +;; deine Variablen überschreibt +(defmacro define-x [] + '(do + (def x 2) + (list x))) + +(def x 4) +(define-x) ; -> (2) +(list x) ; -> (2) + +;; Um das zu verhindern kannst du gensym verwenden um einen eindeutigen +;; Identifikator zu bekommen +(gensym 'x) ; -> x1281 (oder etwas Ähnliches) + +(defmacro define-x-safely [] + (let [sym (gensym 'x)] + `(do + (def ~sym 2) + (list ~sym)))) + +(def x 4) +(define-x-safely) ; -> (2) +(list x) ; -> (4) + +;; Du kannst # innerhalb von ` verwenden um für jedes Symbol automatisch +;; ein gensym zu erstellen +(defmacro define-x-hygienically [] + `(do + (def x# 2) + (list x#))) + +(def x 4) +(define-x-hygienically) ; -> (2) +(list x) ; -> (4) + +;; Es ist üblich, Hilfsfunktionen mit Macros zu verwenden. Lass uns einige +;; erstellen, die uns helfen , eine (dumme) arithmetische Syntax +;; zu unterstützen +(declare inline-2-helper) +(defn clean-arg [arg] + (if (seq? arg) + (inline-2-helper arg) + arg)) + +(defn apply-arg + "Bekomme die Argumente [x (+ y)], gebe (+ x y) zurück" + [val [op arg]] + (list op val (clean-arg arg))) + +(defn inline-2-helper + [[arg1 & ops-and-args]] + (let [ops (partition 2 ops-and-args)] + (reduce apply-arg (clean-arg arg1) ops))) + +;; Wir können es sofort testen, ohne ein Macro zu erstellen +(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5)) + +; Allerdings, brauchen wir ein Macro, wenn wir es zur Kompilierungszeit +; ausführen wollen +(defmacro inline-2 [form] + (inline-2-helper form)) + +(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1))) +; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1) + +(inline-2 (1 + (3 / 2) - (1 / 2) + 1)) +; -> 3 (eigentlich, 3N, da die Zahl zu einem rationalen Bruch mit / umgewandelt wird) +``` + +### Weiterführende Literatur + +[Macros schreiben](http://www.braveclojure.com/writing-macros/) + +[Offiziele Docs](http://clojure.org/macros) + +[Wann verwendet man Macros?](https://lispcast.com/when-to-use-a-macro/) diff --git a/de-de/crystal-de.html.markdown b/de-de/crystal-de.html.markdown new file mode 100644 index 00000000..535267ee --- /dev/null +++ b/de-de/crystal-de.html.markdown @@ -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/) diff --git a/de-de/csharp-de.html.markdown b/de-de/csharp-de.html.markdown index 78bb0a6b..662c2e76 100644 --- a/de-de/csharp-de.html.markdown +++ b/de-de/csharp-de.html.markdown @@ -1,890 +1,890 @@ ----
-language: c#
-contributors:
- - ["Irfan Charania", "https://github.com/irfancharania"]
- - ["Max Yankov", "https://github.com/golergka"]
- - ["Melvyn Laïly", "http://x2a.yt"]
- - ["Shaun McCarthy", "http://www.shaunmccarthy.com"]
-translators:
- - ["Frederik Ring", "https://github.com/m90"]
-filename: LearnCSharp-de.cs
-lang: de-de
----
-C# ist eine elegante, typsichere und objektorientierte Sprache, mit der Entwickler eine Vielzahl sicherer und robuster Anwendungen erstellen können, die im .NET Framework ausgeführt werden.
-
-[Mehr über C# erfährst du hier.](http://msdn.microsoft.com/de-de/library/vstudio/z1zx9t92.aspx)
-
-```c#
-// Einzeilige Kommentare starten mit zwei Schrägstrichen: //
-/*
-Mehrzeile Kommentare wie in C Schrägstrich / Stern
-*/
-/// <summary>
-/// XML-Kommentare können zur automatisierten Dokumentation verwendet werden
-/// </summary>
-
-// Zu Beginn werden die in der Datei verwendeten Namespaces aufgeführt
-using System;
-using System.Collections.Generic;
-using System.Data.Entity;
-using System.Dynamic;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Net;
-using System.Threading.Tasks;
-using System.IO;
-
-// definiert einen Namespace um Code in "packages" zu organisieren
-namespace Learning
-{
- // Jede .cs-Datei sollte zumindest eine Klasse mit dem Namen der Datei
- // enthalten. Das ist zwar nicht zwingend erforderlich, es anders zu
- // handhaben führt aber unweigerlich ins Chaos (wirklich)!
- public class LearnCSharp
- {
- // Zuerst erklärt dieses Tutorial die Syntax-Grundlagen,
- // wenn du bereits Java oder C++ programmieren kannst:
- // lies bei "Interessante Features" weiter!
- public static void Syntax()
- {
- // Mit Console.WriteLine kannst du einfachen Text ausgeben:
- Console.WriteLine("Hallo Welt");
- Console.WriteLine(
- "Integer: " + 10 +
- " Double: " + 3.14 +
- " Boolean: " + true);
-
- // Console.Write erzeugt keinen Zeilenumbruch
- Console.Write("Hallo ");
- Console.Write("Welt");
-
- ///////////////////////////////////////////////////
- // Typen & Variablen
- ///////////////////////////////////////////////////
-
- // Deklariere eine Variable mit <Typ> <Name>
-
- // Sbyte - Vorzeichenbehaftete 8-Bit Ganzzahl
- // (-128 <= sbyte <= 127)
- sbyte fooSbyte = 100;
-
- // Byte - Vorzeichenlose 8-Bit Ganzzahl
- // (0 <= byte <= 255)
- byte fooByte = 100;
-
- // Short - 16-Bit Ganzzahl
- // Vorzeichenbehaftet - (-32,768 <= short <= 32,767)
- // Vorzeichenlos - (0 <= ushort <= 65,535)
- short fooShort = 10000;
- ushort fooUshort = 10000;
-
- // Integer - 32-bit Ganzzahl
- int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647)
- uint fooUint = 1; // (0 <= uint <= 4,294,967,295)
-
- // Long - 64-bit Ganzzahl
- long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
- ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615)
- // Ganze Zahlen werden standardmäßig - je nach Größe - als int oder
- // uint behandelt. Ein nachgestelltes L markiert den Wert als long
- // oder ulong.
-
- // Double - Double-precision 64-bit IEEE 754 Fließkommazahl
- double fooDouble = 123.4; // Genauigkeit: 15-16 Stellen
-
- // Float - Single-precision 32-bit IEEE 754 Fließkommazahl
- float fooFloat = 234.5f; // Genauigkeit: 7 Stellen
- // Das nachgestellte f zeigt an dass es sich um einen Wert vom Typ
- // float handelt
-
- // Decimal - ein 128-Bit-Datentyp mit größerer Genauigkeit als
- // andere Fließkommatypen, und somit bestens geeignet für
- // die Berechnung von Geld- und Finanzwerten
- decimal fooDecimal = 150.3m;
-
- // Boolean - true & false
- bool fooBoolean = true; // oder false
-
- // Char - Ein einzelnes 16-Bit Unicode Zeichen
- char fooChar = 'A';
-
- // Strings - im Gegensatz zu allen vorhergehenden Basistypen, die
- // alle Werttypen sind, ist String ein Referenztyp. Strings sind
- // somit nullable, Werttypen sind dies nicht.
- string fooString = "\"maskiere\" Anführungszeichen, und füge \n (Umbrüche) und \t (Tabs) hinzu";
- Console.WriteLine(fooString);
-
- // Jeder Buchstabe eines Strings kann über seinen Index
- // referenziert werden:
- char charFromString = fooString[1]; // => 'e'
- // Strings sind unveränderlich:
- // `fooString[1] = 'X';` funktioniert nicht
-
- // Ein Vergleich zweier Strings, unter Berücksichtigung der
- // aktuellen, sprachspezifischen Gegebenheiten (also z.B. a,ä,b,c
- // in deutschsprachigen Umgebungen), und ohne Beachtung von
- // Groß- und Kleinschreibung:
- string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase);
-
- // Formatierung, genau wie "sprintf"
- string fooFs = string.Format("Mikrofon Check, {0} {1}, {0} {1:0.0}", 1, 2);
-
- // Datumsangaben und Formatierung
- DateTime fooDate = DateTime.Now;
- Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy"));
-
- // Durch ein vorangestelltes @ lässt sich ein mehrzeiliger String
- // schreiben. Um " zu maskieren benutzt man ""
- string bazString = @"Hier geht es
-zur nächsten Zeile, ""Wahnsinn!"", die Massen waren kaum zu bändigen";
-
- // Die Keywords const oder readonly kennzeichnen eine
- // unveränderliche Variable/Konstante. Die Werte von Konstanten
- // werden übrigens bereits zur Compile-Zeit berechnet.
- const int HOURS_I_WORK_PER_WEEK = 9001;
-
- ///////////////////////////////////////////////////
- // Datenstrukturen
- ///////////////////////////////////////////////////
-
- // Arrays - Index beginnt bei Null
- // Die Größe des Arrays wird bei der Deklaration festgelegt.
- // Die syntaktische Struktur um ein neues Array zu erzeugen sieht
- // folgendermaßen aus:
- // <datatype>[] <varname> = new <datatype>[<array size>];
- int[] intArray = new int[10];
-
- // Arrays können auch über ein Array-Literal deklariert werden:
- int[] y = { 9000, 1000, 1337 };
-
- // Indizierung eines Arrays - Zugriff auf ein bestimmtes Element
- Console.WriteLine("intArray @ 0: " + intArray[0]);
- // Arrays sind veränderbar
- intArray[1] = 1;
-
- // Listen
- // Durch ihre größere Flexibilität kommen Listen in C# weit
- // häufiger zum Einsatz als Arrays. Eine Liste wird so deklariert:
- // List<datatype> <varname> = new List<datatype>();
- List<int> intList = new List<int>();
- List<string> stringList = new List<string>();
- List<int> z = new List<int> { 9000, 1000, 1337 };
- // Die <> kennzeichnen "Generics", mehr dazu unter "Coole Sachen"
-
- // Listen haben keinen Default-Wert.
- // Bevor auf einen Index zugegriffen werden kann, muss dieser
- // auch gesetzt worden sein:
- intList.Add(1);
- Console.WriteLine("intList @ 0: " + intList[0]);
-
- // Andere interessante Datenstrukturen sind:
- // Stack/Queue
- // Dictionary (entspricht einer Hash Map)
- // HashSet
- // Read-only Collections
- // Tuple (.Net 4+)
-
- ///////////////////////////////////////
- // Operatoren
- ///////////////////////////////////////
- Console.WriteLine("\n->Operatoren");
-
- // kurze Schreibweise um mehrere Deklarationen zusammenzufassen:
- // (Benutzung vom C# Styleguide aber ausdrücklich abgeraten!)
- int i1 = 1, i2 = 2;
-
- // Arithmetik funktioniert wie erwartet:
- Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3
-
- // Modulo
- Console.WriteLine("11%3 = " + (11 % 3)); // => 2
-
- // Vergleiche
- Console.WriteLine("3 == 2? " + (3 == 2)); // => false
- Console.WriteLine("3 != 2? " + (3 != 2)); // => true
- Console.WriteLine("3 > 2? " + (3 > 2)); // => true
- Console.WriteLine("3 < 2? " + (3 < 2)); // => false
- Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true
- Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true
-
- // Bitweise Operatoren
- /*
- ~ Unäres bitweises NICHT
- << Verschieben nach links
- >> Verschieben nach rechts
- & Bitweises UND
- ^ Bitweises exklusives ODER
- | Bitweises inklusives ODER
- */
-
- // Inkremente
- int i = 0;
- Console.WriteLine("\n->Inkrement / Dekrement");
- Console.WriteLine(i++); //i = 1. Post-Inkrement
- Console.WriteLine(++i); //i = 2. Pre-Inkrement
- Console.WriteLine(i--); //i = 1. Post-Dekrement
- Console.WriteLine(--i); //i = 0. Pre-Dekrement
-
- ///////////////////////////////////////
- // Kontrollstrukturen
- ///////////////////////////////////////
- Console.WriteLine("\n->Kontrollstrukturen");
-
- // If-Statements funktionieren wie in C
- int j = 10;
- if (j == 10)
- {
- Console.WriteLine("Ich werde ausgegeben");
- }
- else if (j > 10)
- {
- Console.WriteLine("Ich nicht");
- }
- else
- {
- Console.WriteLine("Ich leider auch nicht");
- }
-
- // Ternärer Operator
- // Anstatt eines einfachen if/else lässt sich auch folgendes schreiben:
- // <condition> ? <true> : <false>
- int zumVergleich = 17;
- string isTrue = zumVergleich == 17 ? "Ja" : "Nein";
-
- // while-Schleife
- int fooWhile = 0;
- while (fooWhile < 100)
- {
- // Wird 100mal wiederholt, fooWhile 0->99
- fooWhile++;
- }
-
- // do-while-Schleife
- int fooDoWhile = 0;
- do
- {
- // Wird 100mal wiederholt, fooDoWhile 0->99
- fooDoWhile++;
- } while (fooDoWhile < 100);
-
- //for-Schleifen => for(<start_statement>; <conditional>; <step>)
- for (int fooFor = 0; fooFor < 10; fooFor++)
- {
- // Wird 10mal wiederholt, fooFor 0->9
- }
-
- // foreach-Schleife
- // Die normale Syntax für eine foreach-Schleife lautet:
- // foreach(<iteratorType> <iteratorName> in <enumerable>)
- // foreach kann mit jedem Objekt verwendet werden das IEnumerable
- // oder IEnumerable<T> implementiert. Alle Auflistungs-Typen
- // (Array, List, Dictionary...) im .NET Framework implementieren
- // eines dieser beiden Interfaces.
-
- foreach (char character in "Hallo Welt".ToCharArray())
- {
- // Ein Durchgang für jedes Zeichen im String
- }
- // (ToCharArray() könnte man hier übrigens auch weglassen,
- // da String IEnumerable bereits implementiert)
-
- // Switch Struktur
- // Ein Switch funktioniert mit byte, short, char und int Datentypen.
- // Auch Aufzählungstypen können verwendet werden, genau wie
- // die Klasse String, und ein paar Sonderklassen, die Wrapper für
- // Primitives sind: Character, Byte, Short und Integer
- int month = 3;
- string monthString;
- switch (month)
- {
- case 1:
- monthString = "Januar";
- break;
- case 2:
- monthString = "Februar";
- break;
- case 3:
- monthString = "März";
- break;
- // Man kann für mehrere Fälle auch das selbe Verhalten
- // definieren. Jeder Block muss aber mit einem break-Statement
- // abgeschlossen werden. Einzelne Fälle können über
- // `goto case x` erreicht werden
- case 6:
- case 7:
- case 8:
- monthString = "Sommer!!";
- break;
- default:
- monthString = "Irgendein anderer Monat";
- break;
- }
-
- ///////////////////////////////////////
- // Umwandlung von Datentypen und Typecasting
- ///////////////////////////////////////
-
- // Umwandlung
-
- // von String nach Integer
- // bei einem Fehler wirft diese Code eine Exception
- int.Parse("123"); //gibt die Ganzzahl 123 zurück
-
- // TryParse gibt bei einem Fehler den Default-Wert zurück
- // (im Fall von int: 0)
- int tryInt;
- if (int.TryParse("123", out tryInt)) // gibt true oder false zurück
- {
- Console.WriteLine(tryInt); // 123
- }
-
- // von Integer nach String
- // Die Klasse Convert stellt Methoden zur Konvertierung von
- // unterschiedlichsten Daten zur Verfügung:
- Convert.ToString(123); // "123"
- // oder
- tryInt.ToString(); // "123"
- }
-
- ///////////////////////////////////////
- // Klassen
- ///////////////////////////////////////
- public static void Classes()
- {
-
- // Benutze das new-Keyword um eine Instanz einer Klasse zu erzeugen
- Bicycle trek = new Bicycle();
-
- // So werden Methoden der Instanz aufgerufen
- trek.SpeedUp(3); // Es empfiehlt sich immer Getter und Setter zu benutzen
- trek.Cadence = 100;
-
- // ToString ist eine Konvention über die man üblicherweiser
- // Informationen über eine Instanz erhält
- Console.WriteLine("Infos zu trek: " + trek.ToString());
-
- // Wir instantiieren ein neues Hochrad
- PennyFarthing funbike = new PennyFarthing(1, 10);
- Console.WriteLine("Infos zu funbike: " + funbike.ToString());
-
- Console.Read();
- } // Ende der Methode main
-
- // Main als Konsolenstartpunkt
- // Eine Konsolenanwendung muss eine Methode Main als Startpunkt besitzen
- public static void Main(string[] args)
- {
- OtherInterestingFeatures();
- }
-
- ///////////////////////////////////////
- // Interessante Features
- ///////////////////////////////////////
-
- // Methodensignaturen
-
- public // Sichtbarkeit
- static // Erlaubt einen Zugriff auf der Klasse (nicht auf einer Instanz)
- int // Typ des Rückgabewerts,
- MethodSignatures(
- // Erstes Argument, erwartet int
- int maxCount,
- // setzt sich selbst auf 0 wenn kein anderer Wert übergeben wird
- int count = 0,
- int another = 3,
- // enthält alle weiteren der Methode übergebenen Parameter (quasi Splats)
- params string[] otherParams
- )
- {
- return -1;
- }
-
- // Methoden können überladen werden, solange sie eindeutige
- // Signaturen haben
- public static void MethodSignatures(string maxCount)
- {
- }
-
- // Generische Typen
- // Die Typen für TKey und TValue werden erst beim Aufruf der Methode
- // festgelegt. Diese Methode emuliert z.B. SetDefault aus Python:
- public static TValue SetDefault<TKey, TValue>(
- IDictionary<TKey, TValue> dictionary,
- TKey key,
- TValue defaultItem)
- {
- TValue result;
- if (!dictionary.TryGetValue(key, out result))
- {
- return dictionary[key] = defaultItem;
- }
- return result;
- }
-
- // Möglichen Typen lassen sich auch über ihr Interface beschränken:
- public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int>
- {
- // Da T ein IEnumerable ist können wir foreach benutzen
- foreach (var item in toPrint)
- {
- // Item ist ein int
- Console.WriteLine(item.ToString());
- }
- }
-
- public static void OtherInterestingFeatures()
- {
- // Optionale Parameter
- MethodSignatures(3, 1, 3, "Ein paar", "extra", "Strings");
- // setzt explizit einen bestimmten Parameter, andere werden übersprungen
- MethodSignatures(3, another: 3);
-
- // Erweiterungsmethoden
- int i = 3;
- i.Print(); // Weiter unten definiert
-
- // Nullables - perfekt für die Interaktion mit
- // Datenbanken / Rückgabewerten
- // Jeder Wert (d.h. keine Klassen) kann durch das Nachstellen eines ?
- // nullable gemacht werden: <type>? <varname> = <value>
- int? nullable = null; // Die explizite Langform wäre Nullable<int>
- Console.WriteLine("Mein Nullable: " + nullable);
- bool hasValue = nullable.HasValue; // true wenn nicht null
-
- // ?? ist "syntaktischer Zucker" um einen Defaultwert für den Fall
- // dass die Variable null ist festzulegen.
- int notNullable = nullable ?? 0; // 0
-
- // Implizit typisierte Variablen
- // Man kann auch den Typ einer Variable auch vom Compiler
- // bestimmen lassen:
- var magic = "magic ist zur Compile-Zeit ein String, folglich geht keine Typsicherheit verloren";
- magic = 9; // funktioniert nicht da magic vom Typ String ist
-
- // Generics
- var phonebook = new Dictionary<string, string>() {
- {"Resi", "08822 / 43 67"} // Fügt einen Eintrag zum Telefonbuch hinzu
- };
-
- // Hier könnte man auch unser generisches SetDefault von
- // weiter oben benutzen:
- Console.WriteLine(SetDefault<string,string>(phonebook, "Xaver", "kein Telefon")); // kein Telefon
- // TKey und TValue müssen nicht zwingend angegeben werden, da sie
- // auch implizit vom Compiler ermittelt werden können
- Console.WriteLine(SetDefault(phonebook, "Resi", "kein Telefon")); // 08822 / 43 67
-
- // Lambdas - konzise Syntax für Inline-Funktionen
- Func<int, int> square = (x) => x * x; // Das letzte Element vom Typ T ist der Rückgabewert
- Console.WriteLine(square(3)); // 9
-
- // Disposables - einfaches Management von nicht verwalteten Ressourcen
- // So gut wie alle Objekte die auf nicht verwaltete Ressourcen
- // (Dateien, Geräte, ...) zugreifen, implementieren das Interface
- // IDisposable. Das using Statement stellt sicher dass die vom
- // IDisposable benutzten Ressourcen nach der Benutzung wieder
- // freigegeben werden:
- using (StreamWriter writer = new StreamWriter("log.txt"))
- {
- writer.WriteLine("Alles bestens!");
- // Am Ende des Codeblocks werden die Ressourcen wieder
- // freigegeben - auch im Falle einer Exception
- }
-
- // Parallel Klasse
- // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx
- var websites = new string[] {
- "http://www.google.com", "http://www.reddit.com",
- "http://www.shaunmccarthy.com"
- };
- var responses = new Dictionary<string, string>();
-
- // Für jeden Request wird ein neuer Thread erzeugt, der nächste
- // Schritt wird erst nach Beendigung aller Tasks ausgeführt
- Parallel.ForEach(websites,
- // maximal 3 Threads gleichzeitig
- new ParallelOptions() {MaxDegreeOfParallelism = 3},
- website =>
- {
- // Hier folgt eine langwierige, asynchrone Operation
- using (var r = WebRequest.Create(new Uri(website)).GetResponse())
- {
- responses[website] = r.ContentType;
- }
- });
-
- // Dieser Code wird erst nach Beendigung aller Requests ausgeführt
- foreach (var key in responses.Keys)
- {
- Console.WriteLine("{0}:{1}", key, responses[key]);
- }
-
- // Dynamische Objekte (gut um mit anderen Sprachen zu arbeiten)
- dynamic student = new ExpandoObject();
- // hier muss keine Typ angegeben werden
- student.FirstName = "Christian";
-
- // Einem solchen Objekt kann man sogar Methoden zuordnen.
- // Das Beispiel gibt einen String zurück und erwartet einen String
- student.Introduce = new Func<string, string>(
- (introduceTo) => string.Format("Hallo {0}, das ist {1}", student.FirstName, introduceTo));
- Console.WriteLine(student.Introduce("Bettina"));
-
- // IQueryable<T> - So gut wie alle Aufzählungstypen implementieren
- // dieses Interface, welches eine Vielzahl von funktionalen Methoden
- // wie Map / Filter / Reduce zur Verfügung stellt:
- var bikes = new List<Bicycle>();
- // sortiert die Liste
- bikes.Sort();
- // sortiert nach Anzahl Räder
- bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels));
- var result = bikes
- // diese Filter können auch aneinandergehängt werden
- .Where(b => b.Wheels > 3) // (gibt ein IQueryable des vorherigen Typs zurück)
- .Where(b => b.IsBroken && b.HasTassles)
- // diese Zuordnung gibt ein IQueryable<String> zurück
- .Select(b => b.ToString());
-
- // "Reduce" - addiert alle Räder der Aufzählung zu einem Wert
- var sum = bikes.Sum(b => b.Wheels);
-
- // So erzeugt man ein implizit typisiertes Objekt, basierend auf
- // den Parametern der Elemente:
- var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles });
- // Auch wenn wir es hier nicht demonstrieren können:
- // In einer IDE wie VisualStudio kriegen wir hier sogar TypeAhead,
- // da der Compiler in der Lage ist, die passenden Typen zu erkennen.
- foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome))
- {
- Console.WriteLine(bikeSummary.Name);
- }
-
- // AsParallel-Methode
- // Jetzt kommen die Schmankerl! Die AsParallel-Methode kombiniert
- // LINQ und parallele Operationen:
- var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name);
- // Diese Berechnung passiert parallel! Benötigte Threads werden
- // automatisch erzeugt, und die Rechenlast unter ihnen aufgeteilt.
- // Ein Traum für die Verarbeitung von großen Datenmengen
- // auf mehreren Cores!
-
- // LINQ - bildet einen Datenspeicher auf IQueryable<T> Objekte ab
- // LinqToSql beispielsweise speichert und liest aus einer
- // SQL-Datenbank, LinqToXml aus einem XML-Dokument.
- // LINQ-Operationen werden "lazy" ausgeführt.
- var db = new BikeRepository();
-
- // Die verzögerte Ausführung ist optimal für Datenbankabfragen
- var filter = db.Bikes.Where(b => b.HasTassles); // noch keine Abfrage
- // Es können noch mehr Filter hinzugefügt werden (auch mit
- // Bedingungen) - ideal für z.B. "erweiterte Suchen"
- if (42 > 6)
- {
- filter = filter.Where(b => b.IsBroken); // immer noch keine Abfrage
- }
-
- var query = filter
- .OrderBy(b => b.Wheels)
- .ThenBy(b => b.Name)
- .Select(b => b.Name); // auch hier: immer noch keine Abfrage
-
- // Erst hier wird die Datenbankabfrage wirklich ausgeführt,
- // limitiert auf die Elemente die der foreach-Loop verwendet
- foreach (string bike in query)
- {
- Console.WriteLine(result);
- }
-
- }
-
- } // Ende der Klasse LearnCSharp
-
- // Eine .cs-Datei kann auch mehrere Klassen enthalten
-
- public static class Extensions
- {
- // Erweiterungsmethoden
- public static void Print(this object obj)
- {
- Console.WriteLine(obj.ToString());
- }
- }
-
- // Syntax zur Deklaration einer Klasse:
- // <public/private/protected/internal> class <class name>{
- // // Datenfelder, Konstruktoren und Methoden leben alle
- // // innerhalb dieser Deklaration
- // }
-
- public class Bicycle
- {
- // Felder/Variablen der Klasse "Bicycle"
- // Das Keyword public macht das Member von überall zugänglich
- public int Cadence
- {
- get // get definiert eine Methode um die Eigenschaft abzurufen
- {
- return _cadence;
- }
- set // set definiert eine Methode um die Eigenschaft zu setzen
- {
- _cadence = value; // value ist der dem Setter übergebene Wert
- }
- }
- private int _cadence;
-
- // Das Keyword protected macht das Member nur für die Klasse selbst
- // und ihre Subklassen zugänglich
- protected virtual int Gear
- {
- get; // erzeugt eine Eigenschaft für die kein "Zwischenwert" benötigt wird
- set;
- }
-
- // Das Keyword internal macht das Member innerhalb der Assembly zugänglich
- internal int Wheels
- {
- get;
- private set; // get/set kann auch über Keywords modifiziert werden
- }
-
- int _speed; // Member ohne vorangestellte Keywords sind standardmäßig
- // private, sie sind nur innerhalb der Klasse zugänglich.
- // Man kann aber natürlich auch das Keyword private benutzen.
- private string Name { get; set; }
-
- // Ein Enum ist ein klar definierter Satz an benannten Konstanten.
- // Eigentlich ordnet es diese Konstanten nur bestimmten Werten zu
- // (einer int-Zahl, solange nicht anders angegeben). Mögliche Typen für
- // die Werte eines Enums sind byte, sbyte, short, ushort, int, uint,
- // long, oder ulong. Alle Werte in einem Enum sind eindeutig.
- public enum BikeBrand
- {
- Colnago,
- EddyMerckx,
- Bianchi = 42, // so kann man den Wert explizit setzen
- Kynast // 43
- }
- // Nachdem dieser Typ in der Klasse "Bicycle" definiert ist,
- // sollte Code ausserhalb der Klasse den Typen als Bicycle.Brand referenzieren
-
- // Nachdem das Enum deklariert ist, können wir den Typen verwenden:
- public BikeBrand Brand;
-
- // Als static gekennzeichnete Member gehören dem Typ selbst,
- // nicht seinen Instanzen. Man kann sie also ohne Referenz zu einem
- // Objekt benutzen
- // Console.WriteLine("Schon " + Bicycle.BicyclesCreated + " Fahrräder, nur für dieses Tutorial!");
- static public int BicyclesCreated = 0;
-
- // readonly-Werte werden zur Laufzeit gesetzt
- // Ihr Wert kann nur bei ihrer Deklaration, oder in einem Konstruktor
- // festgelegt werden
- readonly bool _hasCardsInSpokes = false; // readonly und private
-
- // Konstruktoren bestimmen was bei einer Instantiierung passiert.
- // Das ist ein Default-Konstruktor:
- public Bicycle()
- {
- // Member der Klasse können über das Keyword this erreicht werden
- this.Gear = 1;
- // oft ist das aber gar nicht nötig
- Cadence = 50;
- _speed = 5;
- Name = "Bonanzarad";
- Brand = BikeBrand.Kynast;
- BicyclesCreated++;
- }
-
- // Das ist ein spezifischer Konstruktor (d.h. er erwartet Argumente):
- public Bicycle(int startCadence, int startSpeed, int startGear,
- string name, bool hasCardsInSpokes, BikeBrand brand)
- : base() // ruft zuerst den "base"-Konstruktor auf
- {
- Gear = startGear;
- Cadence = startCadence;
- _speed = startSpeed;
- Name = name;
- _hasCardsInSpokes = hasCardsInSpokes;
- Brand = brand;
- }
-
- // Konstruktoren können aneinandergehängt werden:
- public Bicycle(int startCadence, int startSpeed, BikeBrand brand) :
- this(startCadence, startSpeed, 0, "richtig große Räder", true, brand)
- {
- }
-
- // Syntax für Methoden:
- // <public/private/protected> <return type> <function name>(<args>)
-
- // Klassen können Getter und Setter für Werte definieren,
- // oder diese Werte direkt als Eigenschaft implementieren
- // (in C# der bevorzugte Weg)
-
- // Parameter von Methoden können Default-Werte haben.
- // "SpeedUp" kann man also auch ohne Parameter aufrufen:
- public void SpeedUp(int increment = 1)
- {
- _speed += increment;
- }
-
- public void SlowDown(int decrement = 1)
- {
- _speed -= decrement;
- }
-
- // Eigenschaften mit get/set
- // wenn es nur um den Zugriff auf Daten geht, ist eine Eigenschaft zu
- // empfehlen. Diese können Getter und Setter haben, oder auch nur
- // einen Getter bzw. einen Setter
- private bool _hasTassles; // private Variable
- public bool HasTassles // öffentliches Interface
- {
- get { return _hasTassles; }
- set { _hasTassles = value; }
- }
-
- // Das kann man auch kürzer schreiben:
- // Dieser Syntax erzeugt automatisch einen hinterlegten Wert,
- // (entsprechend `private bool _isBroken`) der gesetzt
- // bzw. zurückgegeben wird:
- public bool IsBroken { get; private set; }
- public int FrameSize
- {
- get;
- // für Getter und Setter kann der Zugriff auch einzeln
- // beschränkt werden, FrameSize kann also nur von innerhalb
- // der Klasse "Bicycle" gesetzt werden
- private set;
- }
-
- // Diese Methode gibt eine Reihe an Informationen über das Objekt aus:
- public virtual string ToString()
- {
- return "Gang: " + Gear +
- " Kadenz: " + Cadence +
- " Geschwindigkeit: " + _speed +
- " Name: " + Name +
- " Hipster-Karten zwischen den Speichen: " + (_hasCardsInSpokes ? "Na klar!" : "Bloß nicht!") +
- "\n------------------------------\n"
- ;
- }
-
- // Auch Methoden können als static gekennzeichnet werden, nützlich
- // beispielsweise für Helper-Methoden
- public static bool DidWeCreateEnoughBicyclesYet()
- {
- // In einer statischen Methode können wir natürlich auch nur
- // statische Member der Klasse referenzieren
- return BicyclesCreated > 9000;
- }
- // Wenn eine Klasse nur statische Member enthält, kann es eine gute Idee
- // sein die Klasse selbst als static zu kennzeichnen
-
- } // Ende der Klasse "Bicycle"
-
- // "PennyFarthing" ist eine Unterklasse von "Bicycle"
- class PennyFarthing : Bicycle
- {
- // (Hochräder - englisch Penny Farthing - sind diese antiken Fahrräder
- // mit riesigem Vorderrad. Sie haben keine Gangschaltung.)
-
- // hier wird einfach der Elternkonstruktor aufgerufen
- public PennyFarthing(int startCadence, int startSpeed) :
- base(startCadence, startSpeed, 0, "Hochrad", true, BikeBrand.EddyMerckx)
- {
- }
-
- protected override int Gear
- {
- get
- {
- return 0;
- }
- set
- {
- throw new ArgumentException("Ein Hochrad hat keine Gangschaltung, doh!");
- }
- }
-
- public override string ToString()
- {
- string result = "Hochrad ";
- result += base.ToString(); // ruft die "base"-Version der Methode auf
- return result;
- }
- }
-
- // Interfaces (auch Schnittstellen genant) definieren nur die Signaturen
- // ihrer Member, enthalten aber auf keinen Fall ihre Implementierung:
- interface IJumpable
- {
- // Alle Member eines Interfaces sind implizit public
- void Jump(int meters);
- }
-
- interface IBreakable
- {
- // Interfaces können Eigenschaften, Methoden und Events definieren
- bool Broken { get; }
- }
-
- // Eine Klasse kann nur von einer Klasse erben, kann aber eine beliebige
- // Anzahl von Interfaces implementieren
- class MountainBike : Bicycle, IJumpable, IBreakable
- {
- int damage = 0;
-
- public void Jump(int meters)
- {
- damage += meters;
- }
-
- public bool Broken
- {
- get
- {
- return damage > 100;
- }
- }
- }
-
- // Das hier stellt eine Datenbankverbindung für das LinqToSql-Beispiel her.
- // EntityFramework Code First ist großartig
- // (ähnlich zu Ruby's ActiveRecord, aber bidirektional)
- // http://msdn.microsoft.com/de-de/data/jj193542.aspx
- public class BikeRepository : DbSet
- {
- public BikeRepository()
- : base()
- {
- }
-
- public DbSet<Bicycle> Bikes { get; set; }
- }
-} // Ende des Namespaces
-```
-
-## In dieser Übersicht nicht enthalten sind die Themen:
-
- * Flags
- * Attributes
- * Statische Eigenschaften
- * Exceptions, Abstraction
- * ASP.NET (Web Forms/MVC/WebMatrix)
- * Winforms
- * Windows Presentation Foundation (WPF)
-
-## Zum Weiterlesen gibt es viele gute Anlaufpunkte:
-
- * [DotNetPerls](http://www.dotnetperls.com)
- * [C# in Depth](http://manning.com/skeet2)
- * [Programming C#](http://shop.oreilly.com/product/0636920024064.do)
- * [LINQ](http://shop.oreilly.com/product/9780596519254.do)
- * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx)
- * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials)
- * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/overview/exploring-webmatrix)
- * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials)
- * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208)
-
-[C# Coding Conventions](http://msdn.microsoft.com/de-de/library/vstudio/ff926074.aspx)
+--- +language: C# +contributors: + - ["Irfan Charania", "https://github.com/irfancharania"] + - ["Max Yankov", "https://github.com/golergka"] + - ["Melvyn Laïly", "http://x2a.yt"] + - ["Shaun McCarthy", "http://www.shaunmccarthy.com"] +translators: + - ["Frederik Ring", "https://github.com/m90"] +filename: LearnCSharp-de.cs +lang: de-de +--- +C# ist eine elegante, typsichere und objektorientierte Sprache, mit der Entwickler eine Vielzahl sicherer und robuster Anwendungen erstellen können, die im .NET Framework ausgeführt werden. + +[Mehr über C# erfährst du hier.](http://msdn.microsoft.com/de-de/library/vstudio/z1zx9t92.aspx) + +```c# +// Einzeilige Kommentare starten mit zwei Schrägstrichen: // +/* +Mehrzeile Kommentare wie in C Schrägstrich / Stern +*/ +/// <summary> +/// XML-Kommentare können zur automatisierten Dokumentation verwendet werden +/// </summary> + +// Zu Beginn werden die in der Datei verwendeten Namespaces aufgeführt +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Net; +using System.Threading.Tasks; +using System.IO; + +// definiert einen Namespace um Code in "packages" zu organisieren +namespace Learning +{ + // Jede .cs-Datei sollte zumindest eine Klasse mit dem Namen der Datei + // enthalten. Das ist zwar nicht zwingend erforderlich, es anders zu + // handhaben führt aber unweigerlich ins Chaos (wirklich)! + public class LearnCSharp + { + // Zuerst erklärt dieses Tutorial die Syntax-Grundlagen, + // wenn du bereits Java oder C++ programmieren kannst: + // lies bei "Interessante Features" weiter! + public static void Syntax() + { + // Mit Console.WriteLine kannst du einfachen Text ausgeben: + Console.WriteLine("Hallo Welt"); + Console.WriteLine( + "Integer: " + 10 + + " Double: " + 3.14 + + " Boolean: " + true); + + // Console.Write erzeugt keinen Zeilenumbruch + Console.Write("Hallo "); + Console.Write("Welt"); + + /////////////////////////////////////////////////// + // Typen & Variablen + /////////////////////////////////////////////////// + + // Deklariere eine Variable mit <Typ> <Name> + + // Sbyte - Vorzeichenbehaftete 8-Bit Ganzzahl + // (-128 <= sbyte <= 127) + sbyte fooSbyte = 100; + + // Byte - Vorzeichenlose 8-Bit Ganzzahl + // (0 <= byte <= 255) + byte fooByte = 100; + + // Short - 16-Bit Ganzzahl + // Vorzeichenbehaftet - (-32,768 <= short <= 32,767) + // Vorzeichenlos - (0 <= ushort <= 65,535) + short fooShort = 10000; + ushort fooUshort = 10000; + + // Integer - 32-bit Ganzzahl + int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647) + uint fooUint = 1; // (0 <= uint <= 4,294,967,295) + + // Long - 64-bit Ganzzahl + long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) + ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615) + // Ganze Zahlen werden standardmäßig - je nach Größe - als int oder + // uint behandelt. Ein nachgestelltes L markiert den Wert als long + // oder ulong. + + // Double - Double-precision 64-bit IEEE 754 Fließkommazahl + double fooDouble = 123.4; // Genauigkeit: 15-16 Stellen + + // Float - Single-precision 32-bit IEEE 754 Fließkommazahl + float fooFloat = 234.5f; // Genauigkeit: 7 Stellen + // Das nachgestellte f zeigt an dass es sich um einen Wert vom Typ + // float handelt + + // Decimal - ein 128-Bit-Datentyp mit größerer Genauigkeit als + // andere Fließkommatypen, und somit bestens geeignet für + // die Berechnung von Geld- und Finanzwerten + decimal fooDecimal = 150.3m; + + // Boolean - true & false + bool fooBoolean = true; // oder false + + // Char - Ein einzelnes 16-Bit Unicode Zeichen + char fooChar = 'A'; + + // Strings - im Gegensatz zu allen vorhergehenden Basistypen, die + // alle Werttypen sind, ist String ein Referenztyp. Strings sind + // somit nullable, Werttypen sind dies nicht. + string fooString = "\"maskiere\" Anführungszeichen, und füge \n (Umbrüche) und \t (Tabs) hinzu"; + Console.WriteLine(fooString); + + // Jeder Buchstabe eines Strings kann über seinen Index + // referenziert werden: + char charFromString = fooString[1]; // => 'e' + // Strings sind unveränderlich: + // `fooString[1] = 'X';` funktioniert nicht + + // Ein Vergleich zweier Strings, unter Berücksichtigung der + // aktuellen, sprachspezifischen Gegebenheiten (also z.B. a,ä,b,c + // in deutschsprachigen Umgebungen), und ohne Beachtung von + // Groß- und Kleinschreibung: + string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase); + + // Formatierung, genau wie "sprintf" + string fooFs = string.Format("Mikrofon Check, {0} {1}, {0} {1:0.0}", 1, 2); + + // Datumsangaben und Formatierung + DateTime fooDate = DateTime.Now; + Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); + + // Durch ein vorangestelltes @ lässt sich ein mehrzeiliger String + // schreiben. Um " zu maskieren benutzt man "" + string bazString = @"Hier geht es +zur nächsten Zeile, ""Wahnsinn!"", die Massen waren kaum zu bändigen"; + + // Die Keywords const oder readonly kennzeichnen eine + // unveränderliche Variable/Konstante. Die Werte von Konstanten + // werden übrigens bereits zur Compile-Zeit berechnet. + const int HOURS_I_WORK_PER_WEEK = 9001; + + /////////////////////////////////////////////////// + // Datenstrukturen + /////////////////////////////////////////////////// + + // Arrays - Index beginnt bei Null + // Die Größe des Arrays wird bei der Deklaration festgelegt. + // Die syntaktische Struktur um ein neues Array zu erzeugen sieht + // folgendermaßen aus: + // <datatype>[] <varname> = new <datatype>[<array size>]; + int[] intArray = new int[10]; + + // Arrays können auch über ein Array-Literal deklariert werden: + int[] y = { 9000, 1000, 1337 }; + + // Indizierung eines Arrays - Zugriff auf ein bestimmtes Element + Console.WriteLine("intArray @ 0: " + intArray[0]); + // Arrays sind veränderbar + intArray[1] = 1; + + // Listen + // Durch ihre größere Flexibilität kommen Listen in C# weit + // häufiger zum Einsatz als Arrays. Eine Liste wird so deklariert: + // List<datatype> <varname> = new List<datatype>(); + List<int> intList = new List<int>(); + List<string> stringList = new List<string>(); + List<int> z = new List<int> { 9000, 1000, 1337 }; + // Die <> kennzeichnen "Generics", mehr dazu unter "Coole Sachen" + + // Listen haben keinen Default-Wert. + // Bevor auf einen Index zugegriffen werden kann, muss dieser + // auch gesetzt worden sein: + intList.Add(1); + Console.WriteLine("intList @ 0: " + intList[0]); + + // Andere interessante Datenstrukturen sind: + // Stack/Queue + // Dictionary (entspricht einer Hash Map) + // HashSet + // Read-only Collections + // Tuple (.Net 4+) + + /////////////////////////////////////// + // Operatoren + /////////////////////////////////////// + Console.WriteLine("\n->Operatoren"); + + // kurze Schreibweise um mehrere Deklarationen zusammenzufassen: + // (Benutzung vom C# Styleguide aber ausdrücklich abgeraten!) + int i1 = 1, i2 = 2; + + // Arithmetik funktioniert wie erwartet: + Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3 + + // Modulo + Console.WriteLine("11%3 = " + (11 % 3)); // => 2 + + // Vergleiche + Console.WriteLine("3 == 2? " + (3 == 2)); // => false + Console.WriteLine("3 != 2? " + (3 != 2)); // => true + Console.WriteLine("3 > 2? " + (3 > 2)); // => true + Console.WriteLine("3 < 2? " + (3 < 2)); // => false + Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true + Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true + + // Bitweise Operatoren + /* + ~ Unäres bitweises NICHT + << Verschieben nach links + >> Verschieben nach rechts + & Bitweises UND + ^ Bitweises exklusives ODER + | Bitweises inklusives ODER + */ + + // Inkremente + int i = 0; + Console.WriteLine("\n->Inkrement / Dekrement"); + Console.WriteLine(i++); //i = 1. Post-Inkrement + Console.WriteLine(++i); //i = 2. Pre-Inkrement + Console.WriteLine(i--); //i = 1. Post-Dekrement + Console.WriteLine(--i); //i = 0. Pre-Dekrement + + /////////////////////////////////////// + // Kontrollstrukturen + /////////////////////////////////////// + Console.WriteLine("\n->Kontrollstrukturen"); + + // If-Statements funktionieren wie in C + int j = 10; + if (j == 10) + { + Console.WriteLine("Ich werde ausgegeben"); + } + else if (j > 10) + { + Console.WriteLine("Ich nicht"); + } + else + { + Console.WriteLine("Ich leider auch nicht"); + } + + // Ternärer Operator + // Anstatt eines einfachen if/else lässt sich auch folgendes schreiben: + // <condition> ? <true> : <false> + int zumVergleich = 17; + string isTrue = zumVergleich == 17 ? "Ja" : "Nein"; + + // while-Schleife + int fooWhile = 0; + while (fooWhile < 100) + { + // Wird 100mal wiederholt, fooWhile 0->99 + fooWhile++; + } + + // do-while-Schleife + int fooDoWhile = 0; + do + { + // Wird 100mal wiederholt, fooDoWhile 0->99 + fooDoWhile++; + } while (fooDoWhile < 100); + + //for-Schleifen => for(<start_statement>; <conditional>; <step>) + for (int fooFor = 0; fooFor < 10; fooFor++) + { + // Wird 10mal wiederholt, fooFor 0->9 + } + + // foreach-Schleife + // Die normale Syntax für eine foreach-Schleife lautet: + // foreach(<iteratorType> <iteratorName> in <enumerable>) + // foreach kann mit jedem Objekt verwendet werden das IEnumerable + // oder IEnumerable<T> implementiert. Alle Auflistungs-Typen + // (Array, List, Dictionary...) im .NET Framework implementieren + // eines dieser beiden Interfaces. + + foreach (char character in "Hallo Welt".ToCharArray()) + { + // Ein Durchgang für jedes Zeichen im String + } + // (ToCharArray() könnte man hier übrigens auch weglassen, + // da String IEnumerable bereits implementiert) + + // Switch Struktur + // Ein Switch funktioniert mit byte, short, char und int Datentypen. + // Auch Aufzählungstypen können verwendet werden, genau wie + // die Klasse String, und ein paar Sonderklassen, die Wrapper für + // Primitives sind: Character, Byte, Short und Integer + int month = 3; + string monthString; + switch (month) + { + case 1: + monthString = "Januar"; + break; + case 2: + monthString = "Februar"; + break; + case 3: + monthString = "März"; + break; + // Man kann für mehrere Fälle auch das selbe Verhalten + // definieren. Jeder Block muss aber mit einem break-Statement + // abgeschlossen werden. Einzelne Fälle können über + // `goto case x` erreicht werden + case 6: + case 7: + case 8: + monthString = "Sommer!!"; + break; + default: + monthString = "Irgendein anderer Monat"; + break; + } + + /////////////////////////////////////// + // Umwandlung von Datentypen und Typecasting + /////////////////////////////////////// + + // Umwandlung + + // von String nach Integer + // bei einem Fehler wirft diese Code eine Exception + int.Parse("123"); //gibt die Ganzzahl 123 zurück + + // TryParse gibt bei einem Fehler den Default-Wert zurück + // (im Fall von int: 0) + int tryInt; + if (int.TryParse("123", out tryInt)) // gibt true oder false zurück + { + Console.WriteLine(tryInt); // 123 + } + + // von Integer nach String + // Die Klasse Convert stellt Methoden zur Konvertierung von + // unterschiedlichsten Daten zur Verfügung: + Convert.ToString(123); // "123" + // oder + tryInt.ToString(); // "123" + } + + /////////////////////////////////////// + // Klassen + /////////////////////////////////////// + public static void Classes() + { + + // Benutze das new-Keyword um eine Instanz einer Klasse zu erzeugen + Bicycle trek = new Bicycle(); + + // So werden Methoden der Instanz aufgerufen + trek.SpeedUp(3); // Es empfiehlt sich immer Getter und Setter zu benutzen + trek.Cadence = 100; + + // ToString ist eine Konvention über die man üblicherweiser + // Informationen über eine Instanz erhält + Console.WriteLine("Infos zu trek: " + trek.ToString()); + + // Wir instantiieren ein neues Hochrad + PennyFarthing funbike = new PennyFarthing(1, 10); + Console.WriteLine("Infos zu funbike: " + funbike.ToString()); + + Console.Read(); + } // Ende der Methode main + + // Main als Konsolenstartpunkt + // Eine Konsolenanwendung muss eine Methode Main als Startpunkt besitzen + public static void Main(string[] args) + { + OtherInterestingFeatures(); + } + + /////////////////////////////////////// + // Interessante Features + /////////////////////////////////////// + + // Methodensignaturen + + public // Sichtbarkeit + static // Erlaubt einen Zugriff auf der Klasse (nicht auf einer Instanz) + int // Typ des Rückgabewerts, + MethodSignatures( + // Erstes Argument, erwartet int + int maxCount, + // setzt sich selbst auf 0 wenn kein anderer Wert übergeben wird + int count = 0, + int another = 3, + // enthält alle weiteren der Methode übergebenen Parameter (quasi Splats) + params string[] otherParams + ) + { + return -1; + } + + // Methoden können überladen werden, solange sie eindeutige + // Signaturen haben + public static void MethodSignatures(string maxCount) + { + } + + // Generische Typen + // Die Typen für TKey und TValue werden erst beim Aufruf der Methode + // festgelegt. Diese Methode emuliert z.B. SetDefault aus Python: + public static TValue SetDefault<TKey, TValue>( + IDictionary<TKey, TValue> dictionary, + TKey key, + TValue defaultItem) + { + TValue result; + if (!dictionary.TryGetValue(key, out result)) + { + return dictionary[key] = defaultItem; + } + return result; + } + + // Möglichen Typen lassen sich auch über ihr Interface beschränken: + public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int> + { + // Da T ein IEnumerable ist können wir foreach benutzen + foreach (var item in toPrint) + { + // Item ist ein int + Console.WriteLine(item.ToString()); + } + } + + public static void OtherInterestingFeatures() + { + // Optionale Parameter + MethodSignatures(3, 1, 3, "Ein paar", "extra", "Strings"); + // setzt explizit einen bestimmten Parameter, andere werden übersprungen + MethodSignatures(3, another: 3); + + // Erweiterungsmethoden + int i = 3; + i.Print(); // Weiter unten definiert + + // Nullables - perfekt für die Interaktion mit + // Datenbanken / Rückgabewerten + // Jeder Wert (d.h. keine Klassen) kann durch das Nachstellen eines ? + // nullable gemacht werden: <type>? <varname> = <value> + int? nullable = null; // Die explizite Langform wäre Nullable<int> + Console.WriteLine("Mein Nullable: " + nullable); + bool hasValue = nullable.HasValue; // true wenn nicht null + + // ?? ist "syntaktischer Zucker" um einen Defaultwert für den Fall + // dass die Variable null ist festzulegen. + int notNullable = nullable ?? 0; // 0 + + // Implizit typisierte Variablen + // Man kann auch den Typ einer Variable auch vom Compiler + // bestimmen lassen: + var magic = "magic ist zur Compile-Zeit ein String, folglich geht keine Typsicherheit verloren"; + magic = 9; // funktioniert nicht da magic vom Typ String ist + + // Generics + var phonebook = new Dictionary<string, string>() { + {"Resi", "08822 / 43 67"} // Fügt einen Eintrag zum Telefonbuch hinzu + }; + + // Hier könnte man auch unser generisches SetDefault von + // weiter oben benutzen: + Console.WriteLine(SetDefault<string,string>(phonebook, "Xaver", "kein Telefon")); // kein Telefon + // TKey und TValue müssen nicht zwingend angegeben werden, da sie + // auch implizit vom Compiler ermittelt werden können + Console.WriteLine(SetDefault(phonebook, "Resi", "kein Telefon")); // 08822 / 43 67 + + // Lambdas - konzise Syntax für Inline-Funktionen + Func<int, int> square = (x) => x * x; // Das letzte Element vom Typ T ist der Rückgabewert + Console.WriteLine(square(3)); // 9 + + // Disposables - einfaches Management von nicht verwalteten Ressourcen + // So gut wie alle Objekte die auf nicht verwaltete Ressourcen + // (Dateien, Geräte, ...) zugreifen, implementieren das Interface + // IDisposable. Das using Statement stellt sicher dass die vom + // IDisposable benutzten Ressourcen nach der Benutzung wieder + // freigegeben werden: + using (StreamWriter writer = new StreamWriter("log.txt")) + { + writer.WriteLine("Alles bestens!"); + // Am Ende des Codeblocks werden die Ressourcen wieder + // freigegeben - auch im Falle einer Exception + } + + // Parallel Klasse + // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx + var websites = new string[] { + "http://www.google.com", "http://www.reddit.com", + "http://www.shaunmccarthy.com" + }; + var responses = new Dictionary<string, string>(); + + // Für jeden Request wird ein neuer Thread erzeugt, der nächste + // Schritt wird erst nach Beendigung aller Tasks ausgeführt + Parallel.ForEach(websites, + // maximal 3 Threads gleichzeitig + new ParallelOptions() {MaxDegreeOfParallelism = 3}, + website => + { + // Hier folgt eine langwierige, asynchrone Operation + using (var r = WebRequest.Create(new Uri(website)).GetResponse()) + { + responses[website] = r.ContentType; + } + }); + + // Dieser Code wird erst nach Beendigung aller Requests ausgeführt + foreach (var key in responses.Keys) + { + Console.WriteLine("{0}:{1}", key, responses[key]); + } + + // Dynamische Objekte (gut um mit anderen Sprachen zu arbeiten) + dynamic student = new ExpandoObject(); + // hier muss keine Typ angegeben werden + student.FirstName = "Christian"; + + // Einem solchen Objekt kann man sogar Methoden zuordnen. + // Das Beispiel gibt einen String zurück und erwartet einen String + student.Introduce = new Func<string, string>( + (introduceTo) => string.Format("Hallo {0}, das ist {1}", student.FirstName, introduceTo)); + Console.WriteLine(student.Introduce("Bettina")); + + // IQueryable<T> - So gut wie alle Aufzählungstypen implementieren + // dieses Interface, welches eine Vielzahl von funktionalen Methoden + // wie Map / Filter / Reduce zur Verfügung stellt: + var bikes = new List<Bicycle>(); + // sortiert die Liste + bikes.Sort(); + // sortiert nach Anzahl Räder + bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); + var result = bikes + // diese Filter können auch aneinandergehängt werden + .Where(b => b.Wheels > 3) // (gibt ein IQueryable des vorherigen Typs zurück) + .Where(b => b.IsBroken && b.HasTassles) + // diese Zuordnung gibt ein IQueryable<String> zurück + .Select(b => b.ToString()); + + // "Reduce" - addiert alle Räder der Aufzählung zu einem Wert + var sum = bikes.Sum(b => b.Wheels); + + // So erzeugt man ein implizit typisiertes Objekt, basierend auf + // den Parametern der Elemente: + var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles }); + // Auch wenn wir es hier nicht demonstrieren können: + // In einer IDE wie VisualStudio kriegen wir hier sogar TypeAhead, + // da der Compiler in der Lage ist, die passenden Typen zu erkennen. + foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome)) + { + Console.WriteLine(bikeSummary.Name); + } + + // AsParallel-Methode + // Jetzt kommen die Schmankerl! Die AsParallel-Methode kombiniert + // LINQ und parallele Operationen: + var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name); + // Diese Berechnung passiert parallel! Benötigte Threads werden + // automatisch erzeugt, und die Rechenlast unter ihnen aufgeteilt. + // Ein Traum für die Verarbeitung von großen Datenmengen + // auf mehreren Cores! + + // LINQ - bildet einen Datenspeicher auf IQueryable<T> Objekte ab + // LinqToSql beispielsweise speichert und liest aus einer + // SQL-Datenbank, LinqToXml aus einem XML-Dokument. + // LINQ-Operationen werden "lazy" ausgeführt. + var db = new BikeRepository(); + + // Die verzögerte Ausführung ist optimal für Datenbankabfragen + var filter = db.Bikes.Where(b => b.HasTassles); // noch keine Abfrage + // Es können noch mehr Filter hinzugefügt werden (auch mit + // Bedingungen) - ideal für z.B. "erweiterte Suchen" + if (42 > 6) + { + filter = filter.Where(b => b.IsBroken); // immer noch keine Abfrage + } + + var query = filter + .OrderBy(b => b.Wheels) + .ThenBy(b => b.Name) + .Select(b => b.Name); // auch hier: immer noch keine Abfrage + + // Erst hier wird die Datenbankabfrage wirklich ausgeführt, + // limitiert auf die Elemente die der foreach-Loop verwendet + foreach (string bike in query) + { + Console.WriteLine(result); + } + + } + + } // Ende der Klasse LearnCSharp + + // Eine .cs-Datei kann auch mehrere Klassen enthalten + + public static class Extensions + { + // Erweiterungsmethoden + public static void Print(this object obj) + { + Console.WriteLine(obj.ToString()); + } + } + + // Syntax zur Deklaration einer Klasse: + // <public/private/protected/internal> class <class name>{ + // // Datenfelder, Konstruktoren und Methoden leben alle + // // innerhalb dieser Deklaration + // } + + public class Bicycle + { + // Felder/Variablen der Klasse "Bicycle" + // Das Keyword public macht das Member von überall zugänglich + public int Cadence + { + get // get definiert eine Methode um die Eigenschaft abzurufen + { + return _cadence; + } + set // set definiert eine Methode um die Eigenschaft zu setzen + { + _cadence = value; // value ist der dem Setter übergebene Wert + } + } + private int _cadence; + + // Das Keyword protected macht das Member nur für die Klasse selbst + // und ihre Subklassen zugänglich + protected virtual int Gear + { + get; // erzeugt eine Eigenschaft für die kein "Zwischenwert" benötigt wird + set; + } + + // Das Keyword internal macht das Member innerhalb der Assembly zugänglich + internal int Wheels + { + get; + private set; // get/set kann auch über Keywords modifiziert werden + } + + int _speed; // Member ohne vorangestellte Keywords sind standardmäßig + // private, sie sind nur innerhalb der Klasse zugänglich. + // Man kann aber natürlich auch das Keyword private benutzen. + private string Name { get; set; } + + // Ein Enum ist ein klar definierter Satz an benannten Konstanten. + // Eigentlich ordnet es diese Konstanten nur bestimmten Werten zu + // (einer int-Zahl, solange nicht anders angegeben). Mögliche Typen für + // die Werte eines Enums sind byte, sbyte, short, ushort, int, uint, + // long, oder ulong. Alle Werte in einem Enum sind eindeutig. + public enum BikeBrand + { + Colnago, + EddyMerckx, + Bianchi = 42, // so kann man den Wert explizit setzen + Kynast // 43 + } + // Nachdem dieser Typ in der Klasse "Bicycle" definiert ist, + // sollte Code ausserhalb der Klasse den Typen als Bicycle.Brand referenzieren + + // Nachdem das Enum deklariert ist, können wir den Typen verwenden: + public BikeBrand Brand; + + // Als static gekennzeichnete Member gehören dem Typ selbst, + // nicht seinen Instanzen. Man kann sie also ohne Referenz zu einem + // Objekt benutzen + // Console.WriteLine("Schon " + Bicycle.BicyclesCreated + " Fahrräder, nur für dieses Tutorial!"); + static public int BicyclesCreated = 0; + + // readonly-Werte werden zur Laufzeit gesetzt + // Ihr Wert kann nur bei ihrer Deklaration, oder in einem Konstruktor + // festgelegt werden + readonly bool _hasCardsInSpokes = false; // readonly und private + + // Konstruktoren bestimmen was bei einer Instantiierung passiert. + // Das ist ein Default-Konstruktor: + public Bicycle() + { + // Member der Klasse können über das Keyword this erreicht werden + this.Gear = 1; + // oft ist das aber gar nicht nötig + Cadence = 50; + _speed = 5; + Name = "Bonanzarad"; + Brand = BikeBrand.Kynast; + BicyclesCreated++; + } + + // Das ist ein spezifischer Konstruktor (d.h. er erwartet Argumente): + public Bicycle(int startCadence, int startSpeed, int startGear, + string name, bool hasCardsInSpokes, BikeBrand brand) + : base() // ruft zuerst den "base"-Konstruktor auf + { + Gear = startGear; + Cadence = startCadence; + _speed = startSpeed; + Name = name; + _hasCardsInSpokes = hasCardsInSpokes; + Brand = brand; + } + + // Konstruktoren können aneinandergehängt werden: + public Bicycle(int startCadence, int startSpeed, BikeBrand brand) : + this(startCadence, startSpeed, 0, "richtig große Räder", true, brand) + { + } + + // Syntax für Methoden: + // <public/private/protected> <return type> <function name>(<args>) + + // Klassen können Getter und Setter für Werte definieren, + // oder diese Werte direkt als Eigenschaft implementieren + // (in C# der bevorzugte Weg) + + // Parameter von Methoden können Default-Werte haben. + // "SpeedUp" kann man also auch ohne Parameter aufrufen: + public void SpeedUp(int increment = 1) + { + _speed += increment; + } + + public void SlowDown(int decrement = 1) + { + _speed -= decrement; + } + + // Eigenschaften mit get/set + // wenn es nur um den Zugriff auf Daten geht, ist eine Eigenschaft zu + // empfehlen. Diese können Getter und Setter haben, oder auch nur + // einen Getter bzw. einen Setter + private bool _hasTassles; // private Variable + public bool HasTassles // öffentliches Interface + { + get { return _hasTassles; } + set { _hasTassles = value; } + } + + // Das kann man auch kürzer schreiben: + // Dieser Syntax erzeugt automatisch einen hinterlegten Wert, + // (entsprechend `private bool _isBroken`) der gesetzt + // bzw. zurückgegeben wird: + public bool IsBroken { get; private set; } + public int FrameSize + { + get; + // für Getter und Setter kann der Zugriff auch einzeln + // beschränkt werden, FrameSize kann also nur von innerhalb + // der Klasse "Bicycle" gesetzt werden + private set; + } + + // Diese Methode gibt eine Reihe an Informationen über das Objekt aus: + public virtual string ToString() + { + return "Gang: " + Gear + + " Kadenz: " + Cadence + + " Geschwindigkeit: " + _speed + + " Name: " + Name + + " Hipster-Karten zwischen den Speichen: " + (_hasCardsInSpokes ? "Na klar!" : "Bloß nicht!") + + "\n------------------------------\n" + ; + } + + // Auch Methoden können als static gekennzeichnet werden, nützlich + // beispielsweise für Helper-Methoden + public static bool DidWeCreateEnoughBicyclesYet() + { + // In einer statischen Methode können wir natürlich auch nur + // statische Member der Klasse referenzieren + return BicyclesCreated > 9000; + } + // Wenn eine Klasse nur statische Member enthält, kann es eine gute Idee + // sein die Klasse selbst als static zu kennzeichnen + + } // Ende der Klasse "Bicycle" + + // "PennyFarthing" ist eine Unterklasse von "Bicycle" + class PennyFarthing : Bicycle + { + // (Hochräder - englisch Penny Farthing - sind diese antiken Fahrräder + // mit riesigem Vorderrad. Sie haben keine Gangschaltung.) + + // hier wird einfach der Elternkonstruktor aufgerufen + public PennyFarthing(int startCadence, int startSpeed) : + base(startCadence, startSpeed, 0, "Hochrad", true, BikeBrand.EddyMerckx) + { + } + + protected override int Gear + { + get + { + return 0; + } + set + { + throw new ArgumentException("Ein Hochrad hat keine Gangschaltung, doh!"); + } + } + + public override string ToString() + { + string result = "Hochrad "; + result += base.ToString(); // ruft die "base"-Version der Methode auf + return result; + } + } + + // Interfaces (auch Schnittstellen genant) definieren nur die Signaturen + // ihrer Member, enthalten aber auf keinen Fall ihre Implementierung: + interface IJumpable + { + // Alle Member eines Interfaces sind implizit public + void Jump(int meters); + } + + interface IBreakable + { + // Interfaces können Eigenschaften, Methoden und Events definieren + bool Broken { get; } + } + + // Eine Klasse kann nur von einer Klasse erben, kann aber eine beliebige + // Anzahl von Interfaces implementieren + class MountainBike : Bicycle, IJumpable, IBreakable + { + int damage = 0; + + public void Jump(int meters) + { + damage += meters; + } + + public bool Broken + { + get + { + return damage > 100; + } + } + } + + // Das hier stellt eine Datenbankverbindung für das LinqToSql-Beispiel her. + // EntityFramework Code First ist großartig + // (ähnlich zu Ruby's ActiveRecord, aber bidirektional) + // http://msdn.microsoft.com/de-de/data/jj193542.aspx + public class BikeRepository : DbSet + { + public BikeRepository() + : base() + { + } + + public DbSet<Bicycle> Bikes { get; set; } + } +} // Ende des Namespaces +``` + +## In dieser Übersicht nicht enthalten sind die Themen: + + * Flags + * Attributes + * Statische Eigenschaften + * Exceptions, Abstraction + * ASP.NET (Web Forms/MVC/WebMatrix) + * Winforms + * Windows Presentation Foundation (WPF) + +## Zum Weiterlesen gibt es viele gute Anlaufpunkte: + + * [DotNetPerls](http://www.dotnetperls.com) + * [C# in Depth](http://manning.com/skeet2) + * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ](http://shop.oreilly.com/product/9780596519254.do) + * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx) + * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) + * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/overview/exploring-webmatrix) + * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) + +[C# Coding Conventions](http://msdn.microsoft.com/de-de/library/vstudio/ff926074.aspx) diff --git a/de-de/css-de.html.markdown b/de-de/css-de.html.markdown index c31e73d2..da706e91 100644 --- a/de-de/css-de.html.markdown +++ b/de-de/css-de.html.markdown @@ -27,7 +27,7 @@ In diesem Artikel wird am meisten auf generelle Hinweise und die Syntax geachtet ####################*/ /* Eigentlich ist das grundlegende CSS-Statement sehr simpel */ -selektor { eigenschaft: wert; /* mehr eigenschaften...*/ } +selektor { eigenschaft: wert; /* mehr Eigenschaften...*/ } /* Der Selektor wird dazu benutzt, ein Element auf der Seite auszuwählen. @@ -35,7 +35,7 @@ Man kann aber auch alle Elemente auf einer Seite auswählen! */ * { color:red; } /* farbe:rot */ /* -Angenommen wir haben folgendes Element auf einer Seite: +Angenommen, wir haben folgendes Element auf einer Seite: <div class='eine-klasse klasse2' id='eineId' attr='wert' /> */ @@ -170,7 +170,7 @@ empfohlen ist --> ## Spezifität Ein Element kann natürlich auch von mehr als einer Regel in einem Stylesheet -angesprochen werdenm und kann eine Eigenschaft auch öfters als einmal zugewiesen +angesprochen werden und kann eine Eigenschaft auch öfters als einmal zugewiesen bekommen. In diesen Fällen gibt es Regeln, die die Spezifität von Selektoren regeln. Wir haben dieses CSS: diff --git a/de-de/d-de.html.markdown b/de-de/d-de.html.markdown index 2b0b38dd..28ecc7ae 100644 --- a/de-de/d-de.html.markdown +++ b/de-de/d-de.html.markdown @@ -9,7 +9,7 @@ lang: de-de --- ```c -// Es war klar dass das kommt... +// Es war klar, dass das kommt... module hello; import std.stdio; @@ -20,13 +20,13 @@ void main(string[] args) { } ``` -Wenn du so wie ich bist und viel zeit im Internet verbringst stehen die Chancen gut -das du schonmal über [D](http://dlang.org/) gehört hast. -Die D-Sprache ist eine moderne, überall einsetzbare programmiersprache die von Low bis -High Level verwendet werden kann und dabei viele Stile anbietet. +Wenn du so wie ich bist und viel Zeit im Internet verbringst, stehen die Chancen +gut, dass du schonmal über [D](http://dlang.org/) gehört hast. +Die D-Sprache ist eine moderne, überall einsetzbare programmiersprache die von +Low bis High Level verwendet werden kann und dabei viele Stile anbietet. D wird aktiv von Walter Bright und Andrei Alexandrescu entwickelt, zwei super schlaue, -richtig coole leute. Da das jetzt alles aus dem weg ist - auf zu den Beispielen! +richtig coole leute. Da das jetzt alles aus dem Weg ist - auf zu den Beispielen! ```c import std.stdio; @@ -38,7 +38,7 @@ void main() { writeln(i); } - auto n = 1; // auto um den typ vom Compiler bestimmen zu lassen + auto n = 1; // auto um den Typ vom Compiler bestimmen zu lassen // Zahlenliterale können _ verwenden für lesbarkeit while(n < 10_000) { @@ -68,21 +68,22 @@ void main() { } ``` -Neue Typen können mit `struct`, `class`, `union`, und `enum` definiert werden. Structs und unions -werden as-value (koppiert) an methoden übergeben wogegen Klassen als Referenz übergeben werden. -Templates können verwendet werden um alle typen zu parameterisieren. +Neue Typen können mit `struct`, `class`, `union`, und `enum` definiert werden. +Structs und unions werden as-value (koppiert) an Methoden übergeben wogegen +Klassen als Referenz übergeben werden. Templates können verwendet werden um +alle Typen zu parameterisieren. ```c // Hier, T ist ein Type-Parameter, Er funktioniert wie Generics in C#/Java/C++ struct LinkedList(T) { T data = null; - LinkedList!(T)* next; // Das ! wird verwendet um T zu übergeben. (<T> in C#/Java/C++) + LinkedList!(T)* next; // Das ! wird verwendet, um T zu übergeben. (<T> in C#/Java/C++) } class BinTree(T) { T data = null; - // Wenn es nur einen T parameter gibt können die Klammern um ihn weggelassen werden + // Wenn es nur einen T Parameter gibt, können die Klammern um ihn weggelassen werden BinTree!T left; BinTree!T right; } @@ -97,7 +98,7 @@ enum Day { Saturday, } -// Aliase können verwendet werden um die Entwicklung zu erleichtern +// Aliase können verwendet werden, um die Entwicklung zu erleichtern alias IntList = LinkedList!int; alias NumTree = BinTree!double; @@ -111,8 +112,8 @@ T max(T)(T a, T b) { return a; } -// Steht ref vor einem Parameter wird sichergestellt das er als Referenz übergeben wird. -// Selbst bei werten wird es immer eine Referenz sein. +// Steht ref vor einem Parameter, wird sichergestellt, dass er als Referenz +übergeben wird. Selbst bei Werten wird es immer eine Referenz sein. void swap(T)(ref T a, ref T b) { auto temp = a; @@ -120,18 +121,18 @@ void swap(T)(ref T a, ref T b) { b = temp; } -// Templates können ebenso werte parameterisieren. +// Templates können ebenso Werte parameterisieren. class Matrix(uint m, uint n, T = int) { T[m] rows; T[n] columns; } -auto mat = new Matrix!(3, 3); // Standardmäßig ist T vom typ Integer +auto mat = new Matrix!(3, 3); // Standardmäßig ist T vom Typ Integer ``` Wo wir schon bei Klassen sind - Wie wäre es mit Properties! Eine Property -ist eine Funktion die wie ein Wert agiert. Das gibt uns viel klarere Syntax +ist eine Funktion, die wie ein Wert agiert. Das gibt uns viel klarere Syntax im Stil von `structure.x = 7` was gleichgültig wäre zu `structure.setX(7)` ```c @@ -187,18 +188,17 @@ void main() { ``` Mit properties können wir sehr viel logik hinter unseren gettern -und settern hinter einer schönen syntax verstecken +und settern hinter einer schönen Syntax verstecken -Other object-oriented goodies at our disposal Andere Objektorientierte features sind beispielsweise `interface`s, `abstract class` und `override`. Vererbung funktioniert in D wie in Java: -Erben von einer Klasse, so viele interfaces wie man will. +Erben von einer Klasse, so viele Interfaces wie man will. -Jetzt haben wir Objektorientierung in D gesehen aber schauen +Jetzt haben wir Objektorientierung in D gesehen, aber schauen wir uns noch was anderes an. -D bietet funktionale programmierung mit _first-class functions_ -puren funktionen und unveränderbare daten. +D bietet funktionale Programmierung mit _first-class functions_ +puren Funktionen und unveränderbaren Daten. Zusätzlich können viele funktionale Algorithmen wie z.B map, filter, reduce und friends im `std.algorithm` Modul gefunden werden! @@ -207,11 +207,11 @@ import std.algorithm : map, filter, reduce; import std.range : iota; // builds an end-exclusive range void main() { - // Wir wollen die summe aller quadratzahlen zwischen + // Wir wollen die Summe aller Quadratzahlen zwischen // 1 und 100 ausgeben. Nichts leichter als das! - // Einfach eine lambda funktion als template parameter übergeben - // Es ist genau so gut möglich eine normale funktion hier zu übergeben + // Einfach eine Lambda-Funktion als Template Parameter übergeben + // Es ist genau so gut möglich eine normale Funktion hier zu übergeben // Lambdas bieten sich hier aber an. auto num = iota(1, 101).filter!(x => x % 2 == 0) .map!(y => y ^^ 2) @@ -221,13 +221,13 @@ void main() { } ``` -Ist dir aufgefallen wie wir eine Haskell-Style pipeline gebaut haben +Ist dir aufgefallen, wie wir eine Haskell-Style Pipeline gebaut haben um num zu berechnen? Das war möglich durch die Uniform Function Call Syntax. -Mit UFCS können wir auswählen ob wir eine Funktion als Methode oder +Mit UFCS können wir auswählen, ob wir eine Funktion als Methode oder als freie Funktion aufrufen. Walters artikel dazu findet ihr [hier.](http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394) -Kurzgesagt kann man Funktionen deren erster parameter vom typ A ist, als +Kurzgesagt kann man Funktionen, deren erster Parameter vom typ A ist, als Methode auf A anwenden. Parrallel Computing ist eine Tolle sache, findest du nicht auch? @@ -239,10 +239,10 @@ import std.math : sqrt; void main() { // Wir wollen die Wurzel von jeder Zahl in unserem Array berechnen - // und dabei alle Kerne verwenden die wir zur verfügung haben + // und dabei alle Kerne verwenden, die wir zur verfügung haben auto arr = new double[1_000_000]; - // Wir verwenden den index und das element als referenz + // Wir verwenden den Index und das Element als Referenz // und rufen einfach parallel auf! foreach(i, ref elem; parallel(arr)) { ref = sqrt(i + 1.0); diff --git a/de-de/dynamic-programming-de.html.markdown b/de-de/dynamic-programming-de.html.markdown index 58568b3b..9cf461d0 100644 --- a/de-de/dynamic-programming-de.html.markdown +++ b/de-de/dynamic-programming-de.html.markdown @@ -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 diff --git a/de-de/elixir-de.html.markdown b/de-de/elixir-de.html.markdown index 29d5132d..4acb8e23 100644 --- a/de-de/elixir-de.html.markdown +++ b/de-de/elixir-de.html.markdown @@ -1,419 +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
-
-# 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 diff --git a/de-de/elm-de.html.markdown b/de-de/elm-de.html.markdown new file mode 100644 index 00000000..a6a8cd88 --- /dev/null +++ b/de-de/elm-de.html.markdown @@ -0,0 +1,376 @@ +--- +language: Elm +filename: learnelm.elm +contributors: + - ["Max Goldstein", "http://maxgoldste.in/"] +translators: + - ["waynee95", "https://waynee95.me"] +lang: de-de +--- + +Elm ist eine pure funktionale Programmiersprache. Mit Elm werden GUIs +(grafische Benutzeroberfläche) für Webanwendungen erstellt. Durch die statische +Typisierung kann Elm viele Fehler schon bei der Kompilierung abfangen. Ein +Hauptmerkmal von Elm sind die ausführlichen und gut erklärten Fehlermeldungen. + +```haskell +-- Einzeilige Kommentare beginnen mit 2 Bindestrichen. +{- So wird ein mehrzeiliger Kommentar angelegt. +{- Diese können auch verschachtelt werden. -} +-} + +{-- Die Grundlagen --} + +-- Arithmetik +1 + 1 -- 2 +8 - 1 -- 7 +10 * 2 -- 20 + +-- Zahlen ohne Punkt sind entweder vom Typ Int oder Float. +33 / 2 -- 16.5 mit Division von Gleitkommazahlen +33 // 2 -- 16 mit ganzzahliger Division + +-- Exponenten +5 ^ 2 -- 25 + +-- Boolsche Werte +not True -- False +not False -- True +1 == 1 -- True +1 /= 1 -- False +1 < 10 -- True + +-- Strings (Zeichenketten) und Zeichen +"Das hier ist ein String." +'a' -- Zeichen + +-- Strings können konkateniert werden. +"Hello " ++ "world!" -- "Hello world!" + +{-- Listen und Tupel --} + +-- Jedes Element einer Liste muss vom gleichen Typ sein. Listen sind homogen. +["the", "quick", "brown", "fox"] +[1, 2, 3, 4, 5] +-- Das zweite Beispiel kann man auch mit Hilfe der "range" Funktion schreiben. +List.range 1 5 + +-- Listen werden genauso wie Strings konkateniert. +List.range 1 5 ++ List.range 6 10 == List.range 1 10 -- True + +-- Mit dem "cons" Operator lässt sich ein Element an den Anfang einer Liste anfügen. +0 :: List.range 1 5 -- [0, 1, 2, 3, 4, 5] + +-- Die Funktionen "head" und "tail" haben als Rückgabewert den "Maybe" Typ. +-- Dadurch wird die Fehlerbehandlung von fehlenden Elementen explizit, weil +-- man immer mit jedem möglichen Fall umgehen muss. +List.head (List.range 1 5) -- Just 1 +List.tail (List.range 1 5) -- Just [2, 3, 4, 5] +List.head [] -- Nothing +-- List.funktionsName bedeutet, dass diese Funktion aus dem "List"-Modul stammt. + +-- Tupel sind heterogen, jedes Element kann von einem anderen Typ sein. +-- Jedoch haben Tupel eine feste Länge. +("elm", 42) + +-- Das Zugreifen auf Elemente eines Tupels geschieht mittels den Funktionen +-- "first" und "second". +Tuple.first ("elm", 42) -- "elm" +Tuple.second ("elm", 42) -- 42 + +-- Das leere Tupel, genannt "Unit", wird manchmal als Platzhalter verwendet. +-- Es ist das einzige Element vom Typ "Unit". +() + +{-- Kontrollfluss --} + +-- Eine If-Bedingung hat immer einen Else-Zweig und beide Zweige müssen den +-- gleichen Typ haben. +if powerLevel > 9000 then + "WHOA!" +else + "meh" + +-- If-Bedingungen können verkettet werden. +if n < 0 then + "n is negative" +else if n > 0 then + "n is positive" +else + "n is zero" + +-- Mit dem Mustervergleich (pattern matching) kann man bestimmte Fälle direkt +-- behandeln. +case aList of + [] -> "matches the empty list" + [x]-> "matches a list of exactly one item, " ++ toString x + x::xs -> "matches a list of at least one item whose head is " ++ toString x +-- Mustervergleich geht immer von oben nach unten. Würde man [x] als letztes +-- platzieren, dann würde dieser Fall niemals getroffen werden, weil x:xs diesen +-- Fall schon mit einschließt (xs ist in dem Fall die leere Liste). + +-- Mustervergleich an einem Maybe Typ. +case List.head aList of + Just x -> "The head is " ++ toString x + Nothing -> "The list was empty." + +{-- Funktionen --} + +-- Die Syntax für Funktionen in Elm ist minimal. Hier werden Leerzeichen anstelle +-- von runden oder geschweiften Klammern verwendet. Außerdem gibt es kein "return" +-- Keyword. + +-- Eine Funktion wird durch ihren Namen, einer Liste von Parametern gefolgt von +-- einem Gleichheitszeichen und dem Funktionskörper angegeben. +multiply a b = + a * b + +-- Beim Aufruf der Funktion (auch Applikation genannt) werden die Argumente ohne +-- Komma übergeben. +multiply 7 6 -- 42 + +-- Partielle Applikation einer Funktion (Aufrufen einer Funktion mit fehlenden +-- Argumenten). Hierbei entsteht eine neue Funktion, der wir einen Namen geben. +double = + multiply 2 + +-- Konstanten sind Funktionen ohne Parameter. +answer = + 42 + +-- Funktionen, die Funktionen als Parameter haben, nennt man Funktionen höherer +-- Ordnung. In funktionalen Programmiersprachen werden Funktionen als "first-class" +-- behandelt. Man kann sie als Argument übergeben, als Rückgabewert einer Funktion +-- zurückgeben oder einer Variable zuweisen. +List.map double (List.range 1 4) -- [2, 4, 6, 8] + +-- Funktionen können auch als anonyme Funktion (Lambda-Funktionen) übergeben werden. +-- Diese werden mit einem Blackslash eingeleitet, gefolgt von allen Argumenten. +-- Die Funktion "\a -> a * 2" beschreibt die Funktion f(x) = x * 2. +List.map (\a -> a * 2) (List.range 1 4) -- [2, 4, 6, 8] + +-- Mustervergleich kann auch in der Funktionsdefinition verwendet werden. +-- In diesem Fall hat die Funktion ein Tupel als Parameter. (Beachte: Hier +-- werden die Werte des Tupels direkt ausgepackt. Dadurch kann man auf die +-- Verwendung von "first" und "second" verzichten.) +area (width, height) = + width * height + +area (6, 7) -- 42 + +-- Mustervergleich auf Records macht man mit geschweiften Klammern. +-- Bezeichner (lokale Variablen) werden mittels dem "let" Keyword angelegt. +-- (Mehr zu Records weiter unten!) +volume {width, height, depth} = + let + area = width * height + in + area * depth + +volume { width = 3, height = 2, depth = 7 } -- 42 + +-- Rekursive Funktion +fib n = + if n < 2 then + 1 + else + fib (n - 1) + fib (n - 2) + +List.map fib (List.range 0 8) -- [1, 1, 2, 3, 5, 8, 13, 21, 34] + +-- Noch eine rekursive Funktion (Nur ein Beispiel, verwende stattdessen immer +-- List.length!) +listLength aList = + case aList of + [] -> 0 + x::xs -> 1 + listLength xs + +-- Funktionsapplikation hat die höchste Präzedenz, sie binden stärker als Operatoren. +-- Klammern bietet die Möglichkeit der Bevorrangung. +cos (degrees 30) ^ 2 + sin (degrees 30) ^ 2 -- 1 +-- Als erstes wird die Funktion "degrees" mit dem Wert 30 aufgerufen. +-- Danach wird das Ergenis davon den Funktionen "cos", bzw. "sin" übergeben. +-- Dann wird das Ergebnis davon mit 2 quadriert und als letztes werden diese +-- beiden Werte dann addiert. + +{-- Typen und Typ Annotationen --} + +-- Durch Typinferenz kann der Compiler jeden Typ genau bestimmen. Man kann diese +-- aber auch manuell selber angeben (guter Stil!). +-- Typen beginnen immer mit eine Großbuchstaben. Dabei liest man "x : Typ" als +-- "x" ist vom Typ "Typ". +-- Hier ein paar übliche Typen: +5 : Int +6.7 : Float +"hello" : String +True : Bool + +-- Funktionen haben ebenfalls einen Typ. Dabei ist der ganz rechte Typ der +-- Rückgabetyp der Funktion und alle anderen sind die Typen der Parameter. +not : Bool -> Bool +round : Float -> Int + +-- Es ist guter Stil immer den Typ anzugeben, da diese eine Form von Dokumentation +-- sind. Außerdem kann so der Compiler genauere Fehlermeldungen geben. +double : Int -> Int +double x = x * 2 + +-- Funktionen als Parameter werden durch Klammern angegeben. Die folgende Funktion +-- ist nicht auf einen Typ festgelegt, sondern enthält Typvariablen (beginnend +-- mit Kleinbuchstaben). Die konkreten Typen werden erst bei Anwendung der +-- Funktion festgelegt. "List a" bedeutet, dass es sich um eine Liste mit +-- Elementen vom Typ "a" handelt. +List.map : (a -> b) -> List a -> List b + +-- Es gibt drei spezielle kleingeschriebene Typen: "number", "comparable" und +-- "appendable". +add : number -> number -> number +add x y = x + y -- funktioniert mit Ints und Floats. + +max :: comparable -> comparable -> comparable +max a b = if a > b then a else b -- funktioniert mit Typen, die vergleichbar sind. + +append :: appendable -> appendable -> appendable +append xs ys = xs ++ ys -- funktioniert mit Typen, die konkatenierbar sind. + +append "hello" "world" -- "helloworld" +append [1,1,2] [3,5,8] -- [1,1,2,3,5,8] + +{-- Eigene Datentypen erstellen --} + +-- Ein "Record" ist ähnlich wie ein Tupel, nur das jedes Feld einen Namne hat. +-- Dabei spielt die Reihenfolge keine Rolle. +{ x = 3, y = 7 } + +-- Um auf Werte eines Records zuzugreifen, benutzt man einen Punkt gefolgt +-- von dem Namen des Feldes. +{ x = 3, y = 7 }.x -- 3 + +-- Oder mit einer Zugriffsfunktion, welche aus einem Punkt und dem Feldnamen besteht. +.y { x = 3, y = 7 } -- 7 + +-- Wert eines Feldes ändern. (Achtung: Das Feld muss aber vorher schon vorhanden sein!) +{ person | + name = "George" } + +-- Mehrere Felder aufeinmal ändern unter Verwendung des alten Wertes. +{ particle | + position = particle.position + particle.velocity, + velocity = particle.velocity + particle.acceleration } + +-- Du kannst ein Record auch als Typ Annotation verwenden. +-- (Beachte: Ein Record Typ benutzt einen Doppelpunkt und ein Record Wert benutzt +-- ein Gleichheitszeichen!) +origin : { x : Float, y : Float, z : Float } +origin = + { x = 0, y = 0, z = 0 } + +-- Durch das "type" Keyword kann man einem existierenden Typen einen Namen geben. +type alias Point3D = + { x : Float, y : Float, z : Float } + +-- Der Name kann dann als Konstruktor verwendet werden. +otherOrigin : Point3D +otherOrigin = + Point3D 0 0 0 + +-- Aber es ist immernoch der selbe Typ, da es nur ein Alias ist! +origin == otherOrigin -- True + +-- Neben den Records gibt es auch noch so genannte Summentypen. +-- Ein Summentyp hat mehrere Konstruktoren. +type Direction = + North | South | East | West + +-- Ein Konstruktor kann außerdem noch andere Typen enthalten. Rekursion ist +-- auch möglich. +type IntTree = + Leaf | Node Int IntTree IntTree + +-- Diese können auch als Typ Annotation verwendet werden. +root : IntTree +root = + Node 7 Leaf Leaf + +-- Außerdem können auch Typvariablen verwendet werden in einem Konstruktor. +type Tree a = + Leaf | Node a (Tree a) (Tree a) + +-- Beim Mustervergleich kann man auf die verschiedenen Konstruktoren matchen. +leftmostElement : Tree a -> Maybe a +leftmostElement tree = + case tree of + Leaf -> Nothing + Node x Leaf _ -> Just x + Node _ subtree _ -> leftmostElement subtree + +{-- Module und Imports --} + +-- Die Kernbibliotheken und andere Bibliotheken sind in Module aufgeteilt. +-- Für große Projekte können auch eigene Module erstellt werden. + +-- Eine Modul beginnt mit ganz oben. Ohne diese Angabe befindet man sich +-- automatisch im Modul "Main". +module Name where + +-- Ohne genaue Angabe von Exports wird alles exportiert. Es können aber alle +-- Exporte explizit angegeben werden. +module Name (MyType, myValue) where + +-- Importiert das Modul "Dict". Jetzt kann man Funktionen mittels "Dict.insert" +-- aufrufen. +import Dict + +-- Importiert das "Dict" Modul und den "Dict" Typ. Dadurch muss man nicht "Dict.Dict" +-- verwenden. Man kann trotzdem noch Funktionen des Moduls aufrufen, wie "Dict.insert". +import Dict exposing (Dict) + +-- Abkürzung für den Modulnamen. Aufrufen der Funktionen mittels "C.funktionsName". +import Graphics.Collage as C + +{-- Kommandozeilen Programme --} + +-- Eine Elm-Datei kompilieren. +$ elm make MyFile.elm + +-- Beim ersten Aufruf wird Elm die "core" Bibliotheken installieren und eine +-- "elm-package.json"-Datei anlegen, die alle Informationen des Projektes +-- speichert. + +-- Der Reactor ist ein Server, welche alle Dateinen kompiliert und ausführt. +$ elm reactor + +-- Starte das REPL (read-eval-print-loop). +$ elm repl + +-- 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. + +-- Zeigt alle Veränderungen zwischen zwei bestimmten Versionen an. +$ elm package diff elm-lang/html 1.1.0 2.0.0 +-- Der Paketmanager von Elm erzwingt "semantic versioning"! +``` + +Elm ist eine besonders kleine Programmiersprache. Jetzt hast du genug Wissen an +deiner Seite, um dich in fast jedem Elm Code zurecht zu finden. + +Noch ein paar weitere hilfreiche Ressourcen (in Englisch): + +- Die [Elm Homepage](http://elm-lang.org/). Dort findest du: + + - [Anleitung zur Installierung von Elm](http://elm-lang.org/install) + - [Dokumentation](http://elm-lang.org/docs), sowie eine [Referenz zur Syntax](http://elm-lang.org/docs/syntax) + - Viele hilfreiche [Beispiele](http://elm-lang.org/examples) + +- Dokumentation der [Elm Kernbibliotheken](http://package.elm-lang.org/packages/elm-lang/core/latest/). Insbesondere: + + - [Basics](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics) (standardmäßig importiert) + - [Maybe](http://package.elm-lang.org/packages/elm-lang/core/latest/Maybe) sowie [Result](http://package.elm-lang.org/packages/elm-lang/core/latest/Result) (benutzt für Fehlerbehandlung) + - Datenstrukturen, wie [List](http://package.elm-lang.org/packages/elm-lang/core/latest/List), [Array](http://package.elm-lang.org/packages/elm-lang/core/latest/Array), [Dict](http://package.elm-lang.org/packages/elm-lang/core/latest/Dict), und [Set](http://package.elm-lang.org/packages/elm-lang/core/latest/Set) + - JSON [encoding](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Encode) und [decoding](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Decode) + +- [Die Elm Architektur](https://github.com/evancz/elm-architecture-tutorial#the-elm-architecture). + +- Die [Elm mailing list](https://groups.google.com/forum/#!forum/elm-discuss). diff --git a/de-de/git-de.html.markdown b/de-de/git-de.html.markdown index 0896f513..3065a033 100644 --- a/de-de/git-de.html.markdown +++ b/de-de/git-de.html.markdown @@ -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/) diff --git a/de-de/go-de.html.markdown b/de-de/go-de.html.markdown index 9409e181..1b09a1e1 100644 --- a/de-de/go-de.html.markdown +++ b/de-de/go-de.html.markdown @@ -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/). diff --git a/de-de/html-de.html.markdown b/de-de/html-de.html.markdown index 0bf58f9c..8b5597e7 100644 --- a/de-de/html-de.html.markdown +++ b/de-de/html-de.html.markdown @@ -50,10 +50,10 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben <!-- Danach startet sie mit einem Öffnungtag <html>. --> <html> -<!-- Dieser wird am Ende der Datei mit</html> geschlossen. --> +<!-- Dieser wird am Ende der Datei mit </html> geschlossen. --> </html> -<!-- Nichts sollte nach diesen finalen Tag erscheinen. --> +<!-- Nichts sollte nach diesem finalen Tag erscheinen. --> <!-- Dazwischen (Zwischen dem Öffnungs- und Schließungstag <html></html>) finden wir: --> @@ -65,13 +65,13 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben </head> <!-- Nach dem <head> Bereich findet sich der <body> Tag --> -<!-- Bis zu diesen Punkt wird nichts im Browerfenster angezeigt. --> -<!-- Wir müssen den Body mit dem Inhalt füllen der angezeigt werden soll. --> +<!-- Bis zu diesem Punkt wird nichts im Browerfenster angezeigt. --> +<!-- Wir müssen den Body mit dem Inhalt füllen, der angezeigt werden soll. --> <body> <h1>Hallo, Welt!</h1> <!-- Der h1 Tag erstellt einen Titel. --> <!-- Es gibt auch Untertitel für <h1> von den wichtigsten <h2> zu den Unwichtigsten (h6). --> - <a href = "http://codepen.io/anon/pen/xwjLbZ">Komm, schaue was das zeigt</a> <!-- Eine URL wird zum Hyperlink, wenn es das Attribut href="" --> + <a href = "http://codepen.io/anon/pen/xwjLbZ">Komm, schaue was das zeigt</a> <!-- Eine URL wird zum Hyperlink, wenn es das Attribut href="" hat --> <p>Das ist ein Absatz.</p> <!-- Der Tag <p> lässt uns Text auf die HTML Seite hinzufügen. --> <p>Das ist ein anderer Absatz.</p> <ul> <!-- Der <ul> Tag erstellt eine Aufzählungsliste. --> @@ -93,12 +93,12 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben <!-- Es ist ebenso möglich eine Tabelle zu erstellen. --> <table> <!-- Wir öffnen ein <table> Element. --> - <tr> <!-- <tr> erlaubt es uns Reihe zu erstellen. --> - <th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns der Tabelle einen Titel zu geben. --> + <tr> <!-- <tr> erlaubt es uns, Reihen zu erstellen. --> + <th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns, der Tabelle einen Titel zu geben. --> <th>Zweiter Tabllenkopf</th> </tr> <tr> - <td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es eine Tabellenzelle zu erstellen. --> + <td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es, eine Tabellenzelle zu erstellen. --> <td>Erste Zeile, zweite Spalte</td> </tr> <tr> diff --git a/de-de/java-de.html.markdown b/de-de/java-de.html.markdown index e8ac5bda..e52087ec 100644 --- a/de-de/java-de.html.markdown +++ b/de-de/java-de.html.markdown @@ -477,7 +477,7 @@ Für tiefergreifende Fragen ist Google der beste Startpunkt. * [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html) -* [Java Code Conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html) +* [Java Code Conventions](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf) **Online Tutorials** diff --git a/de-de/javascript-de.html.markdown b/de-de/javascript-de.html.markdown index f3917506..a71d4316 100644 --- a/de-de/javascript-de.html.markdown +++ b/de-de/javascript-de.html.markdown @@ -1,525 +1,525 @@ ----
-language: javascript
-contributors:
- - ["Adam Brenecki", "http://adam.brenecki.id.au"]
-translators:
- - ["ggb", "http://www.ideen-und-soehne.de"]
-filename: learnjavascript-de.js
-lang: de-de
----
-
-(Anmerkungen des Original-Autors:)
-JavaScript wurde im Jahr 1995 von Brendan Eich bei Netscape entwickelt. Ursprünglich war es als einfachere Skriptsprache für Websites gedacht, ergänzend zu Java, das für komplexere Webanwendungen verwendet wird. Die enge Integration in Websites und der in Browser eingebaute Support der Sprache haben dafür gesorgt, dass JavaScript weit häufiger für Web-Frontends verwendet wird als Java.
-
-Dabei ist JavaScript inzwischen nicht mehr auf Browser beschränkt: Node.js, ein Projekt, das eine eigene Laufzeitumgebung auf Grundlage von Google Chromes V8 mitbringt, wird derzeit immer populärer.
-
-Feedback ist herzlich Willkommen! Der ursprüngliche Autor ist unter [@adambrenecki](https://twitter.com/adambrenecki) oder [adam@brenecki.id.au](mailto:adam@brenecki.id.au) zu erreichen. Der Übersetzer unter [gregorbg@web.de](mailto:gregorbg@web.de).
-
-```js
-// Kommentare werden wie in C gesetzt: Einzeilige Kommentare starten mit zwei
-// Slashes
-/* während mehrzeilige Kommentare mit einem
-Slash und einem Stern anfangen und enden */
-
-// Statements können mit einem Semikolon beendet werden
-machWas();
-
-// ...müssen sie aber nicht, weil Semikola automatisch eingefügt werden, wenn
-// eine neue Zeile beginnt, abgesehen von einigen Ausnahmen.
-machWas()
-
-// Obwohl wir uns für den Anfang nicht um diese Ausnahmen kümmern müssen ist
-// es besser die Semikola immer zu setzen.
-
-///////////////////////////////////
-// 1. Nummern, Strings und Operationen
-
-// JavaScript hat einen Nummern-Typ (64-bit IEEE 754 double).
-3; // = 3
-1.5; // = 1.5
-
-// Beinahe alle grundlegenden arithmetischen Operationen arbeiten wie erwartet.
-1 + 1; // = 2
-0.1 + 0.2; // = 0.30000000000000004
-10 * 2; // = 20
-35 / 5; // = 7
-
-// Division funktioniert auch mit einem Ergebnis nach dem Komma.
-5 / 2; // = 2.5
-
-// Bit-weise Operationen sind auch möglich; wenn eine Bit-weise Operation
-// ausgeführt wird, wird die Fließkomma-Zahl in einen 32-bit Integer (mit
-// Vorzeichen) umgewandelt.
-1 << 2; // = 4
-
-// Die Rangfolge der Operationen kann mit Klammern erzwungen werden.
-(1 + 3) * 2; // = 8
-
-// Es gibt drei spezielle, nicht-reale Nummern-Werte:
-Infinity; // Ergebnis von z. B. 1 / 0
--Infinity; // Ergebnis von z. B. -1 / 0
-NaN; // Ergebnis von z. B. 0 / 0
-
-// Es gibt auch einen Boolean-Typ (für Wahrheitswerte).
-true;
-false;
-
-// Strings werden mit ' oder " erzeugt.
-'abc';
-"Hello, world";
-
-// Für die Negation wird das ! benutzt.
-!true; // = false
-!false; // = true
-
-// Gleichheit wird mit === geprüft.
-1 === 1; // = true
-2 === 1; // = false
-
-// Ungleichheit wird mit !== überprüft.
-1 !== 1; // = false
-2 !== 1; // = true
-
-// Andere Vergleichsoperatoren sind
-1 < 10; // = true
-1 > 10; // = false
-2 <= 2; // = true
-2 >= 2; // = true
-
-// Strings können mit + verbunden
-"Hello " + "world!"; // = "Hello world!"
-
-// und mit < und > verglichen werden.
-"a" < "b"; // = true
-
-// Für den Vergleich von Werten mit "==" wird eine Typumwandlung erzwungen...
-"5" == 5; // = true
-
-// ...solange man nicht === verwendet.
-"5" === 5; // = false
-
-// Auf einzelne Buchstaben innerhalb eines Strings kann mit der Methode
-// 'charAt' zugegriffen werden
-"This is a string".charAt(0); // = "T"
-
-// Die Methode 'substring' gibt Teilbereiche eines Strings zurück
-"Hello world".substring(0, 5); // = "Hello"
-
-// 'length' ist eine Eigenschaft und wird folglich ohne '()' benutzt
-"Hello".length; // = 5
-
-// Es gibt außerdem die Werte 'null' und 'undefined'
-null; // wird verwendet um einen vorsätzlich gewählten 'Nicht'-Wert anzuzeigen
-undefined; // wird verwendet um anzuzeigen, dass der Wert (aktuell) nicht
- // verfügbar ist (obwohl genau genommen undefined selbst einen Wert
- // darstellt)
-
-// false, null, undefined, NaN, 0 und "" sind 'falsy', d. h. alles andere ist
-// wahr. Man beachte, dass 0 falsch und "0" wahr ist, obwohl 0 == "0".
-
-///////////////////////////////////
-// 2. Variablen, Arrays und Objekte
-
-// Variablen werden mit dem Schlüsselwort 'var' und einem frei wählbaren
-// Bezeichner deklariert. JavaScript ist dynamisch typisiert, so dass man einer
-// Variable keinen Typ zuweisen muss. Die Zuweisung verwendet ein einfaches =.
-var einWert = 5;
-
- // Wenn man das Schlüsselwort 'var' weglässt, bekommt man keinen Fehler
-einAndererWert = 10;
-
-// ...aber die Variable wird im globalen Kontext erzeugt, nicht in dem Kontext,
-// in dem sie erzeugt wurde.
-
-// Variablen die erzeugt wurden ohne ihnen einen Wert zuzuweisen, erhalten den
-// Wert 'undefined'.
-var einDritterWert; // = undefined
-
-// Es existiert eine Kurzform, um mathematische Operationen mit Variablen
-// auszuführen:
-einWert += 5; // äquivalent zu einWert = einWert + 5; einWert ist nun also 10
-einWert *= 10; // einWert ist nach dieser Operation 100
-
-// Und es existiert eine weitere, sogar noch kürzere Form, um 1 zu addieren
-// oder zu subtrahieren
-einWert++; // nun ist einWert 101
-einWert--; // wieder 100
-
-// Arrays sind geordnete Listen von Werten irgendeines Typs
-var myArray = ["Hello", 45, true];
-
-// Auf einzelne Elemente eines Arrays kann zugegriffen werden, in dem der Index
-// in eckigen Klammern hinter das Array geschrieben werden. Die Indexierung
-// beginnt bei 0.
-myArray[1]; // = 45
-
-// Arrays haben keine feste Länge
-myArray.push("World");
-myArray.length; // = 4
-
-// und sind veränderlich
-myArray[3] = "Hello";
-
-// Die Objekte in JavaScript entsprechen 'dictionaries' oder 'maps' in anderen
-// Sprachen: es handelt sich um ungeordnete Schlüssel-Wert-Paare.
-var myObj = { key1: "Hello", key2: "World" };
-
-// Schlüssel sind Strings, aber es werden keine Anführungszeichen benötigt,
-// sofern es sich um reguläre JavaScript-Bezeichner handelt. Werte können von
-// jedem Typ sein.
-var myObj = { myKey: "myValue", "my other key": 4 };
-
-// Auf Attribute von Objekten kann ebenfalls mit eckigen Klammern zugegriffen
-// werden,
-myObj["my other key"]; // = 4
-
-// ... oder in dem man die Punkt-Notation verwendet, vorausgesetzt es handelt
-// sich bei dem Schlüssel um einen validen Bezeichner.
-myObj.myKey; // = "myValue"
-
-// Objekte sind veränderlich, Werte können verändert und neue Schlüssel
-// hinzugefügt werden.
-myObj.myThirdKey = true;
-
-// Der Zugriff auf einen noch nicht definierten Schlüssel, liefert ein
-// undefined.
-myObj.myFourthKey; // = undefined
-
-///////////////////////////////////
-// 3. Logik und Kontrollstrukturen
-
-// Die if-Struktur arbeitet, wie man es erwartet.
-var count = 1;
-if (count == 3){
- // wird evaluiert, wenn count gleich 3 ist
-} else if (count == 4) {
- // wird evaluiert, wenn count gleich 4 ist
-} else {
- // wird evaluiert, wenn es weder 3 noch 4 ist
-}
-
-// Genauso 'while'.
-while (true) {
- // Eine unendliche Schleife!
-}
-
-// Do-while-Scheifen arbeiten wie while-Schleifen, abgesehen davon, dass sie
-// immer mindestens einmal ausgeführt werden.
-var input;
-do {
- input = getInput();
-} while ( !isValid( input ) )
-
-// Die for-Schleife arbeitet genau wie in C und Java:
-// Initialisierung; Bedingung, unter der die Ausführung fortgesetzt wird;
-// Iteration.
-for ( var i = 0; i < 5; i++ ) {
- // wird 5-mal ausgeführt
-}
-
-// '&&' ist das logische und, '||' ist das logische oder
-if (house.size == "big" && house.colour == "blue"){
- house.contains = "bear";
- // Die Größe des Hauses ist groß und die Farbe blau.
-}
-if (colour == "red" || colour == "blue"){
- // Die Farbe ist entweder rot oder blau.
-}
-
-// Die Auswertung von '&&' und '||' erfolgt so, dass abgebrochen wird, wenn die
-// Bedingung erfüllt ist (bei oder) oder nicht-erfüllt ist (bei und). Das ist
-// nützlich, um einen Default-Wert zu setzen.
-var name = otherName || "default";
-
-// Ein 'switch' Statement prüft Gleichheit mit ===
-// ohne ein 'break' nach jedem Fall
-// werden auch die Fälle nach dem korrekten aufgerufen
-grade = 'B';
-switch (grade) {
- case 'A':
- console.log("Great job");
- break;
- case 'B':
- console.log("OK job");
- break;
- case 'C':
- console.log("You can do better");
- break;
- default:
- console.log("Oy vey");
- break;
-}
-
-///////////////////////////////////
-// 4. Funktionen, Geltungsbereich und Closures
-
-// In JavaScript werden Funktionen mit dem Schlüsselwort 'function' deklariert.
-function myFunction(thing){
- return thing.toUpperCase();
-}
-myFunction("foo"); // = "FOO"
-
-// Vorsicht: der Ausdruck der den Rückgabewert einer Funktion bildet muss
-// auf der selben Zeile beginnen auf der auch das 'return' Keyword steht
-// Sonst wird hier ein automatisches Semikolon eingefügt und die Funktion
-// gibt 'undefined' zurück
-function myFunction()
-{
- return // <- Hier wird automatisch ein Semikolon eingefügt
- {
- thisIsAn: 'object literal'
- }
-}
-myFunction(); // = undefined
-
-// In JavaScript sind Funktionen 'Bürger erster Klasse', also können sie wie
-// Variablen verwendet und als Parameter anderen Funktionen übergeben werden
-// - zum Beispiel, um einen 'event handler' zu 'beliefern'.
-function myFunction() {
- // wird ausgeführt, nachdem 5 Sekunden vergangen sind
-}
-setTimeout(myFunction, 5000);
-
-// Funktionen können auch deklariert werden, ohne ihnen einen Namen zuzuweisen.
-// Es ist möglich diese anonymen Funktionen direkt als (oder im) Argument
-// einer anderen Funktion zu definieren.
-setTimeout(function(){
- // wird ausgeführt, nachdem 5 Sekunden vergangen sind
-}, 5000);
-
-// JavaScript hat einen Geltungsbereich, der sich auf Funktionen erstreckt:
-// Funktionen haben ihren eigenen Geltungsbereich, andere Blöcke nicht.
-if(true) {
- var i = 5;
-}
-i; // = 5 - nicht undefined, wie man es von einer Sprache erwarten würde, die
- // ihren Geltungsbereich nach Blöcken richtet
-
-// Daraus ergibt sich ein bestimmtes Muster für sofort-ausführbare, anonyme
-// Funktionen, die es vermeiden, dass der globale Geltungsbereich von Variablen
-// 'verschmutzt' wird.
-(function(){
- var temporary = 5;
- // Auf eine Variable im globalen Geltungsbereich kann zugegriffen werden,
- // sofern sie im globalen Objekt definiert ist (in einem Webbrowser ist
- // dies immer das 'window'-Objekt, in anderen Umgebungen, bspw. Node.js,
- // kann das anders aussehen).
- window.permanent = 10;
-})();
-temporary; // wirft einen ReferenceError
-permanent; // = 10
-
-// Eines der mächtigsten Charakteristika von JavaScript sind Closures. Wird
-// eine Funktion innerhalb einer anderen Funktion definiert, dann hat die
-// innere Funktion Zugriff auf alle Variablen der äußeren Funktion, sogar dann,
-// wenn die äußere Funktion beendet wurde.
-function sayHelloInFiveSeconds(name){
- var prompt = "Hello, " + name + "!";
- function inner(){
- alert(prompt);
- }
- setTimeout(inner, 5000);
- // setTimeout wird asynchron ausgeführt. Also wird sayHelloInFiveSeconds
- // sofort verlassen und setTimeout wird die innere Funktion 'im nachhinein'
- // aufrufen. Dennoch: Weil sayHelloInFiveSeconds eine Hülle um die innere
- // Funktion bildet, hat die innere Funktion immer noch Zugriff auf die
- // Variable prompt.
-}
-sayHelloInFiveSeconds("Adam"); // wird nach 5 Sekunden ein Popup mit der
- // Nachricht "Hello, Adam!" öffnen.
-
-///////////////////////////////////
-// 5. Mehr über Objekte, Konstruktoren und Prototypen
-
-// Objekte können Funktionen enthalten.
-var myObj = {
- myFunc: function(){
- return "Hello world!";
- }
-};
-myObj.myFunc(); // = "Hello world!"
-
-// Wenn Funktionen aufgerufen werden, die zu einem Objekt gehören, können sie
-// auf das eigene Objekt mit dem Schlüsselwort 'this' zugreifen.
-myObj = {
- myString: "Hello world!",
- myFunc: function(){
- return this.myString;
- }
-};
-myObj.myFunc(); // = "Hello world!"
-
-// Worauf 'this' gesetzt wird, ist davon abhängig, wie die Funktion aufgerufen
-// wird, nicht wo sie definiert wurde. Unsere Funktion wird daher nicht
-// funktionieren, sofern sie außerhalb des Kontextes des Objekts aufgerufen
-// wird.
-var myFunc = myObj.myFunc;
-myFunc(); // = undefined
-
-// Umgekehrt ist es möglich eine Funktion einem Objekt zuzuweisen und dadurch
-// Zugriff auf den this-Kontext zu erhalten, sogar dann, wenn die Funktion dem
-// Objekt nach dessen Definition zugewiesen wird.
-var myOtherFunc = function(){
- return this.myString.toUpperCase();
-}
-myObj.myOtherFunc = myOtherFunc;
-myObj.myOtherFunc(); // = "HELLO WORLD!"
-
-// Mit den Methoden 'call' und 'apply' kann der Kontext eines Funktionsaufrufs
-// verändert werden
-
-var anotherFunc = function(s){
- return this.myString + s;
-}
-anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!"
-
-// 'apply' funktioniert beiahe identisch, erwartet die übergebenen Argumente
-// aber in einem Array
-
-anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!"
-
-// Das ist hilfreich wenn man einer Funktion eine beliebige Zahl Argumente
-// übergeben kann
-
-Math.min(42, 6, 27); // = 6
-Math.min([42, 6, 27]); // = NaN (uh-oh!)
-Math.min.apply(Math, [42, 6, 27]); // = 6
-
-// 'call' und 'apply' beeinflussen aber nur den spezifischen Aufruf.
-// Um den Kontext einer Funktion dauerhaft zu ändern wird 'bind' benutzt.
-
-var boundFunc = anotherFunc.bind(myObj);
-boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!"
-
-// Mit 'bind' lassen sich Funktionen auch teilweise anwenden / "curryen".
-var product = function(a, b){ return a * b; }
-var doubler = product.bind(this, 2);
-doubler(8); // = 16
-
-// Wenn eine Funktion mit dem Schlüsselwort 'new' aufgerufen wird, dann wird
-// ein neues Objekt erzeugt. Funktionen, die darauf ausgelegt sind in dieser
-// Art aufgerufen zu werden, werden Konstruktoren genannt.
-var MyConstructor = function(){
- this.myNumber = 5;
-}
-myNewObj = new MyConstructor(); // = {myNumber: 5}
-myNewObj.myNumber; // = 5
-
-// Jedes JavaScript-Objekt hat einen Prototyp. Wenn man versucht auf eine
-// Eigenschaft des Objekts zuzugreifen, das nicht im Objekt selbst existiert,
-// schaut der Interpreter in dessen Prototyp nach.
-
-// Einige JavaScript-Implementierungen erlauben den direkten Zugriff auf den
-// Prototyp eines Objekts durch die magische Eigenschaft __proto__. Obwohl das
-// nützlich ist, um Prototypen im Allgemeinen zu erklären, ist das nicht Teil
-// des Standards; zum Standard-Weg der Nutzung von Prototypen kommen wir
-// später.
-var myObj = {
- myString: "Hello world!",
-};
-var myPrototype = {
- meaningOfLife: 42,
- myFunc: function(){
- return this.myString.toLowerCase()
- }
-};
-myObj.__proto__ = myPrototype;
-myObj.meaningOfLife; // = 42
-
-// Das funktioniert auch bei Funktionen.
-myObj.myFunc(); // = "hello world!"
-
-// Sollte die Eigenschaft nicht im Prototypen des Objekts enthalten sein, dann
-// wird im Prototypen des Prototypen nachgesehen und so weiter.
-myPrototype.__proto__ = {
- myBoolean: true
-};
-myObj.myBoolean; // = true
-
-// Dafür wird nichts hin und her kopiert; jedes Objekt speichert eine Referenz
-// auf seinen Prototypen. Das heißt wenn der Prototyp geändert wird, dann
-// werden die Änderungen überall sichtbar.
-myPrototype.meaningOfLife = 43;
-myObj.meaningOfLife; // = 43
-
-// Es wurde bereits erwähnt, dass __proto__ nicht zum Standard gehört und es
-// gibt ebenso keinen Standard-Weg, um den Prototyp eines existierenden Objekts
-// zu ändern. Es gibt dennoch zwei Wege, wie man ein neues Objekt mit einem
-// gegebenen Prototypen erzeugt.
-
-// Der erste Weg ist die Methode Object.create, die eine jüngere Ergänzung des
-// JavaScript-Standards ist und daher noch nicht in allen Implementierungen
-// verfügbar.
-var myObj = Object.create(myPrototype);
-myObj.meaningOfLife; // = 43
-
-// Der zweite Weg, der immer funktioniert, hat mit den Konstruktoren zu tun.
-// Konstruktoren haben eine Eigenschaft, die Prototyp heißt. Dabei handelt es
-// sich *nicht* um den Prototypen der Konstruktor-Funktion; stattdessen handelt
-// es sich um den Prototypen, der einem neuen Objekt mitgegeben wird, wenn es
-// mit dem Konstruktor und dem Schlüsselwort 'new' erzeugt wird.
-MyConstructor.prototype = {
- getMyNumber: function(){
- return this.myNumber
- }
-};
-var myNewObj2 = new MyConstructor();
-myNewObj2.getMyNumber(); // = 5
-
-// Alle primitiven Typen, also strings und numbers, haben auch Konstruktoren,
-// die zu dem Typ äquivalente Wrapper-Objekte erzeugen.
-var myNumber = 12;
-var myNumberObj = new Number(12);
-myNumber == myNumberObj; // = true
-
-// Genau genommen: Sie sind nicht exakt äquivalent.
-typeof myNumber; // = 'number'
-typeof myNumberObj; // = 'object'
-myNumber === myNumberObj; // = false
-if (0){
- // Dieser Teil wird nicht ausgeführt, weil 0 'falsy' ist.
-}
-
-// Das Wrapper-Objekt und die regulären, eingebauten Typen, teilen sich einen
-// Prototyp; so ist es möglich zum Beispiel einem String weitere Funktionen
-// hinzuzufügen.
-String.prototype.firstCharacter = function(){
- return this.charAt(0);
-}
-"abc".firstCharacter(); // = "a"
-
-// Diese Tatsache wird häufig bei einer Methode mit dem Namen 'polyfilling'
-// verwendet: Dabei wird ein neues Feature von JavaScript in einer älteren
-// Untermenge der Sprache integriert, so dass bestimmte Funktionen auch in
-// älteren Umgebungen und Browsern verwendet werden können.
-
-// Ein Beispiel: Es wurde erwähnt, dass die Methode Object.create nicht in
-// allen Umgebungen verfügbar ist - wir können sie dennoch verwenden, mit einem
-// 'polyfill':
-if (Object.create === undefined){ // überschreib nichts, was eventuell bereits
- // existiert
- Object.create = function(proto){
- // erstelle einen vorübergehenden Konstruktor mit dem richtigen
- // Prototypen
- var Constructor = function(){};
- Constructor.prototype = proto;
- // verwende es dann, um ein neues Objekt mit einem passenden
- // Prototypen zurückzugeben
- return new Constructor();
- }
-}
-```
-
-## Zur weiteren Lektüre (englisch)
-
-Das [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript) bietet eine ausgezeichnete Dokumentation für die Verwendung von JavaScript im Browser. Es ist außerdem ein Wiki und ermöglicht es damit anderen zu helfen, wenn man selbst ein wenig Wissen angesammelt hat.
-
-MDN's [A re-introduction to JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) führt sehr viele der hier vorgestellten Konzepte im Detail aus.
-
-Dieses Tutorial hat nur die Sprache JavaScript vorgestellt; um mehr über den Einsatz in Websites zu lernen, ist es ein guter Start etwas über das [Document Object Model](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core) zu lernen.
-
-[JavaScript Garden](http://bonsaiden.github.io/JavaScript-Garden/) ist eine tiefgehende Einführung in die kontra-intuitiven Parts der Sprache.
-
-[JavaScript: The Definitive Guide](http://www.amazon.com/gp/product/0596805527/) ist ein Klassiker unter den Referenzen.
-
-Zusätzlich zu direkten Beiträgen zu diesem Artikel ist der Inhalt in Anlehnung an Louie Dinh's Python-Tutorial auf dieser Seite und das [JS Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) des Mozilla Developer Network entstanden.
+--- +language: javascript +contributors: + - ["Leigh Brenecki", "https://leigh.net.au"] +translators: + - ["ggb", "http://www.ideen-und-soehne.de"] +filename: learnjavascript-de.js +lang: de-de +--- + +(Anmerkungen des Original-Autors:) +JavaScript wurde im Jahr 1995 von Brendan Eich bei Netscape entwickelt. Ursprünglich war es als einfachere Skriptsprache für Websites gedacht, ergänzend zu Java, das für komplexere Webanwendungen verwendet wird. Die enge Integration in Websites und der in Browser eingebaute Support der Sprache haben dafür gesorgt, dass JavaScript weit häufiger für Web-Frontends verwendet wird als Java. + +Dabei ist JavaScript inzwischen nicht mehr auf Browser beschränkt: Node.js, ein Projekt, das eine eigene Laufzeitumgebung auf Grundlage von Google Chromes V8 mitbringt, wird derzeit immer populärer. + +Feedback ist herzlich Willkommen! Der ursprüngliche Autor ist unter [@excitedleigh](https://twitter.com/excitedleigh) oder [l@leigh.net.au](mailto:l@leigh.net.au) zu erreichen. Der Übersetzer unter [gregorbg@web.de](mailto:gregorbg@web.de). + +```js +// Kommentare werden wie in C gesetzt: Einzeilige Kommentare starten mit zwei +// Slashes +/* während mehrzeilige Kommentare mit einem +Slash und einem Stern anfangen und enden */ + +// Statements können mit einem Semikolon beendet werden +machWas(); + +// ...müssen sie aber nicht, weil Semikola automatisch eingefügt werden, wenn +// eine neue Zeile beginnt, abgesehen von einigen Ausnahmen. +machWas() + +// Obwohl wir uns für den Anfang nicht um diese Ausnahmen kümmern müssen ist +// es besser die Semikola immer zu setzen. + +/////////////////////////////////// +// 1. Nummern, Strings und Operationen + +// JavaScript hat einen Nummern-Typ (64-bit IEEE 754 double). +3; // = 3 +1.5; // = 1.5 + +// Beinahe alle grundlegenden arithmetischen Operationen arbeiten wie erwartet. +1 + 1; // = 2 +0.1 + 0.2; // = 0.30000000000000004 +10 * 2; // = 20 +35 / 5; // = 7 + +// Division funktioniert auch mit einem Ergebnis nach dem Komma. +5 / 2; // = 2.5 + +// Bit-weise Operationen sind auch möglich; wenn eine Bit-weise Operation +// ausgeführt wird, wird die Fließkomma-Zahl in einen 32-bit Integer (mit +// Vorzeichen) umgewandelt. +1 << 2; // = 4 + +// Die Rangfolge der Operationen kann mit Klammern erzwungen werden. +(1 + 3) * 2; // = 8 + +// Es gibt drei spezielle, nicht-reale Nummern-Werte: +Infinity; // Ergebnis von z. B. 1 / 0 +-Infinity; // Ergebnis von z. B. -1 / 0 +NaN; // Ergebnis von z. B. 0 / 0 + +// Es gibt auch einen Boolean-Typ (für Wahrheitswerte). +true; +false; + +// Strings werden mit ' oder " erzeugt. +'abc'; +"Hello, world"; + +// Für die Negation wird das ! benutzt. +!true; // = false +!false; // = true + +// Gleichheit wird mit === geprüft. +1 === 1; // = true +2 === 1; // = false + +// Ungleichheit wird mit !== überprüft. +1 !== 1; // = false +2 !== 1; // = true + +// Andere Vergleichsoperatoren sind +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true + +// Strings können mit + verbunden +"Hello " + "world!"; // = "Hello world!" + +// und mit < und > verglichen werden. +"a" < "b"; // = true + +// Für den Vergleich von Werten mit "==" wird eine Typumwandlung erzwungen... +"5" == 5; // = true + +// ...solange man nicht === verwendet. +"5" === 5; // = false + +// Auf einzelne Buchstaben innerhalb eines Strings kann mit der Methode +// 'charAt' zugegriffen werden +"This is a string".charAt(0); // = "T" + +// Die Methode 'substring' gibt Teilbereiche eines Strings zurück +"Hello world".substring(0, 5); // = "Hello" + +// 'length' ist eine Eigenschaft und wird folglich ohne '()' benutzt +"Hello".length; // = 5 + +// Es gibt außerdem die Werte 'null' und 'undefined' +null; // wird verwendet um einen vorsätzlich gewählten 'Nicht'-Wert anzuzeigen +undefined; // wird verwendet um anzuzeigen, dass der Wert (aktuell) nicht + // verfügbar ist (obwohl genau genommen undefined selbst einen Wert + // darstellt) + +// false, null, undefined, NaN, 0 und "" sind 'falsy', d. h. alles andere ist +// wahr. Man beachte, dass 0 falsch und "0" wahr ist, obwohl 0 == "0". + +/////////////////////////////////// +// 2. Variablen, Arrays und Objekte + +// Variablen werden mit dem Schlüsselwort 'var' und einem frei wählbaren +// Bezeichner deklariert. JavaScript ist dynamisch typisiert, so dass man einer +// Variable keinen Typ zuweisen muss. Die Zuweisung verwendet ein einfaches =. +var einWert = 5; + + // Wenn man das Schlüsselwort 'var' weglässt, bekommt man keinen Fehler +einAndererWert = 10; + +// ...aber die Variable wird im globalen Kontext erzeugt, nicht in dem Kontext, +// in dem sie erzeugt wurde. + +// Variablen die erzeugt wurden ohne ihnen einen Wert zuzuweisen, erhalten den +// Wert 'undefined'. +var einDritterWert; // = undefined + +// Es existiert eine Kurzform, um mathematische Operationen mit Variablen +// auszuführen: +einWert += 5; // äquivalent zu einWert = einWert + 5; einWert ist nun also 10 +einWert *= 10; // einWert ist nach dieser Operation 100 + +// Und es existiert eine weitere, sogar noch kürzere Form, um 1 zu addieren +// oder zu subtrahieren +einWert++; // nun ist einWert 101 +einWert--; // wieder 100 + +// Arrays sind geordnete Listen von Werten irgendeines Typs +var myArray = ["Hello", 45, true]; + +// Auf einzelne Elemente eines Arrays kann zugegriffen werden, in dem der Index +// in eckigen Klammern hinter das Array geschrieben werden. Die Indexierung +// beginnt bei 0. +myArray[1]; // = 45 + +// Arrays haben keine feste Länge +myArray.push("World"); +myArray.length; // = 4 + +// und sind veränderlich +myArray[3] = "Hello"; + +// Die Objekte in JavaScript entsprechen 'dictionaries' oder 'maps' in anderen +// Sprachen: es handelt sich um ungeordnete Schlüssel-Wert-Paare. +var myObj = { key1: "Hello", key2: "World" }; + +// Schlüssel sind Strings, aber es werden keine Anführungszeichen benötigt, +// sofern es sich um reguläre JavaScript-Bezeichner handelt. Werte können von +// jedem Typ sein. +var myObj = { myKey: "myValue", "my other key": 4 }; + +// Auf Attribute von Objekten kann ebenfalls mit eckigen Klammern zugegriffen +// werden, +myObj["my other key"]; // = 4 + +// ... oder in dem man die Punkt-Notation verwendet, vorausgesetzt es handelt +// sich bei dem Schlüssel um einen validen Bezeichner. +myObj.myKey; // = "myValue" + +// Objekte sind veränderlich, Werte können verändert und neue Schlüssel +// hinzugefügt werden. +myObj.myThirdKey = true; + +// Der Zugriff auf einen noch nicht definierten Schlüssel, liefert ein +// undefined. +myObj.myFourthKey; // = undefined + +/////////////////////////////////// +// 3. Logik und Kontrollstrukturen + +// Die if-Struktur arbeitet, wie man es erwartet. +var count = 1; +if (count == 3){ + // wird evaluiert, wenn count gleich 3 ist +} else if (count == 4) { + // wird evaluiert, wenn count gleich 4 ist +} else { + // wird evaluiert, wenn es weder 3 noch 4 ist +} + +// Genauso 'while'. +while (true) { + // Eine unendliche Schleife! +} + +// Do-while-Scheifen arbeiten wie while-Schleifen, abgesehen davon, dass sie +// immer mindestens einmal ausgeführt werden. +var input; +do { + input = getInput(); +} while ( !isValid( input ) ) + +// Die for-Schleife arbeitet genau wie in C und Java: +// Initialisierung; Bedingung, unter der die Ausführung fortgesetzt wird; +// Iteration. +for ( var i = 0; i < 5; i++ ) { + // wird 5-mal ausgeführt +} + +// '&&' ist das logische und, '||' ist das logische oder +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear"; + // Die Größe des Hauses ist groß und die Farbe blau. +} +if (colour == "red" || colour == "blue"){ + // Die Farbe ist entweder rot oder blau. +} + +// Die Auswertung von '&&' und '||' erfolgt so, dass abgebrochen wird, wenn die +// Bedingung erfüllt ist (bei oder) oder nicht-erfüllt ist (bei und). Das ist +// nützlich, um einen Default-Wert zu setzen. +var name = otherName || "default"; + +// Ein 'switch' Statement prüft Gleichheit mit === +// ohne ein 'break' nach jedem Fall +// werden auch die Fälle nach dem korrekten aufgerufen +grade = 'B'; +switch (grade) { + case 'A': + console.log("Great job"); + break; + case 'B': + console.log("OK job"); + break; + case 'C': + console.log("You can do better"); + break; + default: + console.log("Oy vey"); + break; +} + +/////////////////////////////////// +// 4. Funktionen, Geltungsbereich und Closures + +// In JavaScript werden Funktionen mit dem Schlüsselwort 'function' deklariert. +function myFunction(thing){ + return thing.toUpperCase(); +} +myFunction("foo"); // = "FOO" + +// Vorsicht: der Ausdruck der den Rückgabewert einer Funktion bildet muss +// auf der selben Zeile beginnen auf der auch das 'return' Keyword steht +// Sonst wird hier ein automatisches Semikolon eingefügt und die Funktion +// gibt 'undefined' zurück +function myFunction() +{ + return // <- Hier wird automatisch ein Semikolon eingefügt + { + thisIsAn: 'object literal' + } +} +myFunction(); // = undefined + +// In JavaScript sind Funktionen 'Bürger erster Klasse', also können sie wie +// Variablen verwendet und als Parameter anderen Funktionen übergeben werden +// - zum Beispiel, um einen 'event handler' zu 'beliefern'. +function myFunction() { + // wird ausgeführt, nachdem 5 Sekunden vergangen sind +} +setTimeout(myFunction, 5000); + +// Funktionen können auch deklariert werden, ohne ihnen einen Namen zuzuweisen. +// Es ist möglich diese anonymen Funktionen direkt als (oder im) Argument +// einer anderen Funktion zu definieren. +setTimeout(function(){ + // wird ausgeführt, nachdem 5 Sekunden vergangen sind +}, 5000); + +// JavaScript hat einen Geltungsbereich, der sich auf Funktionen erstreckt: +// Funktionen haben ihren eigenen Geltungsbereich, andere Blöcke nicht. +if(true) { + var i = 5; +} +i; // = 5 - nicht undefined, wie man es von einer Sprache erwarten würde, die + // ihren Geltungsbereich nach Blöcken richtet + +// Daraus ergibt sich ein bestimmtes Muster für sofort-ausführbare, anonyme +// Funktionen, die es vermeiden, dass der globale Geltungsbereich von Variablen +// 'verschmutzt' wird. +(function(){ + var temporary = 5; + // Auf eine Variable im globalen Geltungsbereich kann zugegriffen werden, + // sofern sie im globalen Objekt definiert ist (in einem Webbrowser ist + // dies immer das 'window'-Objekt, in anderen Umgebungen, bspw. Node.js, + // kann das anders aussehen). + window.permanent = 10; +})(); +temporary; // wirft einen ReferenceError +permanent; // = 10 + +// Eines der mächtigsten Charakteristika von JavaScript sind Closures. Wird +// eine Funktion innerhalb einer anderen Funktion definiert, dann hat die +// innere Funktion Zugriff auf alle Variablen der äußeren Funktion, sogar dann, +// wenn die äußere Funktion beendet wurde. +function sayHelloInFiveSeconds(name){ + var prompt = "Hello, " + name + "!"; + function inner(){ + alert(prompt); + } + setTimeout(inner, 5000); + // setTimeout wird asynchron ausgeführt. Also wird sayHelloInFiveSeconds + // sofort verlassen und setTimeout wird die innere Funktion 'im nachhinein' + // aufrufen. Dennoch: Weil sayHelloInFiveSeconds eine Hülle um die innere + // Funktion bildet, hat die innere Funktion immer noch Zugriff auf die + // Variable prompt. +} +sayHelloInFiveSeconds("Adam"); // wird nach 5 Sekunden ein Popup mit der + // Nachricht "Hello, Adam!" öffnen. + +/////////////////////////////////// +// 5. Mehr über Objekte, Konstruktoren und Prototypen + +// Objekte können Funktionen enthalten. +var myObj = { + myFunc: function(){ + return "Hello world!"; + } +}; +myObj.myFunc(); // = "Hello world!" + +// Wenn Funktionen aufgerufen werden, die zu einem Objekt gehören, können sie +// auf das eigene Objekt mit dem Schlüsselwort 'this' zugreifen. +myObj = { + myString: "Hello world!", + myFunc: function(){ + return this.myString; + } +}; +myObj.myFunc(); // = "Hello world!" + +// Worauf 'this' gesetzt wird, ist davon abhängig, wie die Funktion aufgerufen +// wird, nicht wo sie definiert wurde. Unsere Funktion wird daher nicht +// funktionieren, sofern sie außerhalb des Kontextes des Objekts aufgerufen +// wird. +var myFunc = myObj.myFunc; +myFunc(); // = undefined + +// Umgekehrt ist es möglich eine Funktion einem Objekt zuzuweisen und dadurch +// Zugriff auf den this-Kontext zu erhalten, sogar dann, wenn die Funktion dem +// Objekt nach dessen Definition zugewiesen wird. +var myOtherFunc = function(){ + return this.myString.toUpperCase(); +} +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!" + +// Mit den Methoden 'call' und 'apply' kann der Kontext eines Funktionsaufrufs +// verändert werden + +var anotherFunc = function(s){ + return this.myString + s; +} +anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" + +// 'apply' funktioniert beiahe identisch, erwartet die übergebenen Argumente +// aber in einem Array + +anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" + +// Das ist hilfreich wenn man einer Funktion eine beliebige Zahl Argumente +// übergeben kann + +Math.min(42, 6, 27); // = 6 +Math.min([42, 6, 27]); // = NaN (uh-oh!) +Math.min.apply(Math, [42, 6, 27]); // = 6 + +// 'call' und 'apply' beeinflussen aber nur den spezifischen Aufruf. +// Um den Kontext einer Funktion dauerhaft zu ändern wird 'bind' benutzt. + +var boundFunc = anotherFunc.bind(myObj); +boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" + +// Mit 'bind' lassen sich Funktionen auch teilweise anwenden / "curryen". +var product = function(a, b){ return a * b; } +var doubler = product.bind(this, 2); +doubler(8); // = 16 + +// Wenn eine Funktion mit dem Schlüsselwort 'new' aufgerufen wird, dann wird +// ein neues Objekt erzeugt. Funktionen, die darauf ausgelegt sind in dieser +// Art aufgerufen zu werden, werden Konstruktoren genannt. +var MyConstructor = function(){ + this.myNumber = 5; +} +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5 + +// Jedes JavaScript-Objekt hat einen Prototyp. Wenn man versucht auf eine +// Eigenschaft des Objekts zuzugreifen, das nicht im Objekt selbst existiert, +// schaut der Interpreter in dessen Prototyp nach. + +// Einige JavaScript-Implementierungen erlauben den direkten Zugriff auf den +// Prototyp eines Objekts durch die magische Eigenschaft __proto__. Obwohl das +// nützlich ist, um Prototypen im Allgemeinen zu erklären, ist das nicht Teil +// des Standards; zum Standard-Weg der Nutzung von Prototypen kommen wir +// später. +var myObj = { + myString: "Hello world!", +}; +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase() + } +}; +myObj.__proto__ = myPrototype; +myObj.meaningOfLife; // = 42 + +// Das funktioniert auch bei Funktionen. +myObj.myFunc(); // = "hello world!" + +// Sollte die Eigenschaft nicht im Prototypen des Objekts enthalten sein, dann +// wird im Prototypen des Prototypen nachgesehen und so weiter. +myPrototype.__proto__ = { + myBoolean: true +}; +myObj.myBoolean; // = true + +// Dafür wird nichts hin und her kopiert; jedes Objekt speichert eine Referenz +// auf seinen Prototypen. Das heißt wenn der Prototyp geändert wird, dann +// werden die Änderungen überall sichtbar. +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43 + +// Es wurde bereits erwähnt, dass __proto__ nicht zum Standard gehört und es +// gibt ebenso keinen Standard-Weg, um den Prototyp eines existierenden Objekts +// zu ändern. Es gibt dennoch zwei Wege, wie man ein neues Objekt mit einem +// gegebenen Prototypen erzeugt. + +// Der erste Weg ist die Methode Object.create, die eine jüngere Ergänzung des +// JavaScript-Standards ist und daher noch nicht in allen Implementierungen +// verfügbar. +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43 + +// Der zweite Weg, der immer funktioniert, hat mit den Konstruktoren zu tun. +// Konstruktoren haben eine Eigenschaft, die Prototyp heißt. Dabei handelt es +// sich *nicht* um den Prototypen der Konstruktor-Funktion; stattdessen handelt +// es sich um den Prototypen, der einem neuen Objekt mitgegeben wird, wenn es +// mit dem Konstruktor und dem Schlüsselwort 'new' erzeugt wird. +MyConstructor.prototype = { + getMyNumber: function(){ + return this.myNumber + } +}; +var myNewObj2 = new MyConstructor(); +myNewObj2.getMyNumber(); // = 5 + +// Alle primitiven Typen, also strings und numbers, haben auch Konstruktoren, +// die zu dem Typ äquivalente Wrapper-Objekte erzeugen. +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true + +// Genau genommen: Sie sind nicht exakt äquivalent. +typeof myNumber; // = 'number' +typeof myNumberObj; // = 'object' +myNumber === myNumberObj; // = false +if (0){ + // Dieser Teil wird nicht ausgeführt, weil 0 'falsy' ist. +} + +// Das Wrapper-Objekt und die regulären, eingebauten Typen, teilen sich einen +// Prototyp; so ist es möglich zum Beispiel einem String weitere Funktionen +// hinzuzufügen. +String.prototype.firstCharacter = function(){ + return this.charAt(0); +} +"abc".firstCharacter(); // = "a" + +// Diese Tatsache wird häufig bei einer Methode mit dem Namen 'polyfilling' +// verwendet: Dabei wird ein neues Feature von JavaScript in einer älteren +// Untermenge der Sprache integriert, so dass bestimmte Funktionen auch in +// älteren Umgebungen und Browsern verwendet werden können. + +// Ein Beispiel: Es wurde erwähnt, dass die Methode Object.create nicht in +// allen Umgebungen verfügbar ist - wir können sie dennoch verwenden, mit einem +// 'polyfill': +if (Object.create === undefined){ // überschreib nichts, was eventuell bereits + // existiert + Object.create = function(proto){ + // erstelle einen vorübergehenden Konstruktor mit dem richtigen + // Prototypen + var Constructor = function(){}; + Constructor.prototype = proto; + // verwende es dann, um ein neues Objekt mit einem passenden + // Prototypen zurückzugeben + return new Constructor(); + } +} +``` + +## Zur weiteren Lektüre (englisch) + +Das [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript) bietet eine ausgezeichnete Dokumentation für die Verwendung von JavaScript im Browser. Es ist außerdem ein Wiki und ermöglicht es damit anderen zu helfen, wenn man selbst ein wenig Wissen angesammelt hat. + +MDN's [A re-introduction to JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) führt sehr viele der hier vorgestellten Konzepte im Detail aus. + +Dieses Tutorial hat nur die Sprache JavaScript vorgestellt; um mehr über den Einsatz in Websites zu lernen, ist es ein guter Start etwas über das [Document Object Model](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core) zu lernen. + +[JavaScript Garden](http://bonsaiden.github.io/JavaScript-Garden/) ist eine tiefgehende Einführung in die kontra-intuitiven Parts der Sprache. + +[JavaScript: The Definitive Guide](http://www.amazon.com/gp/product/0596805527/) ist ein Klassiker unter den Referenzen. + +Zusätzlich zu direkten Beiträgen zu diesem Artikel ist der Inhalt in Anlehnung an Louie Dinh's Python-Tutorial auf dieser Seite und das [JS Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) des Mozilla Developer Network entstanden. diff --git a/de-de/latex-de.html.markdown b/de-de/latex-de.html.markdown index ee9c6e3e..8a952b15 100644 --- a/de-de/latex-de.html.markdown +++ b/de-de/latex-de.html.markdown @@ -39,13 +39,13 @@ filename: latex-de.tex % Dieses Kommando kann man später benutzen. \newcommand{\comment}[1]{} -% Es können durchaus noch weitere Optione für das Dokument gesetzt werden! +% Es können durchaus noch weitere Optionen für das Dokument gesetzt werden! \author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu} \date{\today} \title{Learn \LaTeX\ in Y Minutes!} % Nun kann's losgehen mit unserem Dokument. -% Alles vor dieser Zeile wird die Preamble genannt. +% Alles vor dieser Zeile wird die Präambel genannt. \begin{document} \comment{ @@ -62,7 +62,7 @@ filename: latex-de.tex % Inhalt erscheinen. % Dieser Befehl ist in den Dokumentenklassen article und report verfügbar. \begin{abstract} - \LaTeX -Documentation geschrieben in \LaTeX ! Wie ungewöhnlich und garantiert nicht meine Idee! + \LaTeX -Dokumentation geschrieben in \LaTeX ! Wie ungewöhnlich und garantiert nicht meine Idee! \end{abstract} % Section Befehle sind intuitiv. @@ -113,7 +113,7 @@ anderen Wissenschaften. Und deswegen müssen wir in der Lage sein, spezielle Symbole zu unserem Paper hinzuzufügen! \\ Mathe kennt sehr viele Symbole, viel mehr als auf einer Tastatur zu finden sind; -Symbole für Mengen und relationen, Pfeile, Operatoren und Griechische Buchstaben, +Symbole für Mengen und Relationen, Pfeile, Operatoren und Griechische Buchstaben, um nur ein paar zu nennen.\\ Mengen und Relationen spielen eine sehr wichtige Rolle in vielen mathematischen diff --git a/de-de/make-de.html.markdown b/de-de/make-de.html.markdown index cf90dc29..3674f2f5 100644 --- a/de-de/make-de.html.markdown +++ b/de-de/make-de.html.markdown @@ -1,262 +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äftig 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 das 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 das 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) + diff --git a/de-de/nix-de.html.markdown b/de-de/nix-de.html.markdown index 79b60d20..a55a91c7 100644 --- a/de-de/nix-de.html.markdown +++ b/de-de/nix-de.html.markdown @@ -8,11 +8,11 @@ translators: lang: de-de --- -Nix ist eine simple funktionale Programmiersprache, die für den +Nix ist eine simple funktionale Programmiersprache, die für den [Nix package manager](https://nixos.org/nix/) und [NixOS](https://nixos.org/) entwickelt wurde. -Du kannst Nix Ausdrücke evaluieren mithilfe von +Du kannst Nix Ausdrücke evaluieren mithilfe von [nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate) oder [`nix-repl`](https://github.com/edolstra/nix-repl). @@ -24,7 +24,7 @@ with builtins; [ # Inline Kommentare sehen so aus. - /* Multizeilen Kommentare + /* Multizeilen Kommentare sehen so aus. */ @@ -61,7 +61,7 @@ with builtins; [ "String Literale sind in Anführungszeichen." " - String Literale können mehrere + String Literale können mehrere Zeilen umspannen. " @@ -95,7 +95,7 @@ with builtins; [ tutorials/learn.nix #=> /the-base-path/tutorials/learn.nix - # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine + # Ein Pfad muss mindestens einen Schrägstrich enthalten. Ein Pfad für eine # Datei im selben Verzeichnis benötigt ein ./ Präfix. ./learn.nix #=> /the-base-path/learn.nix @@ -238,7 +238,7 @@ with builtins; [ #=> { d = 2; e = 3; } # Die Nachkommen eines Attributs können in diesem Feld nicht zugeordnet werden, wenn - # das Attribut selbst nicht zugewiesen wurde. + # das Attribut selbst nicht zugewiesen wurde. { a = { b = 1; }; a.c = 2; @@ -261,9 +261,9 @@ with builtins; [ #=> 7 # Die erste Linie diese Tutorials startet mit "with builtins;", - # weil builtins ein Set mit allen eingebauten + # weil builtins ein Set mit allen eingebauten # Funktionen (length, head, tail, filter, etc.) umfasst. - # Das erspart uns beispielsweise "builtins.length" zu schreiben, + # Das erspart uns beispielsweise "builtins.length" zu schreiben, # anstatt nur "length". @@ -305,7 +305,7 @@ with builtins; [ (tryEval (abort "foo")) #=> error: evaluation aborted with the following error message: ‘foo’ - # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst + # `assert` evaluiert zu dem gegebenen Wert, wenn die Bedingung wahr ist, sonst # löst es eine abfangbare Exception aus. (assert 1 < 2; 42) #=> 42 @@ -319,7 +319,7 @@ with builtins; [ #========================================= # Da die Wiederholbarkeit von Builds für den Nix Packetmanager entscheidend ist, - # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar + # werden in der Nix Sprache reine funktionale Elemente betont. Es gibt aber ein paar # unreine Elemente. # Du kannst auf Umgebungsvariablen verweisen. (getEnv "HOME") @@ -355,4 +355,10 @@ with builtins; [ (https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55) * [Susan Potter - Nix Cookbook - Nix By Example] - (http://funops.co/nix-cookbook/nix-by-example/) + (https://ops.functionalalgebra.com/nix-by-example/) + +* [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) diff --git a/de-de/perl-de.html.markdown b/de-de/perl-de.html.markdown index fd8fb3c4..13c00b01 100644 --- a/de-de/perl-de.html.markdown +++ b/de-de/perl-de.html.markdown @@ -8,9 +8,9 @@ translators: lang: de-de --- -Perl 5 ist eine sehr mächtige, funktionsreiche Programmiersprache mit über 25 Jahren Entwicklungsgeschichte. +Perl ist eine sehr mächtige, funktionsreiche Programmiersprache mit über 25 Jahren Entwicklungsgeschichte. -Perl 5 läuft auf über 100 Platformen von portablen Geräten bis hin zu Mainframes. Perl 5 ist geeignet für Rapid-Prototyping und auch groß angelegte Entwicklungs-Projekte. +Perl läuft auf über 100 Platformen von portablen Geräten bis hin zu Mainframes. Perl ist geeignet für Rapid-Prototyping und auch groß angelegte Entwicklungs-Projekte. ```perl # Einzeilige Kommentare beginnen mit dem # Symbol. diff --git a/de-de/processing-de.html.markdown b/de-de/processing-de.html.markdown new file mode 100644 index 00000000..42ae2233 --- /dev/null +++ b/de-de/processing-de.html.markdown @@ -0,0 +1,498 @@ +--- +language: processing +filename: learnprocessing.pde +contributors: + - ["Phone Thant Ko", "http://github.com/phonethantko"] + - ["Divay Prakash", "https://github.com/divayprakash"] +translators: + - ["caminsha", "https://github.com/caminsha"] +filename: processing-de.md +lang: de-de +--- + +## Einführung + +Processing ist eine Programmiersprache, welche es ermöglicht, digitale Kunst +und multimediale Inhalte zu erstellen. Mit Processing können Personen ohne +Programmiererfahrung die Grundlagen der Computerprogrammierung in einem +visuellen Kontext erlernen. + +Obwohl Processing von Java beeinflusst wurde und auf Java basiert, ist die Syntax +sowohl von Java als auch Javascript beeinflusst worden. Weitere Informationen +sind [hier](https://processing.org/reference/) zu finden. + +Die Programmiersprache wird statisch programmiert und kommt mit einer eigenen +offiziellen IDE, damit die Programme kompiliert und ausgeführt werden können. + +``` +/* ------------ + Mehrzeilige Kommentare werden so gemacht +*/ + +// Einzeilige Kommentare funktionieren so // + +/* + Da Processing von Java abstammt, ist die Syntax für Kommentare gleich + wie bei Java (wie du vielleicht oben bemerkt hast)! + Mehrzeilige Kommentare werden wie hier umschloßen. +*/ + +/* ------------------------------------------------- + Schreiben und Ausführen von Processing Programmen + ------------------------------------------------- +*/ + +// In Processing ist der Startpunkt eines Programms die Funktion `setup()` +// mit dem Rückgabetyp `void`. +// Beachte: Die Syntax ist derjenigen von C++ ziemlich ähnlich. +void setup() { + // Dies gibt beim Ausführen "Hallo Welt!" auf der Konsole aus. + println("Hallo Welt!"); // eine weitere Sprache mit einem Semikolon am Ende. +} + +// Normalerweise wird der Code für statische Elemente innerhalb der Methode +// `setup()` geschrieben, da diese lediglich einmal ausgeführt wird. +// Dies kann zum Beispiel das Setzen der Hintergrundfarbe oder das Bestimmen +// der Canvas-Größe sein. +background(color); // Setze die Hintergrundfarbe +size(width, height, [renderer]); // bestimme die Canvasgröße mit dem optionalen + // Parameter `renderer`. +// Du wirst innerhalb dieses Dokuments noch weitere Parameter sehen. + +// Wenn du möchstest, dass Code unendlich oft ausgeführt wird, so muss dieser +// Code innerhalb der `draw()`-Methode stehen. +// `draw()` muss existieren, wenn du möchtest, dass das Programm durchgehend +// läuft. Die `draw()`-Methode darf nur einmal vorkommen. + +int i = 0; +void draw() { + // Dieser Codeblock wird ausgeführt bis er gestoppt wird. + print(i); + i++; // Inkrement-Operator +} + +// Da wir nun wissen, wie man ein funktionierendes Skript erstellen kann und wie +// dieses ausgeführt wird, fahren wir mit den unterschiedlichen Datentypen und +// Collections weiter, welche in Processing unterstützt werden. + +/* ------------------------------------------------- + Datentypen und Collections + ------------------------------------------------- +*/ + +// Gemäß den Angaben in der Processingreferenz, unterstützt Processing die +// folgenden acht primitiven Datentypen: +boolean booleanValue = true; // Boolean +byte byteValueOfA = 23; // Byte +char charValueOfA = 'A'; // Char (einzelnes Zeichen) +color colorValueOfWhiteM = color(255, 255, 255); // Farben (angegeben durch die + // `color()`-Methode) +color colorValueOfWhiteH = #FFFFFF; // Farbe (angegeben mit der Hexadezimal- + // schreibweise.) +int intValue = 5; // Integer (ganze Zahl) +long longValue = 2147483648L; // "L" wird hinzugefügt, um es als `long` zu + // markieren. +float floatValue = 1.12345; // Float (32-Bit Gleitkommazahl) +double doubleValue = 1.12345D // Double (64-Bit Gleitkommazahl) + +//BEACHTE! +// Auch wenn es die Datentypen "long" und "double" gibt und auch funktionieren, +// verwenden Processing-Funktionen diese Datentypen nicht. Das bedeutet, dass +// diese zu "int" resp. "float" konvertiert werden müssen. +// Dies geschieht, indem man `(int)` oder `(float)` vor die Variable schreibt, +// bevor diese einer Funktion übergeben werden. + +// Es gibt eine ganze Reiher zusammengesetzter Datentypen, welche in Processing +// gebraucht werden können. Um Zeit zu sparen, gehen wir in diesem Tutorial +// lediglich die wichtigsten durch. + +// String +// Während der Datentyp `char` einfache Anzührungszeichen (' ') braucht, haben +// Strings doppelte Anführungszeichen (" "). +String sampleString = "Hallo, Processing!"; +// Strings können auch durch ein Array von `char`s erstellt werden. +// Wir werden Arrays gleich anschauen. +char source = {'H', 'A', 'L', 'L', 'O'}; +String stringFromSource = new String(source); // HALLO +// Wie auch in Java können in Processing Strings auch zusammengefügt werden +// mit dem +-Operator. +print("Hallo " + "Welt!"); // => Hallo Welt! + + +// Arrays +// In Processing können Arrays jeden Datentypen beinhalten, sogar Objekte. +// Da Arrays ähnlich wie Objekte sind, müssen diese mit dem Schlüsselwort `new` +// erstellt werden. +int[] intArray = new int[5]; +int[] intArrayWithValues = {1, 2, 3} // Arrays können auch mit Daten gefüllt + // werden. +// ArrayList +// Die Funktionen einer ArrayList sind ähnlich wie die eines Arrays und können +// auch jegliche Datentypen beinhalten. Der einzige Unterschied zwischen Arrays +// und `ArrayList`s ist, dass eine `ArrayList` die Größe dynamisch anpassen kann, +// da es eine Implementierung des "List" Interface in Java ist. +ArrayList<Integer> intArrayList = new ArrayList<Integer>(); + +// Objekte +// Da Processing auf Java basiert, unterstützt Processing die Objektorientierte +// Programmierung. Dies bedeutet, dass du grundsätzlich jegliche Datentypen +// selber erstellen kannst und diese nach deinen Bedürfnissen manipulieren kannst. +// Selbstverständlich muss eine Klasse definiert werden bevor du ein Objekt +// davon instanzieren kannst. +// Format: ClassName InstanceName +SomeRandomClass myObject // hier musst du das Objekt später instazieren +// Hier wird das Objekt direkt instanziert: +SomeRandomClass myObjectInstantiated = new SomeRandomClass(); + +// Processing hat noch weitere Collections (wie zum Beispiel Dictionaries und +// Listen). Aus Einfachheitsgründen wird dies in diesem Tutorial weggelassen. + +/* ------------------------------------------------- + Mathematik + ------------------------------------------------- +*/ + +// Arithmetik +1 + 1 // => 2 +2 -1 // => 1 +2 * 3 // => 6 +3 / 2 // => 1 +3.0 / 2 // => 1.5 +3.0 % 2 // => 1.0 (Modulo) + +// Processing beinhaltet auch einige Funktionen, welche mathematische +// Operationen vereinfachen +float f = sq(3); // Quadrat => f = 9.0 +float p = pow(3, 3); // Potenz => p = 27.0 +int a = abs(-13); // Absolute Zahl => a = 13 +int r1 = round(3.1); // Runden => r1 = 3 +int r2 = round(3.7); // Runden => r2 = 4 +int sr = sqrt(25); // Quadratwurzel => sr = 5.0 + +// Vektoren +// Processing bietet eine einfache Möglichkeit an, mit Vektoren zu arbeiten mit +// der Klasse PVector. Die Klasse kann zwei- und dreidimensionale Vektoren +// darstellen und bietet Methoden an, welche nützlich sein können für Matrizen- +// Operationen. Weitere Informationen findest du hier: +// (https://processing.org/reference/PVector.html) + +// Trigonometrie +// Processing unterstützt auch trigonometrische Operationen mit Hilfe dieser +// Funktionen: `sin()`, `cos()`, `tan()`, `asin()`, `atan()`. Für die einfache +// Konvertierung gibt es außerdem noch die Funktionen `degrees()` und `radians()`. +// Die trigonometrischen Funktionen rechnen mit dem Winkelmaß Radian, wodurch +// die Gradzahlen zuerst konvertiert werden müssen. +float one = sin(PI/2); // => one = 1.0 +// Wie du vielleicht bemerkt hast, existieren einige Konstanten für trigo- +// metrische Operationen; `PI`, `HALF_PI`, `QUARTER_PI` und so weiter ... + +/* ------------------------------------------------- + Kontrollstrukturen + ------------------------------------------------- +*/ + +// Bedingte Anweisungen +// Bedinge Anweisungen werden gleich wie in Java geschrieben. +if (author.getAppearence().equals("hot")) { + print("Narzissmus vom Feinsten!") +} else { + // Du kannst hier weitere Bedingungen prüfen. + print("Irgendetwas ist falsch hier!"); +} +// Für die `if`-Anweisungen gibt es auch eine Kurzschreibweise +// Dies sind sogenannte ternäre Operatoren. +int i = 3; +String value = (i > 5) ? "Groß" : "Klein"; // => "Klein" + +// Die Switch-Case-Anweisung kann verwendet werden, um mehrere Bedingungen +// zu prüfen. +// Wichtig ist, dass nach jeder Bedingung ein `break`-Statement verwendet wird, +// sonst werden alle folgenden ausgeführt und es wird nicht mehr überprüft, ob +// die Bedingung wahr ist. +int value = 2; +switch(value) { + case 0: + print("Auf keinen Fall!"); // Dies wird nicht ausgeführt. + break; // Geht zum nächsten Statement und prüft dieses + case 1: + print("Wir kommen näher..."); // Auch dies wird nicht ausgeführt + break; + case 2: + print("Bravo!"); // Dies wird ausgeführt. + break; + default: + print("Nicht gefunden."); // Diese Zeile wird ausgeführt, wenn keine + // der anderen Operatoren wahr sind. + break; +} + +// Wiederholungen +// For-Schleifen - Auch hier ist die Syntax wieder gleich wie in Java +for(int i = 0; i < 5; i++) { + print(i); // Gibt die Zahlen 0 bis 4 aus. +} + +// While-Statements +int j = 3; +while(j > 0) { + print(j); + j--; // Dies ist wichtig, dass der Code nicht unendlich lange läuft. +} + +// `loop()` | `noloop()` | `redraw()` | `exit()` +// Dies sind spezifische Funktionen, welche in Processing verwendet werden +// können, um den Programmablauf zu steuern. +loop(); // erlaubt es der `draw()`-Methode immer zu laufen, während +noloop(); // dies nur für einmal erlaubt. +redraw(); // führt die `draw()`-Methode noch einmal aus. +exit(); // Diese Methode stoppt das Programm. Dies kann nützlich sein, wenn die + // Methode `draw()` immer läuft. +``` + +## Mit Processing zeichnen + +Da du nun die Grundsätze der Programmiersprache verstanden hast, schauen wir +uns nun das Beste an Processing an - Das Zeichnen! + +``` + +/* ------------------------------------------------- + Figuren + ------------------------------------------------- +*/ + +// 2D-Figuren + +// Punkte +point(x,y); // im zweidimensionalen Raum +point(x, y, z); // im dreidimensionalen Raum +// Diese Befehle zeichnen einen Punkt an der Koordinate. + +// Linien +line(x1, y1, x2, y2); // im zweidimensionalen Raum +// Dies zeichnet eine Linie, welche durch die zwei Punkte (x1, y1) und (x2, y2) +// definiert wird. +line(x1, y1, z1, x2, y2, z2); // im dreidimensionalen Raum +// Analog wird hier eine Linie gezeichnet mit drei Punkten + +// Dreieck +triangle(x1, y1, x2, y2, x3, y3); +// Zeichnet ein Dreieck, welches als Eckpunkte die drei Koordinaten hat. + +// Rechteck +rect(a, b, c, d, [r]); // Mit dem optionalen Parameter kann der Winkel aller + // vier Ecken definiert werden +rect(a, b, c, d, [tl, tr, br, bl]); // Mit weiteren optionalen Parametern kann + // jeder Winkel des Rechtecks definiert werden. +// Dies zeichnet ein Quadrat mit der Koordinate {a, b} als linke obere Ecke +// die Parameter c und d sind für die Breite und Höhe. + +// Vierecke +quad(x, y, x2, y2, x3, y3, x4, y4); +// Dies zeichnet ein Viereck, welches die einzelnen Koordinaten als Eckpunkte hat. + +// Ellipse +ellipse(x, y, width, height); +// Zeichnet eine Ellipse beim Punkt {x. y}. Die Breite und die Höhe werden durch +// die Parameter width und height definiert. + +// Arc +arc(x, y, width, height, start, stop, [mode]); +// Die ersten vier Parameter sollten selbsterklärend sein. +// start und end definieren die Winkel, bei welchen `arc` starten resp. enden +// (in Radians) +// Der optionale Parameter `mode` definiert, ob der Kreisbogen gefüllt wird +// oder nicht. +// Die möglichen Optionen für `mode` sind: PIE, CHORD und OPEN. + +// Kurven +// Processing bietet zwei mögliche Kurven an, welche verwendet werden können. +// Da es hier darum geht, dass es möglichst simpel ist, werden hier keine +// weiteren Details genannt. Wenn du Kurven in deinem Programm verwenden möchtest, +// sind die folgenden Links empfehlenswert: +// https://processing.org/reference/curve_.html +// https://processing.org/reference/bezier_.html + + +// 3D-Figuren + +// Der dreidimensionale Raum kann aktiviert werden, indem man den Renderer- +// Parameter in der Methode `size()` zu "P3D" setzt. +size(width, height, P3D); +// Im dreidimensionalen Raum müssen die Koordinaten übersetzt werden, damit +// diese korrekt gerendert werden. + +// Box +box(size); // Würfel mit der Seitenlänge `size` +box(w, h, d); // Quader definiert durch Breite, Höhe und Tiefe + +// Kugel +sphere(radius); // Die Größe wird definiert durch den Parameter `radius` +// Der Mechanismus hinter dem Rendern von Kugeln wurde durch mosaikartige +// Dreiecke implementiert. +// Mit der folgenden Funktion ist es möglich, zu bestimmen wie detailliert die +// Kugel gerendert wird. +// spereDetail(res); +// Weitere Informationen sind hier zu finden: (https://processing.org/reference/sphereDetail_.html) + +// Unregelmäßige Figuren +// Was ist, wenn du etwas zeichnen möchtest, was nicht durch Processing-Funktionen +// abgedeckt ist? +// Es ist möglich, die Funktionen `beginShape()`, `endShape()` und `vertex(x,y) +// zu verwenden. +// Weitere Informationen findest du hier: (https://processing.org/reference/beginShape_.html) +// Du kannst selber gemachte Formen auch verwenden mit der PShape-Klasse. +// Informationen zu PShape gibt es hier: (https://processing.org/reference/PShape.html) + +/* ------------------------------------------------- + Transformationen + ------------------------------------------------- +*/ + +// Tranformationen sind nützlich, um ständig zu wissen, wo die Koordinaten und +// die Ecken einer Form sind, welche du gezeichnet hast. Grundsätzlich sind dies +// Matrizenoperationen. `pushMatrix()`, `popMatrix()` und `translate()`. +pushMatrix(); // Speichert das aktuelle Koordinatensystem auf dem Stack + // alle Transformationen werden hier angewendet. +popMatrix(); // Stellt das gespeicherte Koordinatensystem wieder her. +// Wenn du diese Funktionen verwendest, kann das Koordinatensystem gespeichert +// und visualisiert werden, ohne dass es Konflikte gibt. + +// Translate +translate(x,y); // Setzt den Ursprung zu diesem Punkt. +translate(x, y, z); // Pendant zu der oberen Funktion im dreidimensionalen Raum + +// Rotationen +rotate(angle); // Rotiere, um den Betrag, welcher spezifiert wurde. +// Es gibt drei Pendants im dreidimensionalen Raum. +// Namentlich sind dies: `rotateX(angle)`, `rotateY(angle)` und `rotateZ(angle)` + +// Skalierung +scale(s); // Skaliert das Koordinatensystem (entweder erweitern oder verkleinern) + +/* ------------------------------------------------- + Styling und Texturen + ------------------------------------------------- +*/ + +// Farben +// Wie ich zuvor schon erklärt habe, kann die Hintergrundfarbe mit der Funktion +// `background()` definiert werden. Außerdem ist es möglich, dass man zuerst +// eine Farbe definiert und diese erst danach der Funktion übergeben wird. +color c = color(255, 255, 255); // WEISS! +// Standardmäßig verwendet Processing das RGB-Farbschema, aber dies kann +// zu HSB konfiguriert werden, indem die Funktion `colorMode()` verwendet wird. +// Weitere Informationen findest du hier: (https://processing.org/reference/colorMode_.html) +background(c); // Ab jetzt ist der Hintergrund in weiß. +// Du kannst die Funktion `fill()` verwenden, um die Farbe auszuwählen, mit +// welcher die Formen ausgefüllt werden. +// Dies muss konfiguriert werden bevor Formen und Figuren gezeichnet werden. +fill(color(0, 0, 0)); +// Wenn du nur die Farbe der Umrandungen definieren möchtest, kannst du die +// Funktion `stroke()` verwenden. +stroke(255, 255, 0, 200); // Linienfarbe wird zu gelb mit einer höheren + // Transparenz geändert. + +// Bilder +// Processing kann Bilder rendern und diese unterschiedlich verwenden. Die +// meisten Bilder sind im Datentyp `PImage` gespeichert. +filter(shader); // Processing unterstützt mehrere Filter-Funktionen, damit + // Bilder verändert werden können. +texture(image); // PImage kann als Argument, weiteren Funktionen übergeben + // werden, um die Figuren zu "Text" zu machen. +``` + +Wenn du weitere Dinge mit Processing kennenlernen willst, dann gibt es unzählige +Dinge, welche du mit Processing machen kannst. Das Rendern von Modellen, +Schattierungen und viele mehr. Für ein kurzes Tutorial bietet Processing zu viel, +daher verweise ich dich, falls du interessiert bist, auf die offizielle +Dokumentaion. + +``` +// Bevor wir weiterfahren, werde ich einige Aspekte zum Importieren von +// Bibliotheken und Paketen sagen, damit du Processing erweitern kannst.. + +/* ------------------------------------------------- + Import + ------------------------------------------------- +*/ + +// Die Macht von Processing kann besser veranschaulicht werden, wenn wir +// Bibliotheken und Pakete importieren. +// Die Import-Anweisung kann wie unten geschrieben zu Beginn des Quelltextes +// geschrieben werden. +import processing.something.*; +``` + +## Beispielprogramm + +Lass uns ein Beispiel von openprocessing.org ansehen, welches verdeutlicht, +was man in Processing mit nur wenigen Zeilen Code machen kann. + +Kopiere den nachfolgenden Code in deine Processing IDE. + +``` +// Disclaimer: Ich habe das Porgramm nicht selbst geschriben. Diese Skizze +// stammt aus openprocessing, allerdings soll dieses Programm zeigen, wie wenig +// Zeilen Code notwendig sind, um etwas Cooles zu machen. +// Abgerufen von: (https://www.openprocessing.org/sketch/559769) + +float theta; +float a; +float col; +float num; + +void setup() { + size(600,600); +} + +void draw() { + background(#F2F2F2); + translate(width/2, height/2); + theta = map(sin(millis()/1000.0), -1, 1, 0, PI/6); + + float num=6; + for (int i=0; i<num; i++) { + a =350; + rotate(TWO_PI/num); + branch(a); + } +} + +void branch(float len) { + col=map(len, 0, 90, 150, 255); + fill(col, 0, 74); + stroke (col, 0, 74); + line(0, 0, 0, -len); + ellipse(0, -len, 3, 3); + len*=0.7; + + if (len>30) { + pushMatrix(); + translate(0, -30); + rotate(theta); + branch(len); + popMatrix(); + + pushMatrix(); + translate(0, -30); + rotate(-theta); + branch(len); + popMatrix(); + } +} +``` + +Processing ist einfach zu erlernen und ist vorallem nützlich, um Multimedia- +Inhalte (auch in 3D) zu erstellen ohne viel Code zu schreiben. Es ist so einfach +gehalten, dass man den Code durchlesen kann und man versteht den Programmablauf +bereits. + +Wenn du externe Bibliotheken, Pakete oder eigene Klassen einbindest, kann ein +Programm, welches mit Processing geschrieben wurde, durchaus auch kompliziert +werden. + +## Einige nützliche Links + +- [Processing Webseite](http://processing.org) +- [Processing Sketches](http://openprocessing.org) diff --git a/de-de/pug-de.html.markdown b/de-de/pug-de.html.markdown new file mode 100644 index 00000000..ce31c648 --- /dev/null +++ b/de-de/pug-de.html.markdown @@ -0,0 +1,208 @@ +--- +language: Pug +contributors: + - ["Michael Warner", "https://github.com/MichaelJGW"] +filename: lernepug-de.pug +translators: + - ["denniskeller", "https://github.com/denniskeller"] +lang: de-de +--- + +## Erste Schritte mit Pug + +Pug ist eine kleine Sprache, die zu HTML kompiliert. Sie hat eine +saubere Syntax mit zusätzlichen Funktionen wie if Anweisungen und Schleifen. +Sie kann auch als serverseitige Templatingsprache für Serversprachen +wie NodeJS verwendet werden. + +### Die Sprache +```pug + +//- Einzeilenkommentar + +//- Mehrzeiliger + Kommentar + +//- ---TAGS--- +//- Grundlagen +div +//- <div></div> +h1 +//- <h1></h1> +mein-benutzerdefiniertesTag +//- <mein-benutzerdefiniertesTag></mein-benutzerdefiniertesTag> + +//- Geschwister +div +div +//- <div></div> + <div></div> + +//- Kind +div + div +//- <div> + <div></div> + </div> + +//- Text +h1 Hallo Welt +//- <h1>Hallo Welt</h1> + +//- Multizeilentext +div. + Hallo + Welt +//- <div> + Hallo + Welt + </div> + +//- ---ATTRIBUTE--- +div(class="meine-klasse" id="meine-id" mein-benutzerdefiniertes-attr="data" enabled) +//- <div class="meine-klasse" id="meine-id" mein-benutzerdefiniertes-attr="data" enabled></div> + +//- Kurzhand +span.meine-klasse +//- <span class="meine-klasse"></span> +.meine-klasse +//- <div class="meine-klasse"></div> +div#meine-id +//- <div id="meine-id"></div> +div#meine-id.meine-klasse +//- <div class="meine-klasse" id="meine-id"></div> + + +//- ---JS--- +- const sprache = "pug"; + +//- Multizeilen JS +- + const srache = "pug"; + const cool = true; + +//- JS Klassen +- const meineKlasse = ['class1', 'class2', 'class3'] +div(class=meineKlasse) +//- <div class="class1 class2 class3"></div> + +//- JS Stil +- const meineStile = {'color':'white', 'background-color':'blue'} +div(styles=meineStile) +//- <div styles="{"color":"white","background-color":"blue"}"></div> + +//- JS Attributte +- const meineAttribute = {"src": "foto.png", "alt": "meine Bilder"} +img&attributes(meineAttribute) +//- <img src="foto.png" alt="meine Bilder"> +- let deaktiviert = false +input(type="text" disabled=deaktiviert) +//- <input type="text"> +- deaktiviert = true +input(type="text" disabled=deaktiviert) +//- <input type="text" disabled> + +//- JS Templating +- const name = "Bob"; +h1 Hi #{name} +h1= name +//- <h1>Hi Bob</h1> +//- <h1>Bob</h1> + +//- ---Schleifen--- + +//- 'each' und 'for' machen das Selbe. Wir werden nur 'each' verwenden. + +each value, i in [1,2,3] + p=value +//- + <p>1</p> + <p>2</p> + <p>3</p> + +each value, index in [1,2,3] + p=value + '-' + index +//- + <p>1-0</p> + <p>2-1</p> + <p>3-2</p> + +each value in [] + p=value +//- + +each value in [] + p=value +else + p Keine Werte sind hier + +//- <p>Keine Werte sind hier</p> + +//- ---BEDINGUNGEN--- + +- const zahl = 5 +if zahl < 5 + p zahl ist kleiner als 5 +else if zahl > 5 + p zahl ist größer als 5 +else + p zahl ist 5 +//- <p>zahl ist 5</p> + +- const bestellungsStatus = "Ausstehend"; +case bestellungsStatus + when "Ausstehend" + p.warn Deine Bestellung steht noch aus + when "Abgeschlossen" + p.success Bestellung ist abgeschlossen. + when -1 + p.error Ein Fehler ist aufgetreten + default + p kein Bestellprotokoll gefunden +//- <p class="warn">Deine Bestellung steht noch aus</p> + +//- --INCLUDE-- +//- File path -> "includes/nav.pug" +h1 Firmenname +nav + a(href="index.html") Home + a(href="about.html") Über uns + +//- Dateipfad -> "index.pug" +html + body + include includes/nav.pug +//- + <html> + <body> + <h1>Firmenname</h1> + <nav><a href="index.html">Home</a><a href="about.html">Über uns</a></nav> + </body> + </html> + +//- Importiere JS und CSS +script + include scripts/index.js +style + include styles/theme.css + +//- ---MIXIN--- +mixin basic() + div Hallo ++basic("Bob") +//- <div>Hallo</div> + +mixin comment(name, kommentar) + div + span.comment-name= name + div.comment-text= kommentar ++comment("Bob", "Das ist super") +//- <div>Hallo</div> + +``` + + +### Zusätzliche Ressourcen +- [The Site](https://pugjs.org/) +- [The Docs](https://pugjs.org/api/getting-started.html) +- [GitHub Repo](https://github.com/pugjs/pug) diff --git a/de-de/pyqt-de.html.markdown b/de-de/pyqt-de.html.markdown index 93ee20d4..3b9b6ebb 100644 --- a/de-de/pyqt-de.html.markdown +++ b/de-de/pyqt-de.html.markdown @@ -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(): diff --git a/de-de/python-de.html.markdown b/de-de/python-de.html.markdown index ee77683e..337f1224 100644 --- a/de-de/python-de.html.markdown +++ b/de-de/python-de.html.markdown @@ -1,9 +1,10 @@ --- -language: python +language: Python contributors: - ["Louie Dinh", "http://ldinh.ca"] translators: - ["kultprok", "http:/www.kulturproktologie.de"] + - ["matthiaskern", "https://github.com/matthiaskern"] filename: learnpython-de.py lang: de-de --- @@ -11,13 +12,16 @@ lang: de-de Anmerkungen des ursprünglichen Autors: Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode. -Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service] +Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service]. -Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber auf Python 2.x anwendbar sein. Haltet Ausschau nach einem Rundgang durch Python 3, der bald erscheinen soll. +Hinweis: Dieser Beitrag bezieht sich implizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/pythonlegacy/) weiter. Beachte hierbei, +dass Python 2 als veraltet gilt und für neue Projekte nicht mehr verwendet werden sollte. ```python + # Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz) -""" Mehrzeilige Strings werden mit + +""" Mehrzeilige Strings werden mit drei '-Zeichen geschrieben und werden oft als Kommentare genutzt. """ @@ -33,15 +37,24 @@ Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber au 1 + 1 #=> 2 8 - 1 #=> 7 10 * 2 #=> 20 -35 / 5 #=> 7 -# Division ist ein wenig kniffliger. Ganze Zahlen werden ohne Rest dividiert -# und das Ergebnis wird automatisch abgerundet. -5 / 2 #=> 2 +# Außer Division, welche automatisch Gleitkommazahlen zurückgibt +35 / 5 # => 7.0 + +# Eine Division kann mit "//" für positive sowie negative Werte abgerundet werden. +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # funktioniert auch mit floats +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 -# Um das zu ändern, müssen wir Gleitkommazahlen einführen und benutzen -2.0 # Das ist eine Gleitkommazahl -11.0 / 4.0 #=> 2.75 Ahhh...schon besser +# Benutzt man eine Gleitkommazahl, ist auch das Ergebnis eine solche +3 * 2.0 # => 6.0 + +# Der Rest einer Division +7 % 3 # => 1 + +# Potenz +2**4 # => 16 # Rangfolge wird mit Klammern erzwungen (1 + 3) * 2 #=> 8 @@ -54,6 +67,18 @@ False not True #=> False not False #=> True +# Boolesche Operatoren +# Hinweis: "and" und "or" müssen klein geschrieben werden +True and False #=> False +False or True #=> True + +# Für die Benutzung von Booleschen Operatoren und ganzen Zahlen +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True + # Gleichheit ist == 1 == 1 #=> True 2 == 1 #=> False @@ -76,58 +101,59 @@ not False #=> True "Das ist ein String." 'Das ist auch ein String.' -# Strings können addiert werden! -"Hello " + "world!" #=> "Hello world!" +# Strings können auch addiert werden! Vermeide dies aber lieber. +"Hallo " + "Welt!" #=> "Hallo Welt!" +# Strings können ohne "+" addiert werden +"Hallo " "welt!" # => "Hallo Welt!" # Ein String kann wie eine Liste von Zeichen verwendet werden "Das ist ein String"[0] #=> 'D' -# Mit % können Strings formatiert werden, etwa so: -"%s können %s werden" % ("Strings", "interpoliert") +# .format kann Strings formatieren +"{} können {} werden".format("Strings", "formatiert") + +# Schneller geht das mit Wiederholungen +"{0} mag Spagetthi, {0} liebt es zu Schwimmen und ganz besonders mag {0} {1}".format("Hans", "Blattsalat") +#=> "Hans mag Spagetthi, Hans liebt es zu Schwimmen und ganz besonders mag Hans Blattsalat" -# Ein modernerer Weg, um Strings zu formatieren, ist die format-Methode. -# Diese Methode wird bevorzugt -"{0} können {1} werden".format("Strings", "formatiert") -# Wir können Schlüsselwörter verwenden, wenn wir nicht abzählen wollen. -"{name} will {food} essen".format(name="Bob", food="Lasagne") +# Die Formatierung kann auch mit `f-strings` oder formattierten Strings gemacht +# werden (ab Python 3.6+) +name = "Sandra" +f"Sie hat gesagt, ihr name sei {name}." # => Sie hat gesagt, ihr Name sei Sandra." +# Es ist möglich, andere Anweisungen innerhalb der geschweiften Klammern zu +# setzen, welche dann im Output des Strings angezeigt werden. +f"{name} ist {len(name)} Zeichen lang" # => Sandra ist 6 Zeichen lang. # None ist ein Objekt None #=> None # Verwendet nicht das Symbol für Gleichheit `==`, um Objekte mit None zu vergleichen -# Benutzt stattdessen `is` +# Benutzt stattdessen `is`. Dieser Operator testet Objektidentität "etc" is None #=> False None is None #=> True -# Der 'is'-Operator testet Objektidentität. Das ist nicht -# sehr nützlich, wenn wir mit primitiven Datentypen arbeiten, aber -# sehr nützlich bei Objekten. - # None, 0, und leere Strings/Listen werden alle als False bewertet. # Alle anderen Werte sind True -0 == False #=> True -"" == False #=> True - +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False #################################################### ## 2. Variablen und Collections #################################################### # Textausgabe ist sehr einfach -print "Ich bin Python. Schön, dich kennenzulernen!" - +print("Ich bin Python. Schön, dich kennenzulernen!") # Es gibt keinen Grund, Variablen vor der Zuweisung zu deklarieren. some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm some_var #=> 5 -# Das Ansprechen einer noch nicht deklarierte Variable löst eine Exception aus. +# Das Ansprechen einer noch nicht deklarierten Variable löst eine Exception aus. # Unter "Kontrollstruktur" kann noch mehr über # Ausnahmebehandlung erfahren werden. -some_other_var # Löst einen NameError aus - -# if kann als Ausdruck verwendet werden -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +some_unknown_var # Löst einen NameError aus # Listen speichern Sequenzen li = [] @@ -150,7 +176,7 @@ li[0] #=> 1 li[-1] #=> 3 # Bei Zugriffen außerhalb der Liste kommt es jedoch zu einem IndexError -li[4] # Raises an IndexError +li[4] # Verursacht einen IndexError # Wir können uns Ranges mit Slice-Syntax ansehen li[1:3] #=> [2, 4] @@ -158,6 +184,12 @@ li[1:3] #=> [2, 4] li[2:] #=> [4, 3] # Das Ende auslassen li[:3] #=> [1, 2, 4] +# Jeden Zweiten Eintrag auswählen +li[::2] # =>[1, 4] +# Eine umgekehrte Kopie zurückgeben +li[::-1] # => [3, 4, 2, 1] +# Jegliche Kombination dieser Syntax machen fortgeschrittene Slices möglich +# li[Start:Ende:Schritt] # Ein bestimmtes Element mit del aus der Liste entfernen del li[2] # li ist jetzt [1, 2, 3] @@ -174,7 +206,6 @@ li.extend(other_li) # Jetzt ist li [1, 2, 3, 4, 5, 6] # Die Länge der Liste mit len ermitteln len(li) #=> 6 - # Tupel sind wie Listen, nur unveränderlich. tup = (1, 2, 3) tup[0] #=> 1 @@ -190,11 +221,10 @@ tup[:2] #=> (1, 2) a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3 # Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen d, e, f = 4, 5, 6 -# Es ist kinderleicht zwei Werte zu tauschen -e, d = d, e # d is now 5 and e is now 4 - +# Es ist kinderleicht, zwei Werte zu tauschen +e, d = d, e # d ist nun 5 und e ist nun 4 -# Dictionarys (Wörterbucher) speichern Key-Value-Paare +# Dictionarys (Wörterbucher) speichern Schlüssel-Werte-Paare empty_dict = {} # Hier ein gefülltes Wörterbuch filled_dict = {"one": 1, "two": 2, "three": 3} @@ -203,15 +233,15 @@ filled_dict = {"one": 1, "two": 2, "three": 3} filled_dict["one"] #=> 1 # So holen wir alle Keys (Schlüssel) als Liste -filled_dict.keys() #=> ["three", "two", "one"] +list(filled_dict.keys()) #=> ["three", "two", "one"] # Hinweis - Die Reihenfolge von Schlüsseln in der Liste ist nicht garantiert. # Einzelne Resultate können anders angeordnet sein. # Alle Values (Werte) als Liste -filled_dict.values() #=> [3, 2, 1] +list(filled_dict.values()) #=> [3, 2, 1] # Hinweis - Hier gelten dieselben Einschränkungen für die Reihenfolge wie bei Schlüsseln. -# Das Vorhandensein eines Schlüssels im Wörterbuch mit in prüfen +# Das Vorhandensein eines Schlüssels im Wörterbuch mit "in" prüfen "one" in filled_dict #=> True 1 in filled_dict #=> False @@ -229,17 +259,23 @@ filled_dict.get("four", 4) #=> 4 filled_dict.setdefault("five", 5) #filled_dict["five"] wird auf 5 gesetzt filled_dict.setdefault("five", 6) #filled_dict["five"] ist noch immer 5 +# Einträge zu einem Wörterbuch hinzufügen +filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} +#filled_dict["four"] = 4 # noch ein Weg, Werte hinzuzufügen + +# Schlüssel von einem Wörterbuch entfernen +del filled_dict["one"] # Entfert den Schlüssel "one" # Sets speichern Mengen empty_set = set() # Initialisieren wir ein Set mit ein paar Werten -some_set = set([1,2,2,3,4]) # some_set ist jetzt set([1, 2, 3, 4]) +some_set = {1, 1, 2, 2, 3, 4} # some_set ist jetzt {1, 2, 3, 4} -# Seit Python 2.7 kann {} benutzt werden, um ein Set zu erstellen -filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} +# Neue Variablen können einer Menge gleichgesetzt werden +filled_set = some_set # Mehr Elemente hinzufügen -filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} +filled_set.add(5) # filled_set ist jetzt {1, 2, 3, 4, 5} # Schnittmengen werden mit & gebildet other_set = {3, 4, 5, 6} @@ -257,7 +293,7 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6} #################################################### -## 3. Kontrollstruktur +## 3. Kontrollstruktur und Iteratoren #################################################### # Erstellen wir mal eine Variable @@ -266,11 +302,11 @@ some_var = 5 # Hier eine if-Anweisung. Die Einrückung ist in Python wichtig! # gibt "some_var ist kleiner als 10" aus if some_var > 10: - print "some_var ist viel größer als 10." + print("some_var ist viel größer als 10.") elif some_var < 10: # Dieser elif-Absatz ist optional. - print "some_var ist kleiner als 10." + print("some_var ist kleiner als 10.") else: # Das hier ist auch optional. - print "some_var ist tatsächlich 10." + print("some_var ist tatsächlich 10.") """ @@ -281,9 +317,9 @@ Ausgabe: maus ist ein Säugetier """ for animal in ["hund", "katze", "maus"]: - # Wir können Strings mit % formatieren - print "%s ist ein Säugetier" % animal - + # Wir können Strings mit format() formatieren + print("{} ist ein Säugetier".format(animal)) + """ `range(Zahl)` gibt eine null-basierte Liste bis zur angegebenen Zahl wieder Ausgabe: @@ -293,7 +329,18 @@ Ausgabe: 3 """ for i in range(4): - print i + print(i) + +""" +"range(unten, oben)" gibt eine Liste von der unteren Zahl bis zur oberen Zahl aus +Ausgabe: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) """ While-Schleifen laufen, bis eine Bedingung erfüllt ist. @@ -305,18 +352,59 @@ Ausgabe: """ x = 0 while x < 4: - print x + print(x) x += 1 # Kurzform für x = x + 1 # Ausnahmebehandlung mit einem try/except-Block - -# Funktioniert in Python 2.6 und höher: try: # Mit raise wird ein Fehler ausgegeben raise IndexError("Das hier ist ein Index-Fehler") except IndexError as e: pass # Pass ist nur eine no-op. Normalerweise würden wir hier den Fehler klären. +except (TypeError, NameError): + pass # Mehrere Fehler können zusammen geklärt werden, falls erforderlich. +else: # Optional, hinter allen except-Blöcken + print("Keine Probleme!") # Wird nur ausgeführt, wenn keine Ausnahmen aufgetreten sind +finally: # Wird immer ausgeführt + print("Hier können wir Ressourcen aufräumen") + +# alternativ zu einem try/finally Block um Aufzuräumen: +with open("meineDatei.txt") as f: + for line in f: + print(line) + +# Python bietet ein fundamentales Konzept der Iteration. +# Das Objekt, auf das die Iteration, also die Wiederholung einer Methode +# angewandt wird, heißt auf Englisch "iterable". +# Die range Methode gibt ein solches Objekt aus. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) #=> range(1,10). Dies ist ein "iterable" Objekt. + +# Über dieses können wir auch iterieren +for i in our_iterable: + print(i) # Gibt one, two, three aus + +# Allerdings können wir die einzelnen Elemente nicht mit ihrem Index ausgeben +our_iterable[1] # TypeError + +# Ein iterable ist ein Objekt, das weiß wie es einen Iteratoren erschafft. +our_iterator = iter(our_iterable) + +# Unser Iterator ist ein Objekt, das sich merkt, welchen Status es gerade hat +# während wir durch es gehen. Das jeweils nächste Objekt bekommen wir mit "next()" +next(our_iterator) #=> "one" + +# Es hält den vorherigen Status +next(our_iterator) #=> "two" +next(our_iterator) #=> "three" +# Nachdem alle Daten ausgegeben worden sind, kommt eine StopIterator Ausnahme zurück +next(our_iterator) # Gibt StopIteration aus + +# Alle Elemente können mit "list()" ausgegeben werden +list(filled_dict.keys()) #=> ["one", "two", "three"] #################################################### ## 4. Funktionen @@ -324,7 +412,7 @@ except IndexError as e: # Mit def neue Funktionen erstellen def add(x, y): - print "x ist %s und y ist %s" % (x, y) + print("x ist %s und y ist %s" % (x, y)) return x + y # Werte werden mit return zurückgegeben # Funktionen mit Parametern aufrufen @@ -348,10 +436,10 @@ def keyword_args(**kwargs): # Rufen wir es mal auf, um zu sehen, was passiert keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} -# Wir können beides gleichzeitig machem, wenn wir wollen +# Wir können beides gleichzeitig machen, wenn wir wollen def all_the_args(*args, **kwargs): - print args - print kwargs + print(args) + print(kwargs) """ all_the_args(1, 2, a=3, b=4) Ausgabe: (1, 2) @@ -366,6 +454,25 @@ all_the_args(*args) # äquivalent zu foo(1, 2, 3, 4) all_the_args(**kwargs) # äquivalent zu foo(a=3, b=4) all_the_args(*args, **kwargs) # äquivalent zu foo(1, 2, 3, 4, a=3, b=4) + +# Anwendungsbereich von Funktionen +x = 5 + +def setX(num): + # lokale Variable x ist nicht die globale Variable x + x = num # => 43 + print (x) # => 43 + +def setGlobalX(num): + global x + print (x) # => 5 + x = num # globale Variable x ist jetzt 6 + print (x) # => 6 + +setX(43) +setGlobalX(6) + + # Python hat First-Class-Funktionen def create_adder(x): def adder(y): @@ -386,72 +493,24 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] [add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] - #################################################### -## 5. Module +## 5. Klassen #################################################### -# Wir können Module importieren -import math -print math.sqrt(16) #=> 4.0 - -# Wir können auch nur spezielle Funktionen eines Moduls importieren -from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 - -# Wir können auch alle Funktionen eines Moduls importieren -# Warnung: Dies wird nicht empfohlen -from math import * - -# Wir können Modulnamen abkürzen -import math as m -math.sqrt(16) == m.sqrt(16) #=> True - -# Module sind in Python nur gewöhnliche Dateien. Wir -# können unsere eigenen schreiben und importieren. Der Name des -# Moduls ist der Dateiname. - -# Wir können herausfinden, welche Funktionen und Attribute in einem -# Modul definiert sind. -import math -dir(math) - -# Wenn Sie ein Python-Skript namens math.py im selben Ordner -# wie Ihr aktuelles Skript haben, wird die Datei math.py -# anstelle des integrierten Python-Moduls geladen. -# Dies geschieht, weil der lokale Ordner Vorrang -# vor den in Python integrierten Bibliotheken hat. - - -#################################################### -## 6. Klassen -#################################################### - -# Wir verwenden das Schlüsselwort "class" um eine Klasse zu erzeugen. +# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten. class Human(object): # Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt species = "H. sapiens" - # Ein simpler Konstruktor, wird aufgerufen, wenn diese Klasse instanziiert wird. - # Beachten Sie, dass die doppelten vorangestellten und nachgestellten - # Unterstriche Objekte oder Attribute bezeichnen, die von Python verwendet werden, - # aber in benutzergesteuerten Namespaces leben. - # Methoden (oder Objekte oder Attribute) wie: __init__, __str__, __repr__ usw. - # werden als Sondermethoden (oder manchmal als Dundermethoden bezeichnet) bezeichnet. - # Sie sollten solche Namen nicht selbst erfinden. + # Ein simpler Konstruktor def __init__(self, name): # Wir weisen das Argument name dem name-Attribut der Instanz zu self.name = name - # Eine Instanzmethode. Alle Methoden erhalten "self" als erstes Argument. + # Eine Instanzmethode. Alle Methoden erhalten self als erstes Argument. def say(self, msg): - return "%s: %s" % (self.name, msg) - - # Eine weitere Instanzmethode - def sing(self): - return 'yo... yo... microphone check... one two... one two...' + return "{name}: {message}".format(name=self.name, message=msg) # Eine Klassenmethode wird von allen Instanzen geteilt. # Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen @@ -464,269 +523,87 @@ class Human(object): def grunt(): return "*grunt*" - # Eine Eigenschaft (Property) ist wie ein Getter. - # Es verwandelt die Methode age() in ein schreibgeschütztes Attribut mit demselben Namen. - # Es ist jedoch nicht nötig, triviale Getter und Setter in Python zu schreiben. - @property - def age(self): - return self._age - - # Damit kann die Eigenschaft festgelegt werden - @age.setter - def age(self, age): - self._age = age - - # Damit kann die Eigenschaft gelöscht werden - @age.deleter - def age(self): - del self._age - -# Wenn ein Python-Interpreter eine Quelldatei liest, führt er den gesamten Code aus. -# Diese __name__-Prüfung stellt sicher, dass dieser Codeblock nur ausgeführt wird, -# wenn dieses Modul das Hauptprogramm ist. -if __name__ == '__main__': - # Eine Instanz einer Klasse erstellen - i = Human(name="Ian") - i.say("hi") # "Ian: hi" - j = Human("Joel") - j.say("hello") # "Joel: hello" - # i und j sind Instanzen des Typs Mensch, oder anders ausgedrückt: Sie sind Objekte des Menschen - - # Rufen wir unsere Klassenmethode auf - i.say(i.get_species()) # "Ian: H. sapiens" - - # Ändern wir das gemeinsame Attribut - Human.species = "H. neanderthalensis" - i.say(i.get_species()) # => "Ian: H. neanderthalensis" - j.say(j.get_species()) # => "Joel: H. neanderthalensis" - - # Aufruf der statischen Methode - print(Human.grunt()) # => "*grunt*" - - # Kann keine statische Methode mit Instanz des Objekts aufrufen, - # da i.grunt () automatisch "self" (das Objekt i) als Argument verwendet - print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given - - # Die Eigenschaft für diese Instanz aktualisieren - i.age = 42 - # die Eigenschaft auslesen - i.say(i.age) # => "Ian: 42" - j.say(j.age) # => "Joel: 0" - # die Eigenschaft löschen - del i.age - # i.age # => würde einen AttributeError werfen - -#################################################### -## 6.1 Inheritance -#################################################### - -# Vererbung ermöglicht die Definition neuer untergeordneter Klassen, -# die Methoden und Variablen von ihrer übergeordneten Klasse erben. - -# Wenn Sie die oben definierte Human-Klasse als Basis- oder Elternklasse verwenden, -# können Sie eine untergeordnete Klasse, Superhero, definieren, die die Klassenvariablen -# wie "species", "name" und "age" sowie Methoden wie "sing" und "grunzen" aus der Klasse Human erbt. -# Die Untergeordnete Klasse kann aber auch eigene Eigenschaften haben. - -# Um von der Modularisierung per Datei zu profitieren, können Sie die Klassen -# in ihren eigenen Dateien platzieren, z. B. human.py - -# Um Funktionen aus anderen Dateien zu importieren, verwenden Sie das folgende Format -# from "Dateiname-ohne-Erweiterung" impotr "Funktion-oder-Klasse" - -from human import Human - -# Geben Sie die übergeordnete(n) Klasse(n) als Parameter für die Klassendefinition an -class Superhero(Human): - - # Wenn die untergeordnete Klasse alle Definitionen des übergeordneten Elements - # ohne Änderungen erben soll, können Sie einfach das Schlüsselwort "pass" - # (und nichts anderes) verwenden. In diesem Fall wird jedoch auskommentiert, - # um eine eindeutige untergeordnete Klasse zuzulassen: - # pass - - # Kindklassen können die Attribute ihrer Eltern überschreiben - species = 'Superhuman' - - # Kinder erben automatisch den Konstruktor ihrer übergeordneten Klasse - # einschließlich ihrer Argumente, können aber auch zusätzliche Argumente oder - # Definitionen definieren und ihre Methoden zB den Klassenkonstruktor überschreiben. - # Dieser Konstruktor erbt das Argument "name" von der Klasse "Human" und - # fügt die Argumente "superpowers" und "movie" hinzu: - def __init__(self, name, movie=False, - superpowers=["super strength", "bulletproofing"]): - - # zusätzliche Klassenattribute hinzufügen: - self.fictional = True - self.movie = movie - # Beachten Sie die veränderlichen Standardwerte, da die Standardwerte gemeinsam genutzt werden - self.superpowers = superpowers - - # Mit der Funktion "super" können Sie auf die Methoden der übergeordneten Klasse - # zugreifen, die vom untergeordneten Objekt überschrieben werden, - # in diesem Fall die Methode __init__. - # Dies ruft den Konstruktor der übergeordneten Klasse auf: - super().__init__(name) - - # überschreiben der "sing" Methode - def sing(self): - return 'Dun, dun, DUN!' - - # eine zusätzliche Instanzmethode hinzufügen - def boast(self): - for power in self.superpowers: - print("I wield the power of {pow}!".format(pow=power)) - -if __name__ == '__main__': - sup = Superhero(name="Tick") - - # Instanztypprüfungen - if isinstance(sup, Human): - print('I am human') - if type(sup) is Superhero: - print('I am a superhero') - - # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, die sowohl von getattr() als auch von super() verwendet wird. - # Dieses Attribut ist dynamisch und kann aktualisiert werden. - print(Superhero.__mro__) # => (<class '__main__.Superhero'>, - # => <class 'human.Human'>, <class 'object'>) - - # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut - print(sup.get_species()) # => Superhuman - - # Ruft die überschriebene Methode auf - print(sup.sing()) # => Dun, dun, DUN! - - # Ruft die Methode von Human auf - sup.say('Spoon') # => Tick: Spoon - - # Aufruf einer Methode, die nur in Superhero existiert - sup.boast() # => I wield the power of super strength! - # => I wield the power of bulletproofing! - - # Vererbtes Klassenattribut - sup.age = 31 - print(sup.age) # => 31 - - # Attribut, das nur in Superhero existiert - print('Am I Oscar eligible? ' + str(sup.movie)) + +# Eine Instanz einer Klasse erstellen +i = Human(name="Ian") +print(i.say("hi")) # gibt "Ian: hi" aus + +j = Human("Joel") +print(j.say("hello")) #gibt "Joel: hello" aus + +# Rufen wir mal unsere Klassenmethode auf +i.get_species() #=> "H. sapiens" + +# Ändern wir mal das gemeinsame Attribut +Human.species = "H. neanderthalensis" +i.get_species() #=> "H. neanderthalensis" +j.get_species() #=> "H. neanderthalensis" + +# Aufruf der statischen Methode +Human.grunt() #=> "*grunt*" + #################################################### -## 6.2 Multiple Inheritance +## 6. Module #################################################### -# Eine weitere Klassendefinition -# bat.py +# Wir können Module importieren +import math +print(math.sqrt(16)) #=> 4.0 -class Bat: +# Wir können auch nur spezielle Funktionen eines Moduls importieren +from math import ceil, floor +print(ceil(3.7)) #=> 4.0 +print(floor(3.7)) #=> 3.0 - species = 'Baty' +# Wir können auch alle Funktionen eines Moduls importieren +# Warnung: Dies wird nicht empfohlen +from math import * - def __init__(self, can_fly=True): - self.fly = can_fly +# Wir können Modulnamen abkürzen +import math as m +math.sqrt(16) == m.sqrt(16) #=> True - # This class also has a say method - def say(self, msg): - msg = '... ... ...' - return msg +# Module sind in Python nur gewöhnliche Dateien. Wir +# können unsere eigenen schreiben und importieren. Der Name des +# Moduls ist der Dateiname. + +# Wir können auch die Funktionen und Attribute eines +# Moduls herausfinden. +import math +dir(math) - # And its own method as well - def sonar(self): - return '))) ... (((' - -if __name__ == '__main__': - b = Bat() - print(b.say('hello')) - print(b.fly) - -# Und noch eine andere Klassendefinition, die von Superhero und Bat erbt -# superhero.py -from superhero import Superhero -from bat import Bat - -# Definieren Sie Batman als eine Kindklasse, das von Superheld und Bat erbt -class Batman(Superhero, Bat): - - def __init__(self, *args, **kwargs): - # In der Regel müssen Sie super aufrufen, um Attribute zu erben: - # super (Batman, selbst) .__ init__ (* args, ** kwargs) - # Allerdings handelt es sich hier um Mehrfachvererbung, und super() - # funktioniert nur mit der nächsten Basisklasse in der MRO-Liste. - # Stattdessen rufen wir explizit __init__ für alle Vorfahren auf. - # Die Verwendung von *args und **kwargs ermöglicht die saubere Übergabe von - # Argumenten, wobei jedes übergeordnete Element eine Schicht der Zwiebel "abschält". - Superhero.__init__(self, 'anonymous', movie=True, - superpowers=['Wealthy'], *args, **kwargs) - Bat.__init__(self, *args, can_fly=False, **kwargs) - # überschreibt den Wert für das Namensattribut - self.name = 'Sad Affleck' - - def sing(self): - return 'nan nan nan nan nan batman!' - -if __name__ == '__main__': - sup = Batman() - - # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, - # die sowohl von getattr() als auch von super() verwendet wird. - # Dieses Attribut ist dynamisch und kann aktualisiert werden. - print(Batman.__mro__) # => (<class '__main__.Batman'>, - # => <class 'superhero.Superhero'>, - # => <class 'human.Human'>, - # => <class 'bat.Bat'>, <class 'object'>) - - # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut - print(sup.get_species()) # => Superhuman - - # Ruft die überschriebene Methode auf - print(sup.sing()) # => nan nan nan nan nan batman! - - # Ruft die Methode von Human auf, weil die Reihenfolge der Vererbung wichtig ist - sup.say('I agree') # => Sad Affleck: I agree - - # Aufrufmethode, die nur im 2. Vorfahren existiert - print(sup.sonar()) # => ))) ... ((( - - # Vererbtes Klassenattribut - sup.age = 100 - print(sup.age) # => 100 - - # Vererbtes Attribut vom 2. Vorfahren, dessen Standardwert überschrieben wurde. - print('Can I fly? ' + str(sup.fly)) # => Can I fly? False - - #################################################### -## 7. Fortgeschrittenes -#################################################### - -# Generatoren helfen Ihnen, lazy Code zu erstellen. +## 7. Fortgeschritten +#################################################### + +# Generatoren helfen, um Code schnell und einfach zu schreiben def double_numbers(iterable): for i in iterable: yield i + i - -# Generatoren sind speichereffizient, da sie nur die Daten laden, -# die zur Verarbeitung des nächsten Werts in der iterierbaren Komponente -# erforderlich sind. Dadurch können sie ansonsten unzulässig große Wertebereiche ausführen. -# HINWEIS: `range` ersetzt` xrange` in Python 3. -for i in double_numbers(range(1, 900000000)): # `range` ist ein Generator. + +# Ein Generator erschafft Werte spontan +# Statt alle Werte auf einmal, wird bei jeder Iteration einer erschaffen. +# iteration. Das heißt, Werte größer als 15 werden nicht behandelt. +# Die range-Methode ist auch ein Generator. Im Fall einer Liste von 1-900000000 +# würde das sehr viel Zeit in Anspruch nehmen. +# Wenn wir eine Variable mit einem Namen erschaffen wollen, das +# normalerweise mit einem Python - Schlüsselwort kollidieren würde, +# benutzen wir einen Unterstrich nach dem Wort. +range_ = range(1, 900000000) +# Alle Nummern bis zu einem Ergebnis von >=30 werden verdoppelt +for i in double_numbers(range_): print(i) if i >= 30: break -# Genauso wie Sie ein 'list comprehension' (Listen Abstraktion) erstellen können, können Sie auch 'generator comprehension' (Generator Abstraktion) erstellen. -values = (-x for x in [1,2,3,4,5]) -for x in values: - print(x) # prints -1 -2 -3 -4 -5 to console/terminal - -# Sie können eine Generator Abstraktion auch direkt in eine Liste umwandeln (casten). -values = (-x for x in [1,2,3,4,5]) -gen_to_list = list(values) -print(gen_to_list) # => [-1, -2, -3, -4, -5] - -# Decorators -# In diesem Beispiel umschliesst "beg" "say". Wenn say_please True ist, wird die zurückgegebene Nachricht geändert. +# Dekoratoren +# In diesem Beispiel die Methode beg umwickelt say +# Beim Aufruf von beg, wird say aufgerufen +# Falls say_please true ist, ändert sich die ausgegebene Nachricht from functools import wraps + def beg(target_function): @wraps(target_function) def wrapper(*args, **kwargs): @@ -737,13 +614,14 @@ def beg(target_function): return wrapper + @beg def say(say_please=False): msg = "Can you buy me a beer?" return msg, say_please -print(say()) # Can you buy me a beer? +print(say()) # Can you buy me a beer? print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( ``` @@ -752,15 +630,18 @@ print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( ### Kostenlos online (Englisch) +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) ### Totholz (Englisch) * [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) * [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) * [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - diff --git a/de-de/python3-de.html.markdown b/de-de/python3-de.html.markdown deleted file mode 100644 index 4ef997a1..00000000 --- a/de-de/python3-de.html.markdown +++ /dev/null @@ -1,655 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://ldinh.ca"] -translators: - - ["kultprok", "http:/www.kulturproktologie.de"] - - ["matthiaskern", "https://github.com/matthiaskern"] -filename: learnpython3-de.py -lang: de-de ---- - -Anmerkungen des ursprünglichen Autors: -Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode. - -Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service]. - -Hinweis: Dieser Beitrag bezieht sich implizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/python/) weiter. - -```python - -# Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz) - -""" Mehrzeilige Strings werden mit - drei '-Zeichen geschrieben und werden - oft als Kommentare genutzt. -""" - -#################################################### -## 1. Primitive Datentypen und Operatoren -#################################################### - -# Die Zahlen -3 #=> 3 - -# Mathematik funktioniert so, wie man das erwartet -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 - -# Außer Division, welche automatisch Gleitkommazahlen zurückgibt -35 / 5 # => 7.0 - -# Eine Division kann mit "//" für positive sowie negative Werte abgerundet werden. -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# Benutzt man eine Gleitkommazahl, ist auch das Ergebnis eine solche -3 * 2.0 # => 6.0 - -# Der Rest einer Division -7 % 3 # => 1 - -# Potenz -2**4 # => 16 - -# Rangfolge wird mit Klammern erzwungen -(1 + 3) * 2 #=> 8 - -# Boolesche Ausdrücke sind primitive Datentypen -True -False - -# Mit not wird negiert -not True #=> False -not False #=> True - -# Boolesche Operatoren -# Hinweis: "and" und "or" müssen klein geschrieben werden -True and False #=> False -False or True #=> True - -# Für die Benutzung von Booleschen Operatoren und ganzen Zahlen -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True - -# Gleichheit ist == -1 == 1 #=> True -2 == 1 #=> False - -# Ungleichheit ist != -1 != 1 #=> False -2 != 1 #=> True - -# Ein paar weitere Vergleiche -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True - -# Vergleiche können verknüpft werden! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False - -# Strings werden mit " oder ' gebildet -"Das ist ein String." -'Das ist auch ein String.' - -# Strings können auch addiert werden! Vermeide dies aber lieber. -"Hallo " + "Welt!" #=> "Hallo Welt!" -# Strings können ohne "+" addiert werden -"Hallo " "welt!" # => "Hallo Welt!" - -# Ein String kann wie eine Liste von Zeichen verwendet werden -"Das ist ein String"[0] #=> 'D' - -# .format kann Strings formatieren -"{} können {} werden".format("Strings", "formatiert") - -# Schneller geht das mit Wiederholungen -"{0} mag Spagetthi, {0} liebt es zu Schwimmen und ganz besonders mag {0} {1}".format("Hans", "Blattsalat") -#=> "Hans mag Spagetthi, Hans liebt es zu Schwimmen und ganz besonders mag Hans Blattsalat" - -# Wir können Schlüsselwörter verwenden, wenn wir nicht abzählen wollen. -"{name} will {food} essen".format(name="Bob", food="Lasagne") -#=> "Bob will Lasagne kochen" - -#Falls dein Python 3 Code auch unter Python 2.5 oder darunter laufen soll, kann das alte Format benutzt werden: -"%s können %s werden" % ("Strings", "interpoliert") - - -# None ist ein Objekt -None #=> None - -# Verwendet nicht das Symbol für Gleichheit `==`, um Objekte mit None zu vergleichen -# Benutzt stattdessen `is`. Dieser Operator testet Objektidentität -"etc" is None #=> False -None is None #=> True - - - -# None, 0, und leere Strings/Listen werden alle als False bewertet. -# Alle anderen Werte sind True -bool(0) # => False -bool("") # => False -bool([]) #=> False -bool({}) #=> False - - -#################################################### -## 2. Variablen und Collections -#################################################### - -# Textausgabe ist sehr einfach -print("Ich bin Python. Schön, dich kennenzulernen!") - -# Es gibt keinen Grund, Variablen vor der Zuweisung zu deklarieren. -some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm -some_var #=> 5 - -# Das Ansprechen einer noch nicht deklarierten Variable löst eine Exception aus. -# Unter "Kontrollstruktur" kann noch mehr über -# Ausnahmebehandlung erfahren werden. -some_unknown_var # Löst einen NameError aus - -# Listen speichern Sequenzen -li = [] -# Wir können mit einer bereits gefüllten Liste anfangen -other_li = [4, 5, 6] - -# append fügt Daten am Ende der Liste ein -li.append(1) #li ist jetzt [1] -li.append(2) #li ist jetzt [1, 2] -li.append(4) #li ist jetzt [1, 2, 4] -li.append(3) #li ist jetzt [1, 2, 4, 3] -# Vom Ende der Liste mit pop entfernen -li.pop() #=> 3 und li ist jetzt [1, 2, 4] -# und dann wieder hinzufügen -li.append(3) # li ist jetzt wieder [1, 2, 4, 3]. - -# Greife auf Listen wie auf Arrays zu -li[0] #=> 1 -# Das letzte Element ansehen -li[-1] #=> 3 - -# Bei Zugriffen außerhalb der Liste kommt es jedoch zu einem IndexError -li[4] # Verursacht einen IndexError - -# Wir können uns Ranges mit Slice-Syntax ansehen -li[1:3] #=> [2, 4] -# Den Anfang auslassen -li[2:] #=> [4, 3] -# Das Ende auslassen -li[:3] #=> [1, 2, 4] -# Jeden Zweiten Eintrag auswählen -li[::2] # =>[1, 4] -# Eine umgekehrte Kopie zurückgeben -li[::-1] # => [3, 4, 2, 1] -# Jegliche Kombination dieser Syntax machen fortgeschrittene Slices möglich -# li[Start:Ende:Schritt] - -# Ein bestimmtes Element mit del aus der Liste entfernen -del li[2] # li ist jetzt [1, 2, 3] - -# Listen können addiert werden -li + other_li #=> [1, 2, 3, 4, 5, 6] - Hinweis: li und other_li werden in Ruhe gelassen - -# Listen mit extend verknüpfen -li.extend(other_li) # Jetzt ist li [1, 2, 3, 4, 5, 6] - -# Mit in auf Existenz eines Elements prüfen -1 in li #=> True - -# Die Länge der Liste mit len ermitteln -len(li) #=> 6 - - -# Tupel sind wie Listen, nur unveränderlich. -tup = (1, 2, 3) -tup[0] #=> 1 -tup[0] = 3 # Löst einen TypeError aus - -# Wir können all diese Listen-Dinge auch mit Tupeln anstellen -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True - -# Wir können Tupel (oder Listen) in Variablen entpacken -a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3 -# Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen -d, e, f = 4, 5, 6 -# Es ist kinderleicht zwei Werte zu tauschen -e, d = d, e # d ist nun 5 und e ist nun 4 - - -# Dictionarys (Wörterbucher) speichern Schlüssel-Werte-Paare -empty_dict = {} -# Hier ein gefülltes Wörterbuch -filled_dict = {"one": 1, "two": 2, "three": 3} - -# Wir können Einträge mit [] nachschlagen -filled_dict["one"] #=> 1 - -# So holen wir alle Keys (Schlüssel) als Liste -list(filled_dict.keys()) #=> ["three", "two", "one"] -# Hinweis - Die Reihenfolge von Schlüsseln in der Liste ist nicht garantiert. -# Einzelne Resultate können anders angeordnet sein. - -# Alle Values (Werte) als Liste -list(filled_dict.values()) #=> [3, 2, 1] -# Hinweis - Hier gelten dieselben Einschränkungen für die Reihenfolge wie bei Schlüsseln. - -# Das Vorhandensein eines Schlüssels im Wörterbuch mit "in" prüfen -"one" in filled_dict #=> True -1 in filled_dict #=> False - -# Einen nicht vorhandenenen Schlüssel zu suchen, löst einen KeyError aus -filled_dict["four"] # KeyError - -# Mit der get-Methode verhindern wir das -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None -# Die get-Methode unterstützt auch ein Standardargument, falls der Wert fehlt -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 - -# Die setdefault-Methode ist ein sicherer Weg, ein neues Schlüssel-Wert-Paar anzulegen -filled_dict.setdefault("five", 5) #filled_dict["five"] wird auf 5 gesetzt -filled_dict.setdefault("five", 6) #filled_dict["five"] ist noch immer 5 - -# Einträge zu einem Wörterbuch hinzufügen -filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} -#filled_dict["four"] = 4 # noch ein Weg, Werte hinzuzufügen - -# Schlüssel von einem Wörterbuch entfernen -del filled_dict["one"] # Entfert den Schlüssel "one" - - -# Sets speichern Mengen -empty_set = set() -# Initialisieren wir ein Set mit ein paar Werten -some_set = {1, 1, 2, 2, 3, 4} # some_set ist jetzt {1, 2, 3, 4} - -# Neue Variablen können einer Menge gleichgesetzt werden -filled_set = some_set - -# Mehr Elemente hinzufügen -filled_set.add(5) # filled_set ist jetzt {1, 2, 3, 4, 5} - -# Schnittmengen werden mit & gebildet -other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} - -# Mengen werden mit | vereinigt -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} - -# Die Differenz einer Menge mit - bilden -{1,2,3,4} - {2,3,5} #=> {1, 4} - -# Auf Vorhandensein von Elementen mit in prüfen -2 in filled_set #=> True -10 in filled_set #=> False - - -#################################################### -## 3. Kontrollstruktur und Iteratoren -#################################################### - -# Erstellen wir mal eine Variable -some_var = 5 - -# Hier eine if-Anweisung. Die Einrückung ist in Python wichtig! -# gibt "some_var ist kleiner als 10" aus -if some_var > 10: - print("some_var ist viel größer als 10.") -elif some_var < 10: # Dieser elif-Absatz ist optional. - print("some_var ist kleiner als 10.") -else: # Das hier ist auch optional. - print("some_var ist tatsächlich 10.") - - -""" -For-Schleifen iterieren über Listen -Ausgabe: - hund ist ein Säugetier - katze ist ein Säugetier - maus ist ein Säugetier -""" -for animal in ["hund", "katze", "maus"]: - # Wir können Strings mit format() formatieren - print("{} ist ein Säugetier".format(animal)) - -""" -`range(Zahl)` gibt eine null-basierte Liste bis zur angegebenen Zahl wieder -Ausgabe: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -"range(unten, oben)" gibt eine Liste von der unteren Zahl bis zur oberen Zahl aus -Ausgabe: - 4 - 5 - 6 - 7 -""" -for i in range(4, 8): - print(i) - -""" -While-Schleifen laufen, bis eine Bedingung erfüllt ist. -Ausgabe: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Kurzform für x = x + 1 - -# Ausnahmebehandlung mit einem try/except-Block -try: - # Mit raise wird ein Fehler ausgegeben - raise IndexError("Das hier ist ein Index-Fehler") -except IndexError as e: - pass # Pass ist nur eine no-op. Normalerweise würden wir hier den Fehler klären. -except (TypeError, NameError): - pass # Mehrere Fehler können zusammen geklärt werden, falls erforderlich. -else: # Optional, hinter allen except-Blöcken - print("Keine Probleme!") # Wird nur ausgeführt, wenn keine Ausnahmen aufgetreten sind -finally: # Wird immer ausgeführt - print("Hier können wir Ressourcen aufräumen") - -# alternativ zu einem try/finally Block um Aufzuräumen: -with open("meineDatei.txt") as f: - for line in f: - print(line) - -# Python bietet ein fundamentales Konzept der Iteration. -# Das Objekt, auf das die Iteration, also die Wiederholung einer Methode angewandt wird heißt auf Englisch "iterable". -# Die range Methode gibt ein solches Objekt aus. - -filled_dict = {"one": 1, "two": 2, "three": 3} -our_iterable = filled_dict.keys() -print(our_iterable) #=> range(1,10). Dies ist ein "iterable" Objekt. - -# Über dieses können wir auch iterieren -for i in our_iterable: - print(i) # Gibt one, two, three aus - -# Allerdings können wir die einzelnen Elemente nicht mit ihrem index ausgeben -our_iterable[1] # TypeError - -# Ein iterable ist ein Objekt, das weiß wie es einen Iteratoren erschafft. -our_iterator = iter(our_iterable) - -# Unser Iterator ist ein Objekt, das sich merkt, welchen Status es gerade hat während wir durch es gehen. -# Das jeweils nächste Objekt bekommen wir mit "next()" -next(our_iterator) #=> "one" - -# Es hält den vorherigen Status -next(our_iterator) #=> "two" -next(our_iterator) #=> "three" - -# Nachdem alle Daten ausgegeben worden sind, kommt eine StopIterator Ausnahme zurück -next(our_iterator) # Gibt StopIteration aus - -# Alle Elemente können mit "list()" ausgegeben werden -list(filled_dict.keys()) #=> ["one", "two", "three"] - - - -#################################################### -## 4. Funktionen -#################################################### - -# Mit def neue Funktionen erstellen -def add(x, y): - print("x ist %s und y ist %s" % (x, y)) - return x + y # Werte werden mit return zurückgegeben - -# Funktionen mit Parametern aufrufen -add(5, 6) #=> Ausgabe ist "x ist 5 und y ist 6" und gibt 11 zurück - -# Ein anderer Weg des Funktionsaufrufs sind Schlüsselwort-Argumente -add(y=6, x=5) # Schlüsselwörter können in beliebiger Reihenfolge übergeben werden. - -# Wir können Funktionen mit beliebiger Anzahl von # Positionsargumenten definieren -def varargs(*args): - return args - -varargs(1, 2, 3) #=> (1,2,3) - - -# Wir können auch Funktionen mit beliebiger Anzahl -# Schlüsselwort-Argumenten definieren -def keyword_args(**kwargs): - return kwargs - -# Rufen wir es mal auf, um zu sehen, was passiert -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} - -# Wir können beides gleichzeitig machen, wenn wir wollen -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) Ausgabe: - (1, 2) - {"a": 3, "b": 4} -""" - -# Beim Aufruf von Funktionen können wir das Gegenteil von varargs/kwargs machen! -# Wir benutzen dann *, um Tupel auszuweiten, und ** für kwargs. -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # äquivalent zu foo(1, 2, 3, 4) -all_the_args(**kwargs) # äquivalent zu foo(a=3, b=4) -all_the_args(*args, **kwargs) # äquivalent zu foo(1, 2, 3, 4, a=3, b=4) - - -# Anwendungsbereich von Funktionen -x = 5 - -def setX(num): - # lokale Variable x ist nicht die globale Variable x - x = num # => 43 - print (x) # => 43 - -def setGlobalX(num): - global x - print (x) # => 5 - x = num # globale Variable x ist jetzt 6 - print (x) # => 6 - -setX(43) -setGlobalX(6) - - -# Python hat First-Class-Funktionen -def create_adder(x): - def adder(y): - return x + y - return adder - -add_10 = create_adder(10) -add_10(3) #=> 13 - -# Es gibt auch anonyme Funktionen -(lambda x: x > 2)(3) #=> True - -# Es gibt auch Funktionen höherer Ordnung als Built-Ins -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] - -# Wir können bei map- und filter-Funktionen auch List Comprehensions einsetzen -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] - -#################################################### -## 5. Klassen -#################################################### - -# Wir bilden die Unterklasse eines Objekts, um Klassen zu erhalten. -class Human(object): - - # Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt - species = "H. sapiens" - - # Ein simpler Konstruktor - def __init__(self, name): - # Wir weisen das Argument name dem name-Attribut der Instanz zu - self.name = name - - # Eine Instanzmethode. Alle Methoden erhalten self als erstes Argument. - def say(self, msg): - return "{name}: {message}".format(name=self.name, message=msg) - - # Eine Klassenmethode wird von allen Instanzen geteilt. - # Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen - @classmethod - def get_species(cls): - return cls.species - - # Eine statische Methode wird ohne Klasse oder Instanz aufgerufen - @staticmethod - def grunt(): - return "*grunt*" - - -# Eine Instanz einer Klasse erstellen -i = Human(name="Ian") -print(i.say("hi")) # gibt "Ian: hi" aus - -j = Human("Joel") -print(j.say("hello")) #gibt "Joel: hello" aus - -# Rufen wir mal unsere Klassenmethode auf -i.get_species() #=> "H. sapiens" - -# Ändern wir mal das gemeinsame Attribut -Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" - -# Aufruf der statischen Methode -Human.grunt() #=> "*grunt*" - - -#################################################### -## 6. Module -#################################################### - -# Wir können Module importieren -import math -print(math.sqrt(16)) #=> 4.0 - -# Wir können auch nur spezielle Funktionen eines Moduls importieren -from math import ceil, floor -print(ceil(3.7)) #=> 4.0 -print(floor(3.7)) #=> 3.0 - -# Wir können auch alle Funktionen eines Moduls importieren -# Warnung: Dies wird nicht empfohlen -from math import * - -# Wir können Modulnamen abkürzen -import math as m -math.sqrt(16) == m.sqrt(16) #=> True - -# Module sind in Python nur gewöhnliche Dateien. Wir -# können unsere eigenen schreiben und importieren. Der Name des -# Moduls ist der Dateiname. - -# Wir können auch die Funktionen und Attribute eines -# Moduls herausfinden. -import math -dir(math) - - -#################################################### -## 7. Fortgeschritten -#################################################### - -# Generatoren helfen um Code schnell und einfach zu schreiben -def double_numbers(iterable): - for i in iterable: - yield i + i - -# Ein Generator erschafft Werte spontan -# Statt alle Werte auf einmal, wird bei jeder Iteration einer erschaffen. -# iteration. Das heißt, Werte größer als 15 werden nicht behandelt. -# Die range-Methode ist auch ein Generator. Im Fall einer Liste von 1-900000000 -# würde das sehr viel Zeit in Anspruch nehmen. -# Wenn wir eine variable mit einem Namen erschaffen wollen, das -# normalerweise mit einem Python - Schlüsselwort kollidieren würde, -# benutzen wir einen Unterstrich nach dem Wort. -range_ = range(1, 900000000) -# Alle Nummern bis zu einem Ergebnis von >=30 werden verdoppelt -for i in double_numbers(range_): - print(i) - if i >= 30: - break - - -# Dekoratoren -# In diesem Beispiel die Methode beg umwickelt say -# Beim Aufruf von beg, say wird aufgerufen -# Falls say_please true ist, ändert sich die ausgegebene Nachricht -from functools import wraps - - -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Please! I am poor :(") - return msg - - return wrapper - - -@beg -def say(say_please=False): - msg = "Can you buy me a beer?" - return msg, say_please - - -print(say()) # Can you buy me a beer? -print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( - -``` - -## Lust auf mehr? - -### Kostenlos online (Englisch) - -* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) -* [Python Course](http://www.python-course.eu/index.php) -* [First Steps With Python](https://realpython.com/learn/python-first-steps/) - -### Totholz (Englisch) - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) diff --git a/de-de/pythonlegacy-de.html.markdown b/de-de/pythonlegacy-de.html.markdown new file mode 100644 index 00000000..d66a8551 --- /dev/null +++ b/de-de/pythonlegacy-de.html.markdown @@ -0,0 +1,766 @@ +--- +language: Python 2 (legacy) +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["kultprok", "http:/www.kulturproktologie.de"] +filename: learnpythonlegacy-de.py +lang: de-de +--- + +Anmerkungen des ursprünglichen Autors: +Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode. + +Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service] + +Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber auf Python 2.x anwendbar sein. Haltet Ausschau nach einem Rundgang durch Python 3, der bald erscheinen soll. + +```python +# Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz) +""" Mehrzeilige Strings werden mit + drei '-Zeichen geschrieben und werden + oft als Kommentare genutzt. +""" + +#################################################### +## 1. Primitive Datentypen und Operatoren +#################################################### + +# Die Zahlen +3 #=> 3 + +# Mathematik funktioniert so, wie man das erwartet +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# Division ist ein wenig kniffliger. Ganze Zahlen werden ohne Rest dividiert +# und das Ergebnis wird automatisch abgerundet. +5 / 2 #=> 2 + +# Um das zu ändern, müssen wir Gleitkommazahlen einführen und benutzen +2.0 # Das ist eine Gleitkommazahl +11.0 / 4.0 #=> 2.75 Ahhh...schon besser + +# Rangfolge wird mit Klammern erzwungen +(1 + 3) * 2 #=> 8 + +# Boolesche Ausdrücke sind primitive Datentypen +True +False + +# Mit not wird negiert +not True #=> False +not False #=> True + +# Gleichheit ist == +1 == 1 #=> True +2 == 1 #=> False + +# Ungleichheit ist != +1 != 1 #=> False +2 != 1 #=> True + +# Ein paar weitere Vergleiche +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# Vergleiche können verknüpft werden! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Strings werden mit " oder ' gebildet +"Das ist ein String." +'Das ist auch ein String.' + +# Strings können addiert werden! +"Hello " + "world!" #=> "Hello world!" + +# Ein String kann wie eine Liste von Zeichen verwendet werden +"Das ist ein String"[0] #=> 'D' + +# Mit % können Strings formatiert werden, etwa so: +"%s können %s werden" % ("Strings", "interpoliert") + +# Ein modernerer Weg, um Strings zu formatieren, ist die format-Methode. +# Diese Methode wird bevorzugt +"{0} können {1} werden".format("Strings", "formatiert") +# Wir können Schlüsselwörter verwenden, wenn wir nicht abzählen wollen. +"{name} will {food} essen".format(name="Bob", food="Lasagne") + +# None ist ein Objekt +None #=> None + +# Verwendet nicht das Symbol für Gleichheit `==`, um Objekte mit None zu vergleichen +# Benutzt stattdessen `is` +"etc" is None #=> False +None is None #=> True + +# Der 'is'-Operator testet Objektidentität. Das ist nicht +# sehr nützlich, wenn wir mit primitiven Datentypen arbeiten, aber +# sehr nützlich bei Objekten. + +# None, 0, und leere Strings/Listen werden alle als False bewertet. +# Alle anderen Werte sind True +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. Variablen und Collections +#################################################### + +# Textausgabe ist sehr einfach +print "Ich bin Python. Schön, dich kennenzulernen!" + + +# Es gibt keinen Grund, Variablen vor der Zuweisung zu deklarieren. +some_var = 5 # kleinschreibung_mit_unterstrichen entspricht der Norm +some_var #=> 5 + +# Das Ansprechen einer noch nicht deklarierte Variable löst eine Exception aus. +# Unter "Kontrollstruktur" kann noch mehr über +# Ausnahmebehandlung erfahren werden. +some_other_var # Löst einen NameError aus + +# if kann als Ausdruck verwendet werden +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Listen speichern Sequenzen +li = [] +# Wir können mit einer bereits gefüllten Liste anfangen +other_li = [4, 5, 6] + +# append fügt Daten am Ende der Liste ein +li.append(1) #li ist jetzt [1] +li.append(2) #li ist jetzt [1, 2] +li.append(4) #li ist jetzt [1, 2, 4] +li.append(3) #li ist jetzt [1, 2, 4, 3] +# Vom Ende der Liste mit pop entfernen +li.pop() #=> 3 und li ist jetzt [1, 2, 4] +# und dann wieder hinzufügen +li.append(3) # li ist jetzt wieder [1, 2, 4, 3]. + +# Greife auf Listen wie auf Arrays zu +li[0] #=> 1 +# Das letzte Element ansehen +li[-1] #=> 3 + +# Bei Zugriffen außerhalb der Liste kommt es jedoch zu einem IndexError +li[4] # Raises an IndexError + +# Wir können uns Ranges mit Slice-Syntax ansehen +li[1:3] #=> [2, 4] +# Den Anfang auslassen +li[2:] #=> [4, 3] +# Das Ende auslassen +li[:3] #=> [1, 2, 4] + +# Ein bestimmtes Element mit del aus der Liste entfernen +del li[2] # li ist jetzt [1, 2, 3] + +# Listen können addiert werden +li + other_li #=> [1, 2, 3, 4, 5, 6] - Hinweis: li und other_li werden in Ruhe gelassen + +# Listen mit extend verknüpfen +li.extend(other_li) # Jetzt ist li [1, 2, 3, 4, 5, 6] + +# Mit in auf Existenz eines Elements prüfen +1 in li #=> True + +# Die Länge der Liste mit len ermitteln +len(li) #=> 6 + + +# Tupel sind wie Listen, nur unveränderlich. +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # Löst einen TypeError aus + +# Wir können all diese Listen-Dinge auch mit Tupeln anstellen +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# Wir können Tupel (oder Listen) in Variablen entpacken +a, b, c = (1, 2, 3) # a ist jetzt 1, b ist jetzt 2 und c ist jetzt 3 +# Tupel werden standardmäßig erstellt, wenn wir uns die Klammern sparen +d, e, f = 4, 5, 6 +# Es ist kinderleicht zwei Werte zu tauschen +e, d = d, e # d is now 5 and e is now 4 + + +# Dictionarys (Wörterbucher) speichern Key-Value-Paare +empty_dict = {} +# Hier ein gefülltes Wörterbuch +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Wir können Einträge mit [] nachschlagen +filled_dict["one"] #=> 1 + +# So holen wir alle Keys (Schlüssel) als Liste +filled_dict.keys() #=> ["three", "two", "one"] +# Hinweis - Die Reihenfolge von Schlüsseln in der Liste ist nicht garantiert. +# Einzelne Resultate können anders angeordnet sein. + +# Alle Values (Werte) als Liste +filled_dict.values() #=> [3, 2, 1] +# Hinweis - Hier gelten dieselben Einschränkungen für die Reihenfolge wie bei Schlüsseln. + +# Das Vorhandensein eines Schlüssels im Wörterbuch mit in prüfen +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# Einen nicht vorhandenenen Schlüssel zu suchen, löst einen KeyError aus +filled_dict["four"] # KeyError + +# Mit der get-Methode verhindern wir das +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# Die get-Methode unterstützt auch ein Standardargument, falls der Wert fehlt +filled_dict.get("one", 4) #=> 1 +filled_dict.get("four", 4) #=> 4 + +# Die setdefault-Methode ist ein sicherer Weg, ein neues Schlüssel-Wert-Paar anzulegen +filled_dict.setdefault("five", 5) #filled_dict["five"] wird auf 5 gesetzt +filled_dict.setdefault("five", 6) #filled_dict["five"] ist noch immer 5 + + +# Sets speichern Mengen +empty_set = set() +# Initialisieren wir ein Set mit ein paar Werten +some_set = set([1,2,2,3,4]) # some_set ist jetzt set([1, 2, 3, 4]) + +# Seit Python 2.7 kann {} benutzt werden, um ein Set zu erstellen +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Mehr Elemente hinzufügen +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} + +# Schnittmengen werden mit & gebildet +other_set = {3, 4, 5, 6} +filled_set & other_set #=> {3, 4, 5} + +# Mengen werden mit | vereinigt +filled_set | other_set #=> {1, 2, 3, 4, 5, 6} + +# Die Differenz einer Menge mit - bilden +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# Auf Vorhandensein von Elementen mit in prüfen +2 in filled_set #=> True +10 in filled_set #=> False + + +#################################################### +## 3. Kontrollstruktur +#################################################### + +# Erstellen wir mal eine Variable +some_var = 5 + +# Hier eine if-Anweisung. Die Einrückung ist in Python wichtig! +# gibt "some_var ist kleiner als 10" aus +if some_var > 10: + print "some_var ist viel größer als 10." +elif some_var < 10: # Dieser elif-Absatz ist optional. + print "some_var ist kleiner als 10." +else: # Das hier ist auch optional. + print "some_var ist tatsächlich 10." + + +""" +For-Schleifen iterieren über Listen +Ausgabe: + hund ist ein Säugetier + katze ist ein Säugetier + maus ist ein Säugetier +""" +for animal in ["hund", "katze", "maus"]: + # Wir können Strings mit % formatieren + print "%s ist ein Säugetier" % animal + +""" +`range(Zahl)` gibt eine null-basierte Liste bis zur angegebenen Zahl wieder +Ausgabe: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +While-Schleifen laufen, bis eine Bedingung erfüllt ist. +Ausgabe: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Kurzform für x = x + 1 + +# Ausnahmebehandlung mit einem try/except-Block + +# Funktioniert in Python 2.6 und höher: +try: + # Mit raise wird ein Fehler ausgegeben + raise IndexError("Das hier ist ein Index-Fehler") +except IndexError as e: + pass # Pass ist nur eine no-op. Normalerweise würden wir hier den Fehler klären. + + +#################################################### +## 4. Funktionen +#################################################### + +# Mit def neue Funktionen erstellen +def add(x, y): + print "x ist %s und y ist %s" % (x, y) + return x + y # Werte werden mit return zurückgegeben + +# Funktionen mit Parametern aufrufen +add(5, 6) #=> Ausgabe ist "x ist 5 und y ist 6" und gibt 11 zurück + +# Ein anderer Weg des Funktionsaufrufs sind Schlüsselwort-Argumente +add(y=6, x=5) # Schlüsselwörter können in beliebiger Reihenfolge übergeben werden. + +# Wir können Funktionen mit beliebiger Anzahl von # Positionsargumenten definieren +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# Wir können auch Funktionen mit beliebiger Anzahl +# Schlüsselwort-Argumenten definieren +def keyword_args(**kwargs): + return kwargs + +# Rufen wir es mal auf, um zu sehen, was passiert +keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} + +# Wir können beides gleichzeitig machem, wenn wir wollen +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) Ausgabe: + (1, 2) + {"a": 3, "b": 4} +""" + +# Beim Aufruf von Funktionen können wir das Gegenteil von varargs/kwargs machen! +# Wir benutzen dann *, um Tupel auszuweiten, und ** für kwargs. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # äquivalent zu foo(1, 2, 3, 4) +all_the_args(**kwargs) # äquivalent zu foo(a=3, b=4) +all_the_args(*args, **kwargs) # äquivalent zu foo(1, 2, 3, 4, a=3, b=4) + +# Python hat First-Class-Funktionen +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) #=> 13 + +# Es gibt auch anonyme Funktionen +(lambda x: x > 2)(3) #=> True + +# Es gibt auch Funktionen höherer Ordnung als Built-Ins +map(add_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# Wir können bei map- und filter-Funktionen auch List Comprehensions einsetzen +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + + +#################################################### +## 5. Module +#################################################### + +# Wir können Module importieren +import math +print math.sqrt(16) #=> 4.0 + +# Wir können auch nur spezielle Funktionen eines Moduls importieren +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Wir können auch alle Funktionen eines Moduls importieren +# Warnung: Dies wird nicht empfohlen +from math import * + +# Wir können Modulnamen abkürzen +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Module sind in Python nur gewöhnliche Dateien. Wir +# können unsere eigenen schreiben und importieren. Der Name des +# Moduls ist der Dateiname. + +# Wir können herausfinden, welche Funktionen und Attribute in einem +# Modul definiert sind. +import math +dir(math) + +# Wenn Sie ein Python-Skript namens math.py im selben Ordner +# wie Ihr aktuelles Skript haben, wird die Datei math.py +# anstelle des integrierten Python-Moduls geladen. +# Dies geschieht, weil der lokale Ordner Vorrang +# vor den in Python integrierten Bibliotheken hat. + + +#################################################### +## 6. Klassen +#################################################### + +# Wir verwenden das Schlüsselwort "class" um eine Klasse zu erzeugen. +class Human(object): + + # Ein Klassenattribut. Es wird von allen Instanzen einer Klasse geteilt + species = "H. sapiens" + + # Ein simpler Konstruktor, wird aufgerufen, wenn diese Klasse instanziiert wird. + # Beachten Sie, dass die doppelten vorangestellten und nachgestellten + # Unterstriche Objekte oder Attribute bezeichnen, die von Python verwendet werden, + # aber in benutzergesteuerten Namespaces leben. + # Methoden (oder Objekte oder Attribute) wie: __init__, __str__, __repr__ usw. + # werden als Sondermethoden (oder manchmal als Dundermethoden bezeichnet) bezeichnet. + # Sie sollten solche Namen nicht selbst erfinden. + def __init__(self, name): + # Wir weisen das Argument name dem name-Attribut der Instanz zu + self.name = name + + # Eine Instanzmethode. Alle Methoden erhalten "self" als erstes Argument. + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # Eine weitere Instanzmethode + def sing(self): + return 'yo... yo... microphone check... one two... one two...' + + # Eine Klassenmethode wird von allen Instanzen geteilt. + # Sie werden mit der aufrufenden Klasse als erstem Argument aufgerufen + @classmethod + def get_species(cls): + return cls.species + + # Eine statische Methode wird ohne Klasse oder Instanz aufgerufen + @staticmethod + def grunt(): + return "*grunt*" + + # Eine Eigenschaft (Property) ist wie ein Getter. + # Es verwandelt die Methode age() in ein schreibgeschütztes Attribut mit demselben Namen. + # Es ist jedoch nicht nötig, triviale Getter und Setter in Python zu schreiben. + @property + def age(self): + return self._age + + # Damit kann die Eigenschaft festgelegt werden + @age.setter + def age(self, age): + self._age = age + + # Damit kann die Eigenschaft gelöscht werden + @age.deleter + def age(self): + del self._age + +# Wenn ein Python-Interpreter eine Quelldatei liest, führt er den gesamten Code aus. +# Diese __name__-Prüfung stellt sicher, dass dieser Codeblock nur ausgeführt wird, +# wenn dieses Modul das Hauptprogramm ist. +if __name__ == '__main__': + # Eine Instanz einer Klasse erstellen + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i und j sind Instanzen des Typs Mensch, oder anders ausgedrückt: Sie sind Objekte des Menschen + + # Rufen wir unsere Klassenmethode auf + i.say(i.get_species()) # "Ian: H. sapiens" + + # Ändern wir das gemeinsame Attribut + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # Aufruf der statischen Methode + print(Human.grunt()) # => "*grunt*" + + # Kann keine statische Methode mit Instanz des Objekts aufrufen, + # da i.grunt () automatisch "self" (das Objekt i) als Argument verwendet + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given + + # Die Eigenschaft für diese Instanz aktualisieren + i.age = 42 + # die Eigenschaft auslesen + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # die Eigenschaft löschen + del i.age + # i.age # => würde einen AttributeError werfen + +#################################################### +## 6.1 Inheritance +#################################################### + +# Vererbung ermöglicht die Definition neuer untergeordneter Klassen, +# die Methoden und Variablen von ihrer übergeordneten Klasse erben. + +# Wenn Sie die oben definierte Human-Klasse als Basis- oder Elternklasse verwenden, +# können Sie eine untergeordnete Klasse, Superhero, definieren, die die Klassenvariablen +# wie "species", "name" und "age" sowie Methoden wie "sing" und "grunzen" aus der Klasse Human erbt. +# Die Untergeordnete Klasse kann aber auch eigene Eigenschaften haben. + +# Um von der Modularisierung per Datei zu profitieren, können Sie die Klassen +# in ihren eigenen Dateien platzieren, z. B. human.py + +# Um Funktionen aus anderen Dateien zu importieren, verwenden Sie das folgende Format +# from "Dateiname-ohne-Erweiterung" impotr "Funktion-oder-Klasse" + +from human import Human + +# Geben Sie die übergeordnete(n) Klasse(n) als Parameter für die Klassendefinition an +class Superhero(Human): + + # Wenn die untergeordnete Klasse alle Definitionen des übergeordneten Elements + # ohne Änderungen erben soll, können Sie einfach das Schlüsselwort "pass" + # (und nichts anderes) verwenden. In diesem Fall wird jedoch auskommentiert, + # um eine eindeutige untergeordnete Klasse zuzulassen: + # pass + + # Kindklassen können die Attribute ihrer Eltern überschreiben + species = 'Superhuman' + + # Kinder erben automatisch den Konstruktor ihrer übergeordneten Klasse + # einschließlich ihrer Argumente, können aber auch zusätzliche Argumente oder + # Definitionen definieren und ihre Methoden zB den Klassenkonstruktor überschreiben. + # Dieser Konstruktor erbt das Argument "name" von der Klasse "Human" und + # fügt die Argumente "superpowers" und "movie" hinzu: + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): + + # zusätzliche Klassenattribute hinzufügen: + self.fictional = True + self.movie = movie + # Beachten Sie die veränderlichen Standardwerte, da die Standardwerte gemeinsam genutzt werden + self.superpowers = superpowers + + # Mit der Funktion "super" können Sie auf die Methoden der übergeordneten Klasse + # zugreifen, die vom untergeordneten Objekt überschrieben werden, + # in diesem Fall die Methode __init__. + # Dies ruft den Konstruktor der übergeordneten Klasse auf: + super().__init__(name) + + # überschreiben der "sing" Methode + def sing(self): + return 'Dun, dun, DUN!' + + # eine zusätzliche Instanzmethode hinzufügen + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) + +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # Instanztypprüfungen + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + + # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, die sowohl von getattr() als auch von super() verwendet wird. + # Dieses Attribut ist dynamisch und kann aktualisiert werden. + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) + + # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut + print(sup.get_species()) # => Superhuman + + # Ruft die überschriebene Methode auf + print(sup.sing()) # => Dun, dun, DUN! + + # Ruft die Methode von Human auf + sup.say('Spoon') # => Tick: Spoon + + # Aufruf einer Methode, die nur in Superhero existiert + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # Vererbtes Klassenattribut + sup.age = 31 + print(sup.age) # => 31 + + # Attribut, das nur in Superhero existiert + print('Am I Oscar eligible? ' + str(sup.movie)) + +#################################################### +## 6.2 Multiple Inheritance +#################################################### + +# Eine weitere Klassendefinition +# bat.py + +class Bat: + + species = 'Baty' + + def __init__(self, can_fly=True): + self.fly = can_fly + + # This class also has a say method + def say(self, msg): + msg = '... ... ...' + return msg + + # And its own method as well + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + +# Und noch eine andere Klassendefinition, die von Superhero und Bat erbt +# superhero.py +from superhero import Superhero +from bat import Bat + +# Definieren Sie Batman als eine Kindklasse, das von Superheld und Bat erbt +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # In der Regel müssen Sie super aufrufen, um Attribute zu erben: + # super (Batman, selbst) .__ init__ (* args, ** kwargs) + # Allerdings handelt es sich hier um Mehrfachvererbung, und super() + # funktioniert nur mit der nächsten Basisklasse in der MRO-Liste. + # Stattdessen rufen wir explizit __init__ für alle Vorfahren auf. + # Die Verwendung von *args und **kwargs ermöglicht die saubere Übergabe von + # Argumenten, wobei jedes übergeordnete Element eine Schicht der Zwiebel "abschält". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # überschreibt den Wert für das Namensattribut + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + +if __name__ == '__main__': + sup = Batman() + + # Die Reihenfolge der Methodenauflösung (MRO = Method Resolution Order) anzeigen, + # die sowohl von getattr() als auch von super() verwendet wird. + # Dieses Attribut ist dynamisch und kann aktualisiert werden. + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # Ruft die übergeordnete Methode auf, verwendet jedoch das eigene Klassenattribut + print(sup.get_species()) # => Superhuman + + # Ruft die überschriebene Methode auf + print(sup.sing()) # => nan nan nan nan nan batman! + + # Ruft die Methode von Human auf, weil die Reihenfolge der Vererbung wichtig ist + sup.say('I agree') # => Sad Affleck: I agree + + # Aufrufmethode, die nur im 2. Vorfahren existiert + print(sup.sonar()) # => ))) ... ((( + + # Vererbtes Klassenattribut + sup.age = 100 + print(sup.age) # => 100 + + # Vererbtes Attribut vom 2. Vorfahren, dessen Standardwert überschrieben wurde. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + +#################################################### +## 7. Fortgeschrittenes +#################################################### + +# Generatoren helfen Ihnen, lazy Code zu erstellen. +def double_numbers(iterable): + for i in iterable: + yield i + i + +# Generatoren sind speichereffizient, da sie nur die Daten laden, +# die zur Verarbeitung des nächsten Werts in der iterierbaren Komponente +# erforderlich sind. Dadurch können sie ansonsten unzulässig große Wertebereiche ausführen. +# HINWEIS: `range` ersetzt` xrange` in Python 3. +for i in double_numbers(range(1, 900000000)): # `range` ist ein Generator. + print(i) + if i >= 30: + break + +# Genauso wie Sie ein 'list comprehension' (Listen Abstraktion) erstellen können, können Sie auch 'generator comprehension' (Generator Abstraktion) erstellen. +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # prints -1 -2 -3 -4 -5 to console/terminal + +# Sie können eine Generator Abstraktion auch direkt in eine Liste umwandeln (casten). +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + +# Decorators +# In diesem Beispiel umschliesst "beg" "say". Wenn say_please True ist, wird die zurückgegebene Nachricht geändert. +from functools import wraps + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( + +``` + +## Lust auf mehr? + +### Kostenlos online (Englisch) + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### Totholz (Englisch) + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/de-de/qt-de.html.markdown b/de-de/qt-de.html.markdown index 480030fe..7d287cab 100644 --- a/de-de/qt-de.html.markdown +++ b/de-de/qt-de.html.markdown @@ -1,7 +1,7 @@ --- category: tool tool: Qt Framework -language: c++ +language: C++ filename: learnqt-de.cpp contributors: - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"] diff --git a/de-de/rst-de.html.markdown b/de-de/rst-de.html.markdown index 072299f5..0eb2b6bf 100644 --- a/de-de/rst-de.html.markdown +++ b/de-de/rst-de.html.markdown @@ -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/ ``` diff --git a/de-de/ruby-de.html.markdown b/de-de/ruby-de.html.markdown index e14603cd..23571377 100644 --- a/de-de/ruby-de.html.markdown +++ b/de-de/ruby-de.html.markdown @@ -1,5 +1,6 @@ --- language: ruby +filename: ruby-de.rb contributors: - ["David Underwood", "http://theflyingdeveloper.com"] - ["Joel Walden", "http://joelwalden.net"] @@ -11,602 +12,677 @@ contributors: - ["Dzianis Dashkevich", "https://github.com/dskecse"] - ["Levi Bostian", "https://github.com/levibostian"] - ["Rahil Momin", "https://github.com/iamrahil"] + - ["Gabriel Halley", "https://github.com/ghalley"] + - ["Persa Zula", "http://persazula.com"] + - ["Jake Faris", "https://github.com/farisj"] + - ["Corey Ward", "https://github.com/coreyward"] + - ["Jannik Siebert", "https://github.com/janniks"] + - ["Keith Miyake", "https://github.com/kaymmm"] translators: - ["Christian Albrecht", "https://github.com/coastalchief"] - ["Dennis Keller", "https://github.com/denniskeller"] -filename: ruby-de.rb + - ["Paul Götze", "https://gitub.com/paulgoetze"] lang: de-de --- -# Dies ist ein Kommentar +```ruby +# Das ist ein Kommentar =begin -Dies sind multi-line -Kommentare. Niemand benutzt -die wirklich. +Das ist ein mehrzeiliger Kommentar. +Die Anfangszeile muss mit "=begin" beginnen +und die Endzeile muss mit "=end" beginnen. + +Alternativ kannst du jede Zeile in einem +mehrzeiligen Kommentar mit dem # Zeichen beginnen. =end -# Objekte - Alles ist ein Objekt +# In Ruby ist (fast) alles ein Objekt. +# Das schließt Zahlen ein... +3.class #=> Integer -## Zahlen sind Objekte -``` -3.class #=> Fixnum -3.to_s #=> "3" -``` +# ...und Zeichenketten (Strings)... +"Hallo".class #=> String -### Simple Arithmetik -``` +# ...und sogar Methoden! +"Hallo".method(:class).class #=> Method + +# Simple Arithmetik 1 + 1 #=> 2 8 - 1 #=> 7 10 * 2 #=> 20 35 / 5 #=> 7 -2**5 #=> 32 -``` +2 ** 5 #=> 32 +5 % 3 #=> 2 -// Arithmetik ist aber eigentlich nur syntaktischer Zucker -// um eine Methode eines Objekt aufzurufen -``` +# Bitweise Operatoren +3 & 5 #=> 1 +3 | 5 #=> 7 +3 ^ 5 #=> 6 + +# Arithmetik ist aber eigentlich nur syntaktischer Zucker +# um eine Methode eines Objekts aufzurufen 1.+(3) #=> 4 10.* 5 #=> 50 -``` +100.methods.include?(:/) #=> true -## Special values sind Objekte -``` -nil # Nothing to see here -true # truth -false # falsehood +## Spezielle Werte sind Objekte +nil # Equivalent zu null in anderen Sprachen +true # Wahrheitswert +false # Falschheitswert nil.class #=> NilClass true.class #=> TrueClass false.class #=> FalseClass -``` -## Objektvergleiche -### Gleicheit -``` +# Gleicheit 1 == 1 #=> true 2 == 1 #=> false -``` -### Ungleichheit -``` + +# Ungleichheit 1 != 1 #=> false 2 != 1 #=> true -``` -### Neben false selbst, nil ist ein anderer 'falsey' Wert -``` -!nil #=> true -!false #=> true -!0 #=> false -``` -### Weitere Vergleiche -``` + +# Neben false selbst, ist nil der einzige andere +# zu Falsch evaluierende Wert + +!!nil #=> false +!!false #=> false +!!0 #=> true +!!"" #=> true + +# Weitere Vergleiche 1 < 10 #=> true 1 > 10 #=> false 2 <= 2 #=> true 2 >= 2 #=> true -``` + +# Kombinierter Vergleichsoperator (gibt `1` zurück wenn das erste Argument +# größer ist, und `-1`, wenn das zweite Argument größer ist, sonst `0`) +1 <=> 10 #=> -1 (1 < 10) +10 <=> 1 #=> 1 (10 > 1) +1 <=> 1 #=> 0 (1 == 1) + ### Logische Operatoren -``` true && false #=> false true || false #=> true -!true #=> false -``` -Es gibt alternative Versionen der logischen Operatoren mit niedrigerer -Wertigkeit. Diese werden meistens bei Flow-Control eingesetzt, um -verschiedenen Ausdrücke zu verketten bis einer true oder false zurück -liefert. +# Es gibt alternative Versionen der logischen Operatoren mit niedrigerer +# Wertigkeit. Diese werden meistens zur Flusskontrolle eingesetzt, um +# verschiedenen Ausdrücke zu verketten bis einer true oder false zurück +# liefert. -#### and -##### `do_something_else` wird nur ausgewertet wenn `do_something` true ist. +# `do_something_else` wird nur ausgewertet wenn `do_something` true ist. do_something() and do_something_else() - -#### or -#####`log_error` wird nur ausgewertet wenn `do_something` false ist. +# `log_error` wird nur ausgewertet wenn `do_something` false ist. do_something() or log_error() -## Strings sind Objekte -``` -'I am a string'.class #=> String -"I am a string too".class #=> String +# String Interpolation +placeholder = 'Ruby' +"Ich kann in #{placeholder} Platzhalter mit doppelten Anführungszeichen füllen." +#=> "Ich kann in Ruby Platzhalter mit doppelten Anführungszeichen füllen." -platzhalter = 'Ruby' -"Ich kann in #{placeholder} Platzhalter mit doppelten Anführungsstrichen füllen." -``` -Einfache Anführungszeichen sollten bevorzugt werden. -Doppelte Anführungszeichen führen interne Berechnungen durch. +# Du kannst Strings mit `+` verbinden, nicht jedoch mit anderen Typen +'hallo ' + 'Welt' #=> "hallo Welt" +'Hallo ' + 3 #=> TypeError: no implicit conversion of Integer into String +'hallo ' + 3.to_s #=> "hallo 3" +"hallo #{3}" #=> "hallo 3" + +# ...oder Strings mit Operatoren kombinieren +'hallo ' * 3 #=> "hallo hallo hallo " + +# ...oder Strings an andere Strings anhängen +'hallo' << ' Welt' #=> "hallo Welt" + +# Du kannst Text mit einer neuen Zeile am Ende ausgeben +puts "Ich gebe Text aus!" +#=> Ich gebe Text aus! +#=> nil + +# ...oder Text ohne einen Zeilenumbruch ausgeben +print "Ich gebe Text aus!" +#=> "Ich gebe Text aus!" => nil -### Strings können verbunden werden, aber nicht mit Zahlen -``` -'hello ' + 'world' #=> "hello world" -'hello ' + 3 #=> TypeError: can't convert Fixnum into String -``` -#### Zahl muss in String konvertiert werden -``` -'hello ' + 3.to_s #=> "hello 3" -``` -### Text ausgeben -``` -puts "I'm printing!" -``` # Variablen -## Zuweisungen -### Diese Zuweisung gibt den zugeordneten Wert zurück -``` x = 25 #=> 25 x #=> 25 -``` -### Damit funktionieren auch mehrfache Zuweisungen -``` + +# Beachte, dass Zuweisungen den zugewiesenen Wert zurückgeben. +# D.h. du kannst mehrfache Zuweisungen machen. + x = y = 10 #=> 10 x #=> 10 y #=> 10 -``` -## Benennung -### Konvention ist snake_case -``` + +# Nutze snake_case für Variablennamen. snake_case = true -``` -### Benutze verständliche Variablennamen -``` -path_to_project_root = '/good/name/' -path = '/bad/name/' -``` -# Symbols (sind auch Objekte) -Symbols sind unveränderliche, wiederverwendbare Konstanten, welche intern -als integer repräsentiert werden. Sie werden häufig anstelle von Strings -verwendet, um sinnvoll Werte zu übermitteln. -Symbols werden mit dem Doppelpunkt gekennzeichnet. -``` +# Nutze verständliche Variablennamen. +path_to_project_root = '/guter/Name/' +m = '/schlechter/Name/' + + +# Symbole sind unveränderliche, wiederverwendbare Konstanten, welche intern +# als Integer repräsentiert werden. Sie werden häufig anstelle von Strings +# verwendet, um semantisch sinnvoll Werte zu übermitteln. +# Symbols werden mit dem Doppelpunkt gekennzeichnet. + :pending.class #=> Symbol + status = :pending + status == :pending #=> true + status == 'pending' #=> false + status == :approved #=> false -``` + +# Strings können in Symbole konvertiert werden und umgekehrt. +status.to_s #=> "pending" +"argon".to_sym #=> :argon + # Arrays -## Ein Array anlegen -``` +# Das ist ein Array. array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] -``` -## Array können verschiedene Typen beinhalten -``` +# Array können verschiedene Typen beinhalten [1, 'hello', false] #=> [1, "hello", false] -``` -## Wie bei arithmetischen Ausdrücken auch wird beim Zugriff auf -## [0] eigentlich die Methode [] des Array Objekts aufgerufen. -``` -array.[] 0 #=> 1 -array.[] 12 #=> nil -``` +## Arrays könnenindiziert werden. -## Arrays können von vorne indiziert werden -``` +# Von vorne... array[0] #=> 1 +array.first #=> 1 array[12] #=> nil -``` -## Arrays können von hinten indiziert werden -``` +# ...oder von hinten... array[-1] #=> 5 -``` +array.last #=> 5 -## Arrays können mit Start Index und Länge indiziert werden -``` +# ...oder mit einem Startindex und einer Länge... array[2, 3] #=> [3, 4, 5] -``` -## Arrays können mit einer Range indiziert werden -``` +# ...oder mit einem Range... array[1..3] #=> [2, 3, 4] -``` -## Einen Wert hinzufügen -``` +# Du kanns ein Array umkehren. +# Gib ein neues Array mit umgkehrten Werten zurück +[1,2,3].reverse #=> [3,2,1] + +# Kehre ein Array an Ort und Stelle um, um die Variable mit den +# umgekehrten Werten zu aktualisieren. +a = [1,2,3] +a.reverse! #=> a==[3,2,1] wegen des Aufrufs von reverse mit Ausrufezeichens ('!') + +# Wie bei der Arithmetik, ist Zugriff mit [index] nur +# syntaktischer Zucker für den Aufruf der `[]` Methode auf dem Objekt. +array.[] 0 #=> 1 +array.[] 12 #=> nil + +# Du kannst Werte zu einem Array hinzufügen... array << 6 #=> [1, 2, 3, 4, 5, 6] +# Oder so array.push(6) #=> [1, 2, 3, 4, 5, 6] -``` -## Testen, ob ein Element schon vorhanden ist -``` +# ...und testen ob ein Element schon vorhanden ist array.include?(1) #=> true -``` -# Hashes -Hashes sind das Hauptfeature um Key/Values zu speichern +# Hashes sind Rubys Hauptdatenstruktur for Schlüssel/Wert Paare. +# Hashes werden durch geschweifte Klammern gekennzeichnet. +hash = { 'Farbe' => 'grün', 'Nummer' => 5 } -## Ein Hash anlegen -``` -hash = { 'color' => 'green', 'number' => 5 } -hash.keys #=> ['color', 'number'] -``` +hash.keys #=> ['farbe', 'nummer'] -## Wert per key herausfinden -``` -hash['color'] #=> 'green' -hash['number'] #=> 5 -hash['nothing here'] #=> nil -// Fragen an einen Hash nach einem Schlüssel, der nicht existiert, ruft nil hervor: -``` +# Hashes can be quickly looked up by key. +hash['Farbe'] #=> "grün" +hash['Nummer'] #=> 5 -## Symbols können auch keys sein -``` -new_hash = { defcon: 3, action: true } -new_hash.keys #=> [:defcon, :action] -``` +# Abfragen eines nicht vorhandenen Schlüssels, gibt nil zurück. +hash['nicht vorhanden'] #=> nil -## Testen ob ein Key oder ein Value existiert -``` -new_hash.has_key?(:defcon) #=> true -new_hash.has_value?(3) #=> true -``` +# Wenn du Symbole als Schlüssel in einem Hash verwendest, kannst du +# eine alternative Syntax verwenden. +hash = { :defcon => 3, :action => true } +hash.keys #=> [:defcon, :action] -### Tipp: Arrays und Hashes sind Enumerable -### Und haben gemeinsame, hilfreiche Methoden wie: -### each, map, count, and more +hash = { defcon: 3, action: true } +hash.keys #=> [:defcon, :action] + +# Testen ob ein Schlüssel oder Wert im Hash existiert +hash.key?(:defcon) #=> true +hash.value?(3) #=> true + +# Tipp: Arrays und Hashes sind Enumerables! +# Sie haben viele nützliche Methoden gemein, wie each, map, count, und andere. # Kontrolstrukturen -## if -``` + +# Bedingungen if true - 'if statement' + 'wenn Bedingung' elsif false - 'else if, optional' + 'sonst wenn, optional' else - 'else, also optional' + 'sonst, auch optional' end -``` -## for - Allerdings werden for Schleifen nicht oft vewendet. -``` -for counter in 1..5 - puts "iteration #{counter}" -end -``` -## Stattdessen: "each" Methode und einen Bloch übergeben -Ein Block ist ein Codeteil, den man einer Methode übergeben kann -Ähnelt stark lambdas, anonymen Funktionen oder Closures in anderen -Programmiersprachen. -``` +# Wenn eine Kontrollstruktur keinen Code-Block, sondern einen einzigen +# Ausdruck ausführt, dann kannst du die nachgestellte if-Notation verwenden +warnings = ['Nachname fehlt', 'Adresse zu kurz'] +puts("Vorhandene Warnungen:\n" + warnings.join("\n")) if !warnings.empty? + +# Formuliere die Bedingung um, wenn sich `unless` besser liest als `if` +puts("Vorhandene Warnungen:\n" + warnings.join("\n")) unless warnings.empty? + +# Schleifen +# Traditionell ist das Benutzen von `for` Schleifen in Ruby eher unüblich. +# Stattdessen werden diese mit Hilfe von Enumerables implementiert, was mit +# dem Aufrufen von `each` einhergeht. (1..5).each do |counter| - puts "iteration #{counter}" + puts "Iteration #{counter}" +end + +# Was in etwa das selbe ist wie Folgendes (selten in Ruby zu sehen). +for counter in 1..5 + puts "Iteration #{counter}" end -``` -Die each Methode einer Range führt den Block für jedes Element der Range aus. +# Das `do |variable| ... end` Konstrukt wird `block` genannt. +# Blocks sind vergleichbar mit Lambdas, anonymen Funktionen +# oder Closures in anderen Programmiersprachen. +# Sie können als Objekte übergeben, aufgerufen oder als Methoden +# zugewiesen werden. -Dem Block wird ein "counter" parameter übergeben. +# Die `each` Methode eines Ranges führt den Block einmal für jedes +# Element des Ranges aus. +# Dem Block wird eine counter Variable als Parameter übergeben. -### Den Block kann man auch in geschweiften Klammern schreiben -``` -(1..5).each { |counter| puts "iteration #{counter}" } -``` +# Du kannst einen Block auch mit geschweiften Klammern schreiben. +(1..5).each { |counter| puts "Iteration #{counter}" } -### Each kann auch über den Inhalt von Datenstrukturen iterieren -``` +# Each kann auch über den Inhalt von Datenstrukturen iterieren. array.each do |element| - puts "#{element} is part of the array" + puts "#{element} is Teil des Arrays" end + hash.each do |key, value| - puts "#{key} is #{value}" + puts "#{key} ist #{value}" +end + +# Um auf den Laufindex zuzugreifen kannst du `each_with_index` verwenden +# und eine index Variable definieren. +array.each_with_index do |element, index| + puts "#{element} ist Nummer #{index} im Array" end counter = 1 while counter <= 5 do - puts "iteration #{counter}" + puts "Iteration #{counter}" counter += 1 end -``` +#=> Iteration 1 +#=> Iteration 2 +#=> Iteration 3 +#=> Iteration 4 +#=> Iteration 5 + +# Es gibt einige andere hilfreiche Schleifenfunktionen in Ruby. +# Wie etwa 'map', 'reduce', 'inject' und viele andere mehr. +# Map zum Beispiel iteriert über das Array, führt für jedes Element +# die Anweisungen aus, +# die im Block definiert sind und gibt ein völlig neues Array zurück. +array = [1,2,3,4,5] +doubled = array.map do |element| + element * 2 +end +puts doubled +#=> [2,4,6,8,10] +puts array +#=> [1,2,3,4,5] -## case -``` +# Case Konstruct grade = 'B' case grade when 'A' - puts 'Way to go kiddo' + puts 'So wird’s gemacht' when 'B' - puts 'Better luck next time' + puts 'Viel Glück beim nächsten Mal' when 'C' - puts 'You can do better' + puts 'Das kannst du besser' when 'D' - puts 'Scraping through' + puts 'Gerade so durch' when 'F' - puts 'You failed!' + puts 'Durchgefallen!' else - puts 'Alternative grading system, eh?' + puts 'Anderes Bewertungssystem, was?' end -=> "Better luck next time" -``` +#=> "Viel Glück beim nächsten Mal" -### Case können auch ranges -``` +# Case kann auch Ranges benutzen grade = 82 case grade when 90..100 - puts 'Hooray!' + puts 'Hurra!' when 80...90 - puts 'OK job' + puts 'OK gemacht' else - puts 'You failed!' + puts 'Durchgefallen!' end -=> "OK job" -``` +#=> "OK gemacht" -# Exception handling: -``` +# Fehlerbehandlung begin - # code here that might raise an exception - raise NoMemoryError, 'You ran out of memory.' + # Code der einen Fehler wirft... + raise NoMemoryError, 'Dein Speicher ist voll.' rescue NoMemoryError => exception_variable - puts 'NoMemoryError was raised', exception_variable + puts 'NoMemoryError ist aufgetreten', exception_variable rescue RuntimeError => other_exception_variable - puts 'RuntimeError was raised now' + puts 'RuntimeError ist aufgetreten' else - puts 'This runs if no exceptions were thrown at all' + puts 'Das wird ausgeführt, wenn keine Fehler geworfen wurden' ensure - puts 'This code always runs no matter what' + puts 'Dieser Code wird immer ausgeführt, egal was vorher passiert' end -``` -# Funktionen -``` + +# Methoden + def double(x) x * 2 end -``` -## Funktionen (und Blocks) -## geben implizit den Wert des letzten Statements zurück -``` + +# Methoden (und Blocks) geben implizit den Wert des letzten Anweisung zurück. double(2) #=> 4 -``` -### Klammern sind optional wenn das Ergebnis nicht mehrdeutig ist -``` +# Klammern sind optional wenn die Anweisung dadurch nicht mehrdeutig wird. double 3 #=> 6 + double double 3 #=> 12 + def sum(x, y) x + y end -``` -### Methoden Parameter werden per Komma getrennt -``` +# Die Argumente einer Methode werden durch ein Komma getrennt. sum 3, 4 #=> 7 + sum sum(3, 4), 5 #=> 12 -``` -## yield -### Alle Methoden haben einen impliziten, optionalen block Parameter -### Dieser wird mit dem Schlüsselword "yield" aufgerufen -``` +# yield +# Alle Methoden haben implizit einen optionalen block Parameter. +# Dieser kann durch das Schlüsselwort 'yield' ausgeführt werden. def surround puts '{' yield puts '}' end -surround { puts 'hello world' } -``` -## Einen Block kann man auch einer Methoden übergeben -### "&" kennzeichnet die Referenz zum übergebenen Block -``` +surround { puts 'hallo Welt' } + +#=> { +#=> hallo Welt +#=> } + +# Blocks können in ein 'Proc' Objekt umgewandelt werden. +# Dieses ist eine Art Container um den Block und erlaubt ihn an eine +# andere Methode zu übergeben, ihn in einen anderen Gültigkeitsbereicht +# einzubinden oder ihn andersweitig zu verändern. +# Am häufigsten findet man dies bei Parameterlisten von Methoden, in Form +# eines letzten '&block' Parameters, der den Block – wenn es einen gibt – +# entgegen nimmt und ihn in ein 'Proc' umwandelt. Die Benennung '&block' ist +# hier nur eine Konvention; es würde genauso mit '&pineapple' funktionieren. def guests(&block) - block.call 'some_argument' + block.class #=> Proc + block.call(4) end -``` -### Eine Liste von Parametern kann man auch übergeben, -### Diese wird in ein Array konvertiert -### "*" kennzeichnet dies. -``` +# Die 'call' Methode eines Proc ist ganz ähnlich zum Aufruf von 'yield', wenn +# ein Block vorhanden ist. Die Argumente, die 'call' übergeben werden, werden +# als Argumente and den Block weitergereicht. + +guests { |n| "Du hast #{n} Gäste." } +# => "Du hast 4 Gäste." + +# Du kannst eine Liste von Argumenten übergeben, die dann in ein Array +# umgewandelt werden. Dafür gibt es den splat-Operator (`*`). def guests(*array) array.each { |guest| puts guest } end -``` + +# Destrukturierung + +# Ruby destrukturiert Arrays automatisch beim Zuweisen mehrerer Variablen. +a, b, c = [1, 2, 3] +a #=> 1 +b #=> 2 +c #=> 3 + +# In manchen Fällen will man den splat-Operator (`*`) verwenden um ein Array in +# eine Liste zu destrukturieren. +ranked_competitors = ["John", "Sally", "Dingus", "Moe", "Marcy"] + +def best(first, second, third) + puts "Gewinner sind #{first}, #{second} und #{third}." +end + +best *ranked_competitors.first(3) #=> Gewinner sind John, Sally and Dingus. + +# Der splat-Operator kann auch in Parametern verwendet werden. +def best(first, second, third, *others) + puts "Gewinner sind #{first}, #{second} und #{third}." + puts "Es gab #{others.count} andere Teilnehmer." +end + +best *ranked_competitors +#=> Gewinner sind John, Sally und Dingus. +#=> Es gab 2 andere Teilnehmer. + +# Per Konvention enden alle Methoden, die einen Wahrheitswert zurück geben, mit einem +# Fragezeichen. +5.even? #=> false +5.odd? #=> true + +# Wenn ein Methodenname mit einem Ausrufezeichen endet, dann tut diese Methode +# per Konvention etwas Destruktives, wie z.B. das aufrufende Objekt zu +# verändern. +# Viele Mehtoden haben eine !-Version um eine direkte Änderung zu machen und +# eine Nicht-!-Version, die ein neues Objekt mit den Veränderungen zurück gibt. +company_name = "Dunder Mifflin" +company_name.upcase #=> "DUNDER MIFFLIN" +company_name #=> "Dunder Mifflin" +# Diesmal verändern wir company_name direkt. +company_name.upcase! #=> "DUNDER MIFFLIN" +company_name #=> "DUNDER MIFFLIN" + # Klassen -## Werden mit dem class Schlüsselwort definiert -``` + +# Du kannst eine Klasse mit dem Schlüsselwort 'class' definieren. class Human -``` -### Konstruktor bzw. Initializer -``` + # Eine Klassenvariable. Sie wird von allen Instanzen einer Klasse geteilt. + @@species = 'H. sapiens' + + # Konstruktor bzw. Initializer def initialize(name, age = 0) - # Assign the argument to the "name" instance variable for the instance + # Weise das Argument der Instanzvariable 'name' zu. @name = name - # If no age given, we will fall back to the default in the arguments list. + # Wenn kein 'age' angegeben wurde wird der Standartwert aus der Argumentenlist verwendet. @age = age end -``` -### setter Methode -``` + # Setter Methode def name=(name) @name = name end -``` -### getter Methode -``` + + # Getter Methode def name @name end -``` -#### getter können mit der attr_accessor Methode vereinfacht definiert werden -``` + # Getter & Setter können auch kürzer mit der attr_accessor Methode erstellt werden. attr_accessor :name - # Getter/setter methods can also be created individually like this + + # Getter & Setter Methoden können auch einzeln erstellt werden. attr_reader :name attr_writer :name - # A class method uses self to distinguish from instance methods. - # It can only be called on the class, not an instance. + + # Eine Klassenmethode unterscheidet sich durch ein 'self' von einer + # Instanzmethode. + # Sie kann nur auf der Klasse und nicht auf einer Instanz der Klasse + # aufgerufen werden. def self.say(msg) puts msg end + def species @@species end end -``` -## Eine Klasse instanziieren -``` +# Instanziieren einer Klasse jim = Human.new('Jim Halpert') dwight = Human.new('Dwight K. Schrute') -``` -## Methodenaufrufe -``` +# Du kannst die Methoden des erstellten Objekts 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" -``` -## Eine Klassenmethode aufrufen -``` +# Aufrufen einer Klassenmethode Human.say('Hi') #=> "Hi" -``` -## Variable Gültigkeit -### Variablen die mit "$" starten, gelten global -``` -$var = "I'm a global var" +# Der Gültigkeitsbereich einer Variablen wird durch ihren Namen definiert. +# Variablen, die mit $ beginnen sind global gültig. +$var = "Ich bin eine globale Variable" defined? $var #=> "global-variable" -``` -### Variablen die mit "@" starten, gelten für die Instanz -``` -@var = "I'm an instance var" +# Variablen, die mit @ beginnen, sind innerhalb einer Instanz gültig. +@var = "Ich bin eine Instanzvariable" defined? @var #=> "instance-variable" -``` -### Variablen die mit "@@" starten, gelten für die Klasse -``` -@@var = "I'm a class var" +# Variablen, die mit @@ beginnen, sind für die Klasse gültig. +@@var = "Ich bin eine Klassenvariable" defined? @@var #=> "class variable" -``` -### Variablen die mit einem Großbuchstaben anfangen, sind Konstanten -``` -Var = "I'm a constant" +# Variablen, die mit einem Großbuchstaben beginnen, sind Konstanten +Var = "Ich bin eine Konstante" defined? Var #=> "constant" -``` -## Class ist auch ein Objekt -### Hat also auch Instanzvariablen -### Eine Klassenvariable wird innerhalb der Klasse und Ableitungen geteilt. +# Class ist in Ruby auch ein Objekt. Deshalb kann eine Klasse Instanzvariablen +# haben. Eine Klassenvariable wird zwischen der Klasse und all ihren +# Ableitungen geteilt. -### Basis Klasse -``` +# Basis Klasse class Human @@foo = 0 + def self.foo @@foo end + def self.foo=(value) @@foo = value end end -``` -### Abgeleitete Klasse -``` +# Abgeleitete Klasse class Worker < Human end -Human.foo # 0 -Worker.foo # 0 -Human.foo = 2 # 2 -Worker.foo # 2 -``` -### Eine Klasseninstanzvariable wird nicht geteilt -``` +Human.foo #=> 0 +Worker.foo #=> 0 + +Human.foo = 2 +Worker.foo #=> 2 + +# Ableitungen einer Klasse haben keinen Zugriff auf eine Eine Klassen-Instanzvariable. class Human @bar = 0 + def self.bar @bar end + def self.bar=(value) @bar = value end end -``` -``` + class Doctor < Human end -``` -``` -Human.bar # 0 -Doctor.bar # nil -``` -``` + +Human.bar #=> 0 +Doctor.bar #=> nil + module ModuleExample def foo 'foo' end end -``` -### Module einbinden, heisst ihre Methoden an die Instanzen der Klasse zu binden -### Module erweitern, heisst ihre Mothden an die Klasse selbst zu binden -``` + +# Ein Einbinden (include) eines Moduls bindet seine Methoden an die Instanzen +# der Klasse. +# Ein Erweitern (extend) eines Moduls bindet seine Methoden an die Klasse +# selbst. class Person include ModuleExample end -``` -``` + class Book extend ModuleExample end -``` -``` -Person.foo # => NoMethodError: undefined method `foo' for Person:Class -Person.new.foo # => 'foo' -Book.foo # => 'foo' -Book.new.foo # => NoMethodError: undefined method `foo' -``` -### Callbacks werden ausgeführt, wenn ein Modul eingebunden oder erweitert wird -``` - module ConcernExample - def self.included(base) - base.extend(ClassMethods) - base.send(:include, InstanceMethods) - end - module ClassMethods - def bar - 'bar' - end - end - module InstanceMethods - def qux - 'qux' - end + +Person.foo #=> NoMethodError: undefined method `foo' for Person:Class +Person.new.foo #=> "foo" +Book.foo #=> "foo" +Book.new.foo #=> NoMethodError: undefined method `foo' + + +# Callbacks werden ausgeführt, wenn ein Modul eingebunden oder erweitert wird. +module ConcernExample + def self.included(base) + base.extend(ClassMethods) + base.send(:include, InstanceMethods) + end + + module ClassMethods + def bar + 'bar' end end - class Something - include ConcernExample + + module InstanceMethods + def qux + 'qux' + end end -``` -``` -Something.bar # => 'bar' -Something.qux # => NoMethodError: undefined method `qux' -Something.new.bar # => NoMethodError: undefined method `bar' -Something.new.qux # => 'qux' +end + +class Something + include ConcernExample +end + +Something.bar #=> "bar" +Something.qux #=> NoMethodError: undefined method `qux' +Something.new.bar #=> NoMethodError: undefined method `bar' +Something.new.qux #=> "qux" ``` -## Weiterführende Hinweise +## Weitere Links -//EN +_(z.T. auf Englisch)_ -- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - A variant of this reference with in-browser challenges. -- [Official Documentation](http://www.ruby-doc.org/core-2.1.1/) +- [Offizielle Ruby Website](https://www.ruby-lang.org/de/) +- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - Eine Variante dieses Dokuments mit in-Browser Challenges. +- [RubyMonk](https://rubymonk.com/) - Lerne Ruby mit einer Reihe interaktiver Tutorials. +- [Offizielle Dokumentation](http://ruby-doc.org/core) - [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/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. -- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide. +- [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](https://try.ruby-lang.org/) - Lerne die Grundlagen der Ruby Programmiersprache, interaktiv im Browser. diff --git a/de-de/rust-de.html.markdown b/de-de/rust-de.html.markdown index faa4ec2b..6208db68 100644 --- a/de-de/rust-de.html.markdown +++ b/de-de/rust-de.html.markdown @@ -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); } diff --git a/de-de/swift-de.html.markdown b/de-de/swift-de.html.markdown index 08f72a35..5828b5d3 100644 --- a/de-de/swift-de.html.markdown +++ b/de-de/swift-de.html.markdown @@ -11,7 +11,7 @@ filename: learnswift-de.swift lang: de-de --- -Swift ist eine Programmiersprache von Apple für die Entwicklung von iOS und OS X Applikationen. Swift wurde 2014 zu Apples WWDC Entwicklerkonferenz vorgestellt und wurde mit dem Ziel entwickelt, fehlerträchtigen Code zu vermeiden sowie mit Objective-C zu koexistieren. Es wird mit dem LLVM Compiler gebaut und ist ab Xcode 6+ verfügbar. +Swift ist eine Programmiersprache von Apple für die Entwicklung von iOS und macOS Applikationen. Swift wurde 2014 zu Apples WWDC Entwicklerkonferenz vorgestellt und wurde mit dem Ziel entwickelt, fehlerträchtigen Code zu vermeiden sowie mit Objective-C zu koexistieren. Es wird mit dem LLVM Compiler gebaut und ist ab Xcode 6+ verfügbar. Das offizielle [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) Buch von Apple ist kostenlos via iBooks verfügbar. diff --git a/de-de/vim-de.html.markdown b/de-de/vim-de.html.markdown new file mode 100644 index 00000000..d0b4eb9d --- /dev/null +++ b/de-de/vim-de.html.markdown @@ -0,0 +1,277 @@ +--- +category: tool +tool: vim +lang: de-de +contributors: +- ["RadhikaG", "https://github.com/RadhikaG"] +translators: +- ["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 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> # Ö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 + +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 + +# Navigieren innerhalb einer Zeile + +0 # Navigiere zum Anfang der Zeile +$ # Navigiere zum Ende der Zeile +^ # Navigiere zum ersten Zeichen, welches kein Leerzeichen ist + +# 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 + +:%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 + +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 < + +# Wortweise navigieren + +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 + +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 + +Vim hat eine eingebaute Dokumentation, welche mit `:help <topic>` aufgerufen +werden kann. +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. + +## Modi + +Vim basiert auf dem Konzept von **modes**. + +- 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 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. + +# 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 +``` + +## Die 'Grammatik' von Vim + +Vim kann als Satz von Kommandos angesehen werden, welche im Format +'Verb-Modifier-Noun' sind. Hierbei gilt: + +- Verb - die Aktion, du machen willst +- Modifier - wie die Aktion gemacht wird +- Noun - das Objekt, auf welchem die Aktion ausgeführt wird. + +Einige wichtige Beispiele von 'Verb', 'Modifier' und 'Nouns': + +``` +# 'Verb' + +d # löschen +c # ändern +y # kopieren +v # visuelles auswählen + +# '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 + +# 'Nouns' + +w # Wort +s # Satz +p # Abschnitt +b # Block + +# 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 +``` + +## 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 +``` + +## Makros + +Makros sind grundsätzlich einfach aufgezeichnete Aktionen +Wenn du mit dem Aufnehmen eines Makros beginnst, werden **alle** Aktionen und +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 +``` + +### Konfigurieren mit ~/.vimrc + +Die Datei .vimrc kann verwendet werden, um Vim beim Starten zu konfigurieren + +Hier ist eine Beispiel ~/.vimrc Datei: + +``` +" Beispiel ~/.vimrc + +" Erforderlich für vim, dass es iMproved ist. +set nocompatible + +" Bestimme den Dateityp anhand des Namens, um ein intelligentes Einrücken etc. +" zu ermöglichen +filetype indent plugin on + +" Aktiviere das Syntax-Highlighting +syntax on + +" Bessere Kommandozeilen-Vervollständigung +set wildmenu + +" Verwende die Suche ohne die Berücksichtigung der Groß-/Kleinschreibung, außer +" wenn mit Großbuchstaben gesucht wird. +set ignorecase +set smartcase + +" Wenn eine neue Zeile erstellt wird und kein Dateispezifisches Einrücken +" aktiviert ist, behält die neue Zeile die gleiche Einrückung wie die aktuelle +" Zeile +set autoindent + +" Zeige links die Zeilennummern an +set number + +" Einrückungsoptionen, ändere diese nach deinen Vorlieben + +" Anzahl sichtbarer Leerzeichen bei einem TAB +set tabstop=4 + +" Anzahl der Leerzeichen während des Bearbeitens bei einem TAB +set softtabstop=4 + +" Anzahl der Einrückungstiefe bei den Operationen (>> und <<) +set shiftwidth=4 + +" Konvertiere TABs zu Leerzeichen +set expandtab + +" Enable intelligent tabbing and spacing for indentation and alignment +" Aktiviere intelligente Tabs und Leerzeichen bei der Einrückung und Ausrichtung +set smarttab +``` + +### Verweise + +- [Vim | Homepage](http://www.vim.org/index.php) +- In der Shell eingeben: `vimtutor` +- [Ein vim Tutorial und Primer, englisch](https://danielmiessler.com/study/vim/) +- [Deutsches Arch Linux Wiki](https://wiki.archlinux.de/title/Vim) +- [Arch Linux Wiki, englisch (dafür ausführlicher)](https://wiki.archlinux.org/index.php/Vim) +- [What are the dark corners of Vim your mom never told you about? (Stack Overflow thread)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about) diff --git a/de-de/visualbasic-de.html.markdown b/de-de/visualbasic-de.html.markdown new file mode 100644 index 00000000..6194e906 --- /dev/null +++ b/de-de/visualbasic-de.html.markdown @@ -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). + diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown index ff45dc8d..00e4fd94 100644 --- a/de-de/yaml-de.html.markdown +++ b/de-de/yaml-de.html.markdown @@ -1,7 +1,7 @@ --- language: yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] translators: - ["Ruben M.", "https://github.com/switchhax"] filename: learnyaml-de.yaml @@ -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 diff --git a/directx9.html.markdown b/directx9.html.markdown index b51f418d..586865c8 100644 --- a/directx9.html.markdown +++ b/directx9.html.markdown @@ -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) diff --git a/docker.html.markdown b/docker.html.markdown new file mode 100644 index 00000000..ec6abe7e --- /dev/null +++ b/docker.html.markdown @@ -0,0 +1,281 @@ +--- +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` + +``` diff --git a/dynamic-programming.html.markdown b/dynamic-programming.html.markdown index c73b1845..ff053384 100644 --- a/dynamic-programming.html.markdown +++ b/dynamic-programming.html.markdown @@ -3,6 +3,7 @@ category: Algorithms & Data Structures name: Dynamic Programming contributors: - ["Akashdeep Goel", "http://github.com/akashdeepgoel"] + - ["Miltiadis Stouras", "https://github.com/mstou"] --- # Dynamic Programming @@ -22,7 +23,7 @@ Always remember! ## Example of Dynamic Programming -The Longest Increasing Subsequence problem is to find the longest increasing subsequence of a given sequence. Given a sequence `S= {a1 , a2 , a3, a4, ............., an-1, an }` we have to find a longest subset such that for all `j` and `i`, `j<i` in the subset `aj<ai`. +The Longest Increasing Subsequence problem is to find the longest increasing subsequence of a given sequence. Given a sequence `S={ a1, a2, a3, a4, ............., an-1, an }` we have to find a longest subset such that for all `j` and `i`, `j<i` in the subset `aj<ai`. First of all we have to find the value of the longest subsequences(LSi) at every index i with last element of sequence being ai. Then largest LSi would be the longest subsequence in the given sequence. To begin LSi is assigned to be one since ai is element of the sequence(Last element). Then for all `j` such that `j<i` and `aj<ai`, we find Largest LSj and add it to LSi. Then algorithm take *O(n2)* time. Pseudo-code for finding the length of the longest increasing subsequence: @@ -48,6 +49,13 @@ for i=0 to n-1 ## Online Resources -* [codechef](https://www.codechef.com/wiki/tutorial-dynamic-programming) +* MIT 6.006: [Lessons 19,20,21,22](https://www.youtube.com/playlist?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb) +* TopCoder: [Dynamic Programming from Novice to Advanced](https://www.topcoder.com/community/data-science/data-science-tutorials/dynamic-programming-from-novice-to-advanced/) +* [CodeChef](https://www.codechef.com/wiki/tutorial-dynamic-programming) * [InterviewBit](https://www.interviewbit.com/courses/programming/topics/dynamic-programming/) - +* GeeksForGeeks: + * [Overlapping Subproblems](https://www.geeksforgeeks.org/dynamic-programming-set-1/) + * [Tabulation vs Memoization](https://www.geeksforgeeks.org/tabulation-vs-memoizatation/) + * [Optimal Substructure Property](https://www.geeksforgeeks.org/dynamic-programming-set-2-optimal-substructure-property/) + * [How to solve a DP problem](https://www.geeksforgeeks.org/solve-dynamic-programming-problem/) +* [How to write DP solutions](https://www.quora.com/Are-there-any-good-resources-or-tutorials-for-dynamic-programming-DP-besides-the-TopCoder-tutorial/answer/Michal-Danilák) diff --git a/easylang.html.markdown b/easylang.html.markdown new file mode 100644 index 00000000..ba33dbf2 --- /dev/null +++ b/easylang.html.markdown @@ -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) + diff --git a/el-gr/bash-gr.html.markdown b/el-gr/bash-gr.html.markdown index 2989969d..239beaa4 100644 --- a/el-gr/bash-gr.html.markdown +++ b/el-gr/bash-gr.html.markdown @@ -8,7 +8,7 @@ lang: el-gr --- Η λέξη «bash» είναι ένα από τα ονόματα του unix shell (τερματικός), το οποίο -διανέμεται επίσης ως προεπιλεγμένος τερματικός για το λειτουργικό σύστημα GNU, τα Linux και τα Mac OS X. +διανέμεται επίσης ως προεπιλεγμένος τερματικός για το λειτουργικό σύστημα GNU, τα Linux και τα macOS. Σχεδόν όλα τα παραδείγματα που ακολουθούν μπορούν να αποτελέσουν μέρος ενός προγράμματος τερματικού (shell script) ή να εκτελεσθούν απευθείας από τον τερματικό. diff --git a/el-gr/ocaml-gr.html.markdown b/el-gr/ocaml-gr.html.markdown new file mode 100644 index 00000000..9a15b2d3 --- /dev/null +++ b/el-gr/ocaml-gr.html.markdown @@ -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/> diff --git a/el-gr/python-gr.html.markdown b/el-gr/python-gr.html.markdown new file mode 100644 index 00000000..203c6e78 --- /dev/null +++ b/el-gr/python-gr.html.markdown @@ -0,0 +1,1031 @@ +--- +language: Python +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] + - ["evuez", "http://github.com/evuez"] + - ["Rommel Martinez", "https://ebzzry.io"] + - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"] +filename: learnpython-gr.py +lang: el-gr +--- + +Η Python δημιουργήθηκε από τον Guido van Rossum στις αρχές των 90s. Πλέον είναι μία από τις πιο +δημοφιλείς γλώσσες. Ερωτευεται κανείς την python για τη συντακτική της απλότητα. +Βασικά είναι εκτελέσιμος ψευδοκώδικας. + +Το Feedback είναι πάντα δεκτό! Μπορείτε να με βρείτε στο [@haritonaras](http://twitter.com/haritonaras) +ή τον αρχικό συγγραφέα στο [@louiedinh](http://twitter.com/louiedinh) ή στο +louiedinh [at] [google's email service] + +Σημείωση: Το παρόν άρθρο ασχολείται μόνο με την Python 3. Δείτε [εδώ](http://learnxinyminutes.com/docs/pythonlegacy/) αν θέλετε να μάθετε την παλιά Python 2.7 + +```python + +# Τα σχόλια μίας γραμμής ξεκινούν με # + +""" Τα σχόλια πολλαπλών γραμμών μπορούν + να γραφούν με τρία ", και συχνά χρησιμοποιούνται + ως documentation. +""" + +#################################################### +## 1. Primitive (πρωταρχικοί) Τύποι Δεδομένων και Τελεστές +#################################################### + +# Αφού έχει αριθμούς +3 # => 3 + +# Λογικά θα έχει και Μαθηματικά... +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 + +# Η διαίρεση ακεραίων κάνει στρογγυλοποίηση προς τα κάτω για θετικούς και αρνητικούς αριθμούς +5 // 3 # => 1 +-5 // 3 # => -2 +5.0 // 3.0 # => 1.0 # works on floats too +-5.0 // 3.0 # => -2.0 + +# Το αποτέλεσμα της διαίρεσης είναι πάντα float +10.0 / 3 # => 3.3333333333333335 + +# Modulo τελεστής +7 % 3 # => 1 + +# Ύψωση σε δύναμη (x**y, x στην y-οστή δύναμη) +2**3 # => 8 + +# Ελέγχουμε την προτεραιότητα πράξεων με παρενθέσεις +(1 + 3) * 2 # => 8 + +# Οι Boolean τιμές είναι primitives (Σημ.: τα κεφαλαία) +True +False + +# άρνηση με το not +not True # => False +not False # => True + +# Boolean τελεστές +# Σημ. ότι τα "and" και "or" είναι case-sensitive +True and False # => False +False or True # => True + +# Τα True και False είναι 1 και 0 αλλά με διαφορετικά keywords +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 + +# Μπορούμε να δούμε τις αριθμητικές τιμές των True και False μέσω των τελεστών σύγκρισης +0 == False # => True +1 == True # => True +2 == True # => False +-5 != False # => True + +# Χρησιμοποιώντας τελεστές boolean σε ακεραίους, οι ακέραιοι γίνονται cast σε +# boolean ώστε να γίνει η αποτίμηση της έκφρασης. +# Το αποτέλεσμα όμως είναι non-cast, δηλαδή ίδιου τύπου με τα αρχικά ορίσματα +# Μην μπερδεύετε τις bool(ints) και bitwise and/or (&,|) +bool(0) # => False +bool(4) # => True +bool(-6) # => True +0 and 2 # => 0 +-5 or 0 # => -5 + +# Ισότητα == +1 == 1 # => True +2 == 1 # => False + +# Διάφορο != +1 != 1 # => False +2 != 1 # => True + +# Περισσότερες συγκρίσεις +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# Κοιτάζουμε αν μία τιμή ανήκει σε ένα εύρος +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False +# Το Chaining (αλυσίδωση? :P) κάνει το παραπάνω πιο όμορφα +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# (is vs. ==) το is ελέγχει αν δύο μεταβλητές αναφέρονται στο ίδιο αντικείμενο, +# αλλά το == ελέγχει αν τα αντικείμενα στα οποία αναφέρονται οι μεταβλητές έχουν τις ίδιες τιμές +a = [1, 2, 3, 4] # το a δείχνει σε μία νέα λίστα, [1,2,3,4] +b = a # το b δείχνει στο αντικείμενο που δείχνει το a +b is a # => True, a και b αναφέρονται στο ίδιο αντικείμενο +b == a # => True, τα αντικείμενα των a κι b είναι ίσα +b = [1, 2, 3, 4] # Το b δείχνει σε μία νέα λίστα, [1, 2, 3, 4] +b is a # => False, a και b δεν αναφέρονται στο ίδιο αντικείμενο +b == a # => True, τα αντικείμενα των a και b είναι ίσα + +# Τα Strings (συμβολοσειρές) δημιουργούνται με " ή ' +"This is a string." +'This is also a string.' + +# Μπορούμε και να προσθέτουμε Strings, αλλά προσπαθήστε να μην το κάνετε +"Hello " + "world!" # => "Hello world!" +# Τα String literals (αλλά όχι οι μεταβλητές) μπορούν να συντμιθούν και χωρίς το '+' +"Hello " "world!" # => "Hello world!" + +# Μπορούμε να φερθούμε σε string σαν να είναι λίστα από χαρακτήρες +"This is a string"[0] # => 'T' + +# Μπορούμε να βρούμε το μήκος ενός string +len("This is a string") # => 16 + +# Το .format μπορεί να χρησιμοποιηθεί για να μορφοποιήσουμε strings, όπως εδώ: +"{} can be {}".format("Strings", "interpolated") # => "Strings can be interpolated" + +# Μπορείς να επαναλάβεις τα ορίσματα του formatting για να γλιτώσεις λίγο χρονο +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" + +# Μπορείς να χρησιμοποιήσεις keywords αν βαριέσαι το μέτρημα. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") # => "Bob wants to eat lasagna" + +# Αν ο κώδικας Python 3 που γράφεις πρόκειται να τρέξει και με python 2.5 ή παλιότερη +# μπορείς επίσης να χρησιμοποιήσεις το παλιό τρόπο για formatting: +"%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way" + +# Μπορείς επίσης να μορφοποιήσεις χρησιμοποιώντας τα f-strings / formatted string literals (σε Python 3.6+) +name = "Reiko" +f"She said her name is {name}." # => "She said her name is Reiko" +# Μπορείς βασικά να βάλεις οποιαδήποτε έκφραση Python στα άγκιστρα και θα εμφανιστεί στο string. +f"{name} is {len(name)} characters long." + + +# το None είναι ένα αντικείμενο (object) +None # => None + +# Μη χρησιμοποιείτε το σύμβολο ισότητας "==" για να συγκρίνετε αντικείμενα με το None +# Χρησιμοποιείτε το "is". Αυτό ελέγχει για ισότητα της ταυτότητας του αντικειμένου. +"etc" is None # => False +None is None # => True + +# Τα None, 0, και τα κενά strings/lists/dicts/tuples αποτιμούνται στην τιμή False +# All other values are True +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False + +#################################################### +## 2. Μεταβλητές (variables) και Συλλογές (collections) +#################################################### + +# Η Python έχει μία συνάρτηση print() +print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! + +# By default, η συνάρτηση print() τυπώνει και ένα χαρακτήρα αλλαγής γραμμμής στο τέλος +# Χρησιμοποιείτε το προαιρετικό όρισμο end για να τυπώνει οτιδήποτε άλλο +print("Hello, World", end="!") # => Hello, World! + +# Απλός τρόπος για να πάρουμε δεδομένα εισόδου από το console +input_string_var = input("Enter some data: ") # επιστρέφει τα δεδομένα ως string +# Σημ.: Στις προηγούμενες εκδόσεις της Python, η μέθοδος input() ονομαζόταν raw_input() + +# Δεν υπάρχουν δηλώσεις, μόνο αναθέσεις τιμών. +# Η σύμβαση είναι να χρησιμοποιούμε μικρά γράμματα με κάτω παύλες +some_var = 5 +some_var # => 5 + +# Η πρόσβαση σε μεταβλητή που δεν έχει λάβει τιμή είναι εξαίρεση +# Δες τον Έλεγχο Ροής για να μάθεις περισσότερα για το χειρισμό εξαιρέσεων +some_unknown_var # Προκαλέι ένα NameError + +# Η παρακάτω έκφραση μπορεί να χρησιμποιηθεί ισοδύναμα με τον τελεστή '?' της C +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# Οι λίστες κρατούν ακολουθίς +li = [] +# Μπορείς να αρχίσεις με μία προ-γεμισμένη λίστα +other_li = [4, 5, 6] + +# Και να βάλεις πράγματα στο τέλος με την μέθοδο append +li.append(1) # η li τώρα είναι [1] +li.append(2) # η li τώρα είναι [1, 2] +li.append(4) # η li τώρα είναι [1, 2, 4] +li.append(3) # η li τώρα είναι [1, 2, 4, 3] +# Αφαιρούμε από το τέλος με την μέθοδο pop +li.pop() # => 3 και η li γίνεται [1, 2, 4] +# Ας βάλουμε το 3 πίσω στη θέση του +li.append(3) # η li γίνεται πάλι [1, 2, 4, 3]. + +# Προσπελαύνουμε τις λίστες όπως τους πίνακες σε άλλες γλώσσες +li[0] # => 1 +# Το τελευταίο στοιχείο... +li[-1] # => 3 + +# Όταν βγαίνουμε εκτός ορίων της λίστας προκαλείται IndexError +li[4] # προκαλεί IndexError + +# Μπορείς να δεις ranges μιας λίστας με το slice syntax ':' +# Ο δείκτης εκίνησης περιλαμβάνεται στο διάστημα, ο δείκτης τερματισμού όχι +# (είναι ανοικτό/κλειστό διάστημα για τους φίλους των μαθηματικών) +li[1:3] # => [2, 4] +# Αγνόησε την αρχή και επίστρεψε τη λίστα +li[2:] # => [4, 3] +# Αγνόησε το τέλος και επίστρεψε τη λίστα +li[:3] # => [1, 2, 4] +# Διάλεξε κάθε δεύτερο στοιχείο +li[::2] # =>[1, 4] +# Επίστρεψε ένα reversed αντίγραφο της λίστας +li[::-1] # => [3, 4, 2, 1] +# Χρησιμοποιείστε οποιαδήποτε συνδυασμό αυτών για να φτιάξετε πιο προχωρημένα slices +# li[start:end:step] + +# Φτιάξε ένα αντίγραφο της λίστας χρησιμοποιώντας slices +li2 = li[:] # => li2 = [1, 2, 4, 3] αλλά το (li2 is li) επιστρέφει False + +# Αφαίρεσε οποιοδήποτε στοιχείο από λίστα με την εντολή "del" +del li[2] # η li γίνεται [1, 2, 3] + +# Αφαιρούμε το πρώτο στιγμυότυπο μιας τιμής +li.remove(2) # η li γίνεται [1, 3] +li.remove(2) # Προκαλεί ένα ValueError καθώς το 2 δεν βρίσκεται στη λίστα. + +# Εισαγωγή ενός στοιχείου σε συγκεκριμένη θέση +li.insert(1, 2) # η li γίνεται πάλι [1, 2, 3] + +# Βρες το index (δείκτη) του πρώτου στοιχείου με τιμή ίση με το όρισμα +li.index(2) # => 1 +li.index(4) # Προκαλεί ValueError καθώς το 4 δεν βρίσκεται στη λίστα + +# Μπορείς να προσθέτεις λίστες +# Σημ.: οι τιμές των li, other_li δεν αλλάζουν. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Σύντμιση λιστών με τη μέθοδο "extend()" +li.extend(other_li) # Τώρα η li είναι [1, 2, 3, 4, 5, 6] + +# Ελεγχος της ύπαρξης στοιχείου σε λίστα με το "in" +1 in li # => True + +# Εξατάζουμε το μήκος με "len()" +len(li) # => 6 + + +# Τα Tuples είναι σαν τις λίστες αλλά είναι αμετάβλητα (immutable). +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Προκαλεί TypeError + +# Σημειώστε ότι ένα tuple μήκους 1 πρέπει να έχει ένα κόμμα μετά το τελευταίο στοιχείο +# αλλά τα tuples άλλων μηκών, ακόμα και μηδενικού μήκους, δεν χρειάζονται κόμμα. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# Μπορείς να εφαρμόσεις τις περισσότερες μεθόδους των λιστών και στα tuples +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Μπορείς να κάνεις unpack/"ξεπακετάρεις" tuples σε μεταβλητές +a, b, c = (1, 2, 3) # a == 1, b == 2 και c == 3 +# Μπορείς επίσης να επεκτείνεις το unpacking +a, *b, c = (1, 2, 3, 4) # a == 1, b == [2, 3] και c == 4 +# Τα Tuples δημιουργούνται by deafult αν δεν βάλεις παρενθέσεις +d, e, f = 4, 5, 6 # το tuple 4, 5, 6 "ξεπακετάρεται" στις μεταβλητές d, e και f +# αντίστοιχα έτσι ώστε να γίνεται d = 4, e = 5 and f = 6 +# Δείτε πόσο εύκολα μπορούμε να εναλλάσουμε δύο τιμές +e, d = d, e # το d παίρνει την τιμή 5 και το e παίρνει την τιμή 4 + + +# Τα λεξικά (Dictionaries) αποθηκεύουν απεικονίσεις από κλειδιά σε τιμές +empty_dict = {} +# Εδώ έχουμε ένα προ-γεμισμένο dictionary +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Σημ. ότι τα κλειδιά για τα dictionaries πρέπει να είναι αμετάβλητοι τύποι +# (immutable) αυτό γίνετια για να διασφαλίσουμε ότι τα κλειδιά μπορούν να +# μετατρέπονται σε σταθερές τιμές κατακερματισμού (hash values) για γρήγορη εύρεση. +# Μερικοί αμετάβλητοι τύποι είναι τα ints, floats, strings, tuples. +invalid_dict = {[1,2,3]: "123"} # => Προκαλεί TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Οι τιμές όμως μπορούν να έχουν οποιοδήποτε τύπο. + +# Βρίσκουμε τιμές με [] +filled_dict["one"] # => 1 + +# Μπορείς να πάρεις όλα τα κλειδιά με τη μέθοδο "keys()". +# Πρέπει να "τυλίξουμε" την κλήση με list() για να το μετατρέψουμε σε λίστα +# Θα μιλήσουμε για αυτά αργότερα. Σημ. - σε εκδόσεις Python < 3.7, η σειρά που +# εμφανίζονται τα κλειδιά δεν είναι εγγυημένη. Τα αποτελέσματά σας ίσως να μην +# είναι ακριβώς ίδια με τα παρακάτω. Στην έκδοση 3.7 πάντως, τα αντικείμενα του +# λεξικού διατηρούν τη σειρά με την οποία εισήχθησαν στο dictionary +list(filled_dict.keys()) # => ["three", "two", "one"] σε Python <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] σε Python 3.7+ + +# Παίρνουμε όλες τις τιμές ενός iterable με τη μέθοδο "values()". Και πάλι +# χρειάζεται να το περιτυλίξουμε σε list() +# Σημ. - όπως παραπάνω σχετικά με τη σειρά των keys +list(filled_dict.values()) # => [3, 2, 1] in Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+ + +# Έλεγχος της ύπαρξης κλειδιών σε ένα dictionary με το "in" +"one" in filled_dict # => True +1 in filled_dict # => False + +# Αν ψάξεις την τιμή ανύπαρκτου κλειδιού προκαλείται KeyError +filled_dict["four"] # KeyError + +# Χρησιμοποιούμε τη μέθοδο "get()" για να αποφύγουμε το KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# στο δεύτερο argument της get() μπορούμε να βάλουμε μία τιμή που πρέπει να +# επιστρέψει αν δεν υπάρχει το key που ψάχνουμε +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 + +# το "setdefault()" εισάγει στο dictionary μόνο αν δεν υπάρχει το κλειδί +filled_dict.setdefault("five", 5) # filled_dict["five"] γίνεται 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] μένει 5 (υπαρκτό κλειδί) + +# Προσθήκη σε dictionary +filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4 # β' τρόπος + +# Αφαίρεση κλειδιών από dictionary με del +del filled_dict["one"] # Αφαιρεί το κλειδί "one" από το filled_dict + +# Από την Python 3.5 μπορείς να χρησιμοποιήσεις και πρόσθετες επιλογές για unpacking +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + + + +# τα Sets -όπως όλοι περιμένουμε- αποθηκεύουν σύνολα +empty_set = set() +# Αρχικοποιούμε ένα set με μερικές τιμές. Ναι, μοιάζει λίγο με dictionary, Sorry. +some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} + +# Παρομοίως με τα κλειδιά του dictionary, τα στοιχεία ενός συνόλου πρέπει να είναι +# αμετάβλητα (immutable) +invalid_set = {[1], 1} # => Προκαλεί TypeError: unhashable type: 'list' +valid_set = {(1,), 1} + +# Προσθέτουμε άλλο ένα στοιχείο στο σύνολο +filled_set = some_set +filled_set.add(5) # το filled_set είναι τώρα {1, 2, 3, 4, 5} +# Τα σύνολα δεν έχουν διπλοτυπα αντικείμενα +filled_set.add(5) # το σύνολο παραμένει ίδιο {1, 2, 3, 4, 5} + +# το & κάνει την τομή δύο συνόλων. +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# και το | την ένωση +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Η διαφορά συνόλων με το - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Το ^ επιστρέφει τη συμμετρική διαφορά +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Ελεγχος για το αν το δεξιά σύνολο είναι υπερσύνολο του δεξιού +{1, 2} >= {1, 2, 3} # => False + +# Ελεγχος για το αν το δεξιά σύνολο είναι υποσύνολο του δεξιού +{1, 2} <= {1, 2, 3} # => True + +# με το in κάνουμε έλεγχο ύπαρξης στοιχείο σε σετ +2 in filled_set # => True +10 in filled_set # => False + + + +#################################################### +## 3. Έλεγχος Ροής και Iterables +#################################################### + +# Φτιάχνουμε μία μεταβλητή +some_var = 5 + +# Εδώ έχουμε ένα if statement. Η στοίχιση είναι σημαντική στην Python! +# Η σύμβαση είναι να χρησιμοποιούμε 4 κενά, όχι tabs. +# Το παρακάτω τυπώνει "some_var is smaller than 10" +if some_var > 10: + print("some_var is totally bigger than 10.") +elif some_var < 10: # το (else if) -> elif μέρος είναι προαιρετικό. + print("some_var is smaller than 10.") +else: # και το else είναι προαιρετικό. + print("some_var is indeed 10.") + + +""" +τα for loops τρέχουν πάνω σε lists +το παρακάτω τυπώνει: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # You can use format() to interpolate formatted strings + print("{} is a mammal".format(animal)) + +""" +το "range(number)" επιστρέφει ένα iterable με αριθμούς +από το μηδέν μέχρι τον δωσμένο αριθμό number (κλειστό/ανοικτό διάστημα) +Το παρακάτω τυπώνει: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +το "range(lower, upper)" επιστρέφει ένα iterable με αριθμούς +από το lower εώς το upper (κλειστό/ανοικτό διάστημα) +το παρακάτω τυπώνει: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) + +""" +το "range(lower, upper, step)" επιστρέφει ένα iterable με αριθμούς +από το lower μέχρι το upper, με βήμα step +αν δεν δώσουμε τιμή βήματος, το default βήμα είναι 1. +το παρακάτω τυπώνει: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) +""" + +τα While loops τρέχουν μέχρι μία συνθήκη να γίνει ψευδής. +το παρακάτω τυπώνει: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # Shorthand for x = x + 1 + +# Χειριζόμαστε εξαιρέσεις με ένα try/except block +try: + # Χρησιμοποιούμε το "raise" για να πετάξουμε ένα error + raise IndexError("This is an index error") +except IndexError as e: + pass # το Pass δεν κάνει τίποτα. Συνήθως κάνουμε ανάκτηση. +except (TypeError, NameError): + pass # Μπορούμε να χειριζόμαστε πολλές εξαιρέσεις μαζί, αν χρειαστεί +else: # Προαιρετικό στο try/except block. Πρέπει να ακολουθεί όλα τα except blocks + print("All good!") # τρέχει μόνο αν ο κώδικας στο try δεν προκαλεί εξαιρέσεις +finally: # Εκτελείται ό,τι και να γίνει + print("We can clean up resources here") + +# Αντί για try/finally για να καθαρίσουμε τους πόρους, μπορούμε να χρησιμοποιούμε το +# with expression as target: + pass to cleanup resources you can use a with statement +with open("myfile.txt") as f: + for line in f: + print(line) + +# Η Python προσφέρει μία θεμελιώδη αφαίρεση (abstraction) που λέγεται Iterable. +# iterable είναι ένα αντικείμενο που μπορεί να χρησιμοποιηθεί ως ακολουθία. +# Το αντικείμενο που επιστρέφει η συνάρτηση range, είναι ένα iterable. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['one', 'two', 'three']). +# Αυτό είναι ένα αντικείμενο που υλοποιεί την iterable διεπαφή μας. + +# μπορούμε να τρέχουμε loops πάνω του. +for i in our_iterable: + print(i) # Prints one, two, three + +# Ωστόσο δεν μπορούμε να προσπελάσουμε τα στοιχεία του με index. +our_iterable[1] # προκαλεί a TypeError + +# Ένα iterable είναι ένα αντικείμενο που ξέρει πώς να δημιουργήσει έναν iterator. +our_iterator = iter(our_iterable) + +# Ο iterator μας είναι ένα αντικείμενο που μπορεί να θυμάται την κατάσταση όπως το διατρέχουμε. +# Παίρνουμε το επόμενο αντικείμενο με το "next()" +next(our_iterator) # => "one" + +# Διατηρεί την κατάσταση καθώς επαναλαμβάνουμε. +next(our_iterator) # => "two" +next(our_iterator) # => "three" + +# Όταν ο iterator έχει επιστρέψει όλα τα δεδομένα του, προκαλεί ένα μια εξαίρεση StopIteration. +next(our_iterator) # προκαλεί StopIteration + +# Μπορείς να πάρεις όλα τα αντικείμενα ενός iteratior καλώντας list() πάνω του. +list(filled_dict.keys()) # => Επιστρέφει ["one", "two", "three"] + + +#################################################### +## 4. Συναρτήσεις +#################################################### + +# Χρησιμποιούμε το "def" για να ορίσουμε νέες συναρτήσεις +def add(x, y): + print("x is {} and y is {}".format(x, y)) + return x + y # επιστρέφει τιμές με την εντολή return + +# Καλούμε συναρτήσεις με παραμέτρους +add(5, 6) # => τυπώνει "x is 5 and y is 6" και επιστρέφει 11 + +# Ένας άλλος τρόπος να καλέσεις συνάρτησει είναι με keyword arguments (ορίσματα λέξεις-κλειδιά) +add(y=6, x=5) # τα Keyword arguments μπορούν να δωθούν με οποιαδήποτε σειρά. + +# Μπορείς να ορίσεις συναρτήσεις που δέχονται μεταβλητό πλήθος ορισμάτων +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + +# Μπορούμε να ορίσουμε και συναρτήσεις που δέχονται μεταβλητό πλήθος keyword arguments +def keyword_args(**kwargs): + return kwargs + +# Για να δούμε τι γίνεται αν την καλέσουμε +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# Μπορείς να κάνεις και τα δύο ταυτόχρονα αν θες +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) τυπώνει: + (1, 2) + {"a": 3, "b": 4} +""" + +# Όταν καλείς συναρτήσεις μπορείς να κάνεις και το αντίστροφο από args/kwargs! +# Χρησιμοποίησε το * για να επεκτείνεις tuples και χρησιμοποίησε το ** για να επεκτείλεις kwargs +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # ισοδύναμο με all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # ισοδύναμο με all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # ισοδύναμο με all_the_args(1, 2, 3, 4, a=3, b=4) + +# Επιστρέφουμε πλειάδα τιμών (με tuple assignments) +def swap(x, y): + return y, x # Επιστρέφει πολλές τιμές ως tuple χωρίς την παρένθεση + # (Σημ.: οι παρενθέσεις έχουν παραλειφθεί αλλά μπορούν να γραφούν) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Ξανά, οι παρενθέσεις έχουν παραληφθεί αλλά μπορούν να γραφούν + +# Εμβέλεια συναρτήσεων +x = 5 + +def set_x(num): + # Η τοπική μεταβλητή x δεν είναι η ίδια με την global μεταβλητή x + x = num # => 43 + print(x) # => 43 + +def set_global_x(num): + global x + print(x) # => 5 + x = num # η global μεταβλητή x τώρα είναι 6 + print(x) # => 6 + +set_x(43) +set_global_x(6) + + +# Η Python έχει πρώτης τάξης συναρτήσεις +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# Αλλά έχει και anonymous συναρτήσεις. +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 + +# Υπάρχουν ενσωματωμένες συναρτήσεις μεγαλύτερης τάξης +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] + +# Μπορούμε να χρησιμοποιήσουμε list comprehensions για ωραία maps και filters +# το List comprehension αποθηκεύει την έξοδο ως μία λίστα που μπορεί και η ίδια +# να είναι μια εμφωλευμένη λίστα +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# Μπορείς επίσης να κατασκευάσεις set και dict comprehensions. +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + + +#################################################### +## 5. Modules +#################################################### + +# Μπορείς να κάνεις import modules +import math +print(math.sqrt(16)) # => 4.0 + +# Μπορείς να πάρεις συγκεκριμένες συναρτήσεις από ένα module +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# Μπορείς να κάνεις import όλες τις συναρτήσεις από ένα module. +# Προσοχή: δεν προτείνεται +from math import * + +# Μπορείς να δημιουργείς συντομογραφίες για τα ονόματα των modules +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Τα Python modules είναι απλά αρχεία Python. Μπορείς να δημιουργήσεις τα δικά σου +# και να τα κάνεις import το όνομα του module είναι ίδιο με το όνομα του αρχείου + +# μπορείς να βρεις ποιες συναρτήσεις και γνωρίσματα ορίζονται στο module +import math +dir(math) + +# Αν έχεις ένα Python script με όνομα math.py στον ίδιο φάκελο με το τρέχον script +# το αρχείο math.py θα φορτωθεί και όχι το built-in Python module +# Αυτό συμβαίνει επειδή τα τοπικά αρχεία έχουν προτεραιότητα έναντι των built-in +# βιβλιοθηκών της Python + + +#################################################### +## 6. Κλάσεις - Classes +#################################################### + +# χρησιμοποιούμε το "class" statement για να δημιουργήσουμε μια κλάση +class Human: + + # Ένα γνώρισμα της κλάσης. Είναι κοινό για όλα τα στιγμιότυπα αυτής. + species = "H. sapiens" + + # Βασικός initializer, καλείται όταν δημιουργείται στιγμιότυπο της κλάσης. + # Σημ. οι διπλές κάτω παύλες πριν και μετά υποδηλώνουν αντικείμενα + # ή γνωρίσματα που χρησιμοποιούνται από την Python αλλά ζουν σε ελεγχόμενα από + # το χρήση namespaces. + # Μέθοδοι (ή αντικείμενα ή γνωρίσματα) σαν τα __init__, __str__, __repr__ κλπ + # είναι ειδικές μέθοδοι (λέγονται και dunder (double underscore) μέθοδοι) + # Δεν πρέπει να δηλώνεις δικές σου τέτοιες συναρτήσεις + def __init__(self, name): + # Εκχώρησε στο attribute name του object το όρισμα + self.name = name + + # Αρχικοποίησε την ιδιότητα + self._age = 0 + + # Μία μέθοδος στιγμιότυπου (instance method). Όλες οι μέθοδοι παίρνουν το + # "self" ως πρώτο όρισμα + def say(self, msg): + print("{name}: {message}".format(name=self.name, message=msg)) + + # Ακόμα μία instance method + def sing(self): + return 'yo... yo... microphone check... one two... one two...' + + # Μία μέθοδος κλάσεις είναι κοινή ανάμεσα σε όλα τα instances. + # Καλούνται με calling class ώς πρώτο όρισμα + @classmethod + def get_species(cls): + return cls.species + + # Μία στατική μέθοδος καλείται χωρίς αναφορά σε κλάση ή στιγμιότυπο + @staticmethod + def grunt(): + return "*grunt*" + + # Ένα property είναι ακριβώς σαν ένα getter. + # Μετατρέπει τη μέθοδο age σε ένα γνώρισμα (attribute) μόνο-για-ανάγνωση + # με το ίδιο όνομα. + # Δεν χρειάζεται να γράφουμε τετριμένους getters και setters στην Python όμως. + @property + def age(self): + return self._age + + # Αυτό επιτρέπει στο property να γίνει set + @age.setter + def age(self, age): + self._age = age + + # Αυτό επιτρέπει σε ένα property να διαγραφεί + @age.deleter + def age(self): + del self._age + + +# Όταν ο διερμηνέας της Python διαβάζει αρχείο πηγαίου κώδικα τον εκτελεί όλο. +# Αυτός ο έλεγχος του __name__ σιγουρεύει ότι αυτό το block κώδικα τρέχει μόνο +# αυτό το module είναι το κύριο πρόγραμμα (και όχι imported) +if __name__ == '__main__': + # Δημιουργούμε στιγμιότυπο κλάσης + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # τα i και j είναι στιγμιότυπα του τύπου Human + + # Καλούμε τη μέθοδο της κλάσης + i.say(i.get_species()) # "Ian: H. sapiens" + # Αλλάζουμε το κοινό attribute των αντικειμένων της κλάσης + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # Καλούμε τη static μέθοδο + print(Human.grunt()) # => "*grunt*" + + # Δεν μπορούμε να καλέσουμε τη στατική μέθοδο με ένα στιγμιότυπο + # επειδή το i.grunt() θα βάλει αυτόματα το self (δηλαδή το αντικείμενο i) ως όρισμα + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given + + # Ενημερώνουμε το property για αυτό το στγμιότυπο + i.age = 42 + # Παίρνουμε το property + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # Διαγράφουμε το property + del i.age + # i.age # => αυτό θα προκαλούσε AttributeError + + +#################################################### +## 6.1 Κληρονομικότητα - Inheritance +#################################################### + +# Η κληρονομικότητα επιτρέπει σε νέες κλάσεις-παιδιά να οριστούν και να υιοθετήσουν +# μεθόδους και μεταβλητές από την κλάση-γονέα. + +# Χρησιμοποιώντας την κλάση Human που ορίστηκε πριν ως τη βασική κλάση (ή κλάση-γονέα) +# μπορούμε να ορίσουμε τις κλάσεις-παιδιά Superhero, που κληρονομεί μεταβλητές όπως +# "species", "name", και "age", καθώς και μεθόδους όπως "sing" και "grunt" +# από την κλάση Human, αλλά επίσης έχει τις δικές του ξεχωριστές ιδιότητες + +# Για να εκμεταλλευτείς το modularization κατά αρχείο, μπορείς να βάλεις την παραπάνω κλάση +# σε δικό της αρχείο, ας πούμε human.py + +# Για να κάνουμε import συναρτήσεις από άλλα αρχεία χρησιμοποιούμε το παρακάτω format +# from "filename-without-extension" import "function-or-class" + +from human import Human + + +# Προσδιόρισε την/τις parent class(es) ως παραμέτρους της κλάσης που ορίζεται +class Superhero(Human): + + # Αν η κλάση-παιδί πρέπει να κληρονομήσει όλους τους οεισμούς της κλάσης-γονέα + # χωρίς καμία αλλαγή, μπορείς απλά να γράψεις pass (και τίποτα άλλο) + # αλλά σε αυτή την περίπτωση είναι σχολιασμένο για να επιτρέψει τη δημιουργία + # ξεχωριστής κλάσης-παιδιού: + # pass + + # Η κλάση παιδί μπορεί να υπερφορτώσει (override) τα attributes της κλάσης από την οποία κληρονομεί + species = 'Superhuman' + + # Τα παιδιά αυτόματα, κληρονομούν τον constructo της κλάσης-γονέα + # συμπεριλαμβανομένων των ορισμάτων, αλλά μπορείς και να ορίσεις πρόσθετα ορίσματα + # ή ορισμούς και να κάνεις override τις μεθόδους, όπως τον constructor. + # Αυτός ο constructor κληρονομεί το όρισμα "name" από την κλάση Human και + # προσθέτει τα ορίσματα "superpower" και "movie": + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): + + # πρόσθήκη επιπλέον attributes της κλάσης: + self.fictional = True + self.movie = movie + # έχετε το νου σας τις μεταβλητές (mutable) default τιμές, καθώς είναι κοινές + self.superpowers = superpowers + + # Η συνάρτηση "super" επιτρέπει την πρόσβαση στις μεθόδους της κλάσης-γονέα + # που είναι υπερφορτωμένες από το παιδί. Σε αυτή την περίπτωση τη μέθοδο __init__ + # Το παρακάτω καλεί τον constructor της κλάσης-γονέα: + super().__init__(name) + + # υπερφόρτωση της μεθόδου sing + def sing(self): + return 'Dun, dun, DUN!' + + # προσθήκη νέας μεθόδου που εφαρμόζεται σε στιγμιότυπα + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) + + +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # Έλεγχος για το αν το στιγμιότυπο sup ανήκει στην κλάση Human + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') +# TODO: + # Παίρνουμε το Method Resolution search Order που χρησιμοποιούν οι getattr() και super() + # Αυτό το attribute είναι δυναμικό και μπορεί να ανανεωθεί + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) + + # Καλούμε μέθοδο της κλάσης-γονέα, αλλά χρησιμοποιεί το δικό της attribute + print(sup.get_species()) # => Superhuman + + # Καλεί την υπερφορτωμένη μέθοδο + print(sup.sing()) # => Dun, dun, DUN! + + # Καλεί μέθοδο από την κλάση Human + sup.say('Spoon') # => Tick: Spoon + + # Καλεί μέθοδο που υπάρχει μόνο στην κλάση Superhero + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # Κληρονομημένο class attribute + sup.age = 31 + print(sup.age) # => 31 + + # Attribute που υπάρχει μόνο στην μέσα στην κλάση Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) + +#################################################### +## 6.2 Πολλαπλή Κληρονομικότητα - Multiple Inheritance +#################################################### + +# Ένας ακόμη ορισμός κλάσης +# bat.py +class Bat: + + species = 'Baty' + + def __init__(self, can_fly=True): + self.fly = can_fly + + # Αυτή η κλάση έχει επίσης μία μέθοδο say + def say(self, msg): + msg = '... ... ...' + return msg + + # Και τη δική της μέθοδο sonar + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + + +# Και ορίζουμε μία ακόμα κλάση που κληρονομεί από τις κλάσεις Superhero και Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Ας πούμε αυτή την κλάση Batman +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # Τυπικά γα να κληρονομήουμε attributes πρέπει να καλέσουμε τη super: + # super(Batman, self).__init__(*args, **kwargs) + # Ωστόσο έχουμε να κάνουμε με πολλαπλή κληρονομικότητα εδώ, και το super() + # δουλεύει μόνο με την αμέσως ανώτερη κλάση στην ιεραρχία. + # Οπότε, καλούμε ρητά την __init__ για όλους τους πρόγονους + # Η χρήση των *args και **kwargs επιτρέπει έναν καθαρό τρόπο για να περνάμε ορίσματα + # με κάθε κλάση-γονέα να "βγάζει μία φλούδα από το κρεμμύδι". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # υπερφορτώνουμε την τιμή του γνωρίσματος name + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # + # Λάβε το Method Resolution search Order που χρησιμοποιείται από το getattr() και το super(). + # Αυτό το attribute είναι δυναμικό και μπορεί να ενημερωθεί + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # Καλεί την μέθοδο της κλάσης-πατέρα αλλά χρησιμοποιεί το attribute της δικής του κλάσης + print(sup.get_species()) # => Superhuman + + # Καλεί την υπερφορτωμένη μέθοδο + print(sup.sing()) # => nan nan nan nan nan batman! + + # Καλεί μέθοδο από την κλάση Human, επειδή μετράει η σειρά της κληρονομιάς + sup.say('I agree') # => Sad Affleck: I agree + + # Καλεί μέθοδο που ανήκει μόνο στον δεύτερο πρόγονο + print(sup.sonar()) # => ))) ... ((( + + # Attribute της κληρονομημένης κλάσης + sup.age = 100 + print(sup.age) # => 100 + + # Κληρονομούμενο attribute από τον δεύτερο πρόγονο του οποίου η default τιμή + # έχει υπερφορτωθεί. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + + +#################################################### +## 7. Προχωρημένα +#################################################### + +# Με τους Generators μπορείς να γράψεις τεμπέλικο κώδικα. +def double_numbers(iterable): + for i in iterable: + yield i + i +# Οι Generators είναι αποδοτικοί από άποψη μνήμης επειδή φορτώνουν μόνο τα δεδομένα +# που είναι αναγκαία για να επεξεργαστούμε την επόμενη τιμή του iterable. +# Αυτό μας επιτρέπει να κάνουμε πράξεις σε τιμές που υπό άλλες συνθήκες θα ήταν +# απαγορευτικά μεγάλες. +for i in double_numbers(range(1, 900000000)): # το `range` είναι ένας generator. + print(i) + if i >= 30: + break + +# Όπως μπορείς να δημιουργήσεις list comprehension, έτσι μπορείς να δημιουργήσεις και +# generator comprehensions +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # τυπώνει -1 -2 -3 -4 -5 στο console/terminal + +# Μπορείς επίσης να μετατρέψεις ένα generator comprehension απευθείας σε λίστα. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + + +# Decorators +# σε αυτό το παράδειγμα το `beg` τυλίγει το `say`. Αν το say_please είναι True τότε +# θα αλλάξει το μήνυμα που επιστρέφεται. +from functools import wraps + + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( +``` + +## Έτοιμοι για περισσότερα? + +### Δωρεάν Online + +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](http://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) diff --git a/el-gr/rust-gr.html.markdown b/el-gr/rust-gr.html.markdown new file mode 100644 index 00000000..d28e3c2c --- /dev/null +++ b/el-gr/rust-gr.html.markdown @@ -0,0 +1,340 @@ +--- +language: Rust +contributors: + - ["P1start", "http://p1start.github.io/"] + - ["Dimitri Kokkonis", "https://github.com/kokkonisd"] +filename: learnrust-gr.rs +lang: el-gr +--- + +_[ΣτΜ.: οι όροι "χαμηλό/υψηλό επίπεδο" αναφέρονται στην εγγύτητα μιας γλώσσας προγραμματισμού ή γενικότερα ενός +στοιχείου στην "μηχανή", ή το υλικό του υπολογιστή. Για παράδειγμα, η φράση "η C είναι μια γλώσσα χαμηλού επιπέδου" +αναφέρεται στο γεγονός ότι η C επιτρέπει άμεση και λεπτομερή διαχείρηση μνήμης, και πιο άμεσο έλεγχο του επεξεργαστή· +σε καμία περίπτωση δεν σημαίνει ότι η C έχει λιγότερες δυνατότητες, και γενικότερα δεν φέρει αρνητική σημασία.]_ + +Η Rust είναι μια γλώσσα προγραμματισμού ανεπτυγμένη από την Mozilla Research. +Συνδυάζει τον έλεγχο της απόδοσης χαμηλού επιπέδου με διευκολύνσεις και ασφάλεια υψηλού επιπέδου. + +Πετυχαίνει αυτούς τους στόχους χωρίς να χρειάζεται garbage collector ή runtime, το οποίο καθιστά δυνατή τη χρήση +βιβλιοθηκών της Rust ως αντικατάσταση της C. + +Η έκδοση 0.1 (η πρώτη της Rust) δημοσιεύθηκε τον Ιανουάριο του 2012, και για τα επόμενα 3 χρόνια η ανάπτυξή της +εξελίχθηκε τόσο γρήγορα που, μέχρι πρότινος, προτείνονταν η χρήση μη-σταθερών εκδόσεων (nightly builds) αντί σταθερών +εκδόσεων. + +Τις 15 Μαΐου 2015 δημοσιεύτηκε η εκδοχή 1.0 της Rust, με πλήρη εγγύηση συμβατότητας με προηγούμενες εκδοχές. Οι +μη-σταθερές εκδόσεις συνήθως περιλαμβάνουν γρηγορότερους χρόνους μεταγλώττισης και γενικότερες βελτιώσεις όσον αφορά +τον μεταγλωττιστή. Η μέθοδος [train release](https://www.plutora.com/blog/agile-release-train) χρησιμοποιείται, με +συστηματικές εκδόσεις να δημοσιεύονται κάθε έξι εβδομάδες. Η beta έκδοση της Rust 1.1 δημοσιεύθηκε ταυτοχρόνως με την +σταθερή έκδοση 1.0. + +Αν και η Rust είναι μια γλώσσα σχετικά χαμηλού επιπέδου, ο σχεδιασμός της περιλαμβάνει κάποιες έννοιες που συναντώνται +συνχότερα σε γλώσσες υψηλού επιπέδου. Αυτό καθιστά την Rust γρήγορη και αποδοτική αλλά επίσης εύκολη και προσβάσιμη. + + +```rust +// Αυτό είναι ένα σχόλιο. Τα σχόλια μίας γραμμής γράφονται έτσι... +// Και επεκτείνονται σε περισσότερες από μία γραμμές έτσι. + +/// Τα σχόλια documentation γράφονται έτσι, και υποστηρίζουν markdown. +/// # Παράδειγμα +/// +/// ``` +/// let five = 5 +/// ``` + +////////////////////// +// 1. Βασικές αρχές // +////////////////////// + +#[allow(dead_code)] +// Συναρτήσεις +// `i32` είναι ο τύπος που αντιστοιχεί στους 32-bit signed ακέραιους +fn add2(x: i32, y: i32) -> i32 { + // Έμεσα εννοούμενη επιστροφή του αποτελέσματος, χωρίς semicolon (;) + x + y +} + +#[allow(unused_variables)] +#[allow(unused_assignments)] +#[allow(dead_code)] +// Συνάρτηση main +fn main() { + // Αριθμοί // + + // Αμετάβλητη δέσμευση (η τιμή που αντιστοιχεί στο όνομα "x" δεν μπορεί να αλλάξει) + let x: i32 = 1; + + // Καταλήξεις integer/float + let y: i32 = 13i32; + let f: f64 = 1.3f64; + + // Εξακρίβωση τύπου (type inference) + // Τις περισσότερες φορες ο μεταγλωττιστής της Rust μπορεί να εξακριβώσει τον τύπο μιας μεταβλητής, επομένως δεν + // χρειάζεται ο προγραμματιστής να τον δηλώνει ρητά. + // Σε αυτό το tutorial, οι τύποι δηλώνονται ρητά σε διάφορα σημεία, αλλά μόνο προκειμένου να είναι πιο ευανάγνωστος + // ο κώδικας. Ο μεταγλωττιστής μπορεί να το διαχειριστεί αυτόματα στις περισσότερες περιπτώσεις. + let implicit_x = 1; + let implicit_f = 1.3; + + // Πράξεις + let sum = x + y + 13; + + // Μεταβλητές (με την έννοια των προστακτικών γλωσσών προγραμματισμού). + // Στη Rust η αμετάβλητη δέσμευση είναι στάνταρ. Το mut δηλώνει μεταβλητότητα. + let mut mutable = 1; + mutable = 4; + mutable += 2; + + // Αλφαριθμητικά // + + // Σταθερά αλφαριθμητικά + let x: &str = "καλημέρα κόσμε!"; + + // Εκτύπωση αλφαριθμητικών + println!("{} {}", f, x); // 1.3 καλημέρα κόσμε! + + // A `String` – a heap-allocated string + let s: String = "καλημέρα κόσμε".to_string(); + + // Ένα κομμάτι αλφαριθμητικού (string slice) – μια αμετάβλητη οπτική γωνία προς ένα άλλο αλφαριθμητικό + // Το αλφαριθμητικό μπορεί να είναι στατικό όπως τα σταθερά αλφαριθμητικά, ή να περιλαμβάνεται σε ένα άλλο, + // δυναμικό αντικείμενο (σε αυτή την περίπτωση τη μεταβλητή `s`) + let s_slice: &str = &s; + + println!("{} {}", s, s_slice); // καλημέρα κόσμε καλημέρα κόσμε + + // Διανύσματα/πίνακες // + + // Πίνακας σταθερού μεγέθους + let four_ints: [i32; 4] = [1, 2, 3, 4]; + + // Δυναμικός πίνακας (διάνυσμα) + let mut vector: Vec<i32> = vec![1, 2, 3, 4]; + vector.push(5); + + // Ένα κομμάτι – μια αμετάβλητη οπτική γωνία προς ένα διάνυσμα ή πίνακα + // Είναι παρόμοιο με το κομμάτι αλφαριθμητικού που είδαμε προηγουμένως + let slice: &[i32] = &vector; + + // Μπορούμε να χρησιμοποιήσουμε το `{:?}` για να εκτυπώσουμε κάτι σε στυλ debug + println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] + + // Tuples (πλειάδες) // + + // Ένα tuple είναι μια σταθερού μεγέθους σειρά από τιμές (πιθανά διαφορετικού τύπου) + let x: (i32, &str, f64) = (1, "καλημέρα", 3.4); + + // Μπορούμε να χρησιμοποιήσουμε το `let` και ένα tuple για να δώσουμε πολλές τιμές σε πολλές μεταβλητές ταυτόχρονα + // (destructuring `let`) + let (a, b, c) = x; + println!("{} {} {}", a, b, c); // 1 καλημέρα 3.4 + + // Μπορούμε επίσης να επιλέξουμε ένα συγκεκριμένο στοιχείο από ένα tuple + println!("{}", x.1); // καλημέρα + + ////////////// + // 2. Τύποι // + ////////////// + + // Δομή + struct Point { + x: i32, + y: i32, + } + + let origin: Point = Point { x: 0, y: 0 }; + + // Μια δομή με ανώνυμα πεδία, ή αλλιώς μια `δομή tuple` (`tuple struct`) + struct Point2(i32, i32); + + let origin2 = Point2(0, 0); + + // Enum, όπως στην C + enum Direction { + Left, + Right, + Up, + Down, + } + + let up = Direction::Up; + + // Enum με πεδία + enum OptionalI32 { + AnI32(i32), + Nothing, + } + + let two: OptionalI32 = OptionalI32::AnI32(2); + let nothing = OptionalI32::Nothing; + + // Γενικότητα (genericity) // + + struct Foo<T> { bar: T } + + // Αυτό ορίζεται στην standard library ως `Option` + enum Optional<T> { + SomeVal(T), + NoVal, + } + + // Μέθοδοι // + + impl<T> Foo<T> { + // Οι μέθοδοι παίρνουν πάντα μια ρητή παράμετρο `self` + fn bar(&self) -> &T { // Δανειζόμαστε το self + &self.bar + } + fn bar_mut(&mut self) -> &mut T { // Γίνεται "μεταβλητός δανεισμός" του self (μπορούμε να το τροποποιήσουμε) + &mut self.bar + } + fn into_bar(self) -> T { // Εδώ το self καταναλώνεται + self.bar + } + } + + let a_foo = Foo { bar: 1 }; + println!("{}", a_foo.bar()); // 1 + + // Χαρακτηρηστικά (traits) (γνωστά ως interfaces ή typeclasses σε άλλες γλώσσες) // + + trait Frobnicate<T> { + fn frobnicate(self) -> Option<T>; + } + + impl<T> Frobnicate<T> for Foo<T> { + fn frobnicate(self) -> Option<T> { + Some(self.bar) + } + } + + let another_foo = Foo { bar: 1 }; + println!("{:?}", another_foo.frobnicate()); // Some(1) + + ////////////////////////////////////////////////// + // 3. Αντιστοιχίσεις Μοτίβων (Pattern Matching) // + ////////////////////////////////////////////////// + + let foo = OptionalI32::AnI32(1); + match foo { + OptionalI32::AnI32(n) => println!("Είναι ένα i32: {}", n), + OptionalI32::Nothing => println!("Δεν είναι τίποτα!"), + } + + // Προχωρημένο pattern matching + struct FooBar { x: i32, y: OptionalI32 } + let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) }; + + match bar { + FooBar { x: 0, y: OptionalI32::AnI32(0) } => + println!("Οι αριθμοί είναι μηδέν!"), + FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m => + println!("Οι αριθμοί είναι οι ίδιοι"), + FooBar { x: n, y: OptionalI32::AnI32(m) } => + println!("Διαφορετικοί αριθμοί: {} {}", n, m), + FooBar { x: _, y: OptionalI32::Nothing } => + println!("Ο δεύτερος αριθμός δεν είναι τίποτα!"), + } + + ///////////////////// + // 4. Έλεγχος ροής // + ///////////////////// + + // Βρόχοι `for` + let array = [1, 2, 3]; + for i in array { + println!("{}", i); + } + + // Διαστήματα + for i in 0u32..10 { + print!("{} ", i); + } + println!(""); + // Τυπώνει `0 1 2 3 4 5 6 7 8 9 ` + + // `if` (υπό συνθήκη διακλάδωση) + if 1 == 1 { + println!("Τα μαθηματικά δουλεύουν!"); + } else { + println!("Ωχ όχι..."); + } + + // `if` ως έκφραση + let value = if true { + "καλό" + } else { + "κακό" + }; + + // Βρόχοι `while` + while 1 == 1 { + println!("Το σύμπαν λειτουργεί κανονικά."); + // Μπορούμε να βγούμε από το βρόχο με το `break` + break + } + + // Ατέρμονος βρόχος + loop { + println!("Καλημέρα!"); + // Μπορούμε να βγούμε από το βρόχο με το `break` + break + } + + ////////////////////////////////// + // 5. Ασφάλεια μνήμης & δείκτες // + ////////////////////////////////// + + // Δείκτης με ιδιοκτήτη – μόνο ένα αντικείμενο μπορεί να είναι ο "ιδιοκτήτης" αυτού του δείκτη ανά πάσα στιγμή + // Αυτό σημαίνει ότι μόλις το `Box` βγει εκτός πλαισίου (out of scope), ο δείκτης μπορεί να ελευθερωθεί με ασφάλεια + let mut mine: Box<i32> = Box::new(3); + *mine = 5; // Dereference του δείκτη + // Εδώ, το `now_its_mine` γίνεται ιδιοκτήτης του `mine`. Δηλαδή, το `mine` μετακινείται. + let mut now_its_mine = mine; + *now_its_mine += 2; + + println!("{}", now_its_mine); // 7 + // println!("{}", mine); // Αυτό παράγει λάθος κατά τη μεταγλώττιση διότι τώρα ο δείκτης ανήκει στο `now_its_mine` + + // Reference (αναφορά) – ένας αμετάβλητος δείκτης που αναφέρεται σε άλλα δεδομένα + // Όταν μια αναφορά δίνεται σε μια τιμή, λέμε πως η τιμή έχει "δανειστεί". + // Όταν μια τιμή δανείζεται αμετάβλητα, δεν μπορεί να είναι mutated (να μεταβληθεί) ή να μετακινηθεί. + // Ένας "δανεισμός" παραμένει ενεργός μέχρι την τελευταία χρήση της μεταβλητής που δανείζεται. + let mut var = 4; + var = 3; + let ref_var: &i32 = &var; + + println!("{}", var); // Αντίθετα με το `mine` προηγουμένως, η μεταβλητή `var` μπορεί ακόμα να χρησιμοποιηθεί + println!("{}", *ref_var); + // var = 5; // Αυτό παράγει λάθος κατά τη μεταγλώττιση γιατί η μεταβλητή `var` είναι δανεισμένη + // *ref_var = 6; // Το ίδιο εδώ, γιατί η `ref_var` αποτελεί αμετάβλητη αναφορά + ref_var; // Εντολή no-op (τίποτα δεν εκτελείται από τον επεξεργαστή), η οποία όμως μετράει ως χρήση και κρατά τον + // "δανεισμό" ενεργό + 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, όχι την τιμή την ίδια. + // var2 = 2; // Λάθος μεταγλώττισης, γιατί η `var2` είναι δανεισμένη. + ref_var2; // Εντολή no-op (τίποτα δεν εκτελείται από τον επεξεργαστή), η οποία όμως μετράει ως χρήση και κρατά τον + // "δανεισμό" ενεργό +} +``` + +## Μάθετε περισσότερα + +Υπάρχουν πολλά ακόμα πράγματα να μάθει κανείς· αυτά είναι μόνο τα βασικά της Rust, που επιτρέπουν να καταλάβουμε το +βασικό τρόπο λειτουργίας της. Για να μάθετε περισσότερα για τη Rust, διαβάστε το [The Rust Programming +Language](http://doc.rust-lang.org/book/index.html) και επισκεφθείτε το subreddit [/r/rust](http://reddit.com/r/rust). +Οι άνθρωποι πίσω από το κανάλι #rust στο irc.mozilla.org είναι επίσης πάντα πρόθυμοι να βοηθήσουν τους αρχάριους. + +Μπορείτε επίσης να παίξετε με τη Rust χρησιμοποιώντας τους εξής online μεταγλωττιστές: + +- [Rust playpen](http://play.rust-lang.org) +- [Rust website](http://rust-lang.org) diff --git a/el-gr/vim-gr.html.markdown b/el-gr/vim-gr.html.markdown new file mode 100644 index 00000000..b11b5c33 --- /dev/null +++ b/el-gr/vim-gr.html.markdown @@ -0,0 +1,267 @@ +--- +category: tool +tool: vim +contributors: + - ["RadhikaG", "https://github.com/RadhikaG"] +filename: LearnVim-gr.txt +lang: el-gr +--- + + +[Vim](http://www.vim.org) +To (Vi IMproved) είναι ένας κλώνος του δημοφιλούς vi editor για Unix. +Είναι ένας text editor σχεδιασμένος για ταχύτητα και αυξημένη παραγωγικότητα, +και υπάρχει σχεδόν σε όλα τα Unix-based συστήματα. Έχει διάφορα keybindings +(συντομεύσεις πλήκτρων) για να πλοηγούμαστε γρήγορα σε συγκεκριμένα σημεία ενός αρχείου, +καθώς και για γρήγορη επεξεργασία. + +## Τα βασικά της πλοήγησης στον Vim + +``` + vim <filename> # Άνοιξε το <filename> στον vim + :help <topic> # Άνοιξε το built-in βοήθημα για το <topic> αν υπάρχει + :q # Βγες από τον vim + :w # Αποθήκευσε το τρέχον αρχείο + :wq # Αποθήκευσε το τρέχον αρχείο και βγες από τον vim + ZZ # Αποθήκευσε το τρέχον αρχείο και βγες από τον vim + :q! # Βγες χωρίς αποθήκευση + # ! *αναγκάζει* το :q να εκτελεστεί, γι αυτό βγαίνει χωρίς saving + :x # Ίδιο με το wq αλλά πιο σύντομο + + u # Undo + CTRL+R # Redo + + h # Μετακινήσου κατά ένα χαρακτήρα αριστερά + j # Μετακινήσου μια γραμμή κάτω + k # Μετακινήσου μια γραμμή πάνω + l # Μετακινήσου μια γραμμή δεξιά + + Ctrl+B # Πήγαινε μία οθόνη πίσω + Ctrl+F # Πήγαινε μία οθόνη μπροστά + Ctrl+U # Πήγαινε μισή οθόνη πίσω + Ctrl+D # Πήγαινε μισή οθόνη μπροστά + + # Μετακινήσεις στην ίδια γραμμή + + 0 # Πήγαινε στην αρχή της γραμμής + $ # Πήγαινε στο τέλος της γραμμής + ^ # Πήγαινε στον πρώτο μη κενό χαρακτήρα της γραμμής + + # Αναζήτηση στο κείμενο + + /word # Υπογραμμίζει όλες τις εμφανίσεις της λέξης μετά τον cursor + ?word # Υπογραμμίζει όλες τις εμφανίσεις της λέξης πριν τον cursor + n # Μετακινεί τον cursor στην επόμενη εμφάνιση της λέξης + N # Μετακινεί τον cursor στην προηγούμενη εμφάνιση της λέξης + + :%s/foo/bar/g # άλλαξε το 'foo' σε 'bar' σε κάθε γραμμή του αρχείου + :s/foo/bar/g # άλλαξε το 'foo' σε 'bar' στην τρέχουσα γραμμή + + # Άλματα σε χαρακτήρες + + f<character> # Άλμα μπροστά και προσγείωση στο επόμενο <character> + t<character> # Άλμα μπροστά και προσγείωση αμέσως πριν το προηγούμενο <character> + + # Για παράδειγμα, + f< # Άλμα μπροστά και προσγείωση σε < + t< # Άλμα μπροστά και προσγείωση αμέσως πριν < + + # Μετακινήσεις κατά λέξεις + + w # Πήγαινε μια λέξη μπροστά + b # Πήγαινε μια λέξη πίσω + e # Πήγαινε στο τέλος της λέξης στην οποία είσαι + + # Άλλοι χαρακτήρες για να τριγυρνάμε + + gg # Πήγαινε στην αρχή του αρχείου + G # Πήγαινε στο τέλος του αρχείου + :NUM # Πήγαινε στη γραμμή με αριθμό NUM (οποιοσδήποτε αριθμός) + H # Πήγαινε στην κορυφή της σελίδας + M # Πήγαινε στην μέση της σελίδας + L # Πήγαινε στο κάτω άκρο της σελίδας +``` + +## Help docs: +Το Vim έχει built-in help documentation που μπορείς να δεις με `:help <topic>`. +Για παράδειγμα το `:help navigation` θα σου εμφανίσει documentation σχετικό με +το πως να πλοηγείσαι στο αρχείο! + +To `:help` μπορεί να χρησιμοποιηθεί και χωρίς option. Αυτό θα εμφανίσει το default +help dialog που σκοπεύει να κάνει το vim πιο προσιτό σε αρχάριους! + +## Modes: + +O Vim στηρίζεται στο concept των **modes**. + +- Command Mode - ο vim εκκινεί σε αυτό mode, χρησιμοποιείται για πλοήγηση και εντολές +- Insert Mode - χρησιμοποιείται για να κάνουμε αλλαγές στα αρχεία +- Visual Mode - χρησιμοποιείται για να υπογραμμίζουμε κείμενα και να κάνουμε διάφορα σε αυτά +- Ex Mode - χρησιμοποιείται για να πάμε στο κάτω μέρος με το ':' που δίνουμε εντολές + +``` + i # Βάζει το vim σε insert mode, πριν τη θέση cursor + a # Βάζει το vim σε insert mode, μετά τη θέση cursor + v # βάζει τον vim σε visual mode + : # Βάζει τον vim σε ex mode + <esc> # φεύγει από όποιο mode είμαστε και πάει σε command mode + + # Αντιγραφή-Επικόληση κειμένου + + y # Yank (κάνε copy) ό,τι είναι επιλεγμένο + yy # Yank την γραμμή στην οποία είσαι + d # διάγραψε ό,τι είναι επιλεγμένο + dd # Διάγραψε τη γραμμή στην οποία είσαι + p # Κάνε Paste το αντεγραμένο κείμενο μετά την θέση του cursor + P # Κάνε Paste το αντεγραμένο κείμενο πριν την θέση του cursor + x # Διάγραψε τον χαρακτήρα που είναι κάτω από τον cursor +``` + +## Η 'γραμματική' του Vim + +Μπορείς να σκεφτείς τον Vim ως ένα σύνολο εντολών +σε μορφή 'Verb-Modifier-Noun', όπου + +- Verb - η ενέργεια που θες να κάνεις +- Modifier - πώς κάνεις την ενέργεια +- Noun - το αντικείμενο που δέχεται την ενέργεια + +Μερικά παραδείγματα ''Ρημάτων', 'Modifiers' και 'Ουσιαστικών': + +``` + # 'Ρήματα' + + d # Διάγραψε + c # Άλλαξε + y # Yank (αντίγραψε) + v # Επίλεξε οπτικά + + # 'Modifiers' + + i # Μέσα + a # Γύρω + NUM # Αριθμός (NUM = οποιοσδήποτε αριθμός) + f # Ψάξε κάτι και πήγαινε εκεί που βρίσκεται + t # Ψάξε κάτι και πήγαινε πριν από εκεί που βρίσκεται + / # Βρες κάποιο string μετά από τον cursor + ? # Βρες κάποιο string πριν τον cursor + + # 'Ουσιαστικά' + + w # Λέξη + s # Πρόταση + p # Παράγραφος + b # Block + + # Δείγματα 'προτάσεων' ή εντολών + + d2w # Διάγραψε 2 λέξεις + cis # Άλλαξε μέσα στην πρώταση + yip # Αντίγραψε την παράγραφο στην οποία βρίσκεσαι + ct< # Άλλαξε σε < + # Άλλαξε το κείμενο από το οποίο είσαι πριν το επόμενο bracketChange the text from where you are to the next open bracket + d$ # Διάγραψε μέχρι το τέλος της γραμμής +``` + +## Μερικά shortcuts και κόλπα + + <!--TODO: Βάλτε κι άλλα!--> +``` + > # Στοίχισε προς τα δεξιά την επιλογή σου κατά ένα block + < # Στοίχισε προς τα αριστερά την επιλογή σου κατά ένα block + :earlier 15m # Κάνε το αρχείο όπως ήταν πριν 15 λεπτά + :later 15m # Ακύρωση για την παραπάνω εντολή + ddp # Αντάλλαξε τις θέσεις διαδοχικών γραμμών + . # Επανάλαβε την προηγούμενη ενέργεια + :w !sudo tee % # Σώσε το τρέχον αρχείο ως root + :set syntax=c # Κάνε syntax highlighting για τη γλώσσα c + :sort # Ταξινόμησε όλες τις γραμμές + :sort! # Ταξινόμησε ανάποδα όλες τις γραμμές (αύξουσα σειρά) + :sort u # Ταξινόμησε όλες τις γραμμές και διάγραψε τις διπλές γραμμές + ~ # Άλλαξε τα κεφαλαία σε μικρά στο επιλεγμένο κείμενο + u # Το επιλεγμένο κείμενο να γίνει πεζά γράμματα + U # Το επιλεγμένο κείμενο να γίνει κεφαλαία γράμματα + + # Fold text + zf # Διπλώνει (συμπιέζει τις γραμμές σε μία) το επιλεγμένο κείμενο + zo # Ξεδιπλώνει το επιλεγμένο fold + zc # Κλείνει το επιλεγμένο fold + zR # Ανοίγει όλα τα folds + zM # Κλείνει όλα τα folds +``` + +## Macros + +Τα macros βασικά είναι καταγραφή ενεργειών. +Όταν ξεικάς να καταγράφεις ένα macro καταγράφονται **όλες** οι ενέργεις και οι +εντολές που χρησιμοποιείς, μέχρι να σταματήσεις την καταγραφή. Όταν καλείς ένα macro, +εκτελείται πάλι η ίδια σειρά από ενέργειες και εντολές στο επιλεγμένο κείμενο. + +``` + qa # Ξεκίνα να καταγράφεις ένα macro που θα ονομαστεί 'a' + q # Σταμάτα την καταγραφή + @a # Τρέξε το macro +``` + +### Configuring ~/.vimrc + +Το αρχείο .vimrc μπορεί να χρησιμοποιηθεί για να κάνεις configure το Vim στο startup. + +Εδώ βλέπουμε δείγμα ενός ~/.vimrc file: + +``` +" 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 +``` + +### Αναφορές + +[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? (Stack Overflow thread)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about) + +[Arch Linux Wiki](https://wiki.archlinux.org/index.php/Vim) diff --git a/elisp.html.markdown b/elisp.html.markdown index f839dac0..5d98ceff 100644 --- a/elisp.html.markdown +++ b/elisp.html.markdown @@ -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) diff --git a/elixir.html.markdown b/elixir.html.markdown index 7af29202..2748a983 100644 --- a/elixir.html.markdown +++ b/elixir.html.markdown @@ -1,7 +1,7 @@ --- -language: elixir +language: Elixir contributors: - - ["Joao Marques", "http://github.com/mrshankly"] + - ["Joao Marques", "https://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] - ["Ryan Plant", "https://github.com/ryanplant-au"] - ["Ev Bogdanov", "https://github.com/evbogdanov"] @@ -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 @@ -439,7 +438,7 @@ self() #=> #PID<0.27.0> # Create an agent with `Agent.start_link`, passing in a function # The initial state of the agent will be whatever that function returns -{ok, my_agent} = Agent.start_link(fn -> ["red", "green"] end) +{:ok, my_agent} = Agent.start_link(fn -> ["red", "green"] end) # `Agent.get` takes an agent name and a `fn` that gets passed the current state # Whatever that `fn` returns is what you'll get back @@ -451,9 +450,10 @@ Agent.update(my_agent, fn colors -> ["blue" | colors] end) ## References -* [Getting started guide](http://elixir-lang.org/getting-started/introduction.html) from the [Elixir website](http://elixir-lang.org) +* [Getting started guide](https://elixir-lang.org/getting-started/introduction.html) from the [Elixir website](https://elixir-lang.org) * [Elixir Documentation](https://elixir-lang.org/docs.html) * ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) by Dave Thomas -* [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf) -* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert +* [Elixir Cheat Sheet](https://media.pragprog.com/titles/elixir/ElixirCheat.pdf) +* ["Learn You Some Erlang for Great Good!"](https://learnyousomeerlang.com/) by Fred Hebert * ["Programming Erlang: Software for a Concurrent World"](https://pragprog.com/book/jaerlang2/programming-erlang) by Joe Armstrong +* [Introduction to Elixir](https://learn-elixir.com/) diff --git a/elm.html.markdown b/elm.html.markdown index ad80adc9..bc7ba4cc 100644 --- a/elm.html.markdown +++ b/elm.html.markdown @@ -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. diff --git a/erlang.html.markdown b/erlang.html.markdown index a9d280d7..62666c3a 100644 --- a/erlang.html.markdown +++ b/erlang.html.markdown @@ -1,7 +1,7 @@ --- language: erlang contributors: - - ["Giovanni Cappellotto", "http://www.focustheweb.com/"] + - ["Giovanni Cappellotto", "http://giovanni.curlybrackets.it/"] filename: learnerlang.erl --- diff --git a/es-es/amd-es.html.markdown b/es-es/amd-es.html.markdown index 40aa6647..83c705c3 100644 --- a/es-es/amd-es.html.markdown +++ b/es-es/amd-es.html.markdown @@ -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> ``` diff --git a/es-es/asciidoc-es.html.markdown b/es-es/asciidoc-es.html.markdown index 6e357915..31406ee1 100644 --- a/es-es/asciidoc-es.html.markdown +++ b/es-es/asciidoc-es.html.markdown @@ -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. diff --git a/es-es/awk-es.html.markdown b/es-es/awk-es.html.markdown index 8da8f024..1ee12956 100644 --- a/es-es/awk-es.html.markdown +++ b/es-es/awk-es.html.markdown @@ -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. diff --git a/es-es/bash-es.html.markdown b/es-es/bash-es.html.markdown index fb89b2a0..27070e79 100644 --- a/es-es/bash-es.html.markdown +++ b/es-es/bash-es.html.markdown @@ -18,7 +18,7 @@ Tutorial de Shell en español. Bash es el nombre del shell de unix, el cual también es distribuido como el shell del sistema operativo GNU. También es el shell -por defecto de Linux y Mac OS X. Casi todos los ejemplos abajo pueden +por defecto de Linux y macOS. Casi todos los ejemplos abajo pueden ser parte de un script shell o ser ejecutados directamente en la terminal. [Leer más aquí.](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/es-es/c++-es.html.markdown b/es-es/c++-es.html.markdown index 2c3762d5..f624d3c7 100644 --- a/es-es/c++-es.html.markdown +++ b/es-es/c++-es.html.markdown @@ -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 diff --git a/es-es/c-es.html.markdown b/es-es/c-es.html.markdown index 8bc1eabb..ae357d91 100644 --- a/es-es/c-es.html.markdown +++ b/es-es/c-es.html.markdown @@ -1,10 +1,11 @@ --- -language: c +language: C filename: learnc-es.c contributors: - ["Adam Bard", "http://adambard.com/"] translators: - ["Francisco García", "http://flaskbreaker.tumblr.com/"] + - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"] lang: es-es --- @@ -423,7 +424,7 @@ libro de C, escrito por Dennis Ritchie, creador de C y Brian Kernighan. Aún as se cuidadoso, es antiguo, contiene algunas inexactitudes, y algunas prácticas han cambiado. -Otro buen recurso es [Learn C the hard way](http://c.learncodethehardway.org/book/). +Otro buen recurso es [Learn C the hard way](http://learncodethehardway.org/c/). Si tienes una pregunta, lee [compl.lang.c Frequently Asked Questions](http://c-faq.com). diff --git a/es-es/chapel-es.html.markdown b/es-es/chapel-es.html.markdown new file mode 100644 index 00000000..732ee298 --- /dev/null +++ b/es-es/chapel-es.html.markdown @@ -0,0 +1,1219 @@ +--- +language: chapel +filename: learnchapel.chpl +contributors: + - ["Ian J. Bertolacci", "https://www.cs.arizona.edu/~ianbertolacci/"] + - ["Ben Harshbarger", "https://github.com/benharsh/"] +translators: + - ["Ivan Alburquerque", "https://github.com/AlburIvan"] +lang: es-es +--- + +Puede leer todo sobre Chapel en [el sitio web oficial de Chapel de Cray](https://chapel-lang.org). +En resumen, Chapel es un lenguaje de programación paralela, código abierto, de alta productividad +desarrolladp en Cray Inc. y está diseñado para ejecutarse en PC multi-nucleos, +así como en supercomputadoras multi-kilocore. + + +Puede encontrar más información y asistencia al final de este documento. + +```chapel +// Los comentarios son de estilo de la familia C + +// comentario de una línea +/* + comentario de múltiples lineas +*/ + +// Impresión básica + +write("Hola, "); +writeln("Mundo!"); + +// write y writeln pueden tomar una lista de cosas para imprimir. +// Cada cosa está impresa justo al lado de las demás, ¡así que incluye espacios! +writeln("hay ", 3, " comas (\",\") en esta línea de código"); + +// Diferentes canales de salida: +stdout.writeln("Esto va a la salida estándar, al igual que lo hace writeln()"); +stderr.writeln("Esto va al error estándar"); + + +// Las variables no tienen que escribirse explícitamente +// mientras el compilador pueda determinar el tipo que contendrá. + +// 10 es un entero, asi que myVar es explícitamente un entero +var myVar = 10; +myVar = -10; +var mySecondVar = myVar; +// var anError; sería un error en tiempo de compilación + +// Podemos (y debemos) escribir cosas explícitamente. +var myThirdVar: real; +var myFourthVar: real = -1.234; +myThirdVar = myFourthVar; + +// Tipos + +// Hay varios tipos básicos. +var myInt: int = -1000; // Enteros firmados +var myUint: uint = 1234; // Enteros sin-firmar +var myReal: real = 9.876; // Números de punto flotante +var myImag: imag = 5.0i; // Números imaginarios +var myCplx: complex = 10 + 9i; // Números complejos +myCplx = myInt + myImag; // Otra manera de formar números complejos +var myBool: bool = false; // Booleanos +var myStr: string = "Una cadena..."; // Cadenas +var singleQuoteStr = 'Otra cadena...'; // Cadena literal con comillas simples + +// Algunos tipos pueden tener tamaños. +var my8Int: int(8) = 10; // Entero de 8 bit (one byte); +var my64Real: real(64) = 1.516; // Real de 64 bit (8 bytes) + +// Conversion de tipos. +var intFromReal = myReal : int; +var intFromReal2: int = myReal : int; + +// Alias de tipo. +type chroma = int; // Tipo de un solo tono +type RGBColor = 3*chroma; // Tipo que representa un color completo +var black: RGBColor = (0,0,0); +var white: RGBColor = (255, 255, 255); + +// Constantes y Parámetros + +// una variable const es una constante y no se puede cambiar después de +// establecerla en tiempo de ejecución. +const almostPi: real = 22.0/7.0; + +// Un parámetro es una constante cuyo valor debe conocerse estáticamente +// en tiempo de compilación. + +param compileTimeConst: int = 16; + +// El modificador de configuración permite establecer valores en la línea de comando. +// Establece valores con --varCmdLineArg=Value o --varCmdLineArg Value en tiempo de ejecución. +config var varCmdLineArg: int = -123; +config const constCmdLineArg: int = 777; + +// config param se puede configurar en tiempo de compilación. +// Establece valores con --set paramCmdLineArg=value en tiempo de compilación. +config param paramCmdLineArg: bool = false; +writeln(varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg); + +// Referencias + +// ref funciona de manera muy similar a una referencia en C ++. En Chapel, +// no se puede hacer una referencia como alias a una variable distinta +// de la variable con la que se inicializa. + +// Aquí, refToActual se refiere a actual. +var actual = 10; +ref refToActual = actual; +writeln(actual, " == ", refToActual); // imprime el mismo valor +actual = -123; // modificar actual (a lo que refToActual se refiere) +writeln(actual, " == ", refToActual); // imprime el mismo valor +refToActual = 99999999; // modificar a qué se refiere refToActual (que es actual) +writeln(actual, " == ", refToActual); // imprime el mismo valor + +// Operadores + +// Operadores matemáticos: +var a: int, thisInt = 1234, thatInt = 5678; +a = thisInt + thatInt; // Adicción +a = thisInt * thatInt; // Multiplicación +a = thisInt - thatInt; // Substracción +a = thisInt / thatInt; // División +a = thisInt ** thatInt; // Exponenciación +a = thisInt % thatInt; // residuo (módulo) + +// Operadores logicos: +var b: bool, thisBool = false, thatBool = true; +b = thisBool && thatBool; // Lógico y +b = thisBool || thatBool; // Lógico o +b = !thisBool; // Lógico negación + +// Operadores relacionales: +b = thisInt > thatInt; // Mas grande que +b = thisInt >= thatInt; // Mas grande o igual que +b = thisInt < a && a <= thatInt; // Menor que, y, Menor o igual que +b = thisInt != thatInt; // No es igual a +b = thisInt == thatInt; // es igual a + +// Operadores bit a bit: +a = thisInt << 10; // Desplazamiento de bit izquierdo por 10 bits; +a = thatInt >> 5; // Desplazamiento de bit derecho por 5 bits; +a = ~thisInt; // Negación bit a bit +a = thisInt ^ thatInt; // bit a bit exclusivo o + +// Operadores de asignación compuesta: +a += thisInt; // Adición-igual (a = a + thisInt;) +a *= thatInt; // Multiplicación-igual (a = a * thatInt;) +b &&= thatBool; // Lógico e igual (b = b && thatBool;) +a <<= 3; // Desplazamiento a la izquierda igual (a = a << 10;) + +// A diferencia de otros lenguajes de familia C, no hay operadores de +// pre / post-incremento / decremento, tales como: +// +// ++j, --j, j++, j-- + +// Operador de intercambio: +var old_this = thisInt; +var old_that = thatInt; +thisInt <=> thatInt; // Intercambia los valores de thisInt y thatInt +writeln((old_this == thatInt) && (old_that == thisInt)); + +// También se pueden definir sobrecargas del operador, como veremos con los procedimientos. + +// Tuplas + +// Las tuplas pueden ser del mismo tipo o de diferentes tipos. +var sameTup: 2*int = (10, -1); +var sameTup2 = (11, -6); +var diffTup: (int,real,complex) = (5, 1.928, myCplx); +var diffTupe2 = (7, 5.64, 6.0+1.5i); + +// Se puede acceder a las tuplas usando corchetes o paréntesis, +// y están indexadas en base 1. +writeln("(", sameTup[1], ",", sameTup(2), ")"); +writeln(diffTup); + +// Las tuplas también se pueden escribir. +diffTup(1) = -1; + +// Los valores de tupla se pueden expandir a sus propias variables. +var (tupInt, tupReal, tupCplx) = diffTup; +writeln(diffTup == (tupInt, tupReal, tupCplx)); + +// También son útiles para imprimit una lista de variables, +// como es común en la depuración. +writeln((a,b,thisInt,thatInt,thisBool,thatBool)); + +// Flujo de control + +// if - then - else funciona como cualquier otro lenguaje de la familia C. +if 10 < 100 then + writeln("All is well"); + +if -1 < 1 then + writeln("Continuando creyendo en la realidad"); +else + writeln("¡Envia un matemático!, algo está mal"); + +// Puedes usar paréntesis si lo prefieres. +if (10 > 100) { + writeln("El Universo está roto, Por favor reinicie el universo."); +} + +if a % 2 == 0 { + writeln(a, " es par."); +} else { + writeln(a, " es impar."); +} + +if a % 3 == 0 { + writeln(a, " es divisible entre 3."); +} else if a % 3 == 1 { + writeln(a, " es divisible entre 3 con un residuo de 1."); +} else { + writeln(b, " es divisible entre 3 con un residuo de 2."); +} + +// Ternario: if - then - else en una declaración. +var maximum = if thisInt < thatInt then thatInt else thisInt; + +// las declaraciones select son muy parecidas a las declaraciones switch +// en otros idiomas. Sin embargo, las declaraciones select no caen +// en cascada como en C o Java. +var inputOption = "anOption"; +select inputOption { + when "anOption" do writeln("Escoge 'anOption'"); + when "otherOption" { + writeln("Escoge 'otherOption'"); + writeln("Que tiene un cuerpo"); + } + otherwise { + writeln("Cualquier otra entrada"); + writeln("El caso otherwise no necesita hacerse si el cuerpo es de una línea"); + } +} + +// Los bucles while y do-while también se comportan como sus contrapartes en C. +var j: int = 1; +var jSum: int = 0; +while (j <= 1000) { + jSum += j; + j += 1; +} +writeln(jSum); + +do { + jSum += j; + j += 1; +} while (j <= 10000); +writeln(jSum); + +// Los bucles for son muy parecidos a los de Python porque iteran en un rango. +// Los rangos (como la expresión 1..10 a continuación) son un objeto de primera clase +// en Chapel, y como tal pueden almacenarse en variables. +for i in 1..10 do write(i, ", "); +writeln(); + +var iSum: int = 0; +for i in 1..1000 { + iSum += i; +} +writeln(iSum); + +for x in 1..10 { + for y in 1..10 { + write((x,y), "\t"); + } + writeln(); +} + +// Rangos y Dominios + +// Los bucles y matrices utilizan rangos y dominios para definir un conjunto de índices +// que se pueden iterar. Los rangos son índices enteros unidimensionales, mientras +// que los dominios pueden ser multidimensionales y representan índices +// de diferentes tipos. + +// Son tipos ciudadanos de primera clase y pueden asignarse a variables. +var range1to10: range = 1..10; // 1, 2, 3, ..., 10 +var range2to11 = 2..11; // 2, 3, 4, ..., 11 +var rangeThisToThat: range = thisInt..thatInt; // usando variables +var rangeEmpty: range = 100..-100; // esto es válido pero no contiene índices + +// Los rangos pueden ser ilimitados. +var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ; // 1, 2, 3, 4, 5, ... +var rangeNegInfTo1 = ..1; // ..., -4, -3, -2, -1, 0, 1 + +// Los rangos se pueden andar (y revertir) utilizando el operador by. +var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10 +var reverse2to10by2 = 2..10 by -2; // 10, 8, 6, 4, 2 + +var trapRange = 10..1 by -1; // No te dejes engañar, esto sigue siendo un rango vacío +writeln("Size of range ", trapRange, " = ", trapRange.length); + +// Note: range(boundedType= ...) and range(stridable= ...) solo son necesarios +// si escribimos explícitamente la variable. + +// El punto final de un rango se puede determinar utilizando el operador de conteo (#). +var rangeCount: range = -5..#12; // intervalo de -5 to 6 + +// Los operadores pueden ser mixtos. +var rangeCountBy: range(stridable=true) = -5..#12 by 2; // -5, -3, -1, 1, 3, 5 +writeln(rangeCountBy); + +// Se pueden consultar las propiedades del rango. +// En este ejemplo, imprime el primer índice, el último índice, el número de índices, +// el paso y si 2 se incluye en el rango. +writeln((rangeCountBy.first, rangeCountBy.last, rangeCountBy.length, + rangeCountBy.stride, rangeCountBy.member(2))); + +for i in rangeCountBy { + write(i, if i == rangeCountBy.last then "\n" else ", "); +} + +// Los dominios rectangulares se definen usando la misma sintaxis de rango, +// pero se requiere que estén delimitados (a diferencia de los rangos). +var domain1to10: domain(1) = {1..10}; // 1D domain from 1..10; +var twoDimensions: domain(2) = {-2..2,0..2}; // 2D domain over product of ranges +var thirdDim: range = 1..16; +var threeDims: domain(3) = {thirdDim, 1..10, 5..10}; // using a range variable + +// Los dominios también pueden ser redimensionados +var resizedDom = {1..10}; +writeln("antes, resizedDom = ", resizedDom); +resizedDom = {-10..#10}; +writeln("despues, resizedDom = ", resizedDom); + +// Los índices pueden iterarse como tuplas. +for idx in twoDimensions do + write(idx, ", "); +writeln(); + +// Estas tuplas también pueden ser deconstruidas. +for (x,y) in twoDimensions { + write("(", x, ", ", y, ")", ", "); +} +writeln(); + +// Los dominios asociativos actúan como conjuntos. +var stringSet: domain(string); // empty set of strings +stringSet += "a"; +stringSet += "b"; +stringSet += "c"; +stringSet += "a"; // Redundant add "a" +stringSet -= "c"; // Remove "c" +writeln(stringSet.sorted()); + +// Los dominios asociativos también pueden tener una sintaxis literal +var intSet = {1, 2, 4, 5, 100}; + +// Tanto los rangos como los dominios se pueden dividir para producir un rango +// o dominio con la intersección de los índices. +var rangeA = 1.. ; // range from 1 to infinity +var rangeB = ..5; // range from negative infinity to 5 +var rangeC = rangeA[rangeB]; // resulting range is 1..5 +writeln((rangeA, rangeB, rangeC)); + +var domainA = {1..10, 5..20}; +var domainB = {-5..5, 1..10}; +var domainC = domainA[domainB]; +writeln((domainA, domainB, domainC)); + +// Matrices + +// Las matrices son similares a otros lenguajes. +// Sus tamaños son definidos usndo dominions que repretsenten sus indices. +var intArray: [1..10] int; +var intArray2: [{1..10}] int; // equivalent + +// Pueden ser accedidos usando brackets o paréntesis +for i in 1..10 do + intArray[i] = -i; +writeln(intArray); + +// No podemos acceder a intArray[0] porque existe fuera del conjunto de índices, +// {1..10}, que definimos al principio. +// intArray [11] es ilegal por la misma razón. +var realDomain: domain(2) = {1..5,1..7}; +var realArray: [realDomain] real; +var realArray2: [1..5,1..7] real; // equivalent +var realArray3: [{1..5,1..7}] real; // equivalent + +for i in 1..5 { + for j in realDomain.dim(2) { // Solo use la segunda dimensión del dominio + realArray[i,j] = -1.61803 * i + 0.5 * j; // Acceso usando la lista de índice + var idx: 2*int = (i,j); // Nota: 'índice' es una palabra reservada + realArray[idx] = - realArray[(i,j)]; // Indice usando tuplas + } +} + +// Las matrices tienen dominios como miembros y pueden ser iterados de manera normal. +for idx in realArray.domain { // De nuevo, idx es una tupla 2*int + realArray[idx] = 1 / realArray[idx[1], idx[2]]; // Acceso por tupla y lista +} + +writeln(realArray); + +// Los valores de una matriz también se pueden iterar directamente. +var rSum: real = 0; +for value in realArray { + rSum += value; // Read a value + value = rSum; // Write a value +} +writeln(rSum, "\n", realArray); + +// Las matrices asociativas (diccionarios) se pueden crear utilizando dominios asociativos. +var dictDomain: domain(string) = { "one", "two" }; +var dict: [dictDomain] int = ["one" => 1, "two" => 2]; +dict["three"] = 3; // Adiciona 'three' a 'dictDomain' implícitamente +for key in dictDomain.sorted() do + writeln(dict[key]); + +// Las matrices se pueden asignar entre sí de diferentes maneras. +// Estos arreglos se usarán en el ejemplo. + +var thisArray : [0..5] int = [0,1,2,3,4,5]; +var thatArray : [0..5] int; + +// Primero, simplemente asigna uno al otro. Esto copia esta matriz en +// thatArray, en lugar de simplemente crear una referencia. Por lo tanto, modificando +// thisArray tampoco modifica thatArray. +thatArray = thisArray; +thatArray[1] = -1; +writeln((thisArray, thatArray)); + +// Asigna un segmento de una matriz a un segmento (del mismo tamaño) en el otro. +thatArray[4..5] = thisArray[1..2]; +writeln((thisArray, thatArray)); + +// Las operaciones también se pueden promover para trabajar en arreglos. +// 'thisPlusThat' también es una matriz. +var thisPlusThat = thisArray + thatArray; +writeln(thisPlusThat); + +// Continuando, las matrices y los bucles también pueden ser expresiones, donde +// la expresión del cuerpo del bucle es el resultado de cada iteración. +var arrayFromLoop = for i in 1..10 do i; +writeln(arrayFromLoop); + +// Una expresión puede resultar en nada, como cuando se filtra con una expresión if. +var evensOrFives = for i in 1..10 do if (i % 2 == 0 || i % 5 == 0) then i; + +writeln(arrayFromLoop); + +// Las expresiones de matriz también se pueden escribir con una notación de paréntesis. +// Nota: esta sintaxis utiliza el concepto paralelo forall discutido más adelante. +var evensOrFivesAgain = [i in 1..10] if (i % 2 == 0 || i % 5 == 0) then i; + +// They can also be written over the values of the array. +arrayFromLoop = [value in arrayFromLoop] value + 1; + + +// Procedimientos + +// Los procedimientos de Chapel tienen funciones de sintaxis similares en otros idiomas. +proc fibonacci(n : int) : int { + if n <= 1 then return n; + return fibonacci(n-1) + fibonacci(n-2); +} + +// Los parámetros de entrada pueden estar sin tipo para crear un procedimiento genérico. +proc doublePrint(thing): void { + write(thing, " ", thing, "\n"); +} + +// Se puede inferir el tipo de retorno, siempre que el compilador pueda resolverlo. +proc addThree(n) { + return n + 3; +} + +doublePrint(addThree(fibonacci(20))); + +// También es posible tomar un número variable de parámetros. +proc maxOf(x ...?k) { + // x se refiere a una tupla de un tipo, con k elementos + var maximum = x[1]; + for i in 2..k do maximum = if maximum < x[i] then x[i] else maximum; + return maximum; +} +writeln(maxOf(1, -10, 189, -9071982, 5, 17, 20001, 42)); + +// Los procedimientos pueden tener valores de parámetros predeterminados, y +// los parámetros pueden nombrarse en la llamada, incluso fuera de orden. +proc defaultsProc(x: int, y: real = 1.2634): (int,real) { + return (x,y); +} + +writeln(defaultsProc(10)); +writeln(defaultsProc(x=11)); +writeln(defaultsProc(x=12, y=5.432)); +writeln(defaultsProc(y=9.876, x=13)); + +// El operador ? se llama operador de consulta y se usa para tomar valores +// indeterminados como tuplas o tamaños de matriz y tipos genéricos. +// Por ejemplo, tomar matrices como parámetros. + +// El operador de consulta se utiliza para determinar el dominio de A. +// Esto es útil para definir el tipo de retorno, aunque no es obligatorio. +proc invertArray(A: [?D] int): [D] int{ + for a in A do a = -a; + return A; +} + +writeln(invertArray(intArray)); + +// Podemos consultar el tipo de argumentos a los procedimientos genéricos. +// Aquí definimos un procedimiento que toma dos argumentos del mismo tipo, +// pero no definimos cuál es ese tipo. +proc genericProc(arg1 : ?valueType, arg2 : valueType): void { + select(valueType) { + when int do writeln(arg1, " and ", arg2, " are ints"); + when real do writeln(arg1, " and ", arg2, " are reals"); + otherwise writeln(arg1, " and ", arg2, " are somethings!"); + } +} + +genericProc(1, 2); +genericProc(1.2, 2.3); +genericProc(1.0+2.0i, 3.0+4.0i); + +// También podemos imponer una forma de polimorfismo con la cláusula where +// Esto permite que el compilador decida qué función usar. + +// Nota: Eso significa que toda la información debe conocerse en tiempo de compilación. +// El modificador param en el argumento se usa para imponer esta restricción. +proc whereProc(param N : int): void + where (N > 0) { + writeln("N is greater than 0"); +} + +proc whereProc(param N : int): void + where (N < 0) { + writeln("N is less than 0"); +} + +whereProc(10); +whereProc(-1); + +// whereProc(0) daría lugar a un error del compilador porque no hay funciones +// que satisfagan la condición de la cláusula where. +// Podríamos haber definido un whereProc sin una cláusula where que +// hubiera servido como captura para todos los demás casos (de los cuales solo hay uno). + +// Las cláusulas where también se pueden usar para restringir según el tipo de argumento. +proc whereType(x: ?t) where t == int { + writeln("Inside 'int' version of 'whereType': ", x); +} + +proc whereType(x: ?t) { + writeln("Inside general version of 'whereType': ", x); +} + +whereType(42); +whereType("hello"); + +// Intenciones + +/* Los modificadores de intención en los argumentos transmiten cómo esos argumentos se pasan al procedimiento. + + * in: copia arg adentro, pero no afuera + * out: copia arg, pero no dentro + * inout: copia arg adentro, copia arg afuera + * ref: pasa arg por referencia +*/ +proc intentsProc(in inarg, out outarg, inout inoutarg, ref refarg) { + writeln("Adentro antes: ", (inarg, outarg, inoutarg, refarg)); + inarg = inarg + 100; + outarg = outarg + 100; + inoutarg = inoutarg + 100; + refarg = refarg + 100; + writeln("Adentro después: ", (inarg, outarg, inoutarg, refarg)); +} + +var inVar: int = 1; +var outVar: int = 2; +var inoutVar: int = 3; +var refVar: int = 4; +writeln("Afuera antes: ", (inVar, outVar, inoutVar, refVar)); +intentsProc(inVar, outVar, inoutVar, refVar); +writeln("Afuera después: ", (inVar, outVar, inoutVar, refVar)); + +// Del mismo modo, podemos definir intentos en el tipo de retorno. +// refElement devuelve una referencia a un elemento de la matriz. Esto tiene más sentido +// práctico para los métodos de clase donde las referencias a elementos en una estructura +// de datos se devuelven a través de un método o iterador. +proc refElement(array : [?D] ?T, idx) ref : T { + return array[idx]; +} + +var myChangingArray : [1..5] int = [1,2,3,4,5]; +writeln(myChangingArray); +ref refToElem = refElement(myChangingArray, 5); // Almacena una referencia al elemento en variable de referencia +writeln(refToElem); +refToElem = -2; // modifica referencia que, a su vez, modifica el valor real en la matriz +writeln(refToElem); +writeln(myChangingArray); + +// Definiciones del operador + +// Chapel permite que los operadores se sobrecarguen. +// Podemos definir los operadores unarios: +// + - ! ~ +// y los operadores binarios: +// + - * / % ** == <= >= < > << >> & | ˆ by +// += -= *= /= %= **= &= |= ˆ= <<= >>= <=> + +// Exclusivo u operador booleano. +proc ^(left : bool, right : bool): bool { + return (left || right) && !(left && right); +} + +writeln(true ^ true); +writeln(false ^ true); +writeln(true ^ false); +writeln(false ^ false); + +// Define un operador * en cualquiera de los dos tipos que devuelve una tupla de esos tipos. +proc *(left : ?ltype, right : ?rtype): (ltype, rtype) { + writeln("\tIn our '*' overload!"); + return (left, right); +} + +writeln(1 * "a"); // Utiliza nuestro * operador. +writeln(1 * 2); // Utiliza el operador predeterminado *. + +// Note: Podrías romper todo si te descuidas con tus sobrecargas. +// Esto aquí lo romperá todo. No lo hagas + +/* + proc +(left: int, right: int): int { + return left - right; + } +*/ + +// Iteradores + +// Los iteradores son hermanas del procedimiento, y casi todo lo relacionado +// con los procedimientos también se aplica a los iteradores. Sin embargo, en lugar de +// devolver un solo valor, los iteradores pueden generar múltiples valores en un bucle. + +// Esto es útil cuando se necesita un conjunto u orden complicado de iteraciones, +// ya que permite que el código que define las iteraciones +// se separe del cuerpo del bucle. +iter oddsThenEvens(N: int): int { + for i in 1..N by 2 do + yield i; // yield values instead of returning. + for i in 2..N by 2 do + yield i; +} + +for i in oddsThenEvens(10) do write(i, ", "); +writeln(); + +// Los iteradores también pueden ceder condicionalmente, cuyo resultado puede ser nada +iter absolutelyNothing(N): int { + for i in 1..N { + if N < i { // Always false + yield i; // Yield statement never happens + } + } +} + +for i in absolutelyNothing(10) { + writeln("Woa there! absolutelyNothing yielded ", i); +} + +// Podemos comprimir dos o más iteradores (que tienen el mismo número de iteraciones) +// usando zip () para crear un solo iterador comprimido, donde cada iteración +// del iterador comprimido produce una tupla de un valor de cada iterador. +for (positive, negative) in zip(1..5, -5..-1) do + writeln((positive, negative)); + +// La iteración de la cremallera es bastante importante en la asignación de matrices, +// segmentos de matrices y expresiones de matriz / bucle. +var fromThatArray : [1..#5] int = [1,2,3,4,5]; +var toThisArray : [100..#5] int; + +// Algunas operaciones de cierre implementan otras operaciones. +// La primera declaración y el bucle son equivalentes. +toThisArray = fromThatArray; +for (i,j) in zip(toThisArray.domain, fromThatArray.domain) { + toThisArray[i] = fromThatArray[j]; +} + +// Estos dos pedazos también son equivalentes. +toThisArray = [j in -100..#5] j; +writeln(toThisArray); + +for (i, j) in zip(toThisArray.domain, -100..#5) { + toThisArray[i] = j; +} +writeln(toThisArray); + +/* + Esto es muy importante para entender por qué esta declaración + exhibe un error de tiempo de ejecución. +*/ + +/* + var iterArray : [1..10] int = [i in 1..10] if (i % 2 == 1) then i; +*/ + +// Aunque el dominio de la matriz y la expresión de bucle son del mismo tamaño, +// el cuerpo de la expresión puede considerarse como un iterador. +// Debido a que los iteradores pueden producir nada, ese iterador produce un número +// diferente de cosas que el dominio de la matriz o bucle, que no está permitido. + +// Clases + +// Las clases son similares a las de C ++ y Java, asignadas en el montón. +class MyClass { + +// Variables miembro + var memberInt : int; + var memberBool : bool = true; + +// Inicializador definido explícitamente. +// También obtenemos el inicializador generado por el compilador, con un argumento por campo. +// Tenga en cuenta que pronto no habrá un inicializador generado por el compilador +// cuando definamos los inicializadores explícitamente. + proc init(val : real) { + this.memberInt = ceil(val): int; + } + +// Desinicializador explícitamente definido. +// Si no escribiéramos uno, obtendríamos el desinicializador generado por el compilador, +// que tiene un cuerpo vacío. + proc deinit() { + writeln("MyClass deinitializer called ", (this.memberInt, this.memberBool)); + } + +// Métodos de clase. + proc setMemberInt(val: int) { + this.memberInt = val; + } + + proc setMemberBool(val: bool) { + this.memberBool = val; + } + + proc getMemberInt(): int{ + return this.memberInt; + } + + proc getMemberBool(): bool { + return this.memberBool; + } +} // termina MyClass + +// Llame al inicializador generado por el compilador, +// utilizando el valor predeterminado para memberBool. +var myObject = new MyClass(10); + myObject = new MyClass(memberInt = 10); // Equivalente +writeln(myObject.getMemberInt()); + +// Same, but provide a memberBool value explicitly. +var myDiffObject = new MyClass(-1, true); + myDiffObject = new MyClass(memberInt = -1, memberBool = true); // Equivalente +writeln(myDiffObject); + +// Llame al inicializador que escribimos. +var myOtherObject = new MyClass(1.95); + myOtherObject = new MyClass(val = 1.95); // Equivalente +writeln(myOtherObject.getMemberInt()); + +// También podemos definir un operador en nuestra clase, +// pero la definición tiene que estar fuera de la definición de la clase. +proc +(A : MyClass, B : MyClass) : MyClass { + return new MyClass(memberInt = A.getMemberInt() + B.getMemberInt(), + memberBool = A.getMemberBool() || B.getMemberBool()); +} + +var plusObject = myObject + myDiffObject; +writeln(plusObject); + +// Destrucción. +delete myObject; +delete myDiffObject; +delete myOtherObject; +delete plusObject; + +// Las clases pueden heredar de una o más clases primarias +class MyChildClass : MyClass { + var memberComplex: complex; +} + +// Aquí hay un ejemplo de clases genéricas. +class GenericClass { + type classType; + var classDomain: domain(1); + var classArray: [classDomain] classType; + +// Constructor explícito. + proc GenericClass(type classType, elements : int) { + this.classDomain = {1..#elements}; + } + +// Copiar constructor. +// Nota: Todavía tenemos que poner el tipo como argumento, pero podemos usar +// el operador de consulta (?) como predeterminado para el tipo del otro objeto. +// Además, podemos aprovechar esto para permitir a nuestro constructor de copias +// copiar clases de diferentes tipos y emitir sobre la marcha. + proc GenericClass(other : GenericClass(?otherType), + type classType = otherType) { + this.classDomain = other.classDomain; + // Copiar y Convertir + for idx in this.classDomain do this[idx] = other[idx] : classType; + } + +// Defina la notación de corchetes en un objeto GenericClass +// para que pueda comportarse como una matriz normal +// i.e. objVar[i] or objVar(i) + proc this(i : int) ref : classType { + return this.classArray[i]; + } + +// Definir un iterador implícito para que la clase produzca +// valores de la matriz a un bucle +// i.e. for i in objVar do ... + iter these() ref : classType { + for i in this.classDomain do + yield this[i]; + } +} // end GenericClass + +// Podemos asignar a la matriz de miembros del objeto usando la notación de +// corchete que definimos. +var realList = new GenericClass(real, 10); +for i in realList.classDomain do realList[i] = i + 1.0; + +// Podemos iterar sobre los valores en nuestra lista con el iterador +// que definimos. +for value in realList do write(value, ", "); +writeln(); + +// Haga una copia de realList usando el constructor de copias. +var copyList = new GenericClass(realList); +for value in copyList do write(value, ", "); +writeln(); + +// Haga una copia de realList y cambie el tipo, también utilizando el constructor de copias. +var copyNewTypeList = new GenericClass(realList, int); +for value in copyNewTypeList do write(value, ", "); +writeln(); + + +// Módulos + +// Los módulos son la forma en que Chapel administra los espacios de nombres. +// Los archivos que contienen estos módulos no necesitan ser nombrados después +// de los módulos (como en Java), pero los archivos implícitamente nombran módulos. +// Por ejemplo, este archivo nombra implícitamente el módulo learnChapelInYMinutes + +module OurModule { + +// Podemos usar módulos dentro de otros módulos. +// Time es uno de los módulos estándar. + use Time; + +// Usaremos este procedimiento en la sección de paralelismo. + proc countdown(seconds: int) { + for i in 1..seconds by -1 { + writeln(i); + sleep(1); + } + } + +// Es posible crear nidos de módulos arbitrariamente profundos. +// i.e. submódulos de OurModule + module ChildModule { + proc foo() { + writeln("ChildModule.foo()"); + } + } + + module SiblingModule { + proc foo() { + writeln("SiblingModule.foo()"); + } + } +} // end OurModule + +// Usando OurModule también usa todos los módulos que usa. +// Como OurModule usa Time, nosotros también usamos Time. +use OurModule; + +// En este punto no hemos usado ChildModule o SiblingModule, por lo que sus símbolos +// (es decir, foo) no están disponibles para nosotros. Sin embargo, los nombres de +// los módulos están disponibles y podemos llamar explícitamente a foo () a través de ellos. +SiblingModule.foo(); +OurModule.ChildModule.foo(); + +// Ahora usamos ChildModule, que permite llamadas no calificadas. +use ChildModule; +foo(); + +// Paralelismo + +// En otros idiomas, el paralelismo generalmente se realiza con librerias complicadas +// y extrañas jerarquías de estructura de clases. +// Chapel lo tiene directamente en el idioma. + +// Podemos declarar un procedimiento principal, pero todo el código anterior +// a main todavía se ejecuta. +proc main() { + +// Una declaración de inicio hará girar el cuerpo de esa declaración en una nueva tarea. +// Una declaración de sincronización garantizará que el progreso de la tarea principal +// no avance hasta que los hijos hayan sincronizado nuevamente. + + sync { + begin { // Inicio del cuerpo de la nueva tarea. + var a = 0; + for i in 1..1000 do a += 1; + writeln("Done: ", a); + } // Fin del nuevo cuerpo de tareas + writeln("escindió una tarea!"); + } + writeln("De nuevo juntos"); + + proc printFibb(n: int) { + writeln("fibonacci(",n,") = ", fibonacci(n)); + } + +// Una declaración de cobegin girará cada declaración del cuerpo en una nueva tarea. +// Observe aquí que las impresiones de cada declaración pueden ocurrir en +// cualquier orden. + cobegin { + printFibb(20); // nueva tarea + printFibb(10); // nueva tarea + printFibb(5); // nueva tarea + { + // Este es un cuerpo de declaración anidado y, por lo tanto, es una + // declaración única para la declaración principal, ejecutada + // por una sola tarea. + writeln("esto se "); + writeln("ejecuta"); + writeln("como un todo"); + } + } + +// Un bucle coforall creará una nueva tarea para CADA iteración. +// Nuevamente vemos que las impresiones suceden en cualquier orden. +// NOTA: ¡coforall debe usarse solo para crear tareas! +// ¡Usarlo para iterar sobre una estructura es una muy mala idea! + var num_tasks = 10; // Number of tasks we want + coforall taskID in 1..#num_tasks { + writeln("Hola de tarea# ", taskID); + } + +// los bucles forall son otro bucle paralelo, pero solo crean un número +// menor de tareas, específicamente --dataParTasksPerLocale = número de tareas. + forall i in 1..100 { + write(i, ", "); + } + writeln(); + +// Aquí vemos que hay secciones que están en orden, seguidas de una sección +// que no seguiría (por ejemplo, 1, 2, 3, 7, 8, 9, 4, 5, 6,). +// Esto se debe a que cada tarea está asumiendo un fragmento del rango 1..10 +// (1..3, 4..6 o 7..9) haciendo ese fragmento en serie, pero cada tarea ocurre en paralelo. +// Sus resultados pueden depender de su máquina y configuración + +// Para los bucles forall y coforall, la ejecución de la tarea principal +// no continuará hasta que todos los hijos se sincronicen. + +// los bucles forall son particularmente útiles para la iteración paralela sobre matrices. +// Hagamos un experimento para ver qué tan rápido es un ciclo paralelo. + + use Time; // Importe el módulo Time para usar objetos de Timer + var timer: Timer; + var myBigArray: [{1..4000,1..4000}] real; // Gran matriz en la que escribiremos + +// Experimento en serie: + timer.start(); // Iniciar temporizador + for (x,y) in myBigArray.domain { // Iteración en serie + myBigArray[x,y] = (x:real) / (y:real); + } + timer.stop(); // Detener temporizador + writeln("Serial: ", timer.elapsed()); // Imprimir tiempo transcurrido + timer.clear(); // Limpia el temporizador para bucle paralelo + +// Experimento Paralelo: + timer.start(); // Iniciar temporizador + forall (x,y) in myBigArray.domain { // Iteración paralela + myBigArray[x,y] = (x:real) / (y:real); + } + timer.stop(); // Detener temporizador + writeln("Parallel: ", timer.elapsed()); // Imprimir tiempo transcurrido + timer.clear(); + +// Puede que hayas notado que (dependiendo de cuántos núcleos tengas) +// el ciclo paralelo fue más rápido que el ciclo serial. + +// La expresión de bucle estilo corchete descrita mucho antes utiliza +// implícitamente un bucle forall. + [val in myBigArray] val = 1 / val; // Operación paralela + +// Las variables atómicas, comunes a muchos idiomas, son aquellas cuyas operaciones +// ocurren sin interrupciones. Por lo tanto, varios subprocesos pueden modificar +// las variables atómicas y pueden saber que sus valores son seguros. +// Las variables atómicas de la capilla pueden ser de tipo bool, int, uint y real. + var uranium: atomic int; + uranium.write(238); // escribir atómicamente una variable + writeln(uranium.read()); // leer atómicamente una variable + +// Las operaciones atómicas se describen como funciones, por lo que puede definir +// las suyas propias. + uranium.sub(3); // restar atómicamente una variable + writeln(uranium.read()); + + var replaceWith = 239; + var was = uranium.exchange(replaceWith); + writeln("El uranio era", was, ", pero ahora es ", replaceWith); + + var isEqualTo = 235; + if uranium.compareExchange(isEqualTo, replaceWith) { + writeln("El uranio era igual a ", isEqualTo, + " pero valor reemplazado por", replaceWith); + } else { + writeln("uranio no era igual a ", isEqualTo, + " así que el valor permanece igual... sea lo que sea"); + } + + sync { + begin { // Tarea del lector + writeln("Lector: esperando que el uranio sea ", isEqualTo); + uranium.waitFor(isEqualTo); + writeln("Lector: el uranio fue configurado (por alguien) para ", isEqualTo); + } + + begin { // Tarea de escritor + writeln("Escritor: establecerá uranio en el valor ", isEqualTo, " en..."); + countdown(3); + uranium.write(isEqualTo); + } + } + +// las variables de sincronización tienen dos estados: vacío y lleno. +// Si lee una variable vacía o escribe una variable completa, +// se espera hasta que la variable esté llena o vacía nuevamente. + var someSyncVar$: sync int; // varName$ Es una convención, no una ley. + sync { + begin { // Tarea del lector + writeln("Lector: esperando leer."); + var read_sync = someSyncVar$; + writeln("Lector: el valor es ", read_sync); + } + + begin { // Tarea de escritor + writeln("Escritor: escribirá en..."); + countdown(3); + someSyncVar$ = 123; + } + } + +// las variales individuales solo se pueden escribir una vez. +// Una lectura en un solo no escrito da como resultado una espera, +// pero cuando la variable tiene un valor, puede leerse indefinidamente. + var someSingleVar$: single int; // varName$ Es una convención, no una ley. + sync { + begin { // Tarea del lector + writeln("Lector: esperando leer."); + for i in 1..5 { + var read_single = someSingleVar$; + writeln("Lector: iteración ", i,", y el valor es ", read_single); + } + } + + begin { // Tarea de escritor + writeln("Escritor: escribirá en ..."); + countdown(3); + someSingleVar$ = 5; // primero y único escrito. + } + } + +// Aquí hay un ejemplo usando atómica y una variable de sincronización +// para crear un mutex de cuenta regresiva +// (también conocido como multiplexor). + var count: atomic int; // nuestro mostrador + var lock$: sync bool; // la cerradura mutex + + count.write(2); // Solo deje dos tareas a la vez. + lock$.writeXF(true); // Establezca lock$ en completo (desbloqueado) + // Nota: el valor en realidad no importa, solo el estado + // (completo: desbloqueado / vacio: bloqueado) + // Además, writeXF() llena (F) la variable de sincronización independientemente de su estado (X) + + coforall task in 1..#5 { // Generar tareas + // Create a barrier + do { + lock$; // Leer lock$ (espera) + } while (count.read() < 1); // Sigue esperando hasta que se abra un lugar + + count.sub(1); //disminuir el contador + lock$.writeXF(true); // Establezca lock$ en completo (señal) + + // 'Trabajo' actual + writeln("Tarea #", task, " trabajando"); + sleep(2); + + count.add(1); // Incrementa el contador + lock$.writeXF(true); // Establezca lock$ en completo (señal) + } + +// Podemos definir las operaciones + * & | ^ && || min max minloc maxloc +// sobre una matriz completa usando escaneos y reducciones. +// Las reducciones aplican la operación en toda la matriz +// y dan como resultado un valor escalar. + + var listOfValues: [1..10] int = [15,57,354,36,45,15,456,8,678,2]; + var sumOfValues = + reduce listOfValues; + var maxValue = max reduce listOfValues; // 'max' da solo el valor máximo + +// maxloc proporciona el valor máximo y el índice del valor máximo. +// Nota: Tenemos que comprimir la matriz y el dominio junto con el iterador zip. + var (theMaxValue, idxOfMax) = maxloc reduce zip(listOfValues, + listOfValues.domain); + + writeln((sumOfValues, maxValue, idxOfMax, listOfValues[idxOfMax])); + +// Los escaneos aplican la operación de forma incremental y devuelven una matriz +// con los valores de la operación en ese índice a medida que avanza a través +// de la matriz desde array.domain.low hasta array.domain.high. + var runningSumOfValues = + scan listOfValues; + var maxScan = max scan listOfValues; + writeln(runningSumOfValues); + writeln(maxScan); +} // end main() +``` + +¿Para quién es este tutorial? +------------------------- + +Este tutorial es para personas que desean aprender las cuerdas de chapel sin tener +que escuchar sobre qué mezcla de fibras son las cuerdas, o cómo fueron trenzadas, +o cómo las configuraciones de trenzas difieren entre sí. No le enseñará cómo +desarrollar código increíblemente eficaz, y no es exhaustivo. +Referirse a [especificación de idioma](https://chapel-lang.org/docs/latest/language/spec.html)(en) y +a [documentación del módulo](https://chapel-lang.org/docs/latest/)(en) para más detalles. + +Ocasionalmente, vuelva aquí en el [website de Chapel](https://chapel-lang.org) +para ver si se han agregado más temas o se han creado más tutoriales. + +### Lo que le falta a este tutorial: + + * Exposición de los [módulos estándar](https://chapel-lang.org/docs/latest/modules/standard.html) + * Múltiples configuraciones regionales (sistema de memoria distribuida) + * Registros + * Iteradores paralelos + +¡Sus comentarios, preguntas y descubrimientos son importantes para los desarrolladores! +----------------------------------------------------------------------- + +El lenguaje Chapel todavía está en desarrollo activo, por lo que +ocasionalmente hay problemas con el rendimiento y +las características del lenguaje. + +Cuanta más información brinde al equipo de desarrollo de Chapel +sobre los problemas que encuentre o las características que le gustaría ver, +mejor será el lenguaje. + + +Hay varias formas de interactuar con los desarrolladores: ++ [Chat de Gitter](https://gitter.im/chapel-lang/chapel) ++ [lista de emails de Sourceforge](https://sourceforge.net/p/chapel/mailman) + +Si está realmente interesado en el desarrollo del compilador o en contribuir al proyecto, +[consulte el repositorio maestro de GitHub](https://github.com/chapel-lang/chapel). +Está bajo el [La licencia Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Instalar el compilador +----------------------- + +[La documentación oficial de Chapel detalla cómo descargar y compilar el compilador de Chapel.](https://chapel-lang.org/docs/usingchapel/QUICKSTART.html) + +Chapel se puede construir e instalar en su máquina promedio 'nix (y cygwin). +[Descargue la última versión de lanzamiento](https://github.com/chapel-lang/chapel/releases/) +y es tan fácil como + + 1. `tar -xvf chapel-<VERSION>.tar.gz` + 2. `cd chapel-<VERSION>` + 3. `source util/setchplenv.bash # or .sh or .csh or .fish` + 4. `make` + 5. `make check # optional` + +You will need to `source util/setchplenv.EXT` from within the Chapel directory +(`$CHPL_HOME`) every time your terminal starts so it's suggested that you drop +that command in a script that will get executed on startup (like .bashrc). + +Necesitará `source util/setchplenv.EXT` desde el directorio de Chapel (`$CHPL_HOME`) +cada vez que se inicie su terminal, por lo que se sugiere que suelte ese comando +en un script que se ejecutará al inicio (como .bashrc). + +Chapel se instala fácilmente con Brew para OS X + + 1. `brew update` + 2. `brew install chapel` + +Compilando Código +-------------- + +Construye como otros compiladores: + +`chpl myFile.chpl -o myExe` + +Argumentos notables: + + * `--fast`: habilita varias optimizaciones y deshabilita las comprobaciones + de los límites de la matriz Solo debe habilitarse cuando la aplicación es estable. + * `--set <Nombre del Symbolo>=<Valor>`: establece el param de configuracion + `<Nombre del Symbolo>` a `<Valor>`en tiempo de compilación. + * `--main-module <Nombre del módulo>`: use el procedimiento main() que se encuentra en el módulo + `<Nombre del módulo>` como principal del ejecutable. + * `--module-dir <Directorio>`: incluye `<Directorio>` en la ruta de búsqueda del módulo. diff --git a/es-es/clojure-es.html.markdown b/es-es/clojure-es.html.markdown index 150d0bb2..9f25425c 100644 --- a/es-es/clojure-es.html.markdown +++ b/es-es/clojure-es.html.markdown @@ -9,28 +9,30 @@ translators: lang: es-es --- -Clojure es un lenguaje de la familia Lisp desarrollado sobre la Máquina Virtual -de Java. Tiene un énfasis mayor en la [programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) pura -que Common Lisp, pero incluyendo la posibilidad de usar [SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular +Clojure es un lenguaje de la familia Lisp desarrollado para la Máquina Virtual +de Java. Tiene un énfasis mayor en la +[programación funcional](https://es.wikipedia.org/wiki/Programación_funcional) +pura que Common Lisp, pero incluye varias utilidades de +[SMT](https://es.wikipedia.org/wiki/Memoria_transacional) para manipular el estado según se presente. -Esta combinación le permite gestionar la concurrencia de manera muy sencilla -y a menudo automáticamente. +Esta combinación le permite gestionar el procesamiento concurrente de manera +muy sencilla, y a menudo automáticamente. -(Necesitas la versión de Clojure 1.2 o posterior) +(Necesitas la versión de Clojure 1.2 o reciente) ```clojure -; Los comentatios comienzan con punto y coma. +; Los comentarios comienzan con punto y coma. -; Clojure se escribe mediante "forms" (patrones), los cuales son -; listas de objectos entre paréntesis, separados por espacios en blanco. +; Clojure se escribe mediante patrones ("forms"), los cuales son +; listas de cosas entre paréntesis, separados por espacios en blanco. -; El "reader" (lector) de Clojure asume que el primer objeto es una -; función o una macro que se va a llamar, y que el resto son argumentos. +; El lector ("reader") de Clojure asume que la primera cosa es una +; función o una macro a llamar, y el resto son argumentos. -; El primer form en un archivo debe ser ns, para establecer el namespace (espacio de -; nombres) +; La primera llamada en un archivo debe ser ns, para establecer el espacio de +; nombres ("namespace") (ns learnclojure) ; Algunos ejemplos básicos: @@ -51,69 +53,70 @@ y a menudo automáticamente. ; También es necesaria la negación para las operaciones lógicas (not true) ; => false -; Cuando se anidan Los patrones, estos funcionan de la manera esperada +; Los patrones anidados funcionan como esperas (+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 ; Tipos ;;;;;;;;;;;;; -; Clojure usa los tipos de objetos de Java para booleanos, strings (cadenas de -; caracteres) y números. -; Usa class para saber de qué tipo es. -(class 1); Los enteros son java.lang.Long por defecto -(class 1.); Los numeros en coma flotante son java.lang.Double -(class ""); Los strings van entre comillas dobles, y son -; son java.lang.String -(class false); Los Booleanos son java.lang.Boolean +; Clojure usa los tipos de objetos de Java para booleanos, cadenas de +; caracteres ("strings") y números. +; Usa class para inspeccionarlos. +(class 1); Los números enteros literales son java.lang.Long por defecto +(class 1.); Los números en coma flotante literales son java.lang.Double +(class ""); Los strings siempre van entre comillas dobles, y son + ; java.lang.String +(class false); Los booleanos son java.lang.Boolean (class nil); El valor "null" se escribe nil -; Si quieres crear una lista de datos, precedela con una comilla -; simple para evitar su evaluación +; Si quieres crear una lista literal de datos, usa ' para evitar su evaluación '(+ 1 2) ; => (+ 1 2) -; (que es una abreviatura de (quote (+ 1 2)) ) +; (que es una abreviatura de (quote (+ 1 2))) -; Puedes evaluar una lista precedida por comilla con eval +; Puedes evaluar una lista precedida por una comilla con eval (eval '(+ 1 2)) ; => 3 ; Colecciones & Secuencias ;;;;;;;;;;;;;;;;;;; -; Las Listas están basadas en las listas enlazadas, mientras que los Vectores en -; arrays. +; Las Listas están basadas en listas enlazadas, mientras que los Vectores en +; arreglos. ; ¡Los Vectores y las Listas también son clases de Java! (class [1 2 3]); => clojure.lang.PersistentVector (class '(1 2 3)); => clojure.lang.PersistentList -; Una lista podría ser escrita como (1 2 3), pero debemos ponerle una -; comilla simple delante para evitar que el reader piense que es una función. +; Una lista podría ser escrita como (1 2 3), pero debemos precederle una +; comilla para evitar que el lector ("reader") piense que es una función. ; Además, (list 1 2 3) es lo mismo que '(1 2 3) -; Las "Colecciones" son solo grupos de datos -; Tanto las listas como los vectores son colecciones: +; Las Colecciones ("collections") son solo grupos de datos +; Tanto las Listas como los Vectores son colecciones: (coll? '(1 2 3)) ; => true (coll? [1 2 3]) ; => true -; Las "Secuencias" (seqs) son descripciones abstractas de listas de datos. -; Solo las listas son seqs. +; Las Secuencias ("seqs") son descripciones abstractas de listas de datos. +; Solo las listas son secuencias ("seqs"). (seq? '(1 2 3)) ; => true (seq? [1 2 3]) ; => false -; Una seq solo necesita proporcionar una entrada cuando es accedida. -; Así que, las seqs pueden ser perezosas -- pueden establecer series infinitas: +; Una secuencia solo necesita proporcionar uno de sus elementos cuando es +; accedido. +; Así que, las secuencias pueden ser perezosas -- pueden definir series +; infinitas: (range 4) ; => (0 1 2 3) (range) ; => (0 1 2 3 4 ...) (una serie infinita) (take 4 (range)) ; (0 1 2 3) -; Usa cons para agregar un elemento al inicio de una lista o vector +; Usa cons para agregar un elemento al inicio de una Lista o Vector (cons 4 [1 2 3]) ; => (4 1 2 3) (cons 4 '(1 2 3)) ; => (4 1 2 3) ; conj agregará un elemento a una colección en la forma más eficiente. -; Para listas, se añade al inicio. Para vectores, al final. +; Para Listas, se añade al inicio. Para vectores, al final. (conj [1 2 3] 4) ; => [1 2 3 4] (conj '(1 2 3) 4) ; => (4 1 2 3) -; Usa concat para concatenar listas o vectores +; Usa concat para concatenar Listas o Vectores (concat [1 2] '(3 4)) ; => (1 2 3 4) ; Usa filter y map para actuar sobre colecciones @@ -125,7 +128,7 @@ y a menudo automáticamente. ; = (+ (+ (+ 1 2) 3) 4) ; => 10 -; reduce puede tener un argumento indicando su valor inicial. +; reduce puede tomar un argumento como su valor inicial también (reduce conj [] '(3 2 1)) ; = (conj (conj (conj [] 3) 2) 1) ; => [3 2 1] @@ -137,43 +140,42 @@ y a menudo automáticamente. ; su última expresión (fn [] "Hello World") ; => fn -; (Necesitas rodearlo con paréntesis para invocarla) +; (Necesitas rodearlo con paréntesis para llamarla) ((fn [] "Hello World")) ; => "Hello World" -; Puedes crear una var (variable) mediante def +; Puedes definir una variable ("var") mediante def (def x 1) x ; => 1 -; Asigna una función a una var +; Asignar una función a una variable ("var") (def hello-world (fn [] "Hello World")) (hello-world) ; => "Hello World" -; Puedes defn como atajo para lo anterior +; Puedes usar defn como atajo para lo anterior (defn hello-world [] "Hello World") -; El [] es el vector de argumentos de la función. +; El [] es el Vector de argumentos de la función. (defn hello [name] (str "Hello " name)) (hello "Steve") ; => "Hello Steve" -; Otra abreviatura para crear funciones es: +; Puedes usar esta abreviatura para definir funciones: (def hello2 #(str "Hello " %1)) (hello2 "Fanny") ; => "Hello Fanny" -; Puedes tener funciones multi-variadic: funciones con un numero variable de -; argumentos +; Puedes tener funciones multi-variables ("multi-variadic") también (defn hello3 ([] "Hello World") ([name] (str "Hello " name))) (hello3 "Jake") ; => "Hello Jake" (hello3) ; => "Hello World" -; Las funciones pueden usar argumentos extras dentro de un seq utilizable en la función +; Las funciones pueden empaquetar argumentos extras en una secuencia para ti (defn count-args [& args] (str "You passed " (count args) " args: " args)) (count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" -; Y puedes mezclarlos con el resto de argumentos declarados de la función. +; Puedes combinar los argumentos regulares y los empaquetados (defn hello-count [name & args] (str "Hello " name ", you passed " (count args) " extra args")) (hello-count "Finn" 1 2 3) @@ -183,17 +185,18 @@ x ; => 1 ; Mapas ;;;;;;;;;; -; Mapas de Hash y mapas de arrays comparten una misma interfaz. Los mapas de Hash -; tienen búsquedas más rápidas pero no mantienen el orden de las claves. +; Los Mapas de Hash ("HashMap") y Mapas de Arreglo ("ArrayMap") comparten una +; interfaz. Los Mapas de Hash tienen búsquedas más rápidas pero no mantienen el +; orden de las llaves. (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap (class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap -; Los mapas de arrays se convertidos en mapas de Hash en la mayoría de -; operaciones si crecen mucho, por lo que no debes preocuparte. +; Los Mapas de Arreglo se convierten automáticamente en Mapas de Hash en la +; mayoría de operaciones si crecen mucho, por lo que no debes preocuparte. -; Los mapas pueden usar cualquier tipo para sus claves, pero generalmente las -; keywords (palabras clave) son lo habitual. -; Las keywords son parecidas a cadenas de caracteres con algunas ventajas de eficiencia +; Los Mapas pueden usar cualquier tipo para sus llaves, pero generalmente las +; Claves ("keywords") son lo habitual. +; Las Claves son como strings con algunas ventajas de eficiencia (class :a) ; => clojure.lang.Keyword (def stringmap {"a" 1, "b" 2, "c" 3}) @@ -205,28 +208,28 @@ keymap ; => {:a 1, :c 3, :b 2} ; Por cierto, las comas son equivalentes a espacios en blanco y no hacen ; nada. -; Recupera un valor de un mapa tratandolo como una función +; Recupera un valor de un Mapa tratándola como una función (stringmap "a") ; => 1 (keymap :a) ; => 1 -; ¡Las keywords pueden ser usadas para recuperar su valor del mapa, también! +; ¡Las Claves pueden ser usadas para recuperar su valor del mapa, también! (:b keymap) ; => 2 ; No lo intentes con strings. ;("a" stringmap) ; => Exception: java.lang.String cannot be cast to clojure.lang.IFn -; Si preguntamos por una clave que no existe nos devuelve nil +; Recuperando una clave no existente nos devuelve nil (stringmap "d") ; => nil -; Usa assoc para añadir nuevas claves a los mapas de Hash +; Usa assoc para añadir nuevas claves a los Mapas de Hash (def newkeymap (assoc keymap :d 4)) newkeymap ; => {:a 1, :b 2, :c 3, :d 4} ; Pero recuerda, ¡los tipos de Clojure son inmutables! keymap ; => {:a 1, :b 2, :c 3} -; Usa dissoc para eliminar llaves +; Usa dissoc para eliminar claves (dissoc keymap :a :b) ; => {:c 3} ; Conjuntos @@ -238,50 +241,86 @@ keymap ; => {:a 1, :b 2, :c 3} ; Añade un elemento con conj (conj #{1 2 3} 4) ; => #{1 2 3 4} -; Elimina elementos con disj +; Elimina uno con disj (disj #{1 2 3} 1) ; => #{2 3} -; Comprueba su existencia usando el conjunto como una función: +; Comprueba su existencia usando al Conjunto como una función: (#{1 2 3} 1) ; => 1 (#{1 2 3} 4) ; => nil -; Hay más funciones en el namespace clojure.sets +; Hay más funciones en el espacio de nombres clojure.sets ; Patrones útiles ;;;;;;;;;;;;;;;;; -; Las construcciones lógicas en clojure son macros, y presentan el mismo aspecto -; que el resto de forms. +; Los operadores lógicos en clojure son solo macros, y presentan el mismo +; aspecto que el resto de patrones. (if false "a" "b") ; => "b" (if false "a") ; => nil -; Usa let para crear un binding (asociación) temporal +; Usa let para definir ("binding") una variable temporal (let [a 1 b 2] (> a b)) ; => false -; Agrupa expresiones mediante do +; Agrupa sentencias mediante do (do (print "Hello") "World") ; => "World" (prints "Hello") -; Las funciones tienen implicita la llamada a do +; Las funciones tienen un do implícito (defn print-and-say-hello [name] (print "Saying hello to " name) (str "Hello " name)) (print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") -; Y el let también +; Y let también (let [name "Urkel"] (print "Saying hello to " name) (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") +; Usa las macros de tubería ("threading", "arrow", "pipeline" o "chain") +; (-> y ->>) para expresar la transformación de datos de una manera más clara. + +; La macro Tubería-primero ("Thread-first") (->) inserta en cada patrón el +; resultado de los previos, como el primer argumento (segundo elemento) +(-> + {:a 1 :b 2} + (assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3) + (dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b) + +; Esta expresión podría ser escrita como: +; (dissoc (assoc {:a 1 :b 2} :c 3) :b) +; y evalua a {:a 1 :c 3} + +; La macro Tubería-último ("Thread-last") hace lo mismo, pero inserta el +; resultado de cada línea al *final* de cada patrón. Esto es útil para las +; operaciones de colecciones en particular: +(->> + (range 10) + (map inc) ;=> (map inc (range 10) + (filter odd?) ;=> (filter odd? (map inc (range 10)) + (into [])) ;=> (into [] (filter odd? (map inc (range 10))) + ; Result: [1 3 5 7 9] + +; Cuando estés en una situación donde quieras tener más libertad en donde +; poner el resultado de transformaciones previas de datos en una expresión, +; puedes usar la macro as->. Con ella, puedes asignar un nombre especifico +; a la salida de la transformaciones y usarlo como identificador en tus +; expresiones encadenadas ("chain"). + +(as-> [1 2 3] input + (map inc input);=> You can use last transform's output at the last position + (nth input 2) ;=> and at the second position, in the same expression + (conj [4 5 6] input [8 9 10])) ;=> or in the middle ! + + ; Módulos ;;;;;;;;;;;;;;; ; Usa use para obtener todas las funciones del módulo (use 'clojure.set) -; Ahora podemos usar más operaciones de conjuntos +; Ahora podemos usar más operaciones de Conjuntos (intersection #{1 2 3} #{2 3 4}) ; => #{2 3} (difference #{1 2 3} #{2 3 4}) ; => #{1} @@ -291,19 +330,18 @@ keymap ; => {:a 1, :b 2, :c 3} ; Usa require para importar un módulo (require 'clojure.string) -; Usa / para llamar a las funciones de un módulo +; Usa / para llamar las funciones de un módulo ; Aquí, el módulo es clojure.string y la función es blank? (clojure.string/blank? "") ; => true -; Puedes asignarle una abreviatura a un modulo al importarlo +; Puedes asignarle una sobrenombre a un modulo al importarlo (require '[clojure.string :as str]) (str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." -; (#"" es una expresión regular) +; (#"" es una expresión regular literal) -; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombre +; Puedes usar require (y use, pero no lo hagas) desde un espacio de nombres ; usando :require, -; No necesitas preceder con comilla simple tus módulos si lo haces de esta -; forma. +; No necesitas preceder con comilla tus módulos si lo haces de esta manera. (ns test (:require [clojure.string :as str] @@ -312,8 +350,8 @@ keymap ; => {:a 1, :b 2, :c 3} ; Java ;;;;;;;;;;;;;;;;; -; Java tiene una enorme librería estándar, por lo que resulta util -; aprender como interactuar con ella. +; Java tiene una enorme y útil librería estándar, por lo que querrás +; aprender como hacer uso de ella. ; Usa import para cargar un módulo de java (import java.util.Date) @@ -326,14 +364,15 @@ keymap ; => {:a 1, :b 2, :c 3} ; Usa el nombre de la clase con un "." al final para crear una nueva instancia (Date.) ; <un objeto Date> -; Usa "." para llamar a métodos o usa el atajo ".método" +; Usa "." para llamar métodos. O, usa el atajo ".método" (. (Date.) getTime) ; <un timestamp> -(.getTime (Date.)) ; exactamente la misma cosa +(.getTime (Date.)) ; exactamente lo mismo. ; Usa / para llamar métodos estáticos. (System/currentTimeMillis) ; <un timestamp> (System siempre está presente) -; Usa doto para hacer frente al uso de clases (mutables) más tolerable +; Usa doto para lidiar con el uso de clases (mutables) de una manera más +; tolerable (import java.util.Calendar) (doto (Calendar/getInstance) (.set 2000 1 1 0 0 0) @@ -342,9 +381,9 @@ keymap ; => {:a 1, :b 2, :c 3} ; STM ;;;;;;;;;;;;;;;;; -; Software Transactional Memory es un mecanismo que usa clojure para gestionar -; el estado persistente. Hay unas cuantas construcciones en clojure que -; hacen uso de este mecanismo. +; La Memoria Transaccional ("Software Transactional Memory" / "STM") es un +; mecanismo que usa clojure para gestionar la persistecia de estado. Hay unas +; cuantas construcciones en clojure que hacen uso de él. ; Un atom es el más sencillo. Se le da un valor inicial (def my-atom (atom {})) @@ -352,14 +391,16 @@ keymap ; => {:a 1, :b 2, :c 3} ; Actualiza un atom con swap! ; swap! toma una función y la llama con el valor actual del atom ; como su primer argumento, y cualquier argumento restante como el segundo -(swap! my-atom assoc :a 1) ; Establece my-atom al resultado de (assoc {} :a 1) -(swap! my-atom assoc :b 2) ; Establece my-atom al resultado de (assoc {:a 1} :b 2) +(swap! my-atom assoc :a 1) ; Establece my-atom al resultado + ; de (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Establece my-atom al resultado + ; de (assoc {:a 1} :b 2) -; Usa '@' para no referenciar al atom sino para obtener su valor +; Usa '@' para no referenciar al atom y obtener su valor my-atom ;=> Atom<#...> (Regresa el objeto Atom) @my-atom ; => {:a 1 :b 2} -; Un sencillo contador usando un atom sería +; Aquí está un sencillo contador usando un atom (def counter (atom 0)) (defn inc-counter [] (swap! counter inc)) @@ -372,22 +413,25 @@ my-atom ;=> Atom<#...> (Regresa el objeto Atom) @counter ; => 5 -; Otros forms que utilizan STM son refs y agents. +; Otras construcciones de STM son refs y agents. ; Refs: http://clojure.org/refs ; Agents: http://clojure.org/agents +``` + ### Lectura adicional -Ésto queda lejos de ser exhaustivo, pero espero que sea suficiente para que puedas empezar tu camino. +Ésto queda lejos de ser exhaustivo, pero ojalá que sea suficiente para que +puedas empezar tu camino. Clojure.org tiene muchos artículos: -[http://clojure.org/](http://clojure.org/) +[http://clojure.org](http://clojure.org) Clojuredocs.org contiene documentación con ejemplos para la mayoría de funciones principales (pertenecientes al core): -[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) +[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/) +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) diff --git a/es-es/css-es.html b/es-es/css-es.html deleted file mode 100644 index 506a9467..00000000 --- a/es-es/css-es.html +++ /dev/null @@ -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) - - diff --git a/es-es/css-es.html.markdown b/es-es/css-es.html.markdown index 6395f5fd..506a9467 100644 --- a/es-es/css-es.html.markdown +++ b/es-es/css-es.html.markdown @@ -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 - ####################*/ - -/* 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. + ## SELECTORS + #################### */ -¡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; } + +/* 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; } + -/* O incluso contiene un valor ('lo' en este caso) */ -[attr~='lo'] { 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'] { } -/*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'] { } +/* You can select an element which is a child of another element */ +div.some-parent > .class-name { } -/* También puedes seleccionar un elemento HTML basándote en sus padres*/ +/* 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 { } -/* Un elemento que es hijo directo de otro elemento (Seleccionado de la forma que -vimos anteriormente) */ +/* Warning: the same selector without a space has another meaning. + Can you guess what? */ +div.some-parent.class-name { } -div.un-padre > .nombre-clase {} +/* You may also select an element based on its adjacent sibling */ +.i-am-just-before + .this-element { } -/* 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 any sibling preceding it */ +.i-am-any-element-before ~ .this-element { } -/* advertencia: el mismo selector sin espacio tiene otro significado. ¿Puedes -identificar la diferencia?*/ +/* There are some selectors called pseudo classes that can be used to select an + element only when it is in a particular state */ -/* También puedes seleccionar un elemento basado en su hermano inmediato previo*/ -.yo-estoy-antes + .este-elemento { } +/* for example, when the cursor hovers over an element */ +selector:hover { } -/*o cualquier hermano previo */ -.yo-soy-cualquiera-antes ~ .estes-elemento {} +/* or a link has been visited */ +selector:visited { } -/* 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) */ +/* or hasn't been visited */ +selected:link { } -/* Por ejemplo, para cuando pasas el mouse por encima de un elemento */ -:hover {} +/* or an element is in focus */ +selected:focus { } -/* o una liga visitada*/ -:visited {} +/* any element that is the first child of its parent */ +selector:first-child {} -/* o una liga no visitada aún*/ -:link {} +/* any element that is the last child of its parent */ +selector:last-child {} -/* o un elemento de un formulario que esté seleccionado */ -:focus {} +/* 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 */ + + /* 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; - 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*/ + /* 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 + +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) . -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: +This process is called cascading, hence the name Cascading Style Sheets. -Dado el siguiente CSS: +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 {} +/* D */ +p { } -/*E*/ -p { propiedad: valor !important; } +/* E */ +p { property: value !important; } +``` +and the following markup: + +```html +<p style='/*F*/ property:value;' class='class1 class2' attr='value'> ``` -Y el siguiente HTML: +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; +} -```xml -<p style='/*F*/ propiedad:valor;' class='clase1 clase2' attr='valor'> -</p> +/* 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; + } +} ``` -El orden respetado es el siguiente: -Recuerda, la preferencia es por cada **property**, no para el bloque completo. +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-`. -* `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`. +The `resolution` feature is not supported by older devices, instead use `device-pixel-ratio`. -## Compatibilidad +Many smartphones and tablets will attempt to render the page as if it were on a desktop unless you provide a `viewport` meta-tag. -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. +```html +<head> + <meta name="viewport" content="width=device-width; initial-scale=1.0"> +</head> +``` + +## Compatibility -[QuirksMode CSS](http://www.quirksmode.org/css/) es una excelente referencia para esto. +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. -## Recursos +## Resources -* 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/). +* [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) -## Otras lecturas +## 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/). +* [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) + diff --git a/es-es/docker-es.html.markdown b/es-es/docker-es.html.markdown new file mode 100644 index 00000000..81e3cefe --- /dev/null +++ b/es-es/docker-es.html.markdown @@ -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 +``` diff --git a/es-es/elixir-es.html.markdown b/es-es/elixir-es.html.markdown index 885165a6..37acf6ad 100644 --- a/es-es/elixir-es.html.markdown +++ b/es-es/elixir-es.html.markdown @@ -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`, diff --git a/es-es/factor-es.html.markdown b/es-es/factor-es.html.markdown new file mode 100644 index 00000000..67c60de7 --- /dev/null +++ b/es-es/factor-es.html.markdown @@ -0,0 +1,200 @@ +--- +language: factor +contributors: + - ["hyphz", "http://github.com/hyphz/"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +filename: learnfactor-es.factor + +lang: es-es +--- +Factor es un lenguaje moderno basado en la pila, basado en Forth, creado por +Slava Pestov. + +El código de este archivo puede escribirse en Factor, pero no importa +directamente porque el encabezado del vocabulario de importación haria que el +comienzo fuera totalmente confuso. + +```factor +! Esto es un comentario + +! Como Forth, toda la programación se realiza mediante la manipulación de la +! pila. +! La intruducción de un valor literal lo coloca en la pila +5 2 3 56 76 23 65 ! No hay salida pero la pila se imprime en modo interactivo + +! Esos números se agregan a la pila de izquierda a derecha +! .s imprime la pila de forma no destructiva. +.s ! 5 2 3 56 76 23 65 + +! La aritmética funciona manipulando datos en la pila. +5 4 + ! Sem saída + +! `.` muestra el resultado superior de la pila y lo imprime. +. ! 9 + +! Más ejemplos de aritmética: +6 7 * . ! 42 +1360 23 - . ! 1337 +12 12 / . ! 1 +13 2 mod . ! 1 + +99 neg . ! -99 +-99 abs . ! 99 +52 23 max . ! 52 +52 23 min . ! 23 + +! Se proporcionan varias palabras para manipular la pila, conocidas +colectivamente como palabras codificadas. + +3 dup - ! duplica el primer item (1st ahora igual a 2nd): 3 - 3 +2 5 swap / ! intercambia el primero con el segundo elemento: 5 / 2 +4 0 drop 2 / ! elimina el primer item (no imprime en pantalla): 4 / 2 +1 2 3 nip .s ! elimina el segundo item (semejante a drop): 1 3 +1 2 clear .s ! acaba con toda la pila +1 2 3 4 over .s ! duplica el segundo item superior: 1 2 3 4 3 +1 2 3 4 2 pick .s ! duplica el tercer item superior: 1 2 3 4 2 3 + +! Creando Palabras +! La palabra `:` factoriza los conjuntos en modo de compilación hasta que vea +la palabra`;`. +: square ( n -- n ) dup * ; ! Sin salida +5 square . ! 25 + +! Podemos ver lo que las palabra hacen también. +! \ suprime la evaluación de una palabra y coloca su identificador en la pila. +\ square see ! : square ( n -- n ) dup * ; + +! Después del nombre de la palabra para crear, la declaración entre paréntesis +da efecto a la pila. +! Podemos usar los nombres que queramos dentro de la declaración: +: weirdsquare ( camel -- llama ) dup * ; + +! Mientras su recuento coincida con el efecto de pila de palabras: +: doubledup ( a -- b ) dup dup ; ! Error: Stack effect declaration is wrong +: doubledup ( a -- a a a ) dup dup ; ! Ok +: weirddoubledup ( i -- am a fish ) dup dup ; ! Além disso Ok + +! Donde Factor difiere de Forth es en el uso de las citaciones. +! Una citacion es un bloque de código que se coloca en la pila como un valor. +! [ inicia el modo de citación; ] termina. +[ 2 + ] ! La cita que suma dos queda en la pila +4 swap call . ! 6 + +! Y así, palabras de orden superior. TONOS de palabras de orden superior +2 3 [ 2 + ] dip .s ! Tomar valor de la parte superior de la pilar, cotizar, retroceder: 4 3 +3 4 [ + ] keep .s ! Copiar el valor desde la parte superior de la pila, cotizar, enviar copia: 7 4 +1 [ 2 + ] [ 3 + ] bi .s ! Ejecute cada cotización en el valor superior, empuje amabos resultados: 3 4 +4 3 1 [ + ] [ + ] bi .s ! Las citas en un bi pueden extraer valores más profundos de la pila: 4 5 ( 1+3 1+4 ) +1 2 [ 2 + ] bi@ .s ! Citar en primer y segundo valor +2 [ + ] curry ! Inyecta el valor dado al comienzo de la pila: [ 2 + ] se deja en la pila + +! Condicionales +! Cualquier valor es verdadero, excepto el valor interno f. +! no existe un valor interno, pero su uso no es esencial. +! Los condicionales son palabras de orden superior, como con los combinadores +! anteriores + +5 [ "Five is true" . ] when ! Cinco es verdadero +0 [ "Zero is true" . ] when ! Cero es verdadero +f [ "F is true" . ] when ! Sin salida +f [ "F is false" . ] unless ! F es falso +2 [ "Two is true" . ] [ "Two is false" . ] if ! Two es verdadero + +! Por defecto, los condicionales consumen el valor bajo prueba, pero las +! variantes con un +! asterisco se dejan solo si es verdad: + +5 [ . ] when* ! 5 +f [ . ] when* ! Sin salida, pila vacía, se consume porque f es falso + + +! Lazos +! Lo has adivinado... estas son palabras de orden superior también. + +5 [ . ] each-integer ! 0 1 2 3 4 +4 3 2 1 0 5 [ + . ] each-integer ! 0 2 4 6 8 +5 [ "Hello" . ] times ! Hello Hello Hello Hello Hello + +! Here's a list: +{ 2 4 6 8 } ! Goes on the stack as one item + +! Aqui está uma lista: +{ 2 4 6 8 } [ 1 + . ] each ! Exibe 3 5 7 9 +{ 2 4 6 8 } [ 1 + ] map ! Salida { 3 5 7 9 } de la pila + +! Reduzir laços ou criar listas: +{ 1 2 3 4 5 } [ 2 mod 0 = ] filter ! Solo mantenga miembros de la lista para los cuales la cita es verdadera: { 2 4 } +{ 2 4 6 8 } 0 [ + ] reduce . ! Como "fold" en lenguajes funcinales: exibe 20 (0+2+4+6+8) +{ 2 4 6 8 } 0 [ + ] accumulate . . ! Como reducir, pero mantiene los valores intermedios en una lista: { 0 2 6 12 } así que 20 +1 5 [ 2 * dup ] replicate . ! Repite la cita 5 veces y recoge los resultados en una lista: { 2 4 8 16 32 } +1 [ dup 100 < ] [ 2 * dup ] produce ! Repite la segunda cita hasta que la primera devuelva falso y recopile los resultados: { 2 4 8 16 32 64 128 } + +! Si todo lo demás falla, un propósito general a repetir. +1 [ dup 10 < ] [ "Hello" . 1 + ] while ! Escribe "Hello" 10 veces + ! Sí, es dificil de leer + ! Para eso están los bucles variantes + +! Variables +! Normalmente, se espera que los programas de Factor mantengan todos los datos +! en la pila. +! El uso de variables con nombre hace que la refactorización sea más difícil +! (y se llama Factor por una razón) +! Variables globales, si las necesitas: + +SYMBOL: name ! Crea un nombre como palabra de identificación +"Bob" name set-global ! Sin salída +name get-global . ! "Bob" + +! Las variables locales nombradas se consideran una extensión, pero están +! disponibles +! En una cita .. +[| m n ! La cita captura los dos valores principales de la pila en m y n + | m n + ] ! Leerlos + +! Ou em uma palavra.. +:: lword ( -- ) ! Tenga en cuenta los dos puntos dobles para invocar la extensión de variable léxica + 2 :> c ! Declara la variable inmutable c para contener 2 + c . ; ! Imprimirlo + +! En una palabra declarada de esta manera, el lado de entrada de la declaración +! de la pila +! se vuelve significativo y proporciona los valores de las variables en las que +! se capturan los valores de pila +:: double ( a -- result ) a 2 * ; + +! Las variables se declaran mutables al terminar su nombre con su signo de +! exclamación +:: mword2 ( a! -- x y ) ! Capture la parte superior de la pila en la variable mutable a + a ! Empujar a + a 2 * a! ! Multiplique por 2 y almacenar el resultado en a + a ; ! Empujar el nuevo valor de a +5 mword2 ! Pila: 5 10 + +! Listas y Secuencias +! Vimos arriba cómo empujar una lista a la pila + +0 { 1 2 3 4 } nth ! Acceder a un miembro específico de una lista: 1 +10 { 1 2 3 4 } nth ! Error: índice de secuencia fuera de los límites +1 { 1 2 3 4 } ?nth ! Lo mismo que nth si el índice está dentro de los límites: 2 +10 { 1 2 3 4 } ?nth ! Sin errores si está fuera de los límites: f + +{ "at" "the" "beginning" } "Append" prefix ! { "Append" "at" "the" "beginning" } +{ "Append" "at" "the" } "end" suffix ! { "Append" "at" "the" "end" } +"in" 1 { "Insert" "the" "middle" } insert-nth ! { "Insert" "in" "the" "middle" } +"Concat" "enate" append ! "Concatenate" - strings are sequences too +"Concatenate" "Reverse " prepend ! "Reverse Concatenate" +{ "Concatenate " "seq " "of " "seqs" } concat ! "Concatenate seq of seqs" +{ "Connect" "subseqs" "with" "separators" } " " join ! "Connect subseqs with separators" + +! Y si desea obtener meta, las citas son secuencias y se pueden desmontar +0 [ 2 + ] nth ! 2 +1 [ 2 + ] nth ! + +[ 2 + ] \ - suffix ! Quotation [ 2 + - ] + + +``` + +##Listo para más? + +* [Documentación de Factor](http://docs.factorcode.org/content/article-help.home.html) diff --git a/es-es/forth-es.html.markdown b/es-es/forth-es.html.markdown index edc5d38c..61123151 100644 --- a/es-es/forth-es.html.markdown +++ b/es-es/forth-es.html.markdown @@ -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. ) diff --git a/es-es/git-es.html.markdown b/es-es/git-es.html.markdown index 749365d1..c93584d8 100644 --- a/es-es/git-es.html.markdown +++ b/es-es/git-es.html.markdown @@ -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) diff --git a/es-es/go-es.html.markdown b/es-es/go-es.html.markdown index 78267695..17bf4a22 100644 --- a/es-es/go-es.html.markdown +++ b/es-es/go-es.html.markdown @@ -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 diff --git a/es-es/hq9+-es.html.markdown b/es-es/hq9+-es.html.markdown new file mode 100644 index 00000000..0e1a36e1 --- /dev/null +++ b/es-es/hq9+-es.html.markdown @@ -0,0 +1,44 @@ +--- +language: HQ9+ +filename: hq9+-es.html +contributors: + - ["Alexey Nazaroff", "https://github.com/rogaven"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es +--- + +HQ9+ es una parodia de los lenguajes de programación esotéricos y fue creado +por Cliff Biffle. +El lenguaje tiene solo cuatro comandos y no está completo de Turing. + +``` +Solo hay cuatro comandos, representados por los siguientes cuatro caracteres +H: imprime "Hello, world!" +Q: imprime el código fuente del programa (ein Quine) +9: imprime la letra de "99 Bottles of Beer" ++: aumenta el acumulador en uno (el valod del acumulador no se puede leer) +Cualquier otro caracter es ignorado. + +Ok. Escribamos el programa: + HQ + +Resultado: + Hello world! + HQ + +HQ9+ es muy simple, pero te permite hacer cosas en él. Otros lenguajes son muy +difíciles.Por ejemplo, el siguiente programa imprime tres copias de sí mismo en +la pantalla: + QQQ +Esto imprime: + QQQ + QQQ + QQQ +``` + +Y esto es todo. Hay muchos intérpretes para HQ9+. +A continuación encontrarás uno de ellos. + ++ [One of online interpreters](https://almnet.de/esolang/hq9plus.php) ++ [HQ9+ official website](http://cliffle.com/esoterica/hq9plus.html) diff --git a/es-es/hy-es.html.markdown b/es-es/hy-es.html.markdown new file mode 100644 index 00000000..bfad3b6e --- /dev/null +++ b/es-es/hy-es.html.markdown @@ -0,0 +1,176 @@ +--- +language: hy +filename: learnhy-es.hy +contributors: + - ["Abhishek L", "http://twitter.com/abhishekl"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es +--- + +Hy es un lenguaje de Lisp escrito sobre Python. Esto es posible convirtiendo +código Hy en un árbol abstracto de Python (ast). Por lo que, esto permite a +Hy llamar a código Pyhton nativo y viceversa. + +Este tutorial funciona para hy >= 0.9.12 + +```clojure +;; Esto es una intrucción muy básica a Hy, como la del siguiente enlace +;; http://try-hy.appspot.com +;; +; Comentarios usando punto y coma, como en otros LISPS + +;; Nociones básicas de expresiones +; Los programas List están hechos de expresiones simbólicas como la siguiente +(some-function args) +; ahora el esencial "Hola Mundo" +(print "hello world") + +;; Tipos de datos simples +; Todos los tipos de datos simples son exactamente semejantes a sus homólogos +; en python +42 ; => 42 +3.14 ; => 3.14 +True ; => True +4+10j ; => (4+10j) un número complejo + +; Vamos a comenzar con un poco de arimética simple +(+ 4 1) ;=> 5 +; el operador es aplicado a todos los argumentos, como en otros lisps +(+ 4 1 2 3) ;=> 10 +(- 2 1) ;=> 1 +(* 4 2) ;=> 8 +(/ 4 1) ;=> 4 +(% 4 2) ;=> 0 o operador módulo +; la exponenciación es representada por el operador ** como python +(** 3 2) ;=> 9 +; las funciones anidadas funcionan como lo esperado +(+ 2 (* 4 2)) ;=> 10 +; también los operadores lógicos igual o no igual se comportan como se espera +(= 5 4) ;=> False +(not (= 5 4)) ;=> True + +;; variables +; las variables se configuran usando SETV, los nombres de las variables pueden +; usar utf-8, excepto for ()[]{}",'`;#| +(setv a 42) +(setv π 3.14159) +(def *foo* 42) +;; otros tipos de datos de almacenamiento +; strings, lists, tuples & dicts +; estos son exactamente los mismos tipos de almacenamiento en python +"hello world" ;=> "hello world" +; las operaciones de cadena funcionan de manera similar en python +(+ "hello " "world") ;=> "hello world" +; Las listas se crean usando [], la indexación comienza en 0 +(setv mylist [1 2 3 4]) +; las tuplas son estructuras de datos inmutables +(setv mytuple (, 1 2)) +; los diccionarios son pares de valor-clave +(setv dict1 {"key1" 42 "key2" 21}) +; :nombre se puede usar para definir palabras clave en Hy que se pueden usar para claves +(setv dict2 {:key1 41 :key2 20}) +; usar 'get' para obtener un elemento en un índice/key +(get mylist 1) ;=> 2 +(get dict1 "key1") ;=> 42 +; Alternativamente, si se usan palabras clave que podrían llamarse directamente +(:key1 dict2) ;=> 41 + +;; funciones y otras estructuras de programa +; las funciones son definidas usando defn, o el último sexp se devuelve por defecto +(defn greet [name] + "A simple greeting" ; un docstring opcional + (print "hello " name)) + +(greet "bilbo") ;=> "hello bilbo" + +; las funciones pueden tener argumentos opcionales, así como argumentos-clave +(defn foolists [arg1 &optional [arg2 2]] + [arg1 arg2]) + +(foolists 3) ;=> [3 2] +(foolists 10 3) ;=> [10 3] + +; las funciones anonimas son creadas usando constructores 'fn' y 'lambda' +; que son similares a 'defn' +(map (fn [x] (* x x)) [1 2 3 4]) ;=> [1 4 9 16] + +;; operaciones de secuencia +; hy tiene algunas utilidades incluidas para operaciones de secuencia, etc. +; recuperar el primer elemento usando 'first' o 'car' +(setv mylist [1 2 3 4]) +(setv mydict {"a" 1 "b" 2}) +(first mylist) ;=> 1 + +; corte listas usando 'slice' +(slice mylist 1 3) ;=> [2 3] + +; obtener elementos de una lista o dict usando 'get' +(get mylist 1) ;=> 2 +(get mydict "b") ;=> 2 +; la lista de indexación comienza a partir de 0, igual que en python +; assoc puede definir elementos clave/índice +(assoc mylist 2 10) ; crear mylist [1 2 10 4] +(assoc mydict "c" 3) ; crear mydict {"a" 1 "b" 2 "c" 3} +; hay muchas otras funciones que hacen que trabajar con secuencias sea +; entretenido + +;; Python interop +;; los import funcionan exactamente como en python +(import datetime) +(import [functools [partial reduce]]) ; importa fun1 e fun2 del module1 +(import [matplotlib.pyplot :as plt]) ; haciendo una importación en foo como en bar +; todos los métodos de python incluídos etc. son accesibles desde hy +; a.foo(arg) is called as (.foo a arg) +(.split (.strip "hello world ")) ;=> ["hello" "world"] + +;; Condicionales +; (if condition (body-if-true) (body-if-false) +(if (= passcode "moria") + (print "welcome") + (print "Speak friend, and Enter!")) + +; anidar múltiples cláusulas 'if else if' con condiciones +(cond + [(= someval 42) + (print "Life, universe and everything else!")] + [(> someval 42) + (print "val too large")] + [(< someval 42) + (print "val too small")]) + +; declaraciones de grupo con 'do', son ejecutadas secuencialmente +; formas como defn tienen un 'do' implícito +(do + (setv someval 10) + (print "someval is set to " someval)) ;=> 10 + +; crear enlaces léxicos con 'let', todas las variables definidas de esta manera +; tienen alcance local +(let [[nemesis {"superman" "lex luther" + "sherlock" "moriarty" + "seinfeld" "newman"}]] + (for [(, h v) (.items nemesis)] + (print (.format "{0}'s nemesis was {1}" h v)))) + +;; clases +; las clases son definidas de la siguiente manera +(defclass Wizard [object] + [[--init-- (fn [self spell] + (setv self.spell spell) ; init the attr magic + None)] + [get-spell (fn [self] + self.spell)]]) + +;; acesse hylang.org +``` + +### Otras lecturas + +Este tutorial apenas es una introducción básica para hy/lisp/python. + +Docs Hy: [http://hy.readthedocs.org](http://hy.readthedocs.org) + +Repo Hy en GitHub: [http://github.com/hylang/hy](http://github.com/hylang/hy) + +Acceso a freenode irc con #hy, hashtag en twitter: #hylang diff --git a/es-es/javascript-es.html.markdown b/es-es/javascript-es.html.markdown index 31512dc4..050154c7 100644 --- a/es-es/javascript-es.html.markdown +++ b/es-es/javascript-es.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["Daniel Zendejas","https://github.com/DanielZendejas"] @@ -19,8 +19,8 @@ para front-end que Java. Sin embargo, JavaScript no sólo se limita a los navegadores web: Node.js, un proyecto que proporciona un entorno de ejecución independiente para el motor V8 de Google Chrome, se está volviendo más y más popular. ¡La retroalimentación es bienvenida! Puedes encontrarme en: -[@adambrenecki](https://twitter.com/adambrenecki), o -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). +[@ExcitedLeigh](https://twitter.com/ExcitedLeigh), o +[l@leigh.net.au](mailto:l@leigh.net.au). ```js // Los comentarios en JavaScript son los mismos como comentarios en C. diff --git a/es-es/julia-es.html.markdown b/es-es/julia-es.html.markdown index e4181609..355c7f29 100644 --- a/es-es/julia-es.html.markdown +++ b/es-es/julia-es.html.markdown @@ -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**. diff --git a/es-es/matlab-es.html.markdown b/es-es/matlab-es.html.markdown index 9f1656bb..9290e505 100644 --- a/es-es/matlab-es.html.markdown +++ b/es-es/matlab-es.html.markdown @@ -1,5 +1,5 @@ --- -language: Matlab +language: MATLAB filename: learnmatlab-es.mat contributors: - ["mendozao", "http://github.com/mendozao"] @@ -31,7 +31,7 @@ esto % Dos símbolos de porcentaje denotan el comienzo de una nueva sección de código. % Secciones de código individuales pueden ser ejecutadas moviendo el cursor hacia la sección, % seguida por un clic en el botón de “Ejecutar Sección” -% o usando Ctrl+Shift+Enter (Windows) o Cmd+Shift+Return (OS X) +% o usando Ctrl+Shift+Enter (Windows) o Cmd+Shift+Return (macOS) %% Este es el comienzo de una sección de código % Una forma de usar las secciones es separar un código de inicio costoso que no cambia, como cargar datos @@ -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/) diff --git a/es-es/objective-c-es.html.markdown b/es-es/objective-c-es.html.markdown index 26cd14d9..28733cfb 100644 --- a/es-es/objective-c-es.html.markdown +++ b/es-es/objective-c-es.html.markdown @@ -9,7 +9,7 @@ translators: lang: es-es filename: LearnObjectiveC-es.m --- -Objective C es el lenguaje de programación principal utilizado por Apple para los sistemas operativos OS X y iOS y sus respectivos frameworks, Cocoa y Cocoa Touch. +Objective C es el lenguaje de programación principal utilizado por Apple para los sistemas operativos macOS y iOS y sus respectivos frameworks, Cocoa y Cocoa Touch. Es un lenguaje de programación para propósito general que le agrega al lenguaje de programación C una mensajería estilo "Smalltalk". diff --git a/es-es/pcre-es.html.markdown b/es-es/pcre-es.html.markdown new file mode 100644 index 00000000..279c9a39 --- /dev/null +++ b/es-es/pcre-es.html.markdown @@ -0,0 +1,84 @@ +--- +language: PCRE +filename: pcre-es.txt +contributors: + - ["Sachin Divekar", "http://github.com/ssd532"] +translators: + - ["Roberto R", "https://github.com/rrodriguze"] +lang: es-es +--- + +Una expresión regular (regex o regexp para abreviar) es una cadena especial +utilizada para definir un patrón, por ejemplo, buscar una secuencia de +caracteres; por ejemplo, `/^[a-z]+:/` se puede usar para extraer `http:` +desde la URL `http://github.com/`. + +PCRE (Pearl Compatible Regular Expressions) es una biblioteca para expresiones +muy similar a la Perls, desde ahí el nombre. Se trata de una de las sintaxis +más comunes para escribir expresiones regulares. + +Hay dos tipos de metacaracteres (caracteres con una función especial): + +* Caracteres reconocidos en todas partes excepto corchetes + +``` + \ caracter de escape + ^ buscar al principio de la cadena (o línea, en modo multilínea) + $ busca al final de la cadena (o línea, en modo multilínea) + . cualquier caracter exceptoo las nuevas líneas + [ inicio de clase de caracter + | condiciones alternativas del separador + ( inicio del subpatrón + ) fin del subpatrón + ? cuantificador "0 o 1" + * quantificatore "0 o más" + + quantificatore "1 o más" + { inicio de cuantificador numérico +``` + +* Caracteres reconocidos entre corchetes + +``` + \ caracter de escape + ^ negar la clase si es el primer caracter + - indica una serie de caracteres + [ clase de caracteres POSIX (si sigue la sintaxis POSIX) + ] termina la clase de caracteres +``` + +PCRE también proporciona clases de caracteres predefinidas + +``` + \d cifra decimal + \D cifra NO decimal + \h espacio horizontal vacío + \H espacio horizontal NO vacío + \s espacio + \S NO esoacui + \v espacio vertical vacío + \V espacio vertical NO vacío + \w palabra + \W "NO palabra" +``` + +## Ejemplos + +Usaremos la siguiente cadena para nuestras pruebas: + +``` +66.249.64.13 - - [18/Sep/2004:11:07:48 +1000] "GET /robots.txt HTTP/1.0" 200 468 "-" "Googlebot/2.1" +``` + +Se trata de una línea de log del servidor web Apache. + +| Regex | Resultado | Comentario | +| :---- | :-------------- | :------ | +| `GET` | GET | Busque exactamente la cadena "GET" (distingue entre mayúsculas y minúsculas) | +| `\d+.\d+.\d+.\d+` | 66.249.64.13 | `\d+` identifica uno o más (cuantificador `+`) números [0-9], `\.` identifica el caracter `.` | +| `(\d+\.){3}\d+` | 66.249.64.13 | `(\d+\.){3}` busca el grupo (`\d+\.`) exactamente 3 veces. | +| `\[.+\]` | [18/Sep/2004:11:07:48 +1000] | `.+` identifica cualquier caracter, excepto las nuevas líneas; `.` indica cualquier carácter | +| `^\S+` | 66.249.64.13 | `^` buscar al inicio de la cadena, `\S+` identifica la primera cadena de caracteres que no sea espacio | +| `\+[0-9]+` | +1000 | `\+` identifica el caracter `+`. `[0-9]` indica una cifra de 0 a 9. La expresión es equivalente a `\+\d+` | + +## Otros recursos +[Regex101](https://regex101.com/) - probador de expresiones regulares diff --git a/es-es/perl-es.html.markdown b/es-es/perl-es.html.markdown index 644182ff..76e9b6e6 100644 --- a/es-es/perl-es.html.markdown +++ b/es-es/perl-es.html.markdown @@ -11,9 +11,9 @@ translators: lang: es-es --- -Perl 5 es un lenguaje de programación altamente capaz, rico en características, con más de 25 años de desarrollo. +Perl es un lenguaje de programación altamente capaz, rico en características, con más de 25 años de desarrollo. -Perl 5 corre en más de 100 plataformas, desde portátiles hasta ordenadores centrales, y es adecuado para realizar desde prototipos rápidos hasta desarrollar proyectos a gran escala. +Perl corre en más de 100 plataformas, desde portátiles hasta ordenadores centrales, y es adecuado para realizar desde prototipos rápidos hasta desarrollar proyectos a gran escala. ```perl # Comentarios de una sola línea con un carácter hash @@ -31,7 +31,7 @@ Perl 5 corre en más de 100 plataformas, desde portátiles hasta ordenadores cen my $animal = "camello"; my $respuesta = 42; -# Los valores escalares pueden ser cadenas de caracteres, números enteros o +# Los valores escalares pueden ser cadenas de caracteres, números enteros o # de punto flotante; Perl automáticamente los convertirá como sea requerido ## Arreglos @@ -52,7 +52,7 @@ my %color_fruta = ( # Los escalares, arreglos y hashes están más documentados en perldata (perldoc perldata) -# Los tipos de datos más complejos se pueden construir utilizando +# Los tipos de datos más complejos se pueden construir utilizando # referencias, las cuales le permiten construir listas y hashes dentro # de listas y hashes @@ -61,7 +61,7 @@ my %color_fruta = ( # Perl tiene la mayoría de las estructuras condicionales y de ciclos más comunes if ( $var ) { ...; -} elsif ( $var eq 'bar' ) { +} elsif ( $var eq 'bar' ) { ...; } else { ...; @@ -98,7 +98,7 @@ foreach (@array) { #### Expresiones regulares -# El soporte de expresiones regulares en Perl es muy amplio y profundo, y +# El soporte de expresiones regulares en Perl es muy amplio y profundo, y # está sujeto a una extensa documentación en perlrequick, perlretut, entre otros. # Sin embargo, resumiendo: @@ -113,7 +113,7 @@ $a =~ s/foo/bar/g; # remplaza TODAS LAS INSTANCIAS de "foo" con "bar" en #### Archivos y E/S -# Puede abrir un archivo para obtener datos o escribirlos utilizando la +# Puede abrir un archivo para obtener datos o escribirlos utilizando la # función "open()" open(my $entrada, "<" "entrada.txt") or die "No es posible abrir entrada.txt: $!"; @@ -122,7 +122,7 @@ open(my $log, ">>", "mi.log") or die "No es posible abrir mi.log: $!"; # Es posible leer desde un gestor de archivo abierto utilizando el operador "<>". # En contexto escalar, leer una sola línea desde el gestor de archivo, y -# en contexto de lista, leer el archivo completo en donde asigna +# en contexto de lista, leer el archivo completo en donde asigna # cada línea a un elemento de la lista my $linea = <$entrada>; diff --git a/es-es/powershell-es.html.markdown b/es-es/powershell-es.html.markdown index 9eb35967..5b12b961 100644 --- a/es-es/powershell-es.html.markdown +++ b/es-es/powershell-es.html.markdown @@ -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)) { diff --git a/es-es/pyqt-es.html.markdown b/es-es/pyqt-es.html.markdown index 6d4fdde7..9a5eab8c 100644 --- a/es-es/pyqt-es.html.markdown +++ b/es-es/pyqt-es.html.markdown @@ -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(): diff --git a/es-es/python-es.html.markdown b/es-es/python-es.html.markdown index 2b8f498a..0b21e479 100644 --- a/es-es/python-es.html.markdown +++ b/es-es/python-es.html.markdown @@ -1,26 +1,25 @@ --- -language: python +language: Python contributors: - - ["Louie Dinh", "http://ldinh.ca"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] translators: - - ["Camilo Garrido", "http://www.twitter.com/hirohope"] - - ["Fabio Souto", "http://fabiosouto.me"] + - ["Camilo Garrido", "http://twitter.com/hirohope"] lang: es-es filename: learnpython-es.py --- -Python fue creado por Guido Van Rossum en el principio de los 90. Ahora es uno -de los lenguajes más populares que existen. Me enamoré de Python por su claridad sintáctica. +Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno +de los lenguajes más populares en existencia. Me enamoré de Python por su claridad sintáctica. Es básicamente pseudocódigo ejecutable. ¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] -Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser aplicable a Python 2.x. ¡Pronto un recorrido por Python 3! - ```python + # Comentarios de una línea comienzan con una almohadilla (o signo gato) -""" Strings multilínea pueden escribirse - usando tres "'s, y comúnmente son usados + +""" Strings multilinea pueden escribirse + usando tres "'s, y comunmente son usados como comentarios. """ @@ -31,69 +30,49 @@ Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser apl # Tienes números 3 #=> 3 -# Evidentemente puedes realizar operaciones matemáticas -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 - -# La división es un poco complicada. Es división entera y toma la parte entera -# de los resultados automáticamente. -5 / 2 #=> 2 +# Matemática es lo que esperarías +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 -# Para arreglar la división necesitamos aprender sobre 'floats' -# (números de coma flotante). -2.0 # Esto es un 'float' -11.0 / 4.0 #=> 2.75 ahhh...mucho mejor +# Excepto la división la cual por defecto retorna un número 'float' (número de coma flotante) +35 / 5 # => 7.0 +# Sin embargo también tienes disponible división entera +34 // 5 # => 6 -# Resultado de la división de enteros truncada para positivos y negativos -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # funciona con números de coma flotante --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# El operador módulo devuelve el resto de una división entre enteros -7 % 3 # => 1 - -# Exponenciación (x elevado a y) -2**4 # => 16 +# Cuando usas un float, los resultados son floats +3 * 2.0 # => 6.0 # Refuerza la precedencia con paréntesis -(1 + 3) * 2 #=> 8 +(1 + 3) * 2 # => 8 -# Operadores booleanos -# Nota: "and" y "or" son sensibles a mayúsculas -True and False #=> False -False or True #=> True -# Podemos usar operadores booleanos con números enteros -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True +# Valores 'boolean' (booleanos) son primitivos +True +False # Niega con 'not' -not True #=> False -not False #=> True +not True # => False +not False # => True + # Igualdad es == -1 == 1 #=> True -2 == 1 #=> False +1 == 1 # => True +2 == 1 # => False # Desigualdad es != -1 != 1 #=> False -2 != 1 #=> True +1 != 1 # => False +2 != 1 # => True # Más comparaciones -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True # ¡Las comparaciones pueden ser concatenadas! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +1 < 2 < 3 # => True +2 < 3 < 2 # => False # Strings se crean con " o ' "Esto es un string." @@ -105,40 +84,41 @@ not False #=> True # Un string puede ser tratado como una lista de caracteres "Esto es un string"[0] #=> 'E' -# % pueden ser usados para formatear strings, como esto: -"%s pueden ser %s" % ("strings", "interpolados") +# .format puede ser usaro para darle formato a los strings, así: +"{} pueden ser {}".format("strings", "interpolados") -# Una forma más reciente de formatear strings es el método 'format'. -# Este método es la forma preferida -"{0} pueden ser {1}".format("strings", "formateados") -# Puedes usar palabras clave si no quieres contar. -"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") +# Puedes reutilizar los argumentos de formato si estos se repiten. +"{0} sé ligero, {0} sé rápido, {0} brinca sobre la {1}".format("Jack", "vela") #=> "Jack sé ligero, Jack sé rápido, Jack brinca sobre la vela" +# Puedes usar palabras claves si no quieres contar. +"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") #=> "Bob quiere comer lasaña" +# También puedes interpolar cadenas usando variables en el contexto +nombre = 'Bob' +comida = 'Lasaña' +f'{nombre} quiere comer {comida}' #=> "Bob quiere comer lasaña" # None es un objeto -None #=> None +None # => None # No uses el símbolo de igualdad `==` para comparar objetos con None -# Usa `is` en lugar de +# Usa `is` en su lugar "etc" is None #=> False None is None #=> True -# El operador 'is' prueba la identidad del objeto. Esto no es -# muy útil cuando se trata de datos primitivos, pero es -# muy útil cuando se trata de objetos. - -# None, 0, y strings/listas vacíos(as) todas se evalúan como False. +# None, 0, y strings/listas/diccionarios/conjuntos vacíos(as) todos se evalúan como False. # Todos los otros valores son True -bool(0) #=> False -bool("") #=> False +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False +bool(set()) #=> False #################################################### ## 2. Variables y Colecciones #################################################### -# Imprimir es muy fácil -print "Soy Python. ¡Encantado de conocerte!" - +# Python tiene una función para imprimir +print("Soy Python. Encantado de conocerte") # No hay necesidad de declarar las variables antes de asignarlas. una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas @@ -148,19 +128,16 @@ una_variable #=> 5 # Ve Control de Flujo para aprender más sobre el manejo de excepciones. otra_variable # Levanta un error de nombre -# 'if' puede ser usado como una expresión -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" - -# Las listas almacenan secuencias +# Listas almacena secuencias lista = [] # Puedes empezar con una lista prellenada otra_lista = [4, 5, 6] # Añadir cosas al final de una lista con 'append' -lista.append(1) # lista ahora es [1] -lista.append(2) # lista ahora es [1, 2] -lista.append(4) # lista ahora es [1, 2, 4] -lista.append(3) # lista ahora es [1, 2, 4, 3] +lista.append(1) #lista ahora es [1] +lista.append(2) #lista ahora es [1, 2] +lista.append(4) #lista ahora es [1, 2, 4] +lista.append(3) #lista ahora es [1, 2, 4, 3] # Remueve del final de la lista con 'pop' lista.pop() #=> 3 y lista ahora es [1, 2, 4] # Pongámoslo de vuelta @@ -181,6 +158,12 @@ lista[1:3] #=> [2, 4] lista[2:] #=> [4, 3] # Omite el final lista[:3] #=> [1, 2, 4] +# Selecciona cada dos elementos +lista[::2] # =>[1, 4] +# Invierte la lista +lista[::-1] # => [3, 4, 2, 1] +# Usa cualquier combinación de estos para crear trozos avanzados +# lista[inicio:final:pasos] # Remueve elementos arbitrarios de una lista con 'del' del lista[2] # lista ahora es [1, 2, 3] @@ -191,14 +174,14 @@ lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan # Concatenar listas con 'extend' lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] -# Chequea la existencia en una lista con +# Verifica la existencia en una lista con 'in' 1 in lista #=> True -# Examina el tamaño de una lista con 'len' +# Examina el largo de una lista con 'len' len(lista) #=> 6 -# Las tuplas son como las listas, pero son inmutables. +# Tuplas son como listas pero son inmutables. tupla = (1, 2, 3) tupla[0] #=> 1 tupla[0] = 3 # Levanta un error TypeError @@ -217,7 +200,7 @@ d, e, f = 4, 5, 6 e, d = d, e # d ahora es 5 y e ahora es 4 -# Diccionarios almacenan mapeos +# Diccionarios relacionan llaves y valores dicc_vacio = {} # Aquí está un diccionario prellenado dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} @@ -225,16 +208,16 @@ dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} # Busca valores con [] dicc_lleno["uno"] #=> 1 -# Obtén todas las llaves como una lista -dicc_lleno.keys() #=> ["tres", "dos", "uno"] +# Obtén todas las llaves como una lista con 'keys()'. Necesitamos envolver la llamada en 'list()' porque obtenemos un iterable. Hablaremos de eso luego. +list(dicc_lleno.keys()) #=> ["tres", "dos", "uno"] # Nota - El orden de las llaves del diccionario no está garantizada. # Tus resultados podrían no ser los mismos del ejemplo. -# Obtén todos los valores como una lista -dicc_lleno.values() #=> [3, 2, 1] +# Obtén todos los valores como una lista. Nuevamente necesitamos envolverlas en una lista para sacarlas del iterable. +list(dicc_lleno.values()) #=> [3, 2, 1] # Nota - Lo mismo que con las llaves, no se garantiza el orden. -# Chequea la existencia de una llave en el diccionario con 'in' +# Verifica la existencia de una llave en el diccionario con 'in' "uno" in dicc_lleno #=> True 1 in dicc_lleno #=> False @@ -248,19 +231,18 @@ dicc_lleno.get("cuatro") #=> None dicc_lleno.get("uno", 4) #=> 1 dicc_lleno.get("cuatro", 4) #=> 4 -# El método 'setdefault' es una manera segura de añadir nuevos pares -# llave-valor en un diccionario +# El método 'setdefault' inserta en un diccionario solo si la llave no está presente dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 +# Remueve llaves de un diccionario con 'del' +del dicc_lleno['uno'] # Remueve la llave 'uno' de dicc_lleno + # Sets (conjuntos) almacenan ... bueno, conjuntos conjunto_vacio = set() -# Inicializar un conjunto con montón de valores -un_conjunto = set([1,2,2,3,4]) # un_conjunto ahora es set([1, 2, 3, 4]) - -# Desde Python 2.7, {} puede ser usado para declarar un conjunto -conjunto_lleno = {1, 2, 2, 3, 4} # => {1 2 3 4} +# Inicializar un conjunto con montón de valores. Yeah, se ve un poco como un diccionario. Lo siento. +un_conjunto = {1,2,2,3,4} # un_conjunto ahora es {1, 2, 3, 4} # Añade más valores a un conjunto conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} @@ -275,7 +257,7 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} # Haz diferencia de conjuntos con - {1,2,3,4} - {2,3,5} #=> {1, 4} -# Chequea la existencia en un conjunto con 'in' +# Verifica la existencia en un conjunto con 'in' 2 in conjunto_lleno #=> True 10 in conjunto_lleno #=> False @@ -284,32 +266,30 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} ## 3. Control de Flujo #################################################### -# Hagamos sólo una variable -una_variable = 5 +# Creemos una variable para experimentar +some_var = 5 -# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python! +# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python! # imprime "una_variable es menor que 10" if una_variable > 10: - print "una_variable es completamente mas grande que 10." + print("una_variable es completamente mas grande que 10.") elif una_variable < 10: # Este condición 'elif' es opcional. - print "una_variable es mas chica que 10." + print("una_variable es mas chica que 10.") else: # Esto también es opcional. - print "una_variable es de hecho 10." - + print("una_variable es de hecho 10.") """ -For itera sobre listas +For itera sobre iterables (listas, cadenas, diccionarios, tuplas, generadores...) imprime: perro es un mamifero gato es un mamifero raton es un mamifero """ for animal in ["perro", "gato", "raton"]: - # Puedes usar % para interpolar strings formateados - print "%s es un mamifero" % animal + print("{} es un mamifero".format(animal)) """ -`range(número)` retorna una lista de números +`range(número)` retorna un generador de números desde cero hasta el número dado imprime: 0 @@ -318,7 +298,7 @@ imprime: 3 """ for i in range(4): - print i + print(i) """ While itera hasta que una condición no se cumple. @@ -330,18 +310,49 @@ imprime: """ x = 0 while x < 4: - print x + print(x) x += 1 # versión corta de x = x + 1 # Maneja excepciones con un bloque try/except - -# Funciona desde Python 2.6 en adelante: try: # Usa raise para levantar un error raise IndexError("Este es un error de indice") except IndexError as e: pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. +# Python oferce una abstracción fundamental llamada Iterable. +# Un iterable es un objeto que puede ser tratado como una sequencia. +# El objeto es retornado por la función 'range' es un iterable. + +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. +for i in nuestro_iterable: + print(i) # Imprime uno, dos, tres + +# Aunque no podemos selecionar un elemento por su índice. +nuestro_iterable[1] # Genera un TypeError + +# Un iterable es un objeto que sabe como crear un iterador. +nuestro_iterator = iter(nuestro_iterable) + +# Nuestro iterador es un objeto que puede recordar el estado mientras lo recorremos. +# Obtenemos el siguiente objeto llamando la función __next__. +nuestro_iterator.__next__() #=> "uno" + +# Mantiene el estado mientras llamamos __next__. +nuestro_iterator.__next__() #=> "dos" +nuestro_iterator.__next__() #=> "tres" + +# Después que el iterador ha retornado todos sus datos, da una excepción StopIterator. +nuestro_iterator.__next__() # Genera StopIteration + +# Puedes obtener todos los elementos de un iterador llamando a list() en el. +list(dicc_lleno.keys()) #=> Retorna ["uno", "dos", "tres"] + + #################################################### ## 4. Funciones @@ -349,7 +360,7 @@ except IndexError as e: # Usa 'def' para crear nuevas funciones def add(x, y): - print "x es %s y y es %s" % (x, y) + print("x es {} y y es {}".format(x, y)) return x + y # Retorna valores con una la declaración return # Llamando funciones con parámetros @@ -358,6 +369,7 @@ add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 # Otra forma de llamar funciones es con argumentos de palabras claves add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. + # Puedes definir funciones que tomen un número variable de argumentos def varargs(*args): return args @@ -373,10 +385,11 @@ def keyword_args(**kwargs): # Llamémosla para ver que sucede 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) @@ -410,23 +423,28 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] # Podemos usar listas por comprensión para mapeos y filtros agradables [add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +# también hay diccionarios +{k:k**2 for k in range(3)} #=> {0: 0, 1: 1, 2: 4} +# y conjuntos por comprensión +{c for c in "la cadena"} #=> {'d', 'l', 'a', 'n', ' ', 'c', 'e'} #################################################### -## 5. Clases +## 5. Classes #################################################### + # Heredamos de object para obtener una clase. class Humano(object): # Un atributo de clase es compartido por todas las instancias de esta clase especie = "H. sapiens" - # Constructor básico, se llama al instanciar la clase. + # Constructor basico def __init__(self, nombre): # Asigna el argumento al atributo nombre de la instancia self.nombre = nombre - # Un método de instancia. Todos los metodos toman self como primer argumento + # Un metodo de instancia. Todos los metodos toman self como primer argumento def decir(self, msg): return "%s: %s" % (self.nombre, msg) @@ -436,7 +454,7 @@ class Humano(object): def get_especie(cls): return cls.especie - # Un metodo estático es llamado sin la clase o instancia como referencia + # Un metodo estatico es llamado sin la clase o instancia como referencia @staticmethod def roncar(): return "*roncar*" @@ -444,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" @@ -467,12 +485,12 @@ Humano.roncar() #=> "*roncar*" # Puedes importar módulos import math -print math.sqrt(16) #=> 4.0 +print(math.sqrt(16)) #=> 4.0 # Puedes obtener funciones específicas desde un módulo from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 +print(ceil(3.7)) #=> 4.0 +print(floor(3.7))#=> 3.0 # Puedes importar todas las funciones de un módulo # Precaución: Esto no es recomendable @@ -495,52 +513,48 @@ dir(math) ## 7. Avanzado #################################################### -# Los generadores permiten evaluación perezosa +# Los generadores te ayudan a hacer un código perezoso (lazy) def duplicar_numeros(iterable): for i in iterable: yield i + i -# Un generador crea valores sobre la marcha -# En vez de generar y devolver todos los valores de una vez, crea un valor -# en cada iteración. En este ejemplo los valores mayores que 15 no serán -# procesados en duplicar_numeros. -# Nota: xrange es un generador que hace lo mismo que range. -# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio. -# xrange crea un generador, mientras que range crea toda la lista. -# Añadimos un guión bajo a los nombres de variable que coinciden con palabras -# reservadas de python. -xrange_ = xrange(1, 900000000) - -# duplica todos los números hasta que encuentra un resultado >= 30 -for i in duplicar_numeros(xrange_): - print i +# Un generador crea valores sobre la marcha. +# En vez de generar y retornar todos los valores de una vez, crea uno en cada iteración. +# Esto significa que valores más grandes que 15 no serán procesados en 'duplicar_numeros'. +# Fíjate que 'range' es un generador. Crear una lista 1-900000000 tomaría mucho tiempo en crearse. +_rango = range(1, 900000000) +# Duplicará todos los números hasta que un resultado >= se encuentre. +for i in duplicar_numeros(_rango): + print(i) if i >= 30: break + # Decoradores -# en este ejemplo pedir rodea a hablar -# Si por_favor es True se cambiará el mensaje. +# en este ejemplo 'pedir' envuelve a 'decir' +# Pedir llamará a 'decir'. Si decir_por_favor es True entonces cambiará el mensaje a retornar from functools import wraps -def pedir(target_function): - @wraps(target_function) +def pedir(_decir): + @wraps(_decir) def wrapper(*args, **kwargs): - msg, por_favor = target_function(*args, **kwargs) - if por_favor: - return "{} {}".format(msg, "¡Por favor! Soy pobre :(") - return msg + mensaje, decir_por_favor = _decir(*args, **kwargs) + if decir_por_favor: + return "{} {}".format(mensaje, "¡Por favor! Soy pobre :(") + return mensaje return wrapper @pedir -def hablar(por_favor=False): - msg = "¿Me puedes comprar una cerveza?" - return msg, por_favor +def decir(decir_por_favor=False): + mensaje = "¿Puedes comprarme una cerveza?" + return mensaje, decir_por_favor + -print hablar() # ¿Me puedes comprar una cerveza? -print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :( +print(decir()) # ¿Puedes comprarme una cerveza? +print(decir(decir_por_favor=True)) # ¿Puedes comprarme una cerveza? ¡Por favor! Soy pobre :() ``` ## ¿Listo para más? @@ -549,9 +563,10 @@ print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! So * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) +* [Python Module of the Week](http://pymotw.com/3/) * [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) ### Encuadernados diff --git a/es-es/python3-es.html.markdown b/es-es/pythonlegacy-es.html.markdown index 3236e73a..0a7304e9 100644 --- a/es-es/python3-es.html.markdown +++ b/es-es/pythonlegacy-es.html.markdown @@ -1,25 +1,26 @@ --- -language: python3 +language: Python 2 (legacy) contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Louie Dinh", "http://ldinh.ca"] translators: - - ["Camilo Garrido", "http://twitter.com/hirohope"] + - ["Camilo Garrido", "http://www.twitter.com/hirohope"] + - ["Fabio Souto", "http://fabiosouto.me"] lang: es-es -filename: learnpython3-es.py +filename: learnpythonlegacy-es.py --- -Python fue creado por Guido Van Rossum en el principio de los 90'. Ahora es uno -de los lenguajes más populares en existencia. Me enamoré de Python por su claridad sintáctica. +Python fue creado por Guido Van Rossum en el principio de los 90. Ahora es uno +de los lenguajes más populares que existen. Me enamoré de Python por su claridad sintáctica. Es básicamente pseudocódigo ejecutable. ¡Comentarios serán muy apreciados! Pueden contactarme en [@louiedinh](http://twitter.com/louiedinh) o louiedinh [at] [servicio de email de google] -```python +Nota: Este artículo aplica a Python 2.7 específicamente, pero debería ser aplicable a Python 2.x. ¡Pronto un recorrido por Python 3! +```python # Comentarios de una línea comienzan con una almohadilla (o signo gato) - -""" Strings multilinea pueden escribirse - usando tres "'s, y comunmente son usados +""" Strings multilínea pueden escribirse + usando tres "'s, y comúnmente son usados como comentarios. """ @@ -30,49 +31,69 @@ Es básicamente pseudocódigo ejecutable. # Tienes números 3 #=> 3 -# Matemática es lo que esperarías -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 +# Evidentemente puedes realizar operaciones matemáticas +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# La división es un poco complicada. Es división entera y toma la parte entera +# de los resultados automáticamente. +5 / 2 #=> 2 -# Excepto la división la cual por defecto retorna un número 'float' (número de coma flotante) -35 / 5 # => 7.0 -# Sin embargo también tienes disponible división entera -34 // 5 # => 6 +# Para arreglar la división necesitamos aprender sobre 'floats' +# (números de coma flotante). +2.0 # Esto es un 'float' +11.0 / 4.0 #=> 2.75 ahhh...mucho mejor -# Cuando usas un float, los resultados son floats -3 * 2.0 # => 6.0 +# Resultado de la división de enteros truncada para positivos y negativos +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # funciona con números de coma flotante +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# El operador módulo devuelve el resto de una división entre enteros +7 % 3 # => 1 + +# Exponenciación (x elevado a y) +2**4 # => 16 # Refuerza la precedencia con paréntesis -(1 + 3) * 2 # => 8 +(1 + 3) * 2 #=> 8 +# Operadores booleanos +# Nota: "and" y "or" son sensibles a mayúsculas +True and False #=> False +False or True #=> True -# Valores 'boolean' (booleanos) son primitivos -True -False +# Podemos usar operadores booleanos con números enteros +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True # Niega con 'not' -not True # => False -not False # => True - +not True #=> False +not False #=> True # Igualdad es == -1 == 1 # => True -2 == 1 # => False +1 == 1 #=> True +2 == 1 #=> False # Desigualdad es != -1 != 1 # => False -2 != 1 # => True +1 != 1 #=> False +2 != 1 #=> True # Más comparaciones -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True # ¡Las comparaciones pueden ser concatenadas! -1 < 2 < 3 # => True -2 < 3 < 2 # => False +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False # Strings se crean con " o ' "Esto es un string." @@ -84,41 +105,40 @@ not False # => True # Un string puede ser tratado como una lista de caracteres "Esto es un string"[0] #=> 'E' -# .format puede ser usaro para darle formato a los strings, así: -"{} pueden ser {}".format("strings", "interpolados") +# % pueden ser usados para formatear strings, como esto: +"%s pueden ser %s" % ("strings", "interpolados") -# Puedes reutilizar los argumentos de formato si estos se repiten. -"{0} sé ligero, {0} sé rápido, {0} brinca sobre la {1}".format("Jack", "vela") #=> "Jack sé ligero, Jack sé rápido, Jack brinca sobre la vela" -# Puedes usar palabras claves si no quieres contar. -"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") #=> "Bob quiere comer lasaña" -# También puedes interpolar cadenas usando variables en el contexto -nombre = 'Bob' -comida = 'Lasaña' -f'{nombre} quiere comer {comida}' #=> "Bob quiere comer lasaña" +# Una forma más reciente de formatear strings es el método 'format'. +# Este método es la forma preferida +"{0} pueden ser {1}".format("strings", "formateados") +# Puedes usar palabras clave si no quieres contar. +"{nombre} quiere comer {comida}".format(nombre="Bob", comida="lasaña") # None es un objeto -None # => None +None #=> None # No uses el símbolo de igualdad `==` para comparar objetos con None -# Usa `is` en su lugar +# Usa `is` en lugar de "etc" is None #=> False None is None #=> True -# None, 0, y strings/listas/diccionarios/conjuntos vacíos(as) todos se evalúan como False. +# El operador 'is' prueba la identidad del objeto. Esto no es +# muy útil cuando se trata de datos primitivos, pero es +# muy útil cuando se trata de objetos. + +# None, 0, y strings/listas vacíos(as) todas se evalúan como False. # Todos los otros valores son True -bool(0) # => False -bool("") # => False -bool([]) #=> False -bool({}) #=> False -bool(set()) #=> False +bool(0) #=> False +bool("") #=> False #################################################### ## 2. Variables y Colecciones #################################################### -# Python tiene una función para imprimir -print("Soy Python. Encantado de conocerte") +# Imprimir es muy fácil +print "Soy Python. ¡Encantado de conocerte!" + # No hay necesidad de declarar las variables antes de asignarlas. una_variable = 5 # La convención es usar guiones_bajos_con_minúsculas @@ -128,16 +148,19 @@ una_variable #=> 5 # Ve Control de Flujo para aprender más sobre el manejo de excepciones. otra_variable # Levanta un error de nombre -# Listas almacena secuencias +# 'if' puede ser usado como una expresión +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Las listas almacenan secuencias lista = [] # Puedes empezar con una lista prellenada otra_lista = [4, 5, 6] # Añadir cosas al final de una lista con 'append' -lista.append(1) #lista ahora es [1] -lista.append(2) #lista ahora es [1, 2] -lista.append(4) #lista ahora es [1, 2, 4] -lista.append(3) #lista ahora es [1, 2, 4, 3] +lista.append(1) # lista ahora es [1] +lista.append(2) # lista ahora es [1, 2] +lista.append(4) # lista ahora es [1, 2, 4] +lista.append(3) # lista ahora es [1, 2, 4, 3] # Remueve del final de la lista con 'pop' lista.pop() #=> 3 y lista ahora es [1, 2, 4] # Pongámoslo de vuelta @@ -158,12 +181,6 @@ lista[1:3] #=> [2, 4] lista[2:] #=> [4, 3] # Omite el final lista[:3] #=> [1, 2, 4] -# Selecciona cada dos elementos -lista[::2] # =>[1, 4] -# Invierte la lista -lista[::-1] # => [3, 4, 2, 1] -# Usa cualquier combinación de estos para crear trozos avanzados -# lista[inicio:final:pasos] # Remueve elementos arbitrarios de una lista con 'del' del lista[2] # lista ahora es [1, 2, 3] @@ -174,14 +191,14 @@ lista + otra_lista #=> [1, 2, 3, 4, 5, 6] - Nota: lista y otra_lista no se tocan # Concatenar listas con 'extend' lista.extend(otra_lista) # lista ahora es [1, 2, 3, 4, 5, 6] -# Verifica la existencia en una lista con 'in' +# Chequea la existencia en una lista con 1 in lista #=> True -# Examina el largo de una lista con 'len' +# Examina el tamaño de una lista con 'len' len(lista) #=> 6 -# Tuplas son como listas pero son inmutables. +# Las tuplas son como las listas, pero son inmutables. tupla = (1, 2, 3) tupla[0] #=> 1 tupla[0] = 3 # Levanta un error TypeError @@ -200,7 +217,7 @@ d, e, f = 4, 5, 6 e, d = d, e # d ahora es 5 y e ahora es 4 -# Diccionarios relacionan llaves y valores +# Diccionarios almacenan mapeos dicc_vacio = {} # Aquí está un diccionario prellenado dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} @@ -208,16 +225,16 @@ dicc_lleno = {"uno": 1, "dos": 2, "tres": 3} # Busca valores con [] dicc_lleno["uno"] #=> 1 -# Obtén todas las llaves como una lista con 'keys()'. Necesitamos envolver la llamada en 'list()' porque obtenemos un iterable. Hablaremos de eso luego. -list(dicc_lleno.keys()) #=> ["tres", "dos", "uno"] +# Obtén todas las llaves como una lista +dicc_lleno.keys() #=> ["tres", "dos", "uno"] # Nota - El orden de las llaves del diccionario no está garantizada. # Tus resultados podrían no ser los mismos del ejemplo. -# Obtén todos los valores como una lista. Nuevamente necesitamos envolverlas en una lista para sacarlas del iterable. -list(dicc_lleno.values()) #=> [3, 2, 1] +# Obtén todos los valores como una lista +dicc_lleno.values() #=> [3, 2, 1] # Nota - Lo mismo que con las llaves, no se garantiza el orden. -# Verifica la existencia de una llave en el diccionario con 'in' +# Chequea la existencia de una llave en el diccionario con 'in' "uno" in dicc_lleno #=> True 1 in dicc_lleno #=> False @@ -231,18 +248,19 @@ dicc_lleno.get("cuatro") #=> None dicc_lleno.get("uno", 4) #=> 1 dicc_lleno.get("cuatro", 4) #=> 4 -# El método 'setdefault' inserta en un diccionario solo si la llave no está presente +# El método 'setdefault' es una manera segura de añadir nuevos pares +# llave-valor en un diccionario dicc_lleno.setdefault("cinco", 5) #dicc_lleno["cinco"] es puesto con valor 5 dicc_lleno.setdefault("cinco", 6) #dicc_lleno["cinco"] todavía es 5 -# Remueve llaves de un diccionario con 'del' -del dicc_lleno['uno'] # Remueve la llave 'uno' de dicc_lleno - # Sets (conjuntos) almacenan ... bueno, conjuntos conjunto_vacio = set() -# Inicializar un conjunto con montón de valores. Yeah, se ve un poco como un diccionario. Lo siento. -un_conjunto = {1,2,2,3,4} # un_conjunto ahora es {1, 2, 3, 4} +# Inicializar un conjunto con montón de valores +un_conjunto = set([1,2,2,3,4]) # un_conjunto ahora es set([1, 2, 3, 4]) + +# Desde Python 2.7, {} puede ser usado para declarar un conjunto +conjunto_lleno = {1, 2, 2, 3, 4} # => {1 2 3 4} # Añade más valores a un conjunto conjunto_lleno.add(5) # conjunto_lleno ahora es {1, 2, 3, 4, 5} @@ -257,7 +275,7 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} # Haz diferencia de conjuntos con - {1,2,3,4} - {2,3,5} #=> {1, 4} -# Verifica la existencia en un conjunto con 'in' +# Chequea la existencia en un conjunto con 'in' 2 in conjunto_lleno #=> True 10 in conjunto_lleno #=> False @@ -266,30 +284,32 @@ conjunto_lleno | otro_conjunto #=> {1, 2, 3, 4, 5, 6} ## 3. Control de Flujo #################################################### -# Creemos una variable para experimentar -some_var = 5 +# Hagamos sólo una variable +una_variable = 5 -# Aquí está una declaración de un 'if'. ¡La indentación es significativa en Python! +# Aquí está una declaración de un 'if'. ¡La indentación es importante en Python! # imprime "una_variable es menor que 10" if una_variable > 10: - print("una_variable es completamente mas grande que 10.") + print "una_variable es completamente mas grande que 10." elif una_variable < 10: # Este condición 'elif' es opcional. - print("una_variable es mas chica que 10.") + print "una_variable es mas chica que 10." else: # Esto también es opcional. - print("una_variable es de hecho 10.") + print "una_variable es de hecho 10." + """ -For itera sobre iterables (listas, cadenas, diccionarios, tuplas, generadores...) +For itera sobre listas imprime: perro es un mamifero gato es un mamifero raton es un mamifero """ for animal in ["perro", "gato", "raton"]: - print("{} es un mamifero".format(animal)) + # Puedes usar % para interpolar strings formateados + print "%s es un mamifero" % animal """ -`range(número)` retorna un generador de números +`range(número)` retorna una lista de números desde cero hasta el número dado imprime: 0 @@ -298,7 +318,7 @@ imprime: 3 """ for i in range(4): - print(i) + print i """ While itera hasta que una condición no se cumple. @@ -310,49 +330,18 @@ imprime: """ x = 0 while x < 4: - print(x) + print x x += 1 # versión corta de x = x + 1 # Maneja excepciones con un bloque try/except + +# Funciona desde Python 2.6 en adelante: try: # Usa raise para levantar un error raise IndexError("Este es un error de indice") except IndexError as e: pass # Pass no hace nada. Usualmente harias alguna recuperacion aqui. -# Python oferce una abstracción fundamental llamada Iterable. -# Un iterable es un objeto que puede ser tratado como una sequencia. -# El objeto es retornado por la función 'range' es un iterable. - -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. -for i in nuestro_iterable: - print(i) # Imprime uno, dos, tres - -# Aunque no podemos selecionar un elemento por su índice. -nuestro_iterable[1] # Genera un TypeError - -# Un iterable es un objeto que sabe como crear un iterador. -nuestro_iterator = iter(nuestro_iterable) - -# Nuestro iterador es un objeto que puede recordar el estado mientras lo recorremos. -# Obtenemos el siguiente objeto llamando la función __next__. -nuestro_iterator.__next__() #=> "uno" - -# Mantiene el estado mientras llamamos __next__. -nuestro_iterator.__next__() #=> "dos" -nuestro_iterator.__next__() #=> "tres" - -# Después que el iterador ha retornado todos sus datos, da una excepción StopIterator. -nuestro_iterator.__next__() # Genera StopIteration - -# Puedes obtener todos los elementos de un iterador llamando a list() en el. -list(dicc_lleno.keys()) #=> Retorna ["uno", "dos", "tres"] - - #################################################### ## 4. Funciones @@ -360,7 +349,7 @@ list(dicc_lleno.keys()) #=> Retorna ["uno", "dos", "tres"] # Usa 'def' para crear nuevas funciones def add(x, y): - print("x es {} y y es {}".format(x, y)) + print "x es %s y y es %s" % (x, y) return x + y # Retorna valores con una la declaración return # Llamando funciones con parámetros @@ -369,7 +358,6 @@ add(5, 6) #=> imprime "x es 5 y y es 6" y retorna 11 # Otra forma de llamar funciones es con argumentos de palabras claves add(y=6, x=5) # Argumentos de palabra clave pueden ir en cualquier orden. - # Puedes definir funciones que tomen un número variable de argumentos def varargs(*args): return args @@ -385,7 +373,6 @@ def keyword_args(**kwargs): # Llamémosla para ver que sucede 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 @@ -423,28 +410,23 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] # Podemos usar listas por comprensión para mapeos y filtros agradables [add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] -# también hay diccionarios -{k:k**2 for k in range(3)} #=> {0: 0, 1: 1, 2: 4} -# y conjuntos por comprensión -{c for c in "la cadena"} #=> {'d', 'l', 'a', 'n', ' ', 'c', 'e'} #################################################### -## 5. Classes +## 5. Clases #################################################### - # Heredamos de object para obtener una clase. class Humano(object): # Un atributo de clase es compartido por todas las instancias de esta clase especie = "H. sapiens" - # Constructor basico + # Constructor básico, se llama al instanciar la clase. def __init__(self, nombre): # Asigna el argumento al atributo nombre de la instancia self.nombre = nombre - # Un metodo de instancia. Todos los metodos toman self como primer argumento + # Un método de instancia. Todos los metodos toman self como primer argumento def decir(self, msg): return "%s: %s" % (self.nombre, msg) @@ -454,7 +436,7 @@ class Humano(object): def get_especie(cls): return cls.especie - # Un metodo estatico es llamado sin la clase o instancia como referencia + # Un metodo estático es llamado sin la clase o instancia como referencia @staticmethod def roncar(): return "*roncar*" @@ -485,12 +467,12 @@ Humano.roncar() #=> "*roncar*" # Puedes importar módulos import math -print(math.sqrt(16)) #=> 4.0 +print math.sqrt(16) #=> 4.0 # Puedes obtener funciones específicas desde un módulo from math import ceil, floor -print(ceil(3.7)) #=> 4.0 -print(floor(3.7))#=> 3.0 +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 # Puedes importar todas las funciones de un módulo # Precaución: Esto no es recomendable @@ -513,48 +495,52 @@ dir(math) ## 7. Avanzado #################################################### -# Los generadores te ayudan a hacer un código perezoso (lazy) +# Los generadores permiten evaluación perezosa def duplicar_numeros(iterable): for i in iterable: yield i + i -# Un generador crea valores sobre la marcha. -# En vez de generar y retornar todos los valores de una vez, crea uno en cada iteración. -# Esto significa que valores más grandes que 15 no serán procesados en 'duplicar_numeros'. -# Fíjate que 'range' es un generador. Crear una lista 1-900000000 tomaría mucho tiempo en crearse. -_rango = range(1, 900000000) -# Duplicará todos los números hasta que un resultado >= se encuentre. -for i in duplicar_numeros(_rango): - print(i) +# Un generador crea valores sobre la marcha +# En vez de generar y devolver todos los valores de una vez, crea un valor +# en cada iteración. En este ejemplo los valores mayores que 15 no serán +# procesados en duplicar_numeros. +# Nota: xrange es un generador que hace lo mismo que range. +# Crear una lista de 1 a 900000000 lleva mucho tiempo y ocupa mucho espacio. +# xrange crea un generador, mientras que range crea toda la lista. +# Añadimos un guión bajo a los nombres de variable que coinciden con palabras +# reservadas de python. +xrange_ = xrange(1, 900000000) + +# duplica todos los números hasta que encuentra un resultado >= 30 +for i in duplicar_numeros(xrange_): + print i if i >= 30: break - # Decoradores -# en este ejemplo 'pedir' envuelve a 'decir' -# Pedir llamará a 'decir'. Si decir_por_favor es True entonces cambiará el mensaje a retornar +# en este ejemplo pedir rodea a hablar +# Si por_favor es True se cambiará el mensaje. from functools import wraps -def pedir(_decir): - @wraps(_decir) +def pedir(target_function): + @wraps(target_function) def wrapper(*args, **kwargs): - mensaje, decir_por_favor = _decir(*args, **kwargs) - if decir_por_favor: - return "{} {}".format(mensaje, "¡Por favor! Soy pobre :(") - return mensaje + msg, por_favor = target_function(*args, **kwargs) + if por_favor: + return "{} {}".format(msg, "¡Por favor! Soy pobre :(") + return msg return wrapper @pedir -def say(decir_por_favor=False): - mensaje = "¿Puedes comprarme una cerveza?" - return mensaje, decir_por_favor - +def hablar(por_favor=False): + msg = "¿Me puedes comprar una cerveza?" + return msg, por_favor -print(decir()) # ¿Puedes comprarme una cerveza? -print(decir(decir_por_favor=True)) # ¿Puedes comprarme una cerveza? ¡Por favor! Soy pobre :() +print hablar() # ¿Me puedes comprar una cerveza? +print hablar(por_favor=True) # ¿Me puedes comprar una cerveza? ¡Por favor! Soy pobre :( ``` ## ¿Listo para más? @@ -563,10 +549,9 @@ print(decir(decir_por_favor=True)) # ¿Puedes comprarme una cerveza? ¡Por favo * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) +* [The Official Docs](http://docs.python.org/2.6/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/3/) +* [Python Module of the Week](http://pymotw.com/2/) * [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) ### Encuadernados diff --git a/es-es/r-es.html.markdown b/es-es/r-es.html.markdown index 2b710b27..850952fa 100644 --- a/es-es/r-es.html.markdown +++ b/es-es/r-es.html.markdown @@ -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. diff --git a/es-es/perl6-es.html.markdown b/es-es/raku-es.html.markdown index bf3ae65e..09341056 100644 --- a/es-es/perl6-es.html.markdown +++ b/es-es/raku-es.html.markdown @@ -1,8 +1,8 @@ --- -name: perl6 +name: Raku category: language -language: perl6 -filename: perl6-es.p6 +language: Raku +filename: learnraku-es.raku contributors: - ["vendethiel", "http://github.com/vendethiel"] - ["Samantha McVey", "https://cry.nu"] @@ -11,10 +11,10 @@ translators: lang: es-es --- -Perl 6 es un lenguaje de programación altamente capaz y con características +Raku es un lenguaje de programación altamente capaz y con características abundantes para hacerlo el lenguage ideal por los próximos 100 años. -El compilador primario de Perl 6 se llama [Rakudo](http://rakudo.org), el cual +El compilador primario de Raku se llama [Rakudo](http://rakudo.org), el cual se ejecuta en JVM y en [MoarVM](http://moarvm.com). Meta-nota: dos signos de números (##) son usados para indicar párrafos, @@ -26,7 +26,7 @@ mientras que un solo signo de número (#) indica notas. # Un comentario de una sola línea comienza con un signo de número #`( - Comentarios multilíneas usan #` y signos de encerradura tales + Comentarios multilíneas usan #` y signos de encerradura tales como (), [], {}, 「」, etc. ) ``` @@ -34,28 +34,28 @@ mientras que un solo signo de número (#) indica notas. ## Variables ```perl6 -## En Perl 6, se declara una variable lexical usando `my` +## En Raku, se declara una variable lexical usando `my` my $variable; -## Perl 6 tiene 3 tipos básicos de variables: escalares, arrays, y hashes. +## Raku tiene 3 tipos básicos de variables: escalares, arrays, y hashes. ``` ### Escalares ```perl6 -# Un escalar representa un solo valor. Variables escalares comienzan +# Un escalar representa un solo valor. Variables escalares comienzan # con un `$` my $str = 'Cadena'; -# Las comillas inglesas ("") permiten la intepolación (lo cual veremos +# Las comillas inglesas ("") permiten la intepolación (lo cual veremos # luego): my $str2 = "Cadena"; ## Los nombres de variables pueden contener pero no terminar con comillas -## simples y guiones. Sin embargo, pueden contener +## simples y guiones. Sin embargo, pueden contener ## (y terminar con) guiones bajos (_): my $nombre'de-variable_ = 5; # Esto funciona! -my $booleano = True; # `True` y `False` son valores booleanos en Perl 6. +my $booleano = True; # `True` y `False` son valores booleanos en Raku. my $inverso = !$booleano; # Puedes invertir un booleano con el operador prefijo `!` my $bool-forzado = so $str; # Y puedes usar el operador prefijo `so` que # convierte su operador en un Bool @@ -70,7 +70,7 @@ my $bool-forzado = so $str; # Y puedes usar el operador prefijo `so` que my @array = 'a', 'b', 'c'; # equivalente a: my @letras = <a b c>; # array de palabras, delimitado por espacios. - # Similar al qw de perl5, o el %w de Ruby. + # Similar al qw de perl, o el %w de Ruby. my @array = 1, 2, 3; say @array[2]; # Los índices de un array empiezan por el 0 -- Este es @@ -83,7 +83,7 @@ say "Interpola todos los elementos de un array usando [] : @array[]"; @array[0, 1] = 5, 6; # Asigna varios valores my @llaves = 0, 2; -@array[@llaves] = @letras; # Asignación usando un array que contiene valores +@array[@llaves] = @letras; # Asignación usando un array que contiene valores # índices say @array; #=> a 6 b ``` @@ -93,19 +93,19 @@ say @array; #=> a 6 b ```perl6 ## Un hash contiene parejas de llaves y valores. ## Puedes construir un objeto Pair usando la sintaxis `LLave => Valor`. -## Tablas de hashes son bien rápidas para búsqueda, y son almacenadas +## Tablas de hashes son bien rápidas para búsqueda, y son almacenadas ## sin ningún orden. ## Ten en cuenta que las llaves son "aplanadas" en contexto de hash, y ## cualquier llave duplicada es deduplicada. my %hash = 1 => 2, 3 => 4; -my %hash = foo => "bar", # las llaves reciben sus comillas +my %hash = foo => "bar", # las llaves reciben sus comillas # automáticamente. "some other" => "value", # las comas colgantes estań bien. ; ## Aunque los hashes son almacenados internamente de forma diferente a los -## arrays, Perl 6 te permite crear un hash usando un array +## arrays, Raku te permite crear un hash usando un array ## con un número par de elementos fácilmente. my %hash = <llave1 valor1 llave2 valor2>; @@ -122,7 +122,7 @@ my %hash = :w(1), # equivalente a `w => 1` say %hash{'llave1'}; # Puedes usar {} para obtener el valor de una llave say %hash<llave2>; # Si es una cadena de texto, puedes actualmente usar <> - # (`{llave1}` no funciona, debido a que Perl 6 no tiene + # (`{llave1}` no funciona, debido a que Raku no tiene # palabras desnudas (barewords en inglés)) ``` @@ -133,7 +133,7 @@ say %hash<llave2>; # Si es una cadena de texto, puedes actualmente usar <> ## creadas con la palabra clave `sub`. sub di-hola { say "¡Hola, mundo!" } -## Puedes proveer argumentos (tipados). Si especificado, +## Puedes proveer argumentos (tipados). Si especificado, ## el tipo será chequeado al tiempo de compilación si es posible. ## De lo contrario, al tiempo de ejecución. sub di-hola-a(Str $nombre) { @@ -165,7 +165,7 @@ say return-for; # imprime Nil ## Una subrutina puede tener argumentos opcionales: sub con-opcional($arg?) { # el signo "?" marca el argumento opcional - say "Podría returnar `(Any)` (valor de Perl parecido al 'null') si no me pasan + say "Podría returnar `(Any)` (valor de Perl parecido al 'null') si no me pasan un argumento, o returnaré mi argumento"; $arg; } @@ -173,7 +173,7 @@ con-opcional; # devuelve Any con-opcional(); # devuelve Any con-opcional(1); # devuelve 1 -## También puedes proveer un argumento por defecto para +## También puedes proveer un argumento por defecto para ## cuando los argumentos no son proveídos: sub hola-a($nombre = "Mundo") { say "¡Hola, $nombre!"; @@ -190,10 +190,10 @@ sub con-nombre($arg-normal, :$nombrado) { } con-nombre(1, nombrado => 6); #=> 7 ## Sin embargo, debes tener algo en cuenta aquí: -## Si pones comillas alrededor de tu llave, Perl 6 no será capaz de verla +## Si pones comillas alrededor de tu llave, Raku no será capaz de verla ## al tiempo de compilación, y entonces tendrás un solo objeto Pair como -## un argumento posicional, lo que significa que el siguiente ejemplo -## falla: +## un argumento posicional, lo que significa que el siguiente ejemplo +## falla: con-nombre(1, 'nombrado' => 6); con-nombre(2, :nombrado(5)); #=> 7 @@ -205,7 +205,7 @@ sub con-nombre-mandatorio(:$str!) { } con-nombre-mandatorio(str => "Mi texto"); #=> Mi texto! con-nombre-mandatorio; # error al tiempo de ejecución: - # "Required named parameter not passed" + # "Required named parameter not passed" # ("Parámetro nombrado requerido no proveído") con-nombre-mandatorio(3);# error al tiempo de ejecución: # "Too many positional parameters passed" @@ -226,7 +226,7 @@ sub nombrado-definido(:$def = 5) { nombrado-definido; #=> 5 nombrado-definido(def => 15); #=> 15 -## Dado que puedes omitir los paréntesis para invocar una función sin +## Dado que puedes omitir los paréntesis para invocar una función sin ## argumentos, necesitas usar "&" en el nombre para almacenar la función ## `di-hola` en una variable. my &s = &di-hola; @@ -240,8 +240,8 @@ sub muchos($principal, *@resto) { #`*@` (slurpy) consumirá lo restante say @resto.join(' / ') ~ "!"; } say muchos('Feliz', 'Cumpleaño', 'Cumpleaño'); #=> Feliz / Cumpleaño! - # Nota que el asterisco (*) no - # consumió el parámetro frontal. + # Nota que el asterisco (*) no + # consumió el parámetro frontal. ## Puedes invocar un función con un array usando el ## operador "aplanador de lista de argumento" `|` @@ -256,12 +256,12 @@ concat3(|@array); #=> a, b, c ## Contenedores ```perl6 -## En Perl 6, valores son actualmente almacenados en "contenedores". -## El operador de asignación le pregunta al contenedor en su izquierda +## En Raku, valores son actualmente almacenados en "contenedores". +## El operador de asignación le pregunta al contenedor en su izquierda ## almacenar el valor a su derecha. Cuando se pasan alrededor, contenedores ## son marcados como inmutables. Esto significa que, en una función, tu ## tendrás un error si tratas de mutar uno de tus argumentos. -## Si realmente necesitas hacerlo, puedes preguntar por un contenedor +## Si realmente necesitas hacerlo, puedes preguntar por un contenedor ## mutable usando `is rw`: sub mutar($n is rw) { $n++; @@ -276,7 +276,7 @@ mutar $m; # ¡$n es ahora 43! ## dado que no contenedor ha sido pasado y números enteros son inmutables ## por naturaleza: -mutar 42; # Parámetro '$n' esperaba un contenedor mutable, +mutar 42; # Parámetro '$n' esperaba un contenedor mutable, # pero recibió un valor Int ## Si en cambio quieres una copia, debes usar `is copy`. @@ -286,7 +286,7 @@ mutar 42; # Parámetro '$n' esperaba un contenedor mutable, my $x = 42; sub x-almacena() is rw { $x } x-almacena() = 52; # En este caso, los paréntesis son mandatorios - # (porque de otra forma, Perl 6 piensa que la función + # (porque de otra forma, Raku piensa que la función # `x-almacena` es un identificador). say $x; #=> 52 ``` @@ -297,9 +297,9 @@ say $x; #=> 52 ```perl6 ## - `if` ## Antes de hablar acerca de `if`, necesitamos saber cuales valores son -## "Truthy" (representa True (verdadero)), y cuales son "Falsey" -## (o "Falsy") -- representa False (falso). Solo estos valores son -## Falsey: 0, (), {}, "", Nil, un tipo (como `Str` o`Int`) y +## "Truthy" (representa True (verdadero)), y cuales son "Falsey" +## (o "Falsy") -- representa False (falso). Solo estos valores son +## Falsey: 0, (), {}, "", Nil, un tipo (como `Str` o`Int`) y ## por supuesto False. Todos los valores son Truthy. if True { say "¡Es verdadero!"; @@ -316,8 +316,8 @@ unless False { ## También puedes usar sus versiones sufijos seguidas por la palabra clave: say "Un poco verdadero" if True; -## - La condicional ternaria, "?? !!" (como `x ? y : z` en otros lenguajes) -## devuelve $valor-si-verdadera si la condición es verdadera y +## - La condicional ternaria, "?? !!" (como `x ? y : z` en otros lenguajes) +## devuelve $valor-si-verdadera si la condición es verdadera y ## $valor-si-falsa si es falsa. ## my $resultado = $valor condición ?? $valor-si-verdadera !! $valor-si-falsa; @@ -338,21 +338,21 @@ say $edad > 18 ?? "Eres un adulto" !! "Eres menor de 18"; ## ## `given` simplemente pone su argumento en `$_` (como un bloque lo haría), ## y `when` lo compara usando el operador de "coincidencia inteligente" (`~~`). -## -## Dado que otras construcciones de Perl 6 usan esta variable (por ejemplo, +## +## Dado que otras construcciones de Raku usan esta variable (por ejemplo, ## el bucle `for`, bloques, etc), esto se significa que el poderoso `when` no -## solo se aplica con un `given`, sino que se puede usar en cualquier +## solo se aplica con un `given`, sino que se puede usar en cualquier ## lugar donde exista una variable `$_`. given "foo bar" { say $_; #=> foo bar - when /foo/ { # No te preocupies acerca de la coincidencia inteligente – + when /foo/ { # No te preocupies acerca de la coincidencia inteligente – # solo ten presente que `when` la usa. # Esto es equivalente a `if $_ ~~ /foo/`. say "¡Yay!"; } when $_.chars > 50 { # coincidencia inteligente con cualquier cosa True es True, - # i.e. (`$a ~~ True`) + # i.e. (`$a ~~ True`) # por lo tanto puedes también poner condiciones "normales". # Este `when` es equivalente a este `if`: # if $_ ~~ ($_.chars > 50) {...} @@ -373,12 +373,12 @@ given "foo bar" { ## pero también puede ser un bucle for al estilo de C: loop { say "¡Este es un bucle infinito!"; - last; # last interrumpe el bucle, como la palabra clave `break` + last; # last interrumpe el bucle, como la palabra clave `break` # en otros lenguajes. } loop (my $i = 0; $i < 5; $i++) { - next if $i == 3; # `next` salta a la siguiente iteración, al igual + next if $i == 3; # `next` salta a la siguiente iteración, al igual # que `continue` en otros lenguajes. Ten en cuenta que # también puedes usar la condicionales postfix (sufijas) # bucles, etc. @@ -391,29 +391,29 @@ for @array -> $variable { } ## Como vimos con `given`, la variable de una "iteración actual" por defecto -## es `$_`. Esto significa que puedes usar `when` en un bucle `for` como +## es `$_`. Esto significa que puedes usar `when` en un bucle `for` como ## normalmente lo harías con `given`. for @array { say "he conseguido a $_"; .say; # Esto es también permitido. - # Una invocación con punto (dot call) sin "tópico" (recibidor) es - # enviada a `$_` por defecto. + # Una invocación con punto (dot call) sin "tópico" (recibidor) es + # enviada a `$_` por defecto. $_.say; # lo mismo de arriba, lo cual es equivalente. } for @array { # Puedes... - next if $_ == 3; # Saltar a la siguiente iteración (`continue` en + next if $_ == 3; # Saltar a la siguiente iteración (`continue` en # lenguages parecido a C) - redo if $_ == 4; # Re-hacer la iteración, manteniendo la + redo if $_ == 4; # Re-hacer la iteración, manteniendo la # misma variable tópica (`$_`) - last if $_ == 5; # Salir fuera del bucle (como `break` + last if $_ == 5; # Salir fuera del bucle (como `break` # en lenguages parecido a C) } -## La sintaxis de "bloque puntiagudo" no es específica al bucle for. -## Es solo una manera de expresar un bloque en Perl 6. +## La sintaxis de "bloque puntiagudo" no es específica al bucle for. +## Es solo una manera de expresar un bloque en Raku. if computación-larga() -> $resultado { say "El resultado es $resultado"; } @@ -423,7 +423,7 @@ if computación-larga() -> $resultado { ```perl6 ## Dados que los lenguajes de la familia Perl son lenguages basados -## mayormente en operadores, los operadores de Perl 6 son actualmente +## mayormente en operadores, los operadores de Raku son actualmente ## subrutinas un poco cómicas en las categorías sintácticas. Por ejemplo, ## infix:<+> (adición) o prefix:<!> (bool not). @@ -455,7 +455,7 @@ if computación-larga() -> $resultado { (1, 2) eqv (1, 3); ## - Operador de coincidencia inteligente (smart matching): `~~` -## Asocia (aliasing en inglés) el lado izquierda a la variable $_ +## Asocia (aliasing en inglés) el lado izquierda a la variable $_ ## y después evalúa el lado derecho. ## Aquí algunas comparaciones semánticas comunes: @@ -464,8 +464,8 @@ if computación-larga() -> $resultado { 'Foo' ~~ 'Foo'; # True si las cadenas de texto son iguales. 12.5 ~~ 12.50; # True si los números son iguales. -## Regex - Para la comparación de una expresión regular en contra -## del lado izquierdo. Devuelve un objeto (Match), el cual evalúa +## Regex - Para la comparación de una expresión regular en contra +## del lado izquierdo. Devuelve un objeto (Match), el cual evalúa ## como True si el regex coincide con el patrón. my $obj = 'abc' ~~ /a/; @@ -475,12 +475,12 @@ say $obj.WHAT; # (Match) ## Hashes 'llave' ~~ %hash; # True si la llave existe en el hash -## Tipo - Chequea si el lado izquierdo "tiene un tipo" (puede chequear +## Tipo - Chequea si el lado izquierdo "tiene un tipo" (puede chequear ## superclases y roles) 1 ~~ Int; # True (1 es un número entero) -## Coincidencia inteligente contra un booleano siempre devuelve ese +## Coincidencia inteligente contra un booleano siempre devuelve ese ## booleano (y lanzará una advertencia). 1 ~~ True; # True @@ -502,13 +502,13 @@ False ~~ True; # True ## Esto también funciona como un atajo para `0..^N`: ^10; # significa 0..^10 -## Esto también nos permite demostrar que Perl 6 tiene arrays +## Esto también nos permite demostrar que Raku tiene arrays ## ociosos/infinitos, usando la Whatever Star: my @array = 1..*; # 1 al Infinito! `1..Inf` es lo mismo. say @array[^10]; # puedes pasar arrays como subíndices y devolverá # un array de resultados. Esto imprimirá # "1 2 3 4 5 6 7 8 9 10" (y no se quedaré sin memoria!) -## Nota: Al leer una lista infinita, Perl 6 "cosificará" los elementos que +## Nota: Al leer una lista infinita, Raku "cosificará" los elementos que ## necesita y los mantendrá en la memoria. Ellos no serán calculados más de ## una vez. Tampoco calculará más elementos de los que necesita. @@ -517,14 +517,14 @@ say @array[^10]; # puedes pasar arrays como subíndices y devolverá say join(' ', @array[15..*]); #=> 15 16 17 18 19 ## lo que es equivalente a: say join(' ', @array[-> $n { 15..$n }]); -## Nota: Si tratas de hacer cualquiera de esos con un array infinito, +## Nota: Si tratas de hacer cualquiera de esos con un array infinito, ## provocará un array infinito (tu programa nunca terminará) ## Puedes usar eso en los lugares que esperaría, como durante la asignación ## a un array my @números = ^20; -## Aquí los números son incrementados por "6"; más acerca del +## Aquí los números son incrementados por "6"; más acerca del ## operador `...` adelante. my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; @números[5..*] = 3, 9 ... *; # aunque la secuencia es infinita, @@ -546,7 +546,7 @@ $a && $b && $c; # Devuelve 0, el primer valor que es False $b || $a; # 1 ## Y porque tu lo querrás, también tienes operadores de asignación -## compuestos: +## compuestos: $a *= 2; # multiplica y asigna. Equivalente a $a = $a * 2; $b %%= 5; # divisible por y asignación. Equivalente $b = $b %% 5; @array .= sort; # invoca el método `sort` y asigna el resultado devuelto. @@ -555,8 +555,8 @@ $b %%= 5; # divisible por y asignación. Equivalente $b = $b %% 5; ## ¡Más sobre subrutinas! ```perl6 -## Como dijimos anteriormente, Perl 6 tiene subrutinas realmente poderosas. -## Veremos unos conceptos claves que la hacen mejores que en cualquier otro +## Como dijimos anteriormente, Raku tiene subrutinas realmente poderosas. +## Veremos unos conceptos claves que la hacen mejores que en cualquier otro ## lenguaje :-). ``` @@ -602,14 +602,14 @@ sub fst(*@ [$fst]) { # o simplemente: `sub fst($fst) { ... }` fst(1); #=> 1 fst(1, 2); # errores con "Too many positional parameters passed" -## También puedes desestructurar hashes (y clases, las cuales -## veremos adelante). La sintaxis es básicamente +## También puedes desestructurar hashes (y clases, las cuales +## veremos adelante). La sintaxis es básicamente ## `%nombre-del-hash (:llave($variable-para-almacenar))`. ## El hash puede permanecer anónimos si solo necesitas los valores extraídos. sub llave-de(% (:azul($val1), :red($val2))) { say "Valores: $val1, $val2."; } -## Después invócala con un hash: (necesitas mantener las llaves +## Después invócala con un hash: (necesitas mantener las llaves ## de los parejas de llave y valor para ser un hash) llave-de({azul => 'blue', rojo => "red"}); #llave-de(%hash); # lo mismo (para un `%hash` equivalente) @@ -621,11 +621,11 @@ sub siguiente-indice($n) { } my $nuevo-n= siguiente-indice(3); # $nuevo-n es ahora 4 -## Este es cierto para todo, excepto para las construcciones de bucles +## Este es cierto para todo, excepto para las construcciones de bucles ## (debido a razones de rendimiento): Hay una razón de construir una lista ## si la vamos a desechar todos los resultados. ## Si todavías quieres construir una, puedes usar la sentencia prefijo `do`: -## (o el prefijo `gather`, el cual veremos luego) +## (o el prefijo `gather`, el cual veremos luego) sub lista-de($n) { do for ^$n { # nota el uso del operador de rango `^` (`0..^N`) $_ # iteración de bucle actual @@ -639,19 +639,19 @@ my @list3 = lista-de(3); #=> (0, 1, 2) ```perl6 ## Puedes crear una lambda con `-> {}` ("bloque puntiagudo") o `{}` ("bloque") my &lambda = -> $argumento { "El argumento pasado a esta lambda es $argumento" } -## `-> {}` y `{}` son casi la misma cosa, excepto que la primerra puede +## `-> {}` y `{}` son casi la misma cosa, excepto que la primerra puede ## tomar argumentos, y la segunda puede ser malinterpretada como un hash ## por el parseador. ## Podemos, por ejemplo, agregar 3 a cada valor de un array usando map: my @arraymas3 = map({ $_ + 3 }, @array); # $_ es el argumento implícito -## Una subrutina (`sub {}`) tiene semánticas diferentes a un -## bloque (`{}` or `-> {}`): Un bloque no tiene "contexto funcional" +## Una subrutina (`sub {}`) tiene semánticas diferentes a un +## bloque (`{}` or `-> {}`): Un bloque no tiene "contexto funcional" ## (aunque puede tener argumentos), lo que significa que si quieres devolver ## algo desde un bloque, vas a returnar desde la función parental. Compara: sub is-in(@array, $elem) { - # esto `devolverá` desde la subrutina `is-in` + # esto `devolverá` desde la subrutina `is-in` # Una vez que la condición evalúa a True, el bucle terminará map({ return True if $_ == $elem }, @array); } @@ -685,7 +685,7 @@ map(sub ($a, $b) { $a + $b + 3 }, @array); # (aquí con `sub`) ### Acerca de tipos... ```perl6 -## Perl 6 es gradualmente tipado. Esto quiere decir que tu especifica el +## Raku es gradualmente tipado. Esto quiere decir que tu especifica el ## tipo de tus variables/argumentos/devoluciones (return), o puedes omitirlos ## y serán "Any" por defecto. ## Obviamente tienes acceso a algunas tipos básicos, como Int y Str. @@ -703,7 +703,7 @@ subset EnteroGrande of Int where * > 500; ### Despacho Múltiple (Multiple Dispatch) ```perl6 -## Perl 6 puede decidir que variante de una subrutina invocar basado en el +## Raku puede decidir que variante de una subrutina invocar basado en el ## tipo de los argumento, o precondiciones arbitrarias, como con un tipo o ## un `where`: @@ -740,9 +740,9 @@ multi sin_ti-o-contigo { } ## Esto es muy útil para muchos propósitos, como subrutinas `MAIN` (de las ## cuales hablaremos luego), y hasta el mismo lenguaje la está usando -## en muchos lugares. +## en muchos lugares. ## -## - `is`, por ejemplo, es actualmente un `multi sub` llamado +## - `is`, por ejemplo, es actualmente un `multi sub` llamado ## `trait_mod:<is>`. ## - `is rw`, es simplemente un despacho a una función con esta signatura: ## sub trait_mod:<is>(Routine $r, :$rw!) {} @@ -754,7 +754,7 @@ multi sin_ti-o-contigo { ## Ámbito (Scoping) ```perl6 -## En Perl 6, a diferencia de otros lenguajes de scripting, (tales como +## En Raku, a diferencia de otros lenguajes de scripting, (tales como ## (Python, Ruby, PHP), debes declarar tus variables antes de usarlas. El ## declarador `my`, del cual aprendiste anteriormente, usa "ámbito léxical". ## Hay otros declaradores (`our`, `state`, ..., ) los cuales veremos luego. @@ -770,7 +770,7 @@ sub externo { } outer()(); #=> 'Foo Bar' -## Como puedes ver, `$archivo-en-ámbito` y `$ámbito-externo` +## Como puedes ver, `$archivo-en-ámbito` y `$ámbito-externo` ## fueron capturados. Pero si intentaramos usar `$bar` fuera de `foo`, ## la variable estaría indefinida (y obtendrías un error al tiempo de ## compilación). @@ -779,12 +779,12 @@ outer()(); #=> 'Foo Bar' ## Twigils ```perl6 -## Hay muchos `twigils` especiales (sigilos compuestos) en Perl 6. -## Los twigils definen el ámbito de las variables. +## Hay muchos `twigils` especiales (sigilos compuestos) en Raku. +## Los twigils definen el ámbito de las variables. ## Los twigils * y ? funcionan con variables regulares: ## * Variable dinámica ## ? Variable al tiempo de compilación -## Los twigils ! y . son usados con los objetos de Perl 6: +## Los twigils ! y . son usados con los objetos de Raku: ## ! Atributo (miembro de la clase) ## . Método (no una variable realmente) @@ -820,20 +820,20 @@ di_ambito(); #=> 1 100 Cambiamos el valor de $*ambito_din_2 en invoca_a_di_ambit ```perl6 ## Para invocar a un método en un objeto, agrega un punto seguido por el -## nombre del objeto: +## nombre del objeto: ## => $object.method ## Las classes son declaradas usando la palabra clave `class`. Los atributos ## son declarados con la palabra clave `has`, y los métodos con `method`. ## Cada atributo que es privado usa el twigil `!`. Por ejemplo: `$!attr`. -## Atributos públicos inmutables usan el twigil `.` (los puedes hacer +## Atributos públicos inmutables usan el twigil `.` (los puedes hacer ## mutables con `is rw`). -## La manera más fácil de recordar el twigil `$.` is comparándolo +## La manera más fácil de recordar el twigil `$.` is comparándolo ## con como los métodos son llamados. -## El modelo de objeto de Perl 6 ("SixModel") es muy flexible, y te permite +## El modelo de objeto de Raku ("SixModel") es muy flexible, y te permite ## agregar métodos dinámicamente, cambiar la semántica, etc ... -## (no hablaremos de todo esto aquí. Por lo tanto, refiérete a: -## https://docs.perl6.org/language/objects.html). +## (no hablaremos de todo esto aquí. Por lo tanto, refiérete a: +## https://docs.raku.org/language/objects.html). class Clase-Atrib { has $.atrib; # `$.atrib` es inmutable. @@ -858,7 +858,7 @@ class Clase-Atrib { }; ## Crear una nueva instancia de Clase-Atrib con $.atrib asignado con 5: -## Nota: No puedes asignarle un valor a atrib-privado desde aquí (más de +## Nota: No puedes asignarle un valor a atrib-privado desde aquí (más de ## esto adelante). my $class-obj = Clase-Atrib.new(atrib => 5); say $class-obj.devolver-valor; #=> 5 @@ -870,12 +870,12 @@ $class-obj.otro-atrib = 10; # En cambio, esto funciona porque el atributo ### Herencia de Objeto ```perl6 -## Perl 6 también tiene herencia (junto a herencia múltiple) +## Raku también tiene herencia (junto a herencia múltiple) ## Mientras los métodos declarados con `method` son heredados, aquellos ## declarados con `submethod` no lo son. ## Submétodos son útiles para la construcción y destrucción de tareas, ## tales como BUILD, o métodos que deben ser anulados por subtipos. -## Aprenderemos acerca de BUILD más adelante. +## Aprenderemos acerca de BUILD más adelante. class Padre { has $.edad; @@ -890,7 +890,7 @@ class Padre { # Herencia usa la palabra clave `is` class Niño is Padre { method hablar { say "Goo goo ga ga" } - # Este método opaca el método `hablar` de Padre. + # Este método opaca el método `hablar` de Padre. # Este niño no ha aprendido a hablar todavía. } my Padre $Richard .= new(edad => 40, nombre => 'Richard'); @@ -899,19 +899,19 @@ $Richard.hablar; #=> "Hola, mi nombre es Richard" ## $Richard es capaz de acceder el submétodo; él sabe como decir su nombre. my Niño $Madison .= new(edad => 1, nombre => 'Madison'); -$Madison.hablar; # imprime "Goo goo ga ga" dado que el método fue cambiado +$Madison.hablar; # imprime "Goo goo ga ga" dado que el método fue cambiado # en la clase Niño. # $Madison.color-favorito # no funciona porque no es heredado ## Cuando se usa `my T $var` (donde `T` es el nombre de la clase), `$var` ## inicia con `T` en si misma, por lo tanto puedes invocar `new` en `$var`. -## (`.=` es sólo la invocación por punto y el operador de asignación: +## (`.=` es sólo la invocación por punto y el operador de asignación: ## `$a .= b` es lo mismo que `$a = $a.b`) ## Por ejemplo, la instancia $Richard pudo también haber sido declarada así: ## my $Richard = Padre.new(edad => 40, nombre => 'Richard'); -## También observa que `BUILD` (el método invocado dentro de `new`) -## asignará propiedades de la clase padre, por lo que puedes pasar +## También observa que `BUILD` (el método invocado dentro de `new`) +## asignará propiedades de la clase padre, por lo que puedes pasar ## `val => 5`. ``` @@ -932,7 +932,7 @@ class Item does PrintableVal { has $.val; ## Cuando se utiliza `does`, un `rol` se mezcla en al clase literalmente: - ## los métodos y atributos se ponen juntos, lo que significa que una clase + ## los métodos y atributos se ponen juntos, lo que significa que una clase ## puede acceder los métodos y atributos privados de su rol (pero no lo inverso!): method access { say $!counter++; @@ -945,17 +945,17 @@ class Item does PrintableVal { ## de su clase hijo/a, pero es un error sin un rol lo hace) ## NOTA: Puedes usar un rol como una clase (con `is ROLE`). En este caso, - ## métodos serán opacados, dado que el compilador considerará `ROLE` - ## como una clase. + ## métodos serán opacados, dado que el compilador considerará `ROLE` + ## como una clase. } ``` ## Excepciones ```perl6 -## Excepciones están construidas al tope de las clases, en el paquete +## Excepciones están construidas al tope de las clases, en el paquete ## `X` (como `X::IO`). -## En Perl 6, excepciones son lanzadas automáticamente. +## En Raku, excepciones son lanzadas automáticamente. open 'foo'; #=> Failed to open file foo: no such file or directory ## También imprimirá la línea donde el error fue lanzado y otra información ## concerniente al error. @@ -966,16 +966,16 @@ die 'Error!'; #=> Error! ## O más explícitamente: die X::AdHoc.new(payload => 'Error!'); -## En Perl 6, `orelse` es similar al operador `or`, excepto que solamente +## En Raku, `orelse` es similar al operador `or`, excepto que solamente ## coincide con variables indefinidas, en cambio de cualquier cosa ## que evalúa a falso. -## Valores indefinidos incluyen: `Nil`, `Mu` y `Failure`, también como +## Valores indefinidos incluyen: `Nil`, `Mu` y `Failure`, también como ## `Int`, `Str` y otros tipos que no han sido inicializados a ningún valor ## todavía. ## Puedes chequear si algo está definido o no usando el método defined: my $no-inicializada; say $no-inicializada.defined; #=> False -## Al usar `orelse`, se desarmará la excepción y creará un alias de dicho +## Al usar `orelse`, se desarmará la excepción y creará un alias de dicho ## fallo en $_ ## Esto evitará que sea automáticamente manejado e imprima una marejada de ## mensajes de errores en la pantalla. @@ -986,7 +986,7 @@ open 'foo' orelse say "Algo pasó {.exception}"; open 'foo' orelse say "Algo pasó $_"; #=> Algo pasó #=> Failed to open file foo: no such file or directory ## Ambos ejemplos anteriores funcionan pero en caso de que consigamos un -## objeto desde el lado izquierdo que no es un fallo, probablemente +## objeto desde el lado izquierdo que no es un fallo, probablemente ## obtendremos una advertencia. Más abajo vemos como usar `try` y `CATCH` ## para ser más expecíficos con las excepciones que capturamos. ``` @@ -994,8 +994,8 @@ open 'foo' orelse say "Algo pasó $_"; #=> Algo pasó ### Usando `try` y `CATCH` ```perl6 -## Al usar `try` y `CATCH`, puedes contener y manejar excepciones sin -## interrumpir el resto del programa. `try` asignará la última excepción +## Al usar `try` y `CATCH`, puedes contener y manejar excepciones sin +## interrumpir el resto del programa. `try` asignará la última excepción ## a la variable especial `$!`. ## Nota: Esto no tiene ninguna relación con las variables $!. @@ -1003,12 +1003,12 @@ try open 'foo'; say "Bueno, lo intenté! $!" if defined $!; #=> Bueno, lo intenté! Failed to open file #foo: no such file or directory ## Ahora, ¿qué debemos hacer si queremos más control sobre la excepción? -## A diferencia de otros lenguajes, en Perl 6 se pone el bloque `CATCH` +## A diferencia de otros lenguajes, en Raku se pone el bloque `CATCH` ## *dentro* del bloque a intentar (`try`). Similarmente como $_ fue asignada ## cuando 'disarmamos' la excepción con `orelse`, también usamos $_ en el ## bloque CATCH. ## Nota: ($! es solo asignada *después* del bloque `try`) -## Por defecto, un bloque `try` tiene un bloque `CATCH` que captura +## Por defecto, un bloque `try` tiene un bloque `CATCH` que captura ## cualquier excepción (`CATCH { default {} }`). try { my $a = (0 %% 0); CATCH { say "Algo pasó: $_" } } @@ -1022,9 +1022,9 @@ try { when X::AdHoc { say "Error: $_" } #=>Error: Failed to open file /dir/foo: no such file or directory - ## Cualquier otra excepción será levantada de nuevo, dado que no + ## Cualquier otra excepción será levantada de nuevo, dado que no ## tenemos un `default`. - ## Básicamente, si un `when` + ## Básicamente, si un `when` ## Basically, if a `when` matches (or there's a `default`) marks the ## exception as ## "handled" so that it doesn't get re-thrown from the `CATCH`. @@ -1032,14 +1032,14 @@ try { } } -## En Perl 6, excepciones poseen ciertas sutilezas. Algunas -## subrutinas en Perl 6 devuelven un `Failure`, el cual es un tipo de +## En Raku, excepciones poseen ciertas sutilezas. Algunas +## subrutinas en Raku devuelven un `Failure`, el cual es un tipo de ## "excepción no levantada". Ellas no son levantadas hasta que tu intentas -## mirar a sus contenidos, a menos que invoques `.Bool`/`.defined` sobre +## mirar a sus contenidos, a menos que invoques `.Bool`/`.defined` sobre ## ellas - entonces, son manejadas. ## (el método `.handled` es `rw`, por lo que puedes marcarlo como `False` ## por ti mismo) -## Puedes levantar un `Failure` usando `fail`. Nota que si el pragma +## Puedes levantar un `Failure` usando `fail`. Nota que si el pragma ## `use fatal` estás siendo utilizado, `fail` levantará una excepión (como ## `die`). fail "foo"; # No estamos intentando acceder el valor, por lo tanto no problema. @@ -1053,27 +1053,27 @@ try { ## También hay otro tipo de excepción: Excepciones de control. ## Esas son excepciones "buenas", las cuales suceden cuando cambias el flujo ## de tu programa, usando operadores como `return`, `next` or `last`. -## Puedes capturarlas con `CONTROL` (no lista un 100% en Rakudo todavía). +## Puedes capturarlas con `CONTROL` (no lista un 100% en Rakudo todavía). ``` ## Paquetes ```perl6 -## Paquetes son una manera de reusar código. Paquetes son como -## "espacio de nombres" (namespaces en inglés), y cualquier elemento del +## Paquetes son una manera de reusar código. Paquetes son como +## "espacio de nombres" (namespaces en inglés), y cualquier elemento del ## modelo seis (`module`, `role`, `class`, `grammar`, `subset` y `enum`) -## son paquetes por ellos mismos. (Los paquetes son como el mínimo común +## son paquetes por ellos mismos. (Los paquetes son como el mínimo común ## denominador) -## Los paquetes son importantes - especialmente dado que Perl es bien +## Los paquetes son importantes - especialmente dado que Perl es bien ## reconocido por CPAN, the Comprehensive Perl Archive Nertwork. ## Puedes usar un módulo (traer sus declaraciones al ámbito) con `use` use JSON::Tiny; # si intalaste Rakudo* o Panda, tendrás este módulo say from-json('[1]').perl; #=> [1] -## A diferencia de Perl 5, no deberías declarar paquetes usando +## A diferencia de Perl, no deberías declarar paquetes usando ## la palabra clave `package`. En vez, usa `class Nombre::Paquete::Aquí;` -## para declarar una clase, o si solamente quieres exportar +## para declarar una clase, o si solamente quieres exportar ## variables/subrutinas, puedes usar `module`. module Hello::World { # forma de llaves @@ -1083,11 +1083,11 @@ module Hello::World { # forma de llaves } unit module Parse::Text; # forma de ámbito de archivo -grammar Parse::Text::Grammar { # Una gramática (grammar en inglés) es un paquete, +grammar Parse::Text::Grammar { # Una gramática (grammar en inglés) es un paquete, # en el cual puedes usar `use` } # Aprenderás más acerca de gramáticas en la sección de regex -## Como se dijo anteriormente, cualquier parte del modelo seis es también un +## Como se dijo anteriormente, cualquier parte del modelo seis es también un ## paquete. Dado que `JSON::Tiny` usa su propia clase `JSON::Tiny::Actions`, ## tu puedes usarla de la manera siguiente: my $acciones = JSON::Tiny::Actions.new; @@ -1098,13 +1098,13 @@ my $acciones = JSON::Tiny::Actions.new; ## Declaradores ```perl6 -## En Perl 6, tu obtienes diferentes comportamientos basado en como declaras +## En Raku, tu obtienes diferentes comportamientos basado en como declaras ## una variable. ## Ya has visto `my` y `has`, ahora exploraremos el resto. ## * las declaraciones `our` ocurren al tiempo `INIT` (ve "Phasers" más abajo) ## Es como `my`, pero también crea una variable paquete. -## (Todas las cosas relacionadas con paquetes (`class`, `role`, etc) son +## (Todas las cosas relacionadas con paquetes (`class`, `role`, etc) son ## `our` por defecto) module Var::Incrementar { our $nuestra-var = 1; # Nota: No puedes colocar una restricción de tipo @@ -1132,7 +1132,7 @@ Var::Incrementar::Inc; #=> 3 # Nota como el valor de $nuestra-var fue Var::Incrementar::no-disponible; #=> Could not find symbol '&no-disponible' ## * `constant` (ocurre al tiempo `BEGIN`) -## Puedes usar la palabra clave `constant` para declarar una +## Puedes usar la palabra clave `constant` para declarar una ## variable/símbolo al tiempo de compilación: constant Pi = 3.14; constant $var = 1; @@ -1151,11 +1151,11 @@ sub aleatorio-fijo { aleatorio-fijo for ^10; # imprimirá el mismo número 10 veces ## Nota, sin embargo, que ellas existen separadamente en diferentes contextos. -## Si declaras una función con un `state` dentro de un bucle, recreará la +## Si declaras una función con un `state` dentro de un bucle, recreará la ## variable por cada iteración del bucle. Observa: for ^5 -> $a { sub foo { - state $valor = rand; # Esto imprimirá un valor diferente + state $valor = rand; # Esto imprimirá un valor diferente # por cada valor de `$a` } for ^5 -> $b { @@ -1165,11 +1165,11 @@ for ^5 -> $a { } ``` -## Phasers +## Phasers ```perl6 -## Un phaser en Perl 6 es un bloque que ocurre a determinados puntos de tiempo -## en tu programa. Se les llama phaser porque marca un cambio en la fase de +## Un phaser en Raku es un bloque que ocurre a determinados puntos de tiempo +## en tu programa. Se les llama phaser porque marca un cambio en la fase de ## de tu programa. Por ejemplo, cuando el programa es compilado, un bucle ## for se ejecuta, dejas un bloque, o una excepción se levanta. ## (¡`CATCH` es actualmente un phaser!) @@ -1191,13 +1191,13 @@ END { say "Se ejecuta al tiempo de ejecución, " ~ "tan tarde como sea posible, una sola vez" } ## * Phasers de bloques -ENTER { say "[*] Se ejecuta cada vez que entra en un bloque, " ~ +ENTER { say "[*] Se ejecuta cada vez que entra en un bloque, " ~ "se repite en bloques de bucle" } -LEAVE { say "Se ejecuta cada vez que abandona un bloque, incluyendo " ~ +LEAVE { say "Se ejecuta cada vez que abandona un bloque, incluyendo " ~ "cuando una excepción ocurre. Se repite en bloques de bucle"} PRE { - say "Impone una precondición a cada entrada de un bloque, " ~ + say "Impone una precondición a cada entrada de un bloque, " ~ "antes que ENTER (especialmente útil para bucles)"; say "Si este bloque no returna un valor truthy, " ~ "una excepción del tipo X::Phaser::PrePost será levantada."; @@ -1209,7 +1209,7 @@ for 0..2 { } POST { - say "Impone una postcondAsserts a poscondición a la salida de un bloque, " ~ + say "Impone una postcondAsserts a poscondición a la salida de un bloque, " ~ "después de LEAVE (especialmente útil para bucles)"; say "Si este bloque no returna un valor truthy, " ~ "una excepción del tipo X::Phaser::PrePost será levantada, como con PRE."; @@ -1250,14 +1250,14 @@ sub do-db-stuff { ## Prefijos de sentencias ```perl6 -## Los prefijos de sentencias actúan como los phasers: Ellos afectan el +## Los prefijos de sentencias actúan como los phasers: Ellos afectan el ## comportamiento del siguiente código. ## Debido a que son ejecutados en línea con el código ejecutable, ellos ## se escriben en letras minúsculas. (`try` and `start` están teoréticamente ## en esa lista, pero serán explicados en otra parte) ## Nota: Ningunos de estos (excepto `start`) necesitan las llaves `{` y `}`. -## - `do` (el cual ya viste) - ejecuta un bloque o una sentencia como un +## - `do` (el cual ya viste) - ejecuta un bloque o una sentencia como un ## término. ## Normalmente no puedes usar una sentencia como un valor (o término): ## @@ -1289,7 +1289,7 @@ say join ',', gather if False { ## - `eager` - Evalúa una sentencia ávidamente (forza contexto ávido) ## No intentes esto en casa: ## -## eager 1..*; # esto probablemente se colgará por un momento +## eager 1..*; # esto probablemente se colgará por un momento ## # (y podría fallar...). ## ## Pero considera lo siguiente: @@ -1302,13 +1302,13 @@ constant tres-veces = eager gather for ^3 { say take $_ }; #=> 0 1 2 ## Iterables ```perl6 -## En Perl 6, los iterables son objetos que pueden ser iterados similar -## a la construcción `for`. +## En Raku, los iterables son objetos que pueden ser iterados similar +## a la construcción `for`. ## `flat`, aplana iterables: say (1, 10, (20, 10) ); #=> (1 10 (20 10)) Nota como la agrupación se mantiene say (1, 10, (20, 10) ).flat; #=> (1 10 20 10) Ahora el iterable es plano -## - `lazy` - Aplaza la evaluación actual hasta que el valor sea requirido +## - `lazy` - Aplaza la evaluación actual hasta que el valor sea requirido ## (forza contexto perezoso) my @lazy-array = (1..100).lazy; say @lazy-array.is-lazy; #=> True # Chequea por "pereza" con el método `is-lazy`. @@ -1333,7 +1333,7 @@ quietly { warn 'Esto es una advertencia!' }; #=> No salida ## ¡Todo el mundo ama los operadores! Tengamos más de ellos. ## La lista de precedencia puede ser encontrada aquí: -## https://docs.perl6.org/language/operators#Operator_Precedence +## https://docs.raku.org/language/operators#Operator_Precedence ## Pero primero, necesitamos un poco de explicación acerca ## de la asociatividad: @@ -1356,7 +1356,7 @@ $a ! $b ! $c; # con asociatividad de lista `!`, esto es `infix:<>` ## Okay, has leído todo esto y me imagino que debería mostrarte ## algo interesante. ## Te mostraré un pequeño secreto (o algo no tan secreto): -## En Perl 6, todos los operadores son actualmente solo subrutinas. +## En Raku, todos los operadores son actualmente solo subrutinas. ## Puedes declarar un operador como declaras una subrutina: sub prefix:<ganar>($ganador) { # se refiere a las categorías de los operadores @@ -1374,14 +1374,14 @@ sub postfix:<!>(Int $n) { } say 5!; #=> 120 # Operadores sufijos (postfix) van *directamente* después del témino. - # No espacios en blanco. Puedes usar paréntesis para disambiguar, + # No espacios en blanco. Puedes usar paréntesis para disambiguar, # i.e. `(5!)!` sub infix:<veces>(Int $n, Block $r) { # infijo va en el medio for ^$n { $r(); # Necesitas los paréntesis explícitos para invocar la función - # almacenada en la variable `$r`. De lo contrario, te estaría + # almacenada en la variable `$r`. De lo contrario, te estaría # refiriendo a la variable (no a la función), como con `&r`. } } @@ -1399,33 +1399,33 @@ say [5]; #=> 3125 # un circunfijo va alrededor. De nuevo, no espacios en blanco. sub postcircumfix:<{ }>(Str $s, Int $idx) { - ## un pos-circunfijo es + ## un pos-circunfijo es ## "después de un término y alrededor de algo" $s.substr($idx, 1); } say "abc"{1}; #=> b # depués del término `"abc"`, y alrededor del índice (1) -## Esto es de gran valor -- porque todo en Perl 6 usa esto. +## Esto es de gran valor -- porque todo en Raku usa esto. ## Por ejemplo, para eliminar una llave de un hash, tu usas el adverbio ## `:delete` (un simple argumento con nombre debajo): %h{$llave}:delete; ## es equivalente a: -postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar +postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar # operadores de esta forma) -## ¡*Todos* usan los mismos bloques básicos! +## ¡*Todos* usan los mismos bloques básicos! ## Categorías sintácticas (prefix, infix, ...), argumentos nombrados ## (adverbios), ... - usados para construir el lenguaje - están al alcance ## de tus manos y disponibles para ti. -## (obviamente, no se te recomienda que hagas un operador de *cualquier +## (obviamente, no se te recomienda que hagas un operador de *cualquier ## cosa* -- Un gran poder conlleva una gran responsabilidad.) ``` ### Meta-operadores! ```perl6 -## ¡Prepárate! Prepárate porque nos estamos metiendo bien hondo -## en el agujero del conejo, y probablemente no querrás regresar a +## ¡Prepárate! Prepárate porque nos estamos metiendo bien hondo +## en el agujero del conejo, y probablemente no querrás regresar a ## otros lenguajes después de leer esto. ## (Me imagino que ya no quieres a este punto). ## Meta-operadores, como su nombre lo sugiere, son operadores *compuestos*. @@ -1434,14 +1434,14 @@ postcircumfix:<{ }>(%h, $llave, :delete); # (puedes invocar ## * El meta-operador reduce (reducir) ## Es un meta-operador prefijo que toman una función binaria y ## una o varias listas. Sino se pasa ningún argumento, -## returna un "valor por defecto" para este operador +## returna un "valor por defecto" para este operador ## (un valor sin significado) o `Any` si no hay ningún valor. ## -## De lo contrario, remueve un elemento de la(s) lista(s) uno a uno, y +## De lo contrario, remueve un elemento de la(s) lista(s) uno a uno, y ## aplica la función binaria al último resultado (o al primer elemento de ## la lista y el elemento que ha sido removido). ## -## Para sumar una lista, podrías usar el meta-operador "reduce" con `+`, +## Para sumar una lista, podrías usar el meta-operador "reduce" con `+`, ## i.e.: say [+] 1, 2, 3; #=> 6 ## es equivalente a `(1+2)+3` @@ -1461,20 +1461,20 @@ say [+] (); #=> 0 # valores sin significado, dado que N*1=N y N+0=N. say [//]; #=> (Any) # No hay valor por defecto para `//`. -## También puedes invocarlo con una función de tu creación usando +## También puedes invocarlo con una función de tu creación usando ## los dobles corchetes: sub add($a, $b) { $a + $b } say [[&add]] 1, 2, 3; #=> 6 ## * El meta-operador zip -## Este es un meta-operador infijo que también puede ser usado como un +## Este es un meta-operador infijo que también puede ser usado como un ## operador "normal". Toma una función binaria opcional (por defecto, solo -## crear un par), y remueve un valor de cada array e invoca su función +## crear un par), y remueve un valor de cada array e invoca su función ## binaria hasta que no tenga más elementos disponibles. Al final, returna ## un array con todos estos nuevos elementos. -(1, 2) Z (3, 4); # ((1, 3), (2, 4)), dado que por defecto, la función +(1, 2) Z (3, 4); # ((1, 3), (2, 4)), dado que por defecto, la función # crea un array. -1..3 Z+ 4..6; # (5, 7, 9), usando la función personalizada infix:<+> +1..3 Z+ 4..6; # (5, 7, 9), usando la función personalizada infix:<+> ## Dado que `Z` tiene asociatividad de lista (ve la lista más arriba), ## puedes usarlo en más de una lista @@ -1487,13 +1487,13 @@ say [[&add]] 1, 2, 3; #=> 6 ## Y para terminar la lista de operadores: ## * El operador secuencia -## El operador secuencia es uno de la más poderosas características de -## Perl 6: Está compuesto, en la izquierda, de la lista que quieres que -## Perl 6 use para deducir (y podría incluir una clausura), y en la derecha, -## un valor o el predicado que dice cuando parar (o Whatever para una +## El operador secuencia es uno de la más poderosas características de +## Raku: Está compuesto, en la izquierda, de la lista que quieres que +## Raku use para deducir (y podría incluir una clausura), y en la derecha, +## un valor o el predicado que dice cuando parar (o Whatever para una ## lista infinita perezosa). my @list = 1, 2, 3 ... 10; # deducción básica -#my @list = 1, 3, 6 ... 10; # esto muere porque Perl 6 no puede deducir el final +#my @list = 1, 3, 6 ... 10; # esto muere porque Raku no puede deducir el final my @list = 1, 2, 3 ...^ 10; # como con rangos, puedes excluir el último elemento # (la iteración cuando el predicado iguala). my @list = 1, 3, 9 ... * > 30; # puedes usar un predicado @@ -1505,8 +1505,8 @@ my @fib = 1, 1, *+* ... *; # lista infinita perezosa de la serie fibonacci, my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalene a lo de arriba) my @fib = 1, 1, { $^a + $^b } ... *; #(... también equivalene a lo de arriba) ## $a and $b siempre tomarán el valor anterior, queriendo decir que -## ellos comenzarán con $a = 1 y $b = 1 (valores que hemos asignado -## de antemano). Por lo tanto, $a = 1 y $b = 2 (resultado del anterior $a+$b), +## ellos comenzarán con $a = 1 y $b = 1 (valores que hemos asignado +## de antemano). Por lo tanto, $a = 1 y $b = 2 (resultado del anterior $a+$b), ## etc. say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 @@ -1519,29 +1519,29 @@ say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 ## Expresiones Regulares ```perl6 -## Estoy seguro que has estado esperando por esta parte. Bien, ahora que -## sabes algo acerca de Perl 6, podemos comenzar. Primeramente, tendrás -## que olvidarte acerca de "PCRE regexps" (perl-compatible regexps) +## Estoy seguro que has estado esperando por esta parte. Bien, ahora que +## sabes algo acerca de Raku, podemos comenzar. Primeramente, tendrás +## que olvidarte acerca de "PCRE regexps" (perl-compatible regexps) ## (expresiones regulares compatible de perl). ## ## IMPORTANTE: No salte esto porque ya sabes acerca de PCRE. Son totalmente -## distintos. Algunas cosas son las mismas (como `?`, `+`, y `*`) pero +## distintos. Algunas cosas son las mismas (como `?`, `+`, y `*`) pero ## algunas veces la semántica cambia (`|`). Asegúrate de leer esto ## cuidadosamente porque podrías trospezarte sino lo haces. ## -## Perl 6 tiene muchas características relacionadas con RegExps. Después de +## Raku tiene muchas características relacionadas con RegExps. Después de ## todo, Rakudo se parsea a si mismo. Primero vamos a estudiar la sintaxis ## por si misma, después hablaremos acerca de gramáticas (parecido a PEG), -## las diferencias entre los declaradores `token`, `regex`, y `rule` y +## las diferencias entre los declaradores `token`, `regex`, y `rule` y ## mucho más. -## Nota aparte: Todavía tienes acceso a los regexes PCRE usando el +## Nota aparte: Todavía tienes acceso a los regexes PCRE usando el ## mofificador `:P5` (Sin embargo, no lo discutiremos en este tutorial). ## -## En esencia, Perl 6 implementa PEG ("Parsing Expression Grammars") +## En esencia, Raku implementa PEG ("Parsing Expression Grammars") ## ("Parseado de Expresiones de Gramáticas") nativamente. El orden jerárquico -## para los parseos ambiguos es determinado por un examen multi-nivel de +## para los parseos ambiguos es determinado por un examen multi-nivel de ## desempate: -## - La coincidencia de token más larga. `foo\s+` le gana a `foo` +## - La coincidencia de token más larga. `foo\s+` le gana a `foo` ## (por 2 o más posiciones) ## - El prefijo literal más largo. `food\w*` le gana a `foo\w*` (por 1) ## - Declaración desde la gramática más derivada a la menos derivada @@ -1550,48 +1550,48 @@ say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 say so 'a' ~~ /a/; #=> True say so 'a' ~~ / a /; #=> True # ¡Más legible con los espacios! -## Nota al lector (del traductor): +## Nota al lector (del traductor): ## Como pudiste haber notado, he decidido traducir "match" y sus diferentes -## formas verbales como "coincidir" y sus diferentes formas. Cuando digo que +## formas verbales como "coincidir" y sus diferentes formas. Cuando digo que ## un regex (o regexp) coincide con cierto texto, me refiero a que el regex ## describe cierto patrón dentro del texto. Por ejemplo, el regex "cencia" -## coincide con el texto "reminiscencia", lo que significa que dentro del +## coincide con el texto "reminiscencia", lo que significa que dentro del ## texto aparece ese patrón de caracteres (una `c`, seguida de una `e`, -## (seguida de una `n`, etc.) +## (seguida de una `n`, etc.) -## En todos nuestros ejemplos, vamos a usar el operador de -## "coincidencia inteligente" contra una expresión regular ("regexp" or +## En todos nuestros ejemplos, vamos a usar el operador de +## "coincidencia inteligente" contra una expresión regular ("regexp" or ## "regex" de aquí en adelante). Estamos convirtiendo el resultado usando `so`, ## pero en efecto, está devolviendo un objeto Match. Ellos saben como responder -## a la indexación de lista, indexación de hash, y devolver la cadena de +## a la indexación de lista, indexación de hash, y devolver la cadena de ## texto coincidente. -## Los resultados de la coincidencia están disponible como `$/` (en +## Los resultados de la coincidencia están disponible como `$/` (en ## ámbito implícito lexical). También puedes usar las variables de captura ## las cuales comienzan con 0: ## `$0`, `$1', `$2`... ## -## Nota que `~~` no hace un chequeo de inicio/final (es decir, +## Nota que `~~` no hace un chequeo de inicio/final (es decir, ## el regexp puede coincider con solo un carácter de la cadena de texto). ## Explicaremos luego como hacerlo. -## En Perl 6, puedes tener un carácter alfanumérico como un literal, +## En Raku, puedes tener un carácter alfanumérico como un literal, ## todo lo demás debe escaparse usando una barra invertida o comillas. -say so 'a|b' ~~ / a '|' b /; # `True`. No sería lo mismo si no se escapara `|` +say so 'a|b' ~~ / a '|' b /; # `True`. No sería lo mismo si no se escapara `|` say so 'a|b' ~~ / a \| b /; # `True`. Otra forma de escaparlo -## El espacio en blanco actualmente no se significa nada en un regexp, +## El espacio en blanco actualmente no se significa nada en un regexp, ## a menos que uses el adverbio `:s` (`:sigspace`, espacio significante). say so 'a b c' ~~ / a b c /; #=> `False`. Espacio no significa nada aquí. say so 'a b c' ~~ /:s a b c /; #=> `True`. Agregamos el modificador `:s` aquí. -## Si usamos solo un espacio entre cadenas de texto en un regexp, Perl 6 +## Si usamos solo un espacio entre cadenas de texto en un regexp, Raku ## nos advertirá: say so 'a b c' ~~ / a b c /; #=> 'False' # Espacio no significa nada aquí. ## Por favor usa comillas o el modificador :s (:sigspace) para suprimir -## esta advertencia, omitir el espacio, o cambiar el espaciamiento. Para -## arreglar esto y hacer los espacios menos ambiguos, usa por lo menos +## esta advertencia, omitir el espacio, o cambiar el espaciamiento. Para +## arreglar esto y hacer los espacios menos ambiguos, usa por lo menos ## dos espacios entre las cadenas de texto o usa el adverbio `:s`. -## Como vimos anteriormente, podemos incorporar `:s` dentro de los +## Como vimos anteriormente, podemos incorporar `:s` dentro de los ## delimitadores de barras. También podemos ponerlos fuera de ellos si ## especificamos `m` for `match` (coincidencia): say so 'a b c' ~~ m:s/a b c/; #=> `True` @@ -1603,7 +1603,7 @@ say so 'abc' ~~ m[a b c]; #=> `True` ## minúsculas y mayúsculas: say so 'ABC' ~~ m:i{a b c}; #=> `True` -## Sin embargo, es importante para como los modificadores son aplicados +## Sin embargo, es importante para como los modificadores son aplicados ## (lo cual verás más abajo)... ## Cuantificando - `?`, `+`, `*` y `**`. @@ -1612,7 +1612,7 @@ so 'ac' ~~ / a b c /; # `False` so 'ac' ~~ / a b? c /; # `True`, la "b" coincidió (apareció) 0 veces. so 'abc' ~~ / a b? c /; # `True`, la "b" coincidió 1 vez. -## ... Como debes saber, espacio en blancos son importante porque +## ... Como debes saber, espacio en blancos son importante porque ## determinan en que parte del regexp es el objetivo del modificador: so 'def' ~~ / a b c? /; # `False`. Solamente la `c` es opcional so 'def' ~~ / a b? c /; # `False`. Espacio en blanco no es significante @@ -1642,7 +1642,7 @@ so 'abbbbbbc' ~~ / a b**3..* c /; # `True` (rangos infinitos no son un problem ## - `<[]>` - Clases de carácteres ## Las clases de carácteres son equivalentes a las clases `[]` de PCRE, -## pero usan una sintaxis de Perl 6: +## pero usan una sintaxis de Raku: say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' ## Puedes usar rangos: @@ -1663,7 +1663,7 @@ so 'foo' ~~ / <-[ f o ]> + /; # False ## ... y componerlos: so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # False (cualquier letra excepto f y o) so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # True (no letra excepto f and o) -so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la +so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la # parte de la izquierda) ``` @@ -1671,7 +1671,7 @@ so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # True (el signo + no reemplaza la ```perl6 ## Grupo: Puedes agrupar partes de tu regexp con `[]`. -## Estos grupos *no son* capturados (como con `(?:)` en PCRE). +## Estos grupos *no son* capturados (como con `(?:)` en PCRE). so 'abc' ~~ / a [ b ] c /; # `True`. El agrupamiento no hace casi nada so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; ## La línea anterior returna `True`. @@ -1680,15 +1680,15 @@ so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; ## Pero esto no va demasiado lejos, porque no podemos actualmente obtener ## devuelta el patrón que coincidió. -## Captura: Podemos actualmente *capturar* los resultados del regexp, +## Captura: Podemos actualmente *capturar* los resultados del regexp, ## usando paréntesis. so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (usando `so` # aquí, `$/` más abajo) -## Ok. Comenzando con las explicaciones de grupos. Como dijimos, +## Ok. Comenzando con las explicaciones de grupos. Como dijimos, ### nuestra objeto `Match` está disponible en la variable `$/`: -say $/; # Imprimirá algo extraño (explicaremos luego) o - # "Nil" si nada coincidió +say $/; # Imprimirá algo extraño (explicaremos luego) o + # "Nil" si nada coincidió ## Como dijimos anteriormente, un objeto Match tiene indexación de array: say $/[0]; #=> 「ABC」 「ABC」 @@ -1696,15 +1696,15 @@ say $/[0]; #=> 「ABC」 「ABC」 # Aquí, tenemos un array de ellos. say $0; # Lo mismo que lo anterior. -## Nuestra captura es `$0` porque es la primera y única captura en el -## regexp. Podrías estarte preguntando porque un array y la respuesta es +## Nuestra captura es `$0` porque es la primera y única captura en el +## regexp. Podrías estarte preguntando porque un array y la respuesta es ## simple: Algunas capturas (indezadas usando `$0`, `$/[0]` o una nombrada) ## será un array si y solo si puedes tener más de un elemento. ## (Así que, con `*`, `+` y `**` (cualquiera los operandos), pero no con `?`). ## Usemos algunos ejemplos para ver como funciona: ## Nota: Pusimos A B C entre comillas para demostrar que el espacio en blanco -## entre ellos no es significante. Si queremos que el espacio en blanco +## entre ellos no es significante. Si queremos que el espacio en blanco ## *sea* significante, podemos utilizar el modificador `:sigspace`. so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # `True` say $/[0]; #=> 「ABC」 @@ -1718,22 +1718,22 @@ say $0.WHAT; #=> (Array) # Un cuantificador específico siempre capturará un Array, # puede ser un rango o un valor específico (hasta 1). -## Las capturas son indezadas por anidación. Esto quiere decir que un grupo -## dentro de un grup estará anidado dentro de su grupo padre: `$/[0][0]`, +## Las capturas son indezadas por anidación. Esto quiere decir que un grupo +## dentro de un grup estará anidado dentro de su grupo padre: `$/[0][0]`, ## para este código: 'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; say $/[0].Str; #=> hello~ say $/[0][0].Str; #=> ~ -## Esto se origina de un hecho bien simple: `$/` no contiene cadenas de -## texto, números enteros o arrays sino que solo contiene objetos Match. -## Estos objetos contienen los métodos `.list`, `.hash` y `.Str`. (Pero -## también puedes usar `match<llave>` para accesar un hash y `match[indice]` +## Esto se origina de un hecho bien simple: `$/` no contiene cadenas de +## texto, números enteros o arrays sino que solo contiene objetos Match. +## Estos objetos contienen los métodos `.list`, `.hash` y `.Str`. (Pero +## también puedes usar `match<llave>` para accesar un hash y `match[indice]` ## para accesar un array. say $/[0].list.perl; #=> (Match.new(...),).list # Podemos ver que es una lista de objetos Match. - # Estos contienen un montón de información: dónde la - # coincidencia comenzó o terminó, el "ast" + # Estos contienen un montón de información: dónde la + # coincidencia comenzó o terminó, el "ast" # (chequea las acciones más abajo), etc. # Verás capturas nombradas más abajo con las gramáticas. @@ -1743,9 +1743,9 @@ so 'abc' ~~ / a [ b | y ] c /; # `True`. o "b" o "y". so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... ## La diferencia entre este `|` y el otro al que estás acustombrado es LTM. -## LTM significa "Longest Token Matching", traducido libremente como +## LTM significa "Longest Token Matching", traducido libremente como ## "Coincidencia de Token Más Larga". Esto significa que el motor ("engine") -## siempre intentará coindidir tanto como sea posible en la cadena de texto. +## siempre intentará coindidir tanto como sea posible en la cadena de texto. ## Básicamente, intentará el patrón más largo que concuerde con el regexp. 'foo' ~~ / fo | foo /; # `foo` porque es más largo. ## Para decidir cual parte es la "más larga", primero separa el regex en @@ -1759,19 +1759,19 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... ## anteriores, aserciones de código, y otras cosas que tradicionalmente no pueden ## ser representadas por regexes normales. ## -## Entonces, todas las alternativas se intentan al mismo tiempo, y la +## Entonces, todas las alternativas se intentan al mismo tiempo, y la ## más larga gana. ## Ejemplos: ## DECLARATIVO | PROCEDIMENTAL / 'foo' \d+ [ <subrule1> || <subrule2> ] /; ## DECLARATIVO (grupos anidados no son un problema) / \s* [ \w & b ] [ c | d ] /; -## Sin embargo, las clausuras y la recursión (de regexes nombrados) +## Sin embargo, las clausuras y la recursión (de regexes nombrados) ## son procedimentales. ## ... Hay más reglas complicadas, como la especifidad (los literales ganan ## son las clases de caracteres) + -## Nota: la primera coincidencia `or` todavía existen, pero ahora se +## Nota: la primera coincidencia `or` todavía existen, pero ahora se ## deletrea `||` 'foo' ~~ / fo || foo /; # `fo` ahora. ``` @@ -1779,19 +1779,19 @@ so 'ayc' ~~ / a [ b | y ] c /; # `True`. Obviamente suficiente... ## Extra: la subrutina MAIN ```perl6 -## La subrutina `MAIN` se invoca cuando tu ejecuta un archivo de Perl 6 -## directamente. Es realmente poderosa porque Perl 6 actualmente parsea -## los argumentos y los pasas a la subrutina. También maneja argumentos +## La subrutina `MAIN` se invoca cuando tu ejecuta un archivo de Raku +## directamente. Es realmente poderosa porque Raku actualmente parsea +## los argumentos y los pasas a la subrutina. También maneja argumentos ## nombrados (`--foo`) y hasta autogenerará un `--help`. sub MAIN($nombre) { say "¡Hola, $nombre!" } ## Esto produce: -## $ perl6 cli.pl +## $ raku cli.pl ## Uso: ## t.pl <nombre> -## Y dado que una subrutina regular en Perl 6, puedes tener múltiples +## Y dado que una subrutina regular en Raku, puedes tener múltiples ## despachos: -## (usando un "Bool" por un argumento nombrado para que podamos hacer +## (usando un "Bool" por un argumento nombrado para que podamos hacer ## `--replace` a cambio de `--replace=1`) subset File of Str where *.IO.d; # convierte a un objeto IO para chequear si # un archivo existe @@ -1800,7 +1800,7 @@ multi MAIN('add', $key, $value, Bool :$replace) { ... } multi MAIN('remove', $key) { ... } multi MAIN('import', File, Str :$as) { ... } # omitiendo parámetros nombrados ## Esto produce: -## $ perl6 cli.pl +## $ raku cli.pl ## Uso: ## t.pl [--replace] add <key> <value> ## t.pl remove <key> @@ -1814,7 +1814,7 @@ multi MAIN('import', File, Str :$as) { ... } # omitiendo parámetros nombrados ### Lista de cosas ```perl6 -## Consideramos que por ahora ya sabes lo básico de Perl 6. +## Consideramos que por ahora ya sabes lo básico de Raku. ## Esta sección es solo para listar algunas operaciones comunes ## las cuales no están en la "parte principal" del tutorial. @@ -1825,13 +1825,13 @@ multi MAIN('import', File, Str :$as) { ... } # omitiendo parámetros nombrados ## (los cuales representan los números -1, 0 o +1). 1 <=> 4; # comparación de orden para caracteres numéricos 'a' leg 'b'; # comparación de orden para cadenas de texto -$obj eqv $obj2; # comparación de orden usando la semántica eqv +$obj eqv $obj2; # comparación de orden usando la semántica eqv ## * Ordenación genérica 3 before 4; # True 'b' after 'a'; # True -## * Operador (por defecto) de circuito corto +## * Operador (por defecto) de circuito corto ## Al igual que `or` y `||`, pero devuelve el primer valor *defined* ## (definido): say Any // Nil // 0 // 5; #=> 0 @@ -1843,9 +1843,9 @@ say True ^^ False; #=> True ## * Flip Flop ## Los operadores flip flop (`ff` y `fff`, equivalente a `..`/`...` en P5) ## son operadores que toman dos predicados para evalualarlos: -## Ellos son `False` hasta que su lado izquierdo devuelve `True`, entonces +## Ellos son `False` hasta que su lado izquierdo devuelve `True`, entonces ## son `True` hasta que su lado derecho devuelve `True`. -## Como los rangos, tu puedes excluir la iteración cuando se convierte en +## Como los rangos, tu puedes excluir la iteración cuando se convierte en ## `True`/`False` usando `^` en cualquier lado. ## Comencemos con un ejemplo: for <well met young hero we shall meet later> { @@ -1861,25 +1861,25 @@ for <well met young hero we shall meet later> { } ## Esto imprimirá "young hero we shall meet" (exluyendo "met"): ## el flip-flop comenzará devolviendo `True` cuando primero encuentra "met" -## (pero no returnará `False` por "met" dabido al `^` al frente de `ff`), +## (pero no returnará `False` por "met" dabido al `^` al frente de `ff`), ## hasta que ve "meet", lo cual es cuando comenzará devolviendo `False`. ## La diferencia entre `ff` (al estilo de awk) y `fff` (al estilo de sed) -## es que `ff` probará su lado derecho cuando su lado izquierdo cambia +## es que `ff` probará su lado derecho cuando su lado izquierdo cambia ## a `True`, y puede returnar a `False` inmediamente (*excepto* que será -## `True` por la iteración con la cual coincidió). Por lo contrario, -## `fff` esperará por la próxima iteración para intentar su lado +## `True` por la iteración con la cual coincidió). Por lo contrario, +## `fff` esperará por la próxima iteración para intentar su lado ## derecho, una vez que su lado izquierdo ha cambiado: .say if 'B' ff 'B' for <A B C B A>; #=> B B # porque el lado derecho se puso a prueba # directamente (y returnó `True`). # Las "B"s se imprimen dadó que coincidió - # en ese momento (returnó a `False` + # en ese momento (returnó a `False` # inmediatamente). .say if 'B' fff 'B' for <A B C B A>; #=> B C B # El lado derecho no se puso a prueba # hasta que `$_` se convirtió en "C" - # (y por lo tanto no coincidió + # (y por lo tanto no coincidió # inmediamente). ## Un flip-flop puede cambiar estado cuantas veces se necesite: @@ -1901,35 +1901,35 @@ for (1, 3, 60, 3, 40, 60) { # Nota: los paréntesis son superfluos aquí ## que no pasará la primera vez: for <a b c> { .say if * ^ff *; # el flip-flop es `True` y nunca returna a `False`, - # pero el `^` lo hace *que no se ejecute* en la + # pero el `^` lo hace *que no se ejecute* en la # primera iteración #=> b c } -## - `===` es la identidad de valor y usa `.WHICH` +## - `===` es la identidad de valor y usa `.WHICH` ## en los objetos para compararlos. -## - `=:=` es la identidad de contenedor y usa `VAR()` +## - `=:=` es la identidad de contenedor y usa `VAR()` ## en los objetos para compararlos. ``` Si quieres ir más allá de lo que se muestra aquí, puedes: - - Leer la [documentación de Perl 6](https://docs.perl6.org/). Esto es un recurso - grandioso acerca de Perl 6. Si estás buscando por algo en particular, usa la + - Leer la [documentación de Raku](https://docs.raku.org/). Esto es un recurso + grandioso acerca de Raku. Si estás buscando por algo en particular, usa la barra de búsquedas. Esto te dará un menú de todas las páginas concernientes a tu término de búsqueda (¡Es mucho mejor que usar Google para encontrar - documentos acerca de Perl 6!) - - Leer el [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). Este es - un gran recurso de fragmentos de código de Perl 6 y explicaciones. Si la documentación + documentos acerca de Raku!) + - Leer el [Raku Advent Calendar](https://rakuadventcalendar.wordpress.com/). Este es + un gran recurso de fragmentos de código de Raku y explicaciones. Si la documentación no describe algo lo suficientemente bien, puedes encontrar información más detallada aquí. Esta información puede ser un poquito más antigua pero hay muchos ejemplos y - explicaciones. Las publicaciones fueron suspendidas al final del 2015 cuando - el lenguaje fue declarado estable y Perl 6.c fue lanzado. - - Unirte a `#perl6` en `irc.freenode.net`. Las personas aquí son siempre serviciales. - - Chequear la [fuente de las funciones y clases de Perl 6 - ](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo está principalmente - escrito en Perl 6 (con mucho de NQP, "Not Quite Perl" ("No Perl Todavía"), un - subconjunto de Perl 6 que es más fácil de implementar y optimizar). - - Leer [documentos acerca del diseño del lenguaje](http://design.perl6.org). + explicaciones. Las publicaciones fueron suspendidas al final del 2015 cuando + el lenguaje fue declarado estable y Raku.c fue lanzado. + - Unirte a `#raku` en `irc.freenode.net`. Las personas aquí son siempre serviciales. + - Chequear la [fuente de las funciones y clases de Raku + ](https://github.com/rakudo/rakudo/tree/master/src/core.c). Rakudo está principalmente + escrito en Raku (con mucho de NQP, "Not Quite Perl" ("No Perl Todavía"), un + subconjunto de Raku que es más fácil de implementar y optimizar). + - Leer [documentos acerca del diseño del lenguaje](http://design.raku.org). Estos explican P6 desde la perspectiva de un implementador, lo cual es bastante interesante. diff --git a/es-es/ruby-es.html.markdown b/es-es/ruby-es.html.markdown index e3e43c18..8b703df1 100644 --- a/es-es/ruby-es.html.markdown +++ b/es-es/ruby-es.html.markdown @@ -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 @@ -139,7 +139,7 @@ status == :pendiente #=> true status == 'pendiente' #=> false -status == :aprovado #=> false +status == :aprobado #=> false # Arreglos diff --git a/es-es/rust-es.html.markdown b/es-es/rust-es.html.markdown index b43cb815..b0a3873c 100644 --- a/es-es/rust-es.html.markdown +++ b/es-es/rust-es.html.markdown @@ -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); } diff --git a/es-es/self-es.html.markdown b/es-es/self-es.html.markdown index 11972214..1f985215 100644 --- a/es-es/self-es.html.markdown +++ b/es-es/self-es.html.markdown @@ -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| diff --git a/es-es/sql-es.html.markdown b/es-es/sql-es.html.markdown new file mode 100644 index 00000000..1ee0d454 --- /dev/null +++ b/es-es/sql-es.html.markdown @@ -0,0 +1,115 @@ +--- +language: SQL +filename: learnsql-es.sql +contributors: + - ["Bob DuCharme", "http://bobdc.com/"] +translators: + - ["FedeHC", "https://github.com/FedeHC"] +lang: es-es +--- + +El lenguaje de consulta estructurada (SQL en inglés) es un lenguaje estándar ISO para crear y trabajar con bases de datos almacenados en un conjunto de tablas. Las implementaciones generalmente añaden sus propias extensiones al lenguaje; [Comparación entre diferentes implementaciones de SQL](http://troels.arvin.dk/db/rdbms/) es una buena referencia sobre las diferencias entre distintos productos. + +Las implementaciones típicamente proveen de una línea de comandos donde uno puede introducir los comandos que se muestran aquí en forma interactiva, y también ofrecen una forma de ejecutar una serie de estos comandos almacenados en un archivo de script (mostrar que uno ha terminado con el prompt interactivo es un buen ejemplo de algo que no está estandarizado - la mayoría de las implementaciones de SQL soportan las palabras clave QUIT, EXIT, o ambas). + +Varios de estos comandos que sirven de ejemplo asumen que la [base de datos de empleados de muestra de MySQL](https://dev.mysql.com/doc/employee/en/) disponible en [github](https://github.com/datacharmer/test_db) ya ha sido cargada. Los archivos github son scripts de comandos, similares a los comandos que aparecen a continuación, que crean y cargan tablas de datos sobre los empleados de una empresa ficticia. La sintaxis para ejecutar estos scripts dependerá de la implementación de SQL que esté utilizando. Una aplicación que se ejecuta desde el prompt del sistema operativo suele ser lo habitual. + + +```sql +-- Los comentarios empiezan con dos guiones. Se termina cada comando con punto +-- y coma. + +-- SQL no distingue entre mayúsculas y minúsculas en palabras clave. Los +-- comandos de ejemplo que aquí se muestran siguen la convención de ser escritos +-- en mayúsculas porque hace más fácil distinguirlos de los nombres de las bases +-- de datos, de las tablas y de las columnas. + +-- A cont. se crea y se elimina una base de datos. Los nombres de la base de +-- datos y de la tabla son sensibles a mayúsculas y minúsculas. +CREATE DATABASE someDatabase; +DROP DATABASE someDatabase; + +-- Lista todas las bases de datos disponibles. +SHOW DATABASES; + +-- Usa una base de datos existente en particular. +USE employees; + +-- Selecciona todas las filas y las columnas de la tabla departments en la base +-- de datos actual. La actividad predeterminada es que el intérprete desplace +-- los resultados por la pantalla. +SELECT * FROM departments; + +-- Recupera todas las filas de la tabla departments, pero sólo las columnas +-- dept_no y dept_name. +-- Separar los comandos en varias líneas está permitido. +SELECT dept_no, + dept_name FROM departments; + +-- Obtiene todas las columnas de departments, pero se limita a 5 filas. +SELECT * FROM departments LIMIT 5; + +-- Obtiene los valores de la columna dept_name desde la tabla departments cuando +-- dept_name tiene como valor la subcadena 'en'. +SELECT dept_name FROM departments WHERE dept_name LIKE '%en%'; + +-- Recuperar todas las columnas de la tabla departments donde la columna +-- dept_name comienza con una 'S' y tiene exactamente 4 caracteres después +-- de ella. +SELECT * FROM departments WHERE dept_name LIKE 'S____'; + +-- Selecciona los valores de los títulos de la tabla titles, pero no muestra +-- duplicados. +SELECT DISTINCT title FROM titles; + +-- Igual que el anterior, pero ordenado por los valores de title (se distingue +-- entre mayúsculas y minúsculas). +SELECT DISTINCT title FROM titles ORDER BY title; + +-- Muestra el número de filas de la tabla departments. +SELECT COUNT(*) FROM departments; + +-- Muestra el número de filas en la tabla departments que contiene 'en' como +-- subcadena en la columna dept_name. +SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%'; + +-- Una unión (JOIN) de información desde varias tablas: la tabla titles muestra +-- quién tiene qué títulos de trabajo, según sus números de empleados, y desde +-- qué fecha hasta qué fecha. Se obtiene esta información, pero en lugar del +-- número de empleado se utiliza el mismo como una referencia cruzada a la +-- tabla employee para obtener el nombre y apellido de cada empleado (y se +-- limita los resultados a 10 filas). +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; + +-- Se enumera todas las tablas de todas las bases de datos. Las implementaciones +-- típicamente proveen sus propios comandos para hacer esto con la base de datos +-- actualmente en uso. +SELECT * FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_TYPE='BASE TABLE'; + +-- Crear una tabla llamada tablename1, con las dos columnas mostradas, a partir +-- de la base de datos en uso. Hay muchas otras opciones disponibles para la +-- forma en que se especifican las columnas, como por ej. sus tipos de datos. +CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20)); + +-- Insertar una fila de datos en la tabla tablename1. Se asume que la tabla ha +-- sido definida para aceptar estos valores como aptos. +INSERT INTO tablename1 VALUES('Richard','Mutt'); + +-- En tablename1, se cambia el valor de fname a 'John' para todas las filas que +-- tengan un valor en lname igual a 'Mutt'. +UPDATE tablename1 SET fname='John' WHERE lname='Mutt'; + +-- Se borra las filas de la tabla tablename1 donde el valor de lname comience +-- con 'M'. +DELETE FROM tablename1 WHERE lname like 'M%'; + +-- Se borra todas las filas de la tabla tablename1, dejando la tabla vacía. +DELETE FROM tablename1; + +-- Se elimina toda la tabla tablename1 por completo. +DROP TABLE tablename1; +``` diff --git a/es-es/swift-es.html.markdown b/es-es/swift-es.html.markdown index 22e3c532..60af1913 100644 --- a/es-es/swift-es.html.markdown +++ b/es-es/swift-es.html.markdown @@ -11,7 +11,7 @@ lang: es-es filename: learnswift-es.swift --- -Swift es un lenguaje de programación para el desarrollo en iOS y OS X creado +Swift es un lenguaje de programación para el desarrollo en iOS y macOS creado por Apple. Diseñado para coexistir con Objective-C y ser más resistente contra el código erroneo, Swift fue introducido en el 2014 en el WWDC, la conferencia de desarrolladores de Apple. diff --git a/es-es/typescript-es.html.markdown b/es-es/typescript-es.html.markdown index c42da4a4..fbe1290b 100644 --- a/es-es/typescript-es.html.markdown +++ b/es-es/typescript-es.html.markdown @@ -12,7 +12,7 @@ TypeScript es un lenguaje cuyo objetivo es facilitar el desarrollo de aplicacion TypeScript añade conceptos comunes como clases, módulos, interfaces, genéricos y (opcionalmente) tipeo estático a JavaScript. Es un superset de JavaScript: todo el código JavaScript es código válido en TypeScript de manera que se puede integrar fácilmente a cualquier proyecto . El compilador TypeScript emite JavaScript. -Este artículo se enfocará solo en la sintáxis extra de TypeScript, y no en [JavaScript] (../javascript/). +Este artículo se enfocará solo en la sintáxis extra de TypeScript, y no en [JavaScript] (../javascript-es/). Para probar el compilador de TypeScript, diríjase al [Área de Pruebas] (http://www.typescriptlang.org/Playground) donde podrá tipear código, y ver como se auto-completa al tiempo que ve el código emitido JavaScript. diff --git a/es-es/visualbasic-es.html.markdown b/es-es/visualbasic-es.html.markdown index c677c20f..fb0b1d27 100644 --- a/es-es/visualbasic-es.html.markdown +++ b/es-es/visualbasic-es.html.markdown @@ -8,7 +8,7 @@ filename: learnvisualbasic-es.vb lang: es-es --- -``` +```visualbasic Module Module1 Sub Main() diff --git a/es-es/wolfram-es.html.markdown b/es-es/wolfram-es.html.markdown index 44ec9e09..6858c286 100644 --- a/es-es/wolfram-es.html.markdown +++ b/es-es/wolfram-es.html.markdown @@ -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 diff --git a/es-es/yaml-es.html.markdown b/es-es/yaml-es.html.markdown index cd3143fb..582fa60e 100644 --- a/es-es/yaml-es.html.markdown +++ b/es-es/yaml-es.html.markdown @@ -3,7 +3,7 @@ language: yaml lang: es-es filename: learnyaml-es.yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] - ["Everardo Medina","https://github.com/everblut"] translators: - ["Daniel Zendejas","https://github.com/DanielZendejas"] diff --git a/fa-ir/css-fa.html.markdown b/fa-ir/css-fa.html.markdown index 4e222eb2..93af9132 100644 --- a/fa-ir/css-fa.html.markdown +++ b/fa-ir/css-fa.html.markdown @@ -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'] diff --git a/fa-ir/javascript-fa.html.markdown b/fa-ir/javascript-fa.html.markdown index fe3555af..d4d3a657 100644 --- a/fa-ir/javascript-fa.html.markdown +++ b/fa-ir/javascript-fa.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] translators: - ["Mohammad Valipour", "https://github.com/mvalipour"] filename: javascript-fa.js @@ -17,8 +17,8 @@ lang: fa-ir قدر دان نظرات سازنده شما هستم! شما میتوانید از طریق زیر با من تماس بگیرید: </p> -[@adambrenecki](https://twitter.com/adambrenecki), or -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). +[@ExcitedLeigh](https://twitter.com/ExcitedLeigh), or +[l@leigh.net.au](mailto:l@leigh.net.au). <p dir='rtl'> // توضیحات همانند C هستند. توضیحات یک خطی با دو خط مورب شروع میشوند., diff --git a/fa-ir/vim-fa.html.markdown b/fa-ir/vim-fa.html.markdown new file mode 100644 index 00000000..f1864619 --- /dev/null +++ b/fa-ir/vim-fa.html.markdown @@ -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) diff --git a/fi-fi/go-fi.html.markdown b/fi-fi/go-fi.html.markdown index af304099..ef88a96e 100644 --- a/fi-fi/go-fi.html.markdown +++ b/fi-fi/go-fi.html.markdown @@ -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/). diff --git a/fi-fi/ruby-fi.html.markdown b/fi-fi/ruby-fi.html.markdown index 52c60182..84a5844f 100644 --- a/fi-fi/ruby-fi.html.markdown +++ b/fi-fi/ruby-fi.html.markdown @@ -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 diff --git a/fish.html.markdown b/fish.html.markdown new file mode 100644 index 00000000..4b70f883 --- /dev/null +++ b/fish.html.markdown @@ -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. + +``` diff --git a/forth.html.markdown b/forth.html.markdown index ff094017..4e2f7599 100644 --- a/forth.html.markdown +++ b/forth.html.markdown @@ -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 diff --git a/fortran.html.markdown b/fortran.html.markdown new file mode 100644 index 00000000..316f8c87 --- /dev/null +++ b/fortran.html.markdown @@ -0,0 +1,457 @@ +--- +language: Fortran +contributors: + - ["Robert Steed", "https://github.com/robochat"] +filename: learnfortran.f90 +--- + +Fortran is one of the oldest computer languages. It was developed in the 1950s +by IBM for numeric calculations (Fortran is an abbreviation of "Formula +Translation"). Despite its age, it is still used for high-performance computing +such as weather prediction. However, the language has changed considerably over +the years, although mostly maintaining backwards compatibility; well known +versions are FORTRAN 77, Fortran 90, Fortran 95, Fortran 2003, Fortran 2008, +Fortran 2018 and Fortran 2023. + +This overview will discuss the features of Fortran 2008 since it is the most +widely implemented of the more recent specifications and the later versions are +largely similar (by comparison FORTRAN 77 is a very different language). + +```fortran + +! This is a comment. + +program example ! declare a program called example. + + ! Code can only exist inside programs, functions, subroutines or modules. + ! Using indentation is not required but it is recommended. + + ! Declaring Variables + ! =================== + + ! All declarations must come before statements and expressions. + + implicit none ! prevents dynamic declaration of variables (recommended!) + ! Implicit none must be redeclared in every function/program/module... + + ! IMPORTANT - Fortran is case insensitive. + real z + REAL Z2 + + real :: v, x ! WARNING: default initial values are compiler dependent! + real :: a = 3, b = 2E12, c = 0.01 + integer :: i, j, k = 1, m + real, parameter :: PI = 3.1415926535897931 ! declare a constant. + logical :: y = .TRUE., n = .FALSE. ! boolean type. + complex :: w = (0, 1) ! sqrt(-1) + character(len=3) :: month ! string of 3 characters. + + real :: array(6) ! declare an array of 6 reals. + real, dimension(4) :: arrayb ! another way to declare an array. + integer :: arrayc(-10:10) ! an array with a custom index. + real :: array2d(3, 2) ! multidimensional array. + + ! The '::' separators are not always necessary but are recommended. + + ! many other variable attributes also exist: + real, pointer :: p ! declare a pointer. + + integer, parameter :: LP = selected_real_kind(20) + real(kind=LP) :: d ! long precision variable. + + ! WARNING: initialising variables during declaration causes problems + ! in functions since this automatically implies the 'save' attribute + ! whereby values are saved between function calls. In general, separate + ! declaration and initialisation code except for constants! + + ! Strings + ! ======= + + character :: a_char = 'i' + character(len=6) :: a_str = "qwerty" + character(len=30) :: str_b + character(len=*), parameter :: a_long_str = "This is a long string." + !can have automatic counting of length using (len=*) but only for constants. + + str_b = a_str//" keyboard" ! concatenate strings using // operator. + + ! Assignment & Arithmetic + ! ======================= + + Z = 1 ! assign to variable z declared above (case insensitive). + j = 10 + 2 - 3 + a = 11.54/(2.3*3.1) + b = 2**3 ! exponentiation + + ! Control Flow Statements & Operators + ! =================================== + + ! Single-line if statement + if (z == a) b = 4 ! condition always need surrounding parentheses. + + if (z /= a) then ! z not equal to a + ! Other symbolic comparisons are < > <= >= == /= + b = 4 + else if (z .GT. a) then ! z greater than a + ! Text equivalents to symbol operators are .LT. .GT. .LE. .GE. .EQ. .NE. + b = 6 + else if (z < a) then ! 'then' must be on this line. + b = 5 ! execution block must be on a new line. + else + b = 10 + end if ! end statement needs the 'if' (or can use 'endif'). + + if (.NOT. (x < c .AND. v >= a .OR. z == z)) then ! boolean operators. + inner: if (.TRUE.) then ! can name if-construct. + b = 1 + end if inner ! then must name endif statement. + end if + + i = 20 + select case (i) + case (0, 1) ! cases i == 0 or i == 1 + j = 0 + case (2:10) ! cases i is 2 to 10 inclusive. + j = 1 + case (11:) ! all cases where i>=11 + j = 2 + case default + j = 3 + end select + + month = 'jan' + ! Condition can be integer, logical or character type. + ! Select constructions can also be named. + monthly:select case(month) + case ("jan") + j = 0 + case default + j = -1 + end select monthly + + do i = 2, 10, 2 ! loops from 2 to 10 (inclusive) in increments of 2. + innerloop: do j = 1, 3 ! loops can be named too. + exit ! quits the loop. + end do innerloop + cycle ! jump to next loop iteration. + end do + + ! Goto statement exists but it is heavily discouraged though. + goto 10 + stop 1 ! stops code immediately (returning specified condition code). +10 j = 201 ! this line is labeled as line 10 + + ! Arrays + ! ====== + array = (/1, 2, 3, 4, 5, 6/) + array = [1, 2, 3, 4, 5, 6] ! using Fortran 2003 notation. + arrayb = [10.2, 3e3, 0.41, 4e-5] + array2d = reshape([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [3, 2]) + + ! Fortran array indexing starts from 1. + ! (by default but can be defined differently for specific arrays). + v = array(1) ! take first element of array. + v = array2d(2, 2) + + print *, array(3:5) ! print all elements from 3rd to 5th (inclusive). + print *, array2d(1, :) ! print first column of 2d array. + + array = array*3 + 2 ! can apply mathematical expressions to arrays. + array = array*array ! array operations occur element-wise. + ! array = array*array2d ! these arrays would not be compatible. + + ! There are many built-in functions that operate on arrays. + c = dot_product(array, array) ! this is the dot product. + ! Use matmul() for matrix maths. + c = sum(array) + c = maxval(array) + print *, minloc(array) + c = size(array) + print *, shape(array) + m = count(array > 0) + + ! Loop over an array (could have used Product() function normally). + v = 1 + do i = 1, size(array) + v = v*array(i) + end do + + ! Conditionally execute element-wise assignments. + array = [1, 2, 3, 4, 5, 6] + where (array > 3) + array = array + 1 + elsewhere(array == 2) + array = 1 + elsewhere + array = 0 + end where + + ! Implied-DO loops are a compact way to create arrays. + array = [(i, i=1, 6)] ! creates an array of [1,2,3,4,5,6] + array = [(i, i=1, 12, 2)] ! creates an array of [1,3,5,7,9,11] + array = [(i**2, i=1, 6)] ! creates an array of [1,4,9,16,25,36] + array = [(4, 5, i=1, 3)] ! creates an array of [4,5,4,5,4,5] + + ! Input/Output + ! ============ + + print *, b ! print the variable 'b' to the command line + + ! We can format our printed output. + print "(I6)", 320 ! prints ' 320' + print "(I6.4)", 3 ! prints ' 0003' + print "(F6.3)", 4.32 ! prints ' 4.320' + + ! The letter indicates the expected type and the number afterwards gives + ! the number of characters to use for printing the value. + ! Letters can be I (integer), F (real), E (engineering format), + ! L (logical), A (characters) ... + print "(I3)", 3200 ! print '***' since the number doesn't fit. + + ! we can have multiple format specifications. + print "(I5,F6.2,E6.2)", 120, 43.41, 43.41 + print "(3I5)", 10, 20, 30 ! 3 repeats of integers (field width = 5). + print "(2(I5,F6.2))", 120, 43.42, 340, 65.3 ! repeated grouping of formats. + + ! We can also read input from the terminal. + read (*, *) v + read (*, "(2F6.2)") v, x ! read two numbers + + ! To write a file. + open (unit=12, file="records.txt", status="replace") + ! The file is referred to by a 'unit number', an integer that you pick in + ! the range 9:99. Status can be one of {'old','replace','new'}. + write (12, "(F10.2,F10.2,F10.2)") c, b, a + close (12) + + ! To read a file. + open (newunit=m, file="records.txt", status="old") + ! The file is referred to by a 'new unit number', an integer that the compiler + ! picks for you. + read (unit=m, fmt="(3F10.2)") a, b, c + close (m) + + ! There are more features available than discussed here and alternative + ! variants due to backwards compatibility with older Fortran versions. + + ! Built-in Functions + ! ================== + + ! Fortran has around 200 functions/subroutines intrinsic to the language. + ! Examples - + call cpu_time(v) ! sets 'v' to a time in seconds. + k = ior(i, j) ! bitwise OR of 2 integers. + v = log10(x) ! log base 10. + i = floor(b) ! returns the closest integer less than or equal to x. + v = aimag(w) ! imaginary part of a complex number. + + ! Functions & Subroutines + ! ======================= + + ! A subroutine runs some code on some input values and can cause + ! side-effects or modify the input values. + + call routine(a, c, v) ! subroutine call. + + ! A function takes a list of input parameters and returns a single value. + ! However the input parameters may still be modified and side effects + ! executed. + + m = func(3, 2, k) ! function call. + + ! Function calls can also be evoked within expressions. + print *, func2(3, 2, k) + + ! A pure function is a function that doesn't modify its input parameters + ! or cause any side-effects. + m = func3(3, 2, k) + +contains ! Zone for defining sub-programs internal to the program. + + ! Fortran has a couple of slightly different ways to define functions. + + integer function func(a, b, c) ! a function returning an integer value. + ! implicit none ! subvariable fields can no longer declare implicit none + integer, intent(in) :: a, b, c ! type of input parameters defined inside the function. + + if (a >= 2) then + func = a + b + c ! the return variable defaults to the function name. + return ! can return the current value from the function at any time. + end if + func = a + c + + ! Don't need a return statement at the end of a function. + end function func + + function func2(a, b, c) result(f) ! return variable declared to be 'f'. + integer, intent(in) :: a, b ! can declare and enforce that variables + !are not modified by the function. + integer, intent(inout) :: c + integer :: f ! function return type declared inside the function. + integer :: cnt = 0 ! GOTCHA - initialisation implies variable is + !saved between function calls. + + f = a + b - c + c = 4 ! altering the value of an input variable. + cnt = cnt + 1 ! count number of function calls. + + end function func2 + + pure function func3(a, b, c) ! a pure function can have no side-effects. + integer, intent(in) :: a, b, c + integer :: func3 + + func3 = a*b*c + + end function func3 + + subroutine routine(d, e, f) + real, intent(inout) :: f + real, intent(in) :: d, e + + f = 2*d + 3*e + f + + end subroutine routine + +end program example ! End of Program Definition ----------------------- + +! Functions and Subroutines declared externally to the program listing need +! to be declared to the program using an Interface declaration (even if they +! are in the same source file!) (see below). It is easier to define them within +! the 'contains' section of a module or program. + +elemental real function func4(a) result(res) +! An elemental function is a Pure function that takes a scalar input variable +! but can also be used on an array where it will be separately applied to all +! of the elements of an array and return a new array. + real, intent(in) :: a + + res = a**2 + 1.0 + +end function func4 + +! Modules +! ======= + +! A module is a useful way to collect related declarations, functions and +! subroutines together for reusability. + +module fruit + + real :: apple + real :: pear + real :: orange + +end module fruit + +module fruity + ! Declarations must be in the order: modules, interfaces, variables. + ! (can declare modules and interfaces in programs too). + + use fruit, only: apple, pear ! use apple and pear from fruit module. + implicit none ! comes after module imports. + + private ! make things private to the module (default is public). + ! Declare some variables/functions explicitly public. + public :: apple, mycar, create_mycar + ! Declare some variables/functions private to the module (redundant here). + private :: func4 + + ! Interfaces + ! ========== + ! Explicitly declare an external function/procedure within the module + ! (better in general to put functions/procedures in the 'contains' section). + interface + elemental real function func4(a) result(res) + real, intent(in) :: a + end function func4 + end interface + + ! Overloaded functions can be defined using named interfaces. + interface myabs + ! Can use 'module procedure' keyword to include functions already + ! defined within the module. + module procedure real_abs, complex_abs + end interface + + ! Derived Data Types + ! ================== + ! Can create custom structured data collections. + type car + character(len=100) :: model + real :: weight ! (kg) + real :: dimensions(3) ! i.e. length-width-height (metres). + character :: colour + contains + procedure :: info ! bind a procedure to a type. + end type car + + type(car) :: mycar ! declare a variable of your custom type. + ! See create_mycar() routine for usage. + + ! Note: There are no executable statements in modules. + +contains + + subroutine create_mycar(mycar) + ! Demonstrates usage of a derived data type. + type(car), intent(out) :: mycar + + ! Access type elements using '%' operator. + mycar%model = "Ford Prefect" + mycar%colour = 'r' + mycar%weight = 1400 + mycar%dimensions(1) = 5.0 ! default indexing starts from 1! + mycar%dimensions(2) = 3.0 + mycar%dimensions(3) = 1.5 + + end subroutine create_mycar + + subroutine info(self) + class(car), intent(in) :: self + ! 'class' keyword used to bind a procedure to a type here. + + print *, "Model : ", self%model + print *, "Colour : ", self%colour + print *, "Weight : ", self%weight + print *, "Dimensions: ", self%dimensions + + end subroutine info + + real pure function real_abs(x) + real, intent(in) :: x + + if (x < 0) then + real_abs = -x + else + real_abs = x + end if + + end function real_abs + + real pure function complex_abs(z) + complex, intent(in) :: z + ! long lines can be continued using the continuation character '&' + + complex_abs = sqrt(real(z)**2 + & + aimag(z)**2) + + end function complex_abs + +end module fruity + +``` + +### More Resources + +For more information on Fortran: + ++ [wikipedia](https://en.wikipedia.org/wiki/Fortran) ++ [Fortran-lang Organization](https://fortran-lang.org/) ++ [Fortran_95_language_features](https://en.wikipedia.org/wiki/Fortran_95_language_features) ++ [fortranwiki.org](http://fortranwiki.org) ++ [www.fortran90.org/](http://www.fortran90.org) ++ [list of Fortran 95 tutorials](http://www.dmoz.org/Computers/Programming/Languages/Fortran/FAQs%2C_Help%2C_and_Tutorials/Fortran_90_and_95/) ++ [Fortran wikibook](https://en.wikibooks.org/wiki/Fortran) ++ [Fortran resources](http://www.fortranplus.co.uk/resources/fortran_resources.pdf) ++ [Mistakes in Fortran 90 Programs That Might Surprise You](http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html) diff --git a/fortran95.html.markdown b/fortran95.html.markdown deleted file mode 100644 index c256bb38..00000000 --- a/fortran95.html.markdown +++ /dev/null @@ -1,452 +0,0 @@ ---- -language: Fortran -contributors: - - ["Robert Steed", "https://github.com/robochat"] -filename: learnfortran.f95 ---- - -Fortran is one of the oldest computer languages. It was developed in the 1950s -by IBM for numeric calculations (Fortran is an abbreviation of "Formula -Translation"). Despite its age, it is still used for high-performance computing -such as weather prediction. However, the language has changed considerably over -the years, although mostly maintaining backwards compatibility; well known -versions are FORTRAN 77, Fortran 90, Fortran 95, Fortran 2003, Fortran 2008 and -Fortran 2015. - -This overview will discuss the features of Fortran 95 since it is the most -widely implemented of the more recent specifications and the later versions are -largely similar (by comparison FORTRAN 77 is a very different language). - -```fortran - -! This is a comment. - - -program example !declare a program called example. - - ! Code can only exist inside programs, functions, subroutines or modules. - ! Using indentation is not required but it is recommended. - - - ! Declaring Variables - ! =================== - - ! All declarations must come before statements and expressions. - - implicit none !prevents dynamic declaration of variables (recommended!) - ! Implicit none must be redeclared in every function/program/module... - - ! IMPORTANT - Fortran is case insensitive. - real z - REAL Z2 - - real :: v,x ! WARNING: default initial values are compiler dependent! - real :: a = 3, b=2E12, c = 0.01 - integer :: i, j, k=1, m - real, parameter :: PI = 3.1415926535897931 !declare a constant. - logical :: y = .TRUE. , n = .FALSE. !boolean type. - complex :: w = (0,1) !sqrt(-1) - character (len=3) :: month !string of 3 characters. - - real :: array(6) !declare an array of 6 reals. - real, dimension(4) :: arrayb !another way to declare an array. - integer :: arrayc(-10:10) !an array with a custom index. - real :: array2d(3,2) !multidimensional array. - - ! The '::' separators are not always necessary but are recommended. - - ! many other variable attributes also exist: - real, pointer :: p !declare a pointer. - - integer, parameter :: LP = selected_real_kind(20) - real (kind = LP) :: d !long precision variable. - - ! WARNING: initialising variables during declaration causes problems - ! in functions since this automatically implies the 'save' attribute - ! whereby values are saved between function calls. In general, separate - ! declaration and initialisation code except for constants! - - - ! Strings - ! ======= - - character :: a_char = 'i' - character (len = 6) :: a_str = "qwerty" - character (len = 30) :: str_b - character (len = *), parameter :: a_long_str = "This is a long string." - !can have automatic counting of length using (len=*) but only for constants. - - str_b = a_str // " keyboard" !concatenate strings using // operator. - - - ! Assignment & Arithmetic - ! ======================= - - Z = 1 !assign to variable z declared above (case insensitive). - j = 10 + 2 - 3 - a = 11.54 / (2.3 * 3.1) - b = 2**3 !exponentiation - - - ! Control Flow Statements & Operators - ! =================================== - - ! Single-line if statement - if (z == a) b = 4 !condition always need surrounding parentheses. - - if (z /= a) then !z not equal to a - ! Other symbolic comparisons are < > <= >= == /= - b = 4 - else if (z .GT. a) then !z greater than a - ! Text equivalents to symbol operators are .LT. .GT. .LE. .GE. .EQ. .NE. - b = 6 - else if (z < a) then !'then' must be on this line. - b = 5 !execution block must be on a new line. - else - b = 10 - end if !end statement needs the 'if' (or can use 'endif'). - - - if (.NOT. (x < c .AND. v >= a .OR. z == z)) then !boolean operators. - inner: if (.TRUE.) then !can name if-construct. - b = 1 - endif inner !then must name endif statement. - endif - - - i = 20 - select case (i) - case (0) !case i == 0 - j=0 - case (1:10) !cases i is 1 to 10 inclusive. - j=1 - case (11:) !all cases where i>=11 - j=2 - case default - j=3 - end select - - - month = 'jan' - ! Condition can be integer, logical or character type. - ! Select constructions can also be named. - monthly: select case (month) - case ("jan") - j = 0 - case default - j = -1 - end select monthly - - - do i=2,10,2 !loops from 2 to 10 (inclusive) in increments of 2. - innerloop: do j=1,3 !loops can be named too. - exit !quits the loop. - end do innerloop - cycle !jump to next loop iteration. - enddo - - - ! Goto statement exists but it is heavily discouraged though. - goto 10 - stop 1 !stops code immediately (returning specified condition code). -10 j = 201 !this line is labeled as line 10 - - - ! Arrays - ! ====== - array = (/1,2,3,4,5,6/) - array = [1,2,3,4,5,6] !using Fortran 2003 notation. - arrayb = [10.2,3e3,0.41,4e-5] - array2d = reshape([1.0,2.0,3.0,4.0,5.0,6.0], [3,2]) - - ! Fortran array indexing starts from 1. - ! (by default but can be defined differently for specific arrays). - v = array(1) !take first element of array. - v = array2d(2,2) - - print *, array(3:5) !print all elements from 3rd to 5th (inclusive). - print *, array2d(1,:) !print first column of 2d array. - - array = array*3 + 2 !can apply mathematical expressions to arrays. - array = array*array !array operations occur element-wise. - !array = array*array2d !these arrays would not be compatible. - - ! There are many built-in functions that operate on arrays. - c = dot_product(array,array) !this is the dot product. - ! Use matmul() for matrix maths. - c = sum(array) - c = maxval(array) - print *, minloc(array) - c = size(array) - print *, shape(array) - m = count(array > 0) - - ! Loop over an array (could have used Product() function normally). - v = 1 - do i = 1, size(array) - v = v*array(i) - end do - - ! Conditionally execute element-wise assignments. - array = [1,2,3,4,5,6] - where (array > 3) - array = array + 1 - elsewhere (array == 2) - array = 1 - elsewhere - array = 0 - end where - - ! Implied-DO loops are a compact way to create arrays. - array = [ (i, i = 1,6) ] !creates an array of [1,2,3,4,5,6] - array = [ (i, i = 1,12,2) ] !creates an array of [1,3,5,7,9,11] - array = [ (i**2, i = 1,6) ] !creates an array of [1,4,9,16,25,36] - array = [ (4,5, i = 1,3) ] !creates an array of [4,5,4,5,4,5] - - - ! Input/Output - ! ============ - - print *, b !print the variable 'b' to the command line - - ! We can format our printed output. - print "(I6)", 320 !prints ' 320' - print "(I6.4)", 3 !prints ' 0003' - print "(F6.3)", 4.32 !prints ' 4.320' - - ! The letter indicates the expected type and the number afterwards gives - ! the number of characters to use for printing the value. - ! Letters can be I (integer), F (real), E (engineering format), - ! L (logical), A (characters) ... - print "(I3)", 3200 !print '***' since the number doesn't fit. - - ! we can have multiple format specifications. - print "(I5,F6.2,E6.2)", 120, 43.41, 43.41 - print "(3I5)", 10, 20, 30 !3 repeats of integers (field width = 5). - print "(2(I5,F6.2))", 120, 43.42, 340, 65.3 !repeated grouping of formats. - - ! We can also read input from the terminal. - read *, v - read "(2F6.2)", v, x !read two numbers - - ! To read a file. - open(unit=11, file="records.txt", status="old") - ! The file is referred to by a 'unit number', an integer that you pick in - ! the range 9:99. Status can be one of {'old','replace','new'}. - read(unit=11, fmt="(3F10.2)") a, b, c - close(11) - - ! To write a file. - open(unit=12, file="records.txt", status="replace") - write(12, "(F10.2,F10.2,F10.2)") c, b, a - close(12) - - ! There are more features available than discussed here and alternative - ! variants due to backwards compatibility with older Fortran versions. - - - ! Built-in Functions - ! ================== - - ! Fortran has around 200 functions/subroutines intrinsic to the language. - ! Examples - - call cpu_time(v) !sets 'v' to a time in seconds. - k = ior(i,j) !bitwise OR of 2 integers. - v = log10(x) !log base 10. - i = floor(b) !returns the closest integer less than or equal to x. - v = aimag(w) !imaginary part of a complex number. - - - ! Functions & Subroutines - ! ======================= - - ! A subroutine runs some code on some input values and can cause - ! side-effects or modify the input values. - - call routine(a,c,v) !subroutine call. - - ! A function takes a list of input parameters and returns a single value. - ! However the input parameters may still be modified and side effects - ! executed. - - m = func(3,2,k) !function call. - - ! Function calls can also be evoked within expressions. - Print *, func2(3,2,k) - - ! A pure function is a function that doesn't modify its input parameters - ! or cause any side-effects. - m = func3(3,2,k) - - -contains ! Zone for defining sub-programs internal to the program. - - ! Fortran has a couple of slightly different ways to define functions. - - integer function func(a,b,c) !a function returning an integer value. - implicit none !best to use implicit none in function definitions too. - integer :: a,b,c !type of input parameters defined inside the function. - if (a >= 2) then - func = a + b + c !the return variable defaults to the function name. - return !can return the current value from the function at any time. - endif - func = a + c - ! Don't need a return statement at the end of a function. - end function func - - - function func2(a,b,c) result(f) !return variable declared to be 'f'. - implicit none - integer, intent(in) :: a,b !can declare and enforce that variables - !are not modified by the function. - integer, intent(inout) :: c - integer :: f !function return type declared inside the function. - integer :: cnt = 0 !GOTCHA - initialisation implies variable is - !saved between function calls. - f = a + b - c - c = 4 !altering the value of an input variable. - cnt = cnt + 1 !count number of function calls. - end function func2 - - - pure function func3(a,b,c) !a pure function can have no side-effects. - implicit none - integer, intent(in) :: a,b,c - integer :: func3 - func3 = a*b*c - end function func3 - - - subroutine routine(d,e,f) - implicit none - real, intent(inout) :: f - real, intent(in) :: d,e - f = 2*d + 3*e + f - end subroutine routine - - -end program example ! End of Program Definition ----------------------- - - -! Functions and Subroutines declared externally to the program listing need -! to be declared to the program using an Interface declaration (even if they -! are in the same source file!) (see below). It is easier to define them within -! the 'contains' section of a module or program. - -elemental real function func4(a) result(res) -! An elemental function is a Pure function that takes a scalar input variable -! but can also be used on an array where it will be separately applied to all -! of the elements of an array and return a new array. - real, intent(in) :: a - res = a**2 + 1.0 -end function func4 - - -! Modules -! ======= - -! A module is a useful way to collect related declarations, functions and -! subroutines together for reusability. - -module fruit - real :: apple - real :: pear - real :: orange -end module fruit - - -module fruity - ! Declarations must be in the order: modules, interfaces, variables. - ! (can declare modules and interfaces in programs too). - - use fruit, only: apple, pear ! use apple and pear from fruit module. - implicit none !comes after module imports. - - private !make things private to the module (default is public). - ! Declare some variables/functions explicitly public. - public :: apple,mycar,create_mycar - ! Declare some variables/functions private to the module (redundant here). - private :: func4 - - ! Interfaces - ! ========== - ! Explicitly declare an external function/procedure within the module - ! (better in general to put functions/procedures in the 'contains' section). - interface - elemental real function func4(a) result(res) - real, intent(in) :: a - end function func4 - end interface - - ! Overloaded functions can be defined using named interfaces. - interface myabs - ! Can use 'module procedure' keyword to include functions already - ! defined within the module. - module procedure real_abs, complex_abs - end interface - - ! Derived Data Types - ! ================== - ! Can create custom structured data collections. - type car - character (len=100) :: model - real :: weight !(kg) - real :: dimensions(3) !i.e. length-width-height (metres). - character :: colour - end type car - - type(car) :: mycar !declare a variable of your custom type. - ! See create_mycar() routine for usage. - - ! Note: There are no executable statements in modules. - -contains - - subroutine create_mycar(mycar) - ! Demonstrates usage of a derived data type. - implicit none - type(car),intent(out) :: mycar - - ! Access type elements using '%' operator. - mycar%model = "Ford Prefect" - mycar%colour = 'r' - mycar%weight = 1400 - mycar%dimensions(1) = 5.0 !default indexing starts from 1! - mycar%dimensions(2) = 3.0 - mycar%dimensions(3) = 1.5 - - end subroutine - - real function real_abs(x) - real :: x - if (x<0) then - real_abs = -x - else - real_abs = x - end if - end function real_abs - - real function complex_abs(z) - complex :: z - ! long lines can be continued using the continuation character '&' - complex_abs = sqrt(real(z)**2 + & - aimag(z)**2) - end function complex_abs - - -end module fruity - -``` - -### More Resources - -For more information on Fortran: - -+ [wikipedia](https://en.wikipedia.org/wiki/Fortran) -+ [Fortran_95_language_features](https://en.wikipedia.org/wiki/Fortran_95_language_features) -+ [fortranwiki.org](http://fortranwiki.org) -+ [www.fortran90.org/](http://www.fortran90.org) -+ [list of Fortran 95 tutorials](http://www.dmoz.org/Computers/Programming/Languages/Fortran/FAQs%2C_Help%2C_and_Tutorials/Fortran_90_and_95/) -+ [Fortran wikibook](https://en.wikibooks.org/wiki/Fortran) -+ [Fortran resources](http://www.fortranplus.co.uk/resources/fortran_resources.pdf) -+ [Mistakes in Fortran 90 Programs That Might Surprise You](http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html) diff --git a/fr-fr/asymptotic-notation-fr.html.markdown b/fr-fr/asymptotic-notation-fr.html.markdown index 491dc3c4..fb0a8220 100644 --- a/fr-fr/asymptotic-notation-fr.html.markdown +++ b/fr-fr/asymptotic-notation-fr.html.markdown @@ -67,21 +67,21 @@ f(n) = 3log n + 100 g(n) = log n ``` -Est-ce que `f(n)` O(g(n))? -Est-ce que `3 log n + 100` O(log n)? +Est-ce que `f(n)` est égal à O(g(n))? +Est-ce que `3 log n + 100` est égal à O(log n)? Regardons maintenant la définition de Big-O. ``` 3log n + 100 <= c * log n ``` -Existe t-il une paire de constantes c, n<sub>0</sub> qui satisfait cela pour tout n > <sub>0</sub>? +Existe t-il une paire de constantes c, n<sub>0</sub> qui satisfait cela pour tout n > n<sub>0</sub>? ``` 3log n + 100 <= 150 * log n, n > 2 (Indéfini avec n = 1) ``` -Oui ! La définition de Big-O a été satisfaite, donc `f(n)` is O(g(n)). +Oui ! La définition de Big-O a été satisfaite, donc `f(n)` est égal à O(g(n)). *Exemple 2* @@ -90,15 +90,15 @@ f(n) = 3*n^2 g(n) = n ``` -Est-ce que `f(n)` O(g(n))? -Est-ce que `3 * n^2` O(n)? +Est-ce que `f(n)` est égal à O(g(n))? +Est-ce que `3 * n^2` est égal à O(n)? Regardons de nouveau la définition de Big-O. ``` 3 * n^2 <= c * n ``` -Existe t-il une paire de constantes c, n<sub>0</sub> qui satisfait cela pour tout n > <sub>0</sub>? +Existe t-il une paire de constantes c, n<sub>0</sub> qui satisfait cela pour tout n > n<sub>0</sub>? Non, il n'en existe pas. `f(n)` n'est pas égal à O(g(n)). ### Big-Omega diff --git a/fr-fr/awk-fr.html.markdown b/fr-fr/awk-fr.html.markdown index 75c48811..bd4e1312 100644 --- a/fr-fr/awk-fr.html.markdown +++ b/fr-fr/awk-fr.html.markdown @@ -10,37 +10,49 @@ lang: fr-fr --- -AWK est un outil standard présent dans chaque système UNIX conforme aux normes POSIX. -C’est un outil en ligne de commande qui ressemble au Perl et qui est excellent dans les tâches de traitement de fichiers texte. -Vous pouvez l’appeler à partir d’un script shell, ou l’utiliser comme un langage de script autonome. +AWK est un outil standard présent dans chaque système UNIX conforme aux normes +POSIX. C’est un outil en ligne de commande qui ressemble au Perl et qui est +excellent dans les tâches de traitement de fichiers texte. +Vous pouvez l’appeler à partir d’un script shell, ou l’utiliser comme un langage +de script autonome. Pourquoi utiliser AWK au lieu du langage Perl ? -Principalement, car AWK fait partie d'UNIX et est donc présent par défaut sur une très grande partie des systèmes d'exploitation UNIX et Linux. -AWK est aussi plus facile à lire que le langage Perl ; et est l'outil idéal pour ce qui concerne le traitement de texte simple. Notamment le traitement de ceux qui necéssitent de lire des fichiers ligne par ligne ; chaque ligne comportant des champs séparés par des délimiteur. - +Principalement, car AWK fait partie d'UNIX et est donc présent par défaut sur +une très grande partie des systèmes d'exploitation UNIX et Linux. +AWK est aussi plus facile à lire que le langage Perl ; et est l'outil idéal pour +ce qui concerne le traitement de texte simple. Notamment le traitement de ceux +qui nécessitent de lire des fichiers ligne par ligne ; chaque ligne comportant +des champs séparés par des délimiteur. ```awk #!/usr/bin/awk -f # Les commentaires commencent par un # - -# les programmes AWK consistent en une collection de règles et d'actions +# Les programmes AWK consistent en une collection de règles et d'actions. règle1 { action; } règle2 { action; } # AWK lit et analyse automatiquement chaque ligne de chaque fichier fourni. -# Chaque ligne est divisée par un délimiteur FS qui est par défaut l'espace (plusieurs espaces ou une tabulation comptent pour un espace). Ce délimiteur peut être changer grâce à l'option -F ou être renseigné au début d'un bloc (exemple: FS = " "). - -# BEGIN est une règle spécifique exécutée au début du programme. C'est à cet endroit que vous mettrez tout le code à exécuter avant de traiter les fichiers texte. Si vous ne disposez pas de fichiers texte, considérez BEGIN comme le point d’entrée principal du script. -# A l'opposé de BEGIN, il existe la règle END. Cette règle est présente après chaque fin de fichier (EOF : End Of File). +# Chaque ligne est divisée par un délimiteur FS qui est par défaut l'espace +# (plusieurs espaces ou une tabulation comptent pour un espace). Ce délimiteur +# peut être changé grâce à l'option -F ou être renseigné au début d'un bloc +# (exemple: FS = " "). + +# BEGIN est une règle spécifique exécutée au début du programme. C'est à cet +# endroit que vous mettrez tout le code à exécuter avant de traiter les fichiers +# texte. Si vous ne disposez pas de fichiers texte, considérez BEGIN comme le +# point d’entrée principal du script. +# À l'opposé de BEGIN, il existe la règle END. Cette règle est présente après +# chaque fin de fichier (EOF : End Of File). BEGIN { # Les variables sont globales. Pas besoin de les déclarer. count = 0; - # les opérateurs sont identiques au langage C et aux langages similaires (exemple: C#, C++) + # Les opérateurs sont identiques au langage C et aux langages similaires + # (tels que C#, C++, etc.) a = count + 1; # addition b = count - 1; # soustraction c = count * 1; # multiplication @@ -59,7 +71,8 @@ BEGIN { a++; b--; - # En tant qu'opérateur préfixé, c'est la valeur incrémentée qui est retournée + # En tant qu'opérateur préfixé, c'est la valeur incrémentée qui + # est retournée ++a; --b; @@ -74,7 +87,8 @@ BEGIN { # Les blocs sont composés d'une multitude de lignes entre accolades while (a < 10) { - print "La concaténation de chaînes de caractères" " se fait avec des séries de chaînes " " séparées par des espaces"; + print "La concaténation de chaînes de caractères" " se fait avec" + "des séries de chaînes " "séparées par des espaces"; print a; a++; @@ -106,14 +120,14 @@ BEGIN { arr[1] = "bar"; # Vous pouvez aussi initialiser un tableau avec la fonction split() - n = split("foo:bar:baz", arr, ":"); # Il y a aussi les tableaux associatifs assoc["foo"] = "bar"; assoc["bar"] = "baz"; - # et les tableaux multi-dimentions, avec certaines limitations que l'on ne mentionnera pas ici + # et les tableaux multi-dimensions, avec certaines limitations que l'on ne + # mentionnera pas ici multidim[0,0] = "foo"; multidim[0,1] = "bar"; multidim[1,0] = "baz"; @@ -123,7 +137,8 @@ BEGIN { if ("foo" in assoc) print "Fooey!"; - # Vous pouvez aussi utilisez l'opérateur 'in' pour parcourir les clés d'un tableau + # Vous pouvez aussi utilisez l'opérateur 'in' pour parcourir les clés + # d'un tableau for (key in assoc) print assoc[key]; @@ -131,16 +146,16 @@ BEGIN { for (argnum in ARGV) print ARGV[argnum]; - # Vous pouvez supprimer des éléments d'un tableau - # C'est utile pour empêcher AWK de supposer que certains arguments soient des fichiers à traiter. + # Vous pouvez supprimer des éléments d'un tableau. + # C'est utile pour empêcher AWK de supposer que certains arguments soient + # des fichiers à traiter. delete ARGV[1]; - # Le nombre d'arguments de la ligne de commande est dans une variable appellée ARGC + # Le nombre d'arguments de la ligne de commande est assigné à + # la variable ARGC print ARGC; - # AWK inclue trois catégories de fonction. - # On les examinera plus tard - + # AWK inclue trois catégories de fonction. On les examinera plus tard. return_value = arithmetic_functions(a, b, c); string_functions(); io_functions(); @@ -149,22 +164,24 @@ BEGIN { # Voici comment définir une fonction function arithmetic_functions(a, b, c, d) { - # La partie la plus ennuieuse de AWK est probablement l’absence de variables locales. - # Tout est global. Pour les scripts courts, c'est très utile, mais pour les scripts plus longs, - # cela peut poser problème. + # La partie la plus ennuyeuse de AWK est probablement l’absence de variables + # locales. Tout est global. Pour les scripts courts, c'est très utile, mais + # pour les scripts plus longs, cela peut poser un problème. - # Il y a cepandant une solution de contournement (enfin ... une bidouille). + # Il y a cependant une solution de contournement (enfin ... une bidouille). # Les arguments d'une fonction sont locaux à cette fonction. - # Et AWK vous permet de définir plus d'arguments à la fonction que nécessaire. - # Il suffit donc de mettre une variable locale dans la déclaration de fonction, - # comme ci-dessus. La convention veut que vous mettiez quelques espaces supplémentaires - # pour faire la distinction entre les paramètres réels et les variables locales. - # Dans cet exemple, a, b et c sont des paramètres réels, - # alors que d est simplement une variable locale. + # Et AWK vous permet de définir plus d'arguments à la fonction que + # nécessaire. Il suffit donc de mettre une variable locale dans la + # déclaration de fonction, comme ci-dessus. La convention veut que vous + # mettiez quelques espaces supplémentaires pour faire la distinction entre + # les paramètres réels et les variables locales. + # Dans cet exemple, a, b et c sont des paramètres réels, alors que d est + # simplement une variable locale. # Maintenant, les fonctions arithmétiques - # La plupart des implémentations de AWK ont des fonctions trigonométriques standards + # La plupart des implémentations de AWK ont des fonctions trigonométriques + # standards localvar = sin(a); localvar = cos(a); localvar = atan2(b, a); # arc tangente de b / a @@ -180,10 +197,10 @@ function arithmetic_functions(a, b, c, d) { localvar = int(5.34); # localvar => 5 # Les nombres aléatoires - srand(); + srand(); # L'argument de la fonction srand() est la valeur de départ pour générer # les nombres aléatoires . Par défaut, il utilise l'heure du système - + localvar = rand(); # Nombre aléatoire entre 0 et 1. # Maintenant on retourne la valeur @@ -195,18 +212,21 @@ function string_functions( localvar, arr) { # AWK a plusieurs fonctions pour le traitement des chaînes de caractères, # dont beaucoup reposent sur des expressions régulières. - # Chercher et remplacer, la première occurence (sub) ou toutes les occurences (gsub) + # Chercher et remplacer, la première occurrence (sub), ou toutes les + # occurrences (gsub). # Les deux renvoient le nombre de correspondances remplacées 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" - # Rechercher une chaîne de caractères qui correspond à une expression régulière - # index() fait la même chose, mais n'autorise pas les expressions régulières + # Rechercher une chaîne de caractères qui correspond à une expression + # régulière index() fait la même chose, mais n'autorise pas les expressions + # régulières. match(localvar, "t"); # => 4, puisque 't' est le quatrième caractère # Séparer par un délimiteur - n = split("foo-bar-baz", arr, "-"); # a[1] = "foo"; a[2] = "bar"; a[3] = "baz"; n = 3 + n = split("foo-bar-baz", arr, "-"); + # résultat : a[1] = "foo"; a[2] = "bar"; a[3] = "baz"; n = 3 # Autre astuces utiles sprintf("%s %d %d %d", "Testing", 1, 2, 3); # => "Testing 1 2 3" @@ -226,26 +246,25 @@ function io_functions( localvar) { printf("%s %d %d %d\n", "Testing", 1, 2, 3); # AWK n'a pas de descripteur de fichier en soi. Il ouvrira automatiquement - # un descripteur de fichier lorsque vous utilisez quelque chose qui en a besoin. - # La chaîne de caractères que vous avez utilisée pour cela peut être traitée - # comme un descripteur de fichier à des fins d'entrée / sortie. - + # un descripteur de fichier lorsque vous utilisez quelque chose qui en a + # besoin. La chaîne de caractères que vous avez utilisée pour cela peut être + # traitée comme un descripteur de fichier à des fins d'entrée / sortie. outfile = "/tmp/foobar.txt"; - print "foobar" > outfile; - # Maintenant, la chaîne de caractères "outfile" est un descripteur de fichier. - # Vous pouvez le fermer + # Maintenant, la chaîne de caractères "outfile" est un descripteur de + # fichier. Vous pouvez le fermer. close(outfile); # Voici comment exécuter quelque chose dans le shell system("echo foobar"); # => affiche foobar - # Lire quelque chose depuis l'entrée standard et la stocker dans une variable locale + # Lire quelque chose depuis l'entrée standard et la stocker dans une + # variable locale getline localvar; - # Lire quelque chose à partir d'un pipe (encore une fois, utilisez une chaine de caractère - # que vous fermerez proprement) + # Lire quelque chose à partir d'un pipe (encore une fois, utilisez une + # chaîne de caractère que vous fermerez proprement) "echo foobar" | getline localvar # localvar => "foobar" close("echo foobar") @@ -256,33 +275,36 @@ function io_functions( localvar) { } # Comme dit au début, AWK consiste en une collection de règles et d'actions. -# Vous connaissez déjà les règles BEGIN et END. Les autres règles ne sont utilisées que si vous traitez -# des lignes à partir de fichiers ou l'entrée standard (stdin). -# Quand vous passez des arguments à AWK, ils sont considérés comme des noms de fichiers à traiter. -# AWK les traitera tous dans l'ordre. Voyez les comme dans à une boucle implicite, -# parcourant les lignes de ces fichiers. -# Ces règles et ces actions ressemblent à des instructions switch dans la boucle. +# Vous connaissez déjà les règles BEGIN et END. Les autres règles ne sont +# utilisées que si vous traitez des lignes à partir de fichiers ou l'entrée +# standard (stdin). +# Quand vous passez des arguments à AWK, ils sont considérés comme des noms de +# fichiers à traiter. AWK les traitera tous dans l'ordre. Voyez les comme dans +# une boucle implicite, parcourant les lignes de ces fichiers. Ces règles et ces +# actions ressemblent à des instructions switch dans la boucle. /^fo+bar$/ { - # Cette action sera exécutée pour chaque ligne qui correspond à l'expression régulière, - # /^fo+bar$/, et sera ignorée pour toute ligne qui n'y correspond pas. - # Imprimons simplement la ligne: + # Cette action sera exécutée pour chaque ligne qui correspond à l'expression + # régulière, /^fo+bar$/, et sera ignorée pour toute ligne qui n'y correspond + # pas. Imprimons simplement la ligne : print; # Pas d'argument ! C'est parce que print a un défaut : $0. - # $0 est le nom de la ligne en cours de traitement. Il est créé automatiquement. + # $0 est le nom de la ligne en cours de traitement. Il est créé + # automatiquement. # Vous devinez probablement qu'il existe d'autres variables $. - # Chaque ligne est divisée implicitement avant que chaque action soit exécutée, comme - # le fait le shell. Et, comme le shell, chaque champ est accessible avec un signe dollar + # Chaque ligne est divisée implicitement avant que chaque action soit + # exécutée, comme le fait le shell. Et, comme le shell, chaque champ est + # accessible avec un signe dollar. - # Ceci affichera les deuxième et quatrième champs de la ligne. + # Ceci affichera les deuxième et quatrième champs de la ligne. print $2, $4; - # AWK défini automatiquement beaucoup d'autres variables qui peuvent vous aider - # à inspecter et traiter chaque ligne. La plus importante est NF + # AWK défini automatiquement beaucoup d'autres variables qui peuvent vous + # aider à inspecter et traiter chaque ligne. La plus importante est NF. # Affiche le nombre de champs de la ligne print NF; @@ -291,33 +313,33 @@ function io_functions( localvar) { print $NF; } -# Chaque règle est en réalité un test conditionel. - +# Chaque règle est en réalité un test conditionnel. a > 0 { # Ceci s’exécutera une fois pour chaque ligne, tant que le test est positif } -# Les expressions régulières sont également des tests conditionels. -#Si le test de l'expression régulières n'est pas vrais alors le bloc n'est pas executé -$0 /^fobar/ { - print "la ligne commance par fobar" +# Les expressions régulières sont également des tests conditionnels. +# Si le test de l'expression régulières n'est pas vrais alors le bloc +# n'est pas exécuté. +$0 /^fobar/ { + print "la ligne commence par foobar" } -# Dans le cas où vous voulez tester votre chaine de caractères sur la ligne en cours de traitement -# $0 est optionnelle. - +# Dans le cas où vous voulez tester votre chaîne de caractères sur la ligne +# en cours de traitement $0 est optionnelle. /^[a-zA-Z0-9]$/ { print "La ligne courante ne contient que des caractères alphanumériques."; } +# AWK peut parcourir un fichier texte ligne par ligne et exécuter des actions en +# fonction de règles établies. Cela est si courant sous UNIX qu'AWK est un +# langage de script. -# AWK peut parcourir un fichier texte ligne par ligne et exécuter des actions en fonction de règles établies -# Cela est si courant sous UNIX qu'AWK est un langage de script. - -# Ce qui suit est un exemple rapide d'un petit script, pour lequel AWK est parfait. -# Le script lit un nom à partir de l'entrée standard, puis affiche l'âge moyen de toutes les -# personnes portant ce prénom. -# Supposons que vous fournissiez comme argument le nom d'un fichier comportant ces données: +# Ce qui suit est un exemple rapide d'un petit script, pour lequel AWK est +# parfait. Le script lit un nom à partir de l'entrée standard, puis affiche +# l'âge moyen de toutes les personnes portant ce prénom. +# Supposons que vous fournissiez comme argument le nom d'un fichier comportant +# ces données : # # Bob Jones 32 # Jane Doe 22 @@ -330,24 +352,26 @@ $0 /^fobar/ { BEGIN { # Premièrement, on demande à l'utilisateur le prénom voulu - print "Pour quel prénom vouldriez vous savoir l'age moyen ?"; + print "Pour quel prénom voudriez vous savoir l'age moyen ?"; - # On récupère la ligne à partir de l'entrée standard, pas de la ligne de commande + # On récupère la ligne à partir de l'entrée standard, pas de la ligne + # de commande : getline name < "/dev/stdin"; } # Maintenant, pour chaque ligne dont le premier champ est le prénom donné $1 == name { - # Ici, nous avons accès à un certain nombre de variables utiles déjà préchargées : + # Ici, nous avons accès à un certain nombre de variables utiles déjà + # préchargées : # $0 est la ligne entière # $3 est le troisième champ. Ici il correspond à l'age qui nous intéresse # NF est le nombre de champs et vaut 3 # NR est le nombre d'enregistrements (lignes) vus jusqu'à présent # FILENAME est le nom du fichier en cours de traitement # FS est séparateur de champs, ici c'est " " (un espace) - # ...etc. Et beaucoup d'autre que vous pouvez connaître dans le manuel de man. - # Pour cela exécutez "man awk" dans votre terminal + # ...etc. Et beaucoup d'autre que vous pouvez connaître dans le manuel de + # man. Pour cela exécutez "man awk" dans votre terminal. # Garder une trace du total accumulé et du nombre de lignes correspondant. sum += $3; @@ -358,9 +382,9 @@ $1 == name { # les fichiers texte. Contrairement à BEGIN, il ne fonctionne que si vous lui # donnez une entrée à traiter. Il sera exécuté une fois que tous les fichiers # auront été lus et traités conformément aux règles et aux actions que vous -# avez fournies. Le but est généralement de produire un rapport final -# ou de faire quelque chose avec l'ensemble des données que vous avez -# accumulées au cours du script. +# avez fournies. Le but est généralement de produire un rapport final, ou de +# faire quelque chose avec l'ensemble des données que vous avez accumulées +# au cours du script. END { @@ -369,9 +393,11 @@ END { } ``` + Pour plus d'informations : * [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 est dans la majorité des systèmes Linux. +* [The GNU Awk User's Guide](https://www.gnu.org/software/gawk/manual/gawk.html) + GNU Awk est dans la majorité des systèmes Linux. * [AWK one-liner collection](http://tuxgraphics.org/~guido/scripts/awk-one-liner.html) diff --git a/fr-fr/bash-fr.html.markdown b/fr-fr/bash-fr.html.markdown index 0e764d7d..58d01e6a 100644 --- a/fr-fr/bash-fr.html.markdown +++ b/fr-fr/bash-fr.html.markdown @@ -17,7 +17,7 @@ lang: fr-fr --- Bash est le nom du shell UNIX, qui était aussi distribué avec le système -d’exploitation GNU et est le shell par défaut sur Linux et Mac OS X. +d’exploitation GNU et est le shell par défaut sur Linux et macOS. Presque tous les exemples ci-dessous peuvent être écrits dans un script shell ou exécutés directement dans le terminal. diff --git a/fr-fr/c++-fr.html.markdown b/fr-fr/c++-fr.html.markdown index 863162f7..b96d0ad0 100644 --- a/fr-fr/c++-fr.html.markdown +++ b/fr-fr/c++-fr.html.markdown @@ -1,5 +1,5 @@ --- -language: c++ +language: C++ filename: learncpp-fr.cpp contributors: - ["Steven Basart", "http://github.com/xksteven"] @@ -69,11 +69,11 @@ void func(); // fonction qui ne prend aucun argument // En C void func(); // fonction qui peut prendre n'importe quel nombre d'arguments -// Utilise nullptr au lieu de NULL in C++ +// Utilise nullptr au lieu de NULL en C++ int* ip = nullptr; // Les en-têtes standards du C sont disponibles en C++, -// mais son préfixés avec "c" et n'ont pas de suffixe .h +// mais sont préfixés avec "c" et n'ont pas de suffixe .h #include <cstdio> int main() @@ -722,7 +722,7 @@ catch (...) // gestion d'un fichier C : void faireQuelqueChoseAvecUnFichier(const char* nomDuFichier) { - // Pour commencer, supposns que rien ne peut échouer. + // Pour commencer, supposons que rien ne peut échouer. FILE* fh = fopen(nomDuFichier, "r"); // Ouvre le fichier en lecture diff --git a/fr-fr/clojure-fr.html.markdown b/fr-fr/clojure-fr.html.markdown index 65747c0d..6215e0cf 100644 --- a/fr-fr/clojure-fr.html.markdown +++ b/fr-fr/clojure-fr.html.markdown @@ -427,7 +427,7 @@ plupart des fonctions principales : 4Clojure est une super manière d'augmenter vos compétences en Clojure et en programmation fonctionnelle : -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org a pas mal d'article pour débuter : [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/fr-fr/crystal-fr.html.markdown b/fr-fr/crystal-fr.html.markdown index 2bb17fc5..02ab3b2b 100644 --- a/fr-fr/crystal-fr.html.markdown +++ b/fr-fr/crystal-fr.html.markdown @@ -350,7 +350,7 @@ sum 3, 4 #=> 7 sum sum(3, 4), 5 #=> 12 # yield -# Toutes les méthodes on un paramètre optionel et implicite de type bloc +# Toutes les méthodes ont un paramètre optionel et implicite de type bloc # il peut être appelé avec le mot clé 'yield' def surround puts '{' diff --git a/fr-fr/csharp-fr.html.markdown b/fr-fr/csharp-fr.html.markdown index 58b3f386..b3bf9c3b 100644 --- a/fr-fr/csharp-fr.html.markdown +++ b/fr-fr/csharp-fr.html.markdown @@ -1,5 +1,5 @@ --- -language: c# +language: C# contributors: - ["Irfan Charania", "https://github.com/irfancharania"] - ["Max Yankov", "https://github.com/golergka"] diff --git a/fr-fr/elisp-fr.html.markdown b/fr-fr/elisp-fr.html.markdown index 2e0a9408..f9bf589c 100644 --- a/fr-fr/elisp-fr.html.markdown +++ b/fr-fr/elisp-fr.html.markdown @@ -328,9 +328,9 @@ lang: fr-fr (other-window 1)) ;; Cette fonction introduit `re-search-forward' : au lieu de chercher -;; la chaîne "Bonjour", nous cherchons un "pattern" en utilisant une -;; "expression régulière" (le préfixe "re-" signifie "regular -;; expression"). +;; la chaîne "Bonjour", nous cherchons un motif ("pattern" en anglais) +;; en utilisant une "expression régulière" (le préfixe "re-" signifie +;; "regular expression"). ;; L'expression régulière est "Bonjour \\(.+\\)!" et se lit : ;; la chaîne "Bonjour ", et @@ -343,7 +343,7 @@ lang: fr-fr (boldify-names) -;; `add-text-properties' ajoute des propriétés textuelles telle que +;; `add-text-properties' ajoute des propriétés textuelles telles que ;; des "faces" (une "face" définit la fonte, la couleur, la taille et ;; d'autres propriétés du texte.) @@ -361,7 +361,7 @@ lang: fr-fr ;; Pour lire en ligne une introduction à Emacs Lisp : ;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html -;; Merci à ces personnes pour leurs retours et suggetions : +;; Merci à ces personnes pour leurs retours et suggestions : ;; - Wes Hardaker ;; - notbob ;; - Kevin Montuori diff --git a/fr-fr/elixir-fr.html.markdown b/fr-fr/elixir-fr.html.markdown index 90cdad7c..f8250e16 100644 --- a/fr-fr/elixir-fr.html.markdown +++ b/fr-fr/elixir-fr.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] diff --git a/fr-fr/fsharp-fr.html.markdown b/fr-fr/fsharp-fr.html.markdown index 3fd41676..dda9945f 100644 --- a/fr-fr/fsharp-fr.html.markdown +++ b/fr-fr/fsharp-fr.html.markdown @@ -140,7 +140,8 @@ module FunctionExamples = let a = add 1 2 printfn "1+2 = %i" a - // partial application to "bake in" parameters (?) + // application partielle des paramètres (curryfication ou "currying" en anglais) + // add42 est une nouvelle fonction qui ne prend plus qu'un paramètre let add42 = add 42 let b = add42 1 printfn "42+1 = %i" b diff --git a/fr-fr/git-fr.html.markdown b/fr-fr/git-fr.html.markdown index 510459fe..a4d0c185 100644 --- a/fr-fr/git-fr.html.markdown +++ b/fr-fr/git-fr.html.markdown @@ -171,6 +171,7 @@ $ git init --help Ne plus suivre certains fichiers et dossiers de Git. Habituellement fait pour les fichiers privés et temporaires qui seraient, autrement, partagés dans le dépôt. + ```bash $ echo "temp/" >> .gitignore $ echo "cle_privee" >> .gitignore @@ -466,6 +467,7 @@ Vous pouvez maintenant pull ! ```bash git pull ``` + `...changes apply...` Vérifiez maintenant que tout est OK @@ -574,8 +576,6 @@ $ git rm /chemin/vers/le/fichier/HelloWorld.c * [SalesForce Cheat Sheet (EN)](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) -* [GitGuys (EN)](http://www.gitguys.com/) - * [Git - the simple guide (EN)](http://rogerdudler.github.io/git-guide/index.html) * [Livre Pro Git](http://www.git-scm.com/book/fr/v1) diff --git a/fr-fr/go-fr.html.markdown b/fr-fr/go-fr.html.markdown index 9d8bef70..5468096a 100644 --- a/fr-fr/go-fr.html.markdown +++ b/fr-fr/go-fr.html.markdown @@ -32,7 +32,7 @@ communauté active. multiligne */ // Un paquet débute avec une clause "package" -// "Main" est un nom spécial déclarant un paquet de type exécutable plutôt +// "main" est un nom spécial déclarant un paquet de type exécutable plutôt // qu'une bibliothèque package main @@ -87,7 +87,7 @@ sauts de ligne.` // Chaîne de caractère. g := 'Σ' // type rune, un alias pour le type int32, contenant un caractère // unicode. - f := 3.14195 // float64, un nombre flottant IEEE-754 de 64-bit. + f := 3.14159 // float64, un nombre flottant IEEE-754 de 64-bit. c := 3 + 4i // complex128, considéré comme deux float64 par le compilateur. // Syntaxe "var" avec une valeur d'initialisation. @@ -422,18 +422,18 @@ func requestServer() { ## En savoir plus -La référence Go se trouve sur [le site officiel de Go](http://golang.org/). +La référence Go se trouve sur [le site officiel de Go](https://go.dev/). Vous pourrez y suivre le tutoriel interactif et en apprendre beaucoup plus. Une lecture de la documentation du langage est grandement conseillée. C'est facile à lire et très court (comparé aux autres langages). -Vous pouvez exécuter et modifier le code sur [Go playground](https://play.golang.org/p/tnWMjr16Mm). Essayez de le modifier et de l'exécuter à partir de votre navigateur! Prennez en note que vous pouvez utiliser [https://play.golang.org](https://play.golang.org) comme un [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) pour tester et coder dans votre navigateur, sans même avoir à installer Go. +Vous pouvez exécuter et modifier le code sur [Go playground](https://go.dev/play/p/tnWMjr16Mm). Essayez de le modifier et de l'exécuter à partir de votre navigateur! Prennez en note que vous pouvez utiliser [https://go.dev/play/](https://go.dev/play/) comme un [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) pour tester et coder dans votre navigateur, sans même avoir à installer Go. Sur la liste de lecteur des étudiants de Go se trouve le [code source de la -librairie standard](http://golang.org/src/pkg/). Bien documentée, elle démontre +librairie standard](https://go.dev/src/). Bien documentée, elle démontre le meilleur de la clarté de Go, le style ainsi que ses expressions. Sinon, vous pouvez cliquer sur le nom d'une fonction dans [la -documentation](http://golang.org/pkg/) et le code source apparaît! +documentation](https://go.dev/pkg/) et le code source apparaît! Une autre excellente ressource pour apprendre est [Go par l'exemple](https://gobyexample.com/). diff --git a/fr-fr/java-fr.html.markdown b/fr-fr/java-fr.html.markdown index d6c68343..b72200d6 100644 --- a/fr-fr/java-fr.html.markdown +++ b/fr-fr/java-fr.html.markdown @@ -31,7 +31,7 @@ Les commentaires sur plusieurs lignes ressemblent à ceci. /** * Les commentaires de la JavaDoc ressemblent à ceci. Ils sont utilisés pour * décrire la classe et ses différents attributs. - * Attributs principaux: + * Attributs principaux : * * @author Nom (et information de contact comme l'email) de(s) auteur(s). * @version Version actuelle du programme. @@ -82,7 +82,7 @@ public class JavaFr { */ // Utilisez Scanner pour lire l'entrée - // Nécessite: import java.util.Scanner; + // Nécessite : import java.util.Scanner; Scanner scanner = new Scanner(System.in); // Lire une chaîne de caractères @@ -160,7 +160,7 @@ public class JavaFr { // L est utilisé pour indiquer que la variable est de type long; // le nombre serait traité comme un int sans le L - // Note: byte, short, int et long sont signés. Ils peuvent avoir des + // Note : byte, short, int et long sont signés. Ils peuvent avoir des // valeurs positives et négatives. // Il n'existe pas de variantes non-signées. // char, toutefois, est non-signé sur 16 bits @@ -203,7 +203,7 @@ public class JavaFr { // BigDecimal - entier immuable et positif de taille arbitraire // - // BigDecimal comprend deux parties: une entier de taille arbitraire + // BigDecimal comprend deux parties : une entier de taille arbitraire // (BigInteger) et un entier de 32 bits représantant la position de la // virgule. // @@ -240,13 +240,13 @@ public class JavaFr { // C'est la manière la plus simple et optimisé par le compilateur String plusConcatenated = "Strings can " + "be concatenated " + "via + operator."; System.out.println(plusConcatenated); - // Affiche: Strings can be concatenated via + operator. + // Affiche : Strings can be concatenated via + operator. // #2 - avec StringBuilder // Cette méthode ne nécessite pas d'objet String intermédiaire. Elle // stocke juste les différentes chaînes de caractères et les assemble // lorsque la méthode toString() est appelée. - // Attention: Cette classe n'est pas thread-safe (l'objet ne peut pas être partagé + // Attention : Cette classe n'est pas thread-safe (l'objet ne peut pas être partagé // entre les threads). Une alternative // (avec un impact sur les performances) thread-safe est d'utiliser la // classe StringBuffer. @@ -255,7 +255,7 @@ public class JavaFr { builderConcatenated.append("can use "); builderConcatenated.append("the StringBuilder class."); System.out.println(builderConcatenated.toString()); // only now is the string built - // Affiche: You can use the StringBuilder class. + // Affiche : You can use the StringBuilder class. // StringBuffer est efficace quand la chaîne de caractères n'est pas // utilisée avec la fin de sa construction. @@ -276,7 +276,7 @@ public class JavaFr { // #3 - avec la méthode format() de la classe String. // Une autre alternative. Rapide et lisible. String.format("%s may prefer %s.", "Or you", "String.format()"); - // Affiche: Or you may prefer String.format(). + // Affiche : Or you may prefer String.format(). // Tableau // La taille du tableau doit être précisée à l'instantiation @@ -419,7 +419,7 @@ public class JavaFr { System.out.println("fooFor Value: " + fooFor); // Fin d'une boucle for avec un label - outer: + outer : for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (i == 5 && j ==5) { @@ -433,9 +433,9 @@ public class JavaFr { // La boucle for est également capable d'itérer aussi bien sur un // tableau que sur des objets qui implémentent l'interface Iterable. int[] fooList = {1, 2, 3, 4, 5, 6, 7, 8, 9}; - // De la forme: for (<object> : <iterable>) - // Lu comme: "Pour chaque élément du tableau" - // note: le type doit correspondre à celui de l'objet itérable + // De la forme : for (<object> : <iterable>) + // Lu comme : "Pour chaque élément du tableau" + // note : le type doit correspondre à celui de l'objet itérable for (int bar : fooList) { System.out.println(bar); //Itère 9 fois et affiche les chiffres de 1 à 9 @@ -511,7 +511,7 @@ public class JavaFr { // Convert Integer To String Integer.toString(123); // retourne un object String correspondant à"123" - // Pour les autres conversions, référer vous aux classes suivantes: + // Pour les autres conversions, référer vous aux classes suivantes : // Double // Long // String @@ -537,7 +537,7 @@ public class JavaFr { // Initialisation avec double accolades // Le langage Java ne permet pas de créer des collections statiques d'une - // manière simple. Généralement, on utilise la forme suivante: + // manière simple. Généralement, on utilise la forme suivante : private static final Set<String> COUNTRIES = new HashSet<String>(); static { COUNTRIES.add("DENMARK"); @@ -566,7 +566,7 @@ public class JavaFr { // Cependant, il est préférable de séparer les // classes dans des fichiers différents. -// Syntaxe de déclaration des classes: +// Syntaxe de déclaration des classes : // <public/private/protected> class <Nom de la classe> { // // Les attributs, les constructeurs et les méthodes de la classe vont ici. // // Les functions de classes sont appelées méthode. @@ -575,11 +575,11 @@ public class JavaFr { class Bicycle { // Attributs et variables de la classe Bicycle - public int cadence; // Public: Peut être accesible depuis n'importe où - private int speed; // Private: Accisible depuis la classe - protected int gear; // Protected: Accisible depuis la classe et ses sous- + public int cadence; // Public : Peut être accesible depuis n'importe où + private int speed; // Private : Accisible depuis la classe + protected int gear; // Protected : Accisible depuis la classe et ses sous- // classes - String name; // default: Uniquement accesible depuis ce package + String name; // default : Uniquement accesible depuis ce package static String className; // Variable de classe static // Bloc static @@ -595,7 +595,7 @@ class Bicycle { // Ceci est le constructeur de la classe Bicycle public Bicycle() { // Vous pouvez aussie appeler un autre constructeur. Par exemple en - // appelant le constructeur de la classe mère (voir héritage): + // appelant le constructeur de la classe mère (voir héritage) : // this(1, 50, 5, "Bontrager"); gear = 1; cadence = 50; @@ -665,7 +665,7 @@ class PennyFarthing extends Bicycle { // Ici nous modifions la méthode setGear() de la classe mère. Il faut donc // utiliser l'annotation @Overide. Pour en savoir plus sur les annotations, // consulter la documention officiel (en anglais) : - // out: http://docs.oracle.com/javase/tutorial/java/annotations/ + // out : http://docs.oracle.com/javase/tutorial/java/annotations/ @Override public void setGear(int gear) { this.gear = 0; @@ -719,7 +719,7 @@ public class Fruit implements Edible, Digestible { } // En Java, on peut hériter uniquement d'une classe mais on peut implémenter -// plusieurs interfaces: +// plusieurs interfaces : public class ExampleClass extends ExampleClassParent implements InterfaceOne, InterfaceTwo { @Override @@ -734,7 +734,7 @@ public class ExampleClass extends ExampleClassParent implements InterfaceOne, // Classes abstraites -// Syntaxe de déclaration: +// Syntaxe de déclaration : // <niveau d'accès> abstract class <nom de la classe abstraite> extends <nom de la // classe mère abstraite> { // // Constantes et variables @@ -758,7 +758,7 @@ public abstract class Animal public void eat() { System.out.println("I am an animal and I am Eating."); - // Note: On peut accéder à une variable privée ici. + // Note : On peut accéder à une variable privée ici. age = 30; } @@ -790,7 +790,7 @@ class Dog extends Animal // age = 30; ==> ERREUR! age est privé et n'est pas accesible. } - // NOTE: Vous obtiendrez une erreur si vous utilisé l'annotation @Override + // NOTE : Vous obtiendrez une erreur si vous utilisé l'annotation @Override // ici car Java n'autorise pas la surcharge de méthodes statiques. Ce qui ce // passe est appelé "method hiding". Si vous voulez en savoir plus, // consultez cette discussion (en anglais) : @@ -828,7 +828,7 @@ public final class SaberToothedCat extends Animal // Méthodes final public abstract class Mammal() { - // Syntaxe: + // Syntaxe : // <niveau d'accès> final <type de retour> <nom de la fonction>(<arguments>) // Les méthodes déclarées comme final ne peuvent pas être surchargées par @@ -846,13 +846,13 @@ public abstract class Mammal() // des valeurs pédéfinies pour celle-ci. En Java, les variables constantes sont // notées en majuscules. // On définie un type enum en utilisant le mot clé enum. Par exemple pour les -// jours de l'année: +// jours de la semaine : public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY } -// On l'utilise ainsi: +// On l'utilise ainsi : public class EnumTest { // On utilise notre énumération Day day; @@ -889,7 +889,7 @@ public class EnumTest { // Le type enum permet de faire bien plus que ce qui est montré ici. Il ne se // limite pas à une liste de constante mais peut inclure des champs et méthodes. -// Vous pouvez en savoir plus ici (en anglais): +// Vous pouvez en savoir plus ici (en anglais) : //https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ``` @@ -899,7 +899,7 @@ public class EnumTest { Les liens ci-dessous sont données si vous souhaitez approfondir sur le sujet, n'hésitez pas à consulter Google pour trouver des exemples spécifiques. -**Guides officiels d'Oracle**: +**Guides officiels d'Oracle** : * [Java Tutorial Trail from Sun / Oracle](https://docs.oracle.com/javase/tutorial/index.html) @@ -918,7 +918,7 @@ n'hésitez pas à consulter Google pour trouver des exemples spécifiques. * [Java Code Conventions](https://www.oracle.com/technetwork/java/codeconvtoc-136057.html) -* Nouvelles fonctionnalités Java 8: +* Nouvelles fonctionnalités Java 8 : * [Lambda expressions (functional programming)](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) * [Date and time API (java.time package)](http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html) @@ -928,7 +928,7 @@ n'hésitez pas à consulter Google pour trouver des exemples spécifiques. * [Codingbat.com](http://codingbat.com/java) -**Livres**: +**Livres** : * [Head First Java](http://www.headfirstlabs.com/books/hfjava/) diff --git a/fr-fr/javascript-fr.html.markdown b/fr-fr/javascript-fr.html.markdown index faa22863..308f1ca8 100644 --- a/fr-fr/javascript-fr.html.markdown +++ b/fr-fr/javascript-fr.html.markdown @@ -1,12 +1,12 @@ --- language: javascript contributors: - - ['Adam Brenecki', 'http://adam.brenecki.id.au'] - - ['Ariel Krakowski', 'http://www.learneroo.com'] + - ["Leigh Brenecki", "https://leigh.net.au"] + - ["Ariel Krakowski", "http://www.learneroo.com"] filename: javascript-fr.js translators: - - ['@nbrugneaux', 'https://nicolasbrugneaux.me'] - - ['Michel Antoine', 'https://github.com/antoin-m'] + - ["@nbrugneaux", "https://nicolasbrugneaux.me"] + - ["Michel Antoine", "https://github.com/antoin-m"] lang: fr-fr --- @@ -94,7 +94,7 @@ let banta = "Harry", santa = "Hermione"; // L'égalité est === ou == // === compare la valeur exacte 2 === '2' // = false -// == convertit la valeur pour comparer 2 === '2' // = true +// == convertit la valeur pour comparer 2 == '2' // = true // En général, il vaut mieux utiliser === pour ne pas faire d'erreur. 1 === 1; // = true 2 === 1; // = false @@ -328,13 +328,15 @@ for (var x in person){ } description; // = "Paul Ken 18 " -// *ES6:* La boucle for...of permet d'itérer sur les propriétés d'un objet -var description = ""; -var person = {fname:"Paul", lname:"Ken", age:18}; -for (var x of person){ - description += x + " "; +// *ES6:* La boucle for...of permet de parcourir un objet itérable +// (ce qui inclut les objets Array, Map, Set, String, ... Mais pas un objet littéral !) +let myPets = ""; +const pets = ["cat", "dog", "hamster", "hedgehog"]; +for (let pet of pets){ //`(const pet of pets)` est également possible + + myPets += pet + " "; } -description; // = "Paul Ken 18 " +myPets; // = 'cat dog hamster hedgehog ' // && est le "et" logique, || est le "ou" logique if (house.size === 'big' && house.colour === 'blue'){ diff --git a/fr-fr/markdown-fr.html.markdown b/fr-fr/markdown-fr.html.markdown index 26c2546a..f5d6aacc 100644 --- a/fr-fr/markdown-fr.html.markdown +++ b/fr-fr/markdown-fr.html.markdown @@ -178,8 +178,8 @@ Vous pouvez également utiliser des sous-listes. 1. Item un 2. Item deux 3. Item trois -* Sub-item -* Sub-item + * Sub-item + * Sub-item 4. Item quatre ``` @@ -210,7 +210,7 @@ l'intérieur du bloc de code. ```md my_array.each do |item| - puts item + puts item end ``` @@ -223,14 +223,16 @@ La fonction `run()` ne vous oblige pas à aller courir! En Markdown GitHub, vous pouvez utiliser des syntaxes spécifiques. - ```ruby - def foobar - puts "Hello world!" - end - ``` +````md +```ruby +def foobar + puts "Hello world!" +end +``` +```` -Pas besoin d'indentation pour le code juste au-dessus, de plus, GitHub -va utiliser une coloration syntaxique pour le langage indiqué après les ```. +Pas besoin d'indentation pour le code juste au-dessus, de plus, GitHub +va utiliser une coloration syntaxique pour le langage indiqué après les <code>```</code>. ## Ligne Horizontale @@ -285,7 +287,7 @@ identifiant. ```md [Ceci][] est un lien. -[ceci]: http://ceciestunlien.com/ +[Ceci]:http://ceciestunlien.com/ ``` Mais ce n'est pas beaucoup utilisé. @@ -301,7 +303,6 @@ d'un point d'exclamation! Là aussi, on peut utiliser le mode "références". - ```md ![Ceci est l'attribut ALT de l'image][monimage] @@ -334,7 +335,7 @@ Tapez \*ce texte\*. ### Touches de clavier -Avec le "Github Flavored Markdown", vous pouvez utiliser la balise `<kdb>` +Avec le "GitHub Flavored Markdown", vous pouvez utiliser la balise `<kdb>` pour représenter une touche du clavier. ```md @@ -348,10 +349,10 @@ Les tableaux ne sont disponibles que dans le "GitHub Flavored Markdown" et ne sont pas tres agréable d'utilisation. Mais si vous en avez besoin : ```md -| Col1 | Col2 | Col3 | -| :----------- | :------: | ------------: | -| Alignement Gauche | Centré | Alignement Droite | -| bla | bla | bla | +| Col1 | Col2 | Col3 | +| :---------------- | :------: | ----------------: | +| Alignement Gauche | Centré | Alignement Droite | +| bla | bla | bla | ``` ou bien, pour un résultat équivalent : diff --git a/fr-fr/objective-c-fr.html.markdown b/fr-fr/objective-c-fr.html.markdown index fbe1741e..191cdfb6 100644 --- a/fr-fr/objective-c-fr.html.markdown +++ b/fr-fr/objective-c-fr.html.markdown @@ -10,7 +10,7 @@ filename: LearnObjectiveC-fr.m lang: fr-fr --- -L'Objective-C est un langage de programmation orienté objet réflexif principalement utilisé par Apple pour les systèmes d'exploitations Mac OS X et iOS et leurs frameworks respectifs, Cocoa et Cocoa Touch. +L'Objective-C est un langage de programmation orienté objet réflexif principalement utilisé par Apple pour les systèmes d'exploitations macOS et iOS et leurs frameworks respectifs, Cocoa et Cocoa Touch. ```objective-c // Les commentaires sur une seule ligne commencent par // @@ -30,7 +30,7 @@ ceci #import <Foundation/Foundation.h> #import "MaClasse.h" -// Si vous activez les modules dans les projets iOS >= 7 ou Mac OS X >= 10.9 +// Si vous activez les modules dans les projets iOS >= 7 ou OS X >= 10.9 // dans Xcode 5, vous pouvez importer les frameworks comme cela : @import Foundation; diff --git a/fr-fr/perl-fr.html.markdown b/fr-fr/perl-fr.html.markdown index e737b7aa..e073bcf5 100644 --- a/fr-fr/perl-fr.html.markdown +++ b/fr-fr/perl-fr.html.markdown @@ -10,9 +10,9 @@ translators: - ["Matteo Taroli", "http://www.matteotaroli.be"] lang: fr-fr --- -Perl 5 est un langage de programmation riche en fonctionnalité, avec plus de 25 ans de développement. +Perl est un langage de programmation riche en fonctionnalité, avec plus de 25 ans de développement. -Perl 5 fonctionne sur plus de 100 plateformes, allant des pc portables aux mainframes et +Perl fonctionne sur plus de 100 plateformes, allant des pc portables aux mainframes et est autant adapté à un prototypage rapide qu'à des projets de grande envergure. ```perl diff --git a/fr-fr/pyqt-fr.html.markdown b/fr-fr/pyqt-fr.html.markdown index 6da9a380..7f0f018b 100644 --- a/fr-fr/pyqt-fr.html.markdown +++ b/fr-fr/pyqt-fr.html.markdown @@ -14,14 +14,14 @@ lang: fr-fr Ceci est une adaptation de l'intro C++ à QT par [Aleksey Kholovchuk](https://github.com/vortexxx192 ), certains exemples du code doivent avoir la même fonctionnalité, -cette version ayant juste été faite en utilisant pyqt! +cette version ayant juste été faite en utilisant pyqt! ```python import sys from PyQt4 import QtGui - + def window(): - # Création de l'objet application + # Création de l'objet application app = QtGui.QApplication(sys.argv) # Création d'un widget où notre label sera placé w = QtGui.QWidget() @@ -47,7 +47,7 @@ if __name__ == '__main__': Pour obtenir certaines des fonctionnalités les plus avancées de **pyqt** nous devons commencer par chercher à construire des éléments supplémentaires. Ici nous voyons comment introduire une boîte de dialogue popup, utile pour demander une confirmation à un utilisateur ou fournir des informations. -```Python +```python import sys from PyQt4.QtGui import * from PyQt4.QtCore import * @@ -66,7 +66,7 @@ def window(): w.setWindowTitle("PyQt Dialog") w.show() sys.exit(app.exec_()) - + # Cette fonction devrait créer une fenêtre de dialogue avec un bouton # qui attend d'être cliqué puis quitte le programme def showdialog(): diff --git a/fr-fr/python-fr.html.markdown b/fr-fr/python-fr.html.markdown index 0ae410de..ca510d66 100644 --- a/fr-fr/python-fr.html.markdown +++ b/fr-fr/python-fr.html.markdown @@ -1,293 +1,377 @@ --- -language: python -filename: learnpython-fr.py +language: Python contributors: - - ["Louie Dinh", "http://ldinh.ca"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] translators: - - ["Sylvain Zyssman", "https://github.com/sylzys"] - - ["Nami-Doc", "https://github.com/Nami-Doc"] + - ["Gnomino", "https://github.com/Gnomino"] + - ["Julien M'Poy", "http://github.com/groovytron"] +filename: learnpython-fr.py lang: fr-fr --- -Python a été créé par Guido Van Rossum au début des années 90. C'est maintenant un des langages de programmation les plus populaires. -Je suis tombé amoureux de Python de par la clarté de sa syntaxe. C'est pratiquement du pseudo-code exécutable. +Python a été créé par Guido Van Rossum au début des années 90. C'est maintenant un des +langages les plus populaires. Je suis tombé amoureux de Python pour la clarté de sa syntaxe. +C'est tout simplement du pseudo-code exécutable. -Vos retours sont grandement appréciés. Vous pouvez me contacter sur Twitter [@louiedinh](http://twitter.com/louiedinh) ou par e-mail: louiedinh [at] [google's email service] +L'auteur original apprécierait les retours (en anglais): vous pouvez le contacter sur Twitter à [@louiedinh](http://twitter.com/louiedinh) ou par mail à l'adresse louiedinh [at] [google's email service] -N.B. : Cet article s'applique spécifiquement à Python 2.7, mais devrait s'appliquer pour toute version Python 2.x. Python 2.7 est en fin de vie et ne sera plus maintenu à partir de 2020, il est donc recommandé d'apprendre Python avec Python 3. Pour Python 3.x, il existe un autre [tutoriel pour Python 3](http://learnxinyminutes.com/docs/fr-fr/python3-fr/). +Note : Cet article s'applique spécifiquement à Python 3. Jettez un coup d'oeil [ici](http://learnxinyminutes.com/docs/fr-fr/python-fr/) pour apprendre le vieux Python 2.7 ```python -# Une ligne simple de commentaire commence par un dièse -""" Les lignes de commentaires multipes peuvent être écrites - en utilisant 3 guillemets ("), et sont souvent utilisées - pour les commentaires + +# Un commentaire d'une ligne commence par un dièse + +""" Les chaînes de caractères peuvent être écrites + avec 3 guillemets doubles ("), et sont souvent + utilisées comme des commentaires. """ #################################################### -## 1. Types Primaires et Opérateurs +## 1. Types de données primaires et opérateurs #################################################### -# Les nombres -3 #=> 3 - -# Les calculs produisent les résultats mathématiques escomptés -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 +# On a des nombres +3 # => 3 -# La division est un peu spéciale. C'est une division d'entiers, et Python arrondi le résultat par défaut automatiquement. -5 / 2 #=> 2 - -# Pour corriger ce problème, on utilise les float. -2.0 # Voici un float -11.0 / 4.0 #=> 2.75 ahhh... beaucoup mieux - -# Forcer la priorité avec les parenthèses -(1 + 3) * 2 #=> 8 - -# Les valeurs booléenes sont de type primitif -True -False +# Les calculs sont ce à quoi on s'attend +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 -# Pour la négation, on utilise "not" -not True #=> False -not False #=> True +# Sauf pour la division qui retourne un float (nombre à virgule flottante) +35 / 5 # => 7.0 -# Pour l'égalité, == -1 == 1 #=> True -2 == 1 #=> False +# Résultats de divisions entières tronqués pour les nombres positifs et négatifs +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # works on floats too +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 -# L'inégalité est symbolisée par != -1 != 1 #=> False -2 != 1 #=> True +# Quand on utilise un float, le résultat est un float +3 * 2.0 # => 6.0 -# D'autres comparateurs -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True +# Modulo (reste de la division) +7 % 3 # => 1 -# On peut enchaîner les comparateurs ! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +# Exponentiation (x**y, x élevé à la puissance y) +2**4 # => 16 -# Les chaînes de caractères sont créées avec " ou ' -"C'est une chaîne." -'C\'est aussi une chaîne.' +# Forcer la priorité de calcul avec des parenthèses +(1 + 3) * 2 # => 8 -# On peut aussi les "additioner" ! -"Hello " + "world!" #=> "Hello world!" - -# Une chaîne peut être traitée comme une liste de caractères -"C'est une chaîne"[0] #=> 'C' +# Les valeurs booléennes sont primitives +True +False -# % peut être utilisé pour formatter des chaîne, comme ceci: -"%s can be %s" % ("strings", "interpolated") +# Négation avec not +not True # => False +not False # => True + +# Opérateurs booléens +# On note que "and" et "or" sont sensibles à la casse +True and False #=> False +False or True #=> True + +# Utilisation des opérations booléennes avec des entiers : +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True + +# On vérifie une égalité avec == +1 == 1 # => True +2 == 1 # => False + +# On vérifie une inégalité avec != +1 != 1 # => False +2 != 1 # => True + +# Autres opérateurs de comparaison +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# On peut enchaîner les comparaisons +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# (is vs. ==) is vérifie si deux variables pointent sur le même objet, mais == vérifie +# si les objets ont la même valeur. +a = [1, 2, 3, 4] # a pointe sur une nouvelle liste, [1, 2, 3, 4] +b = a # b pointe sur a +b is a # => True, a et b pointent sur le même objet +b == a # => True, les objets a et b sont égaux +b = [1, 2, 3, 4] # b pointe sur une nouvelle liste, [1, 2, 3, 4] +b is a # => False, a et b ne pointent pas sur le même objet +b == a # => True, les objets a et b ne pointent pas sur le même objet + +# Les chaînes (ou strings) sont créées avec " ou ' +"Ceci est une chaine" +'Ceci est une chaine aussi.' + +# On peut additionner des chaînes aussi ! Mais essayez d'éviter de le faire. +"Hello " + "world!" # => "Hello world!" +# On peut aussi le faire sans utiliser '+' +"Hello " "world!" # => "Hello world!" + +# On peut traîter une chaîne comme une liste de caractères +"This is a string"[0] # => 'T' + +# .format peut être utilisé pour formatter des chaînes, comme ceci: +"{} peuvent etre {}".format("Les chaînes", "interpolées") + +# On peut aussi réutiliser le même argument pour gagner du temps. +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +#=> "Jack be nimble, Jack be quick, Jack jump over the candle stick" + +# On peut aussi utiliser des mots clés pour éviter de devoir compter. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") #=> "Bob wants to eat lasagna" + +# Il est également possible d'utiliser les f-strings depuis Python 3.6 (https://docs.python.org/3/whatsnew/3.6.html#pep-498-formatted-string-literals) +name = "Fred" +f"Il a dit que son nom est {name}." #=> "Il a dit que son nom est Fred." + +# Si votre code doit aussi être compatible avec Python 2.5 et moins, +# vous pouvez encore utiliser l'ancienne syntaxe : +"Les %s peuvent être %s avec la %s méthode" % ("chaînes", "interpolées", "vieille") -# Une autre manière de formatter les chaînes de caractères est d'utiliser la méthode 'format' -# C'est la méthode à privilégier -"{0} peut être {1}".format("La chaîne", "formattée") -# On peut utiliser des mot-clés au lieu des chiffres. -"{name} veut manger des {food}".format(name="Bob", food="lasagnes") # None est un objet -None #=> None +None # => None -# Ne pas utiliser le symbole d'inégalité "==" pour comparer des objet à None -# Il faut utiliser "is" -"etc" is None #=> False -None is None #=> True +# N'utilisez pas "==" pour comparer des objets à None +# Utilisez plutôt "is". Cela permet de vérifier l'égalité de l'identité des objets. +"etc" is None # => False +None is None # => True -# L'opérateur 'is' teste l'identité de l'objet. -# Ce n'est pas très utilisé avec les types primitifs, mais cela peut être très utile -# lorsque l'on utilise des objets. - -# None, 0, et les chaînes de caractères vides valent False. +# None, 0, and les strings/lists/dicts (chaînes/listes/dictionnaires) valent False lorsqu'ils sont convertis en booléens. # Toutes les autres valeurs valent True -0 == False #=> True -"" == False #=> True +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False #################################################### ## 2. Variables et Collections #################################################### -# Afficher du texte, c'est facile -print "Je suis Python. Enchanté!" - +# Python a une fonction print pour afficher du texte +print("I'm Python. Nice to meet you!") -# Il n'y a pas besoin de déclarer les variables avant de les assigner. -some_var = 5 # La convention veut que l'on utilise des minuscules_avec_underscores -some_var #=> 5 +# Par défaut, la fonction print affiche aussi une nouvelle ligne à la fin. +# Utilisez l'argument optionnel end pour changer ce caractère de fin. +print("Hello, World", end="!") # => Hello, World! -# Accéder à une variable non assignée lève une exception -# Voyez les structures de contrôle pour en apprendre plus sur la gestion des exceptions. -some_other_var # Lève une exception +# Pas besoin de déclarer des variables avant de les définir. +# La convention est de nommer ses variables avec des minuscules_et_underscores +some_var = 5 +some_var # => 5 -# 'if' peut être utilisé comme expression -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +# Tenter d'accéder à une variable non définie lève une exception. +# Voir Structures de contrôle pour en apprendre plus sur le traitement des exceptions. +une_variable_inconnue # Lève une NameError -# Listes +# Les listes permettent de stocker des séquences li = [] -# On peut remplir liste dès l'instanciation +# On peut initialiser une liste pré-remplie other_li = [4, 5, 6] -# On ajoute des éléments avec 'append' -li.append(1) #li contient [1] -li.append(2) #li contient [1, 2] -li.append(4) #li contient [1, 2, 4] -li.append(3) #li contient [1, 2, 4, 3] - -# Et on les supprime avec 'pop' -li.pop() #=> 3 et li contient [1, 2, 4] -# Remettons-le dans la liste -li.append(3) # li contient [1, 2, 4, 3] de nouveau. - -# On accède aux éléments d'une liste comme à ceux un tableau. -li[0] #=> 1 -# Le dernier élément -li[-1] #=> 3 - -# Accèder aux indices hors limite lève une exception -li[4] # Lève un 'IndexError' - -# On peut accèder à des rangs de valeurs avec la syntaxe "slice" -# (C'est un rang de type 'fermé/ouvert' pour les plus matheux) -li[1:3] #=> [2, 4] -# Sans spécifier de fin de rang, on "saute" le début de la liste -li[2:] #=> [4, 3] -# Sans spécifier de début de rang, on "saute" la fin de la liste -li[:3] #=> [1, 2, 4] - -# Retirer un élément spécifique dee la liste avec "del" -del li[2] # li contient [1, 2, 3] - -# On peut additionner des listes entre elles -li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li et other_li existent toujours à part entière +# On ajoute des objets à la fin d'une liste avec .append +li.append(1) # li vaut maintenant [1] +li.append(2) # li vaut maintenant [1, 2] +li.append(4) # li vaut maintenant [1, 2, 4] +li.append(3) # li vaut maintenant [1, 2, 4, 3] +# On enlève le dernier élément avec .pop +li.pop() # => 3 et li vaut maintenant [1, 2, 4] +# Et on le remet +li.append(3) # li vaut de nouveau [1, 2, 4, 3] + +# Accès à un élément d'une liste : +li[0] # => 1 +# Accès au dernier élément : +li[-1] # => 3 + +# Accéder à un élément en dehors des limites lève une IndexError +li[4] # Lève une IndexError + +# On peut accéder à une intervalle avec la syntaxe "slice" +# (c'est un rang du type "fermé/ouvert") +li[1:3] # => [2, 4] +# Omettre les deux premiers éléments +li[2:] # => [4, 3] +# Prendre les trois premiers +li[:3] # => [1, 2, 4] +# Sélectionner un élément sur deux +li[::2] # =>[1, 4] +# Avoir une copie de la liste à l'envers +li[::-1] # => [3, 4, 2, 1] +# Pour des "slices" plus élaborées : +# li[debut:fin:pas] + +# Faire une copie d'une profondeur de un avec les "slices" +li2 = li[:] # => li2 = [1, 2, 4, 3] mais (li2 is li) vaut False. + +# Enlever des éléments arbitrairement d'une liste +del li[2] # li is now [1, 2, 3] + +# On peut additionner des listes +# Note: les valeurs de li et other_li ne sont pas modifiées. +li + other_li # => [1, 2, 3, 4, 5, 6] # Concaténer des listes avec "extend()" -li.extend(other_li) # li vaut maintenant [1, 2, 3, 4, 5, 6] +li.extend(other_li) # Maintenant li contient [1, 2, 3, 4, 5, 6] -# Vérifier l'existence d'un élément dans une liste avec "in" -1 in li #=> True +# Vérifier la présence d'un objet dans une liste avec "in" +1 in li # => True -# Récupérer la longueur avec "len()" -len(li) #=> 6 +# Examiner la longueur avec "len()" +len(li) # => 6 -# Les "tuples" sont comme des listes, mais sont immuables. +# Les tuples sont comme des listes mais sont immuables. tup = (1, 2, 3) -tup[0] #=> 1 -tup[0] = 3 # Lève un 'TypeError' - -# Mais vous pouvez faire tout ceci sur les tuples: -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True - -# Vous pouvez "dé-packager" les tuples (ou les listes) dans des variables -a, b, c = (1, 2, 3) # a vaut maintenant 1, b vaut maintenant 2 and c vaut maintenant 3 -# Sans parenthèses, un tuple est créé par défaut +tup[0] # => 1 +tup[0] = 3 # Lève une TypeError + +# Note : un tuple de taille un doit avoir une virgule après le dernier élément, +# mais ce n'est pas le cas des tuples d'autres tailles, même zéro. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# On peut utiliser la plupart des opérations des listes sur des tuples. +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Vous pouvez décomposer des tuples (ou des listes) dans des variables +a, b, c = (1, 2, 3) # a vaut 1, b vaut 2 et c vaut 3 +# Les tuples sont créés par défaut sans parenthèses d, e, f = 4, 5, 6 -# Voyez maintenant comme il est facile d'inverser 2 valeurs -e, d = d, e # d is now 5 and e is now 4 +# Voyez comme il est facile d'intervertir deux valeurs : +e, d = d, e # d vaut maintenant 5 et e vaut maintenant 4 -# Dictionnaires +# Créer un dictionnaire : empty_dict = {} -# Un dictionnaire pré-rempli +# Un dictionnaire pré-rempli : filled_dict = {"one": 1, "two": 2, "three": 3} -# Trouver des valeurs avec [] -filled_dict["one"] #=> 1 +# Note : les clés des dictionnaires doivent être de types immuables. +# Elles doivent être convertibles en une valeur constante pour une recherche rapide. +# Les types immuables incluent les ints, floats, strings et tuples. +invalid_dict = {[1,2,3]: "123"} # => Lève une TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Par contre, les valeurs peuvent être de tout type. + +# On trouve une valeur avec [] +filled_dict["one"] # => 1 + +# On obtient toutes les clés sous forme d'un itérable avec "keys()" Il faut l'entourer +# de list() pour avoir une liste Note: l'ordre n'est pas garanti. +list(filled_dict.keys()) # => ["three", "two", "one"] -# Récupérer toutes les clés sous forme de liste avec "keys()" -filled_dict.keys() #=> ["three", "two", "one"] -# Note - l'ordre des clés du dictionnaire n'est pas garanti. -# Vos résultats peuvent différer de ceux ci-dessus. -# Récupérer toutes les valeurs sous forme de liste avec "values()" -filled_dict.values() #=> [3, 2, 1] -# Note - Même remarque qu'au-dessus concernant l'ordre des valeurs. +# On obtient toutes les valeurs sous forme d'un itérable avec "values()". +# Là aussi, il faut utiliser list() pour avoir une liste. +# Note : l'ordre n'est toujours pas garanti. +list(filled_dict.values()) # => [3, 2, 1] -# Vérifier l'existence d'une clé dans le dictionnaire avec "in" -"one" in filled_dict #=> True -1 in filled_dict #=> False -# Chercher une clé non existante lève une 'KeyError' -filled_dict["four"] # KeyError +# On vérifie la présence d'une clé dans un dictionnaire avec "in" +"one" in filled_dict # => True +1 in filled_dict # => False -# Utiliser la méthode "get()" pour éviter 'KeyError' -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None -# La méthode get() prend un argument par défaut quand la valeur est inexistante -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 +# L'accès à une clé non-existente lève une KeyError +filled_dict["four"] # KeyError -# La méthode "setdefault()" permet d'ajouter de manière sécuris une paire clé-valeur dans le dictionnnaire -filled_dict.setdefault("five", 5) #filled_dict["five"] vaut 5 -filled_dict.setdefault("five", 6) #filled_dict["five"] is toujours 5 +# On utilise "get()" pour éviter la KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# La méthode get accepte une valeur de retour par défaut en cas de valeur non-existante. +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 +# "setdefault()" insère une valeur dans un dictionnaire si la clé n'est pas présente. +filled_dict.setdefault("five", 5) # filled_dict["five"] devient 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] est toujours 5 -# Les sets stockent ... des sets +# Ajouter à un dictionnaire +filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} +#filled_dict["four"] = 4 # une autre méthode + +# Enlever des clés d'un dictionnaire avec del +del filled_dict["one"] # Enlever la clé "one" de filled_dict. + + +# Les sets stockent des ensembles empty_set = set() -# On initialise un "set()" avec tout un tas de valeurs -some_set = set([1,2,2,3,4]) # some_set vaut maintenant set([1, 2, 3, 4]) +# Initialiser un set avec des valeurs. Oui, ça ressemble aux dictionnaires, désolé. +some_set = {1, 1, 2, 2, 3, 4} # some_set est maintenant {1, 2, 3, 4} + +# Comme les clés d'un dictionnaire, les éléments d'un set doivent être immuables. +invalid_set = {[1], 1} # => Lève une TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Depuis Python 2.7, {} peut être utilisé pour déclarer un 'set' -filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} +# On peut changer un set : +filled_set = some_set -# Ajouter plus d'éléments au set -filled_set.add(5) # filled_set contient maintenant {1, 2, 3, 4, 5} +# Ajouter un objet au set : +filled_set.add(5) # filled_set vaut maintenant {1, 2, 3, 4, 5} -# Intersection de sets avec & +# Chercher les intersections de deux sets avec & other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} +filled_set & other_set # => {3, 4, 5} -# Union de sets avec | -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} +# On fait l'union de sets avec | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} -# Différence de sets avec - -{1,2,3,4} - {2,3,5} #=> {1, 4} +# On fait la différence de deux sets avec - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# On vérifie la présence d'un objet dans un set avec in +2 in filled_set # => True +10 in filled_set # => False -# Vérifier l'existence d'une valeur dans un set avec "in" -2 in filled_set #=> True -10 in filled_set #=> False #################################################### -## 3. Structure de contrôle +## 3. Structures de contrôle et Itérables #################################################### -# Initialisons une variable +# On crée juste une variable some_var = 5 -# Voici une condition 'if'. L'indentation est significative en Python ! -# Affiche "some_var est inférieur à 10" +# Voici une condition "si". L'indentation est significative en Python! +# Affiche: "some_var is smaller than 10" if some_var > 10: - print "some_var est supérieur à 10." -elif some_var < 10: # La clause elif est optionnelle - print "some_var iinférieur à 10." -else: # La clause else également - print "some_var vaut 10." + print("some_var is totally bigger than 10.") +elif some_var < 10: # La clause elif ("sinon si") est optionelle + print("some_var is smaller than 10.") +else: # La clause else ("sinon") l'est aussi. + print("some_var is indeed 10.") """ -Les boucles "for" permettent d'itérer sur les listes +Les boucles "for" itèrent sur une liste Affiche: - chien : mammifère - chat : mammifère - souris : mammifère + chien est un mammifère + chat est un mammifère + souris est un mammifère """ for animal in ["chien", "chat", "souris"]: - # On peut utiliser % pour l'interpolation des chaînes formattées - print "%s : mammifère" % animal + # On peut utiliser format() pour interpoler des chaînes formattées + print("{} est un mammifère".format(animal)) """ -"range(number)" retourne une liste de nombres -de 0 au nombre donné +"range(nombre)" retourne un itérable de nombres +de zéro au nombre donné Affiche: 0 1 @@ -295,10 +379,34 @@ Affiche: 3 """ for i in range(4): - print i + print(i) + +""" +"range(debut, fin)" retourne un itérable de nombre +de debut à fin. +Affiche: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) """ -Les boucles "while" boucle jusqu'à ce que leur condition ne soit plus vraie +"range(debut, fin, pas)" retourne un itérable de nombres +de début à fin en incrémentant de pas. +Si le pas n'est pas indiqué, la valeur par défaut est 1. +Affiche: + 4 + 6 + 8 +""" +for i in range(4, 8, 2): + print(i) +""" + +Les boucles "while" bouclent jusqu'à ce que la condition devienne fausse. Affiche: 0 1 @@ -307,66 +415,135 @@ Affiche: """ x = 0 while x < 4: - print x + print(x) x += 1 # Raccourci pour x = x + 1 -# Gérer les exceptions avec un bloc try/except - -# Fonctionne pour Python 2.6 et ultérieur: +# On gère les exceptions avec un bloc try/except try: - # Utiliser "raise" pour lever une exception - raise IndexError("This is an index error") + # On utilise "raise" pour lever une erreur + raise IndexError("Ceci est une erreur d'index") except IndexError as e: - pass # Pass ne prend pas d'arguments. Généralement, on gère l'erreur ici. + pass # Pass signifie simplement "ne rien faire". Généralement, on gère l'erreur ici. +except (TypeError, NameError): + pass # Si besoin, on peut aussi gérer plusieurs erreurs en même temps. +else: # Clause optionelle des blocs try/except. Doit être après tous les except. + print("Tout va bien!") # Uniquement si aucune exception n'est levée. +finally: # Éxécuté dans toutes les circonstances. + print("On nettoie les ressources ici") + +# Au lieu de try/finally pour nettoyer les ressources, on peut utiliser with +with open("myfile.txt") as f: + for line in f: + print(line) + +# Python offre une abstraction fondamentale : l'Iterable. +# Un itérable est un objet pouvant être traîté comme une séquence. +# L'objet retourné par la fonction range() est un itérable. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) #=> range(1,10). C'est un objet qui implémente l'interface Iterable + +# On peut boucler dessus +for i in our_iterable: + print(i) # Affiche one, two, three + +# Cependant, on ne peut pas accéder aux éléments par leur adresse. +our_iterable[1] # Lève une TypeError + +# Un itérable est un objet qui sait créer un itérateur. +our_iterator = iter(our_iterable) + +# Notre itérateur est un objet qui se rappelle de notre position quand on le traverse. +# On passe à l'élément suivant avec "next()". +next(our_iterator) #=> "one" + +# Il garde son état quand on itère. +next(our_iterator) #=> "two" +next(our_iterator) #=> "three" + +# Après que l'itérateur a retourné toutes ses données, il lève une exception StopIterator +next(our_iterator) # Lève une StopIteration + +# On peut mettre tous les éléments d'un itérateur dans une liste avec list() +list(filled_dict.keys()) #=> Returns ["one", "two", "three"] #################################################### ## 4. Fonctions #################################################### -# Utiliser "def" pour créer une nouvelle fonction +# On utilise "def" pour créer des fonctions def add(x, y): - print "x vaut %s et y vaur %s" % (x, y) - return x + y # Renvoi de valeur avec 'return' + print("x est {} et y est {}".format(x, y)) + return x + y # On retourne une valeur avec return -# Appeller une fonction avec des paramètres -add(5, 6) #=> Affichet "x is 5 et y vaut 6" et renvoie 11 +# Appel d'une fonction avec des paramètres : +add(5, 6) # => affiche "x est 5 et y est 6" et retourne 11 -# Une autre manière d'appeller une fonction, avec les arguments -add(y=6, x=5) # Les arguments peuvent venir dans n'importe quel ordre. +# Une autre manière d'appeler une fonction : avec des arguments +add(y=6, x=5) # Les arguments peuvent être dans n'importe quel ordre. -# On peut définir une foncion qui prend un nombre variable de paramètres +# Définir une fonction qui prend un nombre variable d'arguments def varargs(*args): return args -varargs(1, 2, 3) #=> (1,2,3) +varargs(1, 2, 3) # => (1, 2, 3) - -# On peut également définir une fonction qui prend un nombre -# variable d'arguments +# On peut aussi définir une fonction qui prend un nombre variable de paramètres. def keyword_args(**kwargs): return kwargs -# Appelons-là et voyons ce qu'il se passe -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} +# Appelons la pour voir ce qu'il se passe : +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + -# On peut faire les deux à la fois si on le souhaite +# On peut aussi faire les deux à la fois : def all_the_args(*args, **kwargs): - print args - print kwargs + print(args) + print(kwargs) """ all_the_args(1, 2, a=3, b=4) affiche: (1, 2) {"a": 3, "b": 4} """ -# En appellant les fonctions, on peut faire l'inverse des paramètres / arguments ! -# Utiliser * pour développer les paramètres, et ** pour développer les arguments -params = (1, 2, 3, 4) -args = {"a": 3, "b": 4} -all_the_args(*args) # equivaut à foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivaut à foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivaut à foo(1, 2, 3, 4, a=3, b=4) +# En appelant des fonctions, on peut aussi faire l'inverse : +# utiliser * pour étendre un tuple de paramètres +# et ** pour étendre un dictionnaire d'arguments. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # équivalent à foo(1, 2, 3, 4) +all_the_args(**kwargs) # équivalent à foo(a=3, b=4) +all_the_args(*args, **kwargs) # équivalent à foo(1, 2, 3, 4, a=3, b=4) + +# Retourne plusieurs valeurs (avec un tuple) +def swap(x, y): + return y, x # Retourne plusieurs valeurs avec un tuple sans parenthèses. + # (Note: on peut aussi utiliser des parenthèses) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Là aussi, rien ne nous empêche d'ajouter des parenthèses + +# Portée des fonctions : +x = 5 + +def setX(num): + # La variable locale x n'est pas la même que la variable globale x + x = num # => 43 + print (x) # => 43 + +def setGlobalX(num): + global x + print (x) # => 5 + x = num # la variable globale x est maintenant 6 + print (x) # => 6 + +setX(43) +setGlobalX(6) + # Python a des fonctions de première classe def create_adder(x): @@ -375,67 +552,78 @@ def create_adder(x): return adder add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3) # => 13 -# Mais également des fonctions anonymes -(lambda x: x > 2)(3) #=> True +# Mais aussi des fonctions anonymes +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 -# On trouve aussi des fonctions intégrées plus évoluées -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +# TODO - Fix for iterables +# Il y a aussi des fonctions de base +map(add_10, [1, 2, 3]) # => [11, 12, 13] +map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] -# On peut utiliser la syntaxe des liste pour construire les "maps" et les "filters" -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# On peut utiliser les compréhensions de listes pour de jolies maps et filtres. +# Une compréhension de liste stocke la sortie comme une liste qui peut elle même être une liste imbriquée. +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] #################################################### ## 5. Classes #################################################### -# Une classe est un objet -class Human(object): - # Un attribut de classe. Il est partagé par toutes les instances de cette classe. +# On utilise l'opérateur "class" pour définir une classe +class Human: + + # Un attribut de la classe. Il est partagé par toutes les instances de la classe. species = "H. sapiens" - # Initialiseur basique + # L'initialiseur de base. Il est appelé quand la classe est instanciée. + # Note : les doubles underscores au début et à la fin sont utilisés pour + # les fonctions et attributs utilisés par Python mais contrôlés par l'utilisateur. + # Les méthodes (ou objets ou attributs) comme: __init__, __str__, + # __repr__ etc. sont appelés méthodes magiques. + # Vous ne devriez pas inventer de noms de ce style. def __init__(self, name): - # Assigne le paramètre à l'attribut de l'instance de classe. + # Assigner l'argument à l'attribut de l'instance self.name = name - # Une méthode de l'instance. Toutes les méthodes prennent "self" comme 1er paramètre. + # Une méthode de l'instance. Toutes prennent "self" comme premier argument. def say(self, msg): - return "%s: %s" % (self.name, msg) + return "{name}: {message}".format(name=self.name, message=msg) - # Une méthode de classe est partagée par toutes les instances. - # On les appelle avec le nom de la classe en premier paramètre + # Une méthode de classe est partagée avec entre les instances + # Ils sont appelés avec la classe comme premier argument @classmethod def get_species(cls): return cls.species - # Une méthode statique est appellée sans référence à une classe ou à une instance + # Une méthode statique est appelée sans référence à une instance ni à une classe. @staticmethod def grunt(): return "*grunt*" -# Instancier une classe +# Instantier une classe i = Human(name="Ian") -print i.say("hi") # Affiche "Ian: hi" +print(i.say("hi")) # affiche "Ian: hi" j = Human("Joel") -print j.say("hello") #Affiche "Joel: hello" +print(j.say("hello")) # affiche "Joel: hello" # Appeller notre méthode de classe -i.get_species() #=> "H. sapiens" +i.get_species() # => "H. sapiens" # Changer les attributs partagés Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" # Appeller la méthode statique -Human.grunt() #=> "*grunt*" +Human.grunt() # => "*grunt*" #################################################### @@ -444,45 +632,101 @@ Human.grunt() #=> "*grunt*" # On peut importer des modules import math -print math.sqrt(16) #=> 4.0 +print(math.sqrt(16)) # => 4.0 -# Et récupérer des fonctions spécifiques d'un module +# On peut importer des fonctions spécifiques d'un module from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 -# Récuperer toutes les fonctions d'un module -# Attention, ce n'est pas recommandé. +# On peut importer toutes les fonctions d'un module +# Attention: ce n'est pas recommandé. from math import * -# On peut raccourcir le nom d'un module +# On peut raccourcir un nom de module import math as m -math.sqrt(16) == m.sqrt(16) #=> True +math.sqrt(16) == m.sqrt(16) # => True -# Les modules Python sont juste des fichiers Python ordinaires. -# On peut écrire ses propres modules et les importer. -# Le nom du module doit être le même que le nom du fichier. +# Les modules Python sont juste des fichiers Python. +# Vous pouvez écrire les vôtres et les importer. Le nom du module +# est le nom du fichier. -# On peut trouver quelle fonction et attributs déterminent un module +# On peut voir quels fonctions et objets un module définit import math dir(math) +#################################################### +## 7. Avancé +#################################################### + +# Les générateurs aident à faire du code paresseux (lazy) +def double_numbers(iterable): + for i in iterable: + yield i + i + +# Un générateur crée des valeurs à la volée. +# Au lieu de générer et retourner toutes les valeurs en une fois, il en crée une à chaque +# itération. Cela signifie que les valeurs supérieures à 30 ne seront pas traîtées par +# double_numbers. +# Note : range est un générateur aussi. +# Créer une liste 1-900000000 prendrait beaucoup de temps +# On met un underscore à la fin d'un nom de variable normalement réservé par Python. +range_ = range(1, 900000000) +# Double tous les nombres jusqu'à ce qu'un nombre >=30 soit trouvé +for i in double_numbers(range_): + print(i) + if i >= 30: + break + + +# Decorateurs +# Dans cet exemple, beg enveloppe say +# Beg appellera say. Si say_please vaut True le message retourné sera changé +from functools import wraps + + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # affiche Can you buy me a beer? +print(say(say_please=True)) # affiche Can you buy me a beer? Please! I am poor :( ``` -## Prêt à aller plus loin? +## Prêt pour encore plus ? -### En ligne gratuitement +### En ligne et gratuit (en anglais) +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) + +### En ligne et gratuit (en français) -### Format papier +* [Le petit guide des batteries à découvrir](https://he-arc.github.io/livre-python/) + +### Livres (en anglais) * [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) * [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) * [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - diff --git a/fr-fr/python3-fr.html.markdown b/fr-fr/python3-fr.html.markdown deleted file mode 100644 index 7112cd90..00000000 --- a/fr-fr/python3-fr.html.markdown +++ /dev/null @@ -1,732 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] - - ["Steven Basart", "http://github.com/xksteven"] - - ["Andre Polykanine", "https://github.com/Oire"] - - ["Zachary Ferguson", "http://github.com/zfergus2"] -translators: - - ["Gnomino", "https://github.com/Gnomino"] - - ["Julien M'Poy", "http://github.com/groovytron"] -filename: learnpython3-fr.py -lang: fr-fr ---- - -Python a été créé par Guido Van Rossum au début des années 90. C'est maintenant un des -langages les plus populaires. Je suis tombé amoureux de Python pour la clarté de sa syntaxe. -C'est tout simplement du pseudo-code exécutable. - -L'auteur original apprécierait les retours (en anglais): vous pouvez le contacter sur Twitter à [@louiedinh](http://twitter.com/louiedinh) ou par mail à l'adresse louiedinh [at] [google's email service] - -Note : Cet article s'applique spécifiquement à Python 3. Jettez un coup d'oeil [ici](http://learnxinyminutes.com/docs/fr-fr/python-fr/) pour apprendre le vieux Python 2.7 - -```python - -# Un commentaire d'une ligne commence par un dièse - -""" Les chaînes de caractères peuvent être écrites - avec 3 guillemets doubles ("), et sont souvent - utilisées comme des commentaires. -""" - -#################################################### -## 1. Types de données primaires et opérateurs -#################################################### - -# On a des nombres -3 # => 3 - -# Les calculs sont ce à quoi on s'attend -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 - -# Sauf pour la division qui retourne un float (nombre à virgule flottante) -35 / 5 # => 7.0 - -# Résultats de divisions entières tronqués pour les nombres positifs et négatifs -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# Quand on utilise un float, le résultat est un float -3 * 2.0 # => 6.0 - -# Modulo (reste de la division) -7 % 3 # => 1 - -# Exponentiation (x**y, x élevé à la puissance y) -2**4 # => 16 - -# Forcer la priorité de calcul avec des parenthèses -(1 + 3) * 2 # => 8 - -# Les valeurs booléennes sont primitives -True -False - -# Négation avec not -not True # => False -not False # => True - -# Opérateurs booléens -# On note que "and" et "or" sont sensibles à la casse -True and False #=> False -False or True #=> True - -# Utilisation des opérations booléennes avec des entiers : -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True - -# On vérifie une égalité avec == -1 == 1 # => True -2 == 1 # => False - -# On vérifie une inégalité avec != -1 != 1 # => False -2 != 1 # => True - -# Autres opérateurs de comparaison -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# On peut enchaîner les comparaisons -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# (is vs. ==) is vérifie si deux variables pointent sur le même objet, mais == vérifie -# si les objets ont la même valeur. -a = [1, 2, 3, 4] # a pointe sur une nouvelle liste, [1, 2, 3, 4] -b = a # b pointe sur a -b is a # => True, a et b pointent sur le même objet -b == a # => True, les objets a et b sont égaux -b = [1, 2, 3, 4] # b pointe sur une nouvelle liste, [1, 2, 3, 4] -b is a # => False, a et b ne pointent pas sur le même objet -b == a # => True, les objets a et b ne pointent pas sur le même objet - -# Les chaînes (ou strings) sont créées avec " ou ' -"Ceci est une chaine" -'Ceci est une chaine aussi.' - -# On peut additionner des chaînes aussi ! Mais essayez d'éviter de le faire. -"Hello " + "world!" # => "Hello world!" -# On peut aussi le faire sans utiliser '+' -"Hello " "world!" # => "Hello world!" - -# On peut traîter une chaîne comme une liste de caractères -"This is a string"[0] # => 'T' - -# .format peut être utilisé pour formatter des chaînes, comme ceci: -"{} peuvent etre {}".format("Les chaînes", "interpolées") - -# On peut aussi réutiliser le même argument pour gagner du temps. -"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") -#=> "Jack be nimble, Jack be quick, Jack jump over the candle stick" - -# On peut aussi utiliser des mots clés pour éviter de devoir compter. -"{name} wants to eat {food}".format(name="Bob", food="lasagna") #=> "Bob wants to eat lasagna" - -# Il est également possible d'utiliser les f-strings depuis Python 3.6 (https://docs.python.org/3/whatsnew/3.6.html#pep-498-formatted-string-literals) -name = "Fred" -f"Il a dit que son nom est {name}." #=> "Il a dit que son nom est Fred." - -# Si votre code doit aussi être compatible avec Python 2.5 et moins, -# vous pouvez encore utiliser l'ancienne syntaxe : -"Les %s peuvent être %s avec la %s méthode" % ("chaînes", "interpolées", "vieille") - - -# None est un objet -None # => None - -# N'utilisez pas "==" pour comparer des objets à None -# Utilisez plutôt "is". Cela permet de vérifier l'égalité de l'identité des objets. -"etc" is None # => False -None is None # => True - -# None, 0, and les strings/lists/dicts (chaînes/listes/dictionnaires) valent False lorsqu'ils sont convertis en booléens. -# Toutes les autres valeurs valent True -bool(0) # => False -bool("") # => False -bool([]) #=> False -bool({}) #=> False - - -#################################################### -## 2. Variables et Collections -#################################################### - -# Python a une fonction print pour afficher du texte -print("I'm Python. Nice to meet you!") - -# Par défaut, la fonction print affiche aussi une nouvelle ligne à la fin. -# Utilisez l'argument optionnel end pour changer ce caractère de fin. -print("Hello, World", end="!") # => Hello, World! - -# Pas besoin de déclarer des variables avant de les définir. -# La convention est de nommer ses variables avec des minuscules_et_underscores -some_var = 5 -some_var # => 5 - -# Tenter d'accéder à une variable non définie lève une exception. -# Voir Structures de contrôle pour en apprendre plus sur le traitement des exceptions. -une_variable_inconnue # Lève une NameError - -# Les listes permettent de stocker des séquences -li = [] -# On peut initialiser une liste pré-remplie -other_li = [4, 5, 6] - -# On ajoute des objets à la fin d'une liste avec .append -li.append(1) # li vaut maintenant [1] -li.append(2) # li vaut maintenant [1, 2] -li.append(4) # li vaut maintenant [1, 2, 4] -li.append(3) # li vaut maintenant [1, 2, 4, 3] -# On enlève le dernier élément avec .pop -li.pop() # => 3 et li vaut maintenant [1, 2, 4] -# Et on le remet -li.append(3) # li vaut de nouveau [1, 2, 4, 3] - -# Accès à un élément d'une liste : -li[0] # => 1 -# Accès au dernier élément : -li[-1] # => 3 - -# Accéder à un élément en dehors des limites lève une IndexError -li[4] # Lève une IndexError - -# On peut accéder à une intervalle avec la syntaxe "slice" -# (c'est un rang du type "fermé/ouvert") -li[1:3] # => [2, 4] -# Omettre les deux premiers éléments -li[2:] # => [4, 3] -# Prendre les trois premiers -li[:3] # => [1, 2, 4] -# Sélectionner un élément sur deux -li[::2] # =>[1, 4] -# Avoir une copie de la liste à l'envers -li[::-1] # => [3, 4, 2, 1] -# Pour des "slices" plus élaborées : -# li[debut:fin:pas] - -# Faire une copie d'une profondeur de un avec les "slices" -li2 = li[:] # => li2 = [1, 2, 4, 3] mais (li2 is li) vaut False. - -# Enlever des éléments arbitrairement d'une liste -del li[2] # li is now [1, 2, 3] - -# On peut additionner des listes -# Note: les valeurs de li et other_li ne sont pas modifiées. -li + other_li # => [1, 2, 3, 4, 5, 6] - -# Concaténer des listes avec "extend()" -li.extend(other_li) # Maintenant li contient [1, 2, 3, 4, 5, 6] - -# Vérifier la présence d'un objet dans une liste avec "in" -1 in li # => True - -# Examiner la longueur avec "len()" -len(li) # => 6 - - -# Les tuples sont comme des listes mais sont immuables. -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # Lève une TypeError - -# Note : un tuple de taille un doit avoir une virgule après le dernier élément, -# mais ce n'est pas le cas des tuples d'autres tailles, même zéro. -type((1)) # => <class 'int'> -type((1,)) # => <class 'tuple'> -type(()) # => <class 'tuple'> - -# On peut utiliser la plupart des opérations des listes sur des tuples. -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True - -# Vous pouvez décomposer des tuples (ou des listes) dans des variables -a, b, c = (1, 2, 3) # a vaut 1, b vaut 2 et c vaut 3 -# Les tuples sont créés par défaut sans parenthèses -d, e, f = 4, 5, 6 -# Voyez comme il est facile d'intervertir deux valeurs : -e, d = d, e # d vaut maintenant 5 et e vaut maintenant 4 - - -# Créer un dictionnaire : -empty_dict = {} -# Un dictionnaire pré-rempli : -filled_dict = {"one": 1, "two": 2, "three": 3} - -# Note : les clés des dictionnaires doivent être de types immuables. -# Elles doivent être convertibles en une valeur constante pour une recherche rapide. -# Les types immuables incluent les ints, floats, strings et tuples. -invalid_dict = {[1,2,3]: "123"} # => Lève une TypeError: unhashable type: 'list' -valid_dict = {(1,2,3):[1,2,3]} # Par contre, les valeurs peuvent être de tout type. - -# On trouve une valeur avec [] -filled_dict["one"] # => 1 - -# On obtient toutes les clés sous forme d'un itérable avec "keys()" Il faut l'entourer -# de list() pour avoir une liste Note: l'ordre n'est pas garanti. -list(filled_dict.keys()) # => ["three", "two", "one"] - - -# On obtient toutes les valeurs sous forme d'un itérable avec "values()". -# Là aussi, il faut utiliser list() pour avoir une liste. -# Note : l'ordre n'est toujours pas garanti. -list(filled_dict.values()) # => [3, 2, 1] - - -# On vérifie la présence d'une clé dans un dictionnaire avec "in" -"one" in filled_dict # => True -1 in filled_dict # => False - -# L'accès à une clé non-existente lève une KeyError -filled_dict["four"] # KeyError - -# On utilise "get()" pour éviter la KeyError -filled_dict.get("one") # => 1 -filled_dict.get("four") # => None -# La méthode get accepte une valeur de retour par défaut en cas de valeur non-existante. -filled_dict.get("one", 4) # => 1 -filled_dict.get("four", 4) # => 4 - -# "setdefault()" insère une valeur dans un dictionnaire si la clé n'est pas présente. -filled_dict.setdefault("five", 5) # filled_dict["five"] devient 5 -filled_dict.setdefault("five", 6) # filled_dict["five"] est toujours 5 - -# Ajouter à un dictionnaire -filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} -#filled_dict["four"] = 4 # une autre méthode - -# Enlever des clés d'un dictionnaire avec del -del filled_dict["one"] # Enlever la clé "one" de filled_dict. - - -# Les sets stockent des ensembles -empty_set = set() -# Initialiser un set avec des valeurs. Oui, ça ressemble aux dictionnaires, désolé. -some_set = {1, 1, 2, 2, 3, 4} # some_set est maintenant {1, 2, 3, 4} - -# Comme les clés d'un dictionnaire, les éléments d'un set doivent être immuables. -invalid_set = {[1], 1} # => Lève une TypeError: unhashable type: 'list' -valid_set = {(1,), 1} - -# On peut changer un set : -filled_set = some_set - -# Ajouter un objet au set : -filled_set.add(5) # filled_set vaut maintenant {1, 2, 3, 4, 5} - -# Chercher les intersections de deux sets avec & -other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} - -# On fait l'union de sets avec | -filled_set | other_set # => {1, 2, 3, 4, 5, 6} - -# On fait la différence de deux sets avec - -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} - -# On vérifie la présence d'un objet dans un set avec in -2 in filled_set # => True -10 in filled_set # => False - - - -#################################################### -## 3. Structures de contrôle et Itérables -#################################################### - -# On crée juste une variable -some_var = 5 - -# Voici une condition "si". L'indentation est significative en Python! -# Affiche: "some_var is smaller than 10" -if some_var > 10: - print("some_var is totally bigger than 10.") -elif some_var < 10: # La clause elif ("sinon si") est optionelle - print("some_var is smaller than 10.") -else: # La clause else ("sinon") l'est aussi. - print("some_var is indeed 10.") - - -""" -Les boucles "for" itèrent sur une liste -Affiche: - chien est un mammifère - chat est un mammifère - souris est un mammifère -""" -for animal in ["chien", "chat", "souris"]: - # On peut utiliser format() pour interpoler des chaînes formattées - print("{} est un mammifère".format(animal)) - -""" -"range(nombre)" retourne un itérable de nombres -de zéro au nombre donné -Affiche: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -"range(debut, fin)" retourne un itérable de nombre -de debut à fin. -Affiche: - 4 - 5 - 6 - 7 -""" -for i in range(4, 8): - print(i) - -""" -"range(debut, fin, pas)" retourne un itérable de nombres -de début à fin en incrémentant de pas. -Si le pas n'est pas indiqué, la valeur par défaut est 1. -Affiche: - 4 - 6 - 8 -""" -for i in range(4, 8, 2): - print(i) -""" - -Les boucles "while" bouclent jusqu'à ce que la condition devienne fausse. -Affiche: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Raccourci pour x = x + 1 - -# On gère les exceptions avec un bloc try/except -try: - # On utilise "raise" pour lever une erreur - raise IndexError("Ceci est une erreur d'index") -except IndexError as e: - pass # Pass signifie simplement "ne rien faire". Généralement, on gère l'erreur ici. -except (TypeError, NameError): - pass # Si besoin, on peut aussi gérer plusieurs erreurs en même temps. -else: # Clause optionelle des blocs try/except. Doit être après tous les except. - print("Tout va bien!") # Uniquement si aucune exception n'est levée. -finally: # Éxécuté dans toutes les circonstances. - print("On nettoie les ressources ici") - -# Au lieu de try/finally pour nettoyer les ressources, on peut utiliser with -with open("myfile.txt") as f: - for line in f: - print(line) - -# Python offre une abstraction fondamentale : l'Iterable. -# Un itérable est un objet pouvant être traîté comme une séquence. -# L'objet retourné par la fonction range() est un itérable. - -filled_dict = {"one": 1, "two": 2, "three": 3} -our_iterable = filled_dict.keys() -print(our_iterable) #=> range(1,10). C'est un objet qui implémente l'interface Iterable - -# On peut boucler dessus -for i in our_iterable: - print(i) # Affiche one, two, three - -# Cependant, on ne peut pas accéder aux éléments par leur adresse. -our_iterable[1] # Lève une TypeError - -# Un itérable est un objet qui sait créer un itérateur. -our_iterator = iter(our_iterable) - -# Notre itérateur est un objet qui se rappelle de notre position quand on le traverse. -# On passe à l'élément suivant avec "next()". -next(our_iterator) #=> "one" - -# Il garde son état quand on itère. -next(our_iterator) #=> "two" -next(our_iterator) #=> "three" - -# Après que l'itérateur a retourné toutes ses données, il lève une exception StopIterator -next(our_iterator) # Lève une StopIteration - -# On peut mettre tous les éléments d'un itérateur dans une liste avec list() -list(filled_dict.keys()) #=> Returns ["one", "two", "three"] - - -#################################################### -## 4. Fonctions -#################################################### - -# On utilise "def" pour créer des fonctions -def add(x, y): - print("x est {} et y est {}".format(x, y)) - return x + y # On retourne une valeur avec return - -# Appel d'une fonction avec des paramètres : -add(5, 6) # => affiche "x est 5 et y est 6" et retourne 11 - -# Une autre manière d'appeler une fonction : avec des arguments -add(y=6, x=5) # Les arguments peuvent être dans n'importe quel ordre. - -# Définir une fonction qui prend un nombre variable d'arguments -def varargs(*args): - return args - -varargs(1, 2, 3) # => (1, 2, 3) - -# On peut aussi définir une fonction qui prend un nombre variable de paramètres. -def keyword_args(**kwargs): - return kwargs - -# Appelons la pour voir ce qu'il se passe : -keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} - - -# On peut aussi faire les deux à la fois : -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) affiche: - (1, 2) - {"a": 3, "b": 4} -""" - -# En appelant des fonctions, on peut aussi faire l'inverse : -# utiliser * pour étendre un tuple de paramètres -# et ** pour étendre un dictionnaire d'arguments. -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # équivalent à foo(1, 2, 3, 4) -all_the_args(**kwargs) # équivalent à foo(a=3, b=4) -all_the_args(*args, **kwargs) # équivalent à foo(1, 2, 3, 4, a=3, b=4) - -# Retourne plusieurs valeurs (avec un tuple) -def swap(x, y): - return y, x # Retourne plusieurs valeurs avec un tuple sans parenthèses. - # (Note: on peut aussi utiliser des parenthèses) - -x = 1 -y = 2 -x, y = swap(x, y) # => x = 2, y = 1 -# (x, y) = swap(x,y) # Là aussi, rien ne nous empêche d'ajouter des parenthèses - -# Portée des fonctions : -x = 5 - -def setX(num): - # La variable locale x n'est pas la même que la variable globale x - x = num # => 43 - print (x) # => 43 - -def setGlobalX(num): - global x - print (x) # => 5 - x = num # la variable globale x est maintenant 6 - print (x) # => 6 - -setX(43) -setGlobalX(6) - - -# Python a des fonctions de première classe -def create_adder(x): - def adder(y): - return x + y - return adder - -add_10 = create_adder(10) -add_10(3) # => 13 - -# Mais aussi des fonctions anonymes -(lambda x: x > 2)(3) # => True -(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 - -# TODO - Fix for iterables -# Il y a aussi des fonctions de base -map(add_10, [1, 2, 3]) # => [11, 12, 13] -map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] - -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] - -# On peut utiliser les compréhensions de listes pour de jolies maps et filtres. -# Une compréhension de liste stocke la sortie comme une liste qui peut elle même être une liste imbriquée. -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] - -#################################################### -## 5. Classes -#################################################### - - -# On utilise l'opérateur "class" pour définir une classe -class Human: - - # Un attribut de la classe. Il est partagé par toutes les instances de la classe. - species = "H. sapiens" - - # L'initialiseur de base. Il est appelé quand la classe est instanciée. - # Note : les doubles underscores au début et à la fin sont utilisés pour - # les fonctions et attributs utilisés par Python mais contrôlés par l'utilisateur. - # Les méthodes (ou objets ou attributs) comme: __init__, __str__, - # __repr__ etc. sont appelés méthodes magiques. - # Vous ne devriez pas inventer de noms de ce style. - def __init__(self, name): - # Assigner l'argument à l'attribut de l'instance - self.name = name - - # Une méthode de l'instance. Toutes prennent "self" comme premier argument. - def say(self, msg): - return "{name}: {message}".format(name=self.name, message=msg) - - # Une méthode de classe est partagée avec entre les instances - # Ils sont appelés avec la classe comme premier argument - @classmethod - def get_species(cls): - return cls.species - - # Une méthode statique est appelée sans référence à une instance ni à une classe. - @staticmethod - def grunt(): - return "*grunt*" - - -# Instantier une classe -i = Human(name="Ian") -print(i.say("hi")) # affiche "Ian: hi" - -j = Human("Joel") -print(j.say("hello")) # affiche "Joel: hello" - -# Appeller notre méthode de classe -i.get_species() # => "H. sapiens" - -# Changer les attributs partagés -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" - -# Appeller la méthode statique -Human.grunt() # => "*grunt*" - - -#################################################### -## 6. Modules -#################################################### - -# On peut importer des modules -import math -print(math.sqrt(16)) # => 4.0 - -# On peut importer des fonctions spécifiques d'un module -from math import ceil, floor -print(ceil(3.7)) # => 4.0 -print(floor(3.7)) # => 3.0 - -# On peut importer toutes les fonctions d'un module -# Attention: ce n'est pas recommandé. -from math import * - -# On peut raccourcir un nom de module -import math as m -math.sqrt(16) == m.sqrt(16) # => True - -# Les modules Python sont juste des fichiers Python. -# Vous pouvez écrire les vôtres et les importer. Le nom du module -# est le nom du fichier. - -# On peut voir quels fonctions et objets un module définit -import math -dir(math) - - -#################################################### -## 7. Avancé -#################################################### - -# Les générateurs aident à faire du code paresseux (lazy) -def double_numbers(iterable): - for i in iterable: - yield i + i - -# Un générateur crée des valeurs à la volée. -# Au lieu de générer et retourner toutes les valeurs en une fois, il en crée une à chaque -# itération. Cela signifie que les valeurs supérieures à 30 ne seront pas traîtées par -# double_numbers. -# Note : range est un générateur aussi. -# Créer une liste 1-900000000 prendrait beaucoup de temps -# On met un underscore à la fin d'un nom de variable normalement réservé par Python. -range_ = range(1, 900000000) -# Double tous les nombres jusqu'à ce qu'un nombre >=30 soit trouvé -for i in double_numbers(range_): - print(i) - if i >= 30: - break - - -# Decorateurs -# Dans cet exemple, beg enveloppe say -# Beg appellera say. Si say_please vaut True le message retourné sera changé -from functools import wraps - - -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Please! I am poor :(") - return msg - - return wrapper - - -@beg -def say(say_please=False): - msg = "Can you buy me a beer?" - return msg, say_please - - -print(say()) # affiche Can you buy me a beer? -print(say(say_please=True)) # affiche Can you buy me a beer? Please! I am poor :( -``` - -## Prêt pour encore plus ? - -### En ligne et gratuit (en anglais) - -* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) -* [Python Course](http://www.python-course.eu/index.php) -* [First Steps With Python](https://realpython.com/learn/python-first-steps/) - -### En ligne et gratuit (en français) - -* [Le petit guide des batteries à découvrir](https://he-arc.github.io/livre-python/) - -### Livres (en anglais) - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) diff --git a/fr-fr/pythonlegacy-fr.html.markdown b/fr-fr/pythonlegacy-fr.html.markdown new file mode 100644 index 00000000..10b1a0a6 --- /dev/null +++ b/fr-fr/pythonlegacy-fr.html.markdown @@ -0,0 +1,488 @@ +--- +language: Python 2 (legacy) +filename: learnpythonlegacy-fr.py +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Sylvain Zyssman", "https://github.com/sylzys"] + - ["Nami-Doc", "https://github.com/Nami-Doc"] +lang: fr-fr +--- + +Python a été créé par Guido Van Rossum au début des années 90. C'est maintenant un des langages de programmation les plus populaires. +Je suis tombé amoureux de Python de par la clarté de sa syntaxe. C'est pratiquement du pseudo-code exécutable. + +Vos retours sont grandement appréciés. Vous pouvez me contacter sur Twitter [@louiedinh](http://twitter.com/louiedinh) ou par e-mail: louiedinh [at] [google's email service] + +N.B. : Cet article s'applique spécifiquement à Python 2.7, mais devrait s'appliquer pour toute version Python 2.x. Python 2.7 est en fin de vie et ne sera plus maintenu à partir de 2020, il est donc recommandé d'apprendre Python avec Python 3. Pour Python 3.x, il existe un autre [tutoriel pour Python 3](http://learnxinyminutes.com/docs/fr-fr/python3-fr/). + +```python +# Une ligne simple de commentaire commence par un dièse +""" Les lignes de commentaires multipes peuvent être écrites + en utilisant 3 guillemets ("), et sont souvent utilisées + pour les commentaires +""" + +#################################################### +## 1. Types Primaires et Opérateurs +#################################################### + +# Les nombres +3 #=> 3 + +# Les calculs produisent les résultats mathématiques escomptés +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# La division est un peu spéciale. C'est une division d'entiers, et Python arrondi le résultat par défaut automatiquement. +5 / 2 #=> 2 + +# Pour corriger ce problème, on utilise les float. +2.0 # Voici un float +11.0 / 4.0 #=> 2.75 ahhh... beaucoup mieux + +# Forcer la priorité avec les parenthèses +(1 + 3) * 2 #=> 8 + +# Les valeurs booléenes sont de type primitif +True +False + +# Pour la négation, on utilise "not" +not True #=> False +not False #=> True + +# Pour l'égalité, == +1 == 1 #=> True +2 == 1 #=> False + +# L'inégalité est symbolisée par != +1 != 1 #=> False +2 != 1 #=> True + +# D'autres comparateurs +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# On peut enchaîner les comparateurs ! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Les chaînes de caractères sont créées avec " ou ' +"C'est une chaîne." +'C\'est aussi une chaîne.' + +# On peut aussi les "additioner" ! +"Hello " + "world!" #=> "Hello world!" + +# Une chaîne peut être traitée comme une liste de caractères +"C'est une chaîne"[0] #=> 'C' + +# % peut être utilisé pour formatter des chaîne, comme ceci: +"%s can be %s" % ("strings", "interpolated") + +# Une autre manière de formatter les chaînes de caractères est d'utiliser la méthode 'format' +# C'est la méthode à privilégier +"{0} peut être {1}".format("La chaîne", "formattée") +# On peut utiliser des mot-clés au lieu des chiffres. +"{name} veut manger des {food}".format(name="Bob", food="lasagnes") + +# None est un objet +None #=> None + +# Ne pas utiliser le symbole d'inégalité "==" pour comparer des objet à None +# Il faut utiliser "is" +"etc" is None #=> False +None is None #=> True + +# L'opérateur 'is' teste l'identité de l'objet. +# Ce n'est pas très utilisé avec les types primitifs, mais cela peut être très utile +# lorsque l'on utilise des objets. + +# None, 0, et les chaînes de caractères vides valent False. +# Toutes les autres valeurs valent True +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. Variables et Collections +#################################################### + +# Afficher du texte, c'est facile +print "Je suis Python. Enchanté!" + + +# Il n'y a pas besoin de déclarer les variables avant de les assigner. +some_var = 5 # La convention veut que l'on utilise des minuscules_avec_underscores +some_var #=> 5 + +# Accéder à une variable non assignée lève une exception +# Voyez les structures de contrôle pour en apprendre plus sur la gestion des exceptions. +some_other_var # Lève une exception + +# 'if' peut être utilisé comme expression +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Listes +li = [] +# On peut remplir liste dès l'instanciation +other_li = [4, 5, 6] + +# On ajoute des éléments avec 'append' +li.append(1) #li contient [1] +li.append(2) #li contient [1, 2] +li.append(4) #li contient [1, 2, 4] +li.append(3) #li contient [1, 2, 4, 3] + +# Et on les supprime avec 'pop' +li.pop() #=> 3 et li contient [1, 2, 4] +# Remettons-le dans la liste +li.append(3) # li contient [1, 2, 4, 3] de nouveau. + +# On accède aux éléments d'une liste comme à ceux un tableau. +li[0] #=> 1 +# Le dernier élément +li[-1] #=> 3 + +# Accèder aux indices hors limite lève une exception +li[4] # Lève un 'IndexError' + +# On peut accèder à des rangs de valeurs avec la syntaxe "slice" +# (C'est un rang de type 'fermé/ouvert' pour les plus matheux) +li[1:3] #=> [2, 4] +# Sans spécifier de fin de rang, on "saute" le début de la liste +li[2:] #=> [4, 3] +# Sans spécifier de début de rang, on "saute" la fin de la liste +li[:3] #=> [1, 2, 4] + +# Retirer un élément spécifique dee la liste avec "del" +del li[2] # li contient [1, 2, 3] + +# On peut additionner des listes entre elles +li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li et other_li existent toujours à part entière + +# Concaténer des listes avec "extend()" +li.extend(other_li) # li vaut maintenant [1, 2, 3, 4, 5, 6] + +# Vérifier l'existence d'un élément dans une liste avec "in" +1 in li #=> True + +# Récupérer la longueur avec "len()" +len(li) #=> 6 + + +# Les "tuples" sont comme des listes, mais sont immuables. +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # Lève un 'TypeError' + +# Mais vous pouvez faire tout ceci sur les tuples: +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# Vous pouvez "dé-packager" les tuples (ou les listes) dans des variables +a, b, c = (1, 2, 3) # a vaut maintenant 1, b vaut maintenant 2 and c vaut maintenant 3 +# Sans parenthèses, un tuple est créé par défaut +d, e, f = 4, 5, 6 +# Voyez maintenant comme il est facile d'inverser 2 valeurs +e, d = d, e # d is now 5 and e is now 4 + + +# Dictionnaires +empty_dict = {} +# Un dictionnaire pré-rempli +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Trouver des valeurs avec [] +filled_dict["one"] #=> 1 + +# Récupérer toutes les clés sous forme de liste avec "keys()" +filled_dict.keys() #=> ["three", "two", "one"] +# Note - l'ordre des clés du dictionnaire n'est pas garanti. +# Vos résultats peuvent différer de ceux ci-dessus. + +# Récupérer toutes les valeurs sous forme de liste avec "values()" +filled_dict.values() #=> [3, 2, 1] +# Note - Même remarque qu'au-dessus concernant l'ordre des valeurs. + +# Vérifier l'existence d'une clé dans le dictionnaire avec "in" +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# Chercher une clé non existante lève une 'KeyError' +filled_dict["four"] # KeyError + +# Utiliser la méthode "get()" pour éviter 'KeyError' +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# La méthode get() prend un argument par défaut quand la valeur est inexistante +filled_dict.get("one", 4) #=> 1 +filled_dict.get("four", 4) #=> 4 + +# La méthode "setdefault()" permet d'ajouter de manière sécuris une paire clé-valeur dans le dictionnnaire +filled_dict.setdefault("five", 5) #filled_dict["five"] vaut 5 +filled_dict.setdefault("five", 6) #filled_dict["five"] is toujours 5 + + +# Les sets stockent ... des sets +empty_set = set() +# On initialise un "set()" avec tout un tas de valeurs +some_set = set([1,2,2,3,4]) # some_set vaut maintenant set([1, 2, 3, 4]) + +# Depuis Python 2.7, {} peut être utilisé pour déclarer un 'set' +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Ajouter plus d'éléments au set +filled_set.add(5) # filled_set contient maintenant {1, 2, 3, 4, 5} + +# Intersection de sets avec & +other_set = {3, 4, 5, 6} +filled_set & other_set #=> {3, 4, 5} + +# Union de sets avec | +filled_set | other_set #=> {1, 2, 3, 4, 5, 6} + +# Différence de sets avec - +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# Vérifier l'existence d'une valeur dans un set avec "in" +2 in filled_set #=> True +10 in filled_set #=> False + + +#################################################### +## 3. Structure de contrôle +#################################################### + +# Initialisons une variable +some_var = 5 + +# Voici une condition 'if'. L'indentation est significative en Python ! +# Affiche "some_var est inférieur à 10" +if some_var > 10: + print "some_var est supérieur à 10." +elif some_var < 10: # La clause elif est optionnelle + print "some_var iinférieur à 10." +else: # La clause else également + print "some_var vaut 10." + + +""" +Les boucles "for" permettent d'itérer sur les listes +Affiche: + chien : mammifère + chat : mammifère + souris : mammifère +""" +for animal in ["chien", "chat", "souris"]: + # On peut utiliser % pour l'interpolation des chaînes formattées + print "%s : mammifère" % animal + +""" +"range(number)" retourne une liste de nombres +de 0 au nombre donné +Affiche: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +Les boucles "while" boucle jusqu'à ce que leur condition ne soit plus vraie +Affiche: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Raccourci pour x = x + 1 + +# Gérer les exceptions avec un bloc try/except + +# Fonctionne pour Python 2.6 et ultérieur: +try: + # Utiliser "raise" pour lever une exception + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass ne prend pas d'arguments. Généralement, on gère l'erreur ici. + + +#################################################### +## 4. Fonctions +#################################################### + +# Utiliser "def" pour créer une nouvelle fonction +def add(x, y): + print "x vaut %s et y vaur %s" % (x, y) + return x + y # Renvoi de valeur avec 'return' + +# Appeller une fonction avec des paramètres +add(5, 6) #=> Affichet "x is 5 et y vaut 6" et renvoie 11 + +# Une autre manière d'appeller une fonction, avec les arguments +add(y=6, x=5) # Les arguments peuvent venir dans n'importe quel ordre. + +# On peut définir une foncion qui prend un nombre variable de paramètres +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# On peut également définir une fonction qui prend un nombre +# variable d'arguments +def keyword_args(**kwargs): + return kwargs + +# Appelons-là et voyons ce qu'il se passe +keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} + +# On peut faire les deux à la fois si on le souhaite +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) affiche: + (1, 2) + {"a": 3, "b": 4} +""" + +# En appellant les fonctions, on peut faire l'inverse des paramètres / arguments ! +# Utiliser * pour développer les paramètres, et ** pour développer les arguments +params = (1, 2, 3, 4) +args = {"a": 3, "b": 4} +all_the_args(*args) # equivaut à foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivaut à foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivaut à foo(1, 2, 3, 4, a=3, b=4) + +# Python a des fonctions de première classe +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) #=> 13 + +# Mais également des fonctions anonymes +(lambda x: x > 2)(3) #=> True + +# On trouve aussi des fonctions intégrées plus évoluées +map(add_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# On peut utiliser la syntaxe des liste pour construire les "maps" et les "filters" +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. Classes +#################################################### + +# Une classe est un objet +class Human(object): + + # Un attribut de classe. Il est partagé par toutes les instances de cette classe. + species = "H. sapiens" + + # Initialiseur basique + def __init__(self, name): + # Assigne le paramètre à l'attribut de l'instance de classe. + self.name = name + + # Une méthode de l'instance. Toutes les méthodes prennent "self" comme 1er paramètre. + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # Une méthode de classe est partagée par toutes les instances. + # On les appelle avec le nom de la classe en premier paramètre + @classmethod + def get_species(cls): + return cls.species + + # Une méthode statique est appellée sans référence à une classe ou à une instance + @staticmethod + def grunt(): + return "*grunt*" + + +# Instancier une classe +i = Human(name="Ian") +print i.say("hi") # Affiche "Ian: hi" + +j = Human("Joel") +print j.say("hello") #Affiche "Joel: hello" + +# Appeller notre méthode de classe +i.get_species() #=> "H. sapiens" + +# Changer les attributs partagés +Human.species = "H. neanderthalensis" +i.get_species() #=> "H. neanderthalensis" +j.get_species() #=> "H. neanderthalensis" + +# Appeller la méthode statique +Human.grunt() #=> "*grunt*" + + +#################################################### +## 6. Modules +#################################################### + +# On peut importer des modules +import math +print math.sqrt(16) #=> 4.0 + +# Et récupérer des fonctions spécifiques d'un module +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Récuperer toutes les fonctions d'un module +# Attention, ce n'est pas recommandé. +from math import * + +# On peut raccourcir le nom d'un module +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Les modules Python sont juste des fichiers Python ordinaires. +# On peut écrire ses propres modules et les importer. +# Le nom du module doit être le même que le nom du fichier. + +# On peut trouver quelle fonction et attributs déterminent un module +import math +dir(math) + + +``` + +## Prêt à aller plus loin? + +### En ligne gratuitement + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### Format papier + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/fr-fr/rust-fr.html.markdown b/fr-fr/rust-fr.html.markdown index b3675f5b..6fc0d07d 100644 --- a/fr-fr/rust-fr.html.markdown +++ b/fr-fr/rust-fr.html.markdown @@ -1,5 +1,5 @@ --- -language: rust +language: Rust contributors: - ["P1start", "http://p1start.github.io/"] translators: @@ -221,7 +221,7 @@ fn main() { // `for` boucles / itération let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } @@ -309,7 +309,7 @@ fn main() { Il y a beaucoup plus à Rust -- ce est juste l'essentiel de Rust afin que vous puissiez comprendre les choses les plus importantes. Pour en savoir plus sur Rust, lire [La Programmation Rust -Langue](http://doc.rust-lang.org/book/index.html) et etudier la +Langue](http://doc.rust-lang.org/book/index.html) et étudier la [/r/rust](http://reddit.com/r/rust) subreddit. Les gens sur le canal de #rust sur irc.mozilla.org sont aussi toujours prêts à aider les nouveaux arrivants. diff --git a/fr-fr/set-theory-fr.html.markdown b/fr-fr/set-theory-fr.html.markdown new file mode 100644 index 00000000..d1ac2711 --- /dev/null +++ b/fr-fr/set-theory-fr.html.markdown @@ -0,0 +1,132 @@ +--- +category: Algorithms & Data Structures +name: Set theory +lang: fr-fr +contributors: + - ["kieutrang", "https://github.com/kieutrang1729"] +--- + +La théorie des ensembles est une branche des mathématiques qui étudie les ensembles, leurs opérations et leurs propriétés. + +* Un ensemble est une collection d'éléments disjoints. + +## Symboles de base + +### Opérateurs +* l'opérateur réunion, `∪`, signifie "ou" ; +* l'opérateur intersection, `∩`, signifie "et" ; +* l'opérateur différence, `\`, signifie "sans", (lire "A moins B") ; +* l'opérateur complémentaire, `'`, signifie "le complémentaire de" ; +* l'opérateur croix, `×`, signifie "le produit cartésien de". + +### Autres symboles +* le symbole deux-points, `:`, signifie "tel que" ; +* le symbole d'appartenance, `∈`, signifie "appartient à" ; +* le symbole sous-ensemble, `⊆`, signifie "est un sous-ensemble de" ; +* le symbole sous-ensemble propre, `⊂`, signifie "est un sous-ensemble de mais n'est pas égal à". + +### Ensembles importants +* `∅`, l'ensemble vide, c'est-à-dire l'ensemble ne contenant aucun élément ; +* `ℕ`, l'ensemble des nombres naturels ; +* `ℤ`, l'ensemble des entiers ; +* `ℚ`, l'ensemble des nombres rationnels ; +* `ℝ`, l'ensemble des nombres réels. + +Quelques mise en gardes sur les ensembles définis ci-dessus: +1. Même si l'ensemble vide ne contient aucun élément, il est lui-même un sous-ensemble de n'importe quel ensemble. +2. Il n'y a pas d'accord général sur l'appartenance de zéro dans l'ensemble des nombres naturels, et les livres indiquent explicitement si l'auteur considère le zéro comme nombre naturel ou pas. + + +### Cardinalité + +La cardinalité, ou taille, d'un ensemble est déterminée par le nombre d'éléments dans l'ensemble. L'opérateur de cardinalité s'écrit, `| ... |`. +Par exemple, si `S = { 1, 2, 4 }`, alors `|S| = 3`. + +### L'ensemble vide +* L'ensemble vide peut se définir en compréhension à l'aide d'une propriété qui n'est satisfaite par nul élément, e.g. `∅ = { x : x ≠ x }`, ou `∅ = { x : x ∈ N, x < 0 }`. +* il n'y a qu'un seul ensemble vide. +* l'ensemble vide est sous-ensemble de tout ensemble. +* la cardinalité de l'ensemble vide est 0, ou `|∅| = 0`. + +## Notation ensembliste + +### Définition par extension + +Un ensemble peut être defini en extension par une liste de tous les éléments qui sont contenus dans l'ensemble. Par exemple, `S = { a, b, c, d }`. + +Quand le contexte est clair, on peut raccourcir la liste en utilisant des points de suspension. Par exemple, `E = { 2, 4, 6, 8, ... }` est clairement l'ensemble de tous les nombres pairs, contenant un nombre infini des éléments, même si on a explicitement écrit seulement les quatre premiers. + +### Définition par compréhension + +C'est une notation plus descriptif qui permet de définir un ensemble à l'aide d'un sujet et d'une propriété, et il est noté `S = { sujet : propriété }`. Par exemple, + +``` +A = { x : x est une voyelle } = { a, e, i, o, u, y} +B = { x : x ∈ N, x < 10 } = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } +C = { x : x = 2k, k ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +On peut même appliquer une fonction au sujet, e.g. + +``` +D = { 2x : x ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +## Relations + +### Appartenance + +* Si l'élément `a` est dans l'ensemble `A`, on dit que `a` appartient à `A` et on le note `a ∈ A`. +* Si l'élément `a` n'est pas dans l'ensemble `A`, on dit que `a` n'appartient pas à `A` et on le note `a ∉ A`. + +### Égalité + +* On dit que deux ensembles `A` et `B` sont égaux s'ils contiennent les mêmes éléments, et on le note `A = B`. +* Les ensembles n'ont pas de notion d'ordre, par exemple `{ 1, 2, 3, 4 } = { 2, 3, 1, 4 }`. +* Un élément ne peut apparaître qu'au plus une seule fois - il n'y a jamais de répétition, e.g. `{ 1, 2, 2, 3, 4, 3, 4, 2 } = { 1, 2, 3, 4 }`. +* Deux ensembles `A` et `B` sont égaux si et seulement si `A ⊆ B` et `B ⊆ A`. + +## Ensemble puissance +* L'ensemble puissance d'un ensemble `A` est l'ensemble contenant tous les sous-ensembles de `A`. Il est noté `P(A)`. Si la cardinalité de `A` est `n`, la cardinalité de `P(A)` est `2^n`. + +``` +P(A) = { x : x ⊆ A } +``` + +## Opérations ensemblistes +### Réunion +La réunion de deux ensembles `A` et `B` est l'ensemble contenant tous les éléments qui appartient à `A` ou à `B`. + +``` +A ∪ B = { x : x ∈ A ∪ x ∈ B } +``` + +### Intersection +L'intersection de deux ensembles `A` et `B` est l'ensemble contenant tous les éléments qui appartient à la fois à `A` et à `B`. + +``` +A ∩ B = { x : x ∈ A, x ∈ B } +``` + +### Différence +La différence de deux ensembles `A` et `B` est l'ensemble contenant tous les éléments de l'ensemble `A` qui n'appartient pas à `B`. + +``` +A \ B = { x : x ∈ A, x ∉ B } +``` + +### Différence symétrique +Le différence symétrique de deux ensembles `A` et `B` est l'ensemble contenant tous les éléments de `A` et `B` qui n'apparaissent pas dans leur intersection. + +``` +A △ B = { x : ((x ∈ A) ∩ (x ∉ B)) ∪ ((x ∈ B) ∩ (x ∉ A)) } + +A △ B = (A \ B) ∪ (B \ A) +``` + +### Produit cartésien +Le produit cartésien de deux ensembles `A` et `B` est l'ensemble contenant tous les couples dont le premier élément appartient à `A` et le deuxième à `B`. + +``` +A × B = { (x, y) | x ∈ A, y ∈ B } +``` diff --git a/fr-fr/typescript-fr.html.markdown b/fr-fr/typescript-fr.html.markdown index 52d34650..8a761f61 100644 --- a/fr-fr/typescript-fr.html.markdown +++ b/fr-fr/typescript-fr.html.markdown @@ -12,7 +12,7 @@ TypeScript est un langage visant à faciliter le développement d'applications l TypeScript ajoute des concepts classiques comme les classes, les modules, les interfaces, les génériques et le typage statique (optionnel) à JavaScript. C'est une surcouche de JavaScript : tout le code JavaScript est valide en TypeScript ce qui permet de l'ajouter de façon transparente à n'importe quel projet. Le code TypeScript est transcompilé en JavaScript par le compilateur. -Cet article se concentrera seulement sur la syntaxe supplémentaire de TypeScript, plutôt que celle de [JavaScript] (../javascript/). +Cet article se concentrera seulement sur la syntaxe supplémentaire de TypeScript, plutôt que celle de [JavaScript] (../javascript-fr/). Pour tester le compilateur de TypeScript, rendez-vous au [Playground] (http://www.typescriptlang.org/Playground) où vous pourrez coder, profiter d'une autocomplétion et accéder directement au rendu JavaScript. diff --git a/fr-fr/wolfram-fr.html.markdown b/fr-fr/wolfram-fr.html.markdown index 7b446259..10a37994 100644 --- a/fr-fr/wolfram-fr.html.markdown +++ b/fr-fr/wolfram-fr.html.markdown @@ -21,7 +21,7 @@ Ce code d'exemple peut être utilisé et modifié dans ces logiciels. Cependant, copier-coller directement dans Mathematica peut causer des problèmes de formatage, car il ne contient aucune information de mise en page. -``` +```mathematica (* Ceci est un commentaire *) (* Dans Mathematica, au lieu d'utiliser ces commentaires, vous pouvez créer des diff --git a/fr-fr/yaml-fr.html.markdown b/fr-fr/yaml-fr.html.markdown index c7cb9421..36c33bd1 100644 --- a/fr-fr/yaml-fr.html.markdown +++ b/fr-fr/yaml-fr.html.markdown @@ -36,6 +36,7 @@ valeur_numérique: 100 notation_scientifique: 1e+12 booléen: true valeur_null: null +une_autre_valeur_null: ~ clé avec espaces: valeur # Bien qu'il ne soit pas nécessaire de mettre les chaînes de caractères # entre guillemets, cela reste possible, et parfois utile. diff --git a/fsharp.html.markdown b/fsharp.html.markdown index 064a9fdd..f1f8e95d 100644 --- a/fsharp.html.markdown +++ b/fsharp.html.markdown @@ -33,6 +33,21 @@ let myInt = 5 let myFloat = 3.14 let myString = "hello" // note that no types needed +// Mutable variables +let mutable a=3 +a <- 4 // a is now 4. + +// Somewhat mutable variables +// Reference cells are storage locations that enable you to create mutable values with reference semantics. +// See https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/reference-cells +let xRef = ref 10 +printfn "%d" xRef.Value // 10 +xRef.Value <- 11 +printfn "%d" xRef.Value // 11 + +let a=[ref 0; ref 1] // somewhat mutable list +a[0].Value <- 2 + // ------ Lists ------ let twoToFive = [2; 3; 4; 5] // Square brackets create a list with // semicolon delimiters. @@ -633,6 +648,6 @@ module NetCompatibilityExamples = ## More Information -For more demonstrations of F#, go to the [Try F#](http://www.tryfsharp.org/Learn) site, or my [why use F#](http://fsharpforfunandprofit.com/why-use-fsharp/) series. +For more demonstrations of F#, go to my [why use F#](http://fsharpforfunandprofit.com/why-use-fsharp/) series. -Read more about F# at [fsharp.org](http://fsharp.org/). +Read more about F# at [fsharp.org](http://fsharp.org/) and [dotnet's F# page](https://dotnet.microsoft.com/languages/fsharp). diff --git a/func.html.markdown b/func.html.markdown new file mode 100644 index 00000000..da1b2214 --- /dev/null +++ b/func.html.markdown @@ -0,0 +1,338 @@ +--- +language: FunC +filename: learnFunC.fc +contributors: + - ["Ivan Romanovich", "https://t.me/ton_learn"] + - ["Kirill Malev", "https://fslabs.io"] +--- + +The FunC language is used to program smart contracts on the [The Open Network](https://ton.org) blockchain. Contract logic is executed in TVM, the stack-based TON Virtual Machine. + +FunC is a statically typed, which is similar to C. + +# Basic syntax, the first Smart Contract — Data Types, Storage, Functions + +```c +;; Single line comment + + {- This is a multi-line comment + {- this is a comment in the comment -} + -} + + (int) sum(int a, int b) { + ;; This is a function that gets two integer parameters + ;; and return integer result + return a + b; + ;; All integers are signed and are 257 bit long. Overflow throws exception + ;; expressions must end with a semicolon + } + + () f(int i, cell c, slice s, builder b, cont c, tuple t) { + ;; FunC has 7 atomic types: + ;; int - 257 bit signed integers, + ;; cell - basic for TON opaque data structure, + ;; which contains up to 1,023 bits and up to 4 references to other cells, + ;; slice and builder - special objects to read from and write to cells, + ;; continuation - another flavor of cell that contains + ;; ready-to-execute TVM byte-code. + ;; tuple is an ordered collection of up to 255 components, + ;; having arbitrary value types, possibly distinct. + ;; Finally tensor type (A,B, ...) is an ordered collection ready for + ;; mass assigning like: (int, int) a = (3, 5); + ;; Special case of tensor type is the unit type (). + ;; It represents that a function doesn’t return any value, + ;; or has no arguments. + } + + ;; During execution, the contract has read access to local context: + ;; its storage, balance, time, network config, etc. + ;; Contract may change its storage and code, + ;; and also may send messages to other contracts + + ;; Let’s write a counter smart contract that gets a number + ;; from an incoming message, + ;; adds to already stored numbers and stores result in “storage” + + ;; For handling special events, smart contracts have reserved methods: + ;; recv_internal() handles internal messages from other smart contracts + ;; recv_external() handles external messages from the outside world — + ;; e.g., from a user. + + () recv_internal(slice in_msg_body) { + ;; Cells play the role of memory in the stack-based TVM. + ;; A cell can be transformed into a slice, + ;; and then the data bits and references to + ;; other cells from the cell can be obtained + ;; by loading them from the slice. + ;; Data bits and references to other cells can be stored + ;; into a builder, and then the builder can be finalized into a new cell. + ;; recv_internal gets the slice + ;; with incoming message data as an argument. + + ;; As everything else on TON, permanent storage data is stored as a cell. + ;; It can be retrieved via the get_data() method + ;; begin_parse - converts a cell with data into a readable slice + + slice ds = get_data().begin_parse(); + ;; `.` is a syntax sugar: a.b() is equivalent to b(a) + + ;; load_uint is a function from the FunC standard library; + ;; it loads an unsigned n-bit integer from a slice + int total = ds~load_uint(64); ;; `~` is a "modifying" method: + ;; essentially, it is a syntax sugar: `r = a~b(x)` + ;; is equivalent to (a,r) = b(a,x) + + ;; Now let’s read the incoming value from the message body slice + int n = in_msg_body~load_uint(32); + + total += n; + ;; integers support usual +-*/ operations as well as (+-*/)= syntax sugar + + ;; In order to keep a store integer value, we need to do four things: + ;; create a Builder for the future cell - begin_cell() + ;; write a value to total - store_uint(value, bit_size) + ;; create a Cell from the Builder - end_cell() + ;; write the resulting cell into permanent storage - set_data() + + set_data(begin_cell().store_uint(total, 64).end_cell()); + } + + + + ;; The FunC program is essentially a list of + function declarations/definitions and global variable declarations. + + ;; Any function in FunC matches the following pattern: + ;; [<forall declarator>] <return_type> <function_name>(<comma_separated_function_args>) <specifiers> + + + ;; Specifiers: + ;; The impure specifier indicates that + ;; function calls should not be optimized + ;; (whether its result is used or not) + ;; it is important for methods that change the smart contract data + ;; or send messages + + ;; The method_id specifier allows you to call a GET function by name + + ;; For instance, we can create a get method for the contract above + ;; to allow outside viewers to read counter + + int get_total() method_id { + slice ds = get_data().begin_parse(); + int total = ds~load_uint(64); + + ;; Note that (int) and int is the same, + ;; thus brackets in the function declaration + ;; and in the return statement are omitted. + return total; + } + ;; Now any observer can read get_total value via lite-client or explorer +``` + +# Messages + +The actor model is a model of concurrent computation and is at the heart of TON smart contracts. Each smart contract can process one message at a time, change its own state, or send one or several messages. Processing of the message occurs in one transaction, that is, it cannot be interrupted. Messages to one contract are processed consequently one by one. As a result, the execution of each transaction is local and can be parallelized at the blockchain level, which allows for on-demand throughput horizontal scaling and hosting an unlimited number of users and transactions. + +```c +;; For normal internal message-triggered transactions, +;; before passing control to recv_internal TVM puts the following +;; elements on stack. +;;;; Smart contract balance (in nanoTons) +;;;; Incoming message balance (in nanoTons) +;;;; Cell with an incoming message +;;;; Incoming message body, slice type +;; In turn, recv_internal may use only +;; the required number of fields (like 1 in the example above or 4 below) + +;; Let’s dive into message sending + +() recv_internal ( + int balance, int msg_value, cell in_msg_full, slice in_msg_body) { + ;; + ;; Every message has a strict layout, thus by parsing it, + ;; we can get the sender’s address + ;; first, we need to read some tech flags and + ;; then take the address using load_msg_addr + ;; function from FunC standard library - () + var cs = in_msg_full.begin_parse(); + var flags = cs~load_uint(4); + slice sender_address = cs~load_msg_addr(); + + ;; if we want to send a message, we first need to construct it + ;; message serialization in most cases may be reduced to + var msg = begin_cell() + .store_uint(0x18, 6) ;; tech flags + .store_slice(addr) ;; destination address + .store_coins(amount) ;; attached value + .store_uint(0, 107) ;; more tech flags :) + .store_slice(in_msg_body) ;; just put some payload here + .end_cell(); + + ;; to send messages, use send_raw_message from the standard library. + ;; it accepts two arguments message and mode + send_raw_message(msg, 64); + + ;; mode parameter specifies how to process the funds passed into + ;; the smart contract with the message and the smart contract funds + ;; 64 means send everything from the incoming message — + ;; what’s left after the commission is deducted + + ;; Exceptions can be thrown by conditional primitives throw_if and + ;; throw_unless and by unconditional throw + ;; by default, it will automatically cause a bounce message with 64 mode + + var some = 7; + throw_if(102, some == 10); + ;; Throw exception with code 102 conditionally + throw_unless(103, some != 10); + ;; Throw exception with code 103 conditionally + throw(101); ;; Throw exception with code 101 unconditionally +} +``` + +# Flow control: Conditional Statements and Loops; Dictionaries + +```c +;; FunC, of course, supports if statements + +;;;; usual if-else +if (flag) { + ;;do_something(); +} +else { + ;;do_alternative(); +} + +;; If statements are often used as an operation identifier +;; for a smart contract, for example: + +() recv_internal ( + int balance, int msg_value, cell in_msg_full, slice in_msg_body) { + int op = in_msg_body~load_int(32); + if (op == 1) { + ;; smth here + } else { + if (op == 2) { + ;; smth here + } else { + ;; smth here + } + } +} + +;; Loops +;; FunC supports repeat, while and do { ... } until loops. +;; for loop is not supported. + +;; repeat +int x = 1; +repeat(10) { + x *= 2; +} +;; x = 1024 + +;; while +int x = 2; +while (x < 100) { + x = x * x; +} +;; x = 256 + +;; until loops +int x = 0; +do { + x += 3; +} until (x % 17 == 0); +;; x = 51 + +;; In practice, loops in TON smart contracts are often used to work with +;; dictionaries, or as they are also called in TON hashmaps + +;; A hashmap is a data structure represented by a tree. +;; Hashmap maps keys to values of arbitrary type so that +;; quick lookup and modification are possible. + +;; udict_get_next? from FunC standard library in combination with +;; the loop will help, go through the dictionary + +int key = -1; +do { + (key, slice cs, int f) = dic.udict_get_next?(256, key); + +} until (~ f); + +;; udict_get_next? - Calculates the minimum key k in the dictionary dict +;; that is greater than some given value and returns k, +;; the associated value, and a flag indicating success. +;; If the dictionary is empty, returns (null, null, 0). +``` + +# Functions + +```c +;; Most useful functions are slice reader and builder writer primitives, +;; storage handlers and sending messages + +;; slice begin_parse(cell c) - Converts a cell into a slice +;; (slice, int) load_int(slice s, int len) - +;; Loads a signed len-bit integer from a slice. +;; (slice, int) load_uint(slice s, int len) - +;; Loads a unsigned len-bit integer from a slice. +;; (slice, slice) load_bits(slice s, int len) - +;; Loads the first 0 ≤ len ≤ 1023 bits from slice into a separate slice. +;; (slice, cell) load_ref(slice s) - Loads the reference cell from the slice. + +;; builder begin_cell() - Creates a new empty builder. +;; cell end_cell(builder b) - Converts a builder into an ordinary cell. +;; builder store_int(builder b, int x, int len) - +;; Stores a signed len-bit integer x into b for 0 ≤ len ≤ 257. +;; builder store_uint(builder b, int x, int len) - +;; Stores an unsigned len-bit integer x into b for 0 ≤ len ≤ 256. +;; builder store_slice(builder b, slice s) - Stores slice s into builder b. +;; builder store_ref(builder b, cell c) - +;; Stores a reference to cell c into builder b. + +;; cell get_data() - Returns the persistent contract storage cell. +;; () set_data(cell c) - Sets cell c as persistent contract data. + +;; () send_raw_message(cell msg, int mode) - +;; put message msg into sending queue with mode. +;; Note, that message will be sent after a successful execution +;; of the whole transaction + +;; Detailed descriptions of all standard functions can be found +;; in docs https://ton.org/docs/#/func/stdlib +;; +``` + +## Additional resources +- [FunC Lessons](https://github.com/romanovichim/TonFunClessons_Eng) +- [TON Development Onboarding](https://www.tonspace.co) +- [TON Documentation](https://ton.org/docs/#/) +- [FunC Documentation](https://ton.org/docs/#/func/overview) +- [TON Smart Contracts examples](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont) +- [Community portal](https://society.ton.org) +- [Blockchain portal](https://ton.org) +- [Stackoverflow](https://stackoverflow.com/questions/tagged/ton) + +## Social +- [Developer community](https://t.me/tondev_eng) +- [TON Learn](https://t.me/ton_learn) +- [FunC Lessons Channel](https://github.com/romanovichim/TonFunClessons_Eng) +- [FunC onboarding](https://t.me/func_guide) +- [Tondev News](https://t.me/tondevnews) + +## Useful blogposts +- [Setting up a TON Development Environment](https://society.ton.org/setting-up-a-ton-development-environment) +- [Hello World on TON](https://society.ton.org/ton-hello-world-step-by-step-guide-for-writing-your-first-smart-contract-in-func) + + +## Future To Dos +- Add smart contracts examples +- Add more posts + + +This file is mostly copied from [TonFunClessons 15 minutes intro](https://github.com/romanovichim/TonFunClessons_Eng/blob/main/13lesson/15min.md). + +P.S. If by any chance you're familiar with [Forth](https://learnxinyminutes.com/docs/forth/), you can also take a look at [Fift](https://ton-blockchain.github.io/docs/fiftbase.pdf).
\ No newline at end of file diff --git a/gdscript.html.markdown b/gdscript.html.markdown new file mode 100644 index 00000000..0bfac26a --- /dev/null +++ b/gdscript.html.markdown @@ -0,0 +1,325 @@ +--- +language: GDScript +contributors: + - ["Wichamir", "https://github.com/Wichamir/"] +filename: learngdscript.gd +--- + +GDScript is a dynamically typed scripting language made specifically for +free and open source game engine Godot. GDScript's syntax is similar to +Python's. Its main advantages are ease of use and tight integration with +the engine. It's a perfect fit for game development. + +## Basics + +```nim +# Single-line comments are written using hash symbol. +""" + Multi-line + comments + are + written + using + docstrings. +""" + +# Script file is a class in itself and you can optionally define a name for it. +class_name MyClass + +# Inheritance +extends Node2D + +# Member variables +var x = 8 # int +var y = 1.2 # float +var b = true # bool +var s = "Hello World!" # String +var a = [1, false, "brown fox"] # Array - similar to list in Python, + # it can hold different types + # of variables at once. +var d = { + "key" : "value", + 42 : true +} # Dictionary holds key-value pairs. +var p_arr = PoolStringArray(["Hi", "there", "!"]) # Pool arrays can + # only hold a certain type. + +# Built-in vector types: +var v2 = Vector2(1, 2) +var v3 = Vector3(1, 2, 3) + +# Constants +const ANSWER_TO_EVERYTHING = 42 +const BREAKFAST = "Spam and eggs!" + +# Enums +enum { ZERO, ONE , TWO, THREE } +enum NamedEnum { ONE = 1, TWO, THREE } + +# Exported variables are visible in the inspector. +export(int) var age +export(float) var height +export var person_name = "Bob" # Export type hints are unnecessary + # if you set a default value. + +# Functions +func foo(): + pass # pass keyword is a placeholder for future code + +func add(first, second): + return first + second + +# Printing values +func printing(): + print("GDScript ", "is ", " awesome.") + prints("These", "words", "are", "divided", "by", "spaces.") + printt("These", "words", "are", "divided", "by", "tabs.") + printraw("This gets printed to system console.") + +# Math +func doing_math(): + var first = 8 + var second = 4 + print(first + second) # 12 + print(first - second) # 4 + print(first * second) # 32 + print(first / second) # 2 + print(first % second) # 0 + # There are also +=, -=, *=, /=, %= etc., + # however no ++ or -- operators. + print(pow(first, 2)) # 64 + print(sqrt(second)) # 2 + printt(PI, TAU, INF, NAN) # built-in constants + +# Control flow +func control_flow(): + x = 8 + y = 2 # y was originally a float, + # but we can change its type to int + # using the power of dynamic typing! + + if x < y: + print("x is smaller than y") + elif x > y: + print("x is bigger than y") + else: + print("x and y are equal") + + var a = true + var b = false + var c = false + if a and b or not c: # alternatively you can use &&, || and ! + print("This is true!") + + for i in range(20): # GDScript's range is similar to Python's + print(i) # so this will print numbers from 0 to 19 + + for i in 20: # unlike Python, you can loop over an int directly + print(i) # so this will also print numbers from 0 to 19 + + for i in ["two", 3, 1.0]: # iterating over an array + print(i) + + while x > y: + printt(x, y) + y += 1 + + x = 2 + y = 10 + while x < y: + x += 1 + if x == 6: + continue # 6 won't get printed because of continue statement + prints("x is equal to:", x) + if x == 7: + break # loop will break on 7, so 8, 9 and 10 won't get printed + + match x: + 1: + print("Match is similar to switch.") + 2: + print("However you don't need to put cases before each value.") + 3: + print("Furthermore each case breaks on default.") + break # ERROR! Break statement is unnecessary! + 4: + print("If you need fallthrough use continue.") + continue + _: + print("Underscore is a default case.") + + # ternary operator (one line if-else statement) + prints("x is", "positive" if x >= 0 else "negative") + +# Casting +func casting_examples(): + var i = 42 + var f = float(42) # cast using variables constructor + var b = i as bool # or using "as" keyword + +# Override functions +# By a convention built-in overridable functions start with an underscore, +# but in practice you can override virtually any function. + +# _init is called when object gets initialized +# This is the object's constructor. +func _init(): + # Initialize object's internal stuff here. + pass + +# _ready gets called when script's node and +# its children have entered the scene tree. +func _ready(): + pass + +# _process gets called on every frame. +func _process(delta): + # The delta argument passed to this function is a number of seconds, + # which passed between the last frame and the current one. + print("Delta time equals: ", delta) + +# _physics_process gets called on every physics frame. +# That means delta should be constant. +func _physics_process(delta): + # Simple movement using vector addition and multiplication. + var direction = Vector2(1, 0) # or Vector2.RIGHT + var speed = 100.0 + self.global_position += direction * speed * delta + # self refers to current class instance + +# When overriding you can call parent's function using the dot operator +# like here: +func get_children(): + # Do some additional things here. + var r = .get_children() # call parent's implementation + return r + +# Inner class +class InnerClass: + extends Object + + func hello(): + print("Hello from inner class!") + +func use_inner_class(): + var ic = InnerClass.new() + ic.hello() + ic.free() # use free for memory cleanup +``` + +## Accessing other nodes in the scene tree + +```nim +extends Node2D + +var sprite # This variable will hold the reference. + +# You can get references to other nodes in _ready. +func _ready() -> void: + # NodePath is useful for accessing nodes. + # Create NodePath by passing String to its constructor: + var path1 = NodePath("path/to/something") + # Or by using NodePath literal: + var path2 = @"path/to/something" + # NodePath examples: + var path3 = @"Sprite" # relative path, immediate child of the current node + var path4 = @"Timers/Firerate" # relative path, child of the child + var path5 = @".." # current node's parent + var path6 = @"../Enemy" # current node's sibling + var path7 = @"/root" # absolute path, equivalent to get_tree().get_root() + var path8 = @"/root/Main/Player/Sprite" # absolute path to Player's Sprite + var path9 = @"Timers/Firerate:wait_time" # accessing properties + var path10 = @"Player:position:x" # accessing subproperties + + # Finally, to get a reference use one of these: + sprite = get_node(@"Sprite") as Sprite # always cast to the type you expect + sprite = get_node("Sprite") as Sprite # here String gets + # implicitly casted to NodePath + sprite = get_node(path3) as Sprite + sprite = get_node_or_null("Sprite") as Sprite + sprite = $Sprite as Sprite + +func _process(delta): + # Now we can reuse the reference in other places. + prints("Sprite has global_position of", sprite.global_position) + +# Use onready keyword to assign a value to +# a variable just before _ready executes. +# This is a commonly used syntax sugar. +onready var tween = $Tween as Tween + +# You can export NodePath, so you can assign it within the inspector. +export var nodepath = @"" +onready var reference = get_node(nodepath) as Node +``` + +## Signals + +Signal system is Godot's implementation of the observer programming +pattern. Here's an example: + +```nim +class_name Player extends Node2D + +var hp = 10 + +signal died() # define signal +signal hurt(hp_old, hp_new) # signals can take arguments + +func apply_damage(dmg): + var hp_old = hp + hp -= dmg + emit_signal("hurt", hp_old, hp) # emit signal and pass arguments + if hp <= 0: + emit_signal("died") + +func _ready(): + # connect signal "died" to function "_on_death" defined in self + self.connect("died", self, "_on_death") + +func _on_death(): + self.queue_free() # destroy Player on death +``` + +## Type hints + +GDScript can optionally use static typing. + +```nim +extends Node + +var x: int # define typed variable +var y: float = 4.2 +var z := 1.0 # infer type based on default value using := operator + +onready var node_ref_typed := $Child as Node + +export var speed := 50.0 + +const CONSTANT := "Typed constant." + +func _ready() -> void: + # function returns nothing + x = "string" # ERROR! Type can't be changed! + return + +func join(arg1: String, arg2: String) -> String: + # function takes two Strings and returns a String + return arg1 + arg2 + +func get_child_at(index: int) -> Node: + # function takes an int and returns a Node + return get_children()[index] + +signal example(arg: int) # ERROR! Signals can't take typed arguments! +``` + +## Further Reading + +* [Godot's Website](https://godotengine.org/) +* [Godot Docs](https://docs.godotengine.org/en/stable/) +* [Getting started with GDScript](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/index.html) +* [NodePath](https://docs.godotengine.org/en/stable/classes/class_nodepath.html) +* [Signals](https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html) +* [GDQuest](https://www.gdquest.com/) +* [GDScript.com](https://gdscript.com/) diff --git a/git.html.markdown b/git.html.markdown index aa96c90a..9d33225f 100644 --- a/git.html.markdown +++ b/git.html.markdown @@ -82,12 +82,12 @@ pushed to other repositories, or not! ### Branch A branch is essentially a pointer to the last commit you made. As you go on -committing, this pointer will automatically update to point the latest commit. +committing, this pointer will automatically update to point to the latest commit. ### Tag A tag is a mark on specific point in history. Typically people use this -functionality to mark release points (v1.0, and so on) +functionality to mark release points (v1.0, and so on). ### HEAD and head (component of .git dir) @@ -124,9 +124,12 @@ To configure settings. Whether it be for the repository, the system itself, or global configurations ( global config file is `~/.gitconfig` ). ```bash -# Print & Set Some Basic Config Variables (Global) +# Set & Print Some Basic Config Variables (Global) $ git config --global user.email "MyEmail@Zoho.com" $ git config --global user.name "My Name" + +$ git config --global user.email +$ git config --global user.name ``` [Learn More About git config.](http://git-scm.com/docs/git-config) @@ -579,6 +582,19 @@ $ git rm HelloWorld.c $ git rm /pather/to/the/file/HelloWorld.c ``` +### blame +Examine specific parts of the code's history and find out who was the last author to modify that line. + +```bash +# find the authors on the latest modified lines +$ git blame google_python_style.vim +b88c6a1b (Google Python team 2019-12-30 13:45:23 -0800 12) " See the License for the specific language governing permissions and +b88c6a1b (Google Python team 2019-12-30 13:45:23 -0800 13) " limitations under the License. +b88c6a1b (Google Python team 2019-12-30 13:45:23 -0800 14) +222e6da8 (mshields@google.com 2010-11-29 20:32:06 +0000 15) " Indent Python in the Google way. +222e6da8 (mshields@google.com 2010-11-29 20:32:06 +0000 16) +222e6da8 (mshields@google.com 2010-11-29 20:32:06 +0000 17) setlocal indentexpr=GetGooglePythonIndent(v:lnum) +``` ## Further Information * [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1) @@ -597,8 +613,6 @@ $ git rm /pather/to/the/file/HelloWorld.c * [SalesForce Cheat Sheet](http://res.cloudinary.com/hy4kyit2a/image/upload/SF_git_cheatsheet.pdf) -* [GitGuys](http://www.gitguys.com/) - * [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html) * [Pro Git](http://www.git-scm.com/book/en/v2) diff --git a/go.html.markdown b/go.html.markdown index ae99535b..59ba2e4f 100644 --- a/go.html.markdown +++ b/go.html.markdown @@ -12,6 +12,8 @@ contributors: - ["Alexej Friesen", "https://github.com/heyalexej"] - ["Clayton Walker", "https://github.com/cwalk"] - ["Leonid Shevtsov", "https://github.com/leonid-shevtsov"] + - ["Michael Graf", "https://github.com/maerf0x0"] + - ["John Arundel", "https://github.com/bitfield"] --- Go was created out of the need to get work done. It's not the latest trend @@ -30,8 +32,14 @@ Go comes with a good standard library and a sizeable community. /* Multi- line comment */ + /* A build tag is a line comment starting with // +build + and can be executed by go build -tags="foo bar" command. + Build tags are placed before the package clause near or at the top of the file + followed by a blank line or other line comments. */ +// +build prod, dev, test + // A package clause starts every source file. -// Main is a special name declaring an executable rather than a library. +// main is a special name declaring an executable rather than a library. package main // Import declaration declares library packages referenced in this file. @@ -87,7 +95,7 @@ can include line breaks.` // Same string type. // Non-ASCII literal. Go source is UTF-8. g := 'Σ' // rune type, an alias for int32, holds a unicode code point. - f := 3.14195 // float64, an IEEE-754 64-bit floating point number. + f := 3.14159 // float64, an IEEE-754 64-bit floating point number. c := 3 + 4i // complex128, represented internally with two float64's. // var syntax with initializers. @@ -102,6 +110,11 @@ can include line breaks.` // Same string type. a5 := [...]int{3, 1, 5, 10, 100} // An array initialized with a fixed size of five // elements, with values 3, 1, 5, 10, and 100. + // Arrays have value semantics. + a4_cpy := a4 // a4_cpy is a copy of a4, two separate instances. + a4_cpy[0] = 25 // Only a4_cpy is changed, a4 stays the same. + fmt.Println(a4_cpy[0] == a4[0]) // false + // Slices have dynamic size. Arrays and slices each have advantages // but use cases for slices are much more common. s3 := []int{4, 5, 9} // Compare to a5. No ellipsis here. @@ -109,10 +122,15 @@ can include line breaks.` // Same string type. var d2 [][]float64 // Declaration only, nothing allocated here. bs := []byte("a slice") // Type conversion syntax. + // Slices (as well as maps and channels) have reference semantics. + s3_cpy := s3 // Both variables point to the same instance. + s3_cpy[0] = 0 // Which means both are updated. + fmt.Println(s3_cpy[0] == s3[0]) // true + // Because they are dynamic, slices can be appended to on-demand. // To append elements to a slice, the built-in append() function is used. // First argument is a slice to which we are appending. Commonly, - // the array variable is updated in place, as in example below. + // the slice variable is updated in place, as in example below. s := []int{1, 2, 3} // Result is a slice of length 3. s = append(s, 4, 5, 6) // Added 3 elements. Slice now has length of 6. fmt.Println(s) // Updated slice is now [1 2 3 4 5 6] @@ -161,16 +179,18 @@ func learnNamedReturns(x, y int) (z int) { // Go is fully garbage collected. It has pointers but no pointer arithmetic. // You can make a mistake with a nil pointer, but not by incrementing a pointer. +// Unlike in C/Cpp taking and returning an address of a local variable is also safe. func learnMemory() (p, q *int) { // Named return values p and q have type pointer to int. p = new(int) // Built-in function new allocates memory. - // The allocated int is initialized to 0, p is no longer nil. + // The allocated int slice is initialized to 0, p is no longer nil. s := make([]int, 20) // Allocate 20 ints as a single block of memory. s[3] = 7 // Assign one of them. r := -2 // Declare another local variable. return &s[3], &r // & takes the address of an object. } +// Use the aliased math library (see imports, above) func expensiveComputation() float64 { return m.Exp(10) } @@ -190,7 +210,7 @@ func learnFlowControl() { x := 42.0 switch x { case 0: - case 1: + case 1, 2: // Can have multiple matches on one case case 42: // Cases don't "fall through". /* @@ -202,6 +222,19 @@ func learnFlowControl() { default: // Default case is optional. } + + // Type switch allows switching on the type of something instead of value + var data interface{} + data = "" + switch c := data.(type) { + case string: + fmt.Println(c, "is a string") + case int64: + fmt.Printf("%d is an int64\n", c) + default: + // all other cases + } + // Like if, for doesn't use parens either. // Variables declared in for and if are local to their scope. for x := 0; x < 3; x++ { // ++ is a statement. @@ -324,7 +357,7 @@ func learnInterfaces() { // Functions can have variadic parameters. func learnVariadicParams(myStrings ...interface{}) { // Iterate each value of the variadic. - // The underbar here is ignoring the index argument of the array. + // The underscore here is ignoring the index argument of the array. for _, param := range myStrings { fmt.Println("param:", param) } @@ -423,22 +456,28 @@ func requestServer() { ## Further Reading -The root of all things Go is the [official Go web site](http://golang.org/). +The root of all things Go is the [official Go web site](https://go.dev/). There you can follow the tutorial, play interactively, and read lots. -Aside from a tour, [the docs](https://golang.org/doc/) contain information on +Aside from a tour, [the docs](https://go.dev/doc/) contain information on how to write clean and effective Go code, package and command docs, and release history. -The language definition itself is highly recommended. It's easy to read +The [Go language specification](https://go.dev/ref/spec) itself is highly recommended. It's easy to read and amazingly short (as language definitions go these days.) -You can play around with the code on [Go playground](https://play.golang.org/p/tnWMjr16Mm). Try to change it and run it from your browser! Note that you can use [https://play.golang.org](https://play.golang.org) as a [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) to test things and code in your browser, without even installing Go. +You can play around with the code on [Go playground](https://go.dev/play/p/tnWMjr16Mm). Try to change it and run it from your browser! Note that you can use [https://go.dev/play/](https://go.dev/play/) as a [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) to test things and code in your browser, without even installing Go. On the reading list for students of Go is the [source code to the standard -library](http://golang.org/src/pkg/). Comprehensively documented, it +library](https://go.dev/src/). Comprehensively documented, it demonstrates the best of readable and understandable Go, Go style, and Go idioms. Or you can click on a function name in [the -documentation](http://golang.org/pkg/) and the source code comes up! +documentation](https://go.dev/pkg/) and the source code comes up! Another great resource to learn Go is [Go by example](https://gobyexample.com/). +There are many excellent conference talks and video tutorials on Go available on YouTube, and here are three playlists of the very best, tailored for beginners, intermediate, and advanced Gophers respectively: + +- [Golang University 101](https://www.youtube.com/playlist?list=PLEcwzBXTPUE9V1o8mZdC9tNnRZaTgI-1P) introduces fundamental Go concepts and shows you how to use the Go tools to create and manage Go code +- [Golang University 201](https://www.youtube.com/playlist?list=PLEcwzBXTPUE_5m_JaMXmGEFgduH8EsuTs) steps it up a notch, explaining important techniques like testing, web services, and APIs +- [Golang University 301](https://www.youtube.com/playlist?list=PLEcwzBXTPUE8KvXRFmmfPEUmKoy9LfmAf) dives into more advanced topics like the Go scheduler, implementation of maps and channels, and optimisation techniques + Go Mobile adds support for mobile platforms (Android and iOS). You can write all-Go native mobile apps or write a library that contains bindings from a Go package, which can be invoked via Java (Android) and Objective-C (iOS). Check out the [Go Mobile page](https://github.com/golang/go/wiki/Mobile) for more information. diff --git a/groovy.html.markdown b/groovy.html.markdown index 89ca973a..89eee3dd 100644 --- a/groovy.html.markdown +++ b/groovy.html.markdown @@ -55,6 +55,9 @@ println x //Creating an empty list def technologies = [] +// or create a list with data +technologies = ["Kotlin", "Swift"] + /*** Adding a elements to the list ***/ // As with Java @@ -184,7 +187,7 @@ class Foo { Methods with optional parameters */ -// A mthod can have default values for parameters +// A method can have default values for parameters def say(msg = 'Hello', name = 'world') { "$msg $name!" } @@ -193,7 +196,7 @@ def say(msg = 'Hello', name = 'world') { assert 'Hello world!' == say() // Right most parameter with default value is eliminated first. assert 'Hi world!' == say('Hi') -assert 'learn groovy' == say('learn', 'groovy') +assert 'learn groovy!' == say('learn', 'groovy') /* Logical Branching and Looping diff --git a/hack.html.markdown b/hack.html.markdown index fb6af8e1..24055503 100644 --- a/hack.html.markdown +++ b/hack.html.markdown @@ -1,308 +1,420 @@ --- language: Hack contributors: + - ["Andrew DiMola", "https://github.com/AndrewDiMola"] - ["Stephen Holdaway", "https://github.com/stecman"] - ["David Lima", "https://github.com/davelima"] filename: learnhack.hh --- -Hack is a superset of PHP that runs under a virtual machine called HHVM. Hack -is almost completely interoperable with existing PHP code and adds a bunch of -useful features from statically typed languages. +[Hack](https://hacklang.org/) lets you write code quickly, while also having safety features built in, like static typechecking. - -Only Hack-specific features are covered here. Details about PHP's syntax are -available in the [PHP article](http://learnxinyminutes.com/docs/php/) on this site. +To run Hack code, [install HHVM](https://docs.hhvm.com/hhvm/installation/introduction), the open-source virtual machine. ```php -<?hh - -// Hack syntax is only enabled for files starting with an <?hh marker -// <?hh markers cannot be interspersed with HTML the way <?php can be. -// Using the marker "<?hh //strict" puts the type checker in strict mode. - - -// Scalar parameter type hints -function repeat(string $word, int $count) -{ - $word = trim($word); - return str_repeat($word . ' ', $count); -} - -// Type hints for return values -function add(...$numbers) : int -{ - return array_sum($numbers); -} - -// Functions that return nothing are hinted as "void" -function truncate(resource $handle) : void -{ - // ... -} - -// Type hints must explicitly allow being nullable -function identity(?string $stringOrNull) : ?string -{ - return $stringOrNull; -} - -// Type hints can be specified on class properties -class TypeHintedProperties -{ - public ?string $name; - - protected int $id; - - private float $score = 100.0; - - // Hack's type checker enforces that typed properties either have a - // default value or are set in the constructor. - public function __construct(int $id) - { - $this->id = $id; - } -} - - -// Concise anonymous functions (lambdas) -$multiplier = 5; -array_map($y ==> $y * $multiplier, [1, 2, 3]); - - -// Generics -class Box<T> -{ - protected T $data; - - public function __construct(T $data) { - $this->data = $data; - } - - public function getData(): T { - return $this->data; - } -} - -function openBox(Box<int> $box) : int -{ - return $box->getData(); -} - - -// Shapes -// -// Hack adds the concept of shapes for defining struct-like arrays with a -// guaranteed, type-checked set of keys -type Point2D = shape('x' => int, 'y' => int); +/* ================================== + * READ THE DOCS! + * ================================== + */ + +/* For more information on the Hack language: + * - About Hack: https://hacklang.org/ + * - Documentation: https://docs.hhvm.com/hack/ + */ + +/* ================================== + * A NOTE ON PHP + * ================================== + */ + +// The Hack language began as a superset of PHP. +// Since then, the languages have (largely) diverged. +// You may encounter the .php extension, which is no longer recommended. + +/* ================================== + * COMMENTS + * ================================== + */ + +// Hack has single-line comments... + +/* Multi-line comments... + * + */ + +/** + * ... and a special syntax for doc comments. + * + * Use doc comments to summarize the purpose of a definition, function, class or method. + */ + +/* ================================== + * NAMESPACES + * ================================== + */ + +// Namespaces contain definitions of classes, interfaces, traits, functions, and constants. + +namespace LearnHackinYMinutes { + + /* ================================== + * TYPES + * ================================== + */ + + function demo_hack_types(): void { + + // Hack has five primitive types: bool, int, float, string, and null. + $is_helpful = true; // bool + $int_value = 10; // int + $precise_value = 2.0; // float + $hello_world = "Hello World!"; // string + $null_string = null; // null -function distance(Point2D $a, Point2D $b) : float -{ - return sqrt(pow($b['x'] - $a['x'], 2) + pow($b['y'] - $a['y'], 2)); -} + // Create a `shape` with the shape keyword, with a series of field names and values. + $my_point = shape('x' => -3, 'y' => 6, 'visible' => true); -distance( - shape('x' => -1, 'y' => 5), - shape('x' => 2, 'y' => 50) -); + // Create a `tuple` with the tuple keyword, with a series of two or more types as values. + $apple_basket = tuple("apples", 25); // different types are OK + + // Use `arraykey` to represent either an integer or string. + $the_answer = 42; + $is_answer = process_key($the_answer); + + // Similarly, `num` represents either an int or float. + $lucky_number = 7; + $lucky_square = calculate_square($lucky_number); + } + function process_key(arraykey $the_answer): bool { + if ($the_answer is int) { + return true; + } else { + return false; + } // true + } + + function calculate_square(num $arg)[]: float { + return ((float)$arg * $arg); + } + + // Enums are limited to int or string (as an Arraykey), or other enum values. + enum Permission: string { + Read = 'R'; + Write = 'W'; + Execute = 'E'; + Delete = 'D'; + } + + // In contrast, an enum class can be of any value type! + enum class Random: mixed { + int X = 42; + string S = 'foo'; + } + + /* ================================== + * HACK ARRAYS + * ================================== + */ + + // The following line lets us use functions in the `C\` namespace. + use namespace HH\Lib\C; // the `C` library operates on containers + + function demo_hack_arrays(): void { -// Type aliasing -// -// Hack adds a bunch of type aliasing features for making complex types readable -newtype VectorArray = array<int, Vector<int>>; + // vec: ordered + $v = vec[1, 2, 3]; + $letters = vec['a', 'b', 'c']; -// A tuple containing two integers -newtype Point = (int, int); + $letters[0]; // returns 'a' + $letters[] = 'd'; // appends 'd' + + // `inout` provides pass-by-reference behavior + C\pop_back(inout $letters); // removes 'd' + C\pop_front(inout $letters); // removes 'a' + + // keyset: ordered, without duplicates + $k = keyset[1, 2, 3]; // values must be int or string + $colors = keyset['red', 'blue', 'green']; + + // keyset keys are identical to their values + $colors['blue']; // returns 'blue'. + + $colors[] = 'yellow'; // appends 'yellow' + unset($colors['red']); // removes 'red' + + // dict: ordered, by key-value + $d = dict['a' => 1, 'b' => 3]; // keys must be int or string + $alphabet = dict['a' => 1, 'b' => 2]; -function addPoints(Point $p1, Point $p2) : Point -{ - return tuple($p1[0] + $p2[0], $p1[1] + $p2[1]); -} + $alphabet['a']; // indexing at 'a' returns `1` + $alphabet['c'] = 3; // adds a new key-value pair of `c => 3` -addPoints( - tuple(1, 2), - tuple(5, 6) -); + unset($alphabet['b']); // removes 'b' + } + /* ================================== + * THE HACK STANDARD LIBRARY (HSL) + * ================================== + */ + + // The Hack Standard Library is a set of functions and classes for the Hack language. + // Namespace use declarations are ideally at the top of your file but are placed here for instruction purposes. + + use namespace HH\Lib\Str; // The `Str` library operates on strings + + function demo_hack_standard_library(): void { + + $letters = vec['a', 'b', 'c']; + $colors = keyset['red', 'blue', 'green']; + $alphabet = dict['a' => 1, 'b' => 2]; + + C\contains($letters, 'c'); // checks for a value; returns 'true' + C\contains($colors, 'purple'); // checks for a value; returns 'false' + C\contains_key($alphabet, 'a'); // checks for a key; returns 'true' + C\contains($alphabet, 'd'); // checks for a value; returns 'false' -// First-class enums -enum RoadType : int -{ - Road = 0; - Street = 1; - Avenue = 2; - Boulevard = 3; -} + Str\length("foo"); // returns `3` + Str\join(vec['foo', 'bar', 'baz'], '!'); // returns `foo!bar!baz` + } + + /* ================================== + * HELLO WORLD! + * ================================== + */ + + use namespace HH\Lib\IO; // the `IO` library is a standard API for input / output + + <<__EntryPoint>> // required attribute for the typical entry/main function + async function main(): Awaitable< + void, + > { // does not need to be named 'main' / is an asynchronous function + await IO\request_output()->writeAllAsync( + "Hello World!\n", + ); // prints 'Hello World'! + } -function getRoadType() : RoadType -{ - return RoadType::Avenue; -} + /* ================================== + * FUNCTIONS + * ================================== + */ + // Functions are defined globally. + // When a function is defined in a class, we refer to the function as a method. -// Constructor argument promotion -// -// To avoid boilerplate property and constructor definitions that only set -// properties, Hack adds a concise syntax for defining properties and a -// constructor at the same time. -class ArgumentPromotion -{ - public function __construct(public string $name, - protected int $age, - private bool $isAwesome) {} -} + // Functions have return types (here: `int`) and must return a value of + // that type or return no value when a void return type annotation was used. -class WithoutArgumentPromotion -{ - public string $name; + function add_one(int $x): int { + return $x + 1; + } - protected int $age; + // Functions can also have defined, default values. + function add_value(int $x, int $y = 1): int { + return $x + $y; + } - private bool $isAwesome; + // Functions can be variadic (unspecified length of arguments). + function sum_ints(int $val, int ...$vals): int { + $result = $val; - public function __construct(string $name, int $age, bool $isAwesome) - { - $this->name = $name; - $this->age = $age; - $this->isAwesome = $isAwesome; + foreach ($vals as $v) { + $result += $v; } -} - - -// Co-operative multi-tasking -// -// Two new keywords "async" and "await" can be used to perform multi-tasking -// Note that this does not involve threads - it just allows transfer of control -async function cooperativePrint(int $start, int $end) : Awaitable<void> -{ - for ($i = $start; $i <= $end; $i++) { - echo "$i "; - - // Give other tasks a chance to do something - await RescheduleWaitHandle::create(RescheduleWaitHandle::QUEUE_DEFAULT, 0); + return $result; + } + + // Functions can also be anonymous (defined with the `==>` arrow). + // $f = (int $x): int ==> $x + 1; + + /* ================================== + * PIPE OPERATOR + * ================================== + */ + + // The pipe operator, `|>`, evaluates the result of a left-hand expression + // and stores the result in `$$`, the predefined pipe variable. + + use namespace HH\Lib\Vec; + + function demo_pipe_operator(): void { + + Vec\sort(Vec\map(vec[2, 1, 3], $a ==> $a * $a)); // vec[1,4,9] + + // the same result, but using the pipe operator and pipe variable: + $x = vec[2, 1, 3] + |> Vec\map($$, $a ==> $a * $a) // $$ with value vec[2,1,3] + |> Vec\sort($$); // $$ with value vec[4,1,9] + } + + /* ================================== + * ATTRIBUTES + * ================================== + */ + + // Hack provides built-in attributes that can change runtime or static type checking behavior. + // For example, we used the `__EntryPoint` attribute earlier in the "Hello World!" example. + + // As another example, `__Memoize` caches the result of a function. + <<__Memoize>> + async function do_expensive_task(): Awaitable<string> { + $site_contents = await \HH\Asio\curl_exec("http://hacklang.org"); + return $site_contents; + } + + /* ================================== + * CONTEXTS + * ================================== + */ + + // Hack functions are attached to different contexts and capabilities. + // A context is a grouping of capabilities; that is, a grouping of permissions. + + // To declare allowed contexts (and capabilities), use the Context List `[]`. + // If contexts are not defined, your function includes permissions defined in Hack's `defaults` context. + + // Because the context list is NOT defined, the `defaults` context is implicitly declared. + async function implicit_defaults_context(): Awaitable<void> { + await IO\request_output()->writeAllAsync( + "Hello World!\n", + ); // prints 'Hello World'! + } + + // In the function below, the context list is defined to have the `defaults` context. + // A function can have multiple contexts [context1, context2, ...]. + // `defaults` includes most of the capabilities defined by the Hack language. + async function explicit_defaults_context()[defaults]: Awaitable<void> { + await IO\request_output()->writeAllAsync("Hello World!\n"); + } + + // You can also specify zero contexts to create a pure function (no capabilities). + async function empty_context()[]: Awaitable<void> { + // The following line is an error, as the function does not have IO capabilities. + // await IO\request_output()->writeAllAsync("Hello World!\n"); + } + + /* ================================== + * GENERICS + * ================================== + */ + + // Generics allow classes or methods to be parameterized to any set of types. + // That's pretty cool! + + // Hack typically passes by value: use `inout` to pass by reference. + function swap<T>(inout T $input1, inout T $input2): void { + $temp = $input1; + $input1 = $input2; + $input2 = $temp; + } + + /* ================================== + * CLASSES + * ================================== + */ + + // Classes provide a way to group functionality and state together. + // To define a class, use the `class` keyword. To instantiate, use `new`. + // Like other languages, you can use `$this` to refer to the current instance. + + class Counter { + private int $i = 0; + + public function increment(): void { + $this->i += 1; } -} - -// This prints "1 4 7 2 5 8 3 6 9" -AwaitAllWaitHandle::fromArray([ - cooperativePrint(1, 3), - cooperativePrint(4, 6), - cooperativePrint(7, 9) -])->getWaitHandle()->join(); - - -// Attributes -// -// Attributes are a form of metadata for functions. Hack provides some -// special built-in attributes that introduce useful behaviour. - -// The __Memoize special attribute causes the result of a function to be cached -<<__Memoize>> -function doExpensiveTask() : ?string -{ - return file_get_contents('http://example.com'); -} -// The function's body is only executed once here: -doExpensiveTask(); -doExpensiveTask(); - - -// The __ConsistentConstruct special attribute signals the Hack type checker to -// ensure that the signature of __construct is the same for all subclasses. -<<__ConsistentConstruct>> -class ConsistentFoo -{ - public function __construct(int $x, float $y) - { - // ... + public function get(): int { + return $this->i; } + } - public function someMethod() - { - // ... + // Properties and Methods can be static (not requiring instantiation). + class Person { + public static function favoriteProgrammingLanguage(): string { + return "Hack"; } -} + } -class ConsistentBar extends ConsistentFoo -{ - public function __construct(int $x, float $y) - { - // Hack's type checker enforces that parent constructors are called - parent::__construct($x, $y); + function demo_hack_classes(): void { + // Use `new` to instantiate a class. + $c1 = new Counter(); - // ... - } + // To call a static property or method, use `::` + $typical_person = tuple("Andrew", Person::favoriteProgrammingLanguage()); + } - // The __Override annotation is an optional signal for the Hack type - // checker to enforce that this method is overriding a method in a parent - // or trait. If not, this will error. - <<__Override>> - public function someMethod() - { - // ... + // Abstract class can be defined, but not instantiated directly. + abstract class Machine { + public function openDoors(): void { + return; } -} - -class InvalidFooSubclass extends ConsistentFoo -{ - // Not matching the parent constructor will cause a type checker error: - // - // "This object is of type ConsistentBaz. It is incompatible with this object - // of type ConsistentFoo because some of their methods are incompatible" - // - public function __construct(float $x) - { - // ... + public function closeDoors(): void { + return; } - - // Using the __Override annotation on a non-overridden method will cause a - // type checker error: - // - // "InvalidFooSubclass::otherMethod() is marked as override; no non-private - // parent definition found or overridden parent is defined in non-<?hh code" - // - <<__Override>> - public function otherMethod() - { - // ... + } + + /* ================================== + * INTERFACES + * ================================== + */ + + // A class can implement a set of requirements via an interface. + // An interface is a set of method declarations and constants. + + interface Plane { + // A constant is a named value. Once defined, the value cannot be changed. + const MAX_SPEED = 300; + public function fly(): void; + } + + /* ================================== + * TRAITS + * ================================== + */ + + // A trait defines properties and method declarations. + // Traits are recommended when abstracting code for reuse. + // Traits are included in code via the `use` keyword. + + trait Airplane { + // Introduce a class or interface requirement with the following syntax: + require extends Machine; // abstract class + require implements Plane; // interface + + public function takeOff(): void { + $this->openDoors(); + $this->closeDoors(); + $this->fly(); } -} + } + class Spaceship extends Machine implements Plane { + use Airplane; -// Traits can implement interfaces (standard PHP does not support this) -interface KittenInterface -{ - public function play() : void; -} - -trait CatTrait implements KittenInterface -{ - public function play() : void - { - // ... + public function fly(): void { + // fly like the wind } + } + + /* ================================== + * KEEP READING! + * ================================== + */ + + /* This is a simplified guide! + * There's much more to learn, including: + * - Asynchronous Operations: https://docs.hhvm.com/hack/asynchronous-operations/introduction + * - Reified Generics: https://docs.hhvm.com/hack/reified-generics/reified-generics + * - XHP: https://docs.hhvm.com/hack/XHP/setup + * - ... and more! + */ } -class Samuel -{ - use CatTrait; -} - - -$cat = new Samuel(); -$cat instanceof KittenInterface === true; // True - ``` ## More Information -Visit the [Hack language reference](http://docs.hhvm.com/manual/en/hacklangref.php) -for detailed explanations of the features Hack adds to PHP, or the [official Hack website](http://hacklang.org/) -for more general information. - -Visit the [official HHVM website](http://hhvm.com/) for HHVM installation instructions. +Visit the [Hack language reference](http://docs.hhvm.com/hack/) to learn more about the Hack language. -Visit [Hack's unsupported PHP features article](http://docs.hhvm.com/manual/en/hack.unsupported.php) -for details on the backwards incompatibility between Hack and PHP. +For more information on HHVM, including installation instructions, visit the [official HHVM website](http://hhvm.com/). diff --git a/haskell.html.markdown b/haskell.html.markdown index 90d47c27..edb4121d 100644 --- a/haskell.html.markdown +++ b/haskell.html.markdown @@ -3,6 +3,7 @@ language: Haskell filename: learnhaskell.hs contributors: - ["Adit Bhargava", "http://adit.io"] + - ["Stanislav Modrak", "https://stanislav.gq"] --- Haskell was designed as a practical, purely functional programming @@ -41,6 +42,8 @@ False -- Boolean operations not True -- False not False -- True +True && False -- False +True || False -- True 1 == 1 -- True 1 /= 1 -- False 1 < 10 -- True @@ -61,6 +64,8 @@ not False -- True -- A string is a list of characters ['H', 'e', 'l', 'l', 'o'] -- "Hello" + +-- Lists can be indexed with the `!!` operator followed by an index "This is a string" !! 0 -- 'T' @@ -293,7 +298,13 @@ foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 -- 7. Data Types ---------------------------------------------------- --- Here's how you make your own data type in Haskell +-- A data type is declared with a 'type constructor' on the left +-- and one or more 'data constructors' on the right, separated by +-- the pipe | symbol. This is a sum/union type. Each data constructor +-- is a (possibly nullary) function that creates an object of the type +-- named by the type constructor. + +-- This is essentially an enum data Color = Red | Blue | Green @@ -304,7 +315,62 @@ say Red = "You are Red!" say Blue = "You are Blue!" say Green = "You are Green!" --- Your data types can have parameters too: +-- Note that the type constructor is used in the type signature +-- and the data constructors are used in the body of the function +-- Data constructors are primarily pattern-matched against + +-- This next one is a traditional container type holding two fields +-- In a type declaration, data constructors take types as parameters +-- Data constructors can have the same name as type constructors +-- This is common where the type only has a single data constructor + +data Point = Point Float Float + +-- This can be used in a function like: + +distance :: Point -> Point -> Float +distance (Point x y) (Point x' y') = sqrt $ dx + dy + where dx = (x - x') ** 2 + dy = (y - y') ** 2 + +-- Types can have multiple data constructors with arguments, too + +data Name = Mononym String + | FirstLastName String String + | FullName String String String + +-- To make things clearer we can use record syntax + +data Point2D = CartesianPoint2D { x :: Float, y :: Float } + | PolarPoint2D { r :: Float, theta :: Float } + +myPoint = CartesianPoint2D { x = 7.0, y = 10.0 } + +-- Using record syntax automatically creates accessor functions +-- (the name of the field) + +xOfMyPoint = x myPoint + +-- xOfMyPoint is equal to 7.0 + +-- Record syntax also allows a simple form of update + +myPoint' = myPoint { x = 9.0 } + +-- myPoint' is CartesianPoint2D { x = 9.0, y = 10.0 } + +-- Even if a type is defined with record syntax, it can be declared like +-- a simple data constructor. This is fine: + +myPoint'2 = CartesianPoint2D 3.3 4.0 + +-- It's also useful to pattern match data constructors in `case` expressions + +distanceFromOrigin x = + case x of (CartesianPoint2D x y) -> sqrt $ x ** 2 + y ** 2 + (PolarPoint2D r _) -> r + +-- Your data types can have type parameters too: data Maybe a = Nothing | Just a @@ -313,8 +379,98 @@ Just "hello" -- of type `Maybe String` Just 1 -- of type `Maybe Int` Nothing -- of type `Maybe a` for any `a` +-- For convenience we can also create type synonyms with the 'type' keyword + +type String = [Char] + +-- Unlike `data` types, type synonyms need no constructor, and can be used +-- anywhere a synonymous data type could be used. Say we have the +-- following type synonyms and items with the following type signatures + +type Weight = Float +type Height = Float +type Point = (Float, Float) +getMyHeightAndWeight :: Person -> (Height, Weight) +findCenter :: Circle -> Point +somePerson :: Person +someCircle :: Circle +distance :: Point -> Point -> Float + +-- The following would compile and run without issue, +-- even though it does not make sense semantically, +-- because the type synonyms reduce to the same base types + +distance (getMyHeightAndWeight somePerson) (findCenter someCircle) + +---------------------------------------------------- +-- 8. Typeclasses +---------------------------------------------------- + +-- Typeclasses are one way Haskell does polymorphism +-- They are similar to interfaces in other languages +-- A typeclass defines a set of functions that must +-- work on any type that is in that typeclass. + +-- The Eq typeclass is for types whose instances can +-- be tested for equality with one another. + +class Eq a where + (==) :: a -> a -> Bool + (/=) :: a -> a -> Bool + x == y = not (x /= y) + x /= y = not (x == y) + +-- This defines a typeclass that requires two functions, (==) and (/=) +-- It also declares that one function can be declared in terms of another +-- So it is enough that *either* the (==) function or the (/=) is defined +-- And the other will be 'filled in' based on the typeclass definition + +-- To make a type a member of a type class, the instance keyword is used + +instance Eq TrafficLight where + Red == Red = True + Green == Green = True + Yellow == Yellow = True + _ == _ = False + +-- Now we can use (==) and (/=) with TrafficLight objects + +canProceedThrough :: TrafficLight -> Bool +canProceedThrough t = t /= Red + +-- You can NOT create an instance definition for a type synonym + +-- Functions can be written to take typeclasses with type parameters, +-- rather than types, assuming that the function only relies on +-- features of the typeclass + +isEqual (Eq a) => a -> a -> Bool +isEqual x y = x == y + +-- Note that x and y MUST be the same type, as they are both defined +-- as being of type parameter 'a'. +-- A typeclass does not state that different types in the typeclass can +-- be mixed together. +-- So `isEqual Red 2` is invalid, even though 2 is an Int which is an +-- instance of Eq, and Red is a TrafficLight which is also an instance of Eq + +-- Other common typeclasses are: +-- Ord for types that can be ordered, allowing you to use >, <=, etc. +-- Read for types that can be created from a string representation +-- Show for types that can be converted to a string for display +-- Num, Real, Integral, Fractional for types that can do math +-- Enum for types that can be stepped through +-- Bounded for types with a maximum and minimum + +-- Haskell can automatically make types part of Eq, Ord, Read, Show, Enum, +-- and Bounded with the `deriving` keyword at the end of the type declaration + +data Point = Point Float Float deriving (Eq, Read, Show) + +-- In this case it is NOT necessary to create an 'instance' definition + ---------------------------------------------------- --- 8. Haskell IO +-- 9. Haskell IO ---------------------------------------------------- -- While IO can't be explained fully without explaining monads, @@ -395,7 +551,7 @@ main'' = do ---------------------------------------------------- --- 9. The Haskell REPL +-- 10. The Haskell REPL ---------------------------------------------------- -- Start the repl by typing `ghci`. @@ -447,6 +603,6 @@ qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater There are two popular ways to install Haskell: The traditional [Cabal-based installation](http://www.haskell.org/platform/), and the newer [Stack-based process](https://www.stackage.org/install). You can find a much gentler introduction from the excellent -[Learn you a Haskell](http://learnyouahaskell.com/), +[Learn you a Haskell](http://learnyouahaskell.com/) (or [up-to-date community version](https://learnyouahaskell.github.io/)), [Happy Learn Haskell Tutorial](http://www.happylearnhaskelltutorial.com/) or [Real World Haskell](http://book.realworldhaskell.org/). diff --git a/haxe.html.markdown b/haxe.html.markdown index a31728e1..e086dd7a 100644 --- a/haxe.html.markdown +++ b/haxe.html.markdown @@ -6,8 +6,8 @@ contributors: - ["Dan Korostelev", "https://github.com/nadako/"] --- -Haxe is a web-oriented language that provides platform support for C++, C#, -Swf/ActionScript, Javascript, Java, PHP, Python, Lua, HashLink, and Neko byte code +[Haxe](https://haxe.org/) is a general-purpose language that provides platform support for C++, C#, +Swf/ActionScript, JavaScript, Java, PHP, Python, Lua, HashLink, and Neko bytecode (the latter two being also written by the Haxe author). Note that this guide is for Haxe version 3. Some of the guide may be applicable to older versions, but it is recommended to use other references. @@ -189,7 +189,7 @@ class LearnHaxe3 { trace(m.get('bar') + " is the value for m.get('bar')"); trace(m['bar'] + " is the value for m['bar']"); - var m2 = ['foo' => 4, 'baz' => 6]; // Alternative map syntax + var m2 = ['foo' => 4, 'baz' => 6]; // Alternative map syntax trace(m2 + " is the value for m2"); // Remember, you can use type inference. The Haxe compiler will @@ -234,10 +234,9 @@ class LearnHaxe3 { ^ Bitwise exclusive OR | Bitwise inclusive OR */ - - // increments + var i = 0; - trace("Increments and decrements"); + trace("Pre-/Post- Increments and Decrements"); trace(i++); // i = 1. Post-Increment trace(++i); // i = 2. Pre-Increment trace(i--); // i = 1. Post-Decrement @@ -287,7 +286,7 @@ class LearnHaxe3 { } // do-while loop - var l = 0; + var l = 0; do { trace("do statement always runs at least once"); } while (l > 0); @@ -338,7 +337,7 @@ class LearnHaxe3 { */ var my_dog_name = "fido"; var favorite_thing = ""; - switch(my_dog_name) { + switch (my_dog_name) { case "fido" : favorite_thing = "bone"; case "rex" : favorite_thing = "shoe"; case "spot" : favorite_thing = "tennis ball"; @@ -366,7 +365,7 @@ class LearnHaxe3 { trace("k equals ", k); // outputs 10 - var other_favorite_thing = switch(my_dog_name) { + var other_favorite_thing = switch (my_dog_name) { case "fido" : "teddy"; case "rex" : "stick"; case "spot" : "football"; @@ -559,7 +558,7 @@ class SimpleEnumTest { // You can specify the "full" name, var e_explicit:SimpleEnum = SimpleEnum.Foo; var e = Foo; // but inference will work as well. - switch(e) { + switch (e) { case Foo: trace("e was Foo"); case Bar: trace("e was Bar"); case Baz: trace("e was Baz"); // comment this line to throw an error. @@ -572,7 +571,7 @@ class SimpleEnumTest { You can also specify a default for enum switches as well: */ - switch(e) { + switch (e) { case Foo: trace("e was Foo again"); default : trace("default works here too"); } @@ -595,21 +594,21 @@ class ComplexEnumTest { var e1:ComplexEnum = IntEnum(4); // specifying the enum parameter // Now we can switch on the enum, as well as extract any parameters // it might have had. - switch(e1) { + switch (e1) { case IntEnum(x) : trace('$x was the parameter passed to e1'); default: trace("Shouldn't be printed"); } // another parameter here that is itself an enum... an enum enum? var e2 = SimpleEnumEnum(Foo); - switch(e2){ + switch (e2){ case SimpleEnumEnum(s): trace('$s was the parameter passed to e2'); default: trace("Shouldn't be printed"); } // enums all the way down var e3 = ComplexEnumEnum(ComplexEnumEnum(MultiEnum(4, 'hi', 4.3))); - switch(e3) { + switch (e3) { // You can look for certain nested enums by specifying them // explicitly: case ComplexEnumEnum(ComplexEnumEnum(MultiEnum(i,j,k))) : { @@ -668,7 +667,7 @@ class TypedefsAndStructuralTypes { That would give us a single "Surface" type to work with across all of those platforms. - */ + */ } } @@ -700,8 +699,7 @@ class UsingExample { instance, and the compiler still generates code equivalent to a static method. */ - } - + } } ``` diff --git a/hd-hd/amd.html.markdown b/hd-hd/amd.html.markdown index 0a6581d6..b85567c2 100644 --- a/hd-hd/amd.html.markdown +++ b/hd-hd/amd.html.markdown @@ -12,6 +12,7 @@ lang: hd जावास्क्रिप्ट मॉड्यूल ऐसे मॉड्यूल और इसकी अतुल्यकालिक निर्भरता से भरा हुआ है। यह ब्राउज़र पर्यावरण जहां के लिए विशेष रूप से अच्छी तरह से अनुकूल है, और प्रदर्शन , प्रयोज्य, डीबगिंग, और क्रॉस-डोमेन जैसे मॉड्यूल्स को जल्दी सिंक्रनाइज़ लोडिंग करता hai। ### मूल अवधारणा + ```javascript // बुनियादी एएमडी एपीआई दो तरीकों लेकिन कुछ भी नहीं होते : ` define` और` require` // और सभी मॉड्यूल परिभाषा और खपत के बारे में है : @@ -79,6 +80,7 @@ function require(deps, callback){ ### Require.js के साथ वास्तविक दुनिया के उपयोग परिचयात्मक उदाहरण के विपरीत, ` require.js` (सबसे लोकप्रिय एएमडी पुस्तकालय ) वास्तव में लागू करता है ** ** Amd ** में *A * **, आप XHR के माध्यम से मॉड्यूल और उनकी निर्भरता लोड करने के लिए सक्षम करने के लिए : + ```javascript /* file: app/main.js */ require(['modules/someClass'], function(SomeClass){ @@ -113,6 +115,7 @@ define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){ return SomeClass; }); ``` + अपने ` main.js` में डिफ़ॉल्ट पथ मानचित्रण व्यवहार का उपयोग ` requirejs.config ( configObj ) ` में परिवर्तन करने के लिए: ```javascript @@ -131,6 +134,7 @@ require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolL coolLib.doFancyStuffWith(helpers.transform($('#foo'))); }); ``` + ` require.js` आधारित क्षुधा आमतौर पर एक डाटा विशेषता के रूप में ` require.js` स्क्रिप्ट टैग को पारित कर दिया है कि एक एकल प्रवेश बिंदु (` main.js` ) होगा। यह स्वचालित रूप से भरी हुई है और pageload पर क्रियान्वित किया जाएगा : ```html @@ -151,16 +155,19 @@ require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolL (राइनो भी समर्थन किया है, तो आप शायद Node.js में चलेगा ) ` require.js` ( अपनी परियोजना की निर्भरता ग्राफ का विश्लेषण , और अपने सभी मॉड्यूल युक्त एक एकल फाइल निर्माण कर सकते हैं कि ` r.js` नामक एक स्क्रिप्ट के साथ आता है ठीक से minified और उपभोग के लिए तैयार है, ) नाम दिया है। Install it using `npm`: + ```shell $ npm install requirejs -g ``` अब आप एक विन्यास फाइल के साथ फ़ीड कर सकते हैं: + ```shell $ r.js -o app.build.js ``` हमारे ऊपर के उदाहरण के लिए विन्यास की तरह लग सकता है: + ```javascript /* file : app.build.js */ ({ @@ -177,6 +184,7 @@ $ r.js -o app.build.js ``` उत्पादन में बनाया फ़ाइल का उपयोग करने के लिए, बस ` Data-main` स्वैप: + ```html <script src="require.js" data-main="app/main-built"></script> ``` diff --git a/hd-hd/d.html.markdown b/hd-hd/d.html.markdown index 96274e2b..f5e0858a 100644 --- a/hd-hd/d.html.markdown +++ b/hd-hd/d.html.markdown @@ -126,7 +126,6 @@ class Matrix(uint m, uint n, T = int) { } auto mat = new Matrix!(3, 3); - ``` Classes की बात हो रही है , एक दूसरे के लिए गुणों के बारे में बात करते हैं। एक संपत्ति @@ -176,8 +175,8 @@ class MyClass(T, U) { void main() { auto mc = new MyClass!(int, string)(7, "seven"); - करने के लिए लिखने के लिए मानक पुस्तकालय से - // आयात ' stdio ' मॉड्यूल + // करने के लिए लिखने के लिए मानक पुस्तकालय से + // आयात ' stdio ' मॉड्यूल // सांत्वना (आयात एक गुंजाइश के लिए स्थानीय हो सकता है) । import std.stdio; @@ -235,22 +234,21 @@ UFCS के साथ, हम एक विधि के रूप में ए एक विधि के रूप में ग्रुप ए की किसी भी अभिव्यक्ति पर कुछ प्रकार एक की है । मैं समानता चाहते । समानता की तरह कोई और? ज़रूर तुम करना। चलो कुछ करते हैं! + ```c import std.stdio; import std.parallelism : parallel; import std.math : sqrt; void main() { - // हम हमारे सरणी में वर्गमूल हर नंबर ले जाना चाहता हूँ , - // हम उपलब्ध है के रूप में और के रूप में कई कोर का लाभ ले। + // हम हमारे सरणी में वर्गमूल हर नंबर ले जाना चाहता हूँ , + // हम उपलब्ध है के रूप में और के रूप में कई कोर का लाभ ले। auto arr = new double[1_000_000]; - // संदर्भ के द्वारा एक सूचकांक , और एक सरणी तत्व का प्रयोग + // संदर्भ के द्वारा एक सूचकांक , और एक सरणी तत्व का प्रयोग // और सिर्फ सरणी पर समानांतर फोन! foreach(i, ref elem; parallel(arr)) { ref = sqrt(i + 1.0); } } - - ``` diff --git a/hd-hd/json-hd.html.markdown b/hd-hd/json-hd.html.markdown new file mode 100644 index 00000000..dd1657cd --- /dev/null +++ b/hd-hd/json-hd.html.markdown @@ -0,0 +1,86 @@ +--- +language: json +contributors: + - ["Anna Harren", "https://github.com/iirelu"] + - ["Marco Scannadinari", "https://github.com/marcoms"] + - ["himanshu", "https://github.com/himanshu81494"] + - ["Michael Neth", "https://github.com/infernocloud"] + - ["Athanasios Emmanouilidis", "https://github.com/athanasiosem"] +translators: + - ["Namami Shanker", "https://github.com/NamamiShanker"] +lang: hd-hd +--- + +जैसन(JSON) इस अत्यंत सरल डाटा-इंटरचेंज फॉर्मेट है| जैसा [json.org](https://json.org) कहती है, ये इंसानो के पढ़ने और लिखने के लिए भी आसान है और और मशीन के लिए इसे पार्स और उतपन्न करना भी बेहद सरल है| + +जैसन(JSON) के एक अंश को इनमे से किसी एक का प्रतिनिधित्व(represent) करना चाहिए: + +* एक नाम/वैल्यू जोड़े का कलेक्शन (`{ }`). कई दूसरी भाषाओ में इसे ऑब्जेक्ट, रिकॉर्ड, स्ट्रक्ट, डिक्शनरी, हैश टेबल, कीड लिस्ट, या असोसिएटिव ऐरे का भी नाम दिया जाता है| +* वैल्यूज की एक व्यवस्थित लिस्ट(ordered list) (`[ ]`). कई दूसरी भाषाओ में इसे ऐरे, वेक्टर, लिस्ट, या सीक्वेंस भी कहा जाता है| + +जैसन(JSON) अपने शुद्धतम रूप में कमैंट्स सपोर्ट नहीं करता है, पर ज़्यादातर पारसर C स्टाइल की कमैंट्स (`//`, `/* */`) सपोर्ट करेंगे| कुछ पारसर्स अंतिम कॉमा भी स्वीकार करते हैं (जब आप किसी ऐरे के अंतिम एलिमेंट या किसी ऑब्जेक्ट की अंतिम प्रॉपर्टी के बार एक कॉमा छोड़ देते हैं), पर ऐसी गलतियों से बचना चाहिए बेहतर कम्पेटिबिलिटी के लिए| + + ये उदाहरण १०० प्रतिशत मान्य जैसन(JSON) है| किस्मत से, जैसन(JSON) डॉक्यूमेंट को पढ़ के ही आप इसे समझ जायेंगे| + +समर्थित डाटा टाइप्स: + +* स्ट्रिंग्स(Strings): `"नमस्ते"`, `"\"एक उद्धरण\""`, `"\u0abe"`, `"नयी पंक्ति|\n"` +* अंक(Numbers): `23`, `0.11`, `12e10`, `3.141e-10`, `1.23e+4` +* ऑब्जेक्ट्स(Objects): `{ "की": "मूल्य" }` +* ऐरे(Arrays): `["बहुत सारे मूल्य"]` +* विविध(Miscellaneous): `true`, `false`, `null` + +```json +{ + "की": "मूल्य", + + "की": "हमेशा दोहरे उद्धरण चिह्नों में संलग्न होना चाहिए", + "अंक": 0, + "स्ट्रिंग्स": "नमस्ते| यूनिकोड और \"एस्केप\" सीक्वेंस की अनुमति है|", + "बूलियन है?": true, + "शून्यता ": null, + + "बड़े अंक": 1.2e+100, + + "ऑब्जेक्ट्स": { + "टिप्पणी": "आपके जैसन(JSON) ऑब्जेक्ट को ज़्यादातर ऑब्जेक्ट से ही ढांचा मिलेगा|", + + "ऐरे": [0, 1, 2, 3, "ऐरे में आप कुछ भी रख सकते हैं|", 5], + + "एक और ऑब्जेक्ट": { + "टिप्पणी": "आप एक ऑब्जेक्ट दूसरे ऑब्जेक्ट के अंदर रख सकते हैं| ये बहुत उपयोगी होता है|" + } + }, + + "फ़र्ज़ी": [ + { + "पोटेशियम के स्रोत": ["केला"] + }, + [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, "नव"], + [0, 0, 0, 1] + ] + ], + + "वैकल्पिक शैली": { + "टिप्पणी": "ये देखिये!" + , "कॉमा के स्थान": "से फरक नहीं पड़ता, अगर आपने उसे अगली की से पहले लगाया है तो वो मान्य है|" + , "एक और टिप्पणी": "कितनी अच्छी बात है" + }, + + + + "खाली स्थान": "से फरक नहीं पड़ता", + + + + "ये काफी छोटा था :>": "और ख़तम| अब आपको जैसन(JSON) के बारे में सब कुछ पता है|" +} +``` + +## और जानकारी के लिए + +* [JSON.org](https://json.org) पूरा जैसन(JSON) फ्लोचार्ट के माध्यम से खूबसूरत तरह से दर्शित| +* [JSON Tutorial](https://www.youtube.com/watch?v=wI1CWzNtE-M) जैसन(JSON) का एक संक्षिप्त परिचय| diff --git a/hdl.html.markdown b/hdl.html.markdown new file mode 100644 index 00000000..6b9a2d80 --- /dev/null +++ b/hdl.html.markdown @@ -0,0 +1,231 @@ +--- +language: hdl +filename: learnhdl.hdl +contributors: + - ["Jack Smith", "https://github.com/JSmithTech2019"] +--- + +HDL (hardware description language) is a specialized language used to describe the structure/behavior of real world circuits. + +It is used by circuit designers to simulate circuits and logic prior to wiring and fabricating a hardware circuit. + +HDL allows circuit designers to simulate circuits at a high level without being connected to specific components. + +## Basic building blocks & introduction to the language--- +This programming language is built by simulating hardware chips and wiring. Normal programming functions are replaced with specialized chips that are added to the current wiring design. Every base chip must be written as it's own file and imported to be used in the current chip, though they may be reused as often as desired. + +```verilog +// Single line comments start with two forward slashes. + +/* + * Multiline comments can be written using '/*' and 'star/'. + * These are often used as comments. + * + * Note that they cannot be nested and will end at the first 'star/'. + */ + +//////////////////////////////////////////////////// +// 1. Chips & Components +//////////////////////////////////////////////////// +/* + * Unlike other languages HDL creates an individual chip (function) per file + * These are defined with a name, input arguments, output arguments + * and finally the parts/logic of that specific chip. + */ + +// Note CHIP is capitalized, the chip name does not need to be. +CHIP Ex { + IN a, // Single bit (0 or 1) variable. + c[16]; // 16 bit variable bus of single bit values. + + OUT out[16], // 16 bit variable bus output. + carry; // Single bit output variable + + PARTS: + // The functional components of the chip. +} + +// Lines are ended with semicolons but can be continued using commas. The +// whitespace is ignored. + + + +//////////////////////////////////////////////////// +// 2. Inputs, Outputs, & Variables +//////////////////////////////////////////////////// +/* + * Variables and IO are treated as pins/wires and can carry a single bit + * of data (0 or 1). + */ + +// Hardware works on low level 0's and 1's, in order to use a constant +// high or low we use the terms true and false. +a=false; // This is a 0 value. +b=true; // This is a 1 value. + +// Inputs and outputs can be defined as single bits +IN a, b; // Creates two single bit inputs + +// They can also be defined as busses act as arrays where each +// index can contain a single bit value. +OUT c[16]; // Creates a 16 bit output array. + +// Bussed values can be accessed using brackets +a[0] // The first indexed value in the bus a. +a[0..3] // The first 4 values in the a bus. +// Values can also be passed in entirety. For example if the function +// foo() takes an 8 bit input bus and outputs a 2 bit bus: +foo(in=a[0..7], out=c); // C is now a 2 bit internal bus + + +// Note that internally defined busses cannot be subbussed! +// To access these elements, output or input them separately: +foo(in[0]=false, in[1..7]=a[0..6], out[0]=out1, out[1]=out2); +// out1 and out2 can then be passed into other circuits within the design. + + + +//////////////////////////////////////////////////// +// Combining Subsystems +//////////////////////////////////////////////////// +/* + * HDL relies heavily on using smaller "building block" chips to then be + * added into larger and more complex designs. Creating the smaller components + * and then adding them to the larger circuit allows for fewer lines of code + * as well as reduction in total rewriting of code. + */ + +// We are writing the function AND that checks if inputs I and K are both one. +// To implement this chip we will use the built in NAND gate as well as design +// a custom NOT gate to invert a single input. + +// First we construct the Negation (not) chip. We will use the logically +// complete gate NAND that is built in for this task. +CHIP Not { + IN i; // Not gates only take one single bit input. + OUT o; // The negated value of a. + + PARTS: + // Add the input to the built in chip, which then sends output to the NOT + // output. This effectively negates the given value. + Nand(a=i, b=i, out=o); +} + +// By using the built in NAND gate we were able to construct a NOT gate +// that works like a real world hardware logic chip. Now we must construct +// the AND gate using these two gate primitives. + +// We define a two input, single output AND gate: +CHIP And { + IN i, k; // Two single bit inputs. + OUT o; // One single bit output. + + PARTS: + // Insert I and K into the nand gate and store the output in an internal + // wire called notOut. + Nand(a=i,b=k,out=notOut); + + // Use the not gate we constructed to invert notOut and send to the AND + // output. + Not(in=notOut,out=o); +} + +// Easy! Now we can use Nand, And, and Not gates in higher level circuits. +// Many of these low level components are built in to HDL but any chip can +// be written as a submodule and used in larger designs. +``` + +## Test Files +When working with the nand2tetris hardware simulator chips written using HDL will +then be processed against test and comparison files to test functionality of the +simulated chip versus the expected output. To do this a test file will be loaded +into the hardware simulator and run against the simulated hardware. + +```verilog +// First the chip the test file is written for is loaded +load <chip name>.hdl + +// We set the output file for the simulated chip output as well as the comparison +// file that it will be tested against. We also specify what the output is +// expected to look like. In this case there will be two output columns, each +// will be buffered by a single space on either side and 4 binary values in +// the center of each column. +output-file <chip name>.out, +compare-to <chip name>.cmp, +output-list in%B1.4.1 out%B1.4.1; + +// Then we set initial values for inputs to the chip. For example +set enable1 1, // set input enable1 to 1 +set enable2 0, // set input enable2 to 0 + +// The clock is also controlled in the test file using tick and tock. Tick is a +// positive pulse and tock takes the clock back to 0. Clock cycles can be run +// multiple times in a row with no other changes to inputs or outputs. +tick, +tock, + +// Finally we output the first expected value (from the test file) which is then +// compared with the first line of real output from our HDL circuit. This output +// can be viewed in the <chip name>.out file. +output; + +// An example of <chip name>, a chip that takes in a 4 bit value as input and +// adds 1 to that value could have the following as test code: + +// Set the input value to 0000, clock pulse, compare output from cmp file to actual out. +set in %B0000, +tick, +tock, +output; + +// Set the input value to 0110, clock pulse, compare output from cmp file to actual out. +set in %B0110, +tick, +tock, +output; + +// The expected output for case 1 should be 0001 and case 2 expects 0111, lets +// learn a little more about comparison files before finalizing our lesson. +``` + +## Comparison Files +Now lets take a look at comparison files, the files that hold what the test file +compares with the actual output of an HDL chip in the hardware simulator! + +```verilog +// Like the <chip name> example above, the structure of the comparison file +// would look something like this +| in | out | +| 0000 | 0001 | +| 0110 | 0111 | + +// Notice how the input values specified in the test case are equivalent to the +// `in` column of the comparison file, and that the space buffer is 1 on either side. + +// If the output from the HDL code we not this, such as the output below, then the +// test will fail and the user will know that the simulated chip is not correctly designed. +| in | out | +| 0000 | 0001 | +| 0110 | 0110 | // Error! The chip did not add 1 here, something went wrong. + + +``` + +This is incredibly useful as it allows designers to simulate chip logic prior to +fabricating real life hardware and identify problems in their designs. Be warned that +errors in the test or comparison files can lead to both false positives and also +the more damaging false negatives so ensure that the logic is sound behind the test +creation. + + +Good luck and happy coding! + +## Resources + +* [From Nand To Tetris](https://www.nand2tetris.org) + +## Further Reading + +* [Hardware Description Language](https://en.wikipedia.org/wiki/Hardware_description_language) + +* [HDL Programming Fundamentals](https://www.electronicdesign.com/products/hdl-programming-fundamentals) diff --git a/hjson.html.markdown b/hjson.html.markdown new file mode 100644 index 00000000..6b3cc3ed --- /dev/null +++ b/hjson.html.markdown @@ -0,0 +1,94 @@ +--- +language: Hjson +filename: learnhjson.hjson +contributors: + - ["MrTeferi", "https://github.com/MrTeferi"] +lang: en +--- + +Hjson is an attempt to make [JSON](https://learnxinyminutes.com/docs/json/) more human readable. + +Hjson is a syntax extension to JSON. +It's NOT a proposal to replace JSON or to incorporate it into the JSON spec itself. +It's intended to be used like a user interface for humans, +to read and edit before passing the JSON data to the machine. + +Let's take a look at examples to see the key syntax differences! + +``` +{ + # Comments are totally supported! + + // With forward slashes too! + + /* + Even block style comments, neat! + /* + + # Strings do not require quotes! + # Just keep it to a single line + human: readable + quotes: "are fine too" + + # Notice that commas are also not required! + # If using commas, strings DO require quotes! + object: { + name: Hjson + properties: [ + readable + exciting + fun + ] + with_commas: [ + "quoted", + "quoty", + "quote" + ] + details: ["this", "is", "fine", "too"] + } + + # Multiline quotes with proper whitespace handling are supported! + diary: + ''' + I wish JSON was more human readable. + If only there was a JSON for my needs! + Oh wait.. there is! It's called Hjson. + ''' + + # Backslashes are interpreted as an escape character ONLY in quoted strings + slash: This will not have a new line\n + slash-quoted: "This will definitely have a new line\n" + + # Make sure to use quotes when mixing whitespace with important punctuation + example1: "If, you're, going, to, comma in a string, use, quotes!" + example2: "Also if you want to use {} or [] or any JSON relevant punctuation!" + example3: [because, this, is, totally, BROKEN!] + example4: this is technically OK though: {}[],: + + # Enjoy working with Hjson! + party-time: { + Hjson-lovers: [ + me + my mom + "my dad" + ] + Hjson-power-level: 9000 + supported: { + python: yes + java: yes + javascript: yes + c++: yes + Go: yes + C#: yes + Rust: yes + } + partial-support: ["C", "Kotlin", "Ruby", "Rust"] + } + +} +``` + +## Further Reading + +* [Hjson.github.io](https://hjson.github.io/) Main Hjson site including editor support, how-to, etc. +* [Hjson Packages](https://github.com/hjson/) Various Hjson packages for different applications. diff --git a/hocon.html.markdown b/hocon.html.markdown new file mode 100644 index 00000000..67ea30a2 --- /dev/null +++ b/hocon.html.markdown @@ -0,0 +1,574 @@ +--- +language: hocon +filename: learnhocon.conf +contributors: +- [TehBrian, 'https://tehbrian.xyz'] +--- + +Human-Optimized Configuration Object Notation, or HOCON, is a configuration and +data serialization format designed to be easily editable by humans. + +It's a superset of JSON, meaning that any valid JSON is valid HOCON, but it +differs in being much less pedantic and opinionated. With its flexible yet +easily determinable syntax, resulting configuration files are often much less +noisy than some other formats. + +Additionally, its support for comments makes it much better suited for +user-facing configurations than JSON. + +```hocon +// Comments can either look like this, +# or they can look like this. +// Anything after // or # is a comment. + +################## +### THE BASICS ### +################## + +# Everything in HOCON is either a key, a value, or a separator. +# : and = are separators. They separate the key from the value. +key: value +another_key = another_value + +# You can use either separator with or without whitespace on either side. +colon1:value +colon2: value +colon3 : value +equals1=value +equals2= value +equals3 = value +# As you'll see, HOCON is very nonrestrictive regarding its syntax style. + +# HOCON also isn't opinionated on how keys look. +THIS_IS_A_VALID_KEY: value +this-is-also-a-valid-key: value +keys can have spaces too: value +or even numbers like 12345: value +"you can even quote keys if you'd like!": value + +# A key, followed by any separator, and then finally a value, is called a field. +this_entire_line_is: a field + +################### +### VALUE TYPES ### +################### + +# The types that a value can be are string, number, object, array, boolean, and +# null. Every value type except for array and object are called simple values. + +## SIMPLE VALUES ## + +quoted_string: "I like quoting my strings." +unquoted_string: I don't like quoting my strings. +# Special characters that cannot be used in unquoted strings are: +# $ " { } [ ] : = , + # ` ^ ? ! @ * & +# Unquoted strings do not support any kind of escaping. If using one of those +# special characters is desired, use a quoted string. +multi-line_string: """ + This entire thing is a string! + One giant, multi-line string. + You can put 'single' and "double" quotes without it being invalid. +""" + +number: 123 +negative: -123 +fraction: 3.1415926536 +scientific_notation: 1.2e6 // same as 1.2 * (10^6) + +boolean: true # or false +empty: null + +## ARRAYS ## + +# Arrays hold lists of values. +# Values in arrays can be separated with commas.. +array: [ 1, 2, 3, 4, 5 ] +fibonacci: [1,1,2,3,5,8,13] +multiples_of_5: [5, 10, 15, 20,] # Notice the trailing comma. That's okay here. +# or newlines.. +friends: [ + "Brian" + "Sophie" + "Maya" + "Sabina" +] +# or both! +ingredients: [ + "Egg", + "Sugar", + "Oil", + "Flour", # Notice the trailing comma. That's okay here too. +] +# Once again, HOCON has a very loose syntax. Use whichever style you prefer. +no newline before or after bracket: ["This" + "is" + "an" + "array!"] + +# Just like any other value, arrays can hold other arrays. +array in array: [ [1, 2, 3], ["a", "b", "c"] ] +array in array in array: [ [ [1, 2], [8, 9] ], [ ["a", "b" ], ["y", "z"] ] ] + +## OBJECTS ## + +# Objects hold fields. +# Just like arrays, fields in objects can be separated with commas.. +object: { key: value, another_key: another_value } +server_connection: {ip: "127.0.0.1", port: 80} +first: {letter: a, number: 1,} # Notice the trailing comma. +# or newlines.. +power_grid: { + max_capacity: 15000 + current_power: 1200 +} +# or both! +food_colors: { + carrot: orange, + pear: green, + apple: red, + plum: purple, + banana: yellow, # Trailing commas are okay here too! +} + +# Arrays can hold objects just like any other value type. +coworkers: [ + { + name: Jeff + age: 27 + }, + { + name: Henry + age: 35 + }, + { + name: Timmy + age: 12 + } +] + +# The field separator may be omitted if the key is followed by { +no_separator { + key: value + speed_of_light: very fast + ten: 10 + + # Objects can go inside other objects just like any other value. + another_object { + twenty: 20 + speed_of_sound: also pretty fast + } +} + +# In fact, the entirety of any HOCON document is an actually just an object. +# That object is called the root object. The only difference between it and any +# other object is that the curly brackets at the top and bottom of the document +# may be omitted. + +# This means that HOCON documents can be formatted in the same way that +# regular objects can be formatted, including separating fields with commas +# rather than with newlines. + +# Additionally, while the entirety of a HOCON document can be and is usually an +# object, it can also be an array. If it is an array, the opening and closing +# brackets at the top and bottom of the document must be explicitly written. + +###################### +### DUPLICATE KEYS ### +###################### + +is_happy: false +# If there is a duplicate key, the new value overrides the previous value. +is_happy: true +online_users: [Jacob, Mike] +# Same with arrays. +online_users: [Jacob, Mike, Henry] + +# For objects, it's a bit different. +my_car: { + color: blue + speed: 9001 + passengers: null + + engine: { + running: true + temperature: 137 + } +} +# If there is a duplicate key and both values are objects, +# then the objects are merged. +my_car: { + // These fields are added to the old, previous object. + nickname: "My Favorite Car" + type: 2-door sedan + + // Since the value of this duplicate key is NOT an object, + // it simply overrides the previous value. + speed: 60 + // Same with arrays. They override, not merge. + passengers: ["Nate", "Ty"] + + // This object is recursively merged with the other object. + engine: { + // These two fields are added to the previous object. + type: gas + oil_level: 10 + // This field overrides the previous value. + temperature: 179 + } +} + +# Object merging is done two at a time. That is to say, the first two objects +# merge into one, then that object merges with the next object, and so on. + +# Because of this, if you set a field with an object value to a non-object value +# and then back to an object value, the new object will completely override any +# previous value. + +// Null, a non-object value, completely overrides the object value. +my_car: null + +// Then, this object completely overrides null. +my_car: { + nickname: "My New Car" + type: 4-door minivan + color: gray + speed: 90 + passengers: ["Ayden", "Liz"] +} + +########################### +### VALUE CONCATENATION ### +########################### + +## SIMPLE VALUE CONCATENATION ## + +# Simple values (all value types except objects and arrays) separated by +# whitespace are concatenated into a single string. The whitespace between +# values is preserved. +number_concatenation: 1 2 3 12.5 -3 2e5 // same as: "1 2 3 12.5 -3 2e5" +boolean_concat: true false true // "true false true" +null_concat: null null null // "null null null" +mixed_concat: 1 true null // "1 true null" + +# String value concatenation can appear anywhere that a quoted string can. +number_concat_in_array: [1 2, 3 4, 5 6] // same as: ["1 2", "3 4", "5 6"] + +# In fact, unquoted strings are actually just string value concatenations. +unquoted_string_concat: his name is jeff // same as: "his name is jeff" + +# Going further, even keys that are unquoted strings are actually just string +# value concatenations. +this is a key: value // the KEY is the same as: "this is a key" +# The following field is identical to the field above. +"this is a key": value + +# Quoted strings can also be concatenated. This will be useful later, +# when we cover substitutions. +quoted_string_concat: "her"" name" "is ""jenna" // same as: "her name is jenna" +# Notice that the whitespace (or lack thereof) between values is preserved. + +## ARRAY CONCATENATION ## + +# Arrays separated by whitespace are merged into a single array. +array_concat: [1, 2, 3] [4, 5, 6] // same as: [1, 2, 3, 4, 5, 6] + +# Arrays cannot be concatenated with a non-array value. +//array_concat: true [false] results in an error +//array_concat: 1 [2] results in an error + +## OBJECT CONCATENATION ## + +# Objects separated by whitespace are merged into a single object. +# The merge functionality is identical to that of duplicate key object merging. +lamp: {on: true} {color: tan} // same as: {on: true, color: tan} + +# Similarly to arrays, objects cannot be concatenated with a non-object value. +//object_concat: true {on: false} results in an error +//object_concat: 1 {number: 2} results in an error + +######################## +### PATH EXPRESSIONS ### +######################## + +# Path expressions are used to write out a path through the object graph. +# Think of it as navigating through objects to a specific field. +# Each object to traverse through is called an element, and each element is +# separated with a period. + +country: { + city: { + neighborhood: { + house: { + name: "My House" + address: 123 Example Dr. + } + } + } +} +# For example, the path to the address of the house could be written as: +# country.city.neighborhood.house.address +# Country, city, neighborhood, house, and address are all elements. + +# Path expressions are used in two places: substitutions (which will be +# covered in a moment), and as keys. +# That's right: keys themselves can also be path expressions. +foo: { + bar: { + baz: { + number: 12 + } + } +} +# Rather than tediously specifying each object, a path expression can be used. +# The following field represents the same object found above. +foo.bar.baz.number: 12 + +# Fields and objects specified with path expressions are merged in the same way +# that any object is usually merged. +foo.bar.baz.bool: true +// the object foo's value is: foo { bar { baz { number: 12, bool: true } } } + +##################### +### SUBSTITUTIONS ### +##################### + +# Substitutions refer to a specific value from some path expression. +# They're only allowed in values, not keys or nested inside other substitutions. + +me: { + favorite_animal: parrots + favorite_food: cookies +} +# The syntax for a substitution is either ${path_expression} or +# ${?path_expression}. The latter syntax will be discussed in a moment. +my_fav_animal: ${me.favorite_animal} +my_fav_food: ${me.favorite_food} + +# Substitutions are not parsed inside quoted strings. To get around this, +# either use an unquoted string or value concatenation. +animal_announcement: My favorite animal is ${my_fav_animal} +// the value is: My favorite animal is parrots +food_announcement: "My favorite food is "${my_fav_food}"!" +// the value is: "My favorite food is cookies!" + +# Substitutions are parsed last in the document. Because of this, you can +# reference a key that hasn't been defined yet. +color_announcement: "My favorite color is" ${my_fav_color}"!" +// the value is: "My favorite color is blue!" +my_fav_color: blue + +# Another effect of substitutions being parsed last is that substitutions will +# always use the latest, as in last, value assigned in the entire document, +# which includes merged objects. +color: green +their_favorite_color: ${color} // the value is: orange +color: orange + +random_object: { + number: 12 +} +the_number: ${random_object.number} // the value is: 15 +random_object: { + number: 15 +} + +############################### +### UNDEFINED SUBSTITUTIONS ### +############################### + +# A substitution using the ${path_expression} syntax with an undefined path +# expression, meaning a path expression that does not point to a defined value, +# is invalid and will therefore generate an error. +//${does.not.exist} will throw an error + +# However, an undefined substitution using the ${?path_expression} syntax +# has different behavior depending on what it is the value of. +request: { + # If it is the value of a field, then the field will not be created. + response: ${?does.not.exist} // this field won't be created and does not exist + type: HTTP +} + +request: { + # Additionally, if it would have overridden a previous value, then the + # previous value remains unchanged. + type: ${?does.not.exist} // request.type is still HTTP +} + +# If it is a value in an array, then it is simply not added. +values: [ 172, "Brian", ${?does.not.exist}, null, true, ] +// the value is: [ 172, "Brian", null, true ] + +# If it is part of simple value concatenation, it acts as an empty string. +final_string: "String One"${?does.not.exist}"String Two" +// the value is: "String OneString Two" + +# If it is part of array concatenation, it acts as an empty array. +final_array: [ 1, 2, 3 ] ${?does.not.exist} [ 7, 8, 9 ] +// the value is: [ 1, 2, 3, 7, 8, 9 ] + +# If it is part of object concatenation, it acts as an empty object. +final_array: { a: 1 } ${?does.not.exist} { c: 3 } +// the value is: { a: 1, c: 3 } + +###################################### +### SELF-REFERENTIAL SUBSTITUTIONS ### +###################################### + +# Substitutions normally "look forward" and use the final value defined in the +# document. However, in cases when this would create a cycle, the substitution +# looks only backwards. + +# A field which contains a substitution that points to itself or points to +# other fields that eventually point back to itself is called a +# self-referential field. +letters: "a b c" // the value is: "a b c" +letters: ${letters}" d" // "a b c d" +letters: ${letters}" e" // "a b c d e" + +PATH: [/bin] // the value is: [/bin] +PATH: ${PATH} [/usr/bin] // [/bin, /usr/bin] +PATH: ${PATH} [/usr/local/bin] // [/bin, /usr/bin, /usr/local/bin] + +x: "x" // the value is: "x" +y: ${x}"y" // "xy" +x: ${y}"z" // "xyz" + +########################## +### += FIELD SEPARATOR ### +########################## + +# In addition to : and =, there actually exists another separator: += +# A field separated with += acts as a self-referential array concatenation. +# In short, it appends an element to a previously defined array. + +a: [1] +b: [1] +# This field: +a += 2 // the value is: [1, 2] +# functions the same as: +b: ${?b} [2] // the value is: [1, 2] + +USERS: [/usr/luke] // the value is: [/usr/luke] +USERS += /usr/devon // [/usr/luke, /usr/devon] +USERS += /usr/michael // [/usr/luke, /usr/devon, /usr/michael] + +# Since += only appends elements to a previously existing array, if the previous +# value was not an array, an error will be generated. +OTHER_USERS: /usr/luke +//OTHER_USERS += /usr/devon results in an error + +# Notice that the underlying substitution syntax used is ${?path}, not ${path}. +# Recall that, using the ${?} syntax, an undefined substitution in array +# concatenation acts as an empty array. Because of this, it is perfectly +# acceptable if the field that is being set is initially undefined. +//z: [] not necessary +z += 3 // the value is: [3] +z += 4 // the value is: [3, 4] + +NEW_USERS += /usr/sandra // the value is: [/usr/sandra] +NEW_USERS += /usr/kennedy // [/usr/sandra, /usr/kennedy] +NEW_USERS += /usr/robin // [/usr/sandra, /usr/kennedy, /usr/robin] + +################ +### INCLUDES ### +################ + +# Includes allow you to "import" one HOCON document into another. + +# An include statement consists of the unquoted string "include" followed by +# whitespace and then a resource name, which is one of the following: +# - a single quoted string which is heuristically interpreted as a URL, +# filename, or a Java classpath resource. +# - url(), file(), or classpath(), with the parentheses surrounding a quoted +# string which is either a URL, filename, or classpath resource respectively. +# - required(), with the parentheses surrounding one of the above. +include "https://example.com/config.conf" +include "/foo/bar/config.conf" +include "config.conf" + +include url("https://example.com/config.conf") +include file("/foo/bar/config.conf") +include classpath("config.conf") + +# If the included file does not exist, it will be silently ignored and act as if +# it were an empty object. However, if it is wrapped around required(), then +# parsing will explicitly error if the file cannot be resolved. +//include required("doesnt_exist.conf") will error +//include required(url("https://example.com/doesnt_exist.conf")) will error +//include required(file("doesnt_exist.conf")) will error +//include required(classpath("doesnt_exist.conf")) will error + +# The file specified by the include statement is called the included file, and +# the file which contains the include statement is called the including file. + +# Including a file functions as if you directly replaced the include statement, +# wherever it may be, with the contents of the included file's root object. + +# An included file must have an object as its root value and not an array. +# If the included file has an array as its root value, then it is invalid and +# an error will be generated. + +# Pretend that the following is in a file called user_config.conf: +username: RandomUser1337 +auto_login: true +color_theme: dark +screensaver: { + image: usr/images/screensaver.jpg + turn_on_after: 1m +} + +# And then we include that file. +include file("user_config.conf") + +# We can now reference values from that file! +path_to_user_screensaver: ${screensaver.image} // +greeting: "Welcome, "${username}"!" // the value is: "Welcome, RandomUser1337!" + +# Duplicate keys override as they normally do. +status: "Auto Login: "${auto_login} // the value is: "Auto Login: true" +auto_login: false +status: "Auto Login: "${auto_login} // the value is: "Auto Login: false" + +# Object merging is also the same as usual. +screensaver: { + // This gets added to the screensaver object. + enable_during_day: false + // This overrides the previous value. + turn_on_after: 30s +} + +# Include statements can appear in place of a field. Anywhere that a field +# could appear, an include statement could appear as well. + +# Pretend that the following is in a file called server_settings.conf: +max_connections: 10 +url: example.com +port: 80 +admin_page: { + username: admin + password: pass12345 +} + +# And then we include that file nested inside another object. +websites: { + my_epic_website: { + include file("server_settings.conf") + } +} + +# Now, we can reference the contents of server_settings.conf as if they +# had been written directly into the object my_epic_website. +server_port: ${websites.my_epic_website.port} + +the_password: "The password is: "${websites.my_epic_website.admin_page.password} +// the value is: The password is: pass12345 + +max_conn: "Max Connections: "${websites.my_epic_website.max_connections} +// the value is: Max Connections: 10 +``` + +### More Resources + ++ [Official HOCON Specification](https://github.com/lightbend/config/blob/master/HOCON.md) ++ [HOCON Playground](https://hocon-playground.herokuapp.com) diff --git a/html.html.markdown b/html.html.markdown index b8212776..e9226a61 100644 --- a/html.html.markdown +++ b/html.html.markdown @@ -8,11 +8,11 @@ translators: - ["Dimitri Kokkonis", "https://github.com/kokkonisd"] --- -HTML stands for HyperText Markup Language. +HTML stands for Hypertext Markup Language. -It is a language which allows us to write pages for the world wide web. +It is a language which allows us to write pages for the World Wide Web. It is a markup language, it enables us to write webpages using code to indicate -how text and data should be displayed. In fact, html files are simple text +how text and data should be displayed. In fact, HTML files are simple text files. What is this markup? It is a method of organising the page's data by @@ -171,6 +171,6 @@ HTML is written in files ending with `.html` or `.htm`. The mime type is **HTML is NOT a programming language** ## To Learn More -* [wikipedia](https://en.wikipedia.org/wiki/HTML) -* [HTML tutorial](https://developer.mozilla.org/en-US/docs/Web/HTML) -* [W3School](http://www.w3schools.com/html/html_intro.asp) +* [Wikipedia](https://en.wikipedia.org/wiki/HTML) +* [HTML Tutorial](https://developer.mozilla.org/en-US/docs/Web/HTML) +* [W3Schools](http://www.w3schools.com/html/html_intro.asp) diff --git a/httpie.html.markdown b/httpie.html.markdown new file mode 100644 index 00000000..40481dff --- /dev/null +++ b/httpie.html.markdown @@ -0,0 +1,120 @@ +--- +category: tool +tool: httpie +contributors: + - ["Adaías Magdiel", "https://github.com/AdaiasMagdiel"] +filename: learn-httpie.sh +--- + +HTTPie is a powerful command-line HTTP client designed for easy interaction +with HTTP servers. It provides a simple and intuitive interface, making it an +excellent tool for developers, testers, and system administrators. + +## Basic Usage + +HTTPie follows a simple syntax: http [flags] [METHOD] URL [items]. + +```bash +http GET https://api.example.com/posts +``` + +You can print the request without sending it by using the `--offline` flag. + +```bash +http --offline https://api.example.com/posts +``` + +### URL shortcuts for `localhost` + +HTTPie supports a curl-like shorthand for localhost. For instance, ":3000" +expands to "http://localhost:3000". If the port is omitted, it assumes port 80. + +```bash +http :/users # http://localhost/users +http :5000/rss # http://localhost:5000/rss +``` + +### Optional GET and POST + +If you don't specify the METHOD, the HTTPie will use: + +- GET for requests without body +- POST for requests with body + +```bash +http https://api.example.com/tags # GET tags +http https://api.example.com/tags title="Tutorial" slug="tutorial" # POST a new tag +``` + +## Querystring Parameters + + +If you're manually adding query string parameters in the terminal, try the +`param==value` syntax. It avoids shell escaping for & separators and +automatically URL-escapes special characters in parameter names and values. +This differs from parameters in the full URL, which HTTPie doesn't modify. + +```bash +http https://api.example.com/search q==httpie per_page==20 +``` + +## Sending Data + +You can send data in various formats such as JSON, form data, or files. + +### JSON Data + +```bash +http POST https://api.example.com/posts title="Hello" body="World" +``` + +### Form Data + +```bash +http -f POST https://api.example.com/submit name=John email=john@example.com +``` + +### Files + +```bash +http --form POST https://api.example.com/upload file@/path/to/file.txt +``` + +## Headers and Authentication + +HTTPie allows you to set headers and handle authentication easily. + +### Headers + +```bash +http GET https://api.example.com/posts Authorization:"Bearer Token" User-Agent:"HTTPie" +``` + +### Basic Authentication + +```bash +http -a username:password GET https://api.example.com/protected +``` + +### Bearer Authentication + +```bash +https -A bearer -a token https://api.example.com/admin +``` + +## Response Handling + +HTTPie provides various options for handling responses. + +```bash +http GET https://api.example.com/data Accept:application/json # Pretty Print JSON + +http GET https://api.example.com/image --output image.png # Save Response to File + +http --follow GET https://example.com # Follow Redirects +``` + +## Further Reading + +- [Official Documentation](https://httpie.io/docs/cli). +- [GitHub](https://github.com/httpie). diff --git a/hu-hu/go-hu.html.markdown b/hu-hu/go-hu.html.markdown index 638c9489..451f9147 100644 --- a/hu-hu/go-hu.html.markdown +++ b/hu-hu/go-hu.html.markdown @@ -89,7 +89,7 @@ func learnTypes() { g := 'Σ' // rúna(rune) típus, megegyezik az uint32-vel, egy UTF-8 karaktert // tárol - f := 3.14195 // float64, az IEEE-754 szabványnak megfelelő 64-bites + f := 3.14159 // float64, az IEEE-754 szabványnak megfelelő 64-bites // lebegőpontos szám c := 3 + 4i // complex128, belsőleg két float64-gyel tárolva @@ -325,7 +325,7 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { ## További olvasmányok -Minden Go-val kapcsolatos megtaláható a [hivatalos Go weboldalon](http://golang.org/). +Minden Go-val kapcsolatos megtaláható a [hivatalos Go weboldalon](https://go.dev/). Ott követhetsz egy tutorialt, játszhatsz a nyelvvel az interneten, és sok érdekességet olvashatsz. A nyelv specifikációját kifejezetten érdemes olvasni, viszonylag rövid és sokat tanul belőle az ember. diff --git a/hu-hu/python-hu.html.markdown b/hu-hu/pythonlegacy-hu.html.markdown index 01f1c414..483784ba 100644 --- a/hu-hu/python-hu.html.markdown +++ b/hu-hu/pythonlegacy-hu.html.markdown @@ -1,5 +1,5 @@ --- -language: python +language: Python 2 (legacy) contributors: - ["Louie Dinh", "http://ldinh.ca"] - ["Amin Bandali", "https://aminb.org"] @@ -9,7 +9,7 @@ contributors: - ["habi", "http://github.com/habi"] translators: - ["Tamás Diószegi", "https://github.com/ditam"] -filename: learnpython-hu.py +filename: learnpythonlegacy-hu.py lang: hu-hu --- @@ -20,10 +20,10 @@ bele. Tulajdonképpen futtatható pszeudokód. Szívesen fogadok visszajelzéseket! Elérsz itt: [@louiedinh](http://twitter.com/louiedinh) vagy pedig a louiedinh [kukac] [google email szolgáltatása] címen. -Figyelem: ez a leírás a Python 2.7 verziójára vonatkozok, illetve +Figyelem: ez a leírás a Python 2.7 verziójára vonatkozik, illetve általánosságban a 2.x verziókra. A Python 2.7 azonban már csak 2020-ig lesz támogatva, ezért kezdőknek ajánlott, hogy a Python 3-mal kezdjék az -ismerkedést. A Python 3.x verzióihoz a [Python 3 bemutató](http://learnxinyminutes.com/docs/python3/) +ismerkedést. A Python 3.x verzióihoz a [Python 3 bemutató](http://learnxinyminutes.com/docs/python/) ajánlott. Lehetséges olyan Python kódot írni, ami egyszerre kompatibilis a 2.7 és a 3.x diff --git a/hu-hu/yaml-hu.html.markdown b/hu-hu/yaml-hu.html.markdown index 37ce4cb2..3fb8b87f 100644 --- a/hu-hu/yaml-hu.html.markdown +++ b/hu-hu/yaml-hu.html.markdown @@ -2,7 +2,7 @@ language: yaml filename: learnyaml-hu.yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] translators: - ["Tamás Diószegi", "https://github.com/ditam"] lang: hu-hu diff --git a/hy.html.markdown b/hy.html.markdown index 1287095f..5eddbf55 100644 --- a/hy.html.markdown +++ b/hy.html.markdown @@ -13,8 +13,7 @@ hy to call native python code or python to call native hy code as well This tutorial works for hy ≥ 0.9.12, with some corrections for hy 0.11. ```clojure -;; this gives an gentle introduction to hy for a quick trial head to -;; http://try-hy.appspot.com +;; this gives an gentle introduction to hy ;; ; Semicolon comments, like other LISPS @@ -175,10 +174,10 @@ True ; => True ; create lexical bindings with `let', all variables defined thusly ; have local scope -(let [[nemesis {"superman" "lex luther" +(let [nemesis {"superman" "lex luther" "sherlock" "moriarty" - "seinfeld" "newman"}]] - (for [(, h v) (.items nemesis)] + "seinfeld" "newman"}] + (for [[h v] (.items nemesis)] (print (.format "{0}'s nemesis was {1}" h v)))) ;; classes diff --git a/id-id/asciidoc-id.html.markdown b/id-id/asciidoc-id.html.markdown index ceb56b92..2843b8be 100644 --- a/id-id/asciidoc-id.html.markdown +++ b/id-id/asciidoc-id.html.markdown @@ -4,7 +4,7 @@ contributors: - ["Ryan Mavilia", "http://unoriginality.rocks/"] translators: - ["Rizky Luthfianto", "http://github.com/rilut"] -filename: asciidoc-id.md +filename: asciidoc-id.adoc lang: id-id --- diff --git a/id-id/coffeescript-id.html.markdown b/id-id/coffeescript-id.html.markdown index 7fa40bb6..fc876184 100644 --- a/id-id/coffeescript-id.html.markdown +++ b/id-id/coffeescript-id.html.markdown @@ -16,7 +16,7 @@ dan kompatibel dengan semua *runtime* JavaScript. Lihat juga [website CoffeeScript](http://coffeescript.org/) yang memiliki tutorial lengkap tentang CoffeeScript. -```CoffeeScript +```coffeescript # CoffeeScript adalah bahasa hipster. # Mengikuti tren bahasa modern lainnya. # Sehingga, seperti Ruby dan Python, untuk komentar digunakan tanda pagar. diff --git a/id-id/markdown.html.markdown b/id-id/markdown.html.markdown index 1ff1963b..22fcb17f 100644 --- a/id-id/markdown.html.markdown +++ b/id-id/markdown.html.markdown @@ -54,8 +54,8 @@ __Dan juga teks ini.__ **_Dan juga ini!_** *__Dan ini!__* -<!-- Di markdown ala Github, yang digunakan untuk me-render berkas markdown pada -Github, kita juga punya coretan: --> +<!-- Di markdown ala GitHub, yang digunakan untuk me-render berkas markdown pada +GitHub, kita juga punya coretan: --> ~~Teks ini dirender dengan coretan.~~ @@ -155,7 +155,7 @@ di dalam kode Anda --> John bahkan tidak tahu apa fungsi dari `go_to()` ! -<!-- Di Markdown ala Github, Anda dapat menggunakan syntax spesial untuk kode --> +<!-- Di Markdown ala GitHub, Anda dapat menggunakan syntax spesial untuk kode --> \`\`\`ruby <!-- kecuali hapus backlash tersebut ketika melakukannya, hanya ```ruby ! --> def foobar @@ -163,7 +163,7 @@ def foobar end \`\`\` <!-- Disini juga, tidak ada backslashes, hanya ``` --> -<!-- Teks di atas tidak membutuhkan indentasi, plus Github akan menggunakan syntax +<!-- Teks di atas tidak membutuhkan indentasi, plus GitHub akan menggunakan syntax highlighting dari bahasa yang digunakan setelah ``` --> <!-- Horizontal rule (<hr />) --> @@ -236,14 +236,14 @@ Saya ingin mengetik *teks ini dikelilingi tanda bintang* tapi saya tidak mau tek miring, jadi saya melakukan: \*teks ini dikelilingi tanda bintang\*. <!-- Tombol keyboard --> -<!-- Pada Markdown ala Github, Anda dapat menggunakan tag <kbd> untuk merepresentasikan tombol +<!-- Pada Markdown ala GitHub, Anda dapat menggunakan tag <kbd> untuk merepresentasikan tombol keyboard --> Komputer Anda hang? Coba kirim sebuah <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> <!-- Tabel --> -<!-- Tabel hanya tersedia pada Markdown ala Github dan sedikit merepotkan, namun jika Anda +<!-- Tabel hanya tersedia pada Markdown ala GitHub dan sedikit merepotkan, namun jika Anda sangat menginginkannya: --> | Kol1 | Kol2 | Kol3 | diff --git a/id-id/pyqt-id.html.markdown b/id-id/pyqt-id.html.markdown index c4833d06..a9163326 100644 --- a/id-id/pyqt-id.html.markdown +++ b/id-id/pyqt-id.html.markdown @@ -15,10 +15,10 @@ lang: id-id Tulisan ini diadaptasi dari **Intro Qt untuk C++** oleh [Aleksey Kholovchuk](https://github.com/vortexxx192). Kode-kode yang tertulis di sini akan menghasilkan fungsionalitas yang sama. Bedanya, versi ini dibangun menggunakan **PyQt**! -```Python +```python import sys from PyQt4 import QtGui - + def window(): # Buat objek aplikasi app = QtGui.QApplication(sys.argv) @@ -45,7 +45,7 @@ if __name__ == '__main__': Untuk menunjukkan beberapa fitur yang lebih canggih di **PyQt**, kita akan membangun elemen tambahan. Di sini, kita akan membuat Kotak Popup Dialog, yang berguna untuk meminta pengguna untuk mengkonfirmasi keputusan atau untuk menampilkan informasi. -```Python +```python import sys from PyQt4.QtGui import * from PyQt4.QtCore import * diff --git a/id-id/rst-id.html.markdown b/id-id/rst-id.html.markdown index 06d80089..a5070d64 100644 --- a/id-id/rst-id.html.markdown +++ b/id-id/rst-id.html.markdown @@ -88,14 +88,14 @@ ini :) Ada berbagai macam cara untuk membuat tautan: -- Dengan menambahkan garis bawah setelah sebuah huruf : Github_ dan dengan +- Dengan menambahkan garis bawah setelah sebuah huruf : GitHub_ dan dengan menambahkan URL target setelah teks (cara ini mempunyai kelebihan dengan tidak memasukkan URL yang tidak penting ke dalam teks yang bisa dibaca). - Dengan mengetik URL lengkap yang dapat dipahami : https://github.com (akan otomatis diubah menjadi sebuah link) -- Dengan membuat link seperti di Markdown: `Github <https://github.com/>`_ . +- Dengan membuat link seperti di Markdown: `GitHub <https://github.com/>`_ . -.. _Github https://github.com/ +.. _GitHub https://github.com/ ``` diff --git a/id-id/ruby-id.html.markdown b/id-id/ruby-id.html.markdown index 28135da1..a94aefb2 100644 --- a/id-id/ruby-id.html.markdown +++ b/id-id/ruby-id.html.markdown @@ -619,4 +619,4 @@ Sesuatu.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/) - Edisi lama yang [gratis](http://ruby-doc.com/docs/ProgrammingRuby/) tersedia online. - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - Panduan penulisan kode Ruby oleh komunitas. -- [Try Ruby](http://tryruby.org) - Pelajari dasar bahasa pemrograman Ruby, secara interaktif di browser. +- [Try Ruby](https://try.ruby-lang.org/) - Pelajari dasar bahasa pemrograman Ruby, secara interaktif di browser. diff --git a/images/cairo/build.png b/images/cairo/build.png Binary files differnew file mode 100644 index 00000000..7cadb9ad --- /dev/null +++ b/images/cairo/build.png diff --git a/images/cairo/connect.png b/images/cairo/connect.png Binary files differnew file mode 100644 index 00000000..86146353 --- /dev/null +++ b/images/cairo/connect.png diff --git a/images/cairo/connect2.png b/images/cairo/connect2.png Binary files differnew file mode 100644 index 00000000..08b00a81 --- /dev/null +++ b/images/cairo/connect2.png diff --git a/images/cairo/declare.png b/images/cairo/declare.png Binary files differnew file mode 100644 index 00000000..5b5196ce --- /dev/null +++ b/images/cairo/declare.png diff --git a/images/cairo/deploy.png b/images/cairo/deploy.png Binary files differnew file mode 100644 index 00000000..bdb7e53c --- /dev/null +++ b/images/cairo/deploy.png diff --git a/images/solidity/copy-address.png b/images/solidity/copy-address.png Binary files differnew file mode 100644 index 00000000..b0a698ee --- /dev/null +++ b/images/solidity/copy-address.png diff --git a/images/solidity/metamask-kovan.png b/images/solidity/metamask-kovan.png Binary files differnew file mode 100644 index 00000000..c5d5ae4b --- /dev/null +++ b/images/solidity/metamask-kovan.png diff --git a/images/solidity/remix-add-token.png b/images/solidity/remix-add-token.png Binary files differnew file mode 100644 index 00000000..a1c2f1ac --- /dev/null +++ b/images/solidity/remix-add-token.png diff --git a/images/solidity/remix-choose-file.png b/images/solidity/remix-choose-file.png Binary files differnew file mode 100644 index 00000000..6a16afc8 --- /dev/null +++ b/images/solidity/remix-choose-file.png diff --git a/images/solidity/remix-compile.png b/images/solidity/remix-compile.png Binary files differnew file mode 100644 index 00000000..7afd0d7c --- /dev/null +++ b/images/solidity/remix-compile.png diff --git a/images/solidity/remix-deploy.png b/images/solidity/remix-deploy.png Binary files differnew file mode 100644 index 00000000..7f855f48 --- /dev/null +++ b/images/solidity/remix-deploy.png diff --git a/images/solidity/remix-interact.png b/images/solidity/remix-interact.png Binary files differnew file mode 100644 index 00000000..79f89ae9 --- /dev/null +++ b/images/solidity/remix-interact.png diff --git a/images/solidity/remix-solidity.png b/images/solidity/remix-solidity.png Binary files differnew file mode 100644 index 00000000..f4500967 --- /dev/null +++ b/images/solidity/remix-solidity.png diff --git a/images/solidity/remix-testnet.png b/images/solidity/remix-testnet.png Binary files differnew file mode 100644 index 00000000..6cc845ea --- /dev/null +++ b/images/solidity/remix-testnet.png diff --git a/images/solidity/send-link.png b/images/solidity/send-link.png Binary files differnew file mode 100644 index 00000000..1cd9188e --- /dev/null +++ b/images/solidity/send-link.png diff --git a/it-it/asciidoc-it.html.markdown b/it-it/asciidoc-it.html.markdown index 47a57349..eaa2372b 100644 --- a/it-it/asciidoc-it.html.markdown +++ b/it-it/asciidoc-it.html.markdown @@ -6,7 +6,7 @@ contributors: translators: - ["Ale46", "https://github.com/ale46"] lang: it-it -filename: asciidoc-it.md +filename: asciidoc-it.adoc --- AsciiDoc è un linguaggio di markup simile a Markdown e può essere usato per qualsiasi cosa, dai libri ai blog. Creato nel 2002 da Stuart Rackman, questo linguaggio è semplice ma permette un buon numero di personalizzazioni. diff --git a/it-it/bash-it.html.markdown b/it-it/bash-it.html.markdown index efc47969..dd55b84c 100644 --- a/it-it/bash-it.html.markdown +++ b/it-it/bash-it.html.markdown @@ -22,7 +22,7 @@ translators: lang: it-it --- -Bash è il nome della shell di unix, la quale è stata distribuita anche come shell del sistema oprativo GNU e la shell di default su Linux e Mac OS X. +Bash è il nome della shell di unix, la quale è stata distribuita anche come shell del sistema oprativo GNU e la shell di default su Linux e macOS. Quasi tutti gli esempi sottostanti possono fare parte di uno shell script o eseguiti direttamente nella shell. [Per saperne di più.](http://www.gnu.org/software/bash/manual/bashref.html) @@ -63,7 +63,7 @@ echo ${Variabile} # Sotto ci sono altri esempi che analizzano l'uso dell'espansione dei parametri. # Sostituzione di stringhe nelle variabili -echo ${Variabile/Una/A} +echo ${Variabile/Una/La} # Questo sostituirà la prima occorrenza di "Una" con "La" # Sottostringa di una variabile @@ -140,6 +140,25 @@ then echo "Questo verrà eseguito se $Nome è Daniya O Zach." fi +# C'è anche l'operatore `=~`, che serve per confrontare una stringa con un'espressione regolare: +Email=me@example.com +if [[ "$Email" =~ [a-z]+@[a-z]{2,}\.(com|net|org) ]] +then + echo "Email valida!" +fi +# L'operatore =~ funziona solo dentro alle doppie parentesi quadre [[ ]], +# che hanno un comportamento leggermente diverso rispetto alle singole [ ]. +# Se vuoi approfondire, visita questo link (in inglese): +# http://www.gnu.org/software/bash/manual/bashref.html#Conditional-Constructs + +# Usando `alias`, puoi definire nuovi comandi o modificare quelli già esistenti. +# Ad esempio, così puoi ridefinire il comando ping per inviare solo 5 pacchetti +alias ping='ping -c 5' +# "Scavalca" l'alias e usa il comando vero, utilizzando il backslash +\ping 192.168.1.1 +# Stampa la lista di tutti gli alias +alias -p + # Le espressioni sono nel seguente formato: echo $(( 10 + 5 )) diff --git a/it-it/c++-it.html.markdown b/it-it/c++-it.html.markdown index 449aebfb..a8e0c7b5 100644 --- a/it-it/c++-it.html.markdown +++ b/it-it/c++-it.html.markdown @@ -1,5 +1,5 @@ --- -language: c++ +language: C++ filename: learncpp-it.cpp contributors: - ["Steven Basart", "http://github.com/xksteven"] diff --git a/it-it/elixir-it.html.markdown b/it-it/elixir-it.html.markdown index 60301b1a..ce3e4535 100644 --- a/it-it/elixir-it.html.markdown +++ b/it-it/elixir-it.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Luca 'Kino' Maroni", "https://github.com/kino90"] - ["Joao Marques", "http://github.com/mrshankly"] @@ -21,11 +21,11 @@ e molte altre funzionalità. # Non esistono commenti multilinea, # ma puoi concatenare più commenti. -# Per usare la shell di elixir usa il comando `iex`. +# Per usare la shell di Elixir usa il comando `iex`. # Compila i tuoi moduli con il comando `elixirc`. -# Entrambi i comandi dovrebbero già essere nel tuo PATH se hai installato -# elixir correttamente. +# Entrambi i comandi dovrebbero già essere nel tuo PATH se hai installato +# Elixir correttamente. ## --------------------------- ## -- Tipi di base @@ -65,7 +65,7 @@ coda #=> [2,3] # le tuple hanno dimensione differente. # {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2} -# Ci sono anche i binari +# Ci sono anche i binari <<1,2,3>> # binari (Binary) # Stringhe e liste di caratteri @@ -80,14 +80,14 @@ multi-linea. #=> "Sono una stringa\nmulti-linea.\n" # Le stringhe sono tutte codificate in UTF-8: -"cìaò" +"cìaò" #=> "cìaò" # le stringhe in realtà sono dei binari, e le liste di caratteri sono liste. <<?a, ?b, ?c>> #=> "abc" [?a, ?b, ?c] #=> 'abc' -# `?a` in elixir restituisce il valore ASCII della lettera `a` +# `?a` in Elixir restituisce il valore ASCII della lettera `a` ?a #=> 97 # Per concatenare liste si usa `++`, per binari si usa `<>` @@ -112,7 +112,7 @@ minore..maggiore = 1..10 # Puoi fare pattern matching anche sugli intervalli 5 * 2 #=> 10 10 / 2 #=> 5.0 -# In elixir l'operatore `/` restituisce sempre un decimale. +# In Elixir l'operatore `/` restituisce sempre un decimale. # Per fare una divisione intera si usa `div` div(10, 2) #=> 5 @@ -124,10 +124,11 @@ rem(10, 3) #=> 1 # Questi operatori si aspettano un booleano come primo argomento. true and true #=> true false or true #=> true -# 1 and true #=> ** (ArgumentError) argument error +# 1 and true +#=> ** (BadBooleanError) expected a boolean on left-side of "and", got: 1 # Elixir fornisce anche `||`, `&&` e `!` che accettano argomenti -# di qualsiasi tipo. +# di qualsiasi tipo. # Tutti i valori tranne `false` e `nil` saranno valutati come true. 1 || true #=> 1 false && 1 #=> false @@ -147,7 +148,7 @@ nil && 20 #=> nil 1 < :ciao #=> true # L'ordine generale è definito sotto: -# numeri < atomi < riferimenti < funzioni < porte < pid < tuple < liste +# numeri < atomi < riferimenti < funzioni < porte < pid < tuple < liste # < stringhe di bit # Per citare Joe Armstrong su questo: "L'ordine non è importante, @@ -171,8 +172,8 @@ else "Questo sì" end -# Ti ricordi il pattern matching? -# Moltre strutture di controllo di flusso in elixir si basano su di esso. +# Ti ricordi il pattern matching? +# Moltre strutture di controllo di flusso in Elixir si basano su di esso. # `case` ci permette di confrontare un valore a diversi pattern: case {:uno, :due} do @@ -214,7 +215,7 @@ cond do "Questa sì! (essenzialmente funziona come un else)" end -# `try/catch` si usa per gestire i valori lanciati (throw), +# `try/catch` si usa per gestire i valori lanciati (throw), # Supporta anche una clausola `after` che è invocata in ogni caso. try do throw(:ciao) @@ -235,7 +236,7 @@ quadrato = fn(x) -> x * x end quadrato.(5) #=> 25 # Accettano anche guardie e condizioni multiple. -# le guardie ti permettono di perfezionare il tuo pattern matching, +# le guardie ti permettono di perfezionare il tuo pattern matching, # sono indicate dalla parola chiave `when`: f = fn x, y when x > 0 -> x + y @@ -265,13 +266,13 @@ end Matematica.somma(1, 2) #=> 3 Matematica.quadrato(3) #=> 9 -# Per compilare il modulo 'Matematica' salvalo come `matematica.ex` e usa +# Per compilare il modulo 'Matematica' salvalo come `matematica.ex` e usa # `elixirc`. # nel tuo terminale: elixirc matematica.ex # All'interno di un modulo possiamo definire le funzioni con `def` e funzioni # private con `defp`. -# Una funzione definita con `def` è disponibile per essere invocata anche da +# Una funzione definita con `def` è disponibile per essere invocata anche da # altri moduli, una funziona privata può essere invocata solo localmente. defmodule MatematicaPrivata do def somma(a, b) do @@ -286,7 +287,11 @@ end MatematicaPrivata.somma(1, 2) #=> 3 # MatematicaPrivata.esegui_somma(1, 2) #=> ** (UndefinedFunctionError) -# Anche le dichiarazioni di funzione supportano guardie e condizioni multiple: +# Anche le dichiarazioni di funzione supportano guardie e condizioni multiple. +# Quando viene chiamata una funzione dichiarata con più match, solo la prima +# che matcha viene effettivamente invocata. +# Ad esempio: chiamando area({:cerchio, 3}) vedrà invocata la seconda definizione +# di area mostrata sotto, non la prima: defmodule Geometria do def area({:rettangolo, w, h}) do w * h @@ -302,7 +307,7 @@ Geometria.area({:cerchio, 3}) #=> 28.25999999999999801048 # Geometria.area({:cerchio, "non_un_numero"}) #=> ** (FunctionClauseError) no function clause matching in Geometria.area/1 -# A causa dell'immutabilità dei dati, la ricorsione è molto frequente in elixir +# A causa dell'immutabilità dei dati, la ricorsione è molto frequente in Elixir defmodule Ricorsione do def somma_lista([testa | coda], accumulatore) do somma_lista(coda, accumulatore + testa) @@ -322,16 +327,25 @@ defmodule Modulo do Questo è un attributo incorporato in un modulo di esempio. """ - @miei_dati 100 # Questo è un attributo personalizzato . + @miei_dati 100 # Questo è un attributo personalizzato. IO.inspect(@miei_dati) #=> 100 end +# L'operatore pipe |> permette di passare l'output di una espressione +# come primo parametro di una funzione. +# Questo facilita operazioni quali pipeline di operazioni, composizione di +# funzioni, ecc. +Range.new(1,10) +|> Enum.map(fn x -> x * x end) +|> Enum.filter(fn x -> rem(x, 2) == 0 end) +#=> [4, 16, 36, 64, 100] + ## --------------------------- ## -- Strutture ed Eccezioni ## --------------------------- -# Le Strutture (Structs) sono estensioni alle mappe che portano +# Le Strutture (Structs) sono estensioni alle mappe che portano # valori di default, garanzia alla compilazione e polimorfismo in Elixir. defmodule Persona do defstruct nome: nil, eta: 0, altezza: 0 @@ -367,8 +381,8 @@ end ## -- Concorrenza ## --------------------------- -# Elixir si basa sul modello degli attori per la concorrenza. -# Tutto ciò di cui abbiamo bisogno per scrivere programmi concorrenti in elixir +# Elixir si basa sul modello degli attori per la concorrenza. +# Tutto ciò di cui abbiamo bisogno per scrivere programmi concorrenti in Elixir # sono tre primitive: creare processi, inviare messaggi e ricevere messaggi. # Per creare un nuovo processo si usa la funzione `spawn`, che riceve una @@ -379,12 +393,12 @@ spawn(f) #=> #PID<0.40.0> # `spawn` restituisce un pid (identificatore di processo). Puoi usare questo # pid per inviare messaggi al processo. # Per passare messaggi si usa l'operatore `send`. -# Perché tutto questo sia utile dobbiamo essere capaci di ricevere messaggi, +# Perché tutto questo sia utile dobbiamo essere capaci di ricevere messaggi, # oltre ad inviarli. Questo è realizzabile con `receive`: # Il blocco `receive do` viene usato per mettersi in ascolto di messaggi # ed elaborarli quando vengono ricevuti. Un blocco `receive do` elabora -# un solo messaggio ricevuto: per fare elaborazione multipla di messaggi, +# un solo messaggio ricevuto: per fare elaborazione multipla di messaggi, # una funzione con un blocco `receive do` al suo intero dovrà chiamare # ricorsivamente sé stessa per entrare di nuovo nel blocco `receive do`. defmodule Geometria do @@ -405,7 +419,7 @@ pid = spawn(fn -> Geometria.calcolo_area() end) #=> #PID<0.40.0> # Alternativamente pid = spawn(Geometria, :calcolo_area, []) -# Invia un messaggio a `pid` che farà match su un pattern nel blocco in receive +# Invia un messaggio a `pid` che farà match su un pattern nel blocco in receive send pid, {:rettangolo, 2, 3} #=> Area = 6 # {:rettangolo,2,3} @@ -420,8 +434,8 @@ self() #=> #PID<0.27.0> ## Referenze -* [Getting started guide](http://elixir-lang.org/getting_started/1.html) dalla [pagina web ufficiale di elixir](http://elixir-lang.org) -* [Documentazione Elixir](http://elixir-lang.org/docs/master/) +* [Getting started guide](http://elixir-lang.org/getting_started/1.html) dalla [pagina web ufficiale di Elixir](http://elixir-lang.org) +* [Documentazione Elixir](https://elixir-lang.org/docs.html) * ["Programming Elixir"](https://pragprog.com/book/elixir/programming-elixir) di Dave Thomas * [Elixir Cheat Sheet](http://media.pragprog.com/titles/elixir/ElixirCheat.pdf) * ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) di Fred Hebert diff --git a/it-it/go-it.html.markdown b/it-it/go-it.html.markdown index 797f6b0b..6f974c91 100644 --- a/it-it/go-it.html.markdown +++ b/it-it/go-it.html.markdown @@ -34,7 +34,7 @@ Go include un'ottima libreria standard e ha una community entusiasta. su riga multipla */ // In cima ad ogni file è necessario specificare il package. -// Main è un package speciale che identifica un eseguibile anziché una libreria. +// main è un package speciale che identifica un eseguibile anziché una libreria. package main // Con import sono dichiarate tutte le librerie a cui si fa riferimento @@ -91,7 +91,7 @@ può includere andata a capo.` // Sempre di tipo stringa. // Stringa letterale non ASCII. I sorgenti Go sono in UTF-8. g := 'Σ' // Il tipo runa, alias per int32, è costituito da un code point unicode. - f := 3.14195 // float64, un numero in virgola mobile a 64-bit (IEEE-754) + f := 3.14159 // float64, un numero in virgola mobile a 64-bit (IEEE-754) c := 3 + 4i // complex128, rappresentato internamente con due float64. @@ -422,9 +422,9 @@ func richiediServer() { ## Letture consigliate -La risorsa più importante per imparare il Go è il [sito ufficiale di Go](http://golang.org/). +La risorsa più importante per imparare il Go è il [sito ufficiale di Go](https://go.dev/). Qui puoi seguire i tutorial, scrivere codice in modo interattivo, e leggere tutti i dettagli. -Oltre al tour, [la documentazione](https://golang.org/doc/) contiene informazioni su +Oltre al tour, [la documentazione](https://go.dev/doc/) contiene informazioni su come scrivere ottimo codice in Go, documentazione sui package e sui comandi, e la cronologia delle release. @@ -432,17 +432,17 @@ Anche il documento che definisce il linguaggio è un'ottima lettura. E' semplice da leggere e incredibilmente corto (rispetto ad altri documenti riguardanti la creazione di linguaggi). -Puoi giocare con il codice visto finora nel [Go playground](https://play.golang.org/p/Am120Xe7qf). +Puoi giocare con il codice visto finora nel [Go playground](https://go.dev/play/p/Am120Xe7qf). Prova a cambiarlo e ad eseguirlo dal browser! -Osserva che puoi usare [https://play.golang.org](https://play.golang.org) come +Osserva che puoi usare [https://go.dev/play/](https://go.dev/play/) come una [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) per scrivere codice all'interno del browser, senza neanche installare Go! Una lettura importante per capire Go in modo più profondo è il [codice -sorgente della libreria standard](http://golang.org/src/pkg/). Infatti è +sorgente della libreria standard](https://go.dev/src/). Infatti è molto ben documentato e costituisce quanto più chiaro e conciso ci sia riguardo gli idiomi e le buone pratiche del Go. Inoltre, clickando sul nome di una -funzione [nella documentazione](http://golang.org/pkg/) compare il relativo +funzione [nella documentazione](https://go.dev/pkg/) compare il relativo codice sorgente! Un'altra ottima risorsa per imparare è [Go by example](https://gobyexample.com/). diff --git a/it-it/javascript-it.html.markdown b/it-it/javascript-it.html.markdown index 68bf6287..1d776535 100644 --- a/it-it/javascript-it.html.markdown +++ b/it-it/javascript-it.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["vinniec", "https://github.com/vinniec"] diff --git a/it-it/markdown.html.markdown b/it-it/markdown.html.markdown index b0a123f1..609d3bb7 100644 --- a/it-it/markdown.html.markdown +++ b/it-it/markdown.html.markdown @@ -72,7 +72,7 @@ __Come pure questo.__ *__E questo!__* ``` -In Github Flavored Markdown, che è utilizzato per renderizzare i file markdown su Github, è presente anche lo stile barrato: +In GitHub Flavored Markdown, che è utilizzato per renderizzare i file markdown su GitHub, è presente anche lo stile barrato: ```md ~~Questo testo è barrato.~~ @@ -183,7 +183,7 @@ Potete inoltre inserire un altro tab (o altri quattro spazi) per indentare il vo ```md my_array.each do |item| - puts item + puts item end ``` @@ -193,14 +193,17 @@ Codice inline può essere inserito usando il carattere backtick ` Giovanni non sapeva neppure a cosa servisse la funzione `go_to()`! ``` -In Github Flavored Markdown, potete inoltre usare una sintassi speciale per il codice -<pre> -<code class="highlight">```ruby +In GitHub Flavored Markdown, potete inoltre usare una sintassi speciale per il codice + +````md +```ruby def foobar - puts "Hello world!" + puts "Hello world!" end -```</code></pre> -Se usate questa sintassi, il testo non richiederà di essere indentato, inoltre Github userà l'evidenziazione della sintassi del linguaggio specificato dopo i \`\`\` iniziali +``` +```` + +Se usate questa sintassi, il testo non richiederà di essere indentato, inoltre GitHub userà l'evidenziazione della sintassi del linguaggio specificato dopo i \`\`\` iniziali ## Linea orizzontale Le linee orizzontali (`<hr/>`) sono inserite facilmente usanto tre o più asterischi o trattini, con o senza spazi. @@ -253,7 +256,7 @@ Ma non è comunemente usato. Le immagini sono inserite come i link ma con un punto esclamativo inserito prima delle parentesi quadre! ```md - + ``` E la modalità a riferimento funziona esattamente come ci si aspetta @@ -282,7 +285,7 @@ Voglio inserire *questo testo circondato da asterischi* ma non voglio che venga ``` ### Combinazioni di tasti -In Github Flavored Markdown, potete utilizzare il tag `<kbd>` per raffigurare i tasti della tastiera. +In GitHub Flavored Markdown, potete utilizzare il tag `<kbd>` per raffigurare i tasti della tastiera. ```md Il tuo computer è crashato? Prova a premere @@ -290,7 +293,7 @@ Il tuo computer è crashato? Prova a premere ``` ### Tabelle -Le tabelle sono disponibili solo in Github Flavored Markdown e sono leggeremente complesse, ma se proprio volete inserirle fate come segue: +Le tabelle sono disponibili solo in GitHub Flavored Markdown e sono leggeremente complesse, ma se proprio volete inserirle fate come segue: ```md | Col1 | Col2 | Col3 | @@ -307,4 +310,4 @@ Col 1 | Col2 | Col3 ``` --- -Per altre informazioni, leggete il post ufficiale di John Gruber sulla sintassi [qui](http://daringfireball.net/projects/markdown/syntax) e il magnifico cheatsheet di Adam Pritchard [qui](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). +Per altre informazioni, leggete il post ufficiale di John Gruber sulla sintassi [qui](https://daringfireball.net/projects/markdown/syntax) e il magnifico cheatsheet di Adam Pritchard [qui](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). diff --git a/it-it/matlab-it.html.markdown b/it-it/matlab-it.html.markdown index 38be8848..2668815f 100644 --- a/it-it/matlab-it.html.markdown +++ b/it-it/matlab-it.html.markdown @@ -1,5 +1,5 @@ --- -language: Matlab +language: MATLAB contributors: - ["mendozao", "http://github.com/mendozao"] - ["jamesscottbrown", "http://jamesscottbrown.com"] @@ -114,7 +114,7 @@ A.d.e = false; % Vettori x = [4 32 53 7 1] -x(2) % ans = 32, gli indici in Matlab iniziano da 1, non da 0 +x(2) % ans = 32, gli indici in MATLAB iniziano da 1, non da 0 x(2:3) % ans = 32 53 x(2:end) % ans = 32 53 7 1 @@ -466,7 +466,7 @@ perms(x) % lista tutte le permutazioni di elementi di x % Classi -% Matlab supporta la programmazione orientata agli oggetti. +% MATLAB supporta la programmazione orientata agli oggetti. % La classe deve essere messa in un file con lo stesso nome della classe e estensione .m % Per iniziare, creiamo una semplice classe per memorizzare waypoint GPS % Inizio WaypointClass.m @@ -488,7 +488,7 @@ classdef WaypointClass % Il nome della classe. end % Se si vuole aggiungere due oggetti Waypoint insieme senza chiamare - % una funzione speciale si può sovradefinire una funzione aritmetica di Matlab come questa: + % una funzione speciale si può sovradefinire una funzione aritmetica di MATLAB come questa: function r = plus(o1,o2) r = WaypointClass([o1.latitude] +[o2.latitude], ... [o1.longitude]+[o2.longitude]); @@ -500,7 +500,7 @@ end % Si può creare un oggetto della classe usando un costruttore a = WaypointClass(45.0, 45.0) -% Le proprietà della classe si comportano esattamente come una Struttura Matlab. +% Le proprietà della classe si comportano esattamente come una Struttura MATLAB. a.latitude = 70.0 a.longitude = 25.0 @@ -511,15 +511,15 @@ ans = multiplyLatBy(a,3) % non necessita di essere passato al metodo. ans = a.multiplyLatBy(a,1/3) -% Le funzioni Matlab possono essere sovradefinite per gestire oggetti. -% Nel metodo sopra, è stato sovradefinito come Matlab gestisce +% Le funzioni MATLAB possono essere sovradefinite per gestire oggetti. +% Nel metodo sopra, è stato sovradefinito come MATLAB gestisce % l'addizione di due oggetti Waypoint. b = WaypointClass(15.0, 32.0) c = a + b ``` -## Di più su Matlab +## Di più su MATLAB * Sito ufficiale [http://http://www.mathworks.com/products/matlab/](http://www.mathworks.com/products/matlab/) * Forum ufficiale di MATLAB: [http://www.mathworks.com/matlabcentral/answers/](http://www.mathworks.com/matlabcentral/answers/) diff --git a/it-it/php-composer-it.html.markdown b/it-it/php-composer-it.html.markdown new file mode 100644 index 00000000..509ec336 --- /dev/null +++ b/it-it/php-composer-it.html.markdown @@ -0,0 +1,193 @@ +--- +category: tool +tool: composer +contributors: + - ["Brett Taylor", "https://github.com/glutnix"] +translator: + - ["Agostino Fiscale", "https://github.com/agostinofiscale"] +lang: it-it +filename: LearnComposer-it.sh +--- + +[Composer](https://getcomposer.org/) è uno strumento che ti aiuta a gestire le +dipendenze in PHP. Ti permette di dichiarare le librerie utilizzate dal tuo +progetto e di installarle/aggiornarle per te. + +# Installazione + +```sh +# Se installi l'eseguibile in una cartella... +curl -sS https://getcomposer.org/installer | php +# ...dovrai utilizzare questo approccio, invocando Composer in questo modo: +php composer.phar about + +# Se installi l'eseguibile nella directory ~/bin/composer +# Nota: assicurati che ~/bin si trovi nella variabile di ambiente PATH +curl -sS https://getcomposer.org/installer | php -- --install-dir=~/bin --filename=composer +``` + +Gli utenti Windows possono seguire le istruzioni per [installarlo su Windows](https://getcomposer.org/doc/00-intro.md#installation-windows). + +## Assicuriamoci che il tutto abbia funzionato correttamente + +```sh +# Controlla la versione e la lista delle opzioni disponibili +composer + +# Ottieni ulteriori informazioni riguardanti le opzioni +composer help require + +# Controlla se Composer ha tutto il necessario per funzionare come si deve +# e se è aggiornato correttamente all'ultima versione disponibile. +composer diagnose +composer diag # alias + +# Aggiorna Composer all'ultima versione disponibile +composer self-update +composer self # alias +``` + +# Cominciamo ad usare Composer + +Composer memorizza le dipendenze necessarie nel file `composer.json`. +Puoi editare questo file manualmente, ma è meglio che lasci che Composer se ne +occupi per te. + +```sh +# Crea un nuovo progetto nella cartella attuale +composer init +# ti verranno chieste delle domande interrative riguardanti il tuo progetto. +# Puoi evitare di rispondere almeno che tu non stia sviluppando altri progetti +# che che possano dipendere da questo. + +# Se il file composer.json esiste già, scarichera' le dipendenze necessarie +composer install + +# Scarica le dipendenze necessarie per l'ambiente di produzione +composer install --no-dev + +# Aggiunge una dipendenza per l'ambiente di produzione +composer require guzzlehttp/guzzle +# automaticamente selezionera' l'ultima versione, la scarichera' e la aggiungera' +# come dipendenza nell'apposito campo del file composer.json. + +composer require guzzlehttp/guzzle:6.0.* +# scarichera' l'ultima versione disponibile corrispondente al pattern (es. 6.0.2) +# e lo aggiungera' come dipendenza nell'apposito campo del file composer.json. + +composer require --dev phpunit/phpunit:~4.5.0 +# aggiungera' la dipendenza nell'ambiente di sviluppo utilizzando l'ultima versione +# disponibile nel range >=4.5.0 e < 4.6.0. + +composer require-dev phpunit/phpunit:^4.5.0 +# aggiungera' la dipendenza nell'ambiente di sviluppo utilizzando l'ultima versione +# disponibile nel range >=4.5.0 and < 5.0. + +# Per ulteriori dettagli riguardo le versioni, vedi [la documentazione di Composer sulle versioni](https://getcomposer.org/doc/articles/versions.md) per ulteriori dettagli + +# Per vedere quali pacchetti sono installabili e quali sono gia' stati installati +composer show + +# Per vedere solo quali pacchetti sono gia' stati installati +composer show --installed + +# Per trovare una dipendenza con 'mailgun' nel suo nome o nella descrizione. +composer search mailgun +``` + +[Packagist.org](https://packagist.org/) è il repository principale per i pacchetti +di Composer. Cerca qui pacchetti di terze-parti utili per il tuo progetto. + +## `composer.json` vs `composer.lock` + +Il file `composer.json` memorizza la versione che si preferisce per ogni dipendenza, +insieme ad altre informazioni. + +Il file `composer.lock` memorizza quale versione è stata scaricata per ogni +dipendenza. Non editare mai questo file. + +Se includi il file `composer.lock` nella tua repository git, ogni sviluppatore +andra' a installare la versione attualmente utilizzata dal tuo progetto per +ogni dipendenza. Anche quando una nuova versione è stata rilasciata, Composer +andra' a installare la versione registrata nel file lock. + +```sh +# Se vuoi aggiornare tutte le dipendenze all'ultima versione che corrisponde al pattern descritto +composer update + +# Se vuoi scaricare l'ultima versione di una particolare dipendenza: +composer update phpunit/phpunit + +# Se vuoi cambiare la versione di una una dipendenza, potresti dover rimuovere +# quello attualmente selezionato, per poi richiedere quello corretto successivamente, +# attraverso i seguenti comandi: +composer remove --dev phpunit/phpunit +composer require --dev phpunit/phpunit:^5.0 + +``` + +## Autoloader + +Composer crea una classe autoloader che puoi richiamare nella tua applicazione. +Puoi creare instanze delle classi tramite il loro namespace. + +```php +require __DIR__ . '/vendor/autoload.php'; + +$mailgun = new Mailgun\Mailgun("key"); +``` + +### PSR-4 Autoloader + +Puoi aggiungere i tuoi namespace all'autoloader. + +Nel file `composer.json`, aggiungi il campo "autoload": + +```json +{ + "autoload": { + "psr-4": {"Acme\\": "src/"} + } +} +``` +Questo dira' all'autoloader di controllare ogni risorsa che corrisponde al +namespace `\Acme\` all'interno della cartella `src`. + +In alternativa puoi usare [PSR-0, una Classmap o una lista di file da includere](https://getcomposer.org/doc/04-schema.md#autoload). +Inoltre e' possibile anche utilizzare `autoload-dev` dedicato all'ambiente di sviluppo. + +Quando aggiungi o modifichi una chiave, dovrai ricompilare l'autoload attraverso: + +```sh +composer dump-autoload +composer dump # alias + +# Ottimizza i pacchetti PSR0 e PSR4 per essere caricati anche con le classmap. +# Sara' lento, ma migliorera' le performance in produzione. +composer dump-autoload --optimize --no-dev +``` + +# La cache di Composer + +```sh +# Composer utilizzera i pacchetti scaricati anche per i progetti futuri. Per evitare che accada: +composer clear-cache +``` + +# Problemi? + +```sh +composer diagnose +composer self-update +composer clear-cache +``` + +## Argomenti che non sono stati (ancora) discussi in questo tutorial + +* Creare e distribuire pacchetti personali su Packagist.org o altrove +* Pre- e post- script hooks: eseguire operazioni quando vengono eseguiti degli eventi + +### References + +* [Composer - Dependency Manager for PHP](https://getcomposer.org/) +* [Packagist.org](https://packagist.org/) diff --git a/it-it/pyqt-it.html.markdown b/it-it/pyqt-it.html.markdown index 7238dd7b..7b5a98c2 100644 --- a/it-it/pyqt-it.html.markdown +++ b/it-it/pyqt-it.html.markdown @@ -14,12 +14,12 @@ lang: it-it Questo è un adattamento sull'introduzione di C ++ a QT di [Aleksey Kholovchuk] (https://github.com/vortexxx192 ), alcuni degli esempi di codice dovrebbero avere la stessa funzionalità -che avrebbero se fossero fatte usando pyqt! +che avrebbero se fossero fatte usando pyqt! ```python import sys from PyQt4 import QtGui - + def window(): # Crea un oggetto applicazione app = QtGui.QApplication(sys.argv) @@ -47,7 +47,7 @@ if __name__ == '__main__': Per ottenere alcune delle funzionalità più avanzate in **pyqt**, dobbiamo iniziare a cercare di creare elementi aggiuntivi. Qui mostriamo come creare una finestra popup di dialogo, utile per chiedere all'utente di confermare una decisione o fornire informazioni -```Python +```python import sys from PyQt4.QtGui import * from PyQt4.QtCore import * @@ -66,7 +66,7 @@ def window(): w.setWindowTitle("PyQt Dialog") w.show() sys.exit(app.exec_()) - + # Questa funzione dovrebbe creare una finestra di dialogo con un pulsante # che aspetta di essere cliccato e quindi esce dal programma def showdialog(): diff --git a/it-it/python-it.html.markdown b/it-it/python-it.html.markdown index 794e7a70..de7bb0ed 100644 --- a/it-it/python-it.html.markdown +++ b/it-it/python-it.html.markdown @@ -1,98 +1,89 @@ --- -language: python +language: Python filename: learnpython-it.py contributors: - - ["Louie Dinh", "http://ldinh.ca"] - - ["Amin Bandali", "http://aminbandali.com"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] - ["evuez", "http://github.com/evuez"] + - ["Rommel Martinez", "https://ebzzry.io"] translators: + - ["Draio", "http://github.com/Draio/"] - ["Ale46", "http://github.com/Ale46/"] - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] -lang: it-it +lang: it-it --- -Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari -linguaggi esistenti. Mi sono innamorato di Python per la sua chiarezza sintattica. E' sostanzialmente -pseudocodice eseguibile. -Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service] +Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari linguaggi esistenti. Mi sono innamorato di Python per la sua chiarezza sintattica. E' sostanzialmente pseudocodice eseguibile. -Nota: questo articolo è riferito a Python 2.7 in modo specifico, ma dovrebbe andar -bene anche per Python 2.x. Python 2.7 sta raggiungendo il "fine vita", ovvero non sarà -più supportato nel 2020. Quindi è consigliato imparare Python utilizzando Python 3. -Per maggiori informazioni su Python 3.x, dai un'occhiata al [tutorial di Python 3](http://learnxinyminutes.com/docs/python3/). +Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service] -E' possibile anche scrivere codice compatibile sia con Python 2.7 che con Python 3.x, -utilizzando [il modulo `__future__`](https://docs.python.org/2/library/__future__.html) di Python. -Il modulo `__future__` permette di scrivere codice in Python 3, che può essere eseguito -utilizzando Python 2: cosa aspetti a vedere il tutorial di Python 3? +Nota: Questo articolo è riferito a Python 3 in modo specifico. Se volete avete la necessità di utilizzare Python 2.7 potete consultarla [qui](https://learnxinyminutes.com/docs/it-it/python-it/) ```python # I commenti su una sola linea iniziano con un cancelletto + """ Più stringhe possono essere scritte usando tre ", e sono spesso usate - come commenti + come documentazione """ #################################################### ## 1. Tipi di dati primitivi ed Operatori #################################################### -# Hai i numeri +# Ci sono i numeri 3 # => 3 # La matematica è quello che vi aspettereste -1 + 1 # => 2 -8 - 1 # => 7 +1 + 1 # => 2 +8 - 1 # => 7 10 * 2 # => 20 -35 / 5 # => 7 - -# La divisione è un po' complicata. E' una divisione fra interi in cui viene -# restituito in automatico il risultato intero. -5 / 2 # => 2 - -# Per le divisioni con la virgola abbiamo bisogno di parlare delle variabili floats. -2.0 # Questo è un float -11.0 / 4.0 # => 2.75 ahhh...molto meglio +35 / 5 # => 7.0 -# Il risultato di una divisione fra interi troncati positivi e negativi -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # funziona anche per i floats --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 +# Risultato della divisione intera troncata sia in positivo che in negativo +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # works on floats too +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 -# E' possibile importare il modulo "division" (vedi la sezione 6 di questa guida, Moduli) -# per effettuare la divisione normale usando solo '/'. -from __future__ import division -11/4 # => 2.75 ...divisione normale -11//4 # => 2 ...divisione troncata +# Il risultato di una divisione è sempre un numero decimale (float) +10.0 / 3 # => 3.3333333333333335 # Operazione Modulo -7 % 3 # => 1 +7 % 3 # => 1 # Elevamento a potenza (x alla y-esima potenza) -2**4 # => 16 +2**3 # => 8 # Forzare le precedenze con le parentesi (1 + 3) * 2 # => 8 +# I valori booleani sono primitive del linguaggio (nota la maiuscola) +True +False + +# nega con not +not True # => False +not False # => True + # Operatori Booleani # Nota "and" e "or" sono case-sensitive -True and False #=> False -False or True #=> True +True and False # => False +False or True # => True # Note sull'uso di operatori Bool con interi -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True - -# nega con not -not True # => False -not False # => True +# False è 0 e True è 1 +# Non confonderti tra bool(ints) e le operazioni bitwise and/or (&,|) +0 and 2 # => 0 +-5 or 0 # => -5 +0 == False # => True +2 == True # => False +1 == True # => True +-5 != False != True #=> True # Uguaglianza è == 1 == 1 # => True @@ -112,37 +103,46 @@ not False # => True 1 < 2 < 3 # => True 2 < 3 < 2 # => False +# ('is' vs. '==') +# 'is' controlla se due variabili si riferiscono allo stesso oggetto +# '==' controlla se gli oggetti puntati hanno lo stesso valore. +a = [1, 2, 3, 4] # a punta ad una nuova lista [1, 2, 3, 4] +b = a # b punta a ciò a cui punta a +b is a # => True, a e b puntano allo stesso oggeto +b == a # => True, gli oggetti di a e b sono uguali +b = [1, 2, 3, 4] # b punta ad una nuova lista [1, 2, 3, 4] +b is a # => False, a e b non puntano allo stesso oggetto +b == a # => True, gli oggetti di a e b sono uguali + # Le stringhe sono create con " o ' "Questa è una stringa." 'Anche questa è una stringa.' -# Anche le stringhe possono essere sommate! -"Ciao " + "mondo!" # => Ciao mondo!" -# Le stringhe possono essere sommate anche senza '+' -"Ciao " "mondo!" # => Ciao mondo!" - -# ... oppure moltiplicate -"Hello" * 3 # => "HelloHelloHello" +# Anche le stringhe possono essere sommate! Ma cerca di non farlo. +"Hello " + "world!" # => "Hello world!" +# Le stringhe (ma non le variabili contenenti stringhe) possono essere +# sommate anche senza '+' +"Hello " "world!" # => "Hello world!" # Una stringa può essere considerata come una lista di caratteri "Questa è una stringa"[0] # => 'Q' -# Per sapere la lunghezza di una stringa +# Puoi conoscere la lunghezza di una stringa len("Questa è una stringa") # => 20 -# Formattazione delle stringhe con % -# Anche se l'operatore % per le stringe sarà deprecato con Python 3.1, e verrà rimosso -# successivamente, può comunque essere utile sapere come funziona -x = 'mela' -y = 'limone' -z = "La cesta contiene una %s e un %s" % (x,y) +# .format può essere usato per formattare le stringhe, in questo modo: +"{} possono essere {}".format("Le stringhe", "interpolate") # => "Le stringhe possono essere interpolate" + +# Puoi ripetere gli argomenti di formattazione per risparmiare un po' di codice +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" -# Un nuovo modo per fomattare le stringhe è il metodo format. -# Questo metodo è quello consigliato -"{} è un {}".format("Questo", "test") -"{0} possono essere {1}".format("le stringhe", "formattate") -# Puoi usare delle parole chiave se non vuoi contare -"{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="lasagna") +# Puoi usare dei nomi se non vuoi contare gli argomenti +"{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="le lasagne") # => "Bob vuole mangiare le lasagne" + +# Se il tuo codice Python 3 necessita di eseguire codice Python 2.x puoi ancora +# utilizzare il vecchio stile di formattazione: +"%s possono essere %s nel %s modo" % ("Le stringhe", "interpolate", "vecchio") # => "Le stringhe possono essere interpolate nel vecchio modo" # None è un oggetto None # => None @@ -150,57 +150,54 @@ None # => None # Non usare il simbolo di uguaglianza "==" per comparare oggetti a None # Usa "is" invece "etc" is None # => False -None is None # => True - -# L'operatore 'is' testa l'identità di un oggetto. Questo non è -# molto utile quando non hai a che fare con valori primitivi, ma lo è -# quando hai a che fare con oggetti. - -# Qualunque oggetto può essere usato nei test booleani -# I seguenti valori sono considerati falsi: -# - None -# - Lo zero, come qualunque tipo numerico (quindi 0, 0L, 0.0, 0.j) -# - Sequenze vuote (come '', (), []) -# - Contenitori vuoti (tipo {}, set()) -# - Istanze di classi definite dall'utente, che soddisfano certi criteri -# vedi: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__ -# -# Tutti gli altri valori sono considerati veri: la funzione bool() usata su di loro, ritorna True. -bool(0) # => False -bool("") # => False +None is None # => True +# None, 0, e stringhe/liste/dizionari/tuple vuoti vengono considerati +# falsi (False). Tutti gli altri valori sono considerati veri (True). +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False #################################################### ## 2. Variabili e Collections #################################################### -# Python ha una funzione di stampa -print "Sono Python. Piacere di conoscerti!" # => Sono Python. Piacere di conoscerti! +# Python ha una funzione per scrivere (sul tuo schermo) +print("Sono Python. Piacere di conoscerti!") # => Sono Python. Piacere di conoscerti! + +# Di default la funzione print() scrive e va a capo aggiungendo un carattere +# newline alla fine della stringa. È possibile utilizzare l'argomento opzionale +# end per cambiare quest'ultimo carattere aggiunto. +print("Hello, World", end="!") # => Hello, World! # Un modo semplice per ricevere dati in input dalla riga di comando -variabile_stringa_input = raw_input("Inserisci del testo: ") # Ritorna i dati letti come stringa -variabile_input = input("Inserisci del testo: ") # Interpreta i dati letti come codice python -# Attenzione: bisogna stare attenti quando si usa input() -# Nota: In python 3, input() è deprecato, e raw_input() si chiama input() +variabile_stringa_input = input("Inserisci del testo: ") # Restituisce i dati letti come stringa +# Nota: Nelle precedenti vesioni di Python, il metodo input() +# era chiamato raw_input() # Non c'è bisogno di dichiarare una variabile per assegnarle un valore -una_variabile = 5 # Convenzionalmente si usa caratteri_minuscoli_con_underscores -una_variabile # => 5 +# Come convenzione, per i nomi delle variabili, si utilizzano i caratteri +# minuscoli separati, se necessario, da underscore +some_var = 5 +some_var # => 5 # Accedendo ad una variabile non precedentemente assegnata genera un'eccezione. -# Dai un'occhiata al Control Flow per imparare di più su come gestire le eccezioni. -un_altra_variabile # Genera un errore di nome +# Dai un'occhiata al Control Flow per imparare di più su come gestire +# le eccezioni. +some_unknown_var # Genera un errore di nome # if può essere usato come un'espressione -# E' l'equivalente dell'operatore ternario in C +# È l'equivalente dell'operatore ternario in C "yahoo!" if 3 > 2 else 2 # => "yahoo!" -# Liste immagazzinano sequenze +# Le liste immagazzinano sequenze li = [] # Puoi partire con una lista pre-riempita -altra_li = [4, 5, 6] +other_li = [4, 5, 6] -# Aggiungi cose alla fine di una lista con append +# Aggiungere alla fine di una lista con append li.append(1) # li ora è [1] li.append(2) # li ora è [1, 2] li.append(4) # li ora è [1, 2, 4] @@ -212,14 +209,10 @@ li.append(3) # li ora è [1, 2, 4, 3] di nuovo. # Accedi ad una lista come faresti con un array li[0] # => 1 -# Assegna nuovo valore agli indici che sono già stati inizializzati con = -li[0] = 42 -li[0] # => 42 -li[0] = 1 # Nota: è resettato al valore iniziale # Guarda l'ultimo elemento li[-1] # => 3 -# Guardare al di fuori dei limiti è un IndexError +# Guardare al di fuori dei limiti genera un IndexError li[4] # Genera IndexError # Puoi guardare gli intervalli con la sintassi slice (a fetta). @@ -236,14 +229,11 @@ li[::-1] # => [3, 4, 2, 1] # Usa combinazioni per fare slices avanzate # li[inizio:fine:passo] +# Crea una copia (one layer deep copy) usando la sintassi slices +li2 = li[:] # => li2 = [1, 2, 4, 3] ma (li2 is li) risulterà falso. + # Rimuovi arbitrariamente elementi da una lista con "del" del li[2] # li è ora [1, 2, 3] -# Puoi sommare le liste -li + altra_li # => [1, 2, 3, 4, 5, 6] -# Nota: i valori per li ed altra_li non sono modificati. - -# Concatena liste con "extend()" -li.extend(altra_li) # Ora li è [1, 2, 3, 4, 5, 6] # Rimuove la prima occorrenza di un elemento li.remove(2) # Ora li è [1, 3, 4, 5, 6] @@ -252,10 +242,17 @@ li.remove(2) # Emette un ValueError, poichè 2 non è contenuto nella lista # Inserisce un elemento all'indice specificato li.insert(1, 2) # li è di nuovo [1, 2, 3, 4, 5, 6] -# Ritorna l'indice della prima occorrenza dell'elemento fornito + Ritorna l'indice della prima occorrenza dell'elemento fornito li.index(2) # => 1 li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista +# Puoi sommare le liste +# Nota: i valori per li e per other_li non vengono modificati. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Concatena le liste con "extend()" +li.extend(other_li) # Adesso li è [1, 2, 3, 4, 5, 6] + # Controlla l'esistenza di un valore in una lista con "in" 1 in li # => True @@ -263,93 +260,112 @@ li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista len(li) # => 6 -# Tuple sono come le liste ma immutabili. +# Le tuple sono come le liste ma immutabili. tup = (1, 2, 3) -tup[0] # => 1 +tup[0] # => 1 tup[0] = 3 # Genera un TypeError +# Note that a tuple of length one has to have a comma after the last element but +# tuples of other lengths, even zero, do not. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + # Puoi fare tutte queste cose da lista anche sulle tuple -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True # Puoi scompattare le tuple (o liste) in variabili -a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 and c è ora 3 +a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 e c è ora 3 d, e, f = 4, 5, 6 # puoi anche omettere le parentesi # Le tuple sono create di default se non usi le parentesi g = 4, 5, 6 # => (4, 5, 6) # Guarda come è facile scambiare due valori -e, d = d, e # d è ora 5 ed e è ora 4 - +e, d = d, e # d è ora 5 ed e è ora 4 -# Dizionari immagazzinano mappature -empty_dict = {} -# Questo è un dizionario pre-riempito +# I dizionari memorizzano insiemi di dati indicizzati da nomi arbitrari (chiavi) +empty_dict= {} +# Questo è un dizionario pre-caricato filled_dict = {"uno": 1, "due": 2, "tre": 3} -# Accedi ai valori con [] +# Nota: le chiavi dei dizionari devono essere di tipo immutabile. Questo per +# assicurare che le chiavi possano essere convertite in calori hash costanti +# per un risposta più veloce. +invalid_dict = {[1,2,3]: "123"} # => Emette un TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # I valori, invece, possono essere di qualunque tipo + +# Accedi ai valori indicando la chiave tra [] filled_dict["uno"] # => 1 -# Ottieni tutte le chiavi come una lista con "keys()" -filled_dict.keys() # => ["tre", "due", "uno"] +# Puoi ottenere tutte le chiavi di un dizionario con "keys()" +# (come oggetto iterabile). Per averle in formato lista è necessario +# utilizzare list(). # Nota - Nei dizionari l'ordine delle chiavi non è garantito. # Il tuo risultato potrebbe non essere uguale a questo. +list(filled_dict.keys()) # => ["tre", "due", "uno"] -# Ottieni tutt i valori come una lista con "values()" -filled_dict.values() # => [3, 2, 1] -# Nota - Come sopra riguardo l'ordinamento delle chiavi. -# Ottieni tutte le coppie chiave-valore, sotto forma di lista di tuple, utilizzando "items()" -filled_dicts.items() # => [("uno", 1), ("due", 2), ("tre", 3)] +# Puoi ottenere tutti i valori di un dizionario con "values()" +# (come oggetto iterabile). +# Anche in questo caso, er averle in formato lista, è necessario utilizzare list() +# Anche in questo caso, come per le chiavi, l'ordine non è garantito +list(filled_dict.values()) # => [3, 2, 1] # Controlla l'esistenza delle chiavi in un dizionario con "in" "uno" in filled_dict # => True -1 in filled_dict # => False +1 in filled_dict # => False -# Cercando una chiave non esistente è un KeyError +# Cercando una chiave non esistente genera un KeyError filled_dict["quattro"] # KeyError # Usa il metodo "get()" per evitare KeyError -filled_dict.get("uno") # => 1 -filled_dict.get("quattro") # => None +filled_dict.get("uno") # => 1 +filled_dict.get("quattro") # => None # Il metodo get supporta un argomento di default quando il valore è mancante filled_dict.get("uno", 4) # => 1 filled_dict.get("quattro", 4) # => 4 -# nota che filled_dict.get("quattro") è ancora => None -# (get non imposta il valore nel dizionario) -# imposta il valore di una chiave con una sintassi simile alle liste -filled_dict["quattro"] = 4 # ora, filled_dict["quattro"] => 4 -# "setdefault()" aggiunge al dizionario solo se la chiave data non è presente -filled_dict.setdefault("five", 5) # filled_dict["five"] è impostato a 5 -filled_dict.setdefault("five", 6) # filled_dict["five"] è ancora 5 +# "setdefault()" inserisce un valore per una chiave in un dizionario +# solo se la chiave data non è già presente +filled_dict.setdefault("cinque", 5) # filled_dict["cinque"] viene impostato a 5 +filled_dict.setdefault("cinque", 6) # filled_dict["cinque"] rimane 5 +# Aggiungere una coppia chiave->valore a un dizionario +filled_dict.update({"quattro":4}) # => {"uno": 1, "due": 2, "tre": 3, "quattro": 4} +filled_dict["quattro"] = 4 # un altro modo pe aggiungere a un dizionario -# Sets immagazzina ... sets (che sono come le liste, ma non possono contenere doppioni) -empty_set = set() -# Inizializza un "set()" con un po' di valori -some_set = set([1, 2, 2, 3, 4]) # some_set è ora set([1, 2, 3, 4]) +# Rimuovi una chiave da un dizionario con del +del filled_dict["uno"] # Rimuove la chiave "uno" dal dizionario -# l'ordine non è garantito, anche se a volta può sembrare ordinato -another_set = set([4, 3, 2, 2, 1]) # another_set è ora set([1, 2, 3, 4]) +# Da Python 3.5 puoi anche usare ulteriori opzioni di spacchettamento +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} -# Da Python 2.7, {} può essere usato per dichiarare un set -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# I set sono come le liste ma non possono contenere doppioni +empty_set = set() +# Inizializza un "set()" con un dei valori. Sì, sembra un dizionario. +some_set = {1, 1, 2, 2, 3, 4} # set_nuovo è {1, 2, 3, 4} + +# Come le chiavi di un dizionario, gli elementi di un set devono essere +# di tipo immutabile +invalid_set = {[1], 1} # => Genera un "TypeError: unhashable type: 'list'"" +valid_set = {(1,), 1} -# Aggiungere elementi ad un set -filled_set.add(5) # filled_set è ora {1, 2, 3, 4, 5} +# Aggiungere uno o più elementi ad un set +some_set.add(5) # some_set ora è {1, 2, 3, 4, 5} # Fai intersezioni su un set con & other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} +some_set & other_set # => {3, 4, 5} # Fai unioni su set con | -filled_set | other_set # => {1, 2, 3, 4, 5, 6} +some_set | other_set # => {1, 2, 3, 4, 5, 6} # Fai differenze su set con - -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} # Effettua la differenza simmetrica con ^ {1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} @@ -361,65 +377,77 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6} {1, 2} <= {1, 2, 3} # => True # Controlla l'esistenza in un set con in -2 in filled_set # => True -10 in filled_set # => False +2 in some_set # => True +10 in some_set # => False + #################################################### -## 3. Control Flow +## 3. Control Flow e oggetti Iterabili #################################################### -# Dichiariamo una variabile +# Dichiariamo una variabile some_var = 5 # Questo è un controllo if. L'indentazione è molto importante in python! -# stampa "some_var è più piccola di 10" +# Come convenzione si utilizzano quattro spazi, non la tabulazione. +# Il seguente codice stampa "some_var è minore di 10" if some_var > 10: - print "some_var è decisamente più grande di 10." -elif some_var < 10: # Questa clausola elif è opzionale. - print "some_var è più piccola di 10." -else: # Anche questo è opzionale. - print "some_var è precisamente 10." - + print("some_var è maggiore di 10") +elif some_var < 10: # La clausolo elif è opzionale + print("some_var è minore di 10") +else: # Anche else è opzionale + print("some_var è 10.") """ -I cicli for iterano sulle liste -stampa: +I cicli for iterano sulle liste, cioè ripetono un codice per ogni elemento +di una lista. +Il seguente codice scriverà: cane è un mammifero gatto è un mammifero topo è un mammifero """ for animale in ["cane", "gatto", "topo"]: - # Puoi usare {0} per interpolare le stringhe formattate. (Vedi di seguito.) - print "{0} è un mammifero".format(animale) + # Puoi usare format() per interpolare le stringhe formattate. + print("{} è un mammifero".format(animale)) """ -"range(numero)" restituisce una lista di numeri -da zero al numero dato -stampa: +"range(numero)" restituisce una lista di numeri da zero al numero dato +Il seguente codice scriverà: 0 1 2 3 """ for i in range(4): - print i + print(i) """ -"range(lower, upper)" restituisce una lista di numeri -dal più piccolo (lower) al più grande (upper) -stampa: +"range(lower, upper)" restituisce una lista di numeri dal più piccolo (lower) +al più grande (upper). +Il seguente codice scriverà: 4 5 6 7 """ for i in range(4, 8): - print i + print(i) """ +"range(lower, upper, step)" rrestituisce una lista di numeri dal più piccolo +(lower) al più grande (upper), incrementando del valore step. +Se step non è indicato, avrà come valore di default 1. +Il seguente codice scriverà: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) +""" + I cicli while vengono eseguiti finchè una condizione viene a mancare -stampa: +Il seguente codice scriverà: 0 1 2 @@ -427,28 +455,62 @@ stampa: """ x = 0 while x < 4: - print x + print(x) x += 1 # Forma compatta per x = x + 1 -# Gestisci le eccezioni con un blocco try/except - -# Funziona da Python 2.6 in su: +# Gestione delle eccezioni con un blocco try/except try: # Usa "raise" per generare un errore - raise IndexError("Questo è un errore di indice") + raise IndexError("Questo è un IndexError") except IndexError as e: - pass # Pass è solo una non-operazione. Solitamente vorrai fare un recupero. + pass # Pass è solo una non-operazione. Solitamente vorrai rimediare all'errore. except (TypeError, NameError): pass # Eccezioni multiple possono essere gestite tutte insieme, se necessario. -else: # Clausola opzionale al blocco try/except. Deve seguire tutti i blocchi except - print "Tutto ok!" # Viene eseguita solo se il codice dentro try non genera eccezioni +else: # Clausola opzionale al blocco try/except. Deve essere dopo tutti i blocchi except + print("Tutto ok!") # Viene eseguita solo se il codice dentro try non genera eccezioni finally: # Eseguito sempre - print "Possiamo liberare risorse qui" + print("Possiamo liberare risorse qui") -# Invece di try/finally per liberare risorse puoi usare il metodo with +# Se ti serve solo un try/finally, per liberare risorse, puoi usare il metodo with with open("myfile.txt") as f: for line in f: - print line + print(line) + +# In Python qualunque oggetto in grado di essere trattato come una +# sequenza è definito un oggetto Iterable (itarabile). +# L'oggetto restituito da una funzione range è un iterabile. + +filled_dict = {"uno": 1, "due": 2, "tre": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['uno', 'due', 'tre']). +# Questo è un oggetto che implementa la nostra interfaccia Iterable. + +# È possibile utilizzarlo con i loop: +for i in our_iterable: + print(i) # Scrive uno, due, tre + +# Tuttavia non possiamo recuperarne i valori tramite indice. +our_iterable[1] # Genera un TypeError + +# Un oggetto iterabile è in grado di generare un iteratore +our_iterator = iter(our_iterable) + +# L'iteratore è un oggetto che ricorda il suo stato mentro lo si "attraversa" +# Possiamo accedere al successivo elemento con "next()". +next(our_iterator) # => "uno" + +# Mantiene il suo stato mentro eseguiamo l'iterazione +next(our_iterator) # => "due" +next(our_iterator) # => "tre" + +# Dopo che un iteratore ha restituito tutti i suoi dati, genera +# un'eccezione StopIteration +next(our_iterator) # Raises StopIteration + +# Puoi prendere tutti gli elementi di un iteratore utilizzando list(). +list(filled_dict.keys()) # => Returns ["one", "two", "three"] + + #################################################### ## 4. Funzioni @@ -456,23 +518,20 @@ with open("myfile.txt") as f: # Usa "def" per creare nuove funzioni def aggiungi(x, y): - print "x è {0} e y è {1}".format(x, y) - return x + y # Restituisce valori con il metodo return + print("x è {} e y è {}".format(x, y)) // Scrive i valori formattati in una stringa + return x + y # Restituisce la somma dei valori con il metodo return # Chiamare funzioni con parametri -aggiungi(5, 6) # => stampa "x è 5 e y è 6" e restituisce 11 +aggiungi(5, 6) # => scrive "x è 5 e y è 6" e restituisce 11 # Un altro modo per chiamare funzioni è con parole chiave come argomenti -aggiungi(y=6, x=5) # Le parole chiave come argomenti possono arrivare in ogni ordine. +aggiungi(y=6, x=5) # In questo modo non è necessario rispettare l'ordine degli argomenti - -# Puoi definire funzioni che accettano un numero variabile di argomenti posizionali -# che verranno interpretati come tuple usando il * +# Puoi definire funzioni che accettano un numero non definito di argomenti def varargs(*args): return args -varargs(1, 2, 3) # => (1, 2, 3) - +varargs(1, 2, 3) # => (1, 2, 3) # Puoi definire funzioni che accettano un numero variabile di parole chiave # come argomento, che saranno interpretati come un dizionario usando ** @@ -485,8 +544,8 @@ keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} # Puoi farle entrambi in una volta, se ti va def all_the_args(*args, **kwargs): - print args - print kwargs + print(args) + print(kwargs) """ all_the_args(1, 2, a=3, b=4) stampa: (1, 2) @@ -494,38 +553,44 @@ all_the_args(1, 2, a=3, b=4) stampa: """ # Quando chiami funzioni, puoi fare l'opposto di args/kwargs! -# Usa * per sviluppare gli argomenti posizionale ed usa ** per espandere gli argomenti parola chiave +# Usa * per sviluppare gli argomenti posizionale ed usa ** per +# espandere gli argomenti parola chiave args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalente a foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivalente a foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) - -# puoi passare args e kwargs insieme alle altre funzioni che accettano args/kwargs -# sviluppandoli, rispettivamente, con * e ** -def pass_all_the_args(*args, **kwargs): - all_the_args(*args, **kwargs) - print varargs(*args) - print keyword_args(**kwargs) - -# Funzioni Scope +all_the_args(*args) # equivalente a foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalente a foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) + + +# Restituire valori multipli (with tuple assignments) +def swap(x, y): + return y, x # Restituisce valori multipli come tupla senza parentesi + # (Nota: le parentesi sono state escluse ma possono essere messe) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Le parentesi sono state escluse ma possono essere incluse. + +# Funzioni - Visibilità delle variabili (variable scope) x = 5 def set_x(num): - # La variabile locale x non è uguale alla variabile globale x - x = num # => 43 - print x # => 43 + # La variabile locale x non è la variabile globale x + x = num # => 43 + print(x) # => 43 def set_global_x(num): global x - print x # => 5 - x = num # la variabile globable x è ora 6 - print x # => 6 + print(x) # => 5 + x = num # la variabile globable x è ora 6 + print(x) # => 6 set_x(43) set_global_x(6) -# Python ha funzioni di prima classe + +# Python ha "first class functions" def create_adder(x): def adder(y): return x + y @@ -535,204 +600,381 @@ add_10 = create_adder(10) add_10(3) # => 13 # Ci sono anche funzioni anonime -(lambda x: x > 2)(3) # => True -(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 -# Esse sono incluse in funzioni di alto livello -map(add_10, [1, 2, 3]) # => [11, 12, 13] -map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] +# È possibile creare "mappe" e "filtri" +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] -# Possiamo usare la comprensione delle liste per mappe e filtri -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] +# Possiamo usare le "list comprehensions" per mappe e filtri +# Le "list comprehensions" memorizzano l'output come una lista che può essere +# di per sé una lista annidata +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] # Puoi fare anche la comprensione di set e dizionari -{x for x in 'abcddeef' if x in 'abc'} # => {'d', 'e', 'f'} +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} {x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} #################################################### -## 5. Classi +## 5. Modules +#################################################### + +# Puoi importare moduli +import math +print(math.sqrt(16)) # => 4.0 + +# Puoi ottenere specifiche funzione da un modulo +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# Puoi importare tutte le funzioni da un modulo +# Attenzione: questo non è raccomandato +from math import * + +# Puoi abbreviare i nomi dei moduli +import math as m +math.sqrt(16) == m.sqrt(16) # => True + + +# I moduli di Python sono normali file python. Ne puoi +# scrivere di tuoi ed importarli. Il nome del modulo +# è lo stesso del nome del file. + +# Potete scoprire quali funzioni e attributi +# sono definiti in un modulo +import math +dir(math) + +# Se nella cartella corrente hai uno script chiamato math.py, +# Python caricherà quello invece del modulo math. +# Questo succede perchè la cartella corrente ha priorità +# sulle librerie standard di Python + +# Se hai uno script Python chiamato math.py nella stessa +# cartella del tua script, Python caricherà quello al posto del +# comune modulo math. +# Questo accade perché la cartella locale ha la priorità +# sulle librerie built-in di Python. + + +#################################################### +## 6. Classes #################################################### -# Usiamo una sottoclasse da un oggetto per avere una classe. -class Human(object): +# Usiamo l'istruzione "class" per creare una classe +class Human: - # Un attributo della classe. E' condiviso da tutte le istanze delle classe + # Un attributo della classe. E' condiviso tra tutte le istanze delle classe species = "H. sapiens" - # Costruttore base, richiamato quando la classe viene inizializzata. - # Si noti che il doppio leading e gli underscore finali denotano oggetti - # o attributi che sono usati da python ma che vivono nello spazio dei nome controllato - # dall'utente. Non dovresti usare nomi di questo genere. + # Si noti che i doppi underscore iniziali e finali denotano gli oggetti o + # attributi utilizzati da Python ma che vivono nel namespace controllato + # dall'utente + # Metodi, oggetti o attributi come: __init__, __str__, __repr__, etc. sono + # chiamati metodi speciali (o talvolta chiamati "dunder methods"). + # Non dovresti inventare tali nomi da solo. + def __init__(self, name): # Assegna l'argomento all'attributo name dell'istanza self.name = name # Inizializza una proprietà - self.age = 0 + self._age = 0 # Un metodo dell'istanza. Tutti i metodi prendo "self" come primo argomento def say(self, msg): - return "{0}: {1}".format(self.name, msg) + print("{name}: {message}".format(name=self.name, message=msg)) + + # Un altro metodo dell'istanza + def sing(self): + return 'yo... yo... microphone check... one two... one two...' # Un metodo della classe è condiviso fra tutte le istanze - # Sono chiamate con la classe chiamante come primo argomento + # Sono chiamati con la classe chiamante come primo argomento @classmethod def get_species(cls): return cls.species - # Un metodo statico è chiamato senza una classe od una istanza di riferimento + # Un metodo statico è chiamato senza classe o istanza di riferimento @staticmethod def grunt(): return "*grunt*" - # Una proprietà è come un metodo getter. - # Trasforma il metodo age() in un attributo in sola lettura, che ha lo stesso nome + # Una property è come un metodo getter. + # Trasforma il metodo age() in un attributo in sola lettura, che ha + # lo stesso nome + # In Python non c'è bisogno di scrivere futili getter e setter. @property def age(self): return self._age - # Questo metodo permette di modificare la proprietà + # Questo metodo permette di modificare una property @age.setter def age(self, age): self._age = age - # Questo metodo permette di cancellare la proprietà + # Questo metodo permette di cancellare una property @age.deleter def age(self): del self._age -# Instanziare una classe -i = Human(name="Ian") -print i.say("hi") # stampa "Ian: hi" +# Quando l'interprete Python legge un sorgente esegue tutto il suo codice. +# Questo controllo su __name__ assicura che questo blocco di codice venga +# eseguito solo quando questo modulo è il programma principale. + +if __name__ == '__main__': + # Crea un'istanza della classe + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i e j sono istanze del tipo Human, o in altre parole sono oggetti Human + + # Chiama un metodo della classe + i.say(i.get_species()) # "Ian: H. sapiens" + # Cambia l'attributo condiviso + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # Chiama un metodo statico + print(Human.grunt()) # => "*grunt*" + + # Non è possibile chiamare il metodo statico con l'istanza dell'oggetto + # poiché i.grunt() metterà automaticamente "self" (l'oggetto i) + # come argomento + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given + + # Aggiorna la property (age) di questa istanza + i.age = 42 + # Leggi la property + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # Cancella la property + del i.age + i.age # => questo genererà un AttributeError -j = Human("Joel") -print j.say("hello") # stampa "Joel: hello" -# Chiamare metodi della classe -i.get_species() # => "H. sapiens" +#################################################### +## 6.1 Ereditarietà (Inheritance) +#################################################### -# Cambiare l'attributo condiviso -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" +# L'ereditarietà consente di definire nuove classi figlio che ereditano metodi e +# variabili dalla loro classe genitore. -# Chiamare il metodo condiviso -Human.grunt() # => "*grunt*" +# Usando la classe Human definita sopra come classe base o genitore, possiamo +# definire una classe figlia, Superhero, che erediterà le variabili di classe +# come "species", "name" e "age", così come i metodi, come "sing" e "grunt", +# dalla classe Human, ma potrà anche avere le sue proprietà uniche. -# Aggiorna la proprietà -i.age = 42 +# Per importare le funzioni da altri file usa il seguente formato +# from "nomefile-senza-estensione" import "funzione-o-classe" -# Ritorna il valore della proprietà -i.age # => 42 +from human import Human -# Cancella la proprietà -del i.age -i.age # => Emette un AttributeError +# Specificare le classi genitore come parametri della definizione della classe +class Superhero(Human): + # Se la classe figlio deve ereditare tutte le definizioni del genitore + # senza alcuna modifica, puoi semplicemente usare la parola chiave "pass" + # (e nient'altro) -#################################################### -## 6. Moduli -#################################################### + #Le classi figlio possono sovrascrivere gli attributi dei loro genitori + species = 'Superhuman' -# Puoi importare moduli -import math -print math.sqrt(16) # => 4.0 + # Le classi figlie ereditano automaticamente il costruttore della classe + # genitore, inclusi i suoi argomenti, ma possono anche definire ulteriori + # argomenti o definizioni e sovrascrivere i suoi metodi (compreso il + # costruttore della classe). + # Questo costruttore eredita l'argomento "nome" dalla classe "Human" e + # aggiunge gli argomenti "superpowers" e "movie": -# Puoi ottenere specifiche funzione da un modulo -from math import ceil, floor -print ceil(3.7) # => 4.0 -print floor(3.7) # => 3.0 + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): -# Puoi importare tutte le funzioni da un modulo -# Attenzione: questo non è raccomandato -from math import * + # aggiungi ulteriori attributi della classe + self.fictional = True + self.movie = movie + self.superpowers = superpowers -# Puoi abbreviare i nomi dei moduli -import math as m -math.sqrt(16) == m.sqrt(16) # => True -# puoi anche verificare che le funzioni sono equivalenti -from math import sqrt -math.sqrt == m.sqrt == sqrt # => True + # La funzione "super" ti consente di accedere ai metodi della classe + # genitore che sono stati sovrascritti dalla classe figlia, + # in questo caso il metodo __init__. + # Il seguente codice esegue il costruttore della classe genitore: + super().__init__(name) -# I moduli di Python sono normali file python. Ne puoi -# scrivere di tuoi ed importarli. Il nome del modulo -# è lo stesso del nome del file. + # Sovrascrivere il metodo "sing" + def sing(self): + return 'Dun, dun, DUN!' -# Potete scoprire quali funzioni e attributi -# definiscono un modulo -import math -dir(math) + # Aggiungi un ulteriore metodo dell'istanza + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) -# Se nella cartella corrente hai uno script chiamato math.py, -# Python caricherà quello invece del modulo math. -# Questo succede perchè la cartella corrente ha priorità -# sulle librerie standard di Python +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # Controllo del tipo di istanza + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + + # Ottieni il "Method Resolution search Order" usato sia da getattr () + # che da super (). Questo attributo è dinamico e può essere aggiornato + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) + + # Esegui il metodo principale ma utilizza il proprio attributo di classe + print(sup.get_species()) # => Superhuman + + # Esegui un metodo che è stato sovrascritto + print(sup.sing()) # => Dun, dun, DUN! + + # Esegui un metodo di Human + sup.say('Spoon') # => Tick: Spoon + + # Esegui un metodo che esiste solo in Superhero + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # Attributo di classe ereditato + sup.age = 31 + print(sup.age) # => 31 + + # Attributo che esiste solo in Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) #################################################### -## 7. Avanzate +## 6.2 Ereditarietà multipla #################################################### -# Generatori -# Un generatore appunto "genera" valori solo quando vengono richiesti, -# invece di memorizzarli tutti subito fin dall'inizio +# Un'altra definizione di classe +# bat.py +class Bat: -# Il metodo seguente (che NON è un generatore) raddoppia tutti i valori e li memorizza -# dentro `double_arr`. Se gli oggetti iterabili sono grandi, il vettore risultato -# potrebbe diventare enorme! -def double_numbers(iterable): - double_arr = [] - for i in iterable: - double_arr.append(i + i) + species = 'Baty' -# Eseguendo il seguente codice, noi andiamo a raddoppiare prima tutti i valori, e poi -# li ritorniamo tutti e andiamo a controllare la condizione -for value in double_numbers(range(1000000)): # `test_senza_generatore` - print value - if value > 5: - break + def __init__(self, can_fly=True): + self.fly = can_fly + + # Questa classe ha anche un metodo "say" + def say(self, msg): + msg = '... ... ...' + return msg + + # E anche un suo metodo personale + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + +# Definizione di classe che eredita da Superhero e Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Definisci Batman come classe figlia che eredita sia da Superhero che da Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # In genere per ereditare gli attributi devi chiamare super: + # super(Batman, self).__init__(*args, **kwargs) + # Ma qui abbiamo a che fare con l'ereditarietà multipla, e super() + # funziona solo con la successiva classe nell'elenco MRO. + # Quindi, invece, chiamiamo esplicitamente __init__ per tutti gli + # antenati. L'uso di *args e **kwargs consente di passare in modo + # pulito gli argomenti, con ciascun genitore che "sbuccia un + # livello della cipolla". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # sovrascrivere il valore per l'attributo name + self.name = 'Sad Affleck' -# Invece, potremmo usare un generatore per "generare" il valore raddoppiato non -# appena viene richiesto -def double_numbers_generator(iterable): + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # Ottieni il "Method Resolution search Order" utilizzato da getattr() e super(). + # Questo attributo è dinamico e può essere aggiornato + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # Esegui il metodo del genitore ma utilizza il proprio attributo di classe + print(sup.get_species()) # => Superhuman + + # Esegui un metodo che è stato sovrascritto + print(sup.sing()) # => nan nan nan nan nan batman! + + # Esegui un metodo da Human, perché l'ordine di ereditarietà è importante + sup.say('I agree') # => Sad Affleck: I agree + + # Esegui un metodo che esiste solo nel 2o antenato + print(sup.sonar()) # => ))) ... ((( + + # Attributo di classe ereditato + sup.age = 100 + print(sup.age) # => 100 + + # Attributo ereditato dal secondo antenato il cui valore predefinito + # è stato ignorato. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + + +#################################################### +## 7. Advanced +#################################################### + +# I generatori ti aiutano a creare codice pigro (lazy code). +# Codice che darà un risultato solo quando sarà "valutato" +def double_numbers(iterable): for i in iterable: yield i + i -# Utilizzando lo stesso test di prima, stavolta però con un generatore, ci permette -# di iterare sui valori e raddoppiarli uno alla volta, non appena vengono richiesti dalla -# logica del programma. Per questo, non appena troviamo un valore > 5, usciamo dal ciclo senza -# bisogno di raddoppiare la maggior parte dei valori del range (MOLTO PIU VELOCE!) -for value in double_numbers_generator(xrange(1000000)): # `test_generatore` - print value - if value > 5: +# I generatori sono efficienti in termini di memoria perché caricano +# solo i dati necessari per elaborare il valore successivo nell'iterabile. +# Ciò consente loro di eseguire operazioni su intervalli di valori +# altrimenti proibitivi. +# NOTA: `range` sostituisce` xrange` in Python 3. +for i in double_numbers(range(1, 900000000)): # `range` is a generator. + print(i) + if i >= 30: break -# Nota: hai notato l'uso di `range` in `test_senza_generatore` e `xrange` in `test_generatore`? -# Proprio come `double_numbers_generator` è la versione col generatore di `double_numbers` -# Abbiamo `xrange` come versione col generatore di `range` -# `range` ritorna un array di 1000000 elementi -# `xrange` invece genera 1000000 valori quando lo richiediamo/iteriamo su di essi - -# Allo stesso modo della comprensione delle liste, puoi creare la comprensione -# dei generatori. +# Proprio come è possibile creare una "list comprehension", è possibile +# creare anche delle "generator comprehensions". values = (-x for x in [1,2,3,4,5]) for x in values: - print(x) # stampa -1 -2 -3 -4 -5 + print(x) # prints -1 -2 -3 -4 -5 to console/terminal -# Puoi anche fare il cast diretto di una comprensione di generatori ad una lista. +# Puoi anche trasmettere una "generator comprehensions" direttamente +# ad un elenco. values = (-x for x in [1,2,3,4,5]) gen_to_list = list(values) print(gen_to_list) # => [-1, -2, -3, -4, -5] # Decoratori -# in questo esempio beg include say -# Beg chiamerà say. Se say_please è True allora cambierà il messaggio -# ritornato +# In questo esempio "beg" avvolge/wrappa "say". +# Se say_please è True, cambierà il messaggio restituito. from functools import wraps def beg(target_function): @@ -752,8 +994,8 @@ def say(say_please=False): return msg, say_please -print say() # Puoi comprarmi una birra? -print say(say_please=True) # Puoi comprarmi una birra? Per favore! Sono povero :( +print(say()) # Puoi comprarmi una birra? +print(say(say_please=True)) # Puoi comprarmi una birra? Per favore! Sono povero :( ``` ## Pronto per qualcosa di più? @@ -761,18 +1003,14 @@ print say(say_please=True) # Puoi comprarmi una birra? Per favore! Sono povero ### Gratis Online * [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [Python Course](http://www.python-course.eu/index.php) * [First Steps With Python](https://realpython.com/learn/python-first-steps/) -* [LearnPython](http://www.learnpython.org/) -* [Fullstack Python](https://www.fullstackpython.com/) - -### Libri cartacei - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](http://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) diff --git a/it-it/python3-it.html.markdown b/it-it/python3-it.html.markdown deleted file mode 100644 index 04f78cff..00000000 --- a/it-it/python3-it.html.markdown +++ /dev/null @@ -1,1016 +0,0 @@ ---- -language: python3 -filename: learnpython3-it.py -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] - - ["Steven Basart", "http://github.com/xksteven"] - - ["Andre Polykanine", "https://github.com/Oire"] - - ["Zachary Ferguson", "http://github.com/zfergus2"] - - ["evuez", "http://github.com/evuez"] - - ["Rommel Martinez", "https://ebzzry.io"] -translators: - - ["Draio", "http://github.com/Draio/"] - - ["Ale46", "http://github.com/Ale46/"] - - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] -lang: it-it ---- - -Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari linguaggi esistenti. Mi sono innamorato di Python per la sua chiarezza sintattica. E' sostanzialmente pseudocodice eseguibile. - -Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service] - -Nota: Questo articolo è riferito a Python 3 in modo specifico. Se volete avete la necessità di utilizzare Python 2.7 potete consultarla [qui](https://learnxinyminutes.com/docs/it-it/python-it/) - -```python - -# I commenti su una sola linea iniziano con un cancelletto - - -""" Più stringhe possono essere scritte - usando tre ", e sono spesso usate - come documentazione -""" - -#################################################### -## 1. Tipi di dati primitivi ed Operatori -#################################################### - -# Ci sono i numeri -3 # => 3 - -# La matematica è quello che vi aspettereste -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 -35 / 5 # => 7.0 - -# Risultato della divisione intera troncata sia in positivo che in negativo -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# Il risultato di una divisione è sempre un numero decimale (float) -10.0 / 3 # => 3.3333333333333335 - -# Operazione Modulo -7 % 3 # => 1 - -# Elevamento a potenza (x alla y-esima potenza) -2**3 # => 8 - -# Forzare le precedenze con le parentesi -(1 + 3) * 2 # => 8 - -# I valori booleani sono primitive del linguaggio (nota la maiuscola) -True -False - -# nega con not -not True # => False -not False # => True - -# Operatori Booleani -# Nota "and" e "or" sono case-sensitive -True and False # => False -False or True # => True - -# Note sull'uso di operatori Bool con interi -# False è 0 e True è 1 -# Non confonderti tra bool(ints) e le operazioni bitwise and/or (&,|) -0 and 2 # => 0 --5 or 0 # => -5 -0 == False # => True -2 == True # => False -1 == True # => True --5 != False != True #=> True - -# Uguaglianza è == -1 == 1 # => True -2 == 1 # => False - -# Disuguaglianza è != -1 != 1 # => False -2 != 1 # => True - -# Altri confronti -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# I confronti possono essere concatenati! -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# ('is' vs. '==') -# 'is' controlla se due variabili si riferiscono allo stesso oggetto -# '==' controlla se gli oggetti puntati hanno lo stesso valore. -a = [1, 2, 3, 4] # a punta ad una nuova lista [1, 2, 3, 4] -b = a # b punta a ciò a cui punta a -b is a # => True, a e b puntano allo stesso oggeto -b == a # => True, gli oggetti di a e b sono uguali -b = [1, 2, 3, 4] # b punta ad una nuova lista [1, 2, 3, 4] -b is a # => False, a e b non puntano allo stesso oggetto -b == a # => True, gli oggetti di a e b sono uguali - -# Le stringhe sono create con " o ' -"Questa è una stringa." -'Anche questa è una stringa.' - -# Anche le stringhe possono essere sommate! Ma cerca di non farlo. -"Hello " + "world!" # => "Hello world!" -# Le stringhe (ma non le variabili contenenti stringhe) possono essere -# sommate anche senza '+' -"Hello " "world!" # => "Hello world!" - -# Una stringa può essere considerata come una lista di caratteri -"Questa è una stringa"[0] # => 'Q' - -# Puoi conoscere la lunghezza di una stringa -len("Questa è una stringa") # => 20 - -# .format può essere usato per formattare le stringhe, in questo modo: -"{} possono essere {}".format("Le stringhe", "interpolate") # => "Le stringhe possono essere interpolate" - -# Puoi ripetere gli argomenti di formattazione per risparmiare un po' di codice -"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") -# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" - -# Puoi usare dei nomi se non vuoi contare gli argomenti -"{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="le lasagne") # => "Bob vuole mangiare le lasagne" - -# Se il tuo codice Python 3 necessita di eseguire codice Python 2.x puoi ancora -# utilizzare il vecchio stile di formattazione: -"%s possono essere %s nel %s modo" % ("Le stringhe", "interpolate", "vecchio") # => "Le stringhe possono essere interpolate nel vecchio modo" - -# None è un oggetto -None # => None - -# Non usare il simbolo di uguaglianza "==" per comparare oggetti a None -# Usa "is" invece -"etc" is None # => False -None is None # => True - -# None, 0, e stringhe/liste/dizionari/tuple vuoti vengono considerati -# falsi (False). Tutti gli altri valori sono considerati veri (True). -bool(0) # => False -bool("") # => False -bool([]) # => False -bool({}) # => False -bool(()) # => False - -#################################################### -## 2. Variabili e Collections -#################################################### - -# Python ha una funzione per scrivere (sul tuo schermo) -print("Sono Python. Piacere di conoscerti!") # => Sono Python. Piacere di conoscerti! - -# Di default la funzione print() scrive e va a capo aggiungendo un carattere -# newline alla fine della stringa. È possibile utilizzare l'argomento opzionale -# end per cambiare quest'ultimo carattere aggiunto. -print("Hello, World", end="!") # => Hello, World! - -# Un modo semplice per ricevere dati in input dalla riga di comando -variabile_stringa_input = input("Inserisci del testo: ") # Restituisce i dati letti come stringa -# Nota: Nelle precedenti vesioni di Python, il metodo input() -# era chiamato raw_input() - -# Non c'è bisogno di dichiarare una variabile per assegnarle un valore -# Come convenzione, per i nomi delle variabili, si utilizzano i caratteri -# minuscoli separati, se necessario, da underscore -some_var = 5 -some_var # => 5 - -# Accedendo ad una variabile non precedentemente assegnata genera un'eccezione. -# Dai un'occhiata al Control Flow per imparare di più su come gestire -# le eccezioni. -some_unknown_var # Genera un errore di nome - -# if può essere usato come un'espressione -# È l'equivalente dell'operatore ternario in C -"yahoo!" if 3 > 2 else 2 # => "yahoo!" - -# Le liste immagazzinano sequenze -li = [] -# Puoi partire con una lista pre-riempita -other_li = [4, 5, 6] - -# Aggiungere alla fine di una lista con append -li.append(1) # li ora è [1] -li.append(2) # li ora è [1, 2] -li.append(4) # li ora è [1, 2, 4] -li.append(3) # li ora è [1, 2, 4, 3] -# Rimuovi dalla fine della lista con pop -li.pop() # => 3 e li ora è [1, 2, 4] -# Rimettiamolo a posto -li.append(3) # li ora è [1, 2, 4, 3] di nuovo. - -# Accedi ad una lista come faresti con un array -li[0] # => 1 -# Guarda l'ultimo elemento -li[-1] # => 3 - -# Guardare al di fuori dei limiti genera un IndexError -li[4] # Genera IndexError - -# Puoi guardare gli intervalli con la sintassi slice (a fetta). -# (E' un intervallo chiuso/aperto per voi tipi matematici.) -li[1:3] # => [2, 4] -# Ometti l'inizio -li[2:] # => [4, 3] -# Ometti la fine -li[:3] # => [1, 2, 4] -# Seleziona ogni seconda voce -li[::2] # =>[1, 4] -# Copia al contrario della lista -li[::-1] # => [3, 4, 2, 1] -# Usa combinazioni per fare slices avanzate -# li[inizio:fine:passo] - -# Crea una copia (one layer deep copy) usando la sintassi slices -li2 = li[:] # => li2 = [1, 2, 4, 3] ma (li2 is li) risulterà falso. - -# Rimuovi arbitrariamente elementi da una lista con "del" -del li[2] # li è ora [1, 2, 3] - -# Rimuove la prima occorrenza di un elemento -li.remove(2) # Ora li è [1, 3, 4, 5, 6] -li.remove(2) # Emette un ValueError, poichè 2 non è contenuto nella lista - -# Inserisce un elemento all'indice specificato -li.insert(1, 2) # li è di nuovo [1, 2, 3, 4, 5, 6] - - Ritorna l'indice della prima occorrenza dell'elemento fornito -li.index(2) # => 1 -li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista - -# Puoi sommare le liste -# Nota: i valori per li e per other_li non vengono modificati. -li + other_li # => [1, 2, 3, 4, 5, 6] - -# Concatena le liste con "extend()" -li.extend(other_li) # Adesso li è [1, 2, 3, 4, 5, 6] - -# Controlla l'esistenza di un valore in una lista con "in" -1 in li # => True - -# Esamina la lunghezza con "len()" -len(li) # => 6 - - -# Le tuple sono come le liste ma immutabili. -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # Genera un TypeError - -# Note that a tuple of length one has to have a comma after the last element but -# tuples of other lengths, even zero, do not. -type((1)) # => <class 'int'> -type((1,)) # => <class 'tuple'> -type(()) # => <class 'tuple'> - -# Puoi fare tutte queste cose da lista anche sulle tuple -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True - -# Puoi scompattare le tuple (o liste) in variabili -a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 e c è ora 3 -d, e, f = 4, 5, 6 # puoi anche omettere le parentesi -# Le tuple sono create di default se non usi le parentesi -g = 4, 5, 6 # => (4, 5, 6) -# Guarda come è facile scambiare due valori -e, d = d, e # d è ora 5 ed e è ora 4 - -# I dizionari memorizzano insiemi di dati indicizzati da nomi arbitrari (chiavi) -empty_dict= {} -# Questo è un dizionario pre-caricato -filled_dict = {"uno": 1, "due": 2, "tre": 3} - -# Nota: le chiavi dei dizionari devono essere di tipo immutabile. Questo per -# assicurare che le chiavi possano essere convertite in calori hash costanti -# per un risposta più veloce. -invalid_dict = {[1,2,3]: "123"} # => Emette un TypeError: unhashable type: 'list' -valid_dict = {(1,2,3):[1,2,3]} # I valori, invece, possono essere di qualunque tipo - -# Accedi ai valori indicando la chiave tra [] -filled_dict["uno"] # => 1 - -# Puoi ottenere tutte le chiavi di un dizionario con "keys()" -# (come oggetto iterabile). Per averle in formato lista è necessario -# utilizzare list(). -# Nota - Nei dizionari l'ordine delle chiavi non è garantito. -# Il tuo risultato potrebbe non essere uguale a questo. -list(filled_dict.keys()) # => ["tre", "due", "uno"] - - -# Puoi ottenere tutti i valori di un dizionario con "values()" -# (come oggetto iterabile). -# Anche in questo caso, er averle in formato lista, è necessario utilizzare list() -# Anche in questo caso, come per le chiavi, l'ordine non è garantito -list(filled_dict.values()) # => [3, 2, 1] - -# Controlla l'esistenza delle chiavi in un dizionario con "in" -"uno" in filled_dict # => True -1 in filled_dict # => False - -# Cercando una chiave non esistente genera un KeyError -filled_dict["quattro"] # KeyError - -# Usa il metodo "get()" per evitare KeyError -filled_dict.get("uno") # => 1 -filled_dict.get("quattro") # => None -# Il metodo get supporta un argomento di default quando il valore è mancante -filled_dict.get("uno", 4) # => 1 -filled_dict.get("quattro", 4) # => 4 - - -# "setdefault()" inserisce un valore per una chiave in un dizionario -# solo se la chiave data non è già presente -filled_dict.setdefault("cinque", 5) # filled_dict["cinque"] viene impostato a 5 -filled_dict.setdefault("cinque", 6) # filled_dict["cinque"] rimane 5 - -# Aggiungere una coppia chiave->valore a un dizionario -filled_dict.update({"quattro":4}) # => {"uno": 1, "due": 2, "tre": 3, "quattro": 4} -filled_dict["quattro"] = 4 # un altro modo pe aggiungere a un dizionario - -# Rimuovi una chiave da un dizionario con del -del filled_dict["uno"] # Rimuove la chiave "uno" dal dizionario - -# Da Python 3.5 puoi anche usare ulteriori opzioni di spacchettamento -{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} -{'a': 1, **{'a': 2}} # => {'a': 2} - -# I set sono come le liste ma non possono contenere doppioni -empty_set = set() -# Inizializza un "set()" con un dei valori. Sì, sembra un dizionario. -some_set = {1, 1, 2, 2, 3, 4} # set_nuovo è {1, 2, 3, 4} - -# Come le chiavi di un dizionario, gli elementi di un set devono essere -# di tipo immutabile -invalid_set = {[1], 1} # => Genera un "TypeError: unhashable type: 'list'"" -valid_set = {(1,), 1} - -# Aggiungere uno o più elementi ad un set -some_set.add(5) # some_set ora è {1, 2, 3, 4, 5} - -# Fai intersezioni su un set con & -other_set = {3, 4, 5, 6} -some_set & other_set # => {3, 4, 5} - -# Fai unioni su set con | -some_set | other_set # => {1, 2, 3, 4, 5, 6} - -# Fai differenze su set con - -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} - -# Effettua la differenza simmetrica con ^ -{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} - -# Controlla se il set a sinistra contiene quello a destra -{1, 2} >= {1, 2, 3} # => False - -# Controlla se il set a sinistra è un sottoinsieme di quello a destra -{1, 2} <= {1, 2, 3} # => True - -# Controlla l'esistenza in un set con in -2 in some_set # => True -10 in some_set # => False - - - -#################################################### -## 3. Control Flow e oggetti Iterabili -#################################################### - -# Dichiariamo una variabile -some_var = 5 - -# Questo è un controllo if. L'indentazione è molto importante in python! -# Come convenzione si utilizzano quattro spazi, non la tabulazione. -# Il seguente codice stampa "some_var è minore di 10" -if some_var > 10: - print("some_var è maggiore di 10") -elif some_var < 10: # La clausolo elif è opzionale - print("some_var è minore di 10") -else: # Anche else è opzionale - print("some_var è 10.") - -""" -I cicli for iterano sulle liste, cioè ripetono un codice per ogni elemento -di una lista. -Il seguente codice scriverà: - cane è un mammifero - gatto è un mammifero - topo è un mammifero -""" -for animale in ["cane", "gatto", "topo"]: - # Puoi usare format() per interpolare le stringhe formattate. - print("{} è un mammifero".format(animale)) - -""" -"range(numero)" restituisce una lista di numeri da zero al numero dato -Il seguente codice scriverà: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -"range(lower, upper)" restituisce una lista di numeri dal più piccolo (lower) -al più grande (upper). -Il seguente codice scriverà: - 4 - 5 - 6 - 7 -""" -for i in range(4, 8): - print(i) - -""" -"range(lower, upper, step)" rrestituisce una lista di numeri dal più piccolo -(lower) al più grande (upper), incrementando del valore step. -Se step non è indicato, avrà come valore di default 1. -Il seguente codice scriverà: - 4 - 6 -""" -for i in range(4, 8, 2): - print(i) -""" - -I cicli while vengono eseguiti finchè una condizione viene a mancare -Il seguente codice scriverà: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Forma compatta per x = x + 1 - -# Gestione delle eccezioni con un blocco try/except -try: - # Usa "raise" per generare un errore - raise IndexError("Questo è un IndexError") -except IndexError as e: - pass # Pass è solo una non-operazione. Solitamente vorrai rimediare all'errore. -except (TypeError, NameError): - pass # Eccezioni multiple possono essere gestite tutte insieme, se necessario. -else: # Clausola opzionale al blocco try/except. Deve essere dopo tutti i blocchi except - print("Tutto ok!") # Viene eseguita solo se il codice dentro try non genera eccezioni -finally: # Eseguito sempre - print("Possiamo liberare risorse qui") - -# Se ti serve solo un try/finally, per liberare risorse, puoi usare il metodo with -with open("myfile.txt") as f: - for line in f: - print(line) - -# In Python qualunque oggetto in grado di essere trattato come una -# sequenza è definito un oggetto Iterable (itarabile). -# L'oggetto restituito da una funzione range è un iterabile. - -filled_dict = {"uno": 1, "due": 2, "tre": 3} -our_iterable = filled_dict.keys() -print(our_iterable) # => dict_keys(['uno', 'due', 'tre']). -# Questo è un oggetto che implementa la nostra interfaccia Iterable. - -# È possibile utilizzarlo con i loop: -for i in our_iterable: - print(i) # Scrive uno, due, tre - -# Tuttavia non possiamo recuperarne i valori tramite indice. -our_iterable[1] # Genera un TypeError - -# Un oggetto iterabile è in grado di generare un iteratore -our_iterator = iter(our_iterable) - -# L'iteratore è un oggetto che ricorda il suo stato mentro lo si "attraversa" -# Possiamo accedere al successivo elemento con "next()". -next(our_iterator) # => "uno" - -# Mantiene il suo stato mentro eseguiamo l'iterazione -next(our_iterator) # => "due" -next(our_iterator) # => "tre" - -# Dopo che un iteratore ha restituito tutti i suoi dati, genera -# un'eccezione StopIteration -next(our_iterator) # Raises StopIteration - -# Puoi prendere tutti gli elementi di un iteratore utilizzando list(). -list(filled_dict.keys()) # => Returns ["one", "two", "three"] - - - -#################################################### -## 4. Funzioni -#################################################### - -# Usa "def" per creare nuove funzioni -def aggiungi(x, y): - print("x è {} e y è {}".format(x, y)) // Scrive i valori formattati in una stringa - return x + y # Restituisce la somma dei valori con il metodo return - -# Chiamare funzioni con parametri -aggiungi(5, 6) # => scrive "x è 5 e y è 6" e restituisce 11 - -# Un altro modo per chiamare funzioni è con parole chiave come argomenti -aggiungi(y=6, x=5) # In questo modo non è necessario rispettare l'ordine degli argomenti - -# Puoi definire funzioni che accettano un numero non definito di argomenti -def varargs(*args): - return args - -varargs(1, 2, 3) # => (1, 2, 3) - -# Puoi definire funzioni che accettano un numero variabile di parole chiave -# come argomento, che saranno interpretati come un dizionario usando ** -def keyword_args(**kwargs): - return kwargs - -# Chiamiamola per vedere cosa succede -keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} - - -# Puoi farle entrambi in una volta, se ti va -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) stampa: - (1, 2) - {"a": 3, "b": 4} -""" - -# Quando chiami funzioni, puoi fare l'opposto di args/kwargs! -# Usa * per sviluppare gli argomenti posizionale ed usa ** per -# espandere gli argomenti parola chiave -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalente a foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivalente a foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) - - -# Restituire valori multipli (with tuple assignments) -def swap(x, y): - return y, x # Restituisce valori multipli come tupla senza parentesi - # (Nota: le parentesi sono state escluse ma possono essere messe) - -x = 1 -y = 2 -x, y = swap(x, y) # => x = 2, y = 1 -# (x, y) = swap(x,y) # Le parentesi sono state escluse ma possono essere incluse. - -# Funzioni - Visibilità delle variabili (variable scope) -x = 5 - -def set_x(num): - # La variabile locale x non è la variabile globale x - x = num # => 43 - print(x) # => 43 - -def set_global_x(num): - global x - print(x) # => 5 - x = num # la variabile globable x è ora 6 - print(x) # => 6 - -set_x(43) -set_global_x(6) - - -# Python ha "first class functions" -def create_adder(x): - def adder(y): - return x + y - return adder - -add_10 = create_adder(10) -add_10(3) # => 13 - -# Ci sono anche funzioni anonime -(lambda x: x > 2)(3) # => True -(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 - -# È possibile creare "mappe" e "filtri" -list(map(add_10, [1, 2, 3])) # => [11, 12, 13] -list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] - -list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] - -# Possiamo usare le "list comprehensions" per mappe e filtri -# Le "list comprehensions" memorizzano l'output come una lista che può essere -# di per sé una lista annidata -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] - -# Puoi fare anche la comprensione di set e dizionari -{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} -{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} - - -#################################################### -## 5. Modules -#################################################### - -# Puoi importare moduli -import math -print(math.sqrt(16)) # => 4.0 - -# Puoi ottenere specifiche funzione da un modulo -from math import ceil, floor -print(ceil(3.7)) # => 4.0 -print(floor(3.7)) # => 3.0 - -# Puoi importare tutte le funzioni da un modulo -# Attenzione: questo non è raccomandato -from math import * - -# Puoi abbreviare i nomi dei moduli -import math as m -math.sqrt(16) == m.sqrt(16) # => True - - -# I moduli di Python sono normali file python. Ne puoi -# scrivere di tuoi ed importarli. Il nome del modulo -# è lo stesso del nome del file. - -# Potete scoprire quali funzioni e attributi -# sono definiti in un modulo -import math -dir(math) - -# Se nella cartella corrente hai uno script chiamato math.py, -# Python caricherà quello invece del modulo math. -# Questo succede perchè la cartella corrente ha priorità -# sulle librerie standard di Python - -# Se hai uno script Python chiamato math.py nella stessa -# cartella del tua script, Python caricherà quello al posto del -# comune modulo math. -# Questo accade perché la cartella locale ha la priorità -# sulle librerie built-in di Python. - - -#################################################### -## 6. Classes -#################################################### - -# Usiamo l'istruzione "class" per creare una classe -class Human: - - # Un attributo della classe. E' condiviso tra tutte le istanze delle classe - species = "H. sapiens" - - # Si noti che i doppi underscore iniziali e finali denotano gli oggetti o - # attributi utilizzati da Python ma che vivono nel namespace controllato - # dall'utente - # Metodi, oggetti o attributi come: __init__, __str__, __repr__, etc. sono - # chiamati metodi speciali (o talvolta chiamati "dunder methods"). - # Non dovresti inventare tali nomi da solo. - - def __init__(self, name): - # Assegna l'argomento all'attributo name dell'istanza - self.name = name - - # Inizializza una proprietà - self._age = 0 - - # Un metodo dell'istanza. Tutti i metodi prendo "self" come primo argomento - def say(self, msg): - print("{name}: {message}".format(name=self.name, message=msg)) - - # Un altro metodo dell'istanza - def sing(self): - return 'yo... yo... microphone check... one two... one two...' - - # Un metodo della classe è condiviso fra tutte le istanze - # Sono chiamati con la classe chiamante come primo argomento - @classmethod - def get_species(cls): - return cls.species - - # Un metodo statico è chiamato senza classe o istanza di riferimento - @staticmethod - def grunt(): - return "*grunt*" - - # Una property è come un metodo getter. - # Trasforma il metodo age() in un attributo in sola lettura, che ha - # lo stesso nome - # In Python non c'è bisogno di scrivere futili getter e setter. - @property - def age(self): - return self._age - - # Questo metodo permette di modificare una property - @age.setter - def age(self, age): - self._age = age - - # Questo metodo permette di cancellare una property - @age.deleter - def age(self): - del self._age - -# Quando l'interprete Python legge un sorgente esegue tutto il suo codice. -# Questo controllo su __name__ assicura che questo blocco di codice venga -# eseguito solo quando questo modulo è il programma principale. - -if __name__ == '__main__': - # Crea un'istanza della classe - i = Human(name="Ian") - i.say("hi") # "Ian: hi" - j = Human("Joel") - j.say("hello") # "Joel: hello" - # i e j sono istanze del tipo Human, o in altre parole sono oggetti Human - - # Chiama un metodo della classe - i.say(i.get_species()) # "Ian: H. sapiens" - # Cambia l'attributo condiviso - Human.species = "H. neanderthalensis" - i.say(i.get_species()) # => "Ian: H. neanderthalensis" - j.say(j.get_species()) # => "Joel: H. neanderthalensis" - - # Chiama un metodo statico - print(Human.grunt()) # => "*grunt*" - - # Non è possibile chiamare il metodo statico con l'istanza dell'oggetto - # poiché i.grunt() metterà automaticamente "self" (l'oggetto i) - # come argomento - print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given - - # Aggiorna la property (age) di questa istanza - i.age = 42 - # Leggi la property - i.say(i.age) # => "Ian: 42" - j.say(j.age) # => "Joel: 0" - # Cancella la property - del i.age - i.age # => questo genererà un AttributeError - - -#################################################### -## 6.1 Ereditarietà (Inheritance) -#################################################### - -# L'ereditarietà consente di definire nuove classi figlio che ereditano metodi e -# variabili dalla loro classe genitore. - -# Usando la classe Human definita sopra come classe base o genitore, possiamo -# definire una classe figlia, Superhero, che erediterà le variabili di classe -# come "species", "name" e "age", così come i metodi, come "sing" e "grunt", -# dalla classe Human, ma potrà anche avere le sue proprietà uniche. - -# Per importare le funzioni da altri file usa il seguente formato -# from "nomefile-senza-estensione" import "funzione-o-classe" - -from human import Human - -# Specificare le classi genitore come parametri della definizione della classe -class Superhero(Human): - - # Se la classe figlio deve ereditare tutte le definizioni del genitore - # senza alcuna modifica, puoi semplicemente usare la parola chiave "pass" - # (e nient'altro) - - #Le classi figlio possono sovrascrivere gli attributi dei loro genitori - species = 'Superhuman' - - # Le classi figlie ereditano automaticamente il costruttore della classe - # genitore, inclusi i suoi argomenti, ma possono anche definire ulteriori - # argomenti o definizioni e sovrascrivere i suoi metodi (compreso il - # costruttore della classe). - # Questo costruttore eredita l'argomento "nome" dalla classe "Human" e - # aggiunge gli argomenti "superpowers" e "movie": - - def __init__(self, name, movie=False, - superpowers=["super strength", "bulletproofing"]): - - # aggiungi ulteriori attributi della classe - self.fictional = True - self.movie = movie - self.superpowers = superpowers - - # La funzione "super" ti consente di accedere ai metodi della classe - # genitore che sono stati sovrascritti dalla classe figlia, - # in questo caso il metodo __init__. - # Il seguente codice esegue il costruttore della classe genitore: - super().__init__(name) - - # Sovrascrivere il metodo "sing" - def sing(self): - return 'Dun, dun, DUN!' - - # Aggiungi un ulteriore metodo dell'istanza - def boast(self): - for power in self.superpowers: - print("I wield the power of {pow}!".format(pow=power)) - - -if __name__ == '__main__': - sup = Superhero(name="Tick") - - # Controllo del tipo di istanza - if isinstance(sup, Human): - print('I am human') - if type(sup) is Superhero: - print('I am a superhero') - - # Ottieni il "Method Resolution search Order" usato sia da getattr () - # che da super (). Questo attributo è dinamico e può essere aggiornato - print(Superhero.__mro__) # => (<class '__main__.Superhero'>, - # => <class 'human.Human'>, <class 'object'>) - - # Esegui il metodo principale ma utilizza il proprio attributo di classe - print(sup.get_species()) # => Superhuman - - # Esegui un metodo che è stato sovrascritto - print(sup.sing()) # => Dun, dun, DUN! - - # Esegui un metodo di Human - sup.say('Spoon') # => Tick: Spoon - - # Esegui un metodo che esiste solo in Superhero - sup.boast() # => I wield the power of super strength! - # => I wield the power of bulletproofing! - - # Attributo di classe ereditato - sup.age = 31 - print(sup.age) # => 31 - - # Attributo che esiste solo in Superhero - print('Am I Oscar eligible? ' + str(sup.movie)) - -#################################################### -## 6.2 Ereditarietà multipla -#################################################### - -# Un'altra definizione di classe -# bat.py -class Bat: - - species = 'Baty' - - def __init__(self, can_fly=True): - self.fly = can_fly - - # Questa classe ha anche un metodo "say" - def say(self, msg): - msg = '... ... ...' - return msg - - # E anche un suo metodo personale - def sonar(self): - return '))) ... (((' - -if __name__ == '__main__': - b = Bat() - print(b.say('hello')) - print(b.fly) - -# Definizione di classe che eredita da Superhero e Bat -# superhero.py -from superhero import Superhero -from bat import Bat - -# Definisci Batman come classe figlia che eredita sia da Superhero che da Bat -class Batman(Superhero, Bat): - - def __init__(self, *args, **kwargs): - # In genere per ereditare gli attributi devi chiamare super: - # super(Batman, self).__init__(*args, **kwargs) - # Ma qui abbiamo a che fare con l'ereditarietà multipla, e super() - # funziona solo con la successiva classe nell'elenco MRO. - # Quindi, invece, chiamiamo esplicitamente __init__ per tutti gli - # antenati. L'uso di *args e **kwargs consente di passare in modo - # pulito gli argomenti, con ciascun genitore che "sbuccia un - # livello della cipolla". - Superhero.__init__(self, 'anonymous', movie=True, - superpowers=['Wealthy'], *args, **kwargs) - Bat.__init__(self, *args, can_fly=False, **kwargs) - # sovrascrivere il valore per l'attributo name - self.name = 'Sad Affleck' - - def sing(self): - return 'nan nan nan nan nan batman!' - - -if __name__ == '__main__': - sup = Batman() - - # Ottieni il "Method Resolution search Order" utilizzato da getattr() e super(). - # Questo attributo è dinamico e può essere aggiornato - print(Batman.__mro__) # => (<class '__main__.Batman'>, - # => <class 'superhero.Superhero'>, - # => <class 'human.Human'>, - # => <class 'bat.Bat'>, <class 'object'>) - - # Esegui il metodo del genitore ma utilizza il proprio attributo di classe - print(sup.get_species()) # => Superhuman - - # Esegui un metodo che è stato sovrascritto - print(sup.sing()) # => nan nan nan nan nan batman! - - # Esegui un metodo da Human, perché l'ordine di ereditarietà è importante - sup.say('I agree') # => Sad Affleck: I agree - - # Esegui un metodo che esiste solo nel 2o antenato - print(sup.sonar()) # => ))) ... ((( - - # Attributo di classe ereditato - sup.age = 100 - print(sup.age) # => 100 - - # Attributo ereditato dal secondo antenato il cui valore predefinito - # è stato ignorato. - print('Can I fly? ' + str(sup.fly)) # => Can I fly? False - - - -#################################################### -## 7. Advanced -#################################################### - -# I generatori ti aiutano a creare codice pigro (lazy code). -# Codice che darà un risultato solo quando sarà "valutato" -def double_numbers(iterable): - for i in iterable: - yield i + i - -# I generatori sono efficienti in termini di memoria perché caricano -# solo i dati necessari per elaborare il valore successivo nell'iterabile. -# Ciò consente loro di eseguire operazioni su intervalli di valori -# altrimenti proibitivi. -# NOTA: `range` sostituisce` xrange` in Python 3. -for i in double_numbers(range(1, 900000000)): # `range` is a generator. - print(i) - if i >= 30: - break - -# Proprio come è possibile creare una "list comprehension", è possibile -# creare anche delle "generator comprehensions". -values = (-x for x in [1,2,3,4,5]) -for x in values: - print(x) # prints -1 -2 -3 -4 -5 to console/terminal - -# Puoi anche trasmettere una "generator comprehensions" direttamente -# ad un elenco. -values = (-x for x in [1,2,3,4,5]) -gen_to_list = list(values) -print(gen_to_list) # => [-1, -2, -3, -4, -5] - - -# Decoratori -# In questo esempio "beg" avvolge/wrappa "say". -# Se say_please è True, cambierà il messaggio restituito. -from functools import wraps - -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Per favore! Sono povero :(") - return msg - - return wrapper - - -@beg -def say(say_please=False): - msg = "Puoi comprarmi una birra?" - return msg, say_please - - -print(say()) # Puoi comprarmi una birra? -print(say(say_please=True)) # Puoi comprarmi una birra? Per favore! Sono povero :( -``` - -## Pronto per qualcosa di più? - -### Gratis Online - -* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Course](http://www.python-course.eu/index.php) -* [First Steps With Python](https://realpython.com/learn/python-first-steps/) -* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) -* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) -* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) -* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) -* [Dive Into Python 3](http://www.diveintopython3.net/index.html) -* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) diff --git a/it-it/pythonlegacy-it.html.markdown b/it-it/pythonlegacy-it.html.markdown new file mode 100644 index 00000000..4c8b2a17 --- /dev/null +++ b/it-it/pythonlegacy-it.html.markdown @@ -0,0 +1,778 @@ +--- +language: Python 2 (legacy) +filename: learnpythonlegacy-it.py +contributors: + - ["Louie Dinh", "http://ldinh.ca"] + - ["Amin Bandali", "http://aminbandali.com"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["evuez", "http://github.com/evuez"] +translators: + - ["Ale46", "http://github.com/Ale46/"] + - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] +lang: it-it +--- +Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari +linguaggi esistenti. Mi sono innamorato di Python per la sua chiarezza sintattica. E' sostanzialmente +pseudocodice eseguibile. + +Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service] + +Nota: questo articolo è riferito a Python 2.7 in modo specifico, ma dovrebbe andar +bene anche per Python 2.x. Python 2.7 sta raggiungendo il "fine vita", ovvero non sarà +più supportato nel 2020. Quindi è consigliato imparare Python utilizzando Python 3. +Per maggiori informazioni su Python 3.x, dai un'occhiata al [tutorial di Python 3](http://learnxinyminutes.com/docs/python/). + +E' possibile anche scrivere codice compatibile sia con Python 2.7 che con Python 3.x, +utilizzando [il modulo `__future__`](https://docs.python.org/2/library/__future__.html) di Python. +Il modulo `__future__` permette di scrivere codice in Python 3, che può essere eseguito +utilizzando Python 2: cosa aspetti a vedere il tutorial di Python 3? + +```python + +# I commenti su una sola linea iniziano con un cancelletto + +""" Più stringhe possono essere scritte + usando tre ", e sono spesso usate + come commenti +""" + +#################################################### +## 1. Tipi di dati primitivi ed Operatori +#################################################### + +# Hai i numeri +3 # => 3 + +# La matematica è quello che vi aspettereste +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7 + +# La divisione è un po' complicata. E' una divisione fra interi in cui viene +# restituito in automatico il risultato intero. +5 / 2 # => 2 + +# Per le divisioni con la virgola abbiamo bisogno di parlare delle variabili floats. +2.0 # Questo è un float +11.0 / 4.0 # => 2.75 ahhh...molto meglio + +# Il risultato di una divisione fra interi troncati positivi e negativi +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # funziona anche per i floats +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# E' possibile importare il modulo "division" (vedi la sezione 6 di questa guida, Moduli) +# per effettuare la divisione normale usando solo '/'. +from __future__ import division +11/4 # => 2.75 ...divisione normale +11//4 # => 2 ...divisione troncata + +# Operazione Modulo +7 % 3 # => 1 + +# Elevamento a potenza (x alla y-esima potenza) +2**4 # => 16 + +# Forzare le precedenze con le parentesi +(1 + 3) * 2 # => 8 + +# Operatori Booleani +# Nota "and" e "or" sono case-sensitive +True and False #=> False +False or True #=> True + +# Note sull'uso di operatori Bool con interi +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True + +# nega con not +not True # => False +not False # => True + +# Uguaglianza è == +1 == 1 # => True +2 == 1 # => False + +# Disuguaglianza è != +1 != 1 # => False +2 != 1 # => True + +# Altri confronti +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# I confronti possono essere concatenati! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# Le stringhe sono create con " o ' +"Questa è una stringa." +'Anche questa è una stringa.' + +# Anche le stringhe possono essere sommate! +"Ciao " + "mondo!" # => Ciao mondo!" +# Le stringhe possono essere sommate anche senza '+' +"Ciao " "mondo!" # => Ciao mondo!" + +# ... oppure moltiplicate +"Hello" * 3 # => "HelloHelloHello" + +# Una stringa può essere considerata come una lista di caratteri +"Questa è una stringa"[0] # => 'Q' + +# Per sapere la lunghezza di una stringa +len("Questa è una stringa") # => 20 + +# Formattazione delle stringhe con % +# Anche se l'operatore % per le stringe sarà deprecato con Python 3.1, e verrà rimosso +# successivamente, può comunque essere utile sapere come funziona +x = 'mela' +y = 'limone' +z = "La cesta contiene una %s e un %s" % (x,y) + +# Un nuovo modo per fomattare le stringhe è il metodo format. +# Questo metodo è quello consigliato +"{} è un {}".format("Questo", "test") +"{0} possono essere {1}".format("le stringhe", "formattate") +# Puoi usare delle parole chiave se non vuoi contare +"{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="lasagna") + +# None è un oggetto +None # => None + +# Non usare il simbolo di uguaglianza "==" per comparare oggetti a None +# Usa "is" invece +"etc" is None # => False +None is None # => True + +# L'operatore 'is' testa l'identità di un oggetto. Questo non è +# molto utile quando non hai a che fare con valori primitivi, ma lo è +# quando hai a che fare con oggetti. + +# Qualunque oggetto può essere usato nei test booleani +# I seguenti valori sono considerati falsi: +# - None +# - Lo zero, come qualunque tipo numerico (quindi 0, 0L, 0.0, 0.j) +# - Sequenze vuote (come '', (), []) +# - Contenitori vuoti (tipo {}, set()) +# - Istanze di classi definite dall'utente, che soddisfano certi criteri +# vedi: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__ +# +# Tutti gli altri valori sono considerati veri: la funzione bool() usata su di loro, ritorna True. +bool(0) # => False +bool("") # => False + + +#################################################### +## 2. Variabili e Collections +#################################################### + +# Python ha una funzione di stampa +print "Sono Python. Piacere di conoscerti!" # => Sono Python. Piacere di conoscerti! + +# Un modo semplice per ricevere dati in input dalla riga di comando +variabile_stringa_input = raw_input("Inserisci del testo: ") # Ritorna i dati letti come stringa +variabile_input = input("Inserisci del testo: ") # Interpreta i dati letti come codice python +# Attenzione: bisogna stare attenti quando si usa input() +# Nota: In python 3, input() è deprecato, e raw_input() si chiama input() + +# Non c'è bisogno di dichiarare una variabile per assegnarle un valore +una_variabile = 5 # Convenzionalmente si usa caratteri_minuscoli_con_underscores +una_variabile # => 5 + +# Accedendo ad una variabile non precedentemente assegnata genera un'eccezione. +# Dai un'occhiata al Control Flow per imparare di più su come gestire le eccezioni. +un_altra_variabile # Genera un errore di nome + +# if può essere usato come un'espressione +# E' l'equivalente dell'operatore ternario in C +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# Liste immagazzinano sequenze +li = [] +# Puoi partire con una lista pre-riempita +altra_li = [4, 5, 6] + +# Aggiungi cose alla fine di una lista con append +li.append(1) # li ora è [1] +li.append(2) # li ora è [1, 2] +li.append(4) # li ora è [1, 2, 4] +li.append(3) # li ora è [1, 2, 4, 3] +# Rimuovi dalla fine della lista con pop +li.pop() # => 3 e li ora è [1, 2, 4] +# Rimettiamolo a posto +li.append(3) # li ora è [1, 2, 4, 3] di nuovo. + +# Accedi ad una lista come faresti con un array +li[0] # => 1 +# Assegna nuovo valore agli indici che sono già stati inizializzati con = +li[0] = 42 +li[0] # => 42 +li[0] = 1 # Nota: è resettato al valore iniziale +# Guarda l'ultimo elemento +li[-1] # => 3 + +# Guardare al di fuori dei limiti è un IndexError +li[4] # Genera IndexError + +# Puoi guardare gli intervalli con la sintassi slice (a fetta). +# (E' un intervallo chiuso/aperto per voi tipi matematici.) +li[1:3] # => [2, 4] +# Ometti l'inizio +li[2:] # => [4, 3] +# Ometti la fine +li[:3] # => [1, 2, 4] +# Seleziona ogni seconda voce +li[::2] # =>[1, 4] +# Copia al contrario della lista +li[::-1] # => [3, 4, 2, 1] +# Usa combinazioni per fare slices avanzate +# li[inizio:fine:passo] + +# Rimuovi arbitrariamente elementi da una lista con "del" +del li[2] # li è ora [1, 2, 3] +# Puoi sommare le liste +li + altra_li # => [1, 2, 3, 4, 5, 6] +# Nota: i valori per li ed altra_li non sono modificati. + +# Concatena liste con "extend()" +li.extend(altra_li) # Ora li è [1, 2, 3, 4, 5, 6] + +# Rimuove la prima occorrenza di un elemento +li.remove(2) # Ora li è [1, 3, 4, 5, 6] +li.remove(2) # Emette un ValueError, poichè 2 non è contenuto nella lista + +# Inserisce un elemento all'indice specificato +li.insert(1, 2) # li è di nuovo [1, 2, 3, 4, 5, 6] + +# Ritorna l'indice della prima occorrenza dell'elemento fornito +li.index(2) # => 1 +li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista + +# Controlla l'esistenza di un valore in una lista con "in" +1 in li # => True + +# Esamina la lunghezza con "len()" +len(li) # => 6 + + +# Tuple sono come le liste ma immutabili. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Genera un TypeError + +# Puoi fare tutte queste cose da lista anche sulle tuple +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Puoi scompattare le tuple (o liste) in variabili +a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 and c è ora 3 +d, e, f = 4, 5, 6 # puoi anche omettere le parentesi +# Le tuple sono create di default se non usi le parentesi +g = 4, 5, 6 # => (4, 5, 6) +# Guarda come è facile scambiare due valori +e, d = d, e # d è ora 5 ed e è ora 4 + + +# Dizionari immagazzinano mappature +empty_dict = {} +# Questo è un dizionario pre-riempito +filled_dict = {"uno": 1, "due": 2, "tre": 3} + +# Accedi ai valori con [] +filled_dict["uno"] # => 1 + +# Ottieni tutte le chiavi come una lista con "keys()" +filled_dict.keys() # => ["tre", "due", "uno"] +# Nota - Nei dizionari l'ordine delle chiavi non è garantito. +# Il tuo risultato potrebbe non essere uguale a questo. + +# Ottieni tutt i valori come una lista con "values()" +filled_dict.values() # => [3, 2, 1] +# Nota - Come sopra riguardo l'ordinamento delle chiavi. + +# Ottieni tutte le coppie chiave-valore, sotto forma di lista di tuple, utilizzando "items()" +filled_dicts.items() # => [("uno", 1), ("due", 2), ("tre", 3)] + +# Controlla l'esistenza delle chiavi in un dizionario con "in" +"uno" in filled_dict # => True +1 in filled_dict # => False + +# Cercando una chiave non esistente è un KeyError +filled_dict["quattro"] # KeyError + +# Usa il metodo "get()" per evitare KeyError +filled_dict.get("uno") # => 1 +filled_dict.get("quattro") # => None +# Il metodo get supporta un argomento di default quando il valore è mancante +filled_dict.get("uno", 4) # => 1 +filled_dict.get("quattro", 4) # => 4 +# nota che filled_dict.get("quattro") è ancora => None +# (get non imposta il valore nel dizionario) + +# imposta il valore di una chiave con una sintassi simile alle liste +filled_dict["quattro"] = 4 # ora, filled_dict["quattro"] => 4 + +# "setdefault()" aggiunge al dizionario solo se la chiave data non è presente +filled_dict.setdefault("five", 5) # filled_dict["five"] è impostato a 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] è ancora 5 + + +# Sets immagazzina ... sets (che sono come le liste, ma non possono contenere doppioni) +empty_set = set() +# Inizializza un "set()" con un po' di valori +some_set = set([1, 2, 2, 3, 4]) # some_set è ora set([1, 2, 3, 4]) + +# l'ordine non è garantito, anche se a volta può sembrare ordinato +another_set = set([4, 3, 2, 2, 1]) # another_set è ora set([1, 2, 3, 4]) + +# Da Python 2.7, {} può essere usato per dichiarare un set +filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} + +# Aggiungere elementi ad un set +filled_set.add(5) # filled_set è ora {1, 2, 3, 4, 5} + +# Fai intersezioni su un set con & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# Fai unioni su set con | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Fai differenze su set con - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Effettua la differenza simmetrica con ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Controlla se il set a sinistra contiene quello a destra +{1, 2} >= {1, 2, 3} # => False + +# Controlla se il set a sinistra è un sottoinsieme di quello a destra +{1, 2} <= {1, 2, 3} # => True + +# Controlla l'esistenza in un set con in +2 in filled_set # => True +10 in filled_set # => False + + +#################################################### +## 3. Control Flow +#################################################### + +# Dichiariamo una variabile +some_var = 5 + +# Questo è un controllo if. L'indentazione è molto importante in python! +# stampa "some_var è più piccola di 10" +if some_var > 10: + print "some_var è decisamente più grande di 10." +elif some_var < 10: # Questa clausola elif è opzionale. + print "some_var è più piccola di 10." +else: # Anche questo è opzionale. + print "some_var è precisamente 10." + + +""" +I cicli for iterano sulle liste +stampa: + cane è un mammifero + gatto è un mammifero + topo è un mammifero +""" +for animale in ["cane", "gatto", "topo"]: + # Puoi usare {0} per interpolare le stringhe formattate. (Vedi di seguito.) + print "{0} è un mammifero".format(animale) + +""" +"range(numero)" restituisce una lista di numeri +da zero al numero dato +stampa: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +"range(lower, upper)" restituisce una lista di numeri +dal più piccolo (lower) al più grande (upper) +stampa: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print i + +""" +I cicli while vengono eseguiti finchè una condizione viene a mancare +stampa: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Forma compatta per x = x + 1 + +# Gestisci le eccezioni con un blocco try/except + +# Funziona da Python 2.6 in su: +try: + # Usa "raise" per generare un errore + raise IndexError("Questo è un errore di indice") +except IndexError as e: + pass # Pass è solo una non-operazione. Solitamente vorrai fare un recupero. +except (TypeError, NameError): + pass # Eccezioni multiple possono essere gestite tutte insieme, se necessario. +else: # Clausola opzionale al blocco try/except. Deve seguire tutti i blocchi except + print "Tutto ok!" # Viene eseguita solo se il codice dentro try non genera eccezioni +finally: # Eseguito sempre + print "Possiamo liberare risorse qui" + +# Invece di try/finally per liberare risorse puoi usare il metodo with +with open("myfile.txt") as f: + for line in f: + print line + +#################################################### +## 4. Funzioni +#################################################### + +# Usa "def" per creare nuove funzioni +def aggiungi(x, y): + print "x è {0} e y è {1}".format(x, y) + return x + y # Restituisce valori con il metodo return + +# Chiamare funzioni con parametri +aggiungi(5, 6) # => stampa "x è 5 e y è 6" e restituisce 11 + +# Un altro modo per chiamare funzioni è con parole chiave come argomenti +aggiungi(y=6, x=5) # Le parole chiave come argomenti possono arrivare in ogni ordine. + + +# Puoi definire funzioni che accettano un numero variabile di argomenti posizionali +# che verranno interpretati come tuple usando il * +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + + +# Puoi definire funzioni che accettano un numero variabile di parole chiave +# come argomento, che saranno interpretati come un dizionario usando ** +def keyword_args(**kwargs): + return kwargs + +# Chiamiamola per vedere cosa succede +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# Puoi farle entrambi in una volta, se ti va +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) stampa: + (1, 2) + {"a": 3, "b": 4} +""" + +# Quando chiami funzioni, puoi fare l'opposto di args/kwargs! +# Usa * per sviluppare gli argomenti posizionale ed usa ** per espandere gli argomenti parola chiave +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalente a foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalente a foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) + +# puoi passare args e kwargs insieme alle altre funzioni che accettano args/kwargs +# sviluppandoli, rispettivamente, con * e ** +def pass_all_the_args(*args, **kwargs): + all_the_args(*args, **kwargs) + print varargs(*args) + print keyword_args(**kwargs) + +# Funzioni Scope +x = 5 + +def set_x(num): + # La variabile locale x non è uguale alla variabile globale x + x = num # => 43 + print x # => 43 + +def set_global_x(num): + global x + print x # => 5 + x = num # la variabile globable x è ora 6 + print x # => 6 + +set_x(43) +set_global_x(6) + +# Python ha funzioni di prima classe +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# Ci sono anche funzioni anonime +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 + +# Esse sono incluse in funzioni di alto livello +map(add_10, [1, 2, 3]) # => [11, 12, 13] +map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] + +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# Possiamo usare la comprensione delle liste per mappe e filtri +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# Puoi fare anche la comprensione di set e dizionari +{x for x in 'abcddeef' if x in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + + +#################################################### +## 5. Classi +#################################################### + +# Usiamo una sottoclasse da un oggetto per avere una classe. +class Human(object): + + # Un attributo della classe. E' condiviso da tutte le istanze delle classe + species = "H. sapiens" + + # Costruttore base, richiamato quando la classe viene inizializzata. + # Si noti che il doppio leading e gli underscore finali denotano oggetti + # o attributi che sono usati da python ma che vivono nello spazio dei nome controllato + # dall'utente. Non dovresti usare nomi di questo genere. + def __init__(self, name): + # Assegna l'argomento all'attributo name dell'istanza + self.name = name + + # Inizializza una proprietà + self.age = 0 + + # Un metodo dell'istanza. Tutti i metodi prendo "self" come primo argomento + def say(self, msg): + return "{0}: {1}".format(self.name, msg) + + # Un metodo della classe è condiviso fra tutte le istanze + # Sono chiamate con la classe chiamante come primo argomento + @classmethod + def get_species(cls): + return cls.species + + # Un metodo statico è chiamato senza una classe od una istanza di riferimento + @staticmethod + def grunt(): + return "*grunt*" + + # Una proprietà è come un metodo getter. + # Trasforma il metodo age() in un attributo in sola lettura, che ha lo stesso nome + @property + def age(self): + return self._age + + # Questo metodo permette di modificare la proprietà + @age.setter + def age(self, age): + self._age = age + + # Questo metodo permette di cancellare la proprietà + @age.deleter + def age(self): + del self._age + +# Instanziare una classe +i = Human(name="Ian") +print i.say("hi") # stampa "Ian: hi" + +j = Human("Joel") +print j.say("hello") # stampa "Joel: hello" + +# Chiamare metodi della classe +i.get_species() # => "H. sapiens" + +# Cambiare l'attributo condiviso +Human.species = "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" + +# Chiamare il metodo condiviso +Human.grunt() # => "*grunt*" + +# Aggiorna la proprietà +i.age = 42 + +# Ritorna il valore della proprietà +i.age # => 42 + +# Cancella la proprietà +del i.age +i.age # => Emette un AttributeError + + +#################################################### +## 6. Moduli +#################################################### + +# Puoi importare moduli +import math +print math.sqrt(16) # => 4.0 + +# Puoi ottenere specifiche funzione da un modulo +from math import ceil, floor +print ceil(3.7) # => 4.0 +print floor(3.7) # => 3.0 + +# Puoi importare tutte le funzioni da un modulo +# Attenzione: questo non è raccomandato +from math import * + +# Puoi abbreviare i nomi dei moduli +import math as m +math.sqrt(16) == m.sqrt(16) # => True +# puoi anche verificare che le funzioni sono equivalenti +from math import sqrt +math.sqrt == m.sqrt == sqrt # => True + +# I moduli di Python sono normali file python. Ne puoi +# scrivere di tuoi ed importarli. Il nome del modulo +# è lo stesso del nome del file. + +# Potete scoprire quali funzioni e attributi +# definiscono un modulo +import math +dir(math) + +# Se nella cartella corrente hai uno script chiamato math.py, +# Python caricherà quello invece del modulo math. +# Questo succede perchè la cartella corrente ha priorità +# sulle librerie standard di Python + + +#################################################### +## 7. Avanzate +#################################################### + +# Generatori +# Un generatore appunto "genera" valori solo quando vengono richiesti, +# invece di memorizzarli tutti subito fin dall'inizio + +# Il metodo seguente (che NON è un generatore) raddoppia tutti i valori e li memorizza +# dentro `double_arr`. Se gli oggetti iterabili sono grandi, il vettore risultato +# potrebbe diventare enorme! +def double_numbers(iterable): + double_arr = [] + for i in iterable: + double_arr.append(i + i) + +# Eseguendo il seguente codice, noi andiamo a raddoppiare prima tutti i valori, e poi +# li ritorniamo tutti e andiamo a controllare la condizione +for value in double_numbers(range(1000000)): # `test_senza_generatore` + print value + if value > 5: + break + +# Invece, potremmo usare un generatore per "generare" il valore raddoppiato non +# appena viene richiesto +def double_numbers_generator(iterable): + for i in iterable: + yield i + i + +# Utilizzando lo stesso test di prima, stavolta però con un generatore, ci permette +# di iterare sui valori e raddoppiarli uno alla volta, non appena vengono richiesti dalla +# logica del programma. Per questo, non appena troviamo un valore > 5, usciamo dal ciclo senza +# bisogno di raddoppiare la maggior parte dei valori del range (MOLTO PIU VELOCE!) +for value in double_numbers_generator(xrange(1000000)): # `test_generatore` + print value + if value > 5: + break + +# Nota: hai notato l'uso di `range` in `test_senza_generatore` e `xrange` in `test_generatore`? +# Proprio come `double_numbers_generator` è la versione col generatore di `double_numbers` +# Abbiamo `xrange` come versione col generatore di `range` +# `range` ritorna un array di 1000000 elementi +# `xrange` invece genera 1000000 valori quando lo richiediamo/iteriamo su di essi + +# Allo stesso modo della comprensione delle liste, puoi creare la comprensione +# dei generatori. +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # stampa -1 -2 -3 -4 -5 + +# Puoi anche fare il cast diretto di una comprensione di generatori ad una lista. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + + +# Decoratori +# in questo esempio beg include say +# Beg chiamerà say. Se say_please è True allora cambierà il messaggio +# ritornato +from functools import wraps + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Per favore! Sono povero :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Puoi comprarmi una birra?" + return msg, say_please + + +print say() # Puoi comprarmi una birra? +print say(say_please=True) # Puoi comprarmi una birra? Per favore! Sono povero :( +``` + +## Pronto per qualcosa di più? + +### Gratis Online + +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [LearnPython](http://www.learnpython.org/) +* [Fullstack Python](https://www.fullstackpython.com/) + +### Libri cartacei + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) diff --git a/it-it/qt-it.html.markdown b/it-it/qt-it.html.markdown index d7469f67..ef829493 100644 --- a/it-it/qt-it.html.markdown +++ b/it-it/qt-it.html.markdown @@ -1,7 +1,7 @@ --- category: tool tool: Qt Framework -language: c++ +language: C++ filename: learnqt-it.cpp contributors: - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"] diff --git a/it-it/rst-it.html.markdown b/it-it/rst-it.html.markdown index a834e899..3885cbd8 100644 --- a/it-it/rst-it.html.markdown +++ b/it-it/rst-it.html.markdown @@ -81,11 +81,11 @@ Anche le tabelle più complesse possono essere inserite facilmente (colonne e/o Esistono diversi modi per creare collegamenti: -- Aggiungendo un underscore dopo una parola: Github_ e aggiungendo l'URL di destinazione dopo il testo (questo metodo ha il vantaggio di non inserire URL non necessari all'interno del testo leggibile). +- Aggiungendo un underscore dopo una parola: GitHub_ e aggiungendo l'URL di destinazione dopo il testo (questo metodo ha il vantaggio di non inserire URL non necessari all'interno del testo leggibile). - Digitando un URL completo: https://github.com/ (verrà automaticamente convertito in un collegamento) -- Utilizzando una sintassi simile a Markdown: `Github <https://github.com/>`_ . +- Utilizzando una sintassi simile a Markdown: `GitHub <https://github.com/>`_ . -.. _Github https://github.com/ +.. _GitHub https://github.com/ ``` diff --git a/it-it/ruby-it.html.markdown b/it-it/ruby-it.html.markdown index 295bf28a..1f466cce 100644 --- a/it-it/ruby-it.html.markdown +++ b/it-it/ruby-it.html.markdown @@ -650,4 +650,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/) - Una passata [edizione libera](http://ruby-doc.com/docs/ProgrammingRuby/) è disponibile online. - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide. -- [Try Ruby](http://tryruby.org) - Imparare le basi del linguaggio di programmazion Ruby, interattivamente nel browser. +- [Try Ruby](https://try.ruby-lang.org/) - Imparare le basi del linguaggio di programmazion Ruby, interattivamente nel browser. diff --git a/it-it/rust-it.html.markdown b/it-it/rust-it.html.markdown index e4b7c33f..acb8b8ba 100644 --- a/it-it/rust-it.html.markdown +++ b/it-it/rust-it.html.markdown @@ -1,5 +1,5 @@ --- -language: rust +language: Rust contributors: - ["Carlo Milanesi", "http://github.com/carlomilanesi"] lang: it-it @@ -229,7 +229,7 @@ fn main() { // Ciclo/iterazione con `for` let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } diff --git a/it-it/solidity.html.markdown b/it-it/solidity.html.markdown new file mode 100644 index 00000000..be747e68 --- /dev/null +++ b/it-it/solidity.html.markdown @@ -0,0 +1,1069 @@ +--- +language: Solidity +filename: learnSolidity-it.sol +contributors: + - ["Nemil Dalal", "https://www.nemil.com"] + - ["Joseph Chow", ""] + - ["Bhoomtawath Plinsut", "https://github.com/varshard"] + - ["Shooter", "https://github.com/liushooter"] + - ["Patrick Collins", "https://gist.github.com/PatrickAlphaC"] +translators: + - ["Al", "http://github.com/al-ias"] +lang: it-it +--- + +Solidity permette di programmare su [Ethereum](https://www.ethereum.org/), una +macchina virtuale basata sulla blockchain che consente la creazione e +l'esecuzione degli smart contract senza che sia richiesta centralizzazione o +fiducia negli attori coinvolti. + +Solidity è un linguaggio di programmazione di contratti tipizzato staticamente e +ha molte cose in comune con Javascript e C. Come per gli oggetti nella +programmazione ad oggetti, ogni contratto contiene variabili di stato, funzioni +e tipi di dato semplici. Tra le funzionalità specifiche dei contratti troviamo +le clausole (guardie) dei modifier, gli event notifier per i listener, e le +variabili globali custom. + +Come esempi di contratti su Ethereum troviamo sistemi di crowdfunding, voto, +[finanza decentralizzata](https://defipulse.com/) e aste al buio. + +Compiere errori nel codice Solidity può portare a rischi e costi alti, quindi +bisogna fare attenzione a testare e rilasciare le modifiche lentamente. A +CAUSA DEI CONTINUI CAMBIAMENTI DI ETHEREUM È IMPROBABILE CHE QUESTO DOCUMENTO +RESTI AGGIORNATO, QUINDI COSNIGLIAMO DI SEGUIRE LA CHAT ROOM DI SOLIDITY E IL +BLOG DI ETHEREUM PER TENERSI AGGIORNATI. TUTTO IL CODICE QUI PRESENTE E' FORNITO +COSÌ COM'È, CON ANNESSI RISCHI SOSTANZIALI DI ERRORI O PATTERN DI PROGRAMMAZIONE +DEPRECATI. + +A differenza di altri linguaggi, potresti aver bisogno di usare pattern di +pausing, deprecation e throttling usage per ridurre il rischio. Questo documento +tratta principalmene la sintassi e quindi esclude molti design pattern in voga. + +Visto che Solidity e Ethereum sono in continuo sviluppo, le funzionalità +sperimentali o beta sono evidenziate e soggette a cambiamenti. Ogni Pull Request +è ben accetta. + + +# Lavorare con Remix e Metamask + +Uno dei modi più semplici di scrivere, distribuire e testare il codice Solidity +è usare : + +1. [L'ambiente di sviluppo online Remix](https://remix.ethereum.org/) +2. [Il wallet Metamask](https://metamask.io/). + +Per cominciare, [scarichiamo l'estesione per browser di Metamask](https://metamask.io/). + +Una volta installata, potremo iniziare ad usare Remix. Il codice seguente è +pre-inizializzato, ma prima di addentrarci, diamo un'occhiata a qualche +trucchetto per iniziare ad usare Remix. Carica tutto il necessario [clickando su questo link](https://remix.ethereum.org/#version=soljson-v0.6.6+commit.6c089d02.js&optimize=false&evmVersion=null&gist=f490c0d51141dd0515244db40bbd0c17&runs=200). + +1. Scegli il compilatore per Solidity + + + +2. Apri il file che si caricherà su quel link + + + +3. Compila il file + + + +4. Fai il deploy + + + +5. Smanetta con i contratti + + + +Hai distribuito il tuo primo contratto! Congratulazioni! + +Potrai testarlo e smanettare con le funzioni già definite. Dai un'occhiata ai +commenti per scoprire cosa fanno. + + +## Lavorare su una testnet + +Distribuire e testare su una testnet è il modo più accurato per mettere alla +prova i tuoi smart contract in Solidity. Per farlo procuriamoci prima degli ETH +di test dalla testnet Kovan. + +[Entra in questo Gitter Channel](https://gitter.im/kovan-testnet/faucet) e +scrivici l'indirizzo del tuo wallet Metamask. + +Sul tuo Metamask, dovrai cambiare la testnet in `Kovan`. + + + +Riceverai degli Ethereum di test gratuiti. Abbiamo bisogno di Ethereum per +distribuire degli smart contract su una testnet. + +Nell'esempio precedente non avevamo usato una testnet, ma avevamo distribuito +su un ambiente virtuale fittizio. Quando si lavora su una testnet, possiamo +davvero monitorare e interagire con i nostri contratti in maniera persistente. + +Per distribuire su una testnet, allo step `#4 Fai il deploy`, cambia +l'`environment` selezionato in `injected web3`. In questo modo verrà usato +come network su cui fare il deploy qualsiasi network selezionato sul tuo +Metamask. + + + +Per ora continua a usare la `Javascript VM` a meno che non ti sia detto di +cambiarla. Quando distribuisci su una testnet, Metamask aprirà un pop up che +ti chiederà di "confermare" la transazione. Premi `yes` e dopo un certo lasso +di tempo, ti apparirà la stessa interfaccia per il contratto nella parte +inferiore dello schermo. + + +```javascript +// Iniziamo con un semplice contratto su una Banca +// Permette di depositare, prelevare e fare l'estratto conto + +// simple_bank.sol (nota l'estensione .sol) +/* **** INIZIO DELL'ESEMPIO **** */ + +// Dichiara la versione del compilatore per il file sorgente +pragma solidity ^0.6.6; + +// Inizia con il commento Natspec (i tre slash) +// viene usato per la documentazione - e per i dati descrittivi per gli elementi +// dell'interfaccia utente / azioni + +/// @title SimpleBank +/// @author nemild + +/* 'contract' somiglia a 'class' in altri linguaggi (ha variabili di classe, +ereditarietà, etc.) */ +contract SimpleBank { // CapWords + // Dichiariamo le variabili di stato fuori dalle funzioni, persisteranno + // durante tutta la vita del contratto + + // i dizionari mappano gli indirizzi con i saldi + // fai sempre attenzione agli overflow attack che sfruttano i numeri + mapping (address => uint) private balances; + + // "private" significa che che altri contratti non possono leggere i + // saldi ma le informazioni restano visibili ad altri attori sulla blockchain + + address public owner; + // 'public' lo rende leggibile dall'esterno (ma non modificabile) dagli + // utenti e dai contratti + + // Gli 'event' pubblicano le azioni in modo che siano ascoltabili da + // listener esterni + event LogDepositMade(address accountAddress, uint amount); + + // I 'constructor' possono ricevere uno o più parametri; Si può + // dichiarare un solo costruttore + constructor() public { + // 'msg' fornisce i dettagli sul messaggio che è stato mandato al contratto + // 'msg.sender' è chi invoca il contratto (l'indirizzo di chi lo crea) + owner = msg.sender; + } + + /// @notice Deposita ether nella banca + /// @return Il saldo dell'utente dopo che è stato effettualto il deposito + function deposit() public payable returns (uint) { + // Usiamo 'require' per testare gli input dell'utente, 'assert' per gli + // invarianti interni. Qui ci assicuriamo di non avere a che fare con + // un overflow + require((balances[msg.sender] + msg.value) >= balances[msg.sender]); + + balances[msg.sender] += msg.value; + // Non servono "this." o "self." con le variabili di stato + // Tutti i valori iniziali delle variabili sono impostati automaticamente + // al valore di default per quel tipo di dato + + emit LogDepositMade(msg.sender, msg.value); // Fa scattare l'evento + + return balances[msg.sender]; + } + + /// @notice Preleva ether dalla banca + /// @dev Non restituisce gli ether inviati in eccesso + /// @param withdrawAmount L'importo che si vuole ritirare + /// @return remainingBal + function withdraw(uint withdrawAmount) public returns (uint remainingBal) { + require(withdrawAmount <= balances[msg.sender]); + + // Notiamo come per prima cosa scaliamo i soldi dal saldo, prima di + // invarli. Ogni .transfer/.send in questo contratto può chiamare una + // funzione esterna. Questa cosa potrebbe permettere a chi invoca la + // funzione di richiedere un importo maggiore del suo saldo usando + // una chiamata ricorsiva. Miriamo ad aggiornare lo stato prima che sia + // chiamata una funzione esterna, incluse .transfer/.send + balances[msg.sender] -= withdrawAmount; + + // Qui lancia automaticamente un errore se fallisce, il che implica + // che il saldo (non più aggiornato) viene ripristinato a prima della + // transazione + msg.sender.transfer(withdrawAmount); + + return balances[msg.sender]; + } + + /// @notice Recupera il saldo + /// @return Il saldo dell'utente + // 'view' (ex: constant) impedisce alle funzioni di modificare lo stato + // delle variabili; consente alle le funzioni di essere disponibili in + // locale/fuori dalla blockchain + function balance() view public returns (uint) { + return balances[msg.sender]; + } +} +// ** FINE DELL'ESEMPIO ** + + +// Passiamo alle basi di Solidity + +// 1. TIPI DI DATO E I LORO METODI +// uint viene usato per gli importi in valuta (non ci sono double o float) +// e per le date (in unix time) +uint x; + +// int di 256 bit, non possono essere modificati dopo l'istanziazione +int constant a = 8; +int256 constant a = 8; // stesso effetto della riga prima, qui viene +// dichiarato esplicitamente che è di 256 bit +uint constant VERSION_ID = 0x123A1; // Una costante esadecimale +// con 'constant', il compilatore rimpiazza ogni occorrenza con il valore + +// Tutte le variabili di stato (quelle fuori da una funzione) +// sono 'interne' di default e accessibili SOLO dall'interno del contratto +// e da tutti contratti che le ereditano +// Bisogna usare esplicitamente 'public' per consentire l'accesso dai contratti +// esterni +int256 public a = 8; + +// Per int e uint possiamo esplicitamente assegnare una dimensione tra 8 e 256 +// es. int8, int16, int24 +uint8 b; +int64 c; +uint248 e; + +// Attenzione a non andare in overflow e a proteggersi dagli attacchi che lo fanno +// Ad esempio per quanto rigrada l'addizione, conviene fare: +uint256 c = a + b; +assert(c >= a); // 'assert' testa gli invarianti interni; require viene usato +// per gli input +// Per altri esempi di problemi comuni con le operazioni aritmentiche, dai una +// occhiata alla Zeppelin's SafeMath library +// https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol + + +// Non ci sono funzioni random built-in, puoi ottenere un numero pseudo-casuale +// hashando l'ultimo blockhash, o ottenere un numero realmente casuale usando +// qualcosa come Chainlink VRF. +// https://docs.chain.link/docs/get-a-random-number + +// Conversione di tipo +int x = int(b); + +bool b = true; // oppure 'var b = true;' per l'inferenza di tipo + +// Indirizzi - contengono indirizzi Ethereum di 20 byte/160 bit +// Non sono consentite operazioni aritmetiche +address public owner; + +// Tipi di account: +// Contract account: l'indirizzo viene impostato quando lo si crea (funzione con +// l'indirzzo di chi lo crea, il numero della transazione inviata) +// External Account: (persona/enitità esterna): l'indirizzo viene creato dalla +// chiave pubblica + +// Aggiungi il campo 'public' per indicare che è pubblico/accessibile dall'esterno +// un getter viene creato automaticamente, ma NON un setter + +// Si possono mandare ether a tutti gli indirizzi +owner.transfer(SOME_BALANCE); // fallisce e, in tal caso, ripristina +// lo stato precedente + +// Possiamo anche usare la funzione di livello più basso .send, che restituisce +// false se fallisce +if (owner.send) {} // RICORDA: metti la send in un 'if' dato che gli indirizzi +// usati nei contratti hanno delle funzioni, che vengono eseguite quando viene +// fatta una send, che possono fallire. +// Inoltre fai attenzione a scalare i saldi PRIMA di provare a fare una send, +// dato il rischio di chiamate riscorsive che potrebbero prosciugare il contratto + +// Possiamo controllare il saldo +owner.balance; // il saldo del propietario (utente o contratto) + + +// I Byte sono disposibili in dimensioni da 1 a 32 +byte a; // 'byte' è la stessa cosa di 'bytes1' +bytes2 b; +bytes32 c; + +// Byte con dimensione dinamica +bytes m; // Un array particolare, la stessa cosa dell'array 'byte[]' (ma scritto stringato) +// È più dispendioso di byte1-byte32, che di solito sono preferibili + +// come bytes, ma non permette di accedere alla lunghezza o all'indice (per ora) +string n = "hello"; // salvato in UTF8, nota i doppi apici, non singoli +// le utility function per le stringhe saranno aggiunte in futuro +// sono preferibili bytes32/bytes, dato che UTF8 occupa più memoria + +// Inferenza di tipo +// 'var' fa inferenza di tipo a seconda del primo assegnamento, +// non può essere usata tra i parametri di una funzione +var a = true; +// da usare con cautela, può inferire un tipo errato +// es. un int8 quando un contatore dev'essere un int16 + +// var può essere usata per assegnare una funzione ad una variabile +function a(uint x) returns (uint) { + return x * 2; +} +var f = a; +f(22); // chiamata + +// di default, tutte le variabili sono impostate a 0 durante l'istanziazione + + +// Delete può essere chiamato sulla maggior parte dei valori +// (NON distrugge il valore, ma lo setta a 0, il valore did default) +uint x = 5; + + +// Destructuring/Tuple +(x, y) = (2, 7); // assegna/scambia più valori + + +// 2. STRUTTURE DATI +// Array +bytes32[5] nicknames; // array statico +bytes32[] names; // array dinamico +uint newLength = names.push("John"); // aggiungere un elemento restituisce +// la nuova dimensione dell'array +// Dimesione +names.length; // ottenere la dimensione +names.length = 1; // la dimensione può essere assegnata (solo per gli array nello storage) + +// array multidimensionali +uint[][5] x; // array con 5 array dinamici (ordine opposto rispetto ad +// altri linguaggi) + +// Dizionari (da un tipo qualsiasi a un tipo qualsiasi) +mapping (string => uint) public balances; +balances["charles"] = 1; +// il risultato balances["ada"] è 0, tutte le chiavi non settate +// restituiscono zero +// 'public' permette che si possa fare questo da un altro contratto: +contractName.balances("charles"); // restituisce 1 +// 'public' ha creato getter (ma non un setter), come il seguente: +function balances(string _account) returns (uint balance) { + return balances[_account]; +} + +// Mapping annidati +mapping (address => mapping (address => uint)) public custodians; + +// Fare una delete +delete balances["John"]; +delete balances; // assegna 0 a tutti gli elementi + +// Diversamente da altri linguaggi NON si può iterare tra gli elementi di un +// mapping senza conoscere le chiavi - ma si può costruire una struttura dati a monte +// che lo faccia + +// Strutture dati +struct Bank { + address owner; + uint balance; +} +Bank b = Bank({ + owner: msg.sender, + balance: 5 +}); +// oppure +Bank c = Bank(msg.sender, 5); + +c.balance = 5; // imposta ad un nuovo valore +delete b; +// reimposta, imposta tutte le variabili della struttura a 0, tranne i mapping + +// Enumerazioni +enum State { Created, Locked, Inactive }; // di solito si usano per gli automi a stati finiti +State public state; // Dichiara una variabile da un enum +state = State.Created; +// Le enum possono essere convertite esplicitamente in int +uint createdState = uint(State.Created); // 0 + +// Data location: Memory vs. storage vs. calldata - tutti i tipi complessi +// (array, struct) hanno una data location +// 'memory' non è persistente, 'storage' sì +// Il default è 'storage' per varibili locali e di stato; +// 'memory' per i parametri delle funzioni +// Lo stack può contenere poche varaibili locali + +// Per la maggior parte dei tipi, si può impostare esplicitamente +// quale data location usare + + +// 3. Operatori semplici +// Ci sono operatori logici, a bit e aritmetici +// Potenza: ** +// Or esclusivo: ^ +// Negazione bitwise: ~ + + +// 4. Variabili globali degne di nota +// ** this ** +this; // indirizzo del contratto +// di solito si usa per trasferire altrove il saldo rimanente +// al termine della vita del contratto +this.balance; +this.someFunction(); // invoca una funzione esterna tramite chiamata, +// non attraverso un salto interno + +// ** msg - Il messaggio corrente ricevuto dal contratto ** +msg.sender; // indirizzo di chi ha inviato msg +msg.value; // l'importo di ether forniti a questo contratto espresso in "wei", +// la funzione dovrebbe essere marcata come "payable" +msg.data; // in bytes, tutti gli argomenti del messaggio +msg.gas; // 'gas' restante + +// ** tx - Questa transazione ** +tx.origin; // l'indirizzo di chi ha avviato questa transazione +tx.gasprice; // il prezzo del "gas" per la transazione + +// ** block - Informazioni sul blocco attuale ** +now; // ora corrente (approssimatamente), alias di block.timestamp (in Unix time) +// Da notare come può essere manipolata dai miner, quindi da usare con cautela + +block.number; // numero del blocco attuale +block.difficulty; // difficulty del blocco attuale +block.blockhash(1); // restituisce un bytes32, funziona solo per i 256 blocchi +// più recenti +block.gasLimit(); + +// ** storage - Memoria persistente (in hash) ** +storage['abc'] = 'def'; // mappa da parole di 256 bit a parole di 256 bit + + +// 4. FUNZIONI E ALTRO +// A. Funzioni +// Una semplice funzione +function increment(uint x) returns (uint) { + x += 1; + return x; +} + +// Le funzioni possono restituire molti valori, +// e visto che i valori di ritorno vengono dichiarati prima +// non è richiesta un'instruzione return esplicita +function increment(uint x, uint y) returns (uint x, uint y) { + x += 1; + y += 1; +} +// Chiama la funzione di cui sopra +uint (a,b) = increment(1,1); + +// 'view' (un alias di 'constant') +// indica che la funzione non cambia / non può cambiare le variabili persistenti +// Le funzioni definite con view vengono eseguite localmente, non sulla blockchain +// N.B. la keyword constant sarà presto deprecata +uint y = 1; + +function increment(uint x) view returns (uint x) { + x += 1; + y += 1; // questa riga fallirebbe + // y è una variabile di stato, e non può essere cambiata in una funzione di view +} + +// 'pure' è più restrittivo di 'view' o 'constant', e non +// permette nemmeno di leggere le varaibili di stato +// In realtà è più complicato, per approfondire su +// view/pure: +// http://solidity.readthedocs.io/en/develop/contracts.html#view-functions + +// Modificatori di visibilità per le funzioni +// Possono essere messi vicino a 'view' e includono: +// public - visibile esternamente e internamente (di default per function) +// external - visible solo esternamente (comprese le chiamate fatte con this.) +// private - visibile solo dal contratto attuale +// internal - visibile solo dal contratto attuale, e da quelli che ne derivano + +// Di solito è una buona idea marcare esplicitamente ogni funzione + +// Le funzioni sono hoisted e si può assegnare una funzione ad una variabile +function a() { + var z = b; + b(); +} + +function b() { + +} + +// Tutte le funzioni che ricevono ether devono essere dichiarate come 'payable' +function depositEther() public payable { + balances[msg.sender] += msg.value; +} + + +// I cicli sono da preferire alla ricorsione +// (la profondità massima dello stack è 1024) +// Inoltre, non impostare dei loop senza limiti, +// perchè potresti raggiungere il limite per il gas + +// B. Eventi +// Gli eventi notificano a terze parti; è facile ispezionare e +// accedere agli eventi al di fuori della blockchain (con client leggeri); +// Tipicamente si dichiarano dopo i parametri del contratto + +// Tipicamente, sono capitalized - si usa Log come prefisso per esplicitarli +// meglio ed evitare che si confondano con una chiamata a funzione + +// Dichiarazione +event LogSent(address indexed from, address indexed to, uint amount); +// Da notare le prime lettere maiuscole + +// Chiamata +LogSent(from, to, amount); + +/** + +Una terza parte esterna (entità o contratto), può osservare usando +la libreria Javascript Web3: + +// Quel che se segue è codice Javascript, non Solidity +Coin.LogSent().watch({}, '', function(error, result) { + if (!error) { + console.log("Trasferimento valuta: " + result.args.amount + + " la valuta è stata mandata da " + result.args.from + + " a " + result.args.to + "."); + console.log("I saldi ora sono:\n" + + "Mittente: " + Coin.balances.call(result.args.from) + + "Destinatario: " + Coin.balances.call(result.args.to)); + } +} +**/ + +// È prassi che un contratto dipenda da un altro (es. che dipenda +// dai tassi di cambio forniti da un altro contratto) + +// C. Modifier +// I modifier validano gli input per conto dele funzioni verificando ad esempio +// il saldo minimo o l'autenticazione dell'utente; +// sono simili alle calusole di guardia di altri linguaggi + +// '_' (underscore) viene spesso posizionato nell'ultima riga del body, e indica +// che la funzione chiamata dev'essere posizionata lì +modifier onlyAfter(uint _time) { require (now >= _time); _; } +modifier onlyOwner { require(msg.sender == owner) _; } +// usate comunemente negli automi a stati finiti +modifier onlyIfStateA (State currState) { require(currState == State.A) _; } + +// Si dichiarano appena dopo la definizione di una funzione +function changeOwner(newOwner) +onlyAfter(someTime) +onlyOwner() +onlyIfState(State.A) +{ + owner = newOwner; +} + +// L'underscore può essere messo prima della fine del body, +// ma un'istruzione di ritorno esplicita lo salterebbe, +// quindi è da usare con cautela +modifier checkValue(uint amount) { + _; + if (msg.value > amount) { + uint amountToRefund = amount - msg.value; + msg.sender.transfer(amountToRefund); + } +} + + +// 6. ISTRUZIONI CONDIZIONALI E CICLI + +// Troviamo tutte le istruzioni condizionali di base - incluse if/else, for, +// while, break, continue e return - ma non c'è lo switch + +// La sintassi è la stessa di javascript, ma non esiste la conversione di tipo +// in booleano dai non booleani (bisogna usare gli operatori logici per +// ottenere il valore boolean) + +// Bisogna stare attenti i loop che iterano in base al comportamento +// dell'utente, dato che i contratti hanno un tetto massimo di gas +// per blocco di codice e falliranno se lo superano +// Ad esempio: +for(uint x = 0; x < refundAddressList.length; x++) { + refundAddressList[x].transfer(SOME_AMOUNT); +} + +// Ci sono due errori nel codice precedente: +// 1. Un fallimento su una transfer impedisce al loop di completare tutti +// i cicli, bloccando dei soldi; +// 2. Questo loop potrebbe essere arbitrariamente lungo (si basa sul numero +// degli utenti che hanno diritto al rimborso), quindi potrebbe fallire sempre +// se supera il tetto massimo di gas per blocco; +// Come soluzione, si permette agli utenti di prelevare +// individualmente dal loro subaccount e segnare il rimborso come riscosso +// Ad es. preferire pull payments ai push payment + + +// 7. OGGETTI/CONTRATTI + +// A. Invocare un contratto esterno +contract InfoFeed { + function info() payable returns (uint ret) { return 42; } +} + +contract Consumer { + InfoFeed feed; // punta ad un contratto sulla blockchain + + // Imposta il feed sull'istanza del contratto esistente + function setFeed(address addr) { + // fare attenzione alla conversione di tipo automatica; + // il costruttore non viene invocato + feed = InfoFeed(addr); + } + + // Imposta il feed ad una nuova istanza del contratto + function createNewFeed() { + feed = new InfoFeed(); // viene creata una nuova istanza; + // viene invocato il costruttore + } + + function callFeed() { + // le parentesi finali invocano il contratto, opzionalmente si può + // specificare un importo custom di ether o di gas + feed.info.value(10).gas(800)(); + } +} + +// B. ereditarietà + +// Conta l'ordine, l'ultimo contratto ereditato (es. 'def') può andare +// in overriding su parti dei contratti precedentemente ereditati +contract MyContract is abc, def("a custom argument to def") { + +// Funzione in overriding + function z() { + if (msg.sender == owner) { + def.z(); // invoca la funzione overridden da def + super.z(); // chiama la funzione overridden del padre + } + } +} + +// Funzioni astratte +function someAbstractFunction(uint x); +// non possono essere compilate, vengono usate nei contratti base/astratti +// e poi verranno implementate + +// C. Import + +import "filename"; +import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol"; + + +// 8. ALTRE KEYWORD + +// A. Selfdestruct +// autodistrugge il contratto corrente, inviando i fondi ad un indirizzo +// (di solito il creatore) +selfdestruct(SOME_ADDRESS); + +// rimuove il codice e quanto in memoria dal blocco corrente e da tutti i blocchi futuri +// aiuta ad alleggerire i client, ma le informazioni precedenti continueranno +// a persistere sulla blockchain + +// È un pattern comune, permette al proprietario di terminare il contratto +// e ricevere i fondi rimasti +function remove() { + if(msg.sender == creator) { // Solo il creatore del contratto può farlo + selfdestruct(creator); // Cessa l'attività del contratto, trasferisce i fondi + } +} + +// Si potrebbe voler disattivare il contratto manualmente, anzichè usare una +// selfdestruct (gli ether inviati ad un contratto dopo una selfdestruct +// vengono persi) + + +// 9. NOTE SUL DESIGN DEI CONTRATTI + +// A. Offruscamento +// Tutte le variabili sono pubblicamente visibili sulla blockchain, quindi +// qualsiasi informazione privata ha bisogno di essere offruscata (es. hash con una +// chiave segreta) + +// Passi: 1. Impegnarsi pagare una certa cifra, 2. Rivelare l'impegno preso +keccak256("una_puntata_d_asta", "un segreto"); // impegno + +// in futuro, l'invocazione della funzione rivelatrice del contratto +// mostrerà la puntata con il segreto che produce lo SHA3 +reveal(100, "ilMioSegreto"); + +// B. Ottimizzazione della memoria (storage) +// Scrivere dati sulla blockchain può essere costoso visto che vengono +// conservati per sempre; siamo incoraggati ad usare la memoria in maniera +// scaltra (un giorno la compilazione migliorerà, ma per ora è vantaggioso +// pianificare le strutture dati da usare - e conservarne il minimo possibile +// sulla blockchain) + +// I costi per conservare cose come array multidimensionali sono spesso alti +// (costa conservare dati - non dichiarare variabili parzialmente vuote) + +// C. Accesso ai dati sulla blockchain +// Non si può impedire alle persone o ai computer di leggere il contenuto +// o lo stato delle transazioni + +// Anche se 'private' non permette agli altri *contratti* di leggere alcune +// informazioni direttamente, qualsiasi altro attore può leggerle +// sulla blockchain + +// Tutti i dati, dall'inizio, vegono conservati sulla blockchain e +// tutti possono accedere alle informazioni passate e ai cambiamenti futuri + +// D. Oracle e dati esterni +// Gli oracle consentono di interagire con i tuoi smart contract +// al di fuori della blockchain. +// Vengono usati per ricevere informazioni dal mondo reale, mandare +// richieste post al mondo reale o vice versa. + +// Anche le implementazioni che sfruttano l'ora vengono fatte attraverso +// gli oracle, visto che i contratti devono essere chiamati direttamente e +// non possono fare una "subscribe" a un certo orario. +// Data la decentralizzazione degli smart contract, vorrai ricevere informazioni +// in maniera decentralizzata, altrimenti rischi di ricreare l'accentramento +// che la progettazione degli smart contract si prefigge di prevenire. + +// Il modo migliore di ottenere e usare dati decentralizzati già pronti +// è attraverso i Chainlink Data Feeds +// https://docs.chain.link/docs/get-the-latest-price +// Possiamo fare riferimento a certe informazioni della blockchain +// che sono già state aggregate da più fonti e ridistribuite on-chain, +// usandole come "banche dati" di fonti di informazione. + +// Puoi vedere altri esempi che effettuano chiamate alle API qui: +// https://docs.chain.link/docs/make-a-http-get-request + +// E ovviamente puoi costruire la tua rete di orace, ma assicurati di sapere +// quant'è accentrata o decentralizzata la tua applicazione. + +// Mettere su una rete di oracle per conto tuo + +// E. Cron Job +// I contratti devono essere chiamati manualmente per gestire lo scheduling +// in base all'orario; si può creare un codice esterno che li pinghi reglarmente +// oppure fornire degli incentivi (ether) a qualcun'altro che lo faccia + +// F. Pattern Observer +// Un pattern observer permette di iscriversi come osservatore e +// registrare una funzione che verrà chiamata dall'oracle +// (N.B. l'oracolo paga perchè sia eseguita quest'azione) +// Ci sono alcune somoglianze nella registrazione con Pub/sub + +// Questo è un contratto astratto che importano sia il client che il server +// Il client dovrebbe implementarlo +contract SomeOracleCallback { + function oracleCallback(int _value, uint _time, bytes32 info) external; +} + +contract SomeOracle { + SomeOracleCallback[] callbacks; // array di tutti gli osservatori iscritti + + // Osservatori iscritti + function addSubscriber(SomeOracleCallback a) { + callbacks.push(a); + } + + function notify(value, time, info) private { + for(uint i = 0;i < callbacks.length; i++) { + // tutti gli osservatori iscritti dovranno implementare la oracleCallback + callbacks[i].oracleCallback(value, time, info); + } + } + + function doSomething() public { + // Codice che fa qualcosa + + // Notifica a tutti gli iscritti + notify(_value, _time, _info); + } +} + +// Il contratto client può aggiungersi agli iscritti (con addSubscriber) +// del contratto SomeOracle, importando SomeOracleCallback + +// G. Automi a stati finiti +// vedi l'esempio sotto che usa enum per lo stato e il modifier inState +``` + +Prova l'esempio completo qui sotto [usando remix e la `Javascript VM`](https://remix.ethereum.org/#version=soljson-v0.6.6+commit.6c089d02.js&optimize=false&evmVersion=null&gist=3d12cd503dcedfcdd715ef61f786be0b&runs=200) + +```javascript +// *** ESEMPIO: Un esempio di crowdfunding (molto simile a Kickstarter) *** +// ** START EXAMPLE ** + +// CrowdFunder.sol +pragma solidity ^0.6.6; + +/// @title CrowdFunder +/// @author nemild +contract CrowdFunder { + // Variabili impostate alla creazione dal creatore + address public creator; + address payable public fundRecipient; // il creatore può essere diverso + // da chi riceve i fondi, che dev'essere payable + uint public minimumToRaise; // è richiesto per chiedere il finanziamento, + // altrimenti tutti ricevono un rimborso + string campaignUrl; + byte version = "1"; + + // Strutture dati + enum State { + Fundraising, + ExpiredRefund, + Successful + } + struct Contribution { + uint amount; + address payable contributor; + } + + // Variabili di stato + State public state = State.Fundraising; // inizializzato alla creazione + uint public totalRaised; + uint public raiseBy; + uint public completeAt; + Contribution[] contributions; + + event LogFundingReceived(address addr, uint amount, uint currentTotal); + event LogWinnerPaid(address winnerAddress); + + modifier inState(State _state) { + require(state == _state); + _; + } + + modifier isCreator() { + require(msg.sender == creator); + _; + } + + // Aspetta 24 settimane dopo l'ultimo cambio di stato prima di consentire + // che in contratto venga distrutto + modifier atEndOfLifecycle() { + require(((state == State.ExpiredRefund || state == State.Successful) && + completeAt + 24 weeks < now)); + _; + } + + function crowdFund( + uint timeInHoursForFundraising, + string memory _campaignUrl, + address payable _fundRecipient, + uint _minimumToRaise) + public + { + creator = msg.sender; + fundRecipient = _fundRecipient; + campaignUrl = _campaignUrl; + minimumToRaise = _minimumToRaise; + raiseBy = now + (timeInHoursForFundraising * 1 hours); + } + + function contribute() + public + payable + inState(State.Fundraising) + returns(uint256 id) + { + contributions.push( + Contribution({ + amount: msg.value, + contributor: msg.sender + }) // usiamo un array per iterare + ); + totalRaised += msg.value; + + emit LogFundingReceived(msg.sender, msg.value, totalRaised); + + checkIfFundingCompleteOrExpired(); + return contributions.length - 1; // restituisce l'id + } + + function checkIfFundingCompleteOrExpired() + public + { + if (totalRaised > minimumToRaise) { + state = State.Successful; + payOut(); + + // qui si può incentivare chi ha provocato il cambiamento di stato + } else if ( now > raiseBy ) { + state = State.ExpiredRefund; // ora i finanziatori possono avere + // il rimborso chiamando getRefund(id) + } + completeAt = now; + } + + function payOut() + public + inState(State.Successful) + { + fundRecipient.transfer(address(this).balance); + LogWinnerPaid(fundRecipient); + } + + function getRefund(uint256 id) + inState(State.ExpiredRefund) + public + returns(bool) + { + require(contributions.length > id && id >= 0 && contributions[id].amount != 0 ); + + uint256 amountToRefund = contributions[id].amount; + contributions[id].amount = 0; + + contributions[id].contributor.transfer(amountToRefund); + + return true; + } + + function removeContract() + public + isCreator() + atEndOfLifecycle() + { + selfdestruct(msg.sender); + // il creatore riceve tutti i fondi che non sono stati riscossi + } +} +// ** END EXAMPLE ** + +``` + +Qualche altra funzionalità. + +```javascript +// 10. ATRE FUNZIONALITA' NATIVE + +// Unità di valuta +// La valuta viene definita partendo dai wei, l'unità più piccola di Ether +uint minAmount = 1 wei; +uint a = 1 finney; // 1 ether == 1000 finney +// Per altre unità, vedi: http://ether.fund/tool/converter + +// Unità temporali +1 == 1 second +1 minutes == 60 seconds + +// Le unità temporali si possono moltiplicare, visto che non vegono salvate +// nelle variabili +uint x = 5; +(x * 1 days); // 5 giorni + +// Attenzione ad usare l'operatore di uguaglianza con i secondi/anni bisestili +// (sono da preferire maggiore/minore di) + +// Crittografia +// Tutte le stringhe che vengono passate vengono concatenate prima di +// calcolare l'hash +sha3("ab", "cd"); +ripemd160("abc"); +sha256("def"); + + +// 11.SICUREZZA + +// I bug possono essere disastrosi per i contratti Ethereum e anche +// i pattern comuni di Solidity potrebbero riverlarsi degli antipattern + +// Dai un'occhiata ai link sulla sicurezza alla fine di questo documento + + +// 12. FUNZIONI DI BASSO LIVELLO +// call - è di basso livello, non viene usata spesso, perchè non è type safe +successBoolean = someContractAddress.call('function_name', 'arg1', 'arg2'); + +// callcode - Il codice all'indirizzo target viene eseguito *contestualmente* +// alla chiamata del contratto +// fornisce le stesse funzionalità di una libreria +someContractAddress.callcode('function_name'); + + +// 13. NOTE SULLO STILE +// Basate sulla guida allo stile PEP8 di Python +// Guida completa allo stile: http://solidity.readthedocs.io/en/develop/style-guide.html + +// Riassunto veloce: +// 4 spazi per l'indentazione +// Due righe per separare la dichiarazione dei contratti +// (e altre dichirazioni top level) +// Evitare spazi ai lati interni delle parentesi tonde +// Si possono omettere le parentesi graffe per statement monolinea (if, for, etc) +// L'else dovrebbe essere posizionato su una riga a se + +// 14. COMMENTI NATSPEC +// usati per la documentazione, commenti e UI esterne + +// Natspec dei contratti - sempre sopra la definizione del contratto +/// @title Titolo del contratto +/// @author Nome dell'autore + +// Natspec delle funzioni +/// @notice informazioni su quel che fa la funzione; mostrate quando la funzione viene eseguita +/// @dev Documentazione della funzione per sviluppatori + +// Natspec dei parametri/valori di ritorno delle funzioni +/// @param someParam Una descrizione di quel che fa il parametro +/// @return Descrizione del valore di ritorno +``` + +## Risorse Aggiuntive +- [Documentazione di Solidity](https://solidity.readthedocs.org/en/latest/) +- [Tutorial Chainlink per Principianti](https://docs.chain.link/docs/beginners-tutorial) +- [Best Practice per Smart Contract](https://github.com/ConsenSys/smart-contract-best-practices) +- [Superblocks Lab - Ambiente di sviluppo su browser per Solidity](https://lab.superblocks.com/) +- [EthFiddle - Il JsFiddle di Solidity](https://ethfiddle.com/) +- [Solidity Editor su Browser](https://remix.ethereum.org/) +- [Chat Room Gitter su Solidity](https://gitter.im/ethereum/solidity) +- [Stategie di Progettazione Modulare per Contratti Ethereum](https://docs.erisindustries.com/tutorials/solidity/) +- [Documentazione Chainlink](https://docs.chain.link/docs/getting-started) + +## Framework di Sviluppo per Smart Contract +- [Hardhat](https://hardhat.org/) +- [Brownie](https://github.com/eth-brownie/brownie) +- [Truffle](https://www.trufflesuite.com/) + +## Librerie importanti +- [Zeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts): Librerie che offrono pattern comuni (crowdfuding, safemath, ecc) +- [Chainlink](https://github.com/smartcontractkit/chainlink): Codice che permette di interagire con dati esterni + +## Contratti di esempio +- [Dapp Bin](https://github.com/ethereum/dapp-bin) +- [Esempi Defi](https://github.com/PatrickAlphaC/chainlink_defi) +- [Solidity per Contratti a Piccoli Passi](https://github.com/fivedogit/solidity-baby-steps/tree/master/contracts) +- [Contratti ConsenSys](https://github.com/ConsenSys/dapp-store-contracts) +- [Lo stato delle Dapp](http://dapps.ethercasts.com/) + +## Sicurezza +- [Pensando Alla Sicurezza Degli Smart Contract](https://blog.ethereum.org/2016/06/19/thinking-smart-contract-security/) +- [Sicurezza Degli Smart Contract](https://blog.ethereum.org/2016/06/10/smart-contract-security/) +- [Blog Distribuito di Hacking](http://hackingdistributed.com/) + +## Stile +- [Guida allo Stile di Solidity](http://solidity.readthedocs.io/en/latest/style-guide.html): La guida allo stile di Ethereum deriva in gran parte dalla guida allo stile [PEP 8](https://www.python.org/dev/peps/pep-0008/) di Python. + +## Editor +- [Remix](https://remix.ethereum.org/) +- [Emacs Modalità Solidity](https://github.com/ethereum/emacs-solidity) +- [Vim Solidity](https://github.com/tomlion/vim-solidity) +- Snippet per gli Editor ([Ultisnips format](https://gist.github.com/nemild/98343ce6b16b747788bc)) + +## Cose da fare in futuro +- Nuove keyword: protected, inheritable +- Lista dei design pattern comuni (throttling, RNG, upgrade di versione) +-Anti patterns comuni sulla sicurezza + +Sentiti libero di mandare una pull request con qualsiasi modifica - o scrivi una mail a nemild -/at-/ gmail diff --git a/it-it/sql-it.html.markdown b/it-it/sql-it.html.markdown new file mode 100644 index 00000000..7db2eec1 --- /dev/null +++ b/it-it/sql-it.html.markdown @@ -0,0 +1,112 @@ +--- +language: SQL +filename: learnsql-it.sql +contributors: + - ["Bob DuCharme", "http://bobdc.com/"] +translators: + - ["Christian Grasso", "https://grasso.io"] +lang: it-it +--- + +Structured Query Language (SQL) è un linguaggio standard ISO per la creazione e la gestione +di database organizzati in un insieme di tabelle. Le diverse implementazioni aggiungono +spesso le proprie estensioni al linguaggio base ([confronto tra le diverse implementazioni](http://troels.arvin.dk/db/rdbms/)) + +Le diverse implementazioni forniscono inoltre un prompt per inserire in modo interattivo i comandi +o eseguire il contenuto di uno script. + +I comandi di seguito lavorano sul [database di esempio MySQL](https://dev.mysql.com/doc/employee/en/) +disponibile su [GitHub](https://github.com/datacharmer/test_db). I file .sql contengono liste di comandi +simili a quelli mostrati di seguito, che creano e riempiono delle tabelle con dati di un'azienda fittizia. +Il comando per eseguire questi script può variare in base all'implementazione in uso. + + +```sql +-- I commenti iniziano con due trattini. Ogni comando va terminato con il punto e virgola + +-- SQL è case-insensitive per quanto riguarda i comandi; in genere si +-- preferisce scriverli in maiuscolo per distinguerli dai nomi di +-- database, tabelle e colonne + +-- Crea ed elimina un database. I nomi di database e tabelle sono case-sensitive +CREATE DATABASE someDatabase; +DROP DATABASE someDatabase; + +-- Lista dei database disponibili +SHOW DATABASES; + +-- Attiva uno specifico database +USE employees; + +-- Seleziona tutte le righe e le colonne dalla tabella departments +SELECT * FROM departments; + +-- Seleziona tutte le righe della tabella departments, +-- ma solo le colonne dept_no e dept_name. +-- È possibile suddividere i comandi su più righe. +SELECT dept_no, + dept_name FROM departments; + +-- Seleziona solo le prime 5 righe della tabella departments. +SELECT * FROM departments LIMIT 5; + +-- Ottiene la colonna dept_name della tabella departments +-- solo per le righe il cui valore di dept_name contiene 'en'. +SELECT dept_name FROM departments WHERE dept_name LIKE '%en%'; + +-- Ottiene tutte le colonne della tabella departments +-- solo per le righe che hanno un dept_name formato da una 'S' +-- seguita esattamente da altri 4 caratteri +SELECT * FROM departments WHERE dept_name LIKE 'S____'; + +-- Seleziona i valori di title dalla tabella titles eliminando i duplicati +SELECT DISTINCT title FROM titles; + +-- Come sopra, ma i valori sono ordinati alfabeticamente +SELECT DISTINCT title FROM titles ORDER BY title; + +-- Mostra il numero di righe della tabella departments +SELECT COUNT(*) FROM departments; + +-- Mostra il numero di righe della tabella departments +-- il cui valore di dept_name contiene 'en'. +SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%'; + +-- Un JOIN tra più tabelle: la tabella titles contiene gli +-- incarichi lavorativi associati ad un certo numero di impiegato. +-- Con il JOIN utilizziamo il numero di impiegato per ottenere +-- le informazioni ad esso associate nella tabella employees. +-- (Inoltre selezioniamo solo le prime 10 righe) + +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; + +-- Mostra tutte le tabelle di tutti i database. +-- Spesso le implementazioni forniscono degli shortcut per questo comando +SELECT * FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_TYPE='BASE TABLE'; + +-- Crea una tabella tablename1, con due colonne, per il database in uso. +-- Per le colonne specifichiamo il tipo di dato (stringa di max 20 caratteri) +CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20)); + +-- Inserisce una riga nella tabella tablename1. I valori devono essere +-- appropriati per la definizione della tabella +INSERT INTO tablename1 VALUES('Richard','Mutt'); + +-- In tablename1, modifica il valore di fname a 'John' +-- in tutte le righe che hanno come lname 'Mutt'. +UPDATE tablename1 SET fname='John' WHERE lname='Mutt'; + +-- Elimina tutte le righe di tablename1 +-- il cui lname inizia per 'M'. +DELETE FROM tablename1 WHERE lname like 'M%'; + +-- Elimina tutte le righe della tabella tablename1 +DELETE FROM tablename1; + +-- Elimina la tabella tablename1 +DROP TABLE tablename1; +``` diff --git a/it-it/toml-it.html.markdown b/it-it/toml-it.html.markdown index 99082048..beb63096 100644 --- a/it-it/toml-it.html.markdown +++ b/it-it/toml-it.html.markdown @@ -1,276 +1,276 @@ ----
-language: toml
-filename: learntoml-it.toml
-contributors:
- - ["Alois de Gouvello", "https://github.com/aloisdg"]
-translators:
- - ["Christian Grasso", "https://grasso.io"]
-lang: it-it
----
-
-TOML è l'acronimo di _Tom's Obvious, Minimal Language_. È un linguaggio per la
-serializzazione di dati, progettato per i file di configurazione.
-
-È un'alternativa a linguaggi come YAML e JSON, che punta ad essere più leggibile
-per le persone. Allo stesso tempo, TOML può essere utilizzato in modo abbastanza
-semplice nella maggior parte dei linguaggi di programmazione, in quanto è
-progettato per essere tradotto senza ambiguità in una hash table.
-
-Tieni presente che TOML è ancora in fase di sviluppo, e la sua specifica non è
-ancora stabile. Questo documento utilizza TOML 0.4.0.
-
-```toml
-# I commenti in TOML sono fatti così.
-
-################
-# TIPI SCALARI #
-################
-
-# Il nostro oggetto root (corrispondente all'intero documento) sarà una mappa,
-# anche chiamata dizionario, hash o oggetto in altri linguaggi.
-
-# La key, il simbolo di uguale e il valore devono trovarsi sulla stessa riga,
-# eccetto per alcuni tipi di valori.
-key = "value"
-stringa = "ciao"
-numero = 42
-float = 3.14
-boolean = true
-data = 1979-05-27T07:32:00-08:00
-notazScientifica = 1e+12
-"puoi utilizzare le virgolette per la key" = true # Puoi usare " oppure '
-"la key può contenere" = "lettere, numeri, underscore e trattini"
-
-############
-# Stringhe #
-############
-
-# Le stringhe possono contenere solo caratteri UTF-8 validi.
-# Possiamo effettuare l'escape dei caratteri, e alcuni hanno delle sequenze
-# di escape compatte. Ad esempio, \t corrisponde al TAB.
-stringaSemplice = "Racchiusa tra virgolette. \"Usa il backslash per l'escape\"."
-
-stringaMultiriga = """
-Racchiusa da tre virgolette doppie all'inizio e
-alla fine - consente di andare a capo."""
-
-stringaLiteral = 'Virgolette singole. Non consente di effettuare escape.'
-
-stringaMultirigaLiteral = '''
-Racchiusa da tre virgolette singole all'inizio e
-alla fine - consente di andare a capo.
-Anche in questo caso non si può fare escape.
-Il primo ritorno a capo viene eliminato.
- Tutti gli altri spazi aggiuntivi
- vengono mantenuti.
-'''
-
-# Per i dati binari è consigliabile utilizzare Base64 e
-# gestirli manualmente dall'applicazione.
-
-##########
-# Interi #
-##########
-
-## Gli interi possono avere o meno un segno (+, -).
-## Non si possono inserire zero superflui all'inizio.
-## Non è possibile inoltre utilizzare valori numerici
-## non rappresentabili con una sequenza di cifre.
-int1 = +42
-int2 = 0
-int3 = -21
-
-## Puoi utilizzare gli underscore per migliorare la leggibilità.
-## Fai attenzione a non inserirne due di seguito.
-int4 = 5_349_221
-int5 = 1_2_3_4_5 # VALIDO, ma da evitare
-
-#########
-# Float #
-#########
-
-# I float permettono di rappresentare numeri decimali.
-flt1 = 3.1415
-flt2 = -5e6
-flt3 = 6.626E-34
-
-###########
-# Boolean #
-###########
-
-# I valori boolean (true/false) devono essere scritti in minuscolo.
-bool1 = true
-bool2 = false
-
-############
-# Data/ora #
-############
-
-data1 = 1979-05-27T07:32:00Z # Specifica RFC 3339/ISO 8601 (UTC)
-data2 = 1979-05-26T15:32:00+08:00 # RFC 3339/ISO 8601 con offset
-
-######################
-# TIPI DI COLLECTION #
-######################
-
-#########
-# Array #
-#########
-
-array1 = [ 1, 2, 3 ]
-array2 = [ "Le", "virgole", "sono", "delimitatori" ]
-array3 = [ "Non", "unire", "tipi", "diversi" ]
-array4 = [ "tutte", 'le stringhe', """hanno lo stesso""", '''tipo''' ]
-array5 = [
- "Gli spazi vuoti", "sono", "ignorati"
-]
-
-###########
-# Tabelle #
-###########
-
-# Le tabelle (o hash table o dizionari) sono collection di coppie key/value.
-# Iniziano con un nome tra parentesi quadre su una linea separata.
-# Le tabelle vuote (senza alcun valore) sono valide.
-[tabella]
-
-# Tutti i valori che si trovano sotto il nome della tabella
-# appartengono alla tabella stessa (finchè non ne viene creata un'altra).
-# L'ordine di questi valori non è garantito.
-[tabella-1]
-key1 = "una stringa"
-key2 = 123
-
-[tabella-2]
-key1 = "un'altra stringa"
-key2 = 456
-
-# Utilizzando i punti è possibile creare delle sottotabelle.
-# Ogni parte suddivisa dai punti segue le regole delle key per il nome.
-[tabella-3."sotto.tabella"]
-key1 = "prova"
-
-# Ecco l'equivalente JSON della tabella precedente:
-# { "tabella-3": { "sotto.tabella": { "key1": "prova" } } }
-
-# Gli spazi non vengono considerati, ma è consigliabile
-# evitare di usare spazi superflui.
-[a.b.c] # consigliato
-[ d.e.f ] # identico a [d.e.f]
-
-# Non c'è bisogno di creare le tabelle superiori per creare una sottotabella.
-# [x] queste
-# [x.y] non
-# [x.y.z] servono
-[x.y.z.w] # per creare questa tabella
-
-# Se non è stata già creata prima, puoi anche creare
-# una tabella superiore più avanti.
-[a.b]
-c = 1
-
-[a]
-d = 2
-
-# Non puoi definire una key o una tabella più di una volta.
-
-# ERRORE
-[a]
-b = 1
-
-[a]
-c = 2
-
-# ERRORE
-[a]
-b = 1
-
-[a.b]
-c = 2
-
-# I nomi delle tabelle non possono essere vuoti.
-[] # NON VALIDO
-[a.] # NON VALIDO
-[a..b] # NON VALIDO
-[.b] # NON VALIDO
-[.] # NON VALIDO
-
-##################
-# Tabelle inline #
-##################
-
-tabelleInline = { racchiuseData = "{ e }", rigaSingola = true }
-punto = { x = 1, y = 2 }
-
-####################
-# Array di tabelle #
-####################
-
-# Un array di tabelle può essere creato utilizzando due parentesi quadre.
-# Tutte le tabelle con questo nome saranno elementi dell'array.
-# Gli elementi vengono inseriti nell'ordine in cui si trovano.
-
-[[prodotti]]
-nome = "array di tabelle"
-sku = 738594937
-tabelleVuoteValide = true
-
-[[prodotti]]
-
-[[prodotti]]
-nome = "un altro item"
-sku = 284758393
-colore = "grigio"
-
-# Puoi anche creare array di tabelle nested. Le sottotabelle con doppie
-# parentesi quadre apparterranno alla tabella più vicina sopra di esse.
-
-[[frutta]]
- nome = "mela"
-
- [frutto.geometria]
- forma = "sferica"
- nota = "Sono una proprietà del frutto"
-
- [[frutto.colore]]
- nome = "rosso"
- nota = "Sono un oggetto di un array dentro mela"
-
- [[frutto.colore]]
- nome = "verde"
- nota = "Sono nello stesso array di rosso"
-
-[[frutta]]
- nome = "banana"
-
- [[frutto.colore]]
- nome = "giallo"
- nota = "Anche io sono un oggetto di un array, ma dentro banana"
-```
-
-Ecco l'equivalente JSON dell'ultima tabella:
-
-```json
-{
- "frutta": [
- {
- "nome": "mela",
- "geometria": { "forma": "sferica", "nota": "..."},
- "colore": [
- { "nome": "rosso", "nota": "..." },
- { "nome": "verde", "nota": "..." }
- ]
- },
- {
- "nome": "banana",
- "colore": [
- { "nome": "giallo", "nota": "..." }
- ]
- }
- ]
-}
-```
-
-### Altre risorse
-
-+ [Repository ufficiale di TOML](https://github.com/toml-lang/toml)
+--- +language: toml +filename: learntoml-it.toml +contributors: + - ["Alois de Gouvello", "https://github.com/aloisdg"] +translators: + - ["Christian Grasso", "https://grasso.io"] +lang: it-it +--- + +TOML è l'acronimo di _Tom's Obvious, Minimal Language_. È un linguaggio per la +serializzazione di dati, progettato per i file di configurazione. + +È un'alternativa a linguaggi come YAML e JSON, che punta ad essere più leggibile +per le persone. Allo stesso tempo, TOML può essere utilizzato in modo abbastanza +semplice nella maggior parte dei linguaggi di programmazione, in quanto è +progettato per essere tradotto senza ambiguità in una hash table. + +Tieni presente che TOML è ancora in fase di sviluppo, e la sua specifica non è +ancora stabile. Questo documento utilizza TOML 0.4.0. + +```toml +# I commenti in TOML sono fatti così. + +################ +# TIPI SCALARI # +################ + +# Il nostro oggetto root (corrispondente all'intero documento) sarà una mappa, +# anche chiamata dizionario, hash o oggetto in altri linguaggi. + +# La key, il simbolo di uguale e il valore devono trovarsi sulla stessa riga, +# eccetto per alcuni tipi di valori. +key = "value" +stringa = "ciao" +numero = 42 +float = 3.14 +boolean = true +data = 1979-05-27T07:32:00-08:00 +notazScientifica = 1e+12 +"puoi utilizzare le virgolette per la key" = true # Puoi usare " oppure ' +"la key può contenere" = "lettere, numeri, underscore e trattini" + +############ +# Stringhe # +############ + +# Le stringhe possono contenere solo caratteri UTF-8 validi. +# Possiamo effettuare l'escape dei caratteri, e alcuni hanno delle sequenze +# di escape compatte. Ad esempio, \t corrisponde al TAB. +stringaSemplice = "Racchiusa tra virgolette. \"Usa il backslash per l'escape\"." + +stringaMultiriga = """ +Racchiusa da tre virgolette doppie all'inizio e +alla fine - consente di andare a capo.""" + +stringaLiteral = 'Virgolette singole. Non consente di effettuare escape.' + +stringaMultirigaLiteral = ''' +Racchiusa da tre virgolette singole all'inizio e +alla fine - consente di andare a capo. +Anche in questo caso non si può fare escape. +Il primo ritorno a capo viene eliminato. + Tutti gli altri spazi aggiuntivi + vengono mantenuti. +''' + +# Per i dati binari è consigliabile utilizzare Base64 e +# gestirli manualmente dall'applicazione. + +########## +# Interi # +########## + +## Gli interi possono avere o meno un segno (+, -). +## Non si possono inserire zero superflui all'inizio. +## Non è possibile inoltre utilizzare valori numerici +## non rappresentabili con una sequenza di cifre. +int1 = +42 +int2 = 0 +int3 = -21 + +## Puoi utilizzare gli underscore per migliorare la leggibilità. +## Fai attenzione a non inserirne due di seguito. +int4 = 5_349_221 +int5 = 1_2_3_4_5 # VALIDO, ma da evitare + +######### +# Float # +######### + +# I float permettono di rappresentare numeri decimali. +flt1 = 3.1415 +flt2 = -5e6 +flt3 = 6.626E-34 + +########### +# Boolean # +########### + +# I valori boolean (true/false) devono essere scritti in minuscolo. +bool1 = true +bool2 = false + +############ +# Data/ora # +############ + +data1 = 1979-05-27T07:32:00Z # Specifica RFC 3339/ISO 8601 (UTC) +data2 = 1979-05-26T15:32:00+08:00 # RFC 3339/ISO 8601 con offset + +###################### +# TIPI DI COLLECTION # +###################### + +######### +# Array # +######### + +array1 = [ 1, 2, 3 ] +array2 = [ "Le", "virgole", "sono", "delimitatori" ] +array3 = [ "Non", "unire", "tipi", "diversi" ] +array4 = [ "tutte", 'le stringhe', """hanno lo stesso""", '''tipo''' ] +array5 = [ + "Gli spazi vuoti", "sono", "ignorati" +] + +########### +# Tabelle # +########### + +# Le tabelle (o hash table o dizionari) sono collection di coppie key/value. +# Iniziano con un nome tra parentesi quadre su una linea separata. +# Le tabelle vuote (senza alcun valore) sono valide. +[tabella] + +# Tutti i valori che si trovano sotto il nome della tabella +# appartengono alla tabella stessa (finchè non ne viene creata un'altra). +# L'ordine di questi valori non è garantito. +[tabella-1] +key1 = "una stringa" +key2 = 123 + +[tabella-2] +key1 = "un'altra stringa" +key2 = 456 + +# Utilizzando i punti è possibile creare delle sottotabelle. +# Ogni parte suddivisa dai punti segue le regole delle key per il nome. +[tabella-3."sotto.tabella"] +key1 = "prova" + +# Ecco l'equivalente JSON della tabella precedente: +# { "tabella-3": { "sotto.tabella": { "key1": "prova" } } } + +# Gli spazi non vengono considerati, ma è consigliabile +# evitare di usare spazi superflui. +[a.b.c] # consigliato +[ d.e.f ] # identico a [d.e.f] + +# Non c'è bisogno di creare le tabelle superiori per creare una sottotabella. +# [x] queste +# [x.y] non +# [x.y.z] servono +[x.y.z.w] # per creare questa tabella + +# Se non è stata già creata prima, puoi anche creare +# una tabella superiore più avanti. +[a.b] +c = 1 + +[a] +d = 2 + +# Non puoi definire una key o una tabella più di una volta. + +# ERRORE +[a] +b = 1 + +[a] +c = 2 + +# ERRORE +[a] +b = 1 + +[a.b] +c = 2 + +# I nomi delle tabelle non possono essere vuoti. +[] # NON VALIDO +[a.] # NON VALIDO +[a..b] # NON VALIDO +[.b] # NON VALIDO +[.] # NON VALIDO + +################## +# Tabelle inline # +################## + +tabelleInline = { racchiuseData = "{ e }", rigaSingola = true } +punto = { x = 1, y = 2 } + +#################### +# Array di tabelle # +#################### + +# Un array di tabelle può essere creato utilizzando due parentesi quadre. +# Tutte le tabelle con questo nome saranno elementi dell'array. +# Gli elementi vengono inseriti nell'ordine in cui si trovano. + +[[prodotti]] +nome = "array di tabelle" +sku = 738594937 +tabelleVuoteValide = true + +[[prodotti]] + +[[prodotti]] +nome = "un altro item" +sku = 284758393 +colore = "grigio" + +# Puoi anche creare array di tabelle nested. Le sottotabelle con doppie +# parentesi quadre apparterranno alla tabella più vicina sopra di esse. + +[[frutta]] + nome = "mela" + + [frutto.geometria] + forma = "sferica" + nota = "Sono una proprietà del frutto" + + [[frutto.colore]] + nome = "rosso" + nota = "Sono un oggetto di un array dentro mela" + + [[frutto.colore]] + nome = "verde" + nota = "Sono nello stesso array di rosso" + +[[frutta]] + nome = "banana" + + [[frutto.colore]] + nome = "giallo" + nota = "Anche io sono un oggetto di un array, ma dentro banana" +``` + +Ecco l'equivalente JSON dell'ultima tabella: + +```json +{ + "frutta": [ + { + "nome": "mela", + "geometria": { "forma": "sferica", "nota": "..."}, + "colore": [ + { "nome": "rosso", "nota": "..." }, + { "nome": "verde", "nota": "..." } + ] + }, + { + "nome": "banana", + "colore": [ + { "nome": "giallo", "nota": "..." } + ] + } + ] +} +``` + +### Altre risorse + ++ [Repository ufficiale di TOML](https://github.com/toml-lang/toml) diff --git a/it-it/zfs-it.html.markdown b/it-it/zfs-it.html.markdown new file mode 100644 index 00000000..c1307e67 --- /dev/null +++ b/it-it/zfs-it.html.markdown @@ -0,0 +1,361 @@ +--- +category: tool +tool: zfs +contributors: + - ["sarlalian", "http://github.com/sarlalian"] +translators: + - ["Christian Grasso","https://grasso.io"] +filename: LearnZfs-it.txt +lang: it-it +--- + + +[ZFS](http://open-zfs.org/wiki/Main_Page) è un sistema di storage che combina file system +tradizionali e volume manager in un unico strumento. ZFS utilizza della terminologia +specifica, diversa da quella usata da altri sistemi di storage, ma le sue funzioni lo +rendono un ottimo tool per gli amministratori di sistema. + + +## Concetti base di ZFS + +### Virtual Device + +Un VDEV è simile a un dispositivo gestito da una scheda RAID. Esistono diversi tipi di +VDEV che offrono diversi vantaggi, tra cui ridondanza e velocità. In generale, +i VDEV offrono una maggiore affidabilità rispetto alle schede RAID. Si sconsiglia di +utilizzare ZFS insieme a RAID, poichè ZFS è fatto per gestire direttamente i dischi fisici. + +Tipi di VDEV: + +* stripe (disco singolo, senza ridondanza) +* mirror (mirror su più dischi) +* raidz + * raidz1 (parity a 1 disco, simile a RAID 5) + * raidz2 (parity a 2 dischi, simile a RAID 6) + * raidz3 (parity a 3 dischi) +* disk +* file (non consigliato in production poichè aggiunge un ulteriore filesystem) + +I dati vengono distribuiti tra tutti i VDEV presenti nella Storage Pool, per cui un maggior +numero di VDEV aumenta le operazioni al secondo (IOPS). + +### Storage Pool + +Le Storage Pool di ZFS sono un'astrazione del livello inferiore (VDEV) e consentono di +separare il filesystem visibile agli utenti dal layout reale dei dischi. + +### Dataset + +I dataset sono simili ai filesystem tradizionali, ma con molte più funzioni che rendono +vantaggioso l'utilizzo di ZFS. I dataset supportano il [Copy on Write](https://en.wikipedia.org/wiki/Copy-on-write) +gli snapshot, la gestione delle quota, compressione e deduplicazione. + + +### Limiti + +Una directory può contenere fino a 2^48 file, ognuno dei quali di 16 exabyte. +Una storage pool può contenere fino a 256 zettabyte (2^78), e può essere distribuita +tra 2^64 dispositivi. Un singolo host può avere fino a 2^64 storage pool. + + +## Comandi + +### Storage Pool + +Azioni: + +* List (lista delle pool) +* Status (stato) +* Destroy (rimozione) +* Get/Set (lettura/modifica proprietà) + +Lista delle zpool + +```bash +# Crea una zpool raidz +$ zpool create bucket raidz1 gpt/zfs0 gpt/zfs1 gpt/zfs2 + +# Lista delle zpool +$ zpool list +NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT +zroot 141G 106G 35.2G - 43% 75% 1.00x ONLINE - + +# Informazioni dettagliate su una zpool +$ zpool list -v zroot +NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT +zroot 141G 106G 35.2G - 43% 75% 1.00x ONLINE - + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 141G 106G 35.2G - 43% 75% +``` + +Stato delle zpool + +```bash +# Informazioni sullo stato delle zpool +$ zpool status + pool: zroot + state: ONLINE + scan: scrub repaired 0 in 2h51m with 0 errors on Thu Oct 1 07:08:31 2015 +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 ONLINE 0 0 0 + +errors: No known data errors + +# "Scrubbing" (correzione degli errori) +$ zpool scrub zroot +$ zpool status -v zroot + pool: zroot + state: ONLINE + scan: scrub in progress since Thu Oct 15 16:59:14 2015 + 39.1M scanned out of 106G at 1.45M/s, 20h47m to go + 0 repaired, 0.04% done +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 ONLINE 0 0 0 + +errors: No known data errors +``` + +Proprietà delle zpool + +```bash + +# Proprietà di una zpool (gestite dal sistema o dall'utente) +$ zpool get all zroot +NAME PROPERTY VALUE SOURCE +zroot size 141G - +zroot capacity 75% - +zroot altroot - default +zroot health ONLINE - +... + +# Modifica di una proprietà +$ zpool set comment="Dati" zroot +$ zpool get comment +NAME PROPERTY VALUE SOURCE +tank comment - default +zroot comment Dati local +``` + +Rimozione di una zpool + +```bash +$ zpool destroy test +``` + + +### Dataset + +Azioni: + +* Create +* List +* Rename +* Delete +* Get/Set (proprietà) + +Creazione dataset + +```bash +# Crea un dataset +$ zfs create tank/root/data +$ mount | grep data +tank/root/data on /data (zfs, local, nfsv4acls) + +# Crea un sottodataset +$ zfs create tank/root/data/stuff +$ mount | grep data +tank/root/data on /data (zfs, local, nfsv4acls) +tank/root/data/stuff on /data/stuff (zfs, local, nfsv4acls) + + +# Crea un volume +$ zfs create -V zroot/win_vm +$ zfs list zroot/win_vm +NAME USED AVAIL REFER MOUNTPOINT +tank/win_vm 4.13G 17.9G 64K - +``` + +Lista dei dataset + +```bash +# Lista dei dataset +$ zfs list +NAME USED AVAIL REFER MOUNTPOINT +zroot 106G 30.8G 144K none +zroot/ROOT 18.5G 30.8G 144K none +zroot/ROOT/10.1 8K 30.8G 9.63G / +zroot/ROOT/default 18.5G 30.8G 11.2G / +zroot/backup 5.23G 30.8G 144K none +zroot/home 288K 30.8G 144K none +... + +# Informazioni su un dataset +$ zfs list zroot/home +NAME USED AVAIL REFER MOUNTPOINT +zroot/home 288K 30.8G 144K none + +# Lista degli snapshot +$ zfs list -t snapshot +zroot@daily-2015-10-15 0 - 144K - +zroot/ROOT@daily-2015-10-15 0 - 144K - +zroot/ROOT/default@daily-2015-10-15 0 - 24.2G - +zroot/tmp@daily-2015-10-15 124K - 708M - +zroot/usr@daily-2015-10-15 0 - 144K - +zroot/home@daily-2015-10-15 0 - 11.9G - +zroot/var@daily-2015-10-15 704K - 1.42G - +zroot/var/log@daily-2015-10-15 192K - 828K - +zroot/var/tmp@daily-2015-10-15 0 - 152K - +``` + +Rinominare un dataset + +```bash +$ zfs rename tank/root/home tank/root/old_home +$ zfs rename tank/root/new_home tank/root/home +``` + +Eliminare un dataset + +```bash +# I dataset non possono essere eliminati se hanno degli snapshot +$ zfs destroy tank/root/home +``` + +Lettura/modifica proprietà + +```bash +# Tutte le proprietà di un dataset +$ zfs get all zroot/usr/home │157 # Create Volume +NAME PROPERTY VALUE SOURCE │158 $ zfs create -V zroot/win_vm +zroot/home type filesystem - │159 $ zfs list zroot/win_vm +zroot/home creation Mon Oct 20 14:44 2014 - │160 NAME USED AVAIL REFER MOUNTPOINT +zroot/home used 11.9G - │161 tank/win_vm 4.13G 17.9G 64K - +zroot/home available 94.1G - │162 ``` +zroot/home referenced 11.9G - │163 +zroot/home mounted yes - +... + +# Proprietà specifica +$ zfs get compression zroot/usr/home +NAME PROPERTY VALUE SOURCE +zroot/home compression off default + +# Modifica di una proprietà +$ zfs set compression=gzip-9 mypool/lamb + +# Specifiche proprietà per tutti i dataset +$ zfs list -o name,quota,reservation +NAME QUOTA RESERV +zroot none none +zroot/ROOT none none +zroot/ROOT/default none none +zroot/tmp none none +zroot/usr none none +zroot/home none none +zroot/var none none +... +``` + + +### Snapshot + +Gli snapshot sono una delle funzioni più importanti di ZFS: + +* Lo spazio occupato è la differenza tra il filesystem e l'ultimo snapshot +* Il tempo di creazione è di pochi secondi +* Possono essere ripristinati alla velocità di scrittura del disco +* Possono essere automatizzati molto semplicemente + +Azioni: + +* Create +* Delete +* Rename +* Access +* Send / Receive +* Clone + + +Creazione di uno snapshot + +```bash +# Crea uno snapshot di un singolo dataset +zfs snapshot tank/home/sarlalian@now + +# Crea uno snapshot di un dataset e dei suoi sottodataset +$ zfs snapshot -r tank/home@now +$ zfs list -t snapshot +NAME USED AVAIL REFER MOUNTPOINT +tank/home@now 0 - 26K - +tank/home/sarlalian@now 0 - 259M - +tank/home/alice@now 0 - 156M - +tank/home/bob@now 0 - 156M - +... +``` + +Eliminazione di uno snapshot + +```bash +# Elimina uno snapshot +$ zfs destroy tank/home/sarlalian@now + +# Elimina uno snapshot ricorsivamente +$ zfs destroy -r tank/home/sarlalian@now + +``` + +Rinominare uno snapshot + +```bash +$ zfs rename tank/home/sarlalian@now tank/home/sarlalian@today +$ zfs rename tank/home/sarlalian@now today + +$ zfs rename -r tank/home@now @yesterday +``` + +Accedere ad uno snapshot + +```bash +# Utilizzare il comando cd come per una directory +$ cd /home/.zfs/snapshot/ +``` + +Invio e ricezione + +```bash +# Backup di uno snapshot su un file +$ zfs send tank/home/sarlalian@now | gzip > backup_file.gz + +# Invia uno snapshot ad un altro dataset +$ zfs send tank/home/sarlalian@now | zfs recv backups/home/sarlalian + +# Invia uno snapshot ad un host remoto +$ zfs send tank/home/sarlalian@now | ssh root@backup_server 'zfs recv tank/home/sarlalian' + +# Invia l'intero dataset e i suoi snapshot ad un host remoto +$ zfs send -v -R tank/home@now | ssh root@backup_server 'zfs recv tank/home' +``` + +Clonare gli snapshot + +```bash +# Clona uno snapshot +$ zfs clone tank/home/sarlalian@now tank/home/sarlalian_new + +# Rende il clone indipendente dallo snapshot originale +$ zfs promote tank/home/sarlalian_new +``` + +### Letture aggiuntive (in inglese) + +* [BSDNow's Crash Course on ZFS](http://www.bsdnow.tv/tutorials/zfs) +* [FreeBSD Handbook on ZFS](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/zfs.html) +* [BSDNow's Crash Course on ZFS](http://www.bsdnow.tv/tutorials/zfs) +* [Oracle's Tuning Guide](http://www.oracle.com/technetwork/articles/servers-storage-admin/sto-recommended-zfs-settings-1951715.html) +* [OpenZFS Tuning Guide](http://open-zfs.org/wiki/Performance_tuning) +* [FreeBSD ZFS Tuning Guide](https://wiki.freebsd.org/ZFSTuningGuide) diff --git a/ja-jp/asciidoc.html.markdown b/ja-jp/asciidoc.html.markdown index 7347589a..af19850a 100644 --- a/ja-jp/asciidoc.html.markdown +++ b/ja-jp/asciidoc.html.markdown @@ -5,7 +5,7 @@ contributors: - ["Abel Salgado Romero", "https://twitter.com/abelsromero"] translators: - ["Ryota Kayanuma", "https://github.com/PicoSushi"] -filename: asciidoc-ja.md +filename: asciidoc-ja.adoc lang: ja-jp --- diff --git a/ja-jp/python3-jp.html.markdown b/ja-jp/python-jp.html.markdown index b9731411..18e7d1b8 100644 --- a/ja-jp/python3-jp.html.markdown +++ b/ja-jp/python-jp.html.markdown @@ -1,5 +1,5 @@ --- -language: python3 +language: Python contributors: - ["Louie Dinh", "http://pythonpracticeprojects.com"] - ["Steven Basart", "http://github.com/xksteven"] @@ -11,7 +11,7 @@ contributors: translators: - ["kakakaya", "https://github.com/kakakaya"] - ["Ryota Kayanuma", "https://github.com/PicoSushi"] -filename: learnpython3-jp.py +filename: learnpython-jp.py lang: ja-jp --- @@ -21,7 +21,7 @@ lang: ja-jp フィードバッグは大歓迎です! [@louiedinh](http://twitter.com/louiedinh) または louiedinh [at] [google's email service] にご連絡下さい! -Note: この記事はPython 3に内容を絞っています。もし古いPython 2.7を学習したいなら、 [こちら](http://learnxinyminutes.com/docs/python/) をご確認下さい。 +Note: この記事はPython 3に内容を絞っています。もし古いPython 2.7を学習したいなら、 [こちら](http://learnxinyminutes.com/docs/pythonlegacy/) をご確認下さい。 ```python # 1行のコメントは番号記号(#)から始まります。 @@ -160,8 +160,8 @@ len("This is a string") # => 16 name = "Reiko" f"She said her name is {name}." # => "She said her name is Reiko" -# 基本的に、任意のPythonの文を中括弧に書くことができ、それは評価されて出力されます。 -f"{name} is {len(name)} characters long." +# 基本的に、任意のPythonの文を中括弧に書くことができ、それは文字列で出力されます。 +f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." # None はオブジェクトです(大文字からです!) None # => None @@ -191,7 +191,7 @@ print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! print("Hello, World", end="!") # => Hello, World! # コンソールから入力を得るための簡単な例 -input_string_var = input("Enter some data: ") # 入力を文字列として返します +input_string_var = input("Enter some data: ") # 入力を文字列として返します。 # Note: Python の初期のバージョンでは、 input() は raw_input() という名前で存在します。 # Pythonでは変数の宣言は存在せず、代入のみです。 @@ -201,7 +201,7 @@ some_var # => 5 # 代入されていない変数へのアクセスは例外を引き起こします。 # 例外の取り扱いについては、3章の制御の流れをご確認ください。 -some_unknown_var # NameError を送出します +some_unknown_var # NameError を送出します。 # ifは式として使用できます。 # C言語の「?:(三項演算子)」に対応する例: @@ -228,7 +228,7 @@ li[0] # => 1 li[-1] # => 3 # 範囲外の要素を参照すると IndexError になります。 -li[4] # IndexError が発生します +li[4] # IndexError が発生します。 # スライス構文により範囲を参照できます。 # 開始部分のインデックスに対応する部分は含まれますが、終了部分のインデックスに対応する部分は含まれません。 @@ -238,28 +238,28 @@ li[2:] # => [4, 3] # 末尾を取り除いたリスト li[:3] # => [1, 2, 4] # 1つ飛ばしで選択する -li[::2] # =>[1, 4] +li[::2] # => [1, 4] # 反転したリストを得る li[::-1] # => [3, 4, 2, 1] # これらの任意の組み合わせにより、より複雑なスライスを作ることができます。 # li[start:end:step] # スライスにより、深いコピーを1階層分行うことができます。 -li2 = li[:] # => li2 = [1, 2, 4, 3] だが、 (li2 is li) はFalseになる。 +li2 = li[:] # => li2 = [1, 2, 4, 3] だが、 (li2 is li) は False になる。 # "del"によりリストから任意の要素を削除できます。 del li[2] # li は [1, 2, 3] になりました。 # "remove"で最初に出現する要素を削除できます。 li.remove(2) # li は [1, 3] になりました。 -li.remove(2) # 2はリストの中に存在しないので、 ValueError が発生します。 +li.remove(2) # 2 はリストの中に存在しないので、 ValueError が発生します。 # 要素を好きなところに挿入できます。 li.insert(1, 2) # li は [1, 2, 3] に戻りました。 # "index"で引数の要素が最初に出現する場所のインデックスを得られます。 li.index(2) # => 1 -li.index(4) # 4はリストの中に存在しないので、 ValueError が発生します。 +li.index(4) # 4 はリストの中に存在しないので、 ValueError が発生します。 # リスト同士を足すこともできます。 # Note: li と other_li の値は変更されません。 @@ -295,11 +295,11 @@ tup[:2] # => (1, 2) # タプルやリストから複数の変数に代入することができます。 a, b, c = (1, 2, 3) # a, b, c にはそれぞれ 1, 2, 3 が代入されました。 # 拡張記法もあります。 -a, *b, c = (1, 2, 3, 4) # a は 1 、 b は [2, 3] 、c は4 になります。 +a, *b, c = (1, 2, 3, 4) # a は 1、 b は [2, 3]、c は 4 になります。 # 括弧を作成しなくてもデフォルトでタプルが作成されます。 d, e, f = 4, 5, 6 # 4、5、6がそれぞれd、 e、 fに代入されます。 # 2つの変数を交換するのがどれほど簡単か見てみましょう。 -e, d = d, e # d は 5 、 e は e になります。 +e, d = d, e # d は 5、 e は 4 になります。 # 辞書はマップ(キーと値の組み合わせ)を保存できます。 @@ -373,7 +373,7 @@ valid_set = {(1,), 1} filled_set = some_set filled_set.add(5) # filled_set は {1, 2, 3, 4, 5} になりました。 # 集合は重複した要素を持ちません。 -filled_set.add(5) # 以前の{1, 2, 3, 4, 5}のままです。 +filled_set.add(5) # 以前の {1, 2, 3, 4, 5} のままです。 # & により、集合同士の共通部分が得られます。 other_set = {3, 4, 5, 6} @@ -453,7 +453,7 @@ for i in range(4, 8): """ "range(lower, upper, step)" は、lower の数値から upper の数値までが、 -step 刻みで表現されるiterableを返します +step 刻みで表現されるiterableを返します。 step が与えられない場合、デフォルトは1になります。 出力: 4 @@ -552,7 +552,7 @@ varargs(1, 2, 3) # => (1, 2, 3) def keyword_args(**kwargs): return kwargs -# 何が起こるか、試してみましょう +# 何が起こるか、試してみましょう。 keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} @@ -591,7 +591,7 @@ x = 5 def set_x(num): - # ローカル変数の x はグローバル変数の x とは異なります + # ローカル変数の x はグローバル変数の x とは異なります。 x = num # => 43 print(x) # => 43 @@ -783,7 +783,7 @@ if __name__ == '__main__': from human import Human -# 親クラスを子クラスのパラメータとして指定します +# 親クラスを子クラスのパラメータとして指定します。 class Superhero(Human): # もし子クラスが親クラスの全ての定義を変更なしで継承する場合、"pass"キーワードのみを書くだけで良いです。 diff --git a/ja-jp/vim-jp.html.markdown b/ja-jp/vim-jp.html.markdown new file mode 100644 index 00000000..1d9867ca --- /dev/null +++ b/ja-jp/vim-jp.html.markdown @@ -0,0 +1,275 @@ +--- +category: tool +tool: vim +contributors: + - ["RadhikaG", "https://github.com/RadhikaG"] +translators: + - ["Kota Kato", "https://github.com/kato-k"] +filename: LearnVim-jp.txt +lang: ja-jp +--- + + +[Vim](http://www.vim.org) +(Vi IMproved) は、Unix用の人気なエディタである vi のクローンです。 +これは、速度と生産性を高めることを目的に設計されたエディタであり、 +ほとんどのUnix互換のシステムに組込まれています。 +ファイル内の特定の位置に移動したり、素早く編集したりするための多数のキーバインドを持ちます。 + +`vimtutor`はあなたに`Vim`の使い方を教える素晴しいアプリケーションです。 +Vimパッケージのインストール時に一緒に付属しますので、 +コマンドラインで「vimtutor」を実行するだけで、このチュートリアルを開けるはずです。 +これは、`vim`の全ての主要機能を説明します。 + +訳注) 日本語で`vimtutor`を利用するには、「vimtutor ja」を実行しなければならない場合があります。 + +## 基本のVim操作 + +``` + vim <filename> # <filename>をVimで開く + :help <topic> # <topic>についての組み込みドキュメントが存在する場合、 + # それを開く + :q # Vimを終了する + :w # 編集中のファイルを保存する + :wq # ファイルを保存して、Vimを終了する + ZZ # ファイルを保存して、Vimを終了する。:xと同様 + :q! # ファイルを保存せずにVimを終了する + # :q を ! *強制的に* 実行するため保存せずにVimが終了します + ZQ # ファイルを保存せずにVimを終了する + :x # 変更点がある時、ファイルを保存してVimを終了する + + u # Undo + CTRL+R # Redo + + h # 左に一文字移動 + j # 一行下に移動 + k # 一行上に移動 + l # 右に一文字移動 + + Ctrl+B # ウィンドウを一画面上に移動 + Ctrl+F # ウィンドウを一画面下に移動 + Ctrl+D # ウィンドウを半画面上に移動 + Ctrl+U # ウィンドウを半画面下に移動 + + # 行内を移動する + + 0 # 行頭に移動 + $ # 行末に移動 + ^ # 行の初めの非空白文字に移動 + + # テキストの検索 + + /word # カーソル以降に出現する全ての一致をハイライト + ?word # カーソル以前に出現する全ての一致をハイライト + n # カーソルを次の一致に移動 + N # カーソルを前の一致に移動 + + :%s/foo/bar/g # 全ての行について「foo」を「bar」に置換 + :s/foo/bar/g # 現在の行について「foo」を「bar」に置換 + :%s/\n/\r/g # 改行文字の置換 + + # 文字への移動 + + f<character> # 前方の<character>に移動する + t<character> # 前方の<character>の一文字前に移動する + + # 例 + f< # 前方の < に移動 + t< # 前方の < の一文字前に移動 + + # 単語ごとの移動 + + w # 一単語前に移動 + b # 一単語後ろに移動 + e # 現在の単語の後部に移動 + + # 移動のためのキーバインド + + gg # ファイルの先頭に移動 + G # ファイルの最後に移動 + :NUM # ファイルのNUM行に移動(NUMは任意の行数) + H # カーソルをウィンドウ上部に移動 + M # カーソルをウィンドウ中央に移動 + L # カーソルをウィンドウ下部に移動 +``` + +## ヘルプドキュメント: + +Vimには`:help <topic>`でアクセスできるヘルプドキュメントが組込まれています。 +例えば、`:help navigation`はカーソルを移動する方法についてのドキュメントを開きます。 + +`:help`はオプション無しでも利用できます。 +これにより、Vimにより親しみやすくすることを目的としたデフォルトのヘルプダイアログが開かれます。 + +## モード: + +Vimは**モード**の概念に基づいています。 + +- Command Mode - Vimはこのモードで起動し、移動とコマンドの実行に使われます +- Insert Mode - ファイルに変更を加えるのに使われます +- Visual Mode - テキストをハイライトしてオペレータを適用するために使われます +- Ex Mode - コマンドを入力するための「:」プロンプトで使われます + +``` + i # カーソル位置の前からInsert Modeに入る + a # カーソル位置の後ろからInsert Modeに入る + v # Visual Modeに入る + : # Ex Modeに入る + <esc> # 現在のモードからコマンドモードに「脱出」 + + # テキストのコピーと貼り付け + + y # 選択された対象をヤンクする + yy # 現在の行をヤンクする + d # 選択された対象を削除する + dd # 現在の行を削除する + p # ヤンクされたテキストをカーソルの後ろに貼り付ける + P # ヤンクされたテキストをのカーソルの前に貼り付ける + x # カーソル位置の文字を削除 +``` + +## Vimの「文法」 + +Vimの操作は「動詞・修飾子・名詞」形式のコマンドとして考えることができます。 + +- 動詞 - 動作 +- 修飾子 - 動作の実行方法 +- 名詞 - 動作が作用するオブジェクト + +「動詞・修飾子・名詞」関するいくつかの重要な例: + +``` + # '動詞' + + d # 削除 + c # 変更 + y # ヤンク (コピー) + v # ビジュアル選択 + + # '修飾子' + + i # 内部 + a # 周り + NUM # 回数 (NUMは任意の番号) + f # 任意の一文字まで + t # 任意の一文字の手前まで + / # カーソル以降の任意の文字列まで + ? # カーソル以前の任意の文字列まで + + # '名詞' + + w # 単語 + s # 文 + p # 段落 + b # ブロック + + # 「文」の例 + + d2w # 削除 2 単語 (2単語を削除) + cis # 変更 内部 文 (文の内部を変更) + yip # ヤンク 内部 段落 (段落の内部をヤンク) + ct< # 変更 手前 < (<の手前まで変更) + d$ # 削除 行末まで (行末まで削除) +``` + +## いくつかのショートカットと小技 + + <!--TODO: Add more!--> +``` + > # 選択部を1ブロックインデント + < # 選択部を1ブロックデインデント + :earlier 15m # ファイルを15分前の状態に戻す + :later 15m # 上記のコマンドの逆 + ddp # 連続する行を入れ替え + . # 前回の動作を繰り返す + :w !sudo tee % # 編集中のファイルを管理者として保存 + :set syntax=c # 「C言語」のシンタックスハイライトを利用する + :sort # 全ての行をソートする + :sort! # 全ての行を降順にソートする + :sort u # 全ての行をソートして重複を削除する + ~ # 選択部分の大文字小文字を入れ替える + u # 選択部分を小文字にする + U # 選択部分を大文字にする + J # 現在の行と次の行を結合する + + # テキストの折り畳み + zf # 選択したテキストを折り畳む + zo # 折り畳みを開く + zc # 折り畳みを閉じる + zR # 全ての折り畳みを開く + zM # 全ての折り畳みを閉じる +``` + +## マクロ + +マクロは基本的に記録可能なアクションです。 +マクロの記録を開始すると、記録を停止するまで**全て**の操作とコマンドが記録されます。 +マクロを呼びだすと、まったく同じ一連の操作とコマンドが文書に再度適用されます。 + +``` + qa # 「a」という名前のマクロの記録を開始する + q # 記録を停止する + @a # 「a」マクロを再生する +``` + +### ~/.vimrc の設定 + +ファイル.vimrcは起動時にVimの設定として利用されます + +次は~/.vimrcファイルのサンプルです + +``` +" Example ~/.vimrc +" 2015.10 + +" Required for vim to be iMproved +set nocompatible + +" 自動インデントなどを利用するために、ファイル名からファイルタイプを決定する +filetype indent plugin on + +" シンタックスハイライトを利用する +syntax on + +" より良いコマンドライン補完 +set wildmenu + +" 大文字を利用しない場合、検索で大文字・小文字を区別しない +set ignorecase +set smartcase + +" ファイル固有のインデントが有効でない場合、現在行のインデントを継続する +set autoindent + +" 行番号の表示 +set number + +" インデントに関するオプション + +" TAB文字の幅 +set tabstop=4 + +" 編集中TABキーを押した際の挙動 +set softtabstop=4 + +" << >> を利用した再インデント時のスペースの数 +set shiftwidth=4 + +" TABキーをスペースに変換する +set expandtab + +" 賢いTAB機能を有効にする +set smarttab +``` + +### 参考文献 + +[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? (Stack Overflow thread)](http://stackoverflow.com/questions/726894/what-are-the-dark-corners-of-vim-your-mom-never-told-you-about) + +[Arch Linux Wiki](https://wiki.archlinux.org/index.php/Vim) diff --git a/ja-jp/yaml-jp.html.markdown b/ja-jp/yaml-jp.html.markdown new file mode 100644 index 00000000..28a5d870 --- /dev/null +++ b/ja-jp/yaml-jp.html.markdown @@ -0,0 +1,193 @@ +--- +language: yaml +filename: learnyaml-jp.yaml +contributors: +- [Leigh Brenecki, 'https://leigh.net.au'] +- [Suhas SG, 'https://github.com/jargnar'] +translators: +- [haru, 'https://haru52.com/'] +lang: ja-jp +--- + +YAMLはデータのシリアライズ用言語で、 +人間が直接読み書きしやすいようにデザインされています。 + +YAMLはJSONの厳格なスーパーセットで、 +改行とインデントが構文的に意味を持つというPythonに似た仕様を追加しています。 +しかしPythonとは異なりYAMLではインデントにタブ文字を使うことはできません。 + +```yaml +--- # ドキュメント開始 + +# YAMLのコメントはこんな感じです。 + +############## +# スカラー型 # +############## + +# (ドキュメント全体を含む)ルートオブジェクトはマップになります。 +# これは他言語における辞書型、ハッシュ、オブジェクトなどと等価です。 +キー: 値 +別のキー: 別の値。 +数値: 100 +指数表記: 1e+12 +# 1 はbooleanでなく数値として解釈されます。 +# もしbooleanとして解釈してほしい場合はtrueを使います +boolean: true +null値: null +スペースを 含む キー: 値 +# 文字列をクォートで囲う必要がないことに注意してください。 +# しかし囲うこともできます。 +しかし: 'クォートで囲まれた文字列。' +'キーもクォートで囲えます。': "keyの中で ':' を使いたいときに有用です。" +シングルクォート: 'には ''1つの'' エスケープパターンがあります' +ダブルクォート: "には多くのエスケープパターンがあります:\", \0, \t, \u263A, +\x0d\x0a == \r\n, など、他にもあります。" +# UTF-8/16/32文字はエンコードされている必要があります +上付き2: \u00B2 + +# 複数行の文字列は(| を使う)「リテラルブロック」、 +# または、('>' を使う)「折り畳みブロック」として書くことができます +リテラルブロック: | + この文章のブロック全体が「リテラルブロック」キーの値になり、 + 改行は保持されます。 + + リテラルはインデントを解除するまで続き、先頭行のインデント文字数分を + 各行のテキストの先頭から取り除きます。 + + 「よりインデントの深い」行はその分のインデントを保持します - + この2行はスペース4個分インデントされます。 +折り畳みスタイル: > + この文章のブロック全体が「折り畳みスタイル」の値になります。 + しかしこちらの場合、全ての改行がスペース1個に置き換わります。 + + 直前のような空行は改行文字に変換されます。 + + 「よりインデントの深い」行も改行を保持します - + このテキストは2行にわたって表示されます。 + +################## +# コレクション型 # +################## + +# 入れ子を表現するにはインデントを使います。 +# スペース2個のインデントが好まれます(が必須ではありません)。 +入れ子のマップ: + キー: 値 + 別のキー: 別の値 + 別の入れ子のマップ: + こんにちは: こんにちは + +# マップのキーは文字列である必要はありません。 +0.25: 小数のキー + +# 複数行オブジェクトのような複雑なキーも使用可能です。 +# ? の後にスペースを入れることで複雑なキーの開始を宣言できます。 +? | + これはキーです + 複数行あります +: そしてこれがその値です + +# YAMLではシーケンスを複雑なキー構文で使うこともできます +# しかし、言語パーサーによってはエラーになるかもしれません +# 例 +? - マンチェスター・ユナイテッド + - レアル・マドリード +: [2001-01-01, 2002-02-02] + +# シーケンス(リストや配列と等価)はこんな感じです +# ('-' はインデントとしてカウントしてください): +シーケンス: + - アイテム1 + - アイテム2 + - 0.5 # シーケンスには異なる型の値を混在させられます + - アイテム4 + - キー: 値 + 別のキー: 別の値 + - + - これはシーケンスです + - 別のシーケンス内部 + - - - 入れ子のシーケンス表記は + - 折り畳めます + +# YAMLはJSONのスーパーセットなので、 +# JSON形式のマップとシーケンスを書くこともできます: +jsonマップ: {"キー": "値"} +jsonシーケンス: [3, 2, 1, "発進"] +クォートは任意: {キー: [3, 2, 1, 発進]} + +###################### +# その他のYAMLの機能 # +###################### + +# YAMLには「アンカー」と呼ばれる便利な機能もあります。これによりコンテンツを +# ドキュメント内で簡単に複製できます。これらのキーはどちらも同じ値を持ちます: +アンカーされたコンテンツ: &anchor_name この文字列は2つのキーの値になります。 +他のアンカー: *anchor_name + +# アンカーは複製/継承プロパティとして使えます +ベース: &base + 名前: みんな同じ名前を持ちます + +# 記号 << はマージキー言語非依存型(Merge Key Language-Independent Type) +# と呼ばれます。これは指定された1つ以上のマップの全てのキーを現在のマップに +# 挿入することを示すために使われます。 + +foo: + <<: *base + 年齢: 10 + +bar: + <<: *base + 年齢: 20 + +# fooとbarも「名前: みんな同じ名前を持ちます」を持ちます + +# YAMLにはタグもあり、明示的に型を宣言できます。 +明示的な文字列: !!str 0.5 +# 言語特有のタグを実装したパーサーもあり、例えばPythonの複素数型が使えます。 +pythonの複素数型: !!python/complex 1+2j + +# YAMLの複雑なキーでは言語特有のタグも使えます +? !!python/tuple [5, 7] +: 五十七 +# Python上で {(5, 7): '五十七'} として扱われます + +#################### +# その他のYAMLの型 # +#################### + +# 文字列と数値がYAMLの理解できる唯一のスカラーではありません。 +# ISO形式の日付や日時リテラルもパースされます。 +日時: 2001-12-15T02:59:43.1Z +スペースを含む日時: 2001-12-14 21:59:43.10 -5 +日付: 2002-12-14 + +# !!binaryタグは文字列の実体がバイナリblobのbase64エンコード表現であることを +# 示します。 +gifファイル: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + +# YAMLにはセット型もあり、それはこんな感じです: +セット: + ? アイテム1 + ? アイテム2 + ? アイテム3 +または: {アイテム1, アイテム2, アイテム3} + +# セットは値がnullのただのマップで、直前のセットは以下と等価です: +セット2: + アイテム1: null + アイテム2: null + アイテム3: null + +... # ドキュメント終了 +``` + +### 補足資料 + ++ [YAML公式ウェブサイト](https://yaml.org/) ++ [オンラインYAMLバリデーター](http://www.yamllint.com/) diff --git a/janet.html.markdown b/janet.html.markdown new file mode 100644 index 00000000..62ed7331 --- /dev/null +++ b/janet.html.markdown @@ -0,0 +1,331 @@ +--- +language: Janet +filename: learnJanet.janet +contributors: + - ["John Gabriele", "http://www.unexpected-vortices.com/"] +--- + +[Janet](https://janet-lang.org/) is a Lisp-like (Clojure-like), +lexically-scoped, dynamically-typed, garbage-collected, C-based, high-level +language. The entire language (core library, interpreter, compiler, assembler, +PEG) is about 300-500 kB and should run on many constrained systems. + +I encourage you to try out the code snippets below in the Janet +repl (either by [installing Janet](https://janet-lang.org/docs/index.html), +or else by using the repl embedded in the Janet homepage). + +As we only have a scant *y* minutes, we'll survey the basics here and +leave the remaining details for the manual. So please, keep your arms and +legs inside the vehicle at all times, and on with the scenic tour! + +```python +# A comment. + +# Some literal values. +true +false +nil + +# Typical style for symbols (identifiers-for / names-of things). +do-stuff +pants-on-fire! +foo->bar # Evidently for converting foos to bars. +fully-charged? +_ # Usually used as a dummy variable. + +# Keywords are like symbols that start with a colon, are treated like +# constants, and are typically used as map keys or pieces of syntax in +# macros. +:a +:some-val + +# Numbers ##################################################################### +5 +1e3 # => 1000 +1_000 # => 1000 +2e-03 # => 0.002 +0xff # => 255 + +# You can specify a radix (base) like so: +16rff # => 255 (same as 0xff) +2r1101 # => 13 + +# Some numbers in the math library: +math/pi # => 3.14159 +math/e # => 2.71828 + +# Strings ##################################################################### +"hello" +"hey\tthere" # contains a tab + +# For multi-line strings, use one or more backticks. Backslash-escapes not +# recognized in these (bytes will be parsed literally). +``a long +multi-line +string`` # => "a long\nmulti-line\nstring" + +# Strings and data structures in Janet come in two varieties: mutable and +# immutable. The literal for the mutable variety is written with a `@` in +# front of it. + +# A mutable string (aka "buffer"). +@"this" +@`a multi-line +one here` + +(string "con" "cat" "enate") # => "concatenate" + +# To get a substring: +(string/slice "abcdefgh" 2 5) # => "cde" +# To find a substring: +(string/find "de" "abcdefgh") # => 3 + +# See the string library for more (splitting, replacement, etc.) + +# Data Structures ############################################################# +# Arrays and Tuples +# Arrays are mutable, tuples are immutable. + +# Arrays (mutable) +@(4 5 6) +@[4 5 6] + +# Tuples (immutable) +# Note that an open paren usually indicates a function call, so if you want a +# literal tuple with parens, you need to "quote" it (with a starting single +# quote mark)... +'(4 5 6) +[4 5 6] # ... or just use square brackets. + +# Tables and Structs (associative data structures) +@{:a 1 :b 2 :c 3} # table (mutable) +{:a 1 :b 2 :c 3} # struct (immutable) + +# To "pretty-print" these out, use `pp` instead of `print`. +# More about how to work with arrays/tuples and tables/structs below. + +# Bindings #################################################################### +# Bind a value to a symbol. +(def x 4.7) # Define a constant, `x`. +x # => 4.7 +(quote x) # => x (the symbol x) +'x # => x (the symbol x (shorthand)) +(print x) # prints 4.7 + +# Since we used `def`, can't change to what `x` refers: +(set x 5.6) # Error, `x` is a constant. + +(var y 10) +(set y 12) # Works, since `y` was defined using `var`. + +# Note that bindings are local to the scope they're called in. `let` +# creates a local scope and makes some bindings all in one shot: +(let [a 2 + b 3] + (print "Hello from inside this local scope.") + (* a b)) # => 6 + +# Destructuring is supported, both for arrays/tuples ... +(def a ["foos" "bars" "moos"]) +(let [[s1 _ s2] a] + (print s1 s2)) # foosmoos + +# ... and for tables/structs. +(def t {:a "ayy" :b "bee" :c "sea"}) +(let [{:a a :b b} t] + (print a b)) # ayybee + +# You can even destructure right in a `def`: +(def [aa1 aa2] a) +aa1 # => foos +aa2 # => bars + +(def {:c body-of-water :b insect-friend} t) +body-of-water # => sea +insect-friend # => bee + +# Note that keywords evaluate to themselves, whereas symbols evaluate +# to whatever value they're bound to (unless you quote them). + +# Operators ################################################################### +# Janet supports the usual ensemble of operators. +# +, -, *, /, and so on. Note: +(/ 5 3) # => 1.66667 +(% 5 3) # => 2 (remainder) +(- 5) # => -5 (or you can just write `-5`) + +(++ i) # increments (modifies `i`) +(-- i) # decrements +(+= i 3) # add 3 to `i` +(*= i 3) # triple `i` +# ... and so on for the other operations on numbers. + +# If you don't want to mutate `i`, use `(inc i)` and `(dec i)`. + +# Comparison +# = < > not= <= >= +(< 2 7 12) # => true + +# Functions ################################################################### +# Call them: +(- 5 3) # => 2 (Operators and functions work the same way.) +(math/sin (/ math/pi 2)) # => 1 +(range 5) # => @[0 1 2 3 4] + +# Create them: +(defn mult-by-2 + ``First line of docstring. + + Some more of the docstring.`` + [x] + (print "Hi.") + (print "Will compute using: " x) + (* 2 x)) + +(print (mult-by-2 6)) # => 12 (after printing "Hi" and so forth) + +# If you have a function named "main" in your file, `janet` will automatically +# call it for you when you run the file. + +# Interactively read a function's docs from within the repl: +(doc mult-by-2) + +# Note, functions have to be defined before they can be used in a function, +# so if you design top-down, you'll need to write your functions from the +# bottom of the file up. + +# You can make anonymous functions as well: +(fn [x] (+ x x)) +(fn my-func [x] (+ x x)) # This one's less anonymous. + +# Use `do` to make some side-effecting calls and then evaluate to +# the last form in the `do`: +(def n (do + (print "hi") + (do-some-side-effecting 42) + 3)) +n # => 3 + +# You might say that function bodies provide an "implicit do". + +# Operations on data structures ############################################### +# (Making all of these mutable so we can ... mutate them.) +(def s @"Hello, World!") +(def a @[:a :b :c :d :e]) +(def t @{:a 1 :b 2}) + +(length s) # => 13 +(length a) # => 5 +(length t) # => 2 + +# Getting values: +(s 7) # => 87 (which is the code point for "W") +(a 1) # => :b +(t :a) # => 1 +(keys t) # => @[:a :b] +(values t) # => @[1 2] + +# Changing values (for mutable data structures): +(put s 2 87) # @"HeWlo, World!" +(put a 2 :x) # @[:a :b :x :d :e] +(put t :b 42) # @{:a 1 :b 42} + +# Adding and removing values (again, for mutable data structures): +(buffer/push-string s "??") # @"HeWlo, World!??" +(array/push a :f) # @[:a :b :x :d :e :f] +(array/pop a) # => :f, and it's also removed from `a`. +(put t :x 88) # @{:a 1 :b 42 :x 88} + +# See the manual for a wide variety of functions for working with +# buffers/strings, arrays/tuples, and tables/structs. + +# Flow control ################################################################ +(if some-condition + 42 + 38) + +# Only `nil` and `false` are falsey. Everything else is truthy. + +(if got-it? + 71) # No false-branch value. Returns `nil` if `got-it?` is falsey. + +(var i 10) +(while (pos? i) + (print "... " i) + (-- i)) +# Now `i` is 0. + +# `case` compares the dispatch value to each of the options. +(var x 2) +(case x + 1 "won" + 2 "too" + 3 "tree" + "unknown") # => "too" + +# `cond` evaluates conditions until it gets a `true`. +(set x 8) +(cond + (= x 1) "won" + (= x 2) "too" + (< x 10) "tree" + "oof!") # => "tree" + +(when (avoided-wipeout?) + (do-side-effecty-thing 88) + (smell-the-roses) + (paint-fencepost-error)) + +# Pattern matching. +# `match` is like a high-powered switch expression. If you switch on a data +# structure, it can look inside to try and match on its contents. For example, +# matching on a table or struct: +(def t {:a 1 :b 2 :c 3}) +(match t + {:yar v} (print "matches key :yar! " v) + {:moo v} (print "matches key :moo! " v) + {:c v} (print "matches key :c! " v) + _ (print "no match")) # => prints "matches key :c! 3" + +# Iterating ################################################################### +# Iterate over an integer range: +(for i 0 5 + (print i)) # prints 0, 1, 2, 3, 4 + +# There's also the more general `loop`: +(loop [i :range [0 10] :when (even? i)] + (print i)) + +# Loop over an array/tuple: +(def words ["foo" "bar" "baz"]) +(each word words + (print word)) + +# Loop over a table/struct: +(def t {:a 1 :b 2}) +(eachp [k v] t # Loop over each pair in `t`. + (print k " --> " v)) + +# Can also use `eachk` to loop over keys in a table or struct. + +# Functional programming ###################################################### +# You'll find many familiar old friends here. +(filter even? + (map (fn [x] + (* x x)) + (range 10))) # => @[0 4 16 36 64] + +(reduce + 0 (range 5)) # => 10 + +# ...and lots more (see the API docs). + +# Errata ###################################################################### +(type a) # => the type of `a` (as a keyword) +(describe a) # => a human-readable description of `a` +(string/format "%j" a) # => Janet values, nicely-formatted +``` + +This tour didn't cover a number of other features such as modules, fibers, +PEGs, macros, etc., but should give you a taste of what Janet is like. See +the [Janet manual](https://janet-lang.org/docs/index.html) and the [Janet API +docs](https://janet-lang.org/api/index.html) for more info. diff --git a/java.html.markdown b/java.html.markdown index ca0b04c2..7bf3fa0a 100644 --- a/java.html.markdown +++ b/java.html.markdown @@ -91,6 +91,9 @@ public class LearnJava { int numInt = scanner.nextInt(); // read long input + long numLong = scanner.nextLong(); + + // read float input float numFloat = scanner.nextFloat(); // read double input @@ -123,6 +126,9 @@ public class LearnJava { // <name1> = <name2> = <name3> = <val> int barInt1, barInt2, barInt3; barInt1 = barInt2 = barInt3 = 1; + // Shorthand for multiple declarations + int barInt4 = 1, barInt5 = 2; + /* * Variable types @@ -182,7 +188,7 @@ public class LearnJava { // // BigInteger is a data type that allows programmers to manipulate // integers longer than 64-bits. Integers are stored as an array of - // of bytes and are manipulated using functions built into BigInteger + // bytes and are manipulated using functions built into BigInteger // // BigInteger can be initialized using an array of bytes or a string. BigInteger fooBigInteger = new BigInteger(fooByteArray); @@ -289,7 +295,7 @@ public class LearnJava { // interface. This allows the execution time of basic // operations, such as get and insert element, to remain // constant-amortized even for large sets. - // TreeMap - A Map that is sorted by its keys. Each modification + // TreeMap - A Map that is sorted by its keys. Each modification // maintains the sorting defined by either a Comparator // supplied at instantiation, or comparisons of each Object // if they implement the Comparable interface. @@ -304,8 +310,8 @@ public class LearnJava { /////////////////////////////////////// System.out.println("\n->Operators"); - int i1 = 1, i2 = 2; // Shorthand for multiple declarations - + int i1 = 1, i2 = 2; + // Arithmetic is straightforward System.out.println("1+2 = " + (i1 + i2)); // => 3 System.out.println("2-1 = " + (i2 - i1)); // => 1 @@ -314,7 +320,7 @@ public class LearnJava { System.out.println("1/2.0 = " + (i1 / (double)i2)); // => 0.5 // Modulo - System.out.println("11%3 = "+(11 % 3)); // => 2 + System.out.println("11%3 = " + (11 % 3)); // => 2 // Comparison operators System.out.println("3 == 2? " + (3 == 2)); // => false @@ -368,7 +374,7 @@ public class LearnJava { // While loop int fooWhile = 0; - while(fooWhile < 100) { + while (fooWhile < 100) { System.out.println(fooWhile); // Increment the counter // Iterated 100 times, fooWhile 0,1,2...99 @@ -381,9 +387,9 @@ public class LearnJava { do { System.out.println(fooDoWhile); // Increment the counter - // Iterated 99 times, fooDoWhile 0->99 + // Iterated 100 times, fooDoWhile 0->99 fooDoWhile++; - } while(fooDoWhile < 100); + } while (fooDoWhile < 100); System.out.println("fooDoWhile Value: " + fooDoWhile); // For Loop @@ -470,11 +476,11 @@ public class LearnJava { // <second value>" int foo = 5; String bar = (foo < 10) ? "A" : "B"; - System.out.println("bar : " + bar); // Prints "bar : A", because the + System.out.println("bar : " + bar); // Prints "bar : A", because the // statement is true. // Or simply System.out.println("bar : " + (foo < 10 ? "A" : "B")); - + //////////////////////////////////////// // Converting Data Types @@ -510,10 +516,12 @@ public class LearnJava { // toString returns this Object's string representation. System.out.println("trek info: " + trek.toString()); + } // End main method + private static class TestInitialization { // Double Brace Initialization - // The Java Language has no syntax for how to create static Collections - // in an easy way. Usually you end up in the following way: + // Before Java 11, the Java Language had no syntax for how to create + // static Collections in an easy way. Usually you end up like this: private static final Set<String> COUNTRIES = new HashSet<String>(); static { COUNTRIES.add("DENMARK"); @@ -521,10 +529,10 @@ public class LearnJava { COUNTRIES.add("FINLAND"); } - // But there's a nifty way to achieve the same thing in an - // easier way, by using something that is called Double Brace - // Initialization. - private static final Set<String> COUNTRIES = new HashSet<String>() {{ + // There's a nifty way to achieve the same thing, + // by using something that is called Double Brace Initialization. + private static final Set<String> COUNTRIES_DOUBLE_BRACE = + new HashSet<String>() {{ add("DENMARK"); add("SWEDEN"); add("FINLAND"); @@ -535,8 +543,45 @@ public class LearnJava { // is called when the anonymous inner class is created. // This does not only work for Collections, it works for all // non-final classes. + - } // End main method + // Another option was to initialize the Collection from an array, + // using Arrays.asList() method: + private static final List<String> COUNTRIES_AS_LIST = + Arrays.asList("SWEDEN", "DENMARK", "NORWAY"); + // This has one catch: the list we get is internally backed by the array, + // and since arrays can't change their size, the list backed by the array + // is not resizeable, which means we can't add new elements to it: + public static void main(String[] args) { + COUNTRIES.add("FINLAND"); // throws UnsupportedOperationException! + // However, we can replace elements by index, just like in array: + COUNTRIES.set(1, "FINLAND"); + System.out.println(COUNTRIES); // prints [SWEDEN, FINLAND, NORWAY] + } + // The resizing problem can be circumvented + // by creating another Collection from the List: + private static final Set<String> COUNTRIES_SET = + new HashSet<>(Arrays.asList("SWEDEN", "DENMARK", "NORWAY")); + // It's perfectly fine to add anything to the Set of COUNTRIES now. + } // End TestInitialization class + + private static class TestJava11Initialization { + // Since Java 11, there is a convenient option to initialize Collections: + // Set.of() and List.of() methods. + private static final Set<String> COUNTRIES = + Set.of("SWEDEN", "DENMARK", "NORWAY"); + // There is a massive catch, though: Lists and Sets initialized like this + // 1) are immutable + // 2) can't contain null elements (even check for null elements fails)! + public static void main(String[] args) { + COUNTRIES.add("FINLAND"); // throws UnsupportedOperationException + COUNTRIES.remove("NORWAY"); // throws UnsupportedOperationException + COUNTRIES.contains(null); // throws NullPointerException + } + private static final Set<String> COUNTRIES_WITH_NULL = + Set.of("SWEDEN", null, "NORWAY"); // throws NullPointerException + + } // End TestJava11Initialization class } // End LearnJava class // You can include other, non-public outer-level classes in a .java file, @@ -918,7 +963,7 @@ public class Lambdas { planets.keySet().forEach(p -> System.out.format("%s\n", p)); // Tracing the above, we see that planets is a HashMap, keySet() returns - // a Set of its keys, forEach applies each element as the lambda + // a Set of its keys, forEach applies each element as the lambda // expression of: (parameter p) -> System.out.format("%s\n", p). Each // time, the element is said to be "consumed" and the statement(s) // referred to in the lambda body is applied. Remember the lambda body @@ -998,6 +1043,8 @@ The links provided here below are just to get an understanding of the topic, fee * [Codewars - Java Katas](https://www.codewars.com/?language=java) +* [University of Helsinki - Object-Oriented programming with Java](http://moocfi.github.io/courses/2013/programming-part-1/) + **Books**: * [Head First Java](http://www.headfirstlabs.com/books/hfjava/) diff --git a/javascript.html.markdown b/javascript.html.markdown index c466c09b..4e7c5c09 100644 --- a/javascript.html.markdown +++ b/javascript.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] filename: javascript.js --- @@ -105,6 +105,10 @@ false; "1, 2, " + 3; // = "1, 2, 3" "Hello " + ["world", "!"]; // = "Hello world,!" +// ...which can result in some weird behaviour... +13 + !0; // 14 +"13" + !0; // '13true' + // and are compared with < and > "a" < "b"; // = true @@ -116,10 +120,6 @@ null == undefined; // = true "5" === 5; // = false null === undefined; // = false -// ...which can result in some weird behaviour... -13 + !0; // 14 -"13" + !0; // '13true' - // You can access characters in a string with `charAt` "This is a string".charAt(0); // = 'T' @@ -188,7 +188,7 @@ someVar = myArray.pop(); // Remove last element and return it // Join all elements of an array with semicolon var myArray0 = [32,false,"js",12,56,90]; -myArray0.join(";") // = "32;false;js;12;56;90" +myArray0.join(";"); // = "32;false;js;12;56;90" // Get subarray of elements from index 1 (include) to 4 (exclude) myArray0.slice(1,4); // = [false,"js",12] @@ -405,7 +405,7 @@ myObj = { }; myObj.myFunc(); // = "Hello world!" -// What this is set to has to do with how the function is called, not where +// What `this` is set to has to do with how the function is called, not where // it's defined. So, our function doesn't work if it isn't called in the // context of the object. var myFunc = myObj.myFunc; @@ -586,6 +586,48 @@ if (Object.create === undefined){ // don't overwrite it if it exists return new Constructor(); }; } + +// ES6 Additions + +// The "let" keyword allows you to define variables in a lexical scope, +// as opposed to a function scope like the var keyword does. +let name = "Billy"; + +// Variables defined with let can be reassigned new values. +name = "William"; + +// The "const" keyword allows you to define a variable in a lexical scope +// like with let, but you cannot reassign the value once one has been assigned. + +const pi = 3.14; + +pi = 4.13; // You cannot do this. + +// There is a new syntax for functions in ES6 known as "lambda syntax". +// This allows functions to be defined in a lexical scope like with variables +// defined by const and let. + +const isEven = (number) => { + return number % 2 === 0; +}; + +isEven(7); // false + +// The "equivalent" of this function in the traditional syntax would look like this: + +function isEven(number) { + return number % 2 === 0; +}; + +// I put the word "equivalent" in double quotes because a function defined +// using the lambda syntax cannot be called before the definition. +// The following is an example of invalid usage: + +add(1, 8); + +const add = (firstNumber, secondNumber) => { + return firstNumber + secondNumber; +}; ``` ## Further Reading @@ -613,7 +655,7 @@ attached terminal [Javascript: The Right Way][10] is a guide intended to introduce new developers to JavaScript and help experienced developers learn more about its best practices. -[Javascript:Info][11] is a modern javascript tutorial covering the basics (core language and working with a browser) +[javascript.info][11] is a modern javascript tutorial covering the basics (core language and working with a browser) as well as advanced topics with concise explanations. @@ -629,6 +671,7 @@ Mozilla Developer Network. [5]: http://bonsaiden.github.io/JavaScript-Garden/ [6]: http://www.amazon.com/gp/product/0596805527/ [7]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript +[8]: https://www.javascripttutorial.net/ [8]: http://eloquentjavascript.net/ [10]: http://jstherightway.org/ [11]: https://javascript.info/ diff --git a/jinja.html.markdown b/jinja.html.markdown new file mode 100644 index 00000000..7e5b8e96 --- /dev/null +++ b/jinja.html.markdown @@ -0,0 +1,270 @@ +--- +language: Jinja +contributors: + - ["Adaías Magdiel", "https://github.com/AdaiasMagdiel"] +filename: learn-jinja.j2 +--- + +## Getting Started with Jinja + +Jinja is a fast, expressive, and extensible templating engine for Python +applications. + +Jinja includes a lot of functionalities, such as: +- Template inheritance and inclusion; +- Defining and importing macros within templates; +- Security mechanisms to prevent XSS attacks; +- A sandboxed environment that can safely render untrusted templates; +- Extensible filters, tests, functions, and even syntax. + +A Jinja template is simply a text file. Jinja doesn't require a specific +extension, but it's common to use `.j2` or `.jinja` to make it easier for +some IDEs. + +There are a few kinds of delimiters. The default Jinja delimiters are configured +as follows: + +- `{% ... %}` for Statements +- `{{ ... }}` for Expressions to print to the template output +- `{# ... #}` for Comments not included in the template output + +```jinja +{# This is an example of a comment. #} + +{# + You can use this syntax + to write multiline comments + as well. +#} +``` + + +## VARIABLES + +```jinja +{# You have the option to access variables from the context passed to the template #} + +{{ foo }} + +{# + Additionally, you can use a dot (.) to access attributes of a variable or + use Python syntax, using [] +#} + +{{ foo.bar }} +{{ foo['bar'] }} + +{# Within the template, you can define variables as well #} + +{% set name = "Magdiel" %} +{{ name }} +``` + +## Loops + +```html +<h1>Members</h1> +<ul> +{% for user in users %} + <li>{{ user.username }}</li> +{% endfor %} +</ul> + + +<div> +{% for key, value in my_dict.items() %} + <p>{{ key }}</p> - <p>{{ value }}</p> +{% endfor %} +</div> + + +<div> +{% for idx, url in enumerate(urls) %} + <a href="{{ url }}">Go to url {{ idx + 1 }}</a> +{% endfor %} +</div> +``` + +## Conditionals + +The if statement in Jinja is similar to the if statement in Python. It is +commonly used to check if a variable is defined, not empty, and not false in +its most basic form. + +```html +{% if users %} +<ul> +{% for user in users %} + <li>{{ user.username }}</li> +{% endfor %} +</ul> +{% endif %} + + +{# For multiple branches, elif and else can be used like in Python. #} + + +{% if message.status == "error" %} + <p class="text-red-400">{{ message.content }}</p> +{% elif message.status == "success" %} + <p class="text-green-400">{{ message.content }}</p> +{% else %} + <p class="text-blue-400">{{ message.content }}</p> +{% endif %} +``` + +## Template Inheritance + +One of the most powerful features of Jinja is template inheritance. You can +create a base layout with predefined blocks that you can extend in another file +and override with your own content. + +```html +{# file: base.html.j2 #} + +<!DOCTYPE html> +<html lang="en"> +<head> + {% block head %} + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{% block title %}{% endblock title %} - Learning Jinja</title> + {% endblock head %} +</head> +<body> + <main> + {% block content %}{% endblock %} + {# the endblock tag doesn't need the name of the block #} + </main> +</body> +</html> + + + +{# file: child.html.j2 #} + +{% extends "base.html.j2" %} + +{% block head %} + {{ super() }} + <script> + console.log("There's a console.log here") + </script> +{% endblock %} + +{% block title %}Home{% endblock %} + +{% block content %} + <h1>Index</h1> + <p>Welcome to my home homepage.</p> +{% endblock %} + + + +{# RESULT #} + +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Home - Learning Jinja</title> + <script> + console.log("There's a console.log here") + </script> +</head> +<body> + <main> + <h1>Index</h1> + <p>Welcome to my home homepage.</p> + </main> +</body> +</html> + +``` + +### Including Content + +You can include content from another template on your current template using +the `{% include "template/path" %}` tag. + +```html + +{# file: footer.html.j2 #} + +<footer> + <p>© 2024 - John Doe</p> +</footer> + + + +{# file: index.html.j2 #} +... +<body> + <main> + <h1>Hi! I'm John Doe!</h1> + </main> + {% include "footer.html.j2" %} +</body> +... + + + +{# RESULT #} + +... +<body> + <main> + <h1>Hi! I'm John Doe!</h1> + </main> + <footer> + <p>© 2024 - John Doe</p> + </footer> +</body> +... +``` + +Variables passed to the main template can also be used in the include, as the +included template has access to the context of the main template. + +```html +{# file: greetings.html.j2 #} + +<p>I'm the {{ name }} and i like to {{ hobby }}.</p> + + + +{# file: index.html.j2 #} + +{% set name = "Captain Nemo" %} +{% set hobby = "navigate through the depths of the ocean" %} + +<div> + {% include "greetings.html.j2" %} +</div> + + + +{# RESULT #} + +<div> + <p>I'm the Captain Nemo and i like to navigate through the depths of the ocean.</p> +</div> +``` + +## Macros + +Macros are basically like functions in another languages. You can define macros with or without arguments and reuse them in various parts of your template. + +```html +{% macro input(value="", type="text", placeholder="") -%} + <input type="{{ type }}" value="{{ value }}" placeholder="{{ placeholder }}"> +{%- endmacro %} + +<p>{{ input(placeholder="Your username") }}</p> +<p>{{ input(type="password") }}</p> +``` + +## Official Documentation + +To learn more, access the [official documentation](https://jinja.palletsprojects.com/en/). diff --git a/jq.html.markdown b/jq.html.markdown new file mode 100644 index 00000000..dded34cb --- /dev/null +++ b/jq.html.markdown @@ -0,0 +1,910 @@ +--- +category: tool +tool: jq +contributors: + - ["Jack Kuan", "https://github.com/kjkuan"] +filename: learnjq.sh +--- + +`jq` is a tool for transforming JSON inputs and generating JSON outputs. As a +programming language, jq supports boolean and arithmetic expressions, object +and array indexing; it has conditionals, functions, and even exception +handling... etc. Knowing jq enables you to easily write small programs that +can perform complex queries on JSON documents to find answers, make reports, or +to produce another JSON document for further processing by other programs. + +> **NOTE**: This guide demonstrates the use of jq from the command line, +> specifically, under an environment running the Bash shell. + +```bash +# When running jq from the command line, jq program code can be specified as the +# first argument after any options to `jq`. We often quote such jq program with +# single quotes (`'`) to prevent any special interpretation from the command line +# shell. +# +jq -n '# Comments start with # until the end of line. + # The -n option sets the input to the value, `null`, and prevents `jq` + # from reading inputs from external sources. +' + +# Output: +# null + + +# By default jq reads from *STDIN* a stream of JSON inputs (values). It +# processes each input with the jq program (filters) specified at the command +# line, and prints the outputs of processing each input with the program to +# *STDOUT*. +# +echo ' + "hello" 123 [ + "one", + "two", + "three" + ] + { "name": "jq" } +' | + jq '. # <-- the jq program here is the single dot (.), called the identity + # operator, which stands for the current input. +' + +# Output: +# "hello" +# 123 +# [ +# "one", +# "two", +# "three" +# ] +# { +# "name": "jq" +# } + + +# Notice that jq pretty-prints the outputs by default, therefore, piping +# to `jq` is a simple way to format a response from some REST API endpoint +# that returns JSON. E.g., `curl -s https://freegeoip.app/json/ | jq` + + +# Instead of processing each JSON input with a jq program, you can also +# ask jq to slurp them up as an array. +# +echo '1 "two" 3' | jq -s . + +# Output: +# [ +# 1, +# "two", +# 3 +# ] + + +# Or, treat each line as a string. +# +(echo line 1; echo line 2) | jq -R . + +# Output: +# "line 1" +# "line 2" + + +# Or, combine -s and -R to slurp the input lines into a single string. +# +(echo line 1; echo line 2) | jq -sR . + +# Output: +# "line 1\nline2\n" + + +# Inputs can also come from a JSON file specified at the command line: +# +echo '"hello"' > hello.json +jq . hello.json + +# Output: +# "hello" + + +# Passing a value into a jq program can be done with the `--arg` option. +# Below, `val` is the variable name to bind the value, `123`, to. +# The variable is then referenced as `$val`. +# +jq -n --arg val 123 '$val' # $val is the string "123" here + +# Output: +# "123" + + +# If you need to pass a JSON value, use `--argjson` +# +jq -n --argjson val 123 '$val' # $val is a number + +# Output: +# 123 + + +# Using `--arg` or `--argjson` is an useful way of building JSON output from +# existing input. +# +jq --arg text "$(date; echo "Have a nice day!")" -n '{ "today": $text }' + +# Output: +# { +# "today": "Sun Apr 10 09:53:07 PM EDT 2022\nHave a nice day!" +# } + + +# Instead of outputting values as JSON, you can use the `-r` option to print +# string values unquoted / unescaped. Non-string values are still printed as +# JSON. +# +echo '"hello" 2 [1, "two", null] {}' | jq -r . + +# Output: +# hello +# 2 +# [ +# 1, +# "two", +# null +# ] +# {} + + +# Inside a string in jq, `\(expr)` can be used to substitute the output of +# `expr` into the surrounding string context. +# +jq -rn '"1 + 2 = \(1+2)"' + +# Output: +# 1 + 2 = 3 + + +# The `-r` option is most useful for generating text outputs to be processed +# down in a shell pipeline, especially when combined with an intepolated +# string that is prefixed the `@sh` prefix operator. +# +# The `@sh` operator escapes the outputs of `\(...)` inside a string with +# single quotes so that each resulting string of `\(...)` can be evaluated +# by the shell as a single word / token / argument without special +# interpretations. +# +env_vars=$( + echo '{"var1": "value one", "var2": "value\ntwo"}' \ + | + jq -r ' + "export " + @sh "var1=\(.var1) var2=\(.var2)" + # ^^^^^^^^ ^^^^^^^^ + # "'value one'" "'value\ntwo'" + # + # NOTE: The + (plus) operator here concatenates strings. + ' +) +echo "$env_vars" +eval "$env_vars" +declare -p var1 var2 + +# Output: +# export var1='value one' var2='value +# two' +# declare -- var1="value one" +# declare -- var2="value +# two" + +# There are other string `@prefix` operators (e.g., @base64, @uri, @csv, ...) +# that might be useful to you. See `man jq` for details. + + +# The comma (`,`) operator in jq evaluates each operand and generates multiple +# outputs: +# +jq -n '"one", 2, ["three"], {"four": 4}' + +# Output: +# "one" +# 2 +# [ +# "three" +# ] +# { +# "four": 4 +# } + + +# Any JSON value is a valid jq expression that evaluates to the JSON value +# itself. +# +jq -n '1, "one", [1, 2], {"one": 1}, null, true, false' + +# Output: +# 1 +# "one" +# [ +# 1, +# 2 +# ] +# { +# "one": 1 +# } +# null +# true +# false + + +# Any jq expression can be used where a JSON value is expected, even as object +# keys. (though parenthesis might be required for object keys or values) +# +jq -n '[2*3, 8-1, 16/2], {("tw" + "o"): (1 + 1)}' + +# Output: +# [ +# 6, +# 7, +# 8 +# ] +# { +# "two": 2 +# } + + +# As a shortcut, if a JSON object key looks like a valid identifier (matching +# the regex `^[a-zA-Z_][a-zA-Z_0-9]*$`), quotes can be omitted. +# +jq -n '{ key_1: "value1" }' + +# If a JSON object's key's value is ommited, it is looked up in the current +# input using the key: (see next example for the meaning of `... | ...`) +# +jq -n '{c: 3} | {a: 1, "b", c}' + +# Output: +# { +# "a": 1, +# "b": null, +# "c": 3 +# } + + +# jq programs are more commonly written as a series of expressions (filters) +# connected by the pipe (`|`) operator, which makes the output of its left +# filter the input to its right filter. +# +jq -n '1 | . + 2 | . + 3' # first dot is 1; second dot is 3 + +# Output: +# 6 + +# If an expression evaluates to multiple outputs, then jq will iterate through +# them and propagate each output down the pipeline, and generate multiple +# outputs in the end. +# +jq -n '1, 2, 3 | ., 4 | .' + +# Output: +# 1 +# 4 +# 2 +# 4 +# 3 +# 4 + +# The flows of the data in the last example can be visualized like this: +# (number prefixed with `*` indicates the current output) +# +# *1, 2, 3 | *1, 4 | *1 +# 1, 2, 3 | 1, *4 | *4 +# 1, *2, 3 | *2, 4 | *2 +# 1, 2, 3 | 2, *4 | *4 +# 1, 2, *3 | *3, 4 | *3 +# 1, 2, 3 | 3, *4 | *4 +# +# +# To put it another way, the evaluation of the above example is very similar +# to the following pieces of code in other programming languages: +# +# In Python: +# +# for first_dot in 1, 2, 3: +# for second_dot in first_dot, 4: +# print(second_dot) +# +# In Ruby: +# +# [1, 2, 3].each do |dot| +# [dot, 4].each { |dot| puts dot } +# end +# +# In Javascript: +# +# [1, 2, 3].forEach(dot => { +# [dot, 4].forEach(dot => console.log(dot)) +# }) +# + + +# Below are some examples of array index and object attribute lookups using +# the `[expr]` operator after an expression. If `expr` is a number then it's +# an array index lookup; otherwise, it should be a string, in which case it's +# an object attribute lookup: + +# Array index lookup +# +jq -n '[2, {"four": 4}, 6][1 - 1]' # => 2 +jq -n '[2, {"four": 4}, 6][0]' # => 2 +jq -n '[2, {"four": 4}, 6] | .[0]' # => 2 + +# You can chain the lookups since they are just expressions. +# +jq -n '[2, {"four": 4}, 6][1]["fo" + "ur"]' # => 4 + +# For object attributes, you can also use the `.key` shortcut. +# +jq -n '[2, {"four": 4}, 6][1].four' # => 4 + +# Use `."key"` if the key is not a valid identifier. +# +jq -n '[2, {"f o u r": 4}, 6][1]."f o u r"' # => 4 + +# Array index lookup returns null if the index is not found. +# +jq -n '[2, {"four": 4}, 6][99]' # => null + +# Object attribute lookup returns null if the key is not found. +# +jq -n '[2, {"four": 4}, 6][1].whatever' # => null + +# The alternative operator `//` can be used to provide a default +# value when the result of the left operand is either `null` or `false`. +# +jq -n '.unknown_key // 7' # => 7 + +# If the thing before the lookup operator (`[expr]`) is neither an array +# or an object, then you will get an error: +# +jq -n '123 | .[0]' # => jq: error (at <unknown>): Cannot index number with number +jq -n '"abc" | .name' # => jq: error (at <unknown>): Cannot index string with string "name" +jq -n '{"a": 97} | .[0]' # => jq: error (at <unknown>): Cannot index object with number +jq -n '[89, 64] | .["key"]' # => jq: error (at <unknown>): Cannot index array with string "key" + +# You can, however, append a `?` to a lookup to make jq return `empty` +# instead when such error happens. +# +jq -n '123 | .[0]?' # no output since it's empty. +jq -n '"abc" | .name?' # no output since it's empty. + +# The alternative operator (`//`) also works with `empty`: +# +jq -n '123 | .[0]? // 99' # => 99 +jq -n '"abc" | .name? // "unknown"' # => "unknown" + +# NOTE: `empty` is actually a built-in function in jq. +# With the nested loop explanation we illustrated earlier before, +# `empty` is like the `continue` or the `next` keyword that skips +# the current iteration of the loop in some programming languages. + + +# Strings and arrays can be sliced with the same syntax (`[i:j]`, but no +# steppings) and semantic as found in the Python programming language: +# +# 0 1 2 3 4 5 ... infinite +# array = ["a", "b", "c", "d"] +# -infinite ... -4 -3 -2 -1 +# +jq -n '["Peter", "Jerry"][1]' # => "Jerry" +jq -n '["Peter", "Jerry"][-1]' # => "Jerry" +jq -n '["Peter", "Jerry", "Tom"][1:]' # => ["Jerry", "Tom"] +jq -n '["Peter", "Jerry", "Tom"][:1+1]' # => ["Peter", "Jerry"] +jq -n '["Peter", "Jerry", "Tom"][1:99]' # => ["Jerry", "Tom"] + + +# If the lookup index or key is ommited then jq iterates through +# the collection, generating one output value from each iteration. +# +# These examples produce the same outputs. +# +echo 1 2 3 | jq . +jq -n '1, 2, 3' +jq -n '[1, 2, 3][]' +jq -n '{a: 1, b: 2, c: 3}[]' + +# Output: +# 1 +# 2 +# 3 + + +# You can build an array out of multiple outputs. +# +jq -n '{values: [{a: 1, b: 2, c: 3}[] | . * 2]}' + +# Output: +# { +# "values": [ +# 2, +# 4, +# 6 +# ] +# } + + +# If multiple outputs are not contained, then we'd get multiple outputs +# in the end. +# +jq -n '{values: ({a: 1, b: 2, c: 3}[] | . * 2)}' + +# Output: +# { +# "values": 2 +# } +# { +# "values": 4 +# } +# { +# "values": 6 +# } + + +# Conditional `if ... then ... else ... end` in jq is an expression, so +# both the `then` part and the `else` part are required. In jq, only +# two values, `null` and `false`, are false; all other values are true. +# +jq -n 'if 1 > 2 | not and 1 <= 2 then "Makes sense" else "WAT?!" end' + +# Output +# "Makes sense" + +# Notice that `not` is a built-in function that takes zero arguments, +# that's why it's used as a filter to negate its input value. +# We'll talk about functions soon. + +# Another example using a conditional: +# +jq -n '1, 2, 3, 4, 5 | if . % 2 != 0 then . else empty end' + +# Output +# 1 +# 3 +# 5 + +# The `empty` above is a built-in function that takes 0 arguments and +# generates no outputs. Let's see more examples of built-in functions. + +# The above conditional example can be written using the `select/1` built-in +# function (`/1` indicates the number of arguments expected by the function). +# +jq -n '1, 2, 3, 4, 5 | select(. % 2 != 0)' # NOTE: % gives the remainder. + +# Output +# 1 +# 3 +# 5 + + +# Function arguments in jq are passed with call-by-name semantic, which +# means, an argument is not evaulated at call site, but instead, is +# treated as a lambda expression with the calling context of the call +# site as its scope for variable and function references used in the +# expression. +# +# In the above example, the expression `. % 2 != 0` is what's passed to +# `select/1` as the argument, not `true` or `false`, which is what would +# have been the case had the (boolean) expression was evaluated before it's +# passed to the function. + + +# The `range/1`, `range/2`, and `range/3` built-in functions generate +# integers within a given range. +# +jq -n '[range(3)]' # => [0, 1, 2] +jq -n '[range(0; 4)]' # => [0, 1, 2, 3] +jq -n '[range(2; 10; 2)]' # => [2, 4, 6, 8] + +# Notice that `;` (semicolon) is used to separate function arguments. + + +# The `map/1` function applies a given expression to each element of +# the current input (array) and outputs a new array. +# +jq -n '[range(1; 6) | select(. % 2 != 0)] | map(. * 2)' + +# Output: +# [ +# 2, +# 6, +# 10 +# ] + +# Without using `select/1` and `map/1`, we could have also written the +# above example like this: +# +jq -n '[range(1; 6) | if . % 2 != 0 then . else empty end | . * 2]' + + +# `keys/0` returns an array of keys of the current input. For an object, +# these are the object's attribute names; for an array, these are the +# array indices. +# +jq -n '[range(2; 10; 2)] | keys' # => [0, 1, 2, 3] +jq -n '{a: 1, b: 2, c: 3} | keys' # => ["a", "b", "c"] + +# `values/0` returns an array of values of the current input. For an object, +# these are the object's attribute values; for an array, these are the +# elements of the array. +# +jq -n '[range(2; 10; 2)] | values' # => [2, 4, 6, 8] +jq -n '{a: 1, b: 2, c: 3} | values' # => [1, 2, 3] + + +# `to_entries/0` returns an array of key-value objects of the current input +# object. +# +jq -n '{a: 1, b: 2, c: 3} | to_entries' + +# Output: +# [ +# { +# "key": "a", +# "value": 1 +# }, +# { +# "key": "b", +# "value": 2 +# }, +# { +# "key": "c", +# "value": 3 +# } +# ] + + +# Here's how you can turn an object's attribute into environment variables +# using what we have learned so far. +# +env_vars=$( + jq -rn '{var1: "1 2 3 4", var2: "line1\nline2\n"} + | to_entries[] + | "export " + @sh "\(.key)=\(.value)" + ' +) +eval "$env_vars" +declare -p var1 var2 + +# Output: +# declare -x var1="1 2 3 4" +# declare -x var2="line1 +# line2 +# " + + +# `from_entries/0` is the opposite of `to_entries/0` in that it takes an +# an array of key-value objects and turn that into an object with keys +# and values from the `key` and `value` attributes of the objects. +# +# It's useful together with `to_entries/0` when you need to iterate and +# do something to each attribute of an object. +# +jq -n '{a: 1, b: 2, c: 3} | to_entries | map(.value *= 2) | from_entries' + +# Output: +# { +# "a": 2, +# "b": 4, +# "c": 6 +# } + + +# The example above can be further shortened with the `with_entries/1` built-in: +# +jq -n '{a: 1, b: 2, c: 3} | with_entries(.value *= 2)' + + +# The `group_by/1` generates an array of groups (arrays) from the current +# input (array). The classification is done by applying the expression argument +# to each member of the input array. +# +# Let's look at a contrived example (Note that `tostring`, `tonumber`, +# `length` and `max` are all built-in jq functions. Feel free to look +# them up in the jq manual): +# +# Generate some random numbers. +numbers=$(echo $RANDOM{,,,,,,,,,,,,,,,,,,,,}) +# +# Feed the numbers to jq, classifying them into groups and calculating their +# averages, and finally generate a report. +# +echo $numbers | jq -rs ' # Slurp the numbers into an array. +[ + [ map(tostring) # Turn it into an array of strings. + | group_by(.[0:1]) # Group the numbers by their first digits. + | .[] # Iterate through the array of arrays (groups). + | map(tonumber) # Turn each group back to an array of numbers. + ] # Finally, contain all groups in an array. + + | sort_by([length, max]) # Sort the groups by their sizes. + # If two groups have the same size then the one with the largest + # number wins (is bigger). + + | to_entries[] # Enumerate the array, generating key-value objects. + | # For each object, generate two lines: + "Group \(.key): \(.value | sort | join(" "))" + "\n" + + "Average: \( .value | (add / length) )" + +] # Contain the group+average lines in an array. + # Join the array elements by separator lines (dashes) to produce the report. +| join("\n" + "-"*78 + "\n") +' + +# Output: +# +# Group 0: 3267 +# Average: 3267 +# ------------------------------------------------------------------------------ +# Group 1: 7854 +# Average: 7854 +# ------------------------------------------------------------------------------ +# Group 2: 4415 4447 +# Average: 4431 +# ------------------------------------------------------------------------------ +# Group 3: 681 6426 +# Average: 3553.5 +# ------------------------------------------------------------------------------ +# Group 4: 21263 21361 21801 21832 22947 23523 29174 +# Average: 23128.714285714286 +# ------------------------------------------------------------------------------ +# Group 5: 10373 12698 13132 13924 17444 17963 18934 18979 +# Average: 15430.875 + + +# The `add/1` built-in "reduces" an array of values to a single value. +# You can think of it as sticking the `+` operator in between each value of +# the collection. Here are some examples: +# +jq -n '[1, 2, 3, 4, 5] | add' # => 15 +jq -n '["a", "b", "c"] | add' # => "abc" + +# `+` concatenates arrays +jq -n '[["a"], ["b"], ["c"]] | add' + +# Output: +# [ +# "a", +# "b", +# "c" +# ] + +# `+` merges objects non-recursively. +jq -n '[{a: 1, b: {c: 3}}, {b: 2, c: 4}] | add' + +# Output: +# { +# "a": 1, +# "b": 2, +# "c": 4 +# } + + +# jq provides a special syntax for writing an expression that reduces +# the outputs generated by a given expresion to a single value. +# It has this form: +# +# reduce outputs_expr as $var (initial_value; reduction_expr) +# +# Examples: +# +jq -n 'reduce range(1; 6) as $i (0; . + $i)' # => 15 +jq -n 'reduce (1, 2, 3, 4, 5) as $i (0; . + $i)' # => 15 +jq -n '[1, 2, 3, 4, 5] | reduce .[] as $i (0; . + $i)' # => 15 +jq -n '["a", "b", "c"] | reduce .[] as $i (""; . + $i)' # => "abc" + +# Notice the `.` in the `reduction_expr` is the `initial_value` at first, +# and then it becomes the result of applying the `reduction_expr` as +# we iterate through the values of `outputs_expr`. The expression: +# +# reduce (1, 2, 3, 4, 5) as $i (0; . + $i) +# +# can be thought of as doing: +# +# 0 + 1 | . + 2 | . + 3 | . + 4 | . + 5 +# + + +# The `*` operator when used on two objects, merges both recursively. +# Therefore, to merge JSON objects recursively, you can use `reduce` +# with the `*` operator. For example: +# +echo ' + {"a": 1, "b": {"c": 3}} + { "b": {"d": 4}} + {"a": 99, "e": 5 } +' | jq -s 'reduce .[] as $m ({}; . * $m)' + +# Output: +# { +# "a": 99, +# "b": { +# "c": 3, +# "d": 4 +# }, +# "e": 5 +# } + + +# jq has variable assignment in the form of `expr as $var`, which binds +# the value of `expr` to `$var`, and `$var` is immutable. Further more, +# `... as ...` doesn't change the input of the next filter; its introduction +# in a filter pipeline is only for establishing the binding of a value to a +# variable, and its scope extends to the filters following its definition. +# (i.e., to look up a variable's definition, scan to the left of the filter +# chain from the expression using it until you find the definition) +# +jq -rn '[1, 2, 3, 4, 5] + | (.[0] + .[-1]) as $sum # Always put ( ) around the binding `expr` to avoid surprises. + | ($sum * length / 2) as $result # The current input at this step is still the initial array. + | "The result is: \($result)" # Same. +' + +# Output: +# The result is: 15 + + +# With the `expr as $var` form, if multiple values are generated by `expr` +# then jq will iterate through them and bind each value to `$var` in turn +# for the rest of the pipeline. +# +jq -rn 'range(2; 4) as $i + | range(1; 6) as $j + | "\($i) * \($j) = \($i * $j)" +' + +# Output: +# 2 * 1 = 2 +# 2 * 2 = 4 +# 2 * 3 = 6 +# 2 * 4 = 8 +# 2 * 5 = 10 +# 3 * 1 = 3 +# 3 * 2 = 6 +# 3 * 3 = 9 +# 3 * 4 = 12 +# 3 * 5 = 15 + + +# It's sometimes useful to bind the initial input to a variable at the +# start of a program, so that you can refer to it later down the pipeline. +# +jq -rn "$(cat <<'EOF' + {lookup: {a: 1, b: 2, c: 3}, + bonuses: {a: 5, b: 2, c: 9} + } + | . as $doc + | .bonuses + | to_entries[] + | "\(.key)'s total is \($doc.lookup[.key] + .value)" +EOF +)" + +# Output: +# a's total is 6 +# b's total is 4 +# c's total is 12 + + +# jq supports destructing during varible binding. This lets you extract values +# from an array or an object and bind them to variables. +# +jq -n '[range(5)] | . as [$first, $second] | $second' + +# Output: +# 1 + +jq -n '{ name: "Tom", numbers: [1, 2, 3], age: 32} + | . as { + name: $who, # bind .name to $who + $name, # shorthand for `name: $name` + numbers: [$first, $second], + } + | $name, $second, $first, $who +' + +# Output: +# "Tom" +# 2 +# 1 +# "Tom" + + +# In jq, values can be assigned to an array index or object key via the +# assignment operator, `=`. The same current input is given to both sides +# of the assignment operator, and the assignment itself evaluates to the +# current input. In other words, the assignment expression is evaluated +# for its side effect, and doesn't generate a new output. +# +jq -n '.a = 1 | .b = .a + 1' # => {"a": 1, "b": 2} + +# Note that input is `null` due to `jq -n`, so `.` is `null` in the first +# filter, and assiging to a key under `null` turns it into an object with +# the key. The same input (now an object) then gets piped to the next filter, +# which then sets the `b` key to the value of the `a` key plus `1`, which is `2`. +# + +# Another example: +# +jq -n '.a=1, .a.b=2' # => {"a": 1} {"a": {"b": 2}} + +# In the above example, two objects are generated because both assignments +# received `null` as their inputs, and each operand of the comma operator +# is evaluated independently. Notice also how you can easily generate +# nested objects. + + +# In addition to the assignment operator, jq also has operators like: +# `+=`, `-=`, `*=`, and '/=', ... etc. Basically, `a op= b` is a shorthand +# for `a = a op b`, and they are handy for updating an object attribute or +# an item in an array based on its current value. Examples: +# +jq -n '.a.b.c = 3 | .a.b.c = .a.b.c + 1' # => {"a": {"b": {"c": 4}}} +jq -n '.a.b.c = 3 | .a.b.c += 1' # => {"a": {"b": {"c": 4}}} + + +# To delete a value, use `del/1`, which takes a path expression that specifies +# the locations of the things to be deleted. Example: +# +jq -n '{a: 1, b: {c: 2}, d: [3, 4, 5]} | del(.b.c, .d[1]) | .b.x = 6' + +# Output: +# { +# "a": 1, +# "b": { +# "x": 6 +# }, +# "d": [ +# 3, +# 5 +# ] +# } + + +# Other than using jq's built-in functions, you can define your own. +# In fact, many built-in functions are defined using jq (see the link +# to jq's built-in functions at the end of the doc). +# +jq -n ' + def my_select(expr): if expr then . else empty end; + def my_map(expr): [.[] | expr]; + def sum: reduce .[] as $x (0; . + $x); + def my_range($from; $to): + if $from >= $to then + empty + else + $from, my_range($from + 1; $to) + end + ; + [my_range(1; 6)] | my_map(my_select(. % 2 != 0)) | sum +' + +# Output: +# 9 + +# Some notes about function definitons: +# +# - Functions are usually defined at the beginning, so that they are available +# to the rest of the jq program. +# +# - Each function definion should end with a `;` (semicolon). +# +# - It's also possible to define a function within another, though it's not shown here. +# +# - Function parameters are separated by `;` (semicolor). This is consistent with +# passing multiple arguments when calling a function. +# +# - A function can call itself; in fact, jq has TCO (Tail Call Optimization). +# +# - `def f($a; $b): ...;` is a shorthand for: `def f(a; b): a as $a | b as $b | ...` +``` + + +## Further Reading +- https://stedolan.github.io/jq/manual/ +- https://github.com/stedolan/jq/wiki/jq-Language-Description +- https://github.com/stedolan/jq/wiki/Cookbook +- https://github.com/stedolan/jq/blob/master/src/builtin.jq diff --git a/jquery.html.markdown b/jquery.html.markdown index a1673c10..cdcb89d9 100644 --- a/jquery.html.markdown +++ b/jquery.html.markdown @@ -3,6 +3,7 @@ category: tool tool: jquery contributors: - ["Sawyer Charles", "https://github.com/xssc"] + - ["Devansh Patil", "https://github.com/subtra3t"] filename: jquery.js --- @@ -10,8 +11,9 @@ jQuery is a JavaScript library that helps you "do more, write less". It makes ma Because jQuery is a JavaScript library you should [learn JavaScript first](https://learnxinyminutes.com/docs/javascript/) -```js +**NOTE**: jQuery has fallen out of the limelight in recent years, since you can achieve the same thing with the vanilla DOM (Document Object Model) API. So the only thing it is used for is a couple of handy features, such as the [jQuery date picker](https://api.jqueryui.com/datepicker) (which actually has a standard, unlike the `<input type="date">` HTML element), and the obvious decrease in the code length. +```js /////////////////////////////////// // 1. Selectors diff --git a/json.html.markdown b/json.html.markdown index 3ec7a3af..27f6bbe0 100644 --- a/json.html.markdown +++ b/json.html.markdown @@ -9,9 +9,9 @@ contributors: - ["Athanasios Emmanouilidis", "https://github.com/athanasiosem"] --- -JSON is an extremely simple data-interchange format. As [json.org](http://json.org) says, it is easy for humans to read and write and for machines to parse and generate. +JSON is an extremely simple data-interchange format. As [json.org](https://json.org) says, it is easy for humans to read and write and for machines to parse and generate. -A piece of JSON must represent either: +A piece of JSON can be any value of the types listed later, but in practice almost always represents either: * A collection of name/value pairs (`{ }`). In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array. * An ordered list of values (`[ ]`). In various languages, this is realized as an array, vector, list, or sequence. @@ -80,6 +80,5 @@ Supported data types: ## Further Reading -* [JSON.org](http://json.org) All of JSON beautifully explained using flowchart-like graphics. - +* [JSON.org](https://json.org) All of JSON beautifully explained using flowchart-like graphics. * [JSON Tutorial](https://www.youtube.com/watch?v=wI1CWzNtE-M) A concise introduction to JSON. diff --git a/jsonnet.html.markdown b/jsonnet.html.markdown new file mode 100644 index 00000000..f077c35b --- /dev/null +++ b/jsonnet.html.markdown @@ -0,0 +1,139 @@ +--- +language: jsonnet +filename: learnjsonnet.jsonnet +contributors: + - ["Huan Wang", "https://github.com/fredwangwang"] +--- + +Jsonnet is a powerful templating language for JSON. Any valid JSON +document is a valid Jsonnet object. For an interactive demo/tutorial, +click [here](https://jsonnet.org/learning/tutorial.html) + +```python +// single line comment + +/* + multiline comment +*/ + +# as well as python style comment + +# define a variable. +# Variables have no effect in the generated JSON without being used. +local num1 = 1; +local num2 = 1 + 1; +local num3 = 5 - 2; +local num4 = 9 % 5; +local num5 = 10 / 2.0; +# jsonnet is a lazy language, if a variable is not used, it is not evaluated. +local num_runtime_error = 1 / 0; + +# fields are valid identifiers without quotes +local obj1 = { a: 'letter a', B: 'letter B' }; + +local arr1 = ['a', 'b', 'c']; + +# string literals use " or '. +local str1 = 'a' + 'B'; +# multiline text literal in between ||| +# Each line must start with a white space. +local str_multiline = ||| + this is a + multiline string +|||; +# Python-compatible string formatting is available via % +# When combined with ||| this can be used for templating text files. +local str_templating = ||| + %(f1)0.3f +||| % { f1: 1.2345678 }; +assert str_templating == '1.235\n'; + +# if b then e else e. The else branch is optional and defaults to null +local var1 = if 3 < 2 then "YES"; +assert var1 == null; + +local obj2 = { + # variable defined inside the object ends with ',' + local var_in_obj = 0, + + local vowels = ['a', 'e', 'i', 'o', 'u'], + local numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + + # [num] to look up an array element + first_vowel: vowels[0], + # can also slice the array like in Python + even_numbers: numbers[1::2], + + # python-style list and object comprehensions are also supported + double_numbers: [x * 2 for x in numbers], + even_numbers_map: { + # [ ] syntax in field name is to compute the field name dynamically + [x + '_is_even']: true for x in numbers if x % 2 == 0 + }, + + nested: { + nested_field1: 'some-value', + # self refers to the current object + # ["field-name"] or .field-name can be used to look up a field + nested_field2: self.nested_field1, + nested_field3: self.nested_field1, + # $ refers to outer-most object + nested_field4: $.first_vowel, + + assert self.nested_field1 == self.nested_field2, + assert self.nested_field1 == self.nested_field3, + }, + + special_field: 'EVERYTHING FEELS BAD', +}; + +local obj3 = { + local var_in_obj = 1.234, + local var_in_obj2 = { a: { b: 'c' } }, + + concat_array: [1, 2, 3] + [4], + # strings can be concat with +, + # which implicitly converts one operand to string if needed. + concat_string: '123' + 4, + + # == tests deep equality + equals: { a: { b: 'c', d: {} } } == var_in_obj2, + + special_field: 'this feels good', +}; + +# objects can be merged with + where the right-hand side wins field conflicts +local obj4 = obj2 + obj3; +assert obj4.special_field == 'this feels good'; + +# define a function +# functions have positional parameters, named parameters, and default arguments +local my_function(x, y, z=1) = x + y - z; +local num6 = my_function(7, 8, 9); +local num7 = my_function(8, z=10, y=9); +local num8 = my_function(4, 5); +# inline anonymous function +local num9 = (function(x) x * x)(3); + +local obj5 = { + # define a method + # fields defined with :: are hidden, which does not apper in generated JSON + # function cannot be serialized so need to be hidden + # if the object is used in the generated JSON. + is_odd(x):: x % 2 == 1, +}; +assert obj5 == {}; + +# a jsonnet document has to evaluate to something +# be it an object, list, number or just string literal +"FIN" + +``` + +## Further Reading +There are a few but important concepts that are not touched in this example, including: + +- Passing variables from command line: [Parameterize Entire Config](https://jsonnet.org/learning/tutorial.html#parameterize-entire-config) +- Import other jsonnet libraries/files: [Imports](https://jsonnet.org/learning/tutorial.html#imports) +- In depth example of OOP aspect of Jsonnet: [Object-Orientation](https://jsonnet.org/learning/tutorial.html#Object-Orientation) +- Useful standard library: [Stdlib](https://jsonnet.org/ref/stdlib.html) diff --git a/julia.html.markdown b/julia.html.markdown index 5e9ef1b8..336cd2b8 100644 --- a/julia.html.markdown +++ b/julia.html.markdown @@ -11,7 +11,7 @@ Julia is a new homoiconic functional language focused on technical computing. While having the full power of homoiconic macros, first-class functions, and low-level control, Julia is as easy to learn and use as Python. -This is based on Julia 1.0.0 +This is based on Julia version 1.0.0. ```julia # Single line comments start with a hash (pound) symbol. @@ -83,7 +83,7 @@ false 1 > 10 # => false 2 <= 2 # => true 2 >= 2 # => true -# Comparisons can be chained +# Comparisons can be chained, like in Python but unlike many other languages 1 < 2 < 3 # => true 2 < 3 < 2 # => false @@ -93,28 +93,29 @@ false # Character literals are written with ' 'a' -# Strings are UTF8 encoded. Only if they contain only ASCII characters can -# they be safely indexed. -ascii("This is a string")[1] +# Strings are UTF8 encoded, so strings like "π" or "☃" are not directly equivalent +# to an array of single characters. +# Only if they contain only ASCII characters can they be safely indexed. +ascii("This is a string")[1] # => 'T' # => 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase) -# Julia indexes from 1 +# Beware, Julia indexes everything from 1 (like MATLAB), not 0 (like most languages). # Otherwise, iterating over strings is recommended (map, for loops, etc). -# String can be compared lexicographically -"good" > "bye" # => true +# String can be compared lexicographically, in dictionnary order: +"good" > "bye" # => true "good" == "good" # => true "1 + 2 = 3" == "1 + 2 = $(1 + 2)" # => true -# $ can be used for string interpolation: +# $(..) can be used for string interpolation: "2 + 2 = $(2 + 2)" # => "2 + 2 = 4" # You can put any Julia expression inside the parentheses. # Printing is easy -println("I'm Julia. Nice to meet you!") # => I'm Julia. Nice to meet you! +println("I'm Julia. Nice to meet you!") # => I'm Julia. Nice to meet you! # Another way to format strings is the printf macro from the stdlib Printf. -using Printf -@printf "%d is less than %f\n" 4.5 5.3 # => 5 is less than 5.300000 +using Printf # this is how you load (or import) a module +@printf "%d is less than %f\n" 4.5 5.3 # => 5 is less than 5.300000 #################################################### @@ -123,7 +124,7 @@ using Printf # You don't declare variables before assigning to them. someVar = 5 # => 5 -someVar # => 5 +someVar # => 5 # Accessing a previously unassigned variable is an error try @@ -137,9 +138,10 @@ end SomeOtherVar123! = 6 # => 6 # You can also use certain unicode characters +# here ☃ is a Unicode 'snowman' characters, see http://emojipedia.org/%E2%98%83%EF%B8%8F if it displays wrongly here ☃ = 8 # => 8 -# These are especially handy for mathematical notation -2 * π # => 6.283185307179586 +# These are especially handy for mathematical notation, like the constant π +2 * π # => 6.283185307179586 # A note on naming conventions in Julia: # @@ -171,7 +173,7 @@ matrix = [1 2; 3 4] # => 2×2 Array{Int64,2}: [1 2; 3 4] b = Int8[4, 5, 6] # => 3-element Array{Int8,1}: [4, 5, 6] # Add stuff to the end of a list with push! and append! -# By convention, the exclamation mark '!'' is appended to names of functions +# By convention, the exclamation mark '!' is appended to names of functions # that modify their arguments push!(a, 1) # => [1] push!(a, 2) # => [1,2] @@ -202,10 +204,10 @@ a # => [7,2,4,3,4,5,6] # Function names that end in exclamations points indicate that they modify # their argument. arr = [5,4,6] # => 3-element Array{Int64,1}: [5,4,6] -sort(arr) # => [4,5,6] -arr # => [5,4,6] -sort!(arr) # => [4,5,6] -arr # => [4,5,6] +sort(arr) # => [4,5,6] +arr # => [5,4,6] +sort!(arr) # => [4,5,6] +arr # => [4,5,6] # Looking out of bounds is a BoundsError try @@ -238,7 +240,7 @@ a = [1:5;] # => 5-element Array{Int64,1}: [1,2,3,4,5] a2 = [1:5] # => 1-element Array{UnitRange{Int64},1}: [1:5] # You can look at ranges with slice syntax. -a[1:3] # => [1, 2, 3] +a[1:3] # => [1, 2, 3] a[2:end] # => [2, 3, 4, 5] # Remove elements from an array by index with splice! @@ -276,15 +278,15 @@ in(2, tup) # => true # You can unpack tuples into variables a, b, c = (1, 2, 3) # => (1,2,3) -a # => 1 -b # => 2 -c # => 3 +a # => 1 +b # => 2 +c # => 3 # Tuples are created even if you leave out the parentheses d, e, f = 4, 5, 6 # => (4,5,6) -d # => 4 -e # => 5 -f # => 6 +d # => 4 +e # => 5 +f # => 6 # A 1-element tuple is distinct from the value it contains (1,) == 1 # => false @@ -292,8 +294,8 @@ f # => 6 # Look how easy it is to swap two values e, d = d, e # => (5,4) -d # => 5 -e # => 4 +d # => 5 +e # => 4 # Dictionaries store mappings emptyDict = Dict() # => Dict{Any,Any} with 0 entries @@ -354,6 +356,20 @@ intersect(filledSet, otherSet) # => Set([4, 3, 5]) union(filledSet, otherSet) # => Set([4, 2, 3, 5, 6, 1]) setdiff(Set([1,2,3,4]), Set([2,3,5])) # => Set([4, 1]) +# Assignment with `=` attaches a new label to the same value without copying +a = [1, 2, 3] +b = a +# Now `b` and `a` point to the same value, so changing one affects the other: +a[3] = 5 +b[3] # => 5 + +# The `copy()` function can create a shallow copy of an array, dictionary, +# or other container +a = [1, 2, 3] +c = copy(a) +a[3] = 5 +c[3] # => 3 + #################################################### ## 3. Control Flow #################################################### @@ -375,7 +391,8 @@ end # Iterable types include Range, Array, Set, Dict, and AbstractString. for animal = ["dog", "cat", "mouse"] println("$animal is a mammal") - # You can use $ to interpolate variables or expression into strings + # You can use $ to interpolate variables or expression into strings. + # In this special case, no need for parenthesis: $animal and $(animal) give the same end # => dog is a mammal # => cat is a mammal @@ -408,7 +425,7 @@ end let x = 0 while x < 4 println(x) - x += 1 # Shorthand for x = x + 1 + x += 1 # Shorthand for in place increment: x = x + 1 end end # => 0 diff --git a/kdb+.html.markdown b/kdb+.html.markdown index 027b6571..db842726 100644 --- a/kdb+.html.markdown +++ b/kdb+.html.markdown @@ -560,7 +560,7 @@ select avg height by sex from t / => f | 160 / => m | 177.5 -/ If no aggreation function is specified, last is assumed +/ If no aggregation function is specified, last is assumed select by sex from t / => sex| name age height / => ---| ----------------- @@ -771,6 +771,6 @@ select from splayed / (the columns are read from disk on request) * [*q for mortals* q language tutorial](http://code.kx.com/q4m3/) * [*Introduction to Kdb+* on disk data tutorial](http://code.kx.com/q4m3/14_Introduction_to_Kdb+/) -* [q language reference](http://code.kx.com/q/ref/card/) +* [q language reference](https://code.kx.com/q/ref/) * [Online training courses](http://training.aquaq.co.uk/) * [TorQ production framework](https://github.com/AquaQAnalytics/TorQ) diff --git a/ko-kr/clojure-kr.html.markdown b/ko-kr/clojure-kr.html.markdown index 1d9e53cd..32a5baf3 100644 --- a/ko-kr/clojure-kr.html.markdown +++ b/ko-kr/clojure-kr.html.markdown @@ -377,7 +377,7 @@ Clojuredocs.org는 core 함수들에 대해 다양한 예제와 문서를 보유 [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) 4Clojure는 clojure/FP 스킬을 올릴 수 있는 좋은 길입니다: -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org는 많고 많은 문서들을 보유하고 있습니다: [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/ko-kr/go-kr.html.markdown b/ko-kr/go-kr.html.markdown index 3012c04f..aed0918e 100644 --- a/ko-kr/go-kr.html.markdown +++ b/ko-kr/go-kr.html.markdown @@ -81,7 +81,7 @@ func learnTypes() { // non-ASCII 리터럴. Go 소스는 UTF-8로 작성해야 한다. g := 'Σ' // 유니코드 코드 포인트를 담고 있고, int32 타입의 가칭(alias)인 rune 타입 - f := 3.14195 // float64, an IEEE-754 64-bit 부동소수 타입 + f := 3.14159 // float64, an IEEE-754 64-bit 부동소수 타입 c := 3 + 4i // complex128, 내부적으로는 두 개의 float64 타입으로 표현됨 // 초기값과 함께 사용하는 var 키워드. @@ -332,15 +332,15 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { ## 더 읽어볼 것들 -Go에 대한 모든 것들은 [Go 공식 웹 사이트](http://golang.org/)를 참고하자. +Go에 대한 모든 것들은 [Go 공식 웹 사이트](https://go.dev/)를 참고하자. 여기에는 따라해볼 튜토리얼, 웹 기반의 인터랙티브 실행환경과 많은 읽을거리들이 있다. Go 언어 자체에 대한 스펙도 읽어보기를 적극 추천한다. 읽기 쉽게 되어있고 그리 길지는 않다. -Go 소스코드에 대해 좀더 알아보고 싶다면 [Go 표준 라이브러리](http://golang.org/src/pkg/)를 +Go 소스코드에 대해 좀더 알아보고 싶다면 [Go 표준 라이브러리](https://go.dev/src/)를 분석해보기 바란다. 이해하기 쉽게 문서화되어 있고, Go 스타일 그리고 Go에서의 -관례 배우기에 가장 좋은 방법일 것이다. 또는 [문서](http://golang.org/pkg/) 안에서 +관례 배우기에 가장 좋은 방법일 것이다. 또는 [문서](https://go.dev/pkg/) 안에서 함수 이름 하나를 클릭해보면 소스코드를 브라우저에서 살펴볼 수도 있다. Go를 배울수 있는 또하나의 좋은 방법은 [Go by example](https://gobyexample.com/). diff --git a/ko-kr/javascript-kr.html.markdown b/ko-kr/javascript-kr.html.markdown index 9561e80c..619d8104 100644 --- a/ko-kr/javascript-kr.html.markdown +++ b/ko-kr/javascript-kr.html.markdown @@ -2,7 +2,7 @@ language: javascript category: language contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] translators: - ["wikibook", "http://wikibook.co.kr"] filename: javascript-kr.js @@ -18,8 +18,8 @@ lang: ko-kr 그렇지만 자바스크립트는 웹 브라우저에만 국한되지 않습니다. 구글 크롬의 V8 자바스크립트 엔진을 위한 독립형 런타임을 제공하는 Node.js는 점점 인기를 얻고 있습니다. -피드백 주시면 대단히 감사하겠습니다! [@adambrenecki](https://twitter.com/adambrenecki)나 -[adam@brenecki.id.au](mailto:adam@brenecki.id.au)를 통해 저와 만나실 수 있습니다. +피드백 주시면 대단히 감사하겠습니다! [@ExcitedLeigh](https://twitter.com/ExcitedLeigh)나 +[l@leigh.net.au](mailto:l@leigh.net.au)를 통해 저와 만나실 수 있습니다. ```js // 주석은 C와 비슷합니다. 한 줄짜리 주석은 두 개의 슬래시로 시작하고, diff --git a/ko-kr/markdown-kr.html.markdown b/ko-kr/markdown-kr.html.markdown index 397e9f30..0167f0ff 100644 --- a/ko-kr/markdown-kr.html.markdown +++ b/ko-kr/markdown-kr.html.markdown @@ -25,15 +25,18 @@ lang: ko-kr ## HTML 요소 HTML은 마크다운의 수퍼셋입니다. 모든 HTML 파일은 유효한 마크다운이라는 것입니다. + ```md <!--따라서 주석과 같은 HTML 요소들을 마크다운에 사용할 수 있으며, 마크다운 파서에 영향을 받지 않을 것입니다. 하지만 마크다운 파일에서 HTML 요소를 만든다면 그 요소의 안에서는 마크다운 문법을 사용할 수 없습니다.--> ``` + ## 제목 텍스트 앞에 붙이는 우물 정 기호(#)의 갯수에 따라 `<h1>`부터 `<h6>`까지의 HTML 요소를 손쉽게 작성할 수 있습니다. + ```md # <h1>입니다. ## <h2>입니다. @@ -42,7 +45,9 @@ HTML은 마크다운의 수퍼셋입니다. 모든 HTML 파일은 유효한 마 ##### <h5>입니다. ###### <h6>입니다. ``` + 또한 h1과 h2를 나타내는 다른 방법이 있습니다. + ```md h1입니다. ============= @@ -50,9 +55,11 @@ h1입니다. h2입니다. ------------- ``` + ## 간단한 텍스트 꾸미기 마크다운으로 쉽게 텍스트를 기울이거나 굵게 할 수 있습니다. + ```md *기울인 텍스트입니다.* _이 텍스트도 같습니다._ @@ -64,10 +71,13 @@ __이 텍스트도 같습니다.__ **_이 텍스트도 같습니다._** *__이것도 같습니다.__* ``` + 깃헙 전용 마크다운에는 취소선도 있습니다. + ```md ~~이 텍스트에는 취소선이 그려집니다.~~ ``` + ## 문단 문단은 하나 이상의 빈 줄로 구분되는, 한 줄 이상의 인접한 텍스트입니다. @@ -103,6 +113,7 @@ HTML `<br />` 태그를 삽입하고 싶으시다면, 두 개 이상의 띄어 ## 목록 순서가 없는 목록은 별표, 더하기, 하이픈을 이용해 만들 수 있습니다. + ```md * 이거 * 저거 @@ -140,6 +151,7 @@ HTML `<br />` 태그를 삽입하고 싶으시다면, 두 개 이상의 띄어 1. 둘 1. 셋 ``` + (위의 예시와 똑같이 나타납니다.) 목록 안에 목록이 올 수도 있습니다. @@ -176,7 +188,7 @@ x가 없는 박스들은 체크되지 않은 HTML 체크박스입니다. ```md my_array.each do |item| - puts item + puts item end ``` @@ -188,12 +200,13 @@ x가 없는 박스들은 체크되지 않은 HTML 체크박스입니다. 깃헙 전용 마크다운에서는 코드를 나타내기 위해 특별한 문법을 쓸 수 있습니다. -<pre> -<code class="highlight">```ruby +````md +```ruby def foobar - puts "Hello world!" + puts "Hello world!" end -```</code></pre> +``` +```` 위의 경우에 들여쓰기가 필요없을 뿐 아니라 \`\`\` 뒤에 특정해 준 언어의 문법에 따라 색을 입혀줄 것입니다. @@ -202,12 +215,14 @@ end 수평선(`<hr/>`)은 셋 이상의 별표나 하이픈을 이용해 쉽게 나타낼 수 있습니다. 띄어쓰기가 포함될 수 있습니다. + ```md *** --- - - - **************** ``` + ## 링크 마크다운의 장점 중 하나는 링크를 만들기 쉽다는 것입니다. 대괄호 안에 나타낼 텍스트를 쓰고 @@ -231,20 +246,24 @@ end 참조하는 식으로 링크를 걸 수도 있습니다. -<pre><code class="highlight">[<span class="nv">이 </span>][<span class="ss">링크</span>]에서 더 알아보세요! -[<span class="nv">원하신다면 </span>][<span class="ss">foobar</span>]도 참고하세요. +```md +[이 ][링크]에서 더 알아보세요! +[원하신다면 ][foobar]도 참고하세요. -[<span class="nv">링크</span>]: <span class="sx">http://test.com/</span> <span class="nn">"좋아!"</span> -[<span class="nv">foobar</span>]: <span class="sx">http://foobar.biz/</span> <span class="nn">"됐다!"</span></code></pre> +[링크]: http://test.com/ "좋아!" +[foobar]: http://foobar.biz/ "됐다!" +``` 제목은 작은 따옴표나 괄호에 들어갈 수도 있고, 완전히 생략할 수도 있습니다. 참조는 문서의 어느 곳에든 올 수 있고 참조 ID는 유일하다면 무엇이든 될 수 있습니다. 링크 텍스트를 ID로 사용하는 "묵시적 이름"도 있습니다. -<pre><code class="highlight">[<span class="nv">이것</span>][]은 링크입니다. +```md +[이것][]은 링크입니다. -[<span class="nv">이것</span>]: <span class="sx">http://thisisalink.com/</span></code></pre> +[이것]: http://thisisalink.com/ +``` 하지만 보통 그렇게 추천하지는 않습니다. @@ -257,9 +276,11 @@ end 참조 방식도 가능합니다. -<pre><code class="highlight">![<span class="nv">alt 속성</span>][<span class="ss">이미지</span>] +```md +![alt 속성][이미지] -[<span class="nv">이미지</span>]: <span class="sx">relative/urls/cool/image.jpg</span> <span class="nn">"제목이 필요하다면 여기에"</span></code></pre> +[이미지]: relative/urls/cool/image.jpg "제목이 필요하다면 여기에" +``` ## 기타 ### 자동 링크 @@ -270,9 +291,11 @@ end ``` ### 이메일 자동 링크 + ```md <foo@bar.com> ``` + ### 탈출 문자 ```md @@ -292,17 +315,21 @@ end ### 표 표는 깃헙 전용 마크다운에서만 쓸 수 있고 다소 복잡하지만, 정말 쓰고 싶으시다면 + ```md | 1열 | 2열 | 3열 | | :--------| :-------: | --------: | | 왼쪽 정렬 | 가운데 정렬 | 오른쪽 정렬 | | 머시기 | 머시기 | 머시기 | ``` + 혹은 + ```md 1열 | 2열 | 3열 :-- | :-: | --: 으악 너무 못생겼어 | 그만 | 둬 ``` + --- 추가 정보를 위해, 존 그루버의 공식 문법 [(영어) 문서](http://daringfireball.net/projects/markdown/syntax)와 애덤 프릿차드의 훌륭한 [(영어) 치트싯](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)을 확인하세요. diff --git a/ko-kr/python-kr.html.markdown b/ko-kr/pythonlegacy-kr.html.markdown index 0145754d..978a9f33 100644 --- a/ko-kr/python-kr.html.markdown +++ b/ko-kr/pythonlegacy-kr.html.markdown @@ -1,9 +1,9 @@ --- -language: python +language: Python 2 (legacy) category: language contributors: - ["Louie Dinh", "http://ldinh.ca"] -filename: learnpython-ko.py +filename: learnpythonlegacy-ko.py translators: - ["wikibook", "http://wikibook.co.kr"] lang: ko-kr diff --git a/ko-kr/vim-kr.html.markdown b/ko-kr/vim-kr.html.markdown index cd0fa236..76063143 100644 --- a/ko-kr/vim-kr.html.markdown +++ b/ko-kr/vim-kr.html.markdown @@ -5,12 +5,13 @@ contributors: - ["RadhikaG", "https://github.com/RadhikaG"] translators: - ["Wooseop Kim", "https://github.com/linterpreteur"] + - ["Yeongjae Jang", "https://github.com/Liberatedwinner"] filename: LearnVim-kr.txt lang: ko-kr --- [Vim](http://www.vim.org) -(Vi IMproved)은 유닉스의 인기 있는 vi 에디터의 클론입니다. Vim은 속도와 생산성을 위해 +(Vi IMproved)은 유닉스에서 인기 있는 vi 에디터의 클론입니다. Vim은 속도와 생산성을 위해 설계된 텍스트 에디터로, 대부분의 유닉스 기반 시스템에 내장되어 있습니다. 다양한 단축 키를 통해 파일 안에서 빠르게 이동하고 편집할 수 있습니다. @@ -18,19 +19,21 @@ lang: ko-kr ``` vim <filename> # vim으로 <filename> 열기 + :help <topic> # (존재하는 경우에) <topic>에 대한, 내장된 도움말 문서 열기 :q # vim 종료 :w # 현재 파일 저장 :wq # 파일 저장 후 종료 + ZZ # 파일 저장 후 종료 :q! # 저장하지 않고 종료 # ! *강제로* :q를 실행하여, 저장 없이 종료 - :x # 파일 저장 후 종료 (짧은 :wq) + :x # 파일 저장 후 종료 (:wq의 축약) u # 동작 취소 CTRL+R # 되돌리기 h # 한 글자 왼쪽으로 이동 - j # 아래로 한 줄 이동 - k # 위로 한 줄 이동 + j # 한 줄 아래로 이동 + k # 한 줄 위로 이동 l # 한 글자 오른쪽으로 이동 # 줄 안에서의 이동 @@ -38,6 +41,11 @@ lang: ko-kr 0 # 줄 시작으로 이동 $ # 줄 끝으로 이동 ^ # 줄의 공백이 아닌 첫 문자로 이동 + + Ctrl+B # 한 화면 뒤로 이동 + Ctrl+F # 한 화면 앞으로 이동 + Ctrl+D # 반 화면 앞으로 이동 + Ctrl+U # 반 화면 뒤로 이동 # 텍스트 검색 @@ -48,6 +56,8 @@ lang: ko-kr :%s/foo/bar/g # 파일 모든 줄에 있는 'foo'를 'bar'로 치환 :s/foo/bar/g # 현재 줄에 있는 'foo'를 'bar'로 치환 + :%s/foo/bar/gc # 사용자에게 확인을 요구하는, 모든 줄에 있는 'foo'를 'bar'로 치환 + :%s/\n/\r/g # 한 종류의 개행 문자에서 다른 종류의 것으로 치환 (\n에서 \r로) # 문자로 이동 @@ -74,14 +84,22 @@ lang: ko-kr L # 화면 바닥으로 이동 ``` +## 도움말 문서 + +Vim은 `:help <topic>` 명령을 통해 접근할 수 있는 도움말 문서를 내장하고 있습니다. +예를 들어, `:help navigation` 은 당신의 작업 공간을 탐색하는 방법에 대한 문서를 표시합니다! + +`:help`는 옵션 없이도 사용할 수 있습니다. 이는 기본 도움말 대화 상자를 표시합니다. +이 대화 상자는 Vim을 시작하는 것이 보다 용이하도록 도와줍니다. + ## 모드 Vim은 **모드**의 개념에 기초를 두고 있습니다. -명령어 모드 - vim을 시작하면 처음에 이 모드입니다. 이동과 명령어 입력에 사용합니다. -삽입 모드 - 파일을 수정합니다. -비주얼 모드 - 텍스트를 하이라이트하고 그 텍스트에 대한 작업을 합니다. -실행 모드 - ':' 이후 명령어를 입력합니다. +- 명령어 모드 - vim은 이 모드로 시작됩니다. 이동과 명령어 입력에 사용합니다. +- 삽입 모드 - 파일을 수정합니다. +- 비주얼 모드 - 텍스트를 하이라이트하고 그 텍스트에 대한 작업을 합니다. +- 실행 모드 - ':' 이후 명령어를 입력합니다. ``` i # 커서 위치 앞에서 삽입 모드로 변경 @@ -97,11 +115,11 @@ Vim은 **모드**의 개념에 기초를 두고 있습니다. d # 선택한 객체 삭제 dd # 현재 줄 삭제 p # 커서 위치 뒤에 복사한 텍스트 붙여넣기 - P # 커서 위치 뒤에 복사한 텍스트 붙여넣기 + P # 커서 위치 앞에 복사한 텍스트 붙여넣기 x # 현재 커서 위치의 문자 삭제 ``` -## vim의 문법 +## vim의 '문법' Vim의 명령어는 '서술어-수식어-목적어'로 생각할 수 있습니다. @@ -134,7 +152,7 @@ Vim의 명령어는 '서술어-수식어-목적어'로 생각할 수 있습니 w # 단어를 s # 문장을 p # 문단을 - b # 블락을 + b # 블록을 # 예시 '문장' (명령어) @@ -157,6 +175,22 @@ Vim의 명령어는 '서술어-수식어-목적어'로 생각할 수 있습니 ddp # 이어지는 줄과 위치 맞바꾸기 (dd 후 p) . # 이전 동작 반복 :w !sudo tee % # 현재 파일을 루트 권한으로 저장 + :set syntax=c # 문법 강조를 'C'의 것으로 설정 + :sort # 모든 줄을 정렬 + :sort! # 모든 줄을 역순으로 정렬 + :sort u # 모든 줄을 정렬하고, 중복되는 것을 삭제 + ~ # 선택된 텍스트의 대/소문자 토글 + u # 선택된 텍스트를 소문자로 바꾸기 + U # 선택된 텍스트를 대문자로 바꾸기 + + # 텍스트 폴딩 + zf # 선택된 텍스트 위치에서 폴딩 만들기 + zo # 현재 폴딩 펴기 + zc # 현재 폴딩 접기 + zR # 모든 폴딩 펴기 + zM # 모든 폴딩 접기 + zi # 폴딩 접기/펴기 토글 + zd # 접은 폴딩 삭제 ``` ## 매크로 diff --git a/ko-kr/yaml-kr.html.markdown b/ko-kr/yaml-kr.html.markdown index b6d1de41..c275c47f 100644 --- a/ko-kr/yaml-kr.html.markdown +++ b/ko-kr/yaml-kr.html.markdown @@ -2,19 +2,22 @@ language: yaml filename: learnyaml-kr.yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] - - ["Suhas SG", "https://github.com/jargnar"] +- ["Leigh Brenecki", "https://github.com/adambrenecki"] +- ["Suhas SG", "https://github.com/jargnar"] translators: - - ["Wooseop Kim", "https://github.com/linterpreteur"] +- ["Wooseop Kim", "https://github.com/linterpreteur"] +- ["Justin Yang", "https://github.com/justin-themedium"] lang: ko-kr --- YAML은 인간이 직접 쓰고 읽을 수 있도록 설계된 데이터 직렬화 언어입니다. YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미를 준 JSON의 엄격한 수퍼셋입니다. -하지만 파이썬과는 달리 YAML은 탭 문자를 전혀 허용하지 않습니다. +하지만 파이썬과는 달리 YAML은 탭 문자를 들여쓰기에 사용하지 않습니다. ```yaml +--- # 문서 시작 + # YAML의 주석은 이런 식입니다. ############ @@ -22,19 +25,23 @@ YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미 ############ # 문서 내내 이어질 루트 객체는 맵입니다. -# 맵은 다른 언어의 딕셔너리, 해시, 혹은 객체에 해당됩니다. +# 맵은 다른 언어의 딕셔너리, 해시, 혹은 객체에 해당합니다. 키: 값 다른_키: 다른 값이 여기 옵니다. 숫자_값: 100 -# 숫자 1을 값으로 가지기 위해서는 따옴표에 담아야 합니다. -# 그러지 않는다면 YAML 파서는 그것을 참 값을 가지는 불리언으로 해석할 것입니다. 과학적_표기법: 1e+12 +# 숫자 1은 불리언이 아닌 값으로 처리됩니다. 불리언으로 처리하고 싶다면 +# true를 사용하세요. 불리언: true 널_값: null 띄어서 쓴 키: 값 # 문자열에 따옴표를 칠 필요는 없습니다. 하지만 칠 수도 있습니다. -하지만: "따옴표에 담은 문자열" -"키도 따옴표에 담을 수 있습니다.": "키에 ':'을 넣고 싶다면 유용합니다." +하지만: '따옴표에 담은 문자열' +'키도 따옴표에 담을 수 있습니다.': "키에 ':'을 넣고 싶다면 유용합니다." +작은 따옴표: '는 ''하나''의 이스케이프 패턴을 갖습니다' +큰 따옴표: "는 많이 갖습니다. \", \0, \t, \u263A, \x0d\x0a == \r\n, 그리고 더." +# UTF-8/16/32 문자는 인코딩되어야 합니다. +첨자 2: \u00B2 # 여러 줄의 문자열은 (|을 이용한) '리터럴 블락' 혹은 (>을 이용한) '접은 블락'으로 # 쓸 수 있습니다. @@ -59,12 +66,12 @@ YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미 # 모임 형 # ########## -# 중첩은 들여쓰기로 가능합니다. +# 중첩은 들여쓰기를 사용합니다. 2칸 띄어쓰기가 많이 쓰입니다(필수는 아닙니다). 중첩된_맵: - 키: 값 - 다른_키: 다른 값 - 다른_중첩된_맵: - 안녕: 안녕 + 키: 값 + 다른_키: 다른 값 + 다른_중첩된_맵: + 안녕: 안녕 # 맵은 반드시 문자열 키를 가지는 것은 아닙니다. 0.25: 실수형 키 @@ -72,28 +79,31 @@ YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미 # 키는 여러 줄에 걸친 객체와 같이 복합적일 수도 있습니다. # ?와 그 뒤의 띄어쓰기로 복합 키의 시작을 나타냅니다. ? | - 여러 줄짜리 - 키 + 여러 줄짜리 + 키 : 그리고 그 값 -# YAML은 복합 키 문법으로 연속열 간의 매핑을 지원합니다. +# YAML은 복합 키 문법으로 연속열 간의 매핑도 지원합니다. # 일부 파서는 지원하지 않을 수 있습니다. # 예시 ? - 맨체스터 유나이티드 - 레알 마드리드 -: [ 2001-01-01, 2002-02-02 ] +: [2001-01-01, 2002-02-02] # 리스트 혹은 배열에 대응되는 연속열은 다음과 같습니다. +# (들여쓰기처럼 '-'를 세는 것에 주의하세요) 연속열: - - 하나 - - 둘 - - 0.5 # 연속열은 다른 형을 포함 가능 - - 넷 - - 키: 값 - 다른_키: 다른_값 - - - - 연속열 안의 - - 또 다른 연속열 + - 하나 + - 둘 + - 0.5 # 연속열은 다른 형을 포함 가능 + - 넷 + - 키: 값 + 다른_키: 다른_값 + - + - 연속열 안의 + - 또 다른 연속열 + - - - 중첩된 연속열 지시자 + - 접힘 가능 # YAML은 JSON의 수퍼셋이기 때문에, JSON식으로 맵과 연속열을 작성할 수도 # 있습니다. @@ -111,17 +121,19 @@ YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미 # 앵커는 속성을 복제하거나 상속할 수 있습니다. 기반: &기반 - 이름: 모두 이름이 같다 + 이름: 모두 이름이 같다 -멍멍: &멍멍 - <<: *기반 - 나이: 10 +# 정규식 << 는 병합 키 언어-비종속 타입으로 불립니다. 이는 하나 +# 이상 지정된 맵의 모든 키가 현재 맵 안으로 삽입됨을 나타냅니다. +멍멍: + <<: *기반 + 나이: 10 -야옹: &야옹 - <<: *기반 - 나이: 20 +야옹: + <<: *기반 + 나이: 20 -# 멍멍이와 야옹이는 같은 이름, '모두 이름이 같다'를 같습니다. +# 멍멍이와 야옹이도 '이름: 모두 이름이 같다'를 갖습니다. # 또한 YAML에는 명시적으로 형을 선언할 수 있는 태그가 있습니다. 명시적_문자열: !!str 0.5 @@ -138,8 +150,7 @@ YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미 # 기타 YAML 형 # ############### -# Strings and numbers aren't the only scalars that YAML can understand. -# YAML이 이해할 수 있는 스칼라는 문자열과 수만 있는 것은 아닙니다. +# YAML이 이해할 수 있는 스칼라가 문자열과 수만 있는 것은 아닙니다. # ISO 형식 날짜와 시간 리터럴 또한 해석됩니다. 시간: 2001-12-15T02:59:43.1Z 띄어쓰기_한_시간: 2001-12-14 21:59:43.10 -5 @@ -148,25 +159,27 @@ YAML은 마치 파이썬처럼 개행과 들여쓰기에 문법적으로 의미 # !!binary 태그는 문자열이 실제로는 base64로 인코딩된 # 이진수 객체(BLOB)라는 것을 나타냅니다. 이미지_파일: !!binary | - R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 - OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ - +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC - AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= # YAML에는 다음과 같은 집합도 있습니다. 집합: - ? 하나 - ? 둘 - ? 셋 + ? 하나 + ? 둘 + ? 셋 -# 파이썬과 마찬가지로 집합은 단지 널 값을 갖는 맵입니다. 위는 다음과 같습니다. +# 집합은 단지 널 값을 갖는 맵입니다. 위는 다음과 같습니다. 집합2: - 하나: null - 둘: null - 셋: null + 하나: null + 둘: null + 셋: null + +... # 문서 끝 ``` ### 더 읽기 -+ [(영어) YAML 공식 사이트](http://yaml.org/) -+ [(영어) 온라인 YAML 검사기](http://codebeautify.org/yaml-validator) ++ [(영어) YAML 공식 사이트](https://yaml.org/) ++ [(영어) 온라인 YAML 검사기](http://www.yamllint.com/) diff --git a/kotlin.html.markdown b/kotlin.html.markdown index 5bbf6847..a6fac518 100644 --- a/kotlin.html.markdown +++ b/kotlin.html.markdown @@ -26,7 +26,7 @@ any parameters. */ fun main(args: Array<String>) { /* - Declaring values is done using either "var" or "val". + Declaring variables is done using either "var" or "val". "val" declarations cannot be reassigned, whereas "vars" can. */ val fooVal = 10 // we cannot later reassign fooVal to something else @@ -180,7 +180,7 @@ fun helloWorld(val name : String) { // destructuring in "for" loop for ((a, b, c) in listOf(fooData)) { - println("$a $b $c") // => 1 100 4 + println("$a $b $c") // => 1 2 4 } val mapData = mapOf("a" to 1, "b" to 2) @@ -297,7 +297,7 @@ fun helloWorld(val name : String) { else -> println("none of the above") } - // "when" can be used as a function that returns a value. + // "when" can be used as an expression that returns a value. var result = when (i) { 0, 21 -> "0 or 21" in 1..20 -> "in the range 1 to 20" @@ -426,7 +426,7 @@ data class Counter(var value: Int) { operator fun invoke() = println("The value of the counter is $value") } -/* You can also overload operators through an extension methods */ +/* You can also overload operators through extension methods */ // overload -Counter operator fun Counter.unaryMinus() = Counter(-this.value) diff --git a/lambda-calculus.html.markdown b/lambda-calculus.html.markdown index 53a7a7cd..775907c2 100644 --- a/lambda-calculus.html.markdown +++ b/lambda-calculus.html.markdown @@ -41,7 +41,7 @@ Evaluation is done via which is essentially lexically-scoped substitution. When evaluating the -expression `(λx.x)a`, we replace all occurences of "x" in the function's body +expression `(λx.x)a`, we replace all occurrences of "x" in the function's body with "a". - `(λx.x)a` evaluates to: `a` @@ -131,7 +131,7 @@ We can convert an expression in the lambda calculus to an expression in the SKI combinator calculus: 1. `λx.x = I` -2. `λx.c = Kc` +2. `λx.c = Kc` provided that `x` does not occur free in `c` 3. `λx.(y z) = S (λx.y) (λx.z)` Take the church number 2 for example: diff --git a/latex.html.markdown b/latex.html.markdown index c980f5e5..9edc057e 100644 --- a/latex.html.markdown +++ b/latex.html.markdown @@ -2,7 +2,7 @@ language: latex contributors: - ["Chaitanya Krishna Ande", "http://icymist.github.io"] - - ["Colton Kohnke", "http://github.com/voltnor"] + - ["Colton Kohnke", "https://github.com/voltnor"] - ["Sricharan Chiruvolu", "http://sricharan.xyz"] - ["Ramanan Balakrishnan", "https://github.com/ramananbalakrishnan"] - ["Svetlana Golubeva", "https://attillax.github.io/"] @@ -95,8 +95,9 @@ to the source code. Separate paragraphs by empty lines. -You need to add a backslash after abbreviations (if not followed by a comma), because otherwise the spacing after the dot is too large: -E.g., i.e., etc.\ are are such abbreviations. +You need to add a tilde after abbreviations (if not followed by a comma) for a +non-breaking space, because otherwise the spacing after the dot is too large: +E.g., i.e., etc.~are are such abbreviations. \section{Lists} Lists are one of the easiest things to create in \LaTeX! I need to go shopping @@ -123,7 +124,7 @@ Math has many symbols, far beyond what you can find on a keyboard; Set and relation symbols, arrows, operators, and Greek letters to name a few. Sets and relations play a vital role in many mathematical research papers. -Here's how you state all x that belong to X, $\forall$ x $\in$ X. +Here's how you state all x that belong to X, $\forall x \in X$. % Notice how I needed to add $ signs before and after the symbols. This is % because when writing, we are in text-mode. % However, the math symbols only exist in math-mode. @@ -140,8 +141,7 @@ about! Operators are essential parts of a mathematical document: trigonometric functions ($\sin$, $\cos$, $\tan$), logarithms and exponentials ($\log$, $\exp$), -limits ($\lim$), etc.\ -have per-defined LaTeX commands. +limits ($\lim$), etc.~have pre-defined LaTeX commands. Let's write an equation to see how it's done: $\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$ @@ -181,7 +181,9 @@ Summations and Integrals are written with sum and int commands: \section{Figures} Let's insert a figure. Figure placement can get a little tricky. +Basic options are [t] for top, [b] for bottom, [h] for here (approximately). I definitely have to lookup the placement options each time. +% See https://en.wikibooks.org/wiki/LaTeX/Floats,_Figures_and_Captions for more details \begin{figure}[H] % H here denoted the placement option. \centering % centers the figure on the page @@ -198,16 +200,24 @@ We can also insert Tables in the same way as figures. \begin{table}[H] \caption{Caption for the Table.} % the {} arguments below describe how each row of the table is drawn. - % Again, I have to look these up. Each. And. Every. Time. - \begin{tabular}{c|cc} - Number & Last Name & First Name \\ % Column rows are separated by & + % The basics are simple: one letter for each column, to control alignment: + % basic options are: c, l, r and p for centered, left, right and paragraph + % optionally, you can add a | for a vertical line + % See https://en.wikibooks.org/wiki/LaTeX/Tables for more details + \begin{tabular}{c|cc} % here it means "centered | vertical line, centered centered" + Number & First Name & Last Name \\ % Column rows are separated by & \hline % a horizontal line 1 & Biggus & Dickus \\ 2 & Monty & Python \end{tabular} + % it will approximately be displayed like this + % Number | First Name Last Name + % -------|--------------------------- % because of \hline + % 1 | Biggus Dickus + % 2 | Monty Python \end{table} -\section{Getting \LaTeX{} to not compile something (i.e.\ Source Code)} +\section{Getting \LaTeX{} to not compile something (i.e.~Source Code)} Let's say we want to include some code into our \LaTeX{} document, we would then need \LaTeX{} to not try and interpret that text and instead just print it to the document. We do this with a verbatim @@ -218,14 +228,15 @@ environment. \begin{verbatim} print("Hello World!") a%b; % look! We can use % signs in verbatim. - random = 4; #decided by fair random dice roll + random = 4; #decided by fair random dice roll, https://www.xkcd.com/221/ + See https://www.explainxkcd.com/wiki/index.php/221:_Random_Number \end{verbatim} \section{Compiling} By now you're probably wondering how to compile this fabulous document and look at the glorious glory that is a \LaTeX{} pdf. -(yes, this document actually does compile). +(Yes, this document actually does compile). Getting to the final document using \LaTeX{} consists of the following steps: @@ -244,6 +255,7 @@ Step 2 is still happening behind the scenes\footnote{In cases, where you use references (like Eqn.~\ref{eq:pythagoras}), you may need to run Step 2 multiple times, to generate an intermediary *.aux file.}. % Also, this is how you add footnotes to your document! +% with a simple \footnote{...} command. They are numbered ¹, ², ... by default. You write all your formatting information in plain text in Step 1. The compilation part in Step 2 takes care of producing the document in the @@ -262,9 +274,30 @@ There exists two main types of links: visible URL \\ % You can not add extra-spaces or special symbols into shadowing text since it % will cause mistakes during the compilation -This package also produces list of thumbnails in the output pdf document and +This package also produces list of thumbnails in the output PDF document and active links in the table of contents. +\section{Writing in ASCII or other encodings} + +By default, historically LaTeX accepts inputs which are pure ASCII (128), +but not extended ASCII, meaning without accents (à, è etc.) and non-Latin symbols. + +It is easy to insert accents and basic Latin symbols, with backslash shortcuts +Like \,c, \'e, \`A, \ae and \oe etc. % for ç, é, À, etc +% See https://en.wikibooks.org/wiki/LaTeX/Special_Characters#Escaped_codes for more + +To write directly in UTF-8, when compiling with pdflatex, use +\begin{verbatim} + \usepackage[utf8]{inputenc} +\end{verbatim} +The selected font has to support the glyphs used for your document, you have to add +\begin{verbatim} + \usepackage[T1]{fontenc} +\end{verbatim} + +Since LuaTeX and XeLaTeX were designed with built-in support for UTF-8, making +life easier for writing in non-Latin alphabets. + \section{End} That's all for now! @@ -284,6 +317,8 @@ That's all for now! ## More on LaTeX -* The amazing LaTeX wikibook: [https://en.wikibooks.org/wiki/LaTeX](https://en.wikibooks.org/wiki/LaTeX) +* The amazing LaTeX Wikibook: [https://en.wikibooks.org/wiki/LaTeX](https://en.wikibooks.org/wiki/LaTeX) * An actual tutorial: [http://www.latex-tutorial.com/](http://www.latex-tutorial.com/) * A quick guide for learning LaTeX: [Learn LaTeX in 30 minutes](https://www.overleaf.com/learn/latex/Learn_LaTeX_in_30_minutes) +* An interactive platform to learn LaTeX (installationfree) [learnlatex.org/](https://www.learnlatex.org/) +* Stack Exchange's question and answer site about TeX, LaTeX, ConTeXt, etc. [tex.stackexchange.com](https://tex.stackexchange.com/) diff --git a/lbstanza.html.markdown b/lbstanza.html.markdown new file mode 100644 index 00000000..90e7b7e5 --- /dev/null +++ b/lbstanza.html.markdown @@ -0,0 +1,282 @@ +--- +language: LB Stanza +filename: learn-stanza.stanza +contributors: + - ["Mike Hilgendorf", "https://github.com/m-hilgendorf"] +--- + +LB Stanza (or Stanza for short) is a new optionally-typed general purpose programming language from the University of California, Berkeley. Stanza was designed to help programmers tackle the complexity of architecting large programs and significantly increase the productivity of application programmers across the entire software development life cycle. + + +``` +; this is a comment +;<A> +This is a block comment + ;<B> + block comments can be nested with optional tags. + ;<B> +;<A> +defpackage learn-stanza-in-y: + import core + import collections + +;============================================================================== +; The basics, things you'd find in most programming languages +;============================================================================== + + +; Variables can be mutable (var) or immutable (val) +val immutable = "this string can't be changed" +var mutable = "this one can be" +mutable = "like this" + +; The basic data types (annotations are optional) +val an-int: Int = 12345 +val a-long: Long = 12345L +val a-float: Float = 1.2345f +val a-double: Double = 3.14159 +val a-string: String = "this is a string" +val a-multiline-string = \<tag> + this is a "raw" string literal +\<tag> + +; Print a formatted string with println and "..." % [...] +println("this is a formatted string %_ %_" % [mutable, immutable]) + +; Stanza is optionally typed, and has a ? (any) type. +var anything:? = 0 +anything = 3.14159 +anything = "a string" + +; Stanza has basic collections like Tuples, Arrays, Vectors and HashTables +val tuple: Tuple<?> = [mutable, immutable] + +val array = Array<?>(3) +array[0] = "string" +array[1] = 1 +array[2] = 1.23455 +; array[3] = "out-of-bounds" ; arrays are bounds-checked + +val vector = Vector<?>() +vector[0] = "string" +vector[1] = 1 +vector[2] = 3.14159 + +val hash-table = HashTable<String, ?>() +hash-table["0"] = 0 +hash-table["1"] = 1 +hash-table["2"] = 1 + + +;============================================================================== +; Functions +;============================================================================== +; Functions are declared with the `defn` keyword +defn my-function (arg:?) : ; note the space between identifier and arg list + println("called my-function with %_" % [arg]) + +my-function("arg") ; note the lack of a space to call the function + +; Functions can be declared inside another function and capture variables from +; the surrounding environment. +defn outer (arg): + defn inner (): + println("outer had arg: %_" % [arg]) + inner() + +outer("something") + +; functions are "first-class" in stanza, meaning you can assign variables +; to functions and pass functions as arguments to other functions. +val a-function = outer +defn do-n-times (arg, func, n:Int): + for i in 0 to n do : + func(arg) +do-n-times("argument", a-function, 3) + +; sometimes you want to define a function inline, or use an anonymous function. +; for this you can use the syntax: +; fn (args): +; ... +do-n-times("hello", fn (arg): println(arg), 2) + +; there is a shorthand for writing anonymous functions +do-n-times("hello", { println(_) }, 2) + +; the short hand works for multiple arguments as well. +val multi-lambda = { println(_ + 2 * _) } +multi-lambda(1, 2) + +;============================================================================== +; User defined types +;============================================================================== +; Structs are declared with the `defstruct` keyword +defstruct MyStruct: + field + +; constructors are derived automatically +val my-struct = MyStruct("field:value") + +; fields are accessed using function-call syntax +println(field(my-struct)) + +; Stanza supports subtyping with a "multimethod" system based on method +; overloading. +deftype MyType +defmulti a-method (m:MyType) + +defstruct Foo <: MyType +defstruct Bar <: MyType +defmethod a-method (a-foo: Foo): + println("called a-method on a Foo") + +defmethod a-method (a-foo: Bar): + println("called a-method on a Bar") + +;============================================================================== +; The Type System +;============================================================================== +; True and Falseare types with a single value. +val a-true: True = true +val a-false: False = false + +; You can declare a union type, or a value that is one of a set of types +val a-boolean: True|False = true +val another-boolean: True|False = false + +; You can pattern match on types +match(a-boolean): + (t:True): println("is true") + (f:False): println("is false") + +; You can match against a single possible type +match(a-boolean:True): + println("is still true") +else: + println("is not true") + +; You can compose program logic around the type of a variable +if anything is Float : + println("anything is a float") +else if anything is-not String : + println("anything is not an int") +else : + println("I don't know what anything is") + +;============================================================================== +; Control Flow +;============================================================================== +; stanza has the standard basic control flow +val condition = [false, false] +if condition[0] : + ; do something + false +else if condition[1] : + ; do another thing + false +else : + ; whatever else + false + +; there is also a switch statement, which can be used to pattern match +; on values (as opposed to types) +switch(anything): + "this": false + "that": false + "the-other-thing": false + else: false + +; for and while loops are supported +while condition[0]: + println("do stuff") + +for i in 0 to 10 do: + vector[i] = i + +; stanza also supports named labels which can function as break or return +; statements +defn another-fn (): + label<False> return: + label<False> break: + while true: + if condition[0] is False: + break(false) + return(false) + +; For a comprehensive guide on Stanza's advanced control flow, check out +; this page: http://lbstanza.org/chapter9.html from Stanza-by-Example + +;============================================================================== +; Sequences +;============================================================================== +; for "loops" are sugar for a more powerful syntax. +val xs = [1, 2, 3] +val ys = ['a', 'b', 'c'] +val zs = ["foo", "bar", "baz"] + +for (x in xs, y in ys, z in zs) do : + println("x:%_, y:%_, z:%_" % [x, y, z]) + + +;xs, ys, and zs are all "Seqable" meaning they are Seq types (sequences). +; the `do` identifier is a special function that just applies the body of +; the for loop to each element of the sequence. +; +; A common sequence task is concatenating sequences. This is accomplished +; using the `seq-cat` function. This is analogous to "flattening" iterateors +val concat = to-tuple $ + for sequence in [xs, ys, zs] seq-cat: + sequence + +; we can also use a variation to interleave the elements of multiple sequences +val interleaved = to-tuple $ + for (x in xs, y in ys, z in zs) seq-cat : + [x, y, z] + +println("[%,] [%,]" % [concat, interleaved]) + +; Another common task is mapping a sequence to another, for example multiplying +; all the elements of a list of numbers by a constant. To do this we use `seq`. +var numbers = [1.0, 2.0, 3.0, 4.0] +numbers = to-tuple $ + for n in numbers seq : + 2.0 * n +println("%," % [numbers]) + +if find({_ == 2.0}, numbers) is-not False : + println("found it!") + +; or maybe we just want to know if there's something in a sequence +var is-there = + for n in numbers any? : + n == 2.0 + +; since this is "syntactic sugar" we can write it explicitly using an +; anonymous function +is-there = any?({_ == 2.0}, numbers) + +; a detailed reference of the sequence library and various adaptors can +; be found here: http://lbstanza.org/reference.html#anchor439 + + +========================================================================= +; Documentation +;========================================================================= +; +; Top level statements can be prefixed with the "doc" field which takes +; a string value and is used to autogenerate documentation for the package. +doc: \<doc> + # Document Strings + + ``` + val you-can = "include code snippets, too" + ``` + + To render documentation as markdown (compatible with mdbook) + + ```bash + stanza doc source.stanza -o docs + ``` +\<doc> +defn docfn () : false +``` diff --git a/ldpl.html.markdown b/ldpl.html.markdown index cc95f5fb..449c8670 100644 --- a/ldpl.html.markdown +++ b/ldpl.html.markdown @@ -3,6 +3,7 @@ language: LDPL filename: learnLDPL.ldpl contributors: - ["Martín del Río", "https://github.com/lartu"] + - ["John Paul Wohlscheid", "https://github.com/JohnBlood"] --- **LDPL** is a powerful, C++ transpiled, open-source programming language designed @@ -68,7 +69,7 @@ else if myMap:"someIndex" is not equal to 45 then else display "Else!" crlf end if -# Valid LDPL comparisson operators are +# Valid LDPL comparison operators are # - IS EQUAL TO # - IS NOT EQUAL TO # - IS LESS THAN @@ -123,8 +124,8 @@ get random in myNumber # get a random number between 0 and 1 # files, are divided in sections. The sections found in sub-procedures are # the PARAMETERS section, the LOCAL DATA section and the PROCEDURE section. # All sections except the PROCEDURE section can be skipped if they aren't -# used. If no PARAMTERS nor LOCAL DATA sections are used, the PROCEDURE -# keyword may be omited. +# used. If no PARAMETERS nor LOCAL DATA sections are used, the PROCEDURE +# keyword may be omitted. sub myFunction parameters: a is number # LDPL is pass by reference @@ -165,19 +166,6 @@ display myNumber crlf exit ``` -## Topics Not Covered - - * [Command line arguments](https://docs.ldpl-lang.org/variables-in-ldpl/command-line-arguments) - * [Error variables](https://docs.ldpl-lang.org/variables-in-ldpl/errorcode-and-errortext) - * [Import other files](https://docs.ldpl-lang.org/structure-of-ldpl-source-code/importing-other-sources) - * [Identifier naming schemes](https://docs.ldpl-lang.org/naming-rules) - * [Text Statements](https://docs.ldpl-lang.org/text-statements/join-and-in) - * [List Statements](https://docs.ldpl-lang.org/list-statements/push-to) - * [Map Statements](https://docs.ldpl-lang.org/vector-statements/clear) - * [File loading / writing](https://docs.ldpl-lang.org/i-o-statements/load-file-in) - * [Executing commands](https://docs.ldpl-lang.org/i-o-statements/execute) - * [Extending LDPL with C++](https://docs.ldpl-lang.org/extensions/c++-extensions) - ## Further Reading * [LDPL Docs](https://docs.ldpl-lang.org) diff --git a/linker.html.markdown b/linker.html.markdown index ebe6233d..42839e05 100644 --- a/linker.html.markdown +++ b/linker.html.markdown @@ -5,5 +5,5 @@ contributors: - ["Alexander Kovalchuk", "https://github.com/Zamuhrishka"] --- -This article is available in [Russian](http://localhost:4567/docs/ru-ru/linker-ru/). +This article is available in [Russian](https://learnxinyminutes.com/docs/ru-ru/linker-ru/). diff --git a/lsf/lambda-calculus-lsf.html.markdown b/lsf/lambda-calculus-lsf.html.markdown new file mode 100644 index 00000000..88bb638f --- /dev/null +++ b/lsf/lambda-calculus-lsf.html.markdown @@ -0,0 +1,91 @@ +--- +category: Algorithms & Data Structures +name: Lambda Calculus +contributors: + - ["Max Sun", "http://github.com/maxsun"] +translators: + - ["Victore Leve", "https://github.com/AcProIL"] +lang: lsf +--- + +# Calculo λ + +Calculo lambda, creato principto per Alonzo Church, es lingua de programmatura +computatro maximo parvo. Quamquam non habe numero, serie de charactere vel ullo +typo de data non functionale, id pote repraesenta omne machina de Turing. + +Tres elemento compone calculo lambda: **quantitate variabile** (q.v.), +**functione** et **applicatione**. + +| Elemento | Syntaxe | Exemplo | +|----------------------|-----------------------------------|-----------| +| Quantitate variabile | `<nomine>` | `x` | +| Functione | `λ<parametro>.<corpore>` | `λx.x` | +| Applicatione | `<functione><q.v. aut functione>` | `(λx.x)a` | + +Functione fundamentale es identitate: `λx.x` cum argumento primo `x` et cum +corpore secundo `x`. In mathematica, nos scribe `id: x↦x`. + +## Quantitate variabile libero et ligato + +* In functione praecedente, `x` es q.v. ligato nam id es et in copore et + argumento. +* In `λx.y`, `y` es q.v. libero nam non es declarato ante. + +## Valutatione + +Valutatione es facto per reductione beta (reductione β) que es essentialiter +substitutione lexicale. + +Dum valutatione de formula `(λx.x)a`, nos substitue omne evento de `x` in +corpore de functione pro `a`. + +* `(λx.x)a` vale `a` +* `(λx.y)a` vale `y` + +Pote etiam crea functione de ordine supero: `(λx.(λy.x))a` vale `λy.a`. + +Etsi calculo lambda solo tracta functione de uno parametro, nos pote crea +functione cum plure argumento utente methodo de Curry: `λx.(λy.(λz.xyz))` +es scriptura informatica de formula mathematico `f: x, y, z ↦ x(y(z)))`. + +Ergo, interdum, nos ute `λxy.<corpore>` pro `λx.λy.<corpore>`. + +## Arithmetica + +### Logica de Boole + +Es nec numero nec booleano in calculo lambda. + +* «vero» es `v = λx.λy.x` +* «falso» es `f = λx.λy.y` + +Primo, nos pote defini functione «si t tunc a alio b» per `si = λtab.tab`. +Si `t` es vero, valutatione da `(λxy.x) a b` id es `a`. Similiter si `t` es +falso, nos obtine `b`. + +Secundo, nos pote defini operatore de logica: + +* «a et b» es `et = λa.λb.si a b f` +* «a vel b» es `vel = λa.λb.si a t b` +* «non a» es `non = λa.si a f t` + +### Numeros + +Nos pone: + +* `0 = λf.λx.x` (`0: f↦id`) +* `1 = λf.λx.f x` (`1: f↦f`) +* `2 = λf.λx.f(f x)` (`2: f↦f⚬f`) + +Cum mente generale, successore de numero `n` es `S n = λf.λx.f((n f) x)` +(`n+1: f↦f⚬fⁿ`). Id es **`n` est functione que da `fⁿ` ex functione `f`**. + +Postremo additione es `λab.(a S)b` + +## Ut progrede + +### In lingua anglo + +1. [A Tutorial Introduction to the Lambda Calculus](http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf) per Raúl Roja +2. [The Lambda Calculus](http://www.cs.cornell.edu/courses/cs3110/2008fa/recitations/rec26.html), CS 312 Recitation 26 diff --git a/lsf/latex-lsf.html.markdown b/lsf/latex-lsf.html.markdown new file mode 100644 index 00000000..18c2e62b --- /dev/null +++ b/lsf/latex-lsf.html.markdown @@ -0,0 +1,146 @@ +--- +language: latex +lang: lsf +contributors: + - ["Chaitanya Krishna Ande", "http://icymist.github.io"] + - ["Colton Kohnke", "http://github.com/voltnor"] + - ["Sricharan Chiruvolu", "http://sricharan.xyz"] +translators: + - ["Victore Leve", "https://github.com/AcProIL"] +filename: learn-latex-lsf.tex +--- + +```tex +% Solo existe commentario monolinea, illo incipe cum charactere % + +% LaTeX non es sicut MS Word aut OpenOffice: que scribe non es que obtine. +% Primo, scribe imperio (que semper incipe cum \) et secundo programma crea +% lima. + +% Nos defini typo de document (id es articulo aut libro aut libello etc.). +% Optione muta quomodo programma age, per exemplo altore de littera. +\documentclass[12pt]{article} + +% Deinde nos lista paccettos que nos vol ute. Es classe de imperio que alio +% utatore e scribe. Pote muta funda, geometria de pagina, etc. vel adde +% functionnalitate. +\usepackage{euler} +\usepackage{graphicx} + +% Ultimo statione ante scribe documento es metadata id es titulo, auctore et +% tempore. Charactere ~ es spatio que non pote es secato. +\title{Disce LaTeX in~Y Minutos!} +\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu} +\date{\today} + +% Principio de documento +\begin{document} + \maketitle % Nos vol adfige metadata. + + % Saepe nos adde breviario us describe texto. + \begin{abstract} + Hic es exmplo de documento sibre cum lingua de LaTeX. + \end{abstract} + + % \section crea sectione cum titulo dato sicut sperato + \section{Introductione} + + Traductione de hic cursu es importante. + + \subsection{Methodo} + Iste parte non es utile. + + \subsubsection{Methodo peculiare} + % \label da nomine ad parte ut post ute imperio de referentia \ref. + \label{subsec:metpec} + + % Cum asteritco nos indice que nos non vol numero ante titulo de sectione. + \section*{Me non aestima numero…} + + …sed de Peano aut de Church. + + \section{Listas} + + Que me debe scribe: + + \begin{enumerate} % `enumerate` designa lista cum numeros contra `itemize`. + \item articulo, + \item libro, + \item cursu. + \end{enumerate} + + \section{Mathematica} + + Methematicas ute multo programma LaTeX ut communica suo decooperito. + Illo necessita symbolo multo instar de logica vel sagitta vel littera cum + accento. + + % Fornula es in linea si nos scribe inter \( et \) (aut duo $) sed magno si + % nos ute \[ et \]. + \(\forall n\in N_0\) % pro omne n in classe N₀ + \[^{3}/_{4} = \frac{3}{4} < 1\] % ¾ < 1 + + Alphabeta graeco contine littera $\alpha$. + + % Ut scribe equatione cum numero et nomine, existe circumiecto `equation`. + \begin{equation} + c^2 = a^2 + b^2 + \label{eq:pythagoras} + \end{equation} + + \begin{equation} + % Summa ab 1 ad n de numeros dimidio de n(n+1) + \sum_{i=1}^n i = \frac{n(n+1)}{2} + \end{equation} + + \section{Figura} + + % Nos adde imagine `right-triangle.png` cum latitudo de quinque centimetro, + % horizontaliter in centro et cum capite «Triangulo recto». + \begin{figure} + \centering + \includegraphics[width=5cm]{right-triangle.png} + \caption{Triangulo recto} + \label{fig:right-triangle} + \end{figure} + + \subsection{Tabula} + + \begin{table} + \caption{Título para la tabla.} + % Argumento de `tabular` es lineamente de columna. + % c: centro, l: sinistra, r: destra, | linea verticale + \begin{tabular}{c|cc} + Numero & B & C \\ + \hline % linea horizontale + 1 & et & aut \\ + 2 & atque & vel + \end{tabular} + \end{table} + + \section{Stylo} + + Texto pote es \textbf{crasso} et \textit{italico}! + + \section{Texto puro} + + % Circumiecto `verbatim` ignora imperio, nos saepe ute id pro monstra + % programma. + \begin{verbatim} +from math import tau, e +print(e ** tau) + \end{verbatim} + + \section{Et plus!} + LaTeX habe facultate crea bibliographia, paritura, scaccarip… cum paccetto + dedicato. +\end{document} +``` + +Imperio ut conge documento es `pdflatex documento` in terminale. + +## Ut progrede + +### In lingua anglo + +* [LaTeX tutorial](http://www.latex-tutorial.com/) per Claudio Vellage diff --git a/lua.html.markdown b/lua.html.markdown index 0a7c4f00..f11d67a8 100644 --- a/lua.html.markdown +++ b/lua.html.markdown @@ -17,10 +17,7 @@ filename: learnlua.lua -- 1. Variables and flow control. ---------------------------------------------------- -num = 42 -- All numbers are doubles. --- Don't freak out, 64-bit doubles have 52 bits for --- storing exact int values; machine precision is --- not a problem for ints that need < 52 bits. +num = 42 -- Numbers can be integer or floating point. s = 'walternate' -- Immutable strings like Python. t = "double-quotes are also fine" @@ -58,7 +55,7 @@ foo = anUnknownVariable -- Now foo = nil. aBoolValue = false -- Only nil and false are falsy; 0 and '' are true! -if not aBoolValue then print('twas false') end +if not aBoolValue then print('it was false') end -- 'or' and 'and' are short-circuited. -- This is similar to the a?b:c operator in C/js: @@ -116,7 +113,7 @@ function bar(a, b, c) end x, y = bar('zaphod') --> prints "zaphod nil nil" --- Now x = 4, y = 8, values 15..42 are discarded. +-- Now x = 4, y = 8, values 15...42 are discarded. -- Functions are first-class, may be local/global. -- These are the same: @@ -193,7 +190,7 @@ end -- A table can have a metatable that gives the table -- operator-overloadish behavior. Later we'll see --- how metatables support js-prototypey behavior. +-- how metatables support js-prototype behavior. f1 = {a = 1, b = 2} -- Represents the fraction a/b. f2 = {a = 2, b = 3} @@ -364,7 +361,7 @@ end)() -- locals inside mod.lua are invisible outside it. -- This works because mod here = M in mod.lua: -mod.sayHello() -- Says hello to Hrunkner. +mod.sayHello() -- Prints: Why hello there Hrunkner -- This is wrong; sayMyName only exists in mod.lua: mod.sayMyName() -- error @@ -383,23 +380,30 @@ dofile('mod2.lua') --> Hi! (runs it again) -- loadfile loads a lua file but doesn't run it yet. f = loadfile('mod2.lua') -- Call f() to run it. --- loadstring is loadfile for strings. -g = loadstring('print(343)') -- Returns a function. +-- load is loadfile for strings. +-- (loadstring is deprecated, use load instead) +g = load('print(343)') -- Returns a function. g() -- Prints out 343; nothing printed before now. --]] ``` + +## Community + +If you need support join the official Lua [mailing list](https://www.lua.org/lua-l.html), [irc channel](http://lua-users.org/wiki/IrcChannel), or [forum](https://luaforum.com). + + ## References I was excited to learn Lua so I could make games with the <a href="http://love2d.org/">Love 2D game engine</a>. That's the why. -I started with <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV's Lua for programmers</a>. +I started with <a href="https://ebens.me/posts/lua-for-programmers-part-1/">BlackBulletIV's Lua for programmers</a>. Next I read the official <a href="http://www.lua.org/pil/contents.html">Programming in Lua</a> book. That's the how. -It might be helpful to check out the <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Lua short +It might be helpful to check out the <a href="http://lua-users.org/wiki/LuaShortReference">Lua short reference</a> on lua-users.org. The main topics not covered are standard libraries: diff --git a/m.html.markdown b/m.html.markdown index 96828ae5..46e7313b 100644 --- a/m.html.markdown +++ b/m.html.markdown @@ -17,8 +17,8 @@ more fits on one screen without scrolling. The M database is a hierarchical key-value store designed for high-throughput transaction processing. The database is organized into tree structures called -"globals", which are sparse data structures with parallels to modern formats -like JSON. +"globals", (for global variables) which are sparse data structures with parallels +to modern formats like JSON. Originally designed in 1966 for the healthcare applications, M continues to be used widely by healthcare systems and financial institutions for high-throughput @@ -26,7 +26,7 @@ real-time applications. ### Example -Here's an example M program to calculate the Fibonacci series: +Here's an example M program using expanded syntax to calculate the Fibonacci series: ``` fib ; compute the first few Fibonacci terms @@ -39,28 +39,38 @@ fib ; compute the first few Fibonacci terms ``` ### Comments +Comments in M need at least one space before the comment marker of semicolon. +Comments that start with at least two semicolons (;;) are guaranteed to be accessible +within a running program. ``` -; Comments start with a semicolon (;) + ; Comments start with a semicolon (;) ``` ### Data Types -M has two data types: +M has one data type (String) and three interpretations of that string.: ``` -; Numbers - no commas, leading and trailing 0 removed. -; Scientific notation with 'E'. -; Floats with IEEE 754 double-precision values (15 digits of precision) -; Examples: 20, 1e3 (stored as 1000), 0500.20 (stored as 500.2) ; Strings - Characters enclosed in double quotes. ; "" is the null string. Use "" within a string for " ; Examples: "hello", "Scrooge said, ""Bah, Humbug!""" +; +; Numbers - no commas, leading and trailing 0 removed. +; Scientific notation with 'E'. (not 'e') +; Numbers with at least with IEEE 754 double-precision values (guaranteed 15 digits of precision) +; Examples: 20 (stored as 20) , 1e3 (stored as 1000), 0500.20 (stored as 500.2), +; the US National Debt AT sometime on 12-OCT-2020 retrieved from http://www.usdebt.org is 27041423576201.15) +; (required to be stored as at least 27041422576201.10 but most implementations store as 27041432576201.15) +; +; Truthvalues - String interpreted as 0 is used for false and any string interpreted as non-zero (such as 1) for true. ``` ### Commands -Commands are case insensitive, and have a shortened abbreviation, often the first letter. Commands have zero or more arguments,depending on the command. M is whitespace-aware. Spaces are treated as a delimiter between commands and arguments. Each command is separated from its arguments by 1 space. Commands with zero arguments are followed by 2 spaces. +Commands are case insensitive, and have full form, and a shortened abbreviation, often the first letter. Commands have zero or more arguments,depending on the command. This page includes programs written in this terse syntax. M is whitespace-aware. Spaces are treated as a delimiter between commands and arguments. Each command is separated from its arguments by 1 space. Commands with zero arguments are followed by 2 spaces. (technically these are called argumentless commands) + +#### Common Commands from all National and International Standards of M -#### W(rite) +#### Write (abbreviated as W) Print data to the current device. @@ -68,13 +78,19 @@ Print data to the current device. WRITE !,"hello world" ``` -! is syntax for a new line. Multiple statements can be provided as additional arguments: +Output Formatting characters: + + The ! character is syntax for a new line. + The # character is syntax for a new page. + The sequence of the ? character and then a numeric expression is syntax for output of spaces until the number'th colum is printed. + +Multiple statements can be provided as additional arguments before the space separators to the next command: ``` w !,"foo bar"," ","baz" ``` -#### R(ead) +#### Read (abbreviated as R) Retrieve input from the user @@ -82,13 +98,13 @@ Retrieve input from the user READ var r !,"Wherefore art thou Romeo? ",why ``` -Multiple arguments can be passed to a read command. Constants are outputted. Variables are retrieved from the user. The terminal waits for the user to enter the first variable before displaying the second prompt. +As with all M commands, multiple arguments can be passed to a read command. Constants like quoted strings, numbers, and formatting characters are output directly. Values for both global variables and local variables are retrieved from the user. The terminal waits for the user to enter the first variable before displaying the second prompt. ``` r !,"Better one, or two? ",lorem," Better two, or three? ",ipsum ``` -#### S(et) +#### Set (abbreviated as S) Assign a value to a variable @@ -100,19 +116,21 @@ w !,centi,!,micro ;.01 ;.00001 ``` -#### K(ill) +#### Kill (abbreviated as K) Remove a variable from memory or remove a database entry from disk. - +A database node (global variable) is killed depending on the variable name being prefixed by the caret character (^). +If it is not, then the local variable is removed from memory. +If KILLed, automatic garbage collection occurs. ``` KILL centi k micro ``` ### Globals and Arrays -In addition to local variables, M has persistent variables stored to disk called _globals_. Global names must start with a __caret__ (__^__). Globals are the built-in database of M. +In addition to local variables, M has persistent, shared variables that are the built-in database of M. They are stored to disk and called _globals_. Global names must start with a __caret__ (__^__). -Any variable can be an array with the assignment of a _subscript_. Arrays are sparse and do not have a predefined size. Arrays should be visualized like trees, where subscripts are branches and assigned values are leaves. Not all nodes in an array need to have a value. +Any variable (local or global) can be an array with the assignment of a _subscript_. Arrays are sparse and do not have a predefined size. Only if data is stored will a value use memory. Arrays should be visualized like trees, where subscripts are branches and assigned values are leaves. Not all nodes in an array need to have a value. ``` s ^cars=20 @@ -128,7 +146,7 @@ w !,^cars("Tesla",1,"Name") ; Model 3 ``` -Arrays are automatically sorted in order. Take advantage of the built-in sorting by setting your value of interest as the last child subscript of an array rather than its value. +The index values of Arrays are automatically sorted in order. There is a catchphrase of "MUMPS means never having to say you are sorting". Take advantage of the built-in sorting by setting your value of interest as the last child subscript of an array rather than its value, and then storing an empty string for that node. ``` ; A log of temperatures by date and time @@ -171,13 +189,14 @@ s ^TEMPS("11/12","1700",43)="" #### Order of operations Operations in M are _strictly_ evaluated left to right. No operator has precedence over any other. -You should use parentheses to group expressions. +For example, there is NO order of operations where multiply is evaluated before addition. +To change this order, just use parentheses to group expressions to be evaluated first. ``` w 5+3*20 ;160 ;You probably wanted 65 -w 5+(3*20) +write 5+(3*20) ``` ### Flow Control, Blocks, & Code Structure @@ -193,12 +212,12 @@ w !,$$tag^routine(a,b) M has an execution stack. When all levels of the stack have returned, the program ends. Levels are added to the stack with _do_ commands and removed with _quit_ commands. -#### D(o) +#### Do (abbreviated as D) With an argument: execute a block of code & add a level to the stack. ``` -d ^routine ;run a routine from the begining. +d ^routine ;run a routine from the beginning. ; ;routines are identified by a caret. d tag ;run a tag in the current routine d tag^routine ;run a tag in different routine @@ -216,12 +235,14 @@ if a=1 do w "hello" ``` -#### Q(uit) +#### Quit (abbreviated as Q) Stop executing this block and return to the previous stack level. -Quit can return a value. +Quit can return a value, following the comamnd with a single space. +Quit can stop a loop. remember to follow with two spaces. +Quit outside a loop will return from the current subroutine followed by two spaces or a linefeed -#### N(ew) -Clear a given variable's value _for just this stack level_. Useful for preventing side effects. +#### New (abbreviated as N) +Hide with a cleared value a given variable's value _for just this stack level_. Useful for preventing side effects. Putting all this together, we can create a full example of an M routine: @@ -233,20 +254,22 @@ main n length,width ; New length and width so any previous value doesn't persist w !,"Welcome to RECTANGLE. Enter the dimensions of your rectangle." r !,"Length? ",length,!,"Width? ",width - d area(length,width) ;Do a tag - s per=$$perimeter(length,width) ;Get the value of a function + d area(length,width) ;Do/Call subroutine using a tag + s per=$$perimeter(length,width) ;Get the value of a function w !,"Perimeter: ",per - q + quit area(length,width) ; This is a tag that accepts parameters. ; It's not a function since it quits with no value. w !, "Area: ",length*width - q ; Quit: return to the previous level of the stack. + q ; Quit: return to the previous level of the stack. perimeter(length,width) - q 2*(length+width) ; Quits with a value; thus a function + q 2*(length+width) ; Returns a value using Quit ; this is a function ``` + + ### Conditionals, Looping and $Order() F(or) loops can follow a few different patterns: @@ -255,13 +278,15 @@ F(or) loops can follow a few different patterns: ;Finite loop with counter ;f var=start:increment:stop -f i=0:5:25 w i," " ;0 5 10 15 20 25 +f i=0:5:25 w i," " +;0 5 10 15 20 25 ; Infinite loop with counter ; The counter will keep incrementing forever. Use a conditional with Quit to get out of the loop. ;f var=start:increment -f j=1:1 w j," " i j>1E3 q ; Print 1-1000 separated by a space +f j=1:1 w j," " i j>1E3 q +; Print 1-1000 separated by a space ;Argumentless for - infinite loop. Use a conditional with Quit. ; Also read as "forever" - f or for followed by two spaces. @@ -355,7 +380,11 @@ f s date=$ORDER(^TEMPS(date)) q:date="" d ## Further Reading -There's lots more to learn about M. A great short tutorial comes from the University of Northern Iowa and Professor Kevin O'Kane's [Introduction to the MUMPS Language][1] presentation. +There's lots more to learn about M. A great short tutorial comes from the University of Northern Iowa and Professor Kevin O'Kane's [Introduction to the MUMPS Language][1] presentation. More about M using VistA is at + +Intersystems has some products which are a super-set of the M programming language. +* [Iris Description Page][5] +* [Cache Description Page][6] To install an M interpreter / database on your computer, try a [YottaDB Docker image][2]. @@ -368,3 +397,5 @@ YottaDB and its precursor, GT.M, have thorough documentation on all the language [2]: https://yottadb.com/product/get-started/ [3]: https://docs.yottadb.com/ProgrammersGuide/langfeat.html [4]: http://tinco.pair.com/bhaskar/gtm/doc/books/pg/UNIX_manual/index.html +[5]: https://www.intersystems.com/products/intersystems-iris/ +[6]: https://en.wikipedia.org/wiki/InterSystems_Caché diff --git a/make.html.markdown b/make.html.markdown index eecc96bf..f5352f9e 100644 --- a/make.html.markdown +++ b/make.html.markdown @@ -1,246 +1,246 @@ ----
-category: tool
-tool: make
-contributors:
- - ["Robert Steed", "https://github.com/robochat"]
- - ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
-filename: Makefile
----
-
-A Makefile defines a graph of rules for creating a target (or targets).
-Its purpose is to do the minimum amount of work needed to update a
-target to the most recent version of the source. Famously written over a
-weekend by Stuart Feldman in 1976, it is still widely used (particularly
-on Unix and Linux) despite many competitors and criticisms.
-
-There are many varieties of make in existence, however this article
-assumes that we are using GNU make which is the standard on Linux.
-
-```make
-
-# Comments can be written like this.
-
-# File should be named Makefile and then can be run as `make <target>`.
-# Otherwise we use `make -f "filename" <target>`.
-
-# Warning - only use TABS to indent in Makefiles, never spaces!
-
-#-----------------------------------------------------------------------
-# Basics
-#-----------------------------------------------------------------------
-
-# Rules are of the format
-# target: <prerequisite>
-# where prerequisites are optional.
-
-# A rule - this rule will only run if file0.txt doesn't exist.
-file0.txt:
- echo "foo" > file0.txt
- # Even comments in these 'recipe' sections get passed to the shell.
- # Try `make file0.txt` or simply `make` - first rule is the default.
-
-# This rule will only run if file0.txt is newer than file1.txt.
-file1.txt: file0.txt
- cat file0.txt > file1.txt
- # use the same quoting rules as in the shell.
- @cat file0.txt >> file1.txt
- # @ stops the command from being echoed to stdout.
- -@echo 'hello'
- # - means that make will keep going in the case of an error.
- # Try `make file1.txt` on the commandline.
-
-# A rule can have multiple targets and multiple prerequisites
-file2.txt file3.txt: file0.txt file1.txt
- touch file2.txt
- touch file3.txt
-
-# Make will complain about multiple recipes for the same rule. Empty
-# recipes don't count though and can be used to add new dependencies.
-
-#-----------------------------------------------------------------------
-# Phony Targets
-#-----------------------------------------------------------------------
-
-# A phony target. Any target that isn't a file.
-# It will never be up to date so make will always try to run it.
-all: maker process
-
-# We can declare things out of order.
-maker:
- touch ex0.txt ex1.txt
-
-# Can avoid phony rules breaking when a real file has the same name by
-.PHONY: all maker process
-# This is a special target. There are several others.
-
-# A rule with a dependency on a phony target will always run
-ex0.txt ex1.txt: maker
-
-# Common phony targets are: all make clean install ...
-
-#-----------------------------------------------------------------------
-# Automatic Variables & Wildcards
-#-----------------------------------------------------------------------
-
-process: file*.txt #using a wildcard to match filenames
- @echo $^ # $^ is a variable containing the list of prerequisites
- @echo $@ # prints the target name
- #(for multiple target rules, $@ is whichever caused the rule to run)
- @echo $< # the first prerequisite listed
- @echo $? # only the dependencies that are out of date
- @echo $+ # all dependencies including duplicates (unlike normal)
- #@echo $| # all of the 'order only' prerequisites
-
-# Even if we split up the rule dependency definitions, $^ will find them
-process: ex1.txt file0.txt
-# ex1.txt will be found but file0.txt will be deduplicated.
-
-#-----------------------------------------------------------------------
-# Patterns
-#-----------------------------------------------------------------------
-
-# Can teach make how to convert certain files into other files.
-
-%.png: %.svg
- inkscape --export-png $^
-
-# Pattern rules will only do anything if make decides to create the
-# target.
-
-# Directory paths are normally ignored when matching pattern rules. But
-# make will try to use the most appropriate rule available.
-small/%.png: %.svg
- inkscape --export-png --export-dpi 30 $^
-
-# make will use the last version for a pattern rule that it finds.
-%.png: %.svg
- @echo this rule is chosen
-
-# However make will use the first pattern rule that can make the target
-%.png: %.ps
- @echo this rule is not chosen if *.svg and *.ps are both present
-
-# make already has some pattern rules built-in. For instance, it knows
-# how to turn *.c files into *.o files.
-
-# Older makefiles might use suffix rules instead of pattern rules
-.png.ps:
- @echo this rule is similar to a pattern rule.
-
-# Tell make about the suffix rule
-.SUFFIXES: .png
-
-#-----------------------------------------------------------------------
-# Variables
-#-----------------------------------------------------------------------
-# aka. macros
-
-# Variables are basically all string types
-
-name = Ted
-name2="Sarah"
-
-echo:
- @echo $(name)
- @echo ${name2}
- @echo $name # This won't work, treated as $(n)ame.
- @echo $(name3) # Unknown variables are treated as empty strings.
-
-# There are 4 places to set variables.
-# In order of priority from highest to lowest:
-# 1: commandline arguments
-# 2: Makefile
-# 3: shell environment variables - make imports these automatically.
-# 4: make has some predefined variables
-
-name4 ?= Jean
-# Only set the variable if environment variable is not already defined.
-
-override name5 = David
-# Stops commandline arguments from changing this variable.
-
-name4 +=grey
-# Append values to variable (includes a space).
-
-# Pattern-specific variable values (GNU extension).
-echo: name2 = Sara # True within the matching rule
- # and also within its remade recursive dependencies
- # (except it can break when your graph gets too complicated!)
-
-# Some variables defined automatically by make.
-echo_inbuilt:
- echo $(CC)
- echo ${CXX}
- echo $(FC)
- echo ${CFLAGS}
- echo $(CPPFLAGS)
- echo ${CXXFLAGS}
- echo $(LDFLAGS)
- echo ${LDLIBS}
-
-#-----------------------------------------------------------------------
-# Variables 2
-#-----------------------------------------------------------------------
-
-# The first type of variables are evaluated each time they are used.
-# This can be expensive, so a second type of variable exists which is
-# only evaluated once. (This is a GNU make extension)
-
-var := hello
-var2 ::= $(var) hello
-#:= and ::= are equivalent.
-
-# These variables are evaluated procedurally (in the order that they
-# appear), thus breaking with the rest of the language !
-
-# This doesn't work
-var3 ::= $(var4) and good luck
-var4 ::= good night
-
-#-----------------------------------------------------------------------
-# Functions
-#-----------------------------------------------------------------------
-
-# make has lots of functions available.
-
-sourcefiles = $(wildcard *.c */*.c)
-objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
-
-# Format is $(func arg0,arg1,arg2...)
-
-# Some examples
-ls: * src/*
- @echo $(filter %.txt, $^)
- @echo $(notdir $^)
- @echo $(join $(dir $^),$(notdir $^))
-
-#-----------------------------------------------------------------------
-# Directives
-#-----------------------------------------------------------------------
-
-# Include other makefiles, useful for platform specific code
-include foo.mk
-
-sport = tennis
-# Conditional compilation
-report:
-ifeq ($(sport),tennis)
- @echo 'game, set, match'
-else
- @echo "They think it's all over; it is now"
-endif
-
-# There are also ifneq, ifdef, ifndef
-
-foo = true
-
-ifdef $(foo)
-bar = 'hello'
-endif
-```
-
-### More Resources
-
-+ [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"] +filename: Makefile +--- + +A Makefile defines a graph of rules for creating a target (or targets). +Its purpose is to do the minimum amount of work needed to update a +target to the most recent version of the source. Famously written over a +weekend by Stuart Feldman in 1976, it is still widely used (particularly +on Unix and Linux) despite many competitors and criticisms. + +There are many varieties of make in existence, however this article +assumes that we are using GNU make which is the standard on Linux. + +```make + +# Comments can be written like this. + +# File should be named Makefile and then can be run as `make <target>`. +# Otherwise we use `make -f "filename" <target>`. + +# Warning - only use TABS to indent in Makefiles, never spaces! + +#----------------------------------------------------------------------- +# Basics +#----------------------------------------------------------------------- + +# Rules are of the format +# target: <prerequisite> +# where prerequisites are optional. + +# A rule - this rule will only run if file0.txt doesn't exist. +file0.txt: + echo "foo" > file0.txt + # Even comments in these 'recipe' sections get passed to the shell. + # Try `make file0.txt` or simply `make` - first rule is the default. + +# This rule will only run if file0.txt is newer than file1.txt. +file1.txt: file0.txt + cat file0.txt > file1.txt + # use the same quoting rules as in the shell. + @cat file0.txt >> file1.txt + # @ stops the command from being echoed to stdout. + -@echo 'hello' + # - means that make will keep going in the case of an error. + # Try `make file1.txt` on the commandline. + +# A rule can have multiple targets and multiple prerequisites +file2.txt file3.txt: file0.txt file1.txt + touch file2.txt + touch file3.txt + +# Make will complain about multiple recipes for the same rule. Empty +# recipes don't count though and can be used to add new dependencies. + +#----------------------------------------------------------------------- +# Phony Targets +#----------------------------------------------------------------------- + +# A phony target. Any target that isn't a file. +# It will never be up to date so make will always try to run it. +all: maker process + +# We can declare things out of order. +maker: + touch ex0.txt ex1.txt + +# Can avoid phony rules breaking when a real file has the same name by +.PHONY: all maker process +# This is a special target. There are several others. + +# A rule with a dependency on a phony target will always run +ex0.txt ex1.txt: maker + +# Common phony targets are: all make clean install ... + +#----------------------------------------------------------------------- +# Automatic Variables & Wildcards +#----------------------------------------------------------------------- + +process: file*.txt #using a wildcard to match filenames + @echo $^ # $^ is a variable containing the list of prerequisites + @echo $@ # prints the target name + #(for multiple target rules, $@ is whichever caused the rule to run) + @echo $< # the first prerequisite listed + @echo $? # only the dependencies that are out of date + @echo $+ # all dependencies including duplicates (unlike normal) + #@echo $| # all of the 'order only' prerequisites + +# Even if we split up the rule dependency definitions, $^ will find them +process: ex1.txt file0.txt +# ex1.txt will be found but file0.txt will be deduplicated. + +#----------------------------------------------------------------------- +# Patterns +#----------------------------------------------------------------------- + +# Can teach make how to convert certain files into other files. + +%.png: %.svg + inkscape --export-png $^ + +# Pattern rules will only do anything if make decides to create the +# target. + +# Directory paths are normally ignored when matching pattern rules. But +# make will try to use the most appropriate rule available. +small/%.png: %.svg + inkscape --export-png --export-dpi 30 $^ + +# make will use the last version for a pattern rule that it finds. +%.png: %.svg + @echo this rule is chosen + +# However make will use the first pattern rule that can make the target +%.png: %.ps + @echo this rule is not chosen if *.svg and *.ps are both present + +# make already has some pattern rules built-in. For instance, it knows +# how to turn *.c files into *.o files. + +# Older makefiles might use suffix rules instead of pattern rules +.png.ps: + @echo this rule is similar to a pattern rule. + +# Tell make about the suffix rule +.SUFFIXES: .png + +#----------------------------------------------------------------------- +# Variables +#----------------------------------------------------------------------- +# aka. macros + +# Variables are basically all string types + +name = Ted +name2="Sarah" + +echo: + @echo $(name) + @echo ${name2} + @echo $name # This won't work, treated as $(n)ame. + @echo $(name3) # Unknown variables are treated as empty strings. + +# There are 4 places to set variables. +# In order of priority from highest to lowest: +# 1: commandline arguments +# 2: Makefile +# 3: shell environment variables - make imports these automatically. +# 4: make has some predefined variables + +name4 ?= Jean +# Only set the variable if environment variable is not already defined. + +override name5 = David +# Stops commandline arguments from changing this variable. + +name4 +=grey +# Append values to variable (includes a space). + +# Pattern-specific variable values (GNU extension). +echo: name2 = Sara # True within the matching rule + # and also within its remade recursive dependencies + # (except it can break when your graph gets too complicated!) + +# Some variables defined automatically by make. +echo_inbuilt: + echo $(CC) + echo ${CXX} + echo $(FC) + echo ${CFLAGS} + echo $(CPPFLAGS) + echo ${CXXFLAGS} + echo $(LDFLAGS) + echo ${LDLIBS} + +#----------------------------------------------------------------------- +# Variables 2 +#----------------------------------------------------------------------- + +# The first type of variables are evaluated each time they are used. +# This can be expensive, so a second type of variable exists which is +# only evaluated once. (This is a GNU make extension) + +var := hello +var2 ::= $(var) hello +#:= and ::= are equivalent. + +# These variables are evaluated procedurally (in the order that they +# appear), thus breaking with the rest of the language ! + +# This doesn't work +var3 ::= $(var4) and good luck +var4 ::= good night + +#----------------------------------------------------------------------- +# Functions +#----------------------------------------------------------------------- + +# make has lots of functions available. + +sourcefiles = $(wildcard *.c */*.c) +objectfiles = $(patsubst %.c,%.o,$(sourcefiles)) + +# Format is $(func arg0,arg1,arg2...) + +# Some examples +ls: * src/* + @echo $(filter %.txt, $^) + @echo $(notdir $^) + @echo $(join $(dir $^),$(notdir $^)) + +#----------------------------------------------------------------------- +# Directives +#----------------------------------------------------------------------- + +# Include other makefiles, useful for platform specific code +include foo.mk + +sport = tennis +# Conditional compilation +report: +ifeq ($(sport),tennis) + @echo 'game, set, match' +else + @echo "They think it's all over; it is now" +endif + +# There are also ifneq, ifdef, ifndef + +foo = true + +ifdef $(foo) +bar = 'hello' +endif +``` + +### More Resources + ++ [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) diff --git a/markdown.html.markdown b/markdown.html.markdown index cf4286e2..ee213083 100644 --- a/markdown.html.markdown +++ b/markdown.html.markdown @@ -3,12 +3,13 @@ language: markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] - ["Jacob Ward", "http://github.com/JacobCWard/"] + - ["Tomáš Hartman", "https://github.com/tomas-hartman"] filename: markdown.md --- -Markdown was created by John Gruber in 2004. It's meant to be an easy to read -and write syntax which converts easily to HTML (and now many other formats as +Markdown was created by John Gruber in 2004. It's meant to be an easy to read +and write syntax which converts easily to HTML (and now many other formats as well). Markdown also varies in implementation from one parser to a next. This @@ -17,22 +18,31 @@ specific to a certain parser. - [HTML Elements](#html-elements) - [Headings](#headings) -- [Simple Text Styles](#simple-text-styles) +- [Simple text styles](#simple-text-styles) - [Paragraphs](#paragraphs) - [Lists](#lists) - [Code blocks](#code-blocks) - [Horizontal rule](#horizontal-rule) - [Links](#links) + - [Table of contents](#table-of-contents) - [Images](#images) - [Miscellany](#miscellany) + - [Auto-links](#auto-links) + - [Auto-links for emails](#auto-links-for-emails) + - [Escaping characters](#escaping-characters) + - [Keyboard keys](#keyboard-keys) + - [Tables](#tables) +- [Markdownlint](#markdownlint) +- [Further reading](#further-reading) ## HTML Elements + Markdown is a superset of HTML, so any HTML file is valid Markdown. ```md -<!--This means we can use HTML elements in Markdown, such as the comment -element, and they won't be affected by a markdown parser. However, if you -create an HTML element in your markdown file, you cannot use markdown syntax +<!--This means we can use HTML elements in Markdown, such as the comment +element, and they won't be affected by a markdown parser. However, if you +create an HTML element in your markdown file, you cannot use markdown syntax within that element's contents.--> ``` @@ -49,6 +59,7 @@ text you want to be in that element by a number of hashes (#). ##### This is an <h5> ###### This is an <h6> ``` + Markdown also provides us with two alternative ways of indicating h1 and h2. ```md @@ -81,6 +92,7 @@ GitHub, we also have strikethrough: ```md ~~This text is rendered with strikethrough.~~ ``` + ## Paragraphs Paragraphs are a one or multiple adjacent lines of text separated by one or @@ -119,6 +131,7 @@ Block quotes are easy and done with the > character. ``` ## Lists + Unordered lists can be made using asterisks, pluses, or hyphens. ```md @@ -155,9 +168,10 @@ render the numbers in order, but this may not be a good idea. 1. Item two 1. Item three ``` -(This renders the same as the above example) -You can also use sublists +(This renders the same as the example above.) + +You can also use sublists. ```md 1. Item one @@ -189,35 +203,36 @@ a line with four spaces or a tab. ``` You can also re-tab (or add an additional four spaces) for indentation -inside your code +inside your code. ```md my_array.each do |item| - puts item + puts item end ``` -Inline code can be created using the backtick character `` ` `` +Inline code can be created using the backtick character `` ` ``. ```md John didn't even know what the `go_to()` function did! ``` -In GitHub Flavored Markdown, you can use a special syntax for code +In GitHub Flavored Markdown, you can use a special syntax for code. -<pre> -<code class="highlight">```ruby +````md +```ruby def foobar - puts "Hello world!" + puts "Hello world!" end -```</code></pre> +``` +```` The above text doesn't require indenting, plus GitHub will use syntax -highlighting of the language you specify after the \`\`\` +highlighting of the language you specify after the opening <code>```</code>. ## Horizontal rule -Horizontal rules (`<hr/>`) are easily added with three or more asterisks or +Horizontal rules (`<hr/>`) are easily added with three or more asterisks or hyphens, with or without spaces. ```md @@ -235,11 +250,13 @@ the text to display in hard brackets [] followed by the url in parentheses () ```md [Click me!](http://test.com/) ``` + You can also add a link title using quotes inside the parentheses. ```md [Click me!](http://test.com/ "Link to Test.com") ``` + Relative paths work too. ```md @@ -248,11 +265,13 @@ Relative paths work too. Markdown also supports reference style links. -<pre><code class="highlight">[<span class="nv">Click this link</span>][<span class="ss">link1</span>] for more info about it! -[<span class="nv">Also check out this link</span>][<span class="ss">foobar</span>] if you want to. +```md +[Click this link][link1] for more info about it! +[Also check out this link][foobar] if you want to. -[<span class="nv">link1</span>]: <span class="sx">http://test.com/</span> <span class="nn">"Cool!"</span> -[<span class="nv">foobar</span>]: <span class="sx">http://foobar.biz/</span> <span class="nn">"Alright!"</span></code></pre> +[link1]: http://test.com/ "Cool!" +[foobar]: http://foobar.biz/ "Alright!" +``` The title can also be in single quotes or in parentheses, or omitted entirely. The references can be anywhere in your document and the reference IDs @@ -260,13 +279,35 @@ can be anything so long as they are unique. There is also "implicit naming" which lets you use the link text as the id. -<pre><code class="highlight">[<span class="nv">This</span>][] is a link. +```md +[This][] is a link. -[<span class="nv">this</span>]: <span class="sx">http://thisisalink.com/</span></code></pre> +[This]: http://thisisalink.com/ +``` But it's not that commonly used. +### Table of contents + +Some Markdown flavors even make use of the combination of lists, links and +headings in order to create tables of contents. In this case, heading titles in +lowercase are prepended with hash (`#`) and are used as link ids. Should the +heading have multiple words, they will be connected with a hyphen (`-`), that +also replaces some special characters. (Some other special characters are +omitted though.) + +```md +- [Heading](#heading) +- [Another heading](#another-heading) +- [Chapter](#chapter) + - [Subchapter <h3 />](#subchapter-h3-) +``` + +Nonetheless, this is a feature that might not be working in all Markdown +implementations the same way. + ## Images + Images are done the same way as links but with an exclamation point in front! ```md @@ -275,10 +316,14 @@ Images are done the same way as links but with an exclamation point in front! And reference style works as expected. -<pre><code class="highlight">![<span class="nv">This is the alt-attribute.</span>][<span class="ss">myimage</span>] +```md +![This is the alt-attribute.][myimage] + +[myimage]: relative/urls/cool/image.jpg "if you need a title, it's here" +``` -[<span class="nv">myimage</span>]: <span class="sx">relative/urls/cool/image.jpg</span> <span class="nn">"if you need a title, it's here"</span></code></pre> ## Miscellany + ### Auto-links ```md @@ -301,13 +346,14 @@ in italics, so I do this: \*this text surrounded by asterisks\*. ### Keyboard keys -In GitHub Flavored Markdown, you can use a `<kbd>` tag to represent keyboard +In GitHub Flavored Markdown, you can use a `<kbd>` tag to represent keyboard keys. ```md Your computer crashed? Try sending a <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> ``` + ### Tables Tables are only available in GitHub Flavored Markdown and are slightly @@ -319,6 +365,7 @@ cumbersome, but if you really want it: | Left-aligned | Centered | Right-aligned | | blah | blah | blah | ``` + or, for the same results ```md @@ -327,5 +374,21 @@ Col 1 | Col2 | Col3 Ugh this is so ugly | make it | stop ``` +## Markdownlint + +In order to simplify work with Markdown and to unify its coding style, +`Markdownlint` has been created. Available as a +[separate tool](https://github.com/markdownlint/markdownlint) +as well as a plugin for some IDEs, it can be used to ensure validity and +readability of Markdown. + --- + +## Further reading + For more info, check out John Gruber's official post of syntax [here](http://daringfireball.net/projects/markdown/syntax) and Adam Pritchard's great cheatsheet [here](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). + +If you want to learn more on some major Markdown flavors' features, see: + +- [GitHub flavored Markdown](https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) +- [GitLab flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html) diff --git a/matlab.html.markdown b/matlab.html.markdown index 5790bcc6..b0482d0b 100644 --- a/matlab.html.markdown +++ b/matlab.html.markdown @@ -1,5 +1,5 @@ --- -language: Matlab +language: MATLAB filename: learnmatlab.mat contributors: - ["mendozao", "http://github.com/mendozao"] @@ -28,7 +28,7 @@ this % Two percent signs denote the start of a new code section % Individual code sections can be run by moving the cursor to the section followed by % either clicking the "Run Section" button -% or using Ctrl+Shift+Enter (Windows) or Cmd+Shift+Return (OS X) +% or using Ctrl+Shift+Enter (Windows) or Cmd+Shift+Return (macOS) %% This is the start of a code section % One way of using sections is to separate expensive but unchanging start-up code like loading data @@ -134,7 +134,7 @@ A.d.e = false; % Vectors x = [4 32 53 7 1] -x(2) % ans = 32, indices in Matlab start 1, not 0 +x(2) % ans = 32, indices in MATLAB start 1, not 0 x(2:3) % ans = 32 53 x(2:end) % ans = 32 53 7 1 @@ -234,7 +234,7 @@ A' % Concise version of complex transpose % On their own, the arithmetic operators act on whole matrices. When preceded % by a period, they act on each element instead. For example: A * B % Matrix multiplication -A .* B % Multiple each element in A by its corresponding element in B +A .* B % Multiply each element in A by its corresponding element in B % There are several pairs of functions, where one acts on each element, and % the other (whose name ends in m) acts on the whole matrix. @@ -502,7 +502,7 @@ find(x) % Finds all non-zero elements of x and returns their indexes, can use co % Classes -% Matlab can support object-oriented programming. +% MATLAB can support object-oriented programming. % Classes must be put in a file of the class name with a .m extension. % To begin, we create a simple class to store GPS waypoints. % Begin WaypointClass.m @@ -524,7 +524,7 @@ classdef WaypointClass % The class name. end % If we want to add two Waypoint objects together without calling - % a special function we can overload Matlab's arithmetic like so: + % a special function we can overload MATLAB's arithmetic like so: function r = plus(o1,o2) r = WaypointClass([o1.latitude] +[o2.latitude], ... [o1.longitude]+[o2.longitude]); @@ -536,7 +536,7 @@ end % We can create an object of the class using the constructor a = WaypointClass(45.0, 45.0) -% Class properties behave exactly like Matlab Structures. +% Class properties behave exactly like MATLAB Structures. a.latitude = 70.0 a.longitude = 25.0 @@ -547,15 +547,15 @@ ans = multiplyLatBy(a,3) % does not need to be passed to the method. ans = a.multiplyLatBy(1/3) -% Matlab functions can be overloaded to handle objects. -% In the method above, we have overloaded how Matlab handles +% MATLAB functions can be overloaded to handle objects. +% In the method above, we have overloaded how MATLAB handles % the addition of two Waypoint objects. b = WaypointClass(15.0, 32.0) c = a + b ``` -## More on Matlab +## More on MATLAB * [The official website](http://www.mathworks.com/products/matlab/) * [The official MATLAB Answers forum](http://www.mathworks.com/matlabcentral/answers/) diff --git a/mercurial.html.markdown b/mercurial.html.markdown index 98658f83..2c06ca77 100644 --- a/mercurial.html.markdown +++ b/mercurial.html.markdown @@ -22,13 +22,13 @@ and/or directorie(s) over time. * Distributed Architecture - Traditionally version control systems such as CVS and Subversion are a client server architecture with a central server to -store the revsion history of a project. Mercurial however is a truly -distributed architecture, giving each devloper a full local copy of the +store the revision history of a project. Mercurial however is a truly +distributed architecture, giving each developer a full local copy of the entire development history. It works independently of a central server. * Fast - Traditionally version control systems such as CVS and Subversion are a -client server architecture with a central server to store the revsion history +client server architecture with a central server to store the revision history of a project. Mercurial however is a truly distributed architecture, giving -each devloper a full local copy of the entire development history. It works +each developer a full local copy of the entire development history. It works independently of a central server. * Platform Independent - Mercurial was written to be highly platform independent. Much of Mercurial is written in Python, with small performance @@ -56,7 +56,7 @@ any later version. | changeset | Set of changes saved as diffs | | diff | Changes between file(s) | | tag | A named named revision | -| parent(s) | Immediate ancestor(s) of a revison | +| parent(s) | Immediate ancestor(s) of a revision | | branch | A child of a revision | | head | A head is a changeset with no child changesets | | merge | The process of merging two HEADS | @@ -184,7 +184,7 @@ Commit changes to the given files into the repository. # Commit with a message $ hg commit -m 'This is a commit message' -# Commit all added / removed files in the currrent tree +# Commit all added / removed files in the current tree $ hg commit -A 'Adding and removing all existing files in the tree' # amend the parent of the working directory with a new commit that contains the @@ -341,7 +341,7 @@ $ hg revert -a Remove the specified files on the next commit. ```bash -# Remove a spcific file +# Remove a specific file $ hg remove go_away.txt # Remove a group of files by pattern diff --git a/mercury.html.markdown b/mercury.html.markdown index f749bac4..6d278ce0 100644 --- a/mercury.html.markdown +++ b/mercury.html.markdown @@ -254,7 +254,7 @@ received(crypto(Type, _Wallet, Amount)) = S :- % _Wallet is named throwaway * [Mercury Tutorial](https://mercurylang.org/documentation/papers/book.pdf) (pdf link) - a more traditional tutorial with a more relaxed pace * [Mercury Crash Course](https://mercury-in.space/crash.html) - a dense example-driven tutorial with Q&A format -* [Github Wiki Tutorial](https://github.com/Mercury-Language/mercury/wiki/Tutorial) +* [GitHub Wiki Tutorial](https://github.com/Mercury-Language/mercury/wiki/Tutorial) * [Getting Started with Mercury](https://bluishcoder.co.nz/2019/06/23/getting-started-with-mercury.html) - installation and your first steps ### Documentation diff --git a/mips.html.markdown b/mips.html.markdown index 4134d3fa..3add0c5b 100644 --- a/mips.html.markdown +++ b/mips.html.markdown @@ -20,12 +20,12 @@ gateways and routers. # Programs typically contain a .data and .text sections .data # Section where data is stored in memory (allocated in RAM), similar to - # variables in higher level languages + # variables in higher-level languages # Declarations follow a ( label: .type value(s) ) form of declaration hello_world: .asciiz "Hello World\n" # Declare a null terminated string num1: .word 42 # Integers are referred to as words - # (32 bit value) + # (32-bit value) arr1: .word 1, 2, 3, 4, 5 # Array of words arr2: .byte 'a', 'b' # Array of chars (1 byte each) @@ -39,28 +39,30 @@ gateways and routers. _float: .float 3.14 # 4 bytes _double: .double 7.0 # 8 bytes - .align 2 # Memory alignment of data, where - # number indicates byte alignment in - # powers of 2. (.align 2 represents - # word alignment since 2^2 = 4 bytes) + .align 2 # Memory alignment of data, where + # number indicates byte alignment + # in powers of 2. (.align 2 + # represents word alignment since + # 2^2 = 4 bytes) -.text # Section that contains instructions - # and program logic +.text # Section that contains + # instructions and program logic .globl _main # Declares an instruction label as # global, making it accessible to # other files - _main: # MIPS programs execute instructions - # sequentially, where the code under - # this label will be executed firsts + _main: # MIPS programs execute + # instructions sequentially, where + # the code under this label will be + # executed first # Let's print "hello world" - la $a0, hello_world # Load address of string stored in - # memory - li $v0, 4 # Load the syscall value (indicating - # type of functionality) - syscall # Perform the specified syscall with - # the given argument ($a0) + la $a0, hello_world # Load address of string stored + # in memory + li $v0, 4 # Load the syscall value (number + # indicating which syscall to make) + syscall # Perform the specified syscall + # with the given argument ($a0) # Registers (used to hold data during program execution) # $t0 - $t9 # Temporary registers used for @@ -79,22 +81,24 @@ gateways and routers. # Types of load/store instructions la $t0, label # Copy the address of a value in - # memory specified by the label into - # register $t0 + # memory specified by the label + # into register $t0 lw $t0, label # Copy a word value from memory lw $t1, 4($s0) # Copy a word value from an address - # stored in a register with an offset - # of 4 bytes (addr + 4) - lb $t2, label # Copy a byte value to the lower order - # portion of the register $t2 + # stored in a register with an + # offset of 4 bytes (addr + 4) + lb $t2, label # Copy a byte value to the + # lower order portion of + # the register $t2 lb $t2, 0($s0) # Copy a byte value from the source # address in $s0 with offset 0 # Same idea with 'lh' for halfwords - sw $t0, label # Store word value into memory address - # mapped by label + sw $t0, label # Store word value into + # memory address mapped by label sw $t0, 8($s0) # Store word value into address - # specified in $s0 and offset of 8 bytes + # specified in $s0 and offset of + # 8 bytes # Same idea using 'sb' and 'sh' for bytes and halfwords. 'sa' does not exist ### Math ### @@ -107,21 +111,23 @@ gateways and routers. sub $t2, $t0, $t1 # $t2 = $t0 - $t1 mul $t2, $t0, $t1 # $t2 = $t0 * $t1 div $t2, $t0, $t1 # $t2 = $t0 / $t1 (Might not be - # supported in some versons of MARS) - div $t0, $t1 # Performs $t0 / $t1. Get the quotient - # using 'mflo' and remainder using 'mfhi' + # supported in some versions of MARS) + div $t0, $t1 # Performs $t0 / $t1. Get the + # quotient using 'mflo' and + # remainder using 'mfhi' # Bitwise Shifting sll $t0, $t0, 2 # Bitwise shift to the left with # immediate (constant value) of 2 - sllv $t0, $t1, $t2 # Shift left by a variable amount in - # register + sllv $t0, $t1, $t2 # Shift left by a variable amount + # in register srl $t0, $t0, 5 # Bitwise shift to the right (does - # not sign preserve, sign-extends with 0) - srlv $t0, $t1, $t2 # Shift right by a variable amount in - # a register - sra $t0, $t0, 7 # Bitwise arithmetic shift to the right - # (preserves sign) + # not sign preserve, sign-extends + # with 0) + srlv $t0, $t1, $t2 # Shift right by a variable amount + # in a register + sra $t0, $t0, 7 # Bitwise arithmetic shift to + # the right (preserves sign) srav $t0, $t1, $t2 # Shift right by a variable amount # in a register @@ -139,14 +145,15 @@ gateways and routers. # The basic format of these branching instructions typically follow <instr> # <reg1> <reg2> <label> where label is the label we want to jump to if the # given conditional evaluates to true - # Sometimes it is easier to write the conditional logic backwards, as seen + # Sometimes it is easier to write the conditional logic backward, as seen # in the simple if statement example below beq $t0, $t1, reg_eq # Will branch to reg_eq if # $t0 == $t1, otherwise # execute the next line bne $t0, $t1, reg_neq # Branches when $t0 != $t1 - b branch_target # Unconditional branch, will always execute + b branch_target # Unconditional branch, will + # always execute beqz $t0, req_eq_zero # Branches when $t0 == 0 bnez $t0, req_neq_zero # Branches when $t0 != 0 bgt $t0, $t1, t0_gt_t1 # Branches when $t0 > $t1 @@ -155,8 +162,9 @@ gateways and routers. blt $t0, $t1, t0_gt_t1 # Branches when $t0 < $t1 ble $t0, $t1, t0_gte_t1 # Branches when $t0 <= $t1 bltz $t0, t0_lt0 # Branches when $t0 < 0 - slt $s0, $t0, $t1 # Instruction that sends a signal when - # $t0 < $t1 with reuslt in $s0 (1 for true) + slt $s0, $t0, $t1 # "Set on Less Than" + # when $t0 < $t1 with result in $s0 + # (1 for true) # Simple if statement # if (i == j) @@ -178,19 +186,20 @@ gateways and routers. # else # max = c; # else + # if (b > c) # max = b; # else # max = c; # Let $s0 = a, $s1 = b, $s2 = c, $v0 = return register - ble $s0, $s1, a_LTE_b # if (a <= b) branch(a_LTE_b) - ble $s0, $s2, max_C # if (a > b && a <=c) branch(max_C) - move $v0, $s1 # else [a > b && a > c] max = a + ble $s0, $s1, a_LTE_b # if(a <= b) branch(a_LTE_b) + ble $s0, $s2, max_C # if(a > b && a <=c) branch(max_C) + move $v0, $s0 # else [a > b && a > c] max = a j done # Jump to the end of the program a_LTE_b: # Label for when a <= b - ble $s1, $s2, max_C # if (a <= b && b <= c) branch(max_C) - move $v0, $s1 # if (a <= b && b > c) max = b + ble $s1, $s2, max_C # if(a <= b && b <= c) branch(max_C) + move $v0, $s1 # if(a <= b && b > c) max = b j done # Jump to done max_C: @@ -201,12 +210,15 @@ gateways and routers. ## LOOPS ## _loops: # The basic structure of loops is having an exit condition and a jump - instruction to continue its execution + # instruction to continue its execution li $t0, 0 while: - bgt $t0, 10, end_while # While $t0 is less than 10, keep iterating + bgt $t0, 9, end_while # While $t0 is less than 10, + # keep iterating + #actual loop content would go here addi $t0, $t0, 1 # Increment the value - j while # Jump back to the beginning of the loop + j while # Jump back to the beginning of + # the loop end_while: # 2D Matrix Traversal @@ -232,7 +244,7 @@ gateways and routers. ## FUNCTIONS ## _functions: # Functions are callable procedures that can accept arguments and return - values all denoted with labels, like above + # values all denoted with labels, like above main: # Programs begin with main func jal return_1 # jal will store the current PC in $ra @@ -246,7 +258,8 @@ gateways and routers. # How about recursion? # This is a bit more work since we need to make sure we save and restore - # the previous PC in $ra since jal will automatically overwrite on each call + # the previous PC in $ra since jal will automatically overwrite + # on each call li $a0, 3 jal fact @@ -282,19 +295,19 @@ gateways and routers. fact_done: lw $s0, ($sp) - lw $ra, ($sp) # Restore the PC + lw $ra, 4($sp) # Restore the PC addi $sp, $sp, 8 jr $ra ## MACROS ## _macros: - # Macros are extremly useful for substituting repeated code blocks with a + # Macros are extremely useful for substituting repeated code blocks with a # single label for better readability # These are in no means substitutes for functions # These must be declared before it is used - # Macro for printing new lines (since these can be very repetitive) + # Macro for printing newlines (since these can be very repetitive) .macro println() la $a0, newline # New line string stored here li $v0, 4 @@ -338,7 +351,7 @@ gateways and routers. buffer: .space 128 # Allocates a block in memory, does # not automatically clear # These blocks of memory are aligned - # next each other + # next to each other .text la $s0, list # Load address of list @@ -346,7 +359,7 @@ gateways and routers. li $t1, 5 # Length of the list loop: - bgt $t0, $t1, end_loop + bge $t0, $t1, end_loop lw $a0, ($s0) li $v0, 1 diff --git a/mongodb.html.markdown b/mongodb.html.markdown new file mode 100644 index 00000000..f4e7d709 --- /dev/null +++ b/mongodb.html.markdown @@ -0,0 +1,406 @@ +--- +language: MongoDB +filename: mongo.js +contributors: + - ["Raj Piskala", "https://www.rajpiskala.ml/"] +--- + +MongoDB is a NoSQL document database for high volume data storage. + +MongoDB uses collections and documents for its storage. Each document consists +of key-value pairs using JSON-like syntax, similar to a dictionary or JavaScript +object. + +Likewise, as MongoDB is a NoSQL database, it uses its own query language, Mongo +Query Language (MQL) which uses JSON for querying. + +## Getting Started + +### Installation + +MongoDB can either be installed locally following the instructions +[here](https://docs.mongodb.com/manual/installation/) or you can create a +remotely-hosted free 512 MB cluster +[here](https://www.mongodb.com/cloud/atlas/register). Links to videos with +instructions on setup are at the bottom. + +This tutorial assumes that you have the MongoDB Shell from +[here](https://www.mongodb.com/try/download/shell). You can also download the +graphical tool, MongoDB Compass, down below from the same link. + +### Components + +After installing MongoDB, you will notice there are multiple command line tools. +The three most important of which are: + +- `mongod` - The database server which is responsible for managing data and + handling queries +- `mongos` - The sharding router, which is needed if data will be distributed + across multiple machines +- `mongo` - The database shell (using JavaScript) through which we can configure + our database + +Usually we start the `mongod` process and then use a separate terminal with +`mongo` to access and modify our collections. + +### JSON & BSON + +While queries in MongoDB are made using a JSON-like\* format, MongoDB stores its +documents internally in the Binary JSON (BSON format). BSON is not human +readable like JSON as it's a binary encoding. However, this allows for end users +to have access to more types than regular JSON, such as an integer or float +type. Many other types, such as regular expressions, dates, or raw binary are +supported too. + +[Here](https://docs.mongodb.com/manual/reference/bson-types/) is the full list +of all types that are supported. + +- We refer JSON-like to mean JSON but with these extended types. For example, + you can make queries directly with a regular expression or timestamp in + MongoDB and you can receive data that has those types too. + +```js +///////////////////////////////////////////////////////// +/////////////////// Getting Started ///////////////////// +///////////////////////////////////////////////////////// + +// Start up the mongo database server +// NOTE - You will need to do this in a separate terminal as the process will +// take over the terminal. You may want to use the --fork option +mongod // --fork + +// Connecting to a remote Mongo server +// mongo "mongodb+srv://host.ip.address/admin" --username your-username + +// Mongoshell has a proper JavaScript interpreter built in +3 + 2 // 5 + +// Show available databases +// MongoDB comes with the following databases built-in: admin, config, local +show dbs + +// Switch to a new database (pre-existing or about to exist) +// NOTE: There is no "create" command for a database in MongoDB. +// The database is created upon data being inserted into a collection +use employees + +// Create a new collection +// NOTE: Inserting a document will implicitly create a collection anyways, +// so this is not required +db.createCollection('engineers') +db.createCollection('doctors') + +// See what collections exist under employees +show collections + +///////////////////////////////////////////////////////// +// Basic Create/Read/Update/Delete (CRUD) Operations: /// +///////////////////////////////////////////////////////// + +/////////////// Insert (Create) ///////////////////////// + +// Insert one employee into the database +// Each insertion returns acknowledged true or false +// Every document has a unique _id value assigned to it automatically +db.engineers.insertOne({ name: "Jane Doe", age: 21, gender: 'Female' }) + +// Insert a list of employees into the `engineers` collection +// Can insert as an array of objects +db.engineers.insert([ + { name: "Foo Bar", age: 25, gender: 'Male' }, + { name: "Baz Qux", age: 27, gender: 'Other' }, +]) + +// MongoDB does not enforce a schema or structure for objects +// Insert an empty object into the `engineers` collection +db.engineers.insertOne({}) + +// Fields are optional and do not have to match rest of documents +db.engineers.insertOne({ name: "Your Name", gender: "Male" }) + +// Types can vary and are preserved on insertion +// This can require additional validation in some languages to prevent problems +db.engineers.insert({ name: ['Foo', 'Bar'], age: 3.14, gender: true }) + +// Objects or arrays can be nested inside a document +db.engineers.insertOne({ + name: "Your Name", + gender: "Female", + skilledIn: [ + "MongoDB", + "NoSQL", + ], + "date-of-birth": { + "date": 1993-07-20T09:44:18.674Z, + "age": 26 + }, +}) + +// We can override the _id field +// Works fine +db.engineers.insertOne({ + _id: 1, + name: "An Engineer", + age: 25, + gender: "Female", +}) + +// Be careful, as _id must ALWAYS be unique for the collection otherwise +// the insertion will fail +// Fails with a WriteError indicating _id is a duplicate value +db.engineers.insertOne({ + _id: 1, + name: "Another Engineer", + age: 25, + gender: "Male", +}) + +// Works fine as this is a different collection +db.doctors.insertOne({ + _id: 1, + name: "Some Doctor", + age: 26, + gender: "Other", +}) + +/////////////////// Find (Read) //////////////////////// +// Queries are in the form of db.collectionName.find(<filter>) +// Where <filter> is an object + +// Show everything in our database so far, limited to a +// maximum of 20 documents at a time +// Press i to iterate this cursor to the next 20 documents +db.engineers.find({}) + +// We can pretty print the result of any find() query +db.engineers.find({}).pretty() + +// MongoDB queries take in a JS object and search for documents with matching +// key-value pairs +// Returns the first document matching query +// NOTE: Order of insertion is not preserved in the database, output can vary +db.engineers.findOne({ name: 'Foo Bar' }) + +// Returns all documents with the matching key-value properties as a cursor +// (which can be converted to an array) +db.engineers.find({ age: 25 }) + +// Type matters when it comes to queries +// Returns nothing as all ages above are integer type +db.engineers.find({ age: '25' }) + +// find() supports nested objects and arrays just like create() +db.engineers.find({ + name: "Your Name", + gender: "Female", + skilledIn: [ + "MongoDB", + "NoSQL", + ], + "date-of-birth": { + "date": 1993-07-20T09:44:18.674Z, + "age": 26 + }, +}) + +///////////////////////// Update //////////////////////// +// Queries are in the form of db.collectionName.update(<filter>, <update>) +// NOTE: <update> will always use the $set operator. +// Several operators are covered later on in the tutorial. + +// We can update a single object +db.engineers.updateOne({ name: 'Foo Bar' }, { $set: { name: 'John Doe', age: 100 }}) + +// Or update many objects at the same time +db.engineers.update({ age: 25 }, { $set: { age: 26 }}) + +// We can use { upsert: true } if we would like it to insert if the document doesn't already exist, +// or to update if it does +// Returns matched, upserted, modified count +db.engineers.update({ name: 'Foo Baz' }, + { $set: + { + age: 26, + gender: 'Other' + } + }, + { upsert: true } +) + +/////////////////////// Delete ///////////////////////// +// Queries are in the form of db.collectionName.delete(<filter>) + +// Delete first document matching query, always returns deletedCount +db.engineers.deleteOne({ name: 'Foo Baz' }) + +// Delete many documents at once +db.engineers.deleteMany({ gender: 'Male' }) + +// NOTE: There are two methods db.collection.removeOne(<filter>) and +// db.collection.removeMany(<filter>) that also delete objects but have a +// slightly different return value. +// They are not included here as they have been deprecated in the NodeJS driver. + +///////////////////////////////////////////////////////// +//////////////////// Operators ////////////////////////// +///////////////////////////////////////////////////////// + +// Operators in MongoDB have a $ prefix. For this tutorial, we are only looking +// at comparison and logical operators, but there are many other types of +// operators + +//////////////// Comparison Operators /////////////////// + +// Find all greater than or greater than equal to some condition +db.engineers.find({ age: { $gt: 25 }}) +db.engineers.find({ age: { $gte: 25 }}) + +// Find all less than or less than equal to some condition +db.engineers.find({ age: { $lt: 25 }}) +db.engineers.find({ age: { $lte: 25 }}) + +// Find all equal or not equal to +// Note: the $eq operator is added implicitly in most queries +db.engineers.find({ age: { $eq: 25 }}) +db.engineers.find({ age: { $ne: 25 }}) + +// Find all that match any element in the array, or not in the array +db.engineers.find({ age: { $in: [ 20, 23, 24, 25 ]}}) +db.engineers.find({ age: { $nin: [ 20, 23, 24, 25 ]}}) + +//////////////// Logical Operators /////////////////// + +// Join two query clauses together +// NOTE: MongoDB does this implicitly for most queries +db.engineers.find({ $and: [ + gender: 'Female', + age: { + $gte: 18 + } +]}) + +// Match either query condition +db.engineers.find({ $or: [ + gender: 'Female', + age: { + $gte: 18 + } +]}) + +// Negates the query +db.engineers.find({ $not: { + gender: 'Female' +}}) + +// Must match none of the query conditions +db.engineers.find({ $nor [ + gender: 'Female', + age: { + $gte: 18 + } +]}) + +///////////////////////////////////////////////////////// +//////////////// Database Operations: /////////////////// +///////////////////////////////////////////////////////// + +// Delete (drop) the employees database +// THIS WILL DELETE ALL DOCUMENTS IN THE DATABASE! +db.dropDatabase() + +// Create a new database with some data +use example +db.test.insertOne({ name: "Testing data, please ignore!", type: "Test" }) + +// Quit Mongo shell +exit + +// Import/export database as BSON: + +// Mongodump to export data as BSON for all databases +// Exported data is found in under "MongoDB Database Tools/bin/dump" +// NOTE: If the command is not found, navigate to "MongoDB Database Tools/bin" +// and use the executable from there mongodump + +// Mongorestore to restore data from BSON +mongorestore dump + +// Import/export database as JSON: +// Mongoexport to export data as JSON for all databases +mongoexport --collection=example + +// Mongoimport to export data as JSON for all databases +mongoimport --collection=example +``` + +## Further Reading + +### Setup Videos + +- [Install MongoDB - Windows 10](https://www.youtube.com/watch?v=85A6m1soKww) +- [Install MongoDB - Mac](https://www.youtube.com/watch?v=DX15WbKidXY) +- [Install MongoDB - Linux + (Ubuntu)](https://www.youtube.com/watch?v=wD_2pojFWoE) + +### Input Validation + +From the examples above, if input validation or structure is a concern, I would +take a look at the following ORMs: + +- [Mongoose (Node.js)](https://mongoosejs.com/docs/) - Input validation through + schemas that support types, required values, minimum and maximum values. +- [MongoEngine (Python)](http://mongoengine.org/) - Similar to Mongoose, but I + found it somewhat limited in my experience +- [MongoKit (Python)](https://github.com/namlook/mongokit) - Another great + alternative to MongoEngine that I find easier to use than MongoEngine + +For statically strongly typed languages (e.g. Java, C++, Rust), input validation +usually doesn't require a library as they define types and structure at compile +time. + +### Resources + +If you have the time to spare, I would strongly recommend the courses on +[MongoDB University](https://university.mongodb.com/). They're by MongoDB +themselves and go into much more detail while still being concise. They're a mix +of videos and quiz questions and this was how I gained my knowledge of MongoDB. + +I would recommend the following video series for learning MongoDB: + +- [MongoDB Crash Course - Traversy + Media](https://www.youtube.com/watch?v=-56x56UppqQ) +- [MongoDB Tutorial for Beginners - + Amigoscode](https://www.youtube.com/watch?v=Www6cTUymCY) + +Language-specific ones that I used before: + +- [Build A REST API With Node.js, Express, & MongoDB - Web Dev + Simplified](https://www.youtube.com/watch?v=fgTGADljAeg) +- [MongoDB with Python Crash Course - Tutorial for Beginners - + FreeCodeCamp](https://www.youtube.com/watch?v=E-1xI85Zog8) +- [How to Use MongoDB with Java - Random + Coder](https://www.youtube.com/watch?v=reYPUvu2Giw) +- [An Introduction to Using MongoDB with Rust - + MongoDB](https://www.youtube.com/watch?v=qFlftfLGwPM) + +Most of the information above was cross-referenced with the [MongoDB +docs](https://www.mongodb.com/). Here are the docs for each section: + +- [MongoDB Types](https://docs.mongodb.com/manual/reference/bson-types/) - List + of all types that MongoDB supports natively +- [MongoDB Operators](https://docs.mongodb.com/manual/reference/operator/) - + List of operators MongoDB supports natively +- [MongoDB CRUD](https://docs.mongodb.com/manual/reference/command/nav-crud/) - + Commands for create, read, update, delete + +If you've been enjoying MongoDB so far and want to explore intermediate +features, I would look at +[aggregation](https://docs.mongodb.com/manual/reference/command/nav-aggregation/), +[indexing](https://docs.mongodb.com/manual/indexes/), and +[sharding](https://docs.mongodb.com/manual/sharding/). + +- Aggregation - useful for creating advanced queries to be executed by the + database +- Indexing allows for caching, which allows for much faster execution of queries +- Sharding allows for horizontal data scaling and distribution between multiple + machines. diff --git a/montilang.html.markdown b/montilang.html.markdown index cceb7aa1..14b45d31 100644 --- a/montilang.html.markdown +++ b/montilang.html.markdown @@ -170,7 +170,7 @@ printseven /# currently, preprocessor statements can be used to make c++-style constants #/ &DEFINE LOOPSTR 20& -/# must have & on either side with no spaces, 'DEFINE' is case sensative. #/ +/# must have & on either side with no spaces, 'DEFINE' is case sensitive. #/ /# All statements are scanned and replaced before the program is run, regardless of where the statements are placed #/ FOR LOOPSTR 7 PRINT . ENDFOR /# Prints '7' 20 times. At run, 'LOOPSTR' in source code is replaced with '20' #/ @@ -230,4 +230,4 @@ DEL 1 PRINT . /# [1, 3] #/ ## Extra information - [MontiLang.ml](http://montilang.ml/) -- [Github Page](https://github.com/lduck11007/MontiLang) +- [GitHub Page](https://github.com/lduck11007/MontiLang) diff --git a/moonscript.html.markdown b/moonscript.html.markdown index 941578e7..193d7f97 100644 --- a/moonscript.html.markdown +++ b/moonscript.html.markdown @@ -192,7 +192,7 @@ items = {1, 2, 3, 4} doubled = [item * 2 for item in *items] -- Uses `when` to determine if a value should be included. -slice = [item for item in *items when i > 1 and i < 3] +slice = [item for item in *items when item > 1 and item < 3] -- `for` clauses inside of list comprehensions can be chained. diff --git a/ms-my/bash-my.html.markdown b/ms-my/bash-my.html.markdown index e4e55b2c..a97e651c 100644 --- a/ms-my/bash-my.html.markdown +++ b/ms-my/bash-my.html.markdown @@ -17,7 +17,7 @@ translators: lang: ms-my --- -Bash adalah nama daripada unix shell, yang mana telah diagihkan sebagai shell untuk sistem operasi GNU dan sebagai shell lalai pada Linux dan Mac OS X. Hampir semua contoh di bawah boleh menjadi sebahagian daripada skrip shell atau dijalankan terus dalam shell. +Bash adalah nama daripada unix shell, yang mana telah diagihkan sebagai shell untuk sistem operasi GNU dan sebagai shell lalai pada Linux dan macOS. Hampir semua contoh di bawah boleh menjadi sebahagian daripada skrip shell atau dijalankan terus dalam shell. [Baca lebih lanjut di sini.](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/ms-my/clojure-my.html.markdown b/ms-my/clojure-my.html.markdown index e199c8f4..cfcdeb40 100644 --- a/ms-my/clojure-my.html.markdown +++ b/ms-my/clojure-my.html.markdown @@ -413,7 +413,7 @@ Clojuredocs.org mempunyai dokumentasi berserta contoh untuk menggunakan kebanyak [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) 4Clojure ialah cara yang baik untuk mengasah skill Clojure dan functional programming: -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org (yup, serius) juga mengandungi beberapa artikel sebagai permulaan: [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/ms-my/javascript-my.html.markdown b/ms-my/javascript-my.html.markdown index 90e37133..9a7a23ba 100644 --- a/ms-my/javascript-my.html.markdown +++ b/ms-my/javascript-my.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] filename: javascript-ms.js translators: diff --git a/neat.html.markdown b/neat.html.markdown deleted file mode 100644 index f02461ee..00000000 --- a/neat.html.markdown +++ /dev/null @@ -1,297 +0,0 @@ ---- -language: neat -contributors: - - ["Feep", "https://github.com/FeepingCreature"] -filename: LearnNeat.nt ---- - -Neat is basically a smaller version of D1 with some experimental syntax and a focus on terseness without losing the basic C-like syntax. - -[Read more here.](https://github.com/FeepingCreature/fcc/wiki) - -```c -// single line comments start with // -/* - multiline comments look like this -*/ -/+ - or this - /+ these can be nested too, same as D +/ -+/ - -// Module name. This has to match the filename/directory. -module LearnNeat; - -// Make names from another module visible in this one. -import std.file; -// You can import multiple things at once. -import std.math, std.util; -// You can even group up imports! -import std.(process, socket); - -// Global functions! -void foo() { } - -// Main function, same as in C. -// string[] == "array of strings". -// "string" is just an alias for char[], -void main(string[] args) { - // Call functions with "function expression". - writeln "Hello World"; - // You can do it like in C too... if you really want. - writeln ("Hello World"); - // Declare a variable with "type identifier" - string arg = ("Hello World"); - writeln arg; - // (expression, expression) forms a tuple. - // There are no one-value tuples though. - // So you can always use () in the mathematical sense. - // (string) arg; <- is an error - - /* - byte: 8 bit signed integer - char: 8 bit UTF-8 byte component. - short: 16 bit signed integer - int: 32 bit signed integer - long: 64 bit signed integer - - float: 32 bit floating point - double: 64 bit floating point - real: biggest native size floating point (80 bit on x86). - - bool: true or false - */ - int a = 5; - bool b = true; - // as in C, && and || are short-circuit evaluating. - b = b && false; - assert(b == false); - // "" are "format strings". So $variable will be substituted at runtime - // with a formatted version of the variable. - writeln "$a"; - // This will just print $a. - writeln `$a`; - // you can format expressions with $() - writeln "$(2+2)"; - // Note: there is no special syntax for characters. - char c = "a"; - // Cast values by using type: expression. - // There are three kinds of casts: - // casts that just specify conversions that would be happening automatically - // (implicit casts) - float f = float:5; - float f2 = 5; // would also work - // casts that require throwing away information or complicated computation - - // those must always be done explicitly - // (conversion casts) - int i = int:f; - // int i = f; // would not work! - // and, as a last attempt, casts that just reinterpret the raw data. - // Those only work if the types have the same size. - string s = "Hello World"; - // Arrays are (length, pointer) pairs. - // This is a tuple type. Tuple types are (type, type, type). - // The type of a tuple expression is a tuple type. (duh) - (int, char*) array = (int, char*): s; - // You can index arrays and tuples using the expression[index] syntax. - writeln "pointer is $(array[1]) and length is $(array[0])"; - // You can slice them using the expression[from .. to] syntax. - // Slicing an array makes another array. - writeln "$(s[0..5]) World"; - // Alias name = expression gives the expression a name. - // As opposed to a variable, aliases do not have an address - // and can not be assigned to. (Unless the expression is assignable) - alias range = 0 .. 5; - writeln "$(s[range]) World"; - // You can iterate over ranges. - for int i <- range { - write "$(s[i])"; - } - writeln " World"; - // Note that if "range" had been a variable, it would be 'empty' now! - // Range variables can only be iterated once. - // The syntax for iteration is "expression <- iterable". - // Lots of things are iterable. - for char c <- "Hello" { write "$c"; } - writeln " World"; - // For loops are "for test statement"; - alias test = char d <- "Hello"; - for test write "$d"; - writeln " World\t\x05"; // note: escapes work - // Pointers: function the same as in C, btw. The usual. - // Do note: the pointer star sticks with the TYPE, not the VARIABLE! - string* p; - assert(p == null); // default initializer - p = &s; - writeln "$(*p)"; - // Math operators are (almost) standard. - int x = 2 + 3 * 4 << 5; - // Note: XOR is "xor". ^ is reserved for exponentiation (once I implement that). - int y = 3 xor 5; - int z = 5; - assert(z++ == 5); - assert(++z == 7); - writeln "x $x y $y z $z"; - // As in D, ~ concatenates. - string hewo = "Hello " ~ "World"; - // == tests for equality, "is" tests for identity. - assert (hewo == s); - assert !(hewo is s); - // same as - assert (hewo !is s); - - // Allocate arrays using "new array length" - int[] integers = new int[] 10; - assert(integers.length == 10); - assert(integers[0] == 0); // zero is default initializer - integers = integers ~ 5; // This allocates a new array! - assert(integers.length == 11); - - // This is an appender array. - // Instead of (length, pointer), it tracks (capacity, length, pointer). - // When you append to it, it will use the free capacity if it can. - // If it runs out of space, it reallocates - but it will free the old array automatically. - // This makes it convenient for building arrays. - int[auto~] appender; - appender ~= 2; - appender ~= 3; - appender.free(); // same as {mem.free(appender.ptr); appender = null;} - - // Scope variables are automatically freed at the end of the current scope. - scope int[auto~] someOtherAppender; - // This is the same as: - int[auto~] someOtherAppender2; - onExit { someOtherAppender2.free; } - - // You can do a C for loop too - // - but why would you want to? - for (int i = 0; i < 5; ++i) { } - // Otherwise, for and while are the same. - while int i <- 0..4 { - assert(i == 0); - break; // continue works too - } then assert(false); // if we hadn't break'd, this would run at the end - // This is the height of loopdom - the produce-test-consume loop. - do { - int i = 5; - } while (i == 5) { - assert(i == 5); - break; // otherwise we'd go back up to do { - } - - // This is a nested function. - // Nested functions can access the surrounding function. - string returnS() { return s; } - writeln returnS(); - - // Take the address of a function using & - // The type of a global function is ReturnType function(ParameterTypeTuple). - void function() foop = &foo; - - // Similarly, the type of a nested function is ReturnType delegate(ParameterTypeTuple). - string delegate() returnSp = &returnS; - writeln returnSp(); - // Class member functions and struct member functions also fit into delegate variables. - // In general, delegates are functions that carry an additional context pointer. - // ("fat pointers" in C) - - // Allocate a "snapshot" with "new delegate". - // Snapshots are not closures! I used to call them closures too, - // but then my Haskell-using friends yelled at me so I had to stop. - // The difference is that snapshots "capture" their surrounding context - // when "new" is used. - // This allows things like this - int delegate(int) add(int a) { - int add_a(int b) { return a + b; } - // This does not work - the context of add_a becomes invalid - // when add returns. - // return &add_a; - // Instead: - return new &add_a; - } - int delegate(int) dg = add 2; - assert (dg(3) == 5); - // or - assert (((add 2) 3) == 5); - // or - assert (add 2 3 == 5); - // add can also be written as - int delegate(int) add2(int a) { - // this is an implicit, nameless nested function. - return new λ(int b) { return a + b; } - } - // or even - auto add3(int a) { return new λ(int b) -> a + b; } - // hahahaaa - auto add4 = λ(int a) -> new λ(int b) -> a + b; - assert(add4 2 3 == 5); - // If your keyboard doesn't have a λ (you poor sod) - // you can use \ too. - auto add5 = \(int a) -> new \(int b) -> a + b; - // Note! - auto nestfun = λ() { } // There is NO semicolon needed here! - // "}" can always substitute for "};". - // This provides syntactic consistency with built-in statements. - - - // This is a class. - // Note: almost all elements of Neat can be used on the module level - // or just as well inside a function. - class C { - int a; - void writeA() { writeln "$a"; } - // It's a nested class - it exists in the context of main(). - // so if you leave main(), any instances of C become invalid. - void writeS() { writeln "$s"; } - } - C cc = new C; - // cc is a *reference* to C. Classes are always references. - cc.a = 5; // Always used for property access. - auto ccp = &cc; - (*ccp).a = 6; - // or just - ccp.a = 7; - cc.writeA(); - cc.writeS(); // to prove I'm not making things up - // Interfaces work same as in D, basically. Or Java. - interface E { void doE(); } - // Inheritance works same as in D, basically. Or Java. - class D : C, E { - override void writeA() { writeln "hahahahaha no"; } - override void doE() { writeln "eeeee"; } - // all classes inherit from Object. (toString is defined in Object) - override string toString() { return "I am a D"; } - } - C cd = new D; - // all methods are always virtual. - cd.writeA(); - E e = E:cd; // dynamic class cast! - e.doE(); - writeln "$e"; // all interfaces convert to Object implicitly. - - // Templates! - // Templates are parameterized namespaces, taking a type as a parameter. - template Templ(T) { - alias hi = 5, hii = 8; - // Templates always have to include something with the same name as the template - // - this will become the template's _value_. - // Static ifs are evaluated statically, at compile-time. - // Because of this, the test has to be a constant expression, - // or something that can be optimized to a constant. - static if (types-equal (T, int)) { - alias Templ = hi; - } else { - alias Templ = hii; - } - } - assert(Templ!int == 5); - assert(Templ!float == 8); -} -``` - -## Topics Not Covered - - * Extended iterator types and expressions - * Standard library - * Conditions (error handling) - * Macros diff --git a/nim.html.markdown b/nim.html.markdown index 1e17d8f0..81662630 100644 --- a/nim.html.markdown +++ b/nim.html.markdown @@ -3,7 +3,7 @@ language: Nim filename: learnNim.nim contributors: - ["Jason J. Ayala P.", "http://JasonAyala.com"] - - ["Dennis Felsing", "http://felsin9.de/nnis/"] + - ["Dennis Felsing", "https://dennis.felsing.org"] --- Nim (formerly Nimrod) is a statically typed, imperative programming language @@ -28,7 +28,7 @@ Or for unparsable, broken code var # Declare (and assign) variables, letter: char = 'n' # with or without type annotations lang = "N" & "im" - nLength : int = len(lang) + nLength: int = len(lang) boat: float truth: bool = false @@ -142,7 +142,7 @@ when compileBadCode: # Arrays type - RollCounter = array[DieFaces, int] # Array's are fixed length and + RollCounter = array[DieFaces, int] # Arrays are fixed length and DirNames = array[Direction, string] # indexed by any ordinal type. Truths = array[42..44, bool] var diff --git a/nix.html.markdown b/nix.html.markdown index 5941f0e6..677aaf54 100644 --- a/nix.html.markdown +++ b/nix.html.markdown @@ -279,7 +279,7 @@ with builtins; [ #=> 7 # This first line of tutorial starts with "with builtins;" - # because builtins is a set the contains all of the built-in + # because builtins is a set that contains all of the built-in # functions (length, head, tail, filter, etc.). This saves # us from having to write, for example, "builtins.length" # instead of just "length". @@ -305,6 +305,9 @@ with builtins; [ ({x, y, ...}: x + "-" + y) { x = "a"; y = "b"; z = "c"; } #=> "a-b" + # The entire set can be bound to a variable using `@` + (args@{x, y}: args.x + "-" + args.y) { x = "a"; y = "b"; } + #=> "a-b" # Errors #========================================= @@ -355,7 +358,7 @@ with builtins; [ # its contents. You can read files from anywhere. In this example, # we write a file into the store, and then read it back out. (let filename = toFile "foo.txt" "hello!"; in - [filename (builtins.readFile filename)]) + [filename (readFile filename)]) #=> [ "/nix/store/ayh05aay2anx135prqp0cy34h891247x-foo.txt" "hello!" ] # We can also download files into the Nix store. @@ -373,5 +376,11 @@ with builtins; [ * [James Fisher - Nix by example - Part 1: The Nix expression language] (https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55) +* [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://ebzzry.io/en/nix/#nix) + (https://web.archive.org/web/20210121042658/https://ebzzry.io/en/nix/#nix) diff --git a/nl-nl/bash-nl.html.markdown b/nl-nl/bash-nl.html.markdown index af4a8cc8..8d127c57 100644 --- a/nl-nl/bash-nl.html.markdown +++ b/nl-nl/bash-nl.html.markdown @@ -17,7 +17,7 @@ lang: nl-nl filename: LearnBash-nl.sh --- -Bash is de naam van de unix shell, deze wordt gebruikt voor het GNU operating system en is de standaard shell op Linux en Mac OS X. +Bash is de naam van de unix shell, deze wordt gebruikt voor het GNU operating system en is de standaard shell op Linux en macOS. Bijna alle voorbeelden hieronder kunnen deel uitmaken van een shell script of kunnen uitgevoerd worden in de shell. [Lees er meer over hier.](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/nl-nl/json-nl.html.markdown b/nl-nl/json-nl.html.markdown index 906112ff..d243802d 100644 --- a/nl-nl/json-nl.html.markdown +++ b/nl-nl/json-nl.html.markdown @@ -5,26 +5,27 @@ contributors: - ["Anna Harren", "https://github.com/iirelu"] - ["Marco Scannadinari", "https://github.com/marcoms"] - ["himanshu", "https://github.com/himanshu81494"] + - ["Maarten Jacobs", "https://github.com/maartenJacobs"] translators: - ["Niels van Velzen", "https://nielsvanvelzen.me"] lang: nl-nl --- -Gezien JSON een zeer eenvouding formaat heeft zal dit een van de simpelste +Gezien JSON een zeer eenvouding formaat heeft zal dit één van de simpelste Learn X in Y Minutes ooit zijn. -JSON heeft volgens de specificaties geen commentaar, ondanks dat hebben de +JSON heeft volgens de specificaties geen commentaar. Ondanks dat hebben de meeste parsers support voor C-stijl (`//`, `/* */`) commentaar. Sommige parsers staan zelfs trailing komma's toe. -(Een komma na het laatste element in een array of ahter de laatste eigenshap van een object). -Het is wel beter om dit soort dingen te vermijden omdat het niet overal zal werken. +(Een komma na het laatste element in een array of achter de laatste eigenschap van een object). +Het is wel beter om dit soort dingen te vermijden omdat het niet in elke parser zal werken. In het voorbeeld zal alleen 100% geldige JSON gebruikt worden. Data types gesupport door JSON zijn: nummers, strings, booleans, arrays, objecten en null. Gesupporte browsers zijn: Firefox(Mozilla) 3.5, Internet Explorer 8, Chrome, Opera 10, Safari 4. -De extensie voor JSON bestanden is ".json". De MIME type is "application/json" -Enkele nadelen van JSON zijn het gebrek een type definities en een manier van DTD. +De extensie voor JSON bestanden is ".json". De MIME type is "application/json". +Enkele nadelen van JSON zijn het gebrek aan type definities en een manier van DTD. ```json { diff --git a/nl-nl/markdown-nl.html.markdown b/nl-nl/markdown-nl.html.markdown index b5b4681c..0af78d88 100644 --- a/nl-nl/markdown-nl.html.markdown +++ b/nl-nl/markdown-nl.html.markdown @@ -52,7 +52,7 @@ __En deze tekst ook!__ *__En zelfs deze!__* <!-- In de github versie van markdown, die gebruikt wordt om markdown te renderen -op Github, is er ook doorstrepen --> +op GitHub, is er ook doorstrepen --> ~~Deze tekst wordt doorstreept.~~ @@ -142,7 +142,7 @@ Dit item zal aangevinkt zijn in de gerenderde html. John wist zelfs niet dat de `go_to()` functie bestond! -<!-- In Github Markdown kan je een speciale syntax gebruiken die aangeeft welke +<!-- In GitHub Markdown kan je een speciale syntax gebruiken die aangeeft welke taal gebruikt wordt in het code blok. --> \`\`\`ruby <!-- Wis de backslashes om dit te doen, juist ```ruby ! --> @@ -151,7 +151,7 @@ def foobar end \`\`\` <!-- Hier ook, geen backslashes, juist ``` --> -<!-- Voor bovenstaande tekst moet geen tab gebruikt worden. Plus, Github zal syntax +<!-- Voor bovenstaande tekst moet geen tab gebruikt worden. Plus, GitHub zal syntax highlighting gebruiken voor deze specifieke taal. Hier, Ruby. <!-- Horizontale lijn (<hr />) --> @@ -215,13 +215,13 @@ worden. Dit kan je oplossen met backslashes: \*dit\* staat tussen sterretjes <!-- Toetsenbord toetsen --> -<!-- In Github Markdown, kan je <kbd> gebruiken om toetsenbord toetsen weer te geven --> +<!-- In GitHub Markdown, kan je <kbd> gebruiken om toetsenbord toetsen weer te geven --> Loopt je computer vast? Probeer volgende toetsen combinatie: <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> <!-- Tabellen --> -<!-- Tabellen zijn momenteel enkel beschikbaar in Github Markdown en zijn redelijk omslachtig. +<!-- Tabellen zijn momenteel enkel beschikbaar in GitHub Markdown en zijn redelijk omslachtig. Maar als je er echt wilt toevoegen: --> | Col1 | Col2 | Col3 | diff --git a/nl-nl/yaml-nl.html.markdown b/nl-nl/yaml-nl.html.markdown index 11af784f..7e4d37b1 100644 --- a/nl-nl/yaml-nl.html.markdown +++ b/nl-nl/yaml-nl.html.markdown @@ -2,7 +2,7 @@ language: yaml filename: learnyaml-nl.yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] translators: - ["Niels van Velzen", "https://nielsvanvelzen.me"] - ["Sam van Kampen", "http://tehsvk.net"] diff --git a/no-nb/bash-no.html.markdown b/no-nb/bash-no.html.markdown index 481aecbd..9affaa21 100644 --- a/no-nb/bash-no.html.markdown +++ b/no-nb/bash-no.html.markdown @@ -17,7 +17,7 @@ lang: no-nb --- Bash er navnet på unix skallet, som også var distribuert som skallet for GNU operativsystemet og som standard skall på de fleste Linux distribusjoner og -Mac OS X. +macOS. [Les mer her.](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/objective-c.html.markdown b/objective-c.html.markdown index de3884af..c179c295 100644 --- a/objective-c.html.markdown +++ b/objective-c.html.markdown @@ -9,7 +9,7 @@ contributors: filename: LearnObjectiveC.m --- -Objective-C is the main programming language used by Apple for the OS X and iOS operating systems and their respective frameworks, Cocoa and Cocoa Touch. +Objective-C is the main programming language used by Apple for the macOS and iOS operating systems and their respective frameworks, Cocoa and Cocoa Touch. It is a general-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language. ```objective-c @@ -387,7 +387,7 @@ if ([myClass respondsToSelector:selectorVar]) { // Checks if class contains meth // Implement the methods in an implementation (MyClass.m) file: @implementation MyClass { long distance; // Private access instance variable - NSNumber height; + NSNumber *height; } // To access a public variable from the interface file, use '_' followed by variable name: diff --git a/ocaml.html.markdown b/ocaml.html.markdown index b631df0a..2c5e13d5 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -3,26 +3,31 @@ language: OCaml filename: learnocaml.ml contributors: - ["Daniil Baturin", "http://baturin.org/"] + - ["Stanislav Modrak", "https://stanislav.gq/"] + - ["Luke Tong", "https://lukert.me/"] --- - OCaml is a strictly evaluated functional language with some imperative features. -Along with StandardML and its dialects it belongs to ML language family. +Along with Standard ML and its dialects it belongs to ML language family. F# is also heavily influenced by OCaml. -Just like StandardML, OCaml features both an interpreter, that can be +Just like Standard ML, OCaml features both an interpreter, that can be used interactively, and a compiler. -The interpreter binary is normally called "ocaml" and the compiler is "ocamlopt". -There is also a bytecode compiler, "ocamlc", but there are few reasons to use it. +The interpreter binary is normally called `ocaml` and the compiler is `ocamlopt`. +There is also a bytecode compiler, `ocamlc`, but there are few reasons to use it. + +It also includes a package manager, `opam`, and a build system, `dune`. It is strongly and statically typed, but instead of using manually written -type annotations, it infers types of expressions using Hindley-Milner algorithm. +type annotations, it infers types of expressions using the +[Hindley-Milner](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system) +algorithm. It makes type annotations unnecessary in most cases, but can be a major source of confusion for beginners. When you are in the top level loop, OCaml will print the inferred type -after you enter an expression. +after you enter an expression ``` # let inc x = x + 1 ;; @@ -31,8 +36,8 @@ val inc : int -> int = <fun> val a : int = 99 ``` -For a source file you can use "ocamlc -i /path/to/file.ml" command -to print all names and type signatures. +For a source file you can use the `ocamlc -i /path/to/file.ml` command +to print all names and type signatures ``` $ cat sigtest.ml @@ -48,12 +53,12 @@ val a : int ``` Note that type signatures of functions of multiple arguments are -written in curried form. A function that takes multiple arguments can be +written in [curried](https://en.wikipedia.org/wiki/Currying) form. +A function that takes multiple arguments can be represented as a composition of functions that take only one argument. -The "f(x,y) = x + y" function from the example above applied to -arguments 2 and 3 is equivalent to the "f0(y) = 2 + y" function applied to 3. -Hence the "int -> int -> int" signature. - +The `f(x,y) = x + y` function from the example above applied to +arguments 2 and 3 is equivalent to the `f0(y) = 2 + y` function applied to 3. +Hence the `int -> int -> int` signature. ```ocaml (*** Comments ***) @@ -65,13 +70,14 @@ Hence the "int -> int -> int" signature. (*** Variables and functions ***) -(* Expressions can be separated by a double semicolon symbol, ";;". +(* Expressions can be separated by a double semicolon ";;". In many cases it's redundant, but in this tutorial we use it after every expression for easy pasting into the interpreter shell. Unnecessary use of expression separators in source code files is often considered to be a bad style. *) -(* Variable and function declarations use "let" keyword. *) +(* Variable and function declarations use the "let" keyword. *) +(* Variables are immutable by default in OCaml *) let x = 10 ;; (* OCaml allows single quote characters in identifiers. @@ -109,42 +115,42 @@ let sqr2 = sqr (-2) ;; "unit" type for it that has the only one value written as "()" *) let print_hello () = print_endline "hello world" ;; -(* Note that you must specify "()" as argument when calling it. *) +(* Note that you must specify "()" as the argument when calling it. *) print_hello () ;; -(* Calling a function with insufficient number of arguments +(* Calling a function with an insufficient number of arguments does not cause an error, it produces a new function. *) 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 ;; (* Evaluates to 5 *) -(* You can use multiple expressions in function body. +(* You can use multiple expressions in the function body. The last expression becomes the return value. All other expressions must be of the "unit" type. This is useful when writing in imperative style, the simplest - form of it is inserting a debug print. *) + form of which is inserting a debug print. *) let print_and_return x = print_endline (string_of_int x); x ;; (* Since OCaml is a functional language, it lacks "procedures". - Every function must return something. So functions that - do not really return anything and are called solely for their - side effects, like print_endline, return value of "unit" type. *) + Every function must return something. So functions that do not + really return anything and are called solely for their side + effects, like print_endline, return a value of "unit" type. *) -(* Definitions can be chained with "let ... in" construct. - This is roughly the same to assigning values to multiple +(* Definitions can be chained with the "let ... in" construct. + This is roughly the same as assigning values to multiple variables before using them in expressions in imperative languages. *) let x = 10 in let y = 20 in x + y ;; -(* Alternatively you can use "let ... and ... in" construct. +(* Alternatively you can use the "let ... and ... in" construct. This is especially useful for mutually recursive functions, - with ordinary "let .. in" the compiler will complain about + with ordinary "let ... in" the compiler will complain about unbound values. *) let rec is_even = function @@ -186,9 +192,9 @@ let my_lambda = fun x -> x * x ;; ~-. 3.4 (* Float only *) (* You can define your own operators or redefine existing ones. - Unlike SML or Haskell, only selected symbols can be used - for operator names and first symbol defines associativity - and precedence rules. *) + Unlike Standard ML or Haskell, only certain symbols can be + used for operator names and the operator's first symbol determines + its associativity and precedence rules. *) let (+) a b = a - b ;; (* Surprise maintenance programmers. *) (* More useful: a reciprocal operator for floats. @@ -201,7 +207,7 @@ let (~/) x = 1.0 /. x ;; (* Lists are enclosed in square brackets, items are separated by semicolons. *) -let my_list = [1; 2; 3] ;; +let my_list = [1; 2; 3] ;; (* Has type "int list". *) (* Tuples are (optionally) enclosed in parentheses, items are separated by commas. *) @@ -223,6 +229,10 @@ List.filter (fun x -> x mod 2 = 0) [1; 2; 3; 4] ;; often referred to as "cons". *) 1 :: [2; 3] ;; (* Gives [1; 2; 3] *) +(* Remember that the cons :: constructor can only cons a single item to the front + of a list. To combine two lists use the append @ operator *) +[1; 2] @ [3; 4] ;; (* Gives [1; 2; 3; 4] *) + (* Arrays are enclosed in [| |] *) let my_array = [| 1; 2; 3 |] ;; @@ -258,7 +268,7 @@ let ocaml = (String.make 1 'O') ^ "Caml" ;; (* There is a printf function. *) Printf.printf "%d %s" 99 "bottles of beer" ;; -(* Unformatted read and write functions are there too. *) +(* There's also unformatted read and write functions. *) print_string "hello world\n" ;; print_endline "hello world" ;; let line = read_line () ;; @@ -291,15 +301,59 @@ let my_point = Point (2.0, 3.0) ;; type 'a list_of_lists = 'a list list ;; type int_list_list = int list_of_lists ;; +(* These features allow for useful optional types *) +type 'a option = Some of 'a | None ;; +let x = Some x ;; +let y = None ;; + (* Types can also be recursive. Like in this type analogous to - built-in list of integers. *) + a built-in list of integers. *) type my_int_list = EmptyList | IntList of int * my_int_list ;; let l = IntList (1, EmptyList) ;; +(* or Trees *) +type 'a tree = + | Empty + | Node of 'a tree * 'a * 'a tree + +let example_tree: int tree = + Node ( + Node (Empty, 7, Empty), + 5, + Node (Empty, 9, Empty) + ) +(* + 5 + / \ + 7 9 +*) + +(*** Records ***) + +(* A collection of values with named fields *) + +type animal = + { + name: string; + color: string; + legs: int; + } +;; + +let cow = + { name: "cow"; + color: "black and white"; + legs: 4; + } +;; +val cow : animal + +cow.name ;; +- : string = "cow" (*** Pattern matching ***) -(* Pattern matching is somewhat similar to switch statement in imperative +(* Pattern matching is somewhat similar to the switch statement in imperative languages, but offers a lot more expressive power. Even though it may look complicated, it really boils down to matching @@ -311,7 +365,7 @@ let l = IntList (1, EmptyList) ;; let is_zero x = match x with | 0 -> true - | _ -> false (* The "_" pattern means "anything else". *) + | _ -> false (* The "_" means "anything else". *) ;; (* Alternatively, you can use the "function" keyword. *) @@ -342,6 +396,19 @@ let say x = say (Cat "Fluffy") ;; (* "Fluffy says meow". *) +(* However, pattern matching must be exhaustive *) +type color = Red | Blue | Green ;; +let what_color x = + match x with + | Red -> "color is red" + | Blue -> "color is blue" + (* Won't compile! You have to add a _ case or a Green case + to ensure all possibilities are accounted for *) +;; +(* Also, the match statement checks each case in order. + So, if a _ case appears first, none of the + following cases will be reached! *) + (** Traversing data structures with pattern matching **) (* Recursive types can be traversed with pattern matching easily. @@ -369,9 +436,75 @@ let rec sum_int_list l = let t = Cons (1, Cons (2, Cons (3, Nil))) ;; sum_int_list t ;; +(* Heres a function to tell if a list is sorted *) +let rec is_sorted l = + match l with + | x :: y :: tail -> x <= y && is_sorted (y :: tail) + | _ -> true +;; + +is_sorted [1; 2; 3] ;; (* True *) +(* OCaml's powerful type inference guesses that l is of type int list + since the <= operator is used on elements of l *) + +(* And another to reverse a list *) +let rec rev (l: 'a list) : 'a list = + match l with + | [] -> [] + | x::tl -> (rev tl) @ [x] +;; + +rev [1; 2; 3] ;; (* Gives [3; 2; 1] *) +(* This function works on lists of any element type *) + +(*** Higher Order Functions ***) + +(* Functions are first class in OCaml *) + +let rec transform (f: 'a -> 'b) (l: 'a list) : 'b list = + match l with + | [] -> [] + | head :: tail -> (f head) :: transform f tail +;; + +transform (fun x -> x + 1) [1; 2; 3] ;; (* Gives [2; 3; 4] *) + +(** Lets combine everything we learned! **) +let rec filter (pred: 'a -> bool) (l: 'a list) : 'a list = + begin match l with + | [] -> [] + | x :: xs -> + let rest = filter pred xs in + if pred x then x :: rest else rest + end +;; + +filter (fun x -> x < 4) [3; 1; 4; 1; 5] ;; (* Gives [3; 1; 1]) *) + +(*** Mutability ***) + +(* Records and variables are immutable: you cannot change where a variable points to *) + +(* However, you can create mutable polymorphic fields *) +type counter = { mutable num : int } ;; + +let c = { num: 0 } ;; +c.num ;; (* Gives 0 *) +c.num <- 1 ;; (* <- operator can set mutable record fields *) +c.num ;; (* Gives 1 *) + +(* OCaml's standard library provides a ref type to make single field mutability easier *) +type 'a ref = { mutable contents : 'a } ;; +let counter = ref 0 ;; +!counter ;; (* ! operator returns x.contents *) +counter := !counter + 1 ;; (* := can be used to set contents *) ``` ## Further reading -* Visit the official website to get the compiler and read the docs: <http://ocaml.org/> -* Try interactive tutorials and a web-based interpreter by OCaml Pro: <http://try.ocamlpro.com/> +* Visit the official website to get the compiler and read the docs: [http://ocaml.org/](http://ocaml.org/) +* Quick tutorial on OCaml: [https://ocaml.org/docs/up-and-running](https://ocaml.org/docs/up-and-running) +* Complete online OCaml v5 playground: [https://ocaml.org/play](https://ocaml.org/play) +* An up-to-date (2022) book (with free online version) "Real World OCaml": [https://www.cambridge.org/core/books/real-world-ocaml-functional-programming-for-the-masses/052E4BCCB09D56A0FE875DD81B1ED571](https://www.cambridge.org/core/books/real-world-ocaml-functional-programming-for-the-masses/052E4BCCB09D56A0FE875DD81B1ED571) +* Online interactive textbook "OCaml Programming: Correct + Efficient + Beautiful" from Cornell University: [https://cs3110.github.io/textbook/cover.html](https://cs3110.github.io/textbook/cover.html) +* Try interactive tutorials and a web-based interpreter by OCaml Pro: [http://try.ocamlpro.com/](http://try.ocamlpro.com/) diff --git a/opencv.html.markdown b/opencv.html.markdown index f8763b35..b083feb8 100644 --- a/opencv.html.markdown +++ b/opencv.html.markdown @@ -14,9 +14,9 @@ Opencv currently supports wide variety of languages like, C++, Python, Java etc #### Installation Please refer to these articles for installation of OpenCV on your computer. -* Windows Installation Instructions: [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows]() -* Mac Installation Instructions (High Sierra): [https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a]() -* Linux Installation Instructions (Ubuntu 18.04): [https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv]() +* Windows Installation Instructions: [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows) +* Mac Installation Instructions (High Sierra): [https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a](https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a) +* Linux Installation Instructions (Ubuntu 18.04): [https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv](https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv) ### Here we will be focusing on python implementation of OpenCV @@ -114,13 +114,15 @@ eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') img = cv2.imread('human.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) -aces = face_cascade.detectMultiScale(gray, 1.3, 5) +faces = face_cascade.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces: + # Draw a rectangle around detected face cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] eyes = eye_cascade.detectMultiScale(roi_gray) for (ex,ey,ew,eh) in eyes: + # Draw a rectangle around detected eyes cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) cv2.imshow('img',img) @@ -133,12 +135,11 @@ cv2.destroyAllWindows() ### Further Reading: -* Download Cascade from [https://github.com/opencv/opencv/blob/master/data/haarcascades]() -* OpenCV drawing Functions [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html]() -* An up-to-date language reference can be found at [https://opencv.org]() -* Additional resources may be found at [https://en.wikipedia.org/wiki/OpenCV]() +* Download Cascade from [https://github.com/opencv/opencv/blob/master/data/haarcascades](https://github.com/opencv/opencv/blob/master/data/haarcascades) +* OpenCV drawing Functions [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html](https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html) +* An up-to-date language reference can be found at [https://opencv.org](https://opencv.org) +* Additional resources may be found at [https://en.wikipedia.org/wiki/OpenCV](https://en.wikipedia.org/wiki/OpenCV) * Good OpenCv Tutorials - * [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html]() - * [https://realpython.com/python-opencv-color-spaces]() - * [https://pyimagesearch.com]() - * [https://www.learnopencv.com]() + * [https://realpython.com/python-opencv-color-spaces](https://realpython.com/python-opencv-color-spaces) + * [https://pyimagesearch.com](https://pyimagesearch.com) + * [https://www.learnopencv.com](https://www.learnopencv.com) diff --git a/opengl.html.markdown b/opengl.html.markdown index 83ace3e8..f6a9085f 100644 --- a/opengl.html.markdown +++ b/opengl.html.markdown @@ -1,765 +1,765 @@ ----
-category: tool
-tool: OpenGL
-filename: learnopengl.cpp
-contributors:
- - ["Simon Deitermann", "s.f.deitermann@t-online.de"]
----
-
-**Open Graphics Library** (**OpenGL**) is a cross-language cross-platform application programming interface
-(API) for rendering 2D computer graphics and 3D vector graphics.<sup>[1]</sup> In this tutorial we will be
-focusing on modern OpenGL from 3.3 and above, ignoring "immediate-mode", Displaylists and
-VBO's without use of Shaders.
-I will be using C++ with SFML for window, image and context creation aswell as GLEW
-for modern OpenGL extensions, though there are many other librarys available.
-
-```cpp
-// Creating an SFML window and OpenGL basic setup.
-#include <GL/glew.h>
-#include <GL/gl.h>
-#include <SFML/Graphics.h>
-#include <iostream>
-
-int main() {
- // First we tell SFML how to setup our OpenGL context.
- sf::ContextSettings context{ 24, // depth buffer bits
- 8, // stencil buffer bits
- 4, // MSAA samples
- 3, // major opengl version
- 3 }; // minor opengl version
- // Now we create the window, enable VSync
- // and set the window active for OpenGL.
- sf::Window window{ sf::VideoMode{ 1024, 768 },
- "opengl window",
- sf::Style::Default,
- context };
- window.setVerticalSyncEnabled(true);
- window.setActive(true);
- // After that we initialise GLEW and check if an error occured.
- GLenum error;
- glewExperimental = GL_TRUE;
- if ((err = glewInit()) != GLEW_OK)
- std::cout << glewGetErrorString(err) << std::endl;
- // Here we set the color glClear will clear the buffers with.
- glClearColor(0.0f, // red
- 0.0f, // green
- 0.0f, // blue
- 1.0f); // alpha
- // Now we can start the event loop, poll for events and draw objects.
- sf::Event event{ };
- while (window.isOpen()) {
- while (window.pollEvent(event)) {
- if (event.type == sf::Event::Closed)
- window.close;
- }
- // Tell OpenGL to clear the color buffer
- // and the depth buffer, this will clear our window.
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Flip front- and backbuffer.
- window.display();
- }
- return 0;
-}
-```
-
-## Loading Shaders
-
-After creating a window and our event loop we should create a function,
-that sets up our shader program.
-
-```cpp
-GLuint createShaderProgram(const std::string& vertexShaderPath,
- const std::string& fragmentShaderPath) {
- // Load the vertex shader source.
- std::stringstream ss{ };
- std::string vertexShaderSource{ };
- std::string fragmentShaderSource{ };
- std::ifstream file{ vertexShaderPath };
- if (file.is_open()) {
- ss << file.rdbuf();
- vertexShaderSource = ss.str();
- file.close();
- }
- // Clear the stringstream and load the fragment shader source.
- ss.str(std::string{ });
- file.open(fragmentShaderPath);
- if (file.is_open()) {
- ss << file.rdbuf();
- fragmentShaderSource = ss.str();
- file.close();
- }
- // Create the program.
- GLuint program = glCreateProgram();
- // Create the shaders.
- GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
- GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
- // Now we can load the shader source into the shader objects and compile them.
- // Because glShaderSource() wants a const char* const*,
- // we must first create a const char* and then pass the reference.
- const char* cVertexSource = vertexShaderSource.c_str();
- glShaderSource(vertexShader, // shader
- 1, // number of strings
- &cVertexSource, // strings
- nullptr); // length of strings (nullptr for 1)
- glCompileShader(vertexShader);
- // Now we have to do the same for the fragment shader.
- const char* cFragmentSource = fragmentShaderSource.c_str();
- glShaderSource(fragmentShader, 1, &cFragmentSource, nullptr);
- glCompileShader(fragmentShader);
- // After attaching the source and compiling the shaders,
- // we attach them to the program;
- glAttachShader(program, vertexShader);
- glAttachShader(program, fragmentShader);
- glLinkProgram(program);
- // After linking the shaders we should detach and delete
- // them to prevent memory leak.
- glDetachShader(program, vertexShader);
- glDetachShader(program, fragmentShader);
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- // With everything done we can return the completed program.
- return program;
-}
-```
-
-If you want to check the compilation log you can add the following between <code>glCompileShader()</code> and <code>glAttachShader()</code>.
-
-```cpp
-GLint logSize = 0;
-std::vector<GLchar> logText{ };
-glGetShaderiv(vertexShader, // shader
- GL_INFO_LOG_LENGTH, // requested parameter
- &logSize); // return object
-if (logSize > 0) {
- logText.resize(logSize);
- glGetShaderInfoLog(vertexShader, // shader
- logSize, // buffer length
- &logSize, // returned length
- logText.data()); // buffer
- std::cout << logText.data() << std::endl;
-}
-```
-
-The same is possibile after <code>glLinkProgram()</code>, just replace <code>glGetShaderiv()</code> with <code>glGetProgramiv()</code>
-and <code>glGetShaderInfoLog()</code> with <code>glGetProgramInfoLog()</code>.
-
-```cpp
-// Now we can create a shader program with a vertex and a fragment shader.
-// ...
-glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-
-GLuint program = createShaderProgram("vertex.glsl", "fragment.glsl");
-
-sf::Event event{ };
-// ...
-// We also have to delete the program at the end of the application.
-// ...
- }
- glDeleteProgram(program);
- return 0;
-}
-// ...
-```
-
-Ofcourse we have to create the vertex and fragment shader before we can load them,
-so lets create two basic shaders.
-
-**Vertex Shader**
-
-```glsl
-// Declare which version of GLSL we use.
-// Here we declare, that we want to use the OpenGL 3.3 version of GLSL.
-#version 330 core
-// At attribute location 0 we want an input variable of type vec3,
-// that contains the position of the vertex.
-// Setting the location is optional, if you don't set it you can ask for the
-// location with glGetAttribLocation().
-layout(location = 0) in vec3 position;
-// Every shader starts in it's main function.
-void main() {
- // gl_Position is a predefined variable that holds
- // the final vertex position.
- // It consists of a x, y, z and w coordinate.
- gl_Position = vec4(position, 1.0);
-}
-```
-
-**Fragment Shader**
-
-```glsl
-#version 330 core
-// The fragment shader does not have a predefined variable for
-// the vertex color, so we have to define a output vec4,
-// that holds the final vertex color.
-out vec4 outColor;
-
-void main() {
- // We simply set the ouput color to red.
- // The parameters are red, green, blue and alpha.
- outColor = vec4(1.0, 0.0, 0.0, 1.0);
-}
-```
-
-## VAO and VBO
-Now we need to define some vertex position we can pass to our shaders. Lets define a simple 2D quad.
-
-```cpp
-// The vertex data is defined in a counter-clockwise way,
-// as this is the default front face.
-std::vector<float> vertexData {
- -0.5f, 0.5f, 0.0f,
- -0.5f, -0.5f, 0.0f,
- 0.5f, -0.5f, 0.0f,
- 0.5f, 0.5f, 0.0f
-};
-// If you want to use a clockwise definition, you can simply call
-glFrontFace(GL_CW);
-// Next we need to define a Vertex Array Object (VAO).
-// The VAO stores the current state while its active.
-GLuint vao = 0;
-glGenVertexArrays(1, &vao);
-glBindVertexArray(vao);
-// With the VAO active we can now create a Vertex Buffer Object (VBO).
-// The VBO stores our vertex data.
-GLuint vbo = 0;
-glGenBuffers(1, &vbo);
-glBindBuffer(GL_ARRAY_BUFFER, vbo);
-// For reading and copying there are also GL_*_READ and GL_*_COPY,
-// if your data changes more often use GL_DYNAMIC_* or GL_STREAM_*.
-glBufferData(GL_ARRAY_BUFFER, // target buffer
- sizeof(vertexData[0]) * vertexData.size(), // size
- vertexData.data(), // data
- GL_STATIC_DRAW); // usage
-// After filling the VBO link it to the location 0 in our vertex shader,
-// which holds the vertex position.
-// ...
-// To ask for the attibute location, if you haven't set it:
-GLint posLocation = glGetAttribLocation(program, "position");
-// ..
-glEnableVertexAttribArray(0);
-glVertexAttribPointer(0, 3, // location and size
- GL_FLOAT, // type of data
- GL_FALSE, // normalized (always false for floats)
- 0, // stride (interleaved arrays)
- nullptr); // offset (interleaved arrays)
-// Everything should now be saved in our VAO and we can unbind it and the VBO.
-glBindVertexArray(0);
-glBindBuffer(GL_ARRAY_BUFFER, 0);
-// Now we can draw the vertex data in our render loop.
-// ...
-glClear(GL_COLOR_BUFFER_BIT);
-// Tell OpenGL we want to use our shader program.
-glUseProgram(program);
-// Binding the VAO loads the data we need.
-glBindVertexArray(vao);
-// We want to draw a quad starting at index 0 of the VBO using 4 indices.
-glDrawArrays(GL_QUADS, 0, 4);
-glBindVertexArray(0);
-window.display();
-// ...
-// Ofcource we have to delete the allocated memory for the VAO and VBO at
-// the end of our application.
-// ...
-glDeleteBuffers(1, &vbo);
-glDeleteVertexArrays(1, &vao);
-glDeleteProgram(program);
-return 0;
-// ...
-```
-
-You can find the current code here: [OpenGL - 1](https://pastebin.com/W8jdmVHD).
-
-## More VBO's and Color
-Let's create another VBO for some colors.
-
-```cpp
-std::vector<float> colorData {
- 1.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 1.0f,
- 1.0f, 1.0f, 0.0f
-};
-```
-
-Next we can simply change some previous parameters to create a second VBO for our colors.
-
-```cpp
-// ...
-GLuint vbo[2];
-glGenBuffers(2, vbo);
-glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
-// ...
-glDeleteBuffers(2, vbo);
-/ ...
-// With these changes made we now have to load our color data into the new VBO
-// ...
-glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
-
-glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
-glBufferData(GL_ARRAY_BUFFER, sizeof(colorData[0]) * colorData.size(),
- colorData.data(), GL_STATIC_DRAW);
-glEnableVertexAttribArray(1);
-glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
-
-glBindVertexArray(0);
-// ...
-```
-
-Next we have to change our vertex shader to pass the color data to the fragment shader.<br>
-**Vertex Shader**
-
-```glsl
-#version 330 core
-
-layout(location = 0) in vec3 position;
-// The new location has to differ from any other input variable.
-// It is the same index we need to pass to
-// glEnableVertexAttribArray() and glVertexAttribPointer().
-layout(location = 1) in vec3 color;
-
-out vec3 fColor;
-
-void main() {
- fColor = color;
- gl_Position = vec4(position, 1.0);
-}
-```
-
-**Fragment Shader**
-
-```glsl
-#version 330 core
-
-in vec3 fColor;
-
-out vec4 outColor;
-
-void main() {
- outColor = vec4(fColor, 1.0);
-}
-```
-
-We define a new input variable ```color``` which represents our color data, this data
-is passed on to ```fColor```, which is an output variable of our vertex shader and
-becomes an input variable for our fragment shader.
-It is imporatant that variables passed between shaders have the exact same name
-and type.
-
-## Handling VBO's
-
-```cpp
-// If you want to completely clear and refill a VBO use glBufferData(),
-// just like we did before.
-// ...
-// There are two mains ways to update a subset of a VBO's data.
-// To update a VBO with existing data
-std::vector<float> newSubData {
- -0.25f, 0.5f, 0.0f
-};
-glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
-glBufferSubData(GL_ARRAY_BUFFER, // target buffer
- 0, // offset
- sizeof(newSubData[0]) * newSubData.size(), // size
- newSubData.data()); // data
-// This would update the first three values in our vbo[0] buffer.
-// If you want to update starting at a specific location just set the second
-// parameter to that value and multiply by the types size.
-// ...
-// If you are streaming data, for example from a file,
-// it is faster to directly pass the data to the buffer.
-// Other access values are GL_READ_ONLY and GL_READ_WRITE.
-glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
-// You can static_cast<float*>() the void* to be more safe.
-void* Ptr = glMapBuffer(GL_ARRAY_BUFFER, // buffer to map
- GL_WRITE_ONLY); // access to buffer
-memcpy(Ptr, newSubData.data(), sizeof(newSubData[0]) * newSubData.size());
-// To copy to a specific location add a destination offset to memcpy().
-glUnmapBuffer(GL_ARRAY_BUFFER);
-// ...
-// There is also a way to copy data from one buffer to another,
-// If we have two VBO's vbo[0] and vbo[1], we can copy like so
-// You can also read from GL_ARRAY_BUFFER.
-glBindBuffer(GL_COPY_READ_BUFFER, vbo[0]);
-// GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER are specifically for
-// copying buffer data.
-glBindBuffer(GL_COPY_WRITE_BUFFER, vbo[1]);
-glCopyBufferSubData(GL_COPY_READ_BUFFER, // read buffer
- GL_COPY_WRITE_BUFFER, // write buffer
- 0, 0, // read and write offset
- sizeof(vbo[0]) * 3); // copy size
-// This will copy the first three elements from vbo[0] to vbo[1].
-```
-
-## Uniforms
-
-**Fragment Shader**
-
-```glsl
-// Uniforms are variables like in and out, however,
-// we can change them easily by passing new values with glUniform().
-// Lets define a time variable in our fragment shader.
-#version 330 core
-// Unlike a in/out variable we can use a uniform in every shader,
-// without the need to pass it to the next one, they are global.
-// Don't use locations already used for attributes!
-// Uniform layout locations require OpenGL 4.3!
-layout(location = 10) uniform float time;
-
-in vec3 fColor;
-
-out vec4 outColor;
-
-void main() {
- // Create a sine wave from 0 to 1 based on the time passed to the shader.
- float factor = (sin(time * 2) + 1) / 2;
- outColor = vec4(fColor.r * factor, fColor.g * factor, fColor.b * factor, 1.0);
-}
-```
-
-Back to our source code.
-
-```cpp
-// If we haven't set the layout location, we can ask for it.
-GLint timeLocation = glGetUniformLocation(program, "time");
-// ...
-// Also we should define a Timer counting the current time.
-sf::Clock clock{ };
-// In out render loop we can now update the uniform every frame.
- // ...
- window.display();
- glUniform1f(10, // location
- clock.getElapsedTime().asSeconds()); // data
-}
-// ...
-```
-
-With the time getting updated every frame the quad should now be changing from
-fully colored to pitch black.
-There are different types of glUniform() you can find simple documentation here:
-[glUniform - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml)
-
-## Indexing and IBO's
-
-Element Array Buffers or more commonly Index Buffer Objects (IBO) allow us to use the
-same vertex data again which makes drawing a lot easier and faster. here's an example:
-
-```cpp
-// Lets create a quad from two rectangles.
-// We can simply use the old vertex data from before.
-// First, we have to create the IBO.
-// The index is referring to the first declaration in the VBO.
-std::vector<unsigned int> iboData {
- 0, 1, 2,
- 0, 2, 3
-};
-// That's it, as you can see we could reuse 0 - the top left
-// and 2 - the bottom right.
-// Now that we have our data, we have to fill it into a buffer.
-// Note that this has to happen between the two glBindVertexArray() calls,
-// so it gets saved into the VAO.
-GLuint ibo = 0;
-glGenBufferrs(1, &ibo);
-glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
-glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(iboData[0]) * iboData.size(),
- iboData.data(), GL_STATIC_DRAW);
-// Next in our render loop, we replace glDrawArrays() with:
-glDrawElements(GL_TRIANGLES, iboData.size(), GL_UNSINGED_INT, nullptr);
-// Remember to delete the allocated memory for the IBO.
-```
-
-You can find the current code here: [OpenGL - 2](https://pastebin.com/R3Z9ACDE).
-
-## Textures
-
-To load out texture we first need a library that loads the data, for simplicity I will be
-using SFML, however there are a lot of librarys for loading image data.
-
-```cpp
-// Lets save we have a texture called "my_tex.tga", we can load it with:
-sf::Image image;
-image.loadFromFile("my_tex.tga");
-// We have to flip the texture around the y-Axis, because OpenGL's texture
-// origin is the bottom left corner, not the top left.
-image.flipVertically();
-// After loading it we have to create a OpenGL texture.
-GLuint texture = 0;
-glGenTextures(1, &texture);
-glBindTexture(GL_TEXTURE_2D, texture);
-// Specify what happens when the coordinates are out of range.
-glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-// Specify the filtering if the object is very large.
-glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-// Load the image data to the texture.
-glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr());
-// Unbind the texture to prevent modifications.
-glBindTexture(GL_TEXTURE_2D, 0);
-// Delete the texture at the end of the application.
-// ...
-glDeleteTextures(1, &texture);
-```
-
-Ofcourse there are more texture formats than only 2D textures,
-You can find further information on parameters here:
-[glBindTexture - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTexture.xhtml)<br>
-[glTexImage2D - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml)<br>
-[glTexParameter - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml)<br>
-
-```cpp
-// With the texture created, we now have to specify the UV,
-// or in OpenGL terms ST coordinates.
-std::vector<float> texCoords {
- // The texture coordinates have to match the triangles/quad
- // definition.
- 0.0f, 1.0f, // start at top-left
- 0.0f, 0.0f, // go round counter-clockwise
- 1.0f, 0.0f,
- 1.0f, 1.0f // end at top-right
-};
-// Now we increase the VBO's size again just like we did for the colors.
-// ...
-GLuint vbo[3];
-glGenBuffers(3, vbo);
-// ...
-glDeleteBuffers(3, vbo);
-// ...
-// Load the texture coordinates into the new buffer.
-glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
-glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords[0]) * texCoords.size(),
- texCoords.data(), GL_STATIC_DRAW);
-glEnableVertexAttribArray(2);
-glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
-// Because the VAO does not store the texture we have to bind it before drawing.
-// ...
-glBindVertexArray(vao);
-glBindTexture(GL_TEXTURE_2D, texture);
-glDrawElements(GL_TRIANGLES, iboData.size(), GL_UNSINGED_INT, nullptr);
-// ...
-```
-
-Change the shaders to pass the data to the fragment shader.<br>
-
-**Vertex Shader**
-
-```glsl
-#version 330 core
-
-layout(location = 0) in vec3 position;
-layout(location = 1) in vec3 color;
-layout(location = 2) in vec2 texCoords;
-
-out vec3 fColor;
-out vec2 fTexCoords;
-
-void main() {
- fColor = color;
- fTexCoords = texCoords;
- gl_Position = vec4(position, 1.0);
-}
-```
-
-**Fragment Shader**
-
-```glsl
-#version 330 core
-// sampler2D represents our 2D texture.
-uniform sampler2D tex;
-uniform float time;
-
-in vec3 fColor;
-in vec2 fTexCoords;
-
-out vec4 outColor;
-
-void main() {
- // texture() loads the current texure data at the specified texture coords,
- // then we can simply multiply them by our color.
- outColor = texture(tex, fTexCoords) * vec4(fColor, 1.0);
-}
-```
-
-You can find the current code here: [OpenGL - 3](https://pastebin.com/u3bcwM6q)
-
-## Matrix Transformation
-
-**Vertex Shader**
-
-```glsl
-#version 330 core
-
-layout(location = 0) in vec3 position;
-layout(location = 1) in vec3 color;
-layout(location = 2) in vec2 texCoords;
-// Create 2 4x4 matricies, 1 for the projection matrix
-// and 1 for the model matrix.
-// Because we draw in a static scene, we don't need a view matrix.
-uniform mat4 projection;
-uniform mat4 model;
-
-out vec3 fColor;
-out vec2 fTexCoords;
-
-void main() {
- fColor = color;
- fTexCoords = texCoords;
- // Multiplay the position by the model matrix and then by the
- // projection matrix.
- // Beware order of multiplication for matricies!
- gl_Position = projection * model * vec4(position, 1.0);
-}
-```
-
-In our source we now need to change the vertex data, create a model- and a projection matrix.
-
-```cpp
-// The new vertex data, counter-clockwise declaration.
-std::vector<float> vertexData {
- 0.0f, 1.0f, 0.0f, // top left
- 0.0f, 0.0f, 0.0f, // bottom left
- 1.0f, 0.0f, 0.0f, // bottom right
- 1.0f, 1.0f, 0.0f // top right
-};
-// Request the location of our matricies.
-GLint projectionLocation = glGetUniformLocation(program, "projection");
-GLint modelLocation = glGetUniformLocation(program, "model");
-// Declaring the matricies.
-// Orthogonal matrix for a 1024x768 window.
-std::vector<float> projection {
- 0.001953f, 0.0f, 0.0f, 0.0f,
- 0.0f, -0.002604f, 0.0f, 0.0f,
- 0.0f, 0.0f, -1.0f, 0.0f,
- -1.0f, 1.0f, 0.0f, 1.0f
-};
-// Model matrix translating to x 50, y 50
-// and scaling to x 200, y 200.
-std::vector<float> model {
- 200.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 200.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 50.0f, 50.0f, 0.0f, 1.0f
-};
-// Now we can send our calculated matricies to the program.
-glUseProgram(program);
-glUniformMatrix4fv(projectionLocation, // location
- 1, // count
- GL_FALSE, // transpose the matrix
- projection.data()); // data
-glUniformMatrix4fv(modelLocation, 1, GL_FALSE, model.data());
-glUseProgram(0);
-// The glUniform*() calls have to be done, while the program is bound.
-```
-
-The application should now display the texture at the defined position and size.<br>
-You can find the current code here: [OpenGL - 4](https://pastebin.com/9ahpFLkY)
-
-```cpp
-// There are many math librarys for OpenGL, which create
-// matricies and vectors, the most used in C++ is glm (OpenGL Mathematics).
-// Its a header only library.
-// The same code using glm would look like:
-glm::mat4 projection{ glm::ortho(0.0f, 1024.0f, 768.0f, 0.0f) };
-glUniformMatrix4fv(projectionLocation, 1, GL_FALSE,
- glm::value_ptr(projection));
-// Initialise the model matrix to the identity matrix, otherwise every
-// multiplication would be 0.
-glm::mat4 model{ 1.0f };
-model = glm::translate(model, glm::vec3{ 50.0f, 50.0f, 0.0f });
-model = glm::scale(model, glm::vec3{ 200.0f, 200.0f, 0.0f });
-glUniformMatrix4fv(modelLocation, 1, GL_FALSE,
- glm::value_ptr(model));
-```
-
-## Geometry Shader
-
-Gemoetry shaders were introduced in OpenGL 3.2, they can produce vertices
-that are send to the rasterizer. They can also change the primitive type e.g.
-they can take a point as an input and output other primitives.
-Geometry shaders are inbetween the vertex and the fragment shader.
-
-**Vertex Shader**
-
-```glsl
-#version 330 core
-
-layout(location = 0) in vec3 position;
-layout(location = 1) in vec3 color;
-// Create an output interface block passed to the next shadaer stage.
-// Interface blocks can be used to structure data passed between shaders.
-out VS_OUT {
- vec3 color;
-} vs_out;
-
-void main() {
- vs_out.color = color
- gl_Position = vec4(position, 1.0);
-}
-```
-
-**Geometry Shader**
-
-```glsl
-#version 330 core
-// The geometry shader takes in points.
-layout(points) in;
-// It outputs a triangle every 3 vertices emitted.
-layout(triangle_strip, max_vertices = 3) out;
-// VS_OUT becomes an input variable in the geometry shader.
-// Every input to the geometry shader in treated as an array.
-in VS_OUT {
- vec3 color;
-} gs_in[];
-// Output color for the fragment shader.
-// You can also simply define color as 'out vec3 color',
-// If you don't want to use interface blocks.
-out GS_OUT {
- vec3 color;
-} gs_out;
-
-void main() {
- // Each emit calls the fragment shader, so we set a color for each vertex.
- gs_out.color = mix(gs_in[0].color, vec3(1.0, 0.0, 0.0), 0.5);
- // Move 0.5 units to the left and emit the new vertex.
- // gl_in[] is the current vertex from the vertex shader, here we only
- // use 0, because we are receiving points.
- gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, 0.0);
- EmitVertex();
- gs_out.color = mix(gs_in[0].color, vec3(0.0, 1.0, 0.0), 0.5);
- // Move 0.5 units to the right and emit the new vertex.
- gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.0, 0.0, 0.0);
- EmitVertex();
- gs_out.color = mix(gs_in[0].color, vec3(0.0, 0.0, 1.0), 0.5);
- // Move 0.5 units up and emit the new vertex.
- gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.75, 0.0, 0.0);
- EmitVertex();
- EndPrimitive();
-}
-```
-
-**Fragment Shader**
-
-```glsl
-in GS_OUT {
- vec3 color;
-} fs_in;
-
-out vec4 outColor;
-
-void main() {
- outColor = vec4(fs_in.color, 1.0);
-}
-```
-
-If you now store a single point with a single color in a VBO and draw them,
-you should see a triangle, with your color mixed half way between
-red, green and blue on each vertex.
-
-
-## Quotes
-<sup>[1]</sup>[OpenGL - Wikipedia](https://en.wikipedia.org/wiki/OpenGL)
-
-## Books
-
-- OpenGL Superbible - Fifth Edition (covering OpenGL 3.3)
-- OpenGL Programming Guide - Eighth Edition (covering OpenGL 4.3)
+--- +category: tool +tool: OpenGL +filename: learnopengl.cpp +contributors: + - ["Simon Deitermann", "s.f.deitermann@t-online.de"] +--- + +**Open Graphics Library** (**OpenGL**) is a cross-language cross-platform application programming interface +(API) for rendering 2D computer graphics and 3D vector graphics.<sup>[1]</sup> In this tutorial we will be +focusing on modern OpenGL from 3.3 and above, ignoring "immediate-mode", Displaylists and +VBO's without use of Shaders. +I will be using C++ with SFML for window, image and context creation aswell as GLEW +for modern OpenGL extensions, though there are many other librarys available. + +```cpp +// Creating an SFML window and OpenGL basic setup. +#include <GL/glew.h> +#include <GL/gl.h> +#include <SFML/Graphics.h> +#include <iostream> + +int main() { + // First we tell SFML how to setup our OpenGL context. + sf::ContextSettings context{ 24, // depth buffer bits + 8, // stencil buffer bits + 4, // MSAA samples + 3, // major opengl version + 3 }; // minor opengl version + // Now we create the window, enable VSync + // and set the window active for OpenGL. + sf::Window window{ sf::VideoMode{ 1024, 768 }, + "opengl window", + sf::Style::Default, + context }; + window.setVerticalSyncEnabled(true); + window.setActive(true); + // After that we initialise GLEW and check if an error occurred. + GLenum error; + glewExperimental = GL_TRUE; + if ((err = glewInit()) != GLEW_OK) + std::cout << glewGetErrorString(err) << std::endl; + // Here we set the color glClear will clear the buffers with. + glClearColor(0.0f, // red + 0.0f, // green + 0.0f, // blue + 1.0f); // alpha + // Now we can start the event loop, poll for events and draw objects. + sf::Event event{ }; + while (window.isOpen()) { + while (window.pollEvent(event)) { + if (event.type == sf::Event::Closed) + window.close; + } + // Tell OpenGL to clear the color buffer + // and the depth buffer, this will clear our window. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // Flip front- and backbuffer. + window.display(); + } + return 0; +} +``` + +## Loading Shaders + +After creating a window and our event loop we should create a function, +that sets up our shader program. + +```cpp +GLuint createShaderProgram(const std::string& vertexShaderPath, + const std::string& fragmentShaderPath) { + // Load the vertex shader source. + std::stringstream ss{ }; + std::string vertexShaderSource{ }; + std::string fragmentShaderSource{ }; + std::ifstream file{ vertexShaderPath }; + if (file.is_open()) { + ss << file.rdbuf(); + vertexShaderSource = ss.str(); + file.close(); + } + // Clear the stringstream and load the fragment shader source. + ss.str(std::string{ }); + file.open(fragmentShaderPath); + if (file.is_open()) { + ss << file.rdbuf(); + fragmentShaderSource = ss.str(); + file.close(); + } + // Create the program. + GLuint program = glCreateProgram(); + // Create the shaders. + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + // Now we can load the shader source into the shader objects and compile them. + // Because glShaderSource() wants a const char* const*, + // we must first create a const char* and then pass the reference. + const char* cVertexSource = vertexShaderSource.c_str(); + glShaderSource(vertexShader, // shader + 1, // number of strings + &cVertexSource, // strings + nullptr); // length of strings (nullptr for 1) + glCompileShader(vertexShader); + // Now we have to do the same for the fragment shader. + const char* cFragmentSource = fragmentShaderSource.c_str(); + glShaderSource(fragmentShader, 1, &cFragmentSource, nullptr); + glCompileShader(fragmentShader); + // After attaching the source and compiling the shaders, + // we attach them to the program; + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glLinkProgram(program); + // After linking the shaders we should detach and delete + // them to prevent memory leak. + glDetachShader(program, vertexShader); + glDetachShader(program, fragmentShader); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + // With everything done we can return the completed program. + return program; +} +``` + +If you want to check the compilation log you can add the following between <code>glCompileShader()</code> and <code>glAttachShader()</code>. + +```cpp +GLint logSize = 0; +std::vector<GLchar> logText{ }; +glGetShaderiv(vertexShader, // shader + GL_INFO_LOG_LENGTH, // requested parameter + &logSize); // return object +if (logSize > 0) { + logText.resize(logSize); + glGetShaderInfoLog(vertexShader, // shader + logSize, // buffer length + &logSize, // returned length + logText.data()); // buffer + std::cout << logText.data() << std::endl; +} +``` + +The same is possible after <code>glLinkProgram()</code>, just replace <code>glGetShaderiv()</code> with <code>glGetProgramiv()</code> +and <code>glGetShaderInfoLog()</code> with <code>glGetProgramInfoLog()</code>. + +```cpp +// Now we can create a shader program with a vertex and a fragment shader. +// ... +glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + +GLuint program = createShaderProgram("vertex.glsl", "fragment.glsl"); + +sf::Event event{ }; +// ... +// We also have to delete the program at the end of the application. +// ... + } + glDeleteProgram(program); + return 0; +} +// ... +``` + +Ofcourse we have to create the vertex and fragment shader before we can load them, +so lets create two basic shaders. + +**Vertex Shader** + +```glsl +// Declare which version of GLSL we use. +// Here we declare, that we want to use the OpenGL 3.3 version of GLSL. +#version 330 core +// At attribute location 0 we want an input variable of type vec3, +// that contains the position of the vertex. +// Setting the location is optional, if you don't set it you can ask for the +// location with glGetAttribLocation(). +layout(location = 0) in vec3 position; +// Every shader starts in it's main function. +void main() { + // gl_Position is a predefined variable that holds + // the final vertex position. + // It consists of a x, y, z and w coordinate. + gl_Position = vec4(position, 1.0); +} +``` + +**Fragment Shader** + +```glsl +#version 330 core +// The fragment shader does not have a predefined variable for +// the vertex color, so we have to define a output vec4, +// that holds the final vertex color. +out vec4 outColor; + +void main() { + // We simply set the output color to red. + // The parameters are red, green, blue and alpha. + outColor = vec4(1.0, 0.0, 0.0, 1.0); +} +``` + +## VAO and VBO +Now we need to define some vertex position we can pass to our shaders. Lets define a simple 2D quad. + +```cpp +// The vertex data is defined in a counter-clockwise way, +// as this is the default front face. +std::vector<float> vertexData { + -0.5f, 0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + 0.5f, 0.5f, 0.0f +}; +// If you want to use a clockwise definition, you can simply call +glFrontFace(GL_CW); +// Next we need to define a Vertex Array Object (VAO). +// The VAO stores the current state while its active. +GLuint vao = 0; +glGenVertexArrays(1, &vao); +glBindVertexArray(vao); +// With the VAO active we can now create a Vertex Buffer Object (VBO). +// The VBO stores our vertex data. +GLuint vbo = 0; +glGenBuffers(1, &vbo); +glBindBuffer(GL_ARRAY_BUFFER, vbo); +// For reading and copying there are also GL_*_READ and GL_*_COPY, +// if your data changes more often use GL_DYNAMIC_* or GL_STREAM_*. +glBufferData(GL_ARRAY_BUFFER, // target buffer + sizeof(vertexData[0]) * vertexData.size(), // size + vertexData.data(), // data + GL_STATIC_DRAW); // usage +// After filling the VBO link it to the location 0 in our vertex shader, +// which holds the vertex position. +// ... +// To ask for the attribute location, if you haven't set it: +GLint posLocation = glGetAttribLocation(program, "position"); +// .. +glEnableVertexAttribArray(0); +glVertexAttribPointer(0, 3, // location and size + GL_FLOAT, // type of data + GL_FALSE, // normalized (always false for floats) + 0, // stride (interleaved arrays) + nullptr); // offset (interleaved arrays) +// Everything should now be saved in our VAO and we can unbind it and the VBO. +glBindVertexArray(0); +glBindBuffer(GL_ARRAY_BUFFER, 0); +// Now we can draw the vertex data in our render loop. +// ... +glClear(GL_COLOR_BUFFER_BIT); +// Tell OpenGL we want to use our shader program. +glUseProgram(program); +// Binding the VAO loads the data we need. +glBindVertexArray(vao); +// We want to draw a quad starting at index 0 of the VBO using 4 indices. +glDrawArrays(GL_QUADS, 0, 4); +glBindVertexArray(0); +window.display(); +// ... +// Ofcource we have to delete the allocated memory for the VAO and VBO at +// the end of our application. +// ... +glDeleteBuffers(1, &vbo); +glDeleteVertexArrays(1, &vao); +glDeleteProgram(program); +return 0; +// ... +``` + +You can find the current code here: [OpenGL - 1](https://pastebin.com/W8jdmVHD). + +## More VBO's and Color +Let's create another VBO for some colors. + +```cpp +std::vector<float> colorData { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f +}; +``` + +Next we can simply change some previous parameters to create a second VBO for our colors. + +```cpp +// ... +GLuint vbo[2]; +glGenBuffers(2, vbo); +glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); +// ... +glDeleteBuffers(2, vbo); +/ ... +// With these changes made we now have to load our color data into the new VBO +// ... +glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + +glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); +glBufferData(GL_ARRAY_BUFFER, sizeof(colorData[0]) * colorData.size(), + colorData.data(), GL_STATIC_DRAW); +glEnableVertexAttribArray(1); +glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + +glBindVertexArray(0); +// ... +``` + +Next we have to change our vertex shader to pass the color data to the fragment shader.<br> +**Vertex Shader** + +```glsl +#version 330 core + +layout(location = 0) in vec3 position; +// The new location has to differ from any other input variable. +// It is the same index we need to pass to +// glEnableVertexAttribArray() and glVertexAttribPointer(). +layout(location = 1) in vec3 color; + +out vec3 fColor; + +void main() { + fColor = color; + gl_Position = vec4(position, 1.0); +} +``` + +**Fragment Shader** + +```glsl +#version 330 core + +in vec3 fColor; + +out vec4 outColor; + +void main() { + outColor = vec4(fColor, 1.0); +} +``` + +We define a new input variable ```color``` which represents our color data, this data +is passed on to ```fColor```, which is an output variable of our vertex shader and +becomes an input variable for our fragment shader. +It is imporatant that variables passed between shaders have the exact same name +and type. + +## Handling VBO's + +```cpp +// If you want to completely clear and refill a VBO use glBufferData(), +// just like we did before. +// ... +// There are two mains ways to update a subset of a VBO's data. +// To update a VBO with existing data +std::vector<float> newSubData { + -0.25f, 0.5f, 0.0f +}; +glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); +glBufferSubData(GL_ARRAY_BUFFER, // target buffer + 0, // offset + sizeof(newSubData[0]) * newSubData.size(), // size + newSubData.data()); // data +// This would update the first three values in our vbo[0] buffer. +// If you want to update starting at a specific location just set the second +// parameter to that value and multiply by the types size. +// ... +// If you are streaming data, for example from a file, +// it is faster to directly pass the data to the buffer. +// Other access values are GL_READ_ONLY and GL_READ_WRITE. +glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); +// You can static_cast<float*>() the void* to be more safe. +void* Ptr = glMapBuffer(GL_ARRAY_BUFFER, // buffer to map + GL_WRITE_ONLY); // access to buffer +memcpy(Ptr, newSubData.data(), sizeof(newSubData[0]) * newSubData.size()); +// To copy to a specific location add a destination offset to memcpy(). +glUnmapBuffer(GL_ARRAY_BUFFER); +// ... +// There is also a way to copy data from one buffer to another, +// If we have two VBO's vbo[0] and vbo[1], we can copy like so +// You can also read from GL_ARRAY_BUFFER. +glBindBuffer(GL_COPY_READ_BUFFER, vbo[0]); +// GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER are specifically for +// copying buffer data. +glBindBuffer(GL_COPY_WRITE_BUFFER, vbo[1]); +glCopyBufferSubData(GL_COPY_READ_BUFFER, // read buffer + GL_COPY_WRITE_BUFFER, // write buffer + 0, 0, // read and write offset + sizeof(vbo[0]) * 3); // copy size +// This will copy the first three elements from vbo[0] to vbo[1]. +``` + +## Uniforms + +**Fragment Shader** + +```glsl +// Uniforms are variables like in and out, however, +// we can change them easily by passing new values with glUniform(). +// Lets define a time variable in our fragment shader. +#version 330 core +// Unlike a in/out variable we can use a uniform in every shader, +// without the need to pass it to the next one, they are global. +// Don't use locations already used for attributes! +// Uniform layout locations require OpenGL 4.3! +layout(location = 10) uniform float time; + +in vec3 fColor; + +out vec4 outColor; + +void main() { + // Create a sine wave from 0 to 1 based on the time passed to the shader. + float factor = (sin(time * 2) + 1) / 2; + outColor = vec4(fColor.r * factor, fColor.g * factor, fColor.b * factor, 1.0); +} +``` + +Back to our source code. + +```cpp +// If we haven't set the layout location, we can ask for it. +GLint timeLocation = glGetUniformLocation(program, "time"); +// ... +// Also we should define a Timer counting the current time. +sf::Clock clock{ }; +// In out render loop we can now update the uniform every frame. + // ... + window.display(); + glUniform1f(10, // location + clock.getElapsedTime().asSeconds()); // data +} +// ... +``` + +With the time getting updated every frame the quad should now be changing from +fully colored to pitch black. +There are different types of glUniform() you can find simple documentation here: +[glUniform - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml) + +## Indexing and IBO's + +Element Array Buffers or more commonly Index Buffer Objects (IBO) allow us to use the +same vertex data again which makes drawing a lot easier and faster. here's an example: + +```cpp +// Lets create a quad from two rectangles. +// We can simply use the old vertex data from before. +// First, we have to create the IBO. +// The index is referring to the first declaration in the VBO. +std::vector<unsigned int> iboData { + 0, 1, 2, + 0, 2, 3 +}; +// That's it, as you can see we could reuse 0 - the top left +// and 2 - the bottom right. +// Now that we have our data, we have to fill it into a buffer. +// Note that this has to happen between the two glBindVertexArray() calls, +// so it gets saved into the VAO. +GLuint ibo = 0; +glGenBufferrs(1, &ibo); +glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); +glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(iboData[0]) * iboData.size(), + iboData.data(), GL_STATIC_DRAW); +// Next in our render loop, we replace glDrawArrays() with: +glDrawElements(GL_TRIANGLES, iboData.size(), GL_UNSIGNED_INT, nullptr); +// Remember to delete the allocated memory for the IBO. +``` + +You can find the current code here: [OpenGL - 2](https://pastebin.com/R3Z9ACDE). + +## Textures + +To load out texture we first need a library that loads the data, for simplicity I will be +using SFML, however there are a lot of librarys for loading image data. + +```cpp +// Lets save we have a texture called "my_tex.tga", we can load it with: +sf::Image image; +image.loadFromFile("my_tex.tga"); +// We have to flip the texture around the y-Axis, because OpenGL's texture +// origin is the bottom left corner, not the top left. +image.flipVertically(); +// After loading it we have to create a OpenGL texture. +GLuint texture = 0; +glGenTextures(1, &texture); +glBindTexture(GL_TEXTURE_2D, texture); +// Specify what happens when the coordinates are out of range. +glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +// Specify the filtering if the object is very large. +glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// Load the image data to the texture. +glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, + 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr()); +// Unbind the texture to prevent modifications. +glBindTexture(GL_TEXTURE_2D, 0); +// Delete the texture at the end of the application. +// ... +glDeleteTextures(1, &texture); +``` + +Ofcourse there are more texture formats than only 2D textures, +You can find further information on parameters here: +[glBindTexture - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTexture.xhtml)<br> +[glTexImage2D - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml)<br> +[glTexParameter - OpenGL Refpage](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml)<br> + +```cpp +// With the texture created, we now have to specify the UV, +// or in OpenGL terms ST coordinates. +std::vector<float> texCoords { + // The texture coordinates have to match the triangles/quad + // definition. + 0.0f, 1.0f, // start at top-left + 0.0f, 0.0f, // go round counter-clockwise + 1.0f, 0.0f, + 1.0f, 1.0f // end at top-right +}; +// Now we increase the VBO's size again just like we did for the colors. +// ... +GLuint vbo[3]; +glGenBuffers(3, vbo); +// ... +glDeleteBuffers(3, vbo); +// ... +// Load the texture coordinates into the new buffer. +glBindBuffer(GL_ARRAY_BUFFER, vbo[2]); +glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords[0]) * texCoords.size(), + texCoords.data(), GL_STATIC_DRAW); +glEnableVertexAttribArray(2); +glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, nullptr); +// Because the VAO does not store the texture we have to bind it before drawing. +// ... +glBindVertexArray(vao); +glBindTexture(GL_TEXTURE_2D, texture); +glDrawElements(GL_TRIANGLES, iboData.size(), GL_UNSIGNED_INT, nullptr); +// ... +``` + +Change the shaders to pass the data to the fragment shader.<br> + +**Vertex Shader** + +```glsl +#version 330 core + +layout(location = 0) in vec3 position; +layout(location = 1) in vec3 color; +layout(location = 2) in vec2 texCoords; + +out vec3 fColor; +out vec2 fTexCoords; + +void main() { + fColor = color; + fTexCoords = texCoords; + gl_Position = vec4(position, 1.0); +} +``` + +**Fragment Shader** + +```glsl +#version 330 core +// sampler2D represents our 2D texture. +uniform sampler2D tex; +uniform float time; + +in vec3 fColor; +in vec2 fTexCoords; + +out vec4 outColor; + +void main() { + // texture() loads the current texure data at the specified texture coords, + // then we can simply multiply them by our color. + outColor = texture(tex, fTexCoords) * vec4(fColor, 1.0); +} +``` + +You can find the current code here: [OpenGL - 3](https://pastebin.com/u3bcwM6q) + +## Matrix Transformation + +**Vertex Shader** + +```glsl +#version 330 core + +layout(location = 0) in vec3 position; +layout(location = 1) in vec3 color; +layout(location = 2) in vec2 texCoords; +// Create 2 4x4 matricies, 1 for the projection matrix +// and 1 for the model matrix. +// Because we draw in a static scene, we don't need a view matrix. +uniform mat4 projection; +uniform mat4 model; + +out vec3 fColor; +out vec2 fTexCoords; + +void main() { + fColor = color; + fTexCoords = texCoords; + // Multiplay the position by the model matrix and then by the + // projection matrix. + // Beware order of multiplication for matricies! + gl_Position = projection * model * vec4(position, 1.0); +} +``` + +In our source we now need to change the vertex data, create a model- and a projection matrix. + +```cpp +// The new vertex data, counter-clockwise declaration. +std::vector<float> vertexData { + 0.0f, 1.0f, 0.0f, // top left + 0.0f, 0.0f, 0.0f, // bottom left + 1.0f, 0.0f, 0.0f, // bottom right + 1.0f, 1.0f, 0.0f // top right +}; +// Request the location of our matricies. +GLint projectionLocation = glGetUniformLocation(program, "projection"); +GLint modelLocation = glGetUniformLocation(program, "model"); +// Declaring the matricies. +// Orthogonal matrix for a 1024x768 window. +std::vector<float> projection { + 0.001953f, 0.0f, 0.0f, 0.0f, + 0.0f, -0.002604f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f +}; +// Model matrix translating to x 50, y 50 +// and scaling to x 200, y 200. +std::vector<float> model { + 200.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 200.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 50.0f, 50.0f, 0.0f, 1.0f +}; +// Now we can send our calculated matricies to the program. +glUseProgram(program); +glUniformMatrix4fv(projectionLocation, // location + 1, // count + GL_FALSE, // transpose the matrix + projection.data()); // data +glUniformMatrix4fv(modelLocation, 1, GL_FALSE, model.data()); +glUseProgram(0); +// The glUniform*() calls have to be done, while the program is bound. +``` + +The application should now display the texture at the defined position and size.<br> +You can find the current code here: [OpenGL - 4](https://pastebin.com/9ahpFLkY) + +```cpp +// There are many math librarys for OpenGL, which create +// matricies and vectors, the most used in C++ is glm (OpenGL Mathematics). +// Its a header only library. +// The same code using glm would look like: +glm::mat4 projection{ glm::ortho(0.0f, 1024.0f, 768.0f, 0.0f) }; +glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, + glm::value_ptr(projection)); +// Initialise the model matrix to the identity matrix, otherwise every +// multiplication would be 0. +glm::mat4 model{ 1.0f }; +model = glm::translate(model, glm::vec3{ 50.0f, 50.0f, 0.0f }); +model = glm::scale(model, glm::vec3{ 200.0f, 200.0f, 0.0f }); +glUniformMatrix4fv(modelLocation, 1, GL_FALSE, + glm::value_ptr(model)); +``` + +## Geometry Shader + +Geometry shaders were introduced in OpenGL 3.2, they can produce vertices +that are send to the rasterizer. They can also change the primitive type e.g. +they can take a point as an input and output other primitives. +Geometry shaders are inbetween the vertex and the fragment shader. + +**Vertex Shader** + +```glsl +#version 330 core + +layout(location = 0) in vec3 position; +layout(location = 1) in vec3 color; +// Create an output interface block passed to the next shadaer stage. +// Interface blocks can be used to structure data passed between shaders. +out VS_OUT { + vec3 color; +} vs_out; + +void main() { + vs_out.color = color + gl_Position = vec4(position, 1.0); +} +``` + +**Geometry Shader** + +```glsl +#version 330 core +// The geometry shader takes in points. +layout(points) in; +// It outputs a triangle every 3 vertices emitted. +layout(triangle_strip, max_vertices = 3) out; +// VS_OUT becomes an input variable in the geometry shader. +// Every input to the geometry shader in treated as an array. +in VS_OUT { + vec3 color; +} gs_in[]; +// Output color for the fragment shader. +// You can also simply define color as 'out vec3 color', +// If you don't want to use interface blocks. +out GS_OUT { + vec3 color; +} gs_out; + +void main() { + // Each emit calls the fragment shader, so we set a color for each vertex. + gs_out.color = mix(gs_in[0].color, vec3(1.0, 0.0, 0.0), 0.5); + // Move 0.5 units to the left and emit the new vertex. + // gl_in[] is the current vertex from the vertex shader, here we only + // use 0, because we are receiving points. + gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, 0.0); + EmitVertex(); + gs_out.color = mix(gs_in[0].color, vec3(0.0, 1.0, 0.0), 0.5); + // Move 0.5 units to the right and emit the new vertex. + gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.0, 0.0, 0.0); + EmitVertex(); + gs_out.color = mix(gs_in[0].color, vec3(0.0, 0.0, 1.0), 0.5); + // Move 0.5 units up and emit the new vertex. + gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.75, 0.0, 0.0); + EmitVertex(); + EndPrimitive(); +} +``` + +**Fragment Shader** + +```glsl +in GS_OUT { + vec3 color; +} fs_in; + +out vec4 outColor; + +void main() { + outColor = vec4(fs_in.color, 1.0); +} +``` + +If you now store a single point with a single color in a VBO and draw them, +you should see a triangle, with your color mixed half way between +red, green and blue on each vertex. + + +## Quotes +<sup>[1]</sup>[OpenGL - Wikipedia](https://en.wikipedia.org/wiki/OpenGL) + +## Books + +- OpenGL Superbible - Fifth Edition (covering OpenGL 3.3) +- OpenGL Programming Guide - Eighth Edition (covering OpenGL 4.3) diff --git a/openscad.html.markdown b/openscad.html.markdown new file mode 100644 index 00000000..63570cbe --- /dev/null +++ b/openscad.html.markdown @@ -0,0 +1,117 @@ +--- +language: openscad +filename: learnopenscad.scad +contributors: + - ["Tom Preston", "https://github.com/tompreston/"] +--- + +Draw 3D models with code using [OpenSCAD](https://openscad.org/). + +``` +// Comments look like this + +// 3D Primitives +cube(10); +cube([5, 10, 20]); +sphere(10); + +// Transformations +translate([20, 0, 0]) cube(10); +rotate([0, 20, 30]) cube(10); + +translate([20, 0, 0]) rotate([0, 20, 30]) cube(10); +rotate([0, 20, 30]) translate([20, 0, 0]) cube(10); + +// Modifiers +// +// * disable +// ! show only +// # highlight / debug +// % transparent / background +// +// For example, show only the rotated cube at the origin, before we translate it. +translate([20, 0, 0]) !rotate([0, 20, 30]) cube(10); + +// Formatting +// The following models are the same. The official docs prefer the second. +rotate([0, 20, 30]) translate([20, 0, 0]) cube(10); + +rotate([0, 20, 30]) + translate([20, 0, 0]) + cube(10); + +rotate([0, 20, 30]) { + translate([20, 0, 0]) { + cube(10); + } +} + +// Loops +num_cubes = 5; +r = 20; +cube_len = 5; + +for (i = [0:num_cubes]) { + echo(str("Plot cube ", i)); + rotate([0, i * 360 / num_cubes, 0]) + translate([r, 0, 0]) + cube(cube_len, center=true); +} + +// Boolean operations +// +// union() - the sum of both shapes +// difference() - the first shape, minus the second shape +// intersection() - only parts of both shapes which intersect +// +cube_l = 20; +cube_w = 10; +cube_h = 10; + +hole_pos_l = 10; +hole_pos_h = 5; +hole_r = 3; + +difference() { + cube([cube_l, cube_w, cube_h]); + translate([hole_pos_l, 0, hole_pos_h]) + rotate([-90, 0, 0]) + cylinder(cube_w, r=hole_r); +} + +// Functions calculate values +function inch2mm(i) = i * 25.4; + +cube(inch2mm(2)); + +// Modules create objects you want to use later +module house(roof="flat", paint=[1,0,0]) { + color(paint) + if (roof=="flat") { + translate([0,-1,0]) cube(); + } else if (roof=="pitched") { + rotate([90,0,0]) + linear_extrude(height=1) + polygon(points=[[0,0],[0,1],[0.5,1.5],[1,1],[1,0]]); + } + else if (roof=="domical") { + translate([0,-1,0]) { + translate([0.5,0.5,1]) + sphere(r=0.5,$fn=20); + cube(); + } + } +} + +house("pitched"); +translate([2, 0, 0]) house("domical"); + +// Import modules and function from other files +include <filename> // Import the content of the file as if they were written in this file +use <filename> // Import modules and functions, but do not execute any commands +``` + +## Further Reading +* Official docs https://openscad.org/documentation.html +* Cheat sheet https://openscad.org/cheatsheet/index.html +* Vim bindings https://github.com/sirtaj/vim-openscad diff --git a/osl.html.markdown b/osl.html.markdown new file mode 100644 index 00000000..1fe010ec --- /dev/null +++ b/osl.html.markdown @@ -0,0 +1,751 @@ +--- +language: osl +filename: learnosl.osl +contributors: + - ["Preetham Pemmasani", "https://github.com/Preetham-ai"] +--- + +OSL (Open Shading Language) is a programming language designed by Sony for Arnold Renderer used for creating shaders. + +[Read more here.](https://raw.githubusercontent.com/imageworks/OpenShadingLanguage/master/src/doc/osl-languagespec.pdf) + +```c + + +// Single-line comments start with // + +/* Multi line comments are preserved. */ + +// Statements can be terminated by ; +divide(1,2); + +/////////////// +// 1. Basics // +/////////////// + +// Declating variables +color Blue; // Initializing a variable +int _num = 3; +float Num = 3.00; +float c[3] = {0.1, 0.2, 3.14}; // Array + +// Math works as you would expect +3 + 1; // 4 +74 - 3; // 71 +20 * 2; // 40 +75/3; // 25.0 + +// And modulo division only works with integers +10 % 2; // 0 +31 % 4; // 1 + +// Bitwise operations only works with integers +- 0 // 1 (Unary Negation) +~ 00100011 // 11011100 (bitwise Compliment) +1 << 2; // 4 (shift Left) +12 >> 1; // 3 (shift Right) +1 & 0; // 0 (bitwise AND) +1 | 0; // 1 (bitwise OR) +1 ^ 1; // 0 (bitwise XOR) + +// We also have booleans +true; +false; + +// Booleans can't be compared to integers +true == 1 // Error +false == 0 // Error + +// Negation uses the ! symbol +!0; // 1 +!1; // 0 +!2; // 0 +//... and so on + +// Relation Operators are defined like: +0 == 0 // true (equal to) +0 != 1 // true (not equal to) +5 < 3 // false (less then) +3 <= 3 // true (less than or equal to) +69 > 69 // false (greater than) +99 >= 52 // true (greater than or equal) + + +// Functions are same as C and C++ +float sum(float a, float b){ + return a+b; +} + +int subtract(int a, int b){ + return a-b; +} + +sum(2,3); // 5 + +//////////////// +// 2. Shaders // +//////////////// + +// Shaders explain the custom behavior of materials and light +// Shader's syntax is similar to the main function in C +// The inputs and the outputs should be initialized to default types +shader multiply(float a = 0.0, + float b = 0.0, + output float c = 0.0){ + c = a*b; +} + +// Double brackets[[ ]] is used to classify metadata of a shader +surface plastic + [[ string help = "Realistic wood shader" ]] +( + color Plastic = color (0.7, 0.5, 0.3) [[ string help = "Base color" ]], + float Reflectivity = 0.5 [[ float min = 0, float max = 1 ]], +){...} + +/////////////////////////////////////// +// Metadata Types +/////////////////////////////////////// + +[[ string label = "IOR" ]] // Display-name in UI of the parameter +[[ string help = "Change Refractive Index" ]] // Info about the parameter +[[ string help = "widget" // Gives widgets to input the parameter + string widget = "number" ]] // input float or int + string widget = "string" ]] // String input + string widget = "boolean" ]] // yes/no (or) 1/0 + string widget = "popup", options = "smooth|rough" ]] // Drop-down list + // enum Drop-down list can also be made + string widget = "mapper", options = "smooth:0|rough:1" ]] + string widget = "filename" ]] // Input files externally + string widget = "null" ]] // null input + +[[ float min = 0.0 ]] // Minimum value of parameter +[[ float max = 0.5 ]] // Maximum value of parameter +[[ int slider = 3.0 // Adds a slider as an input + int slidermin = -1]] // minimum value of the slider + int slidermax = 3]] // maximum value of the slider + int slidercenter = 2]] // origin value of the slider + +[[ float sensitivity = 0.5 ]] // step size for incrementing the parameter +[[ string URL = www.example.com/ ]] // URL of shader's documentation + + + +// There are different types of shaders + +/* Surface shaders determine the basic material properties of a surface and +how it reacts to light */ +// Light shaders are a type of SURFACE shaders used for emissive objects. +// Displacement shaders alter the geometry using position and normals. +// Volume shaders adds a medium like air/smoke/dust into the scene. + +volume multiply(float a = 0.0, float b = 0.0, output float c = 0.0){ + c = 2*a+b; +} + +//////////////////////////////////////// +// 3. Data Types and Global Variables // +//////////////////////////////////////// + +// Data Types + +// 1. The void type indicates a function that doesn't return any value + +// 2. int (Integer) + int x = -12; // Minimum size of 32-bits + int new2 = 0x01cf; // Hexadecimal can also be specified + + /////////////////////////////////////// + // Order of Evaluation + /////////////////////////////////////// + + // From top to bottom, top has higher precedence + //--------------------------// + // Operators // + //--------------------------// + // int++, int-- // + // ++ int --int - ~ ! // + // * / % // + // + - // + // << >> // + // < <= > >= // + // == != // + // & // + // ^ // + // | // + // && // + // || // + // ?: // + // = += -= *= /= // + //--------------------------// + +// 3. float (Floating-point number) + float A = 2.3; // minimum IEEE 32-bit float + float Z = -4.1e2; // Z = -4.1 * 10^2 + + // Order of evaluation is similar to int. + // Operations like ( ~ ! % << >> ^ | & && || ) aren't available in float + +// 4. string + // The syntax is similar to C + string new = "Hello World"; + // some Special characters: + /* + '\"'; // double quote + '\n'; // newline character + '\t'; // tab character (left justifies text) + '\v'; // vertical tab + '\\'; // back slash + '\r'; // carriage return + '\b'; // backspace character + */ + + // Strings are concatenated with whitespace + "Hello " "world!"; // "Hello world!" + // concat function can also be used + string concat ("Hello ","World!"); // "Hello world!" + + // printf function is same as C + int i = 18; + printf("I am %d years old",i); // I am 18 years old + + // String functions can alse be used + int strlen (string s); // gives the length of the string + int len = strlen("Hello, World!"); // len = 13 + + // startswith returns 1 if string starts with prefix, else returns 0 + int starts = startswith("The quick brown fox", "The"); // starts = 1 + + // endswith returns 1 if string starts with suffix, else returns 0 + int ends = endswith("The quick brown fox", "fox"); // ends will be 1 + +// 5. color (Red, Green, Blue) + color p = color(0,1,2); // black + color q = color(1); // white ( same as color(1,1,1) ) + color r = color("rgb", 0.23, 0.1, 0.8); // explicitly specify in RGB + color s = color("hsv", 0.23, 0.1, 0.8); // specify in HSV + // HSV stands for (Hue, Saturation, Luminance) + // HSL stands for (Hue, Saturation, Lightness) + // YIQ, XYZ and xyY formats can also be used + // We can also access the indivudual values of (R,G,B) + float Red = p[0]; // 0 (access the red component) + float Green = p[1]; // 1 (access the green component) + float Blue = p[2]; // 2 (access the blue component) + + // They can also be accessed like this + float Red = p.r; // 0 (access the red component) + float Green = p.g; // 1 (access the green component) + float Blue = p.b; // 2 (access the blue component) + + // Math operators work like this with decreasing precedence + color C = (3,2,3) * (1,0,0); // (3, 0, 0) + color D = (1,1,1) * 255; // (255, 255, 255) + color E = (25,5,125) / 5; // (5, 1, 25) + color F = (30,40,50) / (3,4,5); // (10, 10, 10) + color A = (1,2,3) + (1,0,0); // (2, 2, 3) + color B = (1,2,3) - (1,0,0); // (0, 2, 3) + // Operators like ( - == != ) are also used + + // Color Functions + color blackbody (1500) // Gives color based on temperature (in Kelvin) + float luminance (0.5, 0.3, 0.8) // 0.37 gives luminance cd/m^2 + // Luminance is calculated by 0.2126R+0.7152G+0.0722B + color wavelength color (700) // (1, 0, 0) Gives color based on wavelength + color transformc ("hsl", "rgb") // converts one system to another + +// 6. point (x,y,z) is position of a point in the 3D space +// 7. vector (x,y,z) has length and direction but no position +// 8. normal (x,y,z) is a special vector perpendicular to a surface + // These Operators are the same as color and have the same precedence + L = point(0.5, 0.6, 0.7); + M = vector(30, 100, 70); + N = normal(0, 0, 1); + + // These 3 types can be assigned to a coordinate system + L = point("object", 0.5, 0.6, 0.7); // relative to local space + M = vector("common", 30, 100, 70); // relative to world space + // There's also ("shader", "world", "camera", "screen", "raster", "NDC") + + float x = L[0]; // 0.5 (access the x-component) + float y = L[1]; // 0.6 (access the y-component) + float z = L[2]; // 0.7 (access the z-component) + + // They can also be accessed like this + float x = M.x; // 30 (access the x-component) + float y = M.y; // 100 (access the y-component) + float z = M.z; // 70 (access the z-component) + + float a = dot ((1,2,3), (1,2,3)); // 14 (Dot Product) + vector b = cross ((1,2,3), (1,2,3)); // (0,0,0) (Cross Product) + float l = length(L); // 1.085 (length of vector) + vector normalize (vector L); // (0.460, 0.552, 0.644) Normalizes the vector + + point p0 = point(1, 2, 3); + point p1 = point(4, 5, 6); + point Q = point(0, 0, 0); + + // Finding distance between two points + float len = distance(point(1, 2, 3), point(4, 5, 6)); // 5.196 + // Perpendicular distance from Q to line joining P0 and P1 + float distance (point P0, point P1, point Q); // 2.45 + + +// 9. matrix + // Used for transforming vectors between different coordinate systems. + // They are usually 4x4 (or) 16 floats + matrix zero = 0; // makes a 4x4 zero matrix + /* 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0 */ + + matrix ident = 1; // makes a 4x4 identity matrix + /* 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 */ + + matrix m = 7; // Maked a 4x4 scalar matrix with scaling factor of 7 + /* 7.0, 0.0, 0.0, 0.0, + 0.0, 7.0, 0.0, 0.0, + 0.0, 0.0, 7.0, 0.0, + 0.0, 0.0, 0.0, 7.0 */ + + float x = m[1][1]; // 7 + + // matrices can be constructed using floats in row-major order + // matrices are usually 4x4 with 16 elements + matrix myMatrix = matrix(1.0, 0.0, 0.0, 0.0, // Row 1 + 0.0, 2.0, 0.0, 0.0, // Row 2 + 0.0, 0.0, 3.0, 0.0, // Row 3 + 0.0, 0.0, 0.0, 4.0); // Row 4 + + // matrix transformations are easy to implement + matrix a = matrix ("shader", 1); // converted shader to common + matrix m = matrix ("object", "world"); // converted object to world + + // Operations that can be used with decreasing precedence are: + // ( - * / == !=) + + float determinant (matrix M) // 24 (returns the determinant of the matrix) + float transpose (matrix M) // returns the transpose of the matrix + /* 1.0, 0.0, 0.0, 0.0, + 0.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 3.0, 0.0, + 0.0, 0.0, 0.0, 4.0 */ + +// 10. array + // Arrays in OSL are similar to C + float a[5]; // initialize array a with size 5 + int b[3] = {90,80,70}; // declare array with size 3 + int len = arraylength(b); // 3 + int f = b[1]; // 80 + float anotherarray[3] = b; // arrays can be copied if same type + +// 11. struct (Structures) + // Structures in OSL are similar to C and C++. + struct RGBA { // Defining a structure + color rgb; + float alpha; + }; + + + RGBA col; // Declaring a structure + RGBA b = { color(0.1, 0.2, 0.3), 1 }; // Can also be declared like this + + r.rgb = color (1, 0, 0); // Assign to one field + color c = r.rgb; // Read from a structure field + +// 12. closure + // Closure is used to store data that aren't considered when it executes. + // It cannot be manipulated or read. + // A null closure can always be assigned. + // OSL currently only supports color as their closure. + + // A few examples of closures are: + + // Diffuse BSDF closures: + closure color oren_nayar_diffuse_bsdf(normal N, color alb, float roughness) + closure color burley_diffuse_bsdf(normal N, color alb, float roughness); + + // Dielectric BSDF closure: + closure color dielectric_bsdf(normal N, vector U, color reflection_tint, + color transmission_tint, float roughness_x, float roughness_y, + float ior, string distribution); + + // Conductor BSDF closure: + closure color conductor_bsdf(normal N, vector U, float roughness_x, + float roughness_y, color ior, color extinction, string distribution); + + // Generalized Schlick BSDF closure: + closure color generalized_schlick_bsdf(normal N, vector U, + color reflection_tint, color transmission_tint, + float roughness_x, float roughness_y, color f0, color f90, + float exponent, string distribution); + + // Translucent BSDF closure: + closure color translucent_bsdf(normal N, color albedo); + + // Transparent BSDF closure: + closure color transparent_bsdf(); + + // Subsurface BSSRDF closure: + closure color subsurface_bssrdf(); + + // Sheen BSDF closure: + closure color sheen_bsdf(normal N, color albedo, float roughness); + + // Anisotropic VDF closure: (Volumetric) + closure color anisotropic_vdf(color albedo, color extinction, + float anisotropy); + + // Medium VDF closure: (Volumetric) + closure color medium_vdf(color albedo, float transmission_depth, + color transmission_color, float anisotropy, float ior, int priority); + + closure color uniform edf(color emittance); // Emission closure + closure color holdout(); // Holdout Hides objects beneath it + + // BSDFs can be layered using this closure + closure color layer (closure color top, closure color base); + + + +// Global Variables +// Contains info that the renderer knows +// These variables need not be declared + +point P // Position of the point you are shading +vector I // Incident ray direction from viewing position to shading position +normal N // Normal of the surface at P +normal Ng // Normal of the surface at P irrespective of bump mapping +float u // UV 2D x - parametric coordinate of geometry +float v // UV 2D y - parametric coordinate of geometry +vector dPdu // change of P with respect to u tangent to the surface +vector dPdv // change of P with respect to v tangent to the surface +float time // Current time +float dtime // Time covered +vector dPdtime // change of P with respect to time + +///////////////////// +// 4. Control flow // +///////////////////// + +// Conditionals in OSL are just like in C or C++. + +// If/Else +if (5>2){ + int x = s; + int l = x; +} +else{ + int x = s + l; +} + +// 'while' loop +int i = 0; +while (i < 5) { + i += 1; + printf("Current value of i: %d\n", i); +} + +// 'do-while' loop is where test happens after the body of the loop +int i = 0; +do { + printf("Current value of i: %d\n", i); + i += 1; +} while (i < 5); + +// 'for' loop +for (int i = 0; i < 5; i += 1) { + printf("Current value of i: %d\n", i); +} + +///////////////////// +// 5. Functions // +///////////////////// + +// Math Constants + M_PI // π + M_PI_35 // π/35 + m_E // e + M_LN2 // ln 2 + M_SQRT2 // √2 + M_SQRT1_2 // √(1/2) + +// Geometry Functions + vector N = vector(0.1, 1, 0.2); // Normal vector + vector I = vector(-0.5, 0.2, 0.8); // Incident vector + + // Faceforward tells the direction of vector + vector facing_dir = faceforward(N, I); // facing_dir = (-0.5, 0.2, 0.8) + + // faceforward with three arguments + vector ref = vector(0.3, -0.7, 0.6); // Reference normal + facing_dir = faceforward(N, I, ref); // facing_dir = (0.5, -0.2, -0.8) + + // reflect gives the reflected vector along normal + vector refl = reflect(I, N); // refl = (-0.7, -0.4, 1.4)\ + + // refract gives the refracted vector along normal + float ior = 1.5; // Index of refraction + vector refr = refract(I, N, ior); // refr = (-0.25861, 0.32814, 0.96143) + + /* Fresnel computes the Reflection (R) and Transmission (T) vectors, along + with the scaling factors for reflected (Kr) and transmitted (Kt) light. */ + float Kr, Kt; + vector R, T; + fresnel(I, N, ior, Kr, Kt, R, T); +/* Kr = 0.03958, Kt = 0.96042 + R = (-0.19278, -0.07711, 0.33854) + T = (-0.25861, 0.32814, 0.96143) */ + + // Rotating a point along a given axis + point Q = point(1, 0, 0); + float angle = radians(90); // 90 degrees + vector axis = vector(0, 0, 1); + point rotated_point = rotate(Q, angle, axis); + // rotated_point = point(0, 1, 0) + + // Rotating a point along a line made by 2 points + point P0 = point(0, 0, 0); + point P1 = point(1, 1, 0); + angle = radians(45); // 45 degrees + Q = point(1, 0, 0); + rotated_point = rotate(Q, angle, P0, P1); + // rotated_point = point(0.707107, 0.707107, 0) + + // Calculating normal of surface at point p + point p1 = point(1, 0, 0); // Point on the sphere of radius 1 + vector normal1 = calculatenormal(p1); + // normal1 = vector(1, 0, 0) + + // Transforming units is easy + float transformu ("cm", float x) // converts to cm + float transformu ("cm", "m", float y) // converts cm to m + +// Displacement Functions + void displace (float 5); // Displace by 5 amp units + void bump (float 10); // Bump by 10 amp units + + +// Noise Generation + + type noise (type noise (string noisetype, float u, float v, ...)); // noise + type noise (string noisetype, point p,...); // point instead of coordinates + /* some noises are ("perlin", "snoise", "uperlin", "noise", "cell", "hash" + "simplex", "usimplex", "gabor", etc) */ + + // Noise Names + + // 1. Perlin Noise (perlin, snoise): + // Creates smooth, swirling noise often used for textures. + // Range: [-1, 1] (signed) + color cloud_texture = noise("perlin", P); + + // 2. Simplex Noise (simplex, usimplex): + // Similar to Perlin noise but faster. + // Range: [-1, 1] (signed) for simplex, [0, 1] (unsigned) for usimplex + float bump_amount = 0.2 * noise("simplex", P * 5.0); + + // 3. UPerlin Noise (uperlin, noise): + // Similar to peril + // Range: [0, 1] (unsigned) + color new_texture = noise("uperlin", P); + + // 4. Cell Noise (cell): + // Creates a blocky, cellular and constant values within each unit block + // Range: [0, 1] (unsigned) + color new_texture = noise("cell", P); + + // 5. Hash Noise (hash): + // Generates random, uncorrelated values at each point. + // Range: [0, 1] (unsigned) + color new_texture = noise("hash", P); + + // Gabor Noise (gabor) + // Gabor Noise is advanced version of Perin noies and gives more control + // Range: [-1, 1] (signed) + // Gabor Noise Parameters + + // Anisotropic (default: 0) + // Controls anisotropy: + // 0: Isotropic (equal frequency in all directions) + // 1: Anisotropic with user-defined direction vector (defaults to (1,0,0)) + /* 2: Hybrid mode,anisotropic along direction vector but radially isotropic + perpendicularly. */ + + // Direction (default: (1,0,0)) + // Specifies the direction of anisotropy (used only if anisotropic is 1). + + // bandwidth (default: 1.0) + // Controls the frequency range of the noise. + + // impulses (default: 16) + // Controls the number of impulses used per cell, affecting detail level. + + // do_filter (default: 1) + // Enables/disables antialiasing (filtering). + + result = noise( + "gabor", + P, + "anisotropic", anisotropic, + "direction", direction, + "bandwidth", bandwidth, + "impulses", impulses, + "do_filter", do_filter + ); + + // Specific noises can also be used instead of passing them as types + // pnoise is periodic noise + float n1 = pnoise("perlin", 0.5, 1.0); + // 2D periodic noise with Gabor type + float n2 = pnoise("gabor", 0.2, 0.3, 2.0, 3.0); + // 2D non-periodic simplex noise + float n3 = snoise(0.1, 0.7); + // 2D periodic simplex noise + type psnoise (float u, float v, float uperiod, float vperiod); + float n4 = psnoise(0.4, 0.6, 0.5, 0.25); + // 2D cellular noise + float n5 = cellnoise(0.2, 0.8); + // 2D hash noise + int n6 = hash(0.7, 0.3); + +// Step Function + // Step Functions are used to compare input and threshold + + // The type may be of float, color, point, vector, or normal. + type step (type edge, type x); // Returns 1 if x ≥ edge, else 0 + color checker = step(0.5, P); // P is a point on the surface + /* Pixels with P values below 0.5 will be black, those above or equal will + be white */ + float visibility = step(10, distance(P, light_position)); + // Light is fully visible within 10 units, completely invisible beyond + + type linearstep (type edge0, type edge1, type x); /* Linearstep Returns 0 + if x ≤ edge0, and 1 if x ≥ edge1, with linear interpolation */ + color gradient = linearstep(0, 1, P); + // P is a point on the surface between 0 and 1 + // Color will graduate smoothly from black to white as P moves from 0 to 1 + float fade = linearstep(0.85, 1, N.z); // N.z is the z-component + // Object edges with normals close to vertical (N.z near 1) will fade out + + type smoothstep (type edge0, type edge1, type x); /* smoothstep Returns 0 + if x ≤ edge0, and 1 if x ≥ edge1, with Hermite interpolation */ + float soft_mask = smoothstep(0.2, 0.8, noise(P)); /* noise(P) is a noisy + value between 0 and 1. soft_mask will vary smoothly between 0 and 1 based + on noise(P), with a smoother curve than linearstep */ + +// Splines + // Splines are smooth curves based on a set of control points + + /* The type of interpolation ranges from "catmull-rom", "bezier", + "bspline", "hermite", "linear", or "constant" */ + + // Spline with knot vector + float[] knots = {0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1}; + point[] controls = {point(0),point(1, 2, 1),point(2, 1, 2),point(3, 3, 1)}; + spline curve1 = spline("bezier", 0.5, len(knots), controls); + // curve1 is a Bezier spline evaluated at u = 0.5 + + // Spline with control points + spline curve2 = spline("catmull-rom", 0.25, point(0, 0, 0), point(1, 2, 1), + point(2, 1, 2), point(3, 3, 1)); + // curve2 is a Catmull-Rom spline evaluated at u = 0.25 + + // Constant spline with a single float value + float value = 10; + u = 0.1; + spline curve5 = spline("constant", u, value); + // curve5 is a constant spline with value 10 evaluated at u = 0.1 + + // Hermite spline with point and vector controls + point q0 = point(0, 0, 0), q1 = point(3, 3, 3); + vector t0 = vector(1, 0, 0), t1 = vector(-1, 1, 1); + u = 0.75; + spline curve3 = spline("hermite", u, q0, t0, q1, t1); + // curve3 is a Hermite spline evaluated at u = 0.75 + + // Linear spline with float controls + float f0 = 0, f1 = 1, f2 = 2, f3 = 3; + u = 0.4; + spline curve4 = spline("linear", u, f0, f1, f2, f3); + // curve4 is a linear spline evaluated at u = 0.4 + + // InverseSplines also exist + + // Inverse spline with control values + float y0 = 0, y1 = 1, y2 = 2, y3 = 3; + float v = 1.5; + float u1 = splineinverse("linear", v, y0, y1, y2, y3); + // u1 = 0.5 (linear interpolation between y1 and y2) + + // Inverse spline with knot vector + float[] knots = {0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1}; + float[] values = {0, 1, 4, 9}; + v = 6; + float u2 = splineinverse("bezier", v, len(knots), values); + // u2 = 0.75 (Bezier spline inverse evaluated at v = 6) + + // Inverse spline with constant value + v = 10; + float u3 = splineinverse("constant", v, 10); + // u3 = 0 (since the constant spline always returns 10) + + // Inverse spline with periodic values + float y4 = 0, y5 = 1, y6 = 0; + v = 0.5; + float u4 = splineinverse("periodic", v, y4, y5, y6); + // u4 = 0.75 (periodic spline inverse evaluated at v = 0.5) + + + +// Calculus Operators + // Partial derivative of f with respect to x, y and z using Dx, Dy, Dz + float a = 3.14; + float dx = Dx(a); // partial derivative of a with respect to x + + point p = point(1.0, 2.0, 3.0); + vector dp_dx = Dx(p); // partial derivative of p with respect to x + + vector dv_dy = Dy(N); // partial derivative of normal with respect to y + + color c = color(0.5, 0.2, 0.8); + color dc_dz = Dz(c); // partial derivative of c with respect to z + + + float area (point p) // gives the surface area at the position p + + float filterwidth (float x) // gives the changes of x in adjacent samples + +// Texture Functions + // lookup for a texture at coordinates (x,y) + color col1 = texture("texture.png", 0.5, 0.2); + // Lookup color at (0.5, 0.2) in texture.png + + // 3D lookup for a texture at coordinates (x,y) + color col3 = texture3d("texture3d.vdb", point(0.25, 0.5, 0.75)); + + // parameters are ("blur","width","wrap","fill","alpha","interp", ...) + color col2 = texture("texture.png",1.0,0.75,"blur",0.1,"wrap", "periodic"); + // Lookup color at (1.0, 0.75) with blur 0.1 and periodic wrap mode + +// Light Functions + + float surfacearea (); // Returns the surface area of area light covers + int backfacing (); // Outputs 1 if the normals are backfaced, else 0 + int raytype (string name); // returns 1 if the ray is a particular raytype + + // Tracing a ray from a position in a direction + point pos = point(0, 0, 0); // Starting position of the ray + vector dir = vector(0, 0, 1); // Direction of the ray + int hit = trace(pos, dir); // returns 1 if it hits, else 0 + +``` +### Further reading + +* [Blender Docs for OSL](https://docs.blender.org/manual/en/latest/render/shader_nodes/osl.html) +* [C4D Docs for OSL](https://docs.otoy.com/cinema4d//OpenShadingLanguageOSL.html) +* Open Shading Language on [GitHub](https://github.com/AcademySoftwareFoundation/OpenShadingLanguage) +* [Official OSL Documentation](https://open-shading-language.readthedocs.io/en/main/)
\ No newline at end of file diff --git a/p5.html.markdown b/p5.html.markdown index be22d3e5..2588ffc6 100644 --- a/p5.html.markdown +++ b/p5.html.markdown @@ -7,43 +7,145 @@ contributors: filename: p5.js --- -p5.js is a JavaScript library that starts with the original goal of [Processing](http://processing.org"), to make coding accessible for artists, designers, educators, and beginners, and reinterprets this for today's web. +p5.js is a JavaScript library that starts with the original goal of [Processing](https://processing.org), to make coding accessible for artists, designers, educators, and beginners, and reinterprets this for today's web. Since p5 is a JavaScript library, you should learn [Javascript](https://learnxinyminutes.com/docs/javascript/) first. +To run p5.js code, you can go to [the online editor](https://editor.p5js.org/). + ```js /////////////////////////////////// // p5.js has two important functions to work with. function setup() { - // the setup function gets executed just once when the window is loaded + // the setup function gets executed just once when the window is loaded } function draw() { - // the draw function gets called every single frame. This means that for a frameRate(30) it would get called 30 times per second. + // the draw function gets called every single frame + // if the framerate is set to 30, it would get called 30 times every second } // the following code explains all features function setup() { - createCanvas(640, 480); // creates a new canvas element with 640px as width as 480px as height - background(128); // changes the background color of the canvas, can accept rgb values like background(100,200,20) else grayscale values like background(0) = black or background(255) = white + createCanvas(640, 480); // creates a new canvas element with 640px as width as 480px as height + background(128); // sets the background color to rgb(128, 128, 128) + // background('#aaf') // you can use hex codes and color names too } function draw() { - ellipse(10, 10, 50, 50); // creates a ellipse at the 10px from the left and 10px from the top with width adn height as 50 each, so its basically a circle. - //remember in p5.js the origin is at the top-left corner of the canvas + background('#f2f2fc'); // usually, you call `background` in draw to clear the screen + // creates an ellipse at 10px from the top and 10px from the left, with width and height 37 + ellipse(10, 10, 37, 37); + // remember in p5.js the origin is at the top-left corner of the canvas + + if (mouseIsPressed) { + // mouseIsPressed is a boolean variable that is true when the mouse is down, and false otherwise + + fill(0); // fill sets the fill color, which will stay until it is changed + } else { + fill(255, 255, 255, 240); // fill(a, b, c, d) sets the fill color to rgba(a, b, c, d) + } + + ellipse(mouseX, mouseY, 80, 80); + // mouseX and mouseY are the x and y position of the mouse, respectively + // the above code creates and ellipse under the mouse, and fills it with white or black + + + // some other 2d primitives (shapes) you can draw: + rect(9, 3, 23, 26); // x, y, width, height + noFill(); // sets the fill color to transparent + triangle(100, 400, 130, 200, 200, 300); // x1, y1, x2, y2, x3, y3 + point(100, 300); // create a point at x, y + // there are more, but they are more complex. +} - if (mouseIsPressed) { - // mouseIsPressed is a boolean variable that changes to true if the mouse buttton is pressed down at that instant +/** Bouncing balls animation + * You can copy-paste this code into the online editor at + * https://editor.p5js.org/ + */ +class Ball { + constructor(x, y, xvel, yvel, radius, col) { + this.position = createVector(x, y); // create a p5.Vector object which stores the x and y + this.velocity = createVector(xvel, yvel); // make a p5.Vector storing the velocity + this.radius = radius; + this.col = col; // p5 already uses the word color, so we use col instead + } - fill(0); // fill refers to the innner color or filling color of whatever shape you are going to draw next - } else { - fill(255); // you can give in rgb values like fill(72, 240, 80) to get colors, else a single values determines the grayscale where fill(255) stands for #FFF(white) and fill(0) stands for #000(black) + update() { + this.position.add(this.velocity); // you can add vectors with p5.Vector.add(p5.Vector) + if (this.position.x + this.radius > width) { + // flip the direction the ball is going in if it touches the edge + this.velocity.x *= -1; } + if (this.position.x - this.radius < 0) { + this.velocity.x *= -1; + } + if (this.position.y + this.radius > height) { + this.velocity.y *= -1; + } + if (this.position.y - this.radius < 0) { + this.velocity.y *= -1; + } + } + + render() { + // you can figure out what this does by now + fill(this.col); + ellipse(this.position.x, this.position.y, this.radius); + } +} + +let numBalls = 23; +let balls = []; + +function setup() { + createCanvas(400, 400); // width, height + for (let i = 0; i < numBalls; i++) { + let r = random(255); // random number between 0 and 255 + let g = random(255); + let b = random(255); + + balls.push( + new Ball( + random(30, width), // x position + random(height), // y position + random(-4, 4), // x velocity + random(-4, 4), // y velocity + random(4, 10), // radius + color(r, g, b) // fill color for the ball + ) + ); + } +} + +function draw() { + background(255); + for (let ball of balls) { + ball.update(); + ball.render(); + } +} + +// So far, we have only seen the default rendering mode. +// This time, we will use the 'webgl' renderer - ellipse(mouseX, mouseY, 80, 80); - // mouseX is the x-coordinate of the mouse's current position and mouseY is the y-coordinate of the mouse's current position +function setup() { + createCanvas(400, 400, WEBGL); // width, height, rendering mode +} + +function draw() { + background(0); - // the above code creates a circle wherever mouse's current position and fills it either black or white based on the mouseIsPressed + stroke('#000'); + fill('#aaf'); + + // rotate around the x, y, and z axes by the frame count divided by 50 + rotateX(frameCount / 50); + rotateY(frameCount / 50); + rotateZ(frameCount / 50); + // frameCount is a p5.js variable that stores the amount of frames that have passed + + box(50, 50, 50); // width, height, depth } ``` @@ -51,3 +153,9 @@ function draw() { - [p5.js | get started](http://p5js.org/get-started/) The official documentation - [Code! Programming for Beginners with p5.js - YouTube](https://www.youtube.com/watch?v=yPWkPOfnGsw&vl=en) Introduction and Coding challenges using Processing and p5.js by Coding Train +- [The Coding Train](https://codingtra.in/) A website with sketches made in p5 and processing + +## Source + +- [p5's source code](https://github.com/processing/p5.js) +- [p5.sound.js source](https://github.com/processing/p5.js-sound) diff --git a/pascal.html.markdown b/pascal.html.markdown index 9fb51c3b..fe00791a 100644 --- a/pascal.html.markdown +++ b/pascal.html.markdown @@ -12,10 +12,10 @@ source : [wikipedia](https://en.wikipedia.org/wiki/Pascal_(programming_language) -to compile and run a pascal program you could use a free pascal compiler. [Download Here](https://www.freepascal.org/) +To compile and run a pascal program you could use a free pascal compiler. [Download Here](https://www.freepascal.org/) ```pascal -//Anathomy of a Pascal Program +//Anatomy of a Pascal Program //this is a comment { this is a @@ -23,7 +23,7 @@ to compile and run a pascal program you could use a free pascal compiler. [Downl } //name of the program -program learn_pascal; //<-- dont forget a semicolon +program learn_pascal; //<-- don't forget a semicolon const { @@ -31,7 +31,7 @@ const } type { - this is where you should delcare a custom + this is where you should declare custom data-types } var @@ -44,11 +44,11 @@ begin { area to declare your instruction } -end. // End of a main program area should required a "." symbol +end. // End of a main program area should require a "." symbol ``` ```pascal -//declaring variable +//When declaring variables //you can do this var a:integer; var b:integer; @@ -62,7 +62,7 @@ var a,b : integer; ```pascal program Learn_More; -//Lets learn about data types and their operations +//Let's learn about data types and their operations const PI = 3.141592654; @@ -131,7 +131,7 @@ Begin str := 'apple'; bool := true; //pascal is not a case-sensitive language - //arithmethic operation + //arithmetic operation int := 1 + 1; // int = 2 overwriting the previous assignment int := int + 1; // int = 2 + 1 = 3; int := 4 div 2; //int = 2 division operation where result will be floored diff --git a/perl.html.markdown b/perl.html.markdown index 08001ab0..88185e9d 100644 --- a/perl.html.markdown +++ b/perl.html.markdown @@ -8,9 +8,9 @@ contributors: - ["Dan Book", "http://github.com/Grinnz"] --- -Perl 5 is a highly capable, feature-rich programming language with over 25 years of development. +Perl is a highly capable, feature-rich programming language with over 25 years of development. -Perl 5 runs on over 100 platforms from portables to mainframes and is suitable for both rapid prototyping and large scale development projects. +Perl runs on over 100 platforms from portables to mainframes and is suitable for both rapid prototyping and large scale development projects. ```perl # Single line comments start with a number sign. @@ -217,6 +217,12 @@ open(my $log, ">>", "my.log") or die "Can't open my.log: $!"; my $line = <$in>; my @lines = <$in>; +# You can iterate through the lines in a file one at a time with a while loop: + +while (my $line = <$in>) { + print "Found apples\n" if $line =~ m/apples/; +} + # You can write to an open filehandle using the standard "print" # function. diff --git a/perl6.html.markdown b/perl6.html.markdown deleted file mode 100644 index c7fde218..00000000 --- a/perl6.html.markdown +++ /dev/null @@ -1,1976 +0,0 @@ ---- -category: language -language: perl6 -filename: learnperl6.p6 -contributors: - - ["vendethiel", "http://github.com/vendethiel"] - - ["Samantha McVey", "https://cry.nu"] ---- - -Perl 6 is a highly capable, feature-rich programming language made for at -least the next hundred years. - -The primary Perl 6 compiler is called [Rakudo](http://rakudo.org), which runs on -the JVM and [the MoarVM](http://moarvm.com). - -Meta-note: double pound signs (`##`) are used to indicate paragraphs, -while single pound signs (`#`) indicate notes. - -`#=>` represents the output of a command. - -```perl6 -# Single line comments start with a pound sign. - -#`( Multiline comments use #` and a quoting construct. - (), [], {}, 「」, etc, will work. -) - -# Use the same syntax for multiline comments to embed comments. -for #`(each element in) @array { - put #`(or print element) $_ #`(with newline); -} -``` - -## Variables - -```perl6 -## In Perl 6, you declare a lexical variable using the `my` keyword: -my $variable; -## Perl 6 has 3 basic types of variables: scalars, arrays, and hashes. -``` - -### Scalars - -```perl6 -# Scalars represent a single value. They start with the `$` sigil: -my $str = 'String'; - -# Double quotes allow for interpolation (which we'll see later): -my $str2 = "String"; - -## Variable names can contain but not end with simple quotes and dashes, -## and can contain (and end with) underscores: -my $person's-belongings = 'towel'; # this works! - -my $bool = True; # `True` and `False` are Perl 6's boolean values. -my $inverse = !$bool; # Invert a bool with the prefix `!` operator. -my $forced-bool = so $str; # And you can use the prefix `so` operator -$forced-bool = ?$str; # to turn its operand into a Bool. Or use `?`. -``` - -### Arrays and Lists - -```perl6 -## Arrays represent multiple values. An array variable starts with the `@` -## sigil. Unlike lists, from which arrays inherit, arrays are mutable. - -my @array = 'a', 'b', 'c'; -# equivalent to: -my @letters = <a b c>; # array of words, delimited by space. - # Similar to perl5's qw, or Ruby's %w. -@array = 1, 2, 3; - -say @array[2]; # Array indices start at 0. Here the third element - # is being accessed. - -say "Interpolate an array using []: @array[]"; -#=> Interpolate an array using []: 1 2 3 - -@array[0] = -1; # Assigning a new value to an array index -@array[0, 1] = 5, 6; # Assigning multiple values - -my @keys = 0, 2; -@array[@keys] = @letters; # Assignment using an array containing index values -say @array; #=> a 6 b -``` - -### Hashes, or key-value Pairs. - -```perl6 -## Hashes are pairs of keys and values. You can construct a `Pair` object -## using the syntax `Key => Value`. Hash tables are very fast for lookup, -## and are stored unordered. Keep in mind that keys get "flattened" in hash -## context, and any duplicated keys are deduplicated. -my %hash = 'a' => 1, 'b' => 2; - -%hash = a => 1, # keys get auto-quoted when => (fat comma) is used. - b => 2, # Trailing commas are okay. -; - -## Even though hashes are internally stored differently than arrays, -## Perl 6 allows you to easily create a hash from an even numbered array: -%hash = <key1 value1 key2 value2>; # Or: -%hash = "key1", "value1", "key2", "value2"; - -%hash = key1 => 'value1', key2 => 'value2'; # same result as above - -## You can also use the "colon pair" syntax. This syntax is especially -## handy for named parameters that you'll see later. -%hash = :w(1), # equivalent to `w => 1` - :truey, # equivalent to `:truey(True)` or `truey => True` - :!falsey, # equivalent to `:falsey(False)` or `falsey => False` -; -## The :truey and :!falsey constructs are known as the -## `True` and `False` shortcuts respectively. - -say %hash{'key1'}; # You can use {} to get the value from a key. -say %hash<key2>; # If it's a string without spaces, you can actually use - # <> (quote-words operator). `{key1}` doesn't work, - # as Perl6 doesn't have barewords. -``` - -## Subs - -```perl6 -## Subroutines, or functions as most other languages call them, are -## created with the `sub` keyword. -sub say-hello { say "Hello, world" } - -## You can provide (typed) arguments. If specified, the type will be checked -## at compile-time if possible, otherwise at runtime. -sub say-hello-to( Str $name ) { - say "Hello, $name !"; -} - -## A sub returns the last value of the block. Similarly, the semicolon in -## the last can be omitted. -sub return-value { 5 } -say return-value; # prints 5 - -sub return-empty { } -say return-empty; # prints Nil - -## Some control flow structures produce a value, like `if`: -sub return-if { - if True { "Truthy" } -} -say return-if; # prints Truthy - -## Some don't, like `for`: -sub return-for { - for 1, 2, 3 { 'Hi' } -} -say return-for; # prints Nil - -## Positional arguments are required by default. To make them optional, use -## the `?` after the parameters' names. -sub with-optional( $arg? ) { - # This sub returns `(Any)` (Perl's null-like value) if - # no argument is passed. Otherwise, it returns its argument. - $arg; -} -with-optional; # returns Any -with-optional(); # returns Any -with-optional(1); # returns 1 - -## You can also give them a default value when they're not passed. -## Required parameters must come before optional ones. -sub greeting( $name, $type = "Hello" ) { - say "$type, $name!"; -} - -greeting("Althea"); #=> Hello, Althea! -greeting("Arthur", "Good morning"); #=> Good morning, Arthur! - -## You can also, by using a syntax akin to the one of hashes -## (yay unified syntax !), pass *named* arguments to a `sub`. They're -## optional, and will default to "Any". -sub with-named( $normal-arg, :$named ) { - say $normal-arg + $named; -} -with-named(1, named => 6); #=> 7 - -## There's one gotcha to be aware of, here: If you quote your key, Perl 6 -## won't be able to see it at compile time, and you'll have a single `Pair` -## object as a positional parameter, which means -## `with-named(1, 'named' => 6);` fails. - -with-named(2, :named(5)); #=> 7 - -## To make a named argument mandatory, you can append `!` to the parameter, -## which is the inverse of `?`: -sub with-mandatory-named( :$str! ) { - say "$str!"; -} -with-mandatory-named(str => "My String"); #=> My String! -with-mandatory-named; # runtime error:"Required named parameter not passed" -with-mandatory-named(3);# runtime error:"Too many positional parameters passed" - -## If a sub takes a named boolean argument... -sub takes-a-bool( $name, :$bool ) { - say "$name takes $bool"; -} -## ... you can use the same "short boolean" hash syntax: -takes-a-bool('config', :bool); #=> config takes True -takes-a-bool('config', :!bool); #=> config takes False - -## You can also provide your named arguments with default values: -sub named-def( :$def = 5 ) { - say $def; -} -named-def; #=> 5 -named-def(def => 15); #=> 15 - -## Since you can omit parenthesis to call a function with no arguments, -## you need `&` in the name to store `say-hello` in a variable. This means -## `&say-hello` is a code object and not a subroutine call. -my &s = &say-hello; -my &other-s = sub { say "Anonymous function!" } - -## A sub can have a "slurpy" parameter, or "doesn't-matter-how-many". For -## this, you must use `*@` (slurpy) which will "take everything else". You can -## have as many parameters *before* a slurpy one, but not *after*. -sub as-many($head, *@rest) { - say @rest.join(' / ') ~ " !"; -} -say as-many('Happy', 'Happy', 'Birthday');#=> Happy / Birthday ! - # Note that the splat (the *) did not - # consume the parameter before it. - -## You can call a function with an array using the "argument list flattening" -## operator `|` (it's not actually the only role of this operator, -## but it's one of them). -sub concat3($a, $b, $c) { - say "$a, $b, $c"; -} -concat3(|@array); #=> a, b, c - # `@array` got "flattened" as a part of the argument list -``` - -## Containers - -```perl6 -## In Perl 6, values are actually stored in "containers". The assignment -## operator asks the container on the left to store the value on its right. -## When passed around, containers are marked as immutable which means that, -## in a function, you'll get an error if you try to mutate one of your -## arguments. If you really need to, you can ask for a mutable container by -## using the `is rw` trait: -sub mutate( $n is rw ) { - $n++; # postfix ++ operator increments its argument but returns its old value -} - -my $m = 42; -mutate $m; # the value is incremented but the old value is returned - #=> 42 -say $m; #=> 43 - -## This works because we are passing the container $m to the `mutate` sub. -## If we try to just pass a number instead of passing a variable it won't work -## because there is no container being passed and integers are immutable by -## themselves: - -mutate 42; # Parameter '$n' expected a writable container, but got Int value - -## Similar error would be obtained, if a bound variable is passed to -## to the subroutine: - -my $v := 50; # binding 50 to the variable $v -mutate $v; # Parameter '$n' expected a writable container, but got Int value - -## If what you want is a copy instead, use the `is copy` trait which will -## cause the argument to be copied and allow you to modify the argument -## inside the routine. - -## A sub itself returns a container, which means it can be marked as rw: -my $x = 42; -sub x-store() is rw { $x } -x-store() = 52; # in this case, the parentheses are mandatory - # (else Perl 6 thinks `x-store` is an identifier) -say $x; #=> 52 -``` - -## Control Flow Structures - -### Conditionals - -```perl6 -## - `if` -## Before talking about `if`, we need to know which values are "Truthy" -## (represent True), and which are "Falsey" (represent False). Only these -## values are Falsey: 0, (), {}, "", Nil, A type (like `Str` or `Int`) and -## of course False itself. Any other value is Truthy. -if True { - say "It's true!"; -} - -unless False { - say "It's not false!"; -} - -## As you can see, you don't need parentheses around conditions. However, you -## do need the curly braces around the "body" block. For example, -## `if (true) say;` doesn't work. - -## You can also use their statement modifier (postfix) versions: -say "Quite truthy" if True; #=> Quite truthy -say "Quite falsey" unless False; #=> Quite falsey - -## - Ternary operator, "x ?? y !! z" -## This returns $value-if-true if the condition is true and $value-if-false -## if it is false. -## my $result = condition ?? $value-if-true !! $value-if-false; - -my $age = 30; -say $age > 18 ?? "You are an adult" !! "You are under 18"; -#=> You are an adult -``` - -### given/when, or Perl 6's switch construct - -```perl6 -## `given...when` looks like other languages' `switch`, but is much more -## powerful thanks to smart matching and Perl 6's "topic variable", $_. -## -## The topic variable $_ contains the default argument of a block, a loop's -## current iteration (unless explicitly named), etc. -## -## `given` simply puts its argument into `$_` (like a block would do), -## and `when` compares it using the "smart matching" (`~~`) operator. -## -## Since other Perl 6 constructs use this variable (as said before, like `for`, -## blocks, etc), this means the powerful `when` is not only applicable along -## with a `given`, but instead anywhere a `$_` exists. - -given "foo bar" { - say $_; #=> foo bar - when /foo/ { # Don't worry about smart matching yet. Just know - say "Yay !"; # `when` uses it. This is equivalent to `if $_ ~~ /foo/`. - - } - when $_.chars > 50 { # smart matching anything with True is True, - # i.e. (`$a ~~ True`) - # so you can also put "normal" conditionals. - # This `when` is equivalent to this `if`: - # `if $_ ~~ ($_.chars > 50) {...}` - # which means: `if $_.chars > 50 {...}` - say "Quite a long string !"; - } - default { # same as `when *` (using the Whatever Star) - say "Something else" - } -} -``` - -### Looping constructs - -```perl6 -## - `loop` is an infinite loop if you don't pass it arguments, but can also -## be a C-style `for` loop: -loop { - say "This is an infinite loop !"; - last; # last breaks out of the loop, like - # the `break` keyword in other languages -} - -loop (my $i = 0; $i < 5; $i++) { - next if $i == 3; # `next` skips to the next iteration, like `continue` - # in other languages. Note that you can also use postfix - # conditionals, loops, etc. - say "This is a C-style for loop!"; -} - -## - `for` - Iterating through an array - -my @array = 1, 2, 6, 7, 3; - -## Accessing the array's elements with the topic variable $_. -for @array { - say "I've got $_ !"; -} - -## Accessing the array's elements with a "pointy block", `->`. -## Here each element is read-only. -for @array -> $variable { - say "I've got $variable !"; -} - -## Accessing the array's elements with a "doubly pointy block", `<->`. -## Here each element is read-write so mutating `$variable` mutates -## that element in the array. -for @array <-> $variable { - say "I've got $variable !"; -} - -## As we saw with given, a for loop's default "current iteration" variable -## is `$_`. That means you can use `when` in a `for`loop just like you were -## able to in a `given`. -for @array { - say "I've got $_"; - - .say; # This is also allowed. A dot call with no "topic" (receiver) - # is sent to `$_` by default - $_.say; # This is equivalent to the above statement. -} - -for @array { - # You can... - next if $_ == 3; # Skip to the next iteration (`continue` in C-like lang.) - redo if $_ == 4; # Re-do iteration, keeping the same topic variable (`$_`) - last if $_ == 5; # Or break out of loop (like `break` in C-like lang.) -} - -## The "pointy block" syntax isn't specific to the `for` loop. It's just a way -## to express a block in Perl 6. -sub long-computation { "Finding factors of large primes" } -if long-computation() -> $result { - say "The result is $result."; -} -``` - -## Operators - -```perl6 -## Since Perl languages are very much operator-based languages, Perl 6 -## operators are actually just funny-looking subroutines, in syntactic -## categories, like infix:<+> (addition) or prefix:<!> (bool not). - -## The categories are: -## - "prefix": before (like `!` in `!True`). -## - "postfix": after (like `++` in `$a++`). -## - "infix": in between (like `*` in `4 * 3`). -## - "circumfix": around (like `[`-`]` in `[1, 2]`). -## - "post-circumfix": around, after another term (like `{`-`}` in -## `%hash{'key'}`) - -## The associativity and precedence list are explained below. - -## Alright, you're set to go! - -## Equality Checking -##------------------ - -## - `==` is numeric comparison -3 == 4; #=> False -3 != 4; #=> True - -## - `eq` is string comparison -'a' eq 'b'; #=> False -'a' ne 'b'; #=> True, not equal -'a' !eq 'b'; #=> True, same as above - -## - `eqv` is canonical equivalence (or "deep equality") -(1, 2) eqv (1, 3); #=> False -(1, 2) eqv (1, 2); #=> True -Int === Int #=> True - -## - `~~` is the smart match operator -## Aliases the left hand side to $_ and then evaluates the right hand side. -## Here are some common comparison semantics: - -## String or numeric equality -'Foo' ~~ 'Foo'; # True if strings are equal. -12.5 ~~ 12.50; # True if numbers are equal. - -## Regex - For matching a regular expression against the left side. -## Returns a `Match` object, which evaluates as True if regexp matches. - -my $obj = 'abc' ~~ /a/; -say $obj; #=> 「a」 -say $obj.WHAT; #=> (Match) - -## Hashes -'key' ~~ %hash; # True if key exists in hash. - -## Type - Checks if left side "is of type" (can check superclasses and -## roles). -say 1 ~~ Int; #=> True - -## Smart-matching against a boolean always returns that boolean -## (and will warn). -say 1 ~~ True; #=> True -say False ~~ True; #=> True - -## General syntax is `$arg ~~ &bool-returning-function;`. For a complete list -## of combinations, use this table: -## http://perlcabal.org/syn/S03.html#Smart_matching - -## Of course, you also use `<`, `<=`, `>`, `>=` for numeric comparison. -## Their string equivalent are also available: `lt`, `le`, `gt`, `ge`. -3 > 4; # False -3 >= 4; # False -3 < 4; # True -3 <= 4; # True -'a' gt 'b'; # False -'a' ge 'b'; # False -'a' lt 'b'; # True -'a' le 'b'; # True - - -## Range constructor -##------------------ -3 .. 7; # 3 to 7, both included. -3 ..^ 7; # 3 to 7, exclude right endpoint. -3 ^.. 7; # 3 to 7, exclude left endpoint. -3 ^..^ 7; # 3 to 7, exclude both endpoints. - # 3 ^.. 7 almost like 4 .. 7 when we only consider integers. - # But when we consider decimals : -3.5 ~~ 4 .. 7; # False -3.5 ~~ 3 ^.. 7; # True, This Range also contains decimals greater than 3. - # We describe it like this in some math books: 3.5 ∈ (3,7] - # If you don’t want to understand the concept of interval - # for the time being. At least we should know: -3 ^.. 7 ~~ 4 .. 7; # False - - -## This also works as a shortcut for `0..^N`: -^10; # means 0..^10 - -## This also allows us to demonstrate that Perl 6 has lazy/infinite arrays, -## using the Whatever Star: -my @array = 1..*; # 1 to Infinite! Equivalent to `1..Inf`. -say @array[^10]; # You can pass ranges as subscripts and it'll return - # an array of results. This will print - # "1 2 3 4 5 6 7 8 9 10" (and not run out of memory!) - -## Note: when reading an infinite list, Perl 6 will "reify" the elements -## it needs, then keep them in memory. They won't be calculated more than once. -## It also will never calculate more elements that are needed. - -## An array subscript can also be a closure. It'll be called with the length -## as the argument: -say join(' ', @array[15..*]); #=> 15 16 17 18 19 -## which is equivalent to: -say join(' ', @array[-> $n { 15..$n }]); - -## Note: if you try to do either of those with an infinite array, -## you'll trigger an infinite loop (your program won't finish). - -## You can use that in most places you'd expect, even when assigning to -## an array: -my @numbers = ^20; - -## Here the numbers increase by 6, like an arithmetic sequence; more on the -## sequence (`...`) operator later. -my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; -@numbers[5..*] = 3, 9 ... *; # even though the sequence is infinite, - # only the 15 needed values will be calculated. -say @numbers; #=> 0 1 2 3 4 3 9 15 21 [...] 81 87 - # (only 20 values) - -## and (&&), or (||) -##------------------ -3 && 4; # 4, which is Truthy. Calls `.Bool` on both 3 and 4 and gets `True` - # so it returns 4 since both are `True`. -3 && 0; # 0 -0 && 4; # 0 - -0 || False; # False. Calls `.Bool` on `0` and `False` which are both `False` - # so it retusns `False` since both are `False`. - -## Short-circuit (and tight) versions of the above -## Return the first argument that evaluates to False, or the last argument. - -my ( $a, $b, $c ) = 1, 0, 2; -$a && $b && $c; # Returns 0, the first False value - -## || Returns the first argument that evaluates to True -$b || $a; # 1 - -## And because you're going to want them, you also have compound assignment -## operators: -$a *= 2; # multiply and assignment. Equivalent to $a = $a * 2; -$b %%= 5; # divisible by and assignment. Equivalent to $b = $b %% 2; -$c div= 3; # return divisor and assignment. Equivalent to $c = $c div 3; -$d mod= 4; # return remainder and assignment. Equivalent to $d = $d mod 4; -@array .= sort; # calls the `sort` method and assigns the result back -``` - -## More on subs! - -```perl6 -## As we said before, Perl 6 has *really* powerful subs. We're going -## to see a few more key concepts that make them better than in any -## other language :-). -``` - -### Unpacking! - -```perl6 -## Unpacking is the ability to "extract" arrays and keys -## (AKA "destructuring"). It'll work in `my`s and in parameter lists. -my ($f, $g) = 1, 2; -say $f; #=> 1 -my ($, $, $h) = 1, 2, 3; # keep the non-interesting values anonymous (`$`) -say $h; #=> 3 - -my ($head, *@tail) = 1, 2, 3; # Yes, it's the same as with "slurpy subs" -my (*@small) = 1; - -sub unpack_array( @array [$fst, $snd] ) { - say "My first is $fst, my second is $snd! All in all, I'm @array[]."; - # (^ remember the `[]` to interpolate the array) -} -unpack_array(@tail); #=> My first is 2, my second is 3! All in all, I'm 2 3. - - -## If you're not using the array itself, you can also keep it anonymous, -## much like a scalar: -sub first-of-array( @ [$fst] ) { $fst } -first-of-array(@small); #=> 1 -first-of-array(@tail); # Error: "Too many positional parameters passed" - # (which means the array is too big). - -## You can also use a slurp... -sub slurp-in-array(@ [$fst, *@rest]) { # You could keep `*@rest` anonymous - say $fst + @rest.elems; # `.elems` returns a list's length. - # Here, `@rest` is `(3,)`, since `$fst` - # holds the `2`. -} -slurp-in-array(@tail); #=> 3 - -## You could even extract on a slurpy (but it's pretty useless ;-).) -sub fst(*@ [$fst]) { # or simply: `sub fst($fst) { ... }` - say $fst; -} -fst(1); #=> 1 -fst(1, 2); # errors with "Too many positional parameters passed" - -## You can also destructure hashes (and classes, which you'll learn about -## later). The syntax is basically the same as -## `%hash-name (:key($variable-to-store-value-in))`. -## The hash can stay anonymous if you only need the values you extracted. -sub key-of( % (:value($val), :qua($qua)) ) { - say "Got val $val, $qua times."; -} - -## Then call it with a hash. You need to keep the curly braces for it to be a -## hash or use `%()` instead to indicate a hash is being passed. -key-of({value => 'foo', qua => 1}); #=> Got val foo, 1 times. -key-of(%(value => 'foo', qua => 1)); #=> Got val foo, 1 times. -#key-of(%hash); # the same (for an equivalent `%hash`) - -## The last expression of a sub is returned automatically (though you may -## indicate explicitly by using the `return` keyword, of course): -sub next-index( $n ) { - $n + 1; -} -my $new-n = next-index(3); # $new-n is now 4 - -## This is true for everything, except for the looping constructs (due to -## performance reasons): there's no reason to build a list if we're just going to -## discard all the results. If you still want to build one, you can use the -## `do` statement prefix or the `gather` prefix, which we'll see later: - -sub list-of( $n ) { - do for ^$n { # note the range-to prefix operator `^` (`0..^N`) - $_ # current loop iteration known as the "topic" variable - } -} -my @list3 = list-of(3); #=> (0, 1, 2) -``` - -### lambdas (or anonymous subroutines) - -```perl6 -## You can create a lambda with `-> {}` ("pointy block") , -## `{}` ("block") or `sub {}`. - -my &lambda1 = -> $argument { - "The argument passed to this lambda is $argument" -} - -my &lambda2 = { - "The argument passed to this lambda is $_" -} - -my &lambda3 = sub ($argument) { - "The argument passed to this lambda is $argument" -} - -## `-> {}` and `{}` are pretty much the same thing, except that the former can -## take arguments, and that the latter can be mistaken as a hash by the parser. - -## We can, for example, add 3 to each value of an array using the -## `map` function with a lambda: -my @arrayplus3 = map({ $_ + 3 }, @array); # $_ is the implicit argument - -## A sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`): -## A block doesn't have a "function context" (though it can have arguments), -## which means that if you return from it, you're going to return from the -## parent function. Compare: -sub is-in( @array, $elem ) { - # this will `return` out of the `is-in` sub once the condition evaluated - ## to True, the loop won't be run anymore. - map({ return True if $_ == $elem }, @array); -} -## with: -sub truthy-array( @array ) { - # this will produce an array of `True` and `False`: - # (you can also say `anon sub` for "anonymous subroutine") - map(sub ($i) { if $i { return True } else { return False } }, @array); - # ^ the `return` only returns from the anonymous `sub` -} - -## The `anon` declarator can be used to create an anonymous sub from a -## regular subroutine. The regular sub knows its name but its symbol is -## prevented from getting installed in the lexical scope, the method table -## and everywhere else. - -my $anon-sum = anon sub summation(*@a) { [+] *@a } -say $anon-sum.name; #=> summation -say $anon-sum(2, 3, 5); #=> 10 -#say summation; #=> Error: Undeclared routine: ... - -## You can also use the "whatever star" to create an anonymous subroutine. -## (it'll stop at the furthest operator in the current expression) -my @arrayplus3 = map(*+3, @array); # `*+3` is the same as `{ $_ + 3 }` -my @arrayplus3 = map(*+*+3, @array); # Same as `-> $a, $b { $a + $b + 3 }` - # also `sub ($a, $b) { $a + $b + 3 }` -say (*/2)(4); #=> 2 - # Immediately execute the function Whatever created. -say ((*+3)/5)(5); #=> 1.6 - # It works even in parens! - -## But if you need to have more than one argument (`$_`) in a block (without -## wanting to resort to `-> {}`), you can also use the implicit argument -## syntax, `$^`: -map({ $^a + $^b + 3 }, @array); -# which is equivalent to the following which uses a `sub`: -map(sub ($a, $b) { $a + $b + 3 }, @array); - -## The parameters `$^a`, `$^b`, etc. are known as placeholder parameters or -## self-declared positional parameters. They're sorted lexicographically so -## `{ $^b / $^a }` is equivalent `-> $a, $b { $b / $a }`. -``` - -### About types... - -```perl6 -## Perl 6 is gradually typed. This means you can specify the type of your -## variables/arguments/return types, or you can omit the type annotations in -## in which case they'll default to `Any`. Obviously you get access to a few -## base types, like `Int` and `Str`. The constructs for declaring types are -## "subset", "class", "role", etc. which you'll see later. - -## For now, let us examine "subset" which is a "sub-type" with additional -## checks. For example, "a very big integer is an Int that's greater than 500". -## You can specify the type you're subtyping (by default, `Any`), and add -## additional checks with the `where` clause: -subset VeryBigInteger of Int where * > 500; -## Or the set of the whole numbers: -subset WholeNumber of Int where * >= 0; -``` - -### Multiple Dispatch - -```perl6 -## Perl 6 can decide which variant of a `sub` to call based on the type of the -## arguments, or on arbitrary preconditions, like with a type or `where`: - -## with types: -multi sub sayit( Int $n ) { # note the `multi` keyword here - say "Number: $n"; -} -multi sayit( Str $s ) { # a multi is a `sub` by default - say "String: $s"; -} -sayit("foo"); #=> "String: foo" -sayit(25); #=> "Number: 25" -sayit(True); # fails at *compile time* with "calling 'sayit' will never - # work with arguments of types ..." - -## with arbitrary preconditions (remember subsets?): -multi is-big(Int $n where * > 50) { "Yes!" } # using a closure -multi is-big(Int $n where {$_ > 50}) { "Yes!" } # similar to above -multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching - # (could use a regexp, etc) -multi is-big(Int $) { "No" } - -subset Even of Int where * %% 2; -multi odd-or-even(Even) { "Even" } # The main case using the type. - # We don't name the argument. -multi odd-or-even($) { "Odd" } # "everthing else" hence the $ variable - -## You can even dispatch based on the presence of positional and -## named arguments: -multi with-or-without-you($with) { - say "I wish I could but I can't"; -} -multi with-or-without-you(:$with) { - say "I can live! Actually, I can't."; -} -multi with-or-without-you { - say "Definitely can't live."; -} - -## This is very, very useful for many purposes, like `MAIN` subs (covered -## later), and even the language itself uses it in several places. -## -## - `is`, for example, is actually a `multi sub` named `trait_mod:<is>`, -## and it works off that. -## - `is rw`, is simply a dispatch to a function with this signature: -## sub trait_mod:<is>(Routine $r, :$rw!) {} -## -## (commented out because running this would be a terrible idea!) -``` - -## Scoping - -```perl6 -## In Perl 6, unlike many scripting languages, (such as Python, Ruby, PHP), -## you must declare your variables before using them. The `my` declarator -## you have learned uses "lexical scoping". There are a few other declarators, -## (`our`, `state`, ..., ) which we'll see later. This is called -## "lexical scoping", where in inner blocks, you can access variables from -## outer blocks. -my $file_scoped = 'Foo'; -sub outer { - my $outer_scoped = 'Bar'; - sub inner { - say "$file_scoped $outer_scoped"; - } - &inner; # return the function -} -outer()(); #=> 'Foo Bar' - -## As you can see, `$file_scoped` and `$outer_scoped` were captured. -## But if we were to try and use `$outer_scoped` outside the `outer` sub, -## the variable would be undefined (and you'd get a compile time error). -``` - -## Twigils - -```perl6 -## There are many special `twigils` (composed sigils) in Perl 6. Twigils -## define the variables' scope. -## The * and ? twigils work on standard variables: -## * Dynamic variable -## ? Compile-time variable -## The ! and the . twigils are used with Perl 6's objects: -## ! Attribute (instance attribute) -## . Method (not really a variable) - -## `*` twigil: Dynamic Scope -## These variables use the `*` twigil to mark dynamically-scoped variables. -## Dynamically-scoped variables are looked up through the caller, not through -## the outer scope. - -my $*dyn_scoped_1 = 1; -my $*dyn_scoped_2 = 10; - -sub say_dyn { - say "$*dyn_scoped_1 $*dyn_scoped_2"; -} - -sub call_say_dyn { - my $*dyn_scoped_1 = 25; # Defines $*dyn_scoped_1 only for this sub. - $*dyn_scoped_2 = 100; # Will change the value of the file scoped variable. - say_dyn(); #=> 25 100, $*dyn_scoped 1 and 2 will be looked - # for in the call. - # It uses the value of $*dyn_scoped_1 from inside - # this sub's lexical scope even though the blocks - # aren't nested (they're call-nested). -} -say_dyn(); #=> 1 10 -call_say_dyn(); #=> 25 100 - # Uses $*dyn_scoped_1 as defined in call_say_dyn even though - # we are calling it from outside. -say_dyn(); #=> 1 100 We changed the value of $*dyn_scoped_2 in - # call_say_dyn so now its value has changed. -``` - -## Object Model - -```perl6 -## To call a method on an object, add a dot followed by the method name: -## `$object.method` - -## Classes are declared with the `class` keyword. Attributes are declared -## with the `has` keyword, and methods declared with the `method` keyword. - -## Every attribute that is private uses the ! twigil. For example: `$!attr`. -## Immutable public attributes use the `.` twigil which creates a read-only -## method named after the attribute. In fact, declaring an attribute with `.` -## is equivalent to declaring the same attribute with `!` and then creating -## a read-only method with the attribute's name. However, this is done for us -## by Perl 6 automatically. The easiest way to remember the `$.` twigil is -## by comparing it to how methods are called. - -## Perl 6's object model ("SixModel") is very flexible, and allows you to -## dynamically add methods, change semantics, etc... Unfortunately, these will -## not all be covered here, and you should refer to: -## https://docs.perl6.org/language/objects.html. - -class Human { - has Str $.name; # `$.name` is immutable but with an accessor method. - has Str $.bcountry; # Use `$!bcountry` to modify it inside the class. - has Str $.ccountry is rw; # This attribute can be modified from outside. - has Int $!age = 0; # A private attribute with default value. - - method birthday { - $!age += 1; # Add a year to human's age - } - - method get-age { - return $!age; - } - - # This method is private to the class. Note the `!` before the - # method's name. - method !do-decoration { - return "$!name was born in $!bcountry and now lives in $!ccountry." - } - - # This method is public, just like `birthday` and `get-age`. - method get-info { - self.do-decoration; # Invoking a method on `self` inside the class. - # Use `self!priv-method` for private method. - # Use `self.publ-method` for public method. - } -}; - -## Create a new instance of Human class. -## Note: you can't set private-attribute from here (more later on). -my $person1 = Human.new( - name => "Jord", - bcountry = "Togo", - ccountry => "Togo" -); - -say $person1.name; #=> Jord -say $person1.bcountry; #=> Togo -say $person1.ccountry; #=> Togo - - -# $person1.bcountry = "Mali"; # This fails, because the `has $.bcountry` - # is immutable. Jord can't change his birthplace. -$person1.ccountry = "France"; # This works because the `$.ccountry` is mutable - # (`is rw`). Now Jord's current country is France. - -# Calling methods on the instance objects. -$person1.birthday; #=> 1 -$person1.get-info; #=> Jord was born in Togo and now lives in France. -$person1.do-decoration; # This fails since the method `do-decoration` is - # private. -``` - -### Object Inheritance - -```perl6 -## Perl 6 also has inheritance (along with multiple inheritance). While -## methods are inherited, submethods are not. Submethods are useful for -## object construction and destruction tasks, such as BUILD, or methods that -## must be overridden by subtypes. We will learn about BUILD later on. - -class Parent { - has $.age; - has $.name; - - # This submethod won't be inherited by the Child class. - submethod favorite-color { - say "My favorite color is Blue"; - } - - # This method is inherited - method talk { say "Hi, my name is $!name" } -} - -# Inheritance uses the `is` keyword -class Child is Parent { - method talk { say "Goo goo ga ga" } - # This shadows Parent's `talk` method. - # This child hasn't learned to speak yet! -} - -my Parent $Richard .= new(age => 40, name => 'Richard'); -$Richard.favorite-color; #=> "My favorite color is Blue" -$Richard.talk; #=> "Hi, my name is Richard" -## $Richard is able to access the submethod and he knows how to say his name. - -my Child $Madison .= new(age => 1, name => 'Madison'); -$Madison.talk; #=> "Goo goo ga ga", due to the overridden method. -# $Madison.favorite-color # does not work since it is not inherited. - -## When you use `my T $var`, `$var` starts off with `T` itself in it, -## so you can call `new` on it. -## (`.=` is just the dot-call and the assignment operator: -## `$a .= b` is the same as `$a = $a.b`) -## Also note that `BUILD` (the method called inside `new`) -## will set parent's properties too, so you can pass `val => 5`. -``` - -### Roles, or Mixins - -```perl6 -## Roles are supported too (which are called Mixins in other languages) -role PrintableVal { - has $!counter = 0; - method print { - say $.val; - } -} - -## you "apply" a role (or mixin) with `does` keyword: -class Item does PrintableVal { - has $.val; - - ## When `does`-ed, a `role` literally "mixes in" the class: - ## the methods and attributes are put together, which means a class - ## can access the private attributes/methods of its roles (but - ## not the inverse!): - method access { - say $!counter++; - } - - ## However, this: - ## method print {} - ## is ONLY valid when `print` isn't a `multi` with the same dispatch. - ## (this means a parent class can shadow a child class's `multi print() {}`, - ## but it's an error if a role does) - - ## NOTE: You can use a role as a class (with `is ROLE`). In this case, - ## methods will be shadowed, since the compiler will consider `ROLE` - ## to be a class. -} -``` - -## Exceptions - -```perl6 -## Exceptions are built on top of classes, in the package `X` (like `X::IO`). -## In Perl6 exceptions are automatically 'thrown': -open 'foo'; #=> Failed to open file foo: no such file or directory -## It will also print out what line the error was thrown at -## and other error info. - -## You can throw an exception using `die`: -die 'Error!'; #=> Error! - -## Or more explicitly: -X::AdHoc.new(payload => 'Error!').throw; #=> Error! - -## In Perl 6, `orelse` is similar to the `or` operator, except it only matches -## undefined variables instead of anything evaluating as `False`. -## Undefined values include: `Nil`, `Mu` and `Failure` as well as `Int`, `Str` -## and other types that have not been initialized to any value yet. -## You can check if something is defined or not using the defined method: -my $uninitialized; -say $uninitiazilzed.defined; #=> False - -## When using `orelse` it will disarm the exception and alias $_ to that -## failure. This will prevent it to being automatically handled and printing -## lots of scary error messages to the screen. We can use the `exception` -## method on the `$_` variable to access the exception -open 'foo' orelse say "Something happened {.exception}"; - -## This also works: -open 'foo' orelse say "Something happened $_"; #=> Something happened - #=> Failed to open file foo: no such file or directory -## Both of those above work but in case we get an object from the left side -## that is not a failure we will probably get a warning. We see below how we -## can use try` and `CATCH` to be more specific with the exceptions we catch. -``` - -### Using `try` and `CATCH` - -```perl6 -## By using `try` and `CATCH` you can contain and handle exceptions without -## disrupting the rest of the program. The `try` block will set the last -## exception to the special variable `$!` (known as the error variable). -## Note: This has no relation to $!variables seen inside class definitions. - -try open 'foo'; -say "Well, I tried! $!" if defined $!; -#=> Well, I tried! Failed to open file foo: no such file or directory - -## Now, what if we want more control over handling the exception? -## Unlike many other languages, in Perl 6, you put the `CATCH` block *within* -## the block to `try`. Similar to how the `$_` variable was set when we -## 'disarmed' the exception with `orelse`, we also use `$_` in the CATCH block. -## Note: The `$!` variable is only set *after* the `try` block has caught an -## exception. By default, a `try` block has a `CATCH` block of its own that -## catches any exception (`CATCH { default {} }`). - -try { - my $a = (0 %% 0); - CATCH { - say "Something happened: $_" - } -} -#=> Something happened: Attempt to divide by zero using infix:<%%> - -## You can redefine it using `when`s (and `default`) to handle the exceptions -## you want to catch explicitly: - -try { - open 'foo'; - CATCH { - # In the `CATCH` block, the exception is set to the $_ variable. - when X::AdHoc { - say "Error: $_" - } - when X::Numeric::DivideByZero { - say "Error: $_"; - } - ## Any other exceptions will be re-raised, since we don't have a `default`. - ## Basically, if a `when` matches (or there's a `default`), the - ## exception is marked as "handled" so as to prevent its re-throw - ## from the `CATCH` block. You still can re-throw the exception (see below) - ## by hand. - } -} -#=>Error: Failed to open file /dir/foo: no such file or directory - -## There are also some subtleties to exceptions. Some Perl 6 subs return a -## `Failure`, which is a wrapper around an `Exception` object which is -## "unthrown". They're not thrown until you try to use the variables containing -## them unless you call `.Bool`/`.defined` on them - then they're handled. -## (the `.handled` method is `rw`, so you can mark it as `False` back yourself) -## You can throw a `Failure` using `fail`. Note that if the pragma `use fatal` -## is on, `fail` will throw an exception (like `die`). - -fail "foo"; # We're not trying to access the value, so no problem. -try { - fail "foo"; - CATCH { - default { - say "It threw because we tried to get the fail's value!" - } - } -} - -## There is also another kind of exception: Control exceptions. -## Those are "good" exceptions, which happen when you change your program's -## flow, using operators like `return`, `next` or `last`. -## You can "catch" those with `CONTROL` (not 100% working in Rakudo yet). -``` - -## Packages - -```perl6 -## Packages are a way to reuse code. Packages are like "namespaces", and any -## element of the six model (`module`, `role`, `class`, `grammar`, `subset` and -## `enum`) are actually packages. (Packages are the lowest common denominator) -## Packages are important - especially as Perl is well-known for CPAN, -## the Comprehensive Perl Archive Network. - -## You can use a module (bring its declarations into scope) with -## the `use` keyword: -use JSON::Tiny; # if you installed Rakudo* or Panda, you'll have this module -say from-json('[1]').perl; #=> [1] - -## You should not declare packages using the `package` keyword (unlike Perl 5). -## Instead, use `class Package::Name::Here;` to declare a class, or if you only -## want to export variables/subs, you can use `module` instead. - -module Hello::World { # bracketed form - # If `Hello` doesn't exist yet, it'll just be a "stub", - # that can be redeclared as something else later. - - # ... declarations here ... -} - -unit module Parse::Text; # file-scoped form which extends until - # the end of the file - -grammar Parse::Text::Grammar { - # A grammar is a package, which you could `use`. - # You will learn more about grammars in the regex section -} - -## As said before, any part of the six model is also a package. -## Since `JSON::Tiny` uses its own `JSON::Tiny::Actions` class, you can use it: -my $actions = JSON::Tiny::Actions.new; - -## We'll see how to export variables and subs in the next part. -``` - -## Declarators - -```perl6 -## In Perl 6, you get different behaviors based on how you declare a variable. -## You've already seen `my` and `has`, we'll now explore the others. - -## `our` - these declarations happen at `INIT` time -- (see "Phasers" below). -## It's like `my`, but it also creates a package variable. All packagish -## things such as `class`, `role`, etc. are `our` by default. - -module Var::Increment { - our $our-var = 1; # Note: `our`-declared variables cannot be typed. - my $my-var = 22; - - our sub Inc { - our sub available { # If you try to make inner `sub`s `our`... - # ... Better know what you're doing (Don't !). - say "Don't do that. Seriously. You'll get burned."; - } - - my sub unavailable { # `sub`s are `my`-declared by default - say "Can't access me from outside, I'm 'my'!"; - } - say ++$our-var; # Increment the package variable and output its value - } - -} - -say $Var::Increment::our-var; #=> 1, this works! -say $Var::Increment::my-var; #=> (Any), this will not work! - -Var::Increment::Inc; #=> 2 -Var::Increment::Inc; #=> 3 , notice how the value of $our-var was - # retained. -Var::Increment::unavailable; #=> Could not find symbol '&unavailable' - -## `constant` - these declarations happen at `BEGIN` time. You can use -## the `constant` keyword to declare a compile-time variable/symbol: -constant Pi = 3.14; -constant $var = 1; - -## And if you're wondering, yes, it can also contain infinite lists. -constant why-not = 5, 15 ... *; -say why-not[^5]; #=> 5 15 25 35 45 - -## `state` - these declarations happen at run time, but only once. State -## variables are only initialized one time. In other languages such as C -## they exist as `static` variables. -sub fixed-rand { - state $val = rand; - say $val; -} -fixed-rand for ^10; # will print the same number 10 times - -## Note, however, that they exist separately in different enclosing contexts. -## If you declare a function with a `state` within a loop, it'll re-create the -## variable for each iteration of the loop. See: -for ^5 -> $a { - sub foo { - state $val = rand; # This will be a different value for - # every value of `$a` - } - for ^5 -> $b { - say foo; # This will print the same value 5 times, - # but only 5. Next iteration will re-run `rand`. - } -} -``` - -## Phasers - -```perl6 -## Phasers in Perl 6 are blocks that happen at determined points of time in -## your program. They are called phasers because they mark a change in the -## phase of a program. For example, when the program is compiled, a for loop -## runs, you leave a block, or an exception gets thrown (The `CATCH` block is -## actually a phaser!). Some of them can be used for their return values, -## some of them can't (those that can have a "[*]" in the beginning of their -## explanation text). Let's have a look! - -## Compile-time phasers -BEGIN { say "[*] Runs at compile time, as soon as possible, only once" } -CHECK { say "[*] Runs at compile time, as late as possible, only once" } - -## Run-time phasers -INIT { say "[*] Runs at run time, as soon as possible, only once" } -END { say "Runs at run time, as late as possible, only once" } - -## Block phasers -ENTER { say "[*] Runs everytime you enter a block, repeats on loop blocks" } -LEAVE { - say "Runs everytime you leave a block, even when an exception - happened. Repeats on loop blocks." -} - -PRE { - say "Asserts a precondition at every block entry, - before ENTER (especially useful for loops)"; - say "If this block doesn't return a truthy value, - an exception of type X::Phaser::PrePost is thrown."; -} - -## Example: -for 0..2 { - PRE { $_ > 1 } # This is going to blow up with "Precondition failed" -} - -POST { - say "Asserts a postcondition at every block exit, - after LEAVE (especially useful for loops)"; - say "If this block doesn't return a truthy value, - an exception of type X::Phaser::PrePost is thrown, like PRE."; -} - -for 0..2 { - POST { $_ < 2 } # This is going to blow up with "Postcondition failed" -} - -## Block/exceptions phasers -sub { - KEEP { say "Runs when you exit a block successfully - (without throwing an exception)" } - UNDO { say "Runs when you exit a block unsuccessfully - (by throwing an exception)" } -} - -## Loop phasers -for ^5 { - FIRST { say "[*] The first time the loop is run, before ENTER" } - NEXT { say "At loop continuation time, before LEAVE" } - LAST { say "At loop termination time, after LEAVE" } -} - -## Role/class phasers -COMPOSE { "When a role is composed into a class. /!\ NOT YET IMPLEMENTED" } - -## They allow for cute tricks or clever code...: -say "This code took " ~ (time - CHECK time) ~ "s to compile"; - -## ... or clever organization: -sub do-db-stuff { - $db.start-transaction; # start a new transaction - KEEP $db.commit; # commit the transaction if all went well - UNDO $db.rollback; # or rollback if all hell broke loose -} -``` - -## Statement prefixes - -```perl6 -## Those act a bit like phasers: they affect the behavior of the following -## code. Though, they run in-line with the executable code, so they're in -## lowercase. (`try` and `start` are theoretically in that list, but explained -## elsewhere) Note: all of these (except start) don't need explicit curly -## braces `{` and `}`. - -## `do` - (which you already saw) runs a block or a statement as a term. -## Normally you cannot use a statement as a value (or "term"). `do` helps us -## do it. - -# my $value = if True { 1 } # this fails since `if` is a statement -my $a = do if True { 5 } # with `do`, `if` is now a term returning a value - -## `once` - makes sure a piece of code only runs once. -for ^5 { - once say 1 -}; #=> 1, only prints ... once - -## Similar to `state`, they're cloned per-scope. -for ^5 { - sub { once say 1 }() -}; #=> 1 1 1 1 1, prints once per lexical scope. - -## `gather` - co-routine thread. The `gather` constructs allows us to `take` -## several values from an array/list, much like `do`. -say gather for ^5 { - take $_ * 3 - 1; - take $_ * 3 + 1; -} -#=> -1 1 2 4 5 7 8 10 11 13 - -say join ',', gather if False { - take 1; - take 2; - take 3; -} -# Doesn't print anything. - -## `eager` - evaluates a statement eagerly (forces eager context) -## Don't try this at home: -# eager 1..*; # this will probably hang for a while (and might crash ...). -## But consider: -constant thrice = gather for ^3 { say take $_ }; # Doesn't print anything -## versus: -constant thrice = eager gather for ^3 { say take $_ }; #=> 0 1 2 -``` - -## Iterables - -```perl6 -## Iterables are objects that can be iterated over which are -## are similar to the `for` construct. - -## `flat` - flattens iterables. -say (1, 10, (20, 10) ); #=> (1 10 (20 10)), notice how neste lists are - # preserved -say (1, 10, (20, 10) ).flat; #=> (1 10 20 10), now the iterable is flat - -## - `lazy` - defers actual evaluation until value is fetched by forcing -## lazy context. -my @lazy-array = (1..100).lazy; -say @lazy-array.is-lazy; #=> True, check for laziness with the `is-lazy` method. -say @lazy-array; #=> [...] List has not been iterated on! -my @lazy-array { .print }; # This works and will only do as much work as - # is needed. - -# ( **TODO** explain that gather/take and map are all lazy) - -## `sink` - an `eager` that discards the results by forcing sink context. -constant nilthingie = sink for ^3 { .say } #=> 0 1 2 -say nilthingie.perl; #=> Nil - -## `quietly` - suppresses warnings in blocks. -quietly { warn 'This is a warning!' }; #=> No output - -## `contend` - attempts side effects under STM -## Not yet implemented! -``` - -## More operators thingies! - -```perl6 -## Everybody loves operators! Let's get more of them. - -## The precedence list can be found here: -## https://docs.perl6.org/language/operators#Operator_Precedence -## But first, we need a little explanation about associativity: - -## Binary operators: -$a ! $b ! $c; # with a left-associative `!`, this is `($a ! $b) ! $c` -$a ! $b ! $c; # with a right-associative `!`, this is `$a ! ($b ! $c)` -$a ! $b ! $c; # with a non-associative `!`, this is illegal -$a ! $b ! $c; # with a chain-associative `!`, this is `($a ! $b) and ($b ! $c)` -$a ! $b ! $c; # with a list-associative `!`, this is `infix:<>` - -## Unary operators: -!$a! # with left-associative `!`, this is `(!$a)!` -!$a! # with right-associative `!`, this is `!($a!)` -!$a! # with non-associative `!`, this is illegal -``` - -### Create your own operators! - -```perl6 -## Okay, you've been reading all of that, so you might want to try something -## more exciting?! I'll tell you a little secret (or not-so-secret): -## In Perl 6, all operators are actually just funny-looking subroutines. - -## You can declare an operator just like you declare a sub: -# prefix refers to the operator categories (prefix, infix, postfix, etc). -sub prefix:<win>( $winner ) { - say "$winner Won!"; -} -win "The King"; #=> The King Won! - # (prefix means 'before') - -## you can still call the sub with its "full name": -say prefix:<!>(True); #=> False -prefix:<win>("The Queen"); #=> The Queen Won! - -sub postfix:<!>( Int $n ) { - [*] 2..$n; # using the reduce meta-operator... See below ;-)! -} -say 5!; #=> 120 - # Postfix operators ('after') have to come *directly* after the term. - # No whitespace. You can use parentheses to disambiguate, i.e. `(5!)!` - -sub infix:<times>( Int $n, Block $r ) { # infix ('between') - for ^$n { - $r(); # You need the explicit parentheses to call the function in `$r`, - # else you'd be referring at the variable itself, like with `&r`. - } -} -3 times -> { say "hello" }; #=> hello - #=> hello - #=> hello -## It's recommended to put spaces around your -## infix operator calls. - -## For circumfix and post-circumfix ones -sub circumfix:<[ ]>( Int $n ) { - $n ** $n -} -say [5]; #=> 3125 - # circumfix means 'around'. Again, no whitespace. - -sub postcircumfix:<{ }>( Str $s, Int $idx ) { - ## post-circumfix is 'after a term, around something' - $s.substr($idx, 1); -} -say "abc"{1}; #=> b - # after the term `"abc"`, and around the index (1) - -## This really means a lot -- because everything in Perl 6 uses this. -## For example, to delete a key from a hash, you use the `:delete` adverb -## (a simple named argument underneath): -%h{$key}:delete; -## equivalent to: -postcircumfix:<{ }>( %h, $key, :delete ); # (you can call operators like this) - -## It's *all* using the same building blocks! Syntactic categories -## (prefix infix ...), named arguments (adverbs), ..., etc. used to build -## the language - are available to you. Obviously, you're advised against -## making an operator out of *everything* -- with great power comes great -## responsibility. -``` - -### Meta operators! - -```perl6 -## Oh boy, get ready!. Get ready, because we're delving deep into the rabbit's -## hole, and you probably won't want to go back to other languages after -## reading this. (I'm guessing you don't want to go back at this point but -## let's continue, for the journey is long and enjoyable!). - -## Meta-operators, as their name suggests, are *composed* operators. -## Basically, they're operators that act on another operators. - -## The reduce meta-operator is a prefix meta-operator that takes a binary -## function and one or many lists. If it doesn't get passed any argument, -## it either returns a "default value" for this operator (a meaningless value) -## or `Any` if there's none (examples below). Otherwise, it pops an element -## from the list(s) one at a time, and applies the binary function to the last -## result (or the list's first element) and the popped element. - -## To sum a list, you could use the reduce meta-operator with `+`, i.e.: -say [+] 1, 2, 3; #=> 6, equivalent to (1+2)+3. - -## To multiply a list -say [*] 1..5; #=> 120, equivalent to ((((1*2)*3)*4)*5). - -## You can reduce with any operator, not just with mathematical ones. -## For example, you could reduce with `//` to get first defined element -## of a list: -say [//] Nil, Any, False, 1, 5; #=> False - # (Falsey, but still defined) -## Or with relational operators, i.e., `>` to check elements of a list -## are ordered accordingly: -say say [>] 234, 156, 6, 3, -20; #=> True - -## Default value examples: -say [*] (); #=> 1 -say [+] (); #=> 0 - # meaningless values, since N*1=N and N+0=N. -say [//]; #=> (Any) - # There's no "default value" for `//`. - -## You can also call it with a function you made up, using double brackets: -sub add($a, $b) { $a + $b } -say [[&add]] 1, 2, 3; #=> 6 - -## The zip meta-operator is an infix meta-operator that also can be used as a -## "normal" operator. It takes an optional binary function (by default, it -## just creates a pair), and will pop one value off of each array and call -## its binary function on these until it runs out of elements. It returns an -## array with all of these new elements. -say (1, 2) Z (3, 4); #=> ((1, 3), (2, 4)), since by default the function - # makes an array. -say 1..3 Z+ 4..6; #=> (5, 7, 9), using the custom infix:<+> function - -## Since `Z` is list-associative (see the list above), -## you can use it on more than one list -(True, False) Z|| (False, False) Z|| (False, False); # (True, False) - -## And, as it turns out, you can also use the reduce meta-operator with it: -[Z||] (True, False), (False, False), (False, False); # (True, False) - - -## And to end the operator list: - -## The sequence operator is one of Perl 6's most powerful features: -## it's composed of first, on the left, the list you want Perl 6 to deduce from -## (and might include a closure), and on the right, a value or the predicate -## that says when to stop (or a Whatever Star for a lazy infinite list). - -my @list = 1, 2, 3...10; # basic arithmetic sequence -# my @list = 1, 3, 6...10; # this dies because Perl 6 can't figure out the end -my @list = 1, 2, 3...^10; # as with ranges, you can exclude the last element - # (the iteration ends when the predicate matches). -my @list = 1, 3, 9...* > 30; # you can use a predicate (with the Whatever Star). -my @list = 1, 3, 9 ... { $_ > 30 }; # (equivalent to the above - # using a block here). - -my @fib = 1, 1, *+* ... *; # lazy infinite list of fibonacci sequence, - # computed using a closure! -my @fib = 1, 1, -> $a, $b { $a + $b } ... *; # (equivalent to the above) -my @fib = 1, 1, { $^a + $^b } ... *; # (also equivalent to the above) -## $a and $b will always take the previous values, meaning here -## they'll start with $a = 1 and $b = 1 (values we set by hand), -## then $a = 1 and $b = 2 (result from previous $a+$b), and so on. - -say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55 - # (using a range as the index) -## Note: as for ranges, once reified, elements aren't re-calculated. -## That's why `@primes[^100]` will take a long time the first time you print -## it, then will be instateneous. -``` - -## Regular Expressions - -```perl6 -## I'm sure a lot of you have been waiting for this one. Well, now that you know -## a good deal of Perl 6 already, we can get started. First off, you'll have to -## forget about "PCRE regexps" (perl-compatible regexps). -## -## IMPORTANT: Don't skip them because you know PCRE. They're different. Some -## things are the same (like `?`, `+`, and `*`), but sometimes the semantics -## change (`|`). Make sure you read carefully, because you might trip over a -## new behavior. -## -## Perl 6 has many features related to RegExps. After all, Rakudo parses itself. -## We're first going to look at the syntax itself, then talk about grammars -## (PEG-like), differences between `token`, `regex` and `rule` declarators, -## and some more. Side note: you still have access to PCRE regexps using the -## `:P5` modifier which we won't be discussing this in this tutorial, though. -## -## In essence, Perl 6 natively implements PEG ("Parsing Expression Grammars"). -## The pecking order for ambiguous parses is determined by a multi-level -## tie-breaking test: -## - Longest token matching: `foo\s+` beats `foo` (by 2 or more positions) -## - Longest literal prefix: `food\w*` beats `foo\w*` (by 1) -## - Declaration from most-derived to less derived grammars -## (grammars are actually classes) -## - Earliest declaration wins -say so 'a' ~~ /a/; #=> True -say so 'a' ~~ / a /; #=> True, more readable with some spaces! - -## In all our examples, we're going to use the smart-matching operator against -## a regexp. We're converting the result using `so` to a Boolean value because, -## in fact, it's returning a `Match` object. They know how to respond to list -## indexing, hash indexing, and return the matched string. The results of the -## match are available in the `$/` variable (implicitly lexically-scoped). You -## can also use the capture variables which start at 0: `$0`, `$1', `$2`... -## -## You can also note that `~~` does not perform start/end checking, meaning -## the regexp can be matched with just one character of the string. We'll -## explain later how you can do it. - -## In Perl 6, you can have any alphanumeric as a literal, everything else has -## to be escaped by using a backslash or quotes. -say so 'a|b' ~~ / a '|' b /; #=> `True`, it wouldn't mean the same thing if - # `|` wasn't escaped. -say so 'a|b' ~~ / a \| b /; #=> `True`, another way to escape it. - -## The whitespace in a regexp is actually not significant, unless you use the -## `:s` (`:sigspace`, significant space) adverb. -say so 'a b c' ~~ / a b c /; #=> `False`, space is not significant here! -say so 'a b c' ~~ /:s a b c /; #=> `True`, we added the modifier `:s` here. - -## If we use only one space between strings in a regex, Perl 6 will warn us: -say so 'a b c' ~~ / a b c /; #=> `False`, with warning about space -say so 'a b c' ~~ / a b c /; #=> `False` - -## Please use quotes or :s (:sigspace) modifier (or, to suppress this warning, -## omit the space, or otherwise change the spacing). To fix this and make the -## spaces less ambiguous, either use at least two spaces between strings -## or use the `:s` adverb. - -## As we saw before, we can embed the `:s` inside the slash delimiters, but we -## can also put it outside of them if we specify `m` for 'match': -say so 'a b c' ~~ m:s/a b c/; #=> `True` - -## By using `m` to specify 'match', we can also use delimiters other than -## slashes: -say so 'abc' ~~ m{a b c}; #=> `True` -say so 'abc' ~~ m[a b c]; #=> `True` -# m/.../ is equivalent to /.../ - -## Use the :i adverb to specify case insensitivity: -say so 'ABC' ~~ m:i{a b c}; #=> `True` - -## However, whitespace is important as for how modifiers are applied ( -## (which you'll see just below) ... - -## Quantifying - `?`, `+`, `*` and `**`. -## `?` - zero or one match -so 'ac' ~~ / a b c /; #=> `False` -so 'ac' ~~ / a b? c /; #=> `True`, the "b" matched 0 times. -so 'abc' ~~ / a b? c /; #=> `True`, the "b" matched 1 time. - -## ...As you read before, whitespace is important because it determines which -## part of the regexp is the target of the modifier: -so 'def' ~~ / a b c? /; #=> `False`, only the `c` is optional -so 'def' ~~ / a b? c /; #=> `False`, whitespace is not significant -so 'def' ~~ / 'abc'? /; #=> `True`, the whole "abc" group is optional - -## Here (and below) the quantifier applies only to the `b` - -## `+` - one or more matches -so 'ac' ~~ / a b+ c /; #=> `False`, `+` wants at least one matching -so 'abc' ~~ / a b+ c /; #=> `True`, one is enough -so 'abbbbc' ~~ / a b+ c /; #=> `True`, matched 4 "b"s - -## `*` - zero or more matches -so 'ac' ~~ / a b* c /; #=> `True`, they're all optional. -so 'abc' ~~ / a b* c /; #=> `True` -so 'abbbbc' ~~ / a b* c /; #=> `True` -so 'aec' ~~ / a b* c /; #=> `False`. "b"(s) are optional, not replaceable. - -## `**` - (Unbound) Quantifier -## If you squint hard enough, you might understand why exponentation is used -## for quantity. -so 'abc' ~~ / a b**1 c /; #=> `True`, (exactly one time) -so 'abc' ~~ / a b**1..3 c /; #=> `True`, (one to three times) -so 'abbbc' ~~ / a b**1..3 c /; #=> `True` -so 'abbbbbbc' ~~ / a b**1..3 c /; #=> `False, (too much) -so 'abbbbbbc' ~~ / a b**3..* c /; #=> `True`, (infinite ranges are okay) - -## `<[]>` - Character classes -## Character classes are the equivalent of PCRE's `[]` classes, but they use a -## more perl6-ish syntax: -say 'fooa' ~~ / f <[ o a ]>+ /; #=> 'fooa' - -## You can use ranges: -say 'aeiou' ~~ / a <[ e..w ]> /; #=> 'ae' - -## Just like in normal regexes, if you want to use a special character, escape -## it (the last one is escaping a space which would be equivalent to using -## ' '): -say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; #=> 'he-he !' - -## You'll get a warning if you put duplicate names (which has the nice effect -## of catching the raw quoting): -'he he' ~~ / <[ h e ' ' ]> /; -# Warns "Repeated character (') unexpectedly found in character class" - -## You can also negate character classes... (`<-[]>` equivalent to `[^]` in PCRE) -so 'foo' ~~ / <-[ f o ]> + /; #=> False - -## ... and compose them: -so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; #=> `False`, (any letter except f and o) -so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; #=> `True`, (no letter except f and o) -so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; #=> `True`, (the + doesn't replace the - # left part) -``` - -### Grouping and capturing - -```perl6 -## Group: you can group parts of your regexp with `[]`. Unlike PCRE's `(?:)`, -## these groups are *not* captured. -so 'abc' ~~ / a [ b ] c /; # `True`. The grouping does pretty much nothing -so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; - -## The previous line returns `True`. The regex matches "012" 1 or more time -## (achieved by the the `+` applied to the group). - -## But this does not go far enough, because we can't actually get back what -## we matched. - -## Capture: The results of a regexp can be *captured* by using parentheses. -so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # `True`. (using `so` - # here, `$/` below) - -## So, starting with the grouping explanations. -## As we said before, our `Match` object is stored inside the `$/` variable: -say $/; # Will either print some weird stuff or `Nil` if nothing matched. - -## As we also said before, it has array indexing: -say $/[0]; #=> 「ABC」 「ABC」 - # These corner brackets are `Match` objects. - # Here, we have an array of these. -say $0; # The same as above. - -## Our capture is `$0` because it's the first and only one capture in the -## regexp. You might be wondering why it's an array, and the answer is simple: -## Some captures (indexed using `$0`, `$/[0]` or a named one) will be an array -## if and only if they can have more than one element. Thus any capture with -## `*`, `+` and `**` (whatever the operands), but not with `?`. -## Let's use examples to see that: - -## Note: We quoted A B C to demonstrate that the whitespace between them isn't -## significant. If we want the whitespace to *be* significant there, we -## can use the :sigspace modifier. -say so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; #=> `True` -say $/[0]; #=> 「ABC」 -say $0.WHAT; #=> (Match) - # There can't be more than one, so it's only a single match object. -say so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; #=> True -say $0.WHAT; #=> (Any) - # This capture did not match, so it's empty -so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; #=> `True` -say $0.WHAT; #=> (Array) - # A specific quantifier will always capture an Array, - # be a range or a specific value (even 1). - -## The captures are indexed per nesting. This means a group in a group will be -## nested under its parent group: `$/[0][0]`, for this code: -'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; -say $/[0].Str; #=> hello~ -say $/[0][0].Str; #=> ~ - -## This stems from a very simple fact: `$/` does not contain strings, integers -## or arrays, it only contains Match objects. These contain the `.list`, `.hash` -## and `.Str` methods but you can also just use `match<key>` for hash access -## and `match[idx]` for array access. -say $/[0].list.perl; #=> (Match.new(...),).list - # We can see it's a list of Match objects. These contain - # a bunch of info: where the match started/ended, - # the "ast" (see actions later), etc. - # You'll see named capture below with grammars. - -## Alternation - the `or` of regexps -## WARNING: They are DIFFERENT from PCRE regexps. -say so 'abc' ~~ / a [ b | y ] c /; #=> `True`. Either "b" or "y". -say so 'ayc' ~~ / a [ b | y ] c /; #=> `True`. Obviously enough... - -## The difference between this `|` and the one you're used to is -## LTM ("Longest Token Matching"). This means that the engine will always -## try to match as much as possible in the string. -say 'foo' ~~ / fo | foo /; #=> `foo`, instead of `fo`, because it's longer. - -## To decide which part is the "longest", it first splits the regex in -## two parts: -## The "declarative prefix" (the part that can be statically analyzed) -## and the procedural parts: -## - The declarative prefixes include alternations (`|`), conjunctions (`&`), -## sub-rule calls (not yet introduced), literals, characters classes and -## quantifiers. -## - The procedural part include everything else: back-references, -## code assertions, and other things that can't traditionnaly be represented -## by normal regexps. -## -## Then, all the alternatives are tried at once, and the longest wins. -## Examples: -## DECLARATIVE | PROCEDURAL -/ 'foo' \d+ [ <subrule1> || <subrule2> ] /; -## DECLARATIVE (nested groups are not a problem) -/ \s* [ \w & b ] [ c | d ] /; -## However, closures and recursion (of named regexps) are procedural. -## There are also more complicated rules, like specificity (literals win over -## character classes). - -## Note: the first-matching `or` still exists, but is now spelled `||` -say 'foo' ~~ / fo || foo /; #=> `fo` now. -``` - -## Extra: the MAIN subroutine - -```perl6 -## The `MAIN` subroutine is called when you run a Perl 6 file directly. It's -## very powerful, because Perl 6 actually parses the arguments and pass them -## as such to the sub. It also handles named argument (`--foo`) and will even -## go as far as to autogenerate a `--help` flag. -sub MAIN($name) { - say "Hello, $name!"; -} -## This produces: -## $ perl6 cli.pl -## Usage: -## t.pl <name> - -## And since it's a regular Perl 6 sub, you can have multi-dispatch: -## (using a "Bool" for the named argument so that we can do `--replace` -## instead of `--replace=1`. The presence of `--replace` indicates truthness -## while its absence falseness). - -subset File of Str where *.IO.d; # convert to IO object to check the file exists - -multi MAIN('add', $key, $value, Bool :$replace) { ... } -multi MAIN('remove', $key) { ... } -multi MAIN('import', File, Str :$as) { ... } # omitting parameter name - -## This produces: -## $ perl6 cli.pl -## Usage: -## cli.p6 [--replace] add <key> <value> -## cli.p6 remove <key> -## cli.p6 [--as=<Str>] import <File> - -## As you can see, this is *very* powerful. It even went as far as to show inline -## the constants (the type is only displayed if the argument is `$`/is named). -``` - -## APPENDIX A: -### List of things - -```perl6 -## It's assumed by now you know the Perl6 basics. This section is just here to -## list some common operations, but which are not in the "main part" of the -## tutorial to avoid bloating it up. - -## Operators - -## Sort comparison - they return one value of the `Order` enum: `Less`, `Same` -## and `More` (which numerify to -1, 0 or +1 respectively). -1 <=> 4; # sort comparison for numerics -'a' leg 'b'; # sort comparison for string -$obj eqv $obj2; # sort comparison using eqv semantics - -## Generic ordering -3 before 4; # True -'b' after 'a'; # True - -## Short-circuit default operator - similar to `or` and `||`, but instead -## returns the first *defined* value: -say Any // Nil // 0 // 5; #=> 0 - -## Short-circuit exclusive or (XOR) - returns `True` if one (and only one) of -## its arguments is true -say True ^^ False; #=> True - -## Flip flops - these operators (`ff` and `fff`, equivalent to P5's `..` -## and `...`) are operators that take two predicates to test: They are `False` -## until their left side returns `True`, then are `True` until their right -## side returns `True`. Similar to ranges, you can exclude the iteration when -## it become `True`/`False` by using `^` on either side. Let's start with an -## example : -for <well met young hero we shall meet later> { - # by default, `ff`/`fff` smart-match (`~~`) against `$_`: - if 'met' ^ff 'meet' { # Won't enter the if for "met" - .say # (explained in details below). - } - - if rand == 0 ff rand == 1 { # compare variables other than `$_` - say "This ... probably will never run ..."; - } -} - -## This will print "young hero we shall meet" (excluding "met"): the flip-flop -## will start returning `True` when it first encounters "met" (but will still -## return `False` for "met" itself, due to the leading `^` on `ff`), until it -## sees "meet", which is when it'll start returning `False`. - -## The difference between `ff` (awk-style) and `fff` (sed-style) is that `ff` -## will test its right side right when its left side changes to `True`, and can -## get back to `False` right away (*except* it'll be `True` for the iteration -## that matched) while `fff` will wait for the next iteration to try its right -## side, once its left side changed: -.say if 'B' ff 'B' for <A B C B A>; #=> B B - # because the right-hand-side was tested - # directly (and returned `True`). - # "B"s are printed since it matched that - # time (it just went back to `False` - # right away). -.say if 'B' fff 'B' for <A B C B A>; #=> B C B - # The right-hand-side wasn't tested until - # `$_` became "C" - # (and thus did not match instantly). - -## A flip-flop can change state as many times as needed: -for <test start print it stop not printing start print again stop not anymore> { - .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # exclude both "start" and "stop", - #=> "print it print again" -} - -## You might also use a Whatever Star, which is equivalent to `True` for the -## left side or `False` for the right: -for (1, 3, 60, 3, 40, 60) { # Note: the parenthesis are superfluous here - # (sometimes called "superstitious parentheses") - .say if $_ > 50 ff *; # Once the flip-flop reaches a number greater - # than 50, it'll never go back to `False` - #=> 60 3 40 60 -} - -## You can also use this property to create an `if` that'll not go through the -## first time: -for <a b c> { - .say if * ^ff *; # the flip-flop is `True` and never goes back to `False`, - # but the `^` makes it *not run* on the first iteration - #=> b c -} - -## The `===` operator is the value identity operator and uses `.WHICH` on the -## objects to compare them while `=:=` is the container identity operator -## and uses `VAR()` on the objects to compare them. -``` - -If you want to go further, you can: - - - Read the [Perl 6 Docs](https://docs.perl6.org/). This is a great - resource on Perl6. If you are looking for something, use the search bar. - This will give you a dropdown menu of all the pages referencing your search - term (Much better than using Google to find Perl 6 documents!). - - Read the [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). This - is a great source of Perl 6 snippets and explanations. If the docs don't - describe something well enough, you may find more detailed information here. - This information may be a bit older but there are many great examples and - explanations. Posts stopped at the end of 2015 when the language was declared - stable and Perl 6.c was released. - - Come along on `#perl6` at `irc.freenode.net`. The folks here are - always helpful. - - Check the [source of Perl 6's functions and - classes](https://github.com/rakudo/rakudo/tree/nom/src/core). Rakudo is - mainly written in Perl 6 (with a lot of NQP, "Not Quite Perl", a Perl 6 subset - easier to implement and optimize). - - Read [the language design documents](http://design.perl6.org). They explain - P6 from an implementor point-of-view, but it's still very interesting. diff --git a/phel.html.markdown b/phel.html.markdown new file mode 100644 index 00000000..4dc030fa --- /dev/null +++ b/phel.html.markdown @@ -0,0 +1,337 @@ +--- +language: phel +filename: learnphel.phel +contributors: + - ["Chemaclass", "https://github.com/Chemaclass"] +--- + +[Phel](https://phel-lang.org/) is a functional programming language that compiles to PHP. +It is a dialect of Lisp inspired by Clojure and Janet. + +## Features +- Built on PHP's ecosystem +- Good error reporting +- Persistent Datastructures (Lists, Vectors, Maps and Sets) +- Macros +- Recursive functions +- Powerful but simple Syntax +- REPL + +```newlisp +# Comments begin with a # character and continue until the end of the line. There are no multi-line comments. + +# Phel is written in "forms", which are just +# lists of things inside parentheses, separated by whitespace. + +# The first call in a file should be ns, to set the namespace +(ns learn-phel) + +# More basic examples: + +# str will create a string out of all its arguments +(str "Hello" " " "World") #=> "Hello World" + +# Math is straightforward +(+ 1 1) #=> 2 +(- 2 1) #=> 1 +(* 1 2) #=> 2 +(/ 2 1) #=> 2 + +# Equality is = +(= 1 1) #=> true +(= 2 1) #=> false + +# You need not for logic, too +(not true) #=> false + +# Nesting forms works as you expect +(+ 1 (- 3 2)) # = 1 + (3 - 2) => 2 + +# Phel inherits PHP under the hood, so it can use native PHP (functions and classes) without +# any additional cost by using the `php/` prefix to all PHP native functions. + +# Types +############# + +# Booleans are similar as the native PHP ones + +nil +true +false + +# Symbols are used to name functions and variables in Phel +# For example: symbol, snake_case_symbol, my-module/my-function + +# Keywords are like symbols that begin with a colon character. However, they are used as constants rather than a name for something. + +:keyword +:0x0x0x +:: + +# Numbers in Phel are equivalent to numbers in PHP + +1337 # integer ++1337 # positive integer +-1337 # negative integer + +1.234 # float ++1.234 # positive float +-1.234 # negative float +1.2e3 # float +7E-10 # float + +# Strings are surrounded by double quotes. They almost work the same as PHP double quoted strings. +# A string can be written in multiple lines. The line break character is then ignored by the reader. + +"hello world" + +"this is\na\nstring" + +"this +is +a +string." + +"use backslack to escape \" string" + +"the dollar must not be escaped: $ or $abc just works" + + +# Collections & Sequences +############# + +# Lists are linked-list data structures, while vectors are array-backed +(type '(1 2 3)) #=> :list +(type [1 2 3]) #=> :vector + +# A list would be written as just (1 2 3), but we have to quote +# it to stop the reader thinking it's a function. +# Also, (list 1 2 3) is the same as '(1 2 3) + +# You can produce a (non-lazy) sequence between a range. +(range 1 10 2) #=> (range from to step) +(take 4 (range 10)) + +# Use cons to add an item to the beginning of a list +(cons 4 '(1 2 3)) #=> (4 1 2 3) + +# Use push to add, and put to replace an item in a vector +(push [1 2 3] 4) #=> (1 2 3 4) +(put [1 2 3] 1 4) #=> (1 4 3) + +# Use concat to add lists or vectors together +(concat [1 2] '(3 4)) #=> [1 2 3 4] + +# Use filter, map to interact with collections +(map inc [1 2 3]) #=> [2 3 4] +(filter even? [1 2 3]) #=> [2] + +# Use reduce to reduce them. The initial-value is mandatory +(reduce + 0 [1 2 3 4]) +#=> (+ (+ (+ 1 2) 3) 4) +#=> 10 + +(reduce push [] '(3 2 1)) +#=> (push (push (push [] 3) 2) 1) +#=> [3 2 1] + +# Functions +############# + +# Use fn to create new functions +# A function always returns its last statement +(fn [] "Hello World") #=> <function> + +# You need extra parens to call it +((fn [] "Hello World")) #=> "Hello World" + +# You can bind a value to a symbol using def for definition +(def x 1) +x #=> 1 + +# Variables provide a way to manage mutable state +(def foo (var 10)) # Define a variable with value 10 + +# Assign a function to a definition +(def hello-world (fn [] "Hello World")) +(hello-world) #=> "Hello World" + +# You can shorten this process by using defn +(defn hello-world [] "Hello World") + +# The [] is the list of arguments for the function +(defn hello [name] + (str "Hello " name)) +(hello "Jens") #=> "Hello Jens" + +# You can also use this shorthand to create functions +(def hello2 |(str "Hello " $1)) +(hello2 "Anna") #=> "Hello Anna" + +# Functions can pack extra arguments up in a seq for you +(defn count-args [& args] + (str "You passed " (count args) " args: " args)) +(count-args 1 2 3) #=> "You passed 3 args: @[1 2 3]" + +# You can mix regular and packed arguments +(defn hello-count [name & args] + (str "Hello " name ", you passed " (count args) " extra args")) +(hello-count "Jesus" 1 2) #=> "Hello Jesus, you passed 2 extra args" + + +# Maps +############# + +# Hash maps have faster lookups but don't retain key order +(type {:a 1 :b 2 :c 3}) #=> :hash-map +(type (hash-map :a 1 :b 2 :c 3)) #=> :hash-map + +# Maps can use any hashable type as a key, but usually keywords are best +# Keywords are like strings with some efficiency bonuses and they start with `:` +(type :a) #=> :keyword + +(def stringmap {"a" 1 "b" 2 "c" 3}) +stringmap #=> {"a" 1 "b" 2 "c" 3} + +(def keymap {:a 1 :b 2 :c 3}) +keymap #=> {:a 1 :c 3 :b 2} + +# Retrieve a value from a map by calling it as a function +(stringmap "a") #=> 1 +(keymap :a) #=> 1 + +# Keywords can be used to retrieve their value from a map, too! +(:b keymap) #=> 2 + +# Don't try this with strings +# ("a" stringmap) +# ...Exception: Call to undefined function a() + +# Retrieving a non-present key returns nil +(stringmap "d") #=> nil + +# Use put to add new keys to hash-maps +(def newkeymap (put keymap :d 4)) +newkeymap #=> {:a 1 :b 2 :c 3 :d 4} + +# But remember, phel types are immutable! +keymap #=> {:a 1 :b 2 :c 3} + +# Use unset to remove keys +(unset keymap :a) #=> {:b 2 :c 3} + +# Sets +############# + +# A Set contains unique values in random order + +(type (set 1 2 3)) #=> :set +(set 1 2 3 1 2 3 3 2 1 3 2 1) #=> (set 1 2 3) + +# Add a member with push +(push (set 1 2 3) 4) #=> (set 1 2 3 4) + +# Remove one with unset +(unset (set 1 2 3) 1) #=> (set 2 3) + +# Test for existence by using the set as a function +((set 1 2 3) 1) #=> 1 +((set 1 2 3) 4) #=> nil + +# There are more functions like: count, union, intersection, difference, etc + + +# Useful forms +############# + +# `If` conditionals in phel are special forms +(if false "a" "b") #=> "b" +(if false "a") #=> nil + +# Use let to create temporary bindings +(let [a 1 b 2] + (> a b)) #=> false + +# Group statements together with do +(do + (print "Hello") + "World") #=> "World" (prints "Hello") + +# Functions have an implicit do +(defn print-and-say-hello [name] + (print "Saying hello to " name) + (str "Hello " name)) +(print-and-say-hello "Jeff") #=> "Hello Jeff" (prints "Saying hello to Jeff") + +# So does let +(let [name "Urkel"] + (print "Saying hello to " name) + (str "Hello " name)) #=> "Hello Urkel" (prints "Saying hello to Urkel") + +# Use the threading macros (-> and ->>) to express transformations of +# data more clearly. + +# The "Thread-first" macro (->) inserts into each form the result of +# the previous, as the first argument (second item) +(-> + {:a 1 :b 2} + (put :c 3) #=> (put {:a 1 :b 2} :c 3) + (unset :b)) #=> (unset (put {:a 1 :b 2} :c 3) :b) + + +# The double arrow does the same thing, but inserts the result of +# each line at the *end* of the form. This is useful for collection +# operations in particular: +(->> + (range 10) + (map inc) #=> (map inc (range 10)) + (filter odd?)) #=> (filter odd? (map inc (range 10))) + # Result: [1 3 5 7 9] + + +# When you are in a situation where you want more freedom as where to +# put the result of previous data transformations in an +# expression, you can use the as-> macro. With it, you can assign a +# specific name to transformations' output and use it as a +# placeholder in your chained expressions: + +(as-> [1 2 3] input + (map inc input) #=> You can use last transform's output at the last position + (get input 2) #=> and at the second position, in the same expression + (push [4 5 6] input 8 9 10)) #=> or in the middle ! + # Result: [4 5 6 4 8 9 10] + +# PHP +################# + +# PHP has a huge and useful standard library, and you're able to use +# all native functions with the prefix `php/`. +(php/+ 1 2 3) + +# With :use you can use different namespaces. Similar as `use` in PHP +(ns my\module + (:use \DateTimeImmutable)) + +# You can import functions from other phel files with :require +(ns my\module + (:require phel\test :refer [deftest is])) + +# Use the class name with a "php/new" to make a new instance +(php/new \DateTime) # <a date-time object> + +# Use php/-> to call methods of an object +(def d (php/new \DateTime)) +(php/-> d (getTimestamp)) # <a timestamp> + +# you can do it in one line too +(php/-> (php/new \DateTime) (getTimestamp)) + +# Use php/:: to call static methods +(php/:: \DateTimeImmutable ATOM) # <a timestamp> +``` + +### Further Reading + +This is far from exhaustive, but hopefully it's enough to get you on your feet. + +Read the full documentation in the website: [https://phel-lang.org/](https://phel-lang.org/documentation/getting-started/) diff --git a/php.html.markdown b/php.html.markdown index 40c9dd01..1ef52f68 100644 --- a/php.html.markdown +++ b/php.html.markdown @@ -34,6 +34,7 @@ echo "World\n"; // Prints "World" with a line break ?> Hello World Again! <?php +// That is because historically PHP started as a Template engine /************************************ @@ -41,12 +42,15 @@ Hello World Again! */ // Variables begin with the $ symbol. -// A valid variable name starts with a letter or underscore, +// A valid variable name starts with a letter or an underscore, // followed by any number of letters, numbers, or underscores. +// You don't have to (and cannot) declare variables. +// Once you assign a value, PHP will create the variable with the right type. + // Boolean values are case-insensitive $boolean = true; // or TRUE or True -$boolean = false; // or FALSE or False +$boolean = FALSE; // or false or False // Integers $int1 = 12; // => 12 @@ -88,9 +92,10 @@ $escaped = "This contains a \t tab character."; $unescaped = 'This just contains a slash and a t: \t'; // Enclose a variable in curly braces if needed -$apples = "I have {$number} apples to eat."; -$oranges = "I have ${number} oranges to eat."; -$money = "I have $${number} in the bank."; +$number = 23; +$apples = "I have {$number} apples to eat."; // => I have 23 apples to eat. +$oranges = "I have ${number} oranges to eat."; // => I have 23 oranges to eat. +$money = "I have $${number} in the bank."; // => I have $23 in the bank. // Since PHP 5.3, nowdocs can be used for uninterpolated multi-liners $nowdoc = <<<'END' @@ -105,7 +110,7 @@ $sgl_quotes END; // String concatenation is done with . -echo 'This string ' . 'is concatenated'; +echo 'This string ' . 'is concatenated'; // Returns 'This string is concatenated' // Strings can be passed in as parameters to echo echo 'Multiple', 'Parameters', 'Valid'; // Returns 'MultipleParametersValid' @@ -289,7 +294,7 @@ if (false) { print (false ? 'Does not get printed' : 'Does'); // ternary shortcut operator since PHP 5.3 -// equivalent of "$x ? $x : 'Does'"" +// equivalent of "$x ? $x : 'Does'" $x = false; print($x ?: 'Does'); @@ -439,7 +444,7 @@ $bar('C'); // Prints "A - B - C" // You can call named functions using strings $function_name = 'add'; echo $function_name(1, 2); // => 3 -// Useful for programatically determining which function to run. +// Useful for programmatically determining which function to run. // Or, use call_user_func(callable $callback [, $parameter [, ... ]]); @@ -587,6 +592,12 @@ echo $my_class->property; // => "public" echo $my_class->instanceProp; // => "An instance property" $my_class->myMethod(); // => "MyClass" +// Nullsafe operators since PHP 8 +// You can use this when you're unsure if the abstraction of $my_class contains has a property/method +// it can be used in conjunction with the nullish coalesce operator to ensure proper value +echo $my_class->invalid_property // An error is thrown +echo $my_class?->invalid_property // => NULL +echo $my_class?->invalid_property ?? "public" // => "public" // Extend classes using "extends" class MyOtherClass extends MyClass diff --git a/pl-pl/bf-pl.html.markdown b/pl-pl/bf-pl.html.markdown index 54772961..09c85362 100644 --- a/pl-pl/bf-pl.html.markdown +++ b/pl-pl/bf-pl.html.markdown @@ -7,7 +7,7 @@ contributors: - ["Mathias Bynens", "http://mathiasbynens.be/"] translators: - ["Jakub Młokosiewicz", "https://github.com/hckr"] - - ["Mateusz Burniak", "https://gitbub.com/matbur"] + - ["Mateusz Burniak", "https://github.com/matbur"] lang: pl-pl --- diff --git a/pl-pl/perl-pl.html.markdown b/pl-pl/perl-pl.html.markdown index 3e27cc4f..43d68b05 100644 --- a/pl-pl/perl-pl.html.markdown +++ b/pl-pl/perl-pl.html.markdown @@ -12,10 +12,10 @@ lang: pl-pl --- -Perl 5 jest wysoce użytecznym, bogatym w wiele opcji językiem programowania +Perl jest wysoce użytecznym, bogatym w wiele opcji językiem programowania z ponad 25 latami nieustannego rozwoju. -Perl 5 używany jest na ponad 100 różnych platformach (od przenośnych do w +Perl używany jest na ponad 100 różnych platformach (od przenośnych do w pełni stacjonarnych) i nadaje się zarówno do szybkiego prototypowania jak i projektów deweloperskich prowadzonych na szeroką skalę. diff --git a/pl-pl/python-pl.html.markdown b/pl-pl/pythonlegacy-pl.html.markdown index 222f753f..2b35ce90 100644 --- a/pl-pl/python-pl.html.markdown +++ b/pl-pl/pythonlegacy-pl.html.markdown @@ -1,8 +1,6 @@ --- -name: python -category: language -language: python -filename: learnpython-pl.py +language: Python 2 (legacy) +filename: learnpythonlegacy-pl.py contributors: - ["Louie Dinh", "http://ldinh.ca"] - ["Amin Bandali", "http://aminbandali.com"] diff --git a/powershell.html.markdown b/powershell.html.markdown index db29bf96..50e1e27e 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -3,6 +3,7 @@ category: tool tool: powershell contributors: - ["Wouter Van Schandevijl", "https://github.com/laoujin"] + - ["Andrew Ryan Davis", "https://github.com/AndrewDavis1191"] filename: LearnPowershell.ps1 --- @@ -13,105 +14,386 @@ Nearly all examples below can be a part of a shell script or executed directly in the shell. A key difference with Bash is that it is mostly objects that you manipulate -rather than plain text. +rather than plain text. After years of evolving, it resembles Python a bit. -[Read more here.](https://technet.microsoft.com/en-us/library/bb978526.aspx) +[Read more here.](https://docs.microsoft.com/powershell/scripting/overview) -If you are uncertain about your environment: +Powershell as a Language: ```powershell -Get-ExecutionPolicy -List -Set-ExecutionPolicy AllSigned -# Execution policies include: -# - Restricted: Scripts won't run. -# - RemoteSigned: Downloaded scripts run only if signed by a trusted publisher. -# - AllSigned: Scripts need to be signed by a trusted publisher. -# - Unrestricted: Run all scripts. -help about_Execution_Policies # for more info -# Current PowerShell version: -$PSVersionTable -``` +# Single line comments start with a number symbol. -Getting help: +<# + Multi-line comments + like so +#> -```powershell -# Find commands -Get-Command about_* # alias: gcm -Get-Command -Verb Add -Get-Alias ps -Get-Alias -Definition Get-Process -Get-Help ps | less # alias: help -ps | Get-Member # alias: gm +#################################################### +## 1. Primitive Datatypes and Operators +#################################################### + +# Numbers +3 # => 3 + +# Math +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 + +# Powershell uses banker's rounding, +# meaning [int]1.5 would round to 2 but so would [int]2.5 +# Division always returns a float. +# You must cast result to [int] to round. +[int]5 / [int]3 # => 1.66666666666667 +[int]-5 / [int]3 # => -1.66666666666667 +5.0 / 3.0 # => 1.66666666666667 +-5.0 / 3.0 # => -1.66666666666667 +[int]$result = 5 / 3 +$result # => 2 + +# Modulo operation +7 % 3 # => 1 + +# Exponentiation requires longform or the built-in [Math] class. +[Math]::Pow(2,3) # => 8 + +# Enforce order of operations with parentheses. +1 + 3 * 2 # => 7 +(1 + 3) * 2 # => 8 + +# Boolean values are primitives (Note: the $) +$True # => True +$False # => False + +# negate with ! +!$True # => False +!$False # => True + +# Boolean Operators +# Note "-and" and "-or" usage +$True -and $False # => False +$False -or $True # => True + +# True and False are actually 1 and 0 but only support limited arithmetic. +# However, casting the bool to int resolves this. +$True + $True # => 2 +$True * 8 # => '[System.Boolean] * [System.Int32]' is undefined +[int]$True * 8 # => 8 +$False - 5 # => -5 + +# Comparison operators look at the numerical value of True and False. +0 -eq $False # => True +1 -eq $True # => True +2 -eq $True # => False +-5 -ne $False # => True + +# Using boolean logical operators on ints casts to booleans for evaluation. +# but their non-cast value is returned +# Don't mix up with bool(ints) and bitwise -band/-bor +[bool](0) # => False +[bool](4) # => True +[bool](-6) # => True +0 -band 2 # => 0 +-5 -bor 0 # => -5 + +# Equality is -eq (equals) +1 -eq 1 # => True +2 -eq 1 # => False + +# Inequality is -ne (notequals) +1 -ne 1 # => False +2 -ne 1 # => True + +# More comparisons +1 -lt 10 # => True +1 -gt 10 # => False +2 -le 2 # => True +2 -ge 2 # => True + +# Seeing whether a value is in a range +1 -lt 2 -and 2 -lt 3 # => True +2 -lt 3 -and 3 -lt 2 # => False + +# (-is vs. -eq) -is checks if two objects are the same type. +# -eq checks if the objects have the same values, but sometimes doesn't work +# as expected. +# Note: we called '[Math]' from .NET previously without the preceeding +# namespaces. We can do the same with [Collections.ArrayList] if preferred. +[System.Collections.ArrayList]$a = @() # Point a at a new list +$a = (1,2,3,4) +$b = $a # => Point b at what a is pointing to +$b -is $a.GetType() # => True, a and b equal same type +$b -eq $a # => None! See below +[System.Collections.Hashtable]$b = @{} # => Point a at a new hash table +$b = @{'one' = 1 + 'two' = 2} +$b -is $a.GetType() # => False, a and b types not equal + +# Strings are created with " or ' but " is required for string interpolation +"This is a string." +'This is also a string.' + +# Strings can be added too! But try not to do this. +"Hello " + "world!" # => "Hello world!" + +# A string can be treated like a list of characters +"Hello world!"[0] # => 'H' + +# You can find the length of a string +("This is a string").Length # => 16 + +# You can also format using f-strings or formatted string literals. +$name = "Steve" +$age = 22 +"He said his name is $name." +# => "He said his name is Steve" +"{0} said he is {1} years old." -f $name, $age +# => "Steve said he is 22 years old" +"$name's name is $($name.Length) characters long." +# => "Steve's name is 5 characters long." + +# Strings can be compared with -eq, but are case insensitive. We can +# force with -ceq or -ieq. +"ab" -eq "ab" # => True +"ab" -eq "AB" # => True! +"ab" -ceq "AB" # => False +"ab" -ieq "AB" # => True + +# Escape Characters in Powershell +# Many languages use the '\', but Windows uses this character for +# file paths. Powershell thus uses '`' to escape characters +# Take caution when working with files, as '`' is a +# valid character in NTFS filenames. +"Showing`nEscape Chars" # => new line between Showing and Escape +"Making`tTables`tWith`tTabs" # => Format things with tabs + +# Negate pound sign to prevent comment +# Note that the function of '#' is removed, but '#' is still present +`#Get-Process # => Fail: not a recognized cmdlet + +# $null is not an object +$null # => None + +# $null, 0, and empty strings and arrays all evaluate to False. +# All other values are True +function Test-Value ($value) { + if ($value) { + Write-Output 'True' + } + else { + Write-Output 'False' + } +} -Show-Command Get-EventLog # Display GUI to fill in the parameters +Test-Value ($null) # => False +Test-Value (0) # => False +Test-Value ("") # => False +Test-Value [] # => True +# *[] calls .NET class; creates '[]' string when passed to function +Test-Value ({}) # => True +Test-Value @() # => False + + +#################################################### +## 2. Variables and Collections +#################################################### + +# Powershell uses the "Write-Output" function to print +Write-Output "I'm Posh. Nice to meet you!" # => I'm Posh. Nice to meet you! + +# Simple way to get input data from console +$userInput = Read-Host "Enter some data: " # Returns the data as a string + +# There are no declarations, only assignments. +# Convention is to use camelCase or PascalCase, whatever your team uses. +$someVariable = 5 +$someVariable # => 5 + +# Accessing a previously unassigned variable does not throw exception. +# The value is $null by default + +# Ternary Operators exist in Powershell 7 and up +0 ? 'yes' : 'no' # => no + + +# The default array object in Powershell is an fixed length array. +$defaultArray = "thing","thing2","thing3" +# you can add objects with '+=', but cannot remove objects. +$defaultArray.Add("thing4") # => Exception "Collection was of a fixed size." +# To have a more workable array, you'll want the .NET [ArrayList] class +# It is also worth noting that ArrayLists are significantly faster + +# ArrayLists store sequences +[System.Collections.ArrayList]$array = @() +# You can start with a prefilled ArrayList +[System.Collections.ArrayList]$otherArray = @(4, 5, 6) + +# Add to the end of a list with 'Add' (Note: produces output, append to $null) +$array.Add(1) > $null # $array is now [1] +$array.Add(2) > $null # $array is now [1, 2] +$array.Add(4) > $null # $array is now [1, 2, 4] +$array.Add(3) > $null # $array is now [1, 2, 4, 3] +# Remove from end with index of count of objects-1; array index starts at 0 +$array.RemoveAt($array.Count-1) # => 3 and array is now [1, 2, 4] +# Let's put it back +$array.Add(3) > $null # array is now [1, 2, 4, 3] again. -Update-Help # Run as admin -``` +# Access a list like you would any array +$array[0] # => 1 +# Look at the last element +$array[-1] # => 3 + +# Looking out of bounds returns nothing +$array[4] # blank line returned + +# You can look at ranges with slice syntax. +# The start index is included, the end index is not +# (It's a closed/open range for you mathy types.) +$array[1..3] # Return array from index 1 to 3 => [2, 4] +$array[2..-1] # Return array starting from index 2 => [4, 3] +$array[0..3] # Return array from beginning until index 3 => [1, 2, 4] +$array[0..2] # Return array selecting every second entry => [1, 4] +$array.Reverse() # mutates array to reverse order => [3, 4, 2, 1] +# Use any combination of these to make advanced slices + +# Remove arbitrary elements from a array with "del" +$array.Remove($array[2]) # $array is now [1, 2, 3] + +# Insert an element at a specific index +$array.Insert(1, 2) # $array is now [1, 2, 3] again + +# Get the index of the first item found matching the argument +$array.IndexOf(2) # => 1 +$array.IndexOf(6) # Returns -1 as "outside array" + +# You can add arrays +# Note: values for $array and for $otherArray are not modified. +$array + $otherArray # => [1, 2, 3, 4, 5, 6] + +# Concatenate arrays with "AddRange()" +$array.AddRange($otherArray) # Now $array is [1, 2, 3, 4, 5, 6] + +# Check for existence in a array with "in" +1 -in $array # => True + +# Examine length with "Count" (Note: "Length" on arrayList = each items length) +$array.Count # => 6 + +# -eq doesn't compare array but extract the matching elements +$array = 1,2,3,1,1 +$array -eq 1 # => 1,1,1 +($array -eq 1).Count # => 3 + +# Tuples are like arrays but are immutable. +# To use Tuples in powershell, you must use the .NET tuple class. +$tuple = [System.Tuple]::Create(1, 2, 3) +$tuple.Item(0) # => 1 +$tuple.Item(0) = 3 # Raises a TypeError + +# You can do some of the array methods on tuples, but they are limited. +$tuple.Length # => 3 +$tuple + (4, 5, 6) # => Exception +$tuple[0..2] # => $null +2 -in $tuple # => False + + +# Hashtables store mappings from keys to values, similar to Dictionaries. +$emptyHash = @{} +# Here is a prefilled dictionary +$filledHash = @{"one"= 1 + "two"= 2 + "three"= 3} + +# Look up values with [] +$filledHash["one"] # => 1 + +# Get all keys as an iterable with ".Keys". +# items maintain the order at which they are inserted into the dictionary. +$filledHash.Keys # => ["one", "two", "three"] + +# Get all values as an iterable with ".Values". +$filledHash.Values # => [1, 2, 3] + +# Check for existence of keys or values in a hash with "-in" +"one" -in $filledHash.Keys # => True +1 -in $filledHash.Values # => False + +# Looking up a non-existing key returns $null +$filledHash["four"] # $null + +# Adding to a dictionary +$filledHash.Add("five",5) # $filledHash["five"] is set to 5 +$filledHash.Add("five",6) # exception "Item with key "five" has already been added" +$filledHash["four"] = 4 # $filledHash["four"] is set to 4, running again does nothing + +# Remove keys from a dictionary with del +$filledHash.Remove("one") # Removes the key "one" from filled dict + + +#################################################### +## 3. Control Flow and Iterables +#################################################### + +# Let's just make a variable +$someVar = 5 -The tutorial starts here: +# Here is an if statement. +# This prints "$someVar is smaller than 10" +if ($someVar -gt 10) { + Write-Output "$someVar is bigger than 10." +} +elseif ($someVar -lt 10) { # This elseif clause is optional. + Write-Output "$someVar is smaller than 10." +} +else { # This is optional too. + Write-Output "$someVar is indeed 10." +} -```powershell -# As you already figured, comments start with # - -# Simple hello world example: -echo Hello world! -# echo is an alias for Write-Output (=cmdlet) -# Most cmdlets and functions follow the Verb-Noun naming convention - -# Each command starts on a new line, or after a semicolon: -echo 'This is the first line'; echo 'This is the second line' - -# Declaring a variable looks like this: -$aString="Some string" -# Or like this: -$aNumber = 5 -as [double] -$aList = 1,2,3,4,5 -$anEmptyList = @() -$aString = $aList -join '--' # yes, -split exists also -$aHashtable = @{name1='val1'; name2='val2'} - -# Using variables: -echo $aString -echo "Interpolation: $aString" -echo "$aString has length of $($aString.Length)" -echo '$aString' -echo @" -This is a Here-String -$aString -"@ -# Note that ' (single quote) won't expand the variables! -# Here-Strings also work with single quote - -# Builtin variables: -# There are some useful builtin variables, like -echo "Booleans: $TRUE and $FALSE" -echo "Empty value: $NULL" -echo "Last program's return value: $?" -echo "Exit code of last run Windows-based program: $LastExitCode" -echo "The last token in the last line received by the session: $$" -echo "The first token: $^" -echo "Script's PID: $PID" -echo "Full path of current script directory: $PSScriptRoot" -echo 'Full path of current script: ' + $MyInvocation.MyCommand.Path -echo "FUll path of current directory: $Pwd" -echo "Bound arguments in a function, script or code block: $PSBoundParameters" -echo "Unbound arguments: $($Args -join ', ')." -# More builtins: `help about_Automatic_Variables` - -# Inline another file (dot operator) -. .\otherScriptName.ps1 - - -### Control Flow -# We have the usual if structure: -if ($Age -is [string]) { - echo 'But.. $Age cannot be a string!' -} elseif ($Age -lt 12 -and $Age -gt 0) { - echo 'Child (Less than 12. Greater than 0)' -} else { - echo 'Adult' + +<# +Foreach loops iterate over arrays +prints: + dog is a mammal + cat is a mammal + mouse is a mammal +#> +foreach ($animal in ("dog", "cat", "mouse")) { + # You can use -f to interpolate formatted strings + "{0} is a mammal" -f $animal +} + +<# +For loops iterate over arrays and you can specify indices +prints: + 0 a + 1 b + 2 c + 3 d + 4 e + 5 f + 6 g + 7 h +#> +$letters = ('a','b','c','d','e','f','g','h') +for($i=0; $i -le $letters.Count-1; $i++){ + Write-Host $i, $letters[$i] +} + +<# +While loops go until a condition is no longer met. +prints: + 0 + 1 + 2 + 3 +#> +$x = 0 +while ($x -lt 4) { + Write-Output $x + $x += 1 # Shorthand for x = x + 1 } # Switch statements are more powerful compared to most languages @@ -122,88 +404,53 @@ switch($val) { { $_ -like 's*' } { "Case insensitive"; break } { $_ -clike 's*'} { "clike, ceq, cne for case sensitive"; break } { $_ -notmatch '^.*$'} { "Regex matching. cnotmatch, cnotlike, ..."; break } - { 'x' -contains 'x'} { "FALSE! -contains is for lists!"; break } default { "Others" } } -# The classic for -for($i = 1; $i -le 10; $i++) { - "Loop number $i" +# Handle exceptions with a try/catch block +try { + # Use "throw" to raise an error + throw "This is an error" } -# Or shorter -1..10 | % { "Loop number $_" } - -# PowerShell also offers -foreach ($var in 'val1','val2','val3') { echo $var } -# while () {} -# do {} while () -# do {} until () - -# Exception handling -try {} catch {} finally {} -try {} catch [System.NullReferenceException] { - echo $_.Exception | Format-List -Force +catch { + Write-Output $Error.ExceptionMessage +} +finally { + Write-Output "We can clean up resources here" } -### Providers -# List files and directories in the current directory -ls # or `dir` -cd ~ # goto home - -Get-Alias ls # -> Get-ChildItem -# Uh!? These cmdlets have generic names because unlike other scripting -# languages, PowerShell does not only operate in the current directory. -cd HKCU: # go to the HKEY_CURRENT_USER registry hive - -# Get all providers in your session -Get-PSProvider - - -### Pipeline -# Cmdlets have parameters that control their execution: -Get-ChildItem -Filter *.txt -Name # Get just the name of all txt files -# Only need to type as much of a parameter name until it is no longer ambiguous -ls -fi *.txt -n # -f is not possible because -Force also exists -# Use `Get-Help Get-ChildItem -Full` for a complete overview - -# Results of the previous cmdlet can be passed to the next as input. -# `$_` is the current object in the pipeline object. -ls | Where-Object { $_.Name -match 'c' } | Export-CSV export.txt -ls | ? { $_.Name -match 'c' } | ConvertTo-HTML | Out-File export.html +# Writing to a file +$contents = @{"aa"= 12 + "bb"= 21} +$contents | Export-CSV "$env:HOMEDRIVE\file.csv" # writes to a file -# If you get confused in the pipeline use `Get-Member` for an overview -# of the available methods and properties of the pipelined objects: -ls | Get-Member -Get-Date | gm +$contents = "test string here" +$contents | Out-File "$env:HOMEDRIVE\file.txt" # writes to another file -# ` is the line continuation character. Or end the line with a | -Get-Process | Sort-Object ID -Descending | Select-Object -First 10 Name,ID,VM ` - | Stop-Process -WhatIf +# Read file contents and convert to json +Get-Content "$env:HOMEDRIVE\file.csv" | ConvertTo-Json -Get-EventLog Application -After (Get-Date).AddHours(-2) | Format-List -# Use % as a shorthand for ForEach-Object -(a,b,c) | ForEach-Object ` - -Begin { "Starting"; $counter = 0 } ` - -Process { "Processing $_"; $counter++ } ` - -End { "Finishing: $counter" } +#################################################### +## 4. Functions +#################################################### -# Get-Process as a table with three columns -# The third column is the value of the VM property in MB and 2 decimal places -# Computed columns can be written more verbose as: -# `@{name='lbl';expression={$_}` -ps | Format-Table ID,Name,@{n='VM(MB)';e={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize +# Use "function" to create new functions +# Keep the Verb-Noun naming convention for functions +function Add-Numbers { + $args[0] + $args[1] +} +Add-Numbers 1 2 # => 3 -### Functions -# The [string] attribute is optional. -function foo([string]$name) { - echo "Hey $name, have a function" +# Calling functions with parameters +function Add-ParamNumbers { + param( [int]$firstNumber, [int]$secondNumber ) + $firstNumber + $secondNumber } -# Calling your function -foo "Say my name" +Add-ParamNumbers -FirstNumber 1 -SecondNumber 2 # => 3 # Functions with named parameters, parameter attributes, parsable documentation <# @@ -220,112 +467,353 @@ New-Website siteName 2000 # ERROR! Port argument could not be validated ('name1','name2') | New-Website -Verbose #> function New-Website() { - [CmdletBinding()] - param ( - [Parameter(ValueFromPipeline=$true, Mandatory=$true)] - [Alias('name')] - [string]$siteName, - [ValidateSet(3000,5000,8000)] - [int]$port = 3000 - ) - BEGIN { Write-Verbose 'Creating new website(s)' } - PROCESS { echo "name: $siteName, port: $port" } - END { Write-Verbose 'Website(s) created' } + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$true, Mandatory=$true)] + [Alias('name')] + [string]$siteName, + [ValidateSet(3000,5000,8000)] + [int]$port = 3000 + ) + BEGIN { Write-Output 'Creating new website(s)' } + PROCESS { Write-Output "name: $siteName, port: $port" } + END { Write-Output 'Website(s) created' } +} + + +#################################################### +## 5. Modules +#################################################### + +# You can import modules and install modules +# The Install-Module is similar to pip or npm, pulls from Powershell Gallery +Install-Module dbaTools +Import-Module dbaTools + +$query = "SELECT * FROM dbo.sometable" +$queryParams = @{ + SqlInstance = 'testInstance' + Database = 'testDatabase' + Query = $query +} +Invoke-DbaQuery @queryParams + +# You can get specific functions from a module +Import-Module -Function Invoke-DbaQuery + + +# Powershell modules are just ordinary Posh files. You +# can write your own, and import them. The name of the +# module is the same as the name of the file. + +# You can find out which functions and attributes +# are defined in a module. +Get-Command -module dbaTools +Get-Help dbaTools -Full + + +#################################################### +## 6. Classes +#################################################### + +# We use the "class" statement to create a class +class Instrument { + [string]$Type + [string]$Family } +$instrument = [Instrument]::new() +$instrument.Type = "String Instrument" +$instrument.Family = "Plucked String" + +$instrument + +<# Output: +Type Family +---- ------ +String Instrument Plucked String +#> + + +#################################################### +## 6.1 Inheritance +#################################################### + +# Inheritance allows new child classes to be defined that inherit +# methods and variables from their parent class. + +class Guitar : Instrument +{ + [string]$Brand + [string]$SubType + [string]$ModelType + [string]$ModelNumber +} + +$myGuitar = [Guitar]::new() +$myGuitar.Brand = "Taylor" +$myGuitar.SubType = "Acoustic" +$myGuitar.ModelType = "Presentation" +$myGuitar.ModelNumber = "PS14ce Blackwood" + +$myGuitar.GetType() + +<# +IsPublic IsSerial Name BaseType +-------- -------- ---- -------- +True False Guitar Instrument +#> + + +#################################################### +## 7. Advanced +#################################################### + +# The powershell pipeline allows things like High-Order Functions. -### It's all .NET -# A PS string is in fact a .NET System.String -# All .NET methods and properties are thus available -'string'.ToUpper().Replace('G', 'ggg') -# Or more powershellish -'string'.ToUpper() -replace 'G', 'ggg' - -# Unsure how that .NET method is called again? -'string' | gm - -# Syntax for calling static .NET methods -[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') - -# Note that .NET functions MUST be called with parentheses -# while PS functions CANNOT be called with parentheses. -# If you do call a cmdlet/PS function with parentheses, -# it is the same as passing a single parameter list -$writer = New-Object System.IO.StreamWriter($path, $true) -$writer.Write([Environment]::NewLine) -$writer.Dispose() - -### IO -# Reading a value from input: -$Name = Read-Host "What's your name?" -echo "Hello, $Name!" -[int]$Age = Read-Host "What's your age?" - -# Test-Path, Split-Path, Join-Path, Resolve-Path -# Get-Content filename # returns a string[] -# Set-Content, Add-Content, Clear-Content -Get-Command ConvertTo-*,ConvertFrom-* - - -### Useful stuff -# Refresh your PATH -$env:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + - ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") - -# Find Python in path -$env:PATH.Split(";") | Where-Object { $_ -like "*python*"} - -# Change working directory without having to remember previous path -Push-Location c:\temp # change working directory to c:\temp -Pop-Location # change back to previous working directory -# Aliases are: pushd and popd - -# Unblock a directory after download -Get-ChildItem -Recurse | Unblock-File - -# Open Windows Explorer in working directory -ii . - -# Any key to exit -$host.UI.RawUI.ReadKey() -return - -# Create a shortcut -$WshShell = New-Object -comObject WScript.Shell -$Shortcut = $WshShell.CreateShortcut($link) -$Shortcut.TargetPath = $file -$Shortcut.WorkingDirectory = Split-Path $file -$Shortcut.Save() +# Group-Object is a handy cmdlet that does incredible things. +# It works much like a GROUP BY in SQL. + +<# + The following will get all the running processes, + group them by Name, + and tell us how many instances of each process we have running. + Tip: Chrome and svcHost are usually big numbers in this regard. +#> +Get-Process | Foreach-Object ProcessName | Group-Object + +# Useful pipeline examples are iteration and filtering. +1..10 | ForEach-Object { "Loop number $PSITEM" } +1..10 | Where-Object { $PSITEM -gt 5 } | ConvertTo-Json + +# A notable pitfall of the pipeline is its performance when +# compared with other options. +# Additionally, raw bytes are not passed through the pipeline, +# so passing an image causes some issues. +# See more on that in the link at the bottom. + +<# + Asynchronous functions exist in the form of jobs. + Typically a procedural language, + Powershell can operate non-blocking functions when invoked as Jobs. +#> + +# This function is known to be non-optimized, and therefore slow. +$installedApps = Get-CimInstance -ClassName Win32_Product + +# If we had a script, it would hang at this func for a period of time. +$scriptBlock = {Get-CimInstance -ClassName Win32_Product} +Start-Job -ScriptBlock $scriptBlock + +# This will start a background job that runs the command. +# You can then obtain the status of jobs and their returned results. +$allJobs = Get-Job +$jobResponse = Get-Job | Receive-Job + + +# Math is built in to powershell and has many functions. +$r=2 +$pi=[math]::pi +$r2=[math]::pow( $r, 2 ) +$area = $pi*$r2 +$area + +# To see all possibilities, check the members. +[System.Math] | Get-Member -Static -MemberType All + + +<# + This is a silly one: + You may one day be asked to create a func that could take $start and $end + and reverse anything in an array within the given range + based on an arbitrary array without mutating the original array. + Let's see one way to do that and introduce another data structure. +#> + +$targetArray = 'a','b','c','d','e','f','g','h','i','j','k','l','m' + +function Format-Range ($start, $end, $array) { + [System.Collections.ArrayList]$firstSectionArray = @() + [System.Collections.ArrayList]$secondSectionArray = @() + [System.Collections.Stack]$stack = @() + for ($index = 0; $index -lt $array.Count; $index++) { + if ($index -lt $start) { + $firstSectionArray.Add($array[$index]) > $null + } + elseif ($index -ge $start -and $index -le $end) { + $stack.Push($array[$index]) + } + else { + $secondSectionArray.Add($array[$index]) > $null + } + } + $finalArray = $firstSectionArray + $stack.ToArray() + $secondSectionArray + return $finalArray +} + +Format-Range 2 6 $targetArray +# => 'a','b','g','f','e','d','c','h','i','j','k','l','m' + +# The previous method works, but uses extra memory by allocating new arrays. +# It's also kind of lengthy. +# Let's see how we can do this without allocating a new array. +# This is slightly faster as well. + +function Format-Range ($start, $end) { + while ($start -lt $end) + { + $temp = $targetArray[$start] + $targetArray[$start] = $targetArray[$end] + $targetArray[$end] = $temp + $start++ + $end-- + } + return $targetArray +} + +Format-Range 2 6 # => 'a','b','g','f','e','d','c','h','i','j','k','l','m' ``` +Powershell as a Tool: +Getting Help: -Configuring your shell +```powershell +# Find commands +Get-Command about_* # alias: gcm +Get-Command -Verb Add +Get-Alias ps +Get-Alias -Definition Get-Process + +Get-Help ps | less # alias: help +ps | Get-Member # alias: gm + +Show-Command Get-WinEvent # Display GUI to fill in the parameters + +Update-Help # Run as admin +``` + +If you are uncertain about your environment: ```powershell -# $Profile is the full path for your `Microsoft.PowerShell_profile.ps1` -# All code there will be executed when the PS session starts -if (-not (Test-Path $Profile)) { - New-Item -Type file -Path $Profile -Force - notepad $Profile +Get-ExecutionPolicy -List +Set-ExecutionPolicy AllSigned +# Execution policies include: +# - Restricted: Scripts won't run. +# - RemoteSigned: Downloaded scripts run only if signed by a trusted publisher. +# - AllSigned: Scripts need to be signed by a trusted publisher. +# - Unrestricted: Run all scripts. +help about_Execution_Policies # for more info + +# Current PowerShell version: +$PSVersionTable +``` + +```powershell +# Calling external commands, executables, +# and functions with the call operator. +# Exe paths with arguments passed or containing spaces can create issues. +C:\Program Files\dotnet\dotnet.exe +# The term 'C:\Program' is not recognized as a name of a cmdlet, +# function, script file, or executable program. +# Check the spelling of the name, or if a path was included, +# verify that the path is correct and try again + +"C:\Program Files\dotnet\dotnet.exe" +C:\Program Files\dotnet\dotnet.exe # returns string rather than execute + +&"C:\Program Files\dotnet\dotnet.exe --help" # fail +&"C:\Program Files\dotnet\dotnet.exe" --help # success +# Alternatively, you can use dot-sourcing here +."C:\Program Files\dotnet\dotnet.exe" --help # success + +# the call operator (&) is similar to Invoke-Expression, +# but IEX runs in current scope. +# One usage of '&' would be to invoke a scriptblock inside of your script. +# Notice the variables are scoped +$i = 2 +$scriptBlock = { $i=5; Write-Output $i } +& $scriptBlock # => 5 +$i # => 2 + +invoke-expression ' $i=5; Write-Output $i ' # => 5 +$i # => 5 + +# Alternatively, to preserve changes to public variables +# you can use "Dot-Sourcing". This will run in the current scope. +$x=1 +&{$x=2};$x # => 1 + +.{$x=2};$x # => 2 + + +# Remoting into computers is easy. +Enter-PSSession -ComputerName RemoteComputer + +# Once remoted in, you can run commands as if you're local. +RemoteComputer\PS> Get-Process powershell + +<# +Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName +------- ------ ----- ----- ------ -- -- ----------- + 1096 44 156324 179068 29.92 11772 1 powershell + 545 25 49512 49852 25348 0 powershell +#> +RemoteComputer\PS> Exit-PSSession + +<# + Powershell is an incredible tool for Windows management and Automation. + Let's take the following scenario: + You have 10 servers. + You need to check whether a service is running on all of them. + You can RDP and log in, or PSSession to all of them, but why? + Check out the following +#> + +$serverList = @( + 'server1', + 'server2', + 'server3', + 'server4', + 'server5', + 'server6', + 'server7', + 'server8', + 'server9', + 'server10' +) + +[scriptblock]$script = { + Get-Service -DisplayName 'Task Scheduler' } -# More info: `help about_profiles` -# For a more useful shell, be sure to check the project PSReadLine below + +foreach ($server in $serverList) { + $cmdSplat = @{ + ComputerName = $server + JobName = 'checkService' + ScriptBlock = $script + AsJob = $true + ErrorAction = 'SilentlyContinue' + } + Invoke-Command @cmdSplat | Out-Null +} + +<# + Here we've invoked jobs across many servers. + We can now Receive-Job and see if they're all running. + Now scale this up 100x as many servers :) +#> ``` Interesting Projects * [Channel9](https://channel9.msdn.com/Search?term=powershell%20pipeline#ch9Search&lang-en=en) PowerShell tutorials +* [KevinMarquette's Powershell Blog](https://powershellexplained.com/) Excellent blog that goes into great detail on Powershell * [PSGet](https://github.com/psget/psget) NuGet for PowerShell * [PSReadLine](https://github.com/lzybkr/PSReadLine/) A bash inspired readline implementation for PowerShell (So good that it now ships with Windows10 by default!) * [Posh-Git](https://github.com/dahlbyk/posh-git/) Fancy Git Prompt (Recommended!) +* [Oh-My-Posh](https://github.com/JanDeDobbeleer/oh-my-posh) Shell customization similar to the popular Oh-My-Zsh on Mac * [PSake](https://github.com/psake/psake) Build automation tool * [Pester](https://github.com/pester/Pester) BDD Testing Framework -* [Jump-Location](https://github.com/tkellogg/Jump-Location) Powershell `cd` that reads your mind -* [PowerShell Community Extensions](http://pscx.codeplex.com/) (Dead) - -Not covered - -* WMI: Windows Management Intrumentation (Get-CimInstance) -* Multitasking: Start-Job -scriptBlock {...}, -* Code Signing -* Remoting (Enter-PSSession/Exit-PSSession; Invoke-Command) +* [ZLocation](https://github.com/vors/ZLocation) Powershell `cd` that reads your mind +* [PowerShell Community Extensions](https://github.com/Pscx/Pscx) +* [More on the Powershell Pipeline Issue](https://github.com/PowerShell/PowerShell/issues/1908) diff --git a/processing.html.markdown b/processing.html.markdown index e437ee95..63f10e88 100644 --- a/processing.html.markdown +++ b/processing.html.markdown @@ -2,7 +2,7 @@ language: processing filename: learnprocessing.pde contributors: - - ["Phone Thant Ko", "http://github.com/phonethantko"] + - ["Phone Than Ko", "http://github.com/phonethantko"] - ["Divay Prakash", "https://github.com/divayprakash"] --- @@ -140,7 +140,7 @@ SomeRandomClass myObjectInstantiated = new SomeRandomClass(); // Arithmetic 1 + 1 // 2 -2 - 1 // 0 +2 - 1 // 1 2 * 3 // 6 3 / 2 // 1 3.0 / 2 // 1.5 @@ -150,7 +150,7 @@ SomeRandomClass myObjectInstantiated = new SomeRandomClass(); // operations. float f = sq(3); // f = 9.0 float p = pow(3, 3); // p = 27.0 -int a = abs(-13) // a = 13 +int a = abs(-13); // a = 13 int r1 = round(3.1); // r1 = 3 int r2 = round(3.7); // r2 = 4 float sr = sqrt(25); // sr = 5.0 @@ -191,6 +191,8 @@ int i = 3; String value = (i > 5) ? "Big" : "Small"; // "Small" // Switch-case structure can be used to check multiple conditions concisely. +// It is important to use the break statement. If the `break`-statement does +// not exist the program executes all the following cases after a case was true. int value = 2; switch(value) { case 0: @@ -209,7 +211,7 @@ switch(value) { // Iterative statements // For Statements - Again, the same syntax as in Java -for(int i = 0; i < 5; i ++){ +for(int i = 0; i < 5; i++){ print(i); // prints from 0 to 4 } @@ -254,7 +256,7 @@ line(x1, y1, z1, x2, y2, z2); // In 3D space // Triangle triangle(x1, y1, x2, y2, x3, y3); -// Draws a triangle connecting three points defined by coordinate paramters. +// Draws a triangle connecting three points defined by coordinate parameters. // Rectangle rect(a, b, c, d, [r]); // With optional parameter defining the radius of all corners @@ -354,14 +356,14 @@ color c = color(255, 255, 255); // WHITE! // By default, Processing uses RGB colour scheme but it can be configured to // HSB using colorMode(). Read more here: // (https://processing.org/reference/colorMode_.html) -background(color); // By now, the background colour should be white. +background(c); // By now, the background colour should be white. // You can use fill() function to select the colour for filling the shapes. // It has to be configured before you start drawing shapes so the colours gets // applied. fill(color(0, 0, 0)); // If you just want to colour the outlines of the shapes then you can use // stroke() function. -stroke(255, 255, 255, 200); // stroke colour set to yellow with transparency +stroke(255, 255, 0, 200); // stroke colour set to yellow with transparency // set to a lower value. // Images @@ -373,7 +375,7 @@ texture(image); // PImage can be passed into arguments for texture-mapping the s If you want to take things further, there are more things Processing is powered for. Rendering models, shaders and whatnot. There's too much to cover in a -short documentation, so I will leave them out here. Shoud you be interested, +short documentation, so I will leave them out here. Should you be interested, please check out the references. ``` diff --git a/pt-br/amd-pt.html.markdown b/pt-br/amd-pt.html.markdown index 40c7cd09..886cb253 100644 --- a/pt-br/amd-pt.html.markdown +++ b/pt-br/amd-pt.html.markdown @@ -19,6 +19,7 @@ módulos de forma síncrona fica sujeito a problemas de performance, usabilidade debugging e problemas de acesso em requisições cross-domain. ### Conceito básico + ```javascript // O básico da API de AMD consiste de nada mais que dois métodos: `define` e `require` // e isso é tudo sobre a definição de módulo e consumo: @@ -122,6 +123,7 @@ define(['daos/coisas', 'modules/algunsHelpers'], function(coisasDao, helpers){ return AlgumaClasse; }); ``` + Para alterar o comportamento padrão de mapeamento de caminho de pastas utilize `requirejs.config(configObj)` em seu `main.js`: @@ -141,6 +143,7 @@ require(['jquery', 'coolLibFromBower', 'modules/algunsHelpers'], function($, coo coolLib.facaAlgoDoidoCom(helpers.transform($('#foo'))); }); ``` + Apps baseados em `require.js` geralmente terão um único ponto de acesso (`main.js`) que é passado à tag script do `require.js` como um data-attribute. Ele vai ser automaticamente carregado e executado com o carregamento da página: ```html @@ -162,16 +165,19 @@ Muitas pessoas preferem usar AMD para sanar a organização do código durante o `require.js` vem com um script chamado `r.js` (que você vai provavelmente rodar em node.js, embora Rhino suporte também) que você pode analisar o gráfico de dependências de seu projeto, e fazer em um único arquivo contendo todos os seus módulos (corretamente nomeados), minificados e prontos para serem consumidos. Instale-o utilizando `npm`: + ```shell $ npm install requirejs -g ``` Agora você pode alimentá-lo com um arquivo de configuração: + ```shell $ r.js -o app.build.js ``` Para o nosso exemplo acima a configuração pode ser essa: + ```javascript /* file : app.build.js */ ({ @@ -188,6 +194,7 @@ Para o nosso exemplo acima a configuração pode ser essa: ``` Para usar o arquivo gerado, em produção, simplesmente troque o `data-main`: + ```html <script src="require.js" data-main="app/main-built"></script> ``` diff --git a/pt-br/asciidoc-pt.html.markdown b/pt-br/asciidoc-pt.html.markdown index b12c0693..9fca5af0 100644 --- a/pt-br/asciidoc-pt.html.markdown +++ b/pt-br/asciidoc-pt.html.markdown @@ -5,7 +5,7 @@ contributors: translators: - ["David Lima", "https://github.com/davelima"] lang: pt-br -filename: asciidoc-pt.md +filename: asciidoc-pt.adoc --- AsciiDoc é uma linguagem de marcação similar ao Markdown e pode ser diff --git a/pt-br/awk-pt.html.markdown b/pt-br/awk-pt.html.markdown index 9bf770fd..02bffc41 100644 --- a/pt-br/awk-pt.html.markdown +++ b/pt-br/awk-pt.html.markdown @@ -202,7 +202,7 @@ function string_functions( localvar, arr) { # Ambas retornam o número de instâncias substituídas 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" # Localiza um texto que casa com uma expressão regular # index() faz a mesma coisa, mas não permite uma expressão regular @@ -317,8 +317,8 @@ a > 0 { # Aqui está um exemplo rápido de um script simples, o tipo de coisa que o AWK # é perfeito para fazer. Ele irá ler um nome da entrada padrão e depois -imprimirá a média de idade de todos com esse primeiro nome. Digamos que você -forneça como argumento o nome de um arquivo com esses dados: +# imprimirá a média de idade de todos com esse primeiro nome. Digamos que você +# forneça como argumento o nome de um arquivo com esses dados: # Bob Jones 32 # Jane Doe 22 @@ -370,8 +370,10 @@ END { } ``` + Leituras adicionais (em inglês): * [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 é encontrado na maioria dos sistemas GNU/Linux. +* [The GNU Awk User's Guide](https://www.gnu.org/software/gawk/manual/gawk.html) + GNU AWK é encontrado na maioria dos sistemas GNU/Linux. diff --git a/pt-br/bash-pt.html.markdown b/pt-br/bash-pt.html.markdown index 3a48d994..ab003a18 100644 --- a/pt-br/bash-pt.html.markdown +++ b/pt-br/bash-pt.html.markdown @@ -17,7 +17,7 @@ lang: pt-br Tutorial de shell em português Bash é o nome do shell do Unix, que também é distribuído como shell do sistema -operacional GNU e como shell padrão para Linux e Mac OS X. Praticamente todos +operacional GNU e como shell padrão para Linux e macOS. Praticamente todos os exemplos abaixo podem fazer parte de um shell script e pode ser executados diretamente no shell. @@ -33,7 +33,7 @@ diretamente no shell. # Exemplo simples de hello world: echo Hello World! -# Cada comando começa com uma nova linha, ou após um ponto virgula: +# Cada comando começa com uma nova linha, ou após um ponto e vírgula: echo 'Essa é a primeira linha'; echo 'Essa é a segunda linha' # A declaração de variáveis é mais ou menos assim @@ -41,14 +41,14 @@ Variavel="Alguma string" # Mas não assim: Variavel = "Alguma string" -# Bash interpretará Variavel como um comando e tentará executar e lhe retornar +# Bash interpretará Variavel como um comando e tentará executar e lhe retornará # um erro porque o comando não pode ser encontrado. # Ou assim: Variavel= 'Alguma string' -# Bash interpretará 'Alguma string' como um comando e tentará executar e lhe retornar -# um erro porque o comando não pode ser encontrado. (Nesse caso a a parte 'Variavel=' -# é vista com uma declaração de variável valida apenas para o escopo do comando 'Uma string'). +# Bash interpretará 'Alguma string' como um comando e tentará executar e lhe retornará +# um erro porque o comando não pôde ser encontrado. (Nesse caso a a parte 'Variavel=' +# é vista com uma declaração de variável válida apenas para o escopo do comando 'Uma string'). # Usando a variável: echo $Variavel @@ -65,15 +65,15 @@ echo ${Variavel/Alguma/Uma} # Substring de uma variável Tamanho=7 echo ${Variavel:0:Tamanho} -# Isso retornará apenas os 7 primeiros caractéres da variável +# Isso retornará apenas os 7 primeiros caracteres da variável # Valor padrão de uma variável echo ${Foo:-"ValorPadraoSeFooNaoExistirOuEstiverVazia"} # Isso funciona para nulo (Foo=) e (Foo=""); zero (Foo=0) retorna 0. -# Note que isso apenas retornar o valor padrão e não mudar o valor da variável. +# Note que isso apenas retornará o valor padrão e não mudará o valor da variável. # Variáveis internas -# Tem algumas variáveis internas bem uteis, como +# Tem algumas variáveis internas bem úteis, como echo "O ultimo retorno do programa: $?" echo "PID do script: $$" echo "Numero de argumentos passados para o script $#" @@ -86,7 +86,7 @@ read Nome # Note que nós não precisamos declarar a variável echo Ola, $Nome # Nós temos a estrutura if normal: -# use 'man test' para mais infomações para as condicionais +# use 'man test' para mais informações para as condicionais if [ $Nome -ne $USER ] then echo "Seu nome não é o seu username" @@ -109,7 +109,7 @@ then echo "Isso vai rodar se $Nome é Daniela ou Jose." fi -# Expressões são denotadas com o seguinte formato +# Expressões são escritas com o seguinte formato echo $(( 10 + 5)) # Diferentemente das outras linguagens de programação, bash é um shell, então ele @@ -118,9 +118,9 @@ echo $(( 10 + 5)) ls #Esse comando tem opções que controlam sua execução -ls -l # Lista todo arquivo e diretorio em linhas separadas +ls -l # Lista todo arquivo e diretório em linhas separadas -# Os resultados do comando anterior pode ser passado para outro comando como input. +# Os resultados do comando anterior podem ser passados para outro comando como input. # O comando grep filtra o input com o padrão passado. É assim que listamos apenas # os arquivos .txt no diretório atual: ls -l | grep "\.txt" @@ -165,7 +165,7 @@ echo "#helloworld" | tee output.out > /dev/null rm -v output.out error.err output-and-error.log # Comando podem ser substituídos por outros comandos usando $( ): -# O comando a seguir mostra o número de arquivos e diretórios no diretorio atual +# O comando a seguir mostra o número de arquivos e diretórios no diretório atual echo "Existem $(ls | wc -l) itens aqui." # O mesmo pode ser feito usando crase `` mas elas não podem ser aninhadas - dá se @@ -241,14 +241,14 @@ head -n 10 arquivo.txt sort arquivo.txt # reporta ou omite as linhas repetidas, com -d você as reporta uniq -d arquivo.txt -# exibe apenas a primeira coluna após o caráctere ',' +# exibe apenas a primeira coluna após o caractere ',' cut -d ',' -f 1 arquivo.txt # substitui todas as ocorrencias de 'okay' por 'legal' em arquivo.txt (é compativel com regex) sed -i 's/okay/legal/g' file.txt # exibe para o stdout todas as linhas do arquivo.txt que encaixam com o regex # O exemplo exibe linhas que começam com "foo" e terminam com "bar" grep "^foo.*bar$" arquivo.txt -# passe a opção "-c" para ao invês de imprimir o numero da linha que bate com o regex +# passe a opção "-c" para ao invés de imprimir o número da linha que bate com o regex grep -c "^foo.*bar$" arquivo.txt # se você quer literalmente procurar por uma string, # e não pelo regex, use fgrep (ou grep -F) diff --git a/pt-br/bc-pt.html.markdown b/pt-br/bc-pt.html.markdown new file mode 100644 index 00000000..2a412806 --- /dev/null +++ b/pt-br/bc-pt.html.markdown @@ -0,0 +1,104 @@ +--- +language: bc +contributors: + - ["Btup"] +translators: + - ["David Lima", "https://github.com/davelima"] +lang: pt-br +filename: learnbc-pt.bc +--- +```c +/*Este é um comentário +multi-linhas*/ +# Este é um comentário de uma única linha! (em bc GNU). + + /*1. Variáveis e estruturas de controle*/ +num = 45 /*Todas as variáveis apenas salvam dados do tipo double, e + você não pode salvar strings diretamente em constantes.*/ +num 45; /*Você pode adicionar ponto-e-vírgula após cada linha. + Isto é opcional*/ +/*Blocos são denotados usando os operadores {} (similar ao C):*/ +while(num < 50) { + num += 1 /*equivalente a num=num+1. + a = a op b é equivalente a a op= b.*/ +} +/*E existem os operadores ++ (incrementar) e -- (decrementar).*/ +/* Existem 3 tipos especiais de variáveis: +scale: define a escala de números double. +ibase: define a base de da entrada. +obase: define a base da saída. +*/ +/*Cláusulas If:*/ +hora = read() /*Lê a entrada de um número*/ + +if(hora < 12) { /*Os operadores são idênticos ao C.*/ + print "Bom dia\n" /*"print" imprime strings ou variáveis + separados por vírgula (,).*/ +} else if(hora == 12) { + print "Olá\n" + /*Para escapar strings, inicie a string com \. + Para deixar o escape de strings mais claros, + aqui está uma lista simplificada das strings escapadas + que funcionarão com bc: + \b: backspace + \c: carriage return (enter) + \n: newline (nova linha) + \t: tab + \\: backslash (barra inertida)*/ +} else { + /*Variáveis são globais por padrão.*/ + istoEGlobal = 5 + /*Para tornar uma variável local, use a palavra-chave "auto" em uma função.*/ +} + +/*Todas as variáveis por padrão tem o valor 0*/ +num = variavelEmBranco /*num é igual a 0.*/ + +/*Assim como no C, "0" é considerado "false"*/ +if(!num) {print "false\n"} + +/*Diferente do C, bc não tem o operador ?:. Por exemplo, +este bloco de código causaria um erro: +a = (num) ? 1 : 0 +Entretanto, você pode simular da seguinte forma: +a = (num) && (1) || (0) /*&& é "E", || é "OU"*/ +*/ + +/*Loops For*/ +num = 0 +for(i = 1; i <= 100; i++) {/*Similar ao loop For do C.*/ + num += i +} + + /*2.Funções e arrays*/ +define fac(n) { /*para definir uma função, use "define".*/ + if(n == 1 || n == 0) { + return 1 /*retorna um valor*/ + } + return n * fac(n - 1) /*recursão é permitido*/ +} + +/*Closures e funções anônimas não são permitidas*/ + +num = fac(4) /*24*/ + +/*Exemplo de variáveis locais:*/ +define x(n) { + auto x + x = 1 + return n + x +} +x(3) /*4*/ +print x /*A variável "x" não será acessível de fora da função*/ +/*Arrays são equivalentes aos arrays em C.*/ +for(i = 0; i <= 3; i++) { + a[i] = 1 +} +/*Para acessar um array, faça assim:*/ +print a[0], " ", a[1], " ", a[2], " ", a[3], "\n" +quit /*Adicione essa linha no final do código +para garantir que o programa encerre. Essa linha é opcional.*/ +``` +Aproveite bem essa simples calculadora! (Ou essa linguagem de programação, para ser exato.) + +Este programa inteiro foi escrito em GNU bc. Para rodá-lo, use ```bc learnbc-pt.bc``` diff --git a/pt-br/c++-pt.html.markdown b/pt-br/c++-pt.html.markdown index 42a29991..ca289001 100644 --- a/pt-br/c++-pt.html.markdown +++ b/pt-br/c++-pt.html.markdown @@ -1,5 +1,5 @@ --- -language: c++ +language: C++ filename: learncpp-pt.cpp contributors: - ["Steven Basart", "http://github.com/xksteven"] @@ -363,7 +363,7 @@ void OwnedDog::print() const { Dog::print(); // Chame a função de impressão na classe Dog base de std::cout << "Dog is owned by " << owner << "\n"; - // Prints "Dog is <name> and weights <weight>" + // Imprime "Dog is <name> and weights <weight>" // "Dog is owned by <owner>" } diff --git a/pt-br/c-pt.html.markdown b/pt-br/c-pt.html.markdown index e1c27958..22a86376 100644 --- a/pt-br/c-pt.html.markdown +++ b/pt-br/c-pt.html.markdown @@ -1,6 +1,6 @@ --- -language: c -filename: learnc.c +language: C +filename: learnc-pt.c contributors: - ["Adam Bard", "http://adambard.com/"] - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"] @@ -8,8 +8,8 @@ translators: - ["João Farias", "https://github.com/JoaoGFarias"] - ["Elton Viana", "https://github.com/eltonvs"] - ["Cássio Böck", "https://github.com/cassiobsilva"] + - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"] lang: pt-br -filename: c-pt.el --- Ah, C. Ainda é **a** linguagem de computação de alta performance. @@ -384,7 +384,6 @@ int main() { // Por exemplo, quando um array é passado para uma função ou é atribuído a um // ponteiro, ele transforma-se (convertido implicitamente) em um ponteiro. // Exceções: quando o array é o argumento de um operador `&` (endereço-de): - // Exceptions: when the array is the argument of the `&` (address-of) operator: int arr[10]; int (*ptr_to_arr)[10] = &arr; // &arr não é do tipo `int *`! // É do tipo "ponteiro para array" (de `int`s). @@ -641,7 +640,7 @@ typedef void (*minha_função_type)(char *); Este é *o* livro sobre C, escrito pelos criadores da linguagem. Mas cuidado - ele é antigo e contém alguns erros (bem, ideias que não são mais consideradas boas) ou práticas ultrapassadas. -Outra boa referência é [Learn C the hard way](http://c.learncodethehardway.org/book/). +Outra boa referência é [Learn C the hard way](http://learncodethehardway.org/c/). Se você tem uma pergunta, leia [compl.lang.c Frequently Asked Questions](http://c-faq.com). diff --git a/pt-br/clojure-macros-pt.html.markdown b/pt-br/clojure-macros-pt.html.markdown index d56840e0..c686bb80 100644 --- a/pt-br/clojure-macros-pt.html.markdown +++ b/pt-br/clojure-macros-pt.html.markdown @@ -13,15 +13,15 @@ do Clojure lhe dá acesso a toda a extensão da linguagem para escrever rotinas de geração de código chamados "macros". Macros fornecem uma poderosa forma de adequar a linguagem às suas necessidades. -Pórem Tenha cuidado. É considerado má pratica escrever uma macro quando uma função vai fazer. Use uma macro apenas -quando você precisar do controle sobre quando ou se os argumentos para um formulário será avaliado. +Pórem, tenha cuidado. É considerado má pratica escrever uma macro quando uma função vai fazer. Use uma macro apenas +quando você precisar de controle sobre quando ou se os argumentos de um formulário serão avaliados. Você vai querer estar familiarizado com Clojure. Certifique-se de entender tudo em -[Clojure em Y Minutos](/docs/clojure/). +[Aprenda Clojure em Y Minutos](/docs/clojure/). ```clojure -;; Defina uma macro utilizando defmacro. Sua macro deve ter como saida uma lista que possa -;; ser avaliada como codigo Clojure. +;; Defina uma macro utilizando defmacro. Sua macro deve ter como saída uma lista que possa +;; ser avaliada como código Clojure. ;; ;; Essa macro é a mesma coisa que se você escrever (reverse "Hello World") (defmacro my-first-macro [] @@ -33,14 +33,14 @@ Você vai querer estar familiarizado com Clojure. Certifique-se de entender tudo (macroexpand '(my-first-macro)) ;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World") -;; Você pode avaliar o resultad de macroexpand diretamente: +;; Você pode avaliar o resultado de macroexpand diretamente: (eval (macroexpand '(my-first-macro))) ; -> (\d \l \o \r \W \space \o \l \l \e \H) -;; mas você deve usar esse mais suscinto, sintax como de função: +;; mas você deve usar essa sintaxe mais sucinta e familiar a funções: (my-first-macro) ; -> (\d \l \o \r \W \space \o \l \l \e \H) -;; Você pode tornar as coisas mais faceis pra você, utilizando a sintaxe de citação mais suscinta +;; Você pode tornar as coisas mais fáceis pra você, utilizando a sintaxe de citação mais suscinta ;; para criar listas nas suas macros: (defmacro my-first-quoted-macro [] '(reverse "Hello World")) diff --git a/pt-br/clojure-pt.html.markdown b/pt-br/clojure-pt.html.markdown index b88d4eec..15ad930a 100644 --- a/pt-br/clojure-pt.html.markdown +++ b/pt-br/clojure-pt.html.markdown @@ -5,12 +5,13 @@ contributors: - ["Adam Bard", "http://adambard.com/"] translators: - ["Mariane Siqueira Machado", "https://twitter.com/mariane_sm"] + - ["Ygor Sad", "https://github.com/ysads"] lang: pt-br --- -Clojure é uma linguagem da família do Lisp desenvolvida para a JVM (máquina virtual Java). Possui uma ênfase muito mais forte em [programação funcional] (https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_funcional) pura do que Common Lisp, mas inclui diversas utilidades [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) para lidar com estado a medida que isso se torna necessário. +Clojure é uma linguagem da família do Lisp desenvolvida para a JVM (máquina virtual Java). Possui uma ênfase muito mais forte em [programação funcional] (https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_funcional) pura do que Common Lisp, mas inclui diversos recursos [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) para lidar com estado e mutabilidade, caso isso seja necessário. -Essa combinação permite gerenciar processamento concorrente de maneira muito simples, e frequentemente de maneira automática. +Essa combinação permite gerenciar processamento concorrente de maneira muito simples - frequentemente, de modo automático. (Sua versão de clojure precisa ser pelo menos 1.2) @@ -18,367 +19,552 @@ Essa combinação permite gerenciar processamento concorrente de maneira muito s ```clojure ; Comentários começam por ponto e vírgula -; Clojure é escrito em "forms", os quais são simplesmente -; listas de coisas dentro de parênteses, separados por espaços em branco. +; Código Clojure é escrito em formas - 'forms', em inglês. Tais estruturas são +; simplesmente listas de valores encapsuladas dentro de parênteses, separados por +; espaços em branco. -; O "reader" (leitor) de Clojure presume que o primeiro elemento de -; uma par de parênteses é uma função ou macro, e que os resto são argumentos. +; Ao interpretar um código em Clojure, o interpretador ou leitor - do inglês 'reader' - assume +; que o primeiro valor dentro de uma forma é uma função ou macro, de modo que os demais valores +; são seus argumentos. Isso se deve ao fato de que Clojure, por ser uma derivação de Lisp, +; usa notação prefixa (ou polonesa). -: A primeira chamada de um arquivo deve ser ns, para configurar o namespace (espaço de nomes) +; Num arquivo, a primeira chamada deve ser sempre para a função ns, +; que é responsável por definir em qual namespace o código em questão +; deve ser alocado (ns learnclojure) ; Alguns exemplos básicos: -; str cria uma string concatenando seus argumentos -(str "Hello" " " "World") ; => "Hello World" +; Aqui, str é uma função e "Olá" " " e "Mundo" são seus argumentos. O que ela faz é criar +; uma string concatenando seus argumentos. +(str "Olá" " " "Mundo") ; => "Olá Mundo" -; Cálculos são feitos de forma direta e intuitiva +; Note que espaços em branco separam os argumentos de uma função. Opcionalmente vírgulas +; podem ser usadas, se você quiser. +(str, "Olá", " ", "Mundo") ; => "Olá Mundo" + +; As operações matemáticas básicas usam os operadores de sempre (+ 1 1) ; => 2 (- 2 1) ; => 1 (* 1 2) ; => 2 (/ 2 1) ; => 2 -; Você pode comparar igualdade utilizando = +; Esses operadores aceitam um número arbitrário de argumentos +(+ 2 2 2) ; = 2 + 2 + 2 => 6 +(- 5 1 1) ; = 5 - 1 - 1 => 3 +(* 3 3 3 3) ; = 3 * 3 * 3 * 3 => 81 + +; Para verificar se dois valores são iguais, o operador = pode ser usado (= 1 1) ; => true (= 2 1) ; => false -; Negação para operações lógicas -(not true) ; => false +; Para saber se dois valores são diferentes +(not= 1 2) ; => true +(not (= 1 2)) ; => true -; Aninhar "forms" funciona como esperado +; Conforme vimos acima, é possível aninhar duas formas (+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 +(* (- 3 2) (+ 1 2)) ; = (3 - 2) * (1 + 2) => 3 + +; Se a leitura ficar comprometida, as fórmulas também podem ser escritas em múltiplas linhas +(* (- 3 2) + (+ 1 2)) ; => 3 +(* + (- 3 2) + (+ 1 2)) ; => 3 + ; Tipos ;;;;;;;;;;;;; -; Clojure usa os tipos de objetos de Java para booleanos, strings e números. -; Use `class` para inspecioná-los -(class 1) ; Literais Integer são java.lang.Long por padrão -(class 1.); Literais Float são java.lang.Double -(class ""); Strings são sempre com aspas duplas, e são java.lang.String +; Por ter interoperabilidade com Java, Clojure usa os tipos de objetos de Java para booleanos, +; strings e números. Para descobrir qual o tipo de um valor, você pode usar a função `class`: +(class 1234) ; Literais Integer são java.lang.Long por padrão +(class 1.50) ; Literais Float são java.lang.Double +(class "oi") ; Strings sempre usam aspas duplas e são java.lang.String (class false) ; Booleanos são java.lang.Boolean -(class nil); O valor "null" é chamado nil -; Se você quiser criar um lista de literais, use aspa simples para -; ela não ser avaliada -'(+ 1 2) ; => (+ 1 2) -; (que é uma abreviação de (quote (+ 1 2))) +; Tenha cuidado, ao dividir valores inteiros: +(= (/ 1 2) + (/ 1.0 2.0)) ; => false + +(class (/ 1 2)) ; => clojure.lang.Ratio +(class (/ 1.0 2.0)) ; => java.lang.Double + +; Aqui temos uma diferença em relação a Java, pois valores nulos são representados por `nil` +(class nil) ; nil -; É possível avaliar uma lista com aspa simples -(eval '(+ 1 2)) ; => 3 ; Coleções e sequências ;;;;;;;;;;;;;;;;;;; -; Listas são estruturas encadeadas, enquanto vetores são implementados como arrays. -; Listas e Vetores são classes Java também! -(class [1 2 3]); => clojure.lang.PersistentVector -(class '(1 2 3)); => clojure.lang.PersistentList +; Os dois tipos básicos de coleção são listas - "list" em inglês - e vetores - "vectors" +; no original. A principal diferença entre eles se +; dá pela implementação: +; - Vetores são implementados como arrays +; - Listas são listas ligadas +(class [1 2 3]) ; => clojure.lang.PersistentVector +(class '(1 2 3)) ; => clojure.lang.PersistentList -; Uma lista é escrita como (1 2 3), mas temos que colocar a aspa -; simples para impedir o leitor (reader) de pensar que é uma função. -; Também, (list 1 2 3) é o mesmo que '(1 2 3) +; Outra forma de declarar listas é usando a função list +(list 1 2 3) ; => '(1 2 3) -; "Coleções" são apenas grupos de dados -; Listas e vetores são ambos coleções: +; Clojure classifica conjuntos de dados de duas maneiras + +; "Coleções" são grupos simples de dados +; Tanto listas quanto vetores são coleções: (coll? '(1 2 3)) ; => true (coll? [1 2 3]) ; => true ; "Sequências" (seqs) são descrições abstratas de listas de dados. -; Apenas listas são seqs. +; Sequências - ou seqs - são conjuntos de dados com avaliação "lazy" +; Apenas listas são seqs: (seq? '(1 2 3)) ; => true (seq? [1 2 3]) ; => false -; Um seq precisa apenas prover uma entrada quando é acessada. -; Portanto, já que seqs podem ser avaliadas sob demanda (lazy) -- elas podem definir séries infinitas: -(range 4) ; => (0 1 2 3) -(range) ; => (0 1 2 3 4 ...) (uma série infinita) -(take 4 (range)) ; (0 1 2 3) +; Ter avaliação lazy significa que uma seq somente precisa prover uma informação quando +; ela for requisitada. Isso permite às seqs representar listas infinitas. +(range) ; => (0 1 2 3 4 ...) +(cycle [1 2]) ; => (1 2 1 2 1 2 ...) +(take 4 (range)) ; => (0 1 2 3) -; Use cons para adicionar um item no início de uma lista ou vetor +; A função cons é usada para adicionar um item ao início de uma lista ou vetor: (cons 4 [1 2 3]) ; => (4 1 2 3) (cons 4 '(1 2 3)) ; => (4 1 2 3) -; Conj adiciona um item em uma coleção sempre do jeito mais eficiente. -; Para listas, elas inserem no início. Para vetores, é inserido no final. +; Já conj adiciona um item em uma coleção sempre do jeito mais eficiente. +; Em listas, isso significa inserir no início. Já em vetores, ao final. (conj [1 2 3] 4) ; => [1 2 3 4] (conj '(1 2 3) 4) ; => (4 1 2 3) -; Use concat para concatenar listas e vetores +; Concatenação de coleções pode ser feita usando concat. Note que ela sempre gera uma +; seq como resultado e está sujeita a problemas de perfomance em coleções grandes, por +; conta da natureza lazy das seqs. +(concat '(1 2) [3 4]) ; => (1 2 3 4) (concat [1 2] '(3 4)) ; => (1 2 3 4) -; Use filter, map para interagir com coleções +; Outra forma de concatenar coleções é usando into. Ela não está sujeita a problemas +; com a avaliação lazy, mas o resultado final da ordem e do tipo dos argumentos passados +(into [1 2] '(3 4)) ; => [1 2 3 4] +(into '(1 2) [3 4]) ; => (4 3 1 2) + +; Note que em into a ordem dos parâmetros influencia a coleção final. +(into [1 2] '(3 4)) ; => (1 2 3 4) +(into '(1 2) [3 4]) ; => (4 3 1 2) + +; As funções filter e map podem ser usadas para interagir com as coleções. Repare que +; elas sempre retornam seqs, independentemente do tipo do seu argumento. (map inc [1 2 3]) ; => (2 3 4) -(filter even? [1 2 3]) ; => (2) +(filter even? [1 2 3 4]) ; => (2 4) + +; Use reduce reduzir coleções a um único valor. Também é possível passar um argumento +; para o valor inicial das operações +(reduce + [1 2 3]) ; = (+ (+ (+ 1 2) 3) 4) => 10 +(reduce + 10 [1 2 3 4]) ; = (+ (+ (+ (+ 10 1) 2) 3) 4) => 20 +(reduce conj [] '(3 2 1)) ; = (conj (conj (conj [] 3) 2) 1) => [3 2 1] + +; Reparou na semelhança entre listas e as chamadas de código Clojure? Isso se deve ao +; fato de que todo código clojure é escrito usando listas. É por isso que elas sempre +; são declaradas com o caracter ' na frente. Dessa forma o interpretador não tenta +; avaliá-las. +'(+ 2 3) ; cria uma lista com os elementos +, 2 e 3 +(+ 2 3) ; o interpretador chama a função + passando como argumentos 2 e 3 -; Use reduce para reduzi-los -(reduce + [1 2 3 4]) -; = (+ (+ (+ 1 2) 3) 4) -; => 10 +; Note que ' é apenas uma abreviação para a função quote. +(quote (1 2 3)) ; => '(1 2 3) + +; É possível passar uma lista para que o interpretador a avalie. Note que isso está +; sujeito ao primeiro elemento da lista ser um literal com um nome de uma função válida. +(eval '(+ 2 3)) ; => 5 +(eval '(1 2 3)) ; dá erro pois o interpretador tenta chamar a função 1, que não existe -; Reduce pode receber um argumento para o valor inicial -(reduce conj [] '(3 2 1)) -; = (conj (conj (conj [] 3) 2) 1) -; => [3 2 1] ; Funções ;;;;;;;;;;;;;;;;;;;;; -; Use fn para criar novas funções. Uma função sempre retorna -; sua última expressão. -(fn [] "Hello World") ; => fn +; Use fn para criar novas funções. Uma função sempre retorna sua última expressão. +(fn [] "Olá Mundo") ; => fn + +; Para executar suas funções, é preciso chamá-las, envolvendo-as em parênteses. +((fn [] "Olá Mundo")) ; => "Olá Mundo" + +; Como isso não é muito prático, você pode nomear funções atribuindo elas a literais. +; Isso torna muito mais fácil chamá-las: +(def ola-mundo (fn [] "Olá Mundo")) ; => fn +(ola-mundo) ; => "Olá Mundo" -; (É necessário colocar parênteses para chamá-los) -((fn [] "Hello World")) ; => "Hello World" +; Você pode abreviar esse processo usando defn: +(defn ola-mundo [] "Olá Mundo") -; Você pode atribuir valores a variáveis utilizando def -(def x 1) -x ; => 1 +; Uma função pode receber uma lista de argumentos: +(defn ola + [nome] + (str "Olá " nome)) +(ola "Jonas") ; => "Olá Jonas" -; Atribua uma função para uma var -(def hello-world (fn [] "Hello World")) -(hello-world) ; => "Hello World" +; É possível criar funções que recebam multivariadas, isto é, que aceitam números +; diferentes de argumentos: +(defn soma + ([] 0) + ([a] a) + ([a b] (+ a b))) -; Você pode abreviar esse processo usando defn -(defn hello-world [] "Hello World") +(soma) ; => 0 +(soma 1) ; => 1 +(soma 1 2) ; => 3 -; O [] é uma lista de argumentos para um função. -(defn hello [name] - (str "Hello " name)) -(hello "Steve") ; => "Hello Steve" +; Funções podem agrupar argumentos extras em uma seq: +(defn conta-args + [& args] + (str "Você passou " (count args) " argumentos: " args)) +(conta-args 1 2 3 4) ; => "Você passou 4 argumentos: (1 2 3 4)" -; Você pode ainda usar essa abreviação para criar funcões: -(def hello2 #(str "Hello " %1)) -(hello2 "Fanny") ; => "Hello Fanny" +; Você pode misturar argumentos regulares e argumentos em seq: +(defn ola-e-conta + [nome & args] + (str "Olá " nome ", você passou " (count args) " argumentos extras")) +(ola-e-conta "Maria" 1 2 3 4) ; => "Olá Maria, você passou 4 argumentos extras" -; Vocé pode ter funções multi-variadic, isto é, com um número variável de argumentos -(defn hello3 - ([] "Hello World") - ([name] (str "Hello " name))) -(hello3 "Jake") ; => "Hello Jake" -(hello3) ; => "Hello World" -; Funções podem agrupar argumentos extras em uma seq -(defn count-args [& args] - (str "You passed " (count args) " args: " args)) -(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" +; Nos exemplos acima usamos def para associar nomes a funções, mas poderíamos usá-lo +; para associar nomes a quaisquer valores: +(def xis :x) +xis ; => :x -; Você pode misturar argumentos regulares e argumentos em seq -(defn hello-count [name & args] - (str "Hello " name ", you passed " (count args) " extra args")) -(hello-count "Finn" 1 2 3) -; => "Hello Finn, you passed 3 extra args" +; Inclusive, tais literais podem possuir alguns caracteres não usuais em outras linguagens: +(def *num-resposta* 42) +(def conexao-ativa? true) +(def grito-de-medo! "AAAAAAA") +(def ->vector-vazio []) + +; É possível, inclusive, criar apelidos a nomes que já existem: +(def somar! soma) +(somar! 41 1) ; => 42 + +; Uma forma rápida de criar funções é por meio de funções anônimas. Elas são ótimas +; para manipulação de coleções e seqs, já que podem ser passadas para map, filter +; e reduce. Nessas funções, % é substituído por cada um dos items na seq ou na coleção: +(filter #(not= % nil) ["Joaquim" nil "Maria" nil "Antônio"]) ; => ("Joaquim" "Maria" "Antônio") +(map #(* % (+ % 2)) [1 2]) ; => (3 8) ; Mapas ;;;;;;;;;; -; Hash maps e array maps compartilham uma mesma interface. Hash maps são mais -; rápidos para pesquisa mas não mantém a ordem da chave. +; Existem dois tipos de mapas: hash maps e array maps. Ambos compartilham uma mesma +; interface e funções. Hash maps são mais rápidos para retornar dados, mas não mantém +; as chaves ordenadas. (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap (class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap -; Arraymaps pode automaticamente se tornar hashmaps através da maioria das -; operações se eles ficarem grandes o suficiente, portanto não há necessida de -; se preocupar com isso. - -;Mapas podem usar qualquer valor que se pode derivar um hash como chave +; Clojure converte automaticamente array maps em hash maps, por meio da maioria das +; funções de manipulação de mapas, caso eles fiquem grandes o suficiente. Não é +; preciso se preocupar com isso. - -; Mapas podem usar qualquer valor em que se pode derivar um hash como chave, -; mas normalmente palavras-chave (keywords) são melhores. -; Keywords são como strings mas com algumas vantagens. +; Chaves podem ser qualquer valor do qual possa ser obtido um hash, mas normalmente +; usam-se keywords como chave, por possuírem algumas vantagens. (class :a) ; => clojure.lang.Keyword -(def stringmap {"a" 1, "b" 2, "c" 3}) -stringmap ; => {"a" 1, "b" 2, "c" 3} +; Keywords são como strings, porém, duas keywords de mesmo valor são sempre armazenadas +; na mesma posição de memória, o que as torna mais eficientes. +(identical? :a :a) ; => true +(identical? (String. "a") (String. "a")) ; => false -(def keymap {:a 1, :b 2, :c 3}) -keymap ; => {:a 1, :c 3, :b 2} +(def mapa-strings {"a" 1 "b" 2 "c" 3}) +mapa-strings ; => {"a" 1, "b" 2, "c" 3} -; A propósito, vírgulas são sempre tratadas como espaçoes em branco e não fazem nada. +(def mapa-keywords {:a 1 :b 2 :c 3}) +mapa-keywords ; => {:a 1, :c 3, :b 2} -; Recupere o valor de um mapa chamando ele como uma função -(stringmap "a") ; => 1 -(keymap :a) ; => 1 +; Você pode usar um mapa como função para recuperar um valor dele: +(mapa-strings "a") ; => 1 +(mapa-keywords :a) ; => 1 -; Uma palavra-chave pode ser usada pra recuperar os valores de um mapa -(:b keymap) ; => 2 +; Se a chave buscada for uma keyword, ela também pode ser usada como função para recuperar +; valores. Note que isso não funciona com strings. +(:b mapa-keywords) ; => 2 +("b" mapa-strings) ; => java.lang.String cannot be cast to clojure.lang.IFn -; Não tente isso com strings -;("a" stringmap) -; => Exception: java.lang.String cannot be cast to clojure.lang.IFn +; Se você buscar uma chave que não existe, Clojure retorna nil: +(mapa-strings "d") ; => nil -; Buscar uma chave não presente retorna nil -(stringmap "d") ; => nil +; Use assoc para adicionar novas chaves em um mapa. +(def mapa-keywords-estendido (assoc mapa-keywords :d 4)) +mapa-keywords-estendido ; => {:a 1, :b 2, :c 3, :d 4} -; Use assoc para adicionar novas chaves para hash-maps -(def newkeymap (assoc keymap :d 4)) -newkeymap ; => {:a 1, :b 2, :c 3, :d 4} +; Mas lembre-se que tipos em Clojure são sempre imutáveis! Isso significa que o mapa +; inicial continua com as mesmas informações e um novo mapa, com mais dados, é criado +; a partir dele +mapa-keywords ; => {:a 1, :b 2, :c 3} -; Mas lembre-se, tipos em Clojure são sempre imutáveis! -keymap ; => {:a 1, :b 2, :c 3} +; assoc também pode ser usado para atualizar chaves: +(def outro-mapa-keywords (assoc mapa-keywords :a 0)) +outro-mapa-keywords ; => {:a 0, :b 2, :c 3} ; Use dissoc para remover chaves -(dissoc keymap :a :b) ; => {:c 3} +(dissoc mapa-keywords :a :b) ; => {:c 3} + +; Mapas também são coleções - mas não seqs! +(coll? mapa-keywords) ; => true +(seq? mapa-keywords) ; => false + +; É possível usar filter, map e qualquer outra função de coleções em mapas. +; Porém a cada iteração um vetor no formato [chave valor] vai ser passado como +; argumento. Por isso é conveniente usar funções anônimas. +(filter #(odd? (second %)) mapa-keywords) ; => ([:a 1] [:c 3]) +(map #(inc (second %)) mapa-keywords) ; => (2 3 4) ; Conjuntos ;;;;;; -(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +; Conjuntos são um tipo especial de coleções que não permitem elementos repetidos. +; Eles podem ser criados com #{} ou com a função set. (set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet -; Adicione um membro com conj -(conj #{1 2 3} 4) ; => #{1 2 3 4} +; Note que nem sempre um set vai armazenar seus elementos na ordem esperada. +(def meu-conjunto #{1 2 3}) +meu-conjunto ; => #{1 3 2} -; Remova um membro com disj -(disj #{1 2 3} 1) ; => #{2 3} +; Adição funciona normalmente com conj. +(conj meu-conjunto 4) ; => #{1 4 3 2} -; Test por existência usando set como função: -(#{1 2 3} 1) ; => 1 -(#{1 2 3} 4) ; => nil +; Remoção, no entanto, precisa ser feita com disj: +(disj meu-conjunto 1) ; => #{3 2} -; Existem muitas outras funções no namespace clojure.sets +; Para saber se um elemento está em um conjunto, use-o como função. Nesse aspecto +; conjuntos funcionam de maneira semelhante a mapas. +(meu-conjunto 1) ; => 1 +(meu-conjunto 4) ; => nil -; Forms úteis -;;;;;;;;;;;;;;;;; -; Construções lógicas em Clojure são como macros, e -; se parecem com as demais -(if false "a" "b") ; => "b" -(if false "a") ; => nil +; Condicionais e blocos +;;;;;;;;;;;;;;;;; -; Use let para criar um novo escopo associando sîmbolos a valores (bindings) +; Você pode usar um bloco let para criar um escopo local, no qual estarão disponíveis +; os nomes que você definir: (let [a 1 b 2] - (> a b)) ; => false + (+ a b)) ; => 3 -; Agrupe comandos juntos com "do" -(do - (print "Hello") - "World") ; => "World" (prints "Hello") +(let [cores {:yellow "Amarelo" :blue "Azul"} + nova-cor :red + nome-cor "Vermelho"] + (assoc cores nova-cor nome-cor)) ; => {:yellow "Amarelo", :blue "Azul", :red "Vermelho"} -; Funções tem um do implícito -(defn print-and-say-hello [name] - (print "Saying hello to " name) - (str "Hello " name)) -(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") +; Formas do tipo if aceitam três argumentos: a condição de teste, o comando a ser +; executado caso a condição seja positiva; e o comando para o caso de ela ser falsa. +(if true "a" "b") ; => "a" +(if false "a" "b") ; => "b" + +; Opcionalmente você pode não passar o último argumento, mas se a condição for falsa +; o if vai retornar nil. +(if false "a") ; => nil + +; A forma if somente aceita um comando para ser executado em cada caso. Se você +; precisar executar mais comandos, você pode usar a função do: +(if true + (do + (print "Olá ") + (print "Mundo"))) ; => escreve "Olá Mundo" na saída + +; Se você só deseja tratar o caso de sua condição ser verdadeira, o comando when é +; uma alternativa melhor. Seu comportamento é idêntico a um if sem condição negativa. +; Uma de suas vantagens é permitir a execução de vários comandos sem exigir do: +(when true "a") ; => "a" +(when true + (print "Olá ") + (print "Mundo")) ; => também escreve "Olá Mundo" na saída + +; Isso ocorre porque when possui um bloco do implícito. O mesmo se aplica a funções e +; comandos let: +(defn escreve-e-diz-xis + [nome] + (print "Diga xis, " nome) + (str "Olá " nome)) +(escreve-e-diz-xis "João") ;=> "Olá João", além de escrever "Diga xis, João" na saída. + +(let [nome "Nara"] + (print "Diga xis, " nome) + (str "Olá " nome)) ;=> "Olá João", além de escrever "Diga xis, João" na saída. -; Assim como let -(let [name "Urkel"] - (print "Saying hello to " name) - (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") ; Módulos ;;;;;;;;;;;;;;; -; Use "use" para poder usar todas as funções de um modulo +; Você pode usar a função use para carregar todas as funções de um módulo. (use 'clojure.set) -; Agora nós podemos usar operações com conjuntos +; Agora nós podemos usar operações de conjuntos definidas nesse módulo: (intersection #{1 2 3} #{2 3 4}) ; => #{2 3} (difference #{1 2 3} #{2 3 4}) ; => #{1} -; Você pode escolher um subconjunto de funções para importar -(use '[clojure.set :only [intersection]]) - -; Use require para importar um módulo +; Isso porém não é uma boa prática pois dificulta saber de qual módulo cada função +; veio, além de expor o código a conflitos de nomes, caso dois módulos diferentes +; definam funções com o mesmo nome. A melhor forma de referenciar módulos é por meio +; de require: (require 'clojure.string) -; Use / para chamar funções de um módulo +; Com isso podemos chamar as funções de clojure.string usando o operador / ; Aqui, o módulo é clojure.string e a função é blank? (clojure.string/blank? "") ; => true -; Você pode dar para um módulo um nome mais curto no import +; Porém isso não é muito prático, por isso é possível dar para um nome mais curto para +; o módulo ao carregá-lo: (require '[clojure.string :as str]) -(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." -; (#"" denota uma expressão regular literal) +(str/replace "alguém quer teste?" #"[aeiou]" str/upper-case) ; => "AlgUém qUEr tEstE?" -; Você pode usar require (e até "use", mas escolha require) de um namespace utilizando :require. -; Não é necessário usar aspa simples nos seus módulos se você usar desse jeito. +; Nesse exemplo usamos também a construção #"", que delimita uma expressão regular. + +; É possível carregar outros módulos direto na definição do namespace. Note que nesse +; contexto não é preciso usar ' antes do vetor que define a importação do módulo. (ns test (:require [clojure.string :as str] [clojure.set :as set])) + +; Operadores thread +;;;;;;;;;;;;;;;;; + +; Uma das funções mais interessantes de clojure são os operadores -> e ->> - respectivamente +; thread-first e thread-last macros. Elas permitem o encadeamento de chamadas de funções, +; sendo perfeitas para melhorar a legibilidade em transformações de dados. + +; -> usa o resultado de uma chamada como o primeiro argumento da chamada à função seguinte: +(-> " uMa StRIng com! aLG_uNs ##problemas. " + (str/replace #"[!#_]" "") + (str/replace #"\s+" " ") + str/trim ; se a função só aceitar um argumento, não é preciso usar parênteses + (str/lower-case)) ; => "uma string com alguns problemas." + +; Na thread uma string com vários problemas foi passada como primeiro argumento à função +; str/replace, que criou uma nova string, a partir da original, porém somente com caracteres +; alfabéticos. Essa nova string foi passada como primeiro argumento para a chamada str/replace +; seguinte, que criou uma nova string sem espaços duplos. Essa nova string foi então passada +; como primeiro argumento para str/trim, que removeu espaços de seu início e fim, passando essa +; última string para str/lower-case, que a converteu para caracteres em caixa baixa. + +; ->> é equivalente a ->, porém o retorno de cada função é passado como último argumento da +; função seguinte. Isso é particularmente útil para lidar com seqs, já que as funções que +; as manipulam sempre as tomam como último argumento. +(->> '(1 2 3 4) + (filter even?) ; => '(2 4) + (map inc) ; => '(3 5) + (reduce *)) ; => 15 + + ; Java ;;;;;;;;;;;;;;;;; -; Java tem uma biblioteca padrão enorme e muito útil, -; portanto é importante aprender como utiliza-la. +; A biblioteca padrão de Java é enorme e possui inúmeros algoritmos e estruturas de +; dados já implementados. Por isso é bastante conveniente saber como usá-la dentro +; de Clojure. -; Use import para carregar um modulo java +; Use import para carregar um módulo Java. (import java.util.Date) -; Você pode importar usando ns também. +; Você pode importar classes Java dentro de ns também: (ns test (:import java.util.Date - java.util.Calendar)) + java.util.Calendar + java.util.ArrayList)) ; Use o nome da clase com um "." no final para criar uma nova instância -(Date.) ; <a date object> +(def instante (Date.)) +(class instante) => ; java.util.Date + +; Para chamar um método, use o operador . com o nome do método. Outra forma é +; usar simplesmente .<nome do método> +(. instante getTime) ; => retorna um inteiro representando o instante +(.getTime instante) ; => exatamente o mesmo que acima + +; Para chamar métodos estáticos dentro de classes Java, use / +(System/currentTimeMillis) ; => retorna um timestamp -; Use . para chamar métodos. Ou, use o atalho ".method" -(. (Date.) getTime) ; <a timestamp> -(.getTime (Date.)) ; exatamente a mesma coisa. +; Note que não é preciso importar o módulo System, pois ele está sempre presente -; Use / para chamar métodos estáticos -(System/currentTimeMillis) ; <a timestamp> (o módulo System está sempre presente) +; Caso queira submeter uma instância de uma classe mutável a uma sequência de operações, +; você pode usar a função doto. Ela é funciona de maneira semelhante à função -> - ou +; thread-first -, exceto pelo fato de que ele opera com valores mutáveis. +(doto (java.util.ArrayList.) + (.add 11) + (.add 3) + (.add 7) + (java.util.Collections/sort)) ; => #<ArrayList [3, 7, 11]> -; Use doto para pode lidar com classe (mutáveis) de forma mais tolerável -(import java.util.Calendar) -(doto (Calendar/getInstance) - (.set 2000 1 1 0 0 0) - .getTime) ; => A Date. set to 2000-01-01 00:00:00 ; STM ;;;;;;;;;;;;;;;;; -; Software Transactional Memory é o mecanismo que Clojure usa para gerenciar -; estado persistente. Tem algumas construções em Clojure que o utilizam. +; Até aqui usamos def para associar nomes a valores. Isso, no entanto, possui algumas +; limitações, já que, uma vez definido essa associação, não podemos alterar o valor +; para o qual um nome aponta. Isso significa que nomes definidos com def não se +; comportam como as variáveis de outras linguagens. -; O atom é o mais simples. Passe pra ele um valor inicial -(def my-atom (atom {})) +; Para lidar com estado persistente e mutação de valores, Clojure usa o mecanismo Software +; Transactional Memory. O atom é o mais simples de todos. Passe pra ele um valor inicial e +; e ele criará um objeto que é seguro de atualizar: +(def atom-mapa (atom {})) -; Atualize o atom com um swap!. -; swap! pega uma função e chama ela com o valor atual do atom -; como primeiro argumento, e qualquer argumento restante como o segundo -(swap! my-atom assoc :a 1) ; Coloca o valor do átomo my-atom como o resultado de (assoc {} :a 1) -(swap! my-atom assoc :b 2) ; Coloca o valor do átomo my-atom como o resultado de (assoc {:a 1} :b 2) +; Para acessar o valor de um atom, você pode usar a função deref ou o operador @: +@atom-mapa ; => {} +(deref atom-mapa) ; => {} -; Use '@' para desreferenciar um atom e acessar seu valor -my-atom ;=> Atom<#...> (Retorna o objeto do Atom) -@my-atom ; => {:a 1 :b 2} +; Para mudar o valor de um atom, você deve usar a função swap! +; O que ela faz é chamar a função passada usando o atom como seu primeiro argumento. Com +; isso, ela altera o valor do atom de maneira segura. +(swap! atom-mapa assoc :a 1) ; Atribui a atom-mapa o resultado de (assoc {} :a 1) +(swap! atom-mapa assoc :b 2) ; Atribui a atom-mapa o resultado de (assoc {:a 1} :b 2) -; Abaixo um contador simples usando um atom -(def counter (atom 0)) -(defn inc-counter [] - (swap! counter inc)) +; Observe que essas chamadas alteraram de fato o valor de atom-mapa. Seu novo valor é: +@atom-mapa ; => {:a 1 :b 2} -(inc-counter) -(inc-counter) -(inc-counter) -(inc-counter) -(inc-counter) +; Isso é diferente de fazer: +(def atom-mapa-2 (atom {})) +(def atom-mapa-3 (assoc @atom-mapa-2 :a 1)) -@counter ; => 5 +; Nesse exemplo, atom-mapa-2 permanece com o seu valor original e é gerado um novo mapa, +; atom-mapa-3, que contém o valor de atom-mapa-2 atualizado. Note que atom-mapa-3 é um +; simples mapa, e não uma instância de um atom +@atom-mapa-2 ; => {} +atom-mapa-3 ; => {:a 1} -; Outras construção STM são refs e agents. +(class atom-mapa-2) ; => clojure.lang.Atom +(class atom-mapa-3) ; => clojure.lang.PersistentArrayMap + +; A ideia é que o valor do atom só será atualizado se, após ser executada a função passada +; para swap!, o atom ainda estiver com o mesmo valor de antes. Isto é, se durante a execução +; da função alguém alterar o valor do atom, swap! reexecutará a função recebida usando o valor +; atual do átoma como argumento. + +; Isso é ótimo em situações nas quais é preciso garantir a consistência de algum valor - tais +; como sistemas bancários e sites de compra. Para mais exemplos e informações sobre outras +; construções STM: + +; Exemplos e aplicações: https://www.braveclojure.com/zombie-metaphysics/ ; Refs: http://clojure.org/refs ; Agents: http://clojure.org/agents ``` ### Leitura adicional -Esse tutorial está longe de ser exaustivo, mas deve ser suficiente para que você possa começar. +Esse tutorial está longe de ser completo, mas deve ser suficiente para que você possa dar seus primeiros passos em Clojure. +Caso queira aprender mais: -Clojure.org tem vários artigos: +* clojure.org tem vários artigos: [http://clojure.org/](http://clojure.org/) -Clojuredocs.org tem documentação com exemplos para quase todas as funções principais (pertecentes ao core): +* Brave Clojure possui um e-book que explora em profundidade diversos recursos de clojure, incluindo ótimos exemplos: +[https://www.braveclojure.com/](https://www.braveclojure.com/) + +* clojuredocs.org tem documentação com exemplos para quase todas as funções principais (pertecentes ao core): [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) -4Clojure é um grande jeito de aperfeiçoar suas habilidades em Clojure/Programação Funcional: -[http://www.4clojure.com/](http://www.4clojure.com/) +* 4clojure possui alguns problemas e desafios interessantes para quem quiser treinar clojure ou programação funcional: +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) -Clojure-doc.org tem um bom número de artigos para iniciantes: +* clojure-doc.org tem um bom número de artigos para iniciantes: [http://clojure-doc.org/](http://clojure-doc.org/) + +Clojure for the Brave and True é um livro de introdução ao Clojure e possui uma versão gratuita online: +[https://www.braveclojure.com/clojure-for-the-brave-and-true/](https://www.braveclojure.com/clojure-for-the-brave-and-true/) diff --git a/pt-br/csharp-pt.html.markdown b/pt-br/csharp-pt.html.markdown index 2ff59296..87e5b3a4 100644 --- a/pt-br/csharp-pt.html.markdown +++ b/pt-br/csharp-pt.html.markdown @@ -1,5 +1,5 @@ --- -language: c# +language: C# filename: csharp-pt.cs contributors: - ["Robson Alves", "http://robsonalves.net/"] @@ -78,15 +78,17 @@ namespace Learning.CSharp short fooShort = 10000; ushort fooUshort = 10000; - // Integer - 32-bit integer + // Integer - inteiro de 32 bits int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647) uint fooUint = 1; // (0 <= uint <= 4,294,967,295) - + //Números por padrão são int ou uint, dependendo do tamanho. + // Long - 64-bit integer long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615) - // Numbers default to being int or uint depending on size. - // L is used to denote that this variable value is of type long or ulong + + // Números por padrão são int ou uint dependendo do tamanho. + // L é usado para denotar que o valor da variável é do tipo long ou ulong. // Double - Double-precision 64-bit IEEE 754 Floating Point double fooDouble = 123.4; // Precision: 15-16 digits @@ -151,7 +153,7 @@ on a new line! ""Wow!"", the masses cried"; intArray[1] = 1; // Listas - // Listas são usadas frequentemente tanto quanto matriz por serem mais flexiveis + // Listas são usadas frequentemente tanto quanto matriz por serem mais flexíveis // O formato de declarar uma lista é o seguinte: // List<tipodado> <var nome> = new List<tipodado>(); List<int> intList = new List<int>(); @@ -308,25 +310,26 @@ on a new line! ""Wow!"", the masses cried"; } /////////////////////////////////////// - // Converting Data Types And Typecasting + // Convertendo Data Types e Typecasting /////////////////////////////////////// - // Converting data + // Convertendo dados + + // Converter String para Integer - // Convert String To Integer - // this will throw a FormatException on failure - int.Parse("123");//returns an integer version of "123" + // isso vai jogar um erro FormatException quando houver falha + int.Parse("123");//retorna uma verão em Integer da String "123" - // try parse will default to type default on failure - // in this case: 0 + // try parse vai ir por padrão para o typo default quando houver uma falha + // nesse caso: 0 int tryInt; - if (int.TryParse("123", out tryInt)) // Function is boolean + if (int.TryParse("123", out tryInt)) // Função booleana Console.WriteLine(tryInt); // 123 - // Convert Integer To String - // Convert class has a number of methods to facilitate conversions + // Converter Integer para String + // A classe Convert possuí métodos para facilitar as conversões Convert.ToString(123); - // or + // ou tryInt.ToString(); // Casting @@ -407,12 +410,12 @@ on a new line! ""Wow!"", the masses cried"; return result; } - // You can narrow down the objects that are passed in + // Você pode pode restringir os objetos que são passados public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int> { - // We can iterate, since T is a IEnumerable + // Nos podemos iterar, desde que T seja um "IEnumerable" foreach (var item in toPrint) - // Item is an int + // Item é um inteiro Console.WriteLine(item.ToString()); } @@ -720,9 +723,9 @@ on a new line! ""Wow!"", the masses cried"; _speed -= decrement; } - // properties get/set values - // when only data needs to be accessed, consider using properties. - // properties may have either get or set, or both + // propriedade recupera e/ou atribui valores (get/set). + // quando os dados precisam apenas ser acessados, considere o uso de propriedades. + // uma propriedade pode ter "get" ou "set", ou ambos. private bool _hasTassles; // private variable public bool HasTassles // public accessor { diff --git a/pt-br/css-pt.html.markdown b/pt-br/css-pt.html.markdown index c73669d0..e4f55276 100644 --- a/pt-br/css-pt.html.markdown +++ b/pt-br/css-pt.html.markdown @@ -14,15 +14,15 @@ translators: lang: pt-br --- -Nos primeiros dias da web não havia elementos visuais, apenas texto puro. Mas com maior desenvolvimento de navegadores da web, páginas web totalmente visuais também se tornou comum. +No início da web não havia elementos visuais, apenas texto puro. Mas com maior desenvolvimento de navegadores da web, páginas web totalmente visuais também se tornaram comuns. -CSS ajuda a manter a separação entre o conteúdo (HTML) e o look-and-feel de uma página web. +CSS ajuda a manter a separação entre o conteúdo (HTML) e o visual de uma página web. CSS permite atingir diferentes elementos em uma página HTML e atribuir diferentes propriedades visuais para eles. -Este guia foi escrito para CSS2, embora CSS3 está rapidamente se tornando popular. +Este guia foi escrito para CSS2, embora CSS3 esteja rapidamente se tornando popular. -**NOTA:** Porque CSS produz resultados visuais, a fim de aprender, você precisa tentar de tudo em um playground CSS como [dabblet](http://dabblet.com/). +**NOTA:** Porque CSS produz resultados visuais, a fim de aprender, você precisa treinar em um playground CSS como [dabblet](http://dabblet.com/). O foco principal deste artigo é sobre a sintaxe e algumas dicas gerais. ```css @@ -42,7 +42,7 @@ Abaixo um elemento de exemplo: <div class='class1 class2' id='anID' attr='value' otherAttr='pt-br foo bar' /> */ -/* Você pode direciona-lo usando uma das suas classes CSS */ +/* Você pode direcioná-lo usando uma das suas classes CSS */ .class1 { } /* ou ambas as classes! */ @@ -82,9 +82,9 @@ classe div.some [attr $ = 'ue'] {} /* Você pode selecionar um elemento que é filho de outro elemento */ div.some-parent> .class-name {} -/* Ou um descendente de um outro elemento. As crianças são os descendentes diretos de - seu elemento pai, apenas um nível abaixo da árvore. Pode ser qualquer descendentes - nivelar por baixo da árvore. */ +/* Ou um descendente de um outro elemento. Os filhos são os descendentes diretos de + seu elemento pai, apenas um nível abaixo da árvore. Pode ser quaisquer descendentes + nivelados por baixo da árvore. */ div.some-parent class-name {} /* Atenção: o mesmo seletor sem espaço tem um outro significado. @@ -97,7 +97,7 @@ div.some-parent.class-name {} /* Ou qualquer irmão que o precede */ .i am-qualquer-elemento antes ~ .Este elemento {} -/* Existem alguns selectores chamado pseudo classes que podem ser usados para selecionar um +/* Existem alguns seletores chamados pseudo classes que podem ser usados para selecionar um elemento quando ele está em um determinado estado */ /* Por exemplo, quando o cursor passa sobre um elemento */ @@ -118,7 +118,7 @@ seletor:first-child {} /* Qualquer elemento que é o último filho de seu pai */ seletor:last-child {} -/* Assim como pseudo classes, pseudo elementos permitem que você estilo certas partes de um documento */ +/* Assim como pseudo classes, pseudo elementos permitem que você estilize certas partes de um documento */ /* Corresponde a um primeiro filho virtual do elemento selecionado */ seletor::before {} @@ -127,10 +127,10 @@ seletor::before {} seletor::after {} /* Nos locais apropriados, um asterisco pode ser utilizado como um curinga para selecionar todos - elemento */ + os elementos */ * {} /* */ Todos os elementos .parent * {} /* */ todos os descendentes -.parent> * {} /* */ todas as crianças +.parent> * {} /* */ todos os filhos /* #################### ## PROPRIEDADES @@ -141,7 +141,7 @@ seletor { /* Unidades de comprimento pode ser absoluta ou relativa. */ /* Unidades relativas */ - width: 50%; /* Percentagem de largura elemento pai */ + width: 50%; /* Percentagem de largura do elemento pai */ font-size: 2em; /* Múltiplos de font-size original de elemento */ font-size: 2rem; /* Ou do elemento raiz font-size */ font-size: 2vw; /* Múltiplos de 1% da largura da janela de exibição (CSS 3) */ @@ -181,7 +181,7 @@ seletor { ## Uso -Guardar uma folha de estilo CSS com a extensão `.css`. +Salvar uma folha de estilo CSS com a extensão `.css`. ```xml <!-- Você precisa incluir o arquivo css no da sua página <head>. Isto é o @@ -200,7 +200,7 @@ Guardar uma folha de estilo CSS com a extensão `.css`. ## Precedência ou Cascata -Um elemento pode ser alvo de vários seletores e pode ter um conjunto de propriedades em que mais de uma vez. Nestes casos, uma das regras tem precedência sobre os outros. Geralmente, uma regra em um seletor mais específico têm precedência sobre um menos específico, e uma regra que ocorre mais tarde na folha de estilo substitui uma anterior. +Um elemento pode ser alvo de vários seletores e pode ter um conjunto de propriedades em que mais de uma vez. Nestes casos, uma das regras tem precedência sobre as outras. Geralmente, uma regra em um seletor mais específico têm precedência sobre um menos específico, e uma regra que ocorre mais tarde na folha de estilo substitui uma anterior. Este processo é chamado de cascata, portanto, as Fichas de nome de estilo em cascata. @@ -279,7 +279,7 @@ Muitos smartphones e tablets tentarão renderizar a página como se estivesse nu ## Compatibilidade -A maior parte dos recursos do CSS 2 (e muitos em CSS 3) estão disponíveis em todos os navegadores e dispositivos. Mas é sempre boa prática para verificar antes de usar um novo recurso. +A maior parte dos recursos do CSS 2 (e muitos em CSS 3) estão disponíveis em todos os navegadores e dispositivos. Mas é sempre boa prática verificar antes de usar um novo recurso. ## Recursos @@ -290,9 +290,9 @@ A maior parte dos recursos do CSS 2 (e muitos em CSS 3) estão disponíveis em t ## Leitura adicional -* [Entendendo Estilo Precedência em CSS: Especificidade, Herança, eo Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) +* [Entendendo Estilo Precedência em CSS: Especificidade, Herança, e o Cascade](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) * [Selecionando elementos usando atributos](https://css-tricks.com/almanac/selectors/a/attribute/) * [QuirksMode CSS](http://www.quirksmode.org/css/) * [Z-Index - O empilhamento context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context) -* [SASS](http://sass-lang.com/) e [menos](http://lesscss.org/) para CSS pré-processamento +* [SASS](http://sass-lang.com/) e [Less](http://lesscss.org/) para CSS pré-processamento * [CSS-Tricks](https://css-tricks.com) diff --git a/pt-br/cypher-pt.html.markdown b/pt-br/cypher-pt.html.markdown index 9b60f771..d4400148 100644 --- a/pt-br/cypher-pt.html.markdown +++ b/pt-br/cypher-pt.html.markdown @@ -101,7 +101,7 @@ path = shortestPath( (user)-[:KNOWS*..5]-(other) ) Crie consultas --- -Create a new node +Crie um novo nó ``` CREATE (a:Person {name:"Théo Gauchoux"}) RETURN a diff --git a/pt-br/d-pt.html.markdown b/pt-br/d-pt.html.markdown new file mode 100644 index 00000000..ae4bab22 --- /dev/null +++ b/pt-br/d-pt.html.markdown @@ -0,0 +1,262 @@ +--- +language: D +filename: learnd-pt.d +contributors: + - ["Nick Papanastasiou", "www.nickpapanastasiou.github.io"] +translators: + - ["Julio Vanzelli", "https://github.com/JulioVanzelli"] +lang: pt-br +--- + +```d +// Você sabe o que está por vir... +module hello; + +import std.stdio; + +// args é opcional +void main(string[] args) { + writeln("Hello, World!"); +} +``` + +Se você é como eu e passa muito tempo na Internet, é provável que tenha ouvido +sobre [D] (http://dlang.org/). A linguagem de programação D é moderna, de uso geral, +linguagem multiparadigma com suporte para tudo, desde recursos de baixo nível até +abstrações expressivas de alto nível. + +D é desenvolvido ativamente por um grande grupo de pessoas super-inteligentes e é liderado por +[Walter Bright] (https://en.wikipedia.org/wiki/Walter_Bright) e +[Andrei Alexandrescu] (https://en.wikipedia.org/wiki/Andrei_Alexandrescu). +Com tudo isso fora do caminho, vamos dar uma olhada em alguns exemplos! + +```d +import std.stdio; + +void main() { + + // Condicionais e loops funcionam como esperado. + for(int i = 0; i < 10000; i++) { + writeln(i); + } + + // 'auto' pode ser usado para inferir tipos. + auto n = 1; + + // literais numéricos podem usar '_' como um separador de dígitos para maior clareza. + while(n < 10_000) { + n += n; + } + + do { + n -= (n / 2); + } while(n > 0); + + // Por e enquanto são bons, mas em D-land preferimos loops 'foreach'. + // O '..' cria um intervalo contínuo, incluindo o primeiro valor + // mas excluindo o último. + foreach(n; 1..1_000_000) { + if(n % 2 == 0) + writeln(n); + } + + // Há também 'foreach_reverse' quando você deseja fazer um loop para trás. + foreach_reverse(n; 1..int.max) { + if(n % 2 == 1) { + writeln(n); + } else { + writeln("No!"); + } + } +} +``` + +Podemos definir novos tipos com `struct`,` class`, `union` e` enum`. Estruturas e uniões +são passados para funções por valor(ou seja, copiados) e as classes são passadas por referência. Além disso, +podemos usar modelos para parametrizar tudo isso em tipos e valores! + +```d +// Aqui, 'T' é um parâmetro de tipo. Pense '<T>' em C++/C#/Java. +struct LinkedList(T) { + T data = null; + + // Usar '!' para instanciar um tipo parametrizado. Mais uma vez, pense '<T>'. + LinkedList!(T)* next; +} + +class BinTree(T) { + T data = null; + + // Se houver apenas um parâmetro de modelo, podemos omitir os parênteses. + BinTree!T left; + BinTree!T right; +} + +enum Day { + Sunday, + Monday, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, +} + +// Use o alias para criar abreviações para tipos. +alias IntList = LinkedList!int; +alias NumTree = BinTree!double; + +// Também podemos criar modelos de funções! +T max(T)(T a, T b) { + if(a < b) + return b; + + return a; +} + +// Use a palavra-chave ref para garantir a passagem por referência. Ou seja, mesmo que 'a' +// e 'b' sejam tipos de valor, eles sempre serão passados por referência a 'swap ()'. +void swap(T)(ref T a, ref T b) { + auto temp = a; + + a = b; + b = temp; +} + +// Com os modelos, também podemos parametrizar valores, não apenas tipos. +class Matrix(uint m, uint n, T = int) { + T[m] rows; + T[n] columns; +} + +auto mat = new Matrix!(3, 3); // O tipo 'T' foi padronizado como 'int'. + +``` + +Falando em aulas, vamos falar sobre propriedades por um segundo. Uma propriedade +é aproximadamente uma função que pode agir como um valor I, para que possamos +ter a sintaxe das estruturas POD (`structure.x = 7`) com a semântica de +métodos getter e setter (`object.setX (7)`)! + +```d +// Considere uma classe parametrizada nos tipos 'T' e 'U'. +class MyClass(T, U) { + T _data; + U _other; +} + +// E os métodos "getter" e "setter", assim: +class MyClass(T, U) { + T _data; + U _other; + + // Os construtores sempre são chamados de 'this'. + this(T t, U u) { + // This will call the setter methods below. + data = t; + other = u; + } + + // getters + @property T data() { + return _data; + } + + @property U other() { + return _other; + } + + // setters + @property void data(T t) { + _data = t; + } + + @property void other(U u) { + _other = u; + } +} + +// E nós os usamos desta maneira: +void main() { + auto mc = new MyClass!(int, string)(7, "seven"); + + // Importe o módulo 'stdio' da biblioteca padrão para gravar no + // console (as importações podem ser locais para um escopo). + import std.stdio; + + // Ligue para os getters para buscar os valores. + writefln("Earlier: data = %d, str = %s", mc.data, mc.other); + + // Ligue para os setters para atribuir novos valores. + mc.data = 8; + mc.other = "eight"; + + // Ligue para os getters novamente para buscar os novos valores. + writefln("Later: data = %d, str = %s", mc.data, mc.other); +} +``` + +Com propriedades, podemos adicionar qualquer quantidade de lógica para +nossos métodos getter e setter, e mantenha a sintaxe limpa de +acessando membros diretamente! + +Outras guloseimas orientadas a objetos à nossa disposição, +incluem interfaces, classes abstratas, +e métodos de substituição. D faz herança como Java: +Estenda uma classe, implemente quantas interfaces você desejar. + +Vimos as instalações OOP de D, mas vamos mudar de marcha. D oferece +programação funcional com funções de primeira classe, `pura` +funções e dados imutáveis. Além disso, todos os seus favoritos +algoritmos funcionais (mapear, filtrar, reduzir e amigos) podem ser +encontrado no maravilhoso módulo `std.algorithm`! + +```d +import std.algorithm : map, filter, reduce; +import std.range : iota; // cria uma gama exclusiva de final + +void main() { + // Queremos imprimir a soma de uma lista de quadrados de ints pares + // de 1 a 100. Fácil! + + // Basta passar expressões lambda como parâmetros de modelo! + // Você pode passar qualquer função que desejar, mas as lambdas são convenientes aqui. + auto num = iota(1, 101).filter!(x => x % 2 == 0) + .map!(y => y ^^ 2) + .reduce!((a, b) => a + b); + + writeln(num); +} +``` + +Observe como conseguimos construir um bom pipeline haskelliano para calcular num? +Isso se deve a uma inovação em D, conhecida como Uniform Function Call Syntax (UFCS). +Com o UFCS, podemos optar por escrever uma chamada de função como método +ou chamada de função grátis! Walter escreveu um bom artigo sobre isso +[aqui.] (http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394) +Em resumo, você pode chamar funções cujo primeiro parâmetro +é de algum tipo A em qualquer expressão do tipo A como método. + +Eu gosto de paralelismo. Alguém mais gosta de paralelismo? Com certeza. Vamos fazer um pouco! + +```d +// Digamos que queremos preencher uma matriz grande com a raiz quadrada de todos +// os números inteiros consecutivos começando de 1 (até o tamanho da matriz), e queremos +// fazer isso simultaneamente, aproveitando o número de núcleos que temos +// disponível. + +import std.stdio; +import std.parallelism : parallel; +import std.math : sqrt; + +void main() { + // Crie sua grande variedade + auto arr = new double[1_000_000]; + + // Use um índice, acesse todos os elementos da matriz por referência (porque vamos + // mudar cada elemento) e apenas chame paralelo na matriz! + foreach(i, ref elem; parallel(arr)) { + elem = sqrt(i + 1.0); + } +} +``` diff --git a/pt-br/dart-pt.html.markdown b/pt-br/dart-pt.html.markdown index e9d72850..6aff1ac3 100644 --- a/pt-br/dart-pt.html.markdown +++ b/pt-br/dart-pt.html.markdown @@ -3,15 +3,16 @@ language: dart filename: learndart-pt.dart contributors: - ["Joao Pedrosa", "https://github.com/jpedrosa/"] + - ["Hélio Oliveira", "https://github.com/insign/"] translators: - ["Junior Damacena", "https://github.com/jdamacena/"] lang: pt-br --- Dart é uma novata no reino das linguagens de programação. -Ela empresta muito de outras linguagens mais conhecidas, e tem a meta de não se diferenciar muito de seu irmão, JavaScript. Assim como JavaScript, Dart foi pensada para oferecer grande integração com o Browser. +Ela absorve muitas teorias de outras linguagens mais conhecidas, e tem a meta de não se diferenciar muito de seu irmão, JavaScript. Assim como JavaScript, Dart foi pensada para oferecer grande integração com o navegador. -A característica mais controversa da Dart é a sua Tipagem Opcional, ou seja, não é obrigatório declarar tipos. +As variáveis em Dart tem tipos, mas não é obrigatório declarar devido à função de [detecção automática](https://dart.dev/guides/language/type-system#type-inference). ```dart import "dart:collection"; diff --git a/pt-br/elisp-pt.html.markdown b/pt-br/elisp-pt.html.markdown index fc2d1e40..aa611097 100644 --- a/pt-br/elisp-pt.html.markdown +++ b/pt-br/elisp-pt.html.markdown @@ -111,7 +111,7 @@ filename: learn-emacs-lisp-pt.el (hello) ;; `C-xC-e' => Hello, I am Bastien -;; Os parêntesis vazios na definição da função significam que ela +;; Os parênteses vazios na definição da função significam que ela ;; não aceita argumentos. Mas sempre utilizar `my-name' é um tédio! ;; Vamos dizer à função para aceitar um argumento (o argumento é ;; chamado "name"): diff --git a/pt-br/elixir-pt.html.markdown b/pt-br/elixir-pt.html.markdown index f8c56101..18441ff7 100644 --- a/pt-br/elixir-pt.html.markdown +++ b/pt-br/elixir-pt.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] @@ -20,7 +20,7 @@ e muitos outros recursos. # Não há comentários de múltiplas linhas, # mas você pode empilhar os comentários. -# Para usar o shell do elixir use o comando `iex`. +# Para usar o shell do Elixir use o comando `iex`. # Compile seus módulos com o comando `elixirc`. # Ambos devem estar em seu path se você instalou o Elixir corretamente. @@ -40,7 +40,7 @@ e muitos outros recursos. # Tuplas que são guardadas contiguamente em memória. {1,2,3} # tupla -# Podemos acessar um elemento de uma tupla om a função `elem`: +# Podemos acessar um elemento de uma tupla com a função `elem`: elem({1, 2, 3}, 0) #=> 1 # Listas que são implementadas como listas ligadas. @@ -51,7 +51,7 @@ elem({1, 2, 3}, 0) #=> 1 head #=> 1 tail #=> [2,3] -# Em elixir, bem como em Erlang, o sinal `=` denota pattern match, +# Em Elixir, bem como em Erlang, o sinal `=` denota pattern match, # e não uma atribuição. # # Isto significa que o que estiver à esquerda (pattern) é comparado com o que @@ -85,7 +85,7 @@ linhas. <<?a, ?b, ?c>> #=> "abc" [?a, ?b, ?c] #=> 'abc' -# `?a` em elixir retorna o valor ASCII para a letra `a` +# `?a` em Elixir retorna o valor ASCII para a letra `a` ?a #=> 97 # Para concatenar listas use `++`, para binários use `<>` @@ -98,7 +98,7 @@ linhas. # Ranges são representados como `início..fim` (ambos inclusivos) 1..10 #=> 1..10 menor..maior = 1..10 # Pattern matching pode ser usada em ranges também -[lower, upper] #=> [1, 10] +[menor, maior] #=> [1, 10] ## --------------------------- ## -- Operadores @@ -110,7 +110,7 @@ menor..maior = 1..10 # Pattern matching pode ser usada em ranges também 5 * 2 #=> 10 10 / 2 #=> 5.0 -# Em elixir o operador `/` sempre retorna um float. +# Em Elixir o operador `/` sempre retorna um float. # Para divisão de inteiros use `div` div(10, 2) #=> 5 @@ -167,7 +167,7 @@ else "Isso será" end -# Lembra do patter matching? Muitas estruturas de fluxo de controle em elixir contam com ela. +# Lembra do pattern matching? Muitas estruturas de fluxo de controle em Elixir contam com ela. # `case` nos permite comparar um valor com muitos patterns: case {:um, :dois} do @@ -296,7 +296,7 @@ Geometry.area({:circle, 3}) #=> 28.25999999999999801048 # Geometry.area({:circle, "not_a_number"}) #=> ** (FunctionClauseError) no function clause matching in Geometry.area/1 -# Devido à imutabilidade, recursão é uma grande parte do elixir +# Devido à imutabilidade, recursão é uma grande parte do Elixir defmodule Recursion do def sum_list([head | tail], acc) do sum_list(tail, acc + head) @@ -309,7 +309,7 @@ end Recursion.sum_list([1,2,3], 0) #=> 6 -# Módulos do elixir suportam atributos, hpa atributos embutidos e você +# Módulos do Elixir suportam atributos, hpa atributos embutidos e você # pode também adicionar os seus próprios. defmodule MyMod do @moduledoc """ @@ -361,7 +361,7 @@ end ## --------------------------- # Elixir conta com o modelo de ator para concorrência. Tudo o que precisamos para -# escrever programas concorrentes em elixir são três primitivos: spawning processes, +# escrever programas concorrentes em Elixir são três primitivos: spawning processes, # sending messages e receiving messages. # Para iniciar um novo processo usamos a função `spawn`, a qual leva uma função diff --git a/pt-br/emacs-pt.html.markdown b/pt-br/emacs-pt.html.markdown new file mode 100644 index 00000000..7a86a119 --- /dev/null +++ b/pt-br/emacs-pt.html.markdown @@ -0,0 +1,60 @@ +--- +category: tool +tool: emacs +filename: emacs.txt +contributors: + - ["Joseph Riad", "https://github.com/Joseph-Riad"] +translators: + - ["André de Santa Gabriel", "https://github.com/andredesanta"] +lang: pt-br +--- + +O Emacs começou sua vida como (https://www.gnu.org/software/emacs/emacs-paper.html) e cresceu +ao longo dos anos em um ecossistema completo. Muitas tarefas, geralmente +relegado a um conjunto diversificado de ferramentas pode ser realizado de dentro +Emacs em uma interface consistente e familiar. Exemplos incluem +gerenciamento de diretório, visualização de documentos PDF, edição de arquivos via SSH, gerenciamento de +repos git. Em suma, o Emacs é seu para fazer +o que você quiser: o espectro de usuários varia daqueles que o usam para +editar arquivos de texto para puristas extremos que o usam para substituir virtualmente seu +sistema operacional. + +O Emacs é extensível através de um dialeto especializado do Lisp conhecido como Emacs +Lisp (Elisp), que possui muitas macros voltadas para a edição de texto e +gerenciamento de buffers de texto. Qualquer tecla (combinação) usada no Emacs está vinculada +para uma função Emacs Lisp e pode ser remapeado para qualquer outra função, +incluindo aqueles que você escreve +você mesmo. + +# Conceitos básicos de Emacs + +Aqui, discuto alguns conceitos e terminologia básicos do Emacs que podem ser +confusos para os recém-chegados (especialmente para as pessoas acostumadas à terminologia do Vim): + + - O texto que o Emacs está editando é conhecido como **buffer** + + - Um buffer não corresponde necessariamente a um arquivo real no disco. Pode ser apenas texto na memória. + + - Quando um buffer corresponde a um arquivo no disco, dizemos que o buffer está **visitando** esse arquivo. + + - O Emacs normalmente possui muitos buffers abertos ao mesmo tempo. + + - A exibição do Emacs pode ser dividida em diferentes **windows**. + + - Uma janela do sistema operacional para o Emacs é chamada de **frame**. Assim, quando o manual do Emacs fala sobre a abertura de um novo frame, esse essencialmente significa abrir uma nova janela do SO contendo uma (outra) instância do Emacs. + + - Os conceitos convencionalmente conhecidos como recortar e colar são referido como **killing** e **yanking**, respectivamente no Emacs. + + - A posição atual do cursor é chamada de **point** no Emacs. Tecnicamente, **point** é definido como a posição imediatamente antes do caractere onde o cursor está atualmente. + + - Finalmente, cada buffer pode ter vários **modes** associados: o **major mode** e possivelmente vários **minor modes**. + + - O **major mode** define o principal comportamento do Emacs no buffer atualmente selecionado. Isso pode ser pensado como o tipo de arquivo. Por exemplo, se você estiver editando um arquivo Python, os principais modes é (por padrão) `python-mode`, que faz com que o Emacs destaque a sintaxe Python e idente automaticamente seus blocos de código conforme exigido sintaticamente pelo seu código Python. + + - **Minor modes** definem mudanças sutis no comportamento e várias alterações menores Os modos podem estar ativos ao mesmo tempo no mesmo buffer. Um exemplo menor modo é o modo flyspell, que destaca automaticamente os erros de ortografia no seu buffer. + +# Recursos adicionais + + - [The GNU Emacs Manual](https://www.gnu.org/software/emacs/manual/emacs.html) + - [Emacs Stack Exchange](https://emacs.stackexchange.com/) + - [Emacs Wiki](https://www.emacswiki.org/emacs/EmacsWiki) diff --git a/pt-br/fsharp-pt.html.markdown b/pt-br/fsharp-pt.html.markdown new file mode 100644 index 00000000..55966cda --- /dev/null +++ b/pt-br/fsharp-pt.html.markdown @@ -0,0 +1,639 @@ +--- +language: F# +filename: learnfsharp-pt.fs +contributors: + - ["Scott Wlaschin", "http://fsharpforfunandprofit.com"] + - ["Adelar da Silva Queiróz", "https://adelarsq.github.io"] +lang: pt-br +--- + +F# é uma linguagem de propósito geral funcional e orientada a objetos. É livre, de código aberto e executa em Linux, Mac, Windows e outros. + +Possui um sistema de tipagem poderoso que evita muitos erros em tempo de compilação. Para isto utilizando inferência de tipos, o que a faz se comportar como uma linguagem dinâmica. + +A sintaxe é diferente das linguagens do estilo C (C, C#, Java, etc): + +* Chaves não são usadas para delimitar blocos de código. Ao invés disso é utilizada indentação (semelhante ao Python). +* Espaços em branco são usados para separar parâmetros, ao invés de vírgulas. + +Se você deseja executar o código abaixo, copie e cole em [https://try.fsharp.org](https://try.fsharp.org), que é um REPL online. + +```fsharp + +// comentários de linhas únicas usam barras duplas +(* comentários de linhas múltiplas usam o par (* . . . *) + +-fim do comentário de linhas múltiplas- *) + +// ================================================ +// Sintaxe básica +// ================================================ + +// ------ "Variáveis" (mas não exatamente) ------ +// A palavra reservada "let" define um valor imutável +let myInt = 5 +let myFloat = 3.14 +let myString = "hello" // note que nenhum tipo é necessário + +// ------ Listas ------ +let twoToFive = [2; 3; 4; 5] // Colchetes criam uma lista com + // ponto e vírgula como delimitadores +let oneToFive = 1 :: twoToFive // :: cria uma lista com um novo primeiro elemento +// O resultado é [1; 2; 3; 4; 5] +let zeroToFive = [0; 1] @ twoToFive // @ concatena duas listas + +// IMPORTANTE: vírgulas nunca são usadas como delimitadores, somente ponto e vírgula! + +// ------ Funções ------ +// A palavra chave "let" também define nomes para funções. +let square x = x * x // Note que não são usados parêntesis +square 3 // Agora executando a função. Também sem parêntesis + +let add x y = x + y // Não use add (x,y)! Isto significa algo + // completamente diferente. +add 2 3 // Agora execute a função. + +// para definir uma função de múltiplas linhas apenas use indentação. Nenhum ponto e vírgula é necessário +let evens list = + let isEven x = x % 2 = 0 // Define "isEven"como uma sub função. Note + // que o operador de igualdade é um simples "=". + List.filter isEven list // List.filter é uma função da biblioteca padrão + // com dois parâmetros: uma função que retorna boolean + // e uma lista para verificar + +evens oneToFive // Agora executando a função + +// Usando parênteses é possível deixar mais clara a precedência. Neste exemplo, +// "map" é usado primeiro, com dois argumentos, então executa "sum" no resultado. +// Sem os parênteses, "List.map" seria passado como uma argumento para List.sum +let sumOfSquaresTo100 = + List.sum ( List.map square [1..100] ) + +// É possível redirecionar a saída de uma operação para a próxima usando pipe ("|>") +// Redirecimento de dados é algo comum em F#, similar a pipes Unix. + +// Aqui é a mesma função sumOfSquares escrita com pipe +let sumOfSquaresTo100piped = + [1..100] |> List.map square |> List.sum // "square" foi definido anteriormente + +// você pode definir lambdas (funções anônimas) usando a palavra reservada "fun" +let sumOfSquaresTo100withFun = + [1..100] |> List.map (fun x -> x * x) |> List.sum + +// Em F# não há a palavra chave "return". Funções sempre +// retornam o valor da última expressão usada. + +// ------ Casamento de padrões (Pattern Matching) ------ +// Match..with.. é um poderoso case/switch. +let simplePatternMatch = + let x = "a" + match x with + | "a" -> printfn "x is a" + | "b" -> printfn "x is b" + | _ -> printfn "x is something else" // sublinhado combina com qualquer coisa + +// F# não permite null por padrão -- deve-se usar um Option +// e então efetuar um casamento de padrão. +// Some(..) e None são análogos a Nullable +let validValue = Some(99) +let invalidValue = None + +// Neste exemplo, match..with casa com "Some" e "None", +// e também desconstrói o valor em "Some" ao mesmo tempo. +let optionPatternMatch input = + match input with + | Some i -> printfn "input is an int=%d" i + | None -> printfn "input is missing" + +optionPatternMatch validValue +optionPatternMatch invalidValue + +// ------ Escrevando na tela ------ +// As funções printf/printfn são similares às +// Console.Write/WriteLine encontradas no C#. +printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true +printfn "A string %s, and something generic %A" "hello" [1; 2; 3; 4] + +// Exitem também as funções sprintf/sprintfn para formatação de dados +// em uma string, semelhante à String.Format do C#. + +// ================================================ +// Mais sobre funções +// ================================================ + +// F# é uma liguagem verdadeiramente funcional -- funções fazem +// parte das classes e podem ser combinadas facilmente para criar +// poderosos construtores + +// Módulos podem usar um grupo de funções +// É necessário usar indentação para defini-las. +module FunctionExamples = + + // define uma função de soma + let add x y = x + y + + // básico uso de uma função + let a = add 1 2 + printfn "1 + 2 = %i" a + + // aplicação parcial de parâmetros + let add42 = add 42 + let b = add42 1 + printfn "42 + 1 = %i" b + + // composição para combinar funções + let add1 = add 1 + let add2 = add 2 + let add3 = add1 >> add2 + let c = add3 7 + printfn "3 + 7 = %i" c + + // funções de alta ordem + [1..10] |> List.map add3 |> printfn "new list is %A" + + // listas de funções e mais + let add6 = [add1; add2; add3] |> List.reduce (>>) + let d = add6 7 + printfn "1 + 2 + 3 + 7 = %i" d + +// ================================================ +// Listas e coleções +// ================================================ + +// Existem três tipos de coleções ordenadas: +// * Listas são o tipo mais básico de coleção imutável; +// * Arrays são mutáveis e mais eficientes; +// * Sequences são lazy e infinitas (semelhante a enumerator). +// +// Outras coleções incluem maps e conjuntos imutáveis +// mais todas as coleções padrões do .NET + +module ListExamples = + + // listas usam colchetes + let list1 = ["a"; "b"] + let list2 = "c" :: list1 // :: é usado para adicionar um elemento no início da lista + let list3 = list1 @ list2 // @ é o operador de concatenação + + // list comprehensions (generators) + let squares = [for i in 1..10 do yield i * i] + + // Um gerador de números primos + // - este usa a notação custa para casamento de padrões + // - (p::xs) significa 'primeiro :: cauda' da lista, e pode ser escrito como p :: xs + // isto significa que casa 'p' (o primeiro item da lista), e xs recebe o resto da lista + // que é chamdo de 'cons pattern' + // - usa a palavra chave 'rec', que é necessária quando se usa recursão + let rec sieve = function + | (p::xs) -> p :: sieve [ for x in xs do if x % p > 0 then yield x ] + | [] -> [] + let primes = sieve [2..50] + printfn "%A" primes + + // casamento de padrões (pattern matching) com listas + let listMatcher aList = + match aList with + | [] -> printfn "the list is empty" + | [first] -> printfn "the list has one element %A " first + | [first; second] -> printfn "list is %A and %A" first second + | first :: _ -> printfn "the list has more than two elements, first element %A" first + + listMatcher [1; 2; 3; 4] + listMatcher [1; 2] + listMatcher [1] + listMatcher [] + + // recursão usando listas + let rec sum aList = + match aList with + | [] -> 0 + | x::xs -> x + sum xs + sum [1..10] + + // ----------------------------------------- + // Funções da biblioteca padrão + // ----------------------------------------- + + // mapas + let add3 x = x + 3 + [1..10] |> List.map add3 + + // filtros + let even x = x % 2 = 0 + [1..10] |> List.filter even + + // muito mais -- veja a documentação + +module ArrayExamples = + + // arrays usam colchetes com barra vertical + let array1 = [| "a"; "b" |] + let first = array1.[0] // acesso por índice usando ponto + + // casamento de padrões (pattern matching) para arrays é feito da mesma forma que de listas + let arrayMatcher aList = + match aList with + | [| |] -> printfn "the array is empty" + | [| first |] -> printfn "the array has one element %A " first + | [| first; second |] -> printfn "array is %A and %A" first second + | _ -> printfn "the array has more than two elements" + + arrayMatcher [| 1; 2; 3; 4 |] + + // As funções da biblioteca padrão são as mesmas que para List + + [| 1..10 |] + |> Array.map (fun i -> i + 3) + |> Array.filter (fun i -> i % 2 = 0) + |> Array.iter (printfn "value is %i. ") + + +module SequenceExamples = + + // sequências usam chaves + let seq1 = seq { yield "a"; yield "b" } + + // sequências podem usar yield e + // podem conter subsequencias + let strange = seq { + // "yield" adiciona um elemento + yield 1; yield 2; + + // "yield!" adiciona uma subsequencia + yield! [5..10] + yield! seq { + for i in 1..10 do + if i % 2 = 0 then yield i }} + // teste + strange |> Seq.toList + + // Sequências podem ser criadas usando "unfold" + // Este é um exemplo da série de Fibonacci + let fib = Seq.unfold (fun (fst,snd) -> + Some(fst + snd, (snd, fst + snd))) (0,1) + + // teste + let fib10 = fib |> Seq.take 10 |> Seq.toList + printf "first 10 fibs are %A" fib10 + + +// ================================================ +// Tipos de dados +// ================================================ + +module DataTypeExamples = + + // Todos os dados são imutáveis por padrão + + // Tuplas são uma forma rápida de reprentar n elementos de tipos anônimos + // -- Use a vírgula para criar uma tupla + let twoTuple = 1, 2 + let threeTuple = "a", 2, true + + // Casamento de padrões (pattern match) para desconstruir + let x, y = twoTuple // atribui x = 1, y = 2 + + // ------------------------------------ + // O tipo registro possui nomes nos campos + // ------------------------------------ + + // Use "type" com chaves para definir um registro + type Person = {First:string; Last:string} + + // Use "let" com chaves para criar um registro + let person1 = {First="John"; Last="Doe"} + + // Casamento de padrões para desconstruir + let {First = first} = person1 // atribui first="John" + + // ------------------------------------ + // Tipos union (variantes) possuem um conjunto de escolhas + // Somente um caso pode ser válido por vez. + // ------------------------------------ + + // Use "type" com barra/pipe para definir um union + type Temp = + | DegreesC of float + | DegreesF of float + + // Use qualquer dos tipos para criar um + let temp1 = DegreesF 98.6 + let temp2 = DegreesC 37.0 + + // Casamento de padrões deve cobrir todos os tipos de definidos para desconstruir + let printTemp = function + | DegreesC t -> printfn "%f degC" t + | DegreesF t -> printfn "%f degF" t + + printTemp temp1 + printTemp temp2 + + // ------------------------------------ + // Tipos recursivos + // ------------------------------------ + + // Tipos podem ser combinados recursivamente de formas complexas + // sem ter que criar subclasses + type Employee = + | Worker of Person + | Manager of Employee list + + let jdoe = {First="John"; Last="Doe"} + let worker = Worker jdoe + + // ------------------------------------ + // Modelando com tipos + // ------------------------------------ + + // Tipos union são muito bons para modelagem de estados sem usar flags + type EmailAddress = + | ValidEmailAddress of string + | InvalidEmailAddress of string + + let trySendEmail email = + match email with // casamento de padrões + | ValidEmailAddress address -> () // envia + | InvalidEmailAddress address -> () // não envia + + // A combinação de tipos union e registros juntos + // provê uma grande fundação para DDD (Domain Driven Design). + // Você pode criar centenas de pequenos tipos que refletem + // exatamente o seu domínio. + + type CartItem = { ProductCode: string; Qty: int } + type Payment = Payment of float + type ActiveCartData = { UnpaidItems: CartItem list } + type PaidCartData = { PaidItems: CartItem list; Payment: Payment} + + type ShoppingCart = + | EmptyCart // nenhum dado + | ActiveCart of ActiveCartData + | PaidCart of PaidCartData + + // ------------------------------------ + // Comportamento padrão para tipos + // ------------------------------------ + + // Tipos padrões possuem um padrão já definido, não precisando de codificação nenhuma. + // * Imutáveis + // * Impressão formatada para depuração + // * Igualdade e comparação + // * Serialização + + // Impressão formatada usando %A + printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A" + twoTuple person1 temp1 worker + + // Igualdade e comparação padrão. + // Um exemplo com cartas: + type Suit = Club | Diamond | Spade | Heart + type Rank = Two | Three | Four | Five | Six | Seven | Eight + | Nine | Ten | Jack | Queen | King | Ace + + let hand = [ Club, Ace; Heart, Three; Heart, Ace; + Spade, Jack; Diamond, Two; Diamond, Ace ] + + // ordenando + List.sort hand |> printfn "sorted hand is (low to high) %A" + List.max hand |> printfn "high card is %A" + List.min hand |> printfn "low card is %A" + + +// ================================================ +// Padrões ativos (Active patterns) +// ================================================ + +module ActivePatternExamples = + + // F# possui um tipo especial de casamento de padrões chamado "padrões ativos" ("active patterns") + // onde o padrão pode ser interpretado ou detectado dinamicamente. + + // parêntesis e barra são a sintaxe para "padrões ativos" + + // Você pode usar "elif" ao invés de "else if" em expressões condicionais. + // Elas são equivalentes em F# + + // por exemplo, defina um "padrão ativo" para tratar tipos de caracteres... + let (|Digit|Letter|Whitespace|Other|) ch = + if System.Char.IsDigit(ch) then Digit + elif System.Char.IsLetter(ch) then Letter + elif System.Char.IsWhiteSpace(ch) then Whitespace + else Other + + // ... e então use ele para interpretar de forma bem mais simples + let printChar ch = + match ch with + | Digit -> printfn "%c is a Digit" ch + | Letter -> printfn "%c is a Letter" ch + | Whitespace -> printfn "%c is a Whitespace" ch + | _ -> printfn "%c is something else" ch + + // imprima a lista + ['a'; 'b'; '1'; ' '; '-'; 'c'] |> List.iter printChar + + // ------------------------------------------------ + // FizzBuzz usando padrões ativos (active patterns) + // ------------------------------------------------ + + // É possível criar casamento de padrões parcial também + // Apenas use sublinhado para a definição, e retorne Some se casado. + let (|MultOf3|_|) i = if i % 3 = 0 then Some MultOf3 else None + let (|MultOf5|_|) i = if i % 5 = 0 then Some MultOf5 else None + + // a função principal + let fizzBuzz i = + match i with + | MultOf3 & MultOf5 -> printf "FizzBuzz, " + | MultOf3 -> printf "Fizz, " + | MultOf5 -> printf "Buzz, " + | _ -> printf "%i, " i + + // teste + [1..20] |> List.iter fizzBuzz + +// ================================================ +// Expressividade +// ================================================ + +module AlgorithmExamples = + + // F# possui uma alta razão sinais/ruídos, assim o código + // é lido praticamento como se descreve o algoritmo + + // ------ Exemplo: defina uma função que faça soma dos quadrados ------ + let sumOfSquares n = + [1..n] // 1) pega todos os números de 1 a n + |> List.map square // 2) eleva ao quadrado cada um + |> List.sum // 3) soma os resultados + + // teste + sumOfSquares 100 |> printfn "Sum of squares = %A" + + // ------ Examplo: defina uma função de ordenação ------ + let rec sort list = + match list with + // Se a lista está vazia + | [] -> + [] // retorna a lista vazia + // Se a lista não está vazia + | firstElem::otherElements -> // pega o primeiro elemento + let smallerElements = // extrai os elementos menores + otherElements // dos restantes + |> List.filter (fun e -> e < firstElem) + |> sort // e ordena eles + let largerElements = // extrai os elementos maiores + otherElements // dos restantes + |> List.filter (fun e -> e >= firstElem) + |> sort // e ordena eles + // Combine as 3 partes em uma nova lista e retorne ela + List.concat [smallerElements; [firstElem]; largerElements] + + // teste + sort [1; 5; 23; 18; 9; 1; 3] |> printfn "Sorted = %A" + +// ================================================ +// Código assíncrono +// ================================================ + +module AsyncExample = + + // F# possui suporte a funcionalidades para ajudar a escrever código assíncrono + // sem tornar o código difícil de manter ("pyramid of doom") + // + // O seguinte exemplo efetua download de um conjunto de páginas em paralelo. + + open System.Net + open System + open System.IO + open Microsoft.FSharp.Control.CommonExtensions + + // Obtém o conteúdo de cara página de forma assíncrona + let fetchUrlAsync url = + async { // a palavra chave "async" e chaves + // criam um objeto assíncrono + let req = WebRequest.Create(Uri(url)) + use! resp = req.AsyncGetResponse() + // use! é uma atribuição assíncrona + use stream = resp.GetResponseStream() + // "use" dispara automaticamente close() + // no recurso no fim do escopo + use reader = new IO.StreamReader(stream) + let html = reader.ReadToEnd() + printfn "finished downloading %s" url + } + + // uma lista de sites para fazer download + let sites = ["http://www.bing.com"; + "http://www.google.com"; + "http://www.microsoft.com"; + "http://www.amazon.com"; + "http://www.yahoo.com"] + + // efetue + sites + |> List.map fetchUrlAsync // cria uma lista de tarefas assíncronas + |> Async.Parallel // coloca as tarefas para executarem em paralelo + |> Async.RunSynchronously // inicia cada uma + +// ================================================ +// Compatibilidade com .NET +// ================================================ + +module NetCompatibilityExamples = + + // F# pode pode fazer praticamente tudo que C# pode fazer, e integra + // de forma simples com bibliotecas .NET e Mono + + // ------- usando uma função de uma biblioteca existente ------- + + let (i1success, i1) = System.Int32.TryParse("123"); + if i1success then printfn "parsed as %i" i1 else printfn "parse failed" + + // ------- Implementando interfaces de forma simples! ------- + + // cria um novo objeto que implementa IDisposable + let makeResource name = + { new System.IDisposable + with member this.Dispose() = printfn "%s disposed" name } + + let useAndDisposeResources = + use r1 = makeResource "first resource" + printfn "using first resource" + for i in [1..3] do + let resourceName = sprintf "\tinner resource %d" i + use temp = makeResource resourceName + printfn "\tdo something with %s" resourceName + use r2 = makeResource "second resource" + printfn "using second resource" + printfn "done." + + // ------- Código orientado a objetos ------- + + // F# também possui suporte a orientação a objetos. + // Possui suporte a classes, herança, métodos virtuais, etc. + + // interface com tipo genérico + type IEnumerator<'a> = + abstract member Current : 'a + abstract MoveNext : unit -> bool + + // classe base abstrata com métodos virtuais + [<AbstractClass>] + type Shape() = + // propriedades somente leitura + abstract member Width : int with get + abstract member Height : int with get + // método não virtual + member this.BoundingArea = this.Height * this.Width + // método virtual com implementação base + abstract member Print : unit -> unit + default this.Print () = printfn "I'm a shape" + + // classe concreta que herda da classe base e sobrescreve + type Rectangle(x:int, y:int) = + inherit Shape() + override this.Width = x + override this.Height = y + override this.Print () = printfn "I'm a Rectangle" + + // testes + let r = Rectangle(2, 3) + printfn "The width is %i" r.Width + printfn "The area is %i" r.BoundingArea + r.Print() + + // ------- métodos de extensão ------- + + // Assim como em C#, F# pode extender classes já existentes com métodos de extensão. + type System.String with + member this.StartsWithA = this.StartsWith "A" + + // testes + let s = "Alice" + printfn "'%s' starts with an 'A' = %A" s s.StartsWithA + + // ------- eventos ------- + + type MyButton() = + let clickEvent = new Event<_>() + + [<CLIEvent>] + member this.OnClick = clickEvent.Publish + + member this.TestEvent(arg) = + clickEvent.Trigger(this, arg) + + // teste + let myButton = new MyButton() + myButton.OnClick.Add(fun (sender, arg) -> + printfn "Click event with arg=%O" arg) + + myButton.TestEvent("Hello World!") + +``` + +## Mais Informações + +Para mais demonstrações de F# acesse [why use F#](http://fsharpforfunandprofit.com/why-use-fsharp/). + +Leia mais sobre F# em [fsharp.org](http://fsharp.org/) e [dotnet's F# page](https://dotnet.microsoft.com/languages/fsharp). diff --git a/pt-br/git-pt.html.markdown b/pt-br/git-pt.html.markdown index e59ba901..2cc1c337 100644 --- a/pt-br/git-pt.html.markdown +++ b/pt-br/git-pt.html.markdown @@ -11,6 +11,7 @@ contributors: translators: - ["Suzane Sant Ana", "http://github.com/suuuzi"] - ["Bruno Volcov", "http://github.com/volcov"] + - ["Marcel Ribeiro-Dantas", "http://github.com/mribeirodantas"] --- Git é um sistema distribuido de gestão para código fonte e controle de versões. @@ -67,7 +68,8 @@ referências e outros. ### *Working Tree* (componente do repositório) -A *Working Tree* é basicamente a listagem dos diretórios e arquivos do repositório. É chamada também de diretório do projeto. +A *Working Tree* é basicamente a listagem dos diretórios e arquivos do +repositório. É chamada também de diretório do projeto. ### *Index* (componente do diretório .git) @@ -77,28 +79,37 @@ maior controle sobre o que é registado no repositório git. ### *Commit* -Um *commit** de git é um registo de um cojunto de alterações ou manipulações nos arquivos do projeto. -Por exemplo, ao adicionar cinco arquivos e remover outros 2, estas alterações -serão gravadas num *commit* (ou registo). Este *commit* pode então ser enviado -para outros repositórios ou não! +Um *commit** de git é um registo de um conjunto de alterações ou manipulações +nos arquivos do projeto. Por exemplo, ao adicionar cinco arquivos e remover +outros 2, estas alterações serão gravadas em um *commit* (ou registro). Este +*commit* pode então ser enviado para outros repositórios, caso você queira. ### *Branch* -Um *branch* é essencialmente uma referência que aponta para o último *commit* +Uma *branch* é essencialmente uma referência que aponta para o último *commit* efetuado. Na medida que são feitos novos commits, esta referência é atualizada automaticamente e passa a apontar para o commit mais recente. ### *Tag* Uma tag é uma marcação em um ponto específico da história. Geralmente as -pessoas usam esta funcionalidade para marcar pontos de release (v2.0, e por aí vai) +pessoas usam esta funcionalidade para marcar pontos de release (v2.0, e por aí +vai) ### *HEAD* e *head* (componentes do diretório .git) -*HEAD* é a referência que aponta para o *branch* em uso. Um repositório só tem -uma *HEAD* activa. -*head* é uma referência que aponta para qualquer *commit*. Um repositório pode -ter um número indefinido de *heads* +*HEAD* é a referência que aponta para a *branch* em uso. Um repositório só tem +uma *HEAD* activa. *head* é uma referência que aponta para qualquer *commit*. Um +repositório pode ter um número indefinido de *heads*. + +### Estados no Git + +* Modificado (Modified): Ocorreram mudanças em ao menos um arquivo mas essas +mudanças ainda não foram registradas na base de dados do Git +* Preparado (Staged): Marca o arquivo como preparado para ser adicionado ao +próximo commit +* Consolidado (Committed): As mudanças foram registradas na base de dados do +Git ### Recursos conceituais (EN) @@ -109,8 +120,8 @@ ter um número indefinido de *heads* ### *init* -Cria um repositório Git vazio. As definições, informação guardada e outros do -repositório git são guardados em uma pasta chamada ".git". +Cria um repositório Git vazio. As configurações do repositório, e outras +informações são guardadas em uma pasta dentro do repositório com o nome ".git". ```bash $ git init @@ -118,23 +129,24 @@ $ git init ### *config* -Permite configurar as definições, sejam as definições do repositório, sistema -ou configurações globais. +Permite configurar o git, seja com respeito a definições deste repositório, +do sistema ou configurações globais para todos os repositórios. ```bash -# Imprime e define algumas variáveis de configuração básicas (global) -$ git config --global user.email -$ git config --global user.name - +# Define e imprime algumas variáveis de configuração básicas (global) $ git config --global user.email "MyEmail@Zoho.com" $ git config --global user.name "My Name" + +$ git config --global user.email +$ git config --global user.name ``` [Aprenda mais sobre git config. (EN)](http://git-scm.com/docs/git-config) ### help -Para visualizar rapidamente o detalhamento de cada comando ou apenas lembrar da semântica. +Para visualizar rapidamente o detalhamento de cada comando ou apenas lembrar da +semântica. ```bash # Ver rapidamente os comandos disponiveis @@ -148,16 +160,32 @@ $ git help -a $ git help add $ git help commit $ git help init +# ou git <comando_aqui> --help +$ git add --help +$ git commit --help +$ git init --help +``` + +### Ignorando arquivos + +É possível intencionalmente ignorar arquivos e pastas. Costuma-se utilizar o +arquivo .gitignore para fazer o git ignorar a existência de arquivos e pastas +geralmente utilizados para arquivos privados ou temporários que, de outro modo, +seriam compartilhados com todos que tem acesso ao repositório. + +```bash +$ echo "temp/" >> .gitignore +$ echo "chave_privada" >> .gitignore ``` ### status -Apresenta as diferenças entre o arquivo *index* (a versão corrente -do repositório) e o *commit* da *HEAD* atual. +Apresenta as diferenças entre o arquivo *index* (a versão corrente do +repositório) e o *commit* da *HEAD* atual. ```bash -# Apresenta o *branch*, arquivos não monitorados, alterações e outras +# Apresenta a *branch*, arquivos não monitorados, alterações e outras # diferenças $ git status @@ -173,35 +201,42 @@ incluidos nos commits! ```bash # adiciona um arquivo no diretório do projeto atual -$ git add HelloWorld.java +$ git add OlaMundo.java -# adiciona um arquivo num sub-diretório -$ git add /path/to/file/HelloWorld.c +# adiciona um arquivo em um sub-diretório +$ git add /caminho/para/arquivo/OlaMundo.java # permite usar expressões regulares! $ git add ./*.java + +# Você também pode adicionar tudo no seu diretório de trabalho como alterações +prontas para o próximo commit. +$ git add -A ``` +Esse comando apenas adiciona os arquivos no estado de preparados para o próximo +commit, mas não realiza o commit de fato. + ### branch -Gerencia os *branches*. É possível ver, editar, criar e apagar branches com este +Gerencia as *branches*. É possível ver, editar, criar e apagar branches com este comando. ```bash # listar *branches* existentes e remotos $ git branch -a -# criar um novo *branch* +# criar uma nova *branch* $ git branch myNewBranch -# apagar um *branch* +# apagar uma *branch* $ git branch -d myBranch -# alterar o nome de um *branch* +# alterar o nome de uma *branch* # git branch -m <oldname> <newname> $ git branch -m myBranchName myNewBranchName -# editar a descrição de um *branch* +# editar a descrição de uma *branch* $ git branch myBranchName --edit-description ``` @@ -212,18 +247,22 @@ Gerencia as *tags* ```bash # Listar tags $ git tag + # Criar uma tag anotada. # O parâmetro -m define uma mensagem, que é armazenada com a tag. # Se você não especificar uma mensagem para uma tag anotada, # o Git vai rodar seu editor de texto para você digitar alguma coisa. $ git tag -a v2.0 -m 'minha versão 2.0' + # Mostrar informações sobre a tag # O comando mostra a informação da pessoa que criou a tag, # a data de quando o commit foi taggeado, # e a mensagem antes de mostrar a informação do commit. $ git show v2.0 + # Enviar uma tag para o repositório remoto $ git push origin v2.0 + # Enviar várias tags para o repositório remoto $ git push origin --tags ``` @@ -231,14 +270,16 @@ $ git push origin --tags ### checkout Atualiza todos os arquivos no diretório do projeto para que fiquem iguais -à versão do index ou do *branch* especificado. +à versão do index ou da *branch* especificado. ```bash -# Checkout de um repositório - por padrão para o branch master +# Checkout de um repositório - por padrão para a branch master $ git checkout -# Checkout de um branch especifico + +# Checkout de uma branch especifica $ git checkout branchName -# Cria um novo branch e faz checkout para ele. + +# Cria uma nova branch e faz checkout para ela. # Equivalente a: "git branch <name>; git checkout <name>" $ git checkout -b newBranch ``` @@ -246,22 +287,41 @@ $ git checkout -b newBranch ### clone Clona ou copia um repositório existente para um novo diretório. Também -adiciona *branches* de monitoramento remoto para cada *branch* no repositório -clonado o que permite enviar alterações para um *branch* remoto. +adiciona *branches* no repositório clonado para cada *branch* no repositório +remoto o que permite enviar alterações para uma *branch* no repositório remoto. ```bash # Clona learnxinyminutes-docs $ git clone https://github.com/adambard/learnxinyminutes-docs.git + +# Clone superficial - É mais rápido, mas puxa apenas o último commit +$ git clone --depth 1 https://github.com/adambard/learnxinyminutes-docs.git + +# Clona apenas uma branch em específica +$ git clone -b master-cn https://github.com/adambard/learnxinyminutes-docs.git --single-branch ``` ### commit -Guarda o conteudo atual do index num novo *commit*. Este *commit* contém +Guarda o conteúdo atual do index em um novo *commit*. Este *commit* contém as alterações feitas e a mensagem criada pelo usuário. ```bash -# commit com uma mensagem -$ git commit -m "Added multiplyNumbers() function to HelloWorld.c" +# Realiza um commit com uma mensagem +$ git commit -m "Adicione a função multipliqueNumeros() em OlaMundo.c" + +# Assine um commit com sua chave GPG. Antes disso, você precisa ter +# configurado a opção user.signkey do git com o comando: +# git config --global user.signinkey ID_CHAVE_AQUI +$ git commit -S -m "mensagem do commit aqui" + +# Automaticamente adicione como preparados arquivos modificados ou apagados e +# então realize um commit: +$ git commit -a -m "Modified foo.php and removed bar.php" + +# Altere o último commit (Esse comando cria um novo commit com o conteúdo do +# commit anterior mais suas novas alterações e sobrescreve o último commit) +$ git commit --amend -m "Correct message" ``` ### diff @@ -282,7 +342,7 @@ $ git diff HEAD ### grep -Permite procurar facilmente num repositório +Permite procurar facilmente em um repositório. Configurações opcionais: @@ -313,74 +373,158 @@ Apresenta commits do repositório. # Apresenta todos os commits $ git log -# Apresenta X commits -$ git log -n 10 +# Apresenta apenas mensagem do commit e referência +$ git log --oneline # Apresenta apenas commits de merge $ git log --merges + +# Apresenta todos os commits representados por um gráfico em ASCII +$ git log --graph ``` ### merge -"Merge" junta as alterações de commits externos com o *branch* atual. +"Merge" junta as alterações de commits externos com a *branch* atual. ```bash -# Junta o branch especificado com o atual +# Junta a branch especificada com o atual $ git merge branchName -# Para gerar sempre um commit ao juntar os branches +# Para gerar sempre um commit ao juntar as branches $ git merge --no-ff branchName ``` ### mv -Alterar o nome ou mover um arquivo. +Altera o nome ou move um arquivo. ```bash # Alterar o nome de um arquivo -$ git mv HelloWorld.c HelloNewWorld.c +$ git mv OlaMundo.c OlaNovoMundo.c # Mover um arquivo -$ git mv HelloWorld.c ./new/path/HelloWorld.c +$ git mv OlaMundo.c ./novo/caminho/OlaMundo.c -# Forçar a alteração de nome ou mudança local -# "existingFile" já existe no directório, será sobrescrito. +# Forçar a alteração de nome ou mudança de local +# Se o arquivo já existir no diretório, será sobrescrito. $ git mv -f myFile existingFile ``` ### pull -Puxa alterações de um repositório e as junta com outro branch +Puxa alterações de um repositório e as junta com outra branch ```bash # Atualiza o repositório local, juntando as novas alterações # do repositório remoto 'origin' e branch 'master' # git pull <remote> <branch> -# git pull => aplica a predefinição => git pull origin master $ git pull origin master -# Juntar alterações do branch remote e fazer rebase commits do branch +# Por padrão, o git irá realizar o pull na branch atual fazendo um merge +# com as alterações novas na branch remota +$ git pull + +# Juntar alterações da branch remote e fazer rebase commits da branch # no repositório local, como: "git pull <remote> <branch>, git rebase <branch>" $ git pull origin master --rebase ``` ### push -Enviar e juntar alterações de um branch para o seu branch correspondente -num repositório remoto. +Enviar e juntar alterações de uma branch para a sua branch correspondente +em um repositório remoto. ```bash # Envia e junta as alterações de um repositório local -# para um remoto denominado "origin" no branch "master". +# para um remoto denominado "origin" na branch "master". # git push <remote> <branch> -# git push => aplica a predefinição => git push origin master $ git push origin master + +# Por padrão, o git push irá enviar e realizar merge das mudanças da sua branch +# local com a branch remota +$ git push + +# Para associar a branch local com uma branch específica remota, adicione a +# flag -u +$ git push -u origin master + +# Agora, sempre que você realizar um push daquela branch local, use o atalho: +$ git push ``` +### stash + +O objetivo desse comando do git é pegar o estado "sujo" do seu diretório de +trabalho, que não está pronto (staged), e salvá-lo em um outro lugar para que +você possa trabalhar no seu repositório do zero, mas sem perder as mudanças que +fez. Em qualquer outro momento que você quiser, você pode trazer de volta as +alterações que você tirou dali com o comando stash. + +Digamos que você tem feito algumas alterações no seu repositório, mas agora +você quer realizar um pull do repositório remoto. Como você tem alterações não +commitadas no seu diretório (ele está "sujo"), você não irá conseguir realizar +o `git pull` com sucesso. Mas você pode executar o `git stash` para salvar +essas alterações e conseguir realizar o pull. Depois, você traz de volta. + +```bash +$ git stash +Saved working directory and index state \ + "WIP on master: 049d078 added the index file" + HEAD is now at 049d078 added the index file + (To restore them type "git stash apply") +``` + +Agora você irá conseguir realizar o pull! + +```bash +git pull +``` +`...changes apply...` + +Verifique se está tudo OK com o `git status` + +```bash +$ git status +# On branch master +nothing to commit, working directory clean +``` + +É possível verificar as alterações que você guardou com cada uso do comando +`git stash` com o `git stash list`. Como os usos desse comando são guardados +como em uma pilha, os usos mais recentes estarão no topo. + +```bash +$ git stash list +stash@{0}: WIP on master: 049d078 added the index file +stash@{1}: WIP on master: c264051 Revert "added file_size" +stash@{2}: WIP on master: 21d80a5 added number to log +``` + +Agora vamos trazer o que havíamos salvado com o `git stash` de volta para o +diretório de trabalho. + +```bash +$ git stash pop +# On branch master +# Changes not staged for commit: +# (use "git add <file>..." to update what will be committed) +# +# modified: index.html +# modified: lib/simplegit.rb +# +``` + +`git stash apply` faz a mesma coisa + +Agora podemos voltar a trabalhar no que havíamos deixado de lado! + +[Additional Reading.](http://git-scm.com/book/en/v1/Git-Tools-Stashing) + ### rebase (cautela!) -Pega em todas as alterações que foram registadas num branch e volta a -aplicá-las em outro branch. +Pega em todas as alterações que foram registadas em uma branch e volta a +aplicá-las em outra branch. *Não deve ser feito rebase de commits que foram enviados para um repositório público* @@ -407,31 +551,79 @@ $ git reset # sobrescreve o projeto atual $ git reset --hard -# Move a head do branch atual para o commit especificado, sem alterar o projeto. +# Move a head da branch atual para o commit especificado, sem alterar o projeto. # todas as alterações ainda existem no projeto $ git reset 31f2bb1 -# Inverte a head do branch atual para o commit especificado +# Inverte a head da branch atual para o commit especificado # fazendo com que este esteja em sintonia com o diretório do projeto -# Remove alterações não registadas e todos os commits após o commit especificado +# Remove alterações não registradas e todos os commits após o commit +# especificado $ git reset --hard 31f2bb1 ``` +### reflog (cuidado!) + +O reflog irá listar a maior parte dos comandos que você realizou no git em um +determinado intervalo de tempo. O intervalo padrão é de 90 dias. + +Isso te dá a oportunidade de reverter qualquer comando que você realizou no git +e que tenha tido consequências indesejadas (por exemplo, se um rebase quebrou +sua aplicação). + +Você pode fazer assim: + +1. `git reflog` para listar todos os comandos utilizados no git para o rebase + +``` +38b323f HEAD@{0}: rebase -i (finish): returning to refs/heads/feature/add_git_reflog +38b323f HEAD@{1}: rebase -i (pick): Clarify inc/dec operators +4fff859 HEAD@{2}: rebase -i (pick): Update java.html.markdown +34ed963 HEAD@{3}: rebase -i (pick): [yaml/en] Add more resources (#1666) +ed8ddf2 HEAD@{4}: rebase -i (pick): pythonstatcomp spanish translation (#1748) +2e6c386 HEAD@{5}: rebase -i (start): checkout 02fb96d +``` +2. Selecione para onde você quer resetar. No nosso exemplo, seria o commit +`2e6c386`, ou `HEAD@{5}` +3. 'git reset --hard HEAD@{5}' esse comando irá resetar o seu repositório para +aquele ponto (5 commits atrás). +4. Agora você pode recomeçar o rebase ou apenas deixar como está. + +[Leitura complementar](https://git-scm.com/docs/git-reflog) + +### revert + +O comando revert pode ser utilizado para desfazer um commit. Não deve ser +confundido com o comando reset que restabelece o estado do repositório para um +momento anterior. O revert irá criar um novo commit com alterações inversas a +de um outro commit especificado, portanto revertendo aquelas alterações. + +```bash +# Revertendo um commit específico +$ git revert <commit> +``` + ### rm -O oposto de git add, git rm remove arquivos do branch atual. +O oposto de git add, git rm remove arquivos da branch atual. ```bash -# remove HelloWorld.c -$ git rm HelloWorld.c +# remove OlaMundo.c +$ git rm OlaMundo.c -# Remove um arquivo de um sub-directório -$ git rm /pather/to/the/file/HelloWorld.c +# Remove um arquivo de um sub-diretório +$ git rm /caminho/para/o/arquivo/OlaMundo.c ``` -## Informação complementar (EN) +## Leitura complementar + +* [Configurar o Git (GitHub Docs)](https://docs.github.com/pt/get-started/quickstart/set-up-git) + +* [Learn Git Branching - the most visual and interactive way to learn Git on the web](http://learngitbranching.js.org/) -* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1) +* [Udemy Git Tutorial: A Comprehensive Guide](https://blog.udemy.com/git-tutorial-a-comprehensive-guide/) + +* [Git Immersion - A Guided tour that walks through the fundamentals of git](http://gitimmersion.com/) * [git-scm - Video Tutorials](http://git-scm.com/videos) @@ -441,4 +633,10 @@ $ 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/) +* [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html) + +* [Pro Git (em Português)](https://www.git-scm.com/book/pt-br/v2) + +* [An introduction to Git and GitHub for Beginners (Tutorial)](http://product.hubspot.com/blog/git-and-github-tutorial-for-beginners) + +* [The New Boston tutorial to Git covering basic commands and workflow](https://www.youtube.com/playlist?list=PL6gx4Cwl9DGAKWClAD_iKpNC0bGHxGhcx) diff --git a/pt-br/go-pt.html.markdown b/pt-br/go-pt.html.markdown index 31473ee1..ce10e079 100644 --- a/pt-br/go-pt.html.markdown +++ b/pt-br/go-pt.html.markdown @@ -28,7 +28,7 @@ Go vem com uma biblioteca padrão exaustiva e uma comunidade entusiasta. várias linhas */ // A cláusula package aparece no início de cada arquivo. -// Main é um nome especial declarando um executável ao invés de uma biblioteca. +// main é um nome especial declarando um executável ao invés de uma biblioteca. package main // A cláusula Import declara os pacotes referenciados neste arquivo. @@ -77,7 +77,7 @@ pode incluir quebras de linha.` // mesmo tipo string // literal não-ASCII. A linguagem Go utiliza de raiz a codificação UTF-8. g := 'Σ' // tipo rune, um alias para int32, que contém um código unicode - f := 3.14195 // float64, número de vírgula flutuante de 64bit (IEEE-754) + f := 3.14159 // float64, número de vírgula flutuante de 64bit (IEEE-754) c := 3 + 4i // complex128, representado internamente com dois float64s // Declaração de variáveis, com inicialização. @@ -295,17 +295,17 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { ## Leitura Recomendada -A principal fonte de informação é o [web site oficial Go](http://golang.org/). +A principal fonte de informação é o [web site oficial Go](https://go.dev/). Lá é possível seguir o tutorial, experimentar de forma iterativa, e ler muito. A própria especificação da linguagem é altamente recomendada. É fácil de ler e incrivelmente curta (em relação ao que é habitual hoje em dia). Na lista de leitura para os aprendizes de Go deve constar o [código fonte da -biblioteca padrão](http://golang.org/src/pkg/). Exaustivamente documentado, é +biblioteca padrão](https://go.dev/src/). Exaustivamente documentado, é a melhor demonstração de código fácil de ler e de perceber, do estilo Go, e da sua escrita idiomática. Ou então clique no nome de uma função na [documentação] -(http://golang.org/pkg/) e veja o código fonte aparecer! +(https://go.dev/pkg/) e veja o código fonte aparecer! Outra ótima fonte para aprender Go é o [Go by example](https://gobyexample.com/). Apesar de ser em inglês, é possível recodificar os exemplos para aprender sobre diff --git a/pt-br/groovy-pt.html.markdown b/pt-br/groovy-pt.html.markdown index 1eab9cc3..dff3f2e1 100644 --- a/pt-br/groovy-pt.html.markdown +++ b/pt-br/groovy-pt.html.markdown @@ -5,7 +5,8 @@ filename: learngroovy-pt.groovy contributors: - ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"] translators: - - ["João Farias", "https://github.com/JoaoGFarias"] + - ["João Farias", "https://github.com/joaogfarias"] + - ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"] lang: pt-br --- @@ -14,7 +15,7 @@ Groovy - Uma linguagem dinâmica para a plataforma Java. [Leia mais aqui.](http: ```groovy /* - Prepara-se: + Prepare-se: 1) Instale a máquina virtual de Groovy - http://gvmtool.net/ 2) Instale o Groovy: gvm install groovy @@ -104,7 +105,7 @@ tecnologiasOrdenadas = tecnologias.sort( false ) /*** Manipulando listas ***/ -//Substitue todos os elementos da lista +//Substitui todos os elementos da lista Collections.replaceAll(tecnologias, 'Gradle', 'gradle') //Desorganiza a lista @@ -159,7 +160,7 @@ println devMap.values() usará este campo. * Se você quer uma propriedade private ou protected, você deve prover seus - próprios getters e setter, que devem ser declarados como private ou protected. + próprios getters e setters, que devem ser declarados como private ou protected. * Se você acessar uma propriedade dentro da classe e esta propriedade é definida em tempo de compilação com 'this', implícito ou explícito (por exemplo, @@ -201,8 +202,16 @@ if(x==1) { //Groovy também suporta o operador ternário def y = 10 -def x = (y > 1) ? "functionou" : "falhou" -assert x == "functionou" +def x = (y > 1) ? "funcionou" : "falhou" +assert x == "funcionou" + +//E suporta o 'The Elvis Operator' também! +//Em vez de usar o operador ternário: + +displayName = nome.name ? nome.name : 'Anonimo' + +//Podemos escrever: +displayName = nome.name ?: 'Anonimo' //Loop 'for' //Itera sobre um intervalo (range) @@ -236,7 +245,7 @@ assert x.equals("Roberto Grails Groovy ") /* Operadores - Sobrecarregamento de Operadores para uma lsita dos operadores comuns que + Sobrecarga de Operadores para uma lista dos operadores comuns que Grooby suporta: http://www.groovy-lang.org/operators.html#Operator-Overloading @@ -254,7 +263,7 @@ def nomeUsuario = usuario?.nomeUsuario /* Closures - Um closure, em Grooby, é como um "bloco de código" ou um ponteiro para método. + Um closure, em Groovy, é como um "bloco de código" ou um ponteiro para método. É um pedação de código que é definido e executado em um momento posterior. Mais informação em: http://www.groovy-lang.org/closures.html @@ -269,7 +278,7 @@ clos() def soma = { a, b -> println a+b } soma(2,4) -//Closdures por referir-se a variáveis que não estão listadas em sua +//Closures podem referir-se a variáveis que não estão listadas em sua //lista de parêmetros. def x = 5 def multiplicarPor = { num -> num * x } @@ -309,7 +318,7 @@ chamaClosure(3, 4) /* Expando - A classe Expando é um bean dinâmico que permite adicionar propriedade e + A classe Expando é um bean dinâmico que permite adicionar propriedades e closures como métodos a uma instância desta classe http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html diff --git a/pt-br/haskell-pt.html.markdown b/pt-br/haskell-pt.html.markdown index 181aa471..c55a4c03 100644 --- a/pt-br/haskell-pt.html.markdown +++ b/pt-br/haskell-pt.html.markdown @@ -41,7 +41,7 @@ o desenvolvimento deste paradigma de programação. 7 * 7 -- 7 vezes 7 7 / 7 -- 7 dividido por 7 --- Divisões não são inteiras, são fracionádas por padrão da linguagem +-- Divisões não são inteiras, são fracionadas por padrão da linguagem 28736 / 82374 -- 0.3488479374559934 @@ -67,7 +67,7 @@ not False -- Nega uma falácia 7 > 7 -- 7 é maior que 7 ? -{- Haskell é uma linguagem que tem uma sintáxe bastante familiar na +{- Haskell é uma linguagem que tem uma sintaxe bastante familiar na matemática, por exemplo em chamadas de funções você tem: NomeFunção ArgumentoA ArgumentoB ArgumentoC ... diff --git a/pt-br/javascript-pt.html.markdown b/pt-br/javascript-pt.html.markdown index ed4a6ff3..e38804f3 100644 --- a/pt-br/javascript-pt.html.markdown +++ b/pt-br/javascript-pt.html.markdown @@ -2,7 +2,7 @@ language: javascript filename: javascript-pt.js contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["Willian Justen", "http://willianjusten.com.br"] @@ -20,8 +20,8 @@ que é um projeto que fornece um interpretador baseado no motor V8 do Google Chrome e está se tornando cada vez mais famoso. Feedback são muito apreciados! Você me encontrar em -[@adambrenecki](https://twitter.com/adambrenecki), ou -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). +[@ExcitedLeigh](https://twitter.com/ExcitedLeigh), ou +[l@leigh.net.au](mailto:l@leigh.net.au). ```js // Comentários são como em C. Comentários de uma linha começam com duas barras, @@ -361,7 +361,7 @@ myObj.myFunc(); // = "Olá mundo!" var myFunc = myObj.myFunc; myFunc(); // = undefined -// Inversamente, uma função pode ser atribuída a um objeto e ganhar a acesso +// Inversamente, uma função pode ser atribuída à um objeto e ganhar a acesso // através do `this`, até mesmo se ela não for chamada quando foi definida. var myOtherFunc = function(){ return this.myString.toUpperCase(); @@ -416,7 +416,7 @@ myNewObj.myNumber; // = 5 // vai olhar imediatamente para o seu prototype. // Algumas implementações em JS deixam você acessar o objeto prototype com a -// propriedade mágica `__proto__`. Enquanto isso é util para explicar +// propriedade mágica `__proto__`. Enquanto isso é útil para explicar // prototypes, não é parte de um padrão; nós vamos falar de algumas formas de // usar prototypes depois. @@ -489,7 +489,7 @@ if (0){ } // Entretanto, esses objetos encapsulados e as funções originais compartilham -// um mesmo prototype, portanto você pode adicionar funcionalidades a uma string, +// um mesmo prototype, portanto você pode adicionar funcionalidades à uma string, // por exemplo. String.prototype.firstCharacter = function(){ return this.charAt(0); diff --git a/pt-br/julia-pt.html.markdown b/pt-br/julia-pt.html.markdown index 48d97e58..52675bf5 100644 --- a/pt-br/julia-pt.html.markdown +++ b/pt-br/julia-pt.html.markdown @@ -8,7 +8,7 @@ translators: lang: pt-br --- -Julia é uma linguagem homoiconic funcional focada na computação tecnica. Ao mesmo tempo que ela tem todo o poder dos homoiconic macros, funções de primeira classe, e controle de baixo nivel, Julia é tão facil para aprender e usar quanto Python. +Julia é uma linguagem homoicônica funcional focada na computação técnica. Ao mesmo tempo que ela tem todo o poder dos macros homoicônicos, funções de primeira classe, e controle de baixo nível, Julia é tão fácil para aprender e usar quanto Python. Este tutorial é baseado no Julia 0.3. @@ -104,7 +104,7 @@ println("Eu sou Julia. Prazer em conhece-lo!") ## 2. Variáveis e coleções #################################################### -#Você não declara variáveis antes de atribui-lás. +#Você não declara variáveis antes de atribui-las. some_var = 5 # => 5 some_var # => 5 diff --git a/pt-br/kotlin-pt.html.markdown b/pt-br/kotlin-pt.html.markdown index 7c3313fc..bbe8c0d1 100644 --- a/pt-br/kotlin-pt.html.markdown +++ b/pt-br/kotlin-pt.html.markdown @@ -70,7 +70,7 @@ fun olaMundo(val nome : String) { println(umaStringModelo) /* - Para uma variável receber null deve-se explicitamente declara-la + Para uma variável receber null deve-se explicitamente declará-la como anulável. A declaração de anulável é realizada incluindo uma "?" ao fim do tipo. Pode-se acessar uma variável anulável usando o operador "?." @@ -166,7 +166,7 @@ fun olaMundo(val nome : String) { /* Classes de dados são um modo sucinto de criar classes que servem apenas - para guardas informações. + para guardar informações. Os métodos "hashCode", "equals" e "toString" são gerados automaticamente. */ data class ExemploClasseDados (val x: Int, val y: Int, val z: Int) diff --git a/pt-br/latex-pt.html.markdown b/pt-br/latex-pt.html.markdown index 103af28e..919c0f4f 100644 --- a/pt-br/latex-pt.html.markdown +++ b/pt-br/latex-pt.html.markdown @@ -8,6 +8,7 @@ contributors: - ["Svetlana Golubeva", "https://attillax.github.io/"] translators: - ["Paulo Henrique Rodrigues Pinheiro", "https://github.com/paulohrpinheiro"] + - ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"] lang: pt-br filename: learn-latex-pt.tex --- @@ -16,10 +17,10 @@ filename: learn-latex-pt.tex % Todas as linhas de comentários começam com % % Não existem comentários multilinhas -$ LaTeX não é um programa processador de textos "Visual" como +% LaTeX não é um programa processador de textos "Visual" como % MS Word ou OpenOffice Writer -$ Todo comando LaTeX começa com uma barra invertida (\) +% Todo comando LaTeX começa com uma barra invertida (\) % Documentos LaTeX começam com a definição do tipo que será % compilado % Os tipos de documento podem ser livro, relatório, apresentação, etc. @@ -37,14 +38,11 @@ $ Todo comando LaTeX começa com uma barra invertida (\) \usepackage{float} \usepackage{hyperref} -% Para poder usar caracteres acentuados, use o seguinte pacote: -\usepackage[utf8]{inputenc} - % Podemos definir algumas outras propriedades do documento também! \author{Chaitanya Krishna Ande, Colton Kohnke, Sricharan Chiruvolu \& \\ Svetlana Golubeva} \date{\today} -\title{Aprenda \LaTeX \hspace{1pt} em Y Minutos!} +\title{Aprenda \LaTeX{} em Y Minutos!} % Agora estamos prontos para começar o documento % Tudo antes dessa linha é chamado "preâmbulo". @@ -52,6 +50,7 @@ Svetlana Golubeva} % Se informarmos os campos author (autores), date (data), "title" (título), % LaTeX poderá cria uma página inicial para nós. \maketitle + % Se tivermos seções, poderemos criar uma tabela de conteúdo. Para isso, % o documento deve ser compilado duas vezes, para que tudo apareça na ordem % correta. @@ -62,14 +61,14 @@ Svetlana Golubeva} \newpage -% Muitos artigos de pesquisa possuem um resumo, e pode-se isar comandos +% Muitos artigos de pesquisa possuem um resumo, e pode-se usar comandos % predefinidos para isso. % Isso deve aparecer em sua ordem lógica, portanto, após o topo, % mas antes das seções principais do corpo. % Esse comando está disponível para os documentos do tipo artigo (article) % e relatório (report). \begin{abstract} - Documentação do \LaTeX \hspace{1pt} escrita em \LaTeX! Nada original! + Documentação do \LaTeX{} escrita em \LaTeX! Nada original! \end{abstract} % Comandos para seções são intuitivos. @@ -93,11 +92,17 @@ Muito melhor agora. Afinal nem todas as seções precisam ser numeradas! \section{Algumas notas sobre texto} -%\section{Espaçamento % É necessário mais informação sobre intervalos de espaço. -\LaTeX \hspace{1pt} geralmente é muito bom sobre colocar texto onde ele deve +%\section{Espaçamento} % É necessário mais informação sobre intervalos de espaço. +\LaTeX{} geralmente é muito bom sobre colocar texto onde ele deve ser posto. Se uma linha \\ deve \\ ser \\ quebrada \\ adicione \textbackslash\textbackslash -\hspace{1pt} ao código de seu documento. \\ +\hspace{1pt} ao código de seu documento. + +Separe parágrafos por linhas vazias. + +Você precisa adicionar um til após abreviações (se não forem seguidas de vírgula) +para um espaço sem quebra, senão o espaçamento após o ponto será muito largo: +E.g., i.e., etc.~são exemplos de abreviações. \section{Listas} Listas são uma das coisas mais fáceis de criar no \LaTeX! Preciso fazer compras @@ -112,21 +117,21 @@ amanhã, então façamos uma lista de compras. Não é um item da lista, mas faz parte do bloco enumerate. - \end{enumerate} % Todos os blocos devem ter um final (end{}). +\end{enumerate} % Todos os blocos devem ter um final (end{}). \section{Matemática} -Um dos usos iniciais para \LaTeX \hspace{1pt} foi a produção de artigos +Um dos usos iniciais para \LaTeX{} foi a produção de artigos acadêmicos e técnicos. Usualmente nos campos da matemática e ciência. Assim, é -necessários que consigamos incluir alguns símbolos especiais em nosso texto! \\ +necessários que consigamos incluir alguns símbolos especiais em nosso texto! A matemática tem muitos símbolos, além dos quais se pode encontrar no teclado; símbolos para relações e conjuntos, setas, operadores, e letras gregas, apenas -para mencionar alguns.\\ +para mencionar alguns. Conjuntos e relações são essenciais em muitos textos de pesquisa em matemática. Aqui está como você pode indicar como todo x que pertence -a X, $\forall$ x $\in$ X. \\ +a X, $\forall$ x $\in$ X. % Perceba que é necessário adicionar os sinais $ antes e depois dos símbolos. % Isso é porque quando escrevendo, estamos em modo texto. % Mas os símbolos de matemática só existem no modo matemática. @@ -138,15 +143,14 @@ a X, $\forall$ x $\in$ X. \\ \[a^2 + b^2 = c^2 \] Minha letra grega favorita é $\xi$. Eu também gosto da $\beta$, $\gamma$ e $\sigma$. -Eu ainda não encontrei uma letra grega que o \LaTeX \hspace{1pt} não tenha!\\ +Eu ainda não encontrei uma letra grega que o \LaTeX{} não tenha!\\ Operadores são parte essencial de um documento sobre matemática: funções trigonométricas ($\sin$, $\cos$, $\tan$), logaritmo e exponencial ($\log$, $\exp$), -limites ($\lim$), etc. -possuem comandos pré-definidos em LaTex. +limites ($\lim$), etc.~possuem comandos pré-definidos em LaTex. Vamos escrever uma equação para ver como se faz: -$\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$ \\ +$\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$ Frações (numerador/denominador) podem ser escritas dessa forma: @@ -183,8 +187,10 @@ Somatórios e Integrais são escritas com os comandos sum e int: \section{Figuras} -Insiramos uma Figura. O local para colocar a figura pode ser difícil -de determinar. Eu tenho sempre que verificar as opções toda vez. +Insiramos uma Figura. O local para colocar a figura pode ser difícil de determinar. +Operações básicas são [t] para o topo, [b] para base, [h] para aqui (aproximadamente). +Eu tenho sempre que verificar as opções toda vez. +% Veja https://en.wikibooks.org/wiki/LaTeX/Floats,_Figures_and_Captions para mais detalhes \begin{figure}[H] % H aqui é uma opção para o local da figura. \centering % centra a figura na página @@ -201,36 +207,45 @@ Também podemos incluir tabelas da mesma forma que figuras. \begin{table}[H] \caption{Título para a Tabela.} % os argumentos {} abaixo descrevem como cada linha da tabela é desenhada. - % Aqui também, Preciso ver isso. Toda. E. Cada. Vez. + % O básico é simples: uma letra para cada coluna, para controlar o alinhamento: + % Operações básicas são: c, l, r e p para centro, esquerda, direita e parágrafo + % opcionalmente, você pode adicionar um | para linha vertical + % Veja https://en.wikibooks.org/wiki/LaTeX/Tables para mais detalhes \begin{tabular}{c|cc} - Número & Sobrenome & Primeiro Nome \\ % Colunas são separadas por & + Número & Primeiro Nome & Sobrenome \\ % Colunas são separadas por & \hline % uma linha horizontal 1 & Biggus & Dickus \\ 2 & Monty & Python \end{tabular} + % Vai ficar mais ou menos assim: + % Número | Primeiro Nome Sobrenome + % -------|--------------------------- % por causa do \hline + % 1 | Biggus Dickus + % 2 | Monty Python \end{table} -\section{Fazendo o \LaTeX \hspace{1pt} não compilar algo (o código fonte)} +\section{Fazendo o \LaTeX{} não compilar algo (o código fonte)} Digamos que precisamos incluir algum código dentro do nosso -documento \LaTeX \hspace{1pt}, para isso precisamos com o \LaTeX \hspace{1pt} +documento \LaTeX{}, para isso precisamos com o \LaTeX{} não tente interpretar esse texto e que apenas inclua ele no documento. Fazemos isso com o bloco verbatim. % Existem outros pacotes (por exemplo, minty, lstlisting, etc.) % mas verbatim é o básico \begin{verbatim} - print("Hello World!") + print("Olá mundo!") a%b; % olha só! Podemos usar os sinais % no bloco verbatim. - random = 4; #decided by fair random dice roll + random = 4; #decidido por um lançamento honesto de dado + Veja https://www.explainxkcd.com/wiki/index.php/221:_Random_Number \end{verbatim} \section{Compilando} Imagino que agora você esteja pensando como compilar esse fantástico documento -e visualizar a gloriosa glória que é um pdf gerado por \LaTeX \hspace{1pt} pdf. +e visualizar a gloriosa glória que é um pdf gerado por \LaTeX{} pdf. (sim, esse documento é compilável). \\ -Finalizando o documento usando \LaTeX \hspace{1pt} consiste nos seguintes passos: +Finalizando o documento usando \LaTeX{} consiste nos seguintes passos: \begin{enumerate} \item Escrever o documento em texto puro (o ``código fonte''). \item Compilar o código fonte para gerar um pdf. @@ -240,7 +255,7 @@ Finalizando o documento usando \LaTeX \hspace{1pt} consiste nos seguintes passos \end{verbatim} \end{enumerate} -Existem editores de \LaTeX \hspace{1pt} que combinam os passos 1 e 2 no mesmo +Existem editores de \LaTeX{} que combinam os passos 1 e 2 no mesmo sistema de software. Assim, você pode ver o passo 1, mas não o passo 2 por completo. Passo 2 estará acontecendo escondido\footnote{Por exemplo, quando usar referências (como Equação~\ref{eq:pythagoras}), pode ser necessário executar o @@ -267,6 +282,27 @@ Existem dois tipos principais de links: URL visíveis \\ Esse pacote também produz uma lista de thumbnails no documento pdf gerado e ativa os links na tabela de conteúdo. +\section{Escrevendo em ASCII ou outras codificações} + +Por padrão, historicamente LaTeX aceita entradas que são puro ASCII (128), +mas não ASCII extendido, o que significa sem acentos (à, è etc.) e símbolos não latinos. + +É fácil inserir acentos e símbolos latinos básicos através de atalhos de barra invertida +como \,c, \'e, \`A, \ae e \oe etc. % Para ç, é, À, etc +% Veja https://en.wikibooks.org/wiki/LaTeX/Special_Characters#Escaped_codes para mais detalhes + +Para escrever diretamente em UTF-8 quando compilando com pdflatex, use +\begin{verbatim} + \usepackage[utf8]{inputenc} +\end{verbatim} +A fonte selecionada precisa suportar os glifos usados em seu documento. Você precisa adicionar +\begin{verbatim} + \usepackage[T1]{fontenc} +\end{verbatim} + +Desde LuaTeX e XeLaTeX, suporte para UTF-8 vem embutido por padrão, tornando a vida muito +mais fácil para escrever em alfabetos não latinos. + \section{End} Por enquanto é isso! @@ -276,7 +312,7 @@ Por enquanto é isso! \begin{thebibliography}{1} % como em outras listas, o comando \bibitem pode ser usado para itens da lista % cada entrada pode ser citada diretamente no corpo do texto - \bibitem{latexwiki} The amazing \LaTeX \hspace{1pt} wikibook: {\em + \bibitem{latexwiki} The amazing \LaTeX{} wikibook: {\em https://en.wikibooks.org/wiki/LaTeX} \bibitem{latextutorial} An actual tutorial: {\em http://www.latex-tutorial.com} \end{thebibliography} @@ -289,3 +325,6 @@ https://en.wikibooks.org/wiki/LaTeX} * The amazing LaTeX wikibook: [https://en.wikibooks.org/wiki/LaTeX](https://en.wikibooks.org/wiki/LaTeX) * An actual tutorial: [http://www.latex-tutorial.com/](http://www.latex-tutorial.com/) +* A quick guide for learning LaTeX: [Learn LaTeX in 30 minutes](https://www.overleaf.com/learn/latex/Learn_LaTeX_in_30_minutes) +* An interactive platform to learn LaTeX (installationfree) [learnlatex.org/](https://www.learnlatex.org/) +* Stack Exchange's question and answer site about TeX, LaTeX, ConTeXt, etc. [tex.stackexchange.com](https://tex.stackexchange.com/) diff --git a/pt-br/lua-pt.html.markdown b/pt-br/lua-pt.html.markdown new file mode 100644 index 00000000..4aaf3a1e --- /dev/null +++ b/pt-br/lua-pt.html.markdown @@ -0,0 +1,423 @@ +--- +language: Lua +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] +filename: learnlua-pt.lua +translators: + - ["Iaan Mesquita", "https://github.com/ianitow"] +lang: pt-br +--- + +```lua +-- Dois hífens começam um comentário de uma linha. + +--[[ + Adicionar dois [ ] (colchetes) criam um comentário + de múltiplas linhas. +--]] + +---------------------------------------------------- +-- 1. Variáveis e fluxo de controle. +---------------------------------------------------- + +num = 42 -- Todos os números são doubles. +-- Não se preocupe, doubles de 64-bits contém 52 bits para +-- armazenar corretamente valores int; a precisão da máquina +-- não é um problema para ints que são < 52 bits. + +s = 'alternados' -- String são imutáveis, como em Python. +t = "Aspas duplas também são válidas" +u = [[ Dois colchetes + começam e terminam + strings de múltiplas linhas.]] +t = nil -- Torna t undefined(indefinido); Lua tem um Garbage Collector. + +-- Blocos são representados com palavras do/end: +while num < 50 do + num = num + 1 -- Sem operadores do tipo ++ ou += +end + +--Cláusula If : +if num > 40 then + print('over 40') +elseif s ~= 'walternate' then -- ~= signfica não é igual. + -- Para fazer checagem use == como em Python; Funciona para comparar strings também. + io.write('not over 40\n') -- Padrão para saídas. +else + -- Variáveis são globais por padrão. + thisIsGlobal = 5 -- Camel case é o comum. + + -- Como fazer variáveis locais: + local line = io.read() -- Leia a proxima linha de entrada. + + -- Para concatenação de strings use o operador .. : + print('Winter is coming, ' .. line) +end + +-- Variáveis indefinidas são do tipo nil. +-- Isso não é um erro: +foo = anUnknownVariable -- Agora foo = nil. + +aBoolValue = false + +-- Apenas nil e false são do tipo falso; 0 e '' são verdadeiros! +if not aBoolValue then print('twas false') end + +-- 'or' e 'and' são operadores lógicos. +-- Esse operador em C/JS a?b:c , em lua seria o mesmo que: +ans = aBoolValue and 'yes' or 'no' --> 'no' + +karlSum = 0 +for i = 1, 100 do -- O intervalo inclui inicio e fim. + karlSum = karlSum + i +end + +-- Use "100, 1, -1" para um intervalo que diminui: +fredSum = 0 +for j = 100, 1, -1 do fredSum = fredSum + j end + +-- Em geral, o intervalo é começo, fim[, etapas]. + +-- Outro construtor de loop: +repeat + print('A estrada do futuro.') + num = num - 1 +until num == 0 + + +---------------------------------------------------- +-- 2. Funções. +---------------------------------------------------- + +function fib(n) + if n < 2 then return 1 end + return fib(n - 2) + fib(n - 1) +end + +-- Closures e Funções anônimas são permitidas: +function adder(x) + -- O retorno da função é criado quando adder é + -- chamado, e ele sabe o valor de x: + return function (y) return x + y end +end +a1 = adder(9) +a2 = adder(36) +print(a1(16)) --> 25 +print(a2(64)) --> 100 + +-- Retornos, chamadas de funções e atribuições, todos eles trabalham +-- com listas que podem ter tamanhos incompatíveis. +-- Receptores incompatpiveis serão nil; +-- Destinos incompatíveis serão descartados. + +x, y, z = 1, 2, 3, 4 +-- Agora x = 1, y = 2, z = 3, e 4 é jogado fora. + +function bar(a, b, c) + print(a, b, c) + return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod') --> imprime "zaphod nil nil" +-- Agora x = 4, y = 8, os valores 15...42 foram descartados. + +-- Funções são de primeira-classe, portanto podem ser local/global. +-- Estes exemplos são equivalentes: +function f(x) return x * x end +f = function (x) return x * x end + +-- Logo, estes são equivalentes também: +local function g(x) return math.sin(x) end +local g; g = function (x) return math.sin(x) end +-- 'local g' essa declaração de auto-referência é válida. + +-- A propósito, as funções de trigonometria trabalham em radianos. + +-- Chamadas de função com apenas um parâmetro de string não precisam de parênteses: +print 'hello' -- Funciona perfeitamente. + + +---------------------------------------------------- +-- 3. Tabelas. +---------------------------------------------------- + +-- Tabelas = A unica estrutura de dados composta em Lua; +-- elas são matrizes associativas. +-- Semelhantes aos arrays de PHP ou objetos de javascript, eles são: +-- hash-lookup(chave:valor) que também podem ser usados como listas. + +-- Usando tabelas como dicionário / mapas: + +-- Dicionários literais tem strings como chaves por padrão: +t = {key1 = 'value1', key2 = false} + +-- As chaves do tipo string podem usar notação de ponto,semelhante a javascript: +print(t.key1) -- Imprime 'value1'. +t.newKey = {} -- Adiciona um novo par chave/valor. +t.key2 = nil -- Remove key2 da tabela. + +-- Qualquer notação literal (não-nulo) pode ser uma chave: +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28]) -- imprime "tau" + +-- A correspondência de chave é basicamente o valor para números +-- e strings, mas por identidade para tabelas. +a = u['@!#'] -- Agora a = 'qbert'. +b = u[{}] -- Nós esperavamso o resultado 1729, mas ele é nil: +-- b = nil já que a busca falha. Ela falha +-- porque a chave que usamos não é a mesma que o objeto +-- como aquele que usamos para guardar o valor original. Por isso +-- strings & numeros são chaves mais recomendadas. + +-- Uma chamada de função de apenas um paramêtro de tabela, não precisa de parênteses: + +function h(x) print(x.key1) end +h{key1 = 'Sonmi~451'} -- Imprime 'Sonmi~451'. + +for key, val in pairs(u) do -- Iteração de tabela. + print(key, val) +end + +-- _G é uma tabela especial que guarda tudo que é global. +print(_G['_G'] == _G) -- Imprime 'true'. + +-- Usando tabelas como listas / arrays: + +-- Listas literais com chaves int implícitas: +v = {'value1', 'value2', 1.21, 'gigawatts'} +for i = 1, #v do -- #v é o tamanho de v + print(v[i]) -- Índices começam em 1 !! MUITO LOCO! +end +-- Uma 'list' não é um tipo real. v é apenas uma tabela +-- com chaves int consecutivas, tratando ela como uma lista. + +---------------------------------------------------- +-- 3.1 Metatabelas e metamétodos. +---------------------------------------------------- + +-- Uma tabela pode ter uma metatabela que fornece à tabela +-- um compotamento de sobrecarga de operador. Depois veremos +-- como metatabelas suportam o comportamento do Javascript-prototype. + +f1 = {a = 1, b = 2} -- Representa uma fração de a/b. +f2 = {a = 2, b = 3} + +-- Isso falharia: +-- s = f1 + f2 + +metafraction = {} +function metafraction.__add(f1, f2) + sum = {} + sum.b = f1.b * f2.b + sum.a = f1.a * f2.b + f2.a * f1.b + return sum +end + +setmetatable(f1, metafraction) +setmetatable(f2, metafraction) + +s = f1 + f2 -- chama __add(f1, f2) na metatabela de f1 + +-- f1, f2 não tem chave para sua metatabela, ao contrário de +-- prototypes em javascript, então você deve recuperá-lo com +-- getmetatable(f1). A metatabela é uma tabela normal +-- com chaves que Lua reconhece, como __add. + +-- Mas a proxima linha irá falhar porque s não tem uma metatabela: +-- t = s + s +-- O padrão de Classes abaixo consertam esse problema. + +-- Uma __index em uma metatable sobrecarrega pesquisas de ponto: +defaultFavs = {animal = 'gru', food = 'donuts'} +myFavs = {food = 'pizza'} +setmetatable(myFavs, {__index = defaultFavs}) +eatenBy = myFavs.animal -- Funciona! obrigado, metatabela. + +-- As pesquisas diretas de tabela que falham tentarão pesquisar novamente usando +-- o __index da metatabela, e isso é recursivo. + +-- Um valor de __index também pode ser uma function(tbl, key) +-- para pesquisas mais personalizadas. + +-- Valores do tipo __index,add, .. são chamados de metamétodos. +-- Uma lista completa com os metamétodos. + +-- __add(a, b) para a + b +-- __sub(a, b) para a - b +-- __mul(a, b) para a * b +-- __div(a, b) para a / b +-- __mod(a, b) para a % b +-- __pow(a, b) para a ^ b +-- __unm(a) para -a +-- __concat(a, b) para a .. b +-- __len(a) para #a +-- __eq(a, b) para a == b +-- __lt(a, b) para a < b +-- __le(a, b) para a <= b +-- __index(a, b) <fn or a table> para a.b +-- __newindex(a, b, c) para a.b = c +-- __call(a, ...) para a(...) + +---------------------------------------------------- +-- 3.2 Tabelas como Classes e sua herança. +---------------------------------------------------- + +-- Classes não são disseminadas; existem maneiras diferentes +-- para fazer isso usando tabelas e metamétodos... + +-- A explicação para este exemplo está logo abaixo. + +Dog = {} -- 1. + +function Dog:new() -- 2. + newObj = {sound = 'woof'} -- 3. + self.__index = self -- 4. + return setmetatable(newObj, self) -- 5. +end + +function Dog:makeSound() -- 6. + print('I say ' .. self.sound) +end + +mrDog = Dog:new() -- 7. +mrDog:makeSound() -- 'I say woof' -- 8. + +-- 1. Dog atua como uma classe; mas na verdade, é uma tabela. +-- 2. function tablename:fn(...) é a mesma coisa que +-- function tablename.fn(self, ...) +-- O : apenas adiciona um primeiro argumento chamado self. +-- Leia 7 & 8 abaixo para ver como self obtém seu valor. +-- 3. newObj será uma instância da classe Dog. +-- 4. self = a classe que que foi instanciada. Regularmente +-- self = Dog, mas a herança pode mudar isso. +-- newObj recebe as funções de self como se tivessimos definido em ambos +-- a metatabela de newObj e self __index para self. +-- 5. Lembre-se: setmetatable retorna seu primeiro argumento definido. +-- 6. O : funciona como em 2, mas desta vez esperamos que +-- self seja uma instância já instanciada da classe. +-- 7. Igual a Dog.new(Dog), logo self = Dog no new(). +-- 8. Igual a mrDog.makeSound(mrDog); self = mrDog. + +---------------------------------------------------- + +-- Heranças exemplos: + +LoudDog = Dog:new() -- 1. + +function LoudDog:makeSound() + s = self.sound .. ' ' -- 2. + print(s .. s .. s) +end + +seymour = LoudDog:new() -- 3. +seymour:makeSound() -- 'woof woof woof' -- 4. + +-- 1. LoudDog recebe os metodos e variáveis de Dog. +-- 2. self tem uma chave 'sound' vindo de new(), veja o 3. +-- 3. Mesma coisa que LoudDog.new(LoudDog), convertido para +-- Dog.new(LoudDog) como LoudDog não tem uma chave 'new', +-- mas tem uma chave __index = Dog na sua metatabela o +-- resultado será: a metabela de seymour é a LoudDog, e +-- LoudDog.__index = LoudDog. Então seymour.key será +-- = seymour.key, LoudDog.key, Dog.key,seja qual for a primeira +-- chave fornecida. +-- 4. A chave 'makeSound' foi encontrada em LoudDog; isto +-- é a mesma coisa que LoudDog.makeSound(seymour). + +-- Se precisar de, uma subclasse de new() como uma base: +function LoudDog:new() + newObj = {} + -- define newObj + self.__index = self + return setmetatable(newObj, self) +end + +---------------------------------------------------- +-- 4. Módulos. +---------------------------------------------------- + + +--[[ Estou comentando esta seção, então o resto +-- desse script é executável. +``` + +```lua +-- Suponhamos que o arquivo mod.lua se pareça com isso: +local M = {} + +local function sayMyName() + print('Hrunkner') +end + +function M.sayHello() + print('Why hello there') + sayMyName() +end + +return M + +-- Outro arquivo pode usar as funcionalidades de mod.lua: +local mod = require('mod') -- Roda o arquivo mod.lua. + +-- require é a forma que usamos para incluir módulos. +-- require atua como: (se não for cacheado; veja abaixo) +local mod = (function () + <contents of mod.lua> +end)() +-- É como se mod.lua fosse um corpo de uma função, então +-- os locais dentro de mod.lua são invisíveis fora dele. + +-- Isso irá funcionar porque mod aqui = M dentro de mod.lua: +mod.sayHello() -- Diz olá para Hrunkner. + +-- Isso aqui é errado; sayMyName existe apenas em mod.lua: +mod.sayMyName() -- erro + +-- valores retornados de require são armazenados em cache para que um arquivo seja +-- execute no máximo uma vez, mesmo quando é exigidos várias vezes. + +-- Suponhamos que mod2.lua contém "print('Hi!')". +local a = require('mod2') -- Imprime Hi! +local b = require('mod2') -- Não imprime;pois a=b. + +-- dofile é parecido com require, porém sem cacheamento: +dofile('mod2.lua') --> Hi! +dofile('mod2.lua') --> Hi! (roda novamente) + +-- loadfile carrega um arquivo lua, porém não o executa. +f = loadfile('mod2.lua') -- Chame f() para executar. + +-- loadstring é um loadfile para strings. +g = loadstring('print(343)') -- Retorna uma função. +g() -- Imprime 343; nada foi impresso antes disso. + +--]] + +``` + +## Referências + +Fiquei bastante animado para aprender Lua pois consegui fazer jogos +com a <a href="http://love2d.org/">Love 2D engine de jogos</a>. + +Eu comecei com <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV's para programadores LUA</a>. +Em seguida, eu li a documentação oficial <a href="https://www.lua.org/manual/5.1/pt/index.html#contents">Programando em Lua</a>. +É assim que se começa. + +Pode ser útil conferir <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Uma pequena referencia sobre LUA</a> em lua-users.org. + +Os principais tópicos não cobertos, são as bibliotecas padrões: + +- <a href="http://lua-users.org/wiki/StringLibraryTutorial">Biblioteca de strings</a> +- <a href="http://lua-users.org/wiki/TableLibraryTutorial">Biblioteca de tabelas</a> +- <a href="http://lua-users.org/wiki/MathLibraryTutorial">Biblioteca de matemática</a> +- <a href="http://lua-users.org/wiki/IoLibraryTutorial">Biblioteca de entrada/saída</a> +- <a href="http://lua-users.org/wiki/OsLibraryTutorial">Biblioteca do sistema operacional</a> + +A propósito, todo este arquivo é um código LUA válido, salve-o como +aprenda.lua e rode-o com "lua aprenda.lua" ! + +Este guia foi escrito pela primeira vez por tylerneylon.com, e agora +também disponível em <a href="https://gist.github.com/tylerneylon/5853042">github gist</a>. E também em português. + +Se divirta com lua diff --git a/pt-br/make-pt.html.markdown b/pt-br/make-pt.html.markdown index cbdebde7..d908435a 100644 --- a/pt-br/make-pt.html.markdown +++ b/pt-br/make-pt.html.markdown @@ -1,243 +1,245 @@ ----
-category: tool
-tool: make
-contributors:
- - ["Robert Steed", "https://github.com/robochat"]
- - ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
-filename: Makefile
-
-lang: pt-br
----
-
-Um Makefile define um gráfico de regras para criar um alvo (ou alvos). Sua finalidade é fazer o mínimo de trabalho necessário para atualizar um alvo para a versão mais recente da fonte. Famosamente escrito ao longo de um fim de semana por Stuart Feldman em 1976, ainda é amplamente usada (particularmente no Unix e no Linux) apesar de muitos concorrentes e críticas.
-
-Existem muitas variedades de make na existência, no entanto, este artigo pressupõe que estamos usando o GNU make, que é o padrão no Linux.
-
-```make
-
-# Comentários podem ser escritos assim.
-
-# O arquivo deve ser nomeado Makefile e então pode ser executado como `make <alvo>`.
-# Caso contrário, nós usamos `make -f "nome-do-arquivo" <alvo>`.
-
-# Aviso - use somente TABS para identar em Makefiles, nunca espaços!
-
-#-----------------------------------------------------------------------
-# Noções básicas
-#-----------------------------------------------------------------------
-
-# Regras são do formato
-# alvo: <pré-requisito>
-# onde os pré-requisitos são opcionais.
-
-# Uma regra - esta regra só será executada se o arquivo0.txt não existir.
-arquivo0.txt:
- echo "foo" > arquivo0.txt
- # Mesmo os comentários nestas seções da 'receita' são passados para o shell.
- # Experimentar `make arquivo0.txt` or simplyou simplesmente `make` - primeira regra é o padrão.
-
-# Esta regra só será executada se arquivo0.txt for mais recente que arquivo1.txt.
-arquivo1.txt: arquivo0.txt
- cat arquivo0.txt > arquivo1.txt
- # se as mesmas regras de citação do shell.
- @cat arquivo0.txt >> arquivo1.txt
- # @ pára o comando de ser ecoado para stdout.
- -@echo 'hello'
- # - significa que make continuará em caso de erro.
- # Experimentar `make arquivo1.txt` na linha de comando.
-
-# Uma regra pode ter vários alvos e vários pré-requisitos
-arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt
- touch arquivo2.txt
- touch arquivo3.txt
-
-# Make vai reclamar sobre várias receitas para a mesma regra. Esvaziar
-# receitas não contam e podem ser usadas para adicionar novas dependências.
-
-#-----------------------------------------------------------------------
-# Alvos falsos
-#-----------------------------------------------------------------------
-
-# Um alvo falso. Qualquer alvo que não seja um arquivo.
-# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo.
-all: maker process
-
-# Podemos declarar as coisas fora de ordem.
-maker:
- touch ex0.txt ex1.txt
-
-# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome
-.PHONY: all maker process
-# Este é um alvo especial. Existem vários outros.
-
-# Uma regra com dependência de um alvo falso sempre será executada
-ex0.txt ex1.txt: maker
-
-# Alvos falsos comuns são: todos fazem instalação limpa ...
-
-#-----------------------------------------------------------------------
-# Variáveis Automáticas e Curingas
-#-----------------------------------------------------------------------
-
-process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos
- @echo $^ # $^ é uma variável que contém a lista de pré-requisitos
- @echo $@ # imprime o nome do alvo
- #(fpara várias regras alvo, $@ é o que causou a execução da regra)
- @echo $< # o primeiro pré-requisito listado
- @echo $? # somente as dependências que estão desatualizadas
- @echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal)
- #@echo $| # todos os pré-requisitos 'somente pedidos'
-
-# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los
-process: ex1.txt arquivo0.txt
-# ex1.txt será encontrado, mas arquivo0.txt será desduplicado.
-
-#-----------------------------------------------------------------------
-# Padrões
-#-----------------------------------------------------------------------
-
-# Pode ensinar make a converter certos arquivos em outros arquivos.
-
-%.png: %.svg
- inkscape --export-png $^
-
-# As regras padrões só farão qualquer coisa se decidirem criar o alvo.
-
-# Os caminhos de diretório são normalmente ignorados quando as regras de
-# padrões são correspondentes. Mas make tentará usar a regra mais
-# apropriada disponível.
-small/%.png: %.svg
- inkscape --export-png --export-dpi 30 $^
-
-# make utilizará a última versão para uma regra de padrão que encontrar.
-%.png: %.svg
- @echo esta regra é escolhida
-
-# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo
-%.png: %.ps
- @echo esta regra não é escolhida se *.svg and *.ps estão ambos presentes
-
-# make já tem algumas regras padrões embutidas. Por exemplo, ele sabe
-# como transformar arquivos *.c em arquivos *.o.
-
-# Makefiles antigos podem usar regras de sufixo em vez de regras padrões
-.png.ps:
- @echo essa regra é semelhante a uma regra de padrão.
-
-# make sobre a regra de sufixo
-.SUFFIXES: .png
-
-#-----------------------------------------------------------------------
-# Variáveis
-#-----------------------------------------------------------------------
-# aka. macros
-
-# As variáveis são basicamente todos os tipos de string
-
-name = Ted
-name2="Sarah"
-
-echo:
- @echo $(name)
- @echo ${name2}
- @echo $name # Isso não funcionará, tratado como $ (n)ame.
- @echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias.
-
-# Existem 4 lugares para definir variáveis.
-# Em ordem de prioridade, do maior para o menor:
-# 1: argumentos de linha de comando
-# 2: Makefile
-# 3: variáveis de ambiente do shell - faça importações automaticamente.
-# 4: make tem algumas variáveis predefinidas
-
-name4 ?= Jean
-# Somente defina a variável se a variável de ambiente ainda não estiver definida.
-
-override name5 = David
-# Pára os argumentos da linha de comando de alterar essa variável.
-
-name4 +=grey
-# Anexar valores à variável (inclui um espaço).
-
-# Valores variáveis específicos de padrões (extensão GNU).
-echo: name2 = Sara # Verdadeiro dentro da regra de correspondência
- # e também dentro de suas recursivas dependências
- # (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!)
-
-# Algumas variáveis definidas automaticamente pelo make
-echo_inbuilt:
- echo $(CC)
- echo ${CXX}
- echo $(FC)
- echo ${CFLAGS}
- echo $(CPPFLAGS)
- echo ${CXXFLAGS}
- echo $(LDFLAGS)
- echo ${LDLIBS}
-
-#-----------------------------------------------------------------------
-# Variáveis 2
-#-----------------------------------------------------------------------
-
-# O primeiro tipo de variáveis é avaliado a cada vez que elas são usadas.
-# TIsso pode ser caro, então existe um segundo tipo de variável que é
-# avaliado apenas uma vez. (Esta é uma extensão do GNU make)
-
-var := hello
-var2 ::= $(var) hello
-#:= e ::= são equivalentes.
-
-# Essas variáveis são avaliadas procedimentalmente (na ordem em que
-# aparecem), quebrando assim o resto da línguagem!
-
-# Isso não funciona
-var3 ::= $(var4) and good luck
-var4 ::= good night
-
-#-----------------------------------------------------------------------
-# Funções
-#-----------------------------------------------------------------------
-
-# make tem muitas funções disponíveis.
-
-sourcefiles = $(wildcard *.c */*.c)
-objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
-
-# O formato é $(func arg0,arg1,arg2...)
-
-# Alguns exemplos
-ls: * src/*
- @echo $(filter %.txt, $^)
- @echo $(notdir $^)
- @echo $(join $(dir $^),$(notdir $^))
-
-#-----------------------------------------------------------------------
-# Diretivas
-#-----------------------------------------------------------------------
-
-# Inclua outros makefiles, úteis para código específico da plataforma
-include foo.mk
-
-sport = tennis
-# Compilação condicional
-report:
-ifeq ($(sport),tennis)
- @echo 'game, set, match'
-else
- @echo "They think it's all over; it is now"
-endif
-
-# Há também ifneq, ifdef, ifndef
-
-foo = true
-
-ifdef $(foo)
-bar = 'hello'
-endif
-```
-
-### More Resources
-
-+ [documentação gnu make](https://www.gnu.org/software/make/manual/)
-+ [tutorial de carpintaria de software](http://swcarpentry.github.io/make-novice/)
-+ aprenda C da maneira mais difícil [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: + - ["Rogério Gomes Rio", "https://github.com/rogerlista"] +filename: Makefile-pt + +lang: pt-br +--- + +Um Makefile define um gráfico de regras para criar um alvo (ou alvos). Sua finalidade é fazer o mínimo de trabalho necessário para atualizar um alvo para a versão mais recente da fonte. Famosamente escrito ao longo de um fim de semana por Stuart Feldman em 1976, ainda é amplamente usada (particularmente no Unix e no Linux) apesar de muitos concorrentes e críticas. + +Existem muitas variedades de make na existência, no entanto, este artigo pressupõe que estamos usando o GNU make, que é o padrão no Linux. + +```make + +# Comentários podem ser escritos assim. + +# O arquivo deve ser nomeado Makefile e então pode ser executado como `make <alvo>`. +# Caso contrário, nós usamos `make -f "nome-do-arquivo" <alvo>`. + +# Aviso - use somente TABS para identar em Makefiles, nunca espaços! + +#----------------------------------------------------------------------- +# Noções básicas +#----------------------------------------------------------------------- + +# Regras são do formato +# alvo: <pré-requisito> +# onde os pré-requisitos são opcionais. + +# Uma regra - esta regra só será executada se o arquivo0.txt não existir. +arquivo0.txt: + echo "foo" > arquivo0.txt + # Mesmo os comentários nestas seções da 'receita' são passados para o shell. + # Experimentar `make arquivo0.txt` or simplyou simplesmente `make` - primeira regra é o padrão. + +# Esta regra só será executada se arquivo0.txt for mais recente que arquivo1.txt. +arquivo1.txt: arquivo0.txt + cat arquivo0.txt > arquivo1.txt + # se as mesmas regras de citação do shell. + @cat arquivo0.txt >> arquivo1.txt + # @ pára o comando de ser ecoado para stdout. + -@echo 'hello' + # - significa que make continuará em caso de erro. + # Experimentar `make arquivo1.txt` na linha de comando. + +# Uma regra pode ter vários alvos e vários pré-requisitos +arquivo2.txt arquivo3.txt: arquivo0.txt arquivo1.txt + touch arquivo2.txt + touch arquivo3.txt + +# Make vai reclamar sobre várias receitas para a mesma regra. Esvaziar +# receitas não contam e podem ser usadas para adicionar novas dependências. + +#----------------------------------------------------------------------- +# Alvos falsos +#----------------------------------------------------------------------- + +# Um alvo falso. Qualquer alvo que não seja um arquivo. +# Ele nunca será atualizado, portanto, o make sempre tentará executá-lo. +all: maker process + +# Podemos declarar as coisas fora de ordem. +maker: + touch ex0.txt ex1.txt + +# Pode evitar quebrar regras falsas quando um arquivo real tem o mesmo nome +.PHONY: all maker process +# Este é um alvo especial. Existem vários outros. + +# Uma regra com dependência de um alvo falso sempre será executada +ex0.txt ex1.txt: maker + +# Alvos falsos comuns são: todos fazem instalação limpa ... + +#----------------------------------------------------------------------- +# Variáveis Automáticas e Curingas +#----------------------------------------------------------------------- + +process: Arquivo*.txt # Usando um curinga para corresponder nomes de arquivos + @echo $^ # $^ é uma variável que contém a lista de pré-requisitos + @echo $@ # imprime o nome do alvo + #(fpara várias regras alvo, $@ é o que causou a execução da regra) + @echo $< # o primeiro pré-requisito listado + @echo $? # somente as dependências que estão desatualizadas + @echo $+ # todas as dependências, incluindo duplicadas (ao contrário do normal) + #@echo $| # todos os pré-requisitos 'somente pedidos' + +# Mesmo se dividirmos as definições de dependência de regra, $^ vai encontrá-los +process: ex1.txt arquivo0.txt +# ex1.txt será encontrado, mas arquivo0.txt será desduplicado. + +#----------------------------------------------------------------------- +# Padrões +#----------------------------------------------------------------------- + +# Pode ensinar make a converter certos arquivos em outros arquivos. + +%.png: %.svg + inkscape --export-png $^ + +# As regras padrões só farão qualquer coisa se decidirem criar o alvo. + +# Os caminhos de diretório são normalmente ignorados quando as regras de +# padrões são correspondentes. Mas make tentará usar a regra mais +# apropriada disponível. +small/%.png: %.svg + inkscape --export-png --export-dpi 30 $^ + +# make utilizará a última versão para uma regra de padrão que encontrar. +%.png: %.svg + @echo esta regra é escolhida + +# No entanto, o make usará a primeira regra padrão que pode se tornar o alvo +%.png: %.ps + @echo esta regra não é escolhida se *.svg and *.ps estão ambos presentes + +# make já tem algumas regras padrões embutidas. Por exemplo, ele sabe +# como transformar arquivos *.c em arquivos *.o. + +# Makefiles antigos podem usar regras de sufixo em vez de regras padrões +.png.ps: + @echo essa regra é semelhante a uma regra de padrão. + +# make sobre a regra de sufixo +.SUFFIXES: .png + +#----------------------------------------------------------------------- +# Variáveis +#----------------------------------------------------------------------- +# aka. macros + +# As variáveis são basicamente todos os tipos de string + +name = Ted +name2="Sarah" + +echo: + @echo $(name) + @echo ${name2} + @echo $name # Isso não funcionará, tratado como $ (n)ame. + @echo $(name3) # Variáveis desconhecidas são tratadas como strings vazias. + +# Existem 4 lugares para definir variáveis. +# Em ordem de prioridade, do maior para o menor: +# 1: argumentos de linha de comando +# 2: Makefile +# 3: variáveis de ambiente do shell - faça importações automaticamente. +# 4: make tem algumas variáveis predefinidas + +name4 ?= Jean +# Somente defina a variável se a variável de ambiente ainda não estiver definida. + +override name5 = David +# Pára os argumentos da linha de comando de alterar essa variável. + +name4 +=grey +# Anexar valores à variável (inclui um espaço). + +# Valores variáveis específicos de padrões (extensão GNU). +echo: name2 = Sara # Verdadeiro dentro da regra de correspondência + # e também dentro de suas recursivas dependências + # (exceto que ele pode quebrar quando seu gráfico ficar muito complicado!) + +# Algumas variáveis definidas automaticamente pelo make +echo_inbuilt: + echo $(CC) + echo ${CXX} + echo $(FC) + echo ${CFLAGS} + echo $(CPPFLAGS) + echo ${CXXFLAGS} + echo $(LDFLAGS) + echo ${LDLIBS} + +#----------------------------------------------------------------------- +# Variáveis 2 +#----------------------------------------------------------------------- + +# O primeiro tipo de variáveis é avaliado a cada vez que elas são usadas. +# TIsso pode ser caro, então existe um segundo tipo de variável que é +# avaliado apenas uma vez. (Esta é uma extensão do GNU make) + +var := hello +var2 ::= $(var) hello +#:= e ::= são equivalentes. + +# Essas variáveis são avaliadas procedimentalmente (na ordem em que +# aparecem), quebrando assim o resto da línguagem! + +# Isso não funciona +var3 ::= $(var4) and good luck +var4 ::= good night + +#----------------------------------------------------------------------- +# Funções +#----------------------------------------------------------------------- + +# make tem muitas funções disponíveis. + +sourcefiles = $(wildcard *.c */*.c) +objectfiles = $(patsubst %.c,%.o,$(sourcefiles)) + +# O formato é $(func arg0,arg1,arg2...) + +# Alguns exemplos +ls: * src/* + @echo $(filter %.txt, $^) + @echo $(notdir $^) + @echo $(join $(dir $^),$(notdir $^)) + +#----------------------------------------------------------------------- +# Diretivas +#----------------------------------------------------------------------- + +# Inclua outros makefiles, úteis para código específico da plataforma +include foo.mk + +sport = tennis +# Compilação condicional +report: +ifeq ($(sport),tennis) + @echo 'game, set, match' +else + @echo "They think it's all over; it is now" +endif + +# Há também ifneq, ifdef, ifndef + +foo = true + +ifdef $(foo) +bar = 'hello' +endif +``` + +### More Resources + ++ [documentação gnu make](https://www.gnu.org/software/make/manual/) ++ [tutorial de carpintaria de software](http://swcarpentry.github.io/make-novice/) ++ aprenda C da maneira mais difícil [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html) diff --git a/pt-br/markdown-pt.html.markdown b/pt-br/markdown-pt.html.markdown index c2aa515d..fca864bb 100644 --- a/pt-br/markdown-pt.html.markdown +++ b/pt-br/markdown-pt.html.markdown @@ -4,93 +4,142 @@ contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: - ["Miguel Araújo", "https://github.com/miguelarauj1o"] -lang: pt-br + - ["Gabriele Luz", "https://github.com/gabrieleluz"] + - ["Monique Baptista", "https://github.com/bfmonique"] + - ["Marcel Ribeiro-Dantas", "https://github.com/mribeirodantas"] + +lang: pt-br filename: learnmarkdown-pt.md --- -Markdown foi criado por John Gruber in 2004. Originado para ser fácil de ler e -escrever sintaxe que converte facilmente em HTML (hoje, suporta outros formatos também). - -Dê-me feedback tanto quanto você quiser! / Sinta-se livre para a garfar (fork) e -puxar o projeto (pull request) +O Markdown foi lançado por John Gruber em 2004. Criado para ser uma sintaxe +fácil de ler e escrever e que é facilmente convertida em HTML (hoje, suporta +outros formatos também). + +O Markdown varia em termos de implementação de um parser para outro. Esse guia +irá tentar deixar explícito quando os recursos são universais ou quando são +específicos para um parser em específico. + +- [Elementos HTML](#elementos-html) +- [Cabeçalhos](#cabeçalhos) +- [Estilos de texto simples](#estilos-de-texto-simples) +- [Parágrafos](#parágrafos) +- [Listas](#listas) +- [Blocos de código](#blocos-de-código) +- [Linha Horizontal](#linha-horizontal) +- [Links](#links) + - [Tabela de conteúdo](#tabela-de-conteúdo) +- [Imagens](#imagens) +- [Miscelânea](#miscelânea) + - [Auto-links](#auto-links) + - [Auto-links para e-mails](#auto-links-com-e-mails) + - [Escapando caracteres](#escapando-caracteres) + - [Teclas do teclado](#teclas-do-teclado) + - [Tabelas](#tabelas) +- [Markdownlint](#markdownlint) +- [Leitura complementar](#leitura-complementar) + +## Elementos HTML +O Markdown é um superconjunto do HTML, de modo que qualquer arvquivo HTML é +um arquivo Markdown válido. ```md -<!-- Markdown é um superconjunto do HTML, de modo que qualquer arvquivo HTML é -um arquivo Markdown válido, isso significa que nós podemos usar elementos HTML -em Markdown, como o elemento de comentário, e eles não serão afetados pelo analisador -de remarcação. No entanto, se você criar um elemento HTML em seu arquivo Markdown, você -não pode usar sintaxe remarcação dentro desse conteúdo do elemento.--> +<!--Isso significa que nós podemos usar elementos HTML em Markdown, como o +elemento de comentário, e eles não serão afetados pelo analisador de +remarcação. No entanto, se você criar um elemento HTML em seu arquivo Markdown, +você não pode usar sintaxe de remarcação dentro do conteúdo desse elemento.--> +``` -<!--Markdown também varia de implementação de um analisador para uma próxima. -Este guia vai tentar esclarecer quando as características são universais, ou quando eles são -específico para um determinado parser --> +## Cabeçalhos -<!-- Cabeçalhos --> -<!-- Você pode criar elementos HTML <h1> até <h6> facilmente antecedendo o texto -que deseja estar nesse elemento por um número de hashes (#) --> +Você pode criar elementos HTML `<h1>` até `<h6>` facilmente antecedendo o texto +que deseja estar nesse elemento por um número de cerquilhas (#). + +```md # Isto é um cabeçalho <h1> ## Isto é um cabeçalho <h2> ### Isto é um cabeçalho <h3> #### Isto é um cabeçalho <h4> ##### Isto é um cabeçalho <h5> ###### Isto é um cabeçalho <h6> +``` -<!-- Markdown também nos fornece duas maneiras alternativas de indicar h1 e h2 --> +Markdown também nos fornece duas maneiras alternativas de indicar h1 e h2. + +```md Isto é um cabeçalho h1 ====================== Isto é um cabeçalho h2 ---------------------- +``` -<!-- Estilos de texto simples --> -<!-- O texto pode ser facilmente denominado como remarcação itálico, negrito ou tachado usando --> +## Estilos de texto simples +O texto pode ser facilmente estilizado como itálico ou negrito usando Markdown. + +```md *Este texto está em itálico* _E este também está._ **Este texto está em negrito** -__E este também está._ +__E este também está.__ ***Este texto está em negrito e itálico.*** **_E este também está_** -*--Danouse! Este também__* +*__Danou-se! Este também__* +``` -<!-- Em GitHub Flavored Markdown, que é usado para processar arquivos Markdown -GitHub, nós também temos: --> +No GitHub Flavored Markdown, que é usado para processar arquivos Markdown +GitHub, nós também temos: +```md ~~Este texto é processado com tachado.~~ +``` -<!-- Os parágrafos estão uma ou várias linhas adjacentes de texto separadas por -uma ou múltiplas linhas em branco. --> +## Parágrafos +Os parágrafos estão em uma ou várias linhas adjacentes de texto separadas por +uma ou múltiplas linhas em branco. +```md Este é um parágrafo. Eu estou digitando em um parágrafo, não é legal? -Agora, eu estou no parágrado 2. -... Ainda continuo no parágrafo 2! :) +Agora, eu estou no parágrafo 2. +Ainda continuo no parágrafo 2! -Eu estou no parágrafo três. -<!-- Se você quiser inserir uma tag HTML <br />, você pode acabar com um parágrafo -com dois ou mais espaços e, em seguida, começar um novo parágrafo --> +Eu estou no parágrafo três! +``` + +Se você quiser inserir uma tag HTML `<br />`, você pode acabar com um parágrafo +com dois ou mais espaços e, em seguida, começar um novo parágrafo. -Termino com dois espaços (destacar-me para vê-los). +```md +Termino com dois espaços (selecione essa linha para vê-los). Há um <br /> acima de mim! +``` -<!-- Bloco de citações são fáceis e feito com o caractere >. --> +Blocos de citações são fáceis e feitos com o caractere >. +```md > Este é um bloco de citação. Você pode -> Enrolar manualmente suas linhas e colocar um `>` antes de cada linha ou você pode -> deixar suas linhas ficarem muito longas e enrolar por conta própria. Não faz diferença, -> desde que eles começam com um `>`. +> Quebrar manualmente suas linhas e colocar um `>` antes de cada linha ou você +> pode deixar suas linhas ficarem muito longas e quebrarem por conta própria. +> Não faz diferença, desde que elas comecem com um `>`. > Você também pode usar mais de um nível ->> De recuo? -> Como pura é isso? +>> De recuo? +> O quão legal é isso? + +``` + +## Listas -<!-- Listas --> -<!-- As listas não ordenadas podem ser feitas usando asteriscos, positivos ou hífens --> +As listas não ordenadas podem ser feitas usando asteriscos, sinais de positivo +ou hífens. +```md * Item * Item * Outro item @@ -106,146 +155,248 @@ ou - Item - Item - Um último item +``` -<!-- Listas ordenadas são feitas com um número seguido por um ponto --> +Listas ordenadas são feitas com um número seguido por um ponto. +```md 1. Item um 2. Item dois -3. Tem três +3. Item três +``` -<!-- Você não tem poder para rotular os itens corretamente e a remarcação será ainda -tornar os números em ordem, mas isso pode não ser uma boa idéia --> +Você não precisa sequer rotular os itens corretamente e o Markdown ainda +assim deixará os itens em ordem, mas isso pode não ser uma boa idéia. +```md 1. Item um 1. Item dois 1. Item três -<!-- (Isto é processado da mesma forma que o exemplo acima) --> +``` + +(Isto é processado da mesma forma que o exemplo acima) -<!-- Você também pode usar subtítulos --> +Você também pode usar sublistas. +```md 1. Item um 2. Item dois 3. Item três * Sub-item * Sub-item 4. Item quatro +``` -<!-- blocos de código --> -<!-- Você pode indicar um bloco de código (que utiliza o elemento <code>) pelo recuo -uma linha com quatro espaços ou uma guia --> +Existem também listas de tarefas. Isso cria checkboxes (caixas de seleção) do +HTML. - Isto é código - É assim, sacou? +```md +As caixas abaixo sem o 'x' são checkboxes HTML desmarcadas. +- [ ] Primeira tarefa a completar. +- [ ] Segunda tarefa a completar +A caixa de seleção abaixo será exibida como uma checkbox HTML marcada. +- [x] Essa tarefa foi completa +``` -<!-- Você pode também re-guia (ou adicionar mais quatro espaços adicionais) para o recuo -dentro do seu código --> +## Blocos de código - my_array.each do |item| - puts item - end +Você pode indicar um bloco de código (que utiliza o elemento `<code>`) através +de indentação com quatro espaços ou uma tabulação. -<!-- Código embutido pode ser criada usando o caractere de crase ` --> +```md + Isto é código + É assim, sacou? +``` + +Você pode também adicionar mais tabulações (ou adicionar mais quatro espaços +adicionais) para indentação no seu código. -John não sabia nem o que o função 'goto()' fazia! +```md + my_array.each do |item| + puts item + end +``` -<!-- Em GitHub Flavored Markdown, você pode usar uma sintaxe especial para o código --> +Código embutido pode ser criado usando o caractere de crase `` ` ``. -\`\`\`ruby <!-- exceto remover essas barras invertidas quando você faz isso, apenas ``` -ruby! --> +```md +John não sabia nem o que a função `go_to()` fazia! +``` + +No GitHub Flavored Markdown, você pode usar uma sintaxe especial para código. + +````md +```ruby def foobar - puts "Hello world!" + puts "Olá mundo!" end -\`\`\` <!-- Aqui também, não barras invertidas, apenas ``` --> +``` +```` + +O texto acima não requer indentação, além disso o GitHub vai usar o destaque +de sintaxe da linguagem qeu você especificar após a tag <code>```</code>. -<-- O texto acima não requer recuo, mas o GitHub vai usar a sintaxe -destacando do idioma que você especificar após a ``` --> +## Linha Horizontal -<!-- Regra Horizontal (<hr />) --> -<!-- Regras horizontais são facilmente adicionados com três ou mais asteriscos ou hífens, -com ou sem espaços. --> +Linhas horizontais são facilmente adicionadas com três ou mais asteriscos ou +hífens, com ou sem espaços. +```md *** --- - - - **************** +``` + +## Links -<!-- Links --> -<!-- Uma das melhores coisas sobre a remarcação é o quão fácil é fazer ligações. Colocar -o texto a ser exibido entre parênteses rígidos [] seguido pela url em parênteses () --> +Uma das melhores coisas sobre o Mardkwon é o quão fácil é criar links. +Coloque o texto a ser exibido entre colchetes [] seguido pela url entre +parênteses () -[Click aqui!](http://test.com/) +```md +[Clique aqui!](http://test.com/) +``` -<!-- Você também pode adicionar um título link usando aspas dentro dos parênteses --> +Você também pode adicionar um título ao link usando aspas dentro dos parênteses. -[Click aqui!](http://test.com/ "Link para Test.com") +```md +[Cliqueaqui!](http://test.com/ "Link para Test.com") +``` -<!-- Caminhos relativos funcionam também. --> +Caminhos relativos funcionam também. +```md [Ir para música](/música/). +``` -<!-- Markdown também suporta ligações de estilo de referência --> +O Markdown também suporta links para referências no texto. -[Clique neste link] [link1] para mais informações sobre isso! -[Além disso, verifique este link] [foobar] se você quiser. +```md +[Clique nesse link][link1] para mais informações! +[Também cheque esse link][foobar] se você quiser. [link1]: http://test.com/ "Legal!" -[foobar]: http://foobar.biz/ "OK!" +[link2r]: http://foobar.biz/ "Certo!" +``` -<!-- O título também pode estar entre aspas simples ou entre parênteses, ou omitido -inteiramente. As referências podem estar em qualquer lugar no documento e os IDs de referência -pode ser qualquer um, desde que eles são únicos. --> +O título também pode estar entre aspas simples ou entre parênteses, ou omitido +inteiramente. As referências podem estar em qualquer lugar no documento e os +IDs de referência podem ser qualquer um, desde que eles sejam únicos. -<!-- Existe também o "nomear implícita", que permite que você use o texto do link como o id --> +Existe também a "nomeação implícita", que permite que você use o texto do link +como o id: -[Este] [] é um link. +```md +[Isso][] é um link. -[este]: http://thisisalink.com/ +[Isso]: http://thisisalink.com/ +``` + +Mas geralmente não são usados. + +### Tabela de conteúdo -<!-- Mas não são usados normalmente--> +Alguns sabores de Markdown fazem inclusive uso de combinação de listas, links e +cabeçalhos de modo a criar uma tabela de conteúdo. Nesse caso, títulos em +cabeçalhos são precedidos de (`#`) e são usados como ids para links. Se o +cabeçalho consistir de várias palavras, elas serão conectadas por hífens (`-`), +que também substitui alguns caracteres especiais. (Embora alguns outros +carácteres especiais sejam omitidos.) + +```md +- [Cabeçalho](#cabecalho) +- [Um outro cabeçalho](#outro-cabecalho) +- [Capítulo](#capitulo) + - [Subcapítulo <h3 />](#subcapitulo-h3-) +``` -<!-- Imagens --> -<!-- As imagens são feitas da mesma forma que as ligações, mas com um ponto de exclamação na frente! --> +De qualquer modo, esse é um recurso que talvez não funcione em todas as +implementações do Markdown da mesma forma. + +## Imagens + +As imagens são feitas da mesma forma que os links, mas com um ponto de +exclamação na frente! + +```md + +``` - +E estilo de referência funciona como esperado -<!-- E estilo de referência funciona como esperado --> +```md +![Esse é o alt-attribute.][myimage] -![Este é o pairar-texto.][Myimage] +[Minha imagem]: relative/urls/cool/image.jpg "se precisar de um título, está aqui" +``` -[myimage]: relative/urls/legal/image.jpg "se você precisa de um título, é aqui" +## Miscelânea -<!-- Miscelânea --> -<!-- Auto-links --> +### Auto-links +```md <http://testwebsite.com/> é equivalente a [http://testwebsite.com/](http://testwebsite.com/) +``` -<!-- Auto-links para e-mails --> +### Auto-links para e-mails +```md <foo@bar.com> +``` -<!-- Escapando caracteres --> +### Escapando caracteres -Quero digitar * Este texto entre asteriscos *, mas eu não quero que ele seja +Quero digitar *Este texto entre asteriscos*, mas eu não quero que ele seja em itálico, então eu faço o seguinte: \*Este texto entre asteriscos \*. -<!-- Tabelas --> -<!-- Tabelas estão disponíveis apenas no GitHub Flavored Markdown e são ligeiramente -complicadas, mas se você realmente quer: --> +### Teclas do teclado + +No GitHub Flavored Markdown, você pode usar a tag `<kbd>` para representar uma +tecla do teclado. + +```md +Seu computador travou? Tente apertar +<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> +``` + +### Tabelas + +Tabelas estão disponíveis apenas no GitHub Flavored Markdown e são ligeiramente +complicadas, mas se você realmente quer: +```md | Col1 | Col2 | Col3 | | :----------- | :------: | ------------: | | esquerda-alin| Centrado | direita-alinh | | blah | blah | blah | +``` -<!-- Ou, para os mesmos resultados --> +Ou, para os mesmos resultados +```md Col 1 | Col2 | Col3 :-- | :-: | --: Ugh isso é tão feio | faça isto | parar +``` -<!-- O fim! --> +## Markdownlint -``` -Para mais informações, confira o post oficial de John Gruber de sintaxe [aqui](http://daringfireball.net/projects/markdown/syntax) -e de Adam Pritchard grande cheatsheet [aqui](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). +De modo a simplificar o trabalho com Markdown e padronizar estilo de código, o +`Markdownlint` foi criado. Essa ferramenta está disponível como plugin para +algumas interfaces de desenvolvimento (IDEs) e pode ser utilizada como um +utilitário para garantir validade e legibilidade do Markdown. + +--- + +## Leitura complementar + +Para mais informações, confira o post oficial de John Gruber sobre sintaxe [aqui](http://daringfireball.net/projects/markdown/syntax) +e o do cheatsheet do Adam Pritchard [aqui](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). + +Se você quiser aprender mais sobre recursos de alguns sabores específicos de +Markdown, veja: + +- [GitHub flavored Markdown](https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) +- [GitLab flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html) diff --git a/pt-br/matlab-pt.html.markdown b/pt-br/matlab-pt.html.markdown index 5ed6b7ba..947e0699 100644 --- a/pt-br/matlab-pt.html.markdown +++ b/pt-br/matlab-pt.html.markdown @@ -1,5 +1,5 @@ --- -language: Matlab +language: MATLAB contributors: - ["mendozao", "http://github.com/mendozao"] - ["jamesscottbrown", "http://jamesscottbrown.com"] @@ -120,7 +120,7 @@ A.d.e = false; % Vetores x = [4 32 53 7 1] -x(2) % Resposta = 32, índices no Matlab começam por 1, não 0 +x(2) % Resposta = 32, índices no MATLAB começam por 1, não 0 x(2:3) % Resposta = 32 53 x(2:end) % Resposta = 32 53 7 1 @@ -356,7 +356,7 @@ disp(a) % Imprime o valor da variável a disp('Olá Mundo') % Imprime a string fprintf % Imprime na janela de comandos com mais controle -% Estruturas Condicionais (os parênteses são opicionais, porém uma boa prática) +% Estruturas Condicionais (os parênteses são opcionais, porém uma boa prática) if (a > 15) disp('Maior que 15') elseif (a == 23) @@ -479,7 +479,7 @@ perms(x) % Lista todas as permutações de elementos de x % Classes -% Matlab pode suportar programação orientada a objetos. +% MATLAB pode suportar programação orientada a objetos. % Classes devem ser colocadas em um arquivo de mesmo nome com a extensão *.m % Para começar, criamos uma simples classe que armazena posições de GPS % Início ClassePosicoesGPS.m @@ -501,7 +501,7 @@ classdef ClassePosicoesGPS % O nome da classe. end % Se quisermos somar dois objetos de PosicoesGPS juntos sem chamar - % uma função especial nós podemos sobrepor a aritmética do Matlab, desta maneira: + % uma função especial nós podemos sobrepor a aritmética do MATLAB, desta maneira: function r = plus(o1,o2) r = ClassePosicoesGPS([o1.latitude] +[o2.latitude], ... [o1.longitude]+[o2.longitude]); @@ -513,7 +513,7 @@ end % Podemos criar um objeto da classe usando o construtor a = ClassePosicoesGPS(45.0, 45.0) -% Propriedades da classe se comportam exatamente como estruturas Matlab +% Propriedades da classe se comportam exatamente como estruturas MATLAB a.latitude = 70.0 a.longitude = 25.0 @@ -524,15 +524,15 @@ ans = multiplicarLatPor(a,3) % o objeto não precisa ser passado para o método. ans = a.multiplicarLatPor(a,1/3) -% Funções do Matlab podem ser sobrepostas para lidar com objetos. -% No método abaixo, nós sobrepomos a forma como o Matlab lida com a soma de +% Funções do MATLAB podem ser sobrepostas para lidar com objetos. +% No método abaixo, nós sobrepomos a forma como o MATLAB lida com a soma de % dois objetos PosicoesGPS. b = ClassePosicoesGPS(15.0, 32.0) c = a + b ``` -## Mais sobre Matlab +## Mais sobre MATLAB * O site oficial [http://http://www.mathworks.com/products/matlab/](http://www.mathworks.com/products/matlab/) * O fórum oficial de respostas: [http://www.mathworks.com/matlabcentral/answers/](http://www.mathworks.com/matlabcentral/answers/) diff --git a/pt-br/pascal-pt.html.markdown b/pt-br/pascal-pt.html.markdown index 3a37271a..72302695 100644 --- a/pt-br/pascal-pt.html.markdown +++ b/pt-br/pascal-pt.html.markdown @@ -4,6 +4,7 @@ filename: learnpascal-pt.pas contributors: - ["Ganesha Danu", "https://github.com/blinfoldking"] - ["Keith Miyake", "https//github.com/kaymmm"] + - ["Raul Almeida", "https://github.com/almeidaraul"] translators: - ["Raul Almeida", "https://github.com/almeidaraul"] lang: pt-br @@ -157,7 +158,7 @@ BEGIN r := int; // um real pode receber um valor inteiro (mas não o contrário) c := str[1]; //acessando elementos de um vetor: vetor[índice do elemento] - str := 'hello' + 'world'; //concatenção de strings + str := 'hello' + 'world'; //concatenação de strings my_str[0] := 'a'; { só se pode atribuir valores a vetores elemento por elemento (não o vetor inteiro de uma vez) } diff --git a/pt-br/perl-pt.html.markdown b/pt-br/perl-pt.html.markdown index 217861f9..55a10626 100644 --- a/pt-br/perl-pt.html.markdown +++ b/pt-br/perl-pt.html.markdown @@ -10,9 +10,9 @@ translators: lang: pt-br --- -Perl 5 é, uma linguagem de programação altamente capaz, rica em recursos, com mais de 25 anos de desenvolvimento. +Perl é, uma linguagem de programação altamente capaz, rica em recursos, com mais de 25 anos de desenvolvimento. -Perl 5 roda em mais de 100 plataformas, de portáteis a mainframes e é adequada tanto para prototipagem rápida, quanto em projetos de desenvolvimento em grande escala. +Perl roda em mais de 100 plataformas, de portáteis a mainframes e é adequada tanto para prototipagem rápida, quanto em projetos de desenvolvimento em grande escala. ```perl # Comentários de uma linha começam com um sinal de número. diff --git a/pt-br/php-pt.html.markdown b/pt-br/php-pt.html.markdown index 8a1c956e..7db6a671 100644 --- a/pt-br/php-pt.html.markdown +++ b/pt-br/php-pt.html.markdown @@ -7,7 +7,7 @@ translators: - ["Abdala Cerqueira", "http://abda.la"] - ["Raquel Diniz", "http://twitter.com/raquelrdiniz"] lang: pt-br -filename: php-pt.html.markdown +filename: learnphp-pt.php --- Este documento descreve PHP 5+. @@ -20,7 +20,7 @@ Este documento descreve PHP 5+. // Duas barras iniciam o comentário de uma linha. -# O hash (aka pound symbol) também inicia, mas // é mais comum. +# O hash (conhecido como "pound symbol") também inicia, mas // é mais comum. /* O texto envolto por barra-asterisco e asterisco-barra diff --git a/pt-br/processing-pt.html.markdown b/pt-br/processing-pt.html.markdown new file mode 100644 index 00000000..5ed2950a --- /dev/null +++ b/pt-br/processing-pt.html.markdown @@ -0,0 +1,480 @@ +--- +language: processing +filename: learnprocessing.pde +contributors: + - ["Phone Thant Ko", "http://github.com/phonethantko"] + - ["Divay Prakash", "https://github.com/divayprakash"] +translators: + - ["Kemel Zaidan", "https://github.com/kemelzaidan"] +lang: pt-br +--- + +## Introdução + +Processing é uma linguagem de programação para criação de artes digitais e +conteúdo multimídia, permitindo que não programadores aprendam os fundamentos +da programação computacional em um contexto visual. + +Embora a linguagem seja baseada na linguagem Java, sua sintaxe foi amplamente +influenciado por ambas as sintaxes Java e Javascript. +[Veja mais aqui](https://processing.org/reference/) + +A linguagem é tipada estaticamente e também vem com o seu Ambiente de Desenvolvimento +Integrado (do inglês Integrated Development Environment - IDE) oficial para +compilar e executar os scripts. + +``` +/* --------- + Comentários + --------- +*/ + +// Comentário de linha única começa com // + +/* + Como o Processing é baseado em Java, + a sintaxe para seus comentários é a mesma do Java (como você deve ter notado + acima)! + Comentários de várias linhas são agrupados como visto aqui. +*/ + +/* --------------------------------------- + Escrevendo e executando programas em Processing + --------------------------------------- +*/ + +// No Processing, o ponto de entrada do programa é uma função chamada setup() +// com um tipo de retorno void. +// Observação! A sintaxe é muito semelhante à do C++. +void setup() { + // Isso imprime a saída clássica "Hello World!" no console quando executado. + println("Olá Mundo!"); // Mais uma linguagem com esse maldito ponto e vírgula, não é? +} + +// Normalmente, colocamos todos os códigos estáticos dentro do método setup() +// como o próprio nome sugere, uma vez que é executado apenas uma vez. +// Pode variar da definição das cores de fundo, ou o tamanho da tela. +background(color); //define a cor do fundo +size(largura,altura,[renderizador]); // define o tamanho da tela com parâmetro +// opcional para definir o renderizador +// Você verá mais sobre isso ao longo deste documento. + +// Se você deseja executar os códigos indefinidamente, eles devem ser colocados +// dentro do método draw() +// draw() deve existir caso você queira que o código seja executado +// continuamente e, obviamente, só pode haver um método draw(). +int = 0; +void draw(){ + // Este bloco de código faz um loop para sempre até parar + imprima(i); + i++; // Operador de incremento! +} + +// Agora que sabemos como escrever o script de trabalho e como executá-lo, +// continuaremos a explorar quais tipos de dados e coleções são suportados no +// Processing. + +/* ------------------------ + Tipos de dados e coleções + ------------------------ +*/ + +// De acordo com as Referências do Processing, ele suporta 8 tipos primitivos +// de dados da seguinte forma. + +boolean valorBoleano = true; // Boleano +byte valorByteDeA = 23; // Byte +char valorCharDeA = 'A'; // Caractere +color valorDeCorBrancoM = color(255, 255, 255); // Cor (especificada usando +// método color()) +color valorDeCorBrancoH = #FFFFFF; // Cor (especificada usando valor de hash) +int valor = 5; // Inteiro (Número sem decimais) +long valorLongo = 2147483648L; // "L" é adicionado ao número para marcá-lo como um longo +float valorFloat = 1,12345; // Float (números de ponto flutuante de 32 bits) +double valorDouble = 1,12345D; // Double (números de ponto flutuante de 64 bits) + +// NOTA! +// Embora os tipos de dados "long" e "double" funcionem na linguagem, +// funções do Processing não usam esses tipos de dados, portanto +// eles precisam ser convertidos em tipos de dados "int" e "float", +// respectivamente, usando a sintaxe (int) e (float) antes de passar para uma +// função. + +// Existem vários tipos de dados compostos que estão disponíveis por padrão para +// uso no Processing. +// Primeiramente, farei um resumo dos mais usados para economizar tempo. + +// String +// Enquanto o tipo de dados char usa '', o tipo de dados String usa "" - aspas +// duplas. +string stringExemplo = "Olá, Processing!"; +// String também pode ser criada a partir de um array de tipos de dados char. +// Nós vamos discutir array muito em breve. +char fonte = {'H', 'E', 'L', 'L', 'O'}; +String stringDeFonte = new String(source); // HELLO +// Como em Java, strings podem ser concatenadas usando o operador "+". +print("Olá " + "Mundo!"); // Olá Mundo! + +// Array +// Arrays em Processing podem conter quaisquer tipos de dados, incluindo os +// próprios objetos. Como os arrays são semelhantes aos objetos, eles devem +// ser criados com a palavra-chave "new". +int[] arrayInt = new int[5]; +int[] arrayIntComValores = {1, 2, 3}; // Você também pode preencher com dados. + +// Lista de Arrays +// As funções são semelhantes às do array; arraylists podem conter qualquer +// tipo de dados. A única diferença é que as listas de matrizes são +// redimensionadas dinamicamente, pois é uma forma de implementação de matriz +// redimensionável da interface "List" do Java . +ArrayList<Integer> intArrayList = new ArrayList<Integer>(); + +// Objeto +// Como é baseado em Java, o Processing suporta programação orientada a objetos. +// Isso significa que você pode basicamente definir quaisquer tipos de dados de +// sua preferência e manipulá-los para suas necessidades. +// Claro, uma classe tem que ser definida antes para o objeto que você quer. +// Formato --> NomeClasse NameInstancia +UmaClasseQualquer meuObjeto // então instancia mais tarde +//ou +UmaClasseQualquer meuObjetoInstanciado = new UmaClasseQualquer(); + +// O Processing surge com mais coleções (ex. - Dicionários e Listas) por +// padrão, por uma questão de simplicidade, vou deixá-los fora da discussão aqui. + +/* ------------ + Matemática + ------------ +*/ + +// Aritmética +1 + 1 // 2 +2 - 1 // 1 +2 * 3 // 6 +3/2 // 1 +3.0 / 2 // 1.5 +3.0% 2 // 1.0 + +// O Processing também vem com um conjunto de funções que simplificam operações +// matemáticas. +float f = sq(3); // f = 9.0 +float p = pow(3, 3); // p = 27.0 +int a = abs(-13); // a = 13 +int r1 = round(3.1); // r1 = 3 +int r2 = round(3.7); // r2 = 4 +float sr = sqrt(25); // sr = 5.0 + +// Vetores +// O Processing fornece uma maneira fácil de implementar vetores em seu ambiente +// usando a classe PVector. Ela pode descrever um vetor bi ou tridimensional e +// vem com um conjunto de métodos que são úteis para operações com matrizes. +// Você pode encontrar mais informações sobre a classe PVector e suas funções +// aqui. (https://processing.org/reference/PVector.html) + +// Trigonometria +// O Processing também suporta operações trigonométricas fornecendo um +// conjunto de funções. sin(), cos(), tan(), asin(), acos(), atan() e também +// degrees() e radians() para conversão conveniente. +// No entanto, essas funções usam o ângulo em radianos como parâmetro, então é +// necessário converter previamente. +float um = sin(PI/2); // um = 1.0 +// Como você deve ter notado, existe um conjunto de constantes para usos +// trigonométricos; PI, HALF_PI, QUARTER_PI e assim por diante... + +/* ------------- + Controle de fluxo + ------------- +*/ + +// Declarações Condicionais +// Instruções If - A mesma sintaxe das instruções if em Java. +if (author.getAppearance().equals("quente")) { + print("Narcisismo no máximo!"); +} else { + // Você pode verificar outras condições aqui. + print("Algo está realmente errado aqui!"); +} +// Um atalho para instruções if-else também pode ser usado. +int = 3; +String valor = (i > 5) ? "Grande" : "Pequena"; // "Pequena" + +// A estrutura switch-case pode ser usada para verificar várias condições de +// forma concisa. É importante usar a instrução break. Se a instrução `break` +// não existe o programa executa todos os casos a seguir após um caso ser +// verdadeiro. +int valor = 2; +switch(valor) { + case 0: + print("Nada!"); // Isso não é executado. + break; // Salta para a próxima instrução + case 1: + print("Chegando lá..."); // Isso novamente não é executado. + break; + case 2: + print("Bravo!"); // Esta linha é executada. + break; + default: + print("Não encontrado!"); // Esta linha é executada se nosso valor for algum outro valor. + break; +} + +// Declarações iterativas +// Declarações For - Novamente, a mesma sintaxe que em Java +for(int i = 0; i < 5; i++){ + print(i); // imprime de 0 a 4 +} + +// Declarações While - Novamente, nada de novo se você estiver familiarizado com +// a sintaxe Java. +int j = 3; +while(j > 0) { + print(j); + j--; // Isso é importante para evitar que o código seja executado indefinidamente. +} + +// loop()| noLoop() | redraw() | exit() +// Estas são mais funções específicas do Processing para configurar o fluxo do +// programa. +loop(); // permite que o método draw() seja executado para sempre enquanto +noLoop(); // só permite que ele seja executado uma vez. +redraw(); // executa o método draw() mais uma vez. +exit(); // Isso para o programa. É útil para programas com draw() +// rodando continuamente. +``` + +## Desenho com Processing + +Como você já deve ter entendido o básico da linguagem, vamos agora +ver a melhor parte do Processing - DESENHAR. + +``` +/* ------ + Formas + ------ +*/ + +// Formas 2D + +// Ponto +point(x, y); // No espaço 2D +point(x, y, z); // No espaço 3D +// Desenha um ponto no espaço de coordenadas. + +// Linha +line(x1, y1, x2, y2); // No espaço 2D +line(x1, y1, z1, x2, y2, z2); // No espaço 3D +// Desenha uma linha conectando dois pontos definidos por (x1, y1) e (x2, y2). + +// Triângulo +triangle(x1, y1, x2, y2, x3, y3); +// Desenha um triângulo conectando três pontos definidos por parâmetros de coordenadas. + +// Retângulo +rect(a, b, c, d, [r]); // Com parâmetro opcional definindo o raio de todos os cantos +rect(a, b, c, d, [te, td, bd, be]); // Com conjunto opcional de parâmetros definindo +// raio de cada canto +// Desenha um retângulo com {a, b} como coordenada superior esquerda e c e d como largura +// e altura respectivamente. + +// Quad +quad(x, y, x2, y2, x3, y3, x4, y4); +// Desenha um quadrilátero com parâmetros que definem as coordenadas de cada canto +// ponto. + +// Elipse +ellipse(x, y, largura, altura); +// Desenha um eclipse no ponto {x, y} com largura e altura especificadas. + +// Arco +arc(x, y, largura, altura, inicio, fim, [modo]); +// Enquanto os primeiros quatro parâmetros são autoexplicativos, +// início e fim definem os ângulos que o arco começa e termina (em radianos). +// O parâmetro opcional [mode] define o preenchimento; +// PIE dá o contorno de torta, CHORD dá o contorno reto e OPEN é como +// CHORD porém sem contorno + +// Curvas +// O Processing fornece duas implementações de curvas; usando curve() e +// bezier(). Como pretendo manter isso simples, não vou discutir mais detalhes. +// No entanto, se você quiser implementá-lo em seu sketch, aqui estão as +// referências: (https://processing.org/reference/curve_.html) +// (https://processing.org/reference/bezier_.html) + +// Formas 3D + +// espaço 3D +pode ser configurado definindo "P3D" para o parâmetro do renderizador no +// método size(). +size(largura, altura, P3D); +// No espaço 3D, você terá que traduzir para a coordenada específica para +// renderiza as formas 3D. + +// Caixa +box(tamanho); // Cubo com o mesmo comprimento definido pelo tamanho +box(w, h, d); // Caixa com largura, altura e profundidade definidas separadamente + +// Esfera +sphere(raio); // Seu tamanho é definido usando o parâmetro raio +// O mecanismo por trás da renderização das esferas é implementado por +// triângulos em mosaico. Dito isso, o nível de detalhe sendo renderizado é +// controlado pela função sphereDetail(res) +// Mais informações aqui: (https://processing.org/reference/sphereDetail_.html) + +// Formas irregulares +// E se você quiser desenhar algo que não foi disponibilizado pelo Processing +// funções? +// Você pode usar beginShape(), endShape(), vertex(x,y) para definir formas por +// especificando cada ponto. Mais informações aqui: +// (https://processing.org/reference/beginShape_.html) +// Você também pode usar formas personalizadas usando a classe PShape: +// (https://processing.org/reference/PShape.html) + +/* --------------- + Transformações + --------------- +*/ + +// As transformações são particularmente úteis para acompanhar o espaço de +// coordenadas e os vértices das formas que você desenhou. Particularmente; +// métodos de pilha de matrizes; pushMatrix(), popMatrix() e translate(x,y) +pushMatriz(); // Salva o sistema de coordenadas atual na pilha +// ... aplique todas as transformações aqui ... +popMatriz(); // Restaura o sistema de coordenadas salvo +// Usando-os, o sistema de coordenadas pode ser preservado e visualizado sem +// causar qualquer conflito. + +// Traduzir +translate(x,y); // Traduz para o ponto{x, y} ou seja - configurando a origem para esse ponto +translate(x, y, z); // Contraparte 3D da função + +// Rotacionar +rotate(ângulo); // Gira a quantidade especificada pelo parâmetro ângulo +// Possui 3 contrapartes 3D para realizar a rotação, uma para cada dimensão: +// rotateX(ângulo), rotateY(ângulo), rotateZ(ângulo) + +// Escala +scale(s); // Dimensiona o sistema de coordenadas expandindo ou contraindo-o. + +/* -------------------- + Estilo e texturas + -------------------- +*/ + +// Cores +// Como discuti anteriormente, a cor de fundo pode ser configurada usando a +// função background(). Você pode definir a cor de um objeto de antemão e depois +// passar para a função como um argumento. +color c = cor(255, 255, 255); // BRANCO! +// Por padrão, o Processing usa o esquema de cores RGB, mas pode ser configurado +// para HSB usando colorMode(). Leia mais aqui: +// (https://processing.org/reference/colorMode_.html) +background(c); // Até agora, a cor de fundo deve ser branca. +// Você pode usar a função fill() para selecionar a cor para preencher as formas. +// Tem que ser configurado antes de você começar a desenhar formas para que as +// cores fiquem aplicadas. +fill(color(0, 0, 0)); +// Se você quiser apenas colorir os contornos das formas, você pode usar +// função stroke(). +stroke(255, 255, 0, 200); // cor do traço definida para amarelo com transparência +// definido para um valor menor. + +// Imagens +// O Processing pode renderizar imagens e usá-las de várias maneiras. +// Principalmente armazenado como Tipo de dados PImage. +filter(sombreador); // O Processing suporta várias funções de filtro para manipulação de imagens. +texture(imagem); // PImage pode ser passado em argumentos para mapeamento de textura das formas. +``` + +Se você quiser levar as coisas adiante, há mais coisas que o Processing tem o poder de fazer. Renderizar modelos, shaders e outros efeitos. Há muito para se cobrir em uma +documentação curta, então vou deixá-los aqui. Se você se interessar, por favor verifique as referências. + +``` +// Antes de prosseguirmos, vou falar um pouco mais sobre como importar bibliotecas +// para que você possa estender a funcionalidade do Processing para outros horizontes. + +/* ------- + Importações + ------- +*/ + +// As possibilidades do Processing pode ser estendidas ainda mais quando +// importamos bibliotecas e pacotes em nossos esboços. +// A instrução de importação pode ser escrita como abaixo na parte superior +// do código-fonte. +import processing.algumacoisa.*; +``` + +## VAC? + +Vamos ao código? Vamos sujar as mãos! + +Vamos ver um exemplo do openprocessing para visualizar o quanto o Processing é +capaz de fazer com poucas linhas de código. + +Copie o código abaixo em seu IDE do Processing e veja a mágica. + +``` +// Isenção de responsabilidade: eu não escrevi este programa porque atualmente +// estou ocupado com meu estágio e este sketch é adaptado do openprocessing pois +// mostra algo legal com um código simples. +// Recuperado de: (https://www.openprocessing.org/sketch/559769) + +float theta; +float a; +float col; +float num; + +void setup() { + size(600,600); +} + +void draw() { + background(#F2F2F2); + translate(width/2, height/2); + theta = map(sin(millis()/1000.0), -1, 1, 0, PI/6); + + float num=6; + for (int i=0; i<num; i++) { + a =350; + rotate(TWO_PI/num); + branch(a); + } + +} + +void branch(float len) { + col=map(len, 0, 90, 150, 255); + fill(col, 0, 74); + stroke (col, 0, 74); + line(0, 0, 0, -len); + ellipse(0, -len, 3, 3); + len *= 0.7; + + if (len>30) { + pushMatrix(); + translate(0, -30); + rotate(theta); + branch(len); + popMatrix(); + + pushMatrix(); + translate(0, -30); + rotate(-theta); + branch(len); + popMatrix(); + + } +} +``` + +A linguagem Processing é fácil de aprender e é particularmente útil para criar +conteúdo (mesmo em 3D) sem ter que digitar muitos códigos. É tão simples +que você pode ler o código e ter uma ideia aproximada do fluxo do programa. + +No entanto, isso não se aplica quando você introduz bibliotecas externas, pacotes +e até mesmo suas próprias aulas. (Confie em mim! Projetos em processing podem ficar realmente monstruosos...) + +## Alguns recursos úteis + + - [Site do Processing](http://processing.org) + - [Sketches em Processing](http://openprocessing.org) diff --git a/pt-br/pug-pt.html.markdown b/pt-br/pug-pt.html.markdown new file mode 100644 index 00000000..52eda86a --- /dev/null +++ b/pt-br/pug-pt.html.markdown @@ -0,0 +1,211 @@ +--- +language: Pug +contributors: + - ["Michael Warner", "https://github.com/MichaelJGW"] +filename: index-pt.pug +translators: + - ["Adaías Magdiel", "https://adaiasmagdiel.com/"] +lang: pt-br +--- + +## Começando com Pug + +Pug é uma pequena linguagem que compila para HTML. Possui uma sintaxe limpa +com algumas funcionalidades adicionais, como declarações if e loops. Também pode ser utilizada +como uma linguagem de templates no lado do servidor para tecnologias como o Node.js. + +### The Language +```pug + +//- Comentário de uma linha + +//- Comentário de + várias linhas + +//- ---TAGS--- +//- Básico +div +//- <div></div> +h1 +//- <h1></h1> +minha-propriaTag +//- <minha-propriaTag></minha-propriaTag> + +//- Tags irmãs +div +div +//- <div></div> + <div></div> + +//- Tags aninhadas +div + div +//- <div> + <div></div> + </div> + +//- Textos +h1 Olá, pessoas +//- <h1>Olá, pessoas</h1> + +//- Texto de várias linhas +div. + Oi, + tudo bem? +//- <div> + Oi, + tudo bem? + </div> + +//- ---ATRIBUTOS--- +div(class="minha-class" id="meu-id" meu-proprio-atributo="data" enabled) +//- <div class="minha-class" id="meu-id" meu-proprio-atributo="data" enabled></div> + +//- Abreviações +span.minha-class +//- <span class="minha-class"></span> +.minha-class +//- <div class="minha-class"></div> +div#meu-id +//- <div id="meu-id"></div> +div#meu-id.minha-class +//- <div class="minha-class" id="meu-id"></div> + + +//- ---JAVASCRIPT--- +- const lang = "pug"; + +//- Javascript em várias linhas +- + const lang = "pug"; + const awesome = true; + +//- Classes com Javascript +- const myClass = ['class1', 'class2', 'class3'] +div(class=myClass) +//- <div class="class1 class2 class3"></div> + +//- Estilos com Javascript +- const myStyles = {'color':'white', 'background-color':'blue'} +div(styles=myStyles) +//- <div styles="{"color":"white","background-color":"blue"}"></div> + +//- Atributos com Javascript +- const myAttributes = {"src": "photo.png", "alt": "My Photo"} +img&attributes(myAttributes) +//- <img src="photo.png" alt="My Photo"> +- let disabled = false +input(type="text" disabled=disabled) +//- <input type="text"> +- disabled = true +input(type="text" disabled=disabled) +//- <input type="text" disabled> + +//- Templates com Javascript +- const name = "Bob"; +h1 Olá, #{name} +h1= name +//- <h1>Olá, Bob</h1> +//- <h1>Bob</h1> + +//- ---LOOPS--- + +//- 'each' e 'for' tem a mesma função, aqui nós usaremos apenas 'each'. + +each value, i in [1,2,3] + p=value +//- + <p>1</p> + <p>2</p> + <p>3</p> + +each value, index in [1,2,3] + p=value + '-' + index +//- + <p>1-0</p> + <p>2-1</p> + <p>3-2</p> + +each value in [] + p=value +//- + +each value in [] + p=value +else + p Sem valores + +//- <p>Sem valores</p> + +//- ---CONDICIONAIS--- + +- const number = 5 +if number < 5 + p o número é menor do que 5 +else if number > 5 + p o número é maior do que 5 +else + p o número é 5 +//- <p>o número é 5</p> + +- const orderStatus = "Aguardando"; +case orderStatus + when "Aguardando" + p.warn Seu pedido está em espera + when "Completado" + p.success Seu pedido foi completado. + when -1 + p.error Ocorreu algum erro + default + p Nenhum registro de pedido encontrado +//- <p class="warn">Seu pedido está em espera</p> + +//- --INCLUINDO CONTEÚDOS-- +//- Caminho do arquivo -> "includes/nav.pug" +h1 Indústrias ACME +nav + a(href="index.html") Início + a(href="about.html") Sobre Nós + +//- Caminho do arquivo -> "index.pug" +html + body + include includes/nav.pug +//- + <html> + <body> + <h1>Indústrias ACME</h1> + <nav><a href="index.html">Início</a><a href="about.html">Sobre Nós</a></nav> + </body> + </html> + +//- Importando Javascript e CSS +script + include scripts/index.js +style + include styles/theme.css + +//- ---MIXIN--- +mixin basic + div Olá ++basic +//- <div>Olá</div> + +mixin comment(nome, comentario) + div + span.comment-name= nome + div.comment-text= comentario ++comment("Gil", "Tudo é divino, tudo é maravilhoso") +//- + <div> + <span class="comment-name">Gil</span> + <div class="comment-text">Tudo é divino, tudo é maravilhoso</div> + </div> + +``` + + +### Saiba Mais +- [Site Oficial](https://pugjs.org/) +- [Documentação](https://pugjs.org/api/getting-started.html) +- [Repositório no GitHub](https://github.com/pugjs/pug) diff --git a/pt-br/pyqt-pt.html.markdown b/pt-br/pyqt-pt.html.markdown index 40fe82d5..42f744e2 100644 --- a/pt-br/pyqt-pt.html.markdown +++ b/pt-br/pyqt-pt.html.markdown @@ -24,7 +24,7 @@ o pyqt! ```python import sys from PyQt4 import QtGui - + def window(): # Cria um objeto para a aplicação app = QtGui.QApplication(sys.argv) @@ -54,7 +54,7 @@ outros elementos. Aqui mostraremos como criar uma janela popup, muito útil para perguntar ao usuário qual decisão tomar ou exibir alguma informação. -```Python +```python import sys from PyQt4.QtGui import * from PyQt4.QtCore import * @@ -73,7 +73,7 @@ def window(): w.setWindowTitle("PyQt Dialog") w.show() sys.exit(app.exec_()) - + # Essa função deve criar uma janela de diálogo com um botão, # aguarda ser clicado e encerra o programa def showdialog(): diff --git a/pt-br/python-pt.html.markdown b/pt-br/python-pt.html.markdown index 82b70117..3f9c54c1 100644 --- a/pt-br/python-pt.html.markdown +++ b/pt-br/python-pt.html.markdown @@ -1,29 +1,36 @@ --- -language: python +language: Python contributors: - - ["Louie Dinh", "http://ldinh.ca"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] translators: - - ["Vilson Vieira", "http://automata.cc"] + - ["Paulo Henrique Rodrigues Pinheiro", "http://www.sysincloud.it"] + - ["Monique Baptista", "https://github.com/bfmonique"] lang: pt-br filename: learnpython-pt.py --- -Python foi criado por Guido Van Rossum no começo dos anos 90. Atualmente é uma -das linguagens de programação mais populares. Eu me apaixonei por Python, por -sua clareza de sintaxe. É basicamente pseudocódigo executável. +Python foi criada por Guido Van Rossum nos anos 1990. Ela é atualmente uma +das linguagens mais populares existentes. Eu me apaixonei por +Python por sua clareza sintática. É praticamente pseudocódigo executável. -Comentários serão muito apreciados! Você pode me contactar em -[@louiedinh](http://twitter.com/louiedinh) ou louiedinh [arroba] -[serviço de email do google] +Opniões são muito bem vindas. Você pode encontrar-me em +[@louiedinh](http://twitter.com/louiedinh) ou louiedinh [em] +[serviço de e-mail do google]. -Nota: Este artigo usa Python 2.7 especificamente, mas deveria ser aplicável a -qualquer Python 2.x. Logo haverá uma versão abordando Python 3! +Observação: Este artigo trata de Python 3 especificamente. Verifique +[aqui](http://learnxinyminutes.com/docs/pt-br/python-pt/) se você pretende +aprender o velho Python 2.7. ```python -# Comentários de uma linha começam com cerquilha (ou sustenido) + +# Comentários em uma única linha começam com uma cerquilha (também conhecido por sustenido). + """ Strings de várias linhas podem ser escritas usando três ", e são comumente usadas - como comentários + como comentários. """ #################################################### @@ -31,287 +38,385 @@ qualquer Python 2.x. Logo haverá uma versão abordando Python 3! #################################################### # Você usa números normalmente -3 #=> 3 - -# Operadores matemáticos são aqueles que você já está acostumado -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 - -# A divisão é um pouco estranha. A divisão de números inteiros arredonda -# para baixo o resultado, automaticamente -5 / 2 #=> 2 +3 # => 3 -# Para concertar a divisão, precisamos aprender sobre números de ponto -# flutuante (conhecidos como 'float'). -2.0 # Isso é um 'float' -11.0 / 4.0 #=> 2.75 ahhh... muito melhor +# Matemática é como você espera que seja +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 -# Forçamos a precedência de operadores usando parênteses -(1 + 3) * 2 #=> 8 +# Números são inteiros por padrão, exceto na divisão, que retorna número +# de ponto flutuante (float). +35 / 5 # => 7.0 -# Valores booleanos (ou 'boolean') são também tipos primitivos -True -False +# O resultado da divisão inteira arredonda para baixo tanto para números +# positivos como para negativos. +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # funciona em float também +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 -# Negamos usando 'not' -not True #=> False -not False #=> True +# Quando você usa um float, o resultado é float. +3 * 2.0 # => 6.0 -# Testamos igualdade usando '==' -1 == 1 #=> True -2 == 1 #=> False +# operador módulo +7 % 3 # => 1 -# E desigualdade com '!=' -1 != 1 #=> False -2 != 1 #=> True - -# Mais comparações -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True +# Exponenciação (x**y, x elevado à potência y) +2**4 # => 16 -# As comparações podem ser encadeadas! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +# Determine a precedência usando parênteses +(1 + 3) * 2 # => 8 -# Strings são criadas com " ou ' -"Isso é uma string." -'Isso também é uma string.' +# Valores lógicos são primitivos (Atenção à primeira letra maiúscula) +True +False -# Strings podem ser somadas (ou melhor, concatenadas)! -"Olá " + "mundo!" #=> "Olá mundo!" +# negação lógica com not +not True # => False +not False # => True -# Uma string pode ser tratada como uma lista de caracteres -"Esta é uma string"[0] #=> 'E' +# Operadores lógicos +# Observe que "and" e "or" são sensíveis a maiúsculas e minúsculas +True and False # => False +False or True # => True -# O caractere % pode ser usado para formatar strings, desta forma: -"%s podem ser %s" % ("strings", "interpoladas") +# Observe a utilização de operadores lógicos com números inteiros +0 and 2 # => 0 +-5 or 0 # => -5 +0 == False # => True +2 == True # => False +1 == True # => True -# Um jeito novo de formatar strings é usando o método 'format'. -# Esse método é o jeito mais usado -"{0} podem ser {1}".format("strings", "formatadas") -# Você pode usar palavras-chave (ou 'keywords') se você não quiser contar. -"{nome} quer comer {comida}".format(nome="João", comida="lasanha") +# Igualdade é == +1 == 1 # => True +2 == 1 # => False -# 'None' é um objeto -None #=> None +# Diferença é != +1 != 1 # => False +2 != 1 # => True -# Não use o operador de igualdade `==` para comparar objetos com 'None' -# Ao invés disso, use `is` -"etc" is None #=> False -None is None #=> True +# Mais comparações +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# Comparações podem ser agrupadas +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# 'is' verifica se duas variáveis representam o mesmo endereço +# na memória; '==' verifica se duas variáveis têm o mesmo valor +a = [1, 2, 3, 4] # Referência a uma nova lista, [1, 2, 3, 4] +b = a # b referencia o que está referenciado por a +b is a # => True, a e b referenciam o mesmo objeto +b == a # => True, objetos a e b tem o mesmo conteúdo +b = [1, 2, 3, 4] # Referência a uma nova lista, [1, 2, 3, 4] +b is a # => False, a e b não referenciam o mesmo objeto +b == a # => True, objetos a e b tem o mesmo conteúdo -# O operador 'is' teste a identidade de um objeto. Isso não é -# muito útil quando estamos lidando com valores primitivos, mas é -# muito útil quando lidamos com objetos. +# Strings são criadas com " ou ' +"Isto é uma string." +'Isto também é uma string.' -# None, 0, e strings/listas vazias são todas interpretadas como 'False'. -# Todos os outros valores são 'True' -0 == False #=> True -"" == False #=> True +# Strings também podem ser somadas! Mas tente não fazer isso. +"Olá " + "mundo!" # => "Olá mundo!" +# Strings podem ser somadas sem usar o '+' +"Olá " "mundo!" # => "Olá mundo!" +# Uma string pode ser manipulada como se fosse uma lista de caracteres +"Isso é uma string"[0] # => 'I' -#################################################### -## 2. Variáveis e Coleções -#################################################### +# .format pode ser usado para formatar strings, dessa forma: +"{} podem ser {}".format("Strings", "interpoladas") # => "Strings podem ser interpoladas" -# Imprimir na tela é muito fácil -print "Eu sou o Python. Prazer em te conhecer!" +# Você pode repetir os argumentos para digitar menos. +"Seja ágil {0}, seja rápido {0}, salte sobre o {1} {0}".format("Jack", "castiçal") +# => "Seja ágil Jack, seja rápido Jack, salte sobre o castiçal Jack." +# Você pode usar palavras-chave se quiser contar. +"{nome} quer comer {comida}".format(nome="Beto", comida="lasanha") # => "Beto quer comer lasanha" -# Nós não precisamos declarar variáveis antes de usá-las, basta usar! -alguma_variavel = 5 # A convenção é usar caixa_baixa_com_sobrescritos -alguma_variavel #=> 5 +# Se você precisa executar seu código Python3 com um interpretador Python 2.5 ou acima, você pode usar a velha forma para formatação de texto: +"%s podem ser %s da forma %s" % ("Strings", "interpoladas", "antiga") # => "Strings podem ser interpoladas da forma antiga" -# Acessar uma variável que não teve nenhum valor atribuído anteriormente é -# uma exceção. -# Veja a seção 'Controle' para aprender mais sobre tratamento de exceção. -outra_variavel # Gera uma exceção de erro de nome -# 'if' pode ser usado como uma expressão -"uepa!" if 3 > 2 else 2 #=> "uepa!" +# None é um objeto +None # => None -# Listas armazenam sequências de elementos -lista = [] -# Você pode inicializar uma lista com valores -outra_lista = [4, 5, 6] +# Não use o operador de igualdade "==" para comparar objetos com None +# Use "is" para isso. Ele checará pela identidade dos objetos. +"etc" is None # => False +None is None # => True -# Adicione elementos no final da lista usando 'append' -lista.append(1) # lista é agora [1] -lista.append(2) # lista é agora [1, 2] -lista.append(4) # lista é agora [1, 2, 4] -lista.append(3) # lista é agora [1, 2, 4, 3] -# Remova elementos do fim da lista usando 'pop' -lista.pop() #=> 3 e lista é agora [1, 2, 4] -# Vamos adicionar o elemento novamente -lista.append(3) # lista agora é [1, 2, 4, 3] novamente. +# None, 0, e strings/listas/dicionários vazios todos retornam False. +# Qualquer outra coisa retorna True +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False -# Acesse elementos de uma lista através de seu índices -lista[0] #=> 1 -# Acesse o último elemento com índice negativo! -lista[-1] #=> 3 -# Tentar acessar um elemento fora dos limites da lista gera uma exceção -# do tipo 'IndexError' -lista[4] # Gera uma exceção 'IndexError' - -# Você pode acessar vários elementos ao mesmo tempo usando a sintaxe de -# limites -# (Para quem gosta de matemática, isso é um limite fechado/aberto) -lista[1:3] #=> [2, 4] -# Você pode omitir o fim se quiser os elementos até o final da lista -lista[2:] #=> [4, 3] -# O mesmo para o início -lista[:3] #=> [1, 2, 4] +#################################################### +## 2. Variáveis e coleções +#################################################### -# Remova um elemento qualquer de uma lista usando 'del' -del lista[2] # lista agora é [1, 2, 3] +# Python tem uma função print +print("Eu sou o Python. Prazer em conhecer!") # => Eu sou o Python. Prazer em conhecer! + +# Por padrão a função print também imprime o caractere de nova linha ao final. +# Use o argumento opcional end para mudar o caractere final. +print("Olá, Mundo", end="!") # => Olá, Mundo! + +# Forma simples para capturar dados de entrada via console +input_string_var = input("Digite alguma coisa: ") # Retorna o que foi digitado em uma string +# Observação: Em versões antigas do Python, o método input() era chamado raw_input() + +# Não é necessário declarar variáveis antes de iniciá-las +# É uma convenção usar letras_minúsculas_com_sublinhados +alguma_variavel = 5 +alguma_variavel # => 5 + +# Acessar uma variável que não tenha sido inicializada gera uma exceção. +# Veja Controle de Fluxo para aprender mais sobre tratamento de exceções. +alguma_variavel_nao_inicializada # Gera a exceção NameError + +# Listas armazenam sequências +li = [] +# Você pode iniciar uma lista com valores +outra_li = [4, 5, 6] + +# Adicione conteúdo ao fim da lista com append +li.append(1) # li agora é [1] +li.append(2) # li agora é [1, 2] +li.append(4) # li agora é [1, 2, 4] +li.append(3) # li agora é [1, 2, 4, 3] +# Remova do final da lista com pop +li.pop() # => 3 e agora li é [1, 2, 4] +# Vamos colocá-lo lá novamente! +li.append(3) # li agora é [1, 2, 4, 3] novamente. + +# Acesse uma lista da mesma forma que você faz com um array +li[0] # => 1 +# Acessando o último elemento +li[-1] # => 3 + +# Acessar além dos limites gera um IndexError +li[4] # Gera o IndexError + +# Você pode acessar vários elementos com a sintaxe de limites +# Inclusivo para o primeiro termo, exclusivo para o segundo +li[1:3] # => [2, 4] +# Omitindo o final +li[2:] # => [4, 3] +# Omitindo o início +li[:3] # => [1, 2, 4] +# Selecione cada segunda entrada +li[::2] # => [1, 4] +# Tenha uma cópia em ordem invertida da lista +li[::-1] # => [3, 4, 2, 1] +# Use qualquer combinação dessas para indicar limites complexos +# li[inicio:fim:passo] + +# Faça uma cópia profunda de um nível usando limites +li2 = li[:] # => li2 = [1, 2, 4, 3] mas (li2 is li) resultará em False. + +# Apague elementos específicos da lista com "del" +del li[2] # li agora é [1, 2, 3] + +# Você pode somar listas +# Observação: valores em li e other_li não são modificados. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Concatene listas com "extend()" +li.extend(other_li) # Agora li é [1, 2, 3, 4, 5, 6] + +# Verifique se algo existe na lista com "in" +1 in li # => True + +# Examine tamanho com "len()" +len(li) # => 6 + + +# Tuplas são como l istas, mas imutáveis. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Gera um TypeError + +# Observe que uma tupla de tamanho um precisa ter uma vírgula depois do +# último elemento mas tuplas de outros tamanhos, mesmo vazias, não precisa,. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# Você pode realizar com tuplas a maior parte das operações que faz com listas +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Você pode desmembrar tuplas (ou listas) em variáveis. +a, b, c = (1, 2, 3) # a é 1, b é 2 e c é 3 +# Por padrão, tuplas são criadas se você não coloca parêntesis. +d, e, f = 4, 5, 6 +# Veja como é fácil permutar dois valores +e, d = d, e # d é 5, e é 4 -# Você pode somar listas (obs: as listas originais não são modificadas) -lista + outra_lista #=> [1, 2, 3, 4, 5, 6] +# Dicionários armazenam mapeamentos +empty_dict = {} +# Aqui está um dicionário preenchido na definição da referência +filled_dict = {"um": 1, "dois": 2, "três": 3} -# Você também pode concatenar usando o método 'extend' (lista será modificada!) -lista.extend(outra_lista) # Agora lista é [1, 2, 3, 4, 5, 6] +# Observe que chaves para dicionários devem ser tipos imutáveis. Isto é para +# assegurar que a chave pode ser convertida para uma valor hash constante para +# buscas rápidas. +# Tipos imutáveis incluem inteiros, flotas, strings e tuplas. +invalid_dict = {[1,2,3]: "123"} # => Gera um TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Já os valores, podem ser de qualquer tipo. -# Para checar se um elemento pertence a uma lista, use 'in' -1 in lista #=> True +# Acesse valores com [] +filled_dict["um"] # => 1 -# Saiba quantos elementos uma lista possui com 'len' -len(lista) #=> 6 +# Acesse todas as chaves como um iterável com "keys()". É necessário encapsular +# a chamada com um list() para transformá-las em uma lista. Falaremos sobre isso +# mais adiante. Observe que a ordem de uma chave de dicionário não é garantida. +# Por isso, os resultados aqui apresentados podem não ser exatamente como os +# aqui apresentados. +list(filled_dict.keys()) # => ["três", "dois", "um"] -# Tuplas são iguais a listas, mas são imutáveis -tup = (1, 2, 3) -tup[0] #=> 1 -tup[0] = 3 # Isso gera uma exceção do tipo TypeError - -# Você pode fazer nas tuplas todas aquelas coisas fez com a lista -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True - -# Você pode 'desempacotar' tuplas (ou listas) em variáveis, associando cada -# elemento da tupla/lista a uma variável correspondente -a, b, c = (1, 2, 3) # a agora é 1, b agora é 2, c agora é 3 -# Tuplas são criadas por padrão, mesmo se você não usar parênteses -d, e, f = 4, 5, 6 -# Sabendo disso, veja só como é fácil trocar os valores de duas variáveis! -e, d = d, e # d agora é 5, e agora é 4 +# Acesse todos os valores de um iterável com "values()". Novamente, é +# necessário encapsular ele com list() para não termos um iterável, e sim os +# valores. Observe que, como foi dito acima, a ordem dos elementos não é +# garantida. +list(filled_dict.values()) # => [3, 2, 1] -# Dicionários armazenam 'mapeamentos' (do tipo chave-valor) -dicionario_vazio = {} -# Aqui criamos um dicionário já contendo valores -dicionario = {"um": 1, "dois": 2, "três": 3} +# Verifique a existência de chaves em um dicionário com "in" +"um" in filled_dict # => True +1 in filled_dict # => False -# Acesse valores usando [] -dicionario["um"] #=> 1 +# Acessar uma chave inexistente gera um KeyError +filled_dict["quatro"] # KeyError -# Retorna uma lista com todas as chaves do dicionário -dicionario.keys() #=> ["três", "dois", "um"] -# Nota: A ordem das chaves não é garantida. -# O resultado no seu interpretador não necessariamente será igual a esse. +# Use o método "get()" para evitar um KeyError +filled_dict.get("um") # => 1 +filled_dict.get("quatro") # => None +# O método get permite um parâmetro padrão para quando não existir a chave +filled_dict.get("um", 4) # => 1 +filled_dict.get("quatro", 4) # => 4 -# Retorna uma lista com todos os valores do dicionário -dicionario.values() #=> [3, 2, 1] -# Nota: A mesma nota acima sobre a ordenação é válida aqui. +# "setdefault()" insere em dicionário apenas se a dada chave não existir +filled_dict.setdefault("cinco", 5) # filled_dict["cinco"] tem valor 5 +filled_dict.setdefault("cinco", 6) # filled_dict["cinco"] continua 5 -# Veja se uma chave qualquer está em um dicionário usando 'in' -"um" in dicionario #=> True -1 in dicionario #=> False +# Inserindo em um dicionário +filled_dict.update({"quatro":4}) # => {"um": 1, "dois": 2, "três": 3, "quatro": 4} +#filled_dict["quatro"] = 4 #outra forma de inserir em um dicionário -# Tentar acessar uma chave que não existe gera uma exceção do tipo 'KeyError' -dicionario["quatro"] # Gera uma exceção KeyError +# Remova chaves de um dicionário com del +del filled_dict["um"] # Remove a chave "um" de filled_dict -# Você pode usar o método 'get' para evitar gerar a exceção 'KeyError'. -# Ao invés de gerar essa exceção, irá retornar 'None' se a chave não existir. -dicionario.get("um") #=> 1 -dicionario.get("quatro") #=> None -# O método 'get' suporta um argumento que diz qual valor deverá ser -# retornado se a chave não existir (ao invés de 'None'). -dicionario.get("um", 4) #=> 1 -dicionario.get("quatro", 4) #=> 4 -# O método 'setdefault' é um jeito seguro de adicionar um novo par -# chave-valor a um dicionário, associando um valor padrão imutável à uma chave -dicionario.setdefault("cinco", 5) # dicionario["cinco"] é definido como 5 -dicionario.setdefault("cinco", 6) # dicionario["cinco"] ainda é igual a 5 +# Armazenamento em sets... bem, são conjuntos +empty_set = set() +# Inicializa um set com alguns valores. Sim, ele parece um dicionário. Desculpe. +some_set = {1, 1, 2, 2, 3, 4} # some_set agora é {1, 2, 3, 4} +# Da mesma forma que chaves em um dicionário, elementos de um set devem ser +# imutáveis. +invalid_set = {[1], 1} # => Gera um TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Conjuntos (ou sets) armazenam ... bem, conjuntos -# Nota: lembre-se que conjuntos não admitem elementos repetidos! -conjunto_vazio = set() -# Podemos inicializar um conjunto com valores -conjunto = set([1, 2, 2, 3, 4]) # conjunto é set([1, 2, 3, 4]), sem repetição! +# Pode definir novas variáveis para um conjunto +filled_set = some_set -# Desde o Python 2.7, {} pode ser usado para declarar um conjunto -conjunto = {1, 2, 2, 3, 4} # => {1 2 3 4} +# Inclua mais um item no set +filled_set.add(5) # filled_set agora é {1, 2, 3, 4, 5} -# Adicione mais ítens a um conjunto com 'add' -conjunto.add(5) # conjunto agora é {1, 2, 3, 4, 5} +# Faça interseção de conjuntos com & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} -# Calcule a intersecção de dois conjuntos com & -outro_conj = {3, 4, 5, 6} -conjunto & outro_conj #=> {3, 4, 5} +# Faça união de conjuntos com | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} -# Calcule a união de dois conjuntos com | -conjunto | outro_conj #=> {1, 2, 3, 4, 5, 6} +# Faça a diferença entre conjuntos com - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} -# E a diferença entre dois conjuntos com - -{1,2,3,4} - {2,3,5} #=> {1, 4} +# Verifique a existência em um conjunto com in +2 in filled_set # => True +10 in filled_set # => False -# Veja se um elemento existe em um conjunto usando 'in' -2 in conjunto #=> True -10 in conjunto #=> False #################################################### -## 3. Controle +## 3. Controle de fluxo e iteráveis #################################################### -# Para começar, vamos apenas criar uma variável -alguma_var = 5 +# Iniciemos um variável +some_var = 5 -# Aqui está uma expressão 'if'. Veja como a identação é importante em Python! -# Esses comandos irão imprimir "alguma_var é menor que 10" -if alguma_var > 10: - print "some_var é maior que 10." -elif some_var < 10: # Esse 'elif' é opcional - print "some_var é menor que 10." -else: # Esse 'else' também é opcional - print "some_var é igual a 10." +# Aqui está uma expressão if. Indentação é significante em python! +# imprime "somevar é menor que10" +if some_var > 10: + print("some_var é absolutamente maior que 10.") +elif some_var < 10: # Esta cláusula elif é opcional. + print("some_var é menor que 10.") +else: # Isto também é opcional. + print("some_var é, de fato, 10.") """ -Laços (ou loops) 'for' iteram em listas. -Irá imprimir: +Laços for iteram sobre listas +imprime: cachorro é um mamífero gato é um mamífero rato é um mamífero """ for animal in ["cachorro", "gato", "rato"]: - # Você pode usar % para interpolar strings formatadas - print "%s é um mamífero" % animal - + # Você pode usar format() para interpolar strings formatadas + print("{} é um mamífero".format(animal)) + """ -A função `range(um número)` retorna uma lista de números -do zero até o número dado. -Irá imprimir: +"range(número)" retorna um iterável de números +de zero até o número escolhido +imprime: 0 1 2 3 """ for i in range(4): - print i + print(i) + +""" +"range(menor, maior)" gera um iterável de números +começando pelo menor até o maior +imprime: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) """ -Laços 'while' executam enquanto uma condição dada for verdadeira. -Irá imprimir: +"range(menor, maior, passo)" retorna um iterável de números +começando pelo menor número até o maior númeno, pulando de +passo em passo. Se o passo não for indicado, o valor padrão é um. +imprime: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) +""" + +Laços while executam até que a condição não seja mais válida. +imprime: 0 1 2 @@ -319,143 +424,221 @@ Irá imprimir: """ x = 0 while x < 4: - print x - x += 1 # Isso é um atalho para a expressão x = x + 1 - -# Tratamos excessões usando o bloco try/except -# Funciona em Python 2.6 e versões superiores: + print(x) + x += 1 # Maneira mais curta para for x = x + 1 +# Lide com exceções com um bloco try/except try: - # Use 'raise' para gerar um erro - raise IndexError("Isso é um erro de índice") + # Use "raise" para gerar um erro + raise IndexError("Isto é um erro de índice") except IndexError as e: - pass # Pass é um operador que não faz nada, deixa passar. - # Usualmente você iria tratar a exceção aqui... + pass # Pass é um não-operador. Normalmente você usa algum código de recuperação aqui. +except (TypeError, NameError): + pass # Varias exceções podem ser gerenciadas, se necessário. +else: # Cláusula opcional para o bloco try/except. Deve estar após todos os blocos de exceção. + print("Tudo certo!") # Executa apenas se o código em try não gera exceção +finally: # Sempre é executado + print("Nós podemos fazer o código de limpeza aqui.") + +# Ao invés de try/finally para limpeza você pode usar a cláusula with +with open("myfile.txt") as f: + for line in f: + print(line) + +# Python provê uma abstração fundamental chamada Iterável. +# Um iterável é um objeto que pode ser tratado como uma sequência. +# O objeto retornou a função range, um iterável. + +filled_dict = {"um": 1, "dois": 2, "três": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => range(1,10). Esse é um objeto que implementa nossa interface iterável. + +# Nós podemos percorrê-la. +for i in our_iterable: + print(i) # Imprime um, dois, três + +# Mas não podemos acessar os elementos pelo seu índice. +our_iterable[1] # Gera um TypeError + +# Um iterável é um objeto que sabe como criar um iterador. +our_iterator = iter(our_iterable) + +# Nosso iterador é um objeto que pode lembrar o estado enquanto nós o percorremos. +# Nós acessamos o próximo objeto com "next()". +next(our_iterator) # => "um" + +# Ele mantém o estado enquanto nós o percorremos. +next(our_iterator) # => "dois" +next(our_iterator) # => "três" + +# Após o iterador retornar todos os seus dados, ele gera a exceção StopIterator +next(our_iterator) # Gera StopIteration + +# Você pode capturar todos os elementos de um iterador aplicando list() nele. +list(filled_dict.keys()) # => Retorna ["um", "dois", "três"] #################################################### ## 4. Funções #################################################### -# Use 'def' para definir novas funções -def soma(x, y): - print "x é %s e y é %s" % (x, y) - return x + y # Retorne valores usando 'return' +# Use "def" para criar novas funções. +def add(x, y): + print("x é {} e y é {}".format(x, y)) + return x + y # Retorne valores com a cláusula return # Chamando funções com parâmetros -soma(5, 6) #=> imprime "x é 5 e y é 6" e retorna o valor 11 +add(5, 6) # => imprime "x é 5 e y é 6" e retorna 11 -# Um outro jeito de chamar funções é especificando explicitamente os valores -# de cada parâmetro com chaves -soma(y=6, x=5) # Argumentos com chaves podem vir em qualquer ordem. +# Outro meio de chamar funções é com argumentos nomeados +add(y=6, x=5) # Argumentos nomeados podem aparecer em qualquer ordem. -# Você pode definir funções que recebem um número qualquer de argumentos -# (respeitando a sua ordem) +# Você pode definir funções que pegam um número variável de argumentos +# posicionais def varargs(*args): return args -varargs(1, 2, 3) #=> (1,2,3) +varargs(1, 2, 3) # => (1, 2, 3) +# Você pode definir funções que pegam um número variável de argumentos nomeados +# também +def keyword_args(**kwargs): + return kwargs -# Você também pode definir funções que recebem um número qualquer de argumentos -# com chaves -def args_com_chaves(**ch_args): - return ch_args +# Vamos chamá-lo para ver o que acontece +keyword_args(peh="grande", lago="ness") # => {"peh": "grande", "lago": "ness"} -# Vamos chamar essa função para ver o que acontece -args_com_chaves(pe="grande", lago="Ness") #=> {"pe": "grande", "lago": "Ness"} -# Você pode fazer as duas coisas ao mesmo tempo, se desejar -def todos_args(*args, **ch_wargs): - print args - print ch_args +# Você pode fazer ambos simultaneamente, se você quiser +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) """ -todos_args(1, 2, a=3, b=4) imprime: +all_the_args(1, 2, a=3, b=4) imprime: (1, 2) {"a": 3, "b": 4} """ -# Quando você chamar funções, pode fazer o oposto do que fizemos até agora! -# Podemos usar * para expandir tuplas de argumentos e ** para expandir -# dicionários de argumentos com chave. +# Quando chamar funções, você pode fazer o oposto de args/kwargs! +# Use * para expandir tuplas e use ** para expandir dicionários! args = (1, 2, 3, 4) -ch_args = {"a": 3, "b": 4} -todos_args(*args) # equivalente a todos_args(1, 2, 3, 4) -todos_args(**ch_args) # equivalente a todos_args(a=3, b=4) -todos_args(*args, **ch_args) # equivalente a todos_args(1, 2, 3, 4, a=3, b=4) - -# Em Python, funções são elementos de primeira ordem (são como objetos, -# strings ou números) -def cria_somador(x): - def somador(y): +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalente a foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalente a foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) + +# Retornando múltiplos valores (com atribuição de tuplas) +def swap(x, y): + return y, x # Retorna múltiplos valores como uma tupla sem os parêntesis. + # (Observação: os parêntesis foram excluídos mas podem estar + # presentes) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Novamente, os parêntesis foram excluídos mas podem estar presentes. + +# Escopo de função +x = 5 + +def setX(num): + # A variável local x não é a mesma variável global x + x = num # => 43 + print (x) # => 43 + +def setGlobalX(num): + global x + print (x) # => 5 + x = num # variável global x agora é 6 + print (x) # => 6 + +setX(43) +setGlobalX(6) + + +# Python tem funções de primeira classe +def create_adder(x): + def adder(y): return x + y - return somador + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 -soma_10 = cria_somador(10) -soma_10(3) #=> 13 +# Também existem as funções anônimas +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 -# Desta forma, existem também funções anônimas -(lambda x: x > 2)(3) #=> True +# TODO - Fix for iterables +# Existem funções internas de alta ordem +map(add_10, [1, 2, 3]) # => [11, 12, 13] +map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] -# E existem funções de alta ordem por padrão -map(soma_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] -reduce(lambda x, y: x + y, [3, 4, 5, 6, 7]) #=> 25 +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] -# Nós podemos usar compreensão de listas para mapear e filtrar também -[soma_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +# Nós podemos usar compreensão de lista para interessantes mapas e filtros +# Compreensão de lista armazena a saída como uma lista que pode ser uma lista +# aninhada +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] #################################################### ## 5. Classes #################################################### -# Para criar uma nova classe, devemos herdar de 'object' -class Humano(object): - # Um atributo de classe. Ele é compartilhado por todas as instâncias dessa - # classe - especie = "H. sapiens" - - # Definimos um inicializador básico - def __init__(self, nome): - # Atribui o valor de argumento dado a um atributo da instância - self.nome = nome +# Nós usamos o operador "class" para ter uma classe +class Human: - # Um método de instância. Todos os métodos levam 'self' como primeiro + # Um atributo de classe. Ele é compartilhado por todas as instâncias dessa + # classe. + species = "H. sapiens" + + # Construtor básico, é chamado quando esta classe é instanciada. + # Note que dois sublinhados no início e no final de uma identificados + # significa objetos ou atributos que são usados pelo python mas vivem em + # um namespace controlado pelo usuário. Métodos (ou objetos ou atributos) + # como: __init__, __str__, __repr__, etc. são chamados métodos mágicos (ou + # algumas vezes chamados métodos dunder - "double underscore") + # Você não deve usar nomes assim por sua vontade. + def __init__(self, name): + @ Atribui o argumento ao atributo da instância + self.name = name + + # Um método de instância. Todos os métodos tem "self" como primeiro # argumento - def diga(self, msg): - return "%s: %s" % (self.nome, msg) + def say(self, msg): + return "{name}: {message}".format(name=self.name, message=msg) # Um método de classe é compartilhado por todas as instâncias - # Eles são chamados passando o nome da classe como primeiro argumento + # Eles são chamados com a classe requisitante como primeiro argumento @classmethod - def get_especie(cls): - return cls.especie + def get_species(cls): + return cls.species # Um método estático é chamado sem uma referência a classe ou instância @staticmethod - def ronca(): - return "*arrrrrrr*" + def grunt(): + return "*grunt*" # Instancie uma classe -i = Humano(nome="Ivone") -print i.diga("oi") # imprime "Ivone: oi" +i = Human(name="Ian") +print(i.say("oi")) # imprime "Ian: oi" j = Human("Joel") -print j.say("olá") #prints out "Joel: olá" +print(j.say("olá")) # imprime "Joel: olá" -# Chame nosso método de classe -i.get_especie() #=> "H. sapiens" +# Chama nosso método de classe +i.get_species() # => "H. sapiens" -# Modifique um atributo compartilhado -Humano.especie = "H. neanderthalensis" -i.get_especie() #=> "H. neanderthalensis" -j.get_especie() #=> "H. neanderthalensis" +# Altera um atributo compartilhado +Human.species = "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" -# Chame o método estático -Humano.ronca() #=> "*arrrrrrr*" +# Chama o método estático +Human.grunt() # => "*grunt*" #################################################### @@ -464,46 +647,100 @@ Humano.ronca() #=> "*arrrrrrr*" # Você pode importar módulos import math -print math.sqrt(16) #=> 4.0 +print(math.sqrt(16)) # => 4.0 -# Você pode importar funções específicas de um módulo +# Você pode importar apenas funções específicas de um módulo from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 -# Você também pode importar todas as funções de um módulo -# Atenção: isso não é recomendado! +# Você pode importar todas as funções de um módulo para o namespace atual +# Atenção: isso não é recomendado from math import * -# Você pode usar apelidos para os módulos, encurtando seus nomes +# Você pode encurtar o nome dos módulos import math as m -math.sqrt(16) == m.sqrt(16) #=> True +math.sqrt(16) == m.sqrt(16) # => True -# Módulos em Python são apenas arquivos Python. Você -# pode escrever o seu próprio módulo e importá-lo. O nome do -# módulo será o mesmo que o nome do arquivo. +# Módulos python são apenas arquivos python comuns. Você +# pode escrever os seus, e importá-los. O nome do +# módulo é o mesmo nome do arquivo. -# Você pode descobrir quais funções e atributos -# estão definidos em um módulo qualquer. +# Você pode procurar que atributos e funções definem um módulo. import math dir(math) +#################################################### +## 7. Avançado +#################################################### + +# Geradores podem ajudar você a escrever código "preguiçoso" +def double_numbers(iterable): + for i in iterable: + yield i + i + +# Um gerador cria valores conforme necessário. +# Ao invés de gerar e retornar todos os valores de uma só vez ele cria um em +# cada interação. Isto significa que valores maiores que 15 não serão +# processados em double_numbers. +# Nós usamos um sublinhado ao final do nome das variáveis quando queremos usar +# um nome que normalmente colide com uma palavra reservada do python. +range_ = range(1, 900000000) +# Multiplica por 2 todos os números até encontrar um resultado >= 30 +for i in double_numbers(range_): + print(i) + if i >= 30: + break + + +# Decoradores +# Neste exemplo beg encapsula say +# beg irá chamar say. Se say_please é verdade então ele irá mudar a mensagem +# retornada +from functools import wraps + + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Por favor! Eu sou pobre :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Você me paga uma cerveja?" + return msg, say_please + + +print(say()) # Você me paga uma cerveja? +print(say(say_please=True)) # Você me paga uma cerveja? Por favor! Eu sou pobre :( ``` ## Pronto para mais? -### Online e gratuito +### Free Online +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) -### Livros impressos +### Dead Tree * [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) * [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) * [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - diff --git a/pt-br/python3-pt.html.markdown b/pt-br/python3-pt.html.markdown deleted file mode 100644 index b72c732a..00000000 --- a/pt-br/python3-pt.html.markdown +++ /dev/null @@ -1,746 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] - - ["Steven Basart", "http://github.com/xksteven"] - - ["Andre Polykanine", "https://github.com/Oire"] - - ["Zachary Ferguson", "http://github.com/zfergus2"] -translators: - - ["Paulo Henrique Rodrigues Pinheiro", "http://www.sysincloud.it"] -lang: pt-br -filename: learnpython3-pt.py ---- - -Python foi criado por Guido Van Rossum nos anos 1990. Ele é atualmente uma -das mais populares linguagens em existência. Eu fiquei morrendo de amor -pelo Python por sua clareza sintática. É praticamente pseudocódigo executável. - -Suas opiniões são grandemente apreciadas. Você pode encontrar-me em -[@louiedinh](http://twitter.com/louiedinh) ou louiedinh [em] -[serviço de e-mail do google]. - -Observação: Este artigo trata de Python 3 especificamente. Verifique -[aqui](http://learnxinyminutes.com/docs/pt-br/python-pt/) se você pretende -aprender o velho Python 2.7. - -```python - -# Comentários em uma única linha começam com uma cerquilha (também conhecido por sustenido). - -""" Strings de várias linhas podem ser escritas - usando três ", e são comumente usadas - como comentários. -""" - -#################################################### -## 1. Tipos de dados primitivos e operadores -#################################################### - -# Você usa números normalmente -3 # => 3 - -# Matemática é como você espera que seja -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 - -# Números inteiros por padrão, exceto na divisão, que retorna número -# de ponto flutuante (float). -35 / 5 # => 7.0 - -# O resultado da divisão inteira arredonda para baixo tanto para números -# positivos como para negativos. -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # funciona em float também --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# Quando você usa um float, o resultado é float. -3 * 2.0 # => 6.0 - -# operador módulo -7 % 3 # => 1 - -# Exponenciação (x**y, x elevado à potência y) -2**4 # => 16 - -# Determine a precedência usando parêntesis -(1 + 3) * 2 # => 8 - -# Valores lógicos são primitivos (Atenção à primeira letra maiúscula) -True -False - -# negação lógica com not -not True # => False -not False # => True - -# Operadores lógicos -# Observe que "and" e "or" são sensíveis a maiúsculas e minúsculas -True and False # => False -False or True # => True - -# Observe a utilização de operadores lógicos com números inteiros -0 and 2 # => 0 --5 or 0 # => -5 -0 == False # => True -2 == True # => False -1 == True # => True - -# Igualdade é == -1 == 1 # => True -2 == 1 # => False - -# Diferença é != -1 != 1 # => False -2 != 1 # => True - -# Mais comparações -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# Comparações podem ser agrupadas -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# (operador 'is' e operador '==') is verifica se duas variáveis -# referenciam um mesmo objeto, mas == verifica se as variáveis -# apontam para o mesmo valor. -a = [1, 2, 3, 4] # Referência a uma nova lista, [1, 2, 3, 4] -b = a # b referencia o que está referenciado por a -b is a # => True, a e b referenciam o mesmo objeto -b == a # => True, objetos a e b tem o mesmo conteúdo -b = [1, 2, 3, 4] # Referência a uma nova lista, [1, 2, 3, 4] -b is a # => False, a e b não referenciam o mesmo objeto -b == a # => True, objetos a e b tem o mesmo conteúdo - -# Strings são criadas com " ou ' -"Isto é uma string." -'Isto também é uma string.' - -# Strings também podem ser somadas! Mas tente não fazer isso. -"Olá " + "mundo!" # => "Olá mundo!" -# Strings podem ser somadas sem usar o '+' -"Olá " "mundo!" # => "Olá mundo!" - -# Uma string pode ser manipulada como se fosse uma lista de caracteres -"Isso é uma string"[0] # => 'I' - -# .format pode ser usado para formatar strings, dessa forma: -"{} podem ser {}".format("Strings", "interpoladas") # => "Strings podem ser interpoladas" - -# Você pode repetir os argumentos para digitar menos. -"Seja ágil {0}, seja rápido {0}, salte sobre o {1} {0}".format("Jack", "castiçal") -# => "Seja ágil Jack, seja rápido Jack, salte sobre o castiçal Jack." - -# Você pode usar palavras-chave se quiser contar. -"{nome} quer comer {comida}".format(nome="Beto", comida="lasanha") # => "Beto quer comer lasanha" - -# Se você precisa executar seu código Python3 com um interpretador Python 2.5 ou acima, você pode usar a velha forma para formatação de texto: -"%s podem ser %s da forma %s" % ("Strings", "interpoladas", "antiga") # => "Strings podem ser interpoladas da forma antiga" - - -# None é um objeto -None # => None - -# Não use o operador de igualdade "==" para comparar objetos com None -# Use "is" para isso. Ele checará pela identidade dos objetos. -"etc" is None # => False -None is None # => True - -# None, 0, e strings/listas/dicionários vazios todos retornam False. -# Qualquer outra coisa retorna True -bool(0) # => False -bool("") # => False -bool([]) # => False -bool({}) # => False - - -#################################################### -## 2. Variáveis e coleções -#################################################### - -# Python tem uma função print -print("Eu sou o Python. Prazer em conhecer!") # => Eu sou o Python. Prazer em conhecer! - -# Por padrão a função print também imprime o caractere de nova linha ao final. -# Use o argumento opcional end para mudar o caractere final. -print("Olá, Mundo", end="!") # => Olá, Mundo! - -# Forma simples para capturar dados de entrada via console -input_string_var = input("Digite alguma coisa: ") # Retorna o que foi digitado em uma string -# Observação: Em versões antigas do Python, o método input() era chamado raw_input() - -# Não é necessário declarar variáveis antes de iniciá-las -# È uma convenção usar letras_minúsculas_com_sublinhados -alguma_variavel = 5 -alguma_variavel # => 5 - -# Acessar uma variável que não tenha sido inicializada gera uma exceção. -# Veja Controle de Fluxo para aprender mais sobre tratamento de exceções. -alguma_variavel_nao_inicializada # Gera a exceção NameError - -# Listas armazenam sequencias -li = [] -# Você pode iniciar com uma lista com alguns valores -outra_li = [4, 5, 6] - -# Adicionar conteúdo ao fim da lista com append -li.append(1) # li agora é [1] -li.append(2) # li agora é [1, 2] -li.append(4) # li agora é [1, 2, 4] -li.append(3) # li agora é [1, 2, 4, 3] -# Remover do final da lista com pop -li.pop() # => 3 e agora li é [1, 2, 4] -# Vamos colocá-lo lá novamente! -li.append(3) # li agora é [1, 2, 4, 3] novamente. - -# Acessar uma lista da mesma forma que você faz com um array -li[0] # => 1 -# Acessa o último elemento -li[-1] # => 3 - -# Acessando além dos limites gera um IndexError -li[4] # Gera o IndexError - -# Você pode acessar vários elementos com a sintaxe de limites -# (É um limite fechado, aberto pra você que gosta de matemática.) -li[1:3] # => [2, 4] -# Omitindo o final -li[2:] # => [4, 3] -# Omitindo o início -li[:3] # => [1, 2, 4] -# Selecione cada segunda entrada -li[::2] # => [1, 4] -# Tenha uma cópia em ordem invertida da lista -li[::-1] # => [3, 4, 2, 1] -# Use qualquer combinação dessas para indicar limites complexos -# li[inicio:fim:passo] - -# Faça uma cópia profunda de um nível usando limites -li2 = li[:] # => li2 = [1, 2, 4, 3] mas (li2 is li) resultará em False. - -# Apague elementos específicos da lista com "del" -del li[2] # li agora é [1, 2, 3] - -# Você pode somar listas -# Observação: valores em li e other_li não são modificados. -li + other_li # => [1, 2, 3, 4, 5, 6] - -# Concatene listas com "extend()" -li.extend(other_li) # Agora li é [1, 2, 3, 4, 5, 6] - -# Verifique se algo existe na lista com "in" -1 in li # => True - -# Examine tamanho com "len()" -len(li) # => 6 - - -# Tuplas são como l istas, mas imutáveis. -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # Gera um TypeError - -# Observe que uma tupla de tamanho um precisa ter uma vírgula depois do -# último elemento mas tuplas de outros tamanhos, mesmo vazias, não precisa,. -type((1)) # => <class 'int'> -type((1,)) # => <class 'tuple'> -type(()) # => <class 'tuple'> - -# Você pode realizar com tuplas a maior parte das operações que faz com listas -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True - -# Você pode desmembrar tuplas (ou listas) em variáveis. -a, b, c = (1, 2, 3) # a é 1, b é 2 e c é 3 -# Por padrão, tuplas são criadas se você não coloca parêntesis. -d, e, f = 4, 5, 6 -# Veja como é fácil permutar dois valores -e, d = d, e # d é 5, e é 4 - -# Dicionários armazenam mapeamentos -empty_dict = {} -# Aqui está um dicionário preenchido na definição da referência -filled_dict = {"um": 1, "dois": 2, "três": 3} - -# Observe que chaves para dicionários devem ser tipos imutáveis. Isto é para -# assegurar que a chave pode ser convertida para uma valor hash constante para -# buscas rápidas. -# Tipos imutáveis incluem inteiros, flotas, strings e tuplas. -invalid_dict = {[1,2,3]: "123"} # => Gera um TypeError: unhashable type: 'list' -valid_dict = {(1,2,3):[1,2,3]} # Já os valores, podem ser de qualquer tipo. - -# Acesse valores com [] -filled_dict["um"] # => 1 - -# Acesse todas as chaves como um iterável com "keys()". É necessário encapsular -# a chamada com um list() para transformá-las em uma lista. Falaremos sobre isso -# mais adiante. Observe que a ordem de uma chave de dicionário não é garantida. -# Por isso, os resultados aqui apresentados podem não ser exatamente como os -# aqui apresentados. -list(filled_dict.keys()) # => ["três", "dois", "um"] - - -# Acesse todos os valores de um iterável com "values()". Novamente, é -# necessário encapsular ele com list() para não termos um iterável, e sim os -# valores. Observe que, como foi dito acima, a ordem dos elementos não é -# garantida. -list(filled_dict.values()) # => [3, 2, 1] - - -# Verifique a existência de chaves em um dicionário com "in" -"um" in filled_dict # => True -1 in filled_dict # => False - -# Acessar uma chave inexistente gera um KeyError -filled_dict["quatro"] # KeyError - -# Use o método "get()" para evitar um KeyError -filled_dict.get("um") # => 1 -filled_dict.get("quatro") # => None -# O método get permite um parâmetro padrão para quando não existir a chave -filled_dict.get("um", 4) # => 1 -filled_dict.get("quatro", 4) # => 4 - -# "setdefault()" insere em dicionário apenas se a dada chave não existir -filled_dict.setdefault("cinco", 5) # filled_dict["cinco"] tem valor 5 -filled_dict.setdefault("cinco", 6) # filled_dict["cinco"] continua 5 - -# Inserindo em um dicionário -filled_dict.update({"quatro":4}) # => {"um": 1, "dois": 2, "três": 3, "quatro": 4} -#filled_dict["quatro"] = 4 #outra forma de inserir em um dicionário - -# Remova chaves de um dicionário com del -del filled_dict["um"] # Remove a chave "um" de filled_dict - - -# Armazenamento em sets... bem, são conjuntos -empty_set = set() -# Inicializa um set com alguns valores. Sim, ele parece um dicionário. Desculpe. -some_set = {1, 1, 2, 2, 3, 4} # some_set agora é {1, 2, 3, 4} - -# Da mesma forma que chaves em um dicionário, elementos de um set devem ser -# imutáveis. -invalid_set = {[1], 1} # => Gera um TypeError: unhashable type: 'list' -valid_set = {(1,), 1} - -# Pode definir novas variáveis para um conjunto -filled_set = some_set - -# Inclua mais um item no set -filled_set.add(5) # filled_set agora é {1, 2, 3, 4, 5} - -# Faça interseção de conjuntos com & -other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} - -# Faça união de conjuntos com | -filled_set | other_set # => {1, 2, 3, 4, 5, 6} - -# Faça a diferença entre conjuntos com - -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} - -# Verifique a existência em um conjunto com in -2 in filled_set # => True -10 in filled_set # => False - - - -#################################################### -## 3. Controle de fluxo e iteráveis -#################################################### - -# Iniciemos um variável -some_var = 5 - -# Aqui está uma expressão if. Indentação é significante em python! -# imprime "somevar é menor que10" -if some_var > 10: - print("some_var é absolutamente maior que 10.") -elif some_var < 10: # Esta cláusula elif é opcional. - print("some_var é menor que 10.") -else: # Isto também é opcional. - print("some_var é, de fato, 10.") - - -""" -Laços for iteram sobre listas -imprime: - cachorro é um mamífero - gato é um mamífero - rato é um mamífero -""" -for animal in ["cachorro", "gato", "rato"]: - # Você pode usar format() para interpolar strings formatadas - print("{} é um mamífero".format(animal)) - -""" -"range(número)" retorna um iterável de números -de zero até o número escolhido -imprime: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -"range(menor, maior)" gera um iterável de números -começando pelo menor até o maior -imprime: - 4 - 5 - 6 - 7 -""" -for i in range(4, 8): - print(i) - -""" -"range(menor, maior, passo)" retorna um iterável de números -começando pelo menor número até o maior númeno, pulando de -passo em passo. Se o passo não for indicado, o valor padrão é um. -imprime: - 4 - 6 -""" -for i in range(4, 8, 2): - print(i) -""" - -Laços while executam até que a condição não seja mais válida. -imprime: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Maneira mais curta para for x = x + 1 - -# Lide com exceções com um bloco try/except -try: - # Use "raise" para gerar um erro - raise IndexError("Isto é um erro de índice") -except IndexError as e: - pass # Pass é um não-operador. Normalmente você usa algum código de recuperação aqui. -except (TypeError, NameError): - pass # Varias exceções podem ser gerenciadas, se necessário. -else: # Cláusula opcional para o bloco try/except. Deve estar após todos os blocos de exceção. - print("Tudo certo!") # Executa apenas se o código em try não gera exceção -finally: # Sempre é executado - print("Nós podemos fazer o código de limpeza aqui.") - -# Ao invés de try/finally para limpeza você pode usar a cláusula with -with open("myfile.txt") as f: - for line in f: - print(line) - -# Python provê uma abstração fundamental chamada Iterável. -# Um iterável é um objeto que pode ser tratado como uma sequência. -# O objeto retornou a função range, um iterável. - -filled_dict = {"um": 1, "dois": 2, "três": 3} -our_iterable = filled_dict.keys() -print(our_iterable) # => range(1,10). Esse é um objeto que implementa nossa interface iterável. - -# Nós podemos percorrê-la. -for i in our_iterable: - print(i) # Imprime um, dois, três - -# Mas não podemos acessar os elementos pelo seu índice. -our_iterable[1] # Gera um TypeError - -# Um iterável é um objeto que sabe como criar um iterador. -our_iterator = iter(our_iterable) - -# Nosso iterador é um objeto que pode lembrar o estado enquanto nós o percorremos. -# Nós acessamos o próximo objeto com "next()". -next(our_iterator) # => "um" - -# Ele mantém o estado enquanto nós o percorremos. -next(our_iterator) # => "dois" -next(our_iterator) # => "três" - -# Após o iterador retornar todos os seus dados, ele gera a exceção StopIterator -next(our_iterator) # Gera StopIteration - -# Você pode capturar todos os elementos de um iterador aplicando list() nele. -list(filled_dict.keys()) # => Retorna ["um", "dois", "três"] - - -#################################################### -## 4. Funções -#################################################### - -# Use "def" para criar novas funções. -def add(x, y): - print("x é {} e y é {}".format(x, y)) - return x + y # Retorne valores com a cláusula return - -# Chamando funções com parâmetros -add(5, 6) # => imprime "x é 5 e y é 6" e retorna 11 - -# Outro meio de chamar funções é com argumentos nomeados -add(y=6, x=5) # Argumentos nomeados podem aparecer em qualquer ordem. - -# Você pode definir funções que pegam um número variável de argumentos -# posicionais -def varargs(*args): - return args - -varargs(1, 2, 3) # => (1, 2, 3) - -# Você pode definir funções que pegam um número variável de argumentos nomeados -# também -def keyword_args(**kwargs): - return kwargs - -# Vamos chamá-lo para ver o que acontece -keyword_args(peh="grande", lago="ness") # => {"peh": "grande", "lago": "ness"} - - -# Você pode fazer ambos simultaneamente, se você quiser -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) imprime: - (1, 2) - {"a": 3, "b": 4} -""" - -# Quando chamar funções, você pode fazer o oposto de args/kwargs! -# Use * para expandir tuplas e use ** para expandir dicionários! -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalente a foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivalente a foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivalente a foo(1, 2, 3, 4, a=3, b=4) - -# Retornando múltiplos valores (com atribuição de tuplas) -def swap(x, y): - return y, x # Retorna múltiplos valores como uma tupla sem os parêntesis. - # (Observação: os parêntesis foram excluídos mas podem estar - # presentes) - -x = 1 -y = 2 -x, y = swap(x, y) # => x = 2, y = 1 -# (x, y) = swap(x,y) # Novamente, os parêntesis foram excluídos mas podem estar presentes. - -# Escopo de função -x = 5 - -def setX(num): - # A variável local x não é a mesma variável global x - x = num # => 43 - print (x) # => 43 - -def setGlobalX(num): - global x - print (x) # => 5 - x = num # variável global x agora é 6 - print (x) # => 6 - -setX(43) -setGlobalX(6) - - -# Python tem funções de primeira classe -def create_adder(x): - def adder(y): - return x + y - return adder - -add_10 = create_adder(10) -add_10(3) # => 13 - -# Também existem as funções anônimas -(lambda x: x > 2)(3) # => True -(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 - -# TODO - Fix for iterables -# Existem funções internas de alta ordem -map(add_10, [1, 2, 3]) # => [11, 12, 13] -map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] - -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] - -# Nós podemos usar compreensão de lista para interessantes mapas e filtros -# Compreensão de lista armazena a saída como uma lista que pode ser uma lista -# aninhada -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] - -#################################################### -## 5. Classes -#################################################### - - -# Nós usamos o operador "class" para ter uma classe -class Human: - - # Um atributo de classe. Ele é compartilhado por todas as instâncias dessa - # classe. - species = "H. sapiens" - - # Construtor básico, é chamado quando esta classe é instanciada. - # Note que dois sublinhados no início e no final de uma identificados - # significa objetos ou atributos que são usados pelo python mas vivem em - # um namespace controlado pelo usuário. Métodos (ou objetos ou atributos) - # como: __init__, __str__, __repr__, etc. são chamados métodos mágicos (ou - # algumas vezes chamados métodos dunder - "double underscore") - # Você não deve usar nomes assim por sua vontade. - def __init__(self, name): - @ Atribui o argumento ao atributo da instância - self.name = name - - # Um método de instância. Todos os métodos tem "self" como primeiro - # argumento - def say(self, msg): - return "{name}: {message}".format(name=self.name, message=msg) - - # Um método de classe é compartilhado por todas as instâncias - # Eles são chamados com a classe requisitante como primeiro argumento - @classmethod - def get_species(cls): - return cls.species - - # Um método estático é chamado sem uma referência a classe ou instância - @staticmethod - def grunt(): - return "*grunt*" - - -# Instancie uma classe -i = Human(name="Ian") -print(i.say("oi")) # imprime "Ian: oi" - -j = Human("Joel") -print(j.say("olá")) # imprime "Joel: olá" - -# Chama nosso método de classe -i.get_species() # => "H. sapiens" - -# Altera um atributo compartilhado -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" - -# Chama o método estático -Human.grunt() # => "*grunt*" - - -#################################################### -## 6. Módulos -#################################################### - -# Você pode importar módulos -import math -print(math.sqrt(16)) # => 4.0 - -# Você pode importar apenas funções específicas de um módulo -from math import ceil, floor -print(ceil(3.7)) # => 4.0 -print(floor(3.7)) # => 3.0 - -# Você pode importar todas as funções de um módulo para o namespace atual -# Atenção: isso não é recomendado -from math import * - -# Você pode encurtar o nome dos módulos -import math as m -math.sqrt(16) == m.sqrt(16) # => True - -# Módulos python são apenas arquivos python comuns. Você -# pode escrever os seus, e importá-los. O nome do -# módulo é o mesmo nome do arquivo. - -# Você pode procurar que atributos e funções definem um módulo. -import math -dir(math) - - -#################################################### -## 7. Avançado -#################################################### - -# Geradores podem ajudar você a escrever código "preguiçoso" -def double_numbers(iterable): - for i in iterable: - yield i + i - -# Um gerador cria valores conforme necessário. -# Ao invés de gerar e retornar todos os valores de uma só vez ele cria um em -# cada interação. Isto significa que valores maiores que 15 não serão -# processados em double_numbers. -# Nós usamos um sublinhado ao final do nome das variáveis quando queremos usar -# um nome que normalmente colide com uma palavra reservada do python. -range_ = range(1, 900000000) -# Multiplica por 2 todos os números até encontrar um resultado >= 30 -for i in double_numbers(range_): - print(i) - if i >= 30: - break - - -# Decoradores -# Neste exemplo beg encapsula say -# beg irá chamar say. Se say_please é verdade então ele irá mudar a mensagem -# retornada -from functools import wraps - - -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Por favor! Eu sou pobre :(") - return msg - - return wrapper - - -@beg -def say(say_please=False): - msg = "Você me paga uma cerveja?" - return msg, say_please - - -print(say()) # Você me paga uma cerveja? -print(say(say_please=True)) # Você me paga uma cerveja? Por favor! Eu sou pobre :( -``` - -## Pronto para mais? - -### Free Online - -* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) -* [Python Course](http://www.python-course.eu/index.php) -* [First Steps With Python](https://realpython.com/learn/python-first-steps/) -* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) -* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) -* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) - -### Dead Tree - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) diff --git a/pt-br/pythonlegacy-pt.html.markdown b/pt-br/pythonlegacy-pt.html.markdown new file mode 100644 index 00000000..572bb787 --- /dev/null +++ b/pt-br/pythonlegacy-pt.html.markdown @@ -0,0 +1,509 @@ +--- +language: Python 2 (legacy) +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Vilson Vieira", "http://automata.cc"] +lang: pt-br +filename: learnpythonlegacy-pt.py +--- + +Python foi criado por Guido Van Rossum no começo dos anos 90. Atualmente é uma +das linguagens de programação mais populares. Eu me apaixonei por Python, por +sua clareza de sintaxe. É basicamente pseudocódigo executável. + +Comentários serão muito apreciados! Você pode me contactar em +[@louiedinh](http://twitter.com/louiedinh) ou louiedinh [arroba] +[serviço de email do google] + +Nota: Este artigo usa Python 2.7 especificamente, mas deveria ser aplicável a +qualquer Python 2.x. Logo haverá uma versão abordando Python 3! + +```python +# Comentários de uma linha começam com cerquilha (ou sustenido) +""" Strings de várias linhas podem ser escritas + usando três ", e são comumente usadas + como comentários +""" + +#################################################### +## 1. Tipos de dados primitivos e operadores +#################################################### + +# Você usa números normalmente +3 #=> 3 + +# Operadores matemáticos são aqueles que você já está acostumado +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# A divisão é um pouco estranha. A divisão de números inteiros arredonda +# para baixo o resultado, automaticamente +5 / 2 #=> 2 + +# Para concertar a divisão, precisamos aprender sobre números de ponto +# flutuante (conhecidos como 'float'). +2.0 # Isso é um 'float' +11.0 / 4.0 #=> 2.75 ahhh... muito melhor + +# Forçamos a precedência de operadores usando parênteses +(1 + 3) * 2 #=> 8 + +# Valores booleanos (ou 'boolean') são também tipos primitivos +True +False + +# Negamos usando 'not' +not True #=> False +not False #=> True + +# Testamos igualdade usando '==' +1 == 1 #=> True +2 == 1 #=> False + +# E desigualdade com '!=' +1 != 1 #=> False +2 != 1 #=> True + +# Mais comparações +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# As comparações podem ser encadeadas! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Strings são criadas com " ou ' +"Isso é uma string." +'Isso também é uma string.' + +# Strings podem ser somadas (ou melhor, concatenadas)! +"Olá " + "mundo!" #=> "Olá mundo!" + +# Uma string pode ser tratada como uma lista de caracteres +"Esta é uma string"[0] #=> 'E' + +# O caractere % pode ser usado para formatar strings, desta forma: +"%s podem ser %s" % ("strings", "interpoladas") + +# Um jeito novo de formatar strings é usando o método 'format'. +# Esse método é o jeito mais usado +"{0} podem ser {1}".format("strings", "formatadas") +# Você pode usar palavras-chave (ou 'keywords') se você não quiser contar. +"{nome} quer comer {comida}".format(nome="João", comida="lasanha") + +# 'None' é um objeto +None #=> None + +# Não use o operador de igualdade `==` para comparar objetos com 'None' +# Ao invés disso, use `is` +"etc" is None #=> False +None is None #=> True + +# O operador 'is' teste a identidade de um objeto. Isso não é +# muito útil quando estamos lidando com valores primitivos, mas é +# muito útil quando lidamos com objetos. + +# None, 0, e strings/listas vazias são todas interpretadas como 'False'. +# Todos os outros valores são 'True' +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. Variáveis e Coleções +#################################################### + +# Imprimir na tela é muito fácil +print "Eu sou o Python. Prazer em te conhecer!" + + +# Nós não precisamos declarar variáveis antes de usá-las, basta usar! +alguma_variavel = 5 # A convenção é usar caixa_baixa_com_sobrescritos +alguma_variavel #=> 5 + +# Acessar uma variável que não teve nenhum valor atribuído anteriormente é +# uma exceção. +# Veja a seção 'Controle' para aprender mais sobre tratamento de exceção. +outra_variavel # Gera uma exceção de erro de nome + +# 'if' pode ser usado como uma expressão +"uepa!" if 3 > 2 else 2 #=> "uepa!" + +# Listas armazenam sequências de elementos +lista = [] +# Você pode inicializar uma lista com valores +outra_lista = [4, 5, 6] + +# Adicione elementos no final da lista usando 'append' +lista.append(1) # lista é agora [1] +lista.append(2) # lista é agora [1, 2] +lista.append(4) # lista é agora [1, 2, 4] +lista.append(3) # lista é agora [1, 2, 4, 3] +# Remova elementos do fim da lista usando 'pop' +lista.pop() #=> 3 e lista é agora [1, 2, 4] +# Vamos adicionar o elemento novamente +lista.append(3) # lista agora é [1, 2, 4, 3] novamente. + +# Acesse elementos de uma lista através de seu índices +lista[0] #=> 1 +# Acesse o último elemento com índice negativo! +lista[-1] #=> 3 + +# Tentar acessar um elemento fora dos limites da lista gera uma exceção +# do tipo 'IndexError' +lista[4] # Gera uma exceção 'IndexError' + +# Você pode acessar vários elementos ao mesmo tempo usando a sintaxe de +# limites +# (Para quem gosta de matemática, isso é um limite fechado/aberto) +lista[1:3] #=> [2, 4] +# Você pode omitir o fim se quiser os elementos até o final da lista +lista[2:] #=> [4, 3] +# O mesmo para o início +lista[:3] #=> [1, 2, 4] + +# Remova um elemento qualquer de uma lista usando 'del' +del lista[2] # lista agora é [1, 2, 3] + +# Você pode somar listas (obs: as listas originais não são modificadas) +lista + outra_lista #=> [1, 2, 3, 4, 5, 6] + +# Você também pode concatenar usando o método 'extend' (lista será modificada!) +lista.extend(outra_lista) # Agora lista é [1, 2, 3, 4, 5, 6] + +# Para checar se um elemento pertence a uma lista, use 'in' +1 in lista #=> True + +# Saiba quantos elementos uma lista possui com 'len' +len(lista) #=> 6 + + +# Tuplas são iguais a listas, mas são imutáveis +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # Isso gera uma exceção do tipo TypeError + +# Você pode fazer nas tuplas todas aquelas coisas fez com a lista +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# Você pode 'desempacotar' tuplas (ou listas) em variáveis, associando cada +# elemento da tupla/lista a uma variável correspondente +a, b, c = (1, 2, 3) # a agora é 1, b agora é 2, c agora é 3 +# Tuplas são criadas por padrão, mesmo se você não usar parênteses +d, e, f = 4, 5, 6 +# Sabendo disso, veja só como é fácil trocar os valores de duas variáveis! +e, d = d, e # d agora é 5, e agora é 4 + + +# Dicionários armazenam 'mapeamentos' (do tipo chave-valor) +dicionario_vazio = {} +# Aqui criamos um dicionário já contendo valores +dicionario = {"um": 1, "dois": 2, "três": 3} + +# Acesse valores usando [] +dicionario["um"] #=> 1 + +# Retorna uma lista com todas as chaves do dicionário +dicionario.keys() #=> ["três", "dois", "um"] +# Nota: A ordem das chaves não é garantida. +# O resultado no seu interpretador não necessariamente será igual a esse. + +# Retorna uma lista com todos os valores do dicionário +dicionario.values() #=> [3, 2, 1] +# Nota: A mesma nota acima sobre a ordenação é válida aqui. + +# Veja se uma chave qualquer está em um dicionário usando 'in' +"um" in dicionario #=> True +1 in dicionario #=> False + +# Tentar acessar uma chave que não existe gera uma exceção do tipo 'KeyError' +dicionario["quatro"] # Gera uma exceção KeyError + +# Você pode usar o método 'get' para evitar gerar a exceção 'KeyError'. +# Ao invés de gerar essa exceção, irá retornar 'None' se a chave não existir. +dicionario.get("um") #=> 1 +dicionario.get("quatro") #=> None +# O método 'get' suporta um argumento que diz qual valor deverá ser +# retornado se a chave não existir (ao invés de 'None'). +dicionario.get("um", 4) #=> 1 +dicionario.get("quatro", 4) #=> 4 + +# O método 'setdefault' é um jeito seguro de adicionar um novo par +# chave-valor a um dicionário, associando um valor padrão imutável à uma chave +dicionario.setdefault("cinco", 5) # dicionario["cinco"] é definido como 5 +dicionario.setdefault("cinco", 6) # dicionario["cinco"] ainda é igual a 5 + + +# Conjuntos (ou sets) armazenam ... bem, conjuntos +# Nota: lembre-se que conjuntos não admitem elementos repetidos! +conjunto_vazio = set() +# Podemos inicializar um conjunto com valores +conjunto = set([1, 2, 2, 3, 4]) # conjunto é set([1, 2, 3, 4]), sem repetição! + +# Desde o Python 2.7, {} pode ser usado para declarar um conjunto +conjunto = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Adicione mais ítens a um conjunto com 'add' +conjunto.add(5) # conjunto agora é {1, 2, 3, 4, 5} + +# Calcule a intersecção de dois conjuntos com & +outro_conj = {3, 4, 5, 6} +conjunto & outro_conj #=> {3, 4, 5} + +# Calcule a união de dois conjuntos com | +conjunto | outro_conj #=> {1, 2, 3, 4, 5, 6} + +# E a diferença entre dois conjuntos com - +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# Veja se um elemento existe em um conjunto usando 'in' +2 in conjunto #=> True +10 in conjunto #=> False + + +#################################################### +## 3. Controle +#################################################### + +# Para começar, vamos apenas criar uma variável +alguma_var = 5 + +# Aqui está uma expressão 'if'. Veja como a identação é importante em Python! +# Esses comandos irão imprimir "alguma_var é menor que 10" +if alguma_var > 10: + print "some_var é maior que 10." +elif some_var < 10: # Esse 'elif' é opcional + print "some_var é menor que 10." +else: # Esse 'else' também é opcional + print "some_var é igual a 10." + + +""" +Laços (ou loops) 'for' iteram em listas. +Irá imprimir: + cachorro é um mamífero + gato é um mamífero + rato é um mamífero +""" +for animal in ["cachorro", "gato", "rato"]: + # Você pode usar % para interpolar strings formatadas + print "%s é um mamífero" % animal + +""" +A função `range(um número)` retorna uma lista de números +do zero até o número dado. +Irá imprimir: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +Laços 'while' executam enquanto uma condição dada for verdadeira. +Irá imprimir: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Isso é um atalho para a expressão x = x + 1 + +# Tratamos excessões usando o bloco try/except +# Funciona em Python 2.6 e versões superiores: + +try: + # Use 'raise' para gerar um erro + raise IndexError("Isso é um erro de índice") +except IndexError as e: + pass # Pass é um operador que não faz nada, deixa passar. + # Usualmente você iria tratar a exceção aqui... + + +#################################################### +## 4. Funções +#################################################### + +# Use 'def' para definir novas funções +def soma(x, y): + print "x é %s e y é %s" % (x, y) + return x + y # Retorne valores usando 'return' + +# Chamando funções com parâmetros +soma(5, 6) #=> imprime "x é 5 e y é 6" e retorna o valor 11 + +# Um outro jeito de chamar funções é especificando explicitamente os valores +# de cada parâmetro com chaves +soma(y=6, x=5) # Argumentos com chaves podem vir em qualquer ordem. + +# Você pode definir funções que recebem um número qualquer de argumentos +# (respeitando a sua ordem) +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# Você também pode definir funções que recebem um número qualquer de argumentos +# com chaves +def args_com_chaves(**ch_args): + return ch_args + +# Vamos chamar essa função para ver o que acontece +args_com_chaves(pe="grande", lago="Ness") #=> {"pe": "grande", "lago": "Ness"} + +# Você pode fazer as duas coisas ao mesmo tempo, se desejar +def todos_args(*args, **ch_wargs): + print args + print ch_args +""" +todos_args(1, 2, a=3, b=4) imprime: + (1, 2) + {"a": 3, "b": 4} +""" + +# Quando você chamar funções, pode fazer o oposto do que fizemos até agora! +# Podemos usar * para expandir tuplas de argumentos e ** para expandir +# dicionários de argumentos com chave. +args = (1, 2, 3, 4) +ch_args = {"a": 3, "b": 4} +todos_args(*args) # equivalente a todos_args(1, 2, 3, 4) +todos_args(**ch_args) # equivalente a todos_args(a=3, b=4) +todos_args(*args, **ch_args) # equivalente a todos_args(1, 2, 3, 4, a=3, b=4) + +# Em Python, funções são elementos de primeira ordem (são como objetos, +# strings ou números) +def cria_somador(x): + def somador(y): + return x + y + return somador + +soma_10 = cria_somador(10) +soma_10(3) #=> 13 + +# Desta forma, existem também funções anônimas +(lambda x: x > 2)(3) #=> True + +# E existem funções de alta ordem por padrão +map(soma_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +reduce(lambda x, y: x + y, [3, 4, 5, 6, 7]) #=> 25 + +# Nós podemos usar compreensão de listas para mapear e filtrar também +[soma_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. Classes +#################################################### + +# Para criar uma nova classe, devemos herdar de 'object' +class Humano(object): + + # Um atributo de classe. Ele é compartilhado por todas as instâncias dessa + # classe + especie = "H. sapiens" + + # Definimos um inicializador básico + def __init__(self, nome): + # Atribui o valor de argumento dado a um atributo da instância + self.nome = nome + + # Um método de instância. Todos os métodos levam 'self' como primeiro + # argumento + def diga(self, msg): + return "%s: %s" % (self.nome, msg) + + # Um método de classe é compartilhado por todas as instâncias + # Eles são chamados passando o nome da classe como primeiro argumento + @classmethod + def get_especie(cls): + return cls.especie + + # Um método estático é chamado sem uma referência a classe ou instância + @staticmethod + def ronca(): + return "*arrrrrrr*" + + +# Instancie uma classe +i = Humano(nome="Ivone") +print i.diga("oi") # imprime "Ivone: oi" + +j = Human("Joel") +print j.say("olá") #prints out "Joel: olá" + +# Chame nosso método de classe +i.get_especie() #=> "H. sapiens" + +# Modifique um atributo compartilhado +Humano.especie = "H. neanderthalensis" +i.get_especie() #=> "H. neanderthalensis" +j.get_especie() #=> "H. neanderthalensis" + +# Chame o método estático +Humano.ronca() #=> "*arrrrrrr*" + + +#################################################### +## 6. Módulos +#################################################### + +# Você pode importar módulos +import math +print math.sqrt(16) #=> 4.0 + +# Você pode importar funções específicas de um módulo +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Você também pode importar todas as funções de um módulo +# Atenção: isso não é recomendado! +from math import * + +# Você pode usar apelidos para os módulos, encurtando seus nomes +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Módulos em Python são apenas arquivos Python. Você +# pode escrever o seu próprio módulo e importá-lo. O nome do +# módulo será o mesmo que o nome do arquivo. + +# Você pode descobrir quais funções e atributos +# estão definidos em um módulo qualquer. +import math +dir(math) + + +``` + +## Pronto para mais? + +### Online e gratuito + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### Livros impressos + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/pt-br/pythonstatcomp-pt.html.markdown b/pt-br/pythonstatcomp-pt.html.markdown new file mode 100644 index 00000000..aa532eb4 --- /dev/null +++ b/pt-br/pythonstatcomp-pt.html.markdown @@ -0,0 +1,249 @@ +--- +category: tool +tool: Statistical Computing with Python +contributors: + - ["e99n09", "https://github.com/e99n09"] +translators: + - ["waltercjunior", "https://github.com/waltercjunior"] +filename: pythonstatcomp-pt.py +lang: pt-br +--- + +Este é um tutorial sobre como fazer algumas tarefas típicas de programação estatística usando Python. +É destinado basicamente à pessoas familizarizadas com Python e experientes com programação estatística em linguagens como R, +Stata, SAS, SPSS ou MATLAB. + +```python + + + +# 0. Preparando-se ==== + +""" Para começar, instale o seguinte : jupyther, numpy, scipy, pandas, + matplotlib, seaborn, requests. + Certifique-se de executar este tutorial utilizando o Jupyther notebook para + que você utilize os gráficos embarcados e ter uma fácil consulta à + documentação. + O comando para abrir é simplesmente '`jupyter notebook`, quando abrir então + clique em 'New -> Python'. +""" + +# 1. Aquisição de dados ==== + +""" A única razão das pessoas optarem por Python no lugar de R é que pretendem + interagir com o ambiente web, copiando páginas diretamente ou solicitando + dados utilizando uma API. Você pode fazer estas coisas em R, mas no + contexto de um projeto já usando Python, há uma vantagem em se ater uma + linguágem única. +""" + +import requests # para requisições HTTP (web scraping, APIs) +import os + +# web scraping +r = requests.get("https://github.com/adambard/learnxinyminutes-docs") +r.status_code # se retornou código 200, a requisição foi bem sucedida +r.text # código fonte bruto da página +print(r.text) # formatado bonitinho +# salve a o código fonte d apágina em um arquivo: +os.getcwd() # verifique qual é o diretório de trabalho +with open("learnxinyminutes.html", "wb") as f: + f.write(r.text.encode("UTF-8")) + +# Baixar um arquivo csv +fp = "https://raw.githubusercontent.com/adambard/learnxinyminutes-docs/master/" +fn = "pets.csv" +r = requests.get(fp + fn) +print(r.text) +with open(fn, "wb") as f: + f.write(r.text.encode("UTF-8")) + +""" para mais informações sobre o módulo de solicitações, incluindo API's, veja em + http://docs.python-requests.org/en/latest/user/quickstart/ +""" + +# 2. Lendo um arquivo formato CSV ==== + +""" Um pacote de pandas da Wes McKinney lhe dá um objeto 'DataFrame' em Python. + Se você já usou R, já deve estar familiarizado com a ideia de "data.frame". +""" + +import pandas as pd +import numpy as np +import scipy as sp +pets = pd.read_csv(fn) +pets +# name age weight species +# 0 fluffy 3 14 cat +# 1 vesuvius 6 23 fish +# 2 rex 5 34 dog + +""" Usuários R: observe que o Python, como a maioria das linguagens de programação + influenciada pelo C, a indexação começa de 0. Em R, começa a indexar em 1 + devido à influência do Fortran. +""" + +# duas maneiras diferentes de imprimir uma coluna +pets.age +pets["age"] + +pets.head(2) # imprima as 2 primeiras linhas +pets.tail(1) # imprima a última linha + +pets.name[1] # 'vesuvius' +pets.species[0] # 'cat' +pets["weight"][2] # 34 + +# Em R, você esperaria obter 3 linhas fazendo isso, mas aqui você obtem 2: +pets.age[0:2] +# 0 3 +# 1 6 + +sum(pets.age) * 2 # 28 +max(pets.weight) - min(pets.weight) # 20 + +""" Se você está fazendo alguma álgebra linear séria e processamento de + números você pode desejar apenas arrays, não DataFrames. DataFrames são + ideais para combinar colunas de diferentes tipos de dados. +""" + +# 3. Gráficos ==== + +import matplotlib as mpl +import matplotlib.pyplot as plt +%matplotlib inline + +# Para fazer a visualiação de dados em Python, use matplotlib + +plt.hist(pets.age); + +plt.boxplot(pets.weight); + +plt.scatter(pets.age, pets.weight) +plt.xlabel("age") +plt.ylabel("weight"); + +# seaborn utiliza a biblioteca do matplotlib e torna os enredos mais bonitos + +import seaborn as sns + +plt.scatter(pets.age, pets.weight) +plt.xlabel("age") +plt.ylabel("weight"); + +# também existem algumas funções de plotagem específicas do seaborn +# observe como o seaborn automaticamenteo o eixto x neste gráfico de barras +sns.barplot(pets["age"]) + +# Veteranos em R ainda podem usar o ggplot +from ggplot import * +ggplot(aes(x="age",y="weight"), data=pets) + geom_point() + labs(title="pets") +# fonte: https://pypi.python.org/pypi/ggplot + +# há até um d3.js veja em: https://github.com/mikedewar/d3py + +# 4. Limpeza de dados simples e análise exploratória ==== + +""" Aqui está um exemplo mais complicado que demonstra dados básicos + fluxo de trabalho de limpeza levando à criação de algumas parcelas + e a execução de uma regressão linear. + O conjunto de dados foi transcrito da Wikipedia à mão. Contém + todos os sagrados imperadores romanos e os marcos importantes em suas vidas + (birth, death, coronation, etc.). + O objetivo da análise será explorar se um relacionamento existe + entre o ano de nascimento (birth year) e a expectativa de vida (lifespam) + do imperador. + Fonte de dados: https://en.wikipedia.org/wiki/Holy_Roman_Emperor +""" + +# carregue alguns dados dos sagrados imperadores romanos +url = "https://raw.githubusercontent.com/adambard/learnxinyminutes-docs/master/hre.csv" +r = requests.get(url) +fp = "hre.csv" +with open(fp, "wb") as f: + f.write(r.text.encode("UTF-8")) + +hre = pd.read_csv(fp) + +hre.head() +""" + Ix Dynasty Name Birth Death +0 NaN Carolingian Charles I 2 April 742 28 January 814 +1 NaN Carolingian Louis I 778 20 June 840 +2 NaN Carolingian Lothair I 795 29 September 855 +3 NaN Carolingian Louis II 825 12 August 875 +4 NaN Carolingian Charles II 13 June 823 6 October 877 + + Coronation 1 Coronation 2 Ceased to be Emperor +0 25 December 800 NaN 28 January 814 +1 11 September 813 5 October 816 20 June 840 +2 5 April 823 NaN 29 September 855 +3 Easter 850 18 May 872 12 August 875 +4 29 December 875 NaN 6 October 877 +""" + +# limpar as colunas Birth e Death + +import re # módulo para expressões regulares + +rx = re.compile(r'\d+$') # conincidir com os códigos finais + +""" Esta função aplia a expressão reguar a uma coluna de entrada (here Birth, + Death), nivela a lista resultante, converte-a em uma lista de objetos, e + finalmente converte o tipo do objeto da lista de String para inteiro. para + mais informações sobre o que as diferentes partes do código fazer, veja em: + - https://docs.python.org/2/howto/regex.html + - http://stackoverflow.com/questions/11860476/how-to-unlist-a-python-list + - http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html +""" + +from functools import reduce + +def extractYear(v): + return(pd.Series(reduce(lambda x, y: x + y, map(rx.findall, v), [])).astype(int)) + +hre["BirthY"] = extractYear(hre.Birth) +hre["DeathY"] = extractYear(hre.Death) + +# faça uma coluna infomrnado a idade estimada ("EstAge") +hre["EstAge"] = hre.DeathY.astype(int) - hre.BirthY.astype(int) + +# gráfico de dispersão simples, sem linha de tendência, cor representa dinastia +sns.lmplot("BirthY", "EstAge", data=hre, hue="Dynasty", fit_reg=False) + +# use o scipy para executar uma regrassão linear +from scipy import stats +(slope, intercept, rval, pval, stderr) = stats.linregress(hre.BirthY, hre.EstAge) +# código fonte: http://wiki.scipy.org/Cookbook/LinearRegression + +# varifique o declive (slope) +slope # 0.0057672618839073328 + +# varifique o valor R^2: +rval**2 # 0.020363950027333586 + +# varifique o valor p-value +pval # 0.34971812581498452 + +# use o seaborn para fazer um gráfico de dispersão e traçar a linha de tendência de regrassão linear +sns.lmplot("BirthY", "EstAge", data=hre) + +""" Para mais informações sobre o seaborn, veja + - http://web.stanford.edu/~mwaskom/software/seaborn/ + - https://github.com/mwaskom/seaborn + Para mais informações sobre o SciPy, veja + - http://wiki.scipy.org/SciPy + - http://wiki.scipy.org/Cookbook/ + Para ver uma versão da análise dos sagrados imperadores romanos usando R, consulte + - http://github.com/e99n09/R-notes/blob/master/holy_roman_emperors_dates.R +""" + +``` + +Se você quiser saber mais, obtenha o Python para análise de dados de Wes McKinney. É um excelente recurso e usei-o como referência ao escrever este tutorial. + +Você também pode encontrar muitos tutoriais interativos de IPython sobre assuntos específicos de seus interesses, como Cam Davidson-Pilon's <a href="http://camdavidsonpilon.github.io/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers/" Title="Programação Probabilística e Métodos Bayesianos para Hackers">Programação Probabilística e Métodos Bayesianos para Hackers</a>. + +Mais alguns módulos para pesquisar: + - análise de texto e processamento de linguagem natural: nltk, http://www.nltk.org + - análise de rede social: igraph, http://igraph.org/python/ diff --git a/pt-br/qt-pt.html.markdown b/pt-br/qt-pt.html.markdown index 99579c35..f4211e09 100644 --- a/pt-br/qt-pt.html.markdown +++ b/pt-br/qt-pt.html.markdown @@ -1,7 +1,7 @@ --- category: tool tool: Qt Framework -language: c++ +language: C++ filename: learnqt-pt.cpp contributors: - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"] diff --git a/pt-br/r-pt.html.markdown b/pt-br/r-pt.html.markdown new file mode 100644 index 00000000..5c9304ec --- /dev/null +++ b/pt-br/r-pt.html.markdown @@ -0,0 +1,786 @@ +--- +language: R +contributors: + - ["e99n09", "http://github.com/e99n09"] + - ["isomorphismes", "http://twitter.com/isomorphisms"] + - ["kalinn", "http://github.com/kalinn"] +translators: + - ["Marcel Ribeiro-Dantas", "http://github.com/mribeirodantas"] +lang: pt-br +filename: learnr-pt.r +--- + +R é uma linguagem de programação estatística. Ela tem muitas bibliotecas para carregar e limpar conjuntos de dados, executar análises estatísticas e produzir gráficos. Você também pode executar comandos do `R` dentro de um documento LaTeX. + +```r + +# Comentários começam com o símbolo de Cerquilha, também conhecido como +# jogo da velha + +# Não existe um símbolo especial para comentários em várias linhas +# mas você pode escrever várias linhas de comentários adicionando a +# cerquilha (#) ao início de cada uma delas. + +# No Windows e Linux, você pode usar CTRL-ENTER para executar uma linha. +# No MacOS, o equivalente é COMMAND-ENTER + + + +############################################################################# +# Coisas que você pode fazer sem entender nada sobre programação +############################################################################# + +# Nesta seção, mostramos algumas das coisas legais que você pode fazer em +# R sem entender nada de programação. Não se preocupe em entender tudo o +# que o código faz. Apenas aproveite! + +data() # navegue pelos conjuntos de dados pré-carregados +data(rivers) # carregue este: "Comprimentos dos principais rios norte-americanos" +ls() # observe que "rivers" apareceu na área de trabalho (workspace) +head(rivers) # dê uma espiada no conjunto de dados +# 735 320 325 392 524 450 + +length(rivers) # quantos rios foram medidos? +# 141 +summary(rivers) # consulte um sumário de estatísticas básicas +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 135.0 310.0 425.0 591.2 680.0 3710.0 + +# faça um diagrama de ramos e folhas (uma visualização de dados semelhante a um histograma) +stem(rivers) + +# A vírgula está 2 dígito(s) à direita do símbolo | +# +# 0 | 4 +# 2 | 011223334555566667778888899900001111223333344455555666688888999 +# 4 | 111222333445566779001233344567 +# 6 | 000112233578012234468 +# 8 | 045790018 +# 10 | 04507 +# 12 | 1471 +# 14 | 56 +# 16 | 7 +# 18 | 9 +# 20 | +# 22 | 25 +# 24 | 3 +# 26 | +# 28 | +# 30 | +# 32 | +# 34 | +# 36 | 1 + +stem(log(rivers)) # Observe que os dados não são normais nem log-normais! +# Tome isso, fundamentalistas da curva normal! + +# O ponto decimal está 1 dígito(s) à esquerda do símbolo | +# +# 48 | 1 +# 50 | +# 52 | 15578 +# 54 | 44571222466689 +# 56 | 023334677000124455789 +# 58 | 00122366666999933445777 +# 60 | 122445567800133459 +# 62 | 112666799035 +# 64 | 00011334581257889 +# 66 | 003683579 +# 68 | 0019156 +# 70 | 079357 +# 72 | 89 +# 74 | 84 +# 76 | 56 +# 78 | 4 +# 80 | +# 82 | 2 + +# faça um histograma: +hist(rivers, col="#333333", border="white", breaks=25) # brinque com estes parâmetros +hist(log(rivers), col="#333333", border="white", breaks=25) # você fará mais gráficos mais tarde + +# Aqui está outro conjunto de dados que vem pré-carregado. O R tem toneladas deles. +data(discoveries) +plot(discoveries, col="#333333", lwd=3, xlab="Ano", + main="Número de descobertas importantes por ano") +plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Ano", + main="Número de descobertas importantes por ano") + +# Em vez de deixar a ordenação padrão (por ano), +# também podemos ordenar para ver o que é mais comum: +sort(discoveries) +# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 +# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 +# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 +# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 + +stem(discoveries, scale=2) +# +# O ponto decimal está no símbolo | +# +# 0 | 000000000 +# 1 | 000000000000 +# 2 | 00000000000000000000000000 +# 3 | 00000000000000000000 +# 4 | 000000000000 +# 5 | 0000000 +# 6 | 000000 +# 7 | 0000 +# 8 | 0 +# 9 | 0 +# 10 | 0 +# 11 | +# 12 | 0 + +max(discoveries) +# 12 +summary(discoveries) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 0.0 2.0 3.0 3.1 4.0 12.0 + +# Role um dado algumas vezes +round(runif(7, min=.5, max=6.5)) +# 1 4 6 1 4 6 4 +# Seus números serão diferentes dos meus, a menos que definamos a mesma semente aleatória com o set.seed + +# Obtenha 9 números de forma aleatória a partir de uma distribuição normal +rnorm(9) +# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271 +# [7] -0.59975593 0.57629164 1.08455362 + + + +################################################## +# Tipos de dados e aritmética básica +################################################## + +# Agora para a parte orientada a programação do tutorial. +# Nesta seção você conhecerá os tipos de dados importantes do R: +# integers, numerics, characters, logicals, e factors. +# Existem outros, mas estes são o mínimo que você precisa para +# iniciar. + +# INTEGERS +# Os inteiros de armazenamento longo são escritos com L +5L # 5 +class(5L) # "integer" +# (Experimente ?class para obter mais informações sobre a função class().) +# Em R, todo e qualquer valor, como 5L, é considerado um vetor de comprimento 1 +length(5L) # 1 +# Você pode ter um vetor inteiro com comprimento > 1 também: +c(4L, 5L, 8L, 3L) # 4 5 8 3 +length(c(4L, 5L, 8L, 3L)) # 4 +class(c(4L, 5L, 8L, 3L)) # "integer" + +# NUMERICS +# Um "numeric" é um número de ponto flutuante de precisão dupla +5 # 5 +class(5) # "numeric" +# De novo, tudo em R é um vetor; +# você pode fazer um vetor numérico com mais de um elemento +c(3,3,3,2,2,1) # 3 3 3 2 2 1 +# Você também pode usar a notação científica +5e4 # 50000 +6.02e23 # Número de Avogadro +1.6e-35 # Comprimento de Planck +# Você também pode ter números infinitamente grandes ou pequenos +class(Inf) # "numeric" +class(-Inf) # "numeric" +# Você pode usar "Inf", por exemplo, em integrate(dnorm, 3, Inf) +# isso evita as tabelas de escores-Z. + +# ARITMÉTICA BÁSICA +# Você pode fazer aritmética com números +# Fazer aritmética com uma mistura de números inteiros (integers) e com +# ponto flutuante (numeric) resulta em um numeric +10L + 66L # 76 # integer mais integer resulta em integer +53.2 - 4 # 49.2 # numeric menos numeric resulta em numeric +2.0 * 2L # 4 # numeric vezes integer resulta em numeric +3L / 4 # 0.75 # integer dividido por numeric resulta em numeric +3 %% 2 # 1 # o resto de dois numeric é um outro numeric +# Aritmética ilegal produz um "não-é-um-número" (do inglês Not-a-Number): +0 / 0 # NaN +class(NaN) # "numeric" +# Você pode fazer aritmética em dois vetores com comprimento maior que 1, +# desde que o comprimento do vetor maior seja um múltiplo inteiro do menor +c(1,2,3) + c(1,2,3) # 2 4 6 +# Como um único número é um vetor de comprimento um, escalares são aplicados +# elemento a elemento com relação a vetores +(4 * c(1,2,3) - 2) / 2 # 1 3 5 +# Exceto para escalares, tenha cuidado ao realizar aritmética em vetores com +# comprimentos diferentes. Embora possa ser feito, +c(1,2,3,1,2,3) * c(1,2) # 1 4 3 2 2 6 +# ter comprimentos iguais é uma prática melhor e mais fácil de ler +c(1,2,3,1,2,3) * c(1,2,1,2,1,2) + +# CHARACTERS +# Não há diferença entre strings e caracteres em R +"Horatio" # "Horatio" +class("Horatio") # "character" +class('H') # "character" +# São ambos vetores de caracteres de comprimento 1 +# Aqui está um mais longo: +c('alef', 'bet', 'gimmel', 'dalet', 'he') +# "alef" "bet" "gimmel" "dalet" "he" +length(c("Call","me","Ishmael")) # 3 +# Você pode utilizar expressões regulares (regex) em vetores de caracteres: +substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " +gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." +# R tem vários vetores de caracteres embutidos: +letters +# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" +# [20] "t" "u" "v" "w" "x" "y" "z" +month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" + +# LOGICALS +# Em R, um "logical" é um booleano +class(TRUE) # "logical" +class(FALSE) # "logical" +# O comportamento deles é normal +TRUE == TRUE # TRUE +TRUE == FALSE # FALSE +FALSE != FALSE # FALSE +FALSE != TRUE # TRUE +# Dados ausentes (NA) são logical, também +class(NA) # "logical" +# Use | e & para operações lógicas. +# OR +TRUE | FALSE # TRUE +# AND +TRUE & FALSE # FALSE +# Aplicar | e & a vetores retorna operações lógicas elemento a elemento +c(TRUE,FALSE,FALSE) | c(FALSE,TRUE,FALSE) # TRUE TRUE FALSE +c(TRUE,FALSE,TRUE) & c(FALSE,TRUE,TRUE) # FALSE FALSE TRUE +# Você pode testar se x é TRUE +isTRUE(TRUE) # TRUE +# Aqui obtemos um vetor logical com muitos elementos: +c('Z', 'o', 'r', 'r', 'o') == "Zorro" # FALSE FALSE FALSE FALSE FALSE +c('Z', 'o', 'r', 'r', 'o') == "Z" # TRUE FALSE FALSE FALSE FALSE + +# FACTORS +# A classe factor é para dados categóricos +# Os fatores podem ser ordenados (como as avaliações de crianças) ou +# não ordenados (como as cores) +factor(c("azul", "azul", "verde", NA, "azul")) +# azul azul verde <NA> azul +# Levels: azul verde +# Os "levels" são os valores que os dados categóricos podem assumir +# Observe que os dados ausentes não entram nos levels +levels(factor(c("verde", "verde", "azul", NA, "azul"))) # "azul" "verde" +# Se um vetor de factor tem comprimento 1, seus levels também terão comprimento 1 +length(factor("green")) # 1 +length(levels(factor("green"))) # 1 +# Os fatores são comumente vistos em data frames, uma estrutura de dados que abordaremos +# mais tarde +data(infert) # "Infertilidade após aborto espontâneo e induzido" +levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" + +# NULL +# "NULL" é um valor estranho; use-o para "apagar" um vetor +class(NULL) # NULL +parakeet = c("bico", "penas", "asas", "olhos") +parakeet +# [1] "bico" "penas" "asas" "olhos" +parakeet <- NULL +parakeet +# NULL + +# COERÇÃO DE TIPO +# Coerção de tipo é quando você força um valor a assumir um tipo diferente +as.character(c(6, 8)) # "6" "8" +as.logical(c(1,0,1,1)) # TRUE FALSE TRUE TRUE +# Se você colocar elementos de diferentes tipos em um vetor, coerções estranhas acontecem: +c(TRUE, 4) # 1 4 +c("cachorro", TRUE, 4) # "cachorro" "TRUE" "4" +as.numeric("Bilbo") +# [1] NA +# Warning message: +# NAs introduced by coercion + +# Observe também: esses são apenas os tipos de dados básicos +# Existem muitos outros tipos de dados, como datas, séries temporais, etc. + + + +################################################## +# Variáveis, laços, expressões condicionais +################################################## + +# Uma variável é como uma caixa na qual você armazena um valor para uso posterior. +# Chamamos isso de "atribuir" o valor à variável. +# Ter variáveis nos permite escrever laços, funções e instruções com condição + +# VARIÁVEIS +# Existem muitas maneiras de atribuir valores: +x = 5 # é possível fazer assim +y <- "1" # mas é preferível fazer assim +TRUE -> z # isso funciona, mas é estranho + +# LAÇOS +# Nós temos laços com for +for (i in 1:4) { + print(i) +} +# [1] 1 +# [1] 2 +# [1] 3 +# [1] 4 +# Nós temos laços com while +a <- 10 +while (a > 4) { + cat(a, "...", sep = "") + a <- a - 1 +} +# 10...9...8...7...6...5... +# Tenha em mente que os laços for e while são executados lentamente em R +# Operações em vetores inteiros (por exemplo, uma linha inteira, uma coluna inteira) +# ou funções do tipo apply() (discutiremos mais tarde) são mais indicadas + +# IF/ELSE +# Novamente, bastante padrão +if (4 > 3) { + print("4 é maior que 3") +} else { + print("4 não é maior que 3") +} +# [1] "4 é maior que 3" + +# FUNÇÕES +# Definidas assim: +jiggle <- function(x) { + x = x + rnorm(1, sd=.1) # adicione um pouco de ruído (controlado) + return(x) +} +# Chamada como qualquer outra função R: +jiggle(5) # 5±ε. Após set.seed(2716057), jiggle(5)==5.005043 + + + +########################################################################### +# Estruturas de dados: Vetores, matrizes, data frames e arranjos (arrays) +########################################################################### + +# UNIDIMENSIONAL + +# Vamos começar do início, e com algo que você já sabe: vetores. +vec <- c(8, 9, 10, 11) +vec # 8 9 10 11 +# Consultamos elementos específicos utilizando colchetes +# (Observe que R começa a contar a partir de 1) +vec[1] # 8 +letters[18] # "r" +LETTERS[13] # "M" +month.name[9] # "September" +c(6, 8, 7, 5, 3, 0, 9)[3] # 7 +# Também podemos pesquisar os índices de componentes específicos, +which(vec %% 2 == 0) # 1 3 +# pegue apenas as primeiras ou últimas entradas no vetor, +head(vec, 1) # 8 +tail(vec, 2) # 10 11 +# ou descubra se um determinado valor está no vetor +any(vec == 10) # TRUE +# Se um índice for além do comprimento de um vetor, você obterá NA: +vec[6] # NA +# Você pode encontrar o comprimento do seu vetor com length() +length(vec) # 4 +# Você pode realizar operações em vetores inteiros ou subconjuntos de vetores +vec * 4 # 32 36 40 44 +vec[2:3] * 5 # 45 50 +any(vec[2:3] == 8) # FALSE +# e R tem muitas funções internas para sumarizar vetores +mean(vec) # 9.5 +var(vec) # 1.666667 +sd(vec) # 1.290994 +max(vec) # 11 +min(vec) # 8 +sum(vec) # 38 +# Mais alguns recursos embutidos: +5:15 # 5 6 7 8 9 10 11 12 13 14 15 +seq(from=0, to=31337, by=1337) +# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 +# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 + +# BIDIMENSIONAL (ELEMENTOS DA MESMA CLASSE) + +# Você pode fazer uma matriz com entradas do mesmo tipo assim: +mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6)) +mat +# [,1] [,2] +# [1,] 1 4 +# [2,] 2 5 +# [3,] 3 6 +# Ao contrário de um vetor, a classe de uma matriz é "matrix" independente do que ela contém +class(mat) # "matrix" +# Consulte a primeira linha +mat[1,] # 1 4 +# Execute uma operação na primeira coluna +3 * mat[,1] # 3 6 9 +# Consulte uma célula específica +mat[3,2] # 6 + +# Transponha toda a matriz +t(mat) +# [,1] [,2] [,3] +# [1,] 1 2 3 +# [2,] 4 5 6 + +# Multiplicação de matrizes +mat %*% t(mat) +# [,1] [,2] [,3] +# [1,] 17 22 27 +# [2,] 22 29 36 +# [3,] 27 36 45 + +# cbind() une vetores em colunas para formar uma matriz +mat2 <- cbind(1:4, c("cachorro", "gato", "passaro", "cachorro")) +mat2 +# [,1] [,2] +# [1,] "1" "cachorro" +# [2,] "2" "gato" +# [3,] "3" "passaro" +# [4,] "4" "cachorro" +class(mat2) # matrix +# Mais uma vez, observe o que aconteceu! +# Como as matrizes devem conter todas as entradas da mesma classe, +# tudo foi convertido para a classe character +c(class(mat2[,1]), class(mat2[,2])) + +# rbind() une vetores linha a linha para fazer uma matriz +mat3 <- rbind(c(1,2,4,5), c(6,7,0,4)) +mat3 +# [,1] [,2] [,3] [,4] +# [1,] 1 2 4 5 +# [2,] 6 7 0 4 +# Ah, tudo da mesma classe. Sem coerções. Muito melhor. + +# BIDIMENSIONAL (CLASSES DIFERENTES) + +# Para colunas de tipos diferentes, use um data frame +# Esta estrutura de dados é tão útil para programação estatística, +# que uma versão dela foi adicionada ao Python através do pacote "pandas". + +estudantes <- data.frame(c("Cedric","Fred","George","Cho","Draco","Ginny"), + c(3,2,2,1,0,-1), + c("H", "G", "G", "R", "S", "G")) +names(estudantes) <- c("nome", "ano", "casa") # nomeie as colunas +class(estudantes) # "data.frame" +estudantes +# nome ano casa +# 1 Cedric 3 H +# 2 Fred 2 G +# 3 George 2 G +# 4 Cho 1 R +# 5 Draco 0 S +# 6 Ginny -1 G +class(estudantes$ano) # "numeric" +class(estudantes[,3]) # "factor" +# encontre as dimensões +nrow(estudantes) # 6 +ncol(estudantes) # 3 +dim(estudantes) # 6 3 +# A função data.frame() converte vetores de caracteres em vetores de fator +# por padrão; desligue isso definindo stringsAsFactors = FALSE quando +# você criar um data frame +?data.frame + +# Existem muitas maneiras particulares de consultar partes de um data frame, +# todas sutilmente diferentes +estudantes$ano # 3 2 2 1 0 -1 +estudantes[,2] # 3 2 2 1 0 -1 +estudantes[,"ano"] # 3 2 2 1 0 -1 + +# Uma versão extendida da estrutura data.frame é a data.table +# Se você estiver trabalhando com dados enormes ou em painel, ou precisar mesclar +# alguns conjuntos de dados, data.table pode ser uma boa escolha. Aqui está um tour +# relâmpago: +install.packages("data.table") # baixe o pacote a partir do CRAN +require(data.table) # carregue ele +estudantes <- as.data.table(estudantes) +estudantes # observe a saída ligeiramente diferente +# nome ano casa +# 1: Cedric 3 H +# 2: Fred 2 G +# 3: George 2 G +# 4: Cho 1 R +# 5: Draco 0 S +# 6: Ginny -1 G +estudantes[nome=="Ginny"] # Consulte estudantes com o nome == "Ginny" +# nome ano casa +# 1: Ginny -1 G +estudantes[ano==2] # Consulte estudantes com o ano == 2 +# nome ano casa +# 1: Fred 2 G +# 2: George 2 G +# data.table facilita a fusão de dois conjuntos de dados +# vamos fazer outro data.table para mesclar com os alunos +fundadores <- data.table(casa=c("G","H","R","S"), + fundador=c("Godric","Helga","Rowena","Salazar")) +fundadores +# casa fundador +# 1: G Godric +# 2: H Helga +# 3: R Rowena +# 4: S Salazar +setkey(estudantes, casa) +setkey(fundadores, casa) +estudantes <- fundadores[estudantes] # mescle os dois conjuntos de dados com base na "casa" +setnames(estudantes, c("casa","nomeFundadorCasa","nomeEstudante","ano")) +estudantes[,order(c("nome","ano","casa","nomeFundadorCasa")), with=F] +# nomeEstudante ano casa nomeFundadorCasa +# 1: Fred 2 G Godric +# 2: George 2 G Godric +# 3: Ginny -1 G Godric +# 4: Cedric 3 H Helga +# 5: Cho 1 R Rowena +# 6: Draco 0 S Salazar + +# O data.table torna as tabelas de sumário fáceis +estudantes[,sum(ano),by=casa] +# casa V1 +# 1: G 3 +# 2: H 3 +# 3: R 1 +# 4: S 0 + +# Para remover uma coluna de um data.frame ou data.table, +# atribua a ela o valor NULL +estudantes$nomeFundadorCasa <- NULL +estudantes +# nomeEstudante ano casa +# 1: Fred 2 G +# 2: George 2 G +# 3: Ginny -1 G +# 4: Cedric 3 H +# 5: Cho 1 R +# 6: Draco 0 S + +# Remova uma linha consultando parte dos dados +# Usando data.table: +estudantes[nomeEstudante != "Draco"] +# casa estudanteNome ano +# 1: G Fred 2 +# 2: G George 2 +# 3: G Ginny -1 +# 4: H Cedric 3 +# 5: R Cho 1 +# Usando data.frame: +estudantes <- as.data.frame(estudantes) +estudantes[estudantes$casa != "G",] +# casa nomeFundadorCasa nomeEstudante ano +# 4 H Helga Cedric 3 +# 5 R Rowena Cho 1 +# 6 S Salazar Draco 0 + +# MULTIDIMENSIONAL (TODOS OS ELEMENTOS DE UM TIPO) + +# Arranjos (arrays) criam tabelas n-dimensionais +# Todos os elementos devem ser do mesmo tipo +# Você pode fazer uma tabela bidimensional (como uma matriz) +array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) +# [,1] [,2] [,3] [,4] +# [1,] 1 4 8 3 +# [2,] 2 5 9 6 +# Você pode usar array para fazer matrizes tridimensionais também +array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) +# , , 1 +# +# [,1] [,2] +# [1,] 2 8 +# [2,] 300 9 +# [3,] 4 0 +# +# , , 2 +# +# [,1] [,2] +# [1,] 5 66 +# [2,] 60 7 +# [3,] 0 847 + +# LISTAS (MULTIDIMENSIONAIS, POSSIVELMENTE IMPERFEITAS, DE DIFERENTES TIPOS) + +# Finalmente, R tem listas (de vetores) +lista1 <- list(tempo = 1:40) +lista1$preco = c(rnorm(40,.5*lista1$tempo,4)) # aleatória +lista1 +# Você pode obter itens na lista assim +lista1$tempo # um modo +lista1[["tempo"]] # um outro modo +lista1[[1]] # e ainda um outro modo +# [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 +# [34] 34 35 36 37 38 39 40 +# Você pode obter itens de uma lista como qualquer outro vetor +lista1$preco[4] + +# Listas não são a estrutura de dados mais eficiente para se trabalhar em R; +# a menos que você tenha um bom motivo, você deve se ater a data.frames +# As listas geralmente são retornadas por funções que realizam regressões lineares + +################################################## +# A família de funções apply() +################################################## + +# Lembra de mat? +mat +# [,1] [,2] +# [1,] 1 4 +# [2,] 2 5 +# [3,] 3 6 +# Use apply(X, MARGIN, FUN) para aplicar a função FUN a uma matriz X +# sobre linhas (MARGIN = 1) ou colunas (MARGIN = 2) +# Ou seja, R faz FUN para cada linha (ou coluna) de X, muito mais rápido que um +# laço for ou while faria +apply(mat, MAR = 2, jiggle) +# [,1] [,2] +# [1,] 3 15 +# [2,] 7 19 +# [3,] 11 23 +# Outras funções: ?lappy, ?sapply + +# Não as deixe te intimidar; todos concordam que essas funções são bem confusas + +# O pacote plyr visa substituir (e melhorar!) a família *apply(). +install.packages("plyr") +require(plyr) +?plyr + + + +######################### +# Carregando dados +######################### + +# "pets.csv" é um arquivo hospedado na internet +# (mas também poderia tranquilamente ser um arquivo no seu computador) +require(RCurl) +pets <- read.csv(textConnection(getURL("https://learnxinyminutes.com/docs/pets.csv"))) +pets +head(pets, 2) # primeiras duas linhas +tail(pets, 1) # última linha + +# Para salvar um data frame ou matriz como um arquivo .csv: +write.csv(pets, "pets2.csv") # para criar um novo arquivo .csv +# Define o diretório de trabalho com setwd(), confirme em qual você está com getwd() + +# Experimente ?read.csv e ?write.csv para obter mais informações + + + +######################### +# Análise estatística +######################### + +# Regressão linear! +modeloLinear <- lm(preco ~ tempo, data = lista1) +modeloLinear # imprime na tela o resultado da regressão +# Call: +# lm(formula = preco ~ tempo, data = lista1) +# +# Coefficients: +# (Intercept) tempo +# 0.1453 0.4943 +summary(modeloLinear) # saída mais detalhada da regressão +# Call: +# lm(formula = preco ~ tempo, data = lista1) +# +# Residuals: +# Min 1Q Median 3Q Max +# -8.3134 -3.0131 -0.3606 2.8016 10.3992 +# +# Coefficients: +# Estimate Std. Error t value Pr(>|t|) +# (Intercept) 0.14527 1.50084 0.097 0.923 +# tempo 0.49435 0.06379 7.749 2.44e-09 *** +# --- +# Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 +# +# Residual standard error: 4.657 on 38 degrees of freedom +# Multiple R-squared: 0.6124, Adjusted R-squared: 0.6022 +# F-statistic: 60.05 on 1 and 38 DF, p-value: 2.44e-09 +coef(modeloLinear) # extrai os parâmetros estimados +# (Intercept) tempo +# 0.1452662 0.4943490 +summary(modeloLinear)$coefficients # um outro meio de extrair os resultados +# Estimate Std. Error t value Pr(>|t|) +# (Intercept) 0.1452662 1.50084246 0.09678975 9.234021e-01 +# tempo 0.4943490 0.06379348 7.74920901 2.440008e-09 +summary(modeloLinear)$coefficients[,4] # the p-values +# (Intercept) tempo +# 9.234021e-01 2.440008e-09 + +# MODELOS LINEARES GERAIS +# Regressão logística +set.seed(1) +lista1$sucesso = rbinom(length(lista1$tempo), 1, .5) # binário aleatório +modeloLg <- glm(sucesso ~ tempo, data = lista1, + family=binomial(link="logit")) +modeloLg # imprime na tela o resultado da regressão logística +# Call: glm(formula = sucesso ~ tempo, +# family = binomial(link = "logit"), data = lista1) +# +# Coefficients: +# (Intercept) tempo +# 0.17018 -0.01321 +# +# Degrees of Freedom: 39 Total (i.e. Null); 38 Residual +# Null Deviance: 55.35 +# Residual Deviance: 55.12 AIC: 59.12 +summary(modeloLg) # saída mais detalhada da regressão +# Call: +# glm(formula = sucesso ~ tempo, +# family = binomial(link = "logit"), data = lista1) + +# Deviance Residuals: +# Min 1Q Median 3Q Max +# -1.245 -1.118 -1.035 1.202 1.327 +# +# Coefficients: +# Estimate Std. Error z value Pr(>|z|) +# (Intercept) 0.17018 0.64621 0.263 0.792 +# tempo -0.01321 0.02757 -0.479 0.632 +# +# (Dispersion parameter for binomial family taken to be 1) +# +# Null deviance: 55.352 on 39 degrees of freedom +# Residual deviance: 55.121 on 38 degrees of freedom +# AIC: 59.121 +# +# Number of Fisher Scoring iterations: 3 + + +######################### +# Gráficos +######################### + +# FUNÇÕES DE PLOTAGEM INTEGRADAS +# Gráficos de dispersão! +plot(lista1$tempo, lista1$preco, main = "dados falsos") +# Trace a linha de regressão em um gráfico existente! +abline(modeloLinear, col = "red") +# Obtenha uma variedade de diagnósticos legais +plot(modeloLinear) +# Histogramas! +hist(rpois(n = 10000, lambda = 5), col = "thistle") +# Gráficos de barras! +barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) + +# GGPLOT2 +# Mas estes não são nem os mais bonitos dos gráficos no R +# Experimente o pacote ggplot2 para gráficos diferentes e mais bonitos +install.packages("ggplot2") +require(ggplot2) +?ggplot2 +pp <- ggplot(estudantes, aes(x=casa)) +pp + geom_bar() +ll <- as.data.table(lista1) +pp <- ggplot(ll, aes(x=tempo,preco)) +pp + geom_point() +# ggplot2 tem uma excelente documentação (disponível em http://docs.ggplot2.org/current/) + + + +``` + +## Como faço para obter R? + +* Obtenha o R e uma interface gráfica para o R em [http://www.r-project.org/](http://www.r-project.org/) +* [RStudio](http://www.rstudio.com/ide/) é uma outra interface gráfica diff --git a/pt-br/rust-pt.html.markdown b/pt-br/rust-pt.html.markdown index b2bab214..1080baa4 100644 --- a/pt-br/rust-pt.html.markdown +++ b/pt-br/rust-pt.html.markdown @@ -1,5 +1,5 @@ --- -language: rust +language: Rust filename: rust-pt.rs contributors: - ["Paulo Henrique Rodrigues Pinheiro", "https://about.me/paulohrpinheiro"] @@ -234,7 +234,7 @@ fn main() { // `for` laços de repetição/iteração let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } @@ -329,4 +329,3 @@ mais na página oficial [Rust website](http://rust-lang.org). No Brasil acompanhe os encontros do [Meetup Rust São Paulo] (http://www.meetup.com/pt-BR/Rust-Sao-Paulo-Meetup/). - diff --git a/pt-br/sass-pt.html.markdown b/pt-br/sass-pt.html.markdown index 3d91f1ca..e5175857 100644 --- a/pt-br/sass-pt.html.markdown +++ b/pt-br/sass-pt.html.markdown @@ -4,6 +4,7 @@ filename: learnsass-pt.scss contributors: - ["Laura Kyle", "https://github.com/LauraNK"] - ["Sean Corrales", "https://github.com/droidenator"] + - ["Thalles Augusto", "https://github.com/Theslladev"] translators: - ["Gabriel Gomes", "https://github.com/gabrielgomesferraz"] - ["Cássio Böck", "https://github.com/cassiobsilva"] @@ -16,7 +17,7 @@ Sass (e outros pré-processadores, como [Less](http://lesscss.org/)) ajudam os d Sass tem duas opções de sintaxe diferentes para escolher. SCSS, que tem a mesma sintaxe de CSS, mas com os recursos adicionais de Sass. Ou Sass (a sintaxe original), que usa o recuo, em vez de chaves e ponto e vírgula. Este tutorial é escrito usando SCSS. -Se você já está familiarizado com CSS3, você será capaz de pegar Sass de forma relativamente rápida. Ele não fornece quaisquer novas opções de estilo, mas sim as ferramentas para escrever sua CSS de forma mais eficiente e fazer a manutenção mais fácilmente. +Se você já está familiarizado com CSS3, você será capaz de pegar Sass de forma relativamente rápida. Ele não fornece quaisquer novas opções de estilo, mas sim as ferramentas para escrever sua CSS de forma mais eficiente e fazer a manutenção mais facilmente. ```scss @@ -56,19 +57,19 @@ body { } -/ * Este é muito mais fácil de manter do que ter de mudar a cor -cada vez que aparece em toda a sua folha de estilo. * / +/* Este é muito mais fácil de manter do que ter de mudar a cor +cada vez que aparece em toda a sua folha de estilo. */ -/*Mixins +/* Mixins ==============================*/ -/* Se você achar que você está escrevendo o mesmo código para mais de um -elemento, você pode querer armazenar esse código em um mixin. +/* Se você achar que está escrevendo o mesmo código para mais de um +elemento, você pode armazenar esse código em um mixin. Use a diretiva '@mixin', além de um nome para o seu mixin. */ @@ -87,7 +88,7 @@ div { background-color: $primary-color; } -/* Apoś compilar ficaria assim: */ +/* Após compilar ficaria assim: */ div { display: block; margin-left: auto; @@ -128,7 +129,7 @@ div { -/*Funções +/* Funções ==============================*/ @@ -138,6 +139,7 @@ div { /* Funções pode ser chamado usando seu nome e passando o argumentos necessários */ + body { width: round(10.25px); } @@ -156,14 +158,14 @@ body { background-color: rgba(0, 0, 0, 0.75); } -/* Você também pode definir suas próprias funções. As funções são muito semelhantes aos - mixins. Ao tentar escolher entre uma função ou um mixin, lembre- - que mixins são os melhores para gerar CSS enquanto as funções são melhores para - lógica que pode ser usado em todo o seu código Sass. Os exemplos - seção Operadores Math 'são candidatos ideais para se tornar um reutilizável - função. */ +/* Você também pode definir suas próprias funções. As funções são muito semelhantes + aos mixins. Ao tentar escolher entre uma função ou um mixin, lembre + que mixins são os melhores para gerar CSS enquanto as funções são melhores para + lógica que pode ser usado em todo o seu código Sass. Os exemplos na + seção "Operações Math" são candidatos ideais para se tornar um função + reutilizável. */ -/* Esta função terá um tamanho de destino eo tamanho do pai e calcular +/* Esta função terá um tamanho de destino e o tamanho do pai (parent), calcular e voltar a percentagem */ @function calculate-percentage($target-size, $parent-size) { @@ -220,21 +222,21 @@ $main-content: calculate-percentage(600px, 960px); border-color: #22df56; } -/* Ampliando uma declaração CSS é preferível a criação de um mixin - por causa da maneira agrupa as classes que todos compartilham +/* Ao ampliar uma declaração CSS é preferível a criação de um mixin, + por causa da maneira em que agrupa as classes com todos que compartilham o mesmo estilo base. Se isso for feito com um mixin, a largura, altura, e a borda seria duplicado para cada instrução que o chamado mixin. Enquanto isso não irá afetar o seu fluxo de trabalho, será - adicionar inchaço desnecessário para os arquivos criados pelo compilador Sass. */ + adicionado inchaço desnecessário para os arquivos criados pelo compilador Sass. */ -/*Assentamento +/* Assentamento ==============================*/ -/ * Sass permite seletores ninhos dentro seletores * / +/* Sass permite seletores ninhos dentro seletores */ ul { list-style-type: none; @@ -245,10 +247,10 @@ ul { } } -/* '&' será substituído pelo selector pai. */ +/* '&' será substituído pelo selector pai (parent). */ /* Você também pode aninhar pseudo-classes. */ /* Tenha em mente que o excesso de nidificação vai fazer seu código menos sustentável. -Essas práticas também recomendam não vai mais de 3 níveis de profundidade quando nidificação. +Essas práticas também recomendam não mais de 3 níveis de profundidade quando nidificação. Por exemplo: */ @@ -290,7 +292,7 @@ ul li a { -/*Parciais e Importações +/* Parciais e Importações ==============================*/ @@ -313,7 +315,7 @@ ol { /* Sass oferece @import que pode ser usado para importar parciais em um arquivo. Isso difere da declaração CSS @import tradicional, que faz outra solicitação HTTP para buscar o arquivo importado. Sass converte os - importadas arquivo e combina com o código compilado. */ + arquivo importados e combina com o código compilado. */ @import 'reset'; @@ -322,7 +324,7 @@ body { font-family: Helvetica, Arial, Sans-serif; } -/* Compiles to: */ +/* Compila para: */ html, body, ul, ol { margin: 0; @@ -336,14 +338,14 @@ body { -/*Placeholder Selectors +/* Placeholder Selectors ==============================*/ -/* Os espaços reservados são úteis na criação de uma declaração CSS para ampliar. Se você - queria criar uma instrução CSS que foi usado exclusivamente com @extend, - Você pode fazer isso usando um espaço reservado. Espaços reservados começar com um '%' em vez - de '.' ou '#'. Espaços reservados não aparece no CSS compilado. * / +/* Os Placeholders são úteis na criação de uma declaração CSS para ampliar. Se você + deseja criar uma instrução CSS que foi usado exclusivamente com @extend, + você pode fazer isso usando um Placeholder. Placeholder começar com um '%' em vez + de '.' ou '#'. Placeholder não aparece no CSS compilado. */ %content-window { font-size: 14px; @@ -372,14 +374,14 @@ body { -/*Operações Math -============================== * / +/* Operações Math +============================== */ /* Sass fornece os seguintes operadores: +, -, *, /, e %. estes podem - ser úteis para calcular os valores diretamente no seu Sass arquivos em vez - de usar valores que você já calculados pela mão. Abaixo está um exemplo - de uma criação de um projeto simples de duas colunas. * / + ser úteis para calcular os valores diretamente no seu arquivos Sass em vez + de usar valores que você já calcula manualmente. O exemplo abaixo é + de um projeto simples de duas colunas. */ $content-area: 960px; $main-content: 600px; diff --git a/pt-br/self-pt.html.markdown b/pt-br/self-pt.html.markdown index 2fb2953b..0fadf58d 100644 --- a/pt-br/self-pt.html.markdown +++ b/pt-br/self-pt.html.markdown @@ -117,6 +117,7 @@ Múltiplas expressões são separadas por ponto final. ^ retorna imediatamente. ``` Blocos são realizados (completados) ao enviá-los a mensagem 'value' e herdando (imcumbir a) seus contextos: + ``` "retorna 0" [|x| @@ -147,7 +148,7 @@ o objeto '10' no slot 'x' e retornará o objeto original" # Protótipos -Não existem classes em Self. A maneira de obter um objeto é encontrar um protótipo e copia-lo. +Não existem classes em Self. A maneira de obter um objeto é encontrar um protótipo e copiá-lo. ``` | d | diff --git a/pt-br/set-theory-pt.html.markdown b/pt-br/set-theory-pt.html.markdown new file mode 100644 index 00000000..58fd7979 --- /dev/null +++ b/pt-br/set-theory-pt.html.markdown @@ -0,0 +1,129 @@ +--- +category: Algorithms & Data Structures +name: Set theory +lang: pt-br +contributors: + - ["Andrew Ryan Davis", "https://github.com/AndrewDavis1191"] +translators: + - ["Bárbara Luz", "https://github.com/barbluz"] +--- + +Teoria de conjuntos é uma área da matemática que estuda conjuntos, suas operações e propriedades. +- Um conjunto é uma coleção de itens disjuntos. + +## Símbolos básicos + +### Operações +- a operação de união `∪`, significa "ou" +- a operação de interseção `∩`, que significa "e" +- a operação de exclusão `\`, significa "sem" ou "menos" +- a operação de conjunto complementar `'`, que significa "o inverso de" +- a operação de produto cartesiano `×`,que significa "o produto cartesiano de" + +### Outros símbolos +- `:` ou `|`, símbolos que significam "tal que" +- o símbolo de pertencimento `∈`, que significa "pertence a" +- o símbolo `⊆`, que significa "subconjunto de" (neste caso, o subconjunto pode ser igual ao conjunto) +- o símbolo `⊂`, que significa "subconjunto próprio" (neste caso, o subconjunto não pode ser igual ao conjunto) + +### Conjuntos canônicos +- `∅`, o conjunto vazio, isto é, o conjunto que não possui itens +- `ℕ`, o conjunto de todos os números naturais +- `ℤ`, o conjunto de todos os números inteiros +- `ℚ`, o conjunto de todos os números racionais +- `ℝ`, o conjunto de todos os números reais + +Existem algumas ressalvas sobre os conjuntos canônicos: +- Apesar de o conjunto vazio não conter itens, o conjunto vazio é subconjunto de si mesmo (e portanto de todos os outros conjuntos) +- Matemáticos geralmente não concordam sobre o zero ser um número natural e os livros tipicamente explicitam se o autor considera ou não o zero como um número natural + + +### Cardinalidade +A cardinalidade (ou tamanho) de um conjunto é determinado pela quantidade de itens no conjunto. O operador de cardinalidade é `|...|` + +Por exemplo, se `S = {1, 2, 4}`, então `|S| = 3`. + +### O Conjunto Vazio +- o conjunto vazio pode ser contruído em notação de conjuntos utilizando condições impossíveis, como por exemplo: `∅ = { x : x ≠ x }`, ou `∅ = { x : x ∈ N, x < 0 }` +- o conjunto vazio é sempre único (ou seja, existe um e apenas um conjunto vazio) +- o conjunto vazio é subconjunto de todos os conjuntos +- a cardinalidade do conjunto vazio é `0`, ou seja, `|∅| = 0`. + +## Representando conjuntos + +### Definição Literal +Um conjunto pode ser contruído literalmente fornecendo uma lista completa dos itens contigos no conjunto. Por exemplo `S = { a, b, c, d }` + +Listas longas podem ser encurtadas com reticências, desde que o contexto seja claro. Por exemplo, `E = { 2, 4, 6, 8, ... }` é claramente o conjunto de todos os números pares, contendo um número infinito de objetos, embora só tenhamos escrito explicitamente quatro deles. + +### Definição por compreensão +Conjuntos também podem ser descritos de uma maneira mais descritiva, baseando-se em sujeito e predicado, de forma tal que `S = {sujeito : predicado}`. Por exemplo: + +``` +A = { x : x é uma vogal } = { a, e, i, o, u } (lê-se x, tal que x é uma vogal) +B = { x : x ∈ N, x < 10 } = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } +C = { x : x = 2k, k ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +Ou pode-se também aplicar uma função ao sujeito, ex: +``` +D = { 2x : x ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +## Relações + +### Pertencimento +- Se um valor `a` está contido num conjunto `A`, então dizemos que `a` pertence a `A` e denotamos por `a ∈ A` +- Se o valor `a` não está contido no conjunto `A`, então dizemos que `a` não pertence a `A` e denotamos por `a ∉ A` + +### Igualdade +- Se dois conjuntos contém os mesmos itens, então dizemos que os conjuntos são iguals, ex. `A = B` +- A ordenação não importa quando vamos avaliar a igualdade, ex: `{ 1, 2, 3, 4 } = { 2, 3, 1, 4 }` +- Conjuntos são disjuntos, o que significa que os elementos não podem ser repetidos, ex: `{ 1, 2, 2, 3, 4, 3, 4, 2 } = { 1, 2, 3, 4 }` +- Dois conjuntos `A` e `B` são iguais se, e somente se, `A ⊆ B` e `B ⊆ A` + +### Conjuntos especiais +O Conjunto das Partes +- Seja `A` um conjunto qualquer. O conjunto que contém todos os possíveis subconjuntos de `A` é chamado "conjunto das partes" e é denotado como `P(A)`. Se o conjunto `A` contém `n` elementos, então o conjunto das partes conterá `2^n` elementos. +``` +P(A) = { x : x ⊆ A } +``` + +## Operações entre dois conjuntos + +### União +Dados dois conjuntos `A` e `B`, a união entre esses dois conjuntos são os itens que aparecem em `A` ou em `B`, denotado por `A ∪ B`. + +``` +A ∪ B = { x : x ∈ A ∪ x ∈ B } +``` + +### Interseção +Dados dois conjuntos `A` e `B`, a interseção entre esses dois conjuntos são os itens que aparecem em `A` e em `B`, denotado por `A ∩ B`. + +``` +A ∩ B = { x : x ∈ A, x ∈ B } +``` + +### Diferença +Dados dois conjuntos `A` e `B`, o conjunto da diferença entre `A` e `B` são todos os itens de `A` que não pertencem a `B`. +``` +A \ B = { x : x ∈ A, x ∉ B } +``` + +### Diferença simétrica +Dados dois conjuntos `A` e `B`, a diferença simétrica são todos os itens entre `A` e `B` que não aparecem na interseção desses dois conjuntos. + +``` +A △ B = { x : ((x ∈ A) ∩ (x ∉ B)) ∪ ((x ∈ B) ∩ (x ∉ A)) } + +A △ B = (A \ B) ∪ (B \ A) +``` + +### Produto Cartesiano +Dados dois conjuntos `A` e `B`, o produto cartesiano de `A` e `B` consiste no conjunto contendo todas as combinações dos itens de `A` e `B`. +``` +A × B = { (x, y) | x ∈ A, y ∈ B } +``` + + diff --git a/pt-br/solidity-pt.html.markdown b/pt-br/solidity-pt.html.markdown index d4555fa7..c77ff298 100644 --- a/pt-br/solidity-pt.html.markdown +++ b/pt-br/solidity-pt.html.markdown @@ -259,7 +259,7 @@ nomes.length; // pega o tamanho nomes.length = 1; // tamanhos pode ser alterados (para arrays dinâmicos) // arrays multidimensionais -uint x[][5]; // array com 5 arrays dinâmicos como elementos (ordem da maioria +uint[][5] x; // array com 5 arrays dinâmicos como elementos (ordem da maioria // das linguagens) // Dicionários (qualquer tipo para qualquer tipo) diff --git a/pt-br/sql-pt.html.markdown b/pt-br/sql-pt.html.markdown new file mode 100644 index 00000000..0e4631a6 --- /dev/null +++ b/pt-br/sql-pt.html.markdown @@ -0,0 +1,119 @@ +--- +language: SQL +filename: learnsql-pt.sql +contributors: + - ["Bob DuCharme", "http://bobdc.com/"] +translators: + - ["jovinoguerrero", "https://github.com/jovinoguerrero"] +lang: pt-br +--- + +A linguagem de consulta estruturada (SQL em inglês) é uma linguagem padrão ISO para criar e trabalhar com bancos de dados armazenados num conjunto de tabelas. As implementações geralmente adicionam suas próprias extensões à linguagem; [Comparação entre diferentes implementações de SQL](http://troels.arvin.dk/db/rdbms/) é uma boa referência sobre as diferenças entre os diferentes produtos. + +As implementações normalmente fornecem uma linha de comando onde se pode digitar os comandos mostrados aqui de forma interativa, e também oferecem uma maneira de executar uma série desses comandos armazenados em um arquivo de script (mostrar que é feito com o prompt interativo é um bom exemplo de algo que não é padronizado - a maioria das implementações SQL suporta as palavras-chave QUIT, EXIT ou ambas). + +Vários desses comandos de exemplo assumem que o [banco de dados de funcionários de exemplo MySQL](https://dev.mysql.com/doc/employee/en/) disponível em [github](https://github.com/datacharmer/test_db) já foi carregado. Os arquivos do GitHub são scripts de comandos, semelhantes aos comandos abaixo, que criam e carregam tabelas de dados sobre os funcionários de uma empresa fictícia. A sintaxe para executar esses scripts dependerá da implementação SQL que você está usando. Um aplicativo executado a partir do prompt do sistema operacional geralmente é o normal. + + +```sql +-- Os comentários começam com dois hífens. Cada comando é encerrado com um +-- ponto e vírgula. + +-- SQL não diferencia maiúsculas de minúsculas em palavras-chave. Os +-- comandos de exemplo mostrados aqui seguem a convenção de serem escritos +-- em maiúsculas porque torna mais fácil distingui-los dos nomes dos bancos +-- de dados, tabelas e colunas. + +-- Em seguida, um banco de dados é criado e excluído. Os nomes do banco de +-- dados e da tabela são sensíveis a maiúsculas de minúsculas. +CREATE DATABASE someDatabase; +DROP DATABASE someDatabase; + +-- Mostra numa lista todos os bancos de dados disponíveis. +SHOW DATABASES; + +-- Usa um determinado banco de dados existente. +USE employees; + +-- Seleciona todas as filas e colunas da tabela de departamentos no banco +-- de dados atual. A atividade padrão é o intérprete rolar os resultados +-- na tela. +SELECT * FROM departments; + +-- Recupera todas as filas da tabela de departamentos, mas apenas as colunas +-- dept_no e dept_name. +-- A separação de comandos em várias linhas é permitida. +SELECT dept_no, + dept_name FROM departments; + +-- Obtém todas as colunas de departments, mas é limitado a 5 filas. +SELECT * FROM departments LIMIT 5; + +-- Obtém os valores da coluna dept_name da tabela de departments quando +-- dept_name tem como valor a substring 'en'. +SELECT dept_name FROM departments WHERE dept_name LIKE '%en%'; + +-- Recupera todas as colunas da tabela de departments onde a coluna +-- dept_name começa com um 'S' e tem exatamente 4 caracteres depois dele. +SELECT * FROM departments WHERE dept_name LIKE 'S____'; + +-- Seleciona os valores dos títulos da tabela de titles, mas não mostra +-- duplicatas. +SELECT DISTINCT title FROM titles; + +-- Igual ao anterior, mas ordenado por valores de da coluna title (diferencia +-- maiúsculas de minúsculas). +SELECT DISTINCT title FROM titles ORDER BY title; + +-- Mostra o número de filas da tabela departments. +SELECT COUNT(*) FROM departments; + +-- Mostra o número de filas da tabela departments que contém 'en' como +-- substring na coluna dept_name. +SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%'; + +-- Uma união (JOIN) de informações de várias tabelas: a tabela titles mostra +-- quem tem quais cargos laborais, de acordo com seu número de funcionários, +-- e desde que data até que data. Esta informação é obtida, mas em vez do +-- número do funcionário é usada como referência cruzada a tabela employee +-- para obter o nome e sobrenome de cada funcionário (e limita os resultados +-- a 10 filas). +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; + +-- São listadas todas as tabelas de todas os bancos de dados. As implementações +-- normalmente fornecem seus próprios comandos para fazer isso com o banco de +-- dados atualmente em uso. +SELECT * FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_TYPE='BASE TABLE'; + +-- Cria uma tabela chamada tablename1, com as duas colunas mostradas, a partir +-- do banco de dados em uso. Há muitas outras opções dísponiveis para a forma +-- em que se especificam as colunas, por ex. seus tipos de dados. +CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20)); + +-- Insere uma fila de dados na tabela tablename1. É assumido que a tabela foi +-- definida para aceitar esses valores como adequados. +INSERT INTO tablename1 VALUES('Richard','Mutt'); + +-- Em tablename1, se altera o valor de fname para 'John' em todas as filas que +-- contenham um valor em lname igual a 'Mutt'. +UPDATE tablename1 SET fname='John' WHERE lname='Mutt'; + +-- Se excluem as filas da tabela tablename1 em que o valor de lname começa +-- com 'M'. +DELETE FROM tablename1 WHERE lname like 'M%'; + +-- Se excluem as filas da tabela tablename1, deixando a tabla vazia. +DELETE FROM tablename1; + +-- A tabela tablename1, é excluída completamente. +DROP TABLE tablename1; +``` + +# Leitura adicional + +* [Codecademy - SQL](https://www.codecademy.com/learn/learn-sql) A good introduction to SQL in a “learn by doing it” format. +* [Database System Concepts](https://www.db-book.com/) book’s Chapter 3 - Introduction to SQL has an in depth explanation of SQL concepts. diff --git a/pt-br/stylus-pt.html.markdown b/pt-br/stylus-pt.html.markdown index 804fa806..40c3c02c 100755..100644 --- a/pt-br/stylus-pt.html.markdown +++ b/pt-br/stylus-pt.html.markdown @@ -132,7 +132,7 @@ body { background-color: $primary-color } -/* Apoś compilar ficaria assim: */ +/* Após compilar ficaria assim: */ div { display: block; margin-left: auto; @@ -184,13 +184,13 @@ button /* Funções ==============================*/ -/* Funções no Stylus permitem fazer uma variedade de tarefas, como por exemplo, menipular algum dado. */ +/* Funções no Stylus permitem fazer uma variedade de tarefas, como por exemplo, manipular algum dado. */ body { background darken(#0088DD, 50%) // Escurece a cor #0088DD em 50% } -/** Criando sua própria função */ +/* Criando sua própria função */ somar(a, b) a + b @@ -221,7 +221,7 @@ for <val-name> [, <key-name>] in <expression> for $item in (1..2) /* Repete o bloco 12 vezes */ .col-{$item} - width ($item / 12) * 100% /* Calcula a largula pelo número da coluna* + width ($item / 12) * 100% /* Calcula a largura pelo número da coluna* ``` diff --git a/pt-br/swift-pt.html.markdown b/pt-br/swift-pt.html.markdown index bf410352..96b96427 100644 --- a/pt-br/swift-pt.html.markdown +++ b/pt-br/swift-pt.html.markdown @@ -10,7 +10,7 @@ lang: pt-br --- -Swift é uma linguagem de programação para desenvolvimento de aplicações no iOS e OS X criada pela Apple. Criada para +Swift é uma linguagem de programação para desenvolvimento de aplicações no iOS e macOS criada pela Apple. Criada para coexistir com Objective-C e para ser mais resiliente a código com erros, Swift foi apresentada em 2014 na Apple's developer conference WWDC. Foi construída com o compilador LLVM já incluído no Xcode 6 beta. diff --git a/pt-br/tmux-pt.html.markdown b/pt-br/tmux-pt.html.markdown index ce3be407..e2130e0a 100644 --- a/pt-br/tmux-pt.html.markdown +++ b/pt-br/tmux-pt.html.markdown @@ -59,47 +59,49 @@ As seções tmux acopladas são controladas através de teclas de atalho. (prefi ---------------------------------------------------------------------- (C-b) = Ctrl + b # Abre a opção de receber comandos(atalhos). - (M-1) = Meta + 1 -or- Alt + 1 + (M-1) = Meta + 1 -ou- Alt + 1 ---------------------------------------------------------------------- - ? # Lista todos os comandos. - : # Acessa o prompt command do tmux - r # Força a reinicialização do cliente acoplado. - c # Cria uma nova janela. + ? # Lista todos os comandos. + : # Acessa o prompt command do tmux + r # Força a reinicialização do cliente acoplado. + c # Cria uma nova janela. - ! # Retira o painel atual da janela. - % # Divide o painel atual em dois. Esquerda e direita. - " # Divide o painel atual em dois. Para cima e para baixo. + ! # Retira o painel atual da janela. + % # Divide o painel atual em dois. Esquerda e direita. + " # Divide o painel atual em dois. Para cima e para baixo. - n # Muda para a próxima janela. - p # Muda para a janela anterior. - { # Troca o painel atual pelo anterior. - } # Troca o painel corrent pelo posterior. + n # Muda para a próxima janela. + p # Muda para a janela anterior. + { # Troca o painel atual pelo anterior. + } # Troca o painel corrent pelo posterior. + [ # Entra no modo cópia (Copy Mode) para copiar texto ou ver o histórico. - s # Seleciona uma nova seção para o cliente acoplado iterativamente. - w # Seleciona a janela atual iterativamente. - 0 to 9 # Seleciona a janela de 0 à 9. - d # Separa o cliente atual. - D # Seleciona um cliente a ser separado. + s # Seleciona uma nova seção para o cliente acoplado iterativamente. + w # Seleciona a janela atual iterativamente. + 0 to 9 # Seleciona a janela de 0 à 9. - & # Encerra a janela atual. - x # Encerra o painel atual. + d # Separa o cliente atual. + D # Seleciona um cliente a ser separado. - Up, Down # Move para o painel acima, abaixo, a esquerda ou a direita. + & # Encerra a janela atual. + x # Encerra o painel atual. + + Up, Down # Move para o painel acima, abaixo, a esquerda ou a direita. Left, Right - M-1 to M-5 # Organiza os paines: + M-1 to M-5 # Organiza os paines: # 1) Horizontalmente de maneira igual # 2) Verticalmente de maineira igual. # 3) Principal horizontalmente # 4) Principal verticamente. # 5) Mosaico - C-Up, C-Down # Altera o tamanho do painel atual em uma célula. + C-Up, C-Down # Altera o tamanho do painel atual em uma célula. C-Left, C-Right - M-Up, M-Down # Altera o tamanho do painel atual em cinco células. + M-Up, M-Down # Altera o tamanho do painel atual em cinco células. M-Left, M-Right ``` diff --git a/pt-br/toml-pt.html.markdown b/pt-br/toml-pt.html.markdown new file mode 100644 index 00000000..bdb1decf --- /dev/null +++ b/pt-br/toml-pt.html.markdown @@ -0,0 +1,232 @@ +--- +language: toml +filename: learntoml-pt.toml +contributors: + - ["Alois de Gouvello", "https://github.com/aloisdg"] +translators: + - ["Adaías Magdiel", "https://adaiasmagdiel.com/"] +lang: pt-br +--- + +TOML significa Tom's Obvious, Minimal Language. É uma linguagem de serialização de dados projetada para ser um formato de arquivo de configuração mínimo que é fácil de ler devido à semântica óbvia. + +É uma alternativa ao YAML e JSON. Tem como objetivo ser mais amigável para humanos do que JSON e mais simples que YAML. TOML é projetado para mapear de forma inequívoca para uma tabela de hash e deve ser fácil de converter em estruturas de dados em uma ampla variedade de linguagens. + +Cuidado, a especificação do TOML ainda passa por muitas mudanças. Até que seja marcado como 1.0, você deve assumir que é instável e agir de acordo. Este documento segue o TOML v0.4.0. + +```toml +# Comentários em TOML são feitos desta forma. + +################### +# TIPOS ESCALARES # +################### + +# Nosso objeto raiz (que continuará por todo o documento) será um mapa, +# que é equivalente a um dicionário, hash ou objeto em outras linguagens. + +# A chave, o sinal de igual e o valor precisam estar na mesma linha +# (embora alguns valores possam ser quebrados em várias linhas). +chave = "valor" +string = "Olá" +number = 42 +float = 3.14 +boolean = true +dateTime = 2002-07-16T20:32:00-03:00 +scientificNotation = 1e+12 +"chaves podem estar entre aspas" = true # Tanto " quanto ' são aceitáveis +"chaves podem conter" = "letras, números, underscores e hífens" + +# Uma chave não pode ser vazia, mas uma chave vazia entre aspas é permitido +"" = "blank" # VÁLIDO mas não é recomendado +'' = 'blank' # VÁLIDO mas não é recomendado + +########## +# String # +########## + +# Todas as strings precisam ter apenas caracteres UTF-8 válidos. +# Podemos escapar caracteres e alguns deles têm uma sequência de escape compacta. +# Por exemplo: \t adiciona uma tabulação. Leia a spec para conhecer todos. +basicString = "São cercadas por aspas. \"Sou digno de citação\". Nome\tJosé." + +multiLineString = """ +são cercadas por três aspas +em cada lado e permitem novas linhas.""" + +literalString = 'são cercadas por aspas simples. Escape de caracteres não é permitido.' + +multiLineString = ''' +são cercadas por três aspas simples em cada lado +e permitem novas linhas. Escape de caracteres também não é permitido. +A primeira quebra de linha é removida em strings brutas + Todo outro espaço em branco + é preservado. #! foi preservado? +''' + +# Para dados binários é recomendado que você use Base64, outra codificação ASCII ou UTF8. +# A manipulação dessa codificação será específico da aplicação. + +############ +# Inteiros # +############ + +## Inteiros podem começar com um +, um -, ou nada. +## Zeros à frente não são permitidos. +## Formatos em hexadecimal, octal e binário são permitidos. +## Não são permitidos valores que não podem ser expressados como uma série de dígitos. +int1 = +42 +int2 = 0 +int3 = -21 +int4 = 0xcafebabe +int5 = 0o755 +int6 = 0b11011100 +integerRange = 64 + +## Você pode usar underscores para melhorar a legibilidade. +## Cada underscore precisa estar entre, pelo menos, um dígito. +int7 = 5_349_221 +int8 = 1_2_3_4_5 # VÁLIDO, mas não é recomendado + +######### +# Float # +######### + +# Floats são inteiros seguidos por uma fração e/ou de um expoente. +flt1 = 3.1415 +flt2 = -5e6 +flt3 = 6.626E-34 + +############# +# Booleanos # +############# + +bool1 = true +bool2 = false +booleanosPrecisamEstarEmMinusculo = true + +############ +# Datetime # +############ + +date1 = 1979-05-27T07:32:00Z # Tempo UTC, seguindo especificação RFC 3339/ISO 8601 +date2 = 1979-05-26T15:32:00+08:00 # com um deslocamento segundo a RFC 3339/ISO 8601 +date3 = 1979-05-27T07:32:00 # sem deslocamento +date4 = 1979-05-27 # sem as horas e sem deslocamento + +#################### +# TIPOS DE COLEÇÃO # +#################### + +######### +# Array # +######### + +array1 = [ 1, 2, 3 ] +array2 = [ "Vírgulas", "são", "delimitadores" ] +array3 = [ "Não misture", "tipos", "diferentes" ] +array4 = [ [ 1.2, 2.4 ], ["todas as", 'strings', """são do mesmo""", '''tipo'''] ] +array5 = [ + "Espaços em branco", "são", "ignorados" +] + +########## +# Tabela # +########## + +# Tabelas (ou tabelas de hash, ou dicionários) é uma coleção de pares chave/valor. +# Eles aparecem entre colchetes em uma linha separada. +# Tabelas vazias são permitidas e simplesmente não possuem chave/valor associado. +[tabela] + +# Abaixo disso, e até a próxima tabela ou final do arquivo, estão as chaves/valores dessa tabela. +# Os pares de chave/valor dentro das tabelas não têm garantia de estar em nenhuma ordem específica. +[table-1] +chave1 = "algum texto" +chave2 = 123 + +[table-2] +chave1 = "outro texto" +chave2 = 456 + +# Pontos são proibidos em chaves simples porque são usados para indicar tabelas aninhadas. +# As regras de nomenclatura para cada parte separada por ponto são as mesmas que para chaves. +[dog."tater.man"] +type = "pug" + +# Na terra do JSON, você teria a seguinte estrutura: +# { "dog": { "tater.man": { "type": "pug" } } } + +# Espaços em branco em torno das partes separadas por pontos são ignorados, de qualquer forma, +# é sempre recomendado não utilizar espaços em branco desnecessários. +[a.b.c] # isso é o recomendado +[ d.e.f ] # mesmo que [d.e.f] +[ j . "ʞ" . 'l' ] # mesmo que [j."ʞ".'l'] + +# Você não precisa especificar todas as super-tabelas se não quiser. TOML sabe +# como lidar com isso para você. +# [x] você +# [x.y] não precisa +# [x.y.z] disso +[x.y.z.w] # para isso funcionar + +# Mesmo que uma super-tabela não tenha sido definida diretamente e não tenha definido uma +# chave específica, ainda é possível escrever nela. +[a.b] +c = 1 + +[a] +d = 2 + +# Irá gerar o seguinte JSON: +# { "a": {"b": {"c": 1}, "d": 2 } } + +# Você não pode definir uma chave ou tabela mais de uma vez. É inválido fazer isso. + +# NÃO FAÇA ISSO +[a] +b = 1 + +[a] +c = 2 + +# NEM MESMO ISSO +[a] +b = 1 + +[a.b] +c = 2 + +# O nome de todas as tabelas não pode ser vazio. +[] # INVÁLIDO +[a.] # INVÁLIDO +[a..b] # INVÁLIDO +[.b] # INVÁLIDO +[.] # INVÁLIDO + +#################### +# Tabelas em linha # +#################### + +tabelasEmLinha = { sãoFechadasCom = "{ e }", precisamEstarEmUmaLinha = true } +ponto = { x = 1, y = 2 } + +#################### +# Array de Tabelas # +#################### + +# Um array de tabelas pode ser expresso usando um nome de tabela entre colchetes duplos. +# Cada tabela com o mesmo nome entre colchetes duplos será um item no array. +# As tabelas são inseridas na ordem em que são encontradas. + +[[produtos]] +nome = "array de tabelas" +sku = 738594937 +tabelasVaziasSaoPermitidas = true + +[[produtos]] + +[[produtos]] +nome = "Unhas" +sku = 284758393 +color = "cinza" +``` diff --git a/pt-br/typescript-pt.html.markdown b/pt-br/typescript-pt.html.markdown index 077aa2cc..7d28bf53 100644 --- a/pt-br/typescript-pt.html.markdown +++ b/pt-br/typescript-pt.html.markdown @@ -10,11 +10,11 @@ lang: pt-br Typescript é uma linguagem que visa facilitar o desenvolvimento de aplicações em grande escala escritos em JavaScript. Typescript acrescenta conceitos comuns como classes, módulos, interfaces, genéricos e (opcional) tipagem estática para JavaScript. -É um super conjunto de JavaScript: todo o código JavaScript é o código do texto dactilografado válido para que possa ser adicionados diretamente a qualquer projeto. O compilador emite typescript JavaScript. +É um super conjunto de JavaScript: todo o código JavaScript é TypeScript válido então ele pode ser adicionado diretamente a qualquer projeto. O compilador emite TypeScript JavaScript. -Este artigo irá se concentrar apenas em texto datilografado sintaxe extra, ao contrário de [JavaScript](javascript-pt.html.markdown). +Este artigo irá se concentrar apenas na sintaxe extra do TypeScript, ao contrário de [JavaScript](../javascript-pt/). -Para testar compilador do texto datilografado, de cabeça para o [Parque](http://www.typescriptlang.org/Playground), onde você vai ser capaz de escrever código, ter auto conclusão e ver diretamente o JavaScript emitida. +Para testar o compilador TypeScript, vá para o [Playground](http://www.typescriptlang.org/Playground), onde você vai ser capaz de escrever código, ter auto conclusão e ver diretamente o JavaScript emitido. ```js // Existem 3 tipos básicos no TypeScript @@ -22,7 +22,7 @@ var isDone: boolean = false; var lines: number = 42; var name: string = "Anders"; -// Quando é impossível saber, há o "Qualquer" tipo +// Quando é impossível saber, há o tipo "Qualquer" var notSure: any = 4; notSure = "maybe a string instead"; notSure = false; // Ok, definitivamente um boolean @@ -44,13 +44,13 @@ function bigHorribleAlert(): void { // Funções são cidadãos de primeira classe, apoiar a sintaxe lambda "seta gordura" e // Tipo de uso inferência -// A seguir são equivalentes, a mesma assinatura será inferido pelo -// Compilador, e mesmo JavaScript será emitido +// A seguir são equivalentes, a mesma assinatura será inferida pelo +// Compilador, e o mesmo JavaScript será emitido var f1 = function(i: number): number { return i * i; } -// Tipo de retorno inferida +// Tipo de retorno inferido var f2 = function(i: number) { return i * i; } var f3 = (i: number): number => { return i * i; } -// Tipo de retorno inferida +// Tipo de retorno inferido var f4 = (i: number) => { return i * i; } // Tipo de retorno inferido, one-liner significa nenhuma palavra-chave retorno necessário var f5 = (i: number) => i * i; @@ -65,7 +65,7 @@ interface Person { move(): void; } -// Objeto que implementa a "Pessoa" Interface +// Objeto que implementa a Interface "Pessoa" // Pode ser tratado como uma pessoa desde que tem o nome e mover propriedades var p: Person = { name: "Bobby", move: () => {} }; // Os objetos que têm a propriedade opcional: @@ -88,7 +88,7 @@ class Point { // Propriedades x: number; - // Construtor - the public/private keywords in this context will generate + // Construtor - as palavras-chave public/private nesse contexto irão gerar // o código clichê para a propriedade e a inicialização no // construtor. // Neste exemplo, "y" será definida como "X" é, mas com menos código diff --git a/pt-br/vim-pt.html.markdown b/pt-br/vim-pt.html.markdown index d7617bbe..cc304381 100644 --- a/pt-br/vim-pt.html.markdown +++ b/pt-br/vim-pt.html.markdown @@ -5,6 +5,7 @@ contributors: - ["RadhikaG", "https://github.com/RadhikaG"] translators: - ["David Lima", "https://github.com/davelima"] + - ["Raul Almeida", "https://github.com/almeidaraul"] lang: pt-br filename: LearnVim-pt.txt --- @@ -24,6 +25,7 @@ para agilizar a navegação para pontos específicos no arquivo, além de ediç :w # Salva o arquivo atual :wq # Salva o arquivo e fecha o vim :q! # Fecha o vim e descarta as alterações no arquivo + # ! depois de qualquer comando força a sua execução # ! *força* :q a executar, fechando o vim sem salvar antes :x # Salva o arquivo e fecha o vim (atalho para :wq) @@ -158,7 +160,15 @@ Alguns exemplos importantes de 'Verbos', 'Modificadores' e 'Nomes': :earlier 15m # Reverte o documento para como ele estava há 15 minutos atrás :later 15m # Reverte o comando acima ddp # Troca linhas consecutivas de posição, dd e depois p + xp # Permuta caractere atual e o seguinte + Xp # Permuta caractere atual e o anterior . # Repete a última ação + + # Em geral, o usuário pode associar um comando em maísculas (exemplo: D) com + # "executar este comando até o final da linha" + + # Usar a tecla de um comando duas vezes geralmente significa executar este + # comando sobre toda a linha (exemplo: dd apaga a linha inteira) ``` ## Macros @@ -172,6 +182,7 @@ exatamente a mesma sequencia de ações e comandos na seleção atual. qa # Inicia a gravação de uma macro chamado 'a' q # Para a gravação @a # Executa a macro + @@ # Executa a última macro executada ``` ### Configurando o ~/.vimrc diff --git a/pt-br/visualbasic-pt.html.markdown b/pt-br/visualbasic-pt.html.markdown index 2a7205cd..dcc72c04 100644 --- a/pt-br/visualbasic-pt.html.markdown +++ b/pt-br/visualbasic-pt.html.markdown @@ -8,7 +8,7 @@ lang: pt-br filename: learnvisualbasic-pt.vb --- -``` +```visualbasic Module Module1 module Module1 @@ -28,12 +28,12 @@ module Module1 Console.WriteLine ("2. Entrada Olá Mundo" ) Console.WriteLine ("3. Cálculando números inteiros " ) Console.WriteLine ("4. Calculando números decimais " ) - Console.WriteLine ("5 . Calculadora de Trabalho " ) + Console.WriteLine ("5. Calculadora de Trabalho " ) Console.WriteLine ("6. Usando Do While Loops " ) Console.WriteLine ("7. Usando Para While Loops " ) - Console.WriteLine ("8 . Declarações condicionais " ) + Console.WriteLine ("8. Declarações condicionais " ) Console.WriteLine ("9. Selecione uma bebida" ) - Console.WriteLine ("50 . About" ) + Console.WriteLine ("50. About" ) Console.WriteLine ("Por favor, escolha um número da lista acima " ) Seleção Dim As String = Console.ReadLine Select A seleção dos casos @@ -76,7 +76,7 @@ module Module1 End Sub ' Um - Eu estou usando números para ajudar com a navegação acima quando eu voltar - ' depois de construí-lo . + ' depois de construí-lo. " Nós usamos subs privadas para separar diferentes seções do programa. Private Sub HelloWorldOutput () @@ -94,12 +94,12 @@ module Module1 Console.Title = " Olá Mundo YourName | Saiba X em Y Minutes" ' Variáveis 'Os dados inseridos por um usuário precisam ser armazenados. - ' As variáveis também começar com um Dim e terminar com um Como VariableType . + ' As variáveis também começar com um Dim e terminar com um Como VariableType. ' Neste tutorial, nós queremos saber qual é o seu nome, e faça o programa ' Responder ao que é dito. Nome de usuário Dim As String - " Nós usamos string como string é uma variável de texto baseado . + " Nós usamos string como string é uma variável de texto baseado. Console.WriteLine (" Olá, Qual é o seu nome? ") ' Peça ao usuário seu nome. username = Console.ReadLine () ' armazena o nome do usuário. Console.WriteLine (" Olá " + username) ' A saída é "Olá < seu nome >". @@ -124,10 +124,10 @@ module Module1 'Quatro Sub CalculatingDecimalNumbers particulares () Console.Title = " Calculando com duplo | Saiba X em Y Minutes" - ' Claro que gostaria de ser capaz de somar decimais . + ' Claro que gostaria de ser capaz de somar decimais. " Por isso, poderia mudar o acima de Integer para Double. - " Digite um número inteiro , 1,2 , 2,4 , 50,1 , 104,9 ect + " Digite um número inteiro como 1, 2, 50, 104, etc Console.Write ("Primeiro número:") Dim a As Double = Console.ReadLine Console.Write ("Segundo número:") 'Enter segundo número inteiro. @@ -141,9 +141,9 @@ module Module1 ' Cinco Private Sub WorkingCalculator () Console.Title = " A Calculadora de Trabalho | Saiba X em Y Minutes" - " No entanto, se você gostaria que a calculadora para subtrair, dividir , múltiplos e + " No entanto, se você gostaria que a calculadora para subtrair, dividir, múltiplos e ' somar. - ' Copie e cole o código acima novamente . + ' Copie e cole o código acima novamente. Console.Write ("Primeiro número:") Dim a As Double = Console.ReadLine Console.Write ("Segundo número:") 'Enter segundo número inteiro. @@ -153,7 +153,7 @@ module Module1 Dim e As Integer = a - b Dim f As Integer = a / b - " Ao adicionar as linhas abaixo , somos capazes de calcular a subtração , + " Ao adicionar as linhas abaixo, somos capazes de calcular a subtração, ' multply bem como dividir os valores de a e b Console.Gravar ( a.ToString ( ) + " + " + b.ToString ( ) ) 'Queremos pad as respostas para a esquerda por três espaços. @@ -172,8 +172,8 @@ module Module1 Sub UsingDoWhileLoops particulares () ' Assim como o sub privado anterior ' Desta vez, perguntar se o usuário deseja continuar ( Sim ou Não ? ) - ' Estamos usando Do While Loop , como não temos certeza se o usuário quer usar o - 'programa mais de uma vez . + ' Estamos usando Do While Loop, como não temos certeza se o usuário quer usar o + 'programa mais de uma vez. Console.Title = " UsingDoWhileLoops | Saiba X em Y Minutes" Dim resposta As String ' Nós usamos a variável " String" como a resposta é um texto Do ' Começamos o programa com @@ -195,12 +195,12 @@ module Module1 Console.Write ( a.ToString () + "/" + b.ToString ()) Console.WriteLine (" =" + e.ToString.PadLeft (3) ) Console.ReadLine () - ' Faça a pergunta , se o usuário deseja continuar? Infelizmente, + ' Faça a pergunta, se o usuário deseja continuar? Infelizmente, "é sensível a maiúsculas. Console.Write ( "Deseja continuar? (Sim / não )") " O programa pega a variável e imprime e começa de novo. answer = Console.ReadLine - " O comando para a variável para trabalhar seria , neste caso, " sim " + " O comando para a variável para trabalhar seria, neste caso, " sim " Loop While resposta = "yes" End Sub @@ -233,7 +233,7 @@ module Module1 outro Console.WriteLine (" Olá " + nome do usuário) Console.WriteLine (" Você check-out www.learnxinyminutes.com " ) - Console.ReadLine () ' Fins e imprime a declaração acima . + Console.ReadLine () ' Fins e imprime a declaração acima. End If End Sub @@ -242,15 +242,15 @@ module Module1 Console.Title = "Se Declaração / Else | Saiba X em Y Minutes" 'Às vezes é importante ter em conta mais de duas alternativas. 'Às vezes, há um bom número de outros. - 'Quando este for o caso , mais do que uma if seria necessária . - 'Uma instrução if é ótimo para máquinas de venda automática . Quando o usuário digita um código. - ' A1 , A2, A3 , ect para selecionar um item. + 'Quando este for o caso, mais do que uma if seria necessária. + 'Uma instrução if é ótimo para máquinas de venda automática. Quando o usuário digita um código. + ' A1, A2, A3, etc para selecionar um item. 'Todas as opções podem ser combinadas em uma única if. Seleção Dim Valor String = Console.ReadLine ' para a seleção Console.WriteLine (" A1. Para Soda " ) Console.WriteLine (" A2. Para Fanta " ) - Console.WriteLine (" A3 . Para Guaraná" ) + Console.WriteLine (" A3. Para Guaraná" ) Console.WriteLine (" A4. Para Coca Diet" ) Console.ReadLine () Se a seleção = "A1" Então diff --git a/pt-br/whip-pt.html.markdown b/pt-br/whip-pt.html.markdown index 7bdeec25..b11faf28 100644 --- a/pt-br/whip-pt.html.markdown +++ b/pt-br/whip-pt.html.markdown @@ -71,7 +71,7 @@ false (= 1 1) ; => true (equal 2 1) ; => false -; Por exemplo, inigualdade pode ser verificada combinando as funções +; Por exemplo, desigualdade pode ser verificada combinando as funções ;`not` e `equal`. (! (= 2 1)) ; => true diff --git a/pt-br/yaml-pt.html.markdown b/pt-br/yaml-pt.html.markdown index 0b71877e..b2fb2a7d 100644 --- a/pt-br/yaml-pt.html.markdown +++ b/pt-br/yaml-pt.html.markdown @@ -1,7 +1,8 @@ --- language: yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] + - [Suhas SG, 'https://github.com/jargnar'] translators: - ["Rodrigo Russo", "https://github.com/rodrigozrusso"] filename: learnyaml-pt.yaml @@ -11,10 +12,12 @@ lang: pt-br YAML é uma linguagem de serialização de dados projetado para ser diretamente gravável e legível por seres humanos. -É um superconjunto de JSON, com a adição de indentação e quebras de linhas sintaticamente significativas, como Python. Ao contrário de Python, entretanto, YAML não permite o caracter literal tab para identação. +É um superconjunto de JSON, com a adição de identação e quebras de linhas sintaticamente significativas, como Python. Ao contrário de Python, entretanto, YAML não permite o caracter literal tab para identação. ```yaml -# Commentários em YAML são como este. +--- # início do documento + +# Comentários em YAML são como este. ################### # TIPOS ESCALARES # @@ -30,28 +33,32 @@ boleano: true valor_nulo: null chave com espaco: valor # Observe que strings não precisam de aspas. Porém, elas podem ter. -porem: "Uma string, entre aspas." -"Chaves podem estar entre aspas tambem.": "É útil se você quiser colocar um ':' na sua chave." - -# Seqüências de várias linhas podem ser escritos como um 'bloco literal' (utilizando |), +porem: 'Uma string, entre aspas.' +'Chaves podem estar entre aspas tambem.': "É útil se você quiser colocar um ':' na sua chave." +aspas simples: 'possuem ''um'' padrão de escape' +aspas duplas: "possuem vários: \", \0, \t, \u263A, \x0d\x0a == \r\n, e mais." +# Caracteres UTF-8/16/32 precisam ser codificados +Superscript dois: \u00B2 + +# Seqüências de várias linhas podem ser escritas como um 'bloco literal' (utilizando |), # ou em um 'bloco compacto' (utilizando '>'). bloco_literal: | - Todo esse bloco de texto será o valor da chave 'bloco_literal', - preservando a quebra de com linhas. + Todo esse bloco de texto será o valor da chave 'bloco_literal', + preservando a quebra de com linhas. - O literal continua até de-dented, e a primeira identação é - removida. + O literal continua até 'des-indentar', e a primeira identação é + removida. - Quaisquer linhas que são 'mais identadas' mantém o resto de suas identações - - estas linhas serão identadas com 4 espaços. + Quaisquer linhas que são 'mais identadas' mantém o resto de suas identações - + estas linhas serão identadas com 4 espaços. estilo_compacto: > - Todo esse bloco de texto será o valor de 'estilo_compacto', mas esta - vez, todas as novas linhas serão substituídas com espaço simples. + Todo esse bloco de texto será o valor de 'estilo_compacto', mas esta + vez, todas as novas linhas serão substituídas com espaço simples. - Linhas em branco, como acima, são convertidas em um carater de nova linha. + Linhas em branco, como acima, são convertidas em um carater de nova linha. - Linhas 'mais-indentadas' mantém suas novas linhas também - - este texto irá aparecer em duas linhas. + Linhas 'mais-indentadas' mantém suas novas linhas também - + este texto irá aparecer em duas linhas. #################### # TIPOS DE COLEÇÃO # @@ -59,54 +66,85 @@ estilo_compacto: > # Texto aninhado é conseguido através de identação. um_mapa_aninhado: - chave: valor - outra_chave: Outro valor - outro_mapa_aninhado: - ola: ola + chave: valor + outra_chave: Outro valor + outro_mapa_aninhado: + ola: ola # Mapas não tem que ter chaves com string. 0.25: uma chave com valor flutuante -# As chaves podem ser também objetos multi linhas, utilizando ? para indicar o começo de uma chave. +# As chaves podem ser complexas, como sequência de várias linhas +# Utilizando ? seguido por espaço para indicar o começo de uma chave complexa. ? | - Esta é uma chave - que tem várias linhas + Esta é uma chave + que tem várias linhas : e este é o seu valor -# também permite tipos de coleção de chaves, mas muitas linguagens de programação -# vão reclamar. +# YAML também permite o mapeamento entre sequências com a sintaxe chave complexa +# Alguns analisadores de linguagem de programação podem reclamar +# Um exemplo +? - Manchester United + - Real Madrid +: [2001-01-01, 2002-02-02] -# Sequências (equivalente a listas ou arrays) semelhante à isso: +# Sequências (equivalente a listas ou arrays) semelhante a isso: uma_sequencia: - - Item 1 - - Item 2 - - 0.5 # sequencias podem conter tipos diferentes. - - Item 4 - - chave: valor - outra_chave: outro_valor - - - - Esta é uma sequencia - - dentro de outra sequencia + - Item 1 + - Item 2 + - 0.5 # sequências podem conter tipos diferentes. + - Item 4 + - chave: valor + outra_chave: outro_valor + - + - Esta é uma sequência + - dentro de outra sequência + - - - Indicadores de sequência aninhadas + - podem ser recolhidas # Como YAML é um super conjunto de JSON, você também pode escrever mapas JSON de estilo e -# sequencias: +# sequências: mapa_json: {"chave": "valor"} json_seq: [3, 2, 1, "decolar"] +e aspas são opcionais: {chave: [3, 2, 1, decolar]} -########################## -# RECURSOS EXTRA DO YAML # -########################## +########################### +# RECURSOS EXTRAS DO YAML # +########################### # YAML também tem um recurso útil chamado "âncoras", que permitem que você facilmente duplique # conteúdo em seu documento. Ambas estas chaves terão o mesmo valor: -conteudo_ancora: & nome_ancora Essa string irá aparecer como o valor de duas chaves. -outra_ancora: * nome_ancora +conteudo_ancora: &nome_ancora Essa string irá aparecer como o valor de duas chaves. +outra_ancora: *nome_ancora + +# Âncoras podem ser usadas para dubplicar/herdar propriedades +base: &base + name: Todos possuem o mesmo nome + +# O regexp << é chamado Mesclar o Tipo Chave Independente-de-Idioma. É usado para +# indicar que todas as chaves de um ou mais mapas específicos devam ser inseridos +# no mapa atual. + +foo: + <<: *base + idade: 10 + +bar: + <<: *base + idade: 20 + +# foo e bar terão o mesmo nome: Todos possuem o mesmo nome # YAML também tem tags, que você pode usar para declarar explicitamente os tipos. -string_explicita: !! str 0,5 +string_explicita: !!str 0.5 # Alguns analisadores implementam tags específicas de linguagem, como este para Python de # Tipo de número complexo. -numero_complexo_em_python: !! python / complex 1 + 2j +numero_complexo_em_python: !!python/complex 1+2j + +# Podemos utilizar chaves YAML complexas com tags específicas de linguagem +? !!python/tuple [5, 7] +: Fifty Seven +# Seria {(5, 7): 'Fifty Seven'} em Python #################### # YAML TIPOS EXTRA # @@ -114,27 +152,34 @@ numero_complexo_em_python: !! python / complex 1 + 2j # Strings e números não são os únicos que escalares YAML pode entender. # Data e 'data e hora' literais no formato ISO também são analisados. -datetime: 2001-12-15T02: 59: 43.1Z -datetime_com_espacos 2001/12/14: 21: 59: 43.10 -5 -Data: 2002/12/14 +datetime: 2001-12-15T02:59:43.1Z +datetime_com_espaços: 2001-12-14 21:59:43.10 -5 +date: 2002-12-14 -# A tag !!binary indica que a string é na verdade um base64-encoded (condificado) +# A tag !!binary indica que a string é na verdade um base64-encoded (codificado) # representação de um blob binário. gif_file: !!binary | - R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 - OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ - +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC - AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= # YAML também tem um tipo de conjunto, o que se parece com isso: -set: - ? item1 - ? item2 - ? item3 - -# Como Python, são apenas conjuntos de mapas com valors nulos; o acima é equivalente a: -set2: - item1: nulo - item2: nulo - item3: nulo +conjunto: + ? item1 + ? item2 + ? item3 +ou: {item1, item2, item3} + +# Como Python, são apenas conjuntos de mapas com valores nulos; o acima é equivalente a: +conjunto2: + item1: null + item2: null + item3: null + +... # fim do documento ``` +### Mais Recursos + ++ [Site Oficial do YAML](https://yaml.org/) ++ [Validador YAML Online](http://www.yamllint.com/) diff --git a/pt-pt/git-pt.html.markdown b/pt-pt/git-pt.html.markdown index bd0f0fc5..86710a13 100644 --- a/pt-pt/git-pt.html.markdown +++ b/pt-pt/git-pt.html.markdown @@ -411,5 +411,3 @@ $ git rm /pather/to/the/file/HelloWorld.c * [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/) * [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) - -* [GitGuys](http://www.gitguys.com/) diff --git a/pt-pt/kotlin-pt.html.markdown b/pt-pt/kotlin-pt.html.markdown new file mode 100644 index 00000000..47dbb44d --- /dev/null +++ b/pt-pt/kotlin-pt.html.markdown @@ -0,0 +1,473 @@ +--- +language: kotlin +filename: LearnKotlin-pt.kt +lang: pt-pt +contributors: + - ["S Webber", "https://github.com/s-webber"] +translators: + - ["André Martins", "https://github.com/chriptus13"] +--- + +Kotlin é uma linguagem de programação de tipificação estática para a JVM, Android e browser. Ela é 100% interoperável com Java. +[Lê mais aqui.](https://kotlinlang.org/) + +```kotlin +// Comentários de linha começam com // +/* +Comentários de múltiplas linhas são assim. +*/ + +// A palavra-chave "package" funciona da mesma forma que em Java. +package com.learnxinyminutes.kotlin + +/* +O ponto de entrada de um programa em Kotlin é a função chamada "main". +Esta função tem como único parâmetro um array contendo todos os argumentos passados na linha de comandos. +Desde a versão 1.3 que esta pode também ser definida sem parâmetros. +*/ +fun main(args: Array<String>) { + /* + A declaração de variáveis é feita usando "var" ou "val". + Variáveis declaradas com "val" não podem ser redefinidas, já as declaradas com "var" podem. + */ + val fooVal = 10 // não podemos redefinir mais tarde o valor de fooVal para algo diferente + var fooVar = 10 + fooVar = 20 // fooVar pode ser redefinida + + /* + Na maioria dos casos, o Kotlin pode determinar (inferir) o tipo de uma variável, + assim não precisamos de o dizer explicitamente sempre. + Para especificar o tipo explicitamente fazemos assim: + */ + val foo: Int = 7 + + /* + As Strings são representadas de uma forma semelhante ao Java. + O escape é feito com barras invertidas. + */ + val fooString = "A minha String está aqui!" + val barString = "Imprimir numa nova linha?\nSem problemas!" + val bazString = "Adicionar um tab?\tSem problemas!" + println(fooString) + println(barString) + println(bazString) + + /* + Uma raw string é delimitada por aspas triplas ("""). + Raw strings podem conter caracteres de nova linha ou qualquer outro. + */ + val fooRawString = """ +fun helloWorld(val name : String) { + println("Hello, world!") +} +""" + println(fooRawString) + + /* + As strings podem também conter template expressions. + Uma template expression começa com o símbolo do dollar ($). + */ + val fooTemplateString = "$fooString tem ${fooString.length} caracteres" + println(fooTemplateString) // => A minha String está aqui! tem 25 caracteres + + /* + Para que uma variável possa ter o valor de null esta tem de ser + especificada explicitamente como nullable. + Uma variável pode ser marcada como nullable adicionando um ? ao seu tipo. + A variable can be specified as nullable by appending a ? to its type. + Usando o operador ?. podemos facilmente aceder a propriedades de + uma variável nullable, se esta for null o resultado da expressão será também ele null. + Podemos também usar o operador ?: para especificar um valor alternativo + no caso da variavél ser null. + */ + var fooNullable: String? = "abc" + println(fooNullable?.length) // => 3 + println(fooNullable?.length ?: -1) // => 3 + fooNullable = null + println(fooNullable?.length) // => null + println(fooNullable?.length ?: -1) // => -1 + + /* + As funções são declaradas usando a palavra-chave "fun". + Os parâmetros da função são especificados entre parênteses a seguir ao nome da função. + Estes parâmetros podem opcionalmente ter um valor por omissão. + O tipo de retorno da função, se necessário, é especificado após os parâmetros. + */ + fun hello(name: String = "world"): String { + return "Hello, $name!" + } + println(hello("foo")) // => Hello, foo! + println(hello(name = "bar")) // => Hello, bar! + println(hello()) // => Hello, world! + + /* + Para que uma função receba um número variável de parâmetros podemos + marcar um, e apenas um, parâmetro com a palavra-chave "vararg". + */ + fun varargExample(vararg names: Int) { + println("Argument has ${names.size} elements") + } + varargExample() // => A chamada à função tem 0 argumentos + varargExample(1) // => A chamada à função tem 1 argumentos + varargExample(1, 2, 3) // => A chamada à função tem 3 argumentos + + /* + Quando uma função consiste em apenas uma expressão as chavetas podem ser omitidas + O corpo da mesma é especificado após o símbolo de igual (=). + */ + fun odd(x: Int): Boolean = x % 2 == 1 + println(odd(6)) // => false + println(odd(7)) // => true + + // Se o tipo de retorno da função pode ser inferido então não é necessário especificá-lo. + fun even(x: Int) = x % 2 == 0 + println(even(6)) // => true + println(even(7)) // => false + + // As funções podem ter outras funções como parâmetros e/ou como retorno. + fun not(f: (Int) -> Boolean): (Int) -> Boolean { + return {n -> !f.invoke(n)} + } + // O operador :: pode ser usado para referênciar funções existentes. + val notOdd = not(::odd) + val notEven = not(::even) + /* + Expressões lambda podem ser usadas da seguinte forma. + Os lambdas quando passados a outras funções podem estar + fora dos parênteses da chamada, caso sejam o último parâmetro. + */ + val notZero = not {n -> n == 0} + /* + Se o lambda apenas tiver um parâmetro então a sua + declaração pode ser omitida (em conjunto com "->"). + O nome por omissão do parâmetro será "it". + */ + val notPositive = not {it > 0} + for (i in 0..4) { + println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}") + } + + // Para declararmos classes usa-se a palavra-chave "class". + class ExampleClass(val x: Int) { + fun aMethod(y: Int): Int { + return x + y + } + + infix fun infixMemberFunction(y: Int): Int { + return x * y + } + } + /* + Para se instanciar uma classe usamos o constructor. + De notar que em Kotlin não existe a palavra-chave "new" como no Java. + */ + val fooExampleClass = ExampleClass(7) + // Os métodos da classe podem então ser chamados usando o ponto. + println(fooExampleClass.aMethod(4)) // => 11 + /* + Uma função marcada com a palavra-chave "infix" pode ser chamada + usando a notação infixa. + */ + println(fooExampleClass infixMemberFunction 4) // => 28 + + /* + Data classes são uma forma concisa de criar classes que apenas contêm dados. + Neste tipo de classes os métodos "hashCode"/"equals" e "toString" são gerados + automáticamente. + */ + data class DataClassExample (val x: Int, val y: Int, val z: Int) + val fooData = DataClassExample(1, 2, 4) + println(fooData) // => DataClassExample(x=1, y=2, z=4) + + // Instâncias deste tipo de classes têm acesso ao método "copy". + val fooCopy = fooData.copy(y = 100) + println(fooCopy) // => DataClassExample(x=1, y=100, z=4) + + // Os objectos podem ser desconstruídos para variáveis. + val (a, b, c) = fooCopy + println("$a $b $c") // => 1 100 4 + + // desconstrucção dentro de um ciclo "for" + for ((a, b, c) in listOf(fooData)) { + println("$a $b $c") // => 1 2 4 + } + + val mapData = mapOf("a" to 1, "b" to 2) + // Instâncias de Map.Entry podem também ser desconstruídas. + for ((key, value) in mapData) { + println("$key -> $value") + } + + // A função "with" é semelhante ao bloco "with" do JavaScript. + data class MutableDataClassExample (var x: Int, var y: Int, var z: Int) + val fooMutableData = MutableDataClassExample(7, 4, 9) + with (fooMutableData) { + x -= 2 + y += 2 + z-- + } + println(fooMutableData) // => MutableDataClassExample(x=5, y=6, z=8) + + /* + Podemos criar listas usando a função "listOf". + No Kotlin, por padrão, as listas são imútaveis - não podendo + assim adicionar ou remover elementos das mesmas. + */ + val fooList = listOf("a", "b", "c") + println(fooList.size) // => 3 + println(fooList.first()) // => a + println(fooList.last()) // => c + // Os elementos de uma lista podem ser acedidos usando o seu índice. + println(fooList[1]) // => b + + // Listas mútaveis podem ser criadas usando a função "mutableListOf". + val fooMutableList = mutableListOf("a", "b", "c") + fooMutableList.add("d") + println(fooMutableList.last()) // => d + println(fooMutableList.size) // => 4 + + // Podemos criar conjuntos usando a função "setOf". + val fooSet = setOf("a", "b", "c") + println(fooSet.contains("a")) // => true + println(fooSet.contains("z")) // => false + + // Podemos criar mapas usando a função "mapOf" e através da função infixa "to". + val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9) + // Os valores do mapa podem ser acedidos usando a sua chave. + println(fooMap["a"]) // => 8 + + /* + No Kotlin as sequências representam collecções de dados avaliadas de forma lazy. + Podemos cirar uma sequência usando a função "generateSequence". + */ + val fooSequence = generateSequence(1, { it + 1 }) + val x = fooSequence.take(10).toList() + println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + // Um exemplo de uso das sequências para gerar os números de Fibonacci: + fun fibonacciSequence(): Sequence<Long> { + var a = 0L + var b = 1L + + fun next(): Long { + val result = a + b + a = b + b = result + return a + } + + return generateSequence(::next) + } + val y = fibonacciSequence().take(10).toList() + println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + + // O Kotlin fornece funções de ordem superior convenientes para a manipulação de colecções. + val z = (1..9).map {it * 3} + .filter {it < 20} + .groupBy {it % 2 == 0} + .mapKeys {if (it.key) "even" else "odd"} + println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]} + + // Um ciclo "for" pode ser usado com qualquer coisa que forneça um iterador. + for (c in "hello") { + println(c) + } + + // Um ciclo "while" funciona da mesma forma que em outras linguagens. + var ctr = 0 + while (ctr < 5) { + println(ctr) + ctr++ + } + do { + println(ctr) + ctr++ + } while (ctr < 10) + + /* + Um "if" pode ser usado como uma expressão que produz um valor. + Por esta razão o operador ternário não é necessário no Kotlin. + */ + val num = 5 + val message = if (num % 2 == 0) "even" else "odd" + println("$num is $message") // => 5 is odd + + // O bloco "when" pode ser usado como alternativa para cadeias de "if-else if". + val i = 10 + when { + i < 7 -> println("first block") + fooString.startsWith("hello") -> println("second block") + else -> println("else block") + } + + // O "when" pode ser usado como um "switch" do Java. + when (i) { + 0, 21 -> println("0 or 21") + in 1..20 -> println("in the range 1 to 20") + else -> println("none of the above") + } + + // O "when" pode também ser usado como expressão para produzir um valor. + var result = when (i) { + 0, 21 -> "0 or 21" + in 1..20 -> "in the range 1 to 20" + else -> "none of the above" + } + println(result) + + /* + Podemos utilizar o operador "is" para verificar se um objecto é de um certo tipo. + Se um objecto passar a verificação do tipo pode ser usado como sendo desse tipo + sem conversão explicita, sendo isto chamado de smart cast. + */ + fun smartCastExample(x: Any) : Boolean { + if (x is Boolean) { + // x is automatically cast to Boolean + return x + } else if (x is Int) { + // x is automatically cast to Int + return x > 0 + } else if (x is String) { + // x is automatically cast to String + return x.isNotEmpty() + } else { + return false + } + } + println(smartCastExample("Hello, world!")) // => true + println(smartCastExample("")) // => false + println(smartCastExample(5)) // => true + println(smartCastExample(0)) // => false + println(smartCastExample(true)) // => true + + // Os smart casts funcionam também com o bloco "when". + fun smartCastWhenExample(x: Any) = when (x) { + is Boolean -> x + is Int -> x > 0 + is String -> x.isNotEmpty() + else -> false + } + + /* + Extensões são uma forma de adicionar funcionalidade a classes existentes. + Isto é semelhante aos métodos de extensão do C#. + */ + fun String.remove(c: Char): String { + return this.filter {it != c} + } + println("Hello, world!".remove('l')) // => Hello, world! +} + +// Enum classes são o equivalente aos tipos enum do Java. +enum class EnumExample { + A, B, C // As constantes da enumeração são separadas por vírgula. +} +fun printEnum() = println(EnumExample.A) // => A + +/* +Como cada constante é uma instância da classe enum, +estas podem ser inicializadas da seguinte forma: +*/ +enum class EnumExample(val value: Int) { + A(value = 1), + B(value = 2), + C(value = 3) +} +fun printProperty() = println(EnumExample.A.value) // => 1 + +/* +Cada constante de enumerações tem propriedades para +obter o nome e o ordinal (posição) na respectiva classe. +*/ +fun printName() = println(EnumExample.A.name) // => A +fun printPosition() = println(EnumExample.A.ordinal) // => 0 + +/* +A palavra-chave "object" pode ser usada para criar objectos singleton. +Estes não podem ser instânciados, porém podem ser referênciados como uma +única instância através do seu nome. +São semelhantes aos objectos singleton do Scala. +*/ +object ObjectExample { + fun hello(): String { + return "hello" + } + + override fun toString(): String { + return "Hello, it's me, ${ObjectExample::class.simpleName}" + } +} + + +fun useSingletonObject() { + println(ObjectExample.hello()) // => hello + // Em Kotlin o tipo "Any" é a raíz da hierárquia de classes, tal como o tipo "Object" em Java. + val someRef: Any = ObjectExample + println(someRef) // => Hello, it's me, ObjectExample +} + + +/* +O operador !! serve para realizar um assert de not-null. Este converte qualquer +valor nullable para non-null ou lança exceção se o mesmo for null. +*/ +var b: String? = "abc" +val l = b!!.length // lançaria exceção caso "b" fosse null + +// O modificador "operator" permite fazer overload dos operadores +// [Ver lista de operadores](https://kotlinlang.org/docs/operator-overloading.html) +data class Counter(var value: Int) { + // overload para Counter += Int + operator fun plusAssign(increment: Int) { + this.value += increment + } + + // overload para Counter++ e ++Counter + operator fun inc() = Counter(value + 1) + + // overload para Counter + Counter + operator fun plus(other: Counter) = Counter(this.value + other.value) + + // overload para Counter * Counter + operator fun times(other: Counter) = Counter(this.value * other.value) + + // overload para Counter * Int + operator fun times(value: Int) = Counter(this.value * value) + + // overload para Counter in Counter + operator fun contains(other: Counter) = other.value == this.value + + // overload para Counter[Int] = Int + operator fun set(index: Int, value: Int) { + this.value = index + value + } + + // overload para invocação da instância Counter + operator fun invoke() = println("The value of the counter is $value") +} +/* Podemos também dar overload dos operadores através de métodos de extensão */ +// overload para -Counter +operator fun Counter.unaryMinus() = Counter(-this.value) + +fun operatorOverloadingDemo() { + var counter1 = Counter(0) + var counter2 = Counter(5) + counter1 += 7 + println(counter1) // => Counter(value=7) + println(counter1 + counter2) // => Counter(value=12) + println(counter1 * counter2) // => Counter(value=35) + println(counter2 * 2) // => Counter(value=10) + println(counter1 in Counter(5)) // => false + println(counter1 in Counter(7)) // => true + counter1[26] = 10 + println(counter1) // => Counter(value=36) + counter1() // => The value of the counter is 36 + println(-counter2) // => Counter(value=-5) +} +``` + +### Leituras Adicionais + +* [Tutoriais de Kotlin](https://kotlinlang.org/docs/tutorials/) +* [Experimenta Kotlin no browser](https://play.kotlinlang.org/) +* [Recursos adicionais](http://kotlin.link/)
\ No newline at end of file diff --git a/pt-pt/swift-pt.html.markdown b/pt-pt/swift-pt.html.markdown index 6b263942..a8d3e1ab 100644 --- a/pt-pt/swift-pt.html.markdown +++ b/pt-pt/swift-pt.html.markdown @@ -12,7 +12,7 @@ translators: lang: pt-pt --- -Swift é uma linguagem de programação criada pela Apple para o desenvolvimento em iOS e OS X. +Swift é uma linguagem de programação criada pela Apple para o desenvolvimento em iOS e macOS. Desenhada de forma a coexistir com Objective-C e ser mais resiliente contra código errôneo, a linguagem Swift foi introduzida em 2014 na conferência para desenvolvedores WWDC da Apple. Swift usa o compilador LLVM incluido no XCode 6+. diff --git a/pug.html.markdown b/pug.html.markdown index 0187f1e0..21d8db9f 100644 --- a/pug.html.markdown +++ b/pug.html.markdown @@ -158,13 +158,13 @@ case orderStatus //- <p class="warn">Your order is pending</p> //- --INCLUDE-- -//- File path -> "includes/nav.png" +//- File path -> "includes/nav.pug" h1 Company Name nav a(href="index.html") Home a(href="about.html") About Us -//- File path -> "index.png" +//- File path -> "index.pug" html body include includes/nav.pug @@ -183,9 +183,9 @@ style include styles/theme.css //- ---MIXIN--- -mixin basic() +mixin basic div Hello -+basic("Bob") ++basic //- <div>Hello</div> mixin comment(name, comment) @@ -193,7 +193,11 @@ mixin comment(name, comment) span.comment-name= name div.comment-text= comment +comment("Bob", "This is Awesome") -//- <div>Hello</div> +//- + <div> + <span class="comment-name">Bob</span> + <div class="comment-text">This is Awesome</div> + </div> ``` @@ -201,4 +205,4 @@ mixin comment(name, comment) ### Additional Resources - [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) diff --git a/purescript.html.markdown b/purescript.html.markdown index 6b74ac64..1ceaecf9 100644 --- a/purescript.html.markdown +++ b/purescript.html.markdown @@ -1,24 +1,25 @@ --- -language: purescript +language: PureScript filename: purescript.purs contributors: - ["Fredrik Dyrkell", "http://www.lexicallyscoped.com"] - ["Thimoteus", "https://github.com/Thimoteus"] --- -PureScript is a small strongly, statically typed language compiling to Javascript. +PureScript is a small strongly, statically typed language compiling to JavaScript. -* Learn more at [http://www.purescript.org/](http://www.purescript.org/) -* Documentation: [http://pursuit.purescript.org/](http://pursuit.purescript.org/) -* Book: Purescript by Example, [https://leanpub.com/purescript/](https://leanpub.com/purescript/) +* Learn more at [https://www.purescript.org/](https://www.purescript.org/) +* Documentation: [https://pursuit.purescript.org/](https://pursuit.purescript.org/) +* Book: Purescript by Example, [https://book.purescript.org/](https://book.purescript.org/) -All the noncommented lines of code can be run in the PSCI REPL, though some will -require the `--multi-line-mode` flag. +All the noncommented lines of code can be run in the PSCi REPL, though some +will require "paste" mode (`:paste` followed by multiple lines, terminated by +^D). ```haskell -- --- 1. Primitive datatypes that corresponds to their Javascript +-- 1. Primitive datatypes that corresponds to their JavaScript -- equivalents at runtime. import Prelude @@ -39,7 +40,7 @@ import Prelude 3.0 % 2.0 -- 1.0 4.0 % 2.0 -- 0.0 -- Inspect the type of an expression in psci -:t 9.5/2.5 + 4.4 -- Prim.Number +:t 9.5/2.5 + 4.4 -- Number -- Booleans true :: Boolean -- true @@ -58,9 +59,9 @@ compare 3 2 -- GT true && (9 >= 19 || 1 < 2) -- true -- Strings -"Hellow" :: String -- "Hellow" --- Multiline string without newlines, to run in psci use the --multi-line-mode flag -"Hellow\ +"Hello" :: String -- "Hello" +-- Multiline string without newlines, to run in PSCi use "paste" mode. +"Hello\ \orld" -- "Helloworld" -- Multiline string with newlines """Hello @@ -69,26 +70,26 @@ world""" -- "Hello\nworld" "such " <> "amaze" -- "such amaze" -- --- 2. Arrays are Javascript arrays, but must be homogeneous +-- 2. Arrays are JavaScript arrays, but must be homogeneous [1,1,2,3,5,8] :: Array Int -- [1,1,2,3,5,8] [1.2,2.0,3.14] :: Array Number -- [1.2,2.0,3.14] [true, true, false] :: Array Boolean -- [true,true,false] -- [1,2, true, "false"] won't work --- `Cannot unify Prim.Int with Prim.Boolean` +-- `Cannot unify Int with Boolean` + +-- Requires purescript-arrays (Data.Array) -- Cons (prepend) 1 : [2,4,3] -- [1,2,4,3] --- Requires purescript-arrays (Data.Array) -- and purescript-maybe (Data.Maybe) - -- Safe access return Maybe a -head [1,2,3] -- Just (1) -tail [3,2,1] -- Just ([2,1]) -init [1,2,3] -- Just ([1,2]) -last [3,2,1] -- Just (1) +head [1,2,3] -- (Just 1) +tail [3,2,1] -- (Just [2,1]) +init [1,2,3] -- (Just [1,2]) +last [3,2,1] -- (Just 1) -- Array access - indexing -[3,4,5,6,7] !! 2 -- Just (5) +[3,4,5,6,7] !! 2 -- (Just 5) -- Range 1..5 -- [1,2,3,4,5] length [2,2,2] -- 3 @@ -97,31 +98,30 @@ take 3 [5,4,3,2,1] -- [5,4,3] append [1,2,3] [4,5,6] -- [1,2,3,4,5,6] -- --- 3. Records are Javascript objects, with zero or more fields, which +-- 3. Records are JavaScript objects, with zero or more fields, which -- can have different types. --- In psci you have to write `let` in front of the function to get a --- top level binding. -let book = {title: "Foucault's pendulum", author: "Umberto Eco"} +book = {title: "Foucault's pendulum", author: "Umberto Eco"} -- Access properties book.title -- "Foucault's pendulum" -let getTitle b = b.title +getTitle b = b.title -- Works on all records with a title (but doesn't require any other field) getTitle book -- "Foucault's pendulum" getTitle {title: "Weekend in Monaco", artist: "The Rippingtons"} -- "Weekend in Monaco" -- Can use underscores as shorthand _.title book -- "Foucault's pendulum" -- Update a record -let changeTitle b t = b {title = t} +changeTitle b t = b {title = t} getTitle (changeTitle book "Ill nome della rosa") -- "Ill nome della rosa" -- -- 4. Functions --- In psci's multiline mode -let sumOfSquares :: Int -> Int -> Int - sumOfSquares x y = x*x + y*y +-- In PSCi's paste mode +sumOfSquares :: Int -> Int -> Int +sumOfSquares x y = x*x + y*y sumOfSquares 3 4 -- 25 -let myMod x y = x % y + +myMod x y = x % y myMod 3.0 2.0 -- 1.0 -- Infix application of function 3 `mod` 2 -- 1 @@ -131,48 +131,47 @@ myMod 3.0 2.0 -- 1.0 sumOfSquares 3 4 * sumOfSquares 4 5 -- 1025 -- Conditional -let abs' n = if n>=0 then n else -n +abs' n = if n>=0 then n else -n abs' (-3) -- 3 -- Guarded equations -let abs'' n | n >= 0 = n - | otherwise = -n +-- In PSCi's paste mode +abs'' n | n >= 0 = n + | otherwise = -n -- Pattern matching -- Note the type signature, input is a list of numbers. The pattern matching -- destructures and binds the list into parts. --- Requires purescript-lists (Data.List) -let first :: forall a. List a -> a - first (Cons x _) = x -first (toList [3,4,5]) -- 3 -let second :: forall a. List a -> a - second (Cons _ (Cons y _)) = y -second (toList [3,4,5]) -- 4 -let sumTwo :: List Int -> List Int - sumTwo (Cons x (Cons y rest)) = x + y : rest -fromList (sumTwo (toList [2,3,4,5,6])) :: Array Int -- [5,4,5,6] - --- sumTwo doesn't handle when the list is empty or there's only one element in --- which case you get an error. -sumTwo [1] -- Failed pattern match +-- Requires purescript-lists (Data.List) and purescript-maybe (Data.Maybe) +first :: forall a. List a -> Maybe a +first (x : _) = Just x +first Nil = Nothing +first (fromFoldable [3,4,5]) -- (Just 3) + +second :: forall a. List a -> Maybe a +second Nil = Nothing +second (_ : Nil) = Nothing +second (_ : (y : _)) = Just y +second (fromFoldable [3,4,5]) -- (Just 4) -- Complementing patterns to match -- Good ol' Fibonacci -let fib 1 = 1 - fib 2 = 2 - fib x = fib (x-1) + fib (x-2) +fib 1 = 1 +fib 2 = 2 +fib x = fib (x-1) + fib (x-2) fib 10 -- 89 -- Use underscore to match any, where you don't care about the binding name -let isZero 0 = true - isZero _ = false +isZero 0 = true +isZero _ = false +isZero 9 -- false -- Pattern matching on records -let ecoTitle {author = "Umberto Eco", title = t} = Just t - ecoTitle _ = Nothing +ecoTitle {author: "Umberto Eco", title: t} = Just t +ecoTitle _ = Nothing -ecoTitle book -- Just ("Foucault's pendulum") +ecoTitle {title: "Foucault's pendulum", author: "Umberto Eco"} -- (Just "Foucault's pendulum") ecoTitle {title: "The Quantum Thief", author: "Hannu Rajaniemi"} -- Nothing -- ecoTitle requires both field to type check: ecoTitle {title: "The Quantum Thief"} -- Object lacks required property "author" @@ -180,13 +179,13 @@ ecoTitle {title: "The Quantum Thief"} -- Object lacks required property "author" -- Lambda expressions (\x -> x*x) 3 -- 9 (\x y -> x*x + y*y) 4 5 -- 41 -let sqr = \x -> x*x +sqr = \x -> x*x -- Currying -let myAdd x y = x + y -- is equivalent with -let myAdd' = \x -> \y -> x + y -let add3 = myAdd 3 -:t add3 -- Prim.Int -> Prim.Int +myAdd x y = x + y -- is equivalent with +myAdd' = \x -> \y -> x + y +add3 = myAdd 3 +:t add3 -- Int -> Int -- Forward and backward function composition -- drop 3 followed by taking 5 @@ -195,7 +194,7 @@ let add3 = myAdd 3 (drop 3 <<< take 5) (1..20) -- [4,5] -- Operations using higher order functions -let even x = x `mod` 2 == 0 +even x = x `mod` 2 == 0 filter even (1..10) -- [2,4,6,8,10] map (\x -> x + 11) (1..5) -- [12,13,14,15,16] diff --git a/pyqt.html.markdown b/pyqt.html.markdown index 6bdb6488..2b331874 100644 --- a/pyqt.html.markdown +++ b/pyqt.html.markdown @@ -11,25 +11,25 @@ contributors: This is an adaption on the C++ intro to QT by [Aleksey Kholovchuk](https://github.com/vortexxx192 ), some of the code examples should result in the same functionality -this version just having been done using pyqt! +this version just having been done using pyqt! ```python import sys from PyQt4 import QtGui - + def window(): - # Create an application object + # Create an application object app = QtGui.QApplication(sys.argv) # Create a widget where our label will be placed in w = QtGui.QWidget() - # Add a label to the widget + # Add a label to the widget b = QtGui.QLabel(w) - # Set some text for the label + # Set some text for the label b.setText("Hello World!") - # Give some size and placement information + # Give some size and placement information w.setGeometry(100, 100, 200, 50) b.move(50, 20) - # Give our window a nice title + # Give our window a nice title w.setWindowTitle("PyQt") # Have everything display w.show() @@ -41,10 +41,10 @@ if __name__ == '__main__': ``` -In order to get some of the more advanced features in **pyqt** we need to start looking at building additional elements. +In order to get some of the more advanced features in **pyqt** we need to start looking at building additional elements. Here we show how to introduce a dialog popup box, useful for asking the user to confirm a decision or to provide information. -```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_()) - + # This function should create a dialog window with a button # that waits to be clicked and then exits the program def showdialog(): diff --git a/python.html.markdown b/python.html.markdown index 0cc33a80..9d97e64d 100644 --- a/python.html.markdown +++ b/python.html.markdown @@ -1,32 +1,26 @@ --- -language: python +language: Python contributors: - - ["Louie Dinh", "http://ldinh.ca"] - - ["Amin Bandali", "https://aminb.org"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] - ["Andre Polykanine", "https://github.com/Oire"] + - ["Zachary Ferguson", "http://github.com/zfergus2"] - ["evuez", "http://github.com/evuez"] - - ["asyne", "https://github.com/justblah"] - - ["habi", "http://github.com/habi"] - ["Rommel Martinez", "https://ebzzry.io"] + - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"] + - ["caminsha", "https://github.com/caminsha"] + - ["Stanislav Modrak", "https://stanislav.gq"] + - ["John Paul Wohlscheid", "https://gitpi.us"] filename: learnpython.py --- -Python was created by Guido Van Rossum in the early 90s. It is now one of the +Python was created by Guido van Rossum in the early 90s. It is now one of the most popular languages in existence. I fell in love with Python for its syntactic clarity. It's basically executable pseudocode. -Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) -or louiedinh [at] [google's email service] - -Note: This article applies to Python 2.7 specifically, but should be applicable -to Python 2.x. Python 2.7 is reaching end of life and will stop being -maintained in 2020, it is though recommended to start learning Python with -Python 3. For Python 3.x, take a look at the [Python 3 tutorial](http://learnxinyminutes.com/docs/python3/). - -It is also possible to write Python code which is compatible with Python 2.7 -and 3.x at the same time, using Python [`__future__` imports](https://docs.python.org/2/library/__future__.html). `__future__` imports -allow you to write Python 3 code that will run on Python 2, so check out the -Python 3 tutorial. +Note: This article applies to Python 3 specifically. Check out +[here](http://learnxinyminutes.com/docs/pythonlegacy/) if you want to learn the +old Python 2.7 ```python @@ -34,67 +28,87 @@ Python 3 tutorial. """ Multiline strings can be written using three "s, and are often used - as comments + as documentation. """ #################################################### -# 1. Primitive Datatypes and Operators +## 1. Primitive Datatypes and Operators #################################################### # You have numbers 3 # => 3 # Math is what you would expect -1 + 1 # => 2 -8 - 1 # => 7 +1 + 1 # => 2 +8 - 1 # => 7 10 * 2 # => 20 -35 / 5 # => 7 - -# Division is a bit tricky. It is integer division and floors the results -# automatically. -5 / 2 # => 2 - -# To fix division we need to learn about floats. -2.0 # This is a float -11.0 / 4.0 # => 2.75 ahhh...much better +35 / 5 # => 7.0 -# Result of integer division truncated down both for positive and negative. -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too --5 // 3 # => -2 +# Integer division rounds down for both positive and negative numbers. +5 // 3 # => 1 +-5 // 3 # => -2 +5.0 // 3.0 # => 1.0 # works on floats too -5.0 // 3.0 # => -2.0 -# Note that we can also import division module(Section 6 Modules) -# to carry out normal division with just one '/'. -from __future__ import division - -11 / 4 # => 2.75 ...normal division -11 // 4 # => 2 ...floored division +# The result of division is always a float +10.0 / 3 # => 3.3333333333333335 # Modulo operation -7 % 3 # => 1 +7 % 3 # => 1 +# i % j have the same sign as j, unlike C +-7 % 3 # => 2 -# Exponentiation (x to the yth power) -2 ** 4 # => 16 +# Exponentiation (x**y, x to the yth power) +2**3 # => 8 # Enforce precedence with parentheses +1 + 3 * 2 # => 7 (1 + 3) * 2 # => 8 +# Boolean values are primitives (Note: the capitalization) +True # => True +False # => False + +# negate with not +not True # => False +not False # => True + # Boolean Operators # Note "and" and "or" are case-sensitive True and False # => False -False or True # => True +False or True # => True -# Note using Bool operators with ints -0 and 2 # => 0 --5 or 0 # => -5 -0 == False # => True -2 == True # => False -1 == True # => True +# True and False are actually 1 and 0 but with different keywords +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 -# negate with not -not True # => False -not False # => True +# Comparison operators look at the numerical value of True and False +0 == False # => True +2 > True # => True +2 == True # => False +-5 != False # => True + +# None, 0, and empty strings/lists/dicts/tuples/sets all evaluate to False. +# All other values are True +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False +bool(set()) # => False +bool(4) # => True +bool(-6) # => True + +# Using boolean logical operators on ints casts them to booleans for evaluation, +# but their non-cast value is returned. Don't mix up with bool(ints) and bitwise +# and/or (&,|) +bool(0) # => False +bool(2) # => True +0 and 2 # => 0 +bool(-5) # => True +bool(2) # => True +-5 or 0 # => -5 # Equality is == 1 == 1 # => True @@ -110,93 +124,78 @@ not False # => True 2 <= 2 # => True 2 >= 2 # => True -# Comparisons can be chained! +# Seeing whether a value is in a range +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False +# Chaining makes this look nicer 1 < 2 < 3 # => True 2 < 3 < 2 # => False +# (is vs. ==) is checks if two variables refer to the same object, but == checks +# if the objects pointed to have the same values. +a = [1, 2, 3, 4] # Point a at a new list, [1, 2, 3, 4] +b = a # Point b at what a is pointing to +b is a # => True, a and b refer to the same object +b == a # => True, a's and b's objects are equal +b = [1, 2, 3, 4] # Point b at a new list, [1, 2, 3, 4] +b is a # => False, a and b do not refer to the same object +b == a # => True, a's and b's objects are equal + # Strings are created with " or ' "This is a string." 'This is also a string.' -# Strings can be added too! +# Strings can be added too "Hello " + "world!" # => "Hello world!" -# Strings can be added without using '+' -"Hello " "world!" # => "Hello world!" - -# ... or multiplied -"Hello" * 3 # => "HelloHelloHello" +# String literals (but not variables) can be concatenated without using '+' +"Hello " "world!" # => "Hello world!" # A string can be treated like a list of characters -"This is a string"[0] # => 'T' +"Hello world!"[0] # => 'H' # You can find the length of a string len("This is a string") # => 16 -# String formatting with % -# Even though the % string operator will be deprecated on Python 3.1 and removed -# later at some time, it may still be good to know how it works. -x = 'apple' -y = 'lemon' -z = "The items in the basket are %s and %s" % (x, y) - -# A newer way to format strings is the format method. -# This method is the preferred way -"{} is a {}".format("This", "placeholder") -"{0} can be {1}".format("strings", "formatted") -# You can use keywords if you don't want to count. -"{name} wants to eat {food}".format(name="Bob", food="lasagna") +# Since Python 3.6, you can use f-strings or formatted string literals. +name = "Reiko" +f"She said her name is {name}." # => "She said her name is Reiko" +# Any valid Python expression inside these braces is returned to the string. +f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." # None is an object None # => None # Don't use the equality "==" symbol to compare objects to None -# Use "is" instead +# Use "is" instead. This checks for equality of object identity. "etc" is None # => False -None is None # => True - -# The 'is' operator tests for object identity. This isn't -# very useful when dealing with primitive values, but is -# very useful when dealing with objects. - -# Any object can be used in a Boolean context. -# The following values are considered falsey: -# - None -# - zero of any numeric type (e.g., 0, 0L, 0.0, 0j) -# - empty sequences (e.g., '', (), []) -# - empty containers (e.g., {}, set()) -# - instances of user-defined classes meeting certain conditions -# see: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__ -# -# All other values are truthy (using the bool() function on them returns True). -bool(0) # => False -bool("") # => False - +None is None # => True #################################################### -# 2. Variables and Collections +## 2. Variables and Collections #################################################### -# Python has a print statement -print "I'm Python. Nice to meet you!" # => I'm Python. Nice to meet you! +# Python has a print function +print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! + +# By default the print function also prints out a newline at the end. +# Use the optional argument end to change the end string. +print("Hello, World", end="!") # => Hello, World! # Simple way to get input data from console -input_string_var = raw_input( - "Enter some data: ") # Returns the data as a string -input_var = input("Enter some data: ") # Evaluates the data as python code -# Warning: Caution is recommended for input() method usage -# Note: In python 3, input() is deprecated and raw_input() is renamed to input() - -# No need to declare variables before assigning to them. -some_var = 5 # Convention is to use lower_case_with_underscores +input_string_var = input("Enter some data: ") # Returns the data as a string + +# There are no declarations, only assignments. +# Convention in naming variables is snake_case style +some_var = 5 some_var # => 5 # Accessing a previously unassigned variable is an exception. # See Control Flow to learn more about exception handling. -some_other_var # Raises a name error +some_unknown_var # Raises a NameError # if can be used as an expression # Equivalent of C's '?:' ternary operator -"yahoo!" if 3 > 2 else 2 # => "yahoo!" +"yay!" if 0 > 1 else "nay!" # => "nay!" # Lists store sequences li = [] @@ -204,21 +203,17 @@ li = [] other_li = [4, 5, 6] # Add stuff to the end of a list with append -li.append(1) # li is now [1] -li.append(2) # li is now [1, 2] -li.append(4) # li is now [1, 2, 4] -li.append(3) # li is now [1, 2, 4, 3] +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] # Remove from the end with pop -li.pop() # => 3 and li is now [1, 2, 4] +li.pop() # => 3 and li is now [1, 2, 4] # Let's put it back -li.append(3) # li is now [1, 2, 4, 3] again. +li.append(3) # li is now [1, 2, 4, 3] again. # Access a list like you would any array -li[0] # => 1 -# Assign new values to indexes that have already been initialized with = -li[0] = 42 -li[0] # => 42 -li[0] = 1 # Note: setting it back to the original value +li[0] # => 1 # Look at the last element li[-1] # => 3 @@ -226,39 +221,39 @@ li[-1] # => 3 li[4] # Raises an IndexError # You can look at ranges with slice syntax. +# The start index is included, the end index is not # (It's a closed/open range for you mathy types.) -li[1:3] # => [2, 4] -# Omit the beginning -li[2:] # => [4, 3] -# Omit the end -li[:3] # => [1, 2, 4] -# Select every second entry -li[::2] # =>[1, 4] -# Reverse a copy of the list -li[::-1] # => [3, 4, 2, 1] +li[1:3] # Return list from index 1 to 3 => [2, 4] +li[2:] # Return list starting from index 2 => [4, 3] +li[:3] # Return list from beginning until index 3 => [1, 2, 4] +li[::2] # Return list selecting elements with a step size of 2 => [1, 4] +li[::-1] # Return list in reverse order => [3, 4, 2, 1] # Use any combination of these to make advanced slices # li[start:end:step] +# Make a one layer deep copy using slices +li2 = li[:] # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false. + # Remove arbitrary elements from a list with "del" del li[2] # li is now [1, 2, 3] -# You can add lists -li + other_li # => [1, 2, 3, 4, 5, 6] -# Note: values for li and for other_li are not modified. - -# Concatenate lists with "extend()" -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] - # Remove first occurrence of a value -li.remove(2) # li is now [1, 3, 4, 5, 6] +li.remove(2) # li is now [1, 3] li.remove(2) # Raises a ValueError as 2 is not in the list # Insert an element at a specific index -li.insert(1, 2) # li is now [1, 2, 3, 4, 5, 6] again +li.insert(1, 2) # li is now [1, 2, 3] again -# Get the index of the first item found +# Get the index of the first item found matching the argument li.index(2) # => 1 -li.index(7) # Raises a ValueError as 7 is not in the list +li.index(4) # Raises a ValueError as 4 is not in the list + +# You can add lists +# Note: values for li and for other_li are not modified. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Concatenate lists with "extend()" +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] # Check for existence in a list with "in" 1 in li # => True @@ -266,82 +261,109 @@ li.index(7) # Raises a ValueError as 7 is not in the list # Examine the length with "len()" len(li) # => 6 + # Tuples are like lists but are immutable. tup = (1, 2, 3) -tup[0] # => 1 +tup[0] # => 1 tup[0] = 3 # Raises a TypeError -# You can do all those list thingies on tuples too -len(tup) # => 3 +# Note that a tuple of length one has to have a comma after the last element but +# tuples of other lengths, even zero, do not. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# You can do most of the list operations on tuples too +len(tup) # => 3 tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True +tup[:2] # => (1, 2) +2 in tup # => True # You can unpack tuples (or lists) into variables a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 -d, e, f = 4, 5, 6 # you can leave out the parentheses +# You can also do extended unpacking +a, *b, c = (1, 2, 3, 4) # a is now 1, b is now [2, 3] and c is now 4 # Tuples are created by default if you leave out the parentheses -g = 4, 5, 6 # => (4, 5, 6) +d, e, f = 4, 5, 6 # tuple 4, 5, 6 is unpacked into variables d, e and f +# respectively such that d = 4, e = 5 and f = 6 # Now look how easy it is to swap two values e, d = d, e # d is now 5 and e is now 4 -# Dictionaries store mappings + +# Dictionaries store mappings from keys to values empty_dict = {} # Here is a prefilled dictionary filled_dict = {"one": 1, "two": 2, "three": 3} +# Note keys for dictionaries have to be immutable types. This is to ensure that +# the key can be converted to a constant hash value for quick look-ups. +# Immutable types include ints, floats, strings, tuples. +invalid_dict = {[1,2,3]: "123"} # => Yield a TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Values can be of any type, however. + # Look up values with [] filled_dict["one"] # => 1 -# Get all keys as a list with "keys()" -filled_dict.keys() # => ["three", "two", "one"] -# Note - Dictionary key ordering is not guaranteed. -# Your results might not match this exactly. +# Get all keys as an iterable with "keys()". We need to wrap the call in list() +# to turn it into a list. We'll talk about those later. Note - for Python +# versions <3.7, dictionary key ordering is not guaranteed. Your results might +# not match the example below exactly. However, as of Python 3.7, dictionary +# items maintain the order at which they are inserted into the dictionary. +list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+ -# Get all values as a list with "values()" -filled_dict.values() # => [3, 2, 1] -# Note - Same as above regarding key ordering. -# Get all key-value pairs as a list of tuples with "items()" -filled_dict.items() # => [("one", 1), ("two", 2), ("three", 3)] +# Get all values as an iterable with "values()". Once again we need to wrap it +# in list() to get it out of the iterable. Note - Same as above regarding key +# ordering. +list(filled_dict.values()) # => [3, 2, 1] in Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+ # Check for existence of keys in a dictionary with "in" "one" in filled_dict # => True -1 in filled_dict # => False +1 in filled_dict # => False # Looking up a non-existing key is a KeyError filled_dict["four"] # KeyError # Use "get()" method to avoid the KeyError -filled_dict.get("one") # => 1 -filled_dict.get("four") # => None +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None # The get method supports a default argument when the value is missing -filled_dict.get("one", 4) # => 1 +filled_dict.get("one", 4) # => 1 filled_dict.get("four", 4) # => 4 -# note that filled_dict.get("four") is still => None -# (get doesn't set the value in the dictionary) - -# set the value of a key with a syntax similar to lists -filled_dict["four"] = 4 # now, filled_dict["four"] => 4 # "setdefault()" inserts into a dictionary only if the given key isn't present filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 -# You can declare sets (which are like unordered lists that cannot contain -# duplicate values) using the set object. -empty_set = set() -# Initialize a "set()" with a bunch of values -some_set = set([1, 2, 2, 3, 4]) # some_set is now set([1, 2, 3, 4]) +# Adding to a dictionary +filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4 # another way to add to dict + +# Remove keys from a dictionary with del +del filled_dict["one"] # Removes the key "one" from filled dict + +# From Python 3.5 you can also use the additional unpacking options +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + -# order is not guaranteed, even though it may sometimes look sorted -another_set = set([4, 3, 2, 2, 1]) # another_set is now set([1, 2, 3, 4]) -# Since Python 2.7, {} can be used to declare a set -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# Sets store ... well sets +empty_set = set() +# Initialize a set with a bunch of values. +some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} + +# Similar to keys of a dictionary, elements of a set have to be immutable. +invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Add more items to a set +# Add one more item to the set +filled_set = some_set filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} +# Sets do not have duplicate elements +filled_set.add(5) # it remains as before {1, 2, 3, 4, 5} # Do set intersection with & other_set = {3, 4, 5, 6} @@ -357,37 +379,37 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6} {1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} # Check if set on the left is a superset of set on the right -{1, 2} >= {1, 2, 3} # => False +{1, 2} >= {1, 2, 3} # => False # Check if set on the left is a subset of set on the right -{1, 2} <= {1, 2, 3} # => True +{1, 2} <= {1, 2, 3} # => True # Check for existence in a set with in -2 in filled_set # => True +2 in filled_set # => True 10 in filled_set # => False -10 not in filled_set # => True -# Check data type of variable -type(li) # => list -type(filled_dict) # => dict -type(5) # => int +# Make a one layer deep copy +filled_set = some_set.copy() # filled_set is {1, 2, 3, 4, 5} +filled_set is some_set # => False #################################################### -# 3. Control Flow +## 3. Control Flow and Iterables #################################################### # Let's just make a variable some_var = 5 -# Here is an if statement. Indentation is significant in python! -# prints "some_var is smaller than 10" +# Here is an if statement. Indentation is significant in Python! +# Convention is to use four spaces, not tabs. +# This prints "some_var is smaller than 10" if some_var > 10: - print "some_var is totally bigger than 10." -elif some_var < 10: # This elif clause is optional. - print "some_var is smaller than 10." -else: # This is optional too. - print "some_var is indeed 10." + print("some_var is totally bigger than 10.") +elif some_var < 10: # This elif clause is optional. + print("some_var is smaller than 10.") +else: # This is optional too. + print("some_var is indeed 10.") + """ For loops iterate over lists @@ -397,12 +419,12 @@ prints: mouse is a mammal """ for animal in ["dog", "cat", "mouse"]: - # You can use {0} to interpolate formatted strings. (See above.) - print "{0} is a mammal".format(animal) + # You can use format() to interpolate formatted strings + print("{} is a mammal".format(animal)) """ -"range(number)" returns a list of numbers -from zero to the given number +"range(number)" returns an iterable of numbers +from zero up to (but excluding) the given number prints: 0 1 @@ -410,10 +432,10 @@ prints: 3 """ for i in range(4): - print i + print(i) """ -"range(lower, upper)" returns a list of numbers +"range(lower, upper)" returns an iterable of numbers from the lower number to the upper number prints: 4 @@ -422,7 +444,28 @@ prints: 7 """ for i in range(4, 8): - print i + print(i) + +""" +"range(lower, upper, step)" returns an iterable of numbers +from the lower number to the upper number, while incrementing +by step. If step is not indicated, the default value is 1. +prints: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) + +""" +Loop over a list to retrieve both the index and the value of each list item: + 0 dog + 1 cat + 2 mouse +""" +animals = ["dog", "cat", "mouse"] +for i, value in enumerate(animals): + print(i, value) """ While loops go until a condition is no longer met. @@ -434,72 +477,125 @@ prints: """ x = 0 while x < 4: - print x + print(x) x += 1 # Shorthand for x = x + 1 # Handle exceptions with a try/except block - -# Works on Python 2.6 and up: try: # Use "raise" to raise an error raise IndexError("This is an index error") except IndexError as e: - pass # Pass is just a no-op. Usually you would do recovery here. + pass # Refrain from this, provide a recovery (next example). except (TypeError, NameError): - pass # Multiple exceptions can be handled together, if required. -else: # Optional clause to the try/except block. Must follow all except blocks - print "All good!" # Runs only if the code in try raises no exceptions -finally: # Execute under all circumstances - print "We can clean up resources here" + pass # Multiple exceptions can be processed jointly. +else: # Optional clause to the try/except block. Must follow + # all except blocks. + print("All good!") # Runs only if the code in try raises no exceptions +finally: # Execute under all circumstances + print("We can clean up resources here") # Instead of try/finally to cleanup resources you can use a with statement with open("myfile.txt") as f: for line in f: - print line + print(line) + +# Writing to a file +contents = {"aa": 12, "bb": 21} +with open("myfile1.txt", "w") as file: + file.write(str(contents)) # writes a string to a file + +import json +with open("myfile2.txt", "w") as file: + file.write(json.dumps(contents)) # writes an object to a file + +# Reading from a file +with open('myfile1.txt', "r") as file: + contents = file.read() # reads a string from a file +print(contents) +# print: {"aa": 12, "bb": 21} + +with open('myfile2.txt', "r") as file: + contents = json.load(file) # reads a json object from a file +print(contents) +# print: {"aa": 12, "bb": 21} + + +# Python offers a fundamental abstraction called the Iterable. +# An iterable is an object that can be treated as a sequence. +# The object returned by the range function, is an iterable. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['one', 'two', 'three']). This is an object + # that implements our Iterable interface. + +# We can loop over it. +for i in our_iterable: + print(i) # Prints one, two, three + +# However we cannot address elements by index. +our_iterable[1] # Raises a TypeError + +# An iterable is an object that knows how to create an iterator. +our_iterator = iter(our_iterable) + +# Our iterator is an object that can remember the state as we traverse through +# it. We get the next object with "next()". +next(our_iterator) # => "one" + +# It maintains state as we iterate. +next(our_iterator) # => "two" +next(our_iterator) # => "three" + +# After the iterator has returned all of its data, it raises a +# StopIteration exception +next(our_iterator) # Raises StopIteration + +# We can also loop over it, in fact, "for" does this implicitly! +our_iterator = iter(our_iterable) +for i in our_iterator: + print(i) # Prints one, two, three + +# You can grab all the elements of an iterable or iterator by call of list(). +list(our_iterable) # => Returns ["one", "two", "three"] +list(our_iterator) # => Returns [] because state is saved #################################################### -# 4. Functions +## 4. Functions #################################################### # Use "def" to create new functions def add(x, y): - print "x is {0} and y is {1}".format(x, y) + print("x is {} and y is {}".format(x, y)) return x + y # Return values with a return statement - # Calling functions with parameters add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 # Another way to call functions is with keyword arguments add(y=6, x=5) # Keyword arguments can arrive in any order. - # You can define functions that take a variable number of -# positional args, which will be interpreted as a tuple by using * +# positional arguments def varargs(*args): return args - varargs(1, 2, 3) # => (1, 2, 3) - # You can define functions that take a variable number of -# keyword args, as well, which will be interpreted as a dict by using ** +# keyword arguments, as well def keyword_args(**kwargs): return kwargs - # Let's call it to see what happens keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} # You can do both at once, if you like def all_the_args(*args, **kwargs): - print args - print kwargs - - + print(args) + print(kwargs) """ all_the_args(1, 2, a=3, b=4) prints: (1, 2) @@ -507,96 +603,163 @@ all_the_args(1, 2, a=3, b=4) prints: """ # When calling functions, you can do the opposite of args/kwargs! -# Use * to expand positional args and use ** to expand keyword args. +# Use * to expand args (tuples) and use ** to expand kwargs (dictionaries). args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalent to all_the_args(1, 2, 3, 4) -all_the_args(**kwargs) # equivalent to all_the_args(a=3, b=4) -all_the_args(*args, **kwargs) # equivalent to all_the_args(1, 2, 3, 4, a=3, b=4) - +all_the_args(*args) # equivalent: all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent: all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent: all_the_args(1, 2, 3, 4, a=3, b=4) -# you can pass args and kwargs along to other functions that take args/kwargs -# by expanding them with * and ** respectively -def pass_all_the_args(*args, **kwargs): - all_the_args(*args, **kwargs) - print varargs(*args) - print keyword_args(**kwargs) +# Returning multiple values (with tuple assignments) +def swap(x, y): + return y, x # Return multiple values as a tuple without the parenthesis. + # (Note: parenthesis have been excluded but can be included) +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Again the use of parenthesis is optional. -# Function Scope +# global scope x = 5 - def set_x(num): - # Local var x not the same as global variable x - x = num # => 43 - print x # => 43 - + # local scope begins here + # local var x not the same as global var x + x = num # => 43 + print(x) # => 43 def set_global_x(num): + # global indicates that particular var lives in the global scope global x - print x # => 5 - x = num # global var x is now set to 6 - print x # => 6 - + print(x) # => 5 + x = num # global var x is now set to 6 + print(x) # => 6 set_x(43) set_global_x(6) +""" +prints: + 43 + 5 + 6 +""" # Python has first class functions def create_adder(x): def adder(y): return x + y - return adder - add_10 = create_adder(10) -add_10(3) # => 13 +add_10(3) # => 13 + +# Closures in nested functions: +# We can use the nonlocal keyword to work with variables in nested scope which shouldn't be declared in the inner functions. +def create_avg(): + total = 0 + count = 0 + def avg(n): + nonlocal total, count + total += n + count += 1 + return total/count + return avg +avg = create_avg() +avg(3) # => 3.0 +avg(5) # (3+5)/2 => 4.0 +avg(7) # (8+7)/3 => 5.0 # There are also anonymous functions -(lambda x: x > 2)(3) # => True +(lambda x: x > 2)(3) # => True (lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 # There are built-in higher order functions -map(add_10, [1, 2, 3]) # => [11, 12, 13] -map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] # We can use list comprehensions for nice maps and filters -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +# List comprehension stores the output as a list (which itself may be nested). +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] # You can construct set and dict comprehensions as well. -{x for x in 'abcddeef' if x in 'abc'} # => {'a', 'b', 'c'} -{x: x ** 2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} #################################################### -# 5. Classes +## 5. Modules #################################################### -# We subclass from object to get a class. -class Human(object): +# You can import modules +import math +print(math.sqrt(16)) # => 4.0 + +# You can get specific functions from a module +from math import ceil, floor +print(ceil(3.7)) # => 4 +print(floor(3.7)) # => 3 + +# You can import all functions from a module. +# Warning: this is not recommended +from math import * + +# You can shorten module names +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Python modules are just ordinary Python files. You +# can write your own, and import them. The name of the +# module is the same as the name of the file. + +# You can find out which functions and attributes +# are defined in a module. +import math +dir(math) + +# If you have a Python script named math.py in the same +# folder as your current script, the file math.py will +# be loaded instead of the built-in Python module. +# This happens because the local folder has priority +# over Python's built-in libraries. + + +#################################################### +## 6. Classes +#################################################### + +# We use the "class" statement to create a class +class Human: + # A class attribute. It is shared by all instances of this class species = "H. sapiens" # Basic initializer, this is called when this class is instantiated. # Note that the double leading and trailing underscores denote objects - # or attributes that are used by python but that live in user-controlled - # namespaces. You should not invent such names on your own. + # or attributes that are used by Python but that live in user-controlled + # namespaces. Methods(or objects or attributes) like: __init__, __str__, + # __repr__ etc. are called special methods (or sometimes called dunder + # methods). You should not invent such names on your own. def __init__(self, name): # Assign the argument to the instance's name attribute self.name = name # Initialize property - self.age = 0 + self._age = 0 # the leading underscore indicates the "age" property is + # intended to be used internally + # do not rely on this to be enforced: it's a hint to other devs # An instance method. All methods take "self" as the first argument def say(self, msg): - return "{0}: {1}".format(self.name, msg) + print("{name}: {message}".format(name=self.name, message=msg)) + + # Another instance method + def sing(self): + return 'yo... yo... microphone check... one two... one two...' # A class method is shared among all instances # They are called with the calling class as the first argument @@ -610,8 +773,8 @@ class Human(object): return "*grunt*" # A property is just like a getter. - # It turns the method age() into an read-only attribute - # of the same name. + # It turns the method age() into a read-only attribute of the same name. + # There's no need to write trivial getters and setters in Python, though. @property def age(self): return self._age @@ -627,201 +790,326 @@ class Human(object): del self._age -# Instantiate a class -i = Human(name="Ian") -print i.say("hi") # prints out "Ian: hi" +# When a Python interpreter reads a source file it executes all its code. +# This __name__ check makes sure this code block is only executed when this +# module is the main program. +if __name__ == '__main__': + # Instantiate a class + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i and j are instances of type Human; i.e., they are Human objects. + + # Call our class method + i.say(i.get_species()) # "Ian: H. sapiens" + # Change the shared attribute + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # Call the static method + print(Human.grunt()) # => "*grunt*" + + # Static methods can be called by instances too + print(i.grunt()) # => "*grunt*" + + # Update the property for this instance + i.age = 42 + # Get the property + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # Delete the property + del i.age + # i.age # => this would raise an AttributeError -j = Human("Joel") -print j.say("hello") # prints out "Joel: hello" -# Call our class method -i.get_species() # => "H. sapiens" +#################################################### +## 6.1 Inheritance +#################################################### -# Change the shared attribute -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" +# Inheritance allows new child classes to be defined that inherit methods and +# variables from their parent class. -# Call the static method -Human.grunt() # => "*grunt*" +# Using the Human class defined above as the base or parent class, we can +# define a child class, Superhero, which inherits the class variables like +# "species", "name", and "age", as well as methods, like "sing" and "grunt" +# from the Human class, but can also have its own unique properties. -# Update the property -i.age = 42 +# To take advantage of modularization by file you could place the classes above +# in their own files, say, human.py -# Get the property -i.age # => 42 +# To import functions from other files use the following format +# from "filename-without-extension" import "function-or-class" -# Delete the property -del i.age -i.age # => raises an AttributeError +from human import Human -#################################################### -# 6. Modules -#################################################### -# You can import modules -import math +# Specify the parent class(es) as parameters to the class definition +class Superhero(Human): -print math.sqrt(16) # => 4.0 + # If the child class should inherit all of the parent's definitions without + # any modifications, you can just use the "pass" keyword (and nothing else) + # but in this case it is commented out to allow for a unique child class: + # pass -# You can get specific functions from a module -from math import ceil, floor + # Child classes can override their parents' attributes + species = 'Superhuman' -print ceil(3.7) # => 4.0 -print floor(3.7) # => 3.0 + # Children automatically inherit their parent class's constructor including + # its arguments, but can also define additional arguments or definitions + # and override its methods such as the class constructor. + # This constructor inherits the "name" argument from the "Human" class and + # adds the "superpower" and "movie" arguments: + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): -# You can import all functions from a module. -# Warning: this is not recommended -from math import * + # add additional class attributes: + self.fictional = True + self.movie = movie + # be aware of mutable default values, since defaults are shared + self.superpowers = superpowers -# You can shorten module names -import math as m + # The "super" function lets you access the parent class's methods + # that are overridden by the child, in this case, the __init__ method. + # This calls the parent class constructor: + super().__init__(name) -math.sqrt(16) == m.sqrt(16) # => True -# you can also test that the functions are equivalent -from math import sqrt + # override the sing method + def sing(self): + return 'Dun, dun, DUN!' -math.sqrt == m.sqrt == sqrt # => True + # add an additional instance method + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) -# Python modules are just ordinary python files. You -# can write your own, and import them. The name of the -# module is the same as the name of the file. -# You can find out which functions and attributes -# defines a module. -import math +if __name__ == '__main__': + sup = Superhero(name="Tick") -dir(math) + # Instance type checks + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + # Get the "Method Resolution Order" used by both getattr() and super() + # (the order in which classes are searched for an attribute or method) + # This attribute is dynamic and can be updated + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) -# If you have a Python script named math.py in the same -# folder as your current script, the file math.py will -# be loaded instead of the built-in Python module. -# This happens because the local folder has priority -# over Python's built-in libraries. + # Calls parent method but uses its own class attribute + print(sup.get_species()) # => Superhuman + # Calls overridden method + print(sup.sing()) # => Dun, dun, DUN! + + # Calls method from Human + sup.say('Spoon') # => Tick: Spoon + + # Call method that exists only in Superhero + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! + + # Inherited class attribute + sup.age = 31 + print(sup.age) # => 31 + + # Attribute that only exists within Superhero + print('Am I Oscar eligible? ' + str(sup.movie)) #################################################### -# 7. Advanced +## 6.2 Multiple Inheritance #################################################### -# Generators -# A generator "generates" values as they are requested instead of storing -# everything up front +# Another class definition +# bat.py +class Bat: -# The following method (*NOT* a generator) will double all values and store it -# in `double_arr`. For large size of iterables, that might get huge! -def double_numbers(iterable): - double_arr = [] - for i in iterable: - double_arr.append(i + i) - return double_arr + species = 'Baty' + def __init__(self, can_fly=True): + self.fly = can_fly -# Running the following would mean we'll double all values first and return all -# of them back to be checked by our condition -for value in double_numbers(range(1000000)): # `test_non_generator` - print value - if value > 5: - break + # This class also has a say method + def say(self, msg): + msg = '... ... ...' + return msg + + # And its own method as well + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + + +# And yet another class definition that inherits from Superhero and Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Define Batman as a child that inherits from both Superhero and Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # Typically to inherit attributes you have to call super: + # super(Batman, self).__init__(*args, **kwargs) + # However we are dealing with multiple inheritance here, and super() + # only works with the next base class in the MRO list. + # So instead we explicitly call __init__ for all ancestors. + # The use of *args and **kwargs allows for a clean way to pass + # arguments, with each parent "peeling a layer of the onion". + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # override the value for the name attribute + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # The Method Resolution Order + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # Calls parent method but uses its own class attribute + print(sup.get_species()) # => Superhuman + + # Calls overridden method + print(sup.sing()) # => nan nan nan nan nan batman! + + # Calls method from Human, because inheritance order matters + sup.say('I agree') # => Sad Affleck: I agree + + # Call method that exists only in 2nd ancestor + print(sup.sonar()) # => ))) ... ((( + + # Inherited class attribute + sup.age = 100 + print(sup.age) # => 100 + + # Inherited attribute from 2nd ancestor whose default value was overridden. + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False -# We could instead use a generator to "generate" the doubled value as the item -# is being requested -def double_numbers_generator(iterable): + +#################################################### +## 7. Advanced +#################################################### + +# Generators help you make lazy code. +def double_numbers(iterable): for i in iterable: yield i + i - -# Running the same code as before, but with a generator, now allows us to iterate -# over the values and doubling them one by one as they are being consumed by -# our logic. Hence as soon as we see a value > 5, we break out of the -# loop and don't need to double most of the values sent in (MUCH FASTER!) -for value in double_numbers_generator(xrange(1000000)): # `test_generator` - print value - if value > 5: +# Generators are memory-efficient because they only load the data needed to +# process the next value in the iterable. This allows them to perform +# operations on otherwise prohibitively large value ranges. +# NOTE: `range` replaces `xrange` in Python 3. +for i in double_numbers(range(1, 900000000)): # `range` is a generator. + print(i) + if i >= 30: break -# BTW: did you notice the use of `range` in `test_non_generator` and `xrange` in `test_generator`? -# Just as `double_numbers_generator` is the generator version of `double_numbers` -# We have `xrange` as the generator version of `range` -# `range` would return back and array with 1000000 values for us to use -# `xrange` would generate 1000000 values for us as we request / iterate over those items - # Just as you can create a list comprehension, you can create generator # comprehensions as well. -values = (-x for x in [1, 2, 3, 4, 5]) +values = (-x for x in [1,2,3,4,5]) for x in values: print(x) # prints -1 -2 -3 -4 -5 to console/terminal # You can also cast a generator comprehension directly to a list. -values = (-x for x in [1, 2, 3, 4, 5]) +values = (-x for x in [1,2,3,4,5]) gen_to_list = list(values) print(gen_to_list) # => [-1, -2, -3, -4, -5] -# Decorators -# A decorator is a higher order function, which accepts and returns a function. -# Simple usage example – add_apples decorator will add 'Apple' element into -# fruits list returned by get_fruits target function. -def add_apples(func): - def get_fruits(): - fruits = func() - fruits.append('Apple') - return fruits - return get_fruits - -@add_apples -def get_fruits(): - return ['Banana', 'Mango', 'Orange'] - -# Prints out the list of fruits with 'Apple' element in it: -# Banana, Mango, Orange, Apple -print ', '.join(get_fruits()) - -# in this example beg wraps say -# Beg will call say. If say_please is True then it will change the returned -# message -from functools import wraps +# Decorators are a form of syntactic sugar. +# They make code easier to read while accomplishing clunky syntax. -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Please! I am poor :(") - return msg +# Wrappers are one type of decorator. +# They're really useful for adding logging to existing functions without needing to modify them. +def log_function(func): + def wrapper(*args, **kwargs): + print("Entering function", func.__name__) + result = func(*args, **kwargs) + print("Exiting function", func.__name__) + return result return wrapper +@log_function # equivalent: +def my_function(x,y): # def my_function(x,y): + return x+y # return x+y + # my_function = log_function(my_function) +# The decorator @log_function tells us as we begin reading the function definition +# for my_function that this function will be wrapped with log_function. +# When function definitions are long, it can be hard to parse the non-decorated +# assignment at the end of the definition. -@beg -def say(say_please=False): - msg = "Can you buy me a beer?" - return msg, say_please +my_function(1,2) # => "Entering function my_function" + # => "3" + # => "Exiting function my_function" +# But there's a problem. +# What happens if we try to get some information about my_function? -print say() # Can you buy me a beer? -print say(say_please=True) # Can you buy me a beer? Please! I am poor :( -``` +print(my_function.__name__) # => 'wrapper' +print(my_function.__code__.co_argcount) # => 0. The argcount is 0 because both arguments in wrapper()'s signature are optional. -## Ready For More? +# Because our decorator is equivalent to my_function = log_function(my_function) +# we've replaced information about my_function with information from wrapper + +# Fix this using functools + +from functools import wraps + +def log_function(func): + @wraps(func) # this ensures docstring, function name, arguments list, etc. are all copied + # to the wrapped function - instead of being replaced with wrapper's info + def wrapper(*args, **kwargs): + print("Entering function", func.__name__) + result = func(*args, **kwargs) + print("Exiting function", func.__name__) + return result + return wrapper + +@log_function +def my_function(x,y): + return x+y + +my_function(1,2) # => "Entering function my_function" + # => "3" + # => "Exiting function my_function" + +print(my_function.__name__) # => 'my_function' +print(my_function.__code__.co_argcount) # => 2 + +``` ### Free Online * [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [The Official Docs](https://docs.python.org/3/) +* [Hitchhiker's Guide to Python](https://docs.python-guide.org/en/latest/) +* [Python Course](https://www.python-course.eu) +* [Free Interactive Python Course](http://www.Kikodo.io) * [First Steps With Python](https://realpython.com/learn/python-first-steps/) -* [LearnPython](http://www.learnpython.org/) -* [Fullstack Python](https://www.fullstackpython.com/) - -### Dead Tree - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](https://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](https://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](https://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](https://nbviewer.jupyter.org/gist/anonymous/5924718) +* [Python Tutorial for Intermediates](https://pythonbasics.org/) +* [Build a Desktop App with Python](https://pythonpyqt.com/) diff --git a/python3.html.markdown b/python3.html.markdown deleted file mode 100644 index 430927a9..00000000 --- a/python3.html.markdown +++ /dev/null @@ -1,1047 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] - - ["Steven Basart", "http://github.com/xksteven"] - - ["Andre Polykanine", "https://github.com/Oire"] - - ["Zachary Ferguson", "http://github.com/zfergus2"] - - ["evuez", "http://github.com/evuez"] - - ["Rommel Martinez", "https://ebzzry.io"] - - ["Roberto Fernandez Diaz", "https://github.com/robertofd1995"] -filename: learnpython3.py ---- - -Python was created by Guido van Rossum in the early 90s. It is now one of the most popular -languages in existence. I fell in love with Python for its syntactic clarity. It's basically -executable pseudocode. - -Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) or louiedinh [at] [google's email service] - -Note: This article applies to Python 3 specifically. Check out [here](http://learnxinyminutes.com/docs/python/) if you want to learn the old Python 2.7 - -```python - -# Single line comments start with a number symbol. - -""" Multiline strings can be written - using three "s, and are often used - as documentation. -""" - -#################################################### -## 1. Primitive Datatypes and Operators -#################################################### - -# You have numbers -3 # => 3 - -# Math is what you would expect -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 -35 / 5 # => 7.0 - -# Integer division rounds down for both positive and negative numbers. -5 // 3 # => 1 --5 // 3 # => -2 -5.0 // 3.0 # => 1.0 # works on floats too --5.0 // 3.0 # => -2.0 - -# The result of division is always a float -10.0 / 3 # => 3.3333333333333335 - -# Modulo operation -7 % 3 # => 1 - -# Exponentiation (x**y, x to the yth power) -2**3 # => 8 - -# Enforce precedence with parentheses -(1 + 3) * 2 # => 8 - -# Boolean values are primitives (Note: the capitalization) -True -False - -# negate with not -not True # => False -not False # => True - -# Boolean Operators -# Note "and" and "or" are case-sensitive -True and False # => False -False or True # => True - -# True and False are actually 1 and 0 but with different keywords -True + True # => 2 -True * 8 # => 8 -False - 5 # => -5 - -# Comparison operators look at the numerical value of True and False -0 == False # => True -1 == True # => True -2 == True # => False --5 != False # => True - -# Using boolean logical operators on ints casts them to booleans for evaluation, but their non-cast value is returned -# Don't mix up with bool(ints) and bitwise and/or (&,|) -bool(0) # => False -bool(4) # => True -bool(-6) # => True -0 and 2 # => 0 --5 or 0 # => -5 - -# Equality is == -1 == 1 # => True -2 == 1 # => False - -# Inequality is != -1 != 1 # => False -2 != 1 # => True - -# More comparisons -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# Seeing whether a value is in a range -1 < 2 and 2 < 3 # => True -2 < 3 and 3 < 2 # => False -# Chaining makes this look nicer -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# (is vs. ==) is checks if two variables refer to the same object, but == checks -# if the objects pointed to have the same values. -a = [1, 2, 3, 4] # Point a at a new list, [1, 2, 3, 4] -b = a # Point b at what a is pointing to -b is a # => True, a and b refer to the same object -b == a # => True, a's and b's objects are equal -b = [1, 2, 3, 4] # Point b at a new list, [1, 2, 3, 4] -b is a # => False, a and b do not refer to the same object -b == a # => True, a's and b's objects are equal - -# Strings are created with " or ' -"This is a string." -'This is also a string.' - -# Strings can be added too! But try not to do this. -"Hello " + "world!" # => "Hello world!" -# String literals (but not variables) can be concatenated without using '+' -"Hello " "world!" # => "Hello world!" - -# A string can be treated like a list of characters -"This is a string"[0] # => 'T' - -# You can find the length of a string -len("This is a string") # => 16 - -# .format can be used to format strings, like this: -"{} can be {}".format("Strings", "interpolated") # => "Strings can be interpolated" - -# You can repeat the formatting arguments to save some typing. -"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") -# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" - -# You can use keywords if you don't want to count. -"{name} wants to eat {food}".format(name="Bob", food="lasagna") # => "Bob wants to eat lasagna" - -# If your Python 3 code also needs to run on Python 2.5 and below, you can also -# still use the old style of formatting: -"%s can be %s the %s way" % ("Strings", "interpolated", "old") # => "Strings can be interpolated the old way" - -# You can also format using f-strings or formatted string literals (in Python 3.6+) -name = "Reiko" -f"She said her name is {name}." # => "She said her name is Reiko" -# You can basically put any Python statement inside the braces and it will be output in the string. -f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." - - -# None is an object -None # => None - -# Don't use the equality "==" symbol to compare objects to None -# Use "is" instead. This checks for equality of object identity. -"etc" is None # => False -None is None # => True - -# None, 0, and empty strings/lists/dicts/tuples all evaluate to False. -# All other values are True -bool(0) # => False -bool("") # => False -bool([]) # => False -bool({}) # => False -bool(()) # => False - -#################################################### -## 2. Variables and Collections -#################################################### - -# Python has a print function -print("I'm Python. Nice to meet you!") # => I'm Python. Nice to meet you! - -# By default the print function also prints out a newline at the end. -# Use the optional argument end to change the end string. -print("Hello, World", end="!") # => Hello, World! - -# Simple way to get input data from console -input_string_var = input("Enter some data: ") # Returns the data as a string -# Note: In earlier versions of Python, input() method was named as raw_input() - -# There are no declarations, only assignments. -# Convention is to use lower_case_with_underscores -some_var = 5 -some_var # => 5 - -# Accessing a previously unassigned variable is an exception. -# See Control Flow to learn more about exception handling. -some_unknown_var # Raises a NameError - -# if can be used as an expression -# Equivalent of C's '?:' ternary operator -"yahoo!" if 3 > 2 else 2 # => "yahoo!" - -# Lists store sequences -li = [] -# You can start with a prefilled list -other_li = [4, 5, 6] - -# Add stuff to the end of a list with append -li.append(1) # li is now [1] -li.append(2) # li is now [1, 2] -li.append(4) # li is now [1, 2, 4] -li.append(3) # li is now [1, 2, 4, 3] -# Remove from the end with pop -li.pop() # => 3 and li is now [1, 2, 4] -# Let's put it back -li.append(3) # li is now [1, 2, 4, 3] again. - -# Access a list like you would any array -li[0] # => 1 -# Look at the last element -li[-1] # => 3 - -# Looking out of bounds is an IndexError -li[4] # Raises an IndexError - -# You can look at ranges with slice syntax. -# The start index is included, the end index is not -# (It's a closed/open range for you mathy types.) -li[1:3] # Return list from index 1 to 3 => [2, 4] -li[2:] # Return list starting from index 2 => [4, 3] -li[:3] # Return list from beginning uptil index 3 => [1, 2, 4] -li[::2] # Return list selecting every second entry => [1, 4] -li[::-1] # Return list in reverse order => [3, 4, 2, 1] -# Use any combination of these to make advanced slices -# li[start:end:step] - -# Make a one layer deep copy using slices -li2 = li[:] # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false. - -# Remove arbitrary elements from a list with "del" -del li[2] # li is now [1, 2, 3] - -# Remove first occurrence of a value -li.remove(2) # li is now [1, 3] -li.remove(2) # Raises a ValueError as 2 is not in the list - -# Insert an element at a specific index -li.insert(1, 2) # li is now [1, 2, 3] again - -# Get the index of the first item found matching the argument -li.index(2) # => 1 -li.index(4) # Raises a ValueError as 4 is not in the list - -# You can add lists -# Note: values for li and for other_li are not modified. -li + other_li # => [1, 2, 3, 4, 5, 6] - -# Concatenate lists with "extend()" -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] - -# Check for existence in a list with "in" -1 in li # => True - -# Examine the length with "len()" -len(li) # => 6 - - -# Tuples are like lists but are immutable. -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # Raises a TypeError - -# Note that a tuple of length one has to have a comma after the last element but -# tuples of other lengths, even zero, do not. -type((1)) # => <class 'int'> -type((1,)) # => <class 'tuple'> -type(()) # => <class 'tuple'> - -# You can do most of the list operations on tuples too -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True - -# You can unpack tuples (or lists) into variables -a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 -# You can also do extended unpacking -a, *b, c = (1, 2, 3, 4) # a is now 1, b is now [2, 3] and c is now 4 -# Tuples are created by default if you leave out the parentheses -d, e, f = 4, 5, 6 # tuple 4, 5, 6 is unpacked into variables d, e and f -# respectively such that d = 4, e = 5 and f = 6 -# Now look how easy it is to swap two values -e, d = d, e # d is now 5 and e is now 4 - - -# Dictionaries store mappings from keys to values -empty_dict = {} -# Here is a prefilled dictionary -filled_dict = {"one": 1, "two": 2, "three": 3} - -# Note keys for dictionaries have to be immutable types. This is to ensure that -# the key can be converted to a constant hash value for quick look-ups. -# Immutable types include ints, floats, strings, tuples. -invalid_dict = {[1,2,3]: "123"} # => Raises a TypeError: unhashable type: 'list' -valid_dict = {(1,2,3):[1,2,3]} # Values can be of any type, however. - -# Look up values with [] -filled_dict["one"] # => 1 - -# Get all keys as an iterable with "keys()". We need to wrap the call in list() -# to turn it into a list. We'll talk about those later. Note - for Python -# versions <3.7, dictionary key ordering is not guaranteed. Your results might -# not match the example below exactly. However, as of Python 3.7, dictionary -# items maintain the order at which they are inserted into the dictionary. -list(filled_dict.keys()) # => ["three", "two", "one"] in Python <3.7 -list(filled_dict.keys()) # => ["one", "two", "three"] in Python 3.7+ - - -# Get all values as an iterable with "values()". Once again we need to wrap it -# in list() to get it out of the iterable. Note - Same as above regarding key -# ordering. -list(filled_dict.values()) # => [3, 2, 1] in Python <3.7 -list(filled_dict.values()) # => [1, 2, 3] in Python 3.7+ - -# Check for existence of keys in a dictionary with "in" -"one" in filled_dict # => True -1 in filled_dict # => False - -# Looking up a non-existing key is a KeyError -filled_dict["four"] # KeyError - -# Use "get()" method to avoid the KeyError -filled_dict.get("one") # => 1 -filled_dict.get("four") # => None -# The get method supports a default argument when the value is missing -filled_dict.get("one", 4) # => 1 -filled_dict.get("four", 4) # => 4 - -# "setdefault()" inserts into a dictionary only if the given key isn't present -filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 -filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 - -# Adding to a dictionary -filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} -filled_dict["four"] = 4 # another way to add to dict - -# Remove keys from a dictionary with del -del filled_dict["one"] # Removes the key "one" from filled dict - -# From Python 3.5 you can also use the additional unpacking options -{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} -{'a': 1, **{'a': 2}} # => {'a': 2} - - - -# Sets store ... well sets -empty_set = set() -# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry. -some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} - -# Similar to keys of a dictionary, elements of a set have to be immutable. -invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list' -valid_set = {(1,), 1} - -# Add one more item to the set -filled_set = some_set -filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} -# Sets do not have duplicate elements -filled_set.add(5) # it remains as before {1, 2, 3, 4, 5} - -# Do set intersection with & -other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} - -# Do set union with | -filled_set | other_set # => {1, 2, 3, 4, 5, 6} - -# Do set difference with - -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} - -# Do set symmetric difference with ^ -{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} - -# Check if set on the left is a superset of set on the right -{1, 2} >= {1, 2, 3} # => False - -# Check if set on the left is a subset of set on the right -{1, 2} <= {1, 2, 3} # => True - -# Check for existence in a set with in -2 in filled_set # => True -10 in filled_set # => False - - - -#################################################### -## 3. Control Flow and Iterables -#################################################### - -# Let's just make a variable -some_var = 5 - -# Here is an if statement. Indentation is significant in Python! -# Convention is to use four spaces, not tabs. -# This prints "some_var is smaller than 10" -if some_var > 10: - print("some_var is totally bigger than 10.") -elif some_var < 10: # This elif clause is optional. - print("some_var is smaller than 10.") -else: # This is optional too. - print("some_var is indeed 10.") - - -""" -For loops iterate over lists -prints: - dog is a mammal - cat is a mammal - mouse is a mammal -""" -for animal in ["dog", "cat", "mouse"]: - # You can use format() to interpolate formatted strings - print("{} is a mammal".format(animal)) - -""" -"range(number)" returns an iterable of numbers -from zero to the given number -prints: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -"range(lower, upper)" returns an iterable of numbers -from the lower number to the upper number -prints: - 4 - 5 - 6 - 7 -""" -for i in range(4, 8): - print(i) - -""" -"range(lower, upper, step)" returns an iterable of numbers -from the lower number to the upper number, while incrementing -by step. If step is not indicated, the default value is 1. -prints: - 4 - 6 -""" -for i in range(4, 8, 2): - print(i) - -""" -To loop over a list, and retrieve both the index and the value of each item in the list -prints: - 0 dog - 1 cat - 2 mouse -""" -list = ["dog", "cat", "mouse"] -for i, value in enumerate(list): - print(i, value) - -""" -While loops go until a condition is no longer met. -prints: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Shorthand for x = x + 1 - -# Handle exceptions with a try/except block -try: - # Use "raise" to raise an error - raise IndexError("This is an index error") -except IndexError as e: - pass # Pass is just a no-op. Usually you would do recovery here. -except (TypeError, NameError): - pass # Multiple exceptions can be handled together, if required. -else: # Optional clause to the try/except block. Must follow all except blocks - print("All good!") # Runs only if the code in try raises no exceptions -finally: # Execute under all circumstances - print("We can clean up resources here") - -# Instead of try/finally to cleanup resources you can use a with statement -with open("myfile.txt") as f: - for line in f: - print(line) - -# Writing to a file -contents = {"aa": 12, "bb": 21} -with open("myfile1.txt", "w+") as file: - file.write(str(contents)) # writes a string to a file - -with open("myfile2.txt", "w+") as file: - file.write(json.dumps(contents)) # writes an object to a file - -# Reading from a file -with open('myfile1.txt', "r+") as file: - contents = file.read() # reads a string from a file -print(contents) -# print: {"aa": 12, "bb": 21} - -with open('myfile2.txt', "r+") as file: - contents = json.load(file) # reads a json object from a file -print(contents) -# print: {"aa": 12, "bb": 21} - - -# Python offers a fundamental abstraction called the Iterable. -# An iterable is an object that can be treated as a sequence. -# The object returned by the range function, is an iterable. - -filled_dict = {"one": 1, "two": 2, "three": 3} -our_iterable = filled_dict.keys() -print(our_iterable) # => dict_keys(['one', 'two', 'three']). This is an object that implements our Iterable interface. - -# We can loop over it. -for i in our_iterable: - print(i) # Prints one, two, three - -# However we cannot address elements by index. -our_iterable[1] # Raises a TypeError - -# An iterable is an object that knows how to create an iterator. -our_iterator = iter(our_iterable) - -# Our iterator is an object that can remember the state as we traverse through it. -# We get the next object with "next()". -next(our_iterator) # => "one" - -# It maintains state as we iterate. -next(our_iterator) # => "two" -next(our_iterator) # => "three" - -# After the iterator has returned all of its data, it raises a StopIteration exception -next(our_iterator) # Raises StopIteration - -# You can grab all the elements of an iterator by calling list() on it. -list(filled_dict.keys()) # => Returns ["one", "two", "three"] - - -#################################################### -## 4. Functions -#################################################### - -# Use "def" to create new functions -def add(x, y): - print("x is {} and y is {}".format(x, y)) - return x + y # Return values with a return statement - -# Calling functions with parameters -add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 - -# Another way to call functions is with keyword arguments -add(y=6, x=5) # Keyword arguments can arrive in any order. - -# You can define functions that take a variable number of -# positional arguments -def varargs(*args): - return args - -varargs(1, 2, 3) # => (1, 2, 3) - -# You can define functions that take a variable number of -# keyword arguments, as well -def keyword_args(**kwargs): - return kwargs - -# Let's call it to see what happens -keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} - - -# You can do both at once, if you like -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) prints: - (1, 2) - {"a": 3, "b": 4} -""" - -# When calling functions, you can do the opposite of args/kwargs! -# Use * to expand tuples and use ** to expand kwargs. -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalent to all_the_args(1, 2, 3, 4) -all_the_args(**kwargs) # equivalent to all_the_args(a=3, b=4) -all_the_args(*args, **kwargs) # equivalent to all_the_args(1, 2, 3, 4, a=3, b=4) - -# Returning multiple values (with tuple assignments) -def swap(x, y): - return y, x # Return multiple values as a tuple without the parenthesis. - # (Note: parenthesis have been excluded but can be included) - -x = 1 -y = 2 -x, y = swap(x, y) # => x = 2, y = 1 -# (x, y) = swap(x,y) # Again parenthesis have been excluded but can be included. - -# Function Scope -x = 5 - -def set_x(num): - # Local var x not the same as global variable x - x = num # => 43 - print(x) # => 43 - -def set_global_x(num): - global x - print(x) # => 5 - x = num # global var x is now set to 6 - print(x) # => 6 - -set_x(43) -set_global_x(6) - - -# Python has first class functions -def create_adder(x): - def adder(y): - return x + y - return adder - -add_10 = create_adder(10) -add_10(3) # => 13 - -# There are also anonymous functions -(lambda x: x > 2)(3) # => True -(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 - -# There are built-in higher order functions -list(map(add_10, [1, 2, 3])) # => [11, 12, 13] -list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] - -list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] - -# We can use list comprehensions for nice maps and filters -# List comprehension stores the output as a list which can itself be a nested list -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] - -# You can construct set and dict comprehensions as well. -{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} -{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} - - -#################################################### -## 5. Modules -#################################################### - -# You can import modules -import math -print(math.sqrt(16)) # => 4.0 - -# You can get specific functions from a module -from math import ceil, floor -print(ceil(3.7)) # => 4.0 -print(floor(3.7)) # => 3.0 - -# You can import all functions from a module. -# Warning: this is not recommended -from math import * - -# You can shorten module names -import math as m -math.sqrt(16) == m.sqrt(16) # => True - -# Python modules are just ordinary Python files. You -# can write your own, and import them. The name of the -# module is the same as the name of the file. - -# You can find out which functions and attributes -# are defined in a module. -import math -dir(math) - -# If you have a Python script named math.py in the same -# folder as your current script, the file math.py will -# be loaded instead of the built-in Python module. -# This happens because the local folder has priority -# over Python's built-in libraries. - - -#################################################### -## 6. Classes -#################################################### - -# We use the "class" statement to create a class -class Human: - - # A class attribute. It is shared by all instances of this class - species = "H. sapiens" - - # Basic initializer, this is called when this class is instantiated. - # Note that the double leading and trailing underscores denote objects - # or attributes that are used by Python but that live in user-controlled - # namespaces. Methods(or objects or attributes) like: __init__, __str__, - # __repr__ etc. are called special methods (or sometimes called dunder methods) - # You should not invent such names on your own. - def __init__(self, name): - # Assign the argument to the instance's name attribute - self.name = name - - # Initialize property - self._age = 0 - - # An instance method. All methods take "self" as the first argument - def say(self, msg): - print("{name}: {message}".format(name=self.name, message=msg)) - - # Another instance method - def sing(self): - return 'yo... yo... microphone check... one two... one two...' - - # A class method is shared among all instances - # They are called with the calling class as the first argument - @classmethod - def get_species(cls): - return cls.species - - # A static method is called without a class or instance reference - @staticmethod - def grunt(): - return "*grunt*" - - # A property is just like a getter. - # It turns the method age() into an read-only attribute of the same name. - # There's no need to write trivial getters and setters in Python, though. - @property - def age(self): - return self._age - - # This allows the property to be set - @age.setter - def age(self, age): - self._age = age - - # This allows the property to be deleted - @age.deleter - def age(self): - del self._age - - -# When a Python interpreter reads a source file it executes all its code. -# This __name__ check makes sure this code block is only executed when this -# module is the main program. -if __name__ == '__main__': - # Instantiate a class - i = Human(name="Ian") - i.say("hi") # "Ian: hi" - j = Human("Joel") - j.say("hello") # "Joel: hello" - # i and j are instances of type Human, or in other words: they are Human objects - - # Call our class method - i.say(i.get_species()) # "Ian: H. sapiens" - # Change the shared attribute - Human.species = "H. neanderthalensis" - i.say(i.get_species()) # => "Ian: H. neanderthalensis" - j.say(j.get_species()) # => "Joel: H. neanderthalensis" - - # Call the static method - print(Human.grunt()) # => "*grunt*" - - # Cannot call static method with instance of object - # because i.grunt() will automatically put "self" (the object i) as an argument - print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given - - # Update the property for this instance - i.age = 42 - # Get the property - i.say(i.age) # => "Ian: 42" - j.say(j.age) # => "Joel: 0" - # Delete the property - del i.age - # i.age # => this would raise an AttributeError - - -#################################################### -## 6.1 Inheritance -#################################################### - -# Inheritance allows new child classes to be defined that inherit methods and -# variables from their parent class. - -# Using the Human class defined above as the base or parent class, we can -# define a child class, Superhero, which inherits the class variables like -# "species", "name", and "age", as well as methods, like "sing" and "grunt" -# from the Human class, but can also have its own unique properties. - -# To take advantage of modularization by file you could place the classes above in their own files, -# say, human.py - -# To import functions from other files use the following format -# from "filename-without-extension" import "function-or-class" - -from human import Human - - -# Specify the parent class(es) as parameters to the class definition -class Superhero(Human): - - # If the child class should inherit all of the parent's definitions without - # any modifications, you can just use the "pass" keyword (and nothing else) - # but in this case it is commented out to allow for a unique child class: - # pass - - # Child classes can override their parents' attributes - species = 'Superhuman' - - # Children automatically inherit their parent class's constructor including - # its arguments, but can also define additional arguments or definitions - # and override its methods such as the class constructor. - # This constructor inherits the "name" argument from the "Human" class and - # adds the "superpower" and "movie" arguments: - def __init__(self, name, movie=False, - superpowers=["super strength", "bulletproofing"]): - - # add additional class attributes: - self.fictional = True - self.movie = movie - # be aware of mutable default values, since defaults are shared - self.superpowers = superpowers - - # The "super" function lets you access the parent class's methods - # that are overridden by the child, in this case, the __init__ method. - # This calls the parent class constructor: - super().__init__(name) - - # override the sing method - def sing(self): - return 'Dun, dun, DUN!' - - # add an additional instance method - def boast(self): - for power in self.superpowers: - print("I wield the power of {pow}!".format(pow=power)) - - -if __name__ == '__main__': - sup = Superhero(name="Tick") - - # Instance type checks - if isinstance(sup, Human): - print('I am human') - if type(sup) is Superhero: - print('I am a superhero') - - # Get the Method Resolution search Order used by both getattr() and super() - # This attribute is dynamic and can be updated - print(Superhero.__mro__) # => (<class '__main__.Superhero'>, - # => <class 'human.Human'>, <class 'object'>) - - # Calls parent method but uses its own class attribute - print(sup.get_species()) # => Superhuman - - # Calls overridden method - print(sup.sing()) # => Dun, dun, DUN! - - # Calls method from Human - sup.say('Spoon') # => Tick: Spoon - - # Call method that exists only in Superhero - sup.boast() # => I wield the power of super strength! - # => I wield the power of bulletproofing! - - # Inherited class attribute - sup.age = 31 - print(sup.age) # => 31 - - # Attribute that only exists within Superhero - print('Am I Oscar eligible? ' + str(sup.movie)) - -#################################################### -## 6.2 Multiple Inheritance -#################################################### - -# Another class definition -# bat.py -class Bat: - - species = 'Baty' - - def __init__(self, can_fly=True): - self.fly = can_fly - - # This class also has a say method - def say(self, msg): - msg = '... ... ...' - return msg - - # And its own method as well - def sonar(self): - return '))) ... (((' - -if __name__ == '__main__': - b = Bat() - print(b.say('hello')) - print(b.fly) - - -# And yet another class definition that inherits from Superhero and Bat -# superhero.py -from superhero import Superhero -from bat import Bat - -# Define Batman as a child that inherits from both Superhero and Bat -class Batman(Superhero, Bat): - - def __init__(self, *args, **kwargs): - # Typically to inherit attributes you have to call super: - # super(Batman, self).__init__(*args, **kwargs) - # However we are dealing with multiple inheritance here, and super() - # only works with the next base class in the MRO list. - # So instead we explicitly call __init__ for all ancestors. - # The use of *args and **kwargs allows for a clean way to pass arguments, - # with each parent "peeling a layer of the onion". - Superhero.__init__(self, 'anonymous', movie=True, - superpowers=['Wealthy'], *args, **kwargs) - Bat.__init__(self, *args, can_fly=False, **kwargs) - # override the value for the name attribute - self.name = 'Sad Affleck' - - def sing(self): - return 'nan nan nan nan nan batman!' - - -if __name__ == '__main__': - sup = Batman() - - # Get the Method Resolution search Order used by both getattr() and super(). - # This attribute is dynamic and can be updated - print(Batman.__mro__) # => (<class '__main__.Batman'>, - # => <class 'superhero.Superhero'>, - # => <class 'human.Human'>, - # => <class 'bat.Bat'>, <class 'object'>) - - # Calls parent method but uses its own class attribute - print(sup.get_species()) # => Superhuman - - # Calls overridden method - print(sup.sing()) # => nan nan nan nan nan batman! - - # Calls method from Human, because inheritance order matters - sup.say('I agree') # => Sad Affleck: I agree - - # Call method that exists only in 2nd ancestor - print(sup.sonar()) # => ))) ... ((( - - # Inherited class attribute - sup.age = 100 - print(sup.age) # => 100 - - # Inherited attribute from 2nd ancestor whose default value was overridden. - print('Can I fly? ' + str(sup.fly)) # => Can I fly? False - - - -#################################################### -## 7. Advanced -#################################################### - -# Generators help you make lazy code. -def double_numbers(iterable): - for i in iterable: - yield i + i - -# Generators are memory-efficient because they only load the data needed to -# process the next value in the iterable. This allows them to perform -# operations on otherwise prohibitively large value ranges. -# NOTE: `range` replaces `xrange` in Python 3. -for i in double_numbers(range(1, 900000000)): # `range` is a generator. - print(i) - if i >= 30: - break - -# Just as you can create a list comprehension, you can create generator -# comprehensions as well. -values = (-x for x in [1,2,3,4,5]) -for x in values: - print(x) # prints -1 -2 -3 -4 -5 to console/terminal - -# You can also cast a generator comprehension directly to a list. -values = (-x for x in [1,2,3,4,5]) -gen_to_list = list(values) -print(gen_to_list) # => [-1, -2, -3, -4, -5] - - -# Decorators -# In this example `beg` wraps `say`. If say_please is True then it -# will change the returned message. -from functools import wraps - - -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Please! I am poor :(") - return msg - - return wrapper - - -@beg -def say(say_please=False): - msg = "Can you buy me a beer?" - return msg, say_please - - -print(say()) # Can you buy me a beer? -print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( -``` - -## Ready For More? - -### Free Online - -* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Course](http://www.python-course.eu/index.php) -* [First Steps With Python](https://realpython.com/learn/python-first-steps/) -* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) -* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) -* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) -* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) -* [Dive Into Python 3](http://www.diveintopython3.net/index.html) -* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) diff --git a/pythonlegacy.html.markdown b/pythonlegacy.html.markdown new file mode 100644 index 00000000..95d6aa63 --- /dev/null +++ b/pythonlegacy.html.markdown @@ -0,0 +1,827 @@ +--- +language: Python 2 (legacy) +contributors: + - ["Louie Dinh", "http://ldinh.ca"] + - ["Amin Bandali", "https://aminb.org"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["evuez", "http://github.com/evuez"] + - ["asyne", "https://github.com/justblah"] + - ["habi", "http://github.com/habi"] + - ["Rommel Martinez", "https://ebzzry.io"] +filename: learnpythonlegacy.py +--- + +Python was created by Guido Van Rossum in the early 90s. It is now one of the +most popular languages in existence. I fell in love with Python for its +syntactic clarity. It's basically executable pseudocode. + +Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) +or louiedinh [at] [google's email service] + +Note: This article applies to Python 2.7 specifically, but should be applicable +to Python 2.x. Python 2.7 is reaching end of life and will stop being +maintained in 2020, it is though recommended to start learning Python with +Python 3. For Python 3.x, take a look at the [Python 3 tutorial](http://learnxinyminutes.com/docs/python/). + +It is also possible to write Python code which is compatible with Python 2.7 +and 3.x at the same time, using Python [`__future__` imports](https://docs.python.org/2/library/__future__.html). `__future__` imports +allow you to write Python 3 code that will run on Python 2, so check out the +Python 3 tutorial. + +```python + +# Single line comments start with a number symbol. + +""" Multiline strings can be written + using three "s, and are often used + as comments +""" + +#################################################### +# 1. Primitive Datatypes and Operators +#################################################### + +# You have numbers +3 # => 3 + +# Math is what you would expect +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7 + +# Division is a bit tricky. It is integer division and floors the results +# automatically. +5 / 2 # => 2 + +# To fix division we need to learn about floats. +2.0 # This is a float +11.0 / 4.0 # => 2.75 ahhh...much better + +# Result of integer division truncated down both for positive and negative. +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # works on floats too +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# Note that we can also import division module(Section 6 Modules) +# to carry out normal division with just one '/'. +from __future__ import division + +11 / 4 # => 2.75 ...normal division +11 // 4 # => 2 ...floored division + +# Modulo operation +7 % 3 # => 1 + +# Exponentiation (x to the yth power) +2 ** 4 # => 16 + +# Enforce precedence with parentheses +(1 + 3) * 2 # => 8 + +# Boolean Operators +# Note "and" and "or" are case-sensitive +True and False # => False +False or True # => True + +# Note using Bool operators with ints +0 and 2 # => 0 +-5 or 0 # => -5 +0 == False # => True +2 == True # => False +1 == True # => True + +# negate with not +not True # => False +not False # => True + +# Equality is == +1 == 1 # => True +2 == 1 # => False + +# Inequality is != +1 != 1 # => False +2 != 1 # => True + +# More comparisons +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# Comparisons can be chained! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# Strings are created with " or ' +"This is a string." +'This is also a string.' + +# Strings can be added too! +"Hello " + "world!" # => "Hello world!" +# Strings can be added without using '+' +"Hello " "world!" # => "Hello world!" + +# ... or multiplied +"Hello" * 3 # => "HelloHelloHello" + +# A string can be treated like a list of characters +"This is a string"[0] # => 'T' + +# You can find the length of a string +len("This is a string") # => 16 + +# String formatting with % +# Even though the % string operator will be deprecated on Python 3.1 and removed +# later at some time, it may still be good to know how it works. +x = 'apple' +y = 'lemon' +z = "The items in the basket are %s and %s" % (x, y) + +# A newer way to format strings is the format method. +# This method is the preferred way +"{} is a {}".format("This", "placeholder") +"{0} can be {1}".format("strings", "formatted") +# You can use keywords if you don't want to count. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") + +# None is an object +None # => None + +# Don't use the equality "==" symbol to compare objects to None +# Use "is" instead +"etc" is None # => False +None is None # => True + +# The 'is' operator tests for object identity. This isn't +# very useful when dealing with primitive values, but is +# very useful when dealing with objects. + +# Any object can be used in a Boolean context. +# The following values are considered falsey: +# - None +# - zero of any numeric type (e.g., 0, 0L, 0.0, 0j) +# - empty sequences (e.g., '', (), []) +# - empty containers (e.g., {}, set()) +# - instances of user-defined classes meeting certain conditions +# see: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__ +# +# All other values are truthy (using the bool() function on them returns True). +bool(0) # => False +bool("") # => False + + +#################################################### +# 2. Variables and Collections +#################################################### + +# Python has a print statement +print "I'm Python. Nice to meet you!" # => I'm Python. Nice to meet you! + +# Simple way to get input data from console +input_string_var = raw_input( + "Enter some data: ") # Returns the data as a string +input_var = input("Enter some data: ") # Evaluates the data as python code +# Warning: Caution is recommended for input() method usage +# Note: In python 3, input() is deprecated and raw_input() is renamed to input() + +# No need to declare variables before assigning to them. +some_var = 5 # Convention is to use lower_case_with_underscores +some_var # => 5 + +# Accessing a previously unassigned variable is an exception. +# See Control Flow to learn more about exception handling. +some_other_var # Raises a name error + +# if can be used as an expression +# Equivalent of C's '?:' ternary operator +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# Lists store sequences +li = [] +# You can start with a prefilled list +other_li = [4, 5, 6] + +# Add stuff to the end of a list with append +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] +# Remove from the end with pop +li.pop() # => 3 and li is now [1, 2, 4] +# Let's put it back +li.append(3) # li is now [1, 2, 4, 3] again. + +# Access a list like you would any array +li[0] # => 1 +# Assign new values to indexes that have already been initialized with = +li[0] = 42 +li[0] # => 42 +li[0] = 1 # Note: setting it back to the original value +# Look at the last element +li[-1] # => 3 + +# Looking out of bounds is an IndexError +li[4] # Raises an IndexError + +# You can look at ranges with slice syntax. +# (It's a closed/open range for you mathy types.) +li[1:3] # => [2, 4] +# Omit the beginning +li[2:] # => [4, 3] +# Omit the end +li[:3] # => [1, 2, 4] +# Select every second entry +li[::2] # =>[1, 4] +# Reverse a copy of the list +li[::-1] # => [3, 4, 2, 1] +# Use any combination of these to make advanced slices +# li[start:end:step] + +# Remove arbitrary elements from a list with "del" +del li[2] # li is now [1, 2, 3] + +# You can add lists +li + other_li # => [1, 2, 3, 4, 5, 6] +# Note: values for li and for other_li are not modified. + +# Concatenate lists with "extend()" +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] + +# Remove first occurrence of a value +li.remove(2) # li is now [1, 3, 4, 5, 6] +li.remove(2) # Raises a ValueError as 2 is not in the list + +# Insert an element at a specific index +li.insert(1, 2) # li is now [1, 2, 3, 4, 5, 6] again + +# Get the index of the first item found +li.index(2) # => 1 +li.index(7) # Raises a ValueError as 7 is not in the list + +# Check for existence in a list with "in" +1 in li # => True + +# Examine the length with "len()" +len(li) # => 6 + +# Tuples are like lists but are immutable. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Raises a TypeError + +# You can do all those list thingies on tuples too +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# You can unpack tuples (or lists) into variables +a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 +d, e, f = 4, 5, 6 # you can leave out the parentheses +# Tuples are created by default if you leave out the parentheses +g = 4, 5, 6 # => (4, 5, 6) +# Now look how easy it is to swap two values +e, d = d, e # d is now 5 and e is now 4 + +# Dictionaries store mappings +empty_dict = {} +# Here is a prefilled dictionary +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Look up values with [] +filled_dict["one"] # => 1 + +# Get all keys as a list with "keys()" +filled_dict.keys() # => ["three", "two", "one"] +# Note - Dictionary key ordering is not guaranteed. +# Your results might not match this exactly. + +# Get all values as a list with "values()" +filled_dict.values() # => [3, 2, 1] +# Note - Same as above regarding key ordering. + +# Get all key-value pairs as a list of tuples with "items()" +filled_dict.items() # => [("one", 1), ("two", 2), ("three", 3)] + +# Check for existence of keys in a dictionary with "in" +"one" in filled_dict # => True +1 in filled_dict # => False + +# Looking up a non-existing key is a KeyError +filled_dict["four"] # KeyError + +# Use "get()" method to avoid the KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# The get method supports a default argument when the value is missing +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 +# note that filled_dict.get("four") is still => None +# (get doesn't set the value in the dictionary) + +# set the value of a key with a syntax similar to lists +filled_dict["four"] = 4 # now, filled_dict["four"] => 4 + +# "setdefault()" inserts into a dictionary only if the given key isn't present +filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 + +# You can declare sets (which are like unordered lists that cannot contain +# duplicate values) using the set object. +empty_set = set() +# Initialize a "set()" with a bunch of values +some_set = set([1, 2, 2, 3, 4]) # some_set is now set([1, 2, 3, 4]) + +# order is not guaranteed, even though it may sometimes look sorted +another_set = set([4, 3, 2, 2, 1]) # another_set is now set([1, 2, 3, 4]) + +# Since Python 2.7, {} can be used to declare a set +filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} + +# Add more items to a set +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} + +# Do set intersection with & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# Do set union with | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Do set difference with - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Do set symmetric difference with ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Check if set on the left is a superset of set on the right +{1, 2} >= {1, 2, 3} # => False + +# Check if set on the left is a subset of set on the right +{1, 2} <= {1, 2, 3} # => True + +# Check for existence in a set with in +2 in filled_set # => True +10 in filled_set # => False +10 not in filled_set # => True + +# Check data type of variable +type(li) # => list +type(filled_dict) # => dict +type(5) # => int + + +#################################################### +# 3. Control Flow +#################################################### + +# Let's just make a variable +some_var = 5 + +# Here is an if statement. Indentation is significant in python! +# prints "some_var is smaller than 10" +if some_var > 10: + print "some_var is totally bigger than 10." +elif some_var < 10: # This elif clause is optional. + print "some_var is smaller than 10." +else: # This is optional too. + print "some_var is indeed 10." + +""" +For loops iterate over lists +prints: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # You can use {0} to interpolate formatted strings. (See above.) + print "{0} is a mammal".format(animal) + +""" +"range(number)" returns a list of numbers +from zero to the given number +prints: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +"range(lower, upper)" returns a list of numbers +from the lower number to the upper number +prints: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print i + +""" +While loops go until a condition is no longer met. +prints: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Shorthand for x = x + 1 + +# Handle exceptions with a try/except block + +# Works on Python 2.6 and up: +try: + # Use "raise" to raise an error + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass is just a no-op. Usually you would do recovery here. +except (TypeError, NameError): + pass # Multiple exceptions can be handled together, if required. +else: # Optional clause to the try/except block. Must follow all except blocks + print "All good!" # Runs only if the code in try raises no exceptions +finally: # Execute under all circumstances + print "We can clean up resources here" + +# Instead of try/finally to cleanup resources you can use a with statement +with open("myfile.txt") as f: + for line in f: + print line + + +#################################################### +# 4. Functions +#################################################### + +# Use "def" to create new functions +def add(x, y): + print "x is {0} and y is {1}".format(x, y) + return x + y # Return values with a return statement + + +# Calling functions with parameters +add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 + +# Another way to call functions is with keyword arguments +add(y=6, x=5) # Keyword arguments can arrive in any order. + + +# You can define functions that take a variable number of +# positional args, which will be interpreted as a tuple by using * +def varargs(*args): + return args + + +varargs(1, 2, 3) # => (1, 2, 3) + + +# You can define functions that take a variable number of +# keyword args, as well, which will be interpreted as a dict by using ** +def keyword_args(**kwargs): + return kwargs + + +# Let's call it to see what happens +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# You can do both at once, if you like +def all_the_args(*args, **kwargs): + print args + print kwargs + + +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# When calling functions, you can do the opposite of args/kwargs! +# Use * to expand positional args and use ** to expand keyword args. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalent to all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to all_the_args(1, 2, 3, 4, a=3, b=4) + + +# you can pass args and kwargs along to other functions that take args/kwargs +# by expanding them with * and ** respectively +def pass_all_the_args(*args, **kwargs): + all_the_args(*args, **kwargs) + print varargs(*args) + print keyword_args(**kwargs) + + +# Function Scope +x = 5 + + +def set_x(num): + # Local var x not the same as global variable x + x = num # => 43 + print x # => 43 + + +def set_global_x(num): + global x + print x # => 5 + x = num # global var x is now set to 6 + print x # => 6 + + +set_x(43) +set_global_x(6) + + +# Python has first class functions +def create_adder(x): + def adder(y): + return x + y + + return adder + + +add_10 = create_adder(10) +add_10(3) # => 13 + +# There are also anonymous functions +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 + +# There are built-in higher order functions +map(add_10, [1, 2, 3]) # => [11, 12, 13] +map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] + +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# We can use list comprehensions for nice maps and filters +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# You can construct set and dict comprehensions as well. +{x for x in 'abcddeef' if x in 'abc'} # => {'a', 'b', 'c'} +{x: x ** 2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + + +#################################################### +# 5. Classes +#################################################### + +# We subclass from object to get a class. +class Human(object): + # A class attribute. It is shared by all instances of this class + species = "H. sapiens" + + # Basic initializer, this is called when this class is instantiated. + # Note that the double leading and trailing underscores denote objects + # or attributes that are used by python but that live in user-controlled + # namespaces. You should not invent such names on your own. + def __init__(self, name): + # Assign the argument to the instance's name attribute + self.name = name + + # Initialize property + self.age = 0 + + # An instance method. All methods take "self" as the first argument + def say(self, msg): + return "{0}: {1}".format(self.name, msg) + + # A class method is shared among all instances + # They are called with the calling class as the first argument + @classmethod + def get_species(cls): + return cls.species + + # A static method is called without a class or instance reference + @staticmethod + def grunt(): + return "*grunt*" + + # A property is just like a getter. + # It turns the method age() into an read-only attribute + # of the same name. + @property + def age(self): + return self._age + + # This allows the property to be set + @age.setter + def age(self, age): + self._age = age + + # This allows the property to be deleted + @age.deleter + def age(self): + del self._age + + +# Instantiate a class +i = Human(name="Ian") +print i.say("hi") # prints out "Ian: hi" + +j = Human("Joel") +print j.say("hello") # prints out "Joel: hello" + +# Call our class method +i.get_species() # => "H. sapiens" + +# Change the shared attribute +Human.species = "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" + +# Call the static method +Human.grunt() # => "*grunt*" + +# Update the property +i.age = 42 + +# Get the property +i.age # => 42 + +# Delete the property +del i.age +i.age # => raises an AttributeError + +#################################################### +# 6. Modules +#################################################### + +# You can import modules +import math + +print math.sqrt(16) # => 4.0 + +# You can get specific functions from a module +from math import ceil, floor + +print ceil(3.7) # => 4.0 +print floor(3.7) # => 3.0 + +# You can import all functions from a module. +# Warning: this is not recommended +from math import * + +# You can shorten module names +import math as m + +math.sqrt(16) == m.sqrt(16) # => True +# you can also test that the functions are equivalent +from math import sqrt + +math.sqrt == m.sqrt == sqrt # => True + +# Python modules are just ordinary python files. You +# can write your own, and import them. The name of the +# module is the same as the name of the file. + +# You can find out which functions and attributes +# defines a module. +import math + +dir(math) + + +# If you have a Python script named math.py in the same +# folder as your current script, the file math.py will +# be loaded instead of the built-in Python module. +# This happens because the local folder has priority +# over Python's built-in libraries. + + +#################################################### +# 7. Advanced +#################################################### + +# Generators +# A generator "generates" values as they are requested instead of storing +# everything up front + +# The following method (*NOT* a generator) will double all values and store it +# in `double_arr`. For large size of iterables, that might get huge! +def double_numbers(iterable): + double_arr = [] + for i in iterable: + double_arr.append(i + i) + return double_arr + + +# Running the following would mean we'll double all values first and return all +# of them back to be checked by our condition +for value in double_numbers(range(1000000)): # `test_non_generator` + print value + if value > 5: + break + + +# We could instead use a generator to "generate" the doubled value as the item +# is being requested +def double_numbers_generator(iterable): + for i in iterable: + yield i + i + + +# Running the same code as before, but with a generator, now allows us to iterate +# over the values and doubling them one by one as they are being consumed by +# our logic. Hence as soon as we see a value > 5, we break out of the +# loop and don't need to double most of the values sent in (MUCH FASTER!) +for value in double_numbers_generator(xrange(1000000)): # `test_generator` + print value + if value > 5: + break + +# BTW: did you notice the use of `range` in `test_non_generator` and `xrange` in `test_generator`? +# Just as `double_numbers_generator` is the generator version of `double_numbers` +# We have `xrange` as the generator version of `range` +# `range` would return back and array with 1000000 values for us to use +# `xrange` would generate 1000000 values for us as we request / iterate over those items + +# Just as you can create a list comprehension, you can create generator +# comprehensions as well. +values = (-x for x in [1, 2, 3, 4, 5]) +for x in values: + print(x) # prints -1 -2 -3 -4 -5 to console/terminal + +# You can also cast a generator comprehension directly to a list. +values = (-x for x in [1, 2, 3, 4, 5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + +# Decorators +# A decorator is a higher order function, which accepts and returns a function. +# Simple usage example – add_apples decorator will add 'Apple' element into +# fruits list returned by get_fruits target function. +def add_apples(func): + def get_fruits(): + fruits = func() + fruits.append('Apple') + return fruits + return get_fruits + +@add_apples +def get_fruits(): + return ['Banana', 'Mango', 'Orange'] + +# Prints out the list of fruits with 'Apple' element in it: +# Banana, Mango, Orange, Apple +print ', '.join(get_fruits()) + +# in this example beg wraps say +# Beg will call say. If say_please is True then it will change the returned +# message +from functools import wraps + + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print say() # Can you buy me a beer? +print say(say_please=True) # Can you buy me a beer? Please! I am poor :( +``` + +## Ready For More? + +### Free Online + +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [LearnPython](http://www.learnpython.org/) +* [Fullstack Python](https://www.fullstackpython.com/) + +### Dead Tree + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) diff --git a/qsharp.html.markdown b/qsharp.html.markdown new file mode 100644 index 00000000..04e697a4 --- /dev/null +++ b/qsharp.html.markdown @@ -0,0 +1,204 @@ +--- +language: Q# +contributors: + - ["Vincent van Wingerden", "https://github.com/vivanwin"] + - ["Mariia Mykhailova", "https://github.com/tcNickolas"] + - ["Andrew Ryan Davis", "https://github.com/AndrewDavis1191"] +filename: LearnQSharp.qs +--- + +Q# is a high-level domain-specific language which enables developers to write quantum algorithms. Q# programs can be executed on a quantum simulator running on a classical computer and (in future) on quantum computers. + +```c# +// Single-line comments start with // + + +///////////////////////////////////// +// 1. Quantum data types and operators + +// The most important part of quantum programs is qubits. +// In Q# type Qubit represents the qubits which can be used. +// This will allocate an array of two new qubits as the variable qs. +using (qs = Qubit[2]) { + + // The qubits have internal state that you cannot access to read or modify directly. + // You can inspect the current state of your quantum program + // if you're running it on a classical simulator. + // Note that this will not work on actual quantum hardware! + DumpMachine(); + + // If you want to change the state of a qubit + // you have to do this by applying quantum gates to the qubit. + H(qs[0]); // This changes the state of the first qubit + // from |0⟩ (the initial state of allocated qubits) + // to (|0⟩ + |1⟩) / sqrt(2). + // qs[1] = |1⟩; - this does NOT work, you have to manipulate a qubit by using gates. + + // You can apply multi-qubit gates to several qubits. + CNOT(qs[0], qs[1]); + + // You can also apply a controlled version of a gate: + // a gate that is applied if all control qubits are in |1⟩ state. + // The first argument is an array of control qubits, + // the second argument is the target qubit. + Controlled Y([qs[0]], qs[1]); + + // If you want to apply an anti-controlled gate + // (a gate that is applied if all control qubits are in |0⟩ state), + // you can use a library function. + ApplyControlledOnInt(0, X, [qs[0]], qs[1]); + + // To read the information from the quantum system, you use measurements. + // Measurements return a value of Result data type: Zero or One. + // You can print measurement results as a classical value. + Message($"Measured {M(qs[0])}, {M(qs[1])}"); +} + + +///////////////////////////////////// +// 2. Classical data types and operators + +// Numbers in Q# can be stored in Int, BigInt or Double. +let i = 1; // This defines an Int variable i equal to 1 +let bi = 1L; // This defines a BigInt variable bi equal to 1 +let d = 1.0; // This defines a Double variable d equal to 1 + +// Arithmetic is done as expected, as long as the types are the same +let n = 2 * 10; // = 20 +// Q# does not have implicit type cast, +// so to perform arithmetic on values of different types, +// you need to cast type explicitly +let nd = IntAsDouble(2) * 1.0; // = 20.0 + +// Boolean type is called Bool +let trueBool = true; +let falseBool = false; + +// Logic operators work as expected +let andBool = true and false; +let orBool = true or false; +let notBool = not false; + +// Strings +let str = "Hello World!"; + +// Equality is == +let x = 10 == 15; // is false + +// Range is a sequence of integers and can be defined like: start..step..stop +let xi = 1..2..7; // Gives the sequence 1,3,5,7 + +// Assigning new value to a variable: +// by default all Q# variables are immutable; +// if the variable was defined using let, you cannot reassign its value. + +// When you want to make a variable mutable, you have to declare it as such, +// and use the set word to update value +mutable xii = true; +set xii = false; + +// You can create an array for any data type like this +let xiii = new Double[10]; + +// Getting an element from an array +let xiv = xiii[8]; + +// Assigning a new value to an array element +mutable xv = new Double[10]; +set xv w/= 5 <- 1; + + +///////////////////////////////////// +// 3. Control flow + +// If structures work a little different than most languages +if (a == 1) { + // ... +} elif (a == 2) { + // ... +} else { + // ... +} + +// Foreach loops can be used to iterate over an array +for (qubit in qubits) { + X(qubit); +} + +// Regular for loops can be used to iterate over a range of numbers +for (index in 0 .. Length(qubits) - 1) { + X(qubits[index]); +} + +// While loops are restricted for use in classical context only +mutable index = 0; +while (index < 10) { + set index += 1; +} + +// Quantum equivalent of a while loop is a repeat-until-success loop. +// Because of the probabilistic nature of quantum computing sometimes +// you want to repeat a certain sequence of operations +// until a specific condition is achieved; you can use this loop to express this. +repeat { + // Your operation here +} +until (success criteria) // This could be a measurement to check if the state is reached +fixup { + // Resetting to the initial conditions, if required +} + + +///////////////////////////////////// +// 4. Putting it all together + +// Q# code is written in operations and functions +operation ApplyXGate(source : Qubit) : Unit { + X(source); +} + +// If the operation implements a unitary transformation, you can define +// adjoint and controlled variants of it. +// The easiest way to do that is to add "is Adj + Ctl" after Unit. +// This will tell the compiler to generate the variants automatically. +operation ApplyXGateCA (source : Qubit) : Unit is Adj + Ctl { + X(source); +} + +// Now you can call Adjoint ApplyXGateCA and Controlled ApplyXGateCA. + + +// To run Q# code, you can put @EntryPoint() before the operation you want to run first +@EntryPoint() +operation XGateDemo() : Unit { + using (q = Qubit()) { + ApplyXGate(q); + } +} + +// Here is a simple example: a quantum random number generator. +// We will generate a classical array of random bits using quantum code. +@EntryPoint() +operation QRNGDemo() : Unit { + mutable bits = new Int[5]; // Array we'll use to store bits + using (q = Qubit()) { // Allocate a qubit + for (i in 0 .. 4) { // Generate each bit independently + H(q); // Hadamard gate sets equal superposition + let result = M(q); // Measure qubit gets 0|1 with 50/50 prob + let bit = result == Zero ? 0 | 1; // Convert measurement result to integer + set bits w/= i <- bit; // Write generated bit to an array + } + } + Message($"{bits}"); // Print the result +} +``` + + +## Further Reading + +The [Quantum Katas][1] offer great self-paced tutorials and programming exercises to learn quantum computing and Q#. + +[Q# Documentation][2] is official Q# documentation, including language reference and user guides. + +[1]: https://github.com/microsoft/QuantumKatas +[2]: https://docs.microsoft.com/quantum/ diff --git a/r.html.markdown b/r.html.markdown index 3e855602..a063cc2f 100644 --- a/r.html.markdown +++ b/r.html.markdown @@ -4,6 +4,7 @@ contributors: - ["e99n09", "http://github.com/e99n09"] - ["isomorphismes", "http://twitter.com/isomorphisms"] - ["kalinn", "http://github.com/kalinn"] + - ["mribeirodantas", "http://github.com/mribeirodantas"] filename: learnr.r --- @@ -11,7 +12,7 @@ R is a statistical computing language. It has lots of libraries for uploading an ```r -# Comments start with number symbols. +# Comments start with hash signs, also known as number symbols (#). # You can't make multi-line comments, # but you can stack multiple comments like so. @@ -29,13 +30,13 @@ R is a statistical computing language. It has lots of libraries for uploading an # R without understanding anything about programming. Do not worry # about understanding everything the code does. Just enjoy! -data() # browse pre-loaded data sets -data(rivers) # get this one: "Lengths of Major North American Rivers" -ls() # notice that "rivers" now appears in the workspace -head(rivers) # peek at the data set +data() # browse pre-loaded data sets +data(rivers) # get this one: "Lengths of Major North American Rivers" +ls() # notice that "rivers" now appears in the workspace +head(rivers) # peek at the data set # 735 320 325 392 524 450 -length(rivers) # how many rivers were measured? +length(rivers) # how many rivers were measured? # 141 summary(rivers) # what are some summary statistics? # Min. 1st Qu. Median Mean 3rd Qu. Max. @@ -91,14 +92,15 @@ stem(log(rivers)) # Notice that the data are neither normal nor log-normal! # 82 | 2 # make a histogram: -hist(rivers, col="#333333", border="white", breaks=25) # play around with these parameters -hist(log(rivers), col="#333333", border="white", breaks=25) # you'll do more plotting later +hist(rivers, col = "#333333", border = "white", breaks = 25) +hist(log(rivers), col = "#333333", border = "white", breaks = 25) +# play around with these parameters, you'll do more plotting later # Here's another neat data set that comes pre-loaded. R has tons of these. data(discoveries) -plot(discoveries, col="#333333", lwd=3, xlab="Year", +plot(discoveries, col = "#333333", lwd = 3, xlab = "Year", main="Number of important discoveries per year") -plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year", +plot(discoveries, col = "#333333", lwd = 3, type = "h", xlab = "Year", main="Number of important discoveries per year") # Rather than leaving the default ordering (by year), @@ -109,7 +111,7 @@ sort(discoveries) # [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 # [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 -stem(discoveries, scale=2) +stem(discoveries, scale = 2) # # The decimal point is at the | # @@ -134,7 +136,7 @@ summary(discoveries) # 0.0 2.0 3.0 3.1 4.0 12.0 # Roll a die a few times -round(runif(7, min=.5, max=6.5)) +round(runif(7, min = .5, max = 6.5)) # 1 4 6 1 4 6 4 # Your numbers will differ from mine unless we set the same random.seed(31337) @@ -157,69 +159,68 @@ rnorm(9) # INTEGERS # Long-storage integers are written with L -5L # 5 -class(5L) # "integer" +5L # 5 +class(5L) # "integer" # (Try ?class for more information on the class() function.) # In R, every single value, like 5L, is considered a vector of length 1 -length(5L) # 1 +length(5L) # 1 # You can have an integer vector with length > 1 too: -c(4L, 5L, 8L, 3L) # 4 5 8 3 -length(c(4L, 5L, 8L, 3L)) # 4 -class(c(4L, 5L, 8L, 3L)) # "integer" +c(4L, 5L, 8L, 3L) # 4 5 8 3 +length(c(4L, 5L, 8L, 3L)) # 4 +class(c(4L, 5L, 8L, 3L)) # "integer" # NUMERICS # A "numeric" is a double-precision floating-point number -5 # 5 -class(5) # "numeric" +5 # 5 +class(5) # "numeric" # Again, everything in R is a vector; # you can make a numeric vector with more than one element -c(3,3,3,2,2,1) # 3 3 3 2 2 1 +c(3, 3, 3, 2, 2, 1) # 3 3 3 2 2 1 # You can use scientific notation too -5e4 # 50000 -6.02e23 # Avogadro's number -1.6e-35 # Planck length +5e4 # 50000 +6.02e23 # Avogadro's number +1.6e-35 # Planck length # You can also have infinitely large or small numbers -class(Inf) # "numeric" -class(-Inf) # "numeric" +class(Inf) # "numeric" +class(-Inf) # "numeric" # You might use "Inf", for example, in integrate(dnorm, 3, Inf); # this obviates Z-score tables. # BASIC ARITHMETIC # You can do arithmetic with numbers # Doing arithmetic on a mix of integers and numerics gives you another numeric -10L + 66L # 76 # integer plus integer gives integer -53.2 - 4 # 49.2 # numeric minus numeric gives numeric -2.0 * 2L # 4 # numeric times integer gives numeric -3L / 4 # 0.75 # integer over numeric gives numeric -3 %% 2 # 1 # the remainder of two numerics is another numeric +10L + 66L # 76 # integer plus integer gives integer +53.2 - 4 # 49.2 # numeric minus numeric gives numeric +2.0 * 2L # 4 # numeric times integer gives numeric +3L / 4 # 0.75 # integer over numeric gives numeric +3 %% 2 # 1 # the remainder of two numerics is another numeric # Illegal arithmetic yields you a "not-a-number": -0 / 0 # NaN -class(NaN) # "numeric" +0 / 0 # NaN +class(NaN) # "numeric" # You can do arithmetic on two vectors with length greater than 1, # so long as the larger vector's length is an integer multiple of the smaller -c(1,2,3) + c(1,2,3) # 2 4 6 +c(1, 2, 3) + c(1, 2, 3) # 2 4 6 # Since a single number is a vector of length one, scalars are applied # elementwise to vectors -(4 * c(1,2,3) - 2) / 2 # 1 3 5 +(4 * c(1, 2, 3) - 2) / 2 # 1 3 5 # Except for scalars, use caution when performing arithmetic on vectors with # different lengths. Although it can be done, -c(1,2,3,1,2,3) * c(1,2) # 1 4 3 2 2 6 -# Matching lengths is better practice and easier to read -c(1,2,3,1,2,3) * c(1,2,1,2,1,2) +c(1, 2, 3, 1, 2, 3) * c(1, 2) # 1 4 3 2 2 6 +# Matching lengths is better practice and easier to read most times +c(1, 2, 3, 1, 2, 3) * c(1, 2, 1, 2, 1, 2) # 1 4 3 2 2 6 # CHARACTERS # There's no difference between strings and characters in R -"Horatio" # "Horatio" -class("Horatio") # "character" -class('H') # "character" +"Horatio" # "Horatio" +class("Horatio") # "character" +class("H") # "character" # Those were both character vectors of length 1 # Here is a longer one: -c('alef', 'bet', 'gimmel', 'dalet', 'he') -# => -# "alef" "bet" "gimmel" "dalet" "he" +c("alef", "bet", "gimmel", "dalet", "he") +# => "alef" "bet" "gimmel" "dalet" "he" length(c("Call","me","Ishmael")) # 3 # You can do regex operations on character vectors: -substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " +substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." # R has several built-in character vectors: letters @@ -230,64 +231,61 @@ month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "D # LOGICALS # In R, a "logical" is a boolean -class(TRUE) # "logical" -class(FALSE) # "logical" + +class(TRUE) # "logical" +class(FALSE) # "logical" # Their behavior is normal -TRUE == TRUE # TRUE -TRUE == FALSE # FALSE -FALSE != FALSE # FALSE -FALSE != TRUE # TRUE +TRUE == TRUE # TRUE +TRUE == FALSE # FALSE +FALSE != FALSE # FALSE +FALSE != TRUE # TRUE # Missing data (NA) is logical, too -class(NA) # "logical" +class(NA) # "logical" # Use | and & for logic operations. # OR -TRUE | FALSE # TRUE +TRUE | FALSE # TRUE # AND -TRUE & FALSE # FALSE +TRUE & FALSE # FALSE # Applying | and & to vectors returns elementwise logic operations -c(TRUE,FALSE,FALSE) | c(FALSE,TRUE,FALSE) # TRUE TRUE FALSE -c(TRUE,FALSE,TRUE) & c(FALSE,TRUE,TRUE) # FALSE FALSE TRUE +c(TRUE, FALSE, FALSE) | c(FALSE, TRUE, FALSE) # TRUE TRUE FALSE +c(TRUE, FALSE, TRUE) & c(FALSE, TRUE, TRUE) # FALSE FALSE TRUE # You can test if x is TRUE -isTRUE(TRUE) # TRUE +isTRUE(TRUE) # TRUE # Here we get a logical vector with many elements: -c('Z', 'o', 'r', 'r', 'o') == "Zorro" # FALSE FALSE FALSE FALSE FALSE -c('Z', 'o', 'r', 'r', 'o') == "Z" # TRUE FALSE FALSE FALSE FALSE +c("Z", "o", "r", "r", "o") == "Zorro" # FALSE FALSE FALSE FALSE FALSE +c("Z", "o", "r", "r", "o") == "Z" # TRUE FALSE FALSE FALSE FALSE # FACTORS # The factor class is for categorical data -# Factors can be ordered (like childrens' grade levels) or unordered (like gender) -factor(c("female", "female", "male", NA, "female")) -# female female male <NA> female -# Levels: female male +# Factors can be ordered (like grade levels) or unordered (like colors) +factor(c("blue", "blue", "green", NA, "blue")) +# blue blue green <NA> blue +# Levels: blue green # The "levels" are the values the categorical data can take # Note that missing data does not enter the levels -levels(factor(c("male", "male", "female", NA, "female"))) # "female" "male" +levels(factor(c("green", "green", "blue", NA, "blue"))) # "blue" "green" # If a factor vector has length 1, its levels will have length 1, too -length(factor("male")) # 1 -length(levels(factor("male"))) # 1 +length(factor("green")) # 1 +length(levels(factor("green"))) # 1 # Factors are commonly seen in data frames, a data structure we will cover later -data(infert) # "Infertility after Spontaneous and Induced Abortion" +data(infert) # "Infertility after Spontaneous and Induced Abortion" levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" # NULL # "NULL" is a weird one; use it to "blank out" a vector -class(NULL) # NULL +class(NULL) # NULL parakeet = c("beak", "feathers", "wings", "eyes") -parakeet -# => -# [1] "beak" "feathers" "wings" "eyes" +parakeet # "beak" "feathers" "wings" "eyes" parakeet <- NULL -parakeet -# => -# NULL +parakeet # NULL # TYPE COERCION # Type-coercion is when you force a value to take on a different type -as.character(c(6, 8)) # "6" "8" -as.logical(c(1,0,1,1)) # TRUE FALSE TRUE TRUE +as.character(c(6, 8)) # "6" "8" +as.logical(c(1,0,1,1)) # TRUE FALSE TRUE TRUE # If you put elements of different types into a vector, weird coercions happen: -c(TRUE, 4) # 1 4 -c("dog", TRUE, 4) # "dog" "TRUE" "4" +c(TRUE, 4) # 1 4 +c("dog", TRUE, 4) # "dog" "TRUE" "4" as.numeric("Bilbo") # => # [1] NA @@ -309,14 +307,15 @@ as.numeric("Bilbo") # VARIABLES # Lots of way to assign stuff: -x = 5 # this is possible -y <- "1" # this is preferred -TRUE -> z # this works but is weird +x = 5 # this is possible +y <- "1" # this is preferred traditionally +TRUE -> z # this works but is weird +# Refer to the Internet for the behaviors and preferences about them. # LOOPS # We've got for loops for (i in 1:4) { - print(i) + print(i) } # We've got while loops a <- 10 @@ -341,11 +340,11 @@ if (4 > 3) { # FUNCTIONS # Defined like so: jiggle <- function(x) { - x = x + rnorm(1, sd=.1) #add in a bit of (controlled) noise + x = x + rnorm(1, sd=.1) # add in a bit of (controlled) noise return(x) } # Called like any other R function: -jiggle(5) # 5±ε. After set.seed(2716057), jiggle(5)==5.005043 +jiggle(5) # 5±ε. After set.seed(2716057), jiggle(5)==5.005043 @@ -357,39 +356,39 @@ jiggle(5) # 5±ε. After set.seed(2716057), jiggle(5)==5.005043 # Let's start from the very beginning, and with something you already know: vectors. vec <- c(8, 9, 10, 11) -vec # 8 9 10 11 +vec # 8 9 10 11 # We ask for specific elements by subsetting with square brackets # (Note that R starts counting from 1) -vec[1] # 8 -letters[18] # "r" -LETTERS[13] # "M" -month.name[9] # "September" -c(6, 8, 7, 5, 3, 0, 9)[3] # 7 +vec[1] # 8 +letters[18] # "r" +LETTERS[13] # "M" +month.name[9] # "September" +c(6, 8, 7, 5, 3, 0, 9)[3] # 7 # We can also search for the indices of specific components, -which(vec %% 2 == 0) # 1 3 +which(vec %% 2 == 0) # 1 3 # grab just the first or last few entries in the vector, -head(vec, 1) # 8 -tail(vec, 2) # 10 11 +head(vec, 1) # 8 +tail(vec, 2) # 10 11 # or figure out if a certain value is in the vector -any(vec == 10) # TRUE +any(vec == 10) # TRUE # If an index "goes over" you'll get NA: -vec[6] # NA +vec[6] # NA # You can find the length of your vector with length() -length(vec) # 4 +length(vec) # 4 # You can perform operations on entire vectors or subsets of vectors -vec * 4 # 16 20 24 28 -vec[2:3] * 5 # 25 30 -any(vec[2:3] == 8) # FALSE +vec * 4 # 32 36 40 44 +vec[2:3] * 5 # 45 50 +any(vec[2:3] == 8) # FALSE # and R has many built-in functions to summarize vectors -mean(vec) # 9.5 -var(vec) # 1.666667 -sd(vec) # 1.290994 -max(vec) # 11 -min(vec) # 8 -sum(vec) # 38 +mean(vec) # 9.5 +var(vec) # 1.666667 +sd(vec) # 1.290994 +max(vec) # 11 +min(vec) # 8 +sum(vec) # 38 # Some more nice built-ins: -5:15 # 5 6 7 8 9 10 11 12 13 14 15 -seq(from=0, to=31337, by=1337) +5:15 # 5 6 7 8 9 10 11 12 13 14 15 +seq(from = 0, to = 31337, by = 1337) # => # [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 # [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 @@ -397,7 +396,7 @@ seq(from=0, to=31337, by=1337) # TWO-DIMENSIONAL (ALL ONE CLASS) # You can make a matrix out of entries all of the same type like so: -mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6)) +mat <- matrix(nrow = 3, ncol = 2, c(1, 2, 3, 4, 5, 6)) mat # => # [,1] [,2] @@ -405,13 +404,13 @@ mat # [2,] 2 5 # [3,] 3 6 # Unlike a vector, the class of a matrix is "matrix", no matter what's in it -class(mat) # => "matrix" +class(mat) # "matrix" "array" # Ask for the first row -mat[1,] # 1 4 +mat[1, ] # 1 4 # Perform operation on the first column -3 * mat[,1] # 3 6 9 +3 * mat[, 1] # 3 6 9 # Ask for a specific cell -mat[3,2] # 6 +mat[3, 2] # 6 # Transpose the whole matrix t(mat) @@ -437,14 +436,14 @@ mat2 # [2,] "2" "cat" # [3,] "3" "bird" # [4,] "4" "dog" -class(mat2) # matrix +class(mat2) # matrix # Again, note what happened! # Because matrices must contain entries all of the same class, # everything got converted to the character class -c(class(mat2[,1]), class(mat2[,2])) +c(class(mat2[, 1]), class(mat2[, 2])) # rbind() sticks vectors together row-wise to make a matrix -mat3 <- rbind(c(1,2,4,5), c(6,7,0,4)) +mat3 <- rbind(c(1, 2, 4, 5), c(6, 7, 0, 4)) mat3 # => # [,1] [,2] [,3] [,4] @@ -458,11 +457,11 @@ mat3 # This data structure is so useful for statistical programming, # a version of it was added to Python in the package "pandas". -students <- data.frame(c("Cedric","Fred","George","Cho","Draco","Ginny"), - c(3,2,2,1,0,-1), - c("H", "G", "G", "R", "S", "G")) +students <- data.frame(c("Cedric", "Fred", "George", "Cho", "Draco", "Ginny"), + c( 3, 2, 2, 1, 0, -1), + c( "H", "G", "G", "R", "S", "G")) names(students) <- c("name", "year", "house") # name the columns -class(students) # "data.frame" +class(students) # "data.frame" students # => # name year house @@ -472,21 +471,22 @@ students # 4 Cho 1 R # 5 Draco 0 S # 6 Ginny -1 G -class(students$year) # "numeric" -class(students[,3]) # "factor" +class(students$year) # "numeric" +class(students[,3]) # "factor" # find the dimensions -nrow(students) # 6 -ncol(students) # 3 -dim(students) # 6 3 -# The data.frame() function converts character vectors to factor vectors -# by default; turn this off by setting stringsAsFactors = FALSE when -# you create the data.frame +nrow(students) # 6 +ncol(students) # 3 +dim(students) # 6 3 +# The data.frame() function used to convert character vectors to factor +# vectors by default; This has changed in R 4.0.0. If your R version is +# older, turn this off by setting stringsAsFactors = FALSE when you +# create the data.frame ?data.frame # There are many twisty ways to subset data frames, all subtly unalike -students$year # 3 2 2 1 0 -1 -students[,2] # 3 2 2 1 0 -1 -students[,"year"] # 3 2 2 1 0 -1 +students$year # 3 2 2 1 0 -1 +students[, 2] # 3 2 2 1 0 -1 +students[, "year"] # 3 2 2 1 0 -1 # An augmented version of the data.frame structure is the data.table # If you're working with huge or panel data, or need to merge a few data @@ -503,19 +503,19 @@ students # note the slightly different print-out # 4: Cho 1 R # 5: Draco 0 S # 6: Ginny -1 G -students[name=="Ginny"] # get rows with name == "Ginny" +students[name == "Ginny"] # get rows with name == "Ginny" # => # name year house # 1: Ginny -1 G -students[year==2] # get rows with year == 2 +students[year == 2] # get rows with year == 2 # => # name year house # 1: Fred 2 G # 2: George 2 G # data.table makes merging two data sets easy # let's make another data.table to merge with students -founders <- data.table(house=c("G","H","R","S"), - founder=c("Godric","Helga","Rowena","Salazar")) +founders <- data.table(house = c("G" , "H" , "R" , "S"), + founder = c("Godric", "Helga", "Rowena", "Salazar")) founders # => # house founder @@ -526,8 +526,8 @@ founders setkey(students, house) setkey(founders, house) students <- founders[students] # merge the two data sets by matching "house" -setnames(students, c("house","houseFounderName","studentName","year")) -students[,order(c("name","year","house","houseFounderName")), with=F] +setnames(students, c("house", "houseFounderName", "studentName", "year")) +students[, order(c("name", "year", "house", "houseFounderName")), with = F] # => # studentName year house houseFounderName # 1: Fred 2 G Godric @@ -538,7 +538,7 @@ students[,order(c("name","year","house","houseFounderName")), with=F] # 6: Draco 0 S Salazar # data.table makes summary tables easy -students[,sum(year),by=house] +students[, sum(year), by = house] # => # house V1 # 1: G 3 @@ -571,7 +571,7 @@ students[studentName != "Draco"] # 5: R Cho 1 # Using data.frame: students <- as.data.frame(students) -students[students$house != "G",] +students[students$house != "G", ] # => # house houseFounderName studentName year # 4 H Helga Cedric 3 @@ -583,13 +583,13 @@ students[students$house != "G",] # Arrays creates n-dimensional tables # All elements must be of the same type # You can make a two-dimensional table (sort of like a matrix) -array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) +array(c(c(1, 2, 4, 5), c(8, 9, 3, 6)), dim = c(2, 4)) # => # [,1] [,2] [,3] [,4] # [1,] 1 4 8 3 # [2,] 2 5 9 6 # You can use array to make three-dimensional matrices too -array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) +array(c(c(c(2, 300, 4), c(8, 9, 0)), c(c(5, 60, 0), c(66, 7, 847))), dim = c(3, 2, 2)) # => # , , 1 # @@ -609,7 +609,7 @@ array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) # Finally, R has lists (of vectors) list1 <- list(time = 1:40) -list1$price = c(rnorm(40,.5*list1$time,4)) # random +list1$price = c(rnorm(40, .5*list1$time, 4)) # random list1 # You can get items in the list like so list1$time # one way @@ -682,7 +682,7 @@ write.csv(pets, "pets2.csv") # to make a new .csv file ######################### # Linear regression! -linearModel <- lm(price ~ time, data = list1) +linearModel <- lm(price ~ time, data = list1) linearModel # outputs result of regression # => # Call: @@ -719,7 +719,7 @@ summary(linearModel)$coefficients # another way to extract results # Estimate Std. Error t value Pr(>|t|) # (Intercept) 0.1452662 1.50084246 0.09678975 9.234021e-01 # time 0.4943490 0.06379348 7.74920901 2.440008e-09 -summary(linearModel)$coefficients[,4] # the p-values +summary(linearModel)$coefficients[, 4] # the p-values # => # (Intercept) time # 9.234021e-01 2.440008e-09 @@ -728,8 +728,7 @@ summary(linearModel)$coefficients[,4] # the p-values # Logistic regression set.seed(1) list1$success = rbinom(length(list1$time), 1, .5) # random binary -glModel <- glm(success ~ time, data = list1, - family=binomial(link="logit")) +glModel <- glm(success ~ time, data = list1, family=binomial(link="logit")) glModel # outputs result of logistic regression # => # Call: glm(formula = success ~ time, @@ -745,8 +744,10 @@ glModel # outputs result of logistic regression summary(glModel) # more verbose output from the regression # => # Call: -# glm(formula = success ~ time, -# family = binomial(link = "logit"), data = list1) +# glm( +# formula = success ~ time, +# family = binomial(link = "logit"), +# data = list1) # Deviance Residuals: # Min 1Q Median 3Q Max @@ -780,7 +781,7 @@ plot(linearModel) # Histograms! hist(rpois(n = 10000, lambda = 5), col = "thistle") # Barplots! -barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) +barplot(c(1, 4, 5, 1, 2), names.arg = c("red", "blue", "purple", "green", "yellow")) # GGPLOT2 # But these are not even the prettiest of R's plots @@ -788,10 +789,10 @@ barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) install.packages("ggplot2") require(ggplot2) ?ggplot2 -pp <- ggplot(students, aes(x=house)) +pp <- ggplot(students, aes(x = house)) pp + geom_bar() ll <- as.data.table(list1) -pp <- ggplot(ll, aes(x=time,price)) +pp <- ggplot(ll, aes(x = time, price)) pp + geom_point() # ggplot2 has excellent documentation (available http://docs.ggplot2.org/current/) diff --git a/racket.html.markdown b/racket.html.markdown index 60a895e0..6c40c3c8 100644 --- a/racket.html.markdown +++ b/racket.html.markdown @@ -117,16 +117,16 @@ some-var ; => 5 ;; let* is like let, but allows you to use previous bindings in creating later bindings (let* ([x 1] [y (+ x 1)]) - (* x y)) + (* x y)) ;; finally, letrec allows you to define recursive and mutually recursive functions (letrec ([is-even? (lambda (n) - (or (zero? n) - (is-odd? (sub1 n))))] - [is-odd? (lambda (n) - (and (not (zero? n)) - (is-even? (sub1 n))))]) - (is-odd? 11)) + (or (zero? n) + (is-odd? (sub1 n))))] + [is-odd? (lambda (n) + (and (not (zero? n)) + (is-even? (sub1 n))))]) + (is-odd? 11)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 3. Structs and Collections @@ -413,7 +413,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (loop 5) ; => i=5, i=6, ... ;; Similarly, with a named let -(let loop ((i 0)) +(let loop ([i 0]) (when (< i 10) (printf "i=~a\n" i) (loop (add1 i)))) ; => i=0, i=1, ... @@ -441,17 +441,19 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (for ([i (in-set (set 'x 'y 'z))]) (displayln i)) -(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))]) +(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3))]) (printf "key:~a value:~a\n" k v)) ;;; More Complex Iterations ;; Parallel scan of multiple sequences (stops on shortest) -(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j)) +(for ([i 10] [j '(x y z)]) + (printf "~a:~a\n" i j)) ; => 0:x 1:y 2:z ;; Nested loops -(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j)) +(for* ([i 2] [j '(x y z)]) + (printf "~a:~a\n" i j)) ; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z ;; Conditions @@ -663,8 +665,7 @@ vec ; => #(1 2 3 4) (define amount 0) (define (deposit a) (set! amount (+ amount a))) - (define (balance) amount) - ) + (define (balance) amount)) (require 'bank-account) (deposit 5) diff --git a/perl6-pod.html.markdown b/raku-pod.html.markdown index 80a501b8..b008beab 100644 --- a/perl6-pod.html.markdown +++ b/raku-pod.html.markdown @@ -5,9 +5,9 @@ contributors: filename: learnpod.pod6 --- -Pod is an easy-to-use and purely descriptive mark-up language, +Pod is an easy-to-use and purely descriptive mark-up language, with no presentational components. Besides its use for documenting -Raku Perl 6 programs and modules, Pod can be utilized to write language +Raku programs and modules, Pod can be utilized to write language documentation, blogs, and other types of document composition as well. Pod documents can be easily converted to HTML and many other formats @@ -49,12 +49,12 @@ generate documentation. ``` =begin pod -A very simple Raku Perl 6 Pod document. All the other directives go here! +A very simple Raku Pod document. All the other directives go here! =end pod ``` -Pod documents usually coexist with Raku Perl 6 code. If by themselves, +Pod documents usually coexist with Raku code. If by themselves, Pod files often have the `.pod6` suffix. Moving forward, it's assumed that the constructs being discussed are surrounded by the `=begin pod ... =end pod` directives. @@ -65,7 +65,7 @@ directives. Text can be easily styled as bold, italic, underlined or verbatim (for code formatting) using the following formatting codes: `B<>`, `I<>`, `U<>` -and `C<>`. +and `C<>`. ``` B<This text is in Bold.> @@ -83,7 +83,7 @@ just a single capital letter followed immediately by a set of single or double angle brackets. The Unicode variant («») of the angle brackets can also be used. -### Headings +### Headings Headings are created by using the `=headN` directive where `N` is the heading level. @@ -145,7 +145,7 @@ Unordered lists can be created using the `=item` directive. ``` Sublists are achieved with items at each level specified using the `=item1`, -`=item2`, `=item3`, `...`, `=itemN` etc. directives. The `=item` directive +`=item2`, `=item3`, `...`, `=itemN` etc. directives. The `=item` directive defaults to `=item1`. ``` @@ -157,7 +157,7 @@ defaults to `=item1`. =item1 Item four ``` -Definition lists that define terms or commands use the `=defn` directive. +Definition lists that define terms or commands use the `=defn` directive. This is equivalent to the `<dl>` element in HTML. ``` @@ -186,14 +186,14 @@ As shown in the [Basic Text Formatting](#basic-text-formatting) section, inline code can be created using the `C<>` code. ``` -In Raku Perl 6, there are several functions/methods to output text. Some of them +In Raku, there are several functions/methods to output text. Some of them are C<print>, C<put> and C<say>. ``` ### Comments -Although Pod blocks are ignored by the Raku Perl 6 compiler, everything -indentified as a Pod block will be read and interpreted by Pod renderers. In +Although Pod blocks are ignored by the Rakudo Raku compiler, everything +identified as a Pod block will be read and interpreted by Pod renderers. In order to prevent Pod blocks from being rendered by any renderer, use the `=comment` directive. @@ -206,21 +206,21 @@ order to prevent Pod blocks from being rendered by any renderer, use the To create inline comments, use the `Z<>` code. ``` -Pod is awesome Z<Of course it is!>. And Raku Perl 6 too! +Pod is awesome Z<Of course it is!>. And Raku too! ``` -Given that the Perl interpreter never executes embedded Pod blocks, +Given that the Raku interpreter never executes embedded Pod blocks, comment blocks can also be used as an alternative form of nestable block -comments in Raku Perl 6. +comments. ### Links Creating links in Pod is quite easy and is done by enclosing them in a `L<>` code. The general format is `L<Label|Url>` with `Label` -being optional. +being optional. ``` -Raku Perl 6 homepage is L<https://perl6.org>. +Raku homepage is L<https://raku.org>. L<Click me!|http://link.org/>. ``` @@ -242,7 +242,7 @@ The Pod specifications are not completely handled properly yet and this includes the handling of table. For simplicity's sake, only one way of constructing tables is shown here. To learn about good practices and see examples of both good and bad tables, please visit -<https://docs.perl6.org/language/tables>. +<https://docs.raku.org/language/tables>. ``` =begin table @@ -287,7 +287,7 @@ For example: Delimited blocks are bounded by `=begin` and `=end` markers, both of which are followed by a valid Pod identifier, which is the `typename` of the block. -The general syntax is +The general syntax is ``` =begin BLOCK_TYPE @@ -304,7 +304,7 @@ Top level heading ``` This type of blocks is useful for creating headings, list items, code blocks, -etc. with multiple paragraphs. For example, +etc. with multiple paragraphs. For example, * a multiline item of a list @@ -345,7 +345,7 @@ say pow(6); #=> 36 Paragraph blocks are introduced by a `=for` marker and terminated by the next Pod directive or the first blank line (which is not considered to be part of the block's contents). The `=for` marker is followed by the -`typename` of the block. The general syntax is +`typename` of the block. The general syntax is ``` =for BLOCK_TYPE @@ -360,10 +360,10 @@ Top level heading ``` ## Configuration Data - + Except for abbreviated blocks, both delimited blocks and paragraph blocks can be supplied with configuration information about their -contents right after the `typename` of the block. Thus the following +contents right after the `typename` of the block. Thus the following are more general syntaxes for these blocks: * Delimited blocks @@ -384,16 +384,16 @@ BLOCK DATA ``` The configuration information is provided in a format akin to the -["colon pair"](https://docs.perl6.org/language/glossary#index-entry-Colon_Pair) -syntax in Raku Perl 6. The following table is a simplified version of the -different ways in which configuration info can be supplied. Please go to -<https://docs.perl6.org/language/pod#Configuration_information> for a more +["colon pair"](https://docs.raku.org/language/glossary#index-entry-Colon_Pair) +syntax in Raku. The following table is a simplified version of the +different ways in which configuration info can be supplied. Please go to +<https://docs.raku.org/language/pod#Configuration_information> for a more thorough treatment of the subject. | Value | Specify with... | Example | | :-------- | :------ | :------ | -| List | :key($elem1, $elem2, ...) | :tags('Pod', 'Perl6') | -| Hash | :key{$key1 => $value1, ...} | :feeds{url => 'perl6.org'} | +| List | :key($elem1, $elem2, ...) | :tags('Pod', 'Raku') | +| Hash | :key{$key1 => $value1, ...} | :feeds{url => 'raku.org'} | | Boolean | :key/:key(True) | :skip-test(True) | | Boolean | :!key/:key(False) | :!skip-test | | String | :key('string') | :nonexec-reason('SyntaxError') | @@ -450,7 +450,7 @@ we get the following output: </pre> This is highly dependent on the format output. For example, while this works -when Pod is converted to HTML, it might not be preserved when converted +when Pod is converted to HTML, it might not be preserved when converted to Markdown. ### Block Pre-configuration @@ -549,48 +549,48 @@ a Pod document, enclose them in a `E<>` code. For example: ``` -Raku Perl 6 makes considerable use of the E<171> and E<187> characters. -Raku Perl 6 makes considerable use of the E<laquo> and E<raquo> characters. +Raku makes considerable use of the E<171> and E<187> characters. +Raku makes considerable use of the E<laquo> and E<raquo> characters. ``` is rendered as: -Raku Perl 6 makes considerable use of the « and » characters. -Raku Perl 6 makes considerable use of the « and » characters. +Raku makes considerable use of the « and » characters. +Raku makes considerable use of the « and » characters. ## Rendering Pod -To generate any output (i.e., Markdown, HTML, Text, etc.), you need to -have the Raku Perl 6 compiler installed. In addition, you must install +To generate any output (i.e., Markdown, HTML, Text, etc.), you need to +have the Rakudo Raku compiler installed. In addition, you must install a module (e.g., `Pod::To::Markdown`, `Pod::To::HTML`, `Pod::To::Text`, etc.) that generates your desired output from Pod. -For instructions about installing Raku Perl 6, -[look here](https://perl6.org/downloads/). +For instructions about installing Rakudo for running raku programs, +[look here](https://raku.org/downloads/). Run the following command to generate a certain output: ``` -perl6 --doc=TARGET input.pod6 > output.html +raku --doc=TARGET input.pod6 > output.html ``` with `TARGET` being `Markdown`, `HTML`, `Text`, etc. Thus to generate Markdown from Pod, run this: ``` -perl6 --doc=Markdown input.pod6 > output.html +raku --doc=Markdown input.pod6 > output.html ``` ## Accessing Pod -In order to access Pod documentation from within a Raku Perl 6 program, +In order to access Pod documentation from within a Raku program, it is required to use the special `=` twigil (e.g., `$=pod`, `$=SYNOPSIS`,etc). -The `$=` construct provides the introspection over the Pod structure, +The `$=` construct provides the introspection over the Pod structure, producing a `Pod::Block` tree root from which it is possible to access the whole structure of the Pod document. -If we place the following piece of Raku Perl 6 code and the Pod documentation +If we place the following piece of Raku code and the Pod documentation in the section [Semantic blocks](#semantic-blocks) in the same file: ``` @@ -615,8 +615,8 @@ AUTHOR DESCRIPTION ``` -## Additional Information +## Additional Information -* <https://docs.perl6.org/language/pod> for the Pod documentation. -* <https://docs.perl6.org/language/tables> for advices about Pod tables. -* <https://design.perl6.org/S26.html> for the Pod specification. +* <https://docs.raku.org/language/pod> for the Pod documentation. +* <https://docs.raku.org/language/tables> for advices about Pod tables. +* <https://design.raku.org/S26.html> for the Pod specification. diff --git a/raku.html.markdown b/raku.html.markdown new file mode 100644 index 00000000..39bc0e51 --- /dev/null +++ b/raku.html.markdown @@ -0,0 +1,2274 @@ +--- +category: language +language: Raku +filename: learnraku.raku +contributors: + - ["vendethiel", "http://github.com/vendethiel"] + - ["Samantha McVey", "https://cry.nu"] +--- + +Raku (formerly Perl 6) is a highly capable, feature-rich programming language +made for at least the next hundred years. + +The primary Raku compiler is called [Rakudo](http://rakudo.org), which runs on +the JVM and the [MoarVM](http://moarvm.com). + +Meta-note: + +* Although the pound sign (`#`) is used for sentences and notes, Pod-styled + comments (more below about them) are used whenever it's convenient. +* `# OUTPUT:` is used to represent the output of a command to any standard + stream. If the output has a newline, it's represented by the `` symbol. + The output is always enclosed by angle brackets (`«` and `»`). +* `#=>` represents the value of an expression, return value of a sub, etc. + In some cases, the value is accompanied by a comment. +* Backticks are used to distinguish and highlight the language constructs + from the text. + +```perl6 +#################################################### +# 0. Comments +#################################################### + +# Single line comments start with a pound sign. + +#`( Multiline comments use #` and a quoting construct. + (), [], {}, 「」, etc, will work. +) + +=for comment +Use the same syntax for multiline comments to embed comments. +for #`(each element in) @array { + put #`(or print element) $_ #`(with newline); +} + +# You can also use Pod-styled comments. For example: + +=comment This is a comment that extends until an empty +newline is found. + +=comment +The comment doesn't need to start in the same line as the directive. + +=begin comment +This comment is multiline. + +Empty newlines can exist here too! +=end comment + +#################################################### +# 1. Variables +#################################################### + +# In Raku, you declare a lexical variable using the `my` keyword: +my $variable; + +# Raku has 3 basic types of variables: scalars, arrays, and hashes. + +# +# 1.1 Scalars +# + +# Scalars represent a single value. They start with the `$` sigil: +my $str = 'String'; + +# Double quotes allow for interpolation (which we'll see later): +my $str2 = "$str"; + +# Variable names can contain but not end with simple quotes and dashes, +# and can contain (and end with) underscores: +my $person's-belongings = 'towel'; # this works! + +my $bool = True; # `True` and `False` are Raku's boolean values. +my $inverse = !$bool; # Invert a bool with the prefix `!` operator. +my $forced-bool = so $str; # And you can use the prefix `so` operator +$forced-bool = ?$str; # to turn its operand into a Bool. Or use `?`. + +# +# 1.2 Arrays and Lists +# + +# Arrays represent multiple values. An array variable starts with the `@` +# sigil. Unlike lists, from which arrays inherit, arrays are mutable. + +my @array = 'a', 'b', 'c'; +# equivalent to: +my @letters = <a b c>; +# In the previous statement, we use the quote-words (`<>`) term for array +# of words, delimited by space. Similar to perl's qw, or Ruby's %w. + +@array = 1, 2, 4; + +# Array indices start at 0. Here the third element is being accessed. +say @array[2]; # OUTPUT: «4» + +say "Interpolate an array using []: @array[]"; +# OUTPUT: «Interpolate an array using []: 1 2 3» + +@array[0] = -1; # Assigning a new value to an array index +@array[0, 1] = 5, 6; # Assigning multiple values + +my @keys = 0, 2; +@array[@keys] = @letters; # Assignment using an array containing index values +say @array; # OUTPUT: «a 6 b» + +# +# 1.3 Hashes, or key-value Pairs. +# + +# Hashes are pairs of keys and values. You can construct a `Pair` object +# using the syntax `key => value`. Hash tables are very fast for lookup, +# and are stored unordered. Keep in mind that keys get "flattened" in hash +# context, and any duplicated keys are deduplicated. +my %hash = 'a' => 1, 'b' => 2; + +# Keys get auto-quoted when the fat comma (`=>`) is used. Trailing commas are +# okay. +%hash = a => 1, b => 2, ; + +# Even though hashes are internally stored differently than arrays, +# Raku allows you to easily create a hash from an even numbered array: +%hash = <key1 value1 key2 value2>; # Or: +%hash = "key1", "value1", "key2", "value2"; + +%hash = key1 => 'value1', key2 => 'value2'; # same result as above + +# You can also use the "colon pair" syntax. This syntax is especially +# handy for named parameters that you'll see later. +%hash = :n(2), # equivalent to `n => 2` + :is-even, # equivalent to `:is-even(True)` or `is-even => True` + :!is-odd, # equivalent to `:is-odd(False)` or `is-odd => False` +; +# The `:` (as in `:is-even`) and `:!` (as `:!is-odd`) constructs are known +# as the `True` and `False` shortcuts respectively. + +# As demonstrated in the example below, you can use {} to get the value from a key. +# If it's a string without spaces, you can actually use the quote-words operator +# (`<>`). Since Raku doesn't have barewords, as Perl does, `{key1}` doesn't work +# though. +say %hash{'n'}; # OUTPUT: «2», gets value associated to key 'n' +say %hash<is-even>; # OUTPUT: «True», gets value associated to key 'is-even' + +#################################################### +# 2. Subroutines +#################################################### + +# Subroutines, or functions as most other languages call them, are +# created with the `sub` keyword. +sub say-hello { say "Hello, world" } + +# You can provide (typed) arguments. If specified, the type will be checked +# at compile-time if possible, otherwise at runtime. +sub say-hello-to( Str $name ) { + say "Hello, $name !"; +} + +# A sub returns the last value of the block. Similarly, the semicolon in +# the last expression can be omitted. +sub return-value { 5 } +say return-value; # OUTPUT: «5» + +sub return-empty { } +say return-empty; # OUTPUT: «Nil» + +# Some control flow structures produce a value, for instance `if`: +sub return-if { + if True { "Truthy" } +} +say return-if; # OUTPUT: «Truthy» + +# Some don't, like `for`: +sub return-for { + for 1, 2, 3 { 'Hi' } +} +say return-for; # OUTPUT: «Nil» + +# Positional arguments are required by default. To make them optional, use +# the `?` after the parameters' names. + +# In the following example, the sub `with-optional` returns `(Any)` (Perl's +# null-like value) if no argument is passed. Otherwise, it returns its argument. +sub with-optional( $arg? ) { + $arg; +} +with-optional; # returns Any +with-optional(); # returns Any +with-optional(1); # returns 1 + +# You can also give provide a default value when they're not passed. Doing +# this make said parameter optional. Required parameters must come before +# optional ones. + +# In the sub `greeting`, the parameter `$type` is optional. +sub greeting( $name, $type = "Hello" ) { + say "$type, $name!"; +} + +greeting("Althea"); # OUTPUT: «Hello, Althea!» +greeting("Arthur", "Good morning"); # OUTPUT: «Good morning, Arthur!» + +# You can also, by using a syntax akin to the one of hashes (yay unified syntax!), +# declared named parameters and thus pass named arguments to a subroutine. +# By default, named parameter are optional and will default to `Any`. +sub with-named( $normal-arg, :$named ) { + say $normal-arg + $named; +} +with-named(1, named => 6); # OUTPUT: «7» + +# There's one gotcha to be aware of, here: If you quote your key, Raku +# won't be able to see it at compile time, and you'll have a single `Pair` +# object as a positional parameter, which means the function subroutine +# `with-named(1, 'named' => 6);` fails. +with-named(2, :named(5)); # OUTPUT: «7» + +# Similar to positional parameters, you can provide your named arguments with +# default values. +sub named-def( :$def = 5 ) { + say $def; +} +named-def; # OUTPUT: «5» +named-def(def => 15); # OUTPUT: «15» + +# In order to make a named parameter mandatory, you can append `!` to the +# parameter. This is the inverse of `?`, which makes a required parameter +# optional. + +sub with-mandatory-named( :$str! ) { + say "$str!"; +} +with-mandatory-named(str => "My String"); # OUTPUT: «My String!» +# with-mandatory-named; # runtime error: "Required named parameter not passed" +# with-mandatory-named(3);# runtime error: "Too many positional parameters passed" + +# If a sub takes a named boolean argument, you can use the same "short boolean" +# hash syntax we discussed earlier. +sub takes-a-bool( $name, :$bool ) { + say "$name takes $bool"; +} +takes-a-bool('config', :bool); # OUTPUT: «config takes True» +takes-a-bool('config', :!bool); # OUTPUT: «config takes False» + +# Since parenthesis can be omitted when calling a subroutine, you need to use +# `&` in order to distinguish between a call to a sub with no arguments and +# the code object. + +# For instance, in this example we must use `&` to store the sub `say-hello` +# (i.e., the sub's code object) in a variable, not a subroutine call. +my &s = &say-hello; +my &other-s = sub { say "Anonymous function!" } + +# A sub can have a "slurpy" parameter, or what one'd call a +# "doesn't-matter-how-many" parameter. This is Raku's way of supporting variadic +# functions. For this, you must use `*@` (slurpy) which will "take everything +# else". You can have as many parameters *before* a slurpy one, but not *after*. +sub as-many($head, *@rest) { + @rest.join(' / ') ~ " !"; +} +say as-many('Happy', 'Happy', 'Birthday'); # OUTPUT: «Happy / Birthday !» +say as-many('Happy', ['Happy', 'Birthday'], 'Day'); # OUTPUT: «Happy / Birthday / Day !» + +# Note that the splat (the *) did not consume the parameter before it. + +# There are other two variations of slurpy parameters in Raku. The previous one +# (namely, `*@`), known as flattened slurpy, flattens passed arguments. The other +# two are `**@` and `+@` known as unflattened slurpy and "single argument rule" +# slurpy respectively. The unflattened slurpy doesn't flatten its listy +# arguments (or Iterable ones). +sub b(**@arr) { @arr.perl.say }; +b(['a', 'b', 'c']); # OUTPUT: «[["a", "b", "c"],]» +b(1, $('d', 'e', 'f'), [2, 3]); # OUTPUT: «[1, ("d", "e", "f"), [2, 3]]» +b(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, [1, 2], ([3, 4], 5)]» + +# On the other hand, the "single argument rule" slurpy follows the "single argument +# rule" which dictates how to handle the slurpy argument based upon context and +# roughly states that if only a single argument is passed and that argument is +# Iterable, that argument is used to fill the slurpy parameter array. In any +# other case, `+@` works like `**@`. +sub c(+@arr) { @arr.perl.say }; +c(['a', 'b', 'c']); # OUTPUT: «["a", "b", "c"]» +c(1, $('d', 'e', 'f'), [2, 3]); # OUTPUT: «[1, ("d", "e", "f"), [2, 3]]» +c(1, [1, 2], ([3, 4], 5)); # OUTPUT: «[1, [1, 2], ([3, 4], 5)]» + +# You can call a function with an array using the "argument list flattening" +# operator `|` (it's not actually the only role of this operator, +# but it's one of them). +sub concat3($a, $b, $c) { + say "$a, $b, $c"; +} +concat3(|@array); # OUTPUT: «a, b, c» + # `@array` got "flattened" as a part of the argument list + +#################################################### +# 3. Containers +#################################################### + +# In Raku, values are actually stored in "containers". The assignment +# operator asks the container on the left to store the value on its right. +# When passed around, containers are marked as immutable which means that, +# in a function, you'll get an error if you try to mutate one of your +# arguments. If you really need to, you can ask for a mutable container by +# using the `is rw` trait. +sub mutate( $n is rw ) { + $n++; # postfix ++ operator increments its argument but returns its old value +} +my $m = 42; +mutate $m; #=> 42, the value is incremented but the old value is returned +say $m; # OUTPUT: «43» + +# This works because we are passing the container $m to the `mutate` sub. +# If we try to just pass a number instead of passing a variable, it won't work +# because there is no container being passed and integers are immutable by +# themselves: + +# mutate 42; # Parameter '$n' expected a writable container, but got Int value + +# Similar error would be obtained, if a bound variable is passed to +# to the subroutine. In Raku, you bind a value to a variable using the binding +# operator `:=`. +my $v := 50; # binding 50 to the variable $v +# mutate $v; # Parameter '$n' expected a writable container, but got Int value + +# If what you want is a copy instead, use the `is copy` trait which will +# cause the argument to be copied and allow you to modify the argument +# inside the routine without modifying the passed argument. + +# A sub itself returns a container, which means it can be marked as `rw`. +# Alternatively, you can explicitly mark the returned container as mutable +# by using `return-rw` instead of `return`. +my $x = 42; +my $y = 45; +sub x-store is rw { $x } +sub y-store { return-rw $y } + +# In this case, the parentheses are mandatory or else Raku thinks that +# `x-store` and `y-store` are identifiers. +x-store() = 52; +y-store() *= 2; + +say $x; # OUTPUT: «52» +say $y; # OUTPUT: «90» + +#################################################### +# 4.Control Flow Structures +#################################################### + +# +# 4.1 if/if-else/if-elsif-else/unless +# + +# Before talking about `if`, we need to know which values are "truthy" +# (represent `True`), and which are "falsey" (represent `False`). Only these +# values are falsey: 0, (), {}, "", Nil, a type (like `Str`, `Int`, etc.) and +# of course, `False` itself. Any other value is truthy. +my $number = 5; +if $number < 5 { + say "Number is less than 5" +} +elsif $number == 5 { + say "Number is equal to 5" +} +else { + say "Number is greater than 5" +} + +unless False { + say "It's not false!"; +} + +# `unless` is the equivalent of `if not (X)` which inverts the sense of a +# conditional statement. However, you cannot use `else` or `elsif` with it. + +# As you can see, you don't need parentheses around conditions. However, you +# do need the curly braces around the "body" block. For example, +# `if (True) say 'It's true';` doesn't work. + +# You can also use their statement modifier (postfix) versions: +say "Quite truthy" if True; # OUTPUT: «Quite truthy» +say "Quite falsey" unless False; # OUTPUT: «Quite falsey» + +# The ternary operator (`??..!!`) is structured as follows `condition ?? +# expression1 !! expression2` and it returns expression1 if the condition is +# true. Otherwise, it returns expression2. +my $age = 30; +say $age > 18 ?? "You are an adult" !! "You are under 18"; +# OUTPUT: «You are an adult» + +# +# 4.2 with/with-else/with-orwith-else/without +# + +# The `with` statement is like `if`, but it tests for definedness rather than +# truth, and it topicalizes on the condition, much like `given` which will +# be discussed later. +my $s = "raku"; +with $s.index("r") { say "Found a at $_" } +orwith $s.index("k") { say "Found c at $_" } +else { say "Didn't find r or k" } + +# Similar to `unless` that checks un-truthiness, you can use `without` to +# check for undefined-ness. +my $input01; +without $input01 { + say "No input given." +} +# OUTPUT: «No input given.» + +# There are also statement modifier versions for both `with` and `without`. +my $input02 = 'Hello'; +say $input02 with $input02; # OUTPUT: «Hello» +say "No input given." without $input02; + +# +# 4.3 given/when, or Raku's switch construct +# + +=begin comment +`given...when` looks like other languages' `switch`, but is much more +powerful thanks to smart matching and Raku's "topic variable", `$_`. + +The topic variable `$_ `contains the default argument of a block, a loop's +current iteration (unless explicitly named), etc. + +`given` simply puts its argument into `$_` (like a block would do), + and `when` compares it using the "smart matching" (`~~`) operator. + +Since other Raku constructs use this variable (as said before, like `for`, +blocks, `with` statement etc), this means the powerful `when` is not only +applicable along with a `given`, but instead anywhere a `$_` exists. + +=end comment + +given "foo bar" { + say $_; # OUTPUT: «foo bar» + + # Don't worry about smart matching yet. Just know `when` uses it. This is + # equivalent to `if $_ ~~ /foo/`. + when /foo/ { + say "Yay !"; + } + + # smart matching anything with `True` is `True`, i.e. (`$a ~~ True`) + # so you can also put "normal" conditionals. For example, this `when` is + # equivalent to this `if`: `if $_ ~~ ($_.chars > 50) {...}` + # which means: `if $_.chars > 50 {...}` + when $_.chars > 50 { + say "Quite a long string !"; + } + + # same as `when *` (using the Whatever Star) + default { + say "Something else" + } +} + +# +# 4.4 Looping constructs +# + +# The `loop` construct is an infinite loop if you don't pass it arguments, but +# can also be a C-style `for` loop: +loop { + say "This is an infinite loop !"; + last; +} +# In the previous example, `last` breaks out of the loop very much +# like the `break` keyword in other languages. + +# The `next` keyword skips to the next iteration, like `continue` in other +# languages. Note that you can also use postfix conditionals, loops, etc. +loop (my $i = 0; $i < 5; $i++) { + next if $i == 3; + say "This is a C-style for loop!"; +} + +# The `for` constructs iterates over a list of elements. +my @odd-array = 1, 3, 5, 7, 9; + +# Accessing the array's elements with the topic variable $_. +for @odd-array { + say "I've got $_ !"; +} + +# Accessing the array's elements with a "pointy block", `->`. +# Here each element is read-only. +for @odd-array -> $variable { + say "I've got $variable !"; +} + +# Accessing the array's elements with a "doubly pointy block", `<->`. +# Here each element is read-write so mutating `$variable` mutates +# that element in the array. +for @odd-array <-> $variable { + say "I've got $variable !"; +} + +# As we saw with `given`, a `for` loop's default "current iteration" variable +# is `$_`. That means you can use `when` in a `for`loop just like you were +# able to in a `given`. +for @odd-array { + say "I've got $_"; + + # This is also allowed. A dot call with no "topic" (receiver) is sent to + # `$_` (topic variable) by default. + .say; + + # This is equivalent to the above statement. + $_.say; +} + +for @odd-array { + # You can... + next if $_ == 3; # Skip to the next iteration (`continue` in C-like lang.) + redo if $_ == 4; # Re-do iteration, keeping the same topic variable (`$_`) + last if $_ == 5; # Or break out of loop (like `break` in C-like lang.) +} + +# The "pointy block" syntax isn't specific to the `for` loop. It's just a way +# to express a block in Raku. +sub long-computation { "Finding factors of large primes" } +if long-computation() -> $result { + say "The result is $result."; +} + +#################################################### +# 5. Operators +#################################################### + +=begin comment +Since Perl languages are very much operator-based languages, Raku +operators are actually just funny-looking subroutines, in syntactic +categories, like infix:<+> (addition) or prefix:<!> (bool not). + +The categories are: + - "prefix": before (like `!` in `!True`). + - "postfix": after (like `++` in `$a++`). + - "infix": in between (like `*` in `4 * 3`). + - "circumfix": around (like `[`-`]` in `[1, 2]`). + - "post-circumfix": around, after another term (like `{`-`}` in + `%hash{'key'}`) + +The associativity and precedence list are explained below. + +Alright, you're set to go! + +=end comment + +# +# 5.1 Equality Checking +# + +# `==` is numeric comparison +say 3 == 4; # OUTPUT: «False» +say 3 != 4; # OUTPUT: «True» + +# `eq` is string comparison +say 'a' eq 'b'; # OUTPUT: «False» +say 'a' ne 'b'; # OUTPUT: «True», not equal +say 'a' !eq 'b'; # OUTPUT: «True», same as above + +# `eqv` is canonical equivalence (or "deep equality") +say (1, 2) eqv (1, 3); # OUTPUT: «False» +say (1, 2) eqv (1, 2); # OUTPUT: «True» +say Int === Int; # OUTPUT: «True» + +# `~~` is the smart match operator which aliases the left hand side to $_ and +# then evaluates the right hand side. +# Here are some common comparison semantics: + +# String or numeric equality +say 'Foo' ~~ 'Foo'; # OUTPUT: «True», if strings are equal. +say 12.5 ~~ 12.50; # OUTPUT: «True», if numbers are equal. + +# Regex - For matching a regular expression against the left side. +# Returns a `Match` object, which evaluates as True if regexp matches. +my $obj = 'abc' ~~ /a/; +say $obj; # OUTPUT: «「a」» +say $obj.WHAT; # OUTPUT: «(Match)» + +# Hashes +say 'key' ~~ %hash; # OUTPUT: «True», if key exists in hash. + +# Type - Checks if left side "is of type" (can check superclasses and roles). +say 1 ~~ Int; # OUTPUT: «True» + +# Smart-matching against a boolean always returns that boolean (and will warn). +say 1 ~~ True; # OUTPUT: «True», smartmatch against True always matches +say False.so ~~ True; # OUTPUT: «True», use .so for truthiness + +# General syntax is `$arg ~~ &bool-returning-function;`. For a complete list +# of combinations, refer to the table at: +# https://docs.raku.org/language/operators#index-entry-smartmatch_operator + +# Of course, you also use `<`, `<=`, `>`, `>=` for numeric comparison. +# Their string equivalent are also available: `lt`, `le`, `gt`, `ge`. +say 3 > 4; # OUTPUT: «False» +say 3 >= 4; # OUTPUT: «False» +say 3 < 4; # OUTPUT: «True» +say 3 <= 4; # OUTPUT: «True» +say 'a' gt 'b'; # OUTPUT: «False» +say 'a' ge 'b'; # OUTPUT: «False» +say 'a' lt 'b'; # OUTPUT: «True» +say 'a' le 'b'; # OUTPUT: «True» + +# +# 5.2 Range constructor +# + +say 3 .. 7; # OUTPUT: «3..7», both included. +say 3 ..^ 7; # OUTPUT: «3..^7», exclude right endpoint. +say 3 ^.. 7; # OUTPUT: «3^..7», exclude left endpoint. +say 3 ^..^ 7; # OUTPUT: «3^..^7», exclude both endpoints. + +# The range 3 ^.. 7 is similar like 4 .. 7 when we only consider integers. +# But when we consider decimals: + +say 3.5 ~~ 4 .. 7; # OUTPUT: «False» +say 3.5 ~~ 3 ^.. 7; # OUTPUT: «True», + +# This is because the range `3 ^.. 7` only excludes anything strictly +# equal to 3. Hence, it contains decimals greater than 3. This could +# mathematically be described as 3.5 ∈ (3,7] or in set notation, +# 3.5 ∈ { x | 3 < x ≤ 7 }. + +say 3 ^.. 7 ~~ 4 .. 7; # OUTPUT: «False» + +# This also works as a shortcut for `0..^N`: +say ^10; # OUTPUT: «^10», which means 0..^10 + +# This also allows us to demonstrate that Raku has lazy/infinite arrays, +# using the Whatever Star: +my @natural = 1..*; # 1 to Infinite! Equivalent to `1..Inf`. + +# You can pass ranges as subscripts and it'll return an array of results. +say @natural[^10]; # OUTPUT: «1 2 3 4 5 6 7 8 9 10», doesn't run out of memory! + +# NOTE: when reading an infinite list, Raku will "reify" the elements +# it needs, then keep them in memory. They won't be calculated more than once. +# It also will never calculate more elements than that are needed. + +# An array subscript can also be a closure. It'll be called with the array's +# length as the argument. The following two examples are equivalent: +say join(' ', @array[15..*]); # OUTPUT: «15 16 17 18 19» +say join(' ', @array[-> $n { 15..$n }]); # OUTPUT: «15 16 17 18 19» + +# NOTE: if you try to do either of those with an infinite array, you'll +# trigger an infinite loop (your program won't finish). + +# You can use that in most places you'd expect, even when assigning to an array: +my @numbers = ^20; + +# Here the numbers increase by 6, like an arithmetic sequence; more on the +# sequence (`...`) operator later. +my @seq = 3, 9 ... * > 95; # 3 9 15 21 27 [...] 81 87 93 99; + +# In this example, even though the sequence is infinite, only the 15 +# needed values will be calculated. +@numbers[5..*] = 3, 9 ... *; +say @numbers; # OUTPUT: «0 1 2 3 4 3 9 15 21 [...] 81 87», only 20 values + +# +# 5.3 and (&&), or (||) +# + +# Here `and` calls `.Bool` on both 3 and 4 and gets `True` so it returns +# 4 since both are `True`. +say (3 and 4); # OUTPUT: «4», which is truthy. +say (3 and 0); # OUTPUT: «0» +say (0 and 4); # OUTPUT: «0» + +# Here `or` calls `.Bool` on `0` and `False` which are both `False` +# so it returns `False` since both are `False`. +say (0 or False); # OUTPUT: «False». + +# Both `and` and `or` have tighter versions which also shortcut circuits. +# They're `&&` and `||` respectively. + +# `&&` returns the first operand that evaluates to `False`. Otherwise, +# it returns the last operand. +my ($a, $b, $c, $d, $e) = 1, 0, False, True, 'pi'; +say $a && $b && $c; # OUTPUT: «0», the first falsey value +say $a && $b && $c; # OUTPUT: «False», the first falsey value +say $a && $d && $e; # OUTPUT: «pi», last operand since everything before is truthy + +# `||` returns the first argument that evaluates to `True`. +say $b || $a || $d; # OUTPUT: «1» +say $e || $d || $a; # OUTPUT: «pi» + +# And because you're going to want them, you also have compound assignment +# operators: +$a *= 2; # multiply and assignment. Equivalent to $a = $a * 2; +$b %%= 5; # divisible by and assignment. Equivalent to $b = $b %% 2; +$c div= 3; # return divisor and assignment. Equivalent to $c = $c div 3; +$d mod= 4; # return remainder and assignment. Equivalent to $d = $d mod 4; +@array .= sort; # calls the `sort` method and assigns the result back + +#################################################### +# 6. More on subs! +#################################################### + +# As we said before, Raku has *really* powerful subs. We're going +# to see a few more key concepts that make them better than in any +# other language :-). + +# +# 6.1 Unpacking! +# + +# Unpacking is the ability to "extract" arrays and keys +# (AKA "destructuring"). It'll work in `my`s and in parameter lists. +my ($f, $g) = 1, 2; +say $f; # OUTPUT: «1» +my ($, $, $h) = 1, 2, 3; # keep the non-interesting values anonymous (`$`) +say $h; # OUTPUT: «3» + +my ($head, *@tail) = 1, 2, 3; # Yes, it's the same as with "slurpy subs" +my (*@small) = 1; + +sub unpack_array( @array [$fst, $snd] ) { + say "My first is $fst, my second is $snd! All in all, I'm @array[]."; + # (^ remember the `[]` to interpolate the array) +} +unpack_array(@tail); +# OUTPUT: «My first is 2, my second is 3! All in all, I'm 2 3.» + +# If you're not using the array itself, you can also keep it anonymous, +# much like a scalar: +sub first-of-array( @ [$fst] ) { $fst } +first-of-array(@small); #=> 1 + +# However calling `first-of-array(@tail);` will throw an error ("Too many +# positional parameters passed"), which means the `@tail` has too many +# elements. + +# You can also use a slurpy parameter. You could keep `*@rest` anonymous +# Here, `@rest` is `(3,)`, since `$fst` holds the `2`. This results +# since the length (.elems) of `@rest` is 1. +sub slurp-in-array(@ [$fst, *@rest]) { + say $fst + @rest.elems; +} +slurp-in-array(@tail); # OUTPUT: «3» + +# You could even extract on a slurpy (but it's pretty useless ;-).) +sub fst(*@ [$fst]) { # or simply: `sub fst($fst) { ... }` + say $fst; +} +fst(1); # OUTPUT: «1» + +# Calling `fst(1, 2);` will throw an error ("Too many positional parameters +# passed") though. After all, the `fst` sub declares only a single positional +# parameter. + +# You can also destructure hashes (and classes, which you'll learn about later). +# The syntax is basically the same as +# `%hash-name (:key($variable-to-store-value-in))`. +# The hash can stay anonymous if you only need the values you extracted. + +# In order to call the function, you must supply a hash wither created with +# curly braces or with `%()` (recommended). Alternatively, you can pass +# a variable that contains a hash. + +sub key-of( % (:value($val), :qua($qua)) ) { + say "Got value $val, $qua time" ~~ + $qua == 1 ?? '' !! 's'; +} + +my %foo-once = %(value => 'foo', qua => 1); +key-of({value => 'foo', qua => 2}); # OUTPUT: «Got val foo, 2 times.» +key-of(%(value => 'foo', qua => 0)); # OUTPUT: «Got val foo, 0 times.» +key-of(%foo-once); # OUTPUT: «Got val foo, 1 time.» + +# The last expression of a sub is returned automatically (though you may +# indicate explicitly by using the `return` keyword, of course): +sub next-index( $n ) { + $n + 1; +} +my $new-n = next-index(3); # $new-n is now 4 + +# This is true for everything, except for the looping constructs (due to +# performance reasons): there's no reason to build a list if we're just going to +# discard all the results. If you still want to build one, you can use the +# `do` statement prefix or the `gather` prefix, which we'll see later: + +sub list-of( $n ) { + do for ^$n { $_ } +} +my @list3 = list-of(3); #=> (0, 1, 2) + +# +# 6.2 Lambdas (or anonymous subroutines) +# + +# You can create a lambda by using a pointy block (`-> {}`), a +# block (`{}`) or creating a `sub` without a name. + +my &lambda1 = -> $argument { + "The argument passed to this lambda is $argument" +} + +my &lambda2 = { + "The argument passed to this lambda is $_" +} + +my &lambda3 = sub ($argument) { + "The argument passed to this lambda is $argument" +} + +# Both pointy blocks and blocks are pretty much the same thing, except that +# the former can take arguments, and that the latter can be mistaken as +# a hash by the parser. That being said, blocks can declare what's known +# as placeholders parameters through the twigils `$^` (for positional +# parameters) and `$:` (for named parameters). More on them later on. + +my &mult = { $^numbers * $:times } +say mult 4, :times(6); #=> «24» + +# Both pointy blocks and blocks are quite versatile when working with functions +# that accepts other functions such as `map`, `grep`, etc. For example, +# we add 3 to each value of an array using the `map` function with a lambda: +my @nums = 1..4; +my @res1 = map -> $v { $v + 3 }, @nums; # pointy block, explicit parameter +my @res2 = map { $_ + 3 }, @nums; # block using an implicit parameter +my @res3 = map { $^val + 3 }, @nums; # block with placeholder parameter + +# A sub (`sub {}`) has different semantics than a block (`{}` or `-> {}`): +# A block doesn't have a "function context" (though it can have arguments), +# which means that if you return from it, you're going to return from the +# parent function. + +# Compare: +sub is-in( @array, $elem ) { + say map({ return True if $_ == $elem }, @array); + say 'Hi'; +} + +# with: +sub truthy-array( @array ) { + say map sub ($i) { $i ?? return True !! return False }, @array; + say 'Hi'; +} + +# In the `is-in` sub, the block will `return` out of the `is-in` sub once the +# condition evaluates to `True`, the loop won't be run anymore and the +# following statement won't be executed. The last statement is only executed +# if the block never returns. + +# On the contrary, the `truthy-array` sub will produce an array of `True` and +# `False`, which will printed, and always execute the last execute statement. +# Thus, the `return` only returns from the anonymous `sub` + +# The `anon` declarator can be used to create an anonymous sub from a +# regular subroutine. The regular sub knows its name but its symbol is +# prevented from getting installed in the lexical scope, the method table +# and everywhere else. +my $anon-sum = anon sub summation(*@a) { [+] @a } +say $anon-sum.name; # OUTPUT: «summation» +say $anon-sum(2, 3, 5); # OUTPUT: «10» +#say summation; # Error: Undeclared routine: ... + +# You can also use the Whatever Star to create an anonymous subroutine. +# (it'll stop at the furthest operator in the current expression). +# The following is the same as `{$_ + 3 }`, `-> { $a + 3 }`, +# `sub ($a) { $a + 3 }`, or even `{$^a + 3}` (more on this later). +my @arrayplus3v0 = map * + 3, @nums; + +# The following is the same as `-> $a, $b { $a + $b + 3 }`, +# `sub ($a, $b) { $a + $b + 3 }`, or `{ $^a + $^b + 3 }` (more on this later). +my @arrayplus3v1 = map * + * + 3, @nums; + +say (*/2)(4); # OUTPUT: «2», immediately execute the Whatever function created. +say ((*+3)/5)(5); # OUTPUT: «1.6», it works even in parens! + +# But if you need to have more than one argument (`$_`) in a block (without +# wanting to resort to `-> {}`), you can also either `$^` and `$:` which +# declared placeholder parameters or self-declared positional/named parameters. +say map { $^a + $^b + 3 }, @nums; + +# which is equivalent to the following which uses a `sub`: +map sub ($a, $b) { $a + $b + 3 }, @nums; + +# Placeholder parameters are sorted lexicographically so the following two +# statements are equivalent: +say sort { $^b <=> $^a }, @nums; +say sort -> $a, $b { $b <=> $a }, @nums; + +# +# 6.3 Multiple Dispatch +# + +# Raku can decide which variant of a `sub` to call based on the type of the +# arguments, or on arbitrary preconditions, like with a type or `where`: + +# with types: +multi sub sayit( Int $n ) { # note the `multi` keyword here + say "Number: $n"; +} +multi sayit( Str $s ) { # a multi is a `sub` by default + say "String: $s"; +} +sayit "foo"; # OUTPUT: «String: foo» +sayit 25; # OUTPUT: «Number: 25» +sayit True; # fails at *compile time* with "calling 'sayit' will never + # work with arguments of types ..." + +# with arbitrary preconditions (remember subsets?): +multi is-big(Int $n where * > 50) { "Yes!" } # using a closure +multi is-big(Int $n where {$_ > 50}) { "Yes!" } # similar to above +multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching +multi is-big(Int $) { "No" } + +subset Even of Int where * %% 2; +multi odd-or-even(Even) { "Even" } # Using the type. We don't name the argument. +multi odd-or-even($) { "Odd" } # "everything else" hence the $ variable + +# You can even dispatch based on the presence of positional and named arguments: +multi with-or-without-you($with) { + say "I wish I could but I can't"; +} +multi with-or-without-you(:$with) { + say "I can live! Actually, I can't."; +} +multi with-or-without-you { + say "Definitely can't live."; +} + +# This is very, very useful for many purposes, like `MAIN` subs (covered +# later), and even the language itself uses it in several places. + +# For example, the `is` trait is actually a `multi sub` named `trait_mod:<is>`, +# and it works off that. Thus, `is rw`, is simply a dispatch to a function with +# this signature `sub trait_mod:<is>(Routine $r, :$rw!) {}` + +#################################################### +# 7. About types... +#################################################### + +# Raku is gradually typed. This means you can specify the type of your +# variables/arguments/return types, or you can omit the type annotations in +# in which case they'll default to `Any`. Obviously you get access to a few +# base types, like `Int` and `Str`. The constructs for declaring types are +# `subset`, `class`, `role`, etc. which you'll see later. + +# For now, let us examine `subset` which is a "sub-type" with additional +# checks. For example, "a very big integer is an `Int` that's greater than 500". +# You can specify the type you're subtyping (by default, `Any`), and add +# additional checks with the `where` clause. +subset VeryBigInteger of Int where * > 500; + +# Or the set of the whole numbers: +subset WholeNumber of Int where * >= 0; +my WholeNumber $whole-six = 6; # OK +#my WholeNumber $nonwhole-one = -1; # Error: type check failed... + +# Or the set of Positive Even Numbers whose Mod 5 is 1. Notice we're +# using the previously defined WholeNumber subset. +subset PENFO of WholeNumber where { $_ %% 2 and $_ mod 5 == 1 }; +my PENFO $yes-penfo = 36; # OK +#my PENFO $no-penfo = 2; # Error: type check failed... + +#################################################### +# 8. Scoping +#################################################### + +# In Raku, unlike many scripting languages, (such as Python, Ruby, PHP), +# you must declare your variables before using them. The `my` declarator +# we've used so far uses "lexical scoping". There are a few other declarators, +# (`our`, `state`, ..., ) which we'll see later. This is called +# "lexical scoping", where in inner blocks, you can access variables from +# outer blocks. + +my $file_scoped = 'Foo'; +sub outer { + my $outer_scoped = 'Bar'; + sub inner { + say "$file_scoped $outer_scoped"; + } + &inner; # return the function +} +outer()(); # OUTPUT: «Foo Bar» + +# As you can see, `$file_scoped` and `$outer_scoped` were captured. +# But if we were to try and use `$outer_scoped` outside the `outer` sub, +# the variable would be undefined (and you'd get a compile time error). + +#################################################### +# 9. Twigils +#################################################### + +# There are many special `twigils` (composed sigils) in Raku. Twigils +# define a variable's scope. +# The `*` and `?` twigils work on standard variables: +# * for dynamic variables +# ? for compile-time variables +# +# The `!` and the `.` twigils are used with Raku's objects: +# ! for attributes (instance attribute) +# . for methods (not really a variable) + +# +# `*` twigil: Dynamic Scope +# + +# These variables use the `*` twigil to mark dynamically-scoped variables. +# Dynamically-scoped variables are looked up through the caller, not through +# the outer scope. + +my $*dyn_scoped_1 = 1; +my $*dyn_scoped_2 = 10; + +sub say_dyn { + say "$*dyn_scoped_1 $*dyn_scoped_2"; +} + +sub call_say_dyn { + # Defines $*dyn_scoped_1 only for this sub. + my $*dyn_scoped_1 = 25; + + # Will change the value of the file scoped variable. + $*dyn_scoped_2 = 100; + + # $*dyn_scoped 1 and 2 will be looked for in the call. + say_dyn(); # OUTPUT: «25 100» + + # The call to `say_dyn` uses the value of $*dyn_scoped_1 from inside + # this sub's lexical scope even though the blocks aren't nested (they're + # call-nested). +} +say_dyn(); # OUTPUT: «1 10» + +# Uses $*dyn_scoped_1 as defined in `call_say_dyn` even though we are calling it +# from outside. +call_say_dyn(); # OUTPUT: «25 100» + +# We changed the value of $*dyn_scoped_2 in `call_say_dyn` so now its +# value has changed. +say_dyn(); # OUTPUT: «1 100» + +# TODO: Add information about remaining twigils + +#################################################### +# 10. Object Model +#################################################### + +# To call a method on an object, add a dot followed by the method name: +# `$object.method` + +# Classes are declared with the `class` keyword. Attributes are declared +# with the `has` keyword, and methods declared with the `method` keyword. + +# Every attribute that is private uses the `!` twigil. For example: `$!attr`. +# Immutable public attributes use the `.` twigil which creates a read-only +# method named after the attribute. In fact, declaring an attribute with `.` +# is equivalent to declaring the same attribute with `!` and then creating +# a read-only method with the attribute's name. However, this is done for us +# by Raku automatically. The easiest way to remember the `$.` twigil is +# by comparing it to how methods are called. + +# Raku's object model ("SixModel") is very flexible, and allows you to +# dynamically add methods, change semantics, etc... Unfortunately, these will +# not all be covered here, and you should refer to: +# https://docs.raku.org/language/objects.html. + +class Human { + has Str $.name; # `$.name` is immutable but with an accessor method. + has Str $.bcountry; # Use `$!bcountry` to modify it inside the class. + has Str $.ccountry is rw; # This attribute can be modified from outside. + has Int $!age = 0; # A private attribute with default value. + + method birthday { + $!age += 1; # Add a year to human's age + } + + method get-age { + return $!age; + } + + # This method is private to the class. Note the `!` before the + # method's name. + method !do-decoration { + return "$!name born in $!bcountry and now lives in $!ccountry." + } + + # This method is public, just like `birthday` and `get-age`. + method get-info { + # Invoking a method on `self` inside the class. + # Use `self!priv-method` for private method. + say self!do-decoration; + + # Use `self.public-method` for public method. + say "Age: ", self.get-age; + } +}; + +# Create a new instance of Human class. +# NOTE: Only attributes declared with the `.` twigil can be set via the +# default constructor (more later on). This constructor only accepts named +# arguments. +my $person1 = Human.new( + name => "Jord", + bcountry => "Togo", + ccountry => "Togo" +); + +# Make human 10 years old. +$person1.birthday for 1..10; + +say $person1.name; # OUTPUT: «Jord» +say $person1.bcountry; # OUTPUT: «Togo» +say $person1.ccountry; # OUTPUT: «Togo» +say $person1.get-age; # OUTPUT: «10» + +# This fails, because the `has $.bcountry`is immutable. Jord can't change +# his birthplace. +# $person1.bcountry = "Mali"; + +# This works because the `$.ccountry` is mutable (`is rw`). Now Jord's +# current country is France. +$person1.ccountry = "France"; + +# Calling methods on the instance objects. +$person1.birthday; #=> 1 +$person1.get-info; #=> Jord born in Togo and now lives in France. Age: 10 +# $person1.do-decoration; # This fails since the method `do-decoration` is private. + +# +# 10.1 Object Inheritance +# + +# Raku also has inheritance (along with multiple inheritance). While +# methods are inherited, submethods are not. Submethods are useful for +# object construction and destruction tasks, such as `BUILD`, or methods that +# must be overridden by subtypes. We will learn about `BUILD` later on. + +class Parent { + has $.age; + has $.name; + + # This submethod won't be inherited by the Child class. + submethod favorite-color { + say "My favorite color is Blue"; + } + + # This method is inherited + method talk { say "Hi, my name is $!name" } +} + +# Inheritance uses the `is` keyword +class Child is Parent { + method talk { say "Goo goo ga ga" } + # This shadows Parent's `talk` method. + # This child hasn't learned to speak yet! +} + +my Parent $Richard .= new(age => 40, name => 'Richard'); +$Richard.favorite-color; # OUTPUT: «My favorite color is Blue» +$Richard.talk; # OUTPUT: «Hi, my name is Richard» +# $Richard is able to access the submethod and he knows how to say his name. + +my Child $Madison .= new(age => 1, name => 'Madison'); +$Madison.talk; # OUTPUT: «Goo goo ga ga», due to the overridden method. +# $Madison.favorite-color # does not work since it is not inherited. + +# When you use `my T $var`, `$var` starts off with `T` itself in it, so you can +# call `new` on it. (`.=` is just the dot-call and the assignment operator). +# Thus, `$a .= b` is the same as `$a = $a.b`. Also note that `BUILD` (the method +# called inside `new`) will set parent's properties too, so you can pass `val => +# 5`. + +# +# 10.2 Roles, or Mixins +# + +# Roles are supported too (which are called Mixins in other languages) +role PrintableVal { + has $!counter = 0; + method print { + say $.val; + } +} + +# you "apply" a role (or mixin) with the `does` keyword: +class Item does PrintableVal { + has $.val; + + =begin comment + When `does`-ed, a `role` literally "mixes in" the class: + the methods and attributes are put together, which means a class + can access the private attributes/methods of its roles (but + not the inverse!): + =end comment + method access { + say $!counter++; + } + + =begin comment + However, this: method print {} is ONLY valid when `print` isn't a `multi` + with the same dispatch. This means a parent class can shadow a child class's + `multi print() {}`, but it's an error if a role does) + + NOTE: You can use a role as a class (with `is ROLE`). In this case, + methods will be shadowed, since the compiler will consider `ROLE` + to be a class. + =end comment +} + +#################################################### +# 11. Exceptions +#################################################### + +# Exceptions are built on top of classes, in the package `X` (like `X::IO`). +# In Raku, exceptions are automatically 'thrown': + +# open 'foo'; # OUTPUT: «Failed to open file foo: no such file or directory» + +# It will also print out what line the error was thrown at +# and other error info. + +# You can throw an exception using `die`. Here it's been commented out to +# avoid stopping the program's execution: +# die 'Error!'; # OUTPUT: «Error!» + +# Or more explicitly (commented out too): +# X::AdHoc.new(payload => 'Error!').throw; # OUTPUT: «Error!» + +# In Raku, `orelse` is similar to the `or` operator, except it only matches +# undefined variables instead of anything evaluating as `False`. +# Undefined values include: `Nil`, `Mu` and `Failure` as well as `Int`, `Str` +# and other types that have not been initialized to any value yet. +# You can check if something is defined or not using the defined method: +my $uninitialized; +say $uninitialized.defined; # OUTPUT: «False» + +# When using `orelse` it will disarm the exception and alias $_ to that +# failure. This will prevent it to being automatically handled and printing +# lots of scary error messages to the screen. We can use the `exception` +# method on the `$_` variable to access the exception +open 'foo' orelse say "Something happened {.exception}"; + +# This also works: +open 'foo' orelse say "Something happened $_"; +# OUTPUT: «Something happened Failed to open file foo: no such file or directory» + +# Both of those above work but in case we get an object from the left side +# that is not a failure we will probably get a warning. We see below how we +# can use try` and `CATCH` to be more specific with the exceptions we catch. + +# +# 11.1 Using `try` and `CATCH` +# + +# By using `try` and `CATCH` you can contain and handle exceptions without +# disrupting the rest of the program. The `try` block will set the last +# exception to the special variable `$!` (known as the error variable). +# NOTE: This has no relation to $!variables seen inside class definitions. + +try open 'foo'; +say "Well, I tried! $!" if defined $!; +# OUTPUT: «Well, I tried! Failed to open file foo: no such file or directory» + +# Now, what if we want more control over handling the exception? +# Unlike many other languages, in Raku, you put the `CATCH` block *within* +# the block to `try`. Similar to how the `$_` variable was set when we +# 'disarmed' the exception with `orelse`, we also use `$_` in the CATCH block. +# NOTE: The `$!` variable is only set *after* the `try` block has caught an +# exception. By default, a `try` block has a `CATCH` block of its own that +# catches any exception (`CATCH { default {} }`). + +try { + my $a = (0 %% 0); + CATCH { + default { say "Something happened: $_" } + } +} +# OUTPUT: «Something happened: Attempt to divide by zero using infix:<%%>» + +# You can redefine it using `when`s (and `default`) to handle the exceptions +# you want to catch explicitly: + +try { + open 'foo'; + CATCH { + # In the `CATCH` block, the exception is set to the $_ variable. + when X::AdHoc { + say "Error: $_" + } + when X::Numeric::DivideByZero { + say "Error: $_"; + } + + =begin comment + Any other exceptions will be re-raised, since we don't have a `default`. + Basically, if a `when` matches (or there's a `default`), the + exception is marked as "handled" so as to prevent its re-throw + from the `CATCH` block. You still can re-throw the exception + (see below) by hand. + =end comment + default { + say "Any other error: $_" + } + } +} +# OUTPUT: «Failed to open file /dir/foo: no such file or directory» + +# There are also some subtleties to exceptions. Some Raku subs return a +# `Failure`, which is a wrapper around an `Exception` object which is +# "unthrown". They're not thrown until you try to use the variables containing +# them unless you call `.Bool`/`.defined` on them - then they're handled. +# (the `.handled` method is `rw`, so you can mark it as `False` back yourself) +# You can throw a `Failure` using `fail`. Note that if the pragma `use fatal` +# is on, `fail` will throw an exception (like `die`). + +my $value = 0/0; # We're not trying to access the value, so no problem. +try { + say 'Value: ', $value; # Trying to use the value + CATCH { + default { + say "It threw because we tried to get the fail's value!" + } + } +} + +# There is also another kind of exception: Control exceptions. Those are "good" +# exceptions, which happen when you change your program's flow, using operators +# like `return`, `next` or `last`. You can "catch" those with `CONTROL` (not 100% +# working in Rakudo yet). + +#################################################### +# 12. Packages +#################################################### + +# Packages are a way to reuse code. Packages are like "namespaces", and any +# element of the six model (`module`, `role`, `class`, `grammar`, `subset` and +# `enum`) are actually packages. (Packages are the lowest common denominator) +# Packages are important - especially as Perl is well-known for CPAN, +# the Comprehensive Perl Archive Network. + +# You can use a module (bring its declarations into scope) with `use`: +use JSON::Tiny; # if you installed Rakudo* or Panda, you'll have this module +say from-json('[1]').perl; # OUTPUT: «[1]» + +# You should not declare packages using the `package` keyword (unlike Perl). +# Instead, use `class Package::Name::Here;` to declare a class, or if you only +# want to export variables/subs, you can use `module` instead. + +# If `Hello` doesn't exist yet, it'll just be a "stub", that can be redeclared +# as something else later. +module Hello::World { # bracketed form + # declarations here +} + +# The file-scoped form which extends until the end of the file. For +# instance, `unit module Parse::Text;` will extend until of the file. + +# A grammar is a package, which you could `use`. You will learn more about +# grammars in the regex section. +grammar Parse::Text::Grammar { +} + +# As said before, any part of the six model is also a package. +# Since `JSON::Tiny` uses its own `JSON::Tiny::Actions` class, you can use it: +my $actions = JSON::Tiny::Actions.new; + +# We'll see how to export variables and subs in the next part. + +#################################################### +# 13. Declarators +#################################################### + +# In Raku, you get different behaviors based on how you declare a variable. +# You've already seen `my` and `has`, we'll now explore the others. + +# `our` - these declarations happen at `INIT` time -- (see "Phasers" below). +# It's like `my`, but it also creates a package variable. All packagish +# things such as `class`, `role`, etc. are `our` by default. + +module Var::Increment { + # NOTE: `our`-declared variables cannot be typed. + our $our-var = 1; + my $my-var = 22; + + our sub Inc { + our sub available { # If you try to make inner `sub`s `our`... + # ... Better know what you're doing (Don't !). + say "Don't do that. Seriously. You'll get burned."; + } + + my sub unavailable { # `sub`s are `my`-declared by default + say "Can't access me from outside, I'm 'my'!"; + } + say ++$our-var; # Increment the package variable and output its value + } + +} + +say $Var::Increment::our-var; # OUTPUT: «1», this works! +say $Var::Increment::my-var; # OUTPUT: «(Any)», this will not work! + +say Var::Increment::Inc; # OUTPUT: «2» +say Var::Increment::Inc; # OUTPUT: «3», notice how the value of $our-var was retained. + +# Var::Increment::unavailable; # OUTPUT: «Could not find symbol '&unavailable'» + +# `constant` - these declarations happen at `BEGIN` time. You can use +# the `constant` keyword to declare a compile-time variable/symbol: +constant Pi = 3.14; +constant $var = 1; + +# And if you're wondering, yes, it can also contain infinite lists. +constant why-not = 5, 15 ... *; +say why-not[^5]; # OUTPUT: «5 15 25 35 45» + +# `state` - these declarations happen at run time, but only once. State +# variables are only initialized one time. In other languages such as C +# they exist as `static` variables. +sub fixed-rand { + state $val = rand; + say $val; +} +fixed-rand for ^10; # will print the same number 10 times + +# Note, however, that they exist separately in different enclosing contexts. +# If you declare a function with a `state` within a loop, it'll re-create the +# variable for each iteration of the loop. See: +for ^5 -> $a { + sub foo { + # This will be a different value for every value of `$a` + state $val = rand; + } + for ^5 -> $b { + # This will print the same value 5 times, but only 5. Next iteration + # will re-run `rand`. + say foo; + } +} + +#################################################### +# 14. Phasers +#################################################### + +# Phasers in Raku are blocks that happen at determined points of time in +# your program. They are called phasers because they mark a change in the +# phase of a program. For example, when the program is compiled, a for loop +# runs, you leave a block, or an exception gets thrown (The `CATCH` block is +# actually a phaser!). Some of them can be used for their return values, +# some of them can't (those that can have a "[*]" in the beginning of their +# explanation text). Let's have a look! + +# +# 14.1 Compile-time phasers +# +BEGIN { say "[*] Runs at compile time, as soon as possible, only once" } +CHECK { say "[*] Runs at compile time, as late as possible, only once" } + +# +# 14.2 Run-time phasers +# +INIT { say "[*] Runs at run time, as soon as possible, only once" } +END { say "Runs at run time, as late as possible, only once" } + +# +# 14.3 Block phasers +# +ENTER { say "[*] Runs every time you enter a block, repeats on loop blocks" } +LEAVE { + say "Runs every time you leave a block, even when an exception + happened. Repeats on loop blocks." +} + +PRE { + say "Asserts a precondition at every block entry, + before ENTER (especially useful for loops)"; + say "If this block doesn't return a truthy value, + an exception of type X::Phaser::PrePost is thrown."; +} + +# Example (commented out): +for 0..2 { + # PRE { $_ > 1 } # OUTPUT: «Precondition '{ $_ > 1 }' failed +} + +POST { + say "Asserts a postcondition at every block exit, + after LEAVE (especially useful for loops)"; + say "If this block doesn't return a truthy value, + an exception of type X::Phaser::PrePost is thrown, like PRE."; +} + +# Example (commented out): +for 0..2 { + # POST { $_ < 1 } # OUTPUT: «Postcondition '{ $_ < 1 }' failed +} + +# +# 14.4 Block/exceptions phasers +# +{ + KEEP { say "Runs when you exit a block successfully + (without throwing an exception)" } + UNDO { say "Runs when you exit a block unsuccessfully + (by throwing an exception)" } +} + +# +# 14.5 Loop phasers +# +for ^5 { + FIRST { say "[*] The first time the loop is run, before ENTER" } + NEXT { say "At loop continuation time, before LEAVE" } + LAST { say "At loop termination time, after LEAVE" } +} + +# +# 14.6 Role/class phasers +# +COMPOSE { + say "When a role is composed into a class. /!\ NOT YET IMPLEMENTED" +} + +# They allow for cute tricks or clever code...: +say "This code took " ~ (time - CHECK time) ~ "s to compile"; + +# ... or clever organization: +class DB { + method start-transaction { say "Starting transaction!" } + method commit { say "Committing transaction..." } + method rollback { say "Something went wrong. Rolling back!" } +} + +sub do-db-stuff { + my DB $db .= new; + $db.start-transaction; # start a new transaction + KEEP $db.commit; # commit the transaction if all went well + UNDO $db.rollback; # or rollback if all hell broke loose +} + +do-db-stuff(); + +#################################################### +# 15. Statement prefixes +#################################################### + +# Those act a bit like phasers: they affect the behavior of the following +# code. Though, they run in-line with the executable code, so they're in +# lowercase. (`try` and `start` are theoretically in that list, but explained +# elsewhere) NOTE: all of these (except start) don't need explicit curly +# braces `{` and `}`. + +# +# 15.1 `do` - It runs a block or a statement as a term. +# + +# Normally you cannot use a statement as a value (or "term"). `do` helps +# us do it. With `do`, an `if`, for example, becomes a term returning a value. +=for comment :reason<this fails since `if` is a statement> +my $value = if True { 1 } + +# this works! +my $get-five = do if True { 5 } + +# +# 15.1 `once` - makes sure a piece of code only runs once. +# +for ^5 { + once say 1 +}; +# OUTPUT: «1», only prints ... once + +# Similar to `state`, they're cloned per-scope. +for ^5 { + sub { once say 1 }() +}; +# OUTPUT: «1 1 1 1 1», prints once per lexical scope. + +# +# 15.2 `gather` - co-routine thread. +# + +# The `gather` constructs allows us to `take` several values from an array/list, +# much like `do`. +say gather for ^5 { + take $_ * 3 - 1; + take $_ * 3 + 1; +} +# OUTPUT: «-1 1 2 4 5 7 8 10 11 13» + +say join ',', gather if False { + take 1; + take 2; + take 3; +} +# Doesn't print anything. + +# +# 15.3 `eager` - evaluates a statement eagerly (forces eager context). + +# Don't try this at home. This will probably hang for a while (and might crash) +# so commented out. +# eager 1..*; + +# But consider, this version which doesn't print anything +constant thricev0 = gather for ^3 { say take $_ }; +# to: +constant thricev1 = eager gather for ^3 { say take $_ }; # OUTPUT: «0 1 2» + +#################################################### +# 16. Iterables +#################################################### + +# Iterables are objects that can be iterated over for things such as +# the `for` construct. + +# +# 16.1 `flat` - flattens iterables. +# +say (1, 10, (20, 10) ); # OUTPUT: «(1 10 (20 10))», notice how nested + # lists are preserved +say (1, 10, (20, 10) ).flat; # OUTPUT: «(1 10 20 10)», now the iterable is flat + +# +# 16.2 `lazy` - defers actual evaluation until value is fetched by forcing lazy context. +# +my @lazy-array = (1..100).lazy; +say @lazy-array.is-lazy; # OUTPUT: «True», check for laziness with the `is-lazy` method. + +say @lazy-array; # OUTPUT: «[...]», List has not been iterated on! + +# This works and will only do as much work as is needed. +for @lazy-array { .print }; + +# (**TODO** explain that gather/take and map are all lazy) + +# +# 16.3 `sink` - an `eager` that discards the results by forcing sink context. +# +constant nilthingie = sink for ^3 { .say } #=> 0 1 2 +say nilthingie.perl; # OUTPUT: «Nil» + +# +# 16.4 `quietly` - suppresses warnings in blocks. +# +quietly { warn 'This is a warning!' }; # No output + +#################################################### +# 17. More operators thingies! +#################################################### + +# Everybody loves operators! Let's get more of them. + +# The precedence list can be found here: +# https://docs.raku.org/language/operators#Operator_Precedence +# But first, we need a little explanation about associativity: + +# +# 17.1 Binary operators +# + +my ($p, $q, $r) = (1, 2, 3); + +# Given some binary operator § (not a Raku-supported operator), then: + +# $p § $q § $r; # with a left-associative §, this is ($p § $q) § $r +# $p § $q § $r; # with a right-associative §, this is $p § ($q § $r) +# $p § $q § $r; # with a non-associative §, this is illegal +# $p § $q § $r; # with a chain-associative §, this is ($p § $q) and ($q § $r)§ +# $p § $q § $r; # with a list-associative §, this is `infix:<>` + +# +# 17.2 Unary operators +# + +# Given some unary operator § (not a Raku-supported operator), then: +# §$p§ # with left-associative §, this is (§$p)§ +# §$p§ # with right-associative §, this is §($p§) +# §$p§ # with non-associative §, this is illegal + +# +# 17.3 Create your own operators! +# + +# Okay, you've been reading all of that, so you might want to try something +# more exciting?! I'll tell you a little secret (or not-so-secret): +# In Raku, all operators are actually just funny-looking subroutines. + +# You can declare an operator just like you declare a sub. In the following +# example, `prefix` refers to the operator categories (prefix, infix, postfix, +# circumfix, and post-circumfix). +sub prefix:<win>( $winner ) { + say "$winner Won!"; +} +win "The King"; # OUTPUT: «The King Won!» + +# you can still call the sub with its "full name": +say prefix:<!>(True); # OUTPUT: «False» +prefix:<win>("The Queen"); # OUTPUT: «The Queen Won!» + +sub postfix:<!>( Int $n ) { + [*] 2..$n; # using the reduce meta-operator... See below ;-)! +} +say 5!; # OUTPUT: «120» + +# Postfix operators ('after') have to come *directly* after the term. +# No whitespace. You can use parentheses to disambiguate, i.e. `(5!)!` + +sub infix:<times>( Int $n, Block $r ) { # infix ('between') + for ^$n { + # You need the explicit parentheses to call the function in `$r`, + # else you'd be referring at the code object itself, like with `&r`. + $r(); + } +} +3 times -> { say "hello" }; # OUTPUT: «hellohellohello» + +# It's recommended to put spaces around your infix operator calls. + +# For circumfix and post-circumfix ones +multi circumfix:<[ ]>( Int $n ) { + $n ** $n +} +say [5]; # OUTPUT: «3125» + +# Circumfix means 'around'. Again, no whitespace. + +multi postcircumfix:<{ }>( Str $s, Int $idx ) { + $s.substr($idx, 1); +} +say "abc"{1}; # OUTPUT: «b», after the term `"abc"`, and around the index (1) + +# Post-circumfix is 'after a term, around something' + +# This really means a lot -- because everything in Raku uses this. +# For example, to delete a key from a hash, you use the `:delete` adverb +# (a simple named argument underneath). For instance, the following statements +# are equivalent. +my %person-stans = + 'Giorno Giovanna' => 'Gold Experience', + 'Bruno Bucciarati' => 'Sticky Fingers'; +my $key = 'Bruno Bucciarati'; +%person-stans{$key}:delete; +postcircumfix:<{ }>( %person-stans, 'Giorno Giovanna', :delete ); +# (you can call operators like this) + +# It's *all* using the same building blocks! Syntactic categories +# (prefix infix ...), named arguments (adverbs), ..., etc. used to build +# the language - are available to you. Obviously, you're advised against +# making an operator out of *everything* -- with great power comes great +# responsibility. + +# +# 17.4 Meta operators! +# + +# Oh boy, get ready!. Get ready, because we're delving deep into the rabbit's +# hole, and you probably won't want to go back to other languages after +# reading this. (I'm guessing you don't want to go back at this point but +# let's continue, for the journey is long and enjoyable!). + +# Meta-operators, as their name suggests, are *composed* operators. Basically, +# they're operators that act on another operators. + +# The reduce meta-operator is a prefix meta-operator that takes a binary +# function and one or many lists. If it doesn't get passed any argument, +# it either returns a "default value" for this operator (a meaningless value) +# or `Any` if there's none (examples below). Otherwise, it pops an element +# from the list(s) one at a time, and applies the binary function to the last +# result (or the first element of a list) and the popped element. + +# To sum a list, you could use the reduce meta-operator with `+`, i.e.: +say [+] 1, 2, 3; # OUTPUT: «6», equivalent to (1+2)+3. + +# To multiply a list +say [*] 1..5; # OUTPUT: «120», equivalent to ((((1*2)*3)*4)*5). + +# You can reduce with any operator, not just with mathematical ones. +# For example, you could reduce with `//` to get first defined element +# of a list: +say [//] Nil, Any, False, 1, 5; # OUTPUT: «False» + # (Falsey, but still defined) +# Or with relational operators, i.e., `>` to check elements of a list +# are ordered accordingly: +say [>] 234, 156, 6, 3, -20; # OUTPUT: «True» + +# Default value examples: +say [*] (); # OUTPUT: «1», empty product +say [+] (); # OUTPUT: «0», empty sum +say [//]; # OUTPUT: «(Any)» + # There's no "default value" for `//`. + +# You can also use it with a function you made up, +# You can also surround using double brackets: +sub add($a, $b) { $a + $b } +say [[&add]] 1, 2, 3; # OUTPUT: «6» + +# The zip meta-operator is an infix meta-operator that also can be used as a +# "normal" operator. It takes an optional binary function (by default, it +# just creates a pair), and will pop one value off of each array and call +# its binary function on these until it runs out of elements. It returns an +# array with all of these new elements. +say (1, 2) Z (3, 4); # OUTPUT: «((1, 3), (2, 4))» +say 1..3 Z+ 4..6; # OUTPUT: «(5, 7, 9)» + +# Since `Z` is list-associative (see the list above), you can use it on more +# than one list. +(True, False) Z|| (False, False) Z|| (False, False); # (True, False) + +# And, as it turns out, you can also use the reduce meta-operator with it: +[Z||] (True, False), (False, False), (False, False); # (True, False) + +# And to end the operator list: + +# The sequence operator (`...`) is one of Raku's most powerful features: +# It's composed by the list (which might include a closure) you want Raku to +# deduce from on the left and a value (or either a predicate or a Whatever Star +# for a lazy infinite list) on the right that states when to stop. + +# Basic arithmetic sequence +my @listv0 = 1, 2, 3...10; + +# This dies because Raku can't figure out the end +# my @list = 1, 3, 6...10; + +# As with ranges, you can exclude the last element (the iteration ends when +# the predicate matches). +my @listv1 = 1, 2, 3...^10; + +# You can use a predicate (with the Whatever Star). +my @listv2 = 1, 3, 9...* > 30; + +# Equivalent to the example above but using a block here. +my @listv3 = 1, 3, 9 ... { $_ > 30 }; + +# Lazy infinite list of fibonacci sequence, computed using a closure! +my @fibv0 = 1, 1, *+* ... *; + +# Equivalent to the above example but using a pointy block. +my @fibv1 = 1, 1, -> $a, $b { $a + $b } ... *; + +# Equivalent to the above example but using a block with placeholder parameters. +my @fibv2 = 1, 1, { $^a + $^b } ... *; + +# In the examples with explicit parameters (i.e., $a and $b), $a and $b +# will always take the previous values, meaning that for the Fibonacci sequence, +# they'll start with $a = 1 and $b = 1 (values we set by hand), then $a = 1 +# and $b = 2 (result from previous $a + $b), and so on. + +# In the example we use a range as an index to access the sequence. However, +# it's worth noting that for ranges, once reified, elements aren't re-calculated. +# That's why, for instance, `@primes[^100]` will take a long time the first +# time you print it but then it will be instantaneous. +say @fibv0[^10]; # OUTPUT: «1 1 2 3 5 8 13 21 34 55» + +#################################################### +# 18. Regular Expressions +#################################################### + +# I'm sure a lot of you have been waiting for this one. Well, now that you know +# a good deal of Raku already, we can get started. First off, you'll have to +# forget about "PCRE regexps" (perl-compatible regexps). + +# IMPORTANT: Don't skip them because you know PCRE. They're different. Some +# things are the same (like `?`, `+`, and `*`), but sometimes the semantics +# change (`|`). Make sure you read carefully, because you might trip over a +# new behavior. + +# Raku has many features related to RegExps. After all, Rakudo parses itself. +# We're first going to look at the syntax itself, then talk about grammars +# (PEG-like), differences between `token`, `regex` and `rule` declarators, +# and some more. Side note: you still have access to PCRE regexps using the +# `:P5` modifier which we won't be discussing this in this tutorial, though. + +# In essence, Raku natively implements PEG ("Parsing Expression Grammars"). +# The pecking order for ambiguous parses is determined by a multi-level +# tie-breaking test: +# - Longest token matching: `foo\s+` beats `foo` (by 2 or more positions) +# - Longest literal prefix: `food\w*` beats `foo\w*` (by 1) +# - Declaration from most-derived to less derived grammars +# (grammars are actually classes) +# - Earliest declaration wins +say so 'a' ~~ /a/; # OUTPUT: «True» +say so 'a' ~~ / a /; # OUTPUT: «True», more readable with some spaces! + +# In all our examples, we're going to use the smart-matching operator against +# a regexp. We're converting the result using `so` to a Boolean value because, +# in fact, it's returning a `Match` object. They know how to respond to list +# indexing, hash indexing, and return the matched string. The results of the +# match are available in the `$/` variable (implicitly lexically-scoped). You +# can also use the capture variables which start at 0: `$0`, `$1', `$2`... + +# You can also note that `~~` does not perform start/end checking, meaning +# the regexp can be matched with just one character of the string. We'll +# explain later how you can do it. + +# In Raku, you can have any alphanumeric as a literal, everything else has +# to be escaped by using a backslash or quotes. +say so 'a|b' ~~ / a '|' b /; # OUTPUT: «True», it wouldn't mean the same + # thing if `|` wasn't escaped. +say so 'a|b' ~~ / a \| b /; # OUTPUT: «True», another way to escape it. + +# The whitespace in a regex is actually not significant, unless you use the +# `:s` (`:sigspace`, significant space) adverb. +say so 'a b c' ~~ / a b c /; #=> `False`, space is not significant here! +say so 'a b c' ~~ /:s a b c /; #=> `True`, we added the modifier `:s` here. + +# If we use only one space between strings in a regex, Raku will warn us +# about space being not signicant in the regex: +say so 'a b c' ~~ / a b c /; # OUTPUT: «False» +say so 'a b c' ~~ / a b c /; # OUTPUT: «False» + +# NOTE: Please use quotes or `:s` (`:sigspace`) modifier (or, to suppress this +# warning, omit the space, or otherwise change the spacing). To fix this and make +# the spaces less ambiguous, either use at least two spaces between strings +# or use the `:s` adverb. + +# As we saw before, we can embed the `:s` inside the slash delimiters, but we +# can also put it outside of them if we specify `m` for 'match': +say so 'a b c' ~~ m:s/a b c/; # OUTPUT: «True» + +# By using `m` to specify 'match', we can also use other delimiters: +say so 'abc' ~~ m{a b c}; # OUTPUT: «True» +say so 'abc' ~~ m[a b c]; # OUTPUT: «True» + +# `m/.../` is equivalent to `/.../`: +say 'raku' ~~ m/raku/; # OUTPUT: «True» +say 'raku' ~~ /raku/; # OUTPUT: «True» + +# Use the `:i` adverb to specify case insensitivity: +say so 'ABC' ~~ m:i{a b c}; # OUTPUT: «True» + +# However, whitespace is important as for how modifiers are applied +# (which you'll see just below) ... + +# +# 18.1 Quantifiers - `?`, `+`, `*` and `**`. +# + +# `?` - zero or one match +say so 'ac' ~~ / a b c /; # OUTPUT: «False» +say so 'ac' ~~ / a b? c /; # OUTPUT: «True», the "b" matched 0 times. +say so 'abc' ~~ / a b? c /; # OUTPUT: «True», the "b" matched 1 time. + +# ... As you read before, whitespace is important because it determines which +# part of the regex is the target of the modifier: +say so 'def' ~~ / a b c? /; # OUTPUT: «False», only the "c" is optional +say so 'def' ~~ / a b? c /; # OUTPUT: «False», whitespace is not significant +say so 'def' ~~ / 'abc'? /; # OUTPUT: «True», the whole "abc" group is optional + +# Here (and below) the quantifier applies only to the "b" + +# `+` - one or more matches +say so 'ac' ~~ / a b+ c /; # OUTPUT: «False», `+` wants at least one 'b' +say so 'abc' ~~ / a b+ c /; # OUTPUT: «True», one is enough +say so 'abbbbc' ~~ / a b+ c /; # OUTPUT: «True», matched 4 "b"s + +# `*` - zero or more matches +say so 'ac' ~~ / a b* c /; # OUTPUT: «True», they're all optional +say so 'abc' ~~ / a b* c /; # OUTPUT: «True» +say so 'abbbbc' ~~ / a b* c /; # OUTPUT: «True» +say so 'aec' ~~ / a b* c /; # OUTPUT: «False», "b"(s) are optional, not replaceable. + +# `**` - (Unbound) Quantifier +# If you squint hard enough, you might understand why exponentiation is used +# for quantity. +say so 'abc' ~~ / a b**1 c /; # OUTPUT: «True», exactly one time +say so 'abc' ~~ / a b**1..3 c /; # OUTPUT: «True», one to three times +say so 'abbbc' ~~ / a b**1..3 c /; # OUTPUT: «True» +say so 'abbbbbbc' ~~ / a b**1..3 c /; # OUTPUT: «Fals», too much +say so 'abbbbbbc' ~~ / a b**3..* c /; # OUTPUT: «True», infinite ranges are ok + +# +# 18.2 `<[]>` - Character classes +# + +# Character classes are the equivalent of PCRE's `[]` classes, but they use a +# more raku-ish syntax: +say 'fooa' ~~ / f <[ o a ]>+ /; # OUTPUT: «fooa» + +# You can use ranges (`..`): +say 'aeiou' ~~ / a <[ e..w ]> /; # OUTPUT: «ae» + +# Just like in normal regexes, if you want to use a special character, escape +# it (the last one is escaping a space which would be equivalent to using +# ' '): +say 'he-he !' ~~ / 'he-' <[ a..z \! \ ]> + /; # OUTPUT: «he-he !» + +# You'll get a warning if you put duplicate names (which has the nice effect +# of catching the raw quoting): +'he he' ~~ / <[ h e ' ' ]> /; +# Warns "Repeated character (') unexpectedly found in character class" + +# You can also negate character classes... (`<-[]>` equivalent to `[^]` in PCRE) +say so 'foo' ~~ / <-[ f o ]> + /; # OUTPUT: «False» + +# ... and compose them: +# any letter except "f" and "o" +say so 'foo' ~~ / <[ a..z ] - [ f o ]> + /; # OUTPUT: «False» + +# no letter except "f" and "o" +say so 'foo' ~~ / <-[ a..z ] + [ f o ]> + /; # OUTPUT: «True» + +# the + doesn't replace the left part +say so 'foo!' ~~ / <-[ a..z ] + [ f o ]> + /; # OUTPUT: «True» + +# +# 18.3 Grouping and capturing +# + +# Group: you can group parts of your regexp with `[]`. Unlike PCRE's `(?:)`, +# these groups are *not* captured. +say so 'abc' ~~ / a [ b ] c /; # OUTPUT: «True», the grouping does nothing +say so 'foo012012bar' ~~ / foo [ '01' <[0..9]> ] + bar /; # OUTPUT: «True» + +# The previous line returns `True`. The regex matches "012" one or more time +# (achieved by the the `+` applied to the group). + +# But this does not go far enough, because we can't actually get back what +# we matched. + +# Capture: The results of a regexp can be *captured* by using parentheses. +say so 'fooABCABCbar' ~~ / foo ( 'A' <[A..Z]> 'C' ) + bar /; # OUTPUT: «True» +# (using `so` here, see `$/` below) + +# So, starting with the grouping explanations. As we said before, our `Match` +# object is stored inside the `$/` variable: +say $/; # Will either print the matched object or `Nil` if nothing matched. + +# As we also said before, it has array indexing: +say $/[0]; # OUTPUT: «「ABC」 「ABC」», + +# The corner brackets (「..」) represent (and are) `Match` objects. In the +# previous example, we have an array of them. + +say $0; # The same as above. + +# Our capture is `$0` because it's the first and only one capture in the +# regexp. You might be wondering why it's an array, and the answer is simple: +# Some captures (indexed using `$0`, `$/[0]` or a named one) will be an array +# if and only if they can have more than one element. Thus any capture with +# `*`, `+` and `**` (whatever the operands), but not with `?`. +# Let's use examples to see that: + +# NOTE: We quoted A B C to demonstrate that the whitespace between them isn't +# significant. If we want the whitespace to *be* significant there, we can use the +# `:sigspace` modifier. +say so 'fooABCbar' ~~ / foo ( "A" "B" "C" )? bar /; # OUTPUT: «True» +say $/[0]; # OUTPUT: «「ABC」» +say $0.WHAT; # OUTPUT: «(Match)» + # There can't be more than one, so it's only a single match object. + +say so 'foobar' ~~ / foo ( "A" "B" "C" )? bar /; # OUTPUT: «True» +say $0.WHAT; # OUTPUT: «(Any)», this capture did not match, so it's empty. + +say so 'foobar' ~~ / foo ( "A" "B" "C" ) ** 0..1 bar /; #=> OUTPUT: «True» +say $0.WHAT; # OUTPUT: «(Array)», A specific quantifier will always capture + # an Array, be a range or a specific value (even 1). + +# The captures are indexed per nesting. This means a group in a group will be +# nested under its parent group: `$/[0][0]`, for this code: +'hello-~-world' ~~ / ( 'hello' ( <[ \- \~ ]> + ) ) 'world' /; +say $/[0].Str; # OUTPUT: «hello~» +say $/[0][0].Str; # OUTPUT: «~» + +# This stems from a very simple fact: `$/` does not contain strings, integers +# or arrays, it only contains `Match` objects. These contain the `.list`, `.hash` +# and `.Str` methods but you can also just use `match<key>` for hash access +# and `match[idx]` for array access. + +# In the following example, we can see `$_` is a list of `Match` objects. +# Each of them contain a wealth of information: where the match started/ended, +# the "ast" (see actions later), etc. You'll see named capture below with +# grammars. +say $/[0].list.perl; # OUTPUT: «(Match.new(...),).list» + +# Alternation - the `or` of regexes +# WARNING: They are DIFFERENT from PCRE regexps. +say so 'abc' ~~ / a [ b | y ] c /; # OUTPUT: «True», Either "b" or "y". +say so 'ayc' ~~ / a [ b | y ] c /; # OUTPUT: «True», Obviously enough... + +# The difference between this `|` and the one you're used to is +# LTM ("Longest Token Matching") strategy. This means that the engine will +# always try to match as much as possible in the string. +say 'foo' ~~ / fo | foo /; # OUTPUT: «foo», instead of `fo`, because it's longer. + +# To decide which part is the "longest", it first splits the regex in two parts: +# +# * The "declarative prefix" (the part that can be statically analyzed) +# which includes alternations (`|`), conjunctions (`&`), sub-rule calls (not +# yet introduced), literals, characters classes and quantifiers. +# +# * The "procedural part" includes everything else: back-references, +# code assertions, and other things that can't traditionally be represented +# by normal regexps. + +# Then, all the alternatives are tried at once, and the longest wins. + +# Examples: +# DECLARATIVE | PROCEDURAL +/ 'foo' \d+ [ <subrule1> || <subrule2> ] /; + +# DECLARATIVE (nested groups are not a problem) +/ \s* [ \w & b ] [ c | d ] /; + +# However, closures and recursion (of named regexes) are procedural. +# There are also more complicated rules, like specificity (literals win +# over character classes). + +# NOTE: The alternation in which all the branches are tried in order +# until the first one matches still exists, but is now spelled `||`. +say 'foo' ~~ / fo || foo /; # OUTPUT: «fo», in this case. + +#################################################### +# 19. Extra: the MAIN subroutine +#################################################### + +# The `MAIN` subroutine is called when you run a Raku file directly. It's +# very powerful, because Raku actually parses the arguments and pass them +# as such to the sub. It also handles named argument (`--foo`) and will even +# go as far as to autogenerate a `--help` flag. + +sub MAIN($name) { + say "Hello, $name!"; +} +# Supposing the code above is in file named cli.raku, then running in the command +# line (e.g., $ raku cli.raku) produces: +# Usage: +# cli.raku <name> + +# And since MAIN is a regular Raku sub, you can have multi-dispatch: +# (using a `Bool` for the named argument so that we can do `--replace` +# instead of `--replace=1`. The presence of `--replace` indicates truthness +# while its absence falseness). For example: + + # convert to IO object to check the file exists + =begin comment + subset File of Str where *.IO.d; + + multi MAIN('add', $key, $value, Bool :$replace) { ... } + multi MAIN('remove', $key) { ... } + multi MAIN('import', File, Str :$as) { ... } # omitting parameter name + =end comment + +# Thus $ raku cli.raku produces: +# Usage: +# cli.raku [--replace] add <key> <value> +# cli.raku remove <key> +# cli.raku [--as=<Str>] import <File> + +# As you can see, this is *very* powerful. It even went as far as to show inline +# the constants (the type is only displayed if the argument is `$`/is named). + +#################################################### +# 20. APPENDIX A: +#################################################### + +# It's assumed by now you know the Raku basics. This section is just here to +# list some common operations, but which are not in the "main part" of the +# tutorial to avoid bloating it up. + +# +# 20.1 Operators +# + +# Sort comparison - they return one value of the `Order` enum: `Less`, `Same` +# and `More` (which numerify to -1, 0 or +1 respectively). +say 1 <=> 4; # OUTPUT: «More», sort comparison for numerics +say 'a' leg 'b'; # OUTPUT: «Lessre», sort comparison for string +say 1 eqv 1; # OUTPUT: «Truere», sort comparison using eqv semantics +say 1 eqv 1.0; # OUTPUT: «False» + +# Generic ordering +say 3 before 4; # OUTPUT: «True» +say 'b' after 'a'; # OUTPUT: «True» + +# Short-circuit default operator - similar to `or` and `||`, but instead +# returns the first *defined* value: +say Any // Nil // 0 // 5; # OUTPUT: «0» + +# Short-circuit exclusive or (XOR) - returns `True` if one (and only one) of +# its arguments is true +say True ^^ False; # OUTPUT: «True» + +# Flip flops. These operators (`ff` and `fff`, equivalent to P5's `..` +# and `...`) are operators that take two predicates to test: They are `False` +# until their left side returns `True`, then are `True` until their right +# side returns `True`. Similar to ranges, you can exclude the iteration when +# it become `True`/`False` by using `^` on either side. Let's start with an +# example : + +for <well met young hero we shall meet later> { + # by default, `ff`/`fff` smart-match (`~~`) against `$_`: + if 'met' ^ff 'meet' { # Won't enter the if for "met" + .say # (explained in details below). + } + + if rand == 0 ff rand == 1 { # compare variables other than `$_` + say "This ... probably will never run ..."; + } +} + +# This will print "young hero we shall meet" (excluding "met"): the flip-flop +# will start returning `True` when it first encounters "met" (but will still +# return `False` for "met" itself, due to the leading `^` on `ff`), until it +# sees "meet", which is when it'll start returning `False`. + +# The difference between `ff` (awk-style) and `fff` (sed-style) is that `ff` +# will test its right side right when its left side changes to `True`, and can +# get back to `False` right away (*except* it'll be `True` for the iteration +# that matched) while `fff` will wait for the next iteration to try its right +# side, once its left side changed: + +# The output is due to the right-hand-side being tested directly (and returning +# `True`). "B"s are printed since it matched that time (it just went back to +# `False` right away). +.say if 'B' ff 'B' for <A B C B A>; # OUTPUT: «B B», + +# In this case the right-hand-side wasn't tested until `$_` became "C" +# (and thus did not match instantly). +.say if 'B' fff 'B' for <A B C B A>; #=> «B C B», + +# A flip-flop can change state as many times as needed: +for <test start print it stop not printing start print again stop not anymore> { + # exclude both "start" and "stop", + .say if $_ eq 'start' ^ff^ $_ eq 'stop'; # OUTPUT: «print it print again» +} + +# You might also use a Whatever Star, which is equivalent to `True` for the +# left side or `False` for the right, as shown in this example. +# NOTE: the parenthesis are superfluous here (sometimes called "superstitious +# parentheses"). Once the flip-flop reaches a number greater than 50, it'll +# never go back to `False`. +for (1, 3, 60, 3, 40, 60) { + .say if $_ > 50 ff *; # OUTPUT: «6034060» +} + +# You can also use this property to create an `if` that'll not go through the +# first time. In this case, the flip-flop is `True` and never goes back to +# `False`, but the `^` makes it *not run* on the first iteration +for <a b c> { .say if * ^ff *; } # OUTPUT: «bc» + +# The `===` operator, which uses `.WHICH` on the objects to be compared, is +# the value identity operator whereas the `=:=` operator, which uses `VAR()` on +# the objects to compare them, is the container identity operator. +``` + +If you want to go further and learn more about Raku, you can: + +- Read the [Raku Docs](https://docs.raku.org/). This is a great +resource on Raku. If you are looking for something, use the search bar. +This will give you a dropdown menu of all the pages referencing your search +term (Much better than using Google to find Raku documents!). + +- Read the [Raku Advent Calendar](https://rakuadventcalendar.wordpress.com/). This +is a great source of Raku snippets and explanations. If the docs don't +describe something well enough, you may find more detailed information here. +This information may be a bit older but there are many great examples and +explanations. Posts stopped at the end of 2015 when the language was declared +stable and `Raku v6.c` was released. + +- Come along on `#raku` at [`irc.libera.chat`](https://web.libera.chat/?channel=#raku). The folks here are +always helpful. + +- Check the [source of Raku's functions and +classes](https://github.com/rakudo/rakudo/tree/master/src/core.c). Rakudo is +mainly written in Raku (with a lot of NQP, "Not Quite Perl", a Raku subset +easier to implement and optimize). + +- Read [the language design documents](https://design.raku.org/). They explain +Raku from an implementor point-of-view, but it's still very interesting. diff --git a/raylib.html.markdown b/raylib.html.markdown new file mode 100644 index 00000000..0afc6e03 --- /dev/null +++ b/raylib.html.markdown @@ -0,0 +1,146 @@ +--- +category: tool +tool: raylib +filename: learnraylib.c +contributors: + - ["Nikolas Wipper", "https://notnik.cc"] +--- + +**raylib** is a cross-platform easy-to-use graphics library, built around +OpenGL 1.1, 2.1, 3.3 and OpenGL ES 2.0. Even though it is written in C +it has bindings to over 50 different languages. This tutorial will use C, +more specifically C99. + +```c +#include <raylib.h> + +int main(void) +{ + const int screenWidth = 800; + const int screenHeight = 450; + + // Before initialising raylib we can set configuration flags + SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); + + // raylib doesn't require us to store any instance structures + // At the moment raylib can handle only one window at a time + InitWindow(screenWidth, screenHeight, "MyWindow"); + + // Set our game to run at 60 frames-per-second + SetTargetFPS(60); + + // Set a key that closes the window + // Could be 0 for no key + SetExitKey(KEY_DELETE); + + // raylib defines two types of cameras: Camera3D and Camera2D + // Camera is a typedef for Camera3D + Camera camera = { + .position = {0.0f, 0.0f, 0.0f}, + .target = {0.0f, 0.0f, 1.0f}, + .up = {0.0f, 1.0f, 0.0f}, + .fovy = 70.0f, + .type = CAMERA_PERSPECTIVE + }; + + // raylib supports loading of models, animations, images and sounds + // from various different file formats + Model myModel = LoadModel("my_model.obj"); + Font someFont = LoadFont("some_font.ttf"); + + // Creates a 100x100 render texture + RenderTexture renderTexture = LoadRenderTexture(100, 100); + + // WindowShouldClose checks if the user is closing the window + // This might happen using a shortcut, window controls + // or the key we set earlier + while (!WindowShouldClose()) + { + + // BeginDrawing needs to be called before any draw call + BeginDrawing(); + { + + // Sets the background to a certain color + ClearBackground(BLACK); + + if (IsKeyDown(KEY_SPACE)) + DrawCircle(400, 400, 30, GREEN); + + // Simple draw text + DrawText("Congrats! You created your first window!", + 190, // x + 200, // y + 20, // font size + LIGHTGRAY + ); + + // For most functions there are several versions + // These are usually postfixed with Ex, Pro, V + // or sometimes Rec, Wires (only for 3D), Lines (only for 2D) + DrawTextEx(someFont, + "Text in another font", + (Vector2) {10, 10}, + 20, // font size + 2, // spacing + LIGHTGRAY); + + // Required for drawing 3D, has 2D equivalent + BeginMode3D(camera); + { + + DrawCube((Vector3) {0.0f, 0.0f, 3.0f}, + 1.0f, 1.0f, 1.0f, RED); + + // White tint when drawing will keep the original color + DrawModel(myModel, (Vector3) {0.0f, 0.0f, 3.0f}, + 1.0f, //Scale + WHITE); + + } + // End 3D mode so we can draw normally again + EndMode3D(); + + // Start drawing onto render texture + BeginTextureMode(renderTexture); + { + + // It behaves the same as if we just called `BeginDrawing()` + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + { + + DrawGrid(10, // Slices + 1.0f // Spacing + ); + + } + EndMode3D(); + + } + EndTextureMode(); + + // render textures have a Texture2D field + DrawTexture(renderTexture.texture, 40, 378, BLUE); + + } + EndDrawing(); + } + + // Unloading loaded objects + UnloadFont(someFont); + UnloadModel(myModel); + + // Close window and OpenGL context + CloseWindow(); + + return 0; +} + +``` + +## Further reading +raylib has some [great examples](https://www.raylib.com/examples.html) +If you don't like C check out the [raylib bindings](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)
\ No newline at end of file diff --git a/rdf.html.markdown b/rdf.html.markdown new file mode 100644 index 00000000..5b2105b8 --- /dev/null +++ b/rdf.html.markdown @@ -0,0 +1,160 @@ +--- +language: RDF +filename: learnrdf.ttl +contributors: +- ["Bob DuCharme", "http://bobdc.com/"] +--- + +RDF (Resource Description Framework) is a [W3C +standard](https://www.w3.org/TR/2014/REC-rdf11-concepts-20140225/) data +model. The W3C has standardized several RDF syntaxes; examples below use the +most popular one, [Turtle](https://www.w3.org/TR/turtle/). + +One nice advantage of Turtle files is that if you concatenate any two +syntactically valid Turtle files, you will have another syntactically valid +Turtle file. This is one of many things about RDF that ease data integration. + +The W3C standard query language for RDF datasets is +[SPARQL](https://www.w3.org/TR/sparql11-query/). + +RDF expresses all facts as three-part {subject, predicate, object} statements +known as triples. Because the same entity can be the subject of some triples +and the object of others, a set of triples can represent a graph data +structure. A large-scale storage system for triples is called a triplestore, +and falls into the graph database category of NoSQL databases. + +RDF subjects and predicates must be URIs (Uniform Resource Identifiers), which +usually look like URLs but function as identifiers, not locators. The use of +URIs provides context for resource identifiers to make them unambiguous—for +example, to tell a book title from a job title. + +``` +# The hash symbol is the comment delimiter. + +# Turtle triple statements end with periods like natural language sentences. + +# These two triples tell us that the mythical Example Company's +# employee 134 has a hire date of 2022-11-12 and a family name of Smith: + +<http://example.com/emp134> <http://example.com/hireDate> "2022-11-12" . +<http://example.com/emp134> <http://example.com/familyName> "Smith" . + +# Declaring prefixes to stand in for namespaces reduces verbosity. These +# declarations typically go at the beginning of the file, but the only +# requirement is that they come before the first use of the prefix they declare. + +@prefix ex: <http://example.com/> . +ex:emp134 ex:hireDate "2022-11-12" . +ex:emp134 ex:familyName "Smith" . + +# A semicolon means that the next triple uses the same subject as the last +# one. This is handy for listing data about a single resource. The following +# example means the same thing as the previous one. + +@prefix ex: <http://example.com/> . +ex:emp134 ex:hireDate "2022-11-12" ; + ex:familyName "Smith" . + +# A comma means that the next triple has the same subject and predicate as +# the previous one. + +ex:emp134 ex:nickname "Smithy", "Skipper", "Big J". + +# Three single or double quote marks at the beginning and end of a value let +# you define a multi-line string value. + +ex:emp134 ex:description """ +Skipper joined the company in November. + +He always has a joke for everyone.""" . + +# Using URIs from existing standard vocabulary namespaces eases both data +# integration and interoperability with the large amount of RDF that already +# exists. Mixing and matching of standard and local custom namespaces is +# common. + +@prefix vcard: <http://www.w3.org/2006/vcard/ns#> . +ex:emp134 ex:hireDate "2022-11-12" ; + vcard:family-name "Smith" . + +# Related RDF standards provide vocabularies that are popular for basic +# facts. The rdfs:label predicate from the RDF Schema standard is a common +# way to indicate a human-readable name. + +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +ex:hireDate rdfs:label "hire date" . + +# String object values can include language codes, making +# multi-lingual representation of entities easier for applications +# reading the data (for example, when generating a user interface). + +ex:hireDate rdfs:label "hire date"@en, "date d'embauche"@fr . + +# Representing a triple's object with a URI (or prefixed name) is not required +# but lets you connect up triples into a graph. + +ex:emp134 vcard:family-name "Smith" . +ex:emp113 vcard:family-name "Jones" ; + ex:reportsTo ex:emp134 . + +# Objects can be datatypes from the XML Schema part 2 standard or your own +# custom datatypes. + +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . +ex:emp134 vcard:family-name "Smith"^^xsd:string ; # default data type + ex:hireDate "2022-11-12"^^xsd:date ; + ex:rating "3.5"^^ex:someCustomType . + +# The use of schemas with RDF is optional. Schemas may describe all or a +# subset of a dataset. They use a vocabulary described by the W3C RDF Schema +# (RDFS) standard, usually with a prefix of rdfs. + +# These schemas are descriptive, to ease the accommodation of new +# datasets, not proscriptive rules about how new data should be +# created. The following declares a class. (Note that RDFS is itself +# expressed in triples.) + +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +ex:Person rdf:type rdfs:Class . + +# The following triple means the same as the preceding one but +# uses a Turtle shortcut for terseness and more readability. + +ex:Person a rdfs:Class . + +# That last triple declares that ex:Person is an instance of a class, and the +# following declares that employee 113 is an instance of the class Employee. + +ex:emp113 a ex:Employee . + +# The first triple below is actually unnecessary because a typical +# RDFS processor will infer from the second one that ex:Employee is a +# class. (Only a subset of RDF parsers perform RDFS inferencing.) + +ex:Employee a rdfs:Class . +ex:Employee rdfs:subClassOf ex:Person . + +# An RDF parser that reads the last four triples shown and understands +# RDFS will infer that ex:emp113 is an instance of ex:Person, because +# it's an instance of ex:Employee, a subclass of ex:Person. + +# RDFS lets you declare properties and associate them with classes. +# Properties are first class resources and don't "belong" to classes +# in the object-oriented sense. rdfs:domain means "the following object +# class uses the property named by this triple's subject". rdfs:range +# means "the property named by this triple's subject will have a value of +# the following class or type". + +ex:birthday rdf:type rdf:Property ; + rdfs:domain ex:Person ; + rdfs:range xsd:date . + +``` + +## Further Reading + +* [RDF Primer — Turtle version](https://www.w3.org/2007/02/turtle/primer/) from the W3C +* [What is RDF?](https://www.bobdc.com/blog/whatisrdf/) on bobdc.com +* [What is RDFS?](https://www.bobdc.com/blog/whatisrdfs/) on bobdc.com +* [Introduction to RDF and SPARQL](https://data.europa.eu/sites/default/files/d2.1.2_training_module_1.3_introduction_to_rdf_sparql_en_edp.pdf) at data.europa.eu + diff --git a/reason.html.markdown b/reason.html.markdown index 62d809cf..b8a2215d 100644 --- a/reason.html.markdown +++ b/reason.html.markdown @@ -162,7 +162,7 @@ let maxPassengers = firstTrip.capacity; /* If you define the record type in a different file, you have to reference the filename, if trainJourney was in a file called Trips.re */ -let secondTrip: Trips.firstTrip = { +let secondTrip: Trips.trainJourney = { destination: "Paris", capacity: 50, averageSpeed: 150.0, diff --git a/red.html.markdown b/red.html.markdown index 74538bd7..34c4bcd9 100644 --- a/red.html.markdown +++ b/red.html.markdown @@ -216,7 +216,7 @@ The Red/System language specification can be found [here](http://static.red-lang To learn more about Rebol and Red join the [chat on Gitter](https://gitter.im/red/red). And if that is not working for you drop a mail to us on the [Red mailing list](mailto: red-langNO_SPAM@googlegroups.com) (remove NO_SPAM). -Browse or ask questions on [Stack Overflow](stackoverflow.com/questions/tagged/red). +Browse or ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/red). Maybe you want to try Red right away? That is possible on the [try Rebol and Red site](http://tryrebol.esperconsultancy.nl). diff --git a/ro-ro/bash-ro.html.markdown b/ro-ro/bash-ro.html.markdown index 32a878b2..de946861 100644 --- a/ro-ro/bash-ro.html.markdown +++ b/ro-ro/bash-ro.html.markdown @@ -12,7 +12,7 @@ lang: ro-ro filename: LearnBash-ro.sh --- -Bash este numele shell-ului UNIX, care a fost de asemenea distribuit drept shell pentru sistemul de operare GNU și ca shell implicit pentru Linux si Mac OS X. +Bash este numele shell-ului UNIX, care a fost de asemenea distribuit drept shell pentru sistemul de operare GNU și ca shell implicit pentru Linux si macOS. Aproape toate exemplele de mai jos pot fi parte dintr-un script sau pot fi executate direct in linia de comanda. [Citește mai multe:](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/ro-ro/clojure-ro.html.markdown b/ro-ro/clojure-ro.html.markdown index 32ba9620..77052379 100644 --- a/ro-ro/clojure-ro.html.markdown +++ b/ro-ro/clojure-ro.html.markdown @@ -380,7 +380,7 @@ Clojuredocs.org contine documentatie cu exemple pentru majoritatea functiilor de [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) 4Clojure este o metoda excelenta pentru a exersa Clojure/FP (Programarea Functionala): -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org are un numar de article pentru incepatori: [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/ro-ro/elixir-ro.html.markdown b/ro-ro/elixir-ro.html.markdown index 10fec3c5..60500d64 100644 --- a/ro-ro/elixir-ro.html.markdown +++ b/ro-ro/elixir-ro.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] @@ -22,7 +22,7 @@ posibilități. # Pentru comentarii pe mai multe linii nu există sintaxă separată, # de aceea folosiți mai multe linii cu comentarii. -# Pentru a folosi shell-ul elixir utilizați comanda `iex`. +# Pentru a folosi shell-ul Elixir utilizați comanda `iex`. # Compilați modulele cu comanda `elixirc`. # Ambele comenzi vor lucra în terminal, dacă ați instalat Elixir corect. diff --git a/ro-ro/python-ro.html.markdown b/ro-ro/pythonlegacy-ro.html.markdown index ada0c034..a368ff99 100644 --- a/ro-ro/python-ro.html.markdown +++ b/ro-ro/pythonlegacy-ro.html.markdown @@ -1,10 +1,10 @@ --- -language: python +language: Python 2 (legacy) contributors: - ["Louie Dinh", "http://ldinh.ca"] translators: - ["Ovidiu Ciule", "https://github.com/ociule"] -filename: learnpython-ro.py +filename: learnpythonlegacy-ro.py lang: ro-ro --- diff --git a/rst.html.markdown b/rst.html.markdown index 2423622e..c68c1d54 100644 --- a/rst.html.markdown +++ b/rst.html.markdown @@ -6,9 +6,9 @@ contributors: filename: restructuredtext.rst --- -RST is a file format formely created by Python community to write documentation (and so, is part of Docutils). +RST, Restructured Text, is a file format created by the Python community to write documentation. It is part of [Docutils](https://docutils.sourceforge.io/rst.html). -RST files are simple text files with lightweight syntax (comparing to HTML). +RST is a markup language like HTML but is much more lightweight and easier to read. ## Installation @@ -33,25 +33,27 @@ $ pip install docutils A simple example of the file syntax: ``` -.. Lines starting with two dots are special commands. But if no command can be found, the line is considered as a comment +.. Lines starting with two dots are special commands. But if no command can be found, the line is considered as a comment. ========================================================= Main titles are written using equals signs over and under ========================================================= -Note that there must be as many equals signs as title characters. +Note that each character, including spaces, needs an equals sign above and below. -Title are underlined with equals signs too -========================================== +Titles also use equals signs but are only underneath +==================================================== Subtitles with dashes --------------------- You can put text in *italic* or in **bold**, you can "mark" text as code with double backquote ``print()``. +Special characters can be escaped using a backslash, e.g. \\ or \*. + Lists are similar to Markdown, but a little more involved. -Remember to line up list symbols (like - or *) with the left edge of the previous text block, and remember to use blank lines to separate new lists from parent lists: +Remember to line up list symbols (like - or \*) with the left edge of the previous text block, and remember to use blank lines to separate new lists from parent lists: - First item - Second item @@ -78,15 +80,15 @@ France Paris Japan Tokyo =========== ======== -More complex tables can be done easily (merged columns and/or rows) but I suggest you to read the complete doc for this :) +More complex tables can be done easily (merged columns and/or rows) but I suggest you to read the complete doc for this. :) There are multiple ways to make links: -- By adding an underscore after a word : Github_ and by adding the target URL after the text (this way has the advantage to not insert unnecessary URLs inside readable text). -- By typing a full comprehensible URL : https://github.com/ (will be automatically converted to a link) -- By making a more Markdown-like link: `Github <https://github.com/>`_ . +- By adding an underscore after a word : GitHub_ and by adding the target URL after the text (this way has the advantage of not inserting unnecessary URLs in the visible text). +- By typing a full comprehensible URL : https://github.com/ (will be automatically converted to a link). +- By making a more Markdown-like link: `GitHub <https://github.com/>`_ . -.. _Github https://github.com/ +.. _GitHub: https://github.com/ ``` diff --git a/ru-ru/asymptotic-notation-ru.html.markdown b/ru-ru/asymptotic-notation-ru.html.markdown index 7fd02c47..02ebd205 100644 --- a/ru-ru/asymptotic-notation-ru.html.markdown +++ b/ru-ru/asymptotic-notation-ru.html.markdown @@ -1,225 +1,225 @@ ----
-category: Algorithms & Data Structures
-name: Asymptotic Notation
-contributors:
- - ["Jake Prather", "http://github.com/JakeHP"]
- - ["Divay Prakash", "http://github.com/divayprakash"]
-translators:
- - ["pru-mike", "http://github.com/pru-mike"]
-lang: ru-ru
----
-
-# О-символика
-
-## Что это такое?
-
-О-символика, или асимптотическая запись, — это система символов, позволяющая
-оценить время выполнения алгоритма, устанавливая зависимость времени выполнения
-от увеличения объёма входных данных. Она также известна как оценка
-сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда
-объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро,
-если объём входных данных возрастёт? О-символика позволяет ответить на эти
-вопросы.
-
-## Можно ли по-другому найти ответы на эти вопросы?
-
-Один способ — это подсчитать число элементарных операций в зависимости от
-различных объёмов входных данных. Хотя это и приемлемое решение, тот объём
-работы, которого оно потребует, даже для простых алгоритмов делает его
-использование неоправданным.
-
-Другой способ — это измерить, какое время алгоритм потребует для завершения на
-различных объёмах входных данных. В то же время, точность и относительность
-этого метода (полученное время будет относиться только к той машине, на которой
-оно вычислено) зависит от среды выполнения: компьютерного аппаратного
-обеспечения, мощности процессора и т.д.
-
-## Виды О-символики
-
-В первом разделе этого документа мы определили, что О-символика
-позволяет оценивать алгоритмы в зависимости от изменения размера входных
-данных. Представим, что алгоритм — это функция f, n — размер входных данных и
-f(n) — время выполнения. Тогда для данного алгоритма f с размером входных
-данных n получим какое-то результирующее время выполнения f(n).
-Из этого можно построить график, где ось y — время выполнения, ось x — размер входных
-данных, а точки на графике — это время выполнения для заданного размера входных
-данных.
-
-С помощью О-символики можно оценить функцию или алгоритм
-несколькими различными способами. Например, можно оценить алгоритм исходя
-из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается
-анализ на основе верхней оценки. Как правило не используется нижняя оценка,
-потому что она не подходит под планируемые условия. Отличный пример — алгоритмы
-сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка
-большинства таких алгоритмов может быть дана как одна операция. В то время как в
-большинстве случаев добавляемые элементы должны быть отсортированы
-соответствующим образом при помощи дерева, что может потребовать обхода целой
-ветви. Это и есть худший случай, для которого планируется верхняя оценка.
-
-### Виды функций, пределы и упрощения
-
-```
-Логарифмическая функция — log n
-Линейная функция — an + b
-Квадратичная функция — an^2 + bn +c
-Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа
-Показательная функция — a^n, где a — константа
-```
-
-Приведены несколько базовых функций, используемых при определении сложности в
-различных оценках. Список начинается с самой медленно возрастающей функции
-(логарифм, наиболее быстрое время выполнения) и следует до самой быстро
-возрастающей функции (экспонента, самое медленное время выполнения). Отметим,
-что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций,
-результат намного быстрее возрастает в квадратичной, степенной
-и показательной по сравнению с логарифмической и линейной.
-
-Крайне важно понимать, что при использовании описанной далее нотации необходимо
-использовать упрощённые выражения.
-Это означает, что необходимо отбрасывать константы и слагаемые младших порядков,
-потому что если размер входных данных (n в функции f(n) нашего примера)
-увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков
-и константы становятся пренебрежительно малыми. Таким образом, если есть
-константа, например, размера 2^9001 или любого другого невообразимого размера,
-надо понимать, что её упрощение внесёт значительные искажения в точность
-оценки.
-
-Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу...
-
-```
-Логарифм — log n
-Линейная функция — n
-Квадратичная функция — n^2
-Степенная функция — n^z, где z — константа
-Показательная функция — a^n, где a — константа
-```
-
-### О Большое
-О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего
-случая, или для ограничения заданной функции сверху. Это позволяет сделать
-_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения
-алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная
-сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если
-существуют действительные константы c (c > 0) и n<sub>0</sub>, такие,
-что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>).
-
-*Пример 1*
-
-```
-f(n) = 3log n + 100
-g(n) = log n
-```
-
-Является ли `f(n)` O(g(n))?
-Является ли `3 log n + 100` O(log n)?
-Посмотрим на определение О Большого:
-
-```
-3log n + 100 <= c * log n
-```
-
-Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
-
-```
-3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1)
-```
-
-Да! По определению О Большого `f(n)` является O(g(n)).
-
-*Пример 2*
-
-```
-f(n) = 3 * n^2
-g(n) = n
-```
-
-Является ли `f(n)` O(g(n))?
-Является ли `3 * n^2` O(n)?
-Посмотрим на определение О Большого:
-
-```
-3 * n^2 <= c * n
-```
-
-Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>?
-Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)).
-
-### Омега Большое
-Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки
-лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать
-_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения
-алгоритма.
-
-`f(n)` является Ω(g(n)), если существуют действительные константы
-c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>.
-
-### Примечание
-
-Асимптотические оценки, сделаные при помощи О Большого и Омега Большого, могут
-как являться, так и не являться точными. Для того, чтобы обозначить, что границы не
-являются асимптотически точными, используются записи О Малое и Омега Малое.
-
-### О Малое
-O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней
-границы времени выполнения алгоритма при условии, что граница не является
-асимптотически точной.
-
-`f(n)` является o(g(n)), если можно подобрать такие действительные константы,
-что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
-что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
-
-Определения О-символики для О Большого и О Малого похожи. Главное отличие в том,
-что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_
-константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется
-для _**всех**_ констант c > 0.
-
-### Омега Малое
-Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки
-верхней границы времени выполнения алгоритма при условии, что граница не является
-асимптотически точной.
-
-`f(n)` является ω(g(n)), если можно подобрать такие действительные константы,
-что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так
-что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>).
-
-Определения Ω-символики и ω-символики похожи. Главное отличие в том, что
-если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_
-константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n)
-выполняется для _**всех**_ констант c > 0.
-
-### Тета
-Тета, записывается как **Θ**, — это асимптотическая запись для оценки
-_***асимптотически точной границы***_ времени выполнения алгоритма.
-
-`f(n)` является Θ(g(n)), если для некоторых действительных
-констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0)
-`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>).
-
-∴ `f(n)` является Θ(g(n)) означает, что `f(n)` является O(g(n))
-и `f(n)` является Ω(g(n)).
-
-О Большое — основной инструмент для анализа сложности алгоритмов.
-Также см. примеры по ссылкам.
-
-### Заключение
-Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и
-посмотреть дополнительную литературу. В ней даётся более глубокое описание с
-определениями и примерами.
-
-
-## Дополнительная литература
-
-* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/)
-* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/)
-
-## Ссылки
-
-* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php)
-* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903)
-
-## Ссылки (англ.)
-
-* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
-* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf)
-* [Cheatsheet 2](http://bigocheatsheet.com/)
-
+--- +category: Algorithms & Data Structures +name: Asymptotic Notation +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] + - ["Divay Prakash", "http://github.com/divayprakash"] +translators: + - ["pru-mike", "http://github.com/pru-mike"] +lang: ru-ru +--- + +# О-символика + +## Что это такое? + +О-символика, или асимптотическая запись, — это система символов, позволяющая +оценить время выполнения алгоритма, устанавливая зависимость времени выполнения +от увеличения объёма входных данных. Она также известна как оценка +сложности алгоритмов. Станет ли алгоритм невероятно медленным, когда +объём входных данных увеличится? Будет ли алгоритм выполняться достаточно быстро, +если объём входных данных возрастёт? О-символика позволяет ответить на эти +вопросы. + +## Можно ли по-другому найти ответы на эти вопросы? + +Один способ — это подсчитать число элементарных операций в зависимости от +различных объёмов входных данных. Хотя это и приемлемое решение, тот объём +работы, которого оно потребует, даже для простых алгоритмов делает его +использование неоправданным. + +Другой способ — это измерить, какое время алгоритм потребует для завершения на +различных объёмах входных данных. В то же время, точность и относительность +этого метода (полученное время будет относиться только к той машине, на которой +оно вычислено) зависит от среды выполнения: компьютерного аппаратного +обеспечения, мощности процессора и т.д. + +## Виды О-символики + +В первом разделе этого документа мы определили, что О-символика +позволяет оценивать алгоритмы в зависимости от изменения размера входных +данных. Представим, что алгоритм — это функция f, n — размер входных данных и +f(n) — время выполнения. Тогда для данного алгоритма f с размером входных +данных n получим какое-то результирующее время выполнения f(n). +Из этого можно построить график, где ось y — время выполнения, ось x — размер входных +данных, а точки на графике — это время выполнения для заданного размера входных +данных. + +С помощью О-символики можно оценить функцию или алгоритм +несколькими различными способами. Например, можно оценить алгоритм исходя +из нижней оценки, верхней оценки, тождественной оценки. Чаще всего встречается +анализ на основе верхней оценки. Как правило, не используется нижняя оценка, +потому что она не подходит под планируемые условия. Отличный пример — алгоритмы +сортировки, особенно добавление элементов в древовидную структуру. Нижняя оценка +большинства таких алгоритмов может быть дана как одна операция. В то время как в +большинстве случаев добавляемые элементы должны быть отсортированы +соответствующим образом при помощи дерева, что может потребовать обхода целой +ветви. Это и есть худший случай, для которого планируется верхняя оценка. + +### Виды функций, пределы и упрощения + +``` +Логарифмическая функция — log n +Линейная функция — an + b +Квадратичная функция — an^2 + bn +c +Степенная функция — an^z + . . . + an^2 + a*n^1 + a*n^0, где z — константа +Показательная функция — a^n, где a — константа +``` + +Приведены несколько базовых функций, используемых при определении сложности в +различных оценках. Список начинается с самой медленно возрастающей функции +(логарифм, наиболее быстрое время выполнения) и следует до самой быстро +возрастающей функции (экспонента, самое медленное время выполнения). Отметим, +что в то время, как «n», или размер входных данных, возрастает в каждой из этих функций, +результат намного быстрее возрастает в квадратичной, степенной +и показательной по сравнению с логарифмической и линейной. + +Крайне важно понимать, что при использовании описанной далее нотации необходимо +использовать упрощённые выражения. +Это означает, что необходимо отбрасывать константы и слагаемые младших порядков, +потому что если размер входных данных (n в функции f(n) нашего примера) +увеличивается до бесконечности (в пределе), тогда слагаемые младших порядков +и константы становятся пренебрежительно малыми. Таким образом, если есть +константа, например, размера 2^9001 или любого другого невообразимого размера, +надо понимать, что её упрощение внесёт значительные искажения в точность +оценки. + +Т.к. нам нужны упрощённые выражения, немного скорректируем нашу таблицу... + +``` +Логарифм — log n +Линейная функция — n +Квадратичная функция — n^2 +Степенная функция — n^z, где z — константа +Показательная функция — a^n, где a — константа +``` + +### О Большое +О Большое, записывается как **О**, — это асимптотическая запись для оценки худшего +случая, или для ограничения заданной функции сверху. Это позволяет сделать +_**асимптотическую оценку верхней границы**_ скорости роста времени выполнения +алгоритма. Пусть `f(n)` — время выполнения алгоритма, а `g(n)` — заданная временная +сложность, которая проверяется для алгоритма. Тогда `f(n)` — это O(g(n)), если +существуют действительные константы c (c > 0) и n<sub>0</sub>, такие, +что `f(n)` <= `c g(n)` выполняется для всех n, начиная с некоторого n<sub>0</sub> (n > n<sub>0</sub>). + +*Пример 1* + +``` +f(n) = 3log n + 100 +g(n) = log n +``` + +Является ли `f(n)` O(g(n))? +Является ли `3 log n + 100` O(log n)? +Посмотрим на определение О Большого: + +``` +3log n + 100 <= c * log n +``` + +Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>? + +``` +3log n + 100 <= 150 * log n, n > 2 (не определенно для n = 1) +``` + +Да! По определению О Большого `f(n)` является O(g(n)). + +*Пример 2* + +``` +f(n) = 3 * n^2 +g(n) = n +``` + +Является ли `f(n)` O(g(n))? +Является ли `3 * n^2` O(n)? +Посмотрим на определение О Большого: + +``` +3 * n^2 <= c * n +``` + +Существуют ли константы c и n<sub>0</sub>, такие, что выражение верно для всех n > n<sub>0</sub>? +Нет, не существуют. `f(n)` НЕ ЯВЛЯЕТСЯ O(g(n)). + +### Омега Большое +Омега Большое, записывается как **Ω**, — это асимптотическая запись для оценки +лучшего случая, или для ограничения заданной функции снизу. Это позволяет сделать +_**асимптотическую оценку нижней границы**_ скорости роста времени выполнения +алгоритма. + +`f(n)` является Ω(g(n)), если существуют действительные константы +c (c > 0) и n<sub>0</sub> (n<sub>0</sub> > 0), такие, что `f(n)` >= `c g(n)` для всех n > n<sub>0</sub>. + +### Примечание + +Асимптотические оценки, сделанные при помощи О Большого и Омега Большого, могут +как являться, так и не являться точными. Для того чтобы обозначить, что границы не +являются асимптотически точными, используются записи О Малое и Омега Малое. + +### О Малое +O Малое, записывается как **о**, — это асимптотическая запись для оценки верхней +границы времени выполнения алгоритма при условии, что граница не является +асимптотически точной. + +`f(n)` является o(g(n)), если можно подобрать такие действительные константы, +что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так +что `f(n)` < `c g(n)` выполняется для всех n (n > n<sub>0</sub>). + +Определения О-символики для О Большого и О Малого похожи. Главное отличие в том, +что если f(n) = O(g(n)), тогда условие f(n) <= c g(n) выполняется, если _**существует**_ +константа c > 0, но если f(n) = o(g(n)), тогда условие f(n) < c g(n) выполняется +для _**всех**_ констант c > 0. + +### Омега Малое +Омега Малое, записывается как **ω**, — это асимптотическая запись для оценки +верхней границы времени выполнения алгоритма при условии, что граница не является +асимптотически точной. + +`f(n)` является ω(g(n)), если можно подобрать такие действительные константы, +что для всех c (c > 0) найдётся n<sub>0</sub> (n<sub>0</sub> > 0), так +что `f(n)` > `c g(n)` выполняется для всех n (n > n<sub>0</sub>). + +Определения Ω-символики и ω-символики похожи. Главное отличие в том, что +если f(n) = Ω(g(n)), тогда условие f(n) >= c g(n) выполняется, если _**существует**_ +константа c > 0, но если f(n) = ω(g(n)), тогда условие f(n) > c g(n) +выполняется для _**всех**_ констант c > 0. + +### Тета +Тета, записывается как **Θ**, — это асимптотическая запись для оценки +_***асимптотически точной границы***_ времени выполнения алгоритма. + +`f(n)` является Θ(g(n)), если для некоторых действительных +констант c1, c2 и n<sub>0</sub> (c1 > 0, c2 > 0, n<sub>0</sub> > 0) +`c1 g(n)` < `f(n)` < `c2 g(n)` для всех n (n > n<sub>0</sub>). + +∴ `f(n)` является Θ(g(n)) означает, что `f(n)` является O(g(n)) +и `f(n)` является Ω(g(n)). + +О Большое — основной инструмент для анализа сложности алгоритмов. +Также см. примеры по ссылкам. + +### Заключение +Такую тему сложно изложить кратко, поэтому обязательно стоит пройти по ссылкам и +посмотреть дополнительную литературу. В ней даётся более глубокое описание с +определениями и примерами. + + +## Дополнительная литература + +* [Алгоритмы на Java](https://www.ozon.ru/context/detail/id/18319699/) +* [Алгоритмы. Построение и анализ](https://www.ozon.ru/context/detail/id/33769775/) + +## Ссылки + +* [Оценки времени исполнения. Символ O()](http://algolist.manual.ru/misc/o_n.php) +* [Асимптотический анализ и теория вероятностей](https://www.lektorium.tv/course/22903) + +## Ссылки (англ.) + +* [Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1) +* [Cheatsheet 1](http://web.mit.edu/broder/Public/asymptotics-cheatsheet.pdf) +* [Cheatsheet 2](http://bigocheatsheet.com/) + diff --git a/ru-ru/bash-ru.html.markdown b/ru-ru/bash-ru.html.markdown index ce918340..9978380a 100644 --- a/ru-ru/bash-ru.html.markdown +++ b/ru-ru/bash-ru.html.markdown @@ -26,7 +26,7 @@ lang: ru-ru Bash — это командная оболочка unix, которая распространялась как оболочка для операционной системы GNU и используется в качестве оболочки по умолчанию -для Linux и Mac OS X. +для Linux и macOS. Почти все нижеприведённые примеры могут быть частью shell-скриптов или исполнены напрямую в shell. diff --git a/ru-ru/binary-search-ru.html.markdown b/ru-ru/binary-search-ru.html.markdown index 9ed62cb8..ab1a1585 100644 --- a/ru-ru/binary-search-ru.html.markdown +++ b/ru-ru/binary-search-ru.html.markdown @@ -55,7 +55,7 @@ def search(arr, x): ### На заметку -Существует и другая форма двоичного поиска, которая можеть быть полезна. +Существует и другая форма двоичного поиска, которая может быть полезна. ## На почитать diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index 35994749..43e9e6a3 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -1,5 +1,5 @@ --- -language: c++ +language: C++ filename: learncpp-ru.cpp contributors: - ["Steven Basart", "http://github.com/xksteven"] @@ -17,7 +17,7 @@ C++ - компилируемый, статически типизированн - "лучшая замена C" - язык с поддержкой абстракции данных -- язык с поддержкой объектно-ориентированого программирования +- язык с поддержкой объектно-ориентированного программирования - язык с поддержкой обобщенного программирования Хотя его синтаксис может показаться более трудным или сложным для понимания, чем в более современных языках, @@ -43,11 +43,11 @@ int main(int argc, char** argv) // Аргументы командной строки, переданные в программу, хранятся в переменных // argc и argv, так же, как и в C. // argc указывает на количество аргументов, - // а argv является массивом C-подобных строк (char*), который непосредсвенно + // а argv является массивом C-подобных строк (char*), который непосредственно // содержит аргументы. // Первым аргументом всегда передается имя программы. - // argc и argv могут быть опущены, если вы не планируете работать с аругментами - // коммандной строки. + // argc и argv могут быть опущены, если вы не планируете работать с аргументами + // командной строки. // Тогда сигнатура функции будет иметь следующий вид: int main() // Возвращаемое значение 0 указывает на успешное завершение программы. @@ -162,7 +162,7 @@ void foo() int main() { - // Включает все функци из пространства имен Second в текущую область видимости. + // Включает все функции из пространства имен Second в текущую область видимости. // Обратите внимание, что простой вызов foo() больше не работает, // так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или // из глобальной области видимости. @@ -471,6 +471,7 @@ int main() { // членам\методам без открытых или защищенных методов для этого. class OwnedDog : public Dog { +public: void setOwner(const std::string& dogsOwner); // Переопределяем поведение функции печати для всех OwnedDog. Смотрите @@ -582,10 +583,10 @@ public: // Во время компиляции компилятор фактически генерирует копии каждого шаблона // с замещенными параметрами, поэтому полное определение класса должно присутствовать -// при каждом вызове. Именно поэтому классы шаблонов полностью определены в +// при каждом вызове. Именно поэтому шаблоны классов полностью определены в // заголовочных файлах. -// Чтобы создать экземпляр класса шаблона на стеке: +// Чтобы создать экземпляр шаблона класса на стеке: Box<int> intBox; // и вы можете использовать его, как и ожидалось: @@ -605,7 +606,7 @@ boxOfBox.insert(intBox); // http://en.wikipedia.org/wiki/Typename // (да-да, это ключевое слово имеет собственную страничку на вики). -// Аналогичным образом, шаблонная функция: +// Аналогичным образом, шаблон функции: template<class T> void barkThreeTimes(const T& input) { @@ -622,7 +623,7 @@ Dog fluffy; fluffy.setName("Fluffy"); barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза. -//Параметры шаблона не должны быть классами: +// Параметры шаблона не должны быть классами: template<int Y> void printMessage() { cout << "Learn C++ in " << Y << " minutes!" << endl; @@ -680,7 +681,7 @@ catch (...) // некоторого ресурса неразрывно совмещается с инициализацией, а освобождение - // с уничтожением объекта. -// Чтобы понять, на сколько это полезно, +// Чтобы понять, насколько это полезно, // рассмотрим функцию, которая использует обработчик файлов в С: void doSomethingWithAFile(const char* filename) { @@ -796,7 +797,7 @@ void doSomethingWithAFile(const std::string& filename) // - Контейнеры - стандартная библиотека связанных списков, векторы // (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически // уничтожается сразу же, когда выходит за пределы области видимости. -// - Ипользование мьютексов lock_guard и unique_lock +// - Использование мьютексов lock_guard и unique_lock // Контейнеры с пользовательскими классами в качестве ключей требуют // сравнивающих функций в самом объекте или как указатель на функцию. Примитивы diff --git a/ru-ru/c-ru.html.markdown b/ru-ru/c-ru.html.markdown index 44e7ad3b..a146a76b 100644 --- a/ru-ru/c-ru.html.markdown +++ b/ru-ru/c-ru.html.markdown @@ -1,5 +1,5 @@ --- -language: c +language: C filename: learnc-ru.c contributors: - ["Adam Bard", "http://adambard.com/"] @@ -77,7 +77,7 @@ int main() { // sizeof(obj) возвращает размер объекта obj в байтах. printf("%zu\n", sizeof(int)); // => 4 (на большинстве машин int занимает 4 байта) - // Если аргуметом sizeof будет выражение, то этот аргумент вычисляется + // Если аргументом sizeof будет выражение, то этот аргумент вычисляется // ещё во время компиляции кода (кроме динамических массивов). int a = 1; // size_t это беззнаковый целый тип который использует как минимум 2 байта @@ -308,7 +308,7 @@ int main() { // Это работает, потому что при обращении к имени массива возвращается // указатель на первый элемент. // Например, когда массив передаётся в функцию или присваивается указателю, он - // неяввно преобразуется в указатель. + // неявно преобразуется в указатель. // Исключения: когда массив является аргументом для оператор '&': int arr[10]; int (*ptr_to_arr)[10] = &arr; // &arr не является 'int *'! @@ -335,7 +335,7 @@ int main() { // Работа с памятью с помощью указателей может давать неожиданные и // непредсказуемые результаты. - printf("%d\n", *(my_ptr + 21)); // => Напечатает кто-нибудь-знает-что? + printf("%d\n", *(my_ptr + 21)); // => Напечатает кто-нибудь знает, что? // Скорей всего программа вылетит. // Когда вы закончили работать с памятью, которую ранее выделили, вам необходимо @@ -353,7 +353,7 @@ int main() { // Это не работает, если строка является массивом // (потенциально задаваемой с помощью строкового литерала) - // который находиться в перезаписываемой части памяти: + // который находится в перезаписываемой части памяти: char foo[] = "foo"; foo[0] = 'a'; // это выполнится и строка теперь "aoo" @@ -426,7 +426,7 @@ void function_1() { // Можно получить доступ к структуре и через указатель (*my_rec_ptr).width = 30; - // ... или ещё лучше: используйте оператор -> для лучшей читабельночти + // ... или ещё лучше: используйте оператор -> для лучшей читабельности my_rec_ptr->height = 10; // то же что и "(*my_rec_ptr).height = 10;" } @@ -471,12 +471,12 @@ void str_reverse_through_pointer(char *str_in) { Лучше всего найдите копию [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language) Это **книга** написанная создателями Си. Но будьте осторожны, она содержит идеи которые больше не считаются хорошими. -Другой хороший ресурс: [Learn C the hard way](http://c.learncodethehardway.org/book/). +Другой хороший ресурс: [Learn C the hard way](http://learncodethehardway.org/c/). Если у вас появился вопрос, почитайте [compl.lang.c Frequently Asked Questions](http://c-faq.com). Очень важно использовать правильные отступы и ставить пробелы в нужных местах. -Читаемый код лучше чем красивый или быстрый код. +Читаемый код лучше, чем красивый или быстрый код. Чтобы научиться писать хороший код, почитайте [Linux kernel coding style](https://www.kernel.org/doc/Documentation/CodingStyle). Также не забывайте, что [Google](http://google.com) и [Яндекс](http://yandex.ru) – ваши хорошие друзья. diff --git a/ru-ru/clojure-ru.html.markdown b/ru-ru/clojure-ru.html.markdown index 19233d23..66986fa0 100644 --- a/ru-ru/clojure-ru.html.markdown +++ b/ru-ru/clojure-ru.html.markdown @@ -421,7 +421,7 @@ Clojuredocs.org — сайт документации языка с пример [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) 4Clojure — отличный способ закрепить навыки программирования на clojure, решая задачи вместе с коллегами со всего мира: -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org (да, именно) неплохой перечень статей для начинающих: [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/ru-ru/common-lisp-ru.html.markdown b/ru-ru/common-lisp-ru.html.markdown index d5f9bf0e..0490ee30 100644 --- a/ru-ru/common-lisp-ru.html.markdown +++ b/ru-ru/common-lisp-ru.html.markdown @@ -14,7 +14,8 @@ Common Lisp - мультипарадигменный язык программи спектра задач. Его частенько называют программируемым языком программирования. -Идеальная отправная точка - книга [Common Lisp на практике (перевод)](http://lisper.ru/pcl/). +Идеальная отправная точка - книга +[Common Lisp на практике (перевод)](https://github.com/pcl-ru/pcl-ru/releases/download/v1.1/pcl-ru.pdf). Ещё одна популярная книга [Land of Lisp](http://landoflisp.com/). И одна из последних книг [Common Lisp Recipes](http://weitz.de/cl-recipes/) вобрала в себя лучшие архитектурные решения на основе опыта коммерческой работки автора. @@ -674,7 +675,7 @@ nil ; ложь; а ещё пустой список () тож ## Для чтения На русском -- [Practical Common Lisp](http://www.gigamonkeys.com/book/) +- [Practical Common Lisp](https://github.com/pcl-ru/pcl-ru/releases/download/v1.1/pcl-ru.pdf) На английском - [Practical Common Lisp](http://www.gigamonkeys.com/book/) @@ -685,7 +686,7 @@ nil ; ложь; а ещё пустой список () тож На русском -- [Lisper.ru](http://lisper.ru/) +- [Сообщество в Telegram](https://t.me/lisp_forever) На английском diff --git a/ru-ru/css-ru.html.markdown b/ru-ru/css-ru.html.markdown index e0e5e30b..b543bfeb 100644 --- a/ru-ru/css-ru.html.markdown +++ b/ru-ru/css-ru.html.markdown @@ -20,12 +20,12 @@ HTML элементы и определять их внешний вид. **ВАЖНО:** Так как результатом применения CSS является изменение внешнего вида элементов, постарайтесь использовать CSS-песочницы при изучении языка. -Например [dabblet](http://dabblet.com/). +Например, [dabblet](http://dabblet.com/). В данной статье рассматриваются в первую очередь синтаксис и общие рекомендации. ```css -/* Для комментариев используется слеш-астериск, как на этой строчке. +/* Для комментариев используется слэш-астериск, как на этой строчке. В CSS нет однострочных комментариев; все комментарии записываются таким способом */ /* #################### @@ -104,7 +104,7 @@ div.some-parent.class-name {} .i-am-any-before ~ .this-element {} -/* Существуют псевдо-классы, позволяющие изменять внешний вид элемента +/* Существуют псевдоклассы, позволяющие изменять внешний вид элемента в зависимости от событий, произошедших с элементом */ /* например, когда курсор наведен на элемент */ diff --git a/ru-ru/elixir-ru.html.markdown b/ru-ru/elixir-ru.html.markdown index c8c2c060..8dd48ba7 100644 --- a/ru-ru/elixir-ru.html.markdown +++ b/ru-ru/elixir-ru.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] diff --git a/ru-ru/forth-ru.html.markdown b/ru-ru/forth-ru.html.markdown index 05316578..96fa0941 100644 --- a/ru-ru/forth-ru.html.markdown +++ b/ru-ru/forth-ru.html.markdown @@ -10,11 +10,12 @@ lang: ru-ru Форт создан Чарлзом Муром в 70-е годы. Это императивный, стековый язык программирования и среда исполнения программ. Использовался в таких проектах как Open Firmware. Продолжает применятся в проектах. Применяется в НАСА. -Внимание: эта материал использует реализацию Форта - Gforth, но большая часть написанного будет работать в других средах. +Внимание: этот материал использует реализацию Форта - Gforth, но большая часть написанного будет работать в других средах. -``` + +```forth \ Это комментарий -( Это тоже комментарий, но использыется для предоределённых слов ) +( Это тоже комментарий, но используется для предоределённых слов ) \ --------------------------------- Прекурсор -------------------------------- diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown index 6c8622cc..22249a6e 100644 --- a/ru-ru/go-ru.html.markdown +++ b/ru-ru/go-ru.html.markdown @@ -29,13 +29,13 @@ Go - это язык общего назначения, целью которо комментарий */ // Ключевое слово package присутствует в начале каждого файла. -// Main это специальное имя, обозначающее исполняемый файл, нежели библиотеку. +// main это специальное имя, обозначающее исполняемый файл, нежели библиотеку. package main // Import предназначен для указания зависимостей этого файла. import ( "fmt" // Пакет в стандартной библиотеке Go - "io/ioutil" // Реализация функций ввод/ввывода. + "io/ioutil" // Реализация функций ввод/вывода. "net/http" // Да, это веб-сервер! "strconv" // Конвертирование типов в строки и обратно m "math" // Импортировать math под локальным именем m. @@ -82,7 +82,7 @@ func learnTypes() { // Символ не из ASCII. Исходный код Go в кодировке UTF-8. g := 'Σ' // тип rune, это алиас для типа int32, содержит символ юникода. - f := 3.14195 // float64, 64-х битное число с плавающей точкой (IEEE-754). + f := 3.14159 // float64, 64-х битное число с плавающей точкой (IEEE-754). c := 3 + 4i // complex128, внутри себя содержит два float64. // Синтаксис var с инициализациями. @@ -270,7 +270,7 @@ func learnErrorHandling() { // c – это тип данных channel (канал), объект для конкурентного взаимодействия. func inc(i int, c chan int) { - c <- i + 1 // когда channel слева, <- являтся оператором "отправки". + c <- i + 1 // когда channel слева, <- является оператором "отправки". } // Будем использовать функцию inc для конкурентной инкрементации чисел. @@ -334,12 +334,12 @@ func requestServer() { ## Что дальше -Основа всех основ в Go это [официальный веб сайт](http://golang.org/). +Основа всех основ в Go это [официальный веб сайт](https://go.dev/). Там можно пройти туториал, поиграться с интерактивной средой Go и почитать объёмную документацию. Для живого ознакомления рекомендуется почитать исходные коды [стандартной -библиотеки Go](http://golang.org/src/pkg/). Отлично задокументированная, она +библиотеки Go](https://go.dev/src/). Отлично задокументированная, она является лучшим источником для чтения и понимания Go, его стиля и идиом. Либо -можно, кликнув на имени функции в [документации](http://golang.org/pkg/), +можно, кликнув на имени функции в [документации](https://go.dev/pkg/), перейти к ее исходным кодам. diff --git a/ru-ru/haml-ru.html.markdown b/ru-ru/haml-ru.html.markdown index c2f8852e..ed823496 100644 --- a/ru-ru/haml-ru.html.markdown +++ b/ru-ru/haml-ru.html.markdown @@ -39,7 +39,7 @@ $ haml input_file.haml output_file.html / Комментарии / ------------------------------------------- -/ Комментари начинается с символа косой черты. +/ Комментарии начинается с символа косой черты. / Для написания многострочного комментария расположите ваш комментарий @@ -94,7 +94,7 @@ $ haml input_file.haml output_file.html / выведет 'Да & да' / - Чтобы выполнять Ruby-код без экранрования, можно использовать + Чтобы выполнять Ruby-код без экранирования, можно использовать "восклицательный знак" и "равно" (!=) %p @@ -196,13 +196,13 @@ $ haml input_file.haml output_file.html / ------------------------------------------- / - Фильтры передают связанный блок текста в соотвествующую + Фильтры передают связанный блок текста в соответствующую фильтрующую программу и возвращают результат в Haml Фильтр обозначается двоеточием и названием фильтра: / Markdown filter :markdown - # Заголовк + # Заголовок Текст **внутри** *блока* @@ -221,7 +221,7 @@ $ haml input_file.haml output_file.html </script> / - Существует множество типов фильров (:markdown, :javascript, :coffee, + Существует множество типов фильтров (:markdown, :javascript, :coffee, :css, :ruby и так далее). Вы можете определить собственный фильтр c помощью Haml::Filters. diff --git a/ru-ru/haskell-ru.html.markdown b/ru-ru/haskell-ru.html.markdown index b1b8eb79..aada30c1 100644 --- a/ru-ru/haskell-ru.html.markdown +++ b/ru-ru/haskell-ru.html.markdown @@ -8,7 +8,7 @@ translators: lang: ru-ru --- -Haskell разрабатывался, как чистый функциональный язык программирования, применимый на практике. Язык известен благодаря своей системе типов, и "знаменит" благодаря монадам. [Меня][autor] же Haskell заставляет возвращаться к себе снова и снова именно своей элегантностью и [я][autor] получаю истинное удовольствие, программируя на Haskell. +Haskell разрабатывался, как чистый функциональный язык программирования, применимый на практике. Язык известен благодаря своей системе типов, и "знаменит" благодаря монадам. [Меня][author] же Haskell заставляет возвращаться к себе снова и снова именно своей элегантностью и [я][author] получаю истинное удовольствие, программируя на Haskell. ```haskell -- Однострочные комментарии начинаются с двух дефисов @@ -172,7 +172,7 @@ fib x первое определение, к образцу которого "подойдет" набор аргументов -} fib 1 = 1 -fib 2 = 2 +fib 2 = 1 fib x = fib (x - 1) + fib (x - 2) -- Pattern matching для кортежей выглядит так @@ -544,4 +544,4 @@ Haskell прост в установке, забирайте [здесь](http:/ [Learn you a Haskell](http://learnyouahaskell.com/) и [Real World Haskell](http://book.realworldhaskell.org/). -[autor]: http://adit.io имеется в виду автор оригинального текста Adit Bhargava *(примечание переводчика)* +[author]: http://adit.io имеется в виду автор оригинального текста Adit Bhargava *(примечание переводчика)* diff --git a/ru-ru/html-ru.html.markdown b/ru-ru/html-ru.html.markdown index 120981b9..e18fb8a0 100644 --- a/ru-ru/html-ru.html.markdown +++ b/ru-ru/html-ru.html.markdown @@ -8,28 +8,28 @@ translators: lang: ru-ru --- -HTML расшифровывается как Hypertext Markup Language(гипертекстовый язык разметки). -Это язык используют для написания страниц для World Wide Web(всемирной паутины). -Это язык разметки позволяет писать веб-страниц с помощью кода, чтобы определять, -как должны быть отображены текст и данные. +HTML расшифровывается как Hypertext Markup Language (гипертекстовый язык разметки). +Этот язык используют для написания страниц для World Wide Web (всемирной паутины). +Этот язык разметки позволяет описать веб-страницу с помощью кода, чтобы определить, +как на ней должны быть отображены текст и данные. На самом деле, HTML файлы представляют собой простые текстовые файлы. -Что такое разметка? Это способ организации данных страницы, -путем открытия и закрытия тегов(помещая данные внутрь этих тегов). -Эта разметка служит, чтобы придать значение тексту, который он окружает. +Что такое разметка? Это способ организации данных страницы +путем открытия и закрытия тегов и помещения данных внутрь этих тегов. +Эта разметка служит, чтобы придать значение тексту, который она окружает. Как и в других языках программирования, HTML имеет много версий. Здесь мы будем говорить о HTML5. **Примечание:** Вы можете тестировать различные теги и элементы по мере продвижения -через учебник на сайте, как [codepen](http://codepen.io/pen/) для того, чтобы увидеть +через учебник на сайте [codepen](http://codepen.io/pen/) для того, чтобы увидеть их влияние, понять, как они работают и ознакомиться с языком. -В данной статье рассматривается в основном HTML синтаксис и некоторые полезные советы. +В данной статье рассматривается в основном HTML-синтаксис и некоторые полезные советы. ```html -<!-- Комментарии заключаются как эта лини\! --> +<!-- Это комментарий. --> <!-- #################### Теги #################### --> -<!-- Ниже приведен пример HTML-файл, который мы будем анализировать. --> +<!-- Ниже приведен пример HTML-файла, который мы будем анализировать. --> <!doctype html> <html> @@ -39,7 +39,7 @@ HTML расшифровывается как Hypertext Markup Language(гипе <body> <h1>Привет, мир!</h1> <a href = "http://codepen.io/anon/pen/xwjLbZ"> - Переходите сюда, чтоб посмотреть как это выглядит. + Переходите сюда, чтобы посмотреть, как это выглядит. </a> <p>Это параграф.</p> <p>Это другой параграф.</p> @@ -51,41 +51,41 @@ HTML расшифровывается как Hypertext Markup Language(гипе </body> </html> -<!-- HTML-файл всегда начинается с указанием браузеру, что страница это HTML. --> +<!-- HTML-файл всегда начинается с указания браузеру, что страница — это HTML. --> <!doctype html> -<!-- После этого, страница начинается с <html> тега. --> +<!-- После этого страница начинается с <html> тега. --> <html> -<!-- страница будет закрыта в конце с помощью тега </html>. --> +<!-- Страница будет закрыта в конце с помощью тега </html>. --> </html> <!-- Ничто не должно появиться после этого заключительного тега. --> -<!-- Внутри (между открывающим и закрывающим тегами <html> </ html>), мы находим: --> +<!-- Внутри (между открывающим и закрывающим тегами <html> </ html>) мы находим: --> -<!-- Заголовок определяется <head> (it он должен быть закрыт </head>). --> +<!-- Заголовок определяется <head> (и он должен быть закрыт </head>). --> <!-- Заголовок содержит описание и дополнительную информацию, которая не отображается; это метаданные. --> <head> - <title>Мой сайт</title><!-- Тег <title> указывает браузеру заголовок, чтобы показать в строке заголовка названия и вкладки браузера окна. --> + <title>Мой сайт</title><!-- Тег <title> указывает браузеру заголовок, который следует показать в строке заголовка названия и вкладки браузера окна. --> </head> -<!-- После секция <head>, находится секция - <body> --> -<!-- До этого момента, ничего описаное не будет отображаться в окне браузера. --> -<!-- Мы должны наполнить <body> содержанием, которое будет отображаться. --> +<!-- После секции <head>, находится секция - <body> --> +<!-- До этого момента, ничего из описанного не будет отображаться в окне браузера. --> +<!-- Мы должны наполнить <body> содержанием, которое будет отображаться. --> <body> <h1>Hello, world!</h1> <!-- Тег h1 создает заголовок. --> - <!-- Так же существуют другие заголовки от имеющего большее значение <h1> по убыванию к <h6>. --> - <a href = "http://codepen.io/anon/pen/xwjLbZ">Переходите сюда, чтоб посмотреть как это выглядит.</a> - <!--гиперссылка на URL, заданнf атрибутом href="" --> - <p>Это параграф.</p> <!-- Тег <p> позволяет нам добавдять текст на странице HTML. --> + <!-- Также существуют другие заголовки от имеющего большее значение <h1> до меньшего <h6>. --> + <a href = "http://codepen.io/anon/pen/xwjLbZ">Переходите сюда, чтобы посмотреть, как это выглядит.</a> + <!--гиперссылка на URL, заданная атрибутом href="" --> + <p>Это параграф.</p> <!-- Тег <p> позволяет нам добавлять текст на странице HTML. --> <p>Это другой параграф.</p> <ul> <!-- Тег <ul> создает маркированный список. --> - <!-- Для того, чтобы иметь пронумерованный список лучше использовать <ol> - тогда первый элемент будет иметь значение 1. для второго элемента, 2. и так далее. --> - <li>Это элемент в не нумерованном списке (маркированный список)</li> + <!-- Для того, чтобы иметь пронумерованный список, лучше использовать <ol> + тогда первый элемент будет иметь значение 1., для второго элемента 2. и так далее. --> + <li>Это элемент в ненумерованном списке (маркированный список)</li> <li>Это еще один элемент</li> <li>И это последний пункт в списке</li> </ul> @@ -124,6 +124,6 @@ HTML файлы имеют окончание(расширение) `.html`. ## Узнать больше -* [википедиа](https://ru.wikipedia.org/wiki/HTML) +* [википедия](https://ru.wikipedia.org/wiki/HTML) * [HTML учебник](https://developer.mozilla.org/ru/docs/Web/HTML) * [htmlbook](http://htmlbook.ru/) diff --git a/ru-ru/javascript-ru.html.markdown b/ru-ru/javascript-ru.html.markdown index 1f1ffce6..4c4fa503 100644 --- a/ru-ru/javascript-ru.html.markdown +++ b/ru-ru/javascript-ru.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] filename: javascript-ru.js translators: @@ -420,7 +420,7 @@ myObj.__proto__ = myPrototype; myObj.meaningOfLife; // = 42 // Для функций это тоже работает. -myObj.myFunc(); // = "Привет, мир!" +myObj.myFunc(); // = "привет, мир!" // Если интерпретатор не найдёт свойство в прототипе, то продожит поиск // в прототипе прототипа и так далее. @@ -473,7 +473,7 @@ if (0) { } // Впрочем, объекты-обёртки и встроенные типы имеют общие прототипы, -// поэтому вы можете расширить функционал строк, например: +// поэтому вы можете расширить функциональность строк, например: String.prototype.firstCharacter = function() { return this.charAt(0); } @@ -504,7 +504,7 @@ if (Object.create === undefined) { // не перезаписываем мето [Mozilla Developer Network](https://developer.mozilla.org/ru/docs/Web/JavaScript) — предоставляет отличную документацию для JavaScript, как он используется в браузерах. -Кроме того, это вики, поэтому, если вы знаете больше, вы можете помочь другим, +Кроме того, это вики. Поэтому, если вы знаете больше, вы можете помочь другим, делясь своими знаниями. [JavaScript Garden](http://bonsaiden.github.io/JavaScript-Garden/ru/) — это diff --git a/ru-ru/kotlin-ru.html.markdown b/ru-ru/kotlin-ru.html.markdown index 85f44c96..6ec52927 100644 --- a/ru-ru/kotlin-ru.html.markdown +++ b/ru-ru/kotlin-ru.html.markdown @@ -333,7 +333,7 @@ fun helloWorld(val name : String) { } /* - Расширения - это способ добавить новый функционал к классу. + Расширения - это способ добавить новую функциональность к классу. Это то же самое, что методы расширений в C#. */ fun String.remove(c: Char): String { diff --git a/ru-ru/learnvisualbasic-ru.html.markdown b/ru-ru/learnvisualbasic-ru.html.markdown index 72e1358c..6242fc42 100644 --- a/ru-ru/learnvisualbasic-ru.html.markdown +++ b/ru-ru/learnvisualbasic-ru.html.markdown @@ -8,7 +8,7 @@ filename: learnvisualbasic-ru.vb lang: ru-ru --- -```vbnet +```visualbasic Module Module1 Sub Main() diff --git a/ru-ru/linker-ru.html.markdown b/ru-ru/linker-ru.html.markdown index 7df29c23..14cfd229 100644 --- a/ru-ru/linker-ru.html.markdown +++ b/ru-ru/linker-ru.html.markdown @@ -34,11 +34,11 @@ lang: ru-ru # Определяем точку входа в программу ENTRY(Reset_Handler) -# Определяем перемнную которая содержит адрес вершины стека +# Определяем переменную которая содержит адрес вершины стека _estack = 0x20020000; -# Определяем перемнную которая содержит значение размера кучи +# Определяем переменную которая содержит значение размера кучи _Min_Heap_Size = 0x200; -# Определяем перемнную которая содержит значение размера стека +# Определяем переменную которая содержит значение размера стека _Min_Stack_Size = 0x400; # Описание карты памяти доступной для данного процессора @@ -50,7 +50,7 @@ _Min_Stack_Size = 0x400; # RAM - начинается с адреса 0x20000000 и занимает 128 Кбайт; # CCMRAM - начинается с адреса 0x10000000и занимает 64 Кбайт; # FLASH - начинается с адреса 0x8000000 занимает 1024 Кбайт; -# Причем RAM память доступка для чтения, записи и исполнения. +# Причем RAM память доступна для чтения, записи и исполнения. # CCMRAM память доступна только на чтение и запись. # FLASH память доступна на чтение и исполнение. MEMORY @@ -70,7 +70,7 @@ SECTIONS . = ALIGN(4); # Существует опция --gc-sections, которая позволяет собирать мусор из неиспользуемых - # входных разделов. И если есть разделы, которые сборщик муссора не должен трогать, + # входных разделов. И если есть разделы, которые сборщик мусора не должен трогать, # то их необходимо указать в качестве аргумента функции KEEP() (аналог ключевого слова # volatile). # Запись (*(.isr_vector)) означает разделы .isr_vector во всех объектных файлах. Т.к. @@ -80,8 +80,8 @@ SECTIONS # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - # Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещенна - # данная секция. В нашем слущае секция .isr_vector будет размещена во FLASH памяти. + # Выражение ">ОБЛАСТЬ_ПАМЯТИ" указывает в какую именно область памяти будет помещена + # данная секция. В нашем случае секция .isr_vector будет размещена во FLASH памяти. } >FLASH # ИТОГО: Секция .isr_vector, которая содержит таблицу векторов прерываний выравнивается @@ -125,7 +125,7 @@ SECTIONS # Выравниваем текущую позицию на границу 4-х байт. . = ALIGN(4); - # Указываем, что в данной секции будут хранится области .rodataвсех + # Указываем, что в данной секции будут хранится области .rodata всех # объектных файлов *(.rodata) *(.rodata*) @@ -158,13 +158,13 @@ SECTIONS _edata = .; # Функция AT указывает на то, что данный сектор хранится в одной области памяти - # (в нашем случае FLASH), а исполняться будет из другой обасти памяти (в нашем случае RAM). - # Есть два типа адрессов: - # * VMA (Virtual memory address) - это run-time адрес по которому уомпилятор ожидает + # (в нашем случае FLASH), а исполняться будет из другой области памяти (в нашем случае RAM). + # Есть два типа адресов: + # * VMA (Virtual memory address) - это run-time адрес по которому компилятор ожидает # видеть данные. # * LMA (Load memory address) - это адрес по которому линкер хранит данные. - #Startup должен код скопировать секцию .data из адрессов LMA в адресса VMA. + #Startup должен код скопировать секцию .data из адресов LMA в адреса VMA. } >RAM AT> FLASH diff --git a/ru-ru/lua-ru.html.markdown b/ru-ru/lua-ru.html.markdown index da9ced6a..6bfea4bb 100644 --- a/ru-ru/lua-ru.html.markdown +++ b/ru-ru/lua-ru.html.markdown @@ -98,7 +98,7 @@ end -- Вложенные и анонимные функции являются нормой: function adder(x) - -- Возращаемая функция создаётся, когда вызывается функция adder, + -- Возвращаемая функция создаётся, когда вызывается функция adder, -- и запоминает значение переменной x: return function (y) return x + y end end @@ -363,7 +363,7 @@ end return M --- Другой файл может использовать функционал mod.lua: +-- Другой файл может использовать функциональность mod.lua: local mod = require('mod') -- Запустим файл mod.lua. -- require - стандартный способ подключения модулей. diff --git a/ru-ru/markdown-ru.html.markdown b/ru-ru/markdown-ru.html.markdown index 579a9a20..fc8614c4 100644 --- a/ru-ru/markdown-ru.html.markdown +++ b/ru-ru/markdown-ru.html.markdown @@ -45,7 +45,7 @@ Markdown является надмножеством HTML, поэтому люб HTML-элементов --> ``` -## Заголовки +## Заголовки HTML-элементы от <h1> до <h6> размечаются очень просто: текст, который должен стать заголовком, предваряется @@ -85,7 +85,7 @@ __И этот тоже.__ *__И даже здесь!__* ``` -В Github Flavored Markdown, стандарте, который используется в Github, +В GitHub Flavored Markdown, стандарте, который используется в GitHub, текст также можно сделать зачёркнутым: ```md @@ -110,7 +110,7 @@ __И этот тоже.__ Для вставки принудительных переносов можно завершить абзац двумя дополнительными пробелами: ```md -Эта строка завершается двумя пробелами (выделите, чтобы увидеть!). +Эта строка завершается двумя пробелами (выделите, чтобы увидеть!). Над этой строкой есть <br />! ``` @@ -208,7 +208,7 @@ __И этот тоже.__ ```md my_array.each do |item| - puts item + puts item end ``` @@ -220,18 +220,17 @@ __И этот тоже.__ Ваня даже не знал, что делает функция `go_to()`! ``` -В Github Flavored Markdown для блоков кода можно использовать +В GitHub Flavored Markdown для блоков кода можно использовать специальный синтаксис: -<pre> -<code class="highlight">```ruby +```ruby def foobar - puts "Привет, мир!" + puts "Привет, мир!" end -```</code></pre> +``` Во фрагменте, приведённом выше, отступ не требуется. -Кроме того, Github подсветит синтаксис языка, указанного после \`\`\` +Кроме того, GitHub подсветит синтаксис языка, указанного после \`\`\` ## Горизонтальный разделитель @@ -255,6 +254,7 @@ end ```md [Ссылка!](http://test.com/) ``` + Также для ссылки можно указать всплывающую подсказку (`title`), используя кавычки внутри круглых скобок: @@ -269,11 +269,13 @@ end Markdown также позволяет размечать ссылку в виде сноски: -<pre><code class="highlight">[<span class="nv">Щёлкните эту ссылку</span>][<span class="ss">link1</span>] для подробной информации! -[<span class="nv">Также посмотрите эту ссылку,</span>][<span class="ss">foobar</span>] если хотите. +```md +[Щёлкните эту ссылку][link1] для подробной информации! +[Также посмотрите эту ссылку,][foobar] если хотите. -[<span class="nv">link1</span>]: <span class="sx">http://test.com/</span> <span class="nn">"Круто!"</span> -[<span class="nv">foobar</span>]: <span class="sx">http://foobar.biz/</span> <span class="nn">"Нормально!"</span></code></pre> +[link1]: http://test.com/ "Круто!" +[foobar]: http://foobar.biz/ "Нормально!" +``` `Title` также может быть в одинарных кавычках или круглых скобках, а также отсутствовать вовсе. Ссылки на сноски могут быть в любом месте документа, @@ -281,9 +283,11 @@ Markdown также позволяет размечать ссылку в вид Существует также неявное именование, когда ссылка является идентификатором. -<pre><code class="highlight">[<span class="nv">Это</span>][] ссылка. +```md +[Это][] ссылка. -[<span class="nv">это</span>]: <span class="sx">http://thisisalink.com/</span></code></pre> +[это]: http://thisisalink.com/ +``` Правда, эта возможность не очень распространена. @@ -294,11 +298,15 @@ Markdown также позволяет размечать ссылку в вид ```md  ``` -Изображения тоже могут быть оформлены, как сноски. -<pre><code class="highlight">![<span class="nv">Это альтернативный текст.</span>][<span class="ss">myimage</span>] +Изображения тоже могут быть оформлены как сноски. + +```md +![Это альтернативный текст.][myimage] + +[myimage]: relative/urls/cool/image.jpg "Если нужна подсказка, её можно добавить" +``` -[<span class="nv">myimage</span>]: <span class="sx">relative/urls/cool/image.jpg</span> <span class="nn">"Если нужна подсказка, её можно добавить"</span></code></pre> ## Разное ### Автоссылки @@ -322,7 +330,7 @@ Markdown также позволяет размечать ссылку в вид ``` ### Клавиши на клавиатуре -В Github Flavored Markdown для представления клавиш на клавиатуре +В GitHub Flavored Markdown для представления клавиш на клавиатуре вы можете использовать тег `<kbd>`. ```md @@ -341,6 +349,7 @@ Markdown также позволяет размечать ссылку в вид | Выравнивание | Выравнивание | Выравнивание | | влево | по центру | вправо | ``` + Или более компактно ```md diff --git a/ru-ru/nim-ru.html.markdown b/ru-ru/nim-ru.html.markdown index d05583d7..09784792 100644 --- a/ru-ru/nim-ru.html.markdown +++ b/ru-ru/nim-ru.html.markdown @@ -3,9 +3,10 @@ language: Nim filename: learnNim-ru.nim contributors: - ["Jason J. Ayala P.", "http://JasonAyala.com"] - - ["Dennis Felsing", "http://felsin9.de/nnis/"] + - ["Dennis Felsing", "https://dennis.felsing.org"] translators: - ["Nomadic", "https://github.com/n0madic"] + - ["dvska", "https://github.com/dvska"] lang: ru-ru --- @@ -16,25 +17,25 @@ Nim (ранее известный, как Nimrod) — язык программ Nim эффективный, выразительный и элегантный. ```nim -var # Объявление (и присваивание) переменных, - letter: char = 'n' # с указанием типа или без - lang = "N" & "im" - nLength : int = len(lang) +var # Объявление (и присваивание) переменных, + буква: char = 'n' # с указанием типа или без + язык = "N" & "im" + nLength : int = len(язык) boat: float - truth: bool = false + правда: bool = false -let # Используйте let *сразу* для объявления и связывания переменных. - legs = 400 # legs неизменяемый. - arms = 2_000 # Символ _ игнорируется и удобен для длинных чисел. - aboutPi = 3.15 +let # Используйте let *сразу* для объявления и связывания переменных. + ноги = 400 # ноги неизменяемый. + руки = 2_000 # Символ _ игнорируется и удобен для длинных чисел. + почтиПи = 3.15 const # Константы вычисляются во время компиляции. Это обеспечивает debug = true # производительность и полезно в выражениях этапа компиляции. - compileBadCode = false + компилироватьПлохойКод = false -when compileBadCode: # `when` это `if` этапа компиляции. - legs = legs + 1 # Эта ошибка никогда не будет скомпилирована. - const input = readline(stdin) # Значения констант должны быть известны во +when компилироватьПлохойКод: # `when` это `if` этапа компиляции. + ноги = ноги + 1 # Эта ошибка никогда не будет скомпилирована. + const ввод = readline(stdin) # Значения констант должны быть известны во # время компиляции. discard 1 > 2 # Примечание. Компилятор будет жаловаться, если результат @@ -52,27 +53,27 @@ discard """ # Кортежи var - child: tuple[name: string, age: int] # Кортежи определяют *как* имя поля - today: tuple[sun: string, temp: float] # так *и* порядок полей. + дитя: tuple[имя: string, возраст: int] # Кортежи определяют *как* имя поля + сегодня: tuple[солнце: string, температура: float] # так *и* порядок полей. -child = (name: "Rudiger", age: 2) # Присвоить все сразу литералом () -today.sun = "Overcast" # или отдельно по полям. -today.temp = 70.1 +дитя = (имя: "Rudiger", возраст: 2) # Присвоить все сразу литералом () +сегодня.солнце = "Пасмурно" # или отдельно по полям. +сегодня.температура = 20.1 # Последовательности var - drinks: seq[string] + напитки: seq[string] -drinks = @["Water", "Juice", "Chocolate"] # @[V1,..,Vn] является литералом - # последовательности +напитки = @["Вода", "Сок", "Какао"] # @[V1,..,Vn] является литералом + # последовательности -drinks.add("Milk") +напитки.add("Молоко") -if "Milk" in drinks: - echo "We have Milk and ", drinks.len - 1, " other drinks" +if "Молоко" in напитки: + echo "У нас тут Молоко и ещё", напитки.len - 1, " напиток(ов)" -let myDrink = drinks[2] +let мойНапиток = напитки[2] # # Определение типов @@ -82,30 +83,30 @@ let myDrink = drinks[2] # Это то, что делает статическую типизацию мощной и полезной. type - Name = string # Псевдоним типа дает вам новый тип, который равнозначен - Age = int # старому типу, но более нагляден. - Person = tuple[name: Name, age: Age] # Определение структур данных. - AnotherSyntax = tuple + Имя = string # Псевдоним типа дает вам новый тип, который равнозначен + Возраст = int # старому типу, но более нагляден. + Человек = tuple[имя: Имя, возраст: Возраст] # Определение структур данных. + АльтернативныйСинтаксис = tuple fieldOne: string secondField: int var - john: Person = (name: "John B.", age: 17) - newage: int = 18 # Было бы лучше использовать Age, чем int + джон: Человек = (имя: "John B.", возраст: 17) + новыйВозраст: int = 18 # Было бы лучше использовать Возраст, чем int -john.age = newage # Но это все же работает, потому что int и Age синонимы. +джон.возраст = новыйВозраст # Но это все же работает, потому что int и Возраст синонимы. type - Cash = distinct int # `distinct` делает новый тип несовместимым с его - Desc = distinct string # базовым типом. + Нал = distinct int # `distinct` делает новый тип несовместимым с его + Описание = distinct string # базовым типом. var - money: Cash = 100.Cash # `.Cash` преобразует int в наш тип - description: Desc = "Interesting".Desc + money: Нал = 100.Нал # `.Нал` преобразует int в наш тип + описание: Описание = "Interesting".Описание -when compileBadCode: - john.age = money # Error! age is of type int and money is Cash - john.name = description # Компилятор говорит: "Нельзя!" +when компилироватьПлохойКод: + джон.возраст = money # Error! возраст is of type int and money is Нал + джон.имя = описание # Компилятор говорит: "Нельзя!" # # Дополнительные типы и структуры данных @@ -114,50 +115,50 @@ when compileBadCode: # Перечисления позволяют типу иметь одно из ограниченного числа значений type - Color = enum cRed, cBlue, cGreen - Direction = enum # Альтернативный формат - dNorth - dWest - dEast - dSouth + Цвет = enum цКрасный, цГолубой, цЗеленый + Направление = enum # Альтернативный формат + нСевер + нЗапад + нВосток + нЮг var - orient = dNorth # `orient` имеет тип Direction, со значением `dNorth` - pixel = cGreen # `pixel` имеет тип Color, со значением `cGreen` + напр = нСевер # `напр` имеет тип Направление, со значением `нСевер` + точка = цЗеленый # `точка` имеет тип Цвет, со значением `цЗеленый` -discard dNorth > dEast # Перечисления обычно являются "порядковыми" типами +discard нСевер > нВосток # Перечисления обычно являются "порядковыми" типами # Поддиапазоны определяют ограниченный допустимый диапазон type - DieFaces = range[1..20] # Допустимым значением являются только int от 1 до 20 + Кости = range[1..20] # 🎲 Допустимым значением являются только int от 1 до 20 var - my_roll: DieFaces = 13 + мой_бросок: Кости = 13 -when compileBadCode: - my_roll = 23 # Error! +when компилироватьПлохойКод: + мой_бросок = 23 # Error! -# Arrays +# Массивы type - RollCounter = array[DieFaces, int] # Массивы фиксированной длины и - DirNames = array[Direction, string] # индексируются любым порядковым типом. - Truths = array[42..44, bool] + СчетчикБросков = array[Кости, int] # Массивы фиксированной длины и + ИменаНаправлений = array[Направление, string] # индексируются любым порядковым типом. + Истины = array[42..44, bool] var - counter: RollCounter - directions: DirNames - possible: Truths + счетчик: СчетчикБросков + направления: ИменаНаправлений + возможны: Истины -possible = [false, false, false] # Массивы создаются литералом [V1,..,Vn] -possible[42] = true +возможны = [false, false, false] # Массивы создаются литералом [V1,..,Vn] +возможны[42] = true -directions[dNorth] = "Ahh. The Great White North!" -directions[dWest] = "No, don't go there." +направления[нСевер] = "ОО. Великий белый Север!" +направления[нЗапад] = "Нет, не иди туда." -my_roll = 13 -counter[my_roll] += 1 -counter[my_roll] += 1 +мой_бросок = 13 +счетчик[мой_бросок] += 1 +счетчик[мой_бросок] += 1 -var anotherArray = ["Default index", "starts at", "0"] +var ещеМассив = ["Идекс по умолчанию", "начинается с", "0"] # Доступны другие структуры данных, в том числе таблицы, множества, # списки, очереди и crit-bit деревья. @@ -169,89 +170,94 @@ var anotherArray = ["Default index", "starts at", "0"] # `case`, `readLine()` -echo "Read any good books lately?" +echo "Читали какие-нибудь хорошие книги в последнее время?" + case readLine(stdin) -of "no", "No": - echo "Go to your local library." -of "yes", "Yes": - echo "Carry on, then." +of "нет", "Нет": + echo "Пойдите в свою местную библиотеку." +of "да", "Да": + echo "Тогда продолжим" else: - echo "That's great; I assume." + echo "Здорово!" # `while`, `if`, `continue`, `break` -import strutils as str # http://nim-lang.org/docs/strutils.html (EN) -echo "I'm thinking of a number between 41 and 43. Guess which!" -let number: int = 42 +import strutils as str # http://nim-lang.org/docs/strutils.html (EN) +echo "Я загадало число между 41 и 43. Отгадай!" +let число: int = 42 var - raw_guess: string - guess: int -while guess != number: - raw_guess = readLine(stdin) - if raw_guess == "": continue # Пропустить эту итерацию - guess = str.parseInt(raw_guess) - if guess == 1001: + ввод_догадка: string + догадка: int + +while догадка != число: + ввод_догадка = readLine(stdin) + + if ввод_догадка == "": continue # Пропустить эту итерацию + + догадка = str.parseInt(ввод_догадка) + + if догадка == 1001: echo("AAAAAAGGG!") break - elif guess > number: - echo("Nope. Too high.") - elif guess < number: - echo(guess, " is too low") + elif догадка > число: + echo("Неа. Слишком большое.") + elif догадка < число: + echo(догадка, " это слишком мало") else: - echo("Yeeeeeehaw!") + echo("Точнооооо!") # # Итерации (циклы) # -for i, elem in ["Yes", "No", "Maybe so"]: # Или просто `for elem in` - echo(elem, " is at index: ", i) +for i, элем in ["Да", "Нет", "Может быть"]: # Или просто `for элем in` + echo(элем, " по индексу: ", i) -for k, v in items(@[(person: "You", power: 100), (person: "Me", power: 9000)]): - echo v +for ключ, значение in items(@[(человек: "You", сила: 100), (человек: "Me", сила: 9000)]): + echo значение -let myString = """ -an <example> -`string` to -play with +let мояСтрока = """ +<пример> +`строки` для +тренировки """ # Многострочная "сырая" строка -for line in splitLines(myString): - echo(line) +for строка in splitLines(мояСтрока): + echo(строка) -for i, c in myString: # Индекс и символ. Или `for j in` только для символов - if i mod 2 == 0: continue # Компактная форма `if` - elif c == 'X': break - else: echo(c) +for i, симв in мояСтрока: # Индекс и символ. Или `for j in` только для символов + if i mod 2 == 0: continue # Компактная форма `if` + elif симв == 'X': break + else: echo(симв) # # Процедуры # -type Answer = enum aYes, aNo +type Ответ = enum оДа, оНет -proc ask(question: string): Answer = - echo(question, " (y/n)") +proc спрос(вопрос: string): Ответ = + echo(вопрос, " (д/н)") while true: case readLine(stdin) - of "y", "Y", "yes", "Yes": - return Answer.aYes # Перечисления могут быть квалифицированы - of "n", "N", "no", "No": - return Answer.aNo - else: echo("Please be clear: yes or no") - -proc addSugar(amount: int = 2) = # Значение поумолчанию 2, ничего не возвращает - assert(amount > 0 and amount < 9000, "Crazy Sugar") - for a in 1..amount: - echo(a, " sugar...") - -case ask("Would you like sugar in your tea?") -of aYes: - addSugar(3) -of aNo: - echo "Oh do take a little!" - addSugar() -# Здесь нет необходимости в `else`. Возможны только `yes` и `no`. + of "д", "Д", "да", "Да": + return Ответ.оДа # Перечисления могут быть квалифицированы + of "н", "Н", "нет", "Нет": + return Ответ.оНет + else: echo("Поточнее, да или нет") + +proc добавьСахар(количество: int = 2) = # Значение по умолчанию 2, ничего не возвращает + assert(количество > 0 and количество < 9000, "Диабет ☠") + for a in 1..количество: + echo(a, " кубик...") + +case спрос("Сахарку?") +of оДа: + добавьСахар(3) +of оНет: + echo "Ну немнооожко!" + добавьСахар() +# Здесь нет необходимости в `else`. Возможны только `да` и `нет`. # # FFI (интерфейс внешних функций) @@ -261,7 +267,7 @@ of aNo: proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.} -let cmp = strcmp("C?", "Easy!") +let cmp = strcmp("C?", "Легко!") ``` Кроме того, Nim выделяется среди себе подобных метапрограммированием, diff --git a/ru-ru/objective-c-ru.html.markdown b/ru-ru/objective-c-ru.html.markdown index 3baa15f8..6c7d9f6c 100644 --- a/ru-ru/objective-c-ru.html.markdown +++ b/ru-ru/objective-c-ru.html.markdown @@ -12,7 +12,7 @@ lang: ru-ru --- Objective-C — основной язык программирования, используемый корпорацией Apple -для операционных систем OS X и iOS и их соответствующих фреймворках Cocoa и +для операционных систем macOS и iOS и их соответствующих фреймворках Cocoa и Cocoa Touch. Он является объектно-ориентированным языком программирования общего назначения, который добавляет обмен сообщениями в Smalltalk-стиле к языку программирования C. @@ -507,8 +507,8 @@ distance = 18; // Ссылается на "long distance" из реализац @end // Теперь, если мы хотим создать объект Truck - грузовик, мы должны создать подкласс класса Car, что -// изменит функционал Car и позволит вести себя подобно грузовику. Но что, если мы хотим только добавить -// определенный функционал в уже существующий класс Car? Например - чистка автомобиля. Мы просто создадим +// изменит функциональность Car и позволит вести себя подобно грузовику. Но что, если мы хотим только добавить +// определенную функциональность в уже существующий класс Car? Например - чистка автомобиля. Мы просто создадим // категорию, которая добавит несколько методов для чистки автомобиля в класс Car: // @interface ИмяФайла: Car+Clean.h (ИмяБазовогоКласса+ИмяКатегории.h) #import "Car.h" // Убедитесь в том, что базовый класс импортирован для расширения. diff --git a/ru-ru/pascal-ru.html.markdown b/ru-ru/pascal-ru.html.markdown new file mode 100644 index 00000000..5ea856bc --- /dev/null +++ b/ru-ru/pascal-ru.html.markdown @@ -0,0 +1,217 @@ +--- +language: Pascal +filename: learnpascal-ru.pas +contributors: + - ["Ganesha Danu", "http://github.com/blinfoldking"] + - ["Keith Miyake", "https://github.com/kaymmm"] +translators: + - ["Anton 'Dart' Nikolaev", "https://github.com/dartfnm"] +lang: ru-ru +--- + + +>Pascal - это процедурный язык программирования, который Никлаус Вирт разработал в 1968–69 годах и опубликовал в 1970 году как небольшой эффективный язык, предназначенный для поощрения хороших методов программирования с использованием структурированного программирования и структурирования данных. Он назван в честь французского математика, философа и физика Блеза Паскаля. +> +>source : [wikipedia](https://ru.wikipedia.org/wiki/Паскаль_(язык_программирования))) + + + +Для компиляции и запуска программы на языке Паскаль вы можете использовать бесплатный компилятор FreePascal. [Скачать здесь](https://www.freepascal.org/) + +Либо современный бесплатный компилятор Паскаля нового поколения под платформу .Net [PascalABC.NET](http://pascalabc.net) + +```pascal +// это комментарий +{ + а вот это: + - комментарий на несколько строк +} + +//объявляем имя программы +program learn_pascal; //<-- не забываем ставить точку с запятой (;) + +const + { + это секция в которой вы должны объявлять константы + } +type + { + здесь вы можете объявлять собственные типы данных + } +var + { + секция для объявления переменных + } + +begin //начало основной программы + { + тело вашей программы + } +end. // В конце основной программы обязательно должна стоять точка "." +``` + +```pascal +//объявление переменных +//вы можете сделать так +var a:integer; +var b:integer; +//или так +var + a : integer; + b : integer; +//или даже так +var a,b : integer; +``` + +```pascal +program Learn_More; + +// Познакомимся с типами данных и с их операциями +const + PI = 3.141592654; + GNU = 'GNU''s Not Unix'; + // имена константам принято давать ЗАГЛАВНЫМИ_БУКВАМИ (в верхнем регистре) + // их значения фиксированны т.е никогда не меняются во время выполнения программы + // содержат любой стандартный тип данных (integer, real, boolean, char, string) + +type + ch_array : array [0..255] of char; + // массивы - это составной тип данных + // мы указываем индекс первого и последнего элемента массива ([0..255]) + // здесь мы объявили новый тип данных содержащий 255 символов 'char' + // (по сути, это просто строка - string[256]) + + md_array : array of array of integer; + // массив в массиве - по сути является двумерным массивом + // можно задать массив нулевой (0) длины, а потом динамически расширить его + // это двумерный массив целых чисел + +//Объявление переменных +var + int, c, d : integer; + // три переменные, которые содержат целые числа + // Тип "integer" это 16-битное число в диапазоне [-32,768..32,767] + r : real; + // переменная типа "real" принимает вещественные (дробные) значения + // в диапазоне [3.4E-38..3.4E38] + bool : boolean; + // переменная логического типа, принимающая булевы-значения: True/False (Правда/Ложь) + ch : char; + // эта переменная содержит значение кода одного символа + // тип 'char' это 8-битное число (1 байт), так что никакого Юникода + str : string; + // это переменная составного типа, являющееся строкой + // по сути, строка это массив в 255 символов длиною, по умолчанию + + s : string[50]; + // эта строка может содержать максимум 50 символов + // вы можете сами указать длину строки, чтобы минимизировать использование памяти + my_str: ch_array; + // вы можете объявлять переменные собственных типов + my_2d : md_array; + // динамически расширяемые массивы требуют указания длины перед их использованием. + + // дополнительные целочисленные типы данных + b : byte; // диапазон [0..255] + shi : shortint; // диапазон [-128..127] + smi : smallint; // диапазон [-32,768..32,767] (стандартный Integer) + w : word; // диапазон [0..65,535] + li : longint; // диапазон [-2,147,483,648..2,147,483,647] + lw : longword; // диапазон [0..4,294,967,295] + c : cardinal; // тоже что и longword + i64 : int64; // диапазон [-9223372036854775808..9223372036854775807] + qw : qword; // диапазон [0..18,446,744,073,709,551,615] + + // дополнительные вещественные типы данных (дробные) + rr : real; // диапазон зависит от платформы (т.е. 8-бит, 16-бит и т.д.) + rs : single; // диапазон [1.5E-45..3.4E38] + rd : double; // диапазон [5.0E-324 .. 1.7E308] + re : extended; // диапазон [1.9E-4932..1.1E4932] + rc : comp; // диапазон [-2E64+1 .. 2E63-1] + +Begin + int := 1; // так мы присваиваем значение переменной + r := 3.14; + ch := 'a'; + str := 'apple'; + bool := true; + // Паскаль не чувствителен к регистру + + // арифметические операции + int := 1 + 1; // int = 2; заменяет предыдущее значение + int := int + 1; // int = 2 + 1 = 3; + int := 4 div 2; //int = 2; 'div' операция деления, с отбрасыванием дробной части + int := 3 div 2; //int = 1; + int := 1 div 2; //int = 0; + + bool := true or false; // bool = true + bool := false and true; // bool = false + bool := true xor true; // bool = false + + r := 3 / 2; // деления вещественных чисел с дробной частью + r := int; // вещественной переменной можно присвоить целочисленное значение, но не наоборот + + my_str[0] := 'a'; // для доступа к элементу массива нужно указать его индекс в квадратных скобках ([0]) + + c := str[1]; // первая буква во всех Строках находится по индексу [1] + str := 'hello' + 'world'; //объединяем 2 строки в одну + + SetLength(my_2d,10,10); // инициализируем динамически расширяемый массив + // задаём размер 2х-мерного массива 10×10 + + // первый элемент массива лежит в индексе [0], последний [длина_массива-1] + for c := 0 to 9 do + for d := 0 to 9 do // переменные для счетчиков циклов должны быть объявлены + my_2d[c,d] := c * d; + // обращаться к многомерным массивам нужно с помощью одного набора скобок + +End. +``` + +```pascal +program Functional_Programming; + +Var + i, dummy : integer; + +function factorial_recursion(const a: integer) : integer; +{ Функция расчёта Факториала целочисленного параметра 'a', рекурсивно. Возвращает целое значение } + +// Мы можем объявлять локальные переменные внутри своей функции: +// Var +// local_a : integer; + +Begin + If a >= 1 Then + factorial_recursion := a * factorial_recursion(a-1) + // возвращаем результат, присваивая найденное значение переменной с тем же именем, как у функции + Else + factorial_recursion := 1; +End; // Для завершения функции, используется символ ";" после оператора "End;" + + + +procedure get_integer( var i : integer; dummy : integer ); +{ Эта процедура ждёт от пользователя ввода целого числа и возвращает его значение через параметр i. + Если параметр функции начинается с 'var', это означает, что его значение было передано, по ссылке, то есть, оно может использоваться не только как входное значение, но и для возвращения дополнительных результатов работы функции. + Параметры функции (без 'var'), (такие как "dummy" (пустышка)), передаются по значению, и по сути являются - локальными переменными, таким образом изменения, внесенные внутри функции/процедуры, не влияют на значение переменной за её пределами. +} +Begin // начало процедуры + write('Введите целое число: '); + readln(i); // число, введённое пользователем, сохранится в переменной i + // и её значение будет доступно вызывающей подпрограмме + + dummy := 4; // значение 'dummy' не будет влиять на значения переменной вне процедуры +End; // конец процедуры + +Begin // главный блок программы + dummy := 3; + get_integer(i, dummy); // вызываем процедуру получения числа от пользователя + writeln(i, '! = ', factorial_recursion(i)); // ввыводим значение факториала от i + + writeln('dummy = ', dummy); + // всегда выводит "3", поскольку фиктивная переменная не изменяется. +End. // конец программы + +``` + diff --git a/ru-ru/perl-ru.html.markdown b/ru-ru/perl-ru.html.markdown index a907ba41..a9bb683b 100644 --- a/ru-ru/perl-ru.html.markdown +++ b/ru-ru/perl-ru.html.markdown @@ -9,12 +9,12 @@ translators: lang: ru-ru --- -Perl 5 -- высокоуровневый мощный язык с 25-летней историей. -Особенно хорош для обработки разнообразных текстовых данных. +Perl -- высокоуровневый мощный язык с 25-летней историей. +Особенно хорош для обработки разнообразных текстовых данных. -Perl 5 работает более чем на 100 платформах, от портативных устройств -до мейнфреймов, и подходит как для быстрого прототипирования, -так и для крупных проектов. +Perl работает более чем на 100 платформах, от портативных устройств +до мейнфреймов, и подходит как для быстрого прототипирования, +так и для крупных проектов. ```perl # Комментарии начинаются с символа решетки. @@ -23,8 +23,8 @@ Perl 5 работает более чем на 100 платформах, от п #### Типы переменных в Perl # Скалярные переменные начинаются с знака доллара $. -# Имя переменной состоит из букв, цифр и знаков подчеркивания, -# начиная с буквы или подчеркивания. +# Имя переменной состоит из букв, цифр и знаков подчеркивания, +# начиная с буквы или подчеркивания. ### В Perl три основных типа переменных: скаляры, массивы, хеши. @@ -55,7 +55,7 @@ my %fruit_color = ( banana => "yellow", ); -# Важно: вставка и поиск в хеше выполняются за константное время, +# Важно: вставка и поиск в хеше выполняются за константное время, # независимо от его размера. # Скаляры, массивы и хеши подробно описаны в разделе perldata @@ -81,7 +81,7 @@ unless ( condition ) { } # Это более читаемый вариант для "if (!condition)" -# Специфические Perl-овые пост-условия: +# Специфические Perl-овые пост-условия: print "Yow!" if $zippy; print "We have no bananas" unless $bananas; @@ -129,7 +129,7 @@ open(my $out, ">", "output.txt") or die "Can't open output.txt: $!"; open(my $log, ">>", "my.log") or die "Can't open my.log: $!"; # Читать из файлового дескриптора можно с помощью оператора "<>". -# В скалярном контексте он читает одну строку из файла, в списковом -- +# В скалярном контексте он читает одну строку из файла, в списковом -- # читает сразу весь файл, сохраняя по одной строке в элементе массива: my $line = <$in>; @@ -152,13 +152,13 @@ logger("We have a logger subroutine!"); #### Perl-модули -Perl-овые модули предоставляют широкий набор функциональности, -так что вы можете не изобретать заново велосипеды, а просто скачать -нужный модуль с CPAN (http://www.cpan.org/). -Некоторое количество самых полезных модулей включено в стандартную +Perl-овые модули предоставляют широкий набор функциональности, +так что вы можете не изобретать заново велосипеды, а просто скачать +нужный модуль с CPAN (http://www.cpan.org/). +Некоторое количество самых полезных модулей включено в стандартную поставку Perl. -Раздел документации perlfaq содержит вопросы и ответы о многих частых +Раздел документации perlfaq содержит вопросы и ответы о многих частых задачах, и часто предлагает подходящие CPAN-модули. diff --git a/ru-ru/php-ru.html.markdown b/ru-ru/php-ru.html.markdown index af77a9ca..4a508cfc 100644 --- a/ru-ru/php-ru.html.markdown +++ b/ru-ru/php-ru.html.markdown @@ -125,7 +125,7 @@ echo 'Multiple', 'Parameters', 'Valid'; // печатает 'MultipleParametersV // и никогда не может быть изменена во время выполнения программы! // Правильное имя константы начинается с буквы или символа подчеркивания -// и содержит любое колличество букв, цифр или символов подчеркивания. +// и содержит любое количество букв, цифр или символов подчеркивания. define("FOO", "something"); // Доступ к константе возможен через прямое указание её имени без знака $ @@ -224,7 +224,7 @@ assert($c > $b); // больше assert($a <= $b); // меньше или равно assert($c >= $d); // больше или равно -// Следующие утверждения истинны, если переменные имеют одинаковые тип. +// Следующие утверждения истинны, если переменные имеют одинаковый тип. assert($c === $d); assert($a !== $d); assert(1 == '1'); @@ -251,7 +251,7 @@ echo $string + $string; // => 2 (строка превращается в чис $string = 'one'; echo $string + $string; // => 0 -// Приведение типов (type casting) может быть использовано для преобразование +// Приведение типов (type casting) может быть использовано для преобразования // переменной в другой тип $boolean = (boolean) 1; // => true @@ -458,7 +458,7 @@ include_once 'my-file.php'; require 'my-file.php'; require_once 'my-file.php'; -// Действует также как и include(), но если файл не удалось подключить, +// Действует так же как и include(), но если файл не удалось подключить, // функция выдает фатальную ошибку // Содержимое файла my-include.php: @@ -497,7 +497,7 @@ class MyClass // Конструктор описывается с помощью __construct public function __construct($instanceProp) { - // Доступ к эземпляру класса с помощью $this + // Доступ к экземпляру класса с помощью $this $this->instanceProp = $instanceProp; } @@ -661,7 +661,7 @@ $cls->myTraitMethod(); // Напечатает "I have MyTrait" <?php // По умолчанию, классы существуют в глобальном пространстве имен и могут быть -// вызваны с обратным слешем. +// вызваны с обратным слэшем. $cls = new \MyClass(); @@ -762,7 +762,7 @@ echo "Current method is " . __METHOD__; echo "Current namespace is " . __NAMESPACE__; // Возвращает имя текущего трейта. -// Возвращает только если испольщуется внутри трейта. +// Возвращает только если используется внутри трейта. echo "Current namespace is " . __TRAIT__; @@ -771,7 +771,7 @@ echo "Current namespace is " . __TRAIT__; * */ -// Простую обработку ошибок можно произвести спомощью try catch блока. +// Простую обработку ошибок можно произвести с помощью try catch блока. try { // Выполняем что-то @@ -779,7 +779,7 @@ try { // Обработка исключения } -// При использовании try catch блока в области вилимости, стоит использовать +// При использовании try catch блока в области видимости, стоит использовать // следующий подход: try { @@ -788,7 +788,7 @@ try { // Обработка исключения } -// Специальное(кастомное) исключение - exceptions +// Специальное (кастомное) исключение - exceptions class MyException extends Exception {} @@ -797,7 +797,7 @@ try { $condition = true; if ($condition) { - throw new MyException('Something just happend'); + throw new MyException('Something just happened'); } } catch (MyException $e) { diff --git a/ru-ru/pyqt-ru.html.markdown b/ru-ru/pyqt-ru.html.markdown index 24afc03d..a7e14c02 100644 --- a/ru-ru/pyqt-ru.html.markdown +++ b/ru-ru/pyqt-ru.html.markdown @@ -11,7 +11,7 @@ translators: **Qt** - широко известный кросс-платформенный фреймворк для разработки программного обеспечения, который может быть использован на различных софтварных и хардварных платформах без какого-либо -изменения в коде. Данный фреймворк при этом обладает мощью и скоростью нативных приложений. +изменения в коде. Данный фреймворк при этом обладает мощью и скоростью нативных приложений. Qt и был изначально написан на *C++*. Данный текст является адаптацией введения в Qt на C++ под авторством Алексея Ковальчука для pyqt. @@ -20,7 +20,7 @@ Qt и был изначально написан на *C++*. ```python def window(): - # Создайте объект приложения + # Создайте объект приложения app = QtGui.QApplication(sys.argv) # Создайте виджет, где будет находиться наш лейбл w = QtGui.QWidget() @@ -28,10 +28,10 @@ def window(): b = QtGui.QLabel(w) # Задайте текст для лейбла b.setText("Hello World!") - # Задайте информация о размере и расположении + # Задайте информация о размере и расположении w.setGeometry(100, 100, 200, 50) b.move(50, 20) - # Задайте заголовок окна + # Задайте заголовок окна w.setWindowTitle("PyQt") # Все ранее написанное выводится на экран w.show() @@ -43,11 +43,11 @@ if __name__ == '__main__': ``` -Для того, чтобы получить более продвинутые функции приложения в pyqt, нам необходимо -обратить внимание на создание дополнительных элементов. Ниже представлено создание всплывающего диалогового окна, которое просит пользователя подтвердить его решение или предоставить какую-либо +Для того чтобы получить более продвинутые функции приложения в pyqt, нам необходимо +обратить внимание на создание дополнительных элементов. Ниже представлено создание всплывающего диалогового окна, которое просит пользователя подтвердить его решение или предоставить какую-либо информацию. -```Python +```python import sys from PyQt4.QtGui import * from PyQt4.QtCore import * @@ -67,7 +67,7 @@ def window(): w.show() sys.exit(app.exec_()) -Данная функция должна создавать диалоговое окно с кнопкой, которая ждет клика по себе +Данная функция должна создавать диалоговое окно с кнопкой, которая ждет клика по себе и затем завершает программу. def showdialog(): diff --git a/ru-ru/python-ru.html.markdown b/ru-ru/python-ru.html.markdown index 6087a686..e088593e 100644 --- a/ru-ru/python-ru.html.markdown +++ b/ru-ru/python-ru.html.markdown @@ -1,27 +1,30 @@ --- -language: python +language: Python lang: ru-ru contributors: - ["Louie Dinh", "http://ldinh.ca"] + - ["Steven Basart", "http://github.com/xksteven"] translators: - - ["Yury Timofeev", "http://twitter.com/gagar1n"] - ["Andre Polykanine", "https://github.com/Oire"] + - ["Anton Grouchtchak", "https://github.com/Teraskull"] filename: learnpython-ru.py --- Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис — это -почти исполняемый псевдокод. +почти что исполняемый псевдокод. С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh) или louiedinh [at] [почтовый сервис Google] -Замечание: Эта статья относится к Python 2.7, но должно работать и в других версиях Python 2.x. -Чтобы изучить Python 3.x, обратитесь к статье по Python 3. +Замечание: Эта статья относится только к Python 3. +Если вы хотите изучить Python 2.7, обратитесь к другой статье. ```python + # Однострочные комментарии начинаются с символа решётки. -""" Многострочный текст может быть + +""" Многострочный текст может быть записан, используя 3 знака " и обычно используется в качестве встроенной документации """ @@ -31,323 +34,396 @@ filename: learnpython-ru.py #################################################### # У вас есть числа -3 #=> 3 +3 # => 3 # Математика работает вполне ожидаемо -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 - -# А вот деление немного сложнее. В этом случае происходит деление -# целых чисел, и результат автоматически округляется в меньшую сторону. -5 / 2 #=> 2 - -# Чтобы делить правильно, сначала нужно немного узнать о числах -# с плавающей запятой. -2.0 # Это число с плавающей запятой -11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 # Результат целочисленного деления округляется в меньшую сторону # как для положительных, так и для отрицательных чисел. -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой --5 // 3 # => -2 +5 // 3 # => 1 +-5 // 3 # => -2 +5.0 // 3.0 # => 1.0 # работает и для чисел с плавающей запятой -5.0 // 3.0 # => -2.0 +# # Результат деления возвращает число с плавающей запятой +10.0 / 3 # => 3.3333333333333335 + # Остаток от деления -7 % 3 # => 1 +7 % 3 # => 1 # Возведение в степень -2**4 # => 16 +2**3 # => 8 # Приоритет операций указывается скобками -(1 + 3) * 2 #=> 8 +1 + 3 * 2 # => 7 +(1 + 3) * 2 # => 8 -# Логические операторы -# Обратите внимание: ключевые слова «and» и «or» чувствительны к регистру букв -True and False #=> False -False or True #=> True - -# Обратите внимание, что логические операторы используются и с целыми числами -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True +# Булевы значения - примитивы (Обратите внимание на заглавную букву) +True # => True +False # => False # Для отрицания используется ключевое слово not -not True #=> False -not False #=> True +not True # => False +not False # => True + +# Булевы операторы +# Обратите внимание: ключевые слова "and" и "or" чувствительны к регистру букв +True and False # => False +False or True # => True + +# True и False на самом деле 1 и 0, но с разными ключевыми словами +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 + +# Операторы сравнения обращают внимание на числовое значение True и False +0 == False # => True +1 == True # => True +2 == True # => False +-5 != False # => True + +# Использование булевых логических операторов на типах int превращает их в булевы значения, но возвращаются оригинальные значения +# Не путайте с bool(ints) и bitwise and/or (&,|) +bool(0) # => False +bool(4) # => True +bool(-6) # => True +0 and 2 # => 0 +-5 or 0 # => -5 # Равенство — это == -1 == 1 #=> True -2 == 1 #=> False +1 == 1 # => True +2 == 1 # => False # Неравенство — это != -1 != 1 #=> False -2 != 1 #=> True +1 != 1 # => False +2 != 1 # => True # Ещё немного сравнений -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True - -# Сравнения могут быть записаны цепочкой! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# Проверка, находится ли значение в диапазоне +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False + +# Сравнения могут быть записаны цепочкой +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# (is vs. ==) ключевое слово is проверяет, относятся ли две переменные к одному и тому же объекту, но == проверяет если указанные объекты имеют одинаковые значения. +a = [1, 2, 3, 4] # a указывает на новый список, [1, 2, 3, 4] +b = a # b указывает на то, что указывает a +b is a # => True, a и b относятся к одному и тому же объекту +b == a # => True, Объекты a и b равны +b = [1, 2, 3, 4] # b указывает на новый список, [1, 2, 3, 4] +b is a # => False, a и b не относятся к одному и тому же объекту +b == a # => True, Объекты a и b равны # Строки определяются символом " или ' "Это строка." 'Это тоже строка.' -# И строки тоже можно складывать! -"Привет " + "мир!" #=> "Привет мир!" +# И строки тоже могут складываться! Хотя лучше не злоупотребляйте этим. +"Привет " + "мир!" # => "Привет мир!" -# ... или умножать -"Привет" * 3 # => "ПриветПриветПривет" +# Строки (но не переменные) могут быть объединены без использования '+' +"Привет " "мир!" # => "Привет мир!" # Со строкой можно работать, как со списком символов -"Это строка"[0] #=> 'Э' +"Привет мир!"[0] # => 'П' -# Символ % используется для форматирования строк, например: -"%s могут быть %s" % ("строки", "интерполированы") +# Вы можете найти длину строки +len("Это строка") # => 10 -# Новый способ форматирования строк — использование метода format. -# Это предпочитаемый способ. -"{0} могут быть {1}".format("строки", "форматированы") +# Вы также можете форматировать, используя f-строки (в Python 3.6+) +name = "Рейко" +f"Она сказала, что ее зовут {name}." # => "Она сказала, что ее зовут Рейко" +# Вы можете поместить любой оператор Python в фигурные скобки, и он будет выведен в строке. +f"{name} состоит из {len(name)} символов." # => "Рэйко состоит из 5 символов." -# Если вы не хотите считать, можете использовать ключевые слова. -"{name} хочет есть {food}".format(name="Боб", food="лазанью") # None является объектом -None #=> None +None # => None -# Не используйте оператор равенства '=='' для сравнения -# объектов с None. Используйте для этого «is» -"etc" is None #=> False -None is None #=> True +# Не используйте оператор равенства "==" для сравнения +# объектов с None. Используйте для этого "is" +"etc" is None # => False +None is None # => True -# Оператор 'is' проверяет идентичность объектов. Он не -# очень полезен при работе с примитивными типами, но -# зато просто незаменим при работе с объектами. - -# None, 0 и пустые строки/списки равны False. +# None, 0 и пустые строки/списки/словари/кортежи приводятся к False. # Все остальные значения равны True -0 == False #=> True -"" == False #=> True +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False #################################################### -## 2. Переменные и коллекции +## 2. Переменные и Коллекции #################################################### -# В Python есть оператор print, доступный в версиях 2.x, но удалённый в версии 3 -print "Я Python. Приятно познакомиться!" -# В Python также есть функция print(), доступная в версиях 2.7 и 3, -# Но для версии 2.7 нужно добавить следующий импорт модуля (раскомментируйте)): -# from __future__ import print_function -print("Я тоже Python! ") +# В Python есть функция Print +print("Я Python. Приятно познакомиться!") # => Я Python. Приятно познакомиться! + +# По умолчанию функция, print() также выводит новую строку в конце. +# Используйте необязательный аргумент end, чтобы изменить последнюю строку. +print("Привет мир", end="!") # => Привет мир! + +# Простой способ получить входные данные из консоли +input_string_var = input("Введите данные: ") # Возвращает данные в виде строки +# Примечание: в более ранних версиях Python метод input() назывался raw_input() # Объявлять переменные перед инициализацией не нужно. -some_var = 5 # По соглашению используется нижний_регистр_с_подчёркиваниями -some_var #=> 5 +# По соглашению используется нижний_регистр_с_подчёркиваниями +some_var = 5 +some_var # => 5 -# При попытке доступа к неинициализированной переменной -# выбрасывается исключение. -# См. раздел «Поток управления» для информации об исключениях. -some_other_var # Выбрасывает ошибку именования +# При попытке доступа к неинициализированной переменной выбрасывается исключение. +# Об исключениях см. раздел "Поток управления и итерируемые объекты". +some_unknown_var # Выбрасывает ошибку NameError -# if может быть использован как выражение -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +# if можно использовать как выражение +# Эквивалент тернарного оператора '?:' в C +"да!" if 0 > 1 else "нет!" # => "нет!" # Списки хранят последовательности li = [] # Можно сразу начать с заполненного списка other_li = [4, 5, 6] -# строка разделена в список -a="adambard" -list(a) #=> ['a','d','a','m','b','a','r','d'] - -# Объекты добавляются в конец списка методом append -li.append(1) # [1] -li.append(2) # [1, 2] -li.append(4) # [1, 2, 4] -li.append(3) # [1, 2, 4, 3] -# И удаляются с конца методом pop -li.pop() #=> возвращает 3 и li становится равен [1, 2, 4] +# Объекты добавляются в конец списка методом append() +li.append(1) # [1] +li.append(2) # [1, 2] +li.append(4) # [1, 2, 4] +li.append(3) # [1, 2, 4, 3] +# И удаляются с конца методом pop() +li.pop() # => возвращает 3 и li становится равен [1, 2, 4] # Положим элемент обратно -li.append(3) # [1, 2, 4, 3]. +li.append(3) # [1, 2, 4, 3]. # Обращайтесь со списком, как с обычным массивом -li[0] #=> 1 -# Присваивайте новые значения уже инициализированным индексам с помощью = -li[0] = 42 -li[0] # => 42 -li[0] = 1 # Обратите внимание: возвращаемся на исходное значение +li[0] # => 1 + # Обратимся к последнему элементу -li[-1] #=> 3 +li[-1] # => 3 # Попытка выйти за границы массива приведёт к ошибке индекса -li[4] # Выдаёт IndexError +li[4] # Выбрасывает ошибку IndexError # Можно обращаться к диапазону, используя так называемые срезы # (Для тех, кто любит математику, это называется замкнуто-открытый интервал). -li[1:3] #=> [2, 4] -# Опускаем начало -li[2:] #=> [4, 3] -# Опускаем конец -li[:3] #=> [1, 2, 4] -# Выбираем каждый второй элемент -li[::2] # =>[1, 4] -# Переворачиваем список -li[::-1] # => [3, 4, 2, 1] +li[1:3] # Вернуть список из индекса с 1 по 3 => [2, 4] +li[2:] # Вернуть список, начиная с индекса 2 => [4, 3] +li[:3] # Вернуть список с начала до индекса 3 => [1, 2, 4] +li[::2] # Вернуть список, выбирая каждую вторую запись => [1, 4] +li[::-1] # Вернуть список в обратном порядке => [3, 4, 2, 1] # Используйте сочетания всего вышеназванного для выделения более сложных срезов # li[начало:конец:шаг] +# Сделать однослойную глубокую копию, используя срезы +li2 = li[:] # => li2 = [1, 2, 4, 3], но (li2 is li) вернет False. + # Удаляем произвольные элементы из списка оператором del -del li[2] # li теперь [1, 2, 3] +del li[2] # [1, 2, 3] + +# Удалить первое вхождение значения +li.remove(2) # [1, 3] +li.remove(2) # Выбрасывает ошибку ValueError поскольку 2 нет в списке + +# Вставить элемент по определенному индексу +li.insert(1, 2) # [1, 2, 3] + +# Получить индекс первого найденного элемента, соответствующего аргументу +li.index(2) # => 1 +li.index(4) # Выбрасывает ошибку ValueError поскольку 4 нет в списке # Вы можете складывать, или, как ещё говорят, конкатенировать списки -li + other_li #=> [1, 2, 3, 4, 5, 6] — Замечание: li и other_li не изменяются # Обратите внимание: значения li и other_li при этом не изменились. +li + other_li # => [1, 2, 3, 4, 5, 6] -# Объединять списки можно методом extend +# Объединять списки можно методом extend() li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6] -# Проверить элемент на вхождение в список можно оператором in -1 in li #=> True +# Проверить элемент на наличие в списке можно оператором in +1 in li # => True # Длина списка вычисляется функцией len -len(li) #=> 6 +len(li) # => 6 -# Кортежи — это такие списки, только неизменяемые +# Кортежи похожи на списки, только неизменяемые tup = (1, 2, 3) -tup[0] #=> 1 -tup[0] = 3 # Выдаёт TypeError +tup[0] # => 1 +tup[0] = 3 # Выбрасывает ошибку TypeError + +# Обратите внимание, что кортеж длины 1 должен иметь запятую после последнего элемента, но кортежи другой длины, даже 0, не должны. +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> # Всё то же самое можно делать и с кортежами -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True # Вы можете распаковывать кортежи (или списки) в переменные -a, b, c = (1, 2, 3) # a == 1, b == 2 и c == 3 +a, b, c = (1, 2, 3) # a == 1, b == 2 и c == 3 +# Вы также можете сделать расширенную распаковку +a, *b, c = (1, 2, 3, 4) # a теперь 1, b теперь [2, 3] и c теперь 4 # Кортежи создаются по умолчанию, если опущены скобки -d, e, f = 4, 5, 6 +d, e, f = 4, 5, 6 # кортеж 4, 5, 6 распаковывается в переменные d, e и f +# соответственно, d = 4, e = 5 и f = 6 # Обратите внимание, как легко поменять местами значения двух переменных -e, d = d, e # теперь d == 5, а e == 4 +e, d = d, e # теперь d == 5, а e == 4 -# Словари содержат ассоциативные массивы + +# Словари содержат ассоциативные массивы empty_dict = {} # Вот так описывается предзаполненный словарь filled_dict = {"one": 1, "two": 2, "three": 3} -# Значения извлекаются так же, как из списка, с той лишь разницей, -# что индекс — у словарей он называется ключом — не обязан быть числом -filled_dict["one"] #=> 1 +# Обратите внимание, что ключи для словарей должны быть неизменяемыми типами. Это +# сделано для того, чтобы ключ может быть преобразован в хеш для быстрого поиска. +# Неизменяемые типы включают целые числа, числа с плавающей запятой, строки, кортежи. +invalid_dict = {[1,2,3]: "123"} # => Выбрасывает ошибку TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # Однако значения могут быть любого типа. + +# Поиск значений с помощью [] +filled_dict["one"] # => 1 -# Можно получить все ключи в виде списка с помощью метода keys -filled_dict.keys() #=> ["three", "two", "one"] -# Замечание: сохранение порядка ключей в словаре не гарантируется -# Ваши результаты могут не совпадать с этими. +# Все ключи в виде списка получаются с помощью метода keys(). +# Его вызов нужно обернуть в list(), так как обратно мы получаем +# итерируемый объект, о которых поговорим позднее. Примечание - для Python +# версии <3.7, порядок словарных ключей не гарантируется. Ваши результаты могут +# не точно соответствовать приведенному ниже примеру. Однако, начиная с Python 3.7 +# элементы в словаре сохраняют порядок, в котором они вставляются в словарь. +list(filled_dict.keys()) # => ["three", "two", "one"] в Python <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] в Python 3.7+ -# Можно получить и все значения в виде списка, используйте метод values -filled_dict.values() #=> [3, 2, 1] + +# Все значения в виде списка можно получить с помощью values(). +# И снова нам нужно обернуть вызов в list(), чтобы превратить +# итерируемый объект в список. # То же самое замечание насчёт порядка ключей справедливо и здесь +list(filled_dict.values()) # => [3, 2, 1] в Python <3.7 +list(filled_dict.values()) # => [1, 2, 3] в Python 3.7+ -# При помощи оператора in можно проверять ключи на вхождение в словарь -"one" in filled_dict #=> True -1 in filled_dict #=> False +# При помощи ключевого слова in можно проверять наличие ключей в словаре +"one" in filled_dict # => True +1 in filled_dict # => False -# Попытка получить значение по несуществующему ключу выбросит ошибку ключа -filled_dict["four"] # KeyError +# Попытка получить значение по несуществующему ключу выбросит ошибку KeyError +filled_dict["four"] # Выбрасывает ошибку KeyError # Чтобы избежать этого, используйте метод get() -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None -# Метод get также принимает аргумент по умолчанию, значение которого будет -# возвращено при отсутствии указанного ключа -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 -# Обратите внимание, что filled_dict.get("four") всё ещё => None -# (get не устанавливает значение элемента словаря) - -# Присваивайте значение ключам так же, как и в списках -filled_dict["four"] = 4 # теперь filled_dict["four"] => 4 +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# Метод get поддерживает аргумент по умолчанию, когда значение отсутствует +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 # Метод setdefault() вставляет пару ключ-значение, только если такого ключа нет -filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5 -filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5 +filled_dict.setdefault("five", 5) # filled_dict["five"] возвращает 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] по-прежнему возвращает 5 + +# Добавление элементов в словарь +filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4 # Другой способ добавления элементов + +# Удаляйте ключи из словаря с помощью ключевого слова del +del filled_dict["one"] # Удаляет ключ "one" из словаря + +# После Python 3.5 вы также можете использовать дополнительные параметры распаковки +{'a': 1, **{'b': 2}} # => {'a': 1, 'b': 2} +{'a': 1, **{'a': 2}} # => {'a': 2} + # Множества содержат... ну, в общем, множества -# (которые похожи на списки, только в них не может быть дублирующихся элементов) empty_set = set() -# Инициализация множества набором значений -some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4]) - -# Порядок сортировки не гарантируется, хотя иногда они выглядят отсортированными -another_set = set([4, 3, 2, 2, 1]) # another_set теперь set([1, 2, 3, 4]) +# Инициализация множества набором значений. +# Да, оно выглядит примерно как словарь. Ну извините, так уж вышло. +filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} -# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# Как и ключи словаря, элементы множества должны быть неизменяемыми. +invalid_set = {[1], 1} # => Выбрасывает ошибку TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Добавление новых элементов в множество -filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5} +# Множеству можно назначать новую переменную +filled_set = some_set +filled_set.add(5) # {1, 2, 3, 4, 5} +# В множествах нет повторяющихся элементов +filled_set.add(5) # {1, 2, 3, 4, 5} # Пересечение множеств: & other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} +filled_set & other_set # => {3, 4, 5} # Объединение множеств: | -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} +filled_set | other_set # => {1, 2, 3, 4, 5, 6} # Разность множеств: - -{1,2,3,4} - {2,3,5} #=> {1, 4} +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} -# Проверка на вхождение во множество: in -2 in filled_set #=> True -10 in filled_set #=> False +# Симметричная разница: ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Проверить, является ли множество слева надмножеством множества справа +{1, 2} >= {1, 2, 3} # => False + +# Проверить, является ли множество слева подмножеством множества справа +{1, 2} <= {1, 2, 3} # => True + +# Проверка на наличие в множестве: in +2 in filled_set # => True +10 in filled_set # => False + +# Сделать однослойную глубокую копию +filled_set = some_set.copy() # {1, 2, 3, 4, 5} +filled_set is some_set # => False #################################################### -## 3. Поток управления +## 3. Поток управления и итерируемые объекты #################################################### -# Для начала заведём переменную +# Для начала создадим переменную some_var = 5 # Так выглядит выражение if. Отступы в python очень важны! -# результат: «some_var меньше, чем 10» +# Конвенция заключается в использовании четырех пробелов, а не табуляции. +# Pезультат: "some_var меньше, чем 10" if some_var > 10: - print("some_var намного больше, чем 10.") -elif some_var < 10: # Выражение elif необязательно. + print("some_var точно больше, чем 10.") +elif some_var < 10: # Выражение elif необязательно. print("some_var меньше, чем 10.") -else: # Это тоже необязательно. +else: # Это тоже необязательно. print("some_var равно 10.") """ -Циклы For проходят по спискам - -Результат: +Циклы For проходят по спискам. +Выводит: собака — это млекопитающее кошка — это млекопитающее мышь — это млекопитающее """ for animal in ["собака", "кошка", "мышь"]: - # Можете использовать оператор % для интерполяции форматированных строк - print("%s — это млекопитающее" % animal) - + # Можете использовать format() для интерполяции форматированных строк + print("{} — это млекопитающее".format(animal)) + """ -«range(число)» возвращает список чисел +"range(число)" возвращает список чисел от нуля до заданного числа -Результат: +Выводит: 0 1 2 @@ -357,8 +433,42 @@ for i in range(4): print(i) """ +"range(нижнее, верхнее)" возвращает список чисел +от нижнего числа к верхнему +Выводит: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) + +""" +"range(нижнее, верхнее, шаг)" возвращает список чисел +от нижнего числа к верхнему, от нижнего числа к верхнему, увеличивая +шаг за шагом. Если шаг не указан, значение по умолчанию - 1. +Выводит: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) + +""" +Чтобы перебрать список и получить индекс и значение каждого элемента в списке +Выводит: + 0 собака + 1 кошка + 2 мышь +""" +animals = ["собака", "кошка", "мышь"] +for i, value in enumerate(animals): + print(i, value) + +""" Циклы while продолжаются до тех пор, пока указанное условие не станет ложным. -Результат: +Выводит: 0 1 2 @@ -370,20 +480,81 @@ while x < 4: x += 1 # Краткая запись для x = x + 1 # Обрабатывайте исключения блоками try/except - -# Работает в Python 2.6 и выше: try: # Чтобы выбросить ошибку, используется raise raise IndexError("Это ошибка индекса") except IndexError as e: - # pass — это просто отсутствие оператора. Обычно здесь происходит - # восстановление после ошибки. - pass + pass # pass — это просто отсутствие оператора. Обычно здесь происходит восстановление после ошибки. except (TypeError, NameError): - pass # Несколько исключений можно обработать вместе, если нужно. -else: # Необязательное выражение. Должно следовать за последним блоком except - print("Всё хорошо!") # Выполнится, только если не было никаких исключений + pass # Несколько исключений можно обработать вместе, если нужно. +else: # Необязательное выражение. Должно следовать за последним блоком except + print("Всё хорошо!") # Выполнится, только если не было никаких исключений +finally: # Выполнить при любых обстоятельствах + print("Мы можем очистить ресурсы здесь") + +# Вместо try/finally чтобы очистить ресурсы, можно использовать оператор with +with open("myfile.txt") as f: + for line in f: + print(line) + +# Запись в файл +contents = {"aa": 12, "bb": 21} +with open("myfile1.txt", "w+") as file: + file.write(str(contents)) # Записывает строку в файл + +with open("myfile2.txt", "w+") as file: + file.write(json.dumps(contents)) # Записывает объект в файл + +# Чтение из файла +with open('myfile1.txt', "r+") as file: + contents = file.read() # Читает строку из файла +print(contents) +# print: {"aa": 12, "bb": 21} + +with open('myfile2.txt', "r+") as file: + contents = json.load(file) # Читает объект json из файла +print(contents) +# print: {"aa": 12, "bb": 21} + + +# Python предоставляет фундаментальную абстракцию, +# которая называется итерируемым объектом (Iterable). +# Итерируемый объект — это объект, который воспринимается как последовательность. +# Объект, который возвратила функция range(), итерируемый. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['one', 'two', 'three']). Это объект, реализующий интерфейс Iterable + +# Мы можем проходить по нему циклом. +for i in our_iterable: + print(i) # Выводит one, two, three + +# Но мы не можем обращаться к элементу по индексу. +our_iterable[1] # Выбрасывает ошибку TypeError + +# Итерируемый объект знает, как создавать итератор. +our_iterator = iter(our_iterable) + +# Итератор может запоминать состояние при проходе по объекту. +# Мы получаем следующий объект, вызывая функцию next(). +next(our_iterator) # => "one" +# Он сохраняет состояние при вызове next(). +next(our_iterator) # => "two" +next(our_iterator) # => "three" + +# Возвратив все данные, итератор выбрасывает исключение StopIterator +next(our_iterator) # Выбрасывает исключение StopIteration + +# Мы можем проходить по нему циклом. +our_iterator = iter(our_iterable) +for i in our_iterator: + print(i) # Выводит one, two, three + +# Вы можете получить сразу все элементы итератора, вызвав на нём функцию list(). +list(our_iterable) # => Возвращает ["one", "two", "three"] +list(our_iterator) # => Возвращает [] потому что состояние сохраняется #################################################### @@ -393,30 +564,28 @@ else: # Необязательное выражение. Должно след # Используйте def для создания новых функций def add(x, y): print("x равен %s, а y равен %s" % (x, y)) - return x + y # Возвращайте результат с помощью ключевого слова return + return x + y # Возвращайте результат с помощью ключевого слова return # Вызов функции с аргументами -add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвращает 11 +add(5, 6) # => Выводит "x равен 5, а y равен 6" и возвращает 11 # Другой способ вызова функции — вызов с именованными аргументами -add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке. +add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке. -# Вы можете определить функцию, принимающую переменное число аргументов, -# которые будут интерпретированы как кортеж, если вы не используете * +# Вы можете определить функцию, принимающую переменное число аргументов def varargs(*args): return args -varargs(1, 2, 3) #=> (1,2,3) +varargs(1, 2, 3) # => (1,2,3) # А также можете определить функцию, принимающую переменное число -# именованных аргументов, которые будут интерпретированы как словарь, -# если вы не используете ** +# именованных аргументов def keyword_args(**kwargs): return kwargs # Вызовем эту функцию и посмотрим, что из этого получится -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} # Если хотите, можете использовать оба способа одновременно def all_the_args(*args, **kwargs): @@ -432,77 +601,134 @@ all_the_args(1, 2, a=3, b=4) выводит: # Используйте символ * для распаковки кортежей и ** для распаковки словарей args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # эквивалентно foo(1, 2, 3, 4) -all_the_args(**kwargs) # эквивалентно foo(a=3, b=4) -all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4) - -# вы можете передавать переменное число позиционных или именованных аргументов -# другим функциям, которые их принимают, распаковывая их с помощью -# * или ** соответственно -def pass_all_the_args(*args, **kwargs): - all_the_args(*args, **kwargs) - print varargs(*args) - print keyword_args(**kwargs) +all_the_args(*args) # эквивалентно all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # эквивалентно all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # эквивалентно all_the_args(1, 2, 3, 4, a=3, b=4) + +# Возврат нескольких значений (с назначением кортежей) +def swap(x, y): + return y, x # Возвращает несколько значений в виде кортежа без скобок. + # (Примечание: скобки исключены, но могут быть включены) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # Снова, скобки были исключены, но могут быть включены. # Область определения функций x = 5 -def setX(num): +def set_x(num): # Локальная переменная x — это не то же самое, что глобальная переменная x - x = num # => 43 - print (x) # => 43 - -def setGlobalX(num): + x = num # => 43 + print(x) # => 43 + +def set_global_x(num): global x - print (x) # => 5 - x = num # Глобальная переменная x теперь равна 6 - print (x) # => 6 + print(x) # => 5 + x = num # Глобальная переменная x теперь равна 6 + print(x) # => 6 -setX(43) -setGlobalX(6) +set_x(43) +set_global_x(6) -# В Python функции — «объекты первого класса» +# Python имеет функции первого класса def create_adder(x): def adder(y): return x + y return adder add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3) # => 13 # Также есть и анонимные функции -(lambda x: x > 2)(3) #=> True +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 # Есть встроенные функции высшего порядка -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] + +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] + +# Для удобного отображения и фильтрации можно использовать списочные интерпретации +# Интерпретация списка сохраняет вывод в виде списка, который сам может быть вложенным списком +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# Вы также можете создавать интерпретации множеств и словарей. +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} -# Для удобного отображения и фильтрации можно использовать списочные включения -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] #################################################### -## 5. Классы +## 5. Модули #################################################### -# Чтобы получить класс, мы наследуемся от object. -class Human(object): +# Вы можете импортировать модули +import math +print(math.sqrt(16)) # => 4.0 + +# Вы можете получить определенные функции из модуля +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# Вы можете импортировать все функции из модуля. +# Предупреждение: это не рекомендуется +from math import * - # Атрибут класса. Он разделяется всеми экземплярами этого класса - species = "H. sapiens" +# Вы можете сократить имена модулей +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Модули Python - это обычные файлы Python. Вы +# можете писать свои собственные и импортировать их. Имя +# модуля совпадает с именем файла. + +# Вы можете узнать, какие функции и атрибуты +# определены в модуле. +import math +dir(math) + +# Если у вас есть скрипт Python с именем math.py в той же папке, +# что и ваш текущий скрипт, файл math.py будет +# будет загружен вместо встроенного модуля Python. +# Это происходит потому, что локальная папка имеет приоритет +# над встроенными библиотеками Python. + + +#################################################### +## 6. Классы +#################################################### + +# Мы используем оператор class для создания класса +class Human: + + # Атрибут класса. Он используется всеми экземплярами этого класса + species = "Гомосапиенс" # Обычный конструктор, вызывается при инициализации экземпляра класса # Обратите внимание, что двойное подчёркивание в начале и в конце имени # означает объекты и атрибуты, которые используются Python, но находятся # в пространствах имён, управляемых пользователем. + # Методы (или объекты или атрибуты), например: + # __init__, __str__, __repr__ и т. д. называются специальными методами. # Не придумывайте им имена самостоятельно. def __init__(self, name): - # Присваивание значения аргумента атрибуту класса name + # Присваивание значения аргумента атрибуту self.name = name + # Инициализация свойства + self._age = 0 + # Метод экземпляра. Все методы принимают self в качестве первого аргумента def say(self, msg): - return "%s: %s" % (self.name, msg) + return "{name}: {message}".format(name=self.name, message=msg) + + # Другой метод экземпляра + def sing(self): + return 'йо... йо... проверка микрофона... раз, два... раз, два...' # Метод класса разделяется между всеми экземплярами # Они вызываются с указыванием вызывающего класса в качестве первого аргумента @@ -515,58 +741,242 @@ class Human(object): def grunt(): return "*grunt*" + # property похоже на геттер. + # Оно превращает метод age() в одноименный атрибут только для чтения. + # Однако нет необходимости писать тривиальные геттеры и сеттеры в Python. + @property + def age(self): + return self._age + + # Это позволяет установить свойство + @age.setter + def age(self, age): + self._age = age + + # Это позволяет удалить свойство + @age.deleter + def age(self): + del self._age + + +# Когда интерпретатор Python читает исходный файл, он выполняет весь его код. +# Проверка __name__ гарантирует, что этот блок кода выполняется только тогда, когда +# этот модуль - это основная программа. +if __name__ == '__main__': + # Инициализация экземпляра класса + i = Human(name="Иван") + i.say("привет") # Выводит: "Иван: привет" + j = Human("Пётр") + j.say("привет") # Выводит: "Пётр: привет" + # i и j являются экземплярами типа Human, или другими словами: они являются объектами Human + + # Вызов метода класса + i.say(i.get_species()) # "Иван: Гомосапиенс" + # Изменение разделяемого атрибута + Human.species = "Неандертальец" + i.say(i.get_species()) # => "Иван: Неандертальец" + j.say(j.get_species()) # => "Пётр: Неандертальец" + + # Вызов статического метода + print(Human.grunt()) # => "*grunt*" + + # Невозможно вызвать статический метод с экземпляром объекта + # потому что i.grunt() автоматически поместит "self" (объект i) в качестве аргумента + print(i.grunt()) # => TypeError: grunt() takes 0 positional arguments but 1 was given + + # Обновить свойство для этого экземпляра + i.age = 42 + # Получить свойство + i.say(i.age) # => "Иван: 42" + j.say(j.age) # => "Пётр: 0" + # Удалить свойство + del i.age + # i.age # => это выбрасило бы ошибку AttributeError + + +#################################################### +## 6.1 Наследование +#################################################### + +# Наследование позволяет определять новые дочерние классы, которые наследуют методы и +# переменные от своего родительского класса. + +# Используя класс Human, определенный выше как базовый или родительский класс, мы можем +# определить дочерний класс Superhero, который наследует переменные класса, такие как +# "species", "name" и "age", а также методы, такие как "sing" и "grunt" из класса Human, +# но также может иметь свои уникальные свойства. + +# Чтобы воспользоваться преимуществами модульности по файлам, вы можете поместить +# вышеперечисленные классы в их собственные файлы, например, human.py + +# Чтобы импортировать функции из других файлов, используйте следующий формат +# from "имя-файла-без-расширения" import "функция-или-класс" + +from human import Human + + +# Укажите родительский класс(ы) как параметры определения класса +class Superhero(Human): + + # Если дочерний класс должен наследовать все определения родителя без каких-либо + # изменений, вы можете просто использовать ключевое слово pass (и ничего больше), + # но в этом случае оно закомментировано, чтобы разрешить уникальный дочерний класс: + # pass + + # Дочерние классы могут переопределять атрибуты своих родителей + species = 'Сверхчеловек' + + # Дочерние классы автоматически наследуют конструктор родительского класса, включая + # его аргументы, но также могут определять дополнительные аргументы или определения + # и переопределять его методы, такие как конструктор класса. + # Этот конструктор наследует аргумент "name" от класса "Human" + # и добавляет аргументы "superpower" и "movie": + def __init__(self, name, movie=False, + superpowers=["сверхсила", "пуленепробиваемость"]): + + # добавить дополнительные атрибуты класса: + self.fictional = True + self.movie = movie + # помните об изменяемых значениях по умолчанию, + # поскольку значения по умолчанию являются общими + self.superpowers = superpowers + + # Функция "super" позволяет вам получить доступ к методам родительского класса, + # которые переопределяются дочерним, в данном случае, методом __init__. + # Это вызывает конструктор родительского класса: + super().__init__(name) + + # переопределить метод sing + def sing(self): + return 'Бам, бам, БАМ!' + + # добавить дополнительный метод экземпляра + def boast(self): + for power in self.superpowers: + print("Я обладаю силой '{pow}'!".format(pow=power)) + -# Инициализация экземпляра класса -i = Human(name="Иван") -print(i.say("привет")) # Выводит: «Иван: привет» +if __name__ == '__main__': + sup = Superhero(name="Тик") -j = Human("Пётр") -print(j.say("Привет")) # Выводит: «Пётр: привет» + # Проверка типа экземпляра + if isinstance(sup, Human): + print('Я человек') + if type(sup) is Superhero: + print('Я супергерой') -# Вызов метода класса -i.get_species() #=> "H. sapiens" + # Получить порядок поиска разрешения метода (MRO), + # используемый как getattr(), так и super() + # Этот атрибут является динамическим и может быть обновлен + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) -# Изменение разделяемого атрибута -Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" + # Вызывает родительский метод, но использует свой собственный атрибут класса + print(sup.get_species()) # => Сверхчеловек -# Вызов статического метода -Human.grunt() #=> "*grunt*" + # Вызов переопределенного метода + print(sup.sing()) # => Бам, бам, БАМ! + + # Вызывает метод из Human + sup.say('Ложка') # => Тик: Ложка + + # Метод вызова, существующий только в Superhero + sup.boast() # => Я обладаю силой 'сверхсила'! + # => Я обладаю силой 'пуленепробиваемость'! + + # Атрибут унаследованного класса + sup.age = 31 + print(sup.age) # => 31 + + # Атрибут, который существует только в Superhero + print('Достоин ли я Оскара? ' + str(sup.movie)) #################################################### -## 6. Модули +## 6.2 Множественное наследование #################################################### -# Вы можете импортировать модули -import math -print(math.sqrt(16)) #=> 4.0 +# Eще одно определение класса +# bat.py +class Bat: -# Вы можете импортировать отдельные функции модуля -from math import ceil, floor -print(ceil(3.7)) #=> 4.0 -print(floor(3.7)) #=> 3.0 + species = 'Летучая мышь' -# Можете импортировать все функции модуля. -# (Хотя это и не рекомендуется) -from math import * + def __init__(self, can_fly=True): + self.fly = can_fly -# Можете сокращать имена модулей -import math as m -math.sqrt(16) == m.sqrt(16) #=> True -# Вы также можете убедиться, что функции эквивалентны -from math import sqrt -math.sqrt == m.sqrt == sqrt # => True + # В этом классе также есть метод say + def say(self, msg): + msg = '... ... ...' + return msg -# Модули в Python — это обычные Python-файлы. Вы -# можете писать свои модули и импортировать их. Название -# модуля совпадает с названием файла. + # И свой метод тоже + def sonar(self): + return '))) ... (((' + +if __name__ == '__main__': + b = Bat() + print(b.say('привет')) + print(b.fly) + + +# И еще одно определение класса, унаследованное от Superhero и Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# Определите Batman как дочерний класс, унаследованный от Superhero и Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # Обычно для наследования атрибутов необходимо вызывать super: + # super(Batman, self).__init__(*args, **kwargs) + # Однако здесь мы имеем дело с множественным наследованием, а super() + # работает только со следующим базовым классом в списке MRO. + # Поэтому вместо этого мы вызываем __init__ для всех родителей. + # Использование *args и **kwargs обеспечивает чистый способ передачи + # аргументов, когда каждый родитель "очищает слой луковицы". + Superhero.__init__(self, 'анонимный', movie=True, + superpowers=['Богатый'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # переопределить значение атрибута name + self.name = 'Грустный Бен Аффлек' + + def sing(self): + return 'на на на на на бэтмен!' + + +if __name__ == '__main__': + sup = Batman() + + # Получить порядок поиска разрешения метода (MRO), + # используемый как getattr(), так и super() + # Этот атрибут является динамическим и может быть обновлен + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + + # Вызывает родительский метод, но использует свой собственный атрибут класса + print(sup.get_species()) # => Сверхчеловек + + # Вызов переопределенного метода + print(sup.sing()) # => на на на на на бэтмен! + + # Вызывает метод из Human, потому что порядок наследования имеет значение + sup.say('Я согласен') # => Грустный Бен Аффлек: Я согласен + + # Вызов метода, существующий только во втором родителе + print(sup.sonar()) # => ))) ... ((( + + # Атрибут унаследованного класса + sup.age = 100 + print(sup.age) # => 100 + + # Унаследованный атрибут от второго родителя, + # значение по умолчанию которого было переопределено. + print('Могу ли я летать? ' + str(sup.fly)) # => Могу ли я летать? False -# Вы можете узнать, какие функции и атрибуты определены -# в модуле -import math -dir(math) #################################################### ## 7. Дополнительно @@ -577,28 +987,30 @@ def double_numbers(iterable): for i in iterable: yield i + i -# Генератор создаёт значения на лету. -# Он не возвращает все значения разом, а создаёт каждое из них при каждой -# итерации. Это значит, что значения больше 15 в double_numbers -# обработаны не будут. -# Обратите внимание: xrange — это генератор, который делает то же, что и range. -# Создание списка чисел от 1 до 900000000 требует много места и времени. -# xrange создаёт объект генератора, а не список сразу, как это делает range. -# Если нам нужно имя переменной, совпадающее с ключевым словом Python, -# мы используем подчёркивание в конце -xrange_ = xrange(1, 900000000) - -# Будет удваивать все числа, пока результат не превысит 30 -for i in double_numbers(xrange_): +# Генераторы эффективны с точки зрения памяти, потому что они загружают только данные, +# необходимые для обработки следующего значения в итерации. +# Это позволяет им выполнять операции с недопустимо большими диапазонами значений. +# ПРИМЕЧАНИЕ: "range" заменяет "xrange" в Python 3. +for i in double_numbers(range(1, 900000000)): # "range" - генератор. print(i) if i >= 30: break +# Так же, как вы можете создать интерпретации списков, вы можете создать и +# интерпретации генераторов. +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # Выводит -1 -2 -3 -4 -5 + +# Вы также можете преобразовать интерпретацию генератора непосредственно в список. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + # Декораторы -# В этом примере beg оборачивает say -# Метод beg вызовет say. Если say_please равно True, -# он изменит возвращаемое сообщение +# В этом примере "beg" оборачивает "say". +# Если say_please равно True, он изменит возвращаемое сообщение. from functools import wraps @@ -607,7 +1019,7 @@ def beg(target_function): def wrapper(*args, **kwargs): msg, say_please = target_function(*args, **kwargs) if say_please: - return "{} {}".format(msg, " Пожалуйста! У меня нет денег :(") + return "{} {}".format(msg, "Пожалуйста! У меня нет денег :(") return msg return wrapper @@ -619,8 +1031,8 @@ def say(say_please=False): return msg, say_please -print(say()) # Вы не купите мне пива? -print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :( +print(say()) # Вы не купите мне пива? +print(say(say_please=True)) # Вы не купите мне пива? Пожалуйста! У меня нет денег :( ``` @@ -628,16 +1040,18 @@ print(say(say_please=True)) # Вы не купите мне пива? Пожал ### Бесплатные онлайн-материалы -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Официальная документация](http://docs.python.org/2.6/) +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [Официальная документация](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) - -### Платные - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](http://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](http://nbviewer.jupyter.org/gist/anonymous/5924718) +* [Python Tutorial for Intermediates](https://pythonbasics.org/) +* [Build a Desktop App with Python](https://pythonpyqt.com/) diff --git a/ru-ru/python3-ru.html.markdown b/ru-ru/pythonlegacy-ru.html.markdown index bf80fed2..ead2af3d 100644 --- a/ru-ru/python3-ru.html.markdown +++ b/ru-ru/pythonlegacy-ru.html.markdown @@ -1,23 +1,23 @@ --- -language: python3 +language: Python 2 (legacy) lang: ru-ru contributors: - ["Louie Dinh", "http://ldinh.ca"] - - ["Steven Basart", "http://github.com/xksteven"] translators: + - ["Yury Timofeev", "http://twitter.com/gagar1n"] - ["Andre Polykanine", "https://github.com/Oire"] -filename: learnpython3-ru.py +filename: learnpythonlegacy-ru.py --- Язык Python был создан Гвидо ван Россумом в начале 90-х. Сейчас это один из самых популярных языков. Я влюбился в Python за понятный и доходчивый синтаксис — это -почти что исполняемый псевдокод. +почти исполняемый псевдокод. С благодарностью жду ваших отзывов: [@louiedinh](http://twitter.com/louiedinh) или louiedinh [at] [почтовый сервис Google] -Замечание: Эта статья относится только к Python 3. -Если вы хотите изучить Python 2.7, обратитесь к другой статье. +Замечание: Эта статья относится к Python 2.7, но должно работать и в других версиях Python 2.x. +Чтобы изучить Python 3.x, обратитесь к статье по Python 3. ```python # Однострочные комментарии начинаются с символа решётки. @@ -37,9 +37,16 @@ filename: learnpython3-ru.py 1 + 1 #=> 2 8 - 1 #=> 7 10 * 2 #=> 20 +35 / 5 #=> 7 -# Кроме деления, которое по умолчанию возвращает число с плавающей запятой -35 / 5 # => 7.0 +# А вот деление немного сложнее. В этом случае происходит деление +# целых чисел, и результат автоматически округляется в меньшую сторону. +5 / 2 #=> 2 + +# Чтобы делить правильно, сначала нужно немного узнать о числах +# с плавающей запятой. +2.0 # Это число с плавающей запятой +11.0 / 4.0 #=> 2.75 Вооот... Так гораздо лучше # Результат целочисленного деления округляется в меньшую сторону # как для положительных, так и для отрицательных чисел. @@ -48,10 +55,6 @@ filename: learnpython3-ru.py -5 // 3 # => -2 -5.0 // 3.0 # => -2.0 -# Когда вы используете числа с плавающей запятой, -# результатом будет также число с плавающей запятой -3 * 2.0 # => 6.0 - # Остаток от деления 7 % 3 # => 1 @@ -61,14 +64,6 @@ filename: learnpython3-ru.py # Приоритет операций указывается скобками (1 + 3) * 2 #=> 8 -# Для логических (булевых) значений существует отдельный примитивный тип -True -False - -# Для отрицания используется ключевое слово not -not True #=> False -not False #=> True - # Логические операторы # Обратите внимание: ключевые слова «and» и «or» чувствительны к регистру букв True and False #=> False @@ -81,6 +76,10 @@ False or True #=> True 2 == True #=> False 1 == True #=> True +# Для отрицания используется ключевое слово not +not True #=> False +not False #=> True + # Равенство — это == 1 == 1 #=> True 2 == 1 #=> False @@ -95,7 +94,7 @@ False or True #=> True 2 <= 2 #=> True 2 >= 2 #=> True -# Сравнения могут быть записаны цепочкой: +# Сравнения могут быть записаны цепочкой! 1 < 2 < 3 #=> True 2 < 3 < 2 #=> False @@ -103,70 +102,75 @@ False or True #=> True "Это строка." 'Это тоже строка.' -# И строки тоже могут складываться! Хотя лучше не злоупотребляйте этим. +# И строки тоже можно складывать! "Привет " + "мир!" #=> "Привет мир!" -# Строки можно умножать. -"aa" * 4 #=> "aaaaaaaa" +# ... или умножать +"Привет" * 3 # => "ПриветПриветПривет" # Со строкой можно работать, как со списком символов "Это строка"[0] #=> 'Э' -# Метод format используется для форматирования строк: +# Символ % используется для форматирования строк, например: +"%s могут быть %s" % ("строки", "интерполированы") + +# Новый способ форматирования строк — использование метода format. +# Это предпочитаемый способ. "{0} могут быть {1}".format("строки", "форматированы") -# Вы можете повторять аргументы форматирования, чтобы меньше печатать. -"Ехал {0} через реку, видит {0} - в реке {1}! Сунул {0} руку в реку, {1} за руку греку цап!".format("грека", "рак") -#=> "Ехал грека через реку, видит грека - в реке рак! Сунул грека руку в реку, рак за руку греку цап!" # Если вы не хотите считать, можете использовать ключевые слова. "{name} хочет есть {food}".format(name="Боб", food="лазанью") -# Если ваш код на Python 3 нужно запускать также и под Python 2.5 и ниже, -# вы также можете использовать старый способ форматирования: -"%s можно %s %s способом" % ("строки", "интерполировать", "старым") - # None является объектом None #=> None -# Не используйте оператор равенства '==' для сравнения -# объектов с None. Используйте для этого 'is' +# Не используйте оператор равенства '=='' для сравнения +# объектов с None. Используйте для этого «is» "etc" is None #=> False None is None #=> True -# Оператор «is» проверяет идентичность объектов. Он не +# Оператор 'is' проверяет идентичность объектов. Он не # очень полезен при работе с примитивными типами, но # зато просто незаменим при работе с объектами. -# None, 0 и пустые строки/списки/словари приводятся к False. +# None, 0 и пустые строки/списки равны False. # Все остальные значения равны True -bool(0) # => False -bool("") # => False -bool([]) #=> False -bool({}) #=> False +0 == False #=> True +"" == False #=> True #################################################### ## 2. Переменные и коллекции #################################################### -# В Python есть функция Print -print("Я Python. Приятно познакомиться!") +# В Python есть оператор print, доступный в версиях 2.x, но удалённый в версии 3 +print "Я Python. Приятно познакомиться!" +# В Python также есть функция print(), доступная в версиях 2.7 и 3, +# Но для версии 2.7 нужно добавить следующий импорт модуля (раскомментируйте)): +# from __future__ import print_function +print("Я тоже Python! ") # Объявлять переменные перед инициализацией не нужно. -# По соглашению используется нижний_регистр_с_подчёркиваниями -some_var = 5 +some_var = 5 # По соглашению используется нижний_регистр_с_подчёркиваниями some_var #=> 5 # При попытке доступа к неинициализированной переменной # выбрасывается исключение. -# Об исключениях см. раздел «Поток управления и итерируемые объекты». -some_unknown_var # Выбрасывает ошибку именования +# См. раздел «Поток управления» для информации об исключениях. +some_other_var # Выбрасывает ошибку именования + +# if может быть использован как выражение +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" # Списки хранят последовательности li = [] # Можно сразу начать с заполненного списка other_li = [4, 5, 6] +# строка разделена в список +a="adambard" +list(a) #=> ['a','d','a','m','b','a','r','d'] + # Объекты добавляются в конец списка методом append li.append(1) # [1] li.append(2) # [1, 2] @@ -179,6 +183,10 @@ li.append(3) # [1, 2, 4, 3]. # Обращайтесь со списком, как с обычным массивом li[0] #=> 1 +# Присваивайте новые значения уже инициализированным индексам с помощью = +li[0] = 42 +li[0] # => 42 +li[0] = 1 # Обратите внимание: возвращаемся на исходное значение # Обратимся к последнему элементу li[-1] #=> 3 @@ -200,11 +208,11 @@ li[::-1] # => [3, 4, 2, 1] # li[начало:конец:шаг] # Удаляем произвольные элементы из списка оператором del -del li[2] # [1, 2, 3] +del li[2] # li теперь [1, 2, 3] # Вы можете складывать, или, как ещё говорят, конкатенировать списки -# Обратите внимание: значения li и other_li при этом не изменились. li + other_li #=> [1, 2, 3, 4, 5, 6] — Замечание: li и other_li не изменяются +# Обратите внимание: значения li и other_li при этом не изменились. # Объединять списки можно методом extend li.extend(other_li) # Теперь li содержит [1, 2, 3, 4, 5, 6] @@ -234,7 +242,6 @@ d, e, f = 4, 5, 6 # Обратите внимание, как легко поменять местами значения двух переменных e, d = d, e # теперь d == 5, а e == 4 - # Словари содержат ассоциативные массивы empty_dict = {} # Вот так описывается предзаполненный словарь @@ -244,17 +251,13 @@ filled_dict = {"one": 1, "two": 2, "three": 3} # что индекс — у словарей он называется ключом — не обязан быть числом filled_dict["one"] #=> 1 -# Все ключи в виде списка получаются с помощью метода keys(). -# Его вызов нужно обернуть в list(), так как обратно мы получаем -# итерируемый объект, о которых поговорим позднее. -list(filled_dict.keys()) # => ["three", "two", "one"] +# Можно получить все ключи в виде списка с помощью метода keys +filled_dict.keys() #=> ["three", "two", "one"] # Замечание: сохранение порядка ключей в словаре не гарантируется # Ваши результаты могут не совпадать с этими. -# Все значения в виде списка можно получить с помощью values(). -# И снова нам нужно обернуть вызов в list(), чтобы превратить -# итерируемый объект в список. -list(filled_dict.values()) # => [3, 2, 1] +# Можно получить и все значения в виде списка, используйте метод values +filled_dict.values() #=> [3, 2, 1] # То же самое замечание насчёт порядка ключей справедливо и здесь # При помощи оператора in можно проверять ключи на вхождение в словарь @@ -271,27 +274,28 @@ filled_dict.get("four") #=> None # возвращено при отсутствии указанного ключа filled_dict.get("one", 4) #=> 1 filled_dict.get("four", 4) #=> 4 +# Обратите внимание, что filled_dict.get("four") всё ещё => None +# (get не устанавливает значение элемента словаря) + +# Присваивайте значение ключам так же, как и в списках +filled_dict["four"] = 4 # теперь filled_dict["four"] => 4 -# Метод setdefault вставляет пару ключ-значение, только если такого ключа нет +# Метод setdefault() вставляет пару ключ-значение, только если такого ключа нет filled_dict.setdefault("five", 5) #filled_dict["five"] возвращает 5 filled_dict.setdefault("five", 6) #filled_dict["five"] по-прежнему возвращает 5 -# Добавление элементов в словарь -filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} -#filled_dict["four"] = 4 # Другой способ добавления элементов - -# Удаляйте ключи из словаря с помощью оператора del -del filled_dict["one"] # Удаляет ключ «one» из словаря - # Множества содержат... ну, в общем, множества +# (которые похожи на списки, только в них не может быть дублирующихся элементов) empty_set = set() -# Инициализация множества набором значений. -# Да, оно выглядит примерно как словарь… ну извините, так уж вышло. -filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} +# Инициализация множества набором значений +some_set = set([1,2,2,3,4]) # some_set теперь равно set([1, 2, 3, 4]) -# Множеству можно назначать новую переменную -filled_set = some_set +# Порядок сортировки не гарантируется, хотя иногда они выглядят отсортированными +another_set = set([4, 3, 2, 2, 1]) # another_set теперь set([1, 2, 3, 4]) + +# Начиная с Python 2.7, вы можете использовать {}, чтобы объявить множество +filled_set = {1, 2, 2, 3, 4} # => {1, 2, 3, 4} # Добавление новых элементов в множество filled_set.add(5) # filled_set равно {1, 2, 3, 4, 5} @@ -312,7 +316,7 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6} #################################################### -## 3. Поток управления и итерируемые объекты +## 3. Поток управления #################################################### # Для начала заведём переменную @@ -328,13 +332,17 @@ else: # Это тоже необязательно. print("some_var равно 10.") -# Циклы For проходят по спискам. Результат: - # собака — это млекопитающее - # кошка — это млекопитающее - # мышь — это млекопитающее +""" +Циклы For проходят по спискам + +Результат: + собака — это млекопитающее + кошка — это млекопитающее + мышь — это млекопитающее +""" for animal in ["собака", "кошка", "мышь"]: - # Можете использовать format() для интерполяции форматированных строк - print("{} — это млекопитающее".format(animal)) + # Можете использовать оператор % для интерполяции форматированных строк + print("%s — это млекопитающее" % animal) """ «range(число)» возвращает список чисел @@ -362,6 +370,8 @@ while x < 4: x += 1 # Краткая запись для x = x + 1 # Обрабатывайте исключения блоками try/except + +# Работает в Python 2.6 и выше: try: # Чтобы выбросить ошибку, используется raise raise IndexError("Это ошибка индекса") @@ -374,37 +384,6 @@ except (TypeError, NameError): else: # Необязательное выражение. Должно следовать за последним блоком except print("Всё хорошо!") # Выполнится, только если не было никаких исключений -# Python предоставляет фундаментальную абстракцию, -# которая называется итерируемым объектом (an iterable). -# Итерируемый объект — это объект, который воспринимается как последовательность. -# Объект, который возвратила функция range(), итерируемый. -filled_dict = {"one": 1, "two": 2, "three": 3} -our_iterable = filled_dict.keys() -print(our_iterable) #=> range(1,10). Это объект, реализующий интерфейс iterable - -# Мы можем проходить по нему циклом. -for i in our_iterable: - print(i) # Выводит one, two, three - -# Но мы не можем обращаться к элементу по индексу. -our_iterable[1] # Выбрасывает ошибку типа - -# Итерируемый объект знает, как создавать итератор. -our_iterator = iter(our_iterable) - -# Итератор может запоминать состояние при проходе по объекту. -# Мы получаем следующий объект, вызывая функцию __next__. -our_iterator.__next__() #=> "one" - -# Он сохраняет состояние при вызове __next__. -our_iterator.__next__() #=> "two" -our_iterator.__next__() #=> "three" - -# Возвратив все данные, итератор выбрасывает исключение StopIterator -our_iterator.__next__() # Выбрасывает исключение остановки итератора - -# Вы можете получить сразу все элементы итератора, вызвав на нём функцию list(). -list(filled_dict.keys()) #=> Возвращает ["one", "two", "three"] #################################################### @@ -422,7 +401,8 @@ add(5, 6) #=> выводит «x равен 5, а y равен 6» и возвр # Другой способ вызова функции — вызов с именованными аргументами add(y=6, x=5) # Именованные аргументы можно указывать в любом порядке. -# Вы можете определить функцию, принимающую переменное число аргументов +# Вы можете определить функцию, принимающую переменное число аргументов, +# которые будут интерпретированы как кортеж, если вы не используете * def varargs(*args): return args @@ -430,7 +410,8 @@ varargs(1, 2, 3) #=> (1,2,3) # А также можете определить функцию, принимающую переменное число -# именованных аргументов +# именованных аргументов, которые будут интерпретированы как словарь, +# если вы не используете ** def keyword_args(**kwargs): return kwargs @@ -455,6 +436,14 @@ all_the_args(*args) # эквивалентно foo(1, 2, 3, 4) all_the_args(**kwargs) # эквивалентно foo(a=3, b=4) all_the_args(*args, **kwargs) # эквивалентно foo(1, 2, 3, 4, a=3, b=4) +# вы можете передавать переменное число позиционных или именованных аргументов +# другим функциям, которые их принимают, распаковывая их с помощью +# * или ** соответственно +def pass_all_the_args(*args, **kwargs): + all_the_args(*args, **kwargs) + print varargs(*args) + print keyword_args(**kwargs) + # Область определения функций x = 5 @@ -513,7 +502,7 @@ class Human(object): # Метод экземпляра. Все методы принимают self в качестве первого аргумента def say(self, msg): - return "{name}: {message}".format(name=self.name, message=msg) + return "%s: %s" % (self.name, msg) # Метод класса разделяется между всеми экземплярами # Они вызываются с указыванием вызывающего класса в качестве первого аргумента @@ -566,6 +555,9 @@ from math import * # Можете сокращать имена модулей import math as m math.sqrt(16) == m.sqrt(16) #=> True +# Вы также можете убедиться, что функции эквивалентны +from math import sqrt +math.sqrt == m.sqrt == sqrt # => True # Модули в Python — это обычные Python-файлы. Вы # можете писать свои модули и импортировать их. Название @@ -589,14 +581,15 @@ def double_numbers(iterable): # Он не возвращает все значения разом, а создаёт каждое из них при каждой # итерации. Это значит, что значения больше 15 в double_numbers # обработаны не будут. -# Обратите внимание: range — это тоже генератор. +# Обратите внимание: xrange — это генератор, который делает то же, что и range. # Создание списка чисел от 1 до 900000000 требует много места и времени. +# xrange создаёт объект генератора, а не список сразу, как это делает range. # Если нам нужно имя переменной, совпадающее с ключевым словом Python, # мы используем подчёркивание в конце -range_ = range(1, 900000000) +xrange_ = xrange(1, 900000000) # Будет удваивать все числа, пока результат не превысит 30 -for i in double_numbers(range_): +for i in double_numbers(xrange_): print(i) if i >= 30: break @@ -637,10 +630,9 @@ print(say(say_please=True)) # Вы не купите мне пива? Пожал * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [Официальная документация](http://docs.python.org/3/) +* [Официальная документация](http://docs.python.org/2.6/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/3/) +* [Python Module of the Week](http://pymotw.com/2/) * [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) ### Платные diff --git a/ru-ru/qt-ru.html.markdown b/ru-ru/qt-ru.html.markdown index d0a70c9d..15e2c775 100644 --- a/ru-ru/qt-ru.html.markdown +++ b/ru-ru/qt-ru.html.markdown @@ -1,7 +1,7 @@ --- category: tool tool: Qt Framework -language: c++ +language: C++ filename: learnqt-ru.cpp contributors: - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"] @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) { ``` Обратите внимание на метод *QObject::connect*. Этот метод соединяет *СИГНАЛЫ* одного объекта со *СЛОТАМИ* другого. -**Сигналы** отправляются когда с объектами происходят отпределённые события, например, сигнал *нажатие* отправляется когда пользователь нажимает на объект типа QPushButton. +**Сигналы** отправляются когда с объектами происходят определённые события, например, сигнал *нажатие* отправляется, когда пользователь нажимает на объект типа QPushButton. **Слоты** это *действия*, которые могут быть выполнены в ответ на полученные сигналы. diff --git a/ru-ru/ruby-ru.html.markdown b/ru-ru/ruby-ru.html.markdown index b1fd04e1..8b263be6 100644 --- a/ru-ru/ruby-ru.html.markdown +++ b/ru-ru/ruby-ru.html.markdown @@ -480,7 +480,7 @@ class Human @name end - # Тоже самое можно определить с помощью att_accessor + # Тоже самое можно определить с помощью attr_accessor attr_accessor :name # Также можно создать методы только для записи или чтения diff --git a/ru-ru/rust-ru.html.markdown b/ru-ru/rust-ru.html.markdown index 7bd2809a..a568ac37 100644 --- a/ru-ru/rust-ru.html.markdown +++ b/ru-ru/rust-ru.html.markdown @@ -1,41 +1,38 @@ --- -language: rust +language: Rust filename: learnrust-ru.rs contributors: - ["P1start", "http://p1start.github.io/"] translators: - ["Anatolii Kosorukov", "https://github.com/java1cprog"] + - ["Vasily Starostin", "https://github.com/Basil22"] lang: ru-ru --- -Rust сочетает в себе низкоуровневый контроль над производительностью с удобством высокого уровня и предоставляет гарантии -безопасности. -Он достигает этих целей, не требуя сборщика мусора или времени выполнения, что позволяет использовать библиотеки Rust как замену -для C-библиотек. +Язык Rust разработан в Mozilla Research. Он сочетает низкоуровневую производительность с удобством языка высокого уровня и одновременно гарантирует безопасность памяти. -Первый выпуск Rust, 0.1, произошел в январе 2012 года, и в течение 3 лет развитие продвигалось настолько быстро, что до -недавнего времени использование стабильных выпусков было затруднено, и вместо этого общий совет заключался в том, чтобы -использовать последние сборки. +Он достигает этих целей без сборщика мусора или сложной среды выполнения, что позволяет использовать библиотеки Rust как прямую замену +C-библиотек. И наоборот, Rust умеет использовать готовые С-библиотеки как есть, без накладных расходов. -15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Усовершенствования времени компиляции и -других аспектов компилятора в настоящее время доступны в ночных сборках. Rust приняла модель выпуска на поезде с регулярными выпусками каждые шесть недель. Rust 1.1 beta был доступен одновременно с выпуском Rust 1.0. +Первый выпуск Rust, 0.1, произошел в январе 2012 года. В течение 3 лет развитие продвигалось настолько быстро, что язык серьезно менялся без сохранения совместимости. Это дало возможность обкатать и отполировать синтаксис и возможности языка. -Хотя Rust является языком относительно низкого уровня, Rust имеет некоторые функциональные концепции, которые обычно -встречаются на языках более высокого уровня. Это делает Rust не только быстрым, но и простым и эффективным для ввода кода. +15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Сборка поставляется в трех вариантах: стабильная версия, бета-версия, ночная версия. Все нововведения языка сперва обкатываются на ночной и бета-версиях, и только потом попадают в стабильную. Выход очередной версии происходит раз в 6 недель. В 2018 году вышло второе большое обновление языка, добавившее ему новых возможностей. + +Хотя Rust является языком относительно низкого уровня, он имеет все возможности высокоуровневых языков: процедурное, объектное, функциональное, шаблонное и другие виды программирования. На данный момент Rust является одним из самых мощных (а может быть и самым) по возможностям среди статически типизированных языков. Это делает Rust не только быстрым, но и простым и эффективным для разработки сложного кода. ```rust -// Это однострочный комментарии +// Это однострочный комментарий // /// Так выглядит комментарий для документации /// # Examples /// -/// +/// ``` /// let seven = 7 -/// +/// ``` /////////////// // 1. Основы // @@ -63,10 +60,9 @@ fn main() { let y: i32 = 13i32; let f: f64 = 1.3f64; - // Автоматическое выявление типа данных + // Автоматическое выведение типа данных // В большинстве случаев компилятор Rust может вычислить - // тип переменной, поэтому - // вам не нужно писать явные аннотации типа. + // тип переменной, поэтому вам не нужно явно указывать тип. let implicit_x = 1; let implicit_f = 1.3; @@ -87,12 +83,11 @@ fn main() { // Печать на консоль println!("{} {}", f, x); // 1.3 hello world - // `String` – изменяемя строка + // `String` – изменяемая строка let s: String = "hello world".to_string(); - // Строковый срез - неизменяемый вид в строки - // Это в основном неизменяемая пара указателей на строку - - // Это указатель на начало и конец строкового буфера + // Строковый срез - неизменяемое представление части строки + // Представляет собой пару из указателя на начало фрагмента и его длины let s_slice: &str = &s; @@ -130,7 +125,7 @@ fn main() { // 2. Типы // ////////////// - // Struct + // Структура struct Point { x: i32, y: i32, @@ -154,6 +149,8 @@ fn main() { let up = Direction::Up; // Перечисление с полями + // В отличие от C и C++ компилятор автоматически следит за тем, + // какой именно тип хранится в перечислении. enum OptionalI32 { AnI32(i32), Nothing, @@ -175,7 +172,7 @@ fn main() { // Методы // impl<T> Foo<T> { - fn get_bar(self) -> T { + fn get_bar(self) -> T { self.bar } } @@ -198,9 +195,9 @@ fn main() { let another_foo = Foo { bar: 1 }; println!("{:?}", another_foo.frobnicate()); // Some(1) - ///////////////////////// - // 3. Поиск по шаблону // - ///////////////////////// + ///////////////////////////////// + // 3. Сопоставление по шаблону // + ///////////////////////////////// let foo = OptionalI32::AnI32(1); match foo { @@ -223,17 +220,17 @@ fn main() { println!("The second number is Nothing!"), } - ///////////////////// + ////////////////////////////////////////////// // 4. Управление ходом выполнения программы // - ///////////////////// + ////////////////////////////////////////////// // `for` loops/iteration let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } - // Отрезки + // Диапазоны for i in 0u32..10 { print!("{} ", i); } @@ -266,12 +263,12 @@ fn main() { break; } - ///////////////////////////////// + ////////////////////////////////// // 5. Защита памяти и указатели // - ///////////////////////////////// + ////////////////////////////////// // Владеющий указатель – такой указатель может быть только один - // Это значит, что при вызоде из блока переменная автоматически становится недействительной. + // Это значит, что при выходе из блока переменная автоматически становится недействительной. let mut mine: Box<i32> = Box::new(3); *mine = 5; // dereference // Здесь, `now_its_mine` получает во владение `mine`. Т.е. `mine` была перемещена. diff --git a/ru-ru/sql-ru.html.markdown b/ru-ru/sql-ru.html.markdown index 7353a175..702a8102 100644 --- a/ru-ru/sql-ru.html.markdown +++ b/ru-ru/sql-ru.html.markdown @@ -22,9 +22,9 @@ lang: ru-ru поддерживают ключевые слова QUIT, EXIT или оба). Некоторые команды ниже предполагают использование -[демонстрационного образца базы данных сотрудников от MySQL](https://dev.mysql.com/doc/employee/en/), доступного на [Github](https://github.com/datacharmer/test_db). +[демонстрационного образца базы данных сотрудников от MySQL](https://dev.mysql.com/doc/employee/en/), доступного на [GitHub](https://github.com/datacharmer/test_db). Следовательно, для повторения команд в локальном окружении он должен быть загружен. -Файлы на github — это скрипты с командами, которые схожи с командами ниже, +Файлы на github — это скрипты с командами, схожие с командами ниже, которые создают и манипулируют таблицами и данными о сотрудниках вымышленной компании. Синтаксис для запуска этих скриптов будет зависеть от используемой вами реализации SQL. Обычно используется утилита, запускаемая из командной @@ -50,7 +50,7 @@ SHOW DATABASES; USE employees; -- Выбрать все строки и колонки из таблицы «departments» (отделы) текущей базы. --- В интерактивном режиме обыч но результат будет выведен на экран. +-- В интерактивном режиме обычно результат будет выведен на экран. SELECT * FROM departments; -- Тот же запрос, что и выше, но выбор только колонок «dept_no» и «dept_name». diff --git a/ru-ru/swift-ru.html.markdown b/ru-ru/swift-ru.html.markdown index f2b1fd36..bd2d23a0 100644 --- a/ru-ru/swift-ru.html.markdown +++ b/ru-ru/swift-ru.html.markdown @@ -13,7 +13,7 @@ lang: ru-ru --- Swift - это язык программирования, созданный компанией Apple, для приложений -под iOS и OS X. Разработанный, чтобы сосуществовать с Objective-C и +под iOS и macOS. Разработанный, чтобы сосуществовать с Objective-C и быть более устойчивым к ошибочному коду, Swift был представлен в 2014 году на конференции разработчиков Apple, WWDC. Приложения на Swift собираются с помощью LLVM-компилятора, включенного в Xcode 6+. @@ -622,7 +622,7 @@ class MyShape: Rect { // MARK: Прочее // -// `extension`s: Добавляет расширенный функционал к существующему типу +// `extension`s: Добавляет расширенную функциональность к существующему типу // Класс Square теперь "соответствует" протоколу `CustomStringConvertible` extension Square: CustomStringConvertible { diff --git a/ru-ru/tmux-ru.html.markdown b/ru-ru/tmux-ru.html.markdown index aa7545cc..643c48b0 100644 --- a/ru-ru/tmux-ru.html.markdown +++ b/ru-ru/tmux-ru.html.markdown @@ -249,4 +249,4 @@ set -g status-right "#[fg=green] | #[fg=white]#(tmux-mem-cpu-load)#[fg=green] | [Archlinux Wiki](https://wiki.archlinux.org/index.php/Tmux) -[Отображение CPU/MEM % в статусбаре](https://stackoverflow.com/questions/11558907/is-there-a-better-way-to-display-cpu-usage-in-tmux) +[Отображение CPU/MEM % в статус баре](https://stackoverflow.com/questions/11558907/is-there-a-better-way-to-display-cpu-usage-in-tmux) diff --git a/ru-ru/typescript-ru.html.markdown b/ru-ru/typescript-ru.html.markdown index 09bbb2d1..ad931599 100644 --- a/ru-ru/typescript-ru.html.markdown +++ b/ru-ru/typescript-ru.html.markdown @@ -9,8 +9,8 @@ translators: filename: learntypescript-ru.ts --- -TypeScript — это язык программирования, целью которого является лёгкая разработка широкомасштабируемых JavaScript-приложений. -TypeScript добавляет в Javascript общие концепции, такие, как классы, модули, интерфейсы, обобщённое программирование и (опционально) статическую типизацию. +TypeScript — это язык программирования, целью которого является лёгкая разработка широко масштабируемых JavaScript-приложений. +TypeScript добавляет в Javascript общие концепции, такие как классы, модули, интерфейсы, обобщённое программирование и (опционально) статическую типизацию. Это надмножество языка JavaScript: весь JavaScript-код является валидным TypeScript-кодом, следовательно, может быть добавлен бесшовно в любой проект. Компилятор TypeScript генерирует JavaScript-код. diff --git a/ru-ru/vim-ru.html.markdown b/ru-ru/vim-ru.html.markdown index f43f99eb..60b381e7 100644 --- a/ru-ru/vim-ru.html.markdown +++ b/ru-ru/vim-ru.html.markdown @@ -10,7 +10,7 @@ lang: ru-ru --- [Vim](http://www.vim.org) -(Vi IMproved) это клон полулярного текстового редактора для Unix. Он разработан +(Vi IMproved) это клон популярного текстового редактора для Unix. Он разработан с целью повышения скорости и продуктивности и повсеместно используется в большинство Юникс-подобных систем. В нем имеется множество клавиатурных сочетаний для быстрой навигации к определенным точкам в файле и быстрого @@ -167,8 +167,8 @@ Vim можно рассматривать как набор команд в фо ## Макросы Макросы это просто записываемые действия. -Во время записи макросы запоминают **все** действия и команды до тех пор пока -запись не будет остановлена.При вызове макрос применяет ту же самую последовательность +Во время записи макросы запоминают **все** действия и команды до тех пор, пока +запись не будет остановлена. При вызове макрос применяет ту же самую последовательность действий и команд на выделенном тексте. ``` diff --git a/ru-ru/xml-ru.html.markdown b/ru-ru/xml-ru.html.markdown index bf3f22b0..34e17b9b 100644 --- a/ru-ru/xml-ru.html.markdown +++ b/ru-ru/xml-ru.html.markdown @@ -15,7 +15,7 @@ XML - это язык разметки, предназначенный для х * XML-Синтаксис ```xml -<!-- Комментарии в XML выглядят вот так --> +<!-- Это комментарий. --> <?xml version="1.0" encoding="UTF-8"?> <bookstore> diff --git a/ru-ru/yaml-ru.html.markdown b/ru-ru/yaml-ru.html.markdown index 6eb580d9..693848fc 100644 --- a/ru-ru/yaml-ru.html.markdown +++ b/ru-ru/yaml-ru.html.markdown @@ -2,7 +2,7 @@ language: yaml filename: learnyaml-ru.yaml contributors: -- [Adam Brenecki, 'https://github.com/adambrenecki'] +- [Leigh Brenecki, 'https://github.com/adambrenecki'] - [Suhas SG, 'https://github.com/jargnar'] translators: - [Sergei Babin, 'https://github.com/serzn1'] @@ -12,7 +12,7 @@ lang: ru-ru YAML как язык сериализации данных предназначен прежде всего для использования людьми. Это строгое надмножество JSON с добавлением синтаксически значимых переносов строк и -отступов как в Python. Тем не менее, в отличие от Python, YAML запрещает +отступов как в Python. Тем не менее в отличие от Python, YAML запрещает использование табов для отступов. ```yaml @@ -24,7 +24,7 @@ YAML как язык сериализации данных предназнач # Скалярные величины # ###################### -# Наш корневой объект (который продолжается для всего документа) будет соответствовать +# Наш корневой объект (который продолжается до конца документа) будет соответствовать # типу map, который в свою очередь соответствует словарю, хешу или объекту в других языках. key: value another_key: Другое значение ключа. @@ -53,7 +53,7 @@ literal_block: | Любые строки с большим отступом сохраняют остатки своего отступа - эта строка будет содержать дополнительно 4 пробела. folded_style: > - Весь блок этого тектса будет значением 'folded_style', но в данном случае + Весь блок этого текста будет значением 'folded_style', но в данном случае все символы новой строки будут заменены пробелами. Пустые строки будут преобразованы в перенос строки. @@ -76,7 +76,7 @@ a_nested_map: 0.25: a float key # Ключи также могут быть сложными, например многострочными. -# Мы используем ? с последующим пробелом чтобы обозначить начало сложного ключа. +# Мы используем ? с последующим пробелом, чтобы обозначить начало сложного ключа. ? | Этот ключ который содержит несколько строк @@ -124,7 +124,7 @@ base: &base name: Каждый будет иметь одинаковое имя # Регулярное выражение << называется ключом объединения независимо от типа языка. -# Он используется чтобы показать что все ключи одного или более словарей должны быть +# Он используется, чтобы показать что все ключи одного или более словарей должны быть # добавлены в текущий словарь. foo: &foo @@ -185,5 +185,5 @@ set2: ### Больше информации -+ [YAML оффициальный вебсайт](http://yaml.org/) ++ [YAML официальный вебсайт](http://yaml.org/) + [YAML онлайн валидатор](http://www.yamllint.com/) diff --git a/ru-ru/zfs-ru.html.markdown b/ru-ru/zfs-ru.html.markdown new file mode 100644 index 00000000..46a3fbb5 --- /dev/null +++ b/ru-ru/zfs-ru.html.markdown @@ -0,0 +1,406 @@ +--- +category: tool +tool: zfs +contributors: + - ["sarlalian", "http://github.com/sarlalian"] + - ["A1EF", "https://github.com/A1EF"] +filename: LearnZfs-ru.txt +translators: + - ["A1EF", "https://github.com/A1EF"] +lang: ru-ru +--- + + +[ZFS](http://open-zfs.org/wiki/Main_Page) +представляет собой переосмысление системы хранения данных, комбинирующее в едином инструменте +традиционные файловые системы и системы управления томами. ZFS обладает некоторой специфичной +терминологией, которая отличает её от более традиционных систем хранения данных, однако имеет +отличный набор возможностей, акцентированных на удобстве использования системными администраторами. + + +## Концепции ZFS + +### Виртуальные устройства + +Виртуальное устройство (VDEV) подобно устройству RAID, представляемого RAID-контроллером. +Есть несколько типов виртуальных устройств (VDEV), которые предлагают различные преимущества, +включая отказоустойчивость и скорость доступа. В основном виртуальные устройства (VDEV) +предоставляют лучшую отказоустойчивость и безопасность, нежели RAID-контроллеры. Не рекомендуется +использовать установку RAID с ZFS, поскольку ZFS рассчитывает непосредственно управлять дисками. + +Типы виртуальных устройств (VDEV) + +* mirror (поддерживается n-кратное зеркалирование) +* raidz + * raidz1 (1-диск четности, аналог RAID 5) + * raidz2 (2-диска четности, аналог RAID 6) + * raidz3 (3-диска четности, нет имеет аналогичного RAID-массива) +* disk +* file (не рекомендовано для промышленного применения из-за добавления нежелательного промежуточного слоя иной файловой системы) + +Ваши данные распределяются среди всех виртуальных устройств (VDEV), представленных в пуле хранения, +так что увеличив число виртуальных устройств (VDEV), вы увеличите количество IOPS. + +### Пулы хранения + +ZFS использует пулы хранения как абстракцию над нижним уровнем провайдера хранения (VDEV), позволяя вам отделить видимые пользователю +файловые системы от физического их размещения. + +### ZFS датасеты + +ZFS датасеты подобны традиционным файловым системам, но имеют гораздо больше возможностей, обеспечивающих обилие преимуществ ZFS. +Датасеты поддерживают [Copy on Write](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8), снапшоты, квоты, сжатие и дедубликацию. + + +### Ограничения + +Один каталог может содержать до 2^48 файлов, каждый до 16 эксабайт. Один пул хранения может содержать до 256 зеттабайт (2^78) данных +и может быть распределён по 2^64 устройствам. А один хост может иметь 2^64 пула хранения. Лимиты огромны. + + +## Команды + +### Пулы хранения + +Действия: + +* Просмотр +* Статус +* Удаление +* Получение/установка свойств + +Просмотр пулов + +```bash +# Создание пула типа raidz +$ zpool create zroot raidz1 gpt/zfs0 gpt/zfs1 gpt/zfs2 + +# Просмотр пулов +$ zpool list +NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT +zroot 141G 106G 35.2G - 43% 75% 1.00x ONLINE - + +# Просмотр детализованной информации о конкретном пуле +$ zpool list -v zroot +NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT +zroot 141G 106G 35.2G - 43% 75% 1.00x ONLINE - + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 141G 106G 35.2G - 43% 75% +``` + +Статус пулов + +```bash +# Получение информации о статусе пулов +$ zpool status + pool: zroot + state: ONLINE + scan: scrub repaired 0 in 2h51m with 0 errors on Thu Oct 1 07:08:31 2015 +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 ONLINE 0 0 0 + +errors: No known data errors + +# Скрабинг пула для исправления любых ошибок +$ zpool scrub zroot +$ zpool status -v zroot + pool: zroot + state: ONLINE + scan: scrub in progress since Thu Oct 15 16:59:14 2015 + 39.1M scanned out of 106G at 1.45M/s, 20h47m to go + 0 repaired, 0.04% done +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + gptid/c92a5ccf-a5bb-11e4-a77d-001b2172c655 ONLINE 0 0 0 + +errors: No known data errors +``` + +Свойства пулов + +```bash + +# Получение свойств пула, свойства могут быть заданы пользователем или системой. +$ zpool get all zroot +NAME PROPERTY VALUE SOURCE +zroot size 141G - +zroot capacity 75% - +zroot altroot - default +zroot health ONLINE - +... + +# Установка значения свойства пула +$ zpool set comment="Storage of mah stuff" zroot +$ zpool get comment +NAME PROPERTY VALUE SOURCE +tank comment - default +zroot comment Storage of mah stuff local +``` + +Удаление пула + +```bash +$ zpool destroy test +``` + + +### Датасеты + +Действия: + +* Создание +* Просмотр +* Переименование +* Удаление +* Получение/установка свойств + +Создание датасетов + +```bash +# Создание датасета +$ zfs create zroot/root/data +$ mount | grep data +zroot/root/data on /data (zfs, local, nfsv4acls) + +# Создание дочернего датасета +$ zfs create zroot/root/data/stuff +$ mount | grep data +zroot/root/data on /data (zfs, local, nfsv4acls) +zroot/root/data/stuff on /data/stuff (zfs, local, nfsv4acls) + + +# Создание тома +$ zfs create -V zroot/win_vm +$ zfs list zroot/win_vm +NAME USED AVAIL REFER MOUNTPOINT +zroot/win_vm 4.13G 17.9G 64K - +``` + +Просмотр датасетов + +```bash +# Просмотр всех датасетов +$ zfs list +NAME USED AVAIL REFER MOUNTPOINT +zroot 106G 30.8G 144K none +zroot/ROOT 18.5G 30.8G 144K none +zroot/ROOT/10.1 8K 30.8G 9.63G / +zroot/ROOT/default 18.5G 30.8G 11.2G / +zroot/backup 5.23G 30.8G 144K none +zroot/home 288K 30.8G 144K none +... + +# Просмотр конкретного датасета +$ zfs list zroot/home +NAME USED AVAIL REFER MOUNTPOINT +zroot/home 288K 30.8G 144K none + +# Просмотр снапшотов +$ zfs list -t snapshot +zroot@daily-2015-10-15 0 - 144K - +zroot/ROOT@daily-2015-10-15 0 - 144K - +zroot/ROOT/default@daily-2015-10-15 0 - 24.2G - +zroot/tmp@daily-2015-10-15 124K - 708M - +zroot/usr@daily-2015-10-15 0 - 144K - +zroot/home@daily-2015-10-15 0 - 11.9G - +zroot/var@daily-2015-10-15 704K - 1.42G - +zroot/var/log@daily-2015-10-15 192K - 828K - +zroot/var/tmp@daily-2015-10-15 0 - 152K - +``` + +Переименование датасетов + +```bash +$ zfs rename zroot/root/home zroot/root/old_home +$ zfs rename zroot/root/new_home zroot/root/home +``` + +Удаление датасета + +```bash +# Датасеты не могут быть удалены, если у них имеются какие-то снапшоты +$ zfs destroy zroot/root/home +``` + +Получение / установка свойств датасета + +```bash +# Получение всех свойств +$ zfs get all zroot/usr/home +NAME PROPERTY VALUE SOURCE +zroot/home type filesystem - +zroot/home creation Mon Oct 20 14:44 2014 - +zroot/home used 11.9G - +zroot/home available 94.1G - +zroot/home referenced 11.9G - +zroot/home mounted yes - +... + +# Получения свойства для датасета +$ zfs get compression zroot/usr/home +NAME PROPERTY VALUE SOURCE +zroot/home compression off default + +# Установка значения свойства на датасете +$ zfs set compression=lz4 zroot/lamb + +# Получение значений выбранных свойств всех датасетов +$ zfs list -o name,quota,reservation +NAME QUOTA RESERV +zroot none none +zroot/ROOT none none +zroot/ROOT/default none none +zroot/tmp none none +zroot/usr none none +zroot/home none none +zroot/var none none +... +``` + + +### Снапшоты + +ZFS снапшоты -- одна из очень важных особенностей zfs + +* Место, которое они занимают, равно разнице данных между файловой системой и её снапшотом +* Время создания занимает считанные секунды +* Восстановление настолько быстро, насколько позволяет вам запись данных +* Они очень просты в автоматизации + +Действия: + +* Создание +* Удаление +* Переименование +* Получение доступа к снапшотам +* Отправка / Получение +* Клонирование + + +Создание снапшотов + +```bash +# Создание снапшота единственного датасета +zfs snapshot zroot/home/sarlalian@now + +# Создание снапшота для родительского и дочерних датасетов +$ zfs snapshot -r zroot/home@now +$ zfs list -t snapshot +NAME USED AVAIL REFER MOUNTPOINT +zroot/home@now 0 - 26K - +zroot/home/sarlalian@now 0 - 259M - +zroot/home/alice@now 0 - 156M - +zroot/home/bob@now 0 - 156M - +... +``` + +Удаление снапшотов + +```bash +# Как удалить снапшот +$ zfs destroy zroot/home/sarlalian@now + +# Удаление снапшота в родительском и дочерних датасетах +$ zfs destroy -r zroot/home/sarlalian@now + +``` + +Переименование снапшотов + +```bash +# Переименование снапшота +$ zfs rename zroot/home/sarlalian@now zroot/home/sarlalian@today +$ zfs rename zroot/home/sarlalian@now today + +$ zfs rename -r zroot/home@now @yesterday +``` + +Получение доступа к спапшотам + +```bash +# CD в каталог снапшота +$ cd /home/.zfs/snapshot/ +``` + +Отправка и получение + +```bash +# Сохранение снапшота в файл +$ zfs send zroot/home/sarlalian@now | gzip > backup_file.gz + +# Отправка снапшота в другой датасет +$ zfs send zroot/home/sarlalian@now | zfs recv backups/home/sarlalian + +# Отправка снапшота на удаленный хост +$ zfs send zroot/home/sarlalian@now | ssh root@backup_server 'zfs recv zroot/home/sarlalian' + +# Отправка полного датасета со снапшотами на новый хост +$ zfs send -v -R zroot/home@now | ssh root@backup_server 'zfs recv zroot/home' +``` + +Клонирование снапшотов + +```bash +# Клонирование снапшота +$ zfs clone zroot/home/sarlalian@now zroot/home/sarlalian_new + +# Повышение клона, чтобы он больше не зависел от снапшота +$ zfs promote zroot/home/sarlalian_new +``` + +### Собираем всё вместе + +Нижеследующий скрипт использует FreeBSD, jails и ZFS для автоматизации +подготовки чистой копии стейджинговой базы mysql с живой реплики слейв-ноды. + +```bash +#!/bin/sh + +echo "==== Остановка стейджингового сервера баз данных ====" +jail -r staging + +echo "==== Очистка существующих стейджингового сервера и снапшота ====" +zfs destroy -r zroot/jails/staging +zfs destroy zroot/jails/slave@staging + +echo "==== Фиксация базы на слейве ====" +echo "FLUSH TABLES WITH READ LOCK;" | /usr/local/bin/mysql -u root -pmyrootpassword -h slave + +echo "==== Сохранение снапшота файлов базы слейва как zroot/jails/slave@staging ====" +zfs snapshot zroot/jails/slave@staging + +echo "==== Запуск слейв-ноды сервера баз данных ====" +jail -c slave + +echo "==== Клонирование снапшота слейва на стейджинговый сервер ====" +zfs clone zroot/jails/slave@staging zroot/jails/staging + +echo "==== Установка конфига стейджингово mysql ====" +mv /jails/staging/usr/local/etc/my.cnf /jails/staging/usr/local/etc/my.cnf.slave +cp /jails/staging/usr/local/etc/my.cnf.staging /jails/staging/usr/local/etc/my.cnf + +echo "==== Настройка стейджингового файла rc.conf ====" +mv /jails/staging/etc/rc.conf.local /jails/staging/etc/rc.conf.slave +mv /jails/staging/etc/rc.conf.staging /jails/staging/etc/rc.conf.local + +echo "==== Запуск стейджингово сервера баз данных ====" +jail -c staging + +echo "==== Отключение синхронизации стейджинговой базы с мастером ====" +echo "STOP SLAVE;" | /usr/local/bin/mysql -u root -pmyrootpassword -h staging +echo "RESET SLAVE;" | /usr/local/bin/mysql -u root -pmyrootpassword -h staging +``` + + +### Почитать дополнительно + +* [BSDNow's Crash Course on ZFS](http://www.bsdnow.tv/tutorials/zfs) +* [FreeBSD Handbook on ZFS](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/zfs.html) +* [BSDNow's Crash Course on ZFS](http://www.bsdnow.tv/tutorials/zfs) +* [Oracle's Tuning Guide](http://www.oracle.com/technetwork/articles/servers-storage-admin/sto-recommended-zfs-settings-1951715.html) +* [OpenZFS Tuning Guide](http://open-zfs.org/wiki/Performance_tuning) +* [FreeBSD ZFS Tuning Guide](https://wiki.freebsd.org/ZFSTuningGuide) diff --git a/ruby.html.markdown b/ruby.html.markdown index d77672ab..8e5f924a 100644 --- a/ruby.html.markdown +++ b/ruby.html.markdown @@ -23,6 +23,15 @@ contributors: ```ruby # This is a comment +=begin +This is a multi-line comment. +The beginning line must start with "=begin" +and the ending line must start with "=end". + +You can do this, or start each line in +a multi-line comment with the # character. +=end + # In Ruby, (almost) everything is an object. # This includes numbers... 3.class #=> Integer @@ -172,6 +181,9 @@ array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] # Arrays can contain different types of items. [1, 'hello', false] #=> [1, "hello", false] +# You might prefer %w instead of quotes +%w[foo bar baz] #=> ["foo", "bar", "baz"] + # Arrays can be indexed. # From the front... array[0] #=> 1 @@ -247,7 +259,7 @@ else 'else, also optional' end -# If a condition controls invokation of a single statement rather than a block of code +# If a condition controls invocation of a single statement rather than a block of code # you can use postfix-if notation warnings = ['Patronimic is missing', 'Address too short'] puts("Some warnings occurred:\n" + warnings.join("\n")) if !warnings.empty? @@ -315,6 +327,11 @@ puts doubled puts array #=> [1,2,3,4,5] +# another useful syntax is .map(&:method) +a = ["FOO", "BAR", "BAZ"] +a.map { |s| s.downcase } #=> ["foo", "bar", "baz"] +a.map(&:downcase) #=> ["foo", "bar", "baz"] + # Case construct grade = 'B' @@ -410,7 +427,7 @@ def guests(&block) end # The 'call' method on the Proc is similar to calling 'yield' when a block is -# present. The arguments passed to 'call' will be forwarded to the block as arugments. +# present. The arguments passed to 'call' will be forwarded to the block as arguments. guests { |n| "You have #{n} guests." } # => "You have 4 guests." @@ -421,6 +438,16 @@ def guests(*array) array.each { |guest| puts guest } end +# There is also the shorthand block syntax. It's most useful when you need +# to call a simple method on all array items. +upcased = ['Watch', 'these', 'words', 'get', 'upcased'].map(&:upcase) +puts upcased +#=> ["WATCH", "THESE", "WORDS", "GET", "UPCASED"] + +sum = [1, 2, 3, 4, 5].reduce(&:+) +puts sum +#=> 15 + # Destructuring # Ruby will automatically destructure arrays on assignment to multiple variables. @@ -643,4 +670,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/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide. -- [Try Ruby](http://tryruby.org) - Learn the basic of Ruby programming language, interactive in the browser. +- [Try Ruby](https://try.ruby-lang.org/) - Learn the basic of Ruby programming language, interactive in the browser. diff --git a/rust.html.markdown b/rust.html.markdown index 92794e69..526d20d5 100644 --- a/rust.html.markdown +++ b/rust.html.markdown @@ -1,5 +1,5 @@ --- -language: rust +language: Rust contributors: - ["P1start", "http://p1start.github.io/"] filename: learnrust.rs @@ -22,7 +22,7 @@ currently available in the nightly builds. Rust has adopted a train-based releas model with regular releases every six weeks. Rust 1.1 beta was made available at the same time of the release of Rust 1.0. -Although Rust is a relatively low-level language, Rust has some functional +Although Rust is a relatively low-level language, it has some functional concepts that are generally found in higher-level languages. This makes Rust not only fast, but also easy and efficient to code in. @@ -30,6 +30,9 @@ Rust not only fast, but also easy and efficient to code in. // This is a comment. Line comments look like this... // and extend multiple lines like this. +/* Block comments + /* can be nested. */ */ + /// Documentation comments look like this and support markdown notation. /// # Examples /// @@ -89,11 +92,16 @@ fn main() { println!("{} {}", f, x); // 1.3 hello world // A `String` – a heap-allocated string + // Stored as a `Vec<u8>` and always hold a valid UTF-8 sequence, + // which is not null terminated. let s: String = "hello world".to_string(); // A string slice – an immutable view into another string - // The string buffer can be statically allocated like in a string literal - // or contained in another object (in this case, `s`) + // This is basically an immutable pair of pointers to a string – it doesn’t + // actually contain the contents of a string, just a pointer to + // the begin and a pointer to the end of a string buffer, + // statically allocated or contained in another object (in this case, `s`). + // The string slice is like a view `&[u8]` into `Vec<T>`. let s_slice: &str = &s; println!("{} {}", s, s_slice); // hello world hello world @@ -176,13 +184,19 @@ fn main() { impl<T> Foo<T> { // Methods take an explicit `self` parameter - fn get_bar(self) -> T { + fn bar(&self) -> &T { // self is borrowed + &self.bar + } + fn bar_mut(&mut self) -> &mut T { // self is mutably borrowed + &mut self.bar + } + fn into_bar(self) -> T { // here self is consumed self.bar } } let a_foo = Foo { bar: 1 }; - println!("{}", a_foo.get_bar()); // 1 + println!("{}", a_foo.bar()); // 1 // Traits (known as interfaces or typeclasses in other languages) // @@ -199,6 +213,21 @@ fn main() { let another_foo = Foo { bar: 1 }; println!("{:?}", another_foo.frobnicate()); // Some(1) + // Function pointer types // + + fn fibonacci(n: u32) -> u32 { + match n { + 0 => 1, + 1 => 1, + _ => fibonacci(n - 1) + fibonacci(n - 2), + } + } + + type FunctionPointer = fn(u32) -> u32; + + let fib : FunctionPointer = fibonacci; + println!("Fib: {}", fib(4)); // 5 + ///////////////////////// // 3. Pattern matching // ///////////////////////// @@ -230,7 +259,7 @@ fn main() { // `for` loops/iteration let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } diff --git a/sass.html.markdown b/sass.html.markdown index 224db80e..860e550a 100644 --- a/sass.html.markdown +++ b/sass.html.markdown @@ -16,7 +16,7 @@ This tutorial is written using SCSS. If you're already familiar with CSS3, you'll be able to pick up Sass relatively quickly. It does not provide any new styling properties but rather the tools to write your CSS more efficiently and make maintenance much easier. -```sass +```scss //Single line comments are removed when Sass is compiled to CSS. diff --git a/scala.html.markdown b/scala.html.markdown index c7a8842e..bb20f624 100644 --- a/scala.html.markdown +++ b/scala.html.markdown @@ -252,7 +252,7 @@ weirdSum(2, 4) // => 16 // The return keyword exists in Scala, but it only returns from the inner-most // def that surrounds it. // WARNING: Using return in Scala is error-prone and should be avoided. -// It has no effect on anonymous functions. For example: +// It has no effect on anonymous functions. For example here you may expect foo(7) should return 17 but it returns 7: def foo(x: Int): Int = { val anonFunc: Int => Int = { z => if (z > 5) @@ -260,9 +260,10 @@ def foo(x: Int): Int = { else z + 2 // This line is the return value of anonFunc } - anonFunc(x) // This line is the return value of foo + anonFunc(x) + 10 // This line is the return value of foo } +foo(7) // => 7 ///////////////////////////////////////////////// // 3. Flow Control @@ -301,7 +302,7 @@ do { // Recursion is the idiomatic way of repeating an action in Scala (as in most // other functional languages). // Recursive functions need an explicit return type, the compiler can't infer it. -// Here it's Unit, which is analagous to a `void` return type in Java +// Here it's Unit, which is analogous to a `void` return type in Java def showNumbersInRange(a: Int, b: Int): Unit = { print(a) if (a < b) @@ -480,7 +481,7 @@ class SaintBernard extends Dog { def bite = false } -scala> b +scala> val b = new SaintBernard res0: SaintBernard = SaintBernard@3e57cd70 scala> b.breed res1: String = Saint Bernard @@ -598,7 +599,7 @@ List("Dom", "Bob", "Natalia") foreach println s.map(sq) -val sSquared = s. map(sq) +val sSquared = s.map(sq) sSquared.filter(_ < 10) @@ -716,7 +717,7 @@ import scala.collection.immutable.{Map => _, Set => _, _} // Java classes can also be imported. Scala syntax can be used import java.swing.{JFrame, JWindow} -// Your programs entry point is defined in a scala file using an object, with a +// Your program's entry point is defined in a scala file using an object, with a // single method, main: object Application { def main(args: Array[String]): Unit = { diff --git a/sed.html.markdown b/sed.html.markdown new file mode 100644 index 00000000..3e6d8fc8 --- /dev/null +++ b/sed.html.markdown @@ -0,0 +1,285 @@ +--- +category: tool +tool: sed +filename: learnsed.sed +contributors: + - ["Diomidis Spinellis", "https://www.spinellis.gr"] + +--- + +__Sed__ is a standard tool on every POSIX-compliant UNIX system. +It's like an editor, such as Vim, Visual Studio Code, Atom, or Sublime. +However, rather than typing the commands interactively, you +provide them on the command line or in a file. + +_Sed_'s advantages over an interactive editor is that it can be easily +used to automate text processing tasks, and that it can process +efficiently huge (terabyte-sized) files. +It can perform more complex tasks than _grep_ and for many text +processing tasks its commands are much shorter than what you would +write in _awk_, _Perl_, or _Python_. + +_Sed_ works by reading a line of text (by default from its standard +input, unless some files are specified as arguments), processing +it with the specified commands, and then outputting the result +on its standard output. +You can suppress the default output by specifying the `-n` command-line +argument. + +```perl +#!/usr/bin/sed -f +# Files that begin with the above line and are given execute permission +# can be run as regular scripts. + +# Comments are like this. + +# Commands consist of a single letter and many can be preceded +# by a specification of the lines to which they apply. + +# Delete the input's third line. +3d + +# The same command specified the command line as an argument to sed: +# sed 3d + +# For many commands the specification can consist of two addresses, +# which select an inclusive range. +# Addresses can be specified numerically ($ is the last line) or through +# regular expressions delimited by /. + +# Delete lines 1-10 +1,10d + +# Lines can also be specified as regular expressions, delimited by /. + +# Delete empty lines. +/^$/d + +# Delete blocks starting with SPOILER-BEGIN and ending with SPOILER-END. +/SPOILER-BEGIN/,/SPOILER-END/d + +# A command without an address is applied to all lines. + +# List lines in in a visually unambiguous form (e.g. tab appears as \t). +l + +# A command prefixed by ! will apply to non-matching lines. +# Keep only lines starting with a #. +/^#/!d + +# Below are examples of the most often-used commands. + +# Substitute the first occurence in a line of John with Mary. +s/John/Mary/ + +# Remove all underscore characters (global substitution). +s/_//g + +# Remove all HTML tags. +s/<[^>]*>//g + +# In the replacement string & is the regular expression matched. + +# Put each line inside double quotes. +s/.*/"&"/ + +# In the matched regular expression \(pattern\) is used to store +# a pattern into a buffer. +# In the replacement string \1 refers to the first pattern, \2 to the second +# and so on. \u converts the following character to uppercase \l to lowercase. + +# Convert snake_case_identifiers into camelCaseIdentifiers. +s/_\(.\)/\u\1/g + + +# The p (print) command is typically used together with the -n +# command-line option, which disables the print by default functionality. +# Output all lines between ``` and ```. +/```/,/```/p + + +# The y command maps characters from one set to another. +# Swap decimal and thousand separators (1,234,343.55 becomes 1.234.343,55). +y/.,/,./ + +# Quit after printing the line starting with END. +/^END/q + +# You can stop reading here, and still get 80% of sed's benefits. +# Below are examples of how you can specify multiple sed commands. + +# You can apply multiple commands by separating them with a newline or +# a semicolon. + +# Delete the first and the last line. +1d +$d + +# Delete the first and the last line. +1d;$d + + +# You can group commands in { } blocks. + +# Convert first line to uppercase and print it. +1 { + s/./\u&/g + p +} + +# Convert first line to uppercase and print it (less readable one-liner). +1{s/./\u&/g;p;} + + +# You can also stop reading here, if you're not interested in creating +# sed script files. + +# Below are more advanced commands. You typically put these in a file +# rather than specify them on a command line. If you have to use +# many of these commands in a script, consider using a general purpose +# scripting language, such as Python or Perl. + +# Append a line containing "profile();" after each line ending with ";". +/;$/a\ +profile(); + +# Insert a line containing "profile();" before each line ending with ";". +/;$/i\ +profile(); + +# Change each line text inside REDACTED blocks into [REDACTED]. +/REDACTED-BEGIN/,/REDACTED-END/c\ +[REDACTED] + +# Replace the tag "<ourstyle>" by reading and outputting the file style.css. +/<ourstyle>/ { + r style.css + d +} + +# Change each line inside REDACTED blocks into [REDACTED]. +# Also write (append) a copy of the redacted text in the file redacted.txt. +/REDACTED-BEGIN/,/REDACTED-END/ { + w redacted.txt + c\ + [REDACTED] +} + +# All operations described so far operate on a buffer called "pattern space". +# In addition, sed offers another buffer called "hold space". +# The following commands operate on the two, and can be used to keep +# state or combine multiple lines. + +# Replace the contents of the pattern space with the contents of +# the hold space. +g + +# Append a newline character followed by the contents of the hold +# space to the pattern space. +G + +# Replace the contents of the hold space with the contents of the +# pattern space. +h + +# Append a newline character followed by the contents of the +# pattern space to the hold space. +H + +# Delete the initial segment of the pattern space through the first +# newline character and start the next cycle. +D + +# Replace the contents of the pattern space with the contents of +# the hold space. +g + +# Append a newline character followed by the contents of the hold +# space to the pattern space. +G + +# Replace the contents of the hold space with the contents of the +# pattern space. +h + +# Append a newline character followed by the contents of the +# pattern space to the hold space. +H + +# Write the pattern space to the standard output if the default +# output has not been suppressed, and replace the pattern space +# with the next line of input. +n + +# Append the next line of input to the pattern space, using an +# embedded newline character to separate the appended material from +# the original contents. Note that the current line number +# changes. +N + +# Write the pattern space, up to the first newline character to the +# standard output. +P + +# Swap the contents of the pattern and hold spaces. +x + +# Here is a complete example of some of the buffer commands. +# Move the file's first line to its end. +1 { + h + d +} + +$ { + p + x +} + + +# Three sed commands influence a script's control flow + +# Name this script position "my_label", to which the "b" and +# "t" commands may branch. +:my_label + +# Continue executing commands from the position of my_label. +b my_label + +# Branch to the end of the script. +b + +# Branch to my_label if any substitutions have been made since the most +# recent reading of an input line or execution of a "t" (test) function. +t my_label + +# Here is a complete example of branching +# Join lines that end with a backspace into a single space-separated one + +# Name this position "loop" +: loop +# On lines ending with a backslash +/\\$/ { + # Read the next line and append it to the pattern space + N + # Substitute backslash newline with a space + s/\\\n/ / + # Branch to the top for testing this line's ending + b loop +} +``` + +Further Reading: + +* [The Open Group: sed - stream editor](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html) + The POSIX standard regarding sed. + Follow this for maximum portability. +* [FreeBSD sed -- stream editor](https://www.freebsd.org/cgi/man.cgi?query=sed&sektion=&n=1) + The BSD manual page. + This version of sed runs on BSD systems and macOS. +* [Project GNU: sed, a stream editor](https://www.gnu.org/software/sed/manual/sed.html) + The GNU manual page. GNU sed is found on most Linux systems. +* [Lee E. McMahon: SED -- A Non-interactive Text Editor](https://wolfram.schneider.org/bsd/7thEdManVol2/sed/sed.pdf) + The original sed documentation +* [A collection of sed resources](http://sed.sourceforge.net/) +* [The sed FAQ](http://sed.sourceforge.net/sedfaq.html) diff --git a/set-theory.html.markdown b/set-theory.html.markdown new file mode 100644 index 00000000..144b4bbf --- /dev/null +++ b/set-theory.html.markdown @@ -0,0 +1,134 @@ +--- +category: Algorithms & Data Structures +name: Set theory +contributors: + - ["Andrew Ryan Davis", "https://github.com/AndrewDavis1191"] +--- + +Set theory is a branch of mathematics that studies sets, their operations, and their properties. + +* A set is a collection of disjoint items. + +## Basic symbols + +### Operators +* the union operator, `∪`, pronounced "cup", means "or"; +* the intersection operator, `∩`, pronounced "cap", means "and"; +* the exclusion operator, `\`, means "without"; +* the complement operator, `'`, means "the inverse of"; +* the cross operator, `×`, means "the Cartesian product of". + +### Qualifiers +* the colon, `:`, or the vertical bar `|` qualifiers are interchangeable and mean "such that"; +* the membership qualifier, `∈`, means "belongs to"; +* the subset qualifier, `⊆`, means "is a subset of"; +* the proper subset qualifier, `⊂`, means "is a subset of but is not equal to". + +### Canonical sets +* `∅`, the empty set, i.e. the set containing no items; +* `ℕ`, the set of all natural numbers; +* `ℤ`, the set of all integers; +* `ℚ`, the set of all rational numbers; +* `ℝ`, the set of all real numbers. + +There are a few caveats to mention regarding the canonical sets: +1. Even though the empty set contains no items, the empty set is a subset of itself (and indeed every other set); +2. Mathematicians generally do not universally agree on whether zero is a natural number, and textbooks will typically explicitly state whether or not the author considers zero to be a natural number. + + +### Cardinality + +The cardinality, or size, of a set is determined by the number of items in the set. The cardinality operator is given by a double pipe, `|...|`. + +For example, if `S = { 1, 2, 4 }`, then `|S| = 3`. + +### The Empty Set +* The empty set can be constructed in set builder notation using impossible conditions, e.g. `∅ = { x : x ≠ x }`, or `∅ = { x : x ∈ N, x < 0 }`; +* the empty set is always unique (i.e. there is one and only one empty set); +* the empty set is a subset of all sets; +* the cardinality of the empty set is 0, i.e. `|∅| = 0`. + +## Representing sets + +### Literal Sets + +A set can be constructed literally by supplying a complete list of objects contained in the set. For example, `S = { a, b, c, d }`. + +Long lists may be shortened with ellipses as long as the context is clear. For example, `E = { 2, 4, 6, 8, ... }` is clearly the set of all even numbers, containing an infinite number of objects, even though we've only explicitly written four of them. + +### Set Builder + +Set builder notation is a more descriptive way of constructing a set. It relies on a _subject_ and a _predicate_ such that `S = { subject : predicate }`. For example, + +``` +A = { x : x is a vowel } = { a, e, i, o, u } +B = { x : x ∈ N, x < 10 } = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } +C = { x : x = 2k, k ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +Sometimes the predicate may "leak" into the subject, e.g. + +``` +D = { 2x : x ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +## Relations + +### Membership + +* If the value `a` is contained in the set `A`, then we say `a` belongs to `A` and represent this symbolically as `a ∈ A`. +* If the value `a` is not contained in the set `A`, then we say `a` does not belong to `A` and represent this symbolically as `a ∉ A`. + +### Equality + +* If two sets contain the same items then we say the sets are equal, e.g. `A = B`. +* Order does not matter when determining set equality, e.g. `{ 1, 2, 3, 4 } = { 2, 3, 1, 4 }`. +* Sets are disjoint, meaning elements cannot be repeated, e.g. `{ 1, 2, 2, 3, 4, 3, 4, 2 } = { 1, 2, 3, 4 }`. +* Two sets `A` and `B` are equal if and only if `A ⊆ B` and `B ⊆ A`. + +## Special Sets + +### The Power Set +* Let `A` be any set. The set that contains all possible subsets of `A` is called a "power set" and is written as `P(A)`. If the set `A` contains `n` elements, then `P(A)` contains `2^n` elements. + +``` +P(A) = { x : x ⊆ A } +``` + +## Set operations among two sets +### Union +Given two sets `A` and `B`, the union of the two sets are the items that appear in either `A` or `B`, written as `A ∪ B`. + +``` +A ∪ B = { x : x ∈ A ∪ x ∈ B } +``` + +### Intersection +Given two sets `A` and `B`, the intersection of the two sets are the items that appear in both `A` and `B`, written as `A ∩ B`. + +``` +A ∩ B = { x : x ∈ A, x ∈ B } +``` + +### Difference +Given two sets `A` and `B`, the set difference of `A` with `B` is every item in `A` that does not belong to `B`. + +``` +A \ B = { x : x ∈ A, x ∉ B } +``` + +### Symmetrical difference +Given two sets `A` and `B`, the symmetrical difference is all items among `A` and `B` that doesn't appear in their intersections. + +``` +A △ B = { x : ((x ∈ A) ∩ (x ∉ B)) ∪ ((x ∈ B) ∩ (x ∉ A)) } + +A △ B = (A \ B) ∪ (B \ A) +``` + +### Cartesian product +Given two sets `A` and `B`, the cartesian product between `A` and `B` consists of a set containing all combinations of items of `A` and `B`. + +``` +A × B = { (x, y) | x ∈ A, y ∈ B } +``` diff --git a/sing.html.markdown b/sing.html.markdown new file mode 100644 index 00000000..50b52390 --- /dev/null +++ b/sing.html.markdown @@ -0,0 +1,446 @@ +--- +name: Sing +category: language +language: Sing +filename: learnsing.sing +contributors: + - ["Maurizio De Girolami", "https://github.com/mdegirolami"] +--- + +The purpose of sing is to provide a simple, safe, fast language that +can be a good replacement for c++ for high performance applications. + +Sing is an easy choice because it compiles to human-quality readable c++. + +Because of that, if you work for a while with Sing and, at any time, you discover you don't like Sing anymore, you lose nothing of your work +because you are left with nice and clean c++ code. + +In some way you can also think Sing as a tool to write c++ in a way that enforces some best practices. + +```go +/* Multi- line comment. + /* It can be nested */ + Use it to remark-out part of the code. + It leaves no trace in the intermediate c++ code. + (sing translates into nice human readable c++) +*/ + +// Single line comment, can be placed only before a statement or declaration... +// ...or at the right of the first line of a statement or declaration. +// single line comments are kept into c++. +// +// here we declare if we need to use public declarations from other files. +// (in this case from files 'sio', 'sys') +requires "sio"; +requires "sys"; + +// +// A sing function declaration. +// All the declarations can be made public with the 'public' keyword. +// All the declarations start with a keyword specifying the type of declaration +// (in this case fn for function) then follows the name, the arguments and the +// return type. +// +// Each argument starts with a direction qualifyer (in, out, io) which tells if +// the argument is an input, an output or both... +// ...then follows the argument name and the type. +public fn singmain(in argv [*]string) i32 +{ + // print is from the sio file and sends a string to the console + sio.print("Hello World\n"); + + // type conversions are allowed in the form of <newtype>(expression). + sio.print(string(sum(5, 10)) + "\n"); + + // For clarity you can specify after an argument its name separated by ':'. + var result i32; + recursive_power(10:base, 3:exponent, result); + + // referred here to avoid a 'not used' error. + learnTypes(); + + // functions can only return a single value of some basic type. + return(0); +} + +// You can have as many arguments as you want, comma separated. +// You can also omit the 'in' direction qualifyer (it is the default). +fn sum(arg1 i32, arg2 i32) i32 +{ + // as 'fn' declares a function, 'let' declares a constant. + // With constants, if you place an initializer, you can omit the type. + let the_sum = arg1 + arg2; + + return(the_sum); +} + +// Arguments are passed by reference, which means that in the function body you +// use the argument names to refer to the passed variables. +// Example: all the functions in the recursion stack access the same 'result' +// variable, supplied by the singmain function. +fn recursive_power(base i32, exponent i32, out result i32) void +{ + if (exponent == 0) { + result = 1; + } else { + recursive_power(base, exponent - 1, result); + result *= base; + } +} + +//********************************************************** +// +// TYPES +// +//********************************************************** +fn learnTypes() void +{ + // the var keyword declares mutable variables + // in this case an UTF-8 encoded string + var my_name string; + + // ints of 8..64 bits size + var int0 i8; + var int1 i16; + var int2 i32; + var int3 i64; + + // uints + var uint0 u8; + var uint1 u16; + var uint2 u32; + var uint3 u64; + + // floats + var float0 f32; + var float1 f64; + + // complex + var cmplx0 c64; + var cmplx1 c128; + + cmplx0 = 0; + cmplx1 = 0; + + // and of course... + var bool0 bool; + + // type inference: by default constants are i32, f32, c64 + let an_int32 = 15; + let a_float32 = 15.0; + let a_complex = 15.0 + 3i; + let a_string = "Hello !"; + let a_bool = false; + + // To create constant of different types use a conversion-like syntax: + // NOTE: this is NOT a conversion. Just a type specification + let a_float64 = f64(5.6); + + // in a type definition [] reads as "array of" + // in the example []i32 => array of i32. + var intarray []i32 = {1, 2, 3}; + + // You can specify a length, else the length is given by the initializer + // the last initializer is replicated on the extra items + var sizedarray [10]i32 = {1, 2, 3}; + + // Specify * as the size to get a dynamic array (can change its length) + var dyna_array [*]i32; + + // you can append items to a vector invoking a method-like function on it. + dyna_array.push_back(an_int32); + + // getting the size of the array. sys.validate() is like assert in c + sys.validate(dyna_array.size() == 1); + + // a map that associates a number to a string. + // "map(x)..." reads "map with key of type x and value of type..." + var a_map map(string)i32; + + a_map.insert("one", 1); + a_map.insert("two", 2); + a_map.insert("three", 3); + let key = "two"; + + // note: the second argument of get_safe is the value to be returned + // when the key is not found. + sio.print("\nAnd the value is...: " + string(a_map.get_safe(key, -1))); + + // string concatenation + my_name = "a" + "b"; +} + +// an enum type can only have a value from a discrete set. +// can't be converted to/from int ! +enum Stages {first, second, last} + +// you can refer to enum values (to assign/compare them) +// specifying both the typename and tagname separated with the '.' operator +var current_stage = Stages.first; + + +//********************************************************** +// +// POINTERS +// +//********************************************************** + +// This is a factory for a dynamic vector. +// In a type declaration '*' reads 'pointer to..' +// so the return type is 'pointer to a vector of i32' +fn vectorFactory(first i32, last i32) *[*]i32 +{ + var buffer [*]i32; + + // fill + for (value in first : last) { + buffer.push_back(value); + } + + // The & operator returns the address of the buffer. + // You can only use & on local variables + // As you use & on a variable, that variable is allocated on the HEAP. + return(&buffer); +} + +fn usePointers() void +{ + var bufferptr = vectorFactory(0, 100); + + // you don't need to use the factory pattern to use pointers. + var another_buffer [*]i32; + var another_bufferptr = &another_buffer; + + // you can dereference a pointer with the * operator + // sys.validate is an assertion (causes a signal if the argument is false) + sys.validate((*bufferptr)[0] == 0); + + /* + // as all the pointers to a variable exit their scope the variable is + // no more accessible and is deleted (freed) + */ +} + +//********************************************************** +// +// CLASSES +// +//********************************************************** + +// This is a Class. The member variables can be directly initialized here +class AClass { +public: + var public_var = 100; // same as any other variable declaration + fn is_ready() bool; // same as any other function declaration + fn mut finalize() void; // destructor (called on object deletion) +private: + var private_var string; + + // Changes the member variables and must be marked as 'mut' (mutable) + fn mut private_fun(errmsg string) void; +} + +// How to declare a member function +fn AClass.is_ready() bool +{ + // inside a member function, members can be accessed thrugh the + // this keyword and the field selector '.' + return(this.public_var > 10); +} + +fn AClass.private_fun(errmsg string) void +{ + this.private_var = errmsg; +} + +// using a class +fn useAClass() void +{ + // in this way you create a variable of type AClass. + var instance AClass; + + // then you can access its members through the '.' operator. + if (instance.is_ready()) { + instance.public_var = 0; + } +} + +//********************************************************** +// +// INTERFACES +// +//********************************************************** + +// You can use polymorphism in sing defining an interface... +interface ExampleInterface { + fn mut eraseAll() void; + fn identify_myself() void; +} + +// and then creating classes which implement the interface +// NOTE: you don't need (and cannot) re-declare the interface functions +class Implementer1 : ExampleInterface { +private: + var to_be_erased i32 = 3; +public: + var only_on_impl1 = 0; +} + +class Implementer2 : ExampleInterface { +private: + var to_be_erased f32 = 3; +} + +fn Implementer1.eraseAll() void +{ + this.to_be_erased = 0; +} + +fn Implementer1.identify_myself() void +{ + sio.print("\nI'm the terrible int eraser !!\n"); +} + +fn Implementer2.eraseAll() void +{ + this.to_be_erased = 0; +} + +fn Implementer2.identify_myself() void +{ + sio.print("\nI'm the terrible float eraser !!\n"); +} + +fn interface_casting() i32 +{ + // upcasting is automatic (es: *Implementer1 to *ExampleInterface) + var concrete Implementer1; + var if_ptr *ExampleInterface = &concrete; + + // you can access interface members with (guess what ?) '.' + if_ptr.identify_myself(); + + // downcasting requires a special construct + // (see also below the conditional structures) + typeswitch(ref = if_ptr) { + case *Implementer1: return(ref.only_on_impl1); + case *Implementer2: {} + default: return(0); + } + + return(1); +} + +// All the loop types +fn loops() void +{ + // while: the condition must be strictly of boolean type + var idx = 0; + while (idx < 10) { + ++idx; + } + + // for in an integer range. The last value is excluded + // 'it' is local to the loop and must not be previously declared + for (it in 0 : 10) { + } + + // reverse direction + for (it in 10 : 0) { + } + + // configurable step. The loop stops when it's >= the final value + for (it in 0 : 100 step 3) { + } + + // with an auxiliary counter. + // The counter start always at 0 and increments by one at each iteration + for (counter, it in 3450 : 100 step -22) { + } + + // value assumes in turn all the values from array + var array [*]i32 = {0, 10, 100, 1000}; + for (value in array) { + } + + // as before with auxiliary counter + for (counter, value in array) { + } +} + +// All the conditional structures +interface intface {} +class c0_test : intface {public: fn c0stuff() void;} +class delegating : intface {} + +fn conditionals(in object intface, in objptr *intface) void +{ + let condition1 = true; + let condition2 = true; + let condition3 = true; + var value = 30; + + // condition1 must be a boolean. + if (condition1) { + ++value; // conditioned statement + } + + // you can chain conditions with else if + if (condition1) { + ++value; + } else if (condition2) { + --value; + } + + // a final else runs if any other condition is false + if (condition1) { + ++value; + } else if (condition2) { + --value; + } else { + value = 0; + } + + // based on the switch value selects a case statement + switch (value) { + case 0: sio.print("value is zero"); // a single statement ! + case 1: {} // do nothing + case 2: // falls through + case 3: sio.print("value is more than one"); + case 4: { // a block is a single statement ! + value = 0; + sio.print("how big !!"); + } + default: return; // if no one else matches + } + + // similar to a switch but selects a case based on argument type. + // - object must be a function argument of type interface. + // - the case types must be classes implementing the object interface. + // - in each case statement, ref assumes the class type of that case. + typeswitch(ref = object) { + case c0_test: ref.c0stuff(); + case delegating: {} + default: return; + } + + // - object must be an interface pointer. + // - the case types must be pointers to classes implementing the objptr interface. + // - in each case statement, ref assumes the class pointer type of that case. + typeswitch(ref = objptr) { + case *c0_test: { + ref.c0stuff(); + return; + } + case *delegating: {} + default: sio.print("unknown pointer type !!"); + } +} +``` + +## Further Reading + +[official Sing web site](https://mdegirolami.wixsite.com/singlang). + +If you want to play with sing you are recommended to download the vscode plugin. Please +follow the instructions at [Getting Started](https://mdegirolami.wixsite.com/singlang/copy-of-interfacing-sing-and-c-2) diff --git a/sk-sk/bash-sk.html.markdown b/sk-sk/bash-sk.html.markdown index e9d1490c..1b0f48d4 100644 --- a/sk-sk/bash-sk.html.markdown +++ b/sk-sk/bash-sk.html.markdown @@ -19,7 +19,7 @@ filename: LearnBash-sk.sh Bash je pomenovanie pre unix shell (príkazový interpreter), ktorý bol tiež distribuovaný ako shell pre GNU operačné systémy a ako predvolený -shell pre Linux a Mac OS X. +shell pre Linux a macOS. Takmer všetky príklady uvedené nižšie môžu byť súčasťou shell skriptu alebo vykonané priamo v shelli. diff --git a/sk-sk/elixir-sk.html.markdown b/sk-sk/elixir-sk.html.markdown index 2401f92e..c9522b49 100644 --- a/sk-sk/elixir-sk.html.markdown +++ b/sk-sk/elixir-sk.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] @@ -14,7 +14,7 @@ Elixir je moderný funkcionálny jazyk vytvorený nad Erlang VM (virtuálnym strojom). Je plne kompatibilný s Erlangom, ale ponúka viac štandardnú syntax a množstvo funkcií. -```Elixir +```elixir # Jednoriadkový komentár začína symbolom # @@ -24,7 +24,7 @@ a množstvo funkcií. # Pre spustenie Elixir shellu zadajte príkaz `iex` # Kompiláciu zdrojových kódov vykonáte príkazom `elixirc` -# Obe príkazy by sa už mali nachádzať v path pokiaľ ste nainštalovali elixir +# Obe príkazy by sa už mali nachádzať v path pokiaľ ste nainštalovali Elixir # správne. ## --------------------------- @@ -86,7 +86,7 @@ reťazec. <<?a, ?b, ?c>> #=> "abc" [?a, ?b, ?c] #=> 'abc' -# `?a` v elixire vráti ASCII číselnú reprezentáciu pre znak `a` +# `?a` v Elixir vráti ASCII číselnú reprezentáciu pre znak `a` ?a #=> 97 # Pre spájanie zoznamov sa používa `++`, pre binárne typy `<>` @@ -119,7 +119,7 @@ pohlavia.gillian #=> "žena" 5 * 2 #=> 10 10 / 2 #=> 5.0 -# V elixire operátor `/` vždy vráti float (reálne číslo). +# V Elixir operátor `/` vždy vráti float (reálne číslo). # Pre celočíselné delenie sa používa `div` div(10, 2) #=> 5 @@ -182,7 +182,7 @@ else end # Pamätáte sa na pattern matching? Mnoho štruktúr pre riadenie toku v -# elixire sa spoliehajú práve na pattern matching. +# Elixir sa spoliehajú práve na pattern matching. # `case` dovolí nám porovnať hodnotu oproti mnohým vzorom: case {:one, :two} do @@ -314,7 +314,7 @@ Geometria.oblast({:kruh, 3}) #=> 28.25999999999999801048 # Geometria.oblast({:kruh, "nie_je_cislo"}) #=> ** (FunctionClauseError) no function clause matching in Geometria.oblast/1 -# Vďaka nemeniteľnosti (immutability) je rekurzia významnou časťou elixiru +# Vďaka nemeniteľnosti (immutability) je rekurzia významnou časťou Elixir defmodule Rekurzia do def sumuj_zoznam([hlavicka | schvost], acc) do sumuj_zoznam(chvost, acc + hlavicka) @@ -389,7 +389,7 @@ end ## --------------------------- # Elixir sa pri konkurencii spolieha na Actor model. Všetko čo je -# potrebné na písanie konkuretných programov v elixire sú tri primitívy: +# potrebné na písanie konkuretných programov v Elixir sú tri primitívy: # spawning procesy, posielanie a prijímanie správ. # Na spustnenie nového procesu použijeme `spawn` funkciu, ktorá má ako diff --git a/sk-sk/git-sk.html.markdown b/sk-sk/git-sk.html.markdown index 21741406..1187abc5 100644 --- a/sk-sk/git-sk.html.markdown +++ b/sk-sk/git-sk.html.markdown @@ -139,6 +139,7 @@ $ git init --help ### ignoruj súbory Zámerne prestaneš sledovať súbor(y) a zložky. Typicky sa používa pre súkromné a dočasné súbory, ktoré by boli inak zdieľané v repozitári. + ```bash $ echo "temp/" >> .gitignore $ echo "private_key" >> .gitignore @@ -172,6 +173,7 @@ $ git add /cesta/k/súboru/HelloWorld.c # Môžeš použiť regulárne výrazy! $ git add ./*.java ``` + Tento príkaz len pridáva súbory do staging indexu, necommituje ich do repozitára. ### branch @@ -476,6 +478,7 @@ $ git reset 31f2bb1 # a zosúladí ju s pracovným adresárom (vymaže nekomitnuté zmeny). $ git reset --hard 31f2bb1 ``` + ### revert Vezme naspäť ("od-urobí") commit. Nezamieňaj s resetom, ktorý obnoví stav @@ -514,8 +517,6 @@ $ 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/) - * [Git - jednoducho](http://rogerdudler.github.io/git-guide/index.html) * [Pro Git](http://www.git-scm.com/book/en/v2) diff --git a/sk-sk/latex-sk.html.markdown.tex b/sk-sk/latex-sk.html.markdown index 5e2f9c7f..5e2f9c7f 100644 --- a/sk-sk/latex-sk.html.markdown.tex +++ b/sk-sk/latex-sk.html.markdown diff --git a/sk-sk/learn-latex-sk.tex b/sk-sk/learn-latex-sk.tex deleted file mode 100644 index 5cc7b11f..00000000 --- a/sk-sk/learn-latex-sk.tex +++ /dev/null @@ -1,209 +0,0 @@ -% Všetky komentáre začínajú s % -% Viac-riadkové komentáre sa nedajú urobiť - -% LaTeX NIE JE WYSIWY ("What You See Is What You Get") software ako MS Word, alebo OpenOffice Writer - -% Každý LaTeX príkaz začína s opačným lomítkom (\) - -% LaTeX dokumenty začínajú s definíciou typu kompilovaného dokumentu -% Ostatné typy sú napríklad kniha (book), správa (report), prezentácia (presentation), atď. -% Možnosti dokumentu sa píšu do [] zátvoriek. V tomto prípade tam upresňujeme veľkosť (12pt) fontu. -\documentclass[12pt]{article} - -% Ďalej definujeme balíčky, ktoré dokuemnt používa. -% Ak chceš zahrnúť grafiku, farebný text, či zdrojový kód iného jazyka, musíš rozšíriť možnosti LaTeXu dodatočnými balíčkami. -% Zahŕňam float a caption. Na podporu slovenčiny treba zahrnúť aj utf8 balíček. -\usepackage{caption} -\usepackage{float} -\usepackage[utf8]{inputenc} -% Tu môžme definovať ostatné vlastnosti dokumentu! -% Autori tohto dokumentu, "\\*" znamená "choď na nový riadok" -\author{Chaitanya Krishna Ande, Colton Kohnke \& Sricharan Chiruvolu, \\*Preklad: Terka Slanináková} -% Vygeneruje dnešný dátum -\date{\today} -\title{Nauč sa LaTeX za Y Minút!} -% Teraz môžme začať pracovať na samotnom dokumente. -% Všetko do tohto riadku sa nazýva "Preambula" ("The Preamble") -\begin{document} -% ak zadáme položky author, date a title, LaTeX vytvorí titulnú stranu. -\maketitle - -% Väčšina odborných článkov má abstrakt, na jeho vytvorenie môžeš použiť preddefinované príkazy. -% Ten by sa mal zobraziť v logickom poradí, teda po hlavičke, -% no pred hlavnými sekciami tela.. -% Tento príkaz je tiež dostupný v triedach article a report. -% Tzv. makro "abstract" je fixnou súčasťou LaTeXu, ak chceme použiť abstract -% a napísať ho po slovensky, musíme ho redefinovať nasledujúcim príkazom -\renewcommand\abstractname{Abstrakt} - -\begin{abstract} -LaTeX dokumentácia v LaTeXe! Aké netradičné riešenie cudzieho nápadu! -\end{abstract} - -% Príkazy pre sekciu sú intuitívne -% Všetky nadpisy sekcií sú pridané automaticky do obsahu. -\section{Úvod} -Čaute, volám sa Colton a spoločne sa pustíme do skúmania LaTeXu (toho druhého)! - -\section{Ďalšia sekcia} -Toto je text ďalšej sekcie. Myslím, že potrebuje podsekciu. - -\subsection{Toto je podsekcia} % Podsekcie sú tiež intuitívne. -Zdá sa mi, že treba ďalšiu. - -\subsubsection{Pytagoras} -To je ono! -\label{subsec:pytagoras} - -% Použitím '*' môžeme potlačiť zabudované číslovanie LaTeXu. -% Toto funguje aj na iné príkazy. -\section*{Toto je nečíslovaná sekcia} -Všetky číslované byť nemusia! - -\section{Nejaké poznámočky} -Zarovnávať veci tam, kde ich chceš mať, je všeobecne ľahké. Ak -potrebuješ \\ nový \\ riadok \\ pridaj \textbackslash\textbackslash do -zdrojového kódu. \\ - -\section{Zoznamy} -Zoznamy sú jednou z najjednoduchších vecí vôbec! Treba mi zajtra nakúpiť, urobím si zoznam. -\begin{enumerate} % "enumerate" spustí číslovanie prvkov. - % \item povie LaTeXu, ako že treba pripočítať 1 - \item Vlašský šalát. - \item 5 rožkov. - \item 3 Horalky. - % číslovanie môžeme pozmeniť použitím [] - \item[koľko?] Stredne veľkých guličkoviek. - - Ja už nie som položka zoznamu, no stále som časť "enumerate". - -\end{enumerate} % Všetky prostredia končia s "end". - -\section{Matika} - -Jedným z primárnych použití LaTeXu je písanie akademických, či technických prác. Zvyčajne za použitia matematiky a vedy. Podpora špeciálnych symbolov preto nemôže chýbať!\\ - -Matematika má veľa symbolov, omnoho viac, než by klávesnica mohla reprezentovať; -Množinové a relačné symboly, šípky, operátory a Grécke písmená sú len malou ukážkou.\\ - -Množiny a relácie hrajú hlavnú rolu v mnohých matematických článkoch. -Takto napíšeš, že niečo platí pre všetky x patriace do X, $\forall$ x $\in$ X. \\ -% Všimni si, že som pridal $ pred a po symboloch. Je to -% preto, lebo pri písaní sme v textovom móde, -% no matematické symboly existujú len v matematickom. -% Vstúpime doňho z textového práve '$' znamienkami. -% Platí to aj opačne. Premenná môže byť zobrazená v matematickom móde takisto. -% Do matematického módu sa dá dostať aj s \[\] - -\[a^2 + b^2 = c^2 \] - -Moje obľúbené Grécke písmeno je $\xi$. Tiež sa mi pozdávajú $\beta$, $\gamma$ a $\sigma$. -Ešte som neprišiel na Grécke písmeno, ktoré by LaTeX nepoznal! - -Operátory sú dôležitou súčasťou matematických dokumentov: -goniometrické funkcie ($\sin$, $\cos$, $\tan$), -logaritmy and exponenciálne výrazy ($\log$, $\exp$), -limity ($\lim$), atď. -majú pred-definované LaTeXové príkazy. -Napíšme si rovnicu, nech vidíme, ako to funguje: \\ - -$\cos(2\theta) = \cos^{2}(\theta) - \sin^{2}(\theta)$ - -Zlomky(Čitateľ-menovateľ) sa píšu v týchto formách: - -% 10 / 7 -$^{10}/_{7}$ - -% Relatívne komplexné zlomky sa píšu ako -% \frac{čitateľ}{menovateľ} -$\frac{n!}{k!(n - k)!}$ \\ - -Rovnice tiež môžeme zadať v "rovnicovom prostredí". - -% Takto funguje rovnicové prostredie -\begin{equation} % vstúpi do matematického módu - c^2 = a^2 + b^2. - \label{eq:pythagoras} % na odkazovanie -\end{equation} % všetky \begin príkazy musia mať konečný príkaz. - -Teraz môžeme odkázať na novovytvorenú rovnicu! -Rovn.~\ref{eq:pythagoras} je tiež známa ako Pytagorova Veta, ktorá je tiež predmetom Sekc.~\ref{subsec:pytagoras}. Odkazovať môžme na veľa vecí, napr na: čísla, rovnice, či sekcie. - -Sumácie a Integrály sa píšu príkazmi sum a int: - -% Niektoré prekladače LaTeXu sa môžu sťažovať na prázdne riadky (ak tam sú) -% v rovnicovom prostredí. -\begin{equation} - \sum_{i=0}^{5} f_{i} -\end{equation} -\begin{equation} - \int_{0}^{\infty} \mathrm{e}^{-x} \mathrm{d}x -\end{equation} - -\section{Obrázky} - -Vloženie obrázku môže byť zložitejšie. Ja si vždy možnosti vloženia pozerám pre každý obrázok. -\renewcommand\figurename{Obrázok} -\begin{figure}[H] % H značí možnosť zarovnania. - \centering % nacentruje obrázok na stránku - % Vloží obrázok na 80% šírky stránky. - %\includegraphics[width=0.8\linewidth]{right-triangle.png} - % Zakomentované kvôli kompilácií, použi svoju predstavivosť :). - \caption{Pravouhlý trojuholník so stranami $a$, $b$, $c$} - \label{fig:right-triangle} -\end{figure} -% Opäť, fixné makro "table" nahradíme slovenskou tabuľkou. Pokiaľ preferuješ table, nasledujúci riadok nepridávaj -\renewcommand\tablename{Tabuľka} - -\subsection{Tabuľky} -Tabuľky sa vkládajú podobne ako obrázky. - -\begin{table}[H] - \caption{Nadpis tabuľky.} - % zátvorky: {} hovoria ako sa vykreslí každý riadok. - % Toto si nikdy nepamätám a vždy to musím hľadať. Všetko. Každý. Jeden. Raz! - \begin{tabular}{c|cc} - Číslo & Priezvisko & Krstné meno \\ % Stĺpce sú rozdelené $ - \hline % horizontálna čiara - 1 & Ladislav & Meliško \\ - 2 & Eva & Máziková - \end{tabular} -\end{table} - -% \section{Hyperlinks} % Už čoskoro :) - -\section{Prikáž LaTeXu nekompilovať (napr. Zdrojový Kód)} -Povedzme, že chceme do dokumentu vložiť zdrojový kód, budeme musieť LaTeXu povedať, nech sa ho nesnaží skompilovať, ale nech s ním pracuje ako s textom. -Toto sa robí vo verbatim prostredí. - -% Tiež sú na to špeciálne balíčky, (napr. minty, lstlisting, atď.) -% ale verbatim je to najzákladnejšie, čo môžeš použiť. -\begin{verbatim} - print("Hello World!") - a%b; pozri! Vo verbatime môžme použiť % znamienka. - random = 4; #priradené randomným hodom kockou -\end{verbatim} - -\section{Kompilácia} - -Už by bolo načase túto nádheru skompilovať a zhliadnuť jej úžasnú úžasnosť v podobe LaTeX pdfka, čo povieš? -(áno, tento dokument sa musí kompilovať). \\ -Cesta k finálnemu dokumentu pomocou LaTeXu pozostáva z nasledujúcich krokov: - \begin{enumerate} - \item Napíš dokument v čistom texte (v "zdrojáku"). - \item Skompiluj zdroják na získanie pdfka. - Kompilácia by mala vyzerať nasledovne (v Linuxe): \\ - \begin{verbatim} - $pdflatex learn-latex.tex learn-latex.pdf - \end{verbatim} - \end{enumerate} - -Mnoho LaTeX editorov kombinuje Krok 1 a Krok 2 v jednom prostredí. Krok 1 teda uvidíš, krok 2 už nie. -Ten sa deje za oponou. Kompilácia v 2. kroku sa postará o produkciu dokumentu v tebou zadanom formáte. - -\section{Koniec} - -To je zatiaľ všetko! - -% koniec dokumentu -\end{document} diff --git a/sl-si/asciidoc-sl.html.markdown b/sl-si/asciidoc-sl.html.markdown index 52f30fbd..84bb85a1 100644 --- a/sl-si/asciidoc-sl.html.markdown +++ b/sl-si/asciidoc-sl.html.markdown @@ -6,7 +6,7 @@ contributors: translators: - ["Filip Štamcar", "https://github.com/filips123"] lang: sl-si -filename: asciidoc-sl.md +filename: asciidoc-sl.adoc --- AsciiDoc je označevalni jezik, ki je podoben Markdownu in ga je mogoče uporabiti za vse od knjig do spletnih dnevnikov. Jezik, ki ga je leta 2002 ustvaril Stuart Rackham, je preprost, vendar omogoča veliko prilagoditev. diff --git a/smalltalk.html.markdown b/smalltalk.html.markdown index ae7ecb0e..9c2e870e 100644 --- a/smalltalk.html.markdown +++ b/smalltalk.html.markdown @@ -2,16 +2,15 @@ language: Smalltalk filename: smalltalk.st contributors: - - ["Jigyasa Grover", "https://github.com/jigyasa-grover"] + - ["Jigyasa Grover", "https://jigyasa-grover.github.io"] - ["tim Rowledge", "tim@rowledge.org"] --- +<blockquote>Every effort has been made in the preparation of this material to ensure the accuracy and completeness of the information presented. However, no guarantee is given nor responsibility taken for errors or omissions. In case of any error, questions or suggestions on reach out to me at <a href="https://jigyasa-grover.github.io" target="_blank">jigyasa-grover.github.io</a> or drop me an e-mail at <a href="mailto:grover.jigyasa1@gmail.com" target="_blank">grover[dot]jigyasa1[at]gmail.com</a>.</blockquote> - Smalltalk is a fully object-oriented, dynamically typed, reflective programming language with no 'non-object' types. - Smalltalk was created as the language to underpin the "new world" of computing exemplified by "human–computer symbiosis." - It was designed and created in part for educational use, more so for constructionist learning, at the Learning Research Group (LRG) of Xerox PARC by Alan Kay, Dan Ingalls, Adele Goldberg, Ted Kaehler, Scott Wallace, and others during the 1970s. -`Feedback highly appreciated! Reach me at [@jigyasa_grover](https://twitter.com/jigyasa_grover) or send me an e-mail at grover.jigyasa1@gmail.com.` - ## The Basics ### Everything is an object @@ -22,7 +21,7 @@ Yes, everything. Integers are instances of one of the numeric classes. Classes a - The system knows the class of the object receiving a message and looks up the message in that class's list of methods. If it is not found, the lookup continues in the super class until either it is found or the root of the classes is reached and there is still no relevant method. - If a suitable method is found the code is run, and the same process keeps on going with all the methods sent by that method and so on forever. - If no suitable method is found an exception is raised, which typically results in a user interface notifier to tell the user that the message was not understood. It is entirely possible to catch the exception and do something to fix the problem, which might range from 'ignore it' to 'load some new packages for this class and try again'. -- A method (more strictly an instance of the class CompiledMethod) is a chunk of Smalltalk code that has been compiled into bytecodes. Executing methods start at the beginning and return to the sender when a return is encountered (we use ^ to signify 'return the follwing object') or the end of the code is reached, in which case the current object running the code is returned. +- A method (more strictly an instance of the class CompiledMethod) is a chunk of Smalltalk code that has been compiled into bytecodes. Executing methods start at the beginning and return to the sender when a return is encountered (we use ^ to signify 'return the following object') or the end of the code is reached, in which case the current object running the code is returned. ### Simple syntax Smalltalk has a simple syntax with very few rules. @@ -30,7 +29,8 @@ The most basic operation is to send a message to an object `anObject aMessage` There are three sorts of messages -- unary - a single string that may be several words conjoined in what we call camelcase form, with no arguments. For example 'size', 'reverseBytes', 'convertToLargerFormatPixels' + +- unary - a single symbol that may be several words conjoined in what we call camelcase form, with no arguments. For example 'size', 'reverseBytes', 'convertToLargerFormatPixels' - binary - a small set of symbols of the sort often used for arithmetic operations in most languages, requiring a single argument. For example '+', '//', '@'. We do not use traditional arithmetic precedence, something to keep an eye on. - keyword - the general form where multiple arguments can be passed. As with the unary form we use camelcase to join words together but arguments are inserted in the midst of the message with colons used to separate them lexically. For example 'setTemperature:', 'at:put:', 'drawFrom:to:lineWidth:fillColor:' @@ -38,26 +38,28 @@ There are three sorts of messages `result := myObject doSomethingWith: thatObject` We are sending the message 'doSomethingWith:' to myObject. This happens to be a message that has a single argument but that's not important yet. 'myObject' is a 'MyExampleClass' instance so the system looks at the list of messages understood by MyExampleClass + - beClever -- doWierdThing: +- doWeirdThing: - doSomethingWith In searching we see what initially looks like a match - but no, it lacks the final colon. So we find the super class of MyExampleClass - BigExampleClass. Which has a list of known messages of its own + - beClever - doSomethingWith: - buildCastleInAir - annoyUserByDoing: -We find a proper exact match and start to execute the code -``` +We find a proper exact match and start to execute the code: + +```smalltalk doSomethingWith: argumentObject -"A comment about what this code is meant to do and any known limitations, problems, where it might be further documented etc" -self size > 4 ifTrue: [^argumentObject sizeRelatingTo: self]. + self size > 4 ifTrue: [^argumentObject sizeRelatingTo: self]. ``` Everything here except the `^` involves sending more messages. Event the `ifTrue:` that you might think is a language control structure is just Smalltalk code. -We start by sending `size` to `self`. `self` is the object currently running the code - so in this case it is the myObject we started with. `size` is a very common message that we might anticipate tells us something about how big an object is; you could look it up with the Smalltalk tools very simply. The result we get is then sent the message `>` with the plain old integer 4 (which is an object too; no strange primitive types to pollute the system here) and nobody should be surprised the `>` is a comparison that answers true or false. That boolean (which is actually a Boolean object in Smalltalk) is sent the message `ifTrue:` with the block of code between the `[]` as its argument; obvioulsy a true boolean might be expected to run that block of code and a false to ignore it. +We start by sending `size` to `self`. `self` is the object currently running the code - so in this case it is the myObject we started with. `size` is a very common message that we might anticipate tells us something about how big an object is; you could look it up with the Smalltalk tools very simply. The result we get is then sent the message `>` with the plain old integer 4 (which is an object too; no strange primitive types to pollute the system here) and nobody should be surprised the `>` is a comparison that answers true or false. That boolean (which is actually a Boolean object in Smalltalk) is sent the message `ifTrue:` with the block of code between the `[]` as its argument; obviously a true boolean might be expected to run that block of code and a false to ignore it. If the block is run then we do some more message sending to the argument object and noting the `^` we return the answer back to our starting point and it gets assigned to `result`. If the block is ignored we seem to run out of code and so `self` is returned and assigned to `result`. @@ -94,7 +96,7 @@ Taken from [Smalltalk Cheatsheet](http://www.angelfire.com/tx4/cus/notes/smallta `"Period (.) is the statement separator. Not required on last line of a method"` #### Transcript: -``` +```smalltalk Transcript clear. "clear to transcript window" Transcript show: 'Hello World'. "output string in transcript window" Transcript nextPutAll: 'Hello World'. "output string in transcript window" @@ -108,26 +110,17 @@ Transcript endEntry. "flush the output buffer" ``` #### Assignment: -``` +```smalltalk | x y | x _ 4. "assignment (Squeak) <-" x := 5. "assignment" x := y := z := 6. "compound assignment" x := (y := 6) + 1. x := Object new. "bind to allocated instance of a class" -x := 123 class. "discover the object class" -x := Integer superclass. "discover the superclass of a class" -x := Object allInstances. "get an array of all instances of a class" -x := Integer allSuperclasses. "get all superclasses of a class" -x := 1.2 hash. "hash value for object" -y := x copy. "copy object" -y := x shallowCopy. "copy object (not overridden)" -y := x deepCopy. "copy object and instance vars" -y := x veryDeepCopy. "complete tree copy using a dictionary" ``` #### Constants: -``` +```smalltalk | b | b := true. "true constant" b := false. "false constant" @@ -147,7 +140,7 @@ x := #('abc' 2 $a). "mixing of types allowed" ``` #### Booleans: -``` +```smalltalk | b x y | x := 1. y := 2. b := (x = y). "equals" @@ -168,7 +161,7 @@ b := (x < 5) xor: (y > 1). "test if one true and other false" b := 5 between: 3 and: 12. "between (inclusive)" b := 123 isKindOf: Number. "test if object is class or subclass of" b := 123 isMemberOf: SmallInteger. "test if object is type of class" -b := 123 respondsTo: sqrt. "test if object responds to message" +b := 123 respondsTo: #sqrt. "test if object responds to message" b := x isNil. "test if object is nil" b := x isZero. "test if number is zero" b := x positive. "test if number is positive" @@ -185,7 +178,7 @@ b := $A isLowercase. "test if lower case character" ``` #### Arithmetic expressions: -``` +```smalltalk | x | x := 6 + 3. "addition" x := 6 - 3. "subtraction" @@ -241,7 +234,7 @@ x := 100 atRandom. "quick random number" ``` #### Bitwise Manipulation: -``` +```smalltalk | b x | x := 16rFF bitAnd: 16r0F. "and bits" x := 16rF0 bitOr: 16r0F. "or bits" @@ -257,7 +250,7 @@ b := 16rFF noMask: 16r0F. "test if all bits set in mask clear in recei ``` #### Conversion: -``` +```smalltalk | x | x := 3.99 asInteger. "convert number to integer (truncates in Squeak)" x := 3.99 asFraction. "convert number to fraction" @@ -281,7 +274,7 @@ x := 15 storeStringBase: 16. - `^`expression terminates block & method (exits all nested blocks) - blocks intended for long term storage should not contain `^` -``` +```smalltalk | x y z | x := [ y := 1. z := 2. ]. x value. "simple block usage" x := [ :argOne :argTwo | argOne, ' and ' , argTwo.]. "set up block with argument passing" @@ -304,7 +297,7 @@ Transcript show: (x value: 'First' value: 'Second'); cr. "use block with argu - private (methods private to class) - instance-creation (class methods for creating instance) -``` +```smalltalk | x | x := 2 sqrt. "unary message" x := 2 raisedTo: 10. "keyword message" @@ -319,7 +312,7 @@ x := 3 + 2; * 100. "result=300. Sends message to same ``` #### Conditional Statements: -``` +```smalltalk | x | x > 10 ifTrue: [Transcript show: 'ifTrue'; cr]. "if then" x > 10 ifFalse: [Transcript show: 'ifFalse'; cr]. "if else" @@ -359,7 +352,7 @@ result := (switch at: $B) value. ``` #### Iteration statements: -``` +```smalltalk | x y | x := 4. y := 1. [x > 0] whileTrue: [x := x - 1. y := y * 2]. "while true loop" @@ -371,7 +364,7 @@ x timesRepeat: [y := y * 2]. "times repeat loop (i := 1 to x ``` #### Character: -``` +```smalltalk | x y | x := $A. "character assignment" y := x isLowercase. "test if lower case" @@ -391,10 +384,10 @@ y := $A max: $B. ``` #### Symbol: -``` +```smalltalk | b x y | x := #Hello. "symbol assignment" -y := 'String', 'Concatenation'. "symbol concatenation (result is string)" +y := #Symbol, #Concatenation. "symbol concatenation (result is string)" b := x isEmpty. "test if symbol is empty" y := x size. "string size" y := x at: 2. "char at location" @@ -413,7 +406,7 @@ y := x asSet. "convert symbol to set collect ``` #### String: -``` +```smalltalk | b x y | x := 'This is a string'. "string assignment" x := 'String', 'Concatenation'. "string concatenation" @@ -447,7 +440,7 @@ Fixed length collection - ByteArray: Array limited to byte elements (0-255) - WordArray: Array limited to word elements (0-2^32) -``` +```smalltalk | b x y sum max | x := #(4 3 2 1). "constant array" x := Array with: 5 with: 4 with: 3 with: 2. "create array with up to 4 elements" @@ -490,7 +483,7 @@ y := x asSet. "convert to set collection" #### OrderedCollection: acts like an expandable array -``` +```smalltalk | b x y sum max | x := OrderedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" @@ -537,7 +530,7 @@ y := x asSet. "convert to set collection" #### SortedCollection: like OrderedCollection except order of elements determined by sorting criteria -``` +```smalltalk | b x y sum max | x := SortedCollection with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" @@ -583,7 +576,7 @@ y := x asSet. "convert to set collection" #### Bag: like OrderedCollection except elements are in no particular order -``` +```smalltalk | b x y sum max | x := Bag with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := Bag new. "allocate collection" @@ -619,7 +612,7 @@ like Bag except duplicates not allowed #### IdentitySet: uses identity test (== rather than =) -``` +```smalltalk | b x y sum max | x := Set with: 4 with: 3 with: 2 with: 1. "create collection with up to 4 elements" x := Set new. "allocate collection" @@ -649,7 +642,7 @@ y := x asSet. "convert to set collection" ``` #### Interval: -``` +```smalltalk | b x y sum max | x := Interval from: 5 to: 10. "create interval object" x := 5 to: 10. @@ -679,7 +672,7 @@ y := x asSet. "convert to set collection" ``` #### Associations: -``` +```smalltalk | x y | x := #myVar->'hello'. y := x key. @@ -690,7 +683,7 @@ y := x value. #### IdentityDictionary: uses identity test (== rather than =) -``` +```smalltalk | b x y | x := Dictionary new. "allocate collection" x add: #a->4; @@ -757,7 +750,7 @@ Smalltalk removeKey: #CMRDictionary ifAbsent: []. "remove user dictionary fr ``` #### Internal Stream: -``` +```smalltalk | b x ios | ios := ReadStream on: 'Hello read stream'. ios := ReadStream on: 'Hello read stream' from: 1 to: 5. @@ -785,7 +778,7 @@ b := ios atEnd. ``` #### FileStream: -``` +```smalltalk | b x ios | ios := FileStream newFileNamed: 'ios.txt'. ios nextPut: $H; cr. @@ -805,7 +798,7 @@ ios close. ``` #### Date: -``` +```smalltalk | x y | x := Date today. "create date for today" x := Date dateAndTimeNow. "create date from current time/date" @@ -839,7 +832,7 @@ b := (x <= Date today). "comparison" ``` #### Time: -``` +```smalltalk | x y | x := Time now. "create time from current time" x := Time dateAndTimeNow. "create time from current time/date" @@ -859,7 +852,7 @@ b := (x <= Time now). "comparison" ``` #### Point: -``` +```smalltalk | x y | x := 200@100. "obtain a new point" y := x x. "x coordinate" @@ -884,12 +877,12 @@ x := 20@5 dotProduct: 10@2. "sum of product (x1*x2 + y1*y2)" ``` #### Rectangle: -``` +```smalltalk Rectangle fromUser. ``` #### Pen: -``` +```smalltalk | myPen | Display restoreAfter: [ Display fillWhite. @@ -917,7 +910,7 @@ Display height. "get display height" ``` #### Dynamic Message Calling/Compiling: -``` +```smalltalk | receiver message result argument keyword1 keyword2 argument1 argument2 | "unary message" @@ -957,7 +950,7 @@ result := (Message ``` #### Class/Meta-Class: -``` +```smalltalk | b x | x := String name. "class name" x := String category. "organization category" @@ -990,7 +983,7 @@ Object withAllSubclasses size. "get total number of class entries" ``` #### Debugging: -``` +```smalltalk | a b x | x yourself. "returns receiver" String browse. "browse specified class" @@ -1013,8 +1006,13 @@ Transcript show: a, b; cr. ``` #### Miscellaneous -``` +```smalltalk | x | +x := 1.2 hash. "hash value for object" +y := x copy. "copy object" +y := x shallowCopy. "copy object (not overridden)" +y := x deepCopy. "copy object and instance vars" +y := x veryDeepCopy. "complete tree copy using a dictionary" "Smalltalk condenseChanges." "compress the change file" x := FillInTheBlank request: 'Prompt Me'. "prompt user for input" Utilities openCommandKeyHelp diff --git a/solidity.html.markdown b/solidity.html.markdown index cc719ec7..d40536b4 100644 --- a/solidity.html.markdown +++ b/solidity.html.markdown @@ -6,6 +6,7 @@ contributors: - ["Joseph Chow", ""] - ["Bhoomtawath Plinsut", "https://github.com/varshard"] - ["Shooter", "https://github.com/liushooter"] + - ["Patrick Collins", "https://gist.github.com/PatrickAlphaC"] --- Solidity lets you program on [Ethereum](https://www.ethereum.org/), a @@ -18,7 +19,7 @@ state variables, functions, and common data types. Contract-specific features include modifier (guard) clauses, event notifiers for listeners, and custom global variables. -Some Ethereum contract examples include crowdfunding, voting, and blind auctions. +Some Ethereum contract examples include crowdfunding, voting, [decentralized finance](https://defipulse.com/), and blind auctions. There is a high risk and high cost of errors in Solidity code, so you must be very careful to test and slowly rollout. WITH THE RAPID CHANGES IN ETHEREUM, THIS DOCUMENT IS UNLIKELY TO STAY UP TO @@ -32,6 +33,66 @@ popular design patterns. As Solidity and Ethereum are under active development, experimental or beta features are typically marked, and subject to change. Pull requests welcome. +# Working with Remix and Metamask + +One of the easiest ways to build, deploy, and test solidity code is by using the: + +1. [Remix Web IDE](https://remix.ethereum.org/) +2. [Metamask wallet](https://metamask.io/). + +To get started, [download the Metamask Browser Extension](https://metamask.io/). + +Once installed, we will be working with Remix. The below code will be pre-loaded, but before we head over there, let's look at a few tips to get started with remix. Load it all by [hitting this link](https://remix.ethereum.org/#version=soljson-v0.6.6+commit.6c089d02.js&optimize=false&evmVersion=null&gist=f490c0d51141dd0515244db40bbd0c17&runs=200). + +1. Choose the Solidity compiler + + + +2. Open the file loaded by that link + + + +3. Compile the file + + + +4. Deploy + + + +5. Play with contracts + + + +You've deployed your first contract! Congrats! + +You can test out and play with the functions defined. Check out the comments to learn about what each does. + + +## Working on a testnet + +Deploying and testing on a testnet is the most accurate way to test your smart contracts in solidity. +To do this let's first get some testnet ETH from the Kovan testnet. + +[Pop into this Gitter Channel](https://gitter.im/kovan-testnet/faucet) and drop your metamask address in. + +In your metamask, you'll want to change to the `Kovan` testnet. + + + +You'll be given some free test Ethereum. Ethereum is needed to deploy smart contracts when working with a testnet. + +In the previous example, we didn't use a testnet, we deployed to a fake virtual environment. +When working with a testnet, we can actually see and interact with our contracts in a persistent manner. + +To deploy to a testnet, on the `#4 Deploy` step, change your `environment` to `injected web3`. +This will use whatever network is currently selected in your metamask as the network to deploy to. + + + +For now, please continue to use the `Javascript VM` unless instructed otherwise. When you deploy to a testnet, metamask will pop up to ask you to "confirm" the transaction. Hit yes, and after a delay, you'll get the same contract interface at the bottom of your screen. + + ```javascript // First, a simple Bank contract // Allows deposits, withdrawals, and balance checks @@ -40,7 +101,7 @@ features are typically marked, and subject to change. Pull requests welcome. /* **** START EXAMPLE **** */ // Declare the source file compiler version -pragma solidity ^0.4.19; +pragma solidity ^0.6.6; // Start with Natspec comment (the three slashes) // used for documentation - and as descriptive data for UI elements/actions @@ -67,7 +128,7 @@ contract SimpleBank { // CapWords event LogDepositMade(address accountAddress, uint amount); // Constructor, can receive one or many variables here; only one allowed - function SimpleBank() public { + constructor() public { // msg provides details about the message that's sent to the contract // msg.sender is contract caller (address of contract creator) owner = msg.sender; @@ -84,7 +145,7 @@ contract SimpleBank { // CapWords // no "this." or "self." required with state variable // all values set to data type's initial value by default - LogDepositMade(msg.sender, msg.value); // fire event + emit LogDepositMade(msg.sender, msg.value); // fire event return balances[msg.sender]; } @@ -92,7 +153,7 @@ contract SimpleBank { // CapWords /// @notice Withdraw ether from bank /// @dev This does not return any excess ether sent to it /// @param withdrawAmount amount you want to withdraw - /// @return The balance remaining for the user + /// @return remainingBal function withdraw(uint withdrawAmount) public returns (uint remainingBal) { require(withdrawAmount <= balances[msg.sender]); @@ -153,7 +214,8 @@ assert(c >= a); // assert tests for internal invariants; require is used for use // https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol -// No random functions built in, use other contracts for randomness +// No random functions built in, you can get a pseduo-random number by hashing the current blockhash, or get a truly random number using something like Chainlink VRF. +// https://docs.chain.link/docs/get-a-random-number // Type casting int x = int(b); @@ -216,7 +278,7 @@ f(22); // call // Delete can be called on most types // (does NOT destroy value, but sets value to 0, the initial value) -uint x = 5; +delete x; // Destructuring/Tuples @@ -233,7 +295,7 @@ names.length; // get length names.length = 1; // lengths can be set (for dynamic arrays in storage only) // multidimensional array -uint x[][5]; // arr with 5 dynamic array elements (opp order of most languages) +uint[][5] x; // arr with 5 dynamic array elements (opp order of most languages) // Dictionaries (any type to any other type) mapping (string => uint) public balances; @@ -326,7 +388,7 @@ block.gasLimit(); storage['abc'] = 'def'; // maps 256 bit words to 256 bit words -// 4. FUNCTIONS AND MORE +// 5. FUNCTIONS AND MORE // A. Functions // Simple function function increment(uint x) returns (uint) { @@ -334,13 +396,13 @@ function increment(uint x) returns (uint) { return x; } -// Functions can return many arguments, and by specifying returned arguments -// name don't need to explicitly return +// Functions can return many arguments, +// and by specifying returned arguments name explicit return is not needed function increment(uint x, uint y) returns (uint x, uint y) { x += 1; y += 1; } -// Call previous functon +// Call previous function uint (a,b) = increment(1,1); // 'view' (alias for 'constant') @@ -373,7 +435,7 @@ function increment(uint x) view returns (uint x) { // Functions hoisted - and can assign a function to a variable function a() { var z = b; - b(); + z(); } function b() { @@ -432,9 +494,9 @@ Coin.LogSent().watch({}, '', function(error, result) { // '_' (underscore) often included as last line in body, and indicates // function being called should be placed there modifier onlyAfter(uint _time) { require (now >= _time); _; } -modifier onlyOwner { require(msg.sender == owner) _; } +modifier onlyOwner { require(msg.sender == owner); _; } // commonly used with state machines -modifier onlyIfStateA (State currState) { require(currState == State.A) _; } +modifier onlyIfStateA (State currState) { require(currState == State.A); _; } // Append right after function declaration function changeOwner(newOwner) @@ -584,11 +646,37 @@ reveal(100, "mySecret"); // All data to start of time is stored in blockchain, so // anyone can observe all previous data and changes -// D. Cron Job +// D. Oracles and External Data +// Oracles are ways to interact with your smart contracts outside the blockchain. +// They are used to get data from the real world, send post requests, to the real world +// or vise versa. + +// Time-based implementations of contracts are also done through oracles, as +// contracts need to be directly called and can not "subscribe" to a time. +// Due to smart contracts being decentralized, you also want to get your data +// in a decentralized manner, otherwise you run into the centralized risk that +// smart contract design matter prevents. + +// To easiest way get and use pre-boxed decentralized data is with Chainlink Data Feeds +// https://docs.chain.link/docs/get-the-latest-price +// We can reference on-chain reference points that have already been aggregated by +// multiple sources and delivered on-chain, and we can use it as a "data bank" +// of sources. + +// You can see other examples making API calls here: +// https://docs.chain.link/docs/make-a-http-get-request + +// And you can of course build your own oracle network, just be sure to know +// how centralized vs decentralized your application is. + +// Setting up oracle networks yourself + +// E. Cron Job // Contracts must be manually called to handle time-based scheduling; can create external // code to regularly ping, or provide incentives (ether) for others to +// -// E. Observer Pattern +// F. Observer Pattern // An Observer Pattern lets you register as a subscriber and // register a function which is called by the oracle (note, the oracle pays // for this action to be run) @@ -626,25 +714,28 @@ contract SomeOracle { // Now, your client contract can addSubscriber by importing SomeOracleCallback // and registering with Some Oracle -// F. State machines +// G. State machines // see example below for State enum and inState modifier +``` +Work with the full example below using the [`Javascript VM` in remix here.](https://remix.ethereum.org/#version=soljson-v0.6.6+commit.6c089d02.js&optimize=false&evmVersion=null&gist=3d12cd503dcedfcdd715ef61f786be0b&runs=200) +```javascript // *** EXAMPLE: A crowdfunding example (broadly similar to Kickstarter) *** // ** START EXAMPLE ** // CrowdFunder.sol -pragma solidity ^0.4.19; +pragma solidity ^0.6.6; /// @title CrowdFunder /// @author nemild contract CrowdFunder { // Variables set on create by creator address public creator; - address public fundRecipient; // creator may be different than recipient + address payable public fundRecipient; // creator may be different than recipient, and must be payable uint public minimumToRaise; // required to tip, else everyone gets refund string campaignUrl; - byte constant version = 1; + byte version = "1"; // Data structures enum State { @@ -654,7 +745,7 @@ contract CrowdFunder { } struct Contribution { uint amount; - address contributor; + address payable contributor; } // State variables @@ -684,10 +775,10 @@ contract CrowdFunder { _; } - function CrowdFunder( + function crowdFund( uint timeInHoursForFundraising, - string _campaignUrl, - address _fundRecipient, + string memory _campaignUrl, + address payable _fundRecipient, uint _minimumToRaise) public { @@ -712,7 +803,7 @@ contract CrowdFunder { ); totalRaised += msg.value; - LogFundingReceived(msg.sender, msg.value, totalRaised); + emit LogFundingReceived(msg.sender, msg.value, totalRaised); checkIfFundingCompleteOrExpired(); return contributions.length - 1; // return id @@ -736,7 +827,7 @@ contract CrowdFunder { public inState(State.Successful) { - fundRecipient.transfer(this.balance); + fundRecipient.transfer(address(this).balance); LogWinnerPaid(fundRecipient); } @@ -766,6 +857,11 @@ contract CrowdFunder { } // ** END EXAMPLE ** +``` + +Some more functions. + +```javascript // 10. OTHER NATIVE FUNCTIONS // Currency units @@ -837,18 +933,27 @@ someContractAddress.callcode('function_name'); ## Additional resources - [Solidity Docs](https://solidity.readthedocs.org/en/latest/) +- [Chainlink Beginner Tutorials](https://docs.chain.link/docs/beginners-tutorial) - [Smart Contract Best Practices](https://github.com/ConsenSys/smart-contract-best-practices) - [Superblocks Lab - Browser based IDE for Solidity](https://lab.superblocks.com/) - [EthFiddle - The JsFiddle for Solidity](https://ethfiddle.com/) - [Browser-based Solidity Editor](https://remix.ethereum.org/) - [Gitter Solidity Chat room](https://gitter.im/ethereum/solidity) - [Modular design strategies for Ethereum Contracts](https://docs.erisindustries.com/tutorials/solidity/) +- [Chainlink Documentation](https://docs.chain.link/docs/getting-started) + +## Smart Contract Development Frameworks +- [Hardhat](https://hardhat.org/) +- [Brownie](https://github.com/eth-brownie/brownie) +- [Truffle](https://www.trufflesuite.com/) ## Important libraries -- [Zeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/): Libraries that provide common contract patterns (crowdfuding, safemath, etc) +- [Zeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts): Libraries that provide common contract patterns (crowdfuding, safemath, etc) +- [Chainlink](https://github.com/smartcontractkit/chainlink): Code that allows you to interact with external data ## Sample contracts - [Dapp Bin](https://github.com/ethereum/dapp-bin) +- [Defi Example](https://github.com/PatrickAlphaC/chainlink_defi) - [Solidity Baby Step Contracts](https://github.com/fivedogit/solidity-baby-steps/tree/master/contracts) - [ConsenSys Contracts](https://github.com/ConsenSys/dapp-store-contracts) - [State of Dapps](http://dapps.ethercasts.com/) @@ -862,6 +967,7 @@ someContractAddress.callcode('function_name'); - [Solidity Style Guide](http://solidity.readthedocs.io/en/latest/style-guide.html): Ethereum's style guide is heavily derived from Python's [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guide. ## Editors +- [Remix](https://remix.ethereum.org/) - [Emacs Solidity Mode](https://github.com/ethereum/emacs-solidity) - [Vim Solidity](https://github.com/tomlion/vim-solidity) - Editor Snippets ([Ultisnips format](https://gist.github.com/nemild/98343ce6b16b747788bc)) diff --git a/sorbet.html.markdown b/sorbet.html.markdown new file mode 100644 index 00000000..9c2e809b --- /dev/null +++ b/sorbet.html.markdown @@ -0,0 +1,1040 @@ +--- +language: sorbet +filename: learnsorbet.rb +contributors: + - ["Jeremy Kaplan", "https://jdkaplan.dev"] +--- + +Sorbet is a type checker for Ruby. It adds syntax for method signatures that +enable both static and runtime type checking. + +The easiest way to see it in action is in the playground at +[sorbet.run](https://sorbet.run). + +Try copying in one of the sections below! Each top-level `class` or `module` +is independent from the others. + +```ruby +# Every file should have a "typed sigil" that tells Sorbet how strict to be +# during static type checking. +# +# Strictness levels (lax to strict): +# +# ignore: Sorbet won't even read the file. This means its contents are not +# visible during type checking. Avoid this. +# +# false: Sorbet will only report errors related to constant resolution. This is +# the default if no sigil is included. +# +# true: Sorbet will report all static type errors. This is the sweet spot of +# safety for effort. +# +# strict: Sorbet will require that all methods, constants, and instance +# variables have static types. +# +# strong: Sorbet will no longer allow anything to be T.untyped, even +# explicitly. Almost nothing satisfies this. + +# typed: true + +# Include the runtime type-checking library. This lets you write inline sigs +# and have them checked at runtime (instead of running Sorbet as RBI-only). +# These runtime checks happen even for files with `ignore` or `false` sigils. +require 'sorbet-runtime' + +class BasicSigs + # Bring in the type definition helpers. You'll almost always need this. + extend T::Sig + + # Sigs are defined with `sig` and a block. Define the return value type with + # `returns`. + # + # This method returns a value whose class is `String`. These are the most + # common types, and Sorbet calls them "class types". + sig { returns(String) } + def greet + 'Hello, World!' + end + + # Define parameter value types with `params`. + sig { params(n: Integer).returns(String) } + def greet_repeat(n) + (1..n).map { greet }.join("\n") + end + + # Define keyword parameters the same way. + sig { params(n: Integer, sep: String).returns(String) } + def greet_repeat_2(n, sep: "\n") + (1..n).map { greet }.join(sep) + end + + # Notice that positional/keyword and required/optional make no difference + # here. They're all defined the same way in `params`. + + # For lots of parameters, it's nicer to use do..end and a multiline block + # instead of curly braces. + sig do + params( + str: String, + num: Integer, + sym: Symbol, + ).returns(String) + end + def uhh(str:, num:, sym:) + 'What would you even do with these?' + end + + # For a method whose return value is useless, use `void`. + sig { params(name: String).void } + def say_hello(name) + puts "Hello, #{name}!" + end + + # Splats! Also known as "rest parameters", "*args", "**kwargs", and others. + # + # Type the value that a _member_ of `args` or `kwargs` will have, not `args` + # or `kwargs` itself. + sig { params(args: Integer, kwargs: String).void } + def no_op(*args, **kwargs) + if kwargs[:op] == 'minus' + args.each { |i| puts(i - 1) } + else + args.each { |i| puts(i + 1) } + end + end + + # Most initializers should be `void`. + sig { params(name: String).void } + def initialize(name:) + # Instance variables must have annotated types to participate in static + # type checking. + + # The value in `T.let` is checked statically and at runtime. + @upname = T.let(name.upcase, String) + + # Sorbet can infer this one! + @name = name + end + + # Constants also need annotated types. + SORBET = T.let('A delicious frozen treat', String) + + # Class variables too. + @@the_answer = T.let(42, Integer) + + # Sorbet knows about the `attr_*` family. + sig { returns(String) } + attr_reader :upname + + sig { params(write_only: Integer).returns(Integer) } + attr_writer :write_only + + # You say the reader part and Sorbet will say the writer part. + sig { returns(String) } + attr_accessor :name +end + +module Debugging + extend T::Sig + + # Sometimes it's helpful to know what type Sorbet has inferred for an + # expression. Use `T.reveal_type` to make type-checking show a special error + # with that information. + # + # This is most useful if you have Sorbet integrated into your editor so you + # can see the result as soon as you save the file. + + sig { params(obj: Object).returns(String) } + def debug(obj) + T.reveal_type(obj) # Revealed type: Object + repr = obj.inspect + + # Remember that Ruby methods can be called without arguments, so you can + # save a couple characters! + T.reveal_type repr # Revealed type: String + + "DEBUG: " + repr + end +end + +module StandardLibrary + extend T::Sig + # Sorbet provides some helpers for typing the Ruby standard library. + + # Use T::Boolean to catch both `true` and `false`. + # + # For the curious, this is equivalent to + # + # T.type_alias { T.any(TrueClass, FalseClass) } + # + sig { params(str: String).returns(T::Boolean) } + def confirmed?(str) + str == 'yes' + end + + # Remember that the value `nil` is an instance of NilClass. + sig { params(val: NilClass).void } + def only_nil(val:); end + + # To avoid modifying standard library classes, Sorbet provides wrappers to + # support common generics. + # + # Here's the full list: + # * T::Array + # * T::Enumerable + # * T::Enumerator + # * T::Hash + # * T::Range + # * T::Set + sig { params(config: T::Hash[Symbol, String]).returns(T::Array[String]) } + def merge_values(config) + keyset = [:old_key, :new_key] + config.each_pair.flat_map do |key, value| + keyset.include?(key) ? value : 'sensible default' + end + end + + # Sometimes (usually dependency injection), a method will accept a reference + # to a class rather than an instance of the class. Use `T.class_of(Dep)` to + # accept the `Dep` class itself (or something that inherits from it). + class Dep; end + + sig { params(dep: T.class_of(Dep)).returns(Dep) } + def dependency_injection(dep:) + dep.new + end + + # Blocks, procs, and lambdas, oh my! All of these are typed with `T.proc`. + # + # Limitations: + # 1. All parameters are assumed to be required positional parameters. + # 2. The only runtime check is that the value is a `Proc`. The argument types + # are only checked statically. + sig do + params( + data: T::Array[String], + blk: T.proc.params(val: String).returns(Integer), + ).returns(Integer) + end + def count(data, &blk) + data.sum(&blk) + end + + sig { returns(Integer) } + def count_usage + count(["one", "two", "three"]) { |word| word.length + 1 } + end + + # If the method takes an implicit block, Sorbet will infer `T.untyped` for + # it. Use the explicit block syntax if the types are important. + sig { params(str: String).returns(T.untyped) } + def implicit_block(str) + yield(str) + end + + # If you're writing a DSL and will execute the block in a different context, + # use `bind`. + sig { params(num: Integer, blk: T.proc.bind(Integer).void).void } + def number_fun(num, &blk) + num.instance_eval(&blk) + end + + sig { params(num: Integer).void } + def number_fun_usage(num) + number_fun(10) { puts digits.join } + end + + # If the block doesn't take any parameters, don't include `params`. + sig { params(blk: T.proc.returns(Integer)).returns(Integer) } + def doubled_block(&blk) + 2 * blk.call + end +end + +module Combinators + extend T::Sig + # These methods let you define new types from existing types. + + # Use `T.any` when you have a value that can be one of many types. These are + # sometimes known as "union types" or "sum types". + sig { params(num: T.any(Integer, Float)).returns(Rational) } + def hundreds(num) + num.rationalize + end + + # `T.nilable(Type)` is a convenient alias for `T.any(Type, NilClass)`. + sig { params(val: T.nilable(String)).returns(Integer) } + def strlen(val) + val.nil? ? -1 : val.length + end + + # Use `T.all` when you have a value that must satisfy multiple types. These + # are sometimes known as "intersection types". They're most useful for + # interfaces (described later), but can also describe helper modules. + + module Reversible + extend T::Sig + sig { void } + def reverse + # Pretend this is actually implemented + end + end + + module Sortable + extend T::Sig + sig { void } + def sort + # Pretend this is actually implemented + end + end + + class List + include Reversible + include Sortable + end + + sig { params(list: T.all(Reversible, Sortable)).void } + def rev_sort(list) + # reverse from Reversible + list.reverse + # sort from Sortable + list.sort + end + + def rev_sort_usage + rev_sort(List.new) + end + + # Sometimes, actually spelling out the type every time becomes more confusing + # than helpful. Use type aliases to make them easier to work with. + JSONLiteral = T.type_alias { T.any(Float, String, T::Boolean, NilClass) } + + sig { params(val: JSONLiteral).returns(String) } + def stringify(val) + val.to_s + end +end + +module DataClasses + extend T::Sig + # Use `T::Struct` to create a new class with type-checked fields. It combines + # the best parts of the standard Struct and OpenStruct, and then adds static + # typing on top. + # + # Types constructed this way are sometimes known as "product types". + + class Matcher < T::Struct + # Use `prop` to define a field with both a reader and writer. + prop :count, Integer + # Use `const` to only define the reader and skip the writer. + const :pattern, Regexp + # You can still set a default value with `default`. + const :message, String, default: 'Found one!' + + # This is otherwise a normal class, so you can still define methods. + + # You'll still need to bring `sig` in if you want to use it though. + extend T::Sig + + sig { void } + def reset + self.count = 0 + end + end + + sig { params(text: String, matchers: T::Array[Matcher]).void } + def awk(text, matchers) + matchers.each(&:reset) + text.lines.each do |line| + matchers.each do |matcher| + if matcher.pattern =~ line + Kernel.puts matcher.message + matcher.count += 1 + end + end + end + end + + # Gotchas and limitations + + # 1. `const` fields are not truly immutable. They don't have a writer method, + # but may be changed in other ways. + class ChangeMe < T::Struct + const :list, T::Array[Integer] + end + + sig { params(change_me: ChangeMe).returns(T::Boolean) } + def whoops!(change_me) + change_me = ChangeMe.new(list: [1, 2, 3, 4]) + change_me.list.reverse! + change_me.list == [4, 3, 2, 1] + end + + # 2. `T::Struct` inherits its equality method from `BasicObject`, which uses + # identity equality (also known as "reference equality"). + class Coordinate < T::Struct + const :row, Integer + const :col, Integer + end + + sig { returns(T::Boolean) } + def never_equal! + p1 = Coordinate.new(row: 1, col: 2) + p2 = Coordinate.new(row: 1, col: 2) + p1 != p2 + end + + # Define your own `#==` method to check the fields, if that's what you want. + class Position < T::Struct + extend T::Sig + + const :x, Integer + const :y, Integer + + sig { params(other: Object).returns(T::Boolean) } + def ==(other) + # There's a real implementation here: + # https://github.com/tricycle/sorbet-struct-comparable + true + end + end + + # Use `T::Enum` to define a fixed set of values that are easy to reference. + # This is especially useful when you don't care what the values _are_ as much + # as you care that the set of possibilities is closed and static. + class Crayon < T::Enum + extend T::Sig + + # Initialize members with `enums`. + enums do + # Define each member with `new`. Each of these is an instance of the + # `Crayon` class. + Red = new + Orange = new + Yellow = new + Green = new + Blue = new + Violet = new + Brown = new + Black = new + # The default value of the enum is its name in all-lowercase. To change + # that, pass a value to `new`. + Gray90 = new('light-gray') + end + + sig { returns(String) } + def to_hex + case self + when Red then '#ff0000' + when Green then '#00ff00' + # ... + else '#ffffff' + end + end + end + + sig { params(crayon: Crayon, path: T::Array[Position]).void } + def draw(crayon:, path:) + path.each do |pos| + Kernel.puts "(#{pos.x}, #{pos.y}) = " + crayon.to_hex + end + end + + # To get all the values in the enum, use `.values`. For convenience there's + # already a `#serialize` to get the enum string value. + + sig { returns(T::Array[String]) } + def crayon_names + Crayon.values.map(&:serialize) + end + + # Use the "deserialize" family to go from string to enum value. + + sig { params(name: String).returns(T.nilable(Crayon)) } + def crayon_from_name(name) + if Crayon.has_serialized?(name) + # If the value is not found, this will raise a `KeyError`. + Crayon.deserialize(name) + end + + # If the value is not found, this will return `nil`. + Crayon.try_deserialize(name) + end +end + +module FlowSensitivity + extend T::Sig + # Sorbet understands Ruby's control flow constructs and uses that information + # to get more accurate types when your code branches. + + # You'll see this most often when doing nil checks. + sig { params(name: T.nilable(String)).returns(String) } + def greet_loudly(name) + if name.nil? + 'HELLO, YOU!' + else + # Sorbet knows that `name` must be a String here, so it's safe to call + # `#upcase`. + "HELLO, #{name.upcase}!" + end + end + + # The nils are a special case of refining `T.any`. + sig { params(id: T.any(Integer, T::Array[Integer])).returns(T::Array[String]) } + def database_lookup(id) + if id.is_a?(Integer) + # `ids` must be an Integer here. + [id.to_s] + else + # `ids` must be a T::Array[Integer] here. + id.map(&:to_s) + end + end + + # Sorbet recognizes these methods that narrow type definitions: + # * is_a? + # * kind_of? + # * nil? + # * Class#=== + # * Class#< + # * block_given? + # + # Because they're so common, it also recognizes these Rails extensions: + # * blank? + # * present? + # + # Be careful to maintain Sorbet assumptions if you redefine these methods! + + # Have you ever written this line of code? + # + # raise StandardError, "Can't happen" + # + # Sorbet can help you prove that statically (this is known as + # "exhaustiveness") with `T.absurd`. It's extra cool when combined with + # `T::Enum`! + + class Size < T::Enum + extend T::Sig + + enums do + Byte = new('B') + Kibibyte = new('KiB') + Mebibyte = new('MiB') + # "640K ought to be enough for anybody" + end + + sig { returns(Integer) } + def bytes + case self + when Byte then 1 << 0 + when Kibibyte then 1 << 10 + when Mebibyte then 1 << 20 + else + # Sorbet knows you've checked all the cases, so there's no possible + # value that `self` could have here. + # + # But if you _do_ get here somehow, this will raise at runtime. + T.absurd(self) + + # If you're missing a case, Sorbet can even tell you which one it is! + end + end + end + + # We're gonna need `puts` and `raise` for this next part. + include Kernel + + # Sorbet knows that no code can execute after a `raise` statement because it + # "never returns". + sig { params(num: T.nilable(Integer)).returns(Integer) } + def decrement(num) + raise ArgumentError, '¯\_(ツ)_/¯' unless num + + num - 1 + end + + class CustomError < StandardError; end + + # You can annotate your own error-raising methods with `T.noreturn`. + sig { params(message: String).returns(T.noreturn) } + def oh_no(message = 'A bad thing happened') + puts message + raise CustomError, message + end + + # Infinite loops also don't return. + sig { returns(T.noreturn) } + def loading + loop do + %q(-\|/).each_char do |c| + print "\r#{c} reticulating splines..." + sleep 1 + end + end + end + + # You may run into a situation where Sorbet "loses" your type refinement. + # Remember that almost everything you do in Ruby is a method call that could + # return a different value next time you call it. Sorbet doesn't assume that + # any methods are pure (even those from `attr_reader` and `attr_accessor`). + sig { returns(T.nilable(Integer)) } + def answer + rand > 0.5 ? 42 : nil + end + + sig { void } + def bad_typecheck + if answer.nil? + 0 + else + # But answer might return `nil` if we call it again! + answer + 1 + # ^ Method + does not exist on NilClass component of T.nilable(Integer) + end + end + + sig { void } + def good_typecheck + ans = answer + if ans.nil? + 0 + else + # This time, Sorbet knows that `ans` is non-nil. + ans + 1 + end + end +end + +module InheritancePatterns + extend T::Sig + + # If you have a method that always returns the type of its receiver, use + # `T.self_type`. This is common in fluent interfaces and DSLs. + # + # Warning: This feature is still experimental! + class Logging + extend T::Sig + + sig { returns(T.self_type) } + def log + pp self + self + end + end + + class Data < Logging + extend T::Sig + + sig { params(x: Integer, y: String).void } + def initialize(x: 0, y: '') + @x = x + @y = y + end + + # You don't _have_ to use `T.self_type` if there's only one relevant class. + sig { params(x: Integer).returns(Data) } + def setX(x) + @x = x + self + end + + sig { params(y: String).returns(Data) } + def setY(y) + @y = y + self + end + end + + # Ta-da! + sig { params(data: Data).void } + def chaining(data) + data.setX(1).log.setY('a') + end + + # If it's a class method (a.k.a. singleton method), use `T.attached_class`. + # + # No warning here. This one is stable! + class Box + extend T::Sig + + sig { params(contents: String, weight: Integer).void } + def initialize(contents, weight) + @contents = contents + @weight = weight + end + + sig { params(contents: String).returns(T.attached_class) } + def self.pack(contents) + new(contents, contents.chars.uniq.length) + end + end + + class CompanionCube < Box + extend T::Sig + + sig { returns(String) } + def pick_up + "♥#{@contents}🤍" + end + end + + sig { returns(String) } + def befriend + CompanionCube.pack('').pick_up + end + + # Sorbet has support for abstract classes and interfaces. It can check that + # all the concrete classes and implementations actually define the required + # methods with compatible signatures. + + # Here's an abstract class: + + class WorkflowStep + extend T::Sig + + # Bring in the inheritance helpers. + extend T::Helpers + + # Mark this class as abstract. This means it cannot be instantiated with + # `.new`, but it can still be subclassed. + abstract! + + sig { params(args: T::Array[String]).void } + def run(args) + pre_hook + execute(args) + post_hook + end + + # This is an abstract method, which means it _must_ be implemented by + # subclasses. Add a signature with `abstract` to an empty method to tell + # Sorbet about it. + # + # If this implementation of the method actually gets called at runtime, it + # will raise `NotImplementedError`. + sig { abstract.params(args: T::Array[String]).void } + def execute(args); end + + # The following non-abstract methods _can_ be implemented by subclasses, + # but they're optional. + + sig { void } + def pre_hook; end + + sig { void } + def post_hook; end + end + + class Configure < WorkflowStep + extend T::Sig + + sig { void } + def pre_hook + puts 'Configuring...' + end + + # To implement an abstract method, mark the signature with `override`. + sig { override.params(args: T::Array[String]).void } + def execute(args) + # ... + end + end + + # And here's an interface: + + module Queue + extend T::Sig + + # Bring in the inheritance helpers. + extend T::Helpers + + # Mark this module as an interface. This adds the following restrictions: + # 1. All of its methods must be abstract. + # 2. It cannot have any private or protected methods. + interface! + + sig { abstract.params(num: Integer).void } + def push(num); end + + sig { abstract.returns(T.nilable(Integer)) } + def pop; end + end + + class PriorityQueue + extend T::Sig + + # Include the interface to tell Sorbet that this class implements it. + # Sorbet doesn't support implicitly implemented interfaces (also known as + # "duck typing"). + include Queue + + sig { void } + def initialize + @items = T.let([], T::Array[Integer]) + end + + # Implement the Queue interface's abstract methods. Remember to use + # `override`! + + sig { override.params(num: Integer).void } + def push(num) + @items << num + @items.sort! + end + + sig { override.returns(T.nilable(Integer)) } + def pop + @items.shift + end + end + + # If you use the `included` hook to get class methods from your modules, + # you'll have to use `mixes_in_class_methods` to get them to type-check. + + module Mixin + extend T::Helpers + interface! + + module ClassMethods + extend T::Sig + + sig { void } + def whisk + 'fskfskfsk' + end + end + + mixes_in_class_methods(ClassMethods) + end + + class EggBeater + include Mixin + end + + EggBeater.whisk # Meringue! +end + +module EscapeHatches + extend T::Sig + + # Ruby is a very dynamic language, and sometimes Sorbet can't infer the + # properties you already know to be true. Although there are ways to rewrite + # your code so Sorbet can prove safety, you can also choose to "break out" of + # Sorbet using these "escape hatches". + + # Once you start using `T.nilable`, Sorbet will start telling you _all_ the + # places you're not handling nils. Sometimes, you know a value can't be nil, + # but it's not practical to fix the sigs so Sorbet can prove it. In that + # case, you can use `T.must`. + sig { params(maybe_str: T.nilable(String)).returns(String) } + def no_nils_here(maybe_str) + # If maybe_str _is_ actually nil, this will error at runtime. + str = T.must(maybe_str) + str.downcase + end + + # More generally, if you know that a value must be a specific type, you can + # use `T.cast`. + sig do + params( + str_or_ary: T.any(String, T::Array[String]), + idx_or_range: T.any(Integer, T::Range[Integer]), + ).returns(T::Array[String]) + end + def slice2(str_or_ary, idx_or_range) + # Let's say that, for some reason, we want individual characters from + # strings or sub-arrays from arrays. The other options are not allowed. + if str_or_ary.is_a?(String) + # Here, we know that `idx_or_range` must be a single index. If it's not, + # this will error at runtime. + idx = T.cast(idx_or_range, Integer) + [str_or_ary.chars.fetch(idx)] + else + # Here, we know that `idx_or_range` must be a range. If it's not, this + # will error at runtime. + range = T.cast(idx_or_range, T::Range[Integer]) + str_or_ary.slice(range) || [] + end + end + + # If you know that a method exists, but Sorbet doesn't, you can use + # `T.unsafe` so Sorbet will let you call it. Although we tend to think of + # this as being an "unsafe method call", `T.unsafe` is called on the receiver + # rather than the whole expression. + sig { params(count: Integer).returns(Date) } + def the_future(count) + # Let's say you've defined some extra date helpers that Sorbet can't find. + # So `2.decades` is effectively `(2*10).years` from ActiveSupport. + Date.today + T.unsafe(count).decades + end + + # If this is a method on the implicit `self`, you'll have to make that + # explicit to use `T.unsafe`. + sig { params(count: Integer).returns(Date) } + def the_past(count) + # Let's say that metaprogramming defines a `now` helper method for + # `Time.new`. Using it would normally look like this: + # + # now - 1234 + # + T.unsafe(self).now - 1234 + end + + # There's a special type in Sorbet called `T.untyped`. For any value of this + # type, Sorbet will allow it to be used for any method argument and receive + # any method call. + + sig { params(num: Integer, anything: T.untyped).returns(T.untyped) } + def nothing_to_see_here(num, anything) + anything.digits # Is it an Integer... + anything.upcase # ... or a String? + + # Sorbet will not be able to infer anything about this return value because + # it's untyped. + BasicObject.new + end + + def see_here + # It's actually nil! This will crash at runtime, but Sorbet allows it. + nothing_to_see_here(1, nil) + end + + # For a method without a sig, Sorbet infers the type of each argument and the + # return value to be `T.untyped`. +end + +# The following types are not officially documented but are still useful. They +# may be experimental, deprecated, or not supported. + +module ValueSet + extend T::Sig + + # A common pattern in Ruby is to have a method accept one value from a set of + # options. Especially when starting out with Sorbet, it may not be practical + # to refactor the code to use `T::Enum`. In this case, you can use `T.enum`. + # + # Note: Sorbet can't check this statically becuase it doesn't track the + # values themselves. + sig do + params( + data: T::Array[Numeric], + shape: T.enum([:circle, :square, :triangle]) + ).void + end + def plot_points(data, shape: :circle) + data.each_with_index do |y, x| + Kernel.puts "#{x}: #{y}" + end + end +end + +module Generics + extend T::Sig + + # Generics are useful when you have a class whose method types change based + # on the data it contains or a method whose method type changes based on what + # its arguments are. + + # A generic method uses `type_parameters` to declare type variables and + # `T.type_parameter` to refer back to them. + sig do + type_parameters(:element) + .params( + element: T.type_parameter(:element), + count: Integer, + ).returns(T::Array[T.type_parameter(:element)]) + end + def repeat_value(element, count) + count.times.each_with_object([]) do |elt, ary| + ary << elt + end + end + + sig do + type_parameters(:element) + .params( + count: Integer, + block: T.proc.returns(T.type_parameter(:element)), + ).returns(T::Array[T.type_parameter(:element)]) + end + def repeat_cached(count, &block) + elt = block.call + ary = [] + count.times do + ary << elt + end + ary + end + + # A generic class uses `T::Generic.type_member` to define type variables that + # can be like regular type names. + class BidirectionalHash + extend T::Sig + extend T::Generic + + Left = type_member + Right = type_member + + sig { void } + def initialize + @left_hash = T.let({}, T::Hash[Left, Right]) + @right_hash = T.let({}, T::Hash[Right, Left]) + end + + # Implement just enough to make the methods below work. + + sig { params(lkey: Left).returns(T::Boolean) } + def lhas?(lkey) + @left_hash.has_key?(lkey) + end + + sig { params(rkey: Right).returns(T.nilable(Left)) } + def rget(rkey) + @right_hash[rkey] + end + end + + # To specialize a generic type, use brackets. + sig do + params( + options: BidirectionalHash[Symbol, Integer], + choice: T.any(Symbol, Integer), + ).returns(T.nilable(String)) + end + def lookup(options, choice) + case choice + when Symbol + options.lhas?(choice) ? choice.to_s : nil + when Integer + options.rget(choice).to_s + else + T.absurd(choice) + end + end + + # To specialize through inheritance, re-declare the `type_member` with + # `fixed`. + class Options < BidirectionalHash + Left = type_member(fixed: Symbol) + Right = type_member(fixed: Integer) + end + + sig do + params( + options: Options, + choice: T.any(Symbol, Integer), + ).returns(T.nilable(String)) + end + def lookup2(options, choice) + lookup(options, choice) + end + + # There are other variance annotations you can add to `type_member`, but + # they're rarely used. +end +``` + +## Additional resources + +- [Official Documentation](https://sorbet.org/docs/overview) +- [sorbet.run](https://sorbet.run) - Playground diff --git a/sql.html.markdown b/sql.html.markdown index 2bece208..834cf00b 100644 --- a/sql.html.markdown +++ b/sql.html.markdown @@ -5,18 +5,18 @@ contributors: - ["Bob DuCharme", "http://bobdc.com/"] --- -Structured Query Language (SQL) is an ISO standard language for creating and working with databases stored in a set of tables. Implementations usually add their own extensions to the language; [Comparison of different SQL implementations](http://troels.arvin.dk/db/rdbms/) is a good reference on product differences. +Structured Query Language (SQL) is an [ISO/IEC 9075](https://www.iso.org/standard/63555.html) standard language for creating and working with databases stored in a set of tables. Implementations usually add their own extensions to the language; [Comparison of different SQL implementations](http://troels.arvin.dk/db/rdbms/) is a good reference on product differences. Implementations typically provide a command line prompt where you can enter the commands shown here interactively, and they also offer a way to execute a series of these commands stored in a script file. (Showing that you’re done with the interactive prompt is a good example of something that isn’t standardized--most SQL implementations support the keywords QUIT, EXIT, or both.) -Several of these sample commands assume that the [MySQL employee sample database](https://dev.mysql.com/doc/employee/en/) available on [github](https://github.com/datacharmer/test_db) has already been loaded. The github files are scripts of commands, similar to the relevant commands below, that create and populate tables of data about a fictional company’s employees. The syntax for running these scripts will depend on the SQL implementation you are using. A utility that you run from the operating system prompt is typical. +Several of these sample commands assume that the [MySQL employee sample database](https://dev.mysql.com/doc/employee/en/) available on [github](https://github.com/datacharmer/test_db) has already been loaded. The github files are scripts of commands, similar to the relevant commands below, that create and populate tables of data about a fictional company’s employees. The syntax for running these scripts will depend on the SQL implementation you are using. A utility that you run from the operating system prompt is typical. ```sql -- Comments start with two hyphens. End each command with a semicolon. -- SQL is not case-sensitive about keywords. The sample commands here --- follow the convention of spelling them in upper-case because it makes +-- follow the convention of spelling them in upper-case because it makes -- it easier to distinguish them from database, table, and column names. -- Create and delete a database. Database and table names are case-sensitive. @@ -26,47 +26,47 @@ DROP DATABASE someDatabase; -- List available databases. SHOW DATABASES; --- Use a particular existing database. +-- Use a particular existing database. USE employees; -- Select all rows and columns from the current database's departments table. --- Default activity is for the interpreter to scroll the results on your screen. +-- Default activity is for the interpreter to scroll the results on your screen. SELECT * FROM departments; --- Retrieve all rows from the departments table, --- but only the dept_no and dept_name columns. +-- Retrieve all rows from the departments table, +-- but only the dept_no and dept_name columns. -- Splitting up commands across lines is OK. SELECT dept_no, dept_name FROM departments; --- Retrieve all departments columns, but just 5 rows. +-- Retrieve all departments columns, but just 5 rows. SELECT * FROM departments LIMIT 5; -- Retrieve dept_name column values from the departments --- table where the dept_name value has the substring 'en'. +-- table where the dept_name value has the substring 'en'. SELECT dept_name FROM departments WHERE dept_name LIKE '%en%'; -- Retrieve all columns from the departments table where the dept_name --- column starts with an 'S' and has exactly 4 characters after it. +-- column starts with an 'S' and has exactly 4 characters after it. SELECT * FROM departments WHERE dept_name LIKE 'S____'; -- Select title values from the titles table but don't show duplicates. SELECT DISTINCT title FROM titles; --- Same as above, but sorted (case-sensitive) by the title values. +-- Same as above, but sorted (case-sensitive) by the title values. SELECT DISTINCT title FROM titles ORDER BY title; -- Show the number of rows in the departments table. SELECT COUNT(*) FROM departments; -- Show the number of rows in the departments table that --- have 'en' as a substring of the dept_name value. +-- have 'en' as a substring of the dept_name value. SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%'; --- A JOIN of information from multiple tables: the titles table shows --- who had what job titles, by their employee numbers, from what +-- A JOIN of information from multiple tables: the titles table shows +-- who had what job titles, by their employee numbers, from what -- date to what date. Retrieve this information, but instead of the --- employee number, use the employee number as a cross-reference to +-- employee number, use the employee number as a cross-reference to -- the employees table to get each employee's first and last name -- instead. (And only get 10 rows.) @@ -85,21 +85,26 @@ WHERE TABLE_TYPE='BASE TABLE'; -- for how you specify the columns, such as their datatypes. CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20)); --- Insert a row of data into the table tablename1. This assumes that the --- table has been defined to accept these values as appropriate for it. +-- Insert a row of data into the table tablename1. This assumes that the +-- table has been defined to accept these values as appropriate for it. INSERT INTO tablename1 VALUES('Richard','Mutt'); -- In tablename1, change the fname value to 'John' --- for all rows that have an lname value of 'Mutt'. +-- for all rows that have an lname value of 'Mutt'. UPDATE tablename1 SET fname='John' WHERE lname='Mutt'; -- Delete rows from the tablename1 table -- where the lname value begins with 'M'. -DELETE FROM tablename1 WHERE lname like 'M%'; +DELETE FROM tablename1 WHERE lname LIKE 'M%'; -- Delete all rows from the tablename1 table, leaving the empty table. DELETE FROM tablename1; --- Remove the entire tablename1 table. +-- Remove the entire tablename1 table. DROP TABLE tablename1; ``` + +## Further Reading + +* [Codecademy - SQL](https://www.codecademy.com/learn/learn-sql) A good introduction to SQL in a "learn by doing it" format. +* [Database System Concepts](https://www.db-book.com) book's Chapter 3 - Introduction to SQL has an in depth explanation of SQL concepts. diff --git a/standard-ml.html.markdown b/standard-ml.html.markdown index 0ba42f39..9d6b104d 100644 --- a/standard-ml.html.markdown +++ b/standard-ml.html.markdown @@ -2,8 +2,8 @@ language: "Standard ML" filename: standardml.sml contributors: - - ["Simon Shine", "http://shine.eu.org/"] - - ["David Pedersen", "http://lonelyproton.com/"] + - ["Simon Shine", "https://simonshine.dk/"] + - ["David Pedersen", "https://github.com/davidpdrsn"] - ["James Baker", "http://www.jbaker.io/"] - ["Leo Zovic", "http://langnostic.inaimathi.ca/"] - ["Chris Wilson", "http://sencjw.com/"] @@ -479,3 +479,4 @@ fun decrement_ret x y = (x := !x - 1; y) * Follow the Coursera course [Programming Languages](https://www.coursera.org/course/proglang). * Read *[ML for the Working Programmer](https://www.cl.cam.ac.uk/~lp15/MLbook/pub-details.html)* by Larry C. Paulson. * Use [StackOverflow's sml tag](http://stackoverflow.com/questions/tagged/sml). +* Solve exercises on [Exercism.io's Standard ML track](https://exercism.io/tracks/sml). diff --git a/sv-se/nix-sv.html.markdown b/sv-se/nix-sv.html.markdown index 15d9456b..9069c286 100644 --- a/sv-se/nix-sv.html.markdown +++ b/sv-se/nix-sv.html.markdown @@ -365,4 +365,10 @@ with builtins; [ (https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55) * [Susan Potter - Nix Cookbook - Nix By Example] - (http://funops.co/nix-cookbook/nix-by-example/) + (https://ops.functionalalgebra.com/nix-by-example/) + +* [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) diff --git a/swift.html.markdown b/swift.html.markdown index c2fb3471..36124e11 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -12,7 +12,7 @@ contributors: filename: learnswift.swift --- -Swift is a programming language for iOS and OS X development created by Apple. Designed to coexist with Objective-C and to be more resilient against erroneous code, Swift was introduced in 2014 at Apple's developer conference WWDC. It is built with the LLVM compiler included in Xcode 6+. +Swift is a programming language for iOS and macOS development created by Apple. Designed to coexist with Objective-C and to be more resilient against erroneous code, Swift was introduced in 2014 at Apple's developer conference WWDC. It is built with the LLVM compiler included in Xcode 6+. The official _[Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329)_ book from Apple is now available via iBooks. It goes into much more detail than this guide, and if you have the time and patience to read it, it's recommended. Some of these examples are from that book. @@ -91,7 +91,7 @@ let multiLineString = """ This is a multi-line string. It's called that because it takes up multiple lines (wow!) Any indentation beyond the closing quotation marks is kept, the rest is discarded. - You can include " or "" in multi-line strings because the delimeter is three "s. + You can include " or "" in multi-line strings because the delimiter is three "s. """ // Arrays @@ -159,12 +159,12 @@ let `class` = "keyword" or contains nil (no value) to indicate that a value is missing. Nil is roughly equivalent to `null` in other languages. A question mark (?) after the type marks the value as optional of that type. - + If a type is not optional, it is guaranteed to have a value. - + Because Swift requires every property to have a type, even nil must be explicitly stored as an Optional value. - + Optional<T> is an enum, with the cases .none (nil) and .some(T) (the value) */ @@ -178,7 +178,7 @@ let someOptionalString4 = String?.none //nil To access the value of an optional that has a value, use the postfix operator !, which force-unwraps it. Force-unwrapping is like saying, "I know that this optional definitely has a value, please give it to me." - + Trying to use ! to access a non-existent optional value triggers a runtime error. Always make sure that an optional contains a non-nil value before using ! to force-unwrap its value. @@ -194,7 +194,7 @@ if someOptionalString != nil { // Swift supports "optional chaining," which means that you can call functions // or get properties of optional values and they are optionals of the appropriate type. // You can even do this multiple times, hence the name "chaining." - + let empty = someOptionalString?.isEmpty // Bool? // if-let structure - @@ -334,7 +334,7 @@ repeat { } while i < 5 // The continue statement continues executing a loop at the next iteration -// The break statement ends a swift or loop immediately +// The break statement ends a loop immediately // MARK: - Functions @@ -370,7 +370,7 @@ func say(_ message: String) { } say("Hello") -// Default parameters can be ommitted when calling the function. +// Default parameters can be omitted when calling the function. func printParameters(requiredParameter r: Int, optionalParameter o: Int = 10) { print("The required parameter was \(r) and the optional parameter was \(o)") } @@ -443,7 +443,7 @@ func testGuard() { return // guard statements MUST exit the scope that they are in. // They generally use `return` or `throw`. } - + print("number is \(aNumber)") } testGuard() @@ -564,7 +564,7 @@ enum Furniture { case desk(height: Int) // Associate with String and Int case chair(String, Int) - + func description() -> String { //either placement of let is acceptable switch self { @@ -591,15 +591,15 @@ print(chair.description()) // "Chair of Foo with 40 cm" - Define initializers to set up their initial state - Be extended to expand their functionality beyond a default implementation - Conform to protocols to provide standard functionality of a certain kind - + Classes have additional capabilities that structures don't have: - Inheritance enables one class to inherit the characteristics of another. - Type casting enables you to check and interpret the type of a class instance at runtime. - Deinitializers enable an instance of a class to free up any resources it has assigned. - Reference counting allows more than one reference to a class instance. - + Unless you need to use a class for one of these reasons, use a struct. - + Structures are value types, while classes are reference types. */ @@ -607,7 +607,7 @@ print(chair.description()) // "Chair of Foo with 40 cm" struct NamesTable { let names: [String] - + // Custom subscript subscript(index: Int) -> String { return names[index] @@ -629,7 +629,7 @@ class Shape { class Rect: Shape { var sideLength: Int = 1 - + // Custom getter and setter property var perimeter: Int { get { @@ -640,38 +640,38 @@ class Rect: Shape { sideLength = newValue / 4 } } - + // Computed properties must be declared as `var`, you know, cause' they can change var smallestSideLength: Int { return self.sideLength - 1 } - + // Lazily load a property // subShape remains nil (uninitialized) until getter called lazy var subShape = Rect(sideLength: 4) - + // If you don't need a custom getter and setter, // but still want to run code before and after getting or setting // a property, you can use `willSet` and `didSet` var identifier: String = "defaultID" { - // the `willSet` arg will be the variable name for the new value + // the `someIdentifier` arg will be the variable name for the new value willSet(someIdentifier) { print(someIdentifier) } } - + init(sideLength: Int) { self.sideLength = sideLength // always super.init last when init custom properties super.init() } - + func shrink() { if sideLength > 0 { sideLength -= 1 } } - + override func getArea() -> Int { return sideLength * sideLength } @@ -679,6 +679,9 @@ class Rect: Shape { // A simple class `Square` extends `Rect` class Square: Rect { + // Use a convenience initializer to make calling a designated initializer faster and more "convenient". + // Convenience initializers call other initializers in the same class and pass default values to one or more of their parameters. + // Convenience initializers can have parameters as well, which are useful to customize the called initializer parameters or choose a proper initializer based on the value passed. convenience init() { self.init(sideLength: 5) } @@ -692,6 +695,11 @@ print(mySquare.sideLength) // 4 // cast instance let aShape = mySquare as Shape +// downcast instance: +// Because downcasting can fail, the result can be an optional (as?) or an implicitly unwrpped optional (as!). +let anOptionalSquare = aShape as? Square // This will return nil if aShape is not a Square +let aSquare = aShape as! Square // This will throw a runtime error if aShape is not a Square + // compare instances, not the same as == which compares objects (equal to) if mySquare === mySquare { print("Yep, it's mySquare") @@ -703,13 +711,13 @@ class Circle: Shape { override func getArea() -> Int { return 3 * radius * radius } - + // Place a question mark postfix after `init` is an optional init // which can return nil init?(radius: Int) { self.radius = radius super.init() - + if radius <= 0 { return nil } @@ -813,10 +821,21 @@ for _ in 0..<10 { - Internal: Accessible and subclassible in the module it is declared in. - Fileprivate: Accessible and subclassible in the file it is declared in. - Private: Accessible and subclassible in the enclosing declaration (think inner classes/structs/enums) - + See more here: https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html */ +// MARK: Preventing Overrides + +// You can add keyword `final` before a class or instance method, or a property to prevent it from being overridden +class Shape { + final var finalInteger = 10 +} + +// Prevent a class from being subclassed +final class ViewManager { +} + // MARK: Conditional Compilation, Compile-Time Diagnostics, & Availability Conditions // Conditional Compilation @@ -878,11 +897,11 @@ extension Int { var doubled: Int { return self * 2 } - + func multipliedBy(num: Int) -> Int { return num * self } - + mutating func multiplyBy(num: Int) { self *= num } @@ -904,7 +923,7 @@ func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { } return nil } -findIndex(array: [1, 2, 3, 4], valueToFind: 3) // 2 +findIndex(array: [1, 2, 3, 4], valueToFind: 3) // Optional(2) // You can extend types with generics as well extension Array where Array.Element == Int { @@ -965,18 +984,18 @@ func fakeFetch(value: Int) throws -> String { guard 7 == value else { throw MyError.reallyBadValue(msg: "Some really bad value") } - + return "test" } func testTryStuff() { // assumes there will be no error thrown, otherwise a runtime exception is raised let _ = try! fakeFetch(value: 7) - + // if an error is thrown, then it proceeds, but if the value is nil // it also wraps every return value in an optional, even if its already optional let _ = try? fakeFetch(value: 7) - + do { // normal try operation that provides error handling via `catch` block try fakeFetch(value: 1) diff --git a/ta_in/css-ta.html.markdown b/ta_in/css-ta.html.markdown index cbe88f1e..4ea7f959 100644 --- a/ta_in/css-ta.html.markdown +++ b/ta_in/css-ta.html.markdown @@ -233,6 +233,48 @@ css முன்னுரிமை பின்வருமாறு * `B` இது அடுத்தது. * `D` இதுவே கடைசி . +## Media Queries [மீடியா குரிஸ்] + +CSS மீடியா குரிஸ் CSS 3 அம்சங்கள். பயன்படுத்தும் கணினி, கைபேசி அல்லது சாதனத்தின் பிஸேல் டென்சிட்டிக்கு ஏற்றவாறு மீடியா குரிஸ் விதிகளை பயன்படுத்தலாம். + +```css +/* அனைத்து டேவிஸ்களுக்கும் பொதுவான விதி */ +h1 { + font-size: 2em; + color: white; + background-color: black; +} + +/* பிரிண்ட் செய்யும்போது h1 கலர் மாற்ற */ +@media print { + h1 { + color: black; + background-color: white; + } +} + +/* 480 பிஸேல்ளுக்கு மேல் சிகிரீன் அளவு உள்ள சாதனத்தில் எழுத்து அளவு மிகை படுத்த */ +@media screen and (min-width: 480px) { + h1 { + font-size: 3em; + font-weight: normal; + } +} +``` + +மீடியா குரிஸ் வழங்கும் அம்சங்கள் : +`width`, `height`, `device-width`, `device-height`, `orientation`, `aspect-ratio`, `device-aspect-ratio`, `color`, `color-index`, `monochrome`, `resolution`, `scan`, `grid`. இவையுள் பெரும்பான்மை `min-` அல்லது `max-` வுடன் பயன்படுத்தலாம் . + +`resolution` பழைய சாதனங்களில் பயன்படாது, எனவே `device-pixel-ratio` பயன்படுத்தவும். + +பல கைபேசி மற்றும் கணினிகள், வீடு கணினி திரை அளவு காட்ட முற்படும். எனவே `viewport` மெட்டா டேக் பயன்படுத்தவும். + +```html +<head> + <meta name="viewport" content="width=device-width; initial-scale=1.0"> +</head> +``` + ## css அம்சங்களின் பொருந்தகூடிய தன்மை பெரும்பாலான css 2 வின் அம்சங்கள் எல்லா உலாவிகளிலும் , கருவிகளிலும் உள்ளன. ஆனால் முன்கூட்டியே அந்த அம்சங்களை பரிசோதிப்பது நல்லது. diff --git a/ta_in/javascript-ta.html.markdown b/ta_in/javascript-ta.html.markdown index d3fe5a85..b328765f 100644 --- a/ta_in/javascript-ta.html.markdown +++ b/ta_in/javascript-ta.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ['Adam Brenecki', 'http://adam.brenecki.id.au'] + - ['Leigh Brenecki', 'https://leigh.net.au'] - ['Ariel Krakowski', 'http://www.learneroo.com'] translators: - ["Rasendran Kirushan", "https://github.com/kirushanr"] @@ -22,8 +22,8 @@ javascript 1995 ஆம் ஆண்டு Netscape இல் பணிபுர V8 JavaScript engine Node .js உதவியுடன் இயங்குகிறது . உங்கள் கருத்துக்கள் மிகவும் வரவேற்கபடுகின்றன , என்னுடன் தொடர்புகொள்ள -[@adambrenecki](https://twitter.com/adambrenecki), or -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). +[@ExcitedLeigh](https://twitter.com/ExcitedLeigh), or +[l@leigh.net.au](mailto:l@leigh.net.au). ```js // குறிப்புக்கள் C நிரலாக்கத்தை ஒத்தது .ஒரு வரி குறிப்புக்கள் "//" குறியீடுடன் ஆரம்பமாகும் diff --git a/ta_in/xml-ta.html.markdown b/ta_in/xml-ta.html.markdown index d782399d..13aa9255 100644 --- a/ta_in/xml-ta.html.markdown +++ b/ta_in/xml-ta.html.markdown @@ -5,6 +5,7 @@ contributors: - ["João Farias", "https://github.com/JoaoGFarias"] translators: - ["Rasendran Kirushan", "https://github.com/kirushanr"] + - ["Sridhar Easwaran", "https://github.com/sridhareaswaran"] lang: in-ta --- @@ -14,6 +15,57 @@ XML ஆனது ஒரு கட்டமைப்பு மொழி ஆகு HTML போல் அன்றி , XML ஆனது தகவலை மட்டும் கொண்டு செல்ல்கிறது + +## சில வரையறை மற்றும் முன்னுரை + +பல கூறுகளால் அமைக்கப்பட்டது. ஒவொரு கூறுகளிலும் அட்ட்ரிபூட்க்கள் இருக்கும், அவை அந்தந்த கூறுகளை வரையறுக்க பயன்படும். மேலும் அந்த கூறுகளை தகவல் அல்லது கிளை கூறுகள் இருக்கலாம். அணைத்து கோப்புகளிலும் ரூட்/ஆரம்ப கூறு இருக்கும், அது தனக்குள் கிளை கூறுகளை கொண்டுருக்கும். + +XML பாகுபடுத்தி மிகவும் கண்டிப்பான வீதிகளைக்கொண்டது. [XML தொடரியல் விதிகளை அறிய] (http://www.w3schools.com/xml/xml_syntax.asp). + + +```xml +<!-- இது ஒரு XML குறிப்ப --> +<!-- குறிப்புக்கள் +பலவரி இருக்கலாம் --> + +<!-- கூறுகள்/Elements --> +<!-- Element எனப்படுவது அடிப்படை கூறு. அவை இருவகைப்பாடு. காலியான கூறு: --> +<element1 attribute="value" /> <!-- காலியான கூறு - உள்ளடக்கம் இல்லாதது --> +<!-- மற்றும் காலி-இல்லாத கூறு : --> +<element2 attribute="value">Content</element2> +<!-- கூற்றின் பெயர் எழுத்துக்கள் மற்றும் எண் கொண்டு மட்டுமே இருக்கவேண்டும்.. --> + +<empty /> <!-- காலியான கூறு - உள்ளடக்கம் இல்லாதது --> + +<notempty> <!-- காலி-இல்லாத கூற - துவக்கம் --> + <!-- உள்ளடக்கம் --> +</notempty> <!-- முடிவு --> + +<!-- கூற்றின் பெயர்கள் எழுத்து வடிவுணர்வு கொண்டது--> +<element /> +<!-- ஓட்றது அல்ல --> +<eLEMENT /> + +<!-- Attributes/பண்புகளை --> +<!-- Attribute ஒரு மதிப்பு இணை --> +<element attribute="value" another="anotherValue" many="space-separated list" /> +<!-- ஒரு கூற்றில் Attribute ஒருமுறைதான் தோன்றும். அது ஒரேயொரு பணப்பை கொண்டிருக்கும் --> + +<!-- கீழை கூறுகள் --> +<!-- ஒரு கூரானது பல கீழை கூறுகளை கொண்டிருக்கலாம் : --> +<parent> + <child>Text</child> + <emptysibling /> +</parent> + +<!-- XML இடைவெளி கான்கெடுக்கப்படும். --> +<child> + Text +</child> +<!-- ஓட்றது அல்ல --> +<child>Text</child> +``` + * XML வாக்கிய அமைப்பு diff --git a/tact.html.markdown b/tact.html.markdown new file mode 100644 index 00000000..2cb650ee --- /dev/null +++ b/tact.html.markdown @@ -0,0 +1,603 @@ +--- +language: Tact +filename: tact.tc +contributors: + - ["Tal Kol", "https://www.orbs.com/"] + - ["Kirill Malev", "https://fslabs.io"] + - ["Yash Garg", "https://github.com/yash0501"] +--- + +Tact language is used to program smart contracts on the +[The Open Network](https://ton.org) blockchain. Contract logic is executed in +TVM, the stack-based TON Virtual Machine. + +Tact is a statically typed, but language was designed to be friendly for +developers with JS and Python background. + +This page is based on [Tact-by-Example](https://tact-by-example.org/). +You can use this resource to play around with contracts and check out +the interactive features. + +# Basic syntax, function definition + +```c +// Single line comment + + // This is a multi-line comment + // this is a comment in the comment + + get fun greeting(): String { + // This is a function that returns "hello world" message + // Return type is specified after a colon : + return "hello world"; + } +``` + +# A Simple Counter contract + +This is a simple counter contract that allows users to increment its value. + +This contract has a state variable `val` that persists between contract calls + +- the counter value. When persisted, this variable is encoded as `uint32` - + a 32-bit unsigned integer. Contracts pay rent in proportion to the amount + of persistent space they consume, so compact representations are encouraged. + +State variables should be initialized in `init()` that runs on deployment of +the contract. + +## Messages + +The actor model is a model of concurrent computation and is at the heart of TON +smart contracts. Each smart contract can process one message at a time, change +its own state, or send one or several messages. Processing of the message +occurs in one transaction, that is, it cannot be interrupted. Messages to one +contract are processed consequently one by one. As a result, the execution of +each transaction is local and can be parallelized at the blockchain level, +which allows for on-demand throughput horizontal scaling and hosting an +unlimited number of users and transactions. + +## Receiving messages + +This contract can receive messages from users. Unlike getters that are just +read-only, messages can do write operations and change the contract's +persistent state. Incoming messages are processed in receive() methods as +transactions and cost gas for the sender. + +After deploying the contract, send the increment message by pressing the Send +increment button in order to increase the counter value by one. Afterwards, +call the getter value() to see that the value indeed changed. + +```c +contract Counter { +// Tact allows to create a contract + // persistent state variable of type Int to hold the counter value + val: Int as uint32; + + // initialize the state variable when contract is deployed + init() { + self.val = 0; + } + + // handler for incoming increment messages that change the state + receive("increment") { + self.val = self.val + 1; + } + + // read-only getter for querying the counter value + get fun value(): Int { + return self.val; + } +} +``` + +# The Deployable Trait + +Tact doesn't support classical class inheritance, but contracts can implement +traits. One of the commonly used traits is `Deployable`. It implements a simple +receiver for the Deploy message which helps deploy contracts in a standard way. + +All contracts are deployed by sending them a message. This can be any message, +but best practice is to designate the special `Deploy` +message for this purpose. + +This message has a single field, `queryId`, which is provided by the deployer +(normally zero). If the deploy succeeds, the contract will reply with the +message `DeployOk` and echo the same `queryId` in the response. + +If you're using Tact's [auto-generated](https://docs.tact-lang.org/tools/typescript#tact-contract-in-typescript) TypeScript +classes to deploy, sending the deploy message should look like: + +```c +const msg = { $$type: "Deploy", queryId: 0n }; + await contract.send(sender, { value: toNano(1) }, msg); +``` + +You can see the implementation of the trait [here](https://github.com/tact-lang/tact/blob/main/stdlib/libs/deploy.tact). +Notice that the file deploy.tact needs to be imported from the standard +library using the import keyword. + +```c +// this trait has to be imported +import "@stdlib/deploy"; + +// the Deployable trait adds a default receiver for the "Deploy" message +contract Counter with Deployable { + + val: Int as uint32; + + init() { + self.val = 0; + } + + receive("increment") { + self.val = self.val + 1; + } + + get fun value(): Int { + return self.val; + } +} +``` + +# Integers + +Tact supports a number of primitive data types that are tailored for +smart contract use. + +`Int` is the primary number type. Math in smart contracts is always done +with integers and never with floating points since floats are [unpredictable](https://learn.microsoft.com/en-us/cpp/build/why-floating-point-numbers-may-lose-precision). + +The runtime type `Int` is always 257-bit signed, so all runtime calculations +are done at 257-bit. This should be large enough for pretty much anything you +need as it's large enough to hold the number of atoms in the universe. + +Persistent state variables can be initialized inline or inside `init()`. +If you forget to initialize a state variable, the code will not compile. + +## State costs + +When encoding `Int` to persistent state, we will usually use smaller +representations than 257-bit to reduce storage cost. +The persistent state size is specified in every declaration of +a state variable after the `as` keyword. + +Storing 1000 257-bit integers in state [costs](https://ton.org/docs/develop/smart-contracts/fees#how-to-calculate-fees) about +0.184 TON per year. Storing 1000 32-bit integers only costs +0.023 TON per year by comparison. + +```c +import "@stdlib/deploy"; + +contract Integers with Deployable { + + // contract persistent state variables + // integers can be persisted in state in various sizes + // range -2^256 to 2^256 - 1 (takes 257 bit = 32 bytes + 1 bit) + i1: Int as int257 = 3001; + i2: Int as uint256; // range 0 to 2^256 - 1 (takes 256 bit = 32 bytes) + // range -2^255 to 2^255 - 1 (takes 256 bit = 32 bytes) + i3: Int as int256 = 17; + i4: Int as uint128; // range 0 to 2^128 - 1 (takes 128 bit = 16 bytes) + // range -2^127 to 2^127 - 1 (takes 128 bit = 16 bytes) + i5: Int as int128; + i6: Int as coins; // range 0 to 2^120 - 1 (takes 120 bit = 15 bytes) + // range 0 to 18,446,744,073,709,551,615 (takes 64 bit = 8 bytes) + i7: Int as uint64 = 0x1c4a; + // range -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 + // (takes 64 bit = 8 bytes) + i8: Int as int64 = -203; + i9: Int as uint32 = 0; // range 0 to 4,294,967,295 (takes 32 bit = 4 bytes) + // range -2,147,483,648 to 2,147,483,647 (takes 32 bit = 4 bytes) + i10: Int as int32 = 0; + i11: Int as uint16 = 0; // range 0 to 65,535 (takes 16 bit = 2 bytes) + i12: Int as int16 = 0; // range -32,768 to 32,767 (takes 16 bit = 2 bytes) + i13: Int as uint8 = 0; // range 0 to 255 (takes 8 bit = 1 byte) + i14: Int as int8 = 0; // range -128 to 127 (takes 8 bit = 1 byte) + + init() { + // we can define numbers in hex (base 16) + self.i2 = 0x83dfd552e6372; + self.i4 = 1507998500293440234999; // we can define numbers in decimal + self.i5 = pow(10, 9); // this is 10^9 = 1,000,000,000 + self.i6 = ton("1.23"); // easy to read coin balances + // (coins type is nano-tons, like cents, just with 9 decimals) + } + + receive("show all") { + dump(self.i1); + dump(self.i2); + dump(self.i3); + dump(self.i4); + dump(self.i5); + dump(self.i6); + dump(self.i7); + dump(self.i8); + } + + get fun result(): Int { + return self.i1; + } +} +``` + +## Bools, Addresses, Strings, Operators and Constants + +### Bool + +Bool can be used for boolean variables + +```js +b1: Bool = true; +b2: Bool = false; +``` + +### Address + +Address is another primitive data type. It represents standard addresses on +the TON blockchain. +TON is divided into multiple chains called workchains. One of the internal +fields of the address is the workchain id: +0 - The standard workchain, for regular users. Your contracts will be here. +-1 - The masterchain, usually for validators. + +```js +// bouncable (same foundation wallet) +a1: Address = address("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N"); +// non-bounceable (same foundation wallet) +a2: Address = address("UQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqEBI"); +``` + +### String + +Tact has basic support for strings. Strings support unicode and don't +have any special escape characters like \n. +Strings are immutable. Once a sequence of characters is created, this +sequence cannot be modified. +If you need to concatenate strings in run-time, you can use a StringBuilder. +This object handles gas efficiently and supports append() of various types to +the string. + +```js +s1: String = "hello world"; +sb: StringBuilder = beginString(); +sb.append(self.s1); +``` + +### Integer Operations + +Addition, subtraction, multiplication, division, modulo, +shift left and right, minimum and maximum numbers, absolute value + +```js +i: Int = -12; // temporary variable, runtime Int type is always int257 +i = i1 * 3 + (i2 - i); // basic math expressions +i = i1 % 10; // modulo (remainder after division), 3001 % 10 = 1 +i = i1 / 1000; // integer division (truncation toward zero), 3001 / 1000 = 3 +i = i1 >> 3; // shift right (multiply by 2^n) +i = i1 << 2; // shift left (divide by 2^n) +i = min(i2, 11); // minimum between two numbers +i = max(i2, 66); // maximum between two numbers +i = abs(-1 * i2); // absolute value +``` + +### Constants + +Unlike variables, constants cannot change. Their values are +calculated in compile-time and cannot change during execution. + +```js +const StateUnpaid: Int = 0; +``` + +## Getters, Receivers and Messages + +### Getters + +Getters are special contract functions that allow users to query +information from the contract. +Contract methods starting with the prefix get fun are all getters. +Calling getters is free and does not cost gas. +Getters are read-only, they cannot change the contract persistent state. +A contract cannot execute a getter of another contract. Getters are only +executable by end-users off-chain. + +```js +count: Int as uint32 = 17; + +get fun counter(): Int { + return self.count; +} +``` + +### Receivers + +Contract methods named receive() are the handlers that process +each incoming message type. +Tact will automatically route every incoming message to the correct receiver +listening for it according to its type. A message is only handled by one receiver. + +Handler for "increment" textual message - this is a textual string message, +these cannot carry input arguments + +```js +receive("increment") { + self.val = self.val + 1; +} +``` + +### Messages + +Messages are defined using the message keyword. They can carry input +arguments. For integers, you must define the encoding size, just like in +state variables. + +Handler for the "Add" message - this is a binary message that has an input +argument (amount) + +```js +receive(msg: Add) { + self.val = self.val + msg.amount; +} +``` + +## Structs + +Structs allow you to combine multiple primitives together in a more semantic way. +Structs can define complex data types that contain multiple fields of +different types. They can also be nested. + +```js +// Normal struct +struct Point { + x: Int as int64; + y: Int as int64; +} + +// Nested struct +struct Params { + name: String = "Satoshi"; // default value + age: Int? = null; // optional field + point: Point; // nested structs +} +``` + +## Message Sender and Throwing Errors + +### Message Sender + +Every incoming message is sent from some contract that has +an address. You can query the address of the message sender by calling sender() + +```js +deployer: Address = sender(); +``` + +### Errors + +When an error is thrown, the transaction reverts. By writing a +require() on a condition that isn't met + +```js +require(self.val < 5, "Counter is too high"); +``` + +## Messages Between Contracts, Sending and Receiving TON Coins + +### Messages Between Contracts + +Different contracts can only communicate with +each other by sending each other messages. + +This example sends a message to the to address with value of 1 TON and body +of a comment with a string "Hello, World!". +SendIgnoreErrors means that even when error occurs during message sending +next messages would be sent anyway. + +```js +let to: Address = ...; +let value: Int = ton("1"); +send(SendParameters{ + to: to, // address of receiver + value: value, // amount of TON you want to send + mode: SendIgnoreErrors, // 8-bit flag configuring how to send message + bounce: true, // if set to true (default) then message + // will be bounced back to sender + body: "Hello, World!".asComment() // message body as Cell +}); +``` + +### Receiving TONs + +You can query the contract balance with myBalance() - note +that the value is in nano-tons (like cents, just with 9 decimals). The balance +already contains the incoming message value. +You can also get the incoming TON balance with context().value + +```js +val: Int as int64 = myBalance() +// or +// print how much TON coin were sent with this message +dump(context().value); +``` + +### Sending TONs + +We can send any amount of TON to any address just like we created +a send call between different contracts + +Send mode SendRemainingValue will add to the outgoing value any excess left +from the incoming message after all gas costs are deducted from it. + +```js +amount: Int as coins = ton("1"); +send(SendParameters{ + to: sender(), + bounce: true, + value: amount, + mode: SendRemainingValue + SendIgnoreErrors +}); +``` + +## If/Else statements and Loops + +### If + +Tact supports if statements in a similar syntax to most programming +languages. Curly braces are required. +We can have the else and else if similar to other programming languages. + +```js +if (val > 1000) { + dump("larger than 1000"); +} else if (val > 500) { + dump("between 500 and 1000"); +} else { + dump("smaller than 500"); +} +``` + +### Loops + +Tact does not support traditional 'for' loops, 'break' and 'continue' +statements in loops. +The repeat loop statement input number must fit within an int32. + +```js +// repeat exactly 10 times + +repeat (10) { + i = i + 1; + sum = sum + i; +} + +// While loop + +let x: Int = 10; +while(x > 0) { + x = x - 1; +} + +// do-until loop + +let x: Int = 10; +do { + x = x - 1; +} until (x <= 0); +``` + +## Functions + +Functions in Tact start with the fun keyword. Functions can receive multiple +input arguments and can optionally return a single output value. You can +return a struct if you want to return multiple values. + +```js +fun average(a: Int, b: Int): Int { + return (a + b) / 2; +} +``` + +## Maps and Arrays + +### Maps + +Maps are a dictionary type that can hold an arbitrary number of items, +each under a different key. +The keys in maps can either be an Int type or an Address type. +You can check if a key is found in the map by calling the get() method. +Replace the value under a key by calling the set() method. + +```js +mi1: map<Int, TokenInfo>; // maps with Int as key +ma1: map<Address, TokenInfo>; // maps with Address as key +``` + +### Arrays + +To create an array, define a map with 'Int' type as key as well as value. + +```js +arr: map<Int, Int>; // this is our array implemented with a map +``` + +## Ownable Standard Library + +The Ownable trait allows the contract to set an owner role, which can have +higher priviliges from everybody else. +For this you would need to import the "@stdlib/ownable" library and inherit +it in your contract + +- Use the self.requireOwner() call to verify that the person making that + function call is the owner of contract +- 'ChangeOwner{newOwner: Address}' message which allows the owner to + transfer ownership. +- Define state variables named 'owner: Address' and 'stopped: Bool' and + call 'self.requireNotStopped()' on actions that should be stopped. +- Define state variables named 'owner: Address' and "stopped: Bool' and + call 'self.requireNotStopped()' on actions that should be stopped. + +```js +import "@stdlib/ownable"; +import "@stdlib/deploy"; + +contract Counter with Deployable, Ownable { + owner: Address; + + init() { // initialize a contract with default values like 'constructor' + self.owner = sender(); // we can initialize owner to any value we want, the deployer in this case + self.val = 0; + } + + // this message in only available to the owner + receive("double") { + self.requireOwner(); + self.val = self.val * 2; + } + + // this message will only work until the contract was stopped + receive("increment") { + self.requireNotStopped(); + self.val = self.val + 1; + } + + // this message will only work as long as the contract is not stopped + receive("increment2") { + self.requireNotStopped(); + self.val = self.val + 1; + } +} + +``` + +## Additional resources + +- [TON Documentation](https://ton.org/docs/#/) +- [Tact Docs](https://docs.tact-lang.org/) +- [Tact by Example](https://tact-by-example.org/) +- [Community portal](https://society.ton.org) +- [Blockchain portal](https://ton.org) +- [Stackoverflow](https://stackoverflow.com/questions/tagged/ton) + +## Social + +- [Tact community](https://t.me/tactlang) +- [Developer community](https://t.me/tondev_eng) +- [TON Learn](https://t.me/ton_learn) +- [Tondev News](https://t.me/tondevnews) +- [TON Technical Updates](https://t.me/thetontech) + +## Useful blogposts + +- [Setting up a TON Development Environment](https://society.ton.org/setting-up-a-ton-development-environment) +- [Hello World on TON](https://society.ton.org/ton-hello-world-step-by-step-guide-for-writing-your-first-smart-contract-in-func) + +## Future To Dos + +- Add smart contracts examples +- Add more links to documentations + +This file is based on [Tact By Example](https://tact-by-example.org). + +P.S. If by any chance you're familiar with [Forth](https://learnxinyminutes.com/docs/forth/), +you can also take a look at [Fift](https://ton-blockchain.github.io/docs/fiftbase.pdf). diff --git a/tailspin.html.markdown b/tailspin.html.markdown new file mode 100644 index 00000000..89ccdb1f --- /dev/null +++ b/tailspin.html.markdown @@ -0,0 +1,383 @@ +--- +language: tailspin +filename: learntailspin.tt +contributors: + - ["Torbjörn Gannholm", "https://github.com/tobega/"] + +--- + +**Tailspin** works with streams of values in pipelines. You may often feel +that your program is the machine and that the input data is the program. + +While Tailspin is unlikely to become mainstream, or even production-ready, +it will change the way you think about programming in a good way. + +```c +// Comment to end of line + +// Process data in a pipeline with steps separated by -> +// String literals are delimited by single quotes +// A bang (!) indicates a sink, or end of the pipe +// OUT is the standard output object, ::write is the message to write output +'Hello, World!' -> !OUT::write + +// Output a newline by just entering it in the string (multiline strings) +' +' -> !OUT::write +// Or output the decimal unicode value for newline (10) between $# and ; +'$#10;' -> !OUT::write + +// Define an immutable named value. Value syntax is very literal. +def names: ['Adam', 'George', 'Jenny', 'Lucy']; + +// Stream the list to process each name. Note the use of $ to get the value. +// The current value in the pipeline is always just $ +// String interpolation starts with a $ and ends with ; +$names... -> 'Hello $;! +' -> !OUT::write + +// You can also stream in the interpolation and nest interpolations +// Note the list indexing with parentheses and the slice extraction +// Note the use of ~ to signify an exclusive bound to the range +// Outputs 'Hello Adam, George, Jenny and Lucy!' +'Hello $names(first);$names(first~..~last)... -> ', $;'; and $names(last);! +' -> !OUT::write + +// Conditionally say different things to different people +// Matchers (conditional expressions) are delimited by angle brackets +// A set of matchers, evaluated top down, must be in templates (a function) +// Here it is an inline templates delimited by \( to \) +// Note the doubled '' and $$ to get a literal ' and $ +$names... -> \( + when <='Adam'> do 'What''s up $;?' ! + when <='George'> do 'George, where are the $$10 you owe me?' ! + otherwise 'Hello $;!' ! +\) -> '$;$#10;' -> !OUT::write + +// You can also define templates (functions) +// A lone ! emits the value into the calling pipeline without returning control +// The # sends the value to be matched by the matchers +// Note that templates always take one input value and emit 0 or more outputs +templates collatz-sequence + when <..0> do 'The start seed must be a positive integer' ! + when <=1> do $! +// The ?( to ) allows matching a computed value. Can be concatenated as "and" + when <?($ mod 2 <=1>)> do + $ ! + 3 * $ + 1 -> # + otherwise + $ ! + $ ~/ 2 -> # +end collatz-sequence + +// Collatz sequence from random start on one line separated by spaces +1000 -> SYS::randomInt -> $ + 1 -> collatz-sequence -> '$; ' -> !OUT::write +' +' -> !OUT::write + +// Collatz sequence formatted ten per line by an indexed list template +// Note the square brackets creates a list of the enclosed pipeline results +// The \[i]( to \) defines a templates to apply to each value of a list, +// the i (or whatever identifier you choose) holds the index +[1000 -> SYS::randomInt -> $ + 1 -> collatz-sequence] +-> \[i]( + when <=1|?($i mod 10 <=0>)> do '$;$#10;' ! + otherwise '$; ' ! +\)... -> !OUT::write + +// A range can have an optional stride +def odd-numbers: [1..100:2]; + +// Use mutable state locally. One variable per templates, always called @ +templates product + @: $(first); + $(first~..last)... -> @: $@ * $; + $@ ! +end product + +$odd-numbers(6..8) -> product -> !OUT::write +' +' -> !OUT::write + +// Use processor objects to hold mutable state. +// Note that the outer @ must be referred to by name in inner contexts +// A sink templates gives no output and is called prefixed by ! +// A source templates takes no input and is called prefixed by $ +processor Product + @: 1; + sink accumulate + @Product: $@Product * $; + end accumulate + source result + $@Product ! + end result +end Product + +// The processor is a constructor templates. This one called with $ (no input) +def multiplier: $Product; + +// Call object templates by sending messages with :: +1..7 -> !multiplier::accumulate +-1 -> !multiplier::accumulate +$multiplier::result -> 'The product is $; +' -> !OUT::write + +// Syntax sugar for a processor implementing the collector interface +1..7 -> ..=Product -> 'The collected product is $;$#10;' -> !OUT::write + +// Symbol sets (essentially enums) can be defined for finite sets of values +data colour #{green, red, blue, yellow} + +// Use processor typestates to model state cleanly. +// The last named mutable state value set determines the typestate +processor Lamp + def colours: $; + @Off: 0; + state Off + source switchOn + @On: $@Off mod $colours::length + 1; + 'Shining a $colours($@On); light$#10;' ! + end switchOn + end Off + state On + source turnOff + @Off: $@On; + 'Lamp is off$#10;' ! + end turnOff + end On +end Lamp + +def myLamp: [colour#green, colour#blue] -> Lamp; + +$myLamp::switchOn -> !OUT::write // Shining a green light +$myLamp::turnOff -> !OUT::write // Lamp is off +$myLamp::switchOn -> !OUT::write // Shining a blue light +$myLamp::turnOff -> !OUT::write // Lamp is off +$myLamp::switchOn -> !OUT::write // Shining a green light + +// Use regular expressions to test strings +['banana', 'apple', 'pear', 'cherry']... -> \( + when <'.*a.*'> do '$; contains an ''a''' ! + otherwise '$; has no ''a''' ! +\) -> '$; +' -> !OUT::write + +// Use composers with regular expressions and defined rules to parse strings +composer parse-stock-line + {inventory-id: <INT> (<WS>), name: <'\w+'> (<WS>), currency: <'.{3}'>, + unit-price: <INT> (<WS>?) <parts>?} + rule parts: associated-parts: [<part>+] + rule part: <'[A-Z]\d+'> (<=','>?) +end parse-stock-line + +'705 gizmo EUR5 A67,G456,B32' -> parse-stock-line -> !OUT::write +// {associated-parts: [A67, G456, B32], currency: EUR, +// inventory-id: 705, name: gizmo, unit-price: 5} +' +' -> !OUT::write + +// Stream a string to split it into glyphs. +// A list can be indexed/sliced by an array of indexes +// Outputs ['h','e','l','l','o'], indexing arrays/lists starts at 1 +['abcdefghijklmnopqrstuvwxyz'...] -> $([8,5,12,12,15]) -> !OUT::write +' +' -> !OUT::write + +// We have used only raw strings above. +// Strings can have different types as determined by a tag. +// Comparing different types is an error, unless a wider type bound is set +// Type bound is given in ´´ and '' means any string value, tagged or raw +templates get-string-type + when <´''´ '.*'> do '$; is a raw string' ! + when <´''´ id´'\d+'> do '$; is a numeric id string' ! + when <´''´ =id´'foo'> do 'id foo found' ! + when <´''´ id´'.*'> do '$; is an id' ! + when <´''´ name´'.+'> do '$; is a name' ! + otherwise '$; is not a name or id, nor a raw string' ! +end get-string-type + +[name´'Anna', 'foo', id´'789', city´'London', id´'xzgh', id´'foo']... +-> get-string-type -> '$; +' -> !OUT::write + +// Numbers can be raw, tagged or have a unit of measure +// Type .. is any numeric value, tagged, measure or raw +templates get-number-type + when <´..´ =inventory-id´86> do 'inventory-id 86 found' ! + when <´..´ inventory-id´100..> do '$; is an inventory-id >= 100' ! + when <´..´ inventory-id´0..|..inventory-id´0> do '$; is an inventory-id' ! + when <´..´ 0"m"..> do '$; is an m-measure >= 0"m"' ! + when <´..´ ..0|0..> do '$; is a raw number' ! + otherwise '$; is not a positive m-measure nor an inventory-id, nor raw' ! +end get-number-type + +[inventory-id´86, inventory-id´6, 78"m", 5"s", 99, inventory-id´654]... +-> get-number-type -> '$; +' -> !OUT::write + +// Measures can be used in arithmetic, "1" is the scalar unit +// When mixing measures you have to cast to the result measure +4"m" + 6"m" * 3"1" -> ($ ~/ 2"s")"m/s" -> '$; +' -> !OUT::write + +// Tagged identifiers must be made into raw numbers when used in arithmetic +// Then you can cast the result back to a tagged identifier if you like +inventory-id´300 -> inventory-id´($::raw + 1) -> get-number-type -> '$; +' -> !OUT::write + +// Fields get auto-typed, tagging raw strings or numbers by default +// You cannot assign the wrong type to a field +def item: { inventory-id: 23, name: 'thingy', length: 12"m" }; + +'Field inventory-id $item.inventory-id -> get-number-type; +' -> !OUT::write +'Field name $item.name -> get-string-type; +' -> !OUT::write +'Field length $item.length -> get-number-type; +' -> !OUT::write + +// You can define types and use as type-tests. This also defines a field. +// It would be an error to assign a non-standard plate to a standard-plate field +data standard-plate <'[A-Z]{3}[0-9]{3}'> + +[['Audi', 'XYZ345'], ['BMW', 'I O U']]... -> \( + when <?($(2) <standard-plate>)> do {make: $(1), standard-plate: $(2)}! + otherwise {make: $(1), vanity-plate: $(2)}! +\) -> '$; +' -> !OUT::write + +// You can define union types +data age <"years"|"months"> + +[ {name: 'Cesar', age: 20"years"}, + {name: 'Francesca', age: 19"years"}, + {name: 'Bobby', age: 11"months"}]... +-> \( +// Conditional tests on structures look a lot like literals, with field tests + when <{age: <13"years"..19"years">}> do '$.name; is a teenager'! + when <{age: <"months">}> do '$.name; is a baby'! +// You don't need to handle all cases, 'Cesar' will just be ignored +\) -> '$; +' -> !OUT::write + +// Array/list indexes start at 1 by default, but you can choose +// Slices return whatever overlaps with the actual array +[1..5] -> $(-2..2) -> '$; +' -> !OUT::write // Outputs [1,2] +0:[1..5] -> $(-2..2) -> '$; +' -> !OUT::write // Outputs [1,2,3] +-2:[1..5] -> $(-2..2) -> '$; +' -> !OUT::write // Outputs [1,2,3,4,5] + +// Arrays can have indexes of measures or tagged identifiers +def game-map: 0"y":[ + 1..5 -> 0"x":[ + 1..5 -> level´1:[ + 1..3 -> { + level: $, + terrain-id: 6 -> SYS::randomInt, + altitude: (10 -> SYS::randomInt)"m" + } + ] + ] +]; + +// Projections (indexing) can span several dimensions +$game-map(3"y"; 1"x"..3"x"; level´1; altitude:) -> '$; +' -> !OUT::write // Gives a list of three altitude values + +// Flatten and do a grouping projection to get stats +// Count and Max are built-in collector processors +[$game-map... ... ...] -> $(collect { + occurences: Count, + highest-on-level: Max&{by: :(altitude:), select: :(level:)} + } by $({terrain-id:})) +-> !OUT::write +' +' -> !OUT::write + +// Relations are sets of structures/records. +// Here we get all unique {level:, terrain-id:, altitude:} combinations +def location-types: {|$game-map... ... ...|}; + +// Projections can re-map structures. Note § is the relative accessor +$location-types({terrain-id:, foo: §.level::raw * §.altitude}) +-> '$; +' -> !OUT::write + +// Relational algebra operators can be used on relations +($location-types join {| {altitude: 3"m"} |}) +-> !OUT::write +' +' -> !OUT::write + +// Define your own operators for binary operations +operator (left dot right) + $left -> \[i]($ * $right($i)!\)... -> ..=Sum&{of: :()} ! +end dot + +([1,2,3] dot [2,5,8]) -> 'dot product: $; +' -> !OUT::write + +// Supply parameters to vary templates behaviour +templates die-rolls&{sides:} + 1..$ -> $sides::raw -> SYS::randomInt -> $ + 1 ! +end die-rolls + +[5 -> die-rolls&{sides:4}] -> '$; +' -> !OUT::write + +// Pass templates as parameters, maybe with some parameters pre-filled +source damage-roll&{first:, second:, third:} + (1 -> first) + (1 -> second) + (1 -> third) ! +end damage-roll + +$damage-roll&{first: die-rolls&{sides:4}, + second: die-rolls&{sides:6}, third: die-rolls&{sides:20}} +-> 'Damage done is $; +' -> !OUT::write + +// Write tests inline. Run by --test flag on command line +// Note the ~ in the matcher means "not", +// and the array content matcher matches elements < 1 and > 4 +test 'die-rolls' + assert [100 -> die-rolls&{sides: 4}] <~[<..~1|4~..>]> 'all rolls 1..4' +end 'die-rolls' + +// Provide modified modules to tests (aka test doubles or mocks) +// IN is the standard input object and ::lines gets all lines +source read-numbers + $IN::lines -> # + when <'\d+'> do $! +end read-numbers + +test 'read numbers from input' + use shadowed core-system/ + processor MockIn + source lines + [ + '12a', + '65', + 'abc' + ]... ! + end lines + end MockIn + def IN: $MockIn; + end core-system/ + assert $read-numbers <=65> 'Only 65 is read' +end 'read numbers from input' + +// You can work with byte arrays +composer hexToBytes + <HEX> +end hexToBytes + +'1a5c678d' -> hexToBytes -> ($ and [x 07 x]) -> $(last-1..last) -> '$; +' -> !OUT::write // Outputs 0005 + +``` + +## Further Reading + +- [Main Tailspin site](https://github.com/tobega/tailspin-v0/) +- [Tailspin language reference](https://github.com/tobega/tailspin-v0/blob/master/TailspinReference.md) diff --git a/tcl.html.markdown b/tcl.html.markdown index 3d23870b..51e8651c 100644 --- a/tcl.html.markdown +++ b/tcl.html.markdown @@ -273,7 +273,7 @@ namespace eval people::person1 { ############################################################################### -## 4. Built-in Routines +## 5. Built-in Routines ############################################################################### # Math can be done with the "expr": @@ -308,7 +308,7 @@ set result [+ 5 3] set name Neo expr {{Bob} eq $name} -# The general operators fall back to string string comparison if numeric +# The general operators fall back to string comparison if numeric # operation isn't feasible: expr {{Bob} == $name} diff --git a/tcsh.html.markdown b/tcsh.html.markdown index e38b7a27..8f8429bc 100644 --- a/tcsh.html.markdown +++ b/tcsh.html.markdown @@ -28,23 +28,23 @@ Some more files: ```tcsh #!/bin/tcsh -# First line of the script is shebang which tells the system how to execute the -# script: http://en.wikipedia.org/wiki/Shebang_(Unix) -# TCSH emulates the shebang on systems which don't understand it. +# The first line of the script is a shebang which tells the system how to execute +# the script: http://en.wikipedia.org/wiki/Shebang_(Unix) +# TCSH emulates the shebang on systems that don't understand it. -# In most cases you'll use `#!/bin/tcsh -f', because `-f' option does not load +# In most cases you'll use `#!/bin/tcsh -f`, because `-f` option does not load # any resource or start-up files, or perform any command hashing, and thus # starts faster. # --- the echo command -------------------------------------------------------- -# The `echo' writes each word to the shell's standard output, separated by +# The `echo` writes each word to the shell's standard output, separated by # spaces and terminated with a newline. The echo_style shell variable may be # set to emulate (or not) the flags and escape sequences. # Display the value of echo_style echo $echo_style -# Enable `echo' to support backslashed characters and `-n' option (no new line) +# Enable `echo` to support backslashed characters and `-n` option (no new line) # This is the default for tcsh, but your distro may change it. Slackware has # done so. set echo_style = both @@ -65,17 +65,17 @@ echo 'two\nlines' # --- Basic Syntax ------------------------------------------------------------ # A special character (including a blank or tab) may be prevented from having -# its special meaning by preceding it with a backslash `\'. -# this will display the last history commands +# its special meaning by preceding it with a backslash `\`. +# This will display the last history commands echo !! -# this will not +# This will not echo \!\! -# Single quotes prevents expanding special characters too, but some -# characters like `!' and backslash have higher priority -# `$' (variable value) will not expands +# Single quotes prevent expanding special characters too, but some +# characters like `!` and backslash have higher priority +# `$` (variable value) will not expand echo '$1 tip' -# `!' (history) will expands +# `!` (history) will expand echo '!!' # Strings enclosed by back-quotes will be executed and replaced by the result. @@ -85,16 +85,16 @@ echo `ls` echo 'first line'; echo 'second line' # There is also conditional execution -echo "Always executed" || echo "Only executed if first command fails" -echo "Always executed" && echo "Only executed if first command does NOT fail" +echo "Always executed" || echo "Only executed if the first command fails" +echo "Always executed" && echo "Only executed if the first command does NOT fail" # Parenthesised commands are always executed in a subshell, -# example: create a project and then informs you that it finished while +# example: creates a project and then informs you that it finished while # it does the installation. make && ( espeak "BOSS, compilation finished"; make install ) -# prints the home directory but leaving you where you were +# prints the home directory but leaves you where you were (cd; pwd); pwd # Read tcsh man-page documentation @@ -103,10 +103,10 @@ man tcsh # --- Variables --------------------------------------------------------------- # The shell maintains a list of variables, each of which has as value a list of # zero or more words. The values of shell variables can be displayed and -# changed with the `set' and `unset' commands. -# The system maintains its own list of ``environment'' variables. -# These can be displayed and changed with `printenv', `setenv' and `unsetenv'. -# The syntax of setenv is similar to POSIX sh. +# changed with the `set` and `unset` commands. +# The system maintains its own list of "environment" variables. +# These can be displayed and changed with `printenv`, `setenv`, and `unsetenv`. +# The syntax of `setenv` is similar to POSIX sh. # Assign a value or nothing will create a variable # Assign nothing @@ -122,7 +122,7 @@ set var = `ls` # Remove a variable unset var -# Prints 1 (true) if the variable `var' exists otherwise prints 0 (false) +# Prints 1 (true) if the variable `var` exists otherwise prints 0 (false) echo $?var # Print all variables and their values set @@ -130,10 +130,10 @@ set # Prints the contents of 'var' echo $var; echo "$var"; -# Prints the string `$var' +# Prints the string `$var` echo \$var echo '$var' -# braces can be used to separate variable from the rest when its needed +# Braces can be used to separate variables from the rest when it is needed set num = 12; echo "There ${num}th element" # Prints the number of characters of the value: 6 @@ -147,7 +147,7 @@ echo $var echo $var[*] # Print the count of elements: 5 echo $#var -# Print indexed element; prints the second element: two +# Print the indexed element; This prints the second element: two echo $var[2] # Print range of elements; prints 2nd up to 3rd: two, three echo $var[2-3] @@ -165,8 +165,8 @@ echo $var[-3] # $! the PID of the last background process started by this shell # $$ script's PID -# $path, $PATH the list of directories that will search for executable to run -# $home, $HOME user's home directory, also the `~' can be used instead +# $path, $PATH the list of directories that will search for an executable to run +# $home, $HOME user's home directory, also the `~` can be used instead # $uid user's login ID # $user user's login name # $gid the user's group ID @@ -174,24 +174,24 @@ echo $var[-3] # $cwd, $PWD the Current/Print Working Directory # $owd the previous working directory # $tcsh tcsh version -# $tty the current tty; ttyN for linux console, pts/N for terminal +# $tty the current tty; ttyN for Linux console, pts/N for terminal # emulators under X # $term the terminal type # $verbose if set, causes the words of each command to be printed. -# can be set by the `-v' command line option too. +# can be set by the `-v` command line option too. # $loginsh if set, it is a login shell # TIP: $?0 is always false in interactive shells # TIP: $?prompt is always false in non-interactive shells -# TIP: if `$?tcsh' is unset; you run the original `csh' or something else; -# try `echo $shell' -# TIP: $verbose this is useful to debugging scripts -# NOTE: $PWD and $PATH are synchronised with $cwd and $pwd automatically. +# TIP: if `$?tcsh` is unset; you run the original `csh` or something else; +# try `echo $shell` +# TIP: `$verbose` is useful for debugging scripts +# NOTE: `$PWD` and `$PATH` are synchronised with `$cwd` and `$pwd` automatically. # --- Variable modifiers ------------------------------------------------------ # Syntax: ${var}:m[:mN] # Where <m> is: -# h : the directory t : the filenane r : remove extension e : the extension +# h : the directory t : the filename r : remove extension e : the extension # u : uppercase the first lowercase letter # l : lowercase the first uppercase letter # p : print but do not execute it (hist) @@ -199,8 +199,8 @@ echo $var[-3] # x : like q, but break into words at white spaces # g : apply the following modifier once to each word # a : apply the following modifier as many times as possible to single word -# s/l/r/ : search for `l' and replace with `r', not regex; the `&' in the r is -# replaced by l +# s/l/r/ : search for `l` and replace with `r`, not regex; the `&` in the `r` is +# replaced by `l` # & : Repeat the previous substitution # start with this file @@ -232,7 +232,7 @@ echo 'this string' >> file.txt echo 'this string' >>& file.txt # Redirect the standard input from file.txt cat < file.txt -# Input from keyboard; this stores the input line to variable `x' +# Input from keyboard; this stores the input line to variable `x` set x = $< # Document here; cat << LABEL @@ -243,7 +243,7 @@ LABEL (grep 'AGP' /usr/src/linux/Documentation/* > output-file.txt) >& error-file.txt # example: read a name from standard input and display a greetings message -echo -n "Enter your name? " +echo -n "Enter your name: " set name = $< echo "Greetings $name" @@ -266,15 +266,15 @@ if ( $name != $user ) echo "Your name isn't your username" # NOTE: if $name is empty, tcsh sees the above condition as: # if ( != $user ) ... # which is invalid syntax -# so the "safe" way to use potentially empty variables in tcsh is: +# The "safe" way to use potentially empty variables in tcsh is: # if ( "$name" != $user ) ... # which, when $name is empty, is seen by tcsh as: # if ( "" != $user ) ... # which works as expected # There is also conditional execution -echo "Always executed" || echo "Only executed if first command fails" -echo "Always executed" && echo "Only executed if first command does NOT fail" +echo "Always executed" || echo "Only executed if the first command fails" +echo "Always executed" && echo "Only executed if the first command does NOT fail" # To use && and || with if statements, you don't need multiple pairs of # square brackets: @@ -286,14 +286,14 @@ if ( "$name" == "Daniya" || "$name" == "Zach" ) then echo "This will run if $name is Daniya OR Zach." endif -# String matching operators ( `=~' and `!~' ) +# String matching operators ( `=~` and `!~` ) # The ‘==’ ‘!=’ ‘=~’ and ‘!~’ operators compare their arguments as strings; # all others operate on numbers. The operators ‘=~’ and ‘!~’ are like ‘!=’ # and ‘==’ except that the right hand side is a glob-pattern against which -# the left hand operand is matched. +# the left-hand operand is matched. if ( $user =~ ni[ck]* ) echo "Greetings Mr. Nicholas." -if ( $user !~ ni[ck]* ) echo "Hey, get out of Nicholas PC." +if ( $user !~ ni[ck]* ) echo "Hey, get out of Nicholas' PC." # Arithmetic expressions are denoted with the following format: @ result = 10 + 5 @@ -302,16 +302,16 @@ echo $result # Arithmetic Operators # +, -, *, /, % # -# Arithmetic Operators which must be parenthesised +# Arithmetic Operators which must be parenthesized # !, ~, |, &, ^, ~, <<, >>, # Compare and logical operators # -# All operators are same as in C. +# All operators are the same as in C. # It is non so well documented that numeric expressions require spaces -# in-between; Also, `@' has its own parser, it seems that work well when the -# expression is parenthesised otherwise the primary parser seems it is active. -# Parenthesis require spaces around, this is documented. +# in-between; Also, `@` has its own parser, it seems that it works well when +# the expression is parenthesized, otherwise the primary parser seems to be +# active. Parentheses require spaces around, this is documented. # wrong @ x = $y+1 @@ -330,32 +330,32 @@ echo $result # C's operators ++ and -- are supported if there is not assignment @ result ++ -# None shell created to do mathematics; +# No shell was created to do mathematics; # Except for the basic operations, use an external command with backslashes. # # I suggest the calc as the best option. # (http://www.isthe.com/chongo/tech/comp/calc/) # -# The standard Unix's bc as second option +# The standard Unix's bc as the second option # (https://www.gnu.org/software/bc/manual/html_mono/bc.html) # -# The standard Unix's AWK as third option +# The standard Unix's AWK as the third option # (https://www.gnu.org/software/gawk/manual/gawk.html) -# You can also use `perl', `php' or even several BASICs, but prefer the -# above utilities for faster load-and-run results. +# You can also use `Perl`, `PHP`, `python`, or even several BASICs, but prefer +# the above utilities for faster load-and-run results. # real example: (that I answer in StackExchange) # REQ: x := 1001b OR 0110b -# in `tcsh' expression (by using octal) +# in `tcsh` expression (by using octal) @ x = ( 011 | 06 ); echo $x -# the same by using `calc' (and using binary as the original req) +# the same by using `calc` (and using binary as the original req) set x = `calc '0b1001 | 0b110'`; echo $x # --- File Inquiry Operators -------------------------------------------------- -# NOTE: The builtin `filetest' command do the same thing. +# NOTE: The built-in `filetest` command does the same thing. #### Boolean operators # -r read access -w write access -x execute access -e existence @@ -366,23 +366,23 @@ set x = `calc '0b1001 | 0b110'`; echo $x # -b block device -c char device # -t file (digit) is an open file descriptor for a terminal device -# if the file `README' exists, displays a message +# If the file `README` exists, display a message if ( -e README ) echo "I have already README file" -# if the `less' program is installed, use this instead of `more' +# If the `less` program is installed, use it instead of `more` if ( -e `where less` ) then - alias more 'less' + alias more 'less' endif #### Non-boolean operators # -Z returns the file size in bytes # -M returns the modification time (mtime) -M: returns mtime string -# -A returns the lass access time (atime) -A: returns atime string -# -U returns the owners user ID -U: returns the owners user-name -# -G returns the group ID -G: returns the group-name +# -A returns the last access time (atime) -A: returns atime string +# -U returns the owner's user ID -U: returns the owner's user name +# -G returns the owner's group ID -G: returns the owner's group name # -P returns the permissions as octal number -Pmode returns perm. AND mode -# this will display the date as Unix-time integer: 1498511486 +# this will display the date as a Unix-time integer: 1498511486 filetest -M README.md # This will display "Tue Jun 27 00:11:26 2017" @@ -390,14 +390,14 @@ filetest -M: README.md # --- Basic Commands ---------------------------------------------------------- -# Navigate though file system with `chdir' (cd) +# Navigate through the filesystem with `chdir` (cd) cd path # change working directory -cd # change to home directory -cd - # change to previous directory +cd # change to the home directory +cd - # change to the previous directory cd .. # go up one directory # Examples: -cd ~/Downloads # go to my `Downloads' directory +cd ~/Downloads # go to my `Downloads` directory # Use `mkdir` to create new directories. mkdir newdir @@ -413,7 +413,7 @@ where csh # --- Pipe-lines -------------------------------------------------------------- # A pipeline is a sequence of processes chained together by their standard # streams, so that the output of each process (stdout) feeds directly as input -# (stdin) to the next one. This `pipes' are created with the `|' special +# (stdin) to the next one. These `pipes` are created with the `|` special # character and it is one of the most powerful characteristics of Unix. # example: @@ -422,18 +422,18 @@ ls -l | grep key | less # input (stdin) of the process for "grep key"; and likewise for the process # for "less". -# the `ls', the `grep' and the `less' are programs of Unix and they have their -# own man-page. The `pipe' mechanism is part of the kernel but the syntax -# and the control is job of the shell, the tcsh in our case. +# the `ls`, the `grep`, and the `less` are Unix programs and they have their +# own man-page. The `pipe` mechanism is part of the kernel but the syntax +# and the control is the shell's job, the tcsh in our case. -# NOTE: `pipe' mechanism has Windows too, but it is buggy and I sign it for all -# versions until Windows XP SP3 API32 which was the last one that I worked on. -# Microsoft still denied it but is well known bug since it is a common method -# for inter-process communication. For small I/O it will work well. -# tcsh, along with grep, gcc and perl is one of the first Unix programs that +# NOTE: Windows has the `pipe` mechanism too, but it is buggy and I signed it +# for all versions until Windows XP SP3 API32 which was the last one that I +# worked on. Microsoft denied it, but it is a well-known bug since it is a +# common method for inter-process communication. For small I/O it will work well. +# tcsh, along with grep, GCC, and Perl is one of the first Unix programs that # ported to DOS (with EMX DOS extender) and later to Windows (1998). -# example: this will convert tcsh to PostScript and will show it with okular +# example: this will convert tcsh to PostScript and will show it with Okular zcat /usr/man/man1/tcsh.1.gz | groff -Tps -man | okular - # a better version @@ -451,10 +451,10 @@ set page = tcsh; set loc = (locate -b -n 1 "\\\\"${page}".1.gz"); set page = tcsh; set loc = (locate -b -n 1 "\\\\"${page}".1.gz"); zcat `eval $loc` | groff -Tps -man | ps2pdf - ${page}.pdf && okular tcsh.pdf -# NOTE: `okular' is the default application of KDE environment and it shows -# postcript and pdf files. You can replace it with your lovely pdf viewer. -# zcat, locate, groff, are common programs in all Unices. `ps2pdf' program -# is part of `ghostscript' package that is widely used. +# NOTE: `okular` is the default application of the KDE environment and it shows +# postcript and pdf files. You can replace it with your lovely PDF viewer. +# `zcat`, `locate`, `groff`, are common programs in all Unixes. The `ps2pdf` +# program is part of the `ghostscript` package that is widely used. # --- Control Flow ------------------------------------------------------------ @@ -468,8 +468,8 @@ set page = tcsh; set loc = (locate -b -n 1 "\\\\"${page}".1.gz"); # ...] # endif # -# If the specified expr is true then the commands to the first else are -# executed; otherwise if expr2 is true then the commands to the second else +# If the specified `expr` is true then the commands to the first else are +# executed; otherwise if `expr2` is true then the commands to the second else # are executed, etc. # Any number of else-if pairs are possible; only one endif is needed. # @@ -477,24 +477,24 @@ set page = tcsh; set loc = (locate -b -n 1 "\\\\"${page}".1.gz"); # # if ( expr ) command # -# If `expr' evaluates true, then command is executed. -# `command' must be a simple command, not an alias, a pipeline, a command list -# or a parenthesized command list. With few words, avoid to use it. +# If `expr` evaluates to true, then the command is executed. +# `command` must be a simple command, not an alias, a pipeline, a command list +#, or a parenthesized command list. With a few words, avoid using it. # -# BUG: Input/output redirection occurs even if expr is false and command is -# thus not executed. +# BUG: Input/output redirection occurs even if expr is false and the command +# is thus not executed. # -# check if we are in non-interactive shell and quit if true +# check if we are in a non-interactive shell and quit if true if ( $?USER == 0 || $?prompt == 0 ) exit # check if we are a login shell if ( $?loginsh ) then - # check if you are on linux console (not X's terminal) - if ( $tty =~ tty* ) then - # enable keypad application keys (man console_codes) - echo '\033=' - endif + # check if you are on linux console (not X's terminal) + if ( $tty =~ tty* ) then + # enable keypad application keys (man console_codes) + echo '\033=' + endif endif #### SWITCH-ENDSW @@ -509,37 +509,37 @@ endif # # tcsh uses a case statement that works similarly to switch in C. # Each case label is successively matched, against the specified string which -# is first command and filename expanded. The file metacharacters `*', `?' -# and `[...]' may be used in the case labels. If none of the labels match the -# execution begins after the default label if its defined. -# The command `breaksw' causes execution to continue after the endsw. Otherwise +# is first command and filename expanded. The file metacharacters `*`, `?` +# and `[...]` may be used in the case labels. If none of the labels match the +# execution begins after the default label if it's defined. +# The command `breaksw` causes execution to continue after the endsw. Otherwise, # control may fall through case labels and default labels as in C. switch ( $var ) case *.[1-9]: case *.[1-9].gz: - echo "$var is a man-page." - breaksw + echo "$var is a man-page." + breaksw case *gz: - echo "$var is gzipped" - breaksw + echo "$var is gzipped" + breaksw default: - file $var + file $var endsw #### FOREACH-END # Syntax: # foreach name ( wordlist ) -# ... +# ... # [break | continue] # end # -# Successively sets the variable `name' to each member of `wordlist' and +# Successively sets the variable `name` to each member of `wordlist` and # executes the sequence of commands between this command and the matching -# `end' keyword. The `continue' keyword jump to the next element back to -# top; and the `break' keyword terminates the loop. +# `end` keyword. The `continue` keyword jumps to the next element back to +# top, and the `break` keyword terminates the loop. # -# BUG: `foreach' doesn't ignore here documents when looking for its end. +# BUG: `foreach` doesn't ignore here documents when looking for its end. # example: counting 1 to 10 foreach i ( `seq 1 10` ) @@ -548,12 +548,12 @@ end # example: type all files in the list foreach f ( a.txt b.txt c.txt ) - cat $f + cat $f end # example: convert wma to ogg foreach f ( *.wma ) - ffmpeg -i "$f" "$f:r".ogg + ffmpeg -i "$f" "$f:r".ogg end #### WHILE-END @@ -562,22 +562,22 @@ end # [break | continue] # end # -# Executes the commands between the `while' and the matching `end' while `expr' -# evaluates non-zero. `break' and `continue' may be used to terminate or +# Executes the commands between the `while` and the matching `end` while `expr` +# evaluates non-zero. `break` and `continue` may be used to terminate or # continue the loop prematurely. # count from 1 to 10 set num = 1 while ( $num <= 10 ) - echo $num - @ num ++ + echo $num + @ num ++ end # print all directories of CWD set lst = ( * ) while ( $#lst ) - if ( -d $lst[1] ) echo $lst[1] is directory - shift lst + if ( -d $lst[1] ) echo $lst[1] is directory + shift lst end # separate command-line arguments to options or parameters @@ -585,12 +585,12 @@ set options set params set lst = ( $* ) while ( $#lst ) - if ( "$lst[1]" =~ '-*' ) then - set options = ( $options $lst[1] ) - else - set params = ( $params $lst[1] ) - endif - shift lst + if ( "$lst[1]" =~ '-*' ) then + set options = ( $options $lst[1] ) + else + set params = ( $params $lst[1] ) + endif + shift lst end echo 'options =' $options echo 'parameters =' $params @@ -599,16 +599,16 @@ echo 'parameters =' $params # Syntax: repeat count command # # The specified command, which is subject to the same restrictions as the -# command in the one line if statement above, is executed count times. -# I/O redirections occur exactly once, even if count is 0. +# command in the one line `if` statement above, is executed count times. +# I/O redirections occur exactly once, even if `count` is 0. # -# TIP: in most cases prefer `while' +# TIP: in most cases prefer `while` repeat 3 echo "ding dong" # --- Functions --------------------------------------------------------------- # tcsh has no functions but its expression syntax is advanced enough to use -# `alias' as functions. Another method is recursion +# `alias` as functions. Another method is recursion # Alias argument selectors; the ability to define an alias to take arguments # supplied to it and apply them to the commands that it refers to. @@ -637,48 +637,48 @@ alias cd 'cd \!* && ls' #!/bin/tcsh -f set todo = option1 if ( $#argv > 0 ) then - set todo = $argv[1] + set todo = $argv[1] endif switch ( $todo ) case option1: -# ... - $0 results - breaksw +# ... + $0 results + breaksw case option2: -# ... - $0 results - breaksw +# ... + $0 results + breaksw case results: - echo "print the results here" -# ... - breaksw + echo "print the results here" +# ... + breaksw default: - echo "Unknown option: $todo" -# exit 0 + echo "Unknown option: $todo" +# exit 0 endsw # --- Recursion method --- end --- # --- examples ---------------------------------------------------------------- # this script prints available power-states if no argument is set; -# otherwise it set the state of the $argv[1] +# otherwise it sets the state of the $argv[1] # --- power-state script --- begin -------------------------------------------- #!/bin/tcsh -f # get parameter ("help" for none) set todo = help if ( $#argv > 0 ) then - set todo = $argv[1] + set todo = $argv[1] endif # available options set opts = `cat /sys/power/state` # is known? foreach o ( $opts ) - if ( $todo == $o ) then - # found; execute it - echo -n $todo > /sys/power/state - break - endif + if ( $todo == $o ) then + # found; execute it + echo -n $todo > /sys/power/state + break + endif end # print help and exit echo "usage: $0 [option]" @@ -691,19 +691,19 @@ echo "available options on kernel: $opts" set secret=`shuf -i1-100 -n1` echo "I have a secret number from 1 up to 100" while ( 1 ) - echo -n "Guess: " - set guess = $< - if ( $secret == $guess ) then - echo "You found it" - exit 1 - else - if ( $secret > $guess ) then - echo "its greater" - else if ( $secret < $guess ) then - echo "its lesser" - endif - endif - endif + echo -n "Guess: " + set guess = $< + if ( $secret == $guess ) then + echo "You found it" + exit 1 + else + if ( $secret > $guess ) then + echo "its greater" + else if ( $secret < $guess ) then + echo "its lesser" + endif + endif + endif end # --- secretnum.csh --- end --------------------------------------------------- @@ -711,36 +711,36 @@ end # Appendices #### About [T]CSH: -# * CSH is notorious about its bugs; -# * It was also famous about its advanced interactive mode. -# * TCSH is famous that have the most advanced completition subsystem. -# * TCSH is famous that have the most advanced aliases subsystem; aliases -# can take parameters and often used as functions! -# * TCSH is well known that preferred by people (me too) because of better -# syntax. All shells are using Thomson's syntax with exception of [t]csh, -# fish and plan9's shells (rc, ex). -# * It is smaller and consume far less memory than bash, zsh even mksh! +# * CSH is notorious for its bugs; +# * It is also famous for its advanced interactive mode. +# * TCSH is famous for having the most advanced completion subsystem. +# * TCSH is famous for having the most advanced aliases subsystem; aliases +# can take parameters and often be used as functions! +# * TCSH is well known and preferred by people (me too) because of better +# syntax. All shells are using Thomson's syntax with the exception of +# [t]csh, fish, and plan9's shells (rc, ex). +# * It is smaller and consumes far less memory than bash, zsh, and even mksh! # (memusage reports) -# * TCSH still has bugs; less but have; if you write readable clean code you'll -# find none; well almost none... This has to do with the implementation of -# csh; that no means the other shells has good implementation. -# * no one well known shell is capable for regular programming; if your script -# getting big, use a programming language, or at least PHP or Perl (good -# script languages). +# * TCSH still has bugs; fewer, but it does; if you write readable clean code +# you'll find none; well almost none... This has to do with the implementation +# of csh; that doesn't mean the other shells have a good implementation. +# * no well-known shell is capable of regular programming; if your script +# is getting big, use a programming language, like Python, PHP, or Perl (good +# scripting languages). # -# Advises: -# 1. Do not use redirection in single-line if (it is well documented bug) -# In most cases avoid to use single-line IFs. -# 2. Do not mess up with other shells code, c-shell is not compatible with +# Advice: +# 1. Do not use redirection in single-line IFs (it is well documented bug) +# In most cases avoid using single-line IFs. +# 2. Do not mess up with other shells' code, c-shell is not compatible with # other shells and has different abilities and priorities. # 3. Use spaces as you'll use them to write readable code in any language. -# A bug of csh was `set x=1' worked, `set x = 1' worked, `set x =1' did not! -# 4. It is well documented that numeric expressions require spaces in-between; -# also parenthesise all bit-wise and unary operators. -# 5. Do not write a huge weird expression with several quotes, backslashes etc +# A bug of csh was `set x=1` and `set x = 1` worked, but `set x =1` did not! +# 4. It is well documented that numeric expressions require spaces in between; +# also parenthesize all bit-wise and unary operators. +# 5. Do not write a huge weird expression with several quotes, backslashes, etc # It is bad practice for generic programming, it is dangerous in any shell. # 6. Help tcsh, report the bug here <https://bugs.gw.com/> -# 7. Read the man page, `tcsh' has huge number of options, and variables. +# 7. Read the man page, `tcsh` has a huge number of options and variables. # # I suggest the following options enabled by default # -------------------------------------------------- @@ -770,14 +770,14 @@ end # unset time # unset tperiod # -# NOTE: If the `backslash_quote' is set, it may create compatibility issues -# with other tcsh scripts which was written without it. +# NOTE: If the `backslash_quote` is set, it may create compatibility issues +# with other tcsh scripts that were written without it. # -# NOTE: The same for `parseoctal', but it is better to fix the problematic +# NOTE: The same for `parseoctal`, but it is better to fix the problematic # scripts. # # NOTE: **for beginners only** -# This enable automatically rescan `path' directories if need to. (like bash) +# This enables automatic rescanning of `path` directories if needed. (like bash) # set autorehash #### common aliases diff --git a/texinfo.html.markdown b/texinfo.html.markdown new file mode 100644 index 00000000..1b3ed9e2 --- /dev/null +++ b/texinfo.html.markdown @@ -0,0 +1,183 @@ +--- +language: Texinfo +contributors: + - ["Julien Lepiller", "https://github.com/roptat"] +filename: learntexinfo.texi +--- + +Texinfo is a documentation format you can use to create various types of +documents from the same source. Its main usage is to create documentation +manuals and info pages for GNU projects. + +Texinfo is a markup language that contains text and *@-commands* that specify +what the generator should do. + +## Initial File + +A simple example of a simple manual: + +``` +\input texinfo +@setfilename simple-document.info +@documentencoding UTF-8 +@settitle simple-document +@c This is a comment +@c Replace simple-document above (twice) with the actual document title + +@c Automake will take care of version.texi +@include version.texi + +@copying +Copyright @copyright{} YEAR MY NAME + +@c GFDL is common for GNU projects +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +copy of the license is included in the section entitled ``GNU Free +Documentation License''. +@end quotation +@end copying + +@titlepage +@end titlepage + +@c Now starts the actual content +@contents + +@c The first node must always be Top +@node Top +@c And we give it a title +@top simple-document + +This document quickly describes Texinfo features. + +@c This is the ToC: +@menu +* Introduction:: A short summary of the chapter + +@detailmenu +--- The Detailed Node Listing --- + +Introduction + +* Formatting:: How to format text nicely +* Links:: Linking to other resources, pages, or manuals + +@end detailmenu +@end menu + +@node Introduction +@chapter Introduction + +Each node must have the same name as the menu item that was defined in the ToC. + +@node Formatting +@section Formatting +@c Add something to the content index, so people can get here when searching +@c for something else +@cindex bold text +@cindex titles + +Similar to chapters, sections must have the same name and appear in the same order. + +@subsection This is a subsection title +@subsubsection This is a sub-subsection title + +Each block of text is a paragraph. You can use multiple lines for the paragraph +like so, only empty lines separate paragraphs. + +Common formatting include @emph{emphasis}, @code{inline code}. Specific type of +text can be marked as well: @file{file.txt}, @option{--learn-fast}, +@command{ls} or @var{variable}. You can escape the command character like +so: @@, and a newline with a single @@ at the end of the line. + +You can add different types of blocks: + +@example +Here is an example +@end example + +@lisp +'(this is lisp code) +@end lisp + +@itemize +@item An element in an unordered list +@item A second element in the same list +@end itemize + +@enumerate +@item This list is similar +@item But ordered +@end enumerate + +@quotation +A quotation block, by someone famous maybe +@end quotation + +@table @asis +@item element title +element description + +@item second element title +second element description. Note that the description part can span multiple +paragraphs, contain other blocks etc. This is usually used as a definition +list. + +@code{@@asis} wraps the element title, and tells Texinfo to use them as-is. +@end table + +@table @code +@item do-x +This item title is now wrapped in a code block, as in @code{@@code{do-x}} +@end table + +@c content index can appear at any place in the document, not necessarily after +@c titles. +@cindex function definition +@deffn {Kind of Function} function_name @var{arg1} @var{arg2} @ + @var{arg3} @var{arg4} [@var{optional5}] +This text describes the function. Note how we could use multiple lines for the +function synopsis by escaping the line with a single @@. + +This again can contain multiple paragraphs or blocks. +@end deffn + +@node Links +@section Links + +There are various types of links you can use. A simple link to a URL with +@uref{https://github.com} and optionally with it a title: +@uref{https://github.com, GitHub}. An email address @email{me@@me.me}. +A node in this document, @xref{Introduction}. Always use the exact node name +for that one. @code{xref} will include the text ``see'' before the link. To +insert something different, use @pxref{Introduction} (``See'') or +@xref{Introduction} (nothing is inserted). With an additional argument, you +can change the text of the link, @xref{Introduction, this introduction}. + +It is possible to link to external manuals with these commands by adding +more arguments, as in @code{@@xref{Node name,,, manual-name, link text}}, +@xref{Overview,,, texinfo, Texinfo's manual} for the complete reference +on Texinfo! + +@bye +``` + +## How to Use It + +With `automake`, all you need to do is to give it the path to your manual +in `Makefile.am`: + +``` +info_TEXINFOS= doc/simple-manual.texi +``` + +Then, get your info manual with `make doc/simple-manual.info` or in other formats, +e.g. HTML with `make doc/simple-manual.html`. + +## Readings + +- [Official manual](https://www.gnu.org/software/texinfo/manual/texinfo/html_node/) diff --git a/textile.html.markdown b/textile.html.markdown index 2b81674a..293e647d 100644 --- a/textile.html.markdown +++ b/textile.html.markdown @@ -165,11 +165,11 @@ but again, they use different HTML markup and thus the distinction. ###. Superscripts and Subscripts use carats and tildes: -Superscripts are 2 ^nd^ to none, but subscripts are CO ~2~ L too. +Superscripts are 2 ^and^ to none, but subscripts are CO ~2~ L too. Note the spaces around the superscripts and subscripts. To avoid the spaces, add square brackets around them: -2[^nd^] and CO[~2~]L +2[^and^] and CO[~2~]L ###. Insertions and deletions are indicated using -/+ symbols: This is -deleted- text and this is +inserted+ text. @@ -375,7 +375,7 @@ table(tableclass). |a|classy|table| |a|classy|table| -###. Spanning rows and colums: +###. Spanning rows and columns: A backslash \ is used for a column span: |\2. spans two cols | diff --git a/th-th/typescript.th.html.markdown b/th-th/typescript.th.html.markdown index fc2a823b..5395c2a7 100644 --- a/th-th/typescript.th.html.markdown +++ b/th-th/typescript.th.html.markdown @@ -190,7 +190,7 @@ interface Person { } var p1: Person = { name: "Tyrone", age: 42 }; -p1.age = 25; // Error แน่นอน เพราะ p1.x ถูกกำหนดเป็น read-only +p1.age = 25; // Error แน่นอน เพราะ p1.age ถูกกำหนดเป็น read-only var p2 = { name: "John", age: 60 }; // สังเกตว่า p2 ไม่ได้กำหนดเป็น Person var p3: Person = p2; // ทำได้ เป็น read-only alias ของ p2 และกำหนดเป็น Person diff --git a/tmux.html.markdown b/tmux.html.markdown index 1c2c2da3..095e24fb 100644 --- a/tmux.html.markdown +++ b/tmux.html.markdown @@ -183,7 +183,7 @@ bind a send-prefix ### Theme ########################################################################### -# Statusbar Color Palatte +# Statusbar Color Palette set-option -g status-justify left set-option -g status-bg black set-option -g status-fg white diff --git a/toml.html.markdown b/toml.html.markdown index 385a2437..69dfd754 100755..100644 --- a/toml.html.markdown +++ b/toml.html.markdown @@ -12,7 +12,7 @@ It is an alternative to YAML and JSON. It aims to be more human friendly than JS Be warned, TOML's spec is still changing a lot. Until it's marked as 1.0, you should assume that it is unstable and act accordingly. This document follows TOML v0.4.0. -``` +```toml # Comments in TOML look like this. ################ @@ -69,11 +69,15 @@ The first newline is trimmed in raw strings. ########### ## Integers can start with a +, a - or nothing. -## Leading zeros are not allowed. Hex, octal, and binary forms are not allowed. +## Leading zeros are not allowed. +## Hex, octal, and binary forms are allowed. ## Values that cannot be expressed as a series of digits are not allowed. int1 = +42 int2 = 0 int3 = -21 +int4 = 0xdeadbeef +int5 = 0o755 +int6 = 0b11011100 integerRange = 64 ## You can use underscores to enhance readability. Each @@ -117,7 +121,7 @@ date4 = 1979-05-27 # without offset or time array1 = [ 1, 2, 3 ] array2 = [ "Commas", "are", "delimiters" ] -array3 = [ "Don't mixed", "different", "types" ] +array3 = [ "Don't mix", "different", "types" ] array4 = [ [ 1.2, 2.4 ], ["all", 'strings', """are the same""", '''type'''] ] array5 = [ "Whitespace", "is", "ignored" @@ -171,6 +175,9 @@ c = 1 [a] d = 2 +# Will generate the following in JSON: +# { "a": {"b": {"c": 1}, "d": 2 } } + # You cannot define any key or table more than once. Doing so is invalid. # DO NOT DO THIS @@ -220,7 +227,28 @@ emptyTableAreAllowed = true name = "Nail" sku = 284758393 color = "gray" +``` +The equivalent in JSON would be: + +```json +{ + "products": [ + { + "name": "array of table", + "sku": 7385594937, + "emptyTableAreAllowed": true + }, + {}, + { + "name": "Nail", + "sku": 284758393, + "color": "gray" + } + ] +} +``` +```toml # You can create nested arrays of tables as well. Each double-bracketed # sub-table will belong to the nearest table element above it. @@ -245,11 +273,13 @@ color = "gray" [[fruit.color]] name = "yellow" note = "I am an array item in banana fruit's table/map" + ``` -In JSON land, this code will be: +The equivalent in JSON would be: + +``` -```json { "fruit": [ { diff --git a/tr-tr/bf-tr.html.markdown b/tr-tr/bf-tr.html.markdown index e7015cd0..ef46f362 100644 --- a/tr-tr/bf-tr.html.markdown +++ b/tr-tr/bf-tr.html.markdown @@ -1,6 +1,6 @@ --- language: bf -filename: brainfuck-tr +filename: brainfuck-tr.bf contributors: - ["Prajit Ramachandran", "http://prajitr.github.io"] translators: diff --git a/tr-tr/c++-tr.html.markdown b/tr-tr/c++-tr.html.markdown index 9d65cf9c..c944f245 100644 --- a/tr-tr/c++-tr.html.markdown +++ b/tr-tr/c++-tr.html.markdown @@ -1,5 +1,5 @@ --- -language: c++ +language: C++ lang: tr-tr filename: learncpp-tr.cpp contributors: diff --git a/tr-tr/c-tr.html.markdown b/tr-tr/c-tr.html.markdown index 6042a609..05531d64 100644 --- a/tr-tr/c-tr.html.markdown +++ b/tr-tr/c-tr.html.markdown @@ -1,7 +1,7 @@ --- -name: c +name: C category: language -language: c +language: C filename: learnc-tr.c contributors: - ["Adam Bard", "http://adambard.com/"] @@ -477,7 +477,7 @@ typedef void (*my_fnp_type)(char *); [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)'in bir kopyasını bulundurmak mükemmel olabilir -Diğer bir iyi kaynak ise [Learn C the hard way](http://c.learncodethehardway.org/book/) +Diğer bir iyi kaynak ise [Learn C the hard way](http://learncodethehardway.org/c/) It's very important to use proper spacing, indentation and to be consistent with your coding style in general. Readable code is better than clever code and fast code. For a good, sane coding style to adopt, see the diff --git a/tr-tr/clojure-tr.html.markdown b/tr-tr/clojure-tr.html.markdown index 5ebe5ce6..d21947ee 100644 --- a/tr-tr/clojure-tr.html.markdown +++ b/tr-tr/clojure-tr.html.markdown @@ -482,7 +482,7 @@ Clojuredocs.org, örneklerle bezenmiş Clojure dökümantasyonu: [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) 4Clojure, interaktif bir şekilde FP ve Clojure yeteneklerinizi geliştirmenize olanak veriyor: -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org, Başlangıç için bir içeriklere sahip: [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/tr-tr/csharp-tr.html.markdown b/tr-tr/csharp-tr.html.markdown index 91c7c269..9834be20 100644 --- a/tr-tr/csharp-tr.html.markdown +++ b/tr-tr/csharp-tr.html.markdown @@ -1,5 +1,5 @@ --- -language: c# +language: C# contributors: - ["Irfan Charania", "https://github.com/irfancharania"] - ["Max Yankov", "https://github.com/golergka"] diff --git a/tr-tr/git-tr.html.markdown b/tr-tr/git-tr.html.markdown index 87c1820c..ad2f2e95 100644 --- a/tr-tr/git-tr.html.markdown +++ b/tr-tr/git-tr.html.markdown @@ -587,10 +587,8 @@ $ git rm /pather/to/the/file/HelloWorld.c * [SalesForce Kopya Kağıdı](http://res.cloudinary.com/hy4kyit2a/image/upload/SF_git_cheatsheet.pdf) -* [GitGuys](http://www.gitguys.com/) - * [Git - Basit bir kılavuz](http://rogerdudler.github.io/git-guide/index.html) * [Pro Git](http://www.git-scm.com/book/en/v2) -* [Yeni başlayanlar için Git ve Github](http://product.hubspot.com/blog/git-and-github-tutorial-for-beginners) +* [Yeni başlayanlar için Git ve GitHub](http://product.hubspot.com/blog/git-and-github-tutorial-for-beginners) diff --git a/tr-tr/jquery-tr.html.markdown b/tr-tr/jquery-tr.html.markdown new file mode 100644 index 00000000..4a4ebeae --- /dev/null +++ b/tr-tr/jquery-tr.html.markdown @@ -0,0 +1,338 @@ +--- +category: tool +tool: jquery +contributors: + - ["Seçkin KÜKRER", "https://github.com/leavenha"] +filename: jquery-tr-tr.js +lang: tr-tr +--- + +# Tanım + +jQuery, (IPA: ˈd͡ʒeɪˌkwɪəɹiː). +j + Query, olarak isimlendirilmiş, çünkü çoğunlukla HTML elementlerini sorgulamak ve onları manipüle etmek için kullanılır. + +jQuery, 2006 yılında geliştirilmiş ve günümüzde halen kullanımı yaygın, görece en popüler çapraz-platform JavaScript kütüphanelerinden birisidir. Şimdilerde jQuery ekibi tarafından gelişimi devam etmektedir. Dünyanın bir çok yerinden büyük şirketler ve bağımsız yazılım ekipleri tarafından kullanılmaktadır. + +Genel kullanım amacı animasyonlardır; Galeri, ek menü, sayfa geçişleri, ve diğer tüm gerçeklemelere sağladığı kolaylıkla birlikte Flash'ın alternatifi olarak yorumlanabilir. [Ajax][ajax-wikipedia-page] işlemleri de dahil olmak üzere olay-yönetimi, döküman manipülasyonu ve bir çok programlama görevini kolaylaştırır. + +Resmi sitesinden ([jQuery][jquery-official-website]) indirip web sitenize yükleyebilirsiniz. jQuery günümüz JavaScript kütüphaneleri gibi, küçültülmüş boyutlarda bulut tabanlı İçerik Dağıtım Ağı sistemleri sayesinde bağımsız olarak da sitenize eklenebilir. + +Kütüphanenin kullanımı ile, jQueryUI gibi ek paketlerle gelişmiş ve modern arayüzler gerçekleyebilirsiniz. + +Fakat, jQuery'ye giriş yapmadan önce elbetteki bu kütüphanenin üzerine kurulduğu teknoloji olan [JavaScript'i öğrenmelisiniz][javascript-learnxinyminutes-page]. + +```js + +// Bu belgedeki değişken isimleri Türkçe, +// ve [Lower Camel Case] notasyonu uygulamaktadır. +// Bu belgedeki kod parçalarının çıktıları, +// onları uyguladığınız dökümanın içeriğine bağlı olarak değişmektedir. + +// Döküman boyunca, aşağıdaki gösterimde +// Kod - Çıktı ikilisi ile içeriğin anlamlandırılması +// kolaylaştırılmaya çalışmıştır. +// ornek_kod_parcasi(); +// => "ÖRNEK ÇIKTI" + +// *. Konsept +// jQuery DOM nesnelerini seçmek için inovatif bir yol sunar. +// `$` değişkeni, `jQuery` kütüphanesine işaret eder. +// Fonksiyon notasyonu ile DOM nesnelerini elde eder +// ve üzerinde işlemler gerçekleştirirsiniz. +$(window) +// => jQuery [Window] (1) +// Bize tarayıcının belirlediği window nesnesini verir. + +// 1. Seçiciler +// Tüm nesneleri seçmek için `*` çağırımı yapılır. +const hepsi = $('*'); +// => jQuery [<html>, <head>, <meta>, +// .... <meta>, <title>, <meta>, <meta>, +// .... <meta>, <link>, <link>, …] (1134) = $1 + +// Seçiciler, jQuery'de bir nesne seçmek için kullanılırlar, +const sayfa = $(window); +// => jQuery [window] (1) +// Sayfa, açık döküman nesnesini seçer. + +// Elementler, kendileri için seçicidirler. +const tumParagraflar = $('p'); +// => jQuery [<p>, <p>, <p>] (3) + +// Seçiciler aynı zamanda CSS seçicileri olabilir. +const mavi = $('.mavi'); +// => jQuery [<p class='mavi'] (1) + +// Aynı zamanda element ile birlikte kullanılabilirler. +const maviParagraf = $('p.mavi'); +// => jQuery [<p class='mavi'>] (1) + +// Özellik seçicileri de mevcuttur, +// Elementin özelliği için seçim yaparlar. +const isimSecicisi = $('input[name*="kayit.form"]'); +// => jQuery [<input name='kayit.form.sifre'>, +// <input name='kayit.form.dogumtarihi'> ...] (10) + +// Diğer özellik seçiciler; +/* +- Özelliğin içinde arayan; *= +- Özelliğin içinde verilen kelimeleri arayan; ~= + |-(kelimeler boşlukla ayrılmalı, *='den farkına dikkat ediniz.) +- Özelliğin başlangıç verisini arayan; ^= +- Özelliğin bitiş verisini arayan; $= +- Özelliği tamamen karşılaştıran; = +- Özelliğin eşitsizlik durumunu karşılaştıran; != + +Diğer tüm seçiciler için resmi siteyi kontrol ediniz. +*/ + +// 2. Olaylar ve Efektler +// - Olaylar +// jQuery kullanıcı ile tarayıcı arasındaki etkileşimi olaylar ile ele alır. + +// En yaygın kullanımı tartışmasız ki Dökümanın Yüklenmesi olayıdır. + +// $.ready fonksiyonu, argüman olarak aldığı fonksiyonu, +// seçilen eleman tamamen yüklendiğinde çağıracaktır. +$(document).ready(function(){ + // Dökümanın tamamı yüklendiğine göre, iş mantığımı çağırabiliriz. + console.info('Döküman yüklendi!'); +}) +// => jQuery [#document] (1) + +// Bir dökümanın tamamının yüklenmeden, +// herhangi bir iş mantığı çalıştırmanın +// neden kötü bir fikir olduğunu merak ediyorsanız, +// ileri okuma kısmına danışabilirsiniz. + +// Önce Olay tanımlayalım. + +// Tıklama olayı için `$.click` olay tetikleyicisi kullanılıyor. +$('.mavi').click(function(){ + // Unutmayın ki, önceden tanımlanmış + // bir fonksiyonu da argüman olarak verebilirsiniz. + console.info('Mavi butona tıkladın!'); +}) +// => jQuery [<button>, <button>, <button>, <button>, <button>, …] (365) + +// Çift Tıklama olayı için `$.dblclick` olay tetikleyicisi kullanılıyor. +$('.mavi').dblclick(function(){ + console.info('Mavi butona çift tıkladın!'); +}) +// => jQuery [<button>, <button>, <button>, <button>, <button>, …] (365) + +// Seçilen Elemente birden fazla tetiklenecek fonksiyon tanımalamak +// istersek, Olayları ve Fonksiyonları Anahtar-Değer yapısı sağlayan +// Objeleri kullanarak da çağırabiliriz. + +// => tetiklenecekFonksiyon +$('.mor').on({ + click: () => console.info('Tek tıklama ile tetiklendim!'), + dblclick: () => console.info('Çift tıklama ile tetiklendim!'), + // ... +}); +// => jQuery [<button>, <button>, <button>, <button>, <button>, …] (365) + +// Diğer olay tetikleyicileri; +/* +Elemente, +- Fokus/Odaklanma; $.focus +- Fokus/Odaklanmanın kaybedilmesi; $.blur +- Farenin alanına girmesi; $.mouseenter +- Farenin alanından çıkması; $.mouseleave + +Diğer tüm olay tetikleyicileri için resmi siteyi kontrol ediniz. +*/ + +// Tanımlanan olayları tetiklemek için, +// Kullanıcı-Tarayıcı etkileşimi yerine elle çağrı yapmak da mümkün. +// Tanımlama ile çağırım arasındaki fark sadece sağlanan argümanlardır. +// Argümansız çağırım, olayı tetikler. + +// Tıklama olayını tetiklemek için. +$('.mavi').click(); +// => Mavi butona tıkladın! +// => jQuery [<button>] (1) + +// Çift Tıklama olayını tetiklemek için. +$('.mavi').dblclick(); +// => Mavi butona çift tıkladın! +// => jQuery [<button>] (1) + +// - Efektler +// jQuery bir çok ön-tanımlı efekt sunmakta. +// Bu efektler, belirli parametlerle, farklı iş mantıklarını +// gerçeklemenize izin verebilir. +// Önce parametresiz işlevlere göz atalım. + +// Elementleri saklayabilir, +$('#slaytresmi').hide(); +// => jQuery [<img id='slaytresmi'>] (1) + +// Gizlenen elementleri tekrar görünür yapabilir, +$('#slaytresmi').show(); +// => jQuery [<img id='slaytresmi'>] (1) + +// Yada dilediğiniz CSS niteliğini anime edebilirsiniz, + +// Bu parametre, anime etmek istediğiniz CSS özelliklerini +// belirleyen Obje bilgisidir. +// Yükseklik ve Genişlik bilgileri için değerler belirliyoruz. +const animeEdilecekCSSOzellikleri = + { + weight: "300px", + height: "300px" + }; + +// Diğer anime edilebilir CSS özellikleri; +/* +Elementin, +- Opaklık; opacity +- Dış çevre mesafesi; margin +- Çerçeve yüksekliği; borderWidth +- Satır yüksekliği; lineHeight + +Diğer tüm özellikler için resmi siteyi kontrol ediniz. +*/ + +// Bu parametre animasyonun süresini belirler. +const milisaniyeCinsindenAnimasyonSuresi = + 1200; + +// Bu parametre, 'linear' yada 'swing' metin +// bilgilerinden birini alır ve animasyonun +// akıcılığını belirler. +// x ∈ {'linear', 'swing'} +const animasyonAkiciligi = 'linear'; + +// Bu parametre, bir fonksiyondur ve +// animasyondan sonra çağırılır. +// Bir geri-çağırım (callback*) olarak değerlendirilebilir. +const animasyonGeriCagirimFonksiyonu = function(){ + console.info('Animasyon bitti!'); +}; + +// Şimdi tanımlanan bilgilerimizle animasyonu çağırıyoruz. +$('#slaytresmi').animate(animeEdilecekCSSOzellikleri, + milisaniyeCinsindenAnimasyonSuresi, + animasyonAkiciligi, + animasyonGeriCagirimFonksiyonu); +// => jQuery [<img id='slaytresmi'>] (1) + +// Kütüphane `$.animate` fonksiyonu için, anime edeceğiniz +// CSS özellikleri dışındaki tüm argümanlar için +// ön tanımlı değerler sağlamaktadır. +// Bu değerler için resmi siteyi kontrol ediniz. + +// Diğer ön tanımlı efektler; +/* +Elementi, +- Yukarı kaydırır; $.slideUp +- Verilen saydamlık değerine anime eder; $.fadeTo +- Görünür yada görünmez yapar (geçerli durumuna bağlı); $.toggle + +Diğer tüm efektler için resmi siteyi kontrol ediniz. +*/ + +// 3. Manipülasyon + +// jQuery'de, HTML elementlerinin isteğiniz doğrultusunda +// değiştirilmesi için araçlar sunulmakta. + +// Bir ön-tanımlı CSS sınıfımız olduğunu hayal edebilirsiniz. +// Bu sınıfı istediğimiz elemente uygulamak için, +$('#slaytresmi').addClass('inanilmaz-bir-cerceve-sinifi'); +// => jQuery [<img id='slaytresmi' class='inanilmaz-bir-cerceve-sinifi'>] (1) + +// Bu CSS sınıfını istediğimiz zaman silebiliriz, +$('#slaytresmi').removeClass('inanilmaz-bir-cerceve-sinifi'); +// => jQuery [<img id='slaytresmi'>] (1) + +// Bu HTML elementini, istediğimiz başka bir element ile çevreleyebiliriz, +$('#slaytresmi').wrap('<div class="farkli-bir-cerceve"></div>'); +// => jQuery [<img id='slaytresmi'>] (1) +// Sonucun gözlemlenebilmesi için, elementin çevreleme işlemi sonrası +// döküman üzerindeki yapısını temel bir seçici ile gözlemleyebiliriz; +$('.farli-bir-cerceve') +// => jQuery [<div class='farkli-bir-cerceve>] (1) +// => <div class="farkli-bir-cerceve"> +// <img id='slaytresmi'> +// </div> + +// Elemente içerik ekleyebiliriz, +// Eklemeler döküman içeriğinin sonuna yapılacaktır. +// Bu süreci daha iyi gözlemleyebilmek için içeriğine bakmamız yeterli, +// Ekleme öncesinde; +$('.farkli-bir-cerceve'); +// => jQuery [<div class='farkli-bir-cerceve>] (1) +// => <div class="farkli-bir-cerceve"> +// <img id='slaytresmi'> +// </div> + +// `$.append` fonksiyonu ile ekleme işlemini yapıyoruz. +$('.farkli-bir-cerceve').append('<h1>Bu çerçeve farklı!</h1>'); +// => jQuery [<div class='farkli-bir-cerceve>] (1) +// => <div class="farkli-bir-cerceve"> +// <img id='slaytresmi'> +// <h1>Bu çerçeve farklı!</h1> +// </div> + +// Dökümandan element silebiliriz, +$('.farkli-bir-cerceve > h1').remove(); +// => jQuery [<h1>] (1) + +// Dökümanın güncel halini görmek için seçiciyi çağırıyoruz, +$('.farkli-bir-cerceve'); +// => jQuery [<div class='farkli-bir-cerceve>] (1** +// => <div class="farkli-bir-cerceve"> +// <img id='slaytresmi'> +// </div> + +// Elementlerin özniteliklerini değiştirebilir yada +// silebiliriz. +// Öznitelik erişici ve değiştiricisi, +// Bir fonksiyon notasyonuyla yapılanmış durumda. +// Eğer bir öznitelik bilgisini almak istiyorsak, ilgili öznitelik +// ismini; + +$('.farkli-bir-cerceve > img').attr('id'); +// => 'slaytresmi' + +// Eğer bir öznitelik bilgisini güncellemek istiyorsak, +// ilgili öznitelik ismi ve sonrasında yeni değerini argüman +// olarak $.attr fonksiyonuna iletiyoruz; + +$('.farkli-bir-cerceve > img').attr('id', 'cercevelislaytresmi'); +// => jQuery [<img id='cercevelislaytresmi'>] (1) + +// Diğer ön fonksiyonlar; +/* +Elementin, +- Yükseklik değeri, $.height +- HTML döküman içeriği, $.html +- Girdi içeriği, $.val +- Verilen CSS sınıfına sahipliği, $.hasClass + +Diğer tüm manipülasyon fonksiyonları için resmi siteyi kontrol ediniz. +*/ + +``` + +## Notlar + +- Yaygın bir yanlış bilineni düzeltmek adına; jQuery bir çalışma-çatısı değil, bir *kütüphanedir*. +- [Lower Camel Case][lower-camel-case-notasyonu] notasyonu için Wikipedia sayfası. + +## İleri Okuma + +### İngilizce + +- [jQuery][jquery-official-website] resmi sitesi. + +- [Jakob Jenkov | $(document).ready article](http://tutorials.jenkov.com/jquery/document-ready.html) + +[jquery-official-website]: https://jquery.com +[ajax-wikipedia-page]: https://en.wikipedia.org/wiki/Ajax_(programming) +[javascript-learnxinyminutes-page]: https://learnxinyminutes.com/docs/javascript/ +[lower-camel-case-notasyonu]: https://en.wikipedia.org/wiki/Camel_case#Programming_and_coding diff --git a/tr-tr/python-tr.html.markdown b/tr-tr/python-tr.html.markdown index 99a3eb4e..6d9cdcbe 100644 --- a/tr-tr/python-tr.html.markdown +++ b/tr-tr/python-tr.html.markdown @@ -1,316 +1,344 @@ --- -language: python -filename: learnpython-tr.py +language: Python contributors: - - ["Louie Dinh", "http://ldinh.ca"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] + - ["Batuhan Osman T.", "https://github.com/BTaskaya"] translators: - - ["Haydar KULEKCI", "http://scanf.info/"] + - ["Eray AYDIN", "http://erayaydin.me/"] lang: tr-tr +filename: learnpython-tr.py --- -Python Guido Van Rossum tarafından 90'ların başında yaratılmıştır. Şu anda -varolanlar arasında en iyi dillerden birisidir. Ben (Louie Dinh) Python -dilinin syntax'ının belirginliğine aşığım. O basit olarak çalıştırılabilir -pseudocode'dur. -Geri bildirimlerden son derece mutluluk duyarım! Bana [@louiedinh](http://twitter.com/louiedinh) -adresinden ya da louiedinh [at] [google's email service] adresinden ulaşabilirsiniz. +Python,90ların başlarında Guido Van Rossum tarafından oluşturulmuştur. En popüler olan dillerden biridir. Beni Python'a aşık eden sebep onun syntax beraklığı. Çok basit bir çalıştırılabilir söz koddur. -Çeviri için geri bildirimleri de [@kulekci](http://twitter.com/kulekci) -adresine yapabilirsiniz. +Not: Bu makale Python 3 içindir. Eğer Python 2.7 öğrenmek istiyorsanız [burayı](http://learnxinyminutes.com/docs/pythonlegacy/) kontrol edebilirsiniz. -Not: Bu yazıdaki özellikler Python 2.7 için geçerlidir, ama Python 2.x için de -uygulanabilir. Python 3 için başka bir zaman tekrar bakınız. +```python +# Tek satırlık yorum satırı kare(#) işareti ile başlamaktadır. -```python -# Tek satır yorum hash işareti ile başlar. -""" Çoklu satır diziler üç tane çift tırnak - arasında yazılır. Ve yorum olarak da - kullanılabilir +""" Çok satırlı olmasını istediğiniz yorumlar + üç adet tırnak(") işareti ile + yapılmaktadır """ - #################################################### -## 1. İlkel Veri Tipleri ve Operatörler +## 1. Temel Veri Türleri ve Operatörler #################################################### # Sayılar -3 #=> 3 +3 # => 3 + +# Tahmin edebileceğiniz gibi matematik +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 + +# Bölme işlemi varsayılan olarak onluk döndürür +35 / 5 # => 7.0 + +# Tam sayı bölmeleri, pozitif ve negatif sayılar için aşağıya yuvarlar +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # onluklar için de bu böyledir +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 -# Matematik beklediğiniz gibi -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 +# Onluk kullanırsanız, sonuç da onluk olur +3 * 2.0 # => 6.0 -# Bölünme biraz ilginç. EĞer tam sayılar üzerinde bölünme işlemi yapıyorsanız -# sonuç otomatik olarak kırpılır. -5 / 2 #=> 2 +# Kalan operatörü +7 % 3 # => 1 -# Bölünme işlemini düzenlemek için kayan noktalı sayıları bilmeniz gerekir. -2.0 # Bu bir kayan noktalı sayı -11.0 / 4.0 #=> 2.75 ahhh...daha iyi +# Üs (2 üzeri 4) +2**4 # => 16 -# İşlem önceliğini parantezler ile sağlayabilirsiniz. -(1 + 3) * 2 #=> 8 +# Parantez ile önceliği değiştirebilirsiniz +(1 + 3) * 2 # => 8 -# Boolean değerleri bilindiği gibi +# Boolean(Doğru-Yanlış) değerleri standart True False -# not ile nagatif(mantıksal) değerini alma -not True #=> False -not False #=> True +# 'değil' ile terse çevirme +not True # => False +not False # => True -# Eşitlik == -1 == 1 #=> True -2 == 1 #=> False +# Boolean Operatörleri +# "and" ve "or" büyük küçük harf duyarlıdır +True and False #=> False +False or True #=> True -# Eşitsizlik != -1 != 1 #=> False -2 != 1 #=> True +# Bool operatörleri ile sayı kullanımı +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True -# Daha fazla karşılaştırma -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True +# Eşitlik kontrolü == +1 == 1 # => True +2 == 1 # => False -# Karşılaştırma zincirleme yapılabilir! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +# Eşitsizlik Kontrolü != +1 != 1 # => False +2 != 1 # => True -# Karakter dizisi " veya ' ile oluşturulabilir -"This is a string." -'This is also a string.' +# Diğer karşılaştırmalar +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True -# Karakter dizileri birbirleri ile eklenebilir -"Hello " + "world!" #=> "Hello world!" +# Zincirleme şeklinde karşılaştırma da yapabilirsiniz! +1 < 2 < 3 # => True +2 < 3 < 2 # => False -# A string can be treated like a list of characters -# Bir string'e karakter listesi gibi davranabilirsiniz. -"This is a string"[0] #=> 'T' +# Yazı(Strings) " veya ' işaretleri ile oluşturulabilir +"Bu bir yazı." +'Bu da bir yazı.' -# % karakter dizisini(string) formatlamak için kullanılır, bunun gibi: -"%s can be %s" % ("strings", "interpolated") +# Yazılar da eklenebilir! Fakat bunu yapmanızı önermem. +"Merhaba " + "dünya!" # => "Merhaba dünya!" -# String'leri formatlamanın yeni bir yöntem ise format metodudur. -# Bu metod tercih edilen yöntemdir. -"{0} can be {1}".format("strings", "formatted") -# Eğer saymak istemiyorsanız anahtar kelime kullanabilirsiniz. -"{name} wants to eat {food}".format(name="Bob", food="lasagna") +# Bir yazı(string) karakter listesi gibi işlenebilir +"Bu bir yazı"[0] # => 'B' -# None bir objedir -None #=> None +# .format ile yazıyı biçimlendirebilirsiniz, şu şekilde: +"{} da ayrıca {}".format("yazılar", "işlenebilir") -# "==" eşitliğini non objesi ile karşılaştırmak için kullanmayın. -# Onun yerine "is" kullanın. -"etc" is None #=> False -None is None #=> True +# Biçimlendirme işleminde aynı argümanı da birden fazla kullanabilirsiniz. +"{0} çeviktir, {0} hızlıdır, {0} , {1} üzerinden atlayabilir".format("Ahmet", "şeker çubuğu") +#=> "Ahmet çeviktir, Ahmet hızlıdır, Ahmet , şeker çubuğu üzerinden atlayabilir" -# 'is' operatörü obje kimliği için test etmektedir. Bu ilkel değerler -# için kullanışlı değildir, ama objeleri karşılaştırmak için kullanışlıdır. +# Argümanın sırasını saymak istemiyorsanız, anahtar kelime kullanabilirsiniz. +"{isim} yemek olarak {yemek} istiyor".format(isim="Ahmet", yemek="patates") #=> "Ahmet yemek olarak patates istiyor" -# None, 0 ve boş string/list'ler False olarak değerlendirilir. -# Tüm eşitlikler True döner -0 == False #=> True -"" == False #=> True +# Eğer Python 3 kodunuz ayrıca Python 2.5 ve üstünde çalışmasını istiyorsanız, +# eski stil formatlamayı kullanabilirsiniz: +"%s bu %s yolla da %s" % ("yazılar", "eski", "biçimlendirilebilir") -#################################################### -## 2. Değişkenler ve Kolleksiyonlar -#################################################### +# Hiçbir şey(none) da bir objedir +None # => None -# Ekrana yazdırma oldukça kolaydır. -print "I'm Python. Nice to meet you!" +# Bir değerin none ile eşitlik kontrolü için "==" sembolünü kullanmayın +# Bunun yerine "is" kullanın. Obje türünün eşitliğini kontrol edecektir. +"vb" is None # => False +None is None # => True +# None, 0, ve boş yazılar/listeler/sözlükler hepsi False değeri döndürü. +# Diğer veriler ise True değeri döndürür +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False -# Değişkenlere bir değer atamadan önce tanımlamaya gerek yoktur. -some_var = 5 # Değişken isimlerinde gelenek küçük karakter ve alt çizgi - # kullanmaktır. -some_var #=> 5 -# Daha önceden tanımlanmamış ya da assign edilmemeiş bir değişkene erişmeye -# çalıştığınızda bir hata fırlatılacaktır. Hata ayıklama hakkında daha fazla -# bilgi için kontrol akışı kısmına göz atınız. -some_other_var # isim hatası fırlatılır +#################################################### +## 2. Değişkenler ve Koleksiyonlar +#################################################### -# isterseniz "if"i bir ifade gibi kullanabilirsiniz. -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +# Python bir yazdırma fonksiyonuna sahip +print("Ben Python. Tanıştığıma memnun oldum!") -# Listeler +# Değişkenlere veri atamak için önce değişkeni oluşturmanıza gerek yok. +# Düzenli bir değişken için hepsi_kucuk_ve_alt_cizgi_ile_ayirin +bir_degisken = 5 +bir_degisken # => 5 + +# Önceden tanımlanmamış değişkene erişmek hata oluşturacaktır. +# Kontrol akışları başlığından hata kontrolünü öğrenebilirsiniz. +bir_bilinmeyen_degisken # NameError hatası oluşturur + +# Listeler ile sıralamaları tutabilirsiniz li = [] -# Önceden değerleri tanımlanmış listeler -other_li = [4, 5, 6] - -# Bir listenin sonuna birşeyler eklemek -li.append(1) #li şu anda [1] -li.append(2) #li şu anda [1, 2] -li.append(4) #li şu anda [1, 2, 4] -li.append(3) #li şu anda [1, 2, 4, 3] -# pop ile sondan birşeyler silmek -li.pop() #=> 3 and li is now [1, 2, 4] -# Tekrar sonuna eklemek -li.append(3) # li is now [1, 2, 4, 3] again. - -# Dizi gibi listenin elemanlarına erişmek -li[0] #=> 1 -# Son elemanın değerine ulaşmak -li[-1] #=> 3 - -# Listede bulunmayan bir index'teki elemana erişirken "IndexError" hatası -# fırlatılır -li[4] # IndexError fırlatılır - -# slice syntax'ı ile belli aralıktakı değerlere bakabilirsiniz. -# (Açık ve kapalı aralıklıdır.) -li[1:3] #=> [2, 4] -# Başlangıcı ihmal etme -li[2:] #=> [4, 3] -# Sonu ihmal etme -li[:3] #=> [1, 2, 4] - -# "del" ile istenilen bir elemanı listeden silmek -del li[2] # li is now [1, 2, 3] - -# Listeleri birbiri ile birleştirebilirsiniz. -li + other_li #=> [1, 2, 3, 4, 5, 6] - Not: li ve other_li yanlız bırakılır - -# extend ile listeleri birleştirmek -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] - -# bir değerin liste içerisinde varlığını "in" ile kontrol etmek -1 in li #=> True - -# "len" ile listenin uzunluğunu bulmak -len(li) #=> 6 - -# Tüpler listeler gibidir sadece değişmezler(immutable) +# Önceden doldurulmuş listeler ile başlayabilirsiniz +diger_li = [4, 5, 6] + +# 'append' ile listenin sonuna ekleme yapabilirsiniz +li.append(1) # li artık [1] oldu +li.append(2) # li artık [1, 2] oldu +li.append(4) # li artık [1, 2, 4] oldu +li.append(3) # li artık [1, 2, 4, 3] oldu +# 'pop' ile listenin son elementini kaldırabilirsiniz +li.pop() # => 3 ve li artık [1, 2, 4] +# Çıkarttığımız tekrardan ekleyelim +li.append(3) # li yeniden [1, 2, 4, 3] oldu. + +# Dizi gibi listeye erişim sağlayın +li[0] # => 1 +# Son elemente bakın +li[-1] # => 3 + +# Listede olmayan bir elemente erişim sağlamaya çalışmak IndexError hatası oluşturur +li[4] # IndexError hatası oluşturur + +# Bir kısmını almak isterseniz. +li[1:3] # => [2, 4] +# Başlangıç belirtmezseniz +li[2:] # => [4, 3] +# Sonu belirtmesseniz +li[:3] # => [1, 2, 4] +# Her ikişer objeyi seçme +li[::2] # =>[1, 4] +# Listeyi tersten almak +li[::-1] # => [3, 4, 2, 1] +# Kombinasyonları kullanarak gelişmiş bir şekilde listenin bir kısmını alabilirsiniz +# li[baslangic:son:adim] + +# "del" ile isteğe bağlı, elementleri listeden kaldırabilirsiniz +del li[2] # li artık [1, 2, 3] oldu + +# Listelerde de ekleme yapabilirsiniz +# Not: değerler üzerinde değişiklik yapılmaz. +li + diger_li # => [1, 2, 3, 4, 5, 6] + +# Listeleri birbirine bağlamak için "extend()" kullanılabilir +li.extend(diger_li) # li artık [1, 2, 3, 4, 5, 6] oldu + +# Listedeki bir elementin olup olmadığı kontrolü "in" ile yapılabilir +1 in li # => True + +# Uzunluğu öğrenmek için "len()" kullanılabilir +len(li) # => 6 + + +# Tüpler listeler gibidir fakat değiştirilemez. tup = (1, 2, 3) -tup[0] #=> 1 -tup[0] = 3 # TypeError fırlatılır. - -# Litelerde yapılanların hepsini tüplerde de yapılabilir -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True - -# Tüplerin(veya listelerin) içerisindeki değerleri değişkenelere -# atanabilir -a, b, c = (1, 2, 3) # a şu anda 1, b şu anda 2 ve c şu anda 3 -# Eğer parantez kullanmaz iseniz tüpler varsayılan olarak oluşturulur +tup[0] # => 1 +tup[0] = 3 # TypeError hatası oluşturur + +# Diğer liste işlemlerini tüplerde de uygulayabilirsiniz +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# Tüpleri(veya listeleri) değişkenlere açabilirsiniz +a, b, c = (1, 2, 3) # 'a' artık 1, 'b' artık 2 ve 'c' artık 3 +# Eğer parantez kullanmazsanız varsayılan oalrak tüpler oluşturulur d, e, f = 4, 5, 6 -# şimdi iki değeri değiş tokuş etmek çok kolaydır. -e, d = d, e # d şimdi 5 ve e şimdi 4 +# 2 değeri birbirine değiştirmek bu kadar kolay +e, d = d, e # 'd' artık 5 ve 'e' artık 4 + +# Sözlükler anahtar kodlarla verileri tutar +bos_sozl = {} +# Önceden doldurulmuş sözlük oluşturma +dolu_sozl = {"bir": 1, "iki": 2, "uc": 3} -# Sözlükler (Dictionaries) key-value saklanır. -empty_dict = {} -# Sözlüklere önceden değer atama örneği -filled_dict = {"one": 1, "two": 2, "three": 3} +# Değere bakmak için [] kullanalım +dolu_sozl["bir"] # => 1 -# Değere ulaşmak için [] kullanılır -filled_dict["one"] #=> 1 +# Bütün anahtarları almak için "keys()" kullanılabilir. +# Listelemek için list() kullanacağınız çünkü dönen değerin işlenmesi gerekiyor. Bu konuya daha sonra değineceğiz. +# Not - Sözlük anahtarlarının sıralaması kesin değildir. +# Beklediğiniz çıktı sizinkiyle tam uyuşmuyor olabilir. +list(dolu_sozl.keys()) # => ["uc", "iki", "bir"] -# Tüm anahtarlara(key) "keys()" metodu ile ulaşılır -filled_dict.keys() #=> ["three", "two", "one"] -# Not - Sözlüklerin anahtarlarının sıralı geleceği garanti değildir -# Sonuçlarınız değer listesini aldığınızda tamamen eşleşmeyebilir -# Tüm değerleri almak için "values()" kullanabilirsiniz. -filled_dict.values() #=> [3, 2, 1] -# Not - Sıralama ile ilgili anahtarlar ile aynı durum geçerlidir. +# Tüm değerleri almak için "values()" kullanacağız. Dönen değeri biçimlendirmek için de list() kullanmamız gerekiyor +# Not - Sıralama değişebilir. +list(dolu_sozl.values()) # => [3, 2, 1] -# Bir anahtarın sözlükte oluş olmadığını "in" ile kontrol edilebilir -"one" in filled_dict #=> True -1 in filled_dict #=> False -# Olmayan bir anahtar çağrıldığında KeyError fırlatılır. -filled_dict["four"] # KeyError +# Bir anahtarın sözlükte olup olmadığını "in" ile kontrol edebilirsiniz +"bir" in dolu_sozl # => True +1 in dolu_sozl # => False -# "get()" metodu KeyError fırlatılmasını önler -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None -# get() metodu eğer anahtar mevcut değilse varsayılan bir değer atama -# imknaı sağlar. -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 +# Olmayan bir anahtardan değer elde etmek isterseniz KeyError sorunu oluşacaktır. +dolu_sozl["dort"] # KeyError hatası oluşturur -# "setdefault()" metodu sözlüğe yeni bir key-value eşleşmesi eklemenin -# güvenli bir yoludur. -filled_dict.setdefault("five", 5) #filled_dict["five"] is set to 5 -filled_dict.setdefault("five", 6) #filled_dict["five"] is still 5 +# "get()" metodu ile değeri almaya çalışırsanız KeyError sorunundan kurtulursunuz +dolu_sozl.get("bir") # => 1 +dolu_sozl.get("dort") # => None +# "get" metoduna parametre belirterek değerin olmaması durumunda varsayılan bir değer döndürebilirsiniz. +dolu_sozl.get("bir", 4) # => 1 +dolu_sozl.get("dort", 4) # => 4 +# "setdefault()" metodu sözlükte, belirttiğiniz anahtarın [olmaması] durumunda varsayılan bir değer atayacaktır +dolu_sozl.setdefault("bes", 5) # dolu_sozl["bes"] artık 5 değerine sahip +dolu_sozl.setdefault("bes", 6) # dolu_sozl["bes"] değişmedi, hala 5 değerine sahip -# Sets store ... well sets -empty_set = set() -# Bir demek değer ile bir "set" oluşturmak -some_set = set([1,2,2,3,4]) # some_set is now set([1, 2, 3, 4]) +# Sözlüğe ekleme +dolu_sozl.update({"dort":4}) #=> {"bir": 1, "iki": 2, "uc": 3, "dort": 4} +#dolu_sozl["dort"] = 4 #sözlüğe eklemenin bir diğer yolu -# Python 2.7'den beri {}'ler bir "set" tanımlaman için kullanılabilir -filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} +# Sözlükten anahtar silmek için 'del' kullanılabilir +del dolu_sozl["bir"] # "bir" anahtarını dolu sözlükten silecektir -# Bir set'e daha fazla eleman eklemek -filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} -# "&" işareti ile iki set'in kesişimlerini alınabilir -other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} +# Setler ... set işte :D +bos_set = set() +# Seti bir veri listesi ile de oluşturabilirsiniz. Evet, biraz sözlük gibi duruyor. Üzgünüm. +bir_set = {1, 1, 2, 2, 3, 4} # bir_set artık {1, 2, 3, 4} -# | işareti ile -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} +# Sete yeni setler ekleyebilirsiniz +dolu_set = bir_set -# "-" işareti ile iki set'in farkları alınabilir -{1,2,3,4} - {2,3,5} #=> {1, 4} +# Sete bir diğer öğe ekleme +dolu_set.add(5) # dolu_set artık {1, 2, 3, 4, 5} oldu -# "in" ile değerin set içerisinde olup olmadığını kontrol edebilirsiniz -2 in filled_set #=> True -10 in filled_set #=> False +# Setlerin çakışan kısımlarını almak için '&' kullanabilirsiniz +diger_set = {3, 4, 5, 6} +dolu_set & diger_set # => {3, 4, 5} + +# '|' ile aynı olan elementleri almayacak şekilde setleri birleştirebilirsiniz +dolu_set | diger_set # => {1, 2, 3, 4, 5, 6} + +# Farklılıkları almak için "-" kullanabilirsiniz +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Bir değerin olup olmadığının kontrolü için "in" kullanılabilir +2 in dolu_set # => True +10 in dolu_set # => False #################################################### -## 3. Akış Denetimi +## 3. Kontrol Akışları ve Temel Soyutlandırma #################################################### -# Bir değişken oluşturmak -some_var = 5 +# Bir değişken oluşturalım +bir_degisken = 5 -# Buradaki bir if ifadesi. Girintiler(Intentation) Python'da önemlidir! -# "some_var is smaller than 10" yazdırılır. -if some_var > 10: - print "some_var is totally bigger than 10." -elif some_var < 10: # elif ifadesi isteğe bağlıdır - print "some_var is smaller than 10." -else: # Bu da isteğe bağlıdır. - print "some_var is indeed 10." +# Burada bir "if" ifadesi var. Girinti(boşluk,tab) python için önemlidir! +# çıktı olarak "bir_degisken 10 dan küçük" yazar +if bir_degisken > 10: + print("bir_degisken 10 dan büyük") +elif bir_degisken < 10: # Bu 'elif' ifadesi zorunlu değildir. + print("bir_degisken 10 dan küçük") +else: # Bu ifade de zorunlu değil. + print("bir_degisken değeri 10") """ -For döngüleri listeler üzerinde iterasyon yapar -Ekrana yazdırılan: - dog is a mammal - cat is a mammal - mouse is a mammal +Döngülerle lsiteleri döngüye alabilirsiniz +çıktı: + köpek bir memeli hayvandır + kedi bir memeli hayvandır + fare bir memeli hayvandır """ -for animal in ["dog", "cat", "mouse"]: - # Biçimlendirmeleri string'e katmak için % kullanabilirsiniz - print "%s is a mammal" % animal - +for hayvan in ["köpek", "kedi, "fare"]: + # format ile kolayca yazıyı biçimlendirelim + print("{} bir memeli hayvandır".format(hayvan)) + """ -"range(number)" ifadesi sıfırdan verilen sayıya kadar bir sayı listesi döner -Ekrana yazdırılan: +"range(sayi)" bir sayı listesi döndür +0'dan belirttiğiniz sayıyıa kadar +çıktı: 0 1 2 3 """ for i in range(4): - print i + print(i) """ -While döngüsü koşul sağlanmayana kadar devam eder -Ekrana yazdırılan: +'While' döngüleri koşul çalıştıkça işlemleri gerçekleştirir. +çıktı: 0 1 2 @@ -318,185 +346,295 @@ Ekrana yazdırılan: """ x = 0 while x < 4: - print x - x += 1 # Shorthand for x = x + 1 - -# try/except bloğu ile hatalar ayıklanabilir + print(x) + x += 1 # Uzun hali x = x + 1 -# Python 2.6 ve üstü için çalışacaktır: +# Hataları kontrol altına almak için try/except bloklarını kullanabilirsiniz try: - # "raise" bir hata fırlatmak için kullanılabilir - raise IndexError("This is an index error") + # Bir hata oluşturmak için "raise" kullanabilirsiniz + raise IndexError("Bu bir index hatası") except IndexError as e: - pass # Pass is just a no-op. Usually you would do recovery here. + pass # Önemsiz, devam et. +except (TypeError, NameError): + pass # Çoklu bir şekilde hataları kontrol edebilirsiniz, tabi gerekirse. +else: # İsteğe bağlı bir kısım. Eğer hiçbir hata kontrol mekanizması desteklemiyorsa bu blok çalışacaktır + print("Her şey iyi!") # IndexError, TypeError ve NameError harici bir hatada bu blok çalıştı + +# Temel Soyutlandırma, bir objenin işlenmiş halidir. +# Aşağıdaki örnekte; Obje, range fonksiyonuna temel soyutlandırma gönderdi. + +dolu_sozl = {"bir": 1, "iki": 2, "uc": 3} +temel_soyut = dolu_sozl.keys() +print(temel_soyut) #=> range(1,10). Bu obje temel soyutlandırma arayüzü ile oluşturuldu + +# Temel Soyutlandırılmış objeyi döngüye sokabiliriz. +for i in temel_soyut: + print(i) # Çıktısı: bir, iki, uc + +# Fakat, elementin anahtarına değerine. +temel_soyut[1] # TypeError hatası! + +# 'iterable' bir objenin nasıl temel soyutlandırıldığıdır. +iterator = iter(temel_soyut) + +# 'iterator' o obje üzerinde yaptığımız değişiklikleri hatırlayacaktır +# Bir sonraki objeyi almak için __next__ fonksiyonunu kullanabilirsiniz. +iterator.__next__() #=> "bir" + +# Bir önceki __next__ fonksiyonumuzu hatırlayıp bir sonraki kullanımda bu sefer ondan bir sonraki objeyi döndürecektir +iterator.__next__() #=> "iki" +iterator.__next__() #=> "uc" + +# Bütün nesneleri aldıktan sonra bir daha __next__ kullanımınızda, StopIterator hatası oluşturacaktır. +iterator.__next__() # StopIteration hatası + +# iterator'deki tüm nesneleri almak için list() kullanabilirsiniz. +list(dolu_sozl.keys()) #=> Returns ["bir", "iki", "uc"] #################################################### ## 4. Fonksiyonlar #################################################### +# "def" ile yeni fonksiyonlar oluşturabilirsiniz +def topla(x, y): + print("x = {} ve y = {}".format(x, y)) + return x + y # Değer döndürmek için 'return' kullanmalısınız -# Yeni bir fonksiyon oluşturmak için "def" kullanılır -def add(x, y): - print "x is %s and y is %s" % (x, y) - return x + y # Return values with a return statement +# Fonksiyonu parametleri ile çağırıyoruz +topla(5, 6) # => çıktı "x = 5 ve y = 6" ve değer olarak 11 döndürür -# Fonksiyonu parametre ile çağırmak -add(5, 6) #=> prints out "x is 5 and y is 6" and returns 11 +# Bir diğer fonksiyon çağırma yöntemi de anahtar değerleri ile belirtmek +topla(y=6, x=5) # Anahtar değeri belirttiğiniz için parametre sıralaması önemsiz. -# Diğer bir yol fonksiyonları anahtar argümanları ile çağırmak -add(y=6, x=5) # Anahtar argümanlarının sırası farklı da olabilir +# Sınırsız sayıda argüman da alabilirsiniz +def argumanlar(*argumanlar): + return argumanlar -# Değişken sayıda parametresi olan bir fonksiyon tanımlayabilirsiniz -def varargs(*args): - return args +argumanlar(1, 2, 3) # => (1, 2, 3) -varargs(1, 2, 3) #=> (1,2,3) +# Parametrelerin anahtar değerlerini almak isterseniz +def anahtar_par(**anahtarlar): + return anahtar -# Değişken sayıda anahtar argümanlı parametre alan fonksiyonlar da -# tanımlayabilirsiniz. -def keyword_args(**kwargs): - return kwargs +# Çalıştırdığımızda +anahtar_par(anah1="deg1", anah2="deg2") # => {"anah1": "deg1", "anah2": "deg2"} -# Şu şekilde kullanılacaktır -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} -# Eğer isterseniz ikisini aynı anda da yapabilirsiniz -def all_the_args(*args, **kwargs): - print args - print kwargs +# İsterseniz, bu ikisini birden kullanabilirsiniz +def tum_argumanlar(*argumanlar, **anahtarla): + print(argumanlar) + print(anahtarla) """ -all_the_args(1, 2, a=3, b=4) prints: +tum_argumanlar(1, 2, a=3, b=4) çıktı: (1, 2) {"a": 3, "b": 4} """ -# Fonksiyonu çağırırken, args/kwargs'ın tam tersini de yapabilirsiniz! -# Tüpü yaymak için * ve kwargs'ı yaymak için ** kullanın. -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # foo(1, 2, 3, 4) ile eşit -all_the_args(**kwargs) # foo(a=3, b=4) ile eşit -all_the_args(*args, **kwargs) # foo(1, 2, 3, 4, a=3, b=4) ile eşit - -# Python first-class fonksiyonlara sahiptir -def create_adder(x): - def adder(y): - return x + y - return adder +# Fonksiyonu çağırırken de aynısını kullanabilirsiniz +argumanlar = (1, 2, 3, 4) +anahtarla = {"a": 3, "b": 4} +tum_argumanlar(*argumanlar) # = foo(1, 2, 3, 4) +tum_argumanlar(**anahtarla) # = foo(a=3, b=4) +tum_argumanlar(*argumanlar, **anahtarla) # = foo(1, 2, 3, 4, a=3, b=4) + + +# Fonksiyonlarda kullanacağımız bir değişken oluşturalım +x = 5 + +def belirleX(sayi): + # Fonksiyon içerisindeki x ile global tanımladığımız x aynı değil + x = sayi # => 43 + print (x) # => 43 + +def globalBelirleX(sayi): + global x + print (x) # => 5 + x = sayi # global olan x değişkeni artık 6 + print (x) # => 6 + +belirleX(43) +globalBelirleX(6) -add_10 = create_adder(10) -add_10(3) #=> 13 -# Anonymous fonksiyonlar da vardır -(lambda x: x > 2)(3) #=> True +# Sınıf fonksiyonları oluşturma +def toplama_olustur(x): + def topla(y): + return x + y + return topla + +ekle_10 = toplama_olustur(10) +ekle_10(3) # => 13 -# Dahili yüksek seviye fonksiyonlar vardır -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +# Bilinmeyen fonksiyon +(lambda x: x > 2)(3) # => True -# Map etme(maps) ve filtreleme(filtres) için liste kullanabiliriz. -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +# TODO - Fix for iterables +# Belirli sayıdan yükseğini alma fonksiyonu +map(ekle_10, [1, 2, 3]) # => [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] +# Filtreleme işlemi için liste comprehensions da kullanabiliriz +[ekle_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] #################################################### ## 5. Sınıflar #################################################### -# We subclass from object to get a class. -class Human(object): - - # Bir sınıf özelliği. Bu sınıfın tüm "instance"larına paylaşılmıştır. - species = "H. sapiens" - - # Basic initializer - def __init__(self, name): - # Metoda gelen argümanın değerini sınıfın elemanı olan "name" - # değişkenine atama - self.name = name - - # Bir instance metodu. Tüm metodlar ilk argüman olarak "self" - # parametresini alır - def say(self, msg): - return "%s: %s" % (self.name, msg) - - # Bir sınıf metodu tüm "instance"lar arasında paylaşılır - # İlk argüman olarak sınıfı çağırarak çağrılırlar + +# Sınıf oluşturmak için objeden alt sınıf oluşturacağız. +class Insan(object): + + # Sınıf değeri. Sınıfın tüm nesneleri tarafından kullanılabilir + tur = "H. sapiens" + + # Basit başlatıcı, Sınıf çağrıldığında tetiklenecektir. + # Dikkat edin, iki adet alt çizgi(_) bulunmakta. Bunlar + # python tarafından tanımlanan isimlerdir. + # Kendinize ait bir fonksiyon oluştururken __fonksiyon__ kullanmayınız! + def __init__(self, isim): + # Parametreyi sınıfın değerine atayalım + self.isim = isim + + # Bir metot. Bütün metotlar ilk parametre olarak "self "alır. + def soyle(self, mesaj): + return "{isim}: {mesaj}".format(isim=self.isim, mesaj=mesaj) + + # Bir sınıf metotu bütün nesnelere paylaştırılır + # İlk parametre olarak sınıf alırlar @classmethod - def get_species(cls): - return cls.species + def getir_tur(snf): + return snf.tur - # Bir statik metod bir sınıf ya da instance referansı olmadan çağrılır + # Bir statik metot, sınıf ve nesnesiz çağrılır @staticmethod def grunt(): return "*grunt*" -# Bir sınıf örneği oluşturmak -i = Human(name="Ian") -print i.say("hi") # "Ian: hi" çıktısı verir +# Sınıfı çağıralım +i = Insan(isim="Ahmet") +print(i.soyle("merhaba")) # çıktı "Ahmet: merhaba" -j = Human("Joel") -print j.say("hello") # "Joel: hello" çıktısı verir +j = Insan("Ali") +print(j.soyle("selam")) # çıktı "Ali: selam" -# Sınıf metodunu çağıralım -i.get_species() #=> "H. sapiens" +# Sınıf metodumuzu çağıraim +i.getir_tur() # => "H. sapiens" -# Paylaşılan sınıf özellik değiştirelim. -Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" +# Paylaşılan değeri değiştirelim +Insan.tur = "H. neanderthalensis" +i.getir_tur() # => "H. neanderthalensis" +j.getir_tur() # => "H. neanderthalensis" -# Statik metodu çağırma -Human.grunt() #=> "*grunt*" +# Statik metodumuzu çağıralım +Insan.grunt() # => "*grunt*" #################################################### -## 6. Modüller +## 6. Moduller #################################################### -# Modülleri sayfaya dahil edebilirsiniz +# Modülleri içe aktarabilirsiniz import math -print math.sqrt(16) #=> 4.0 +print(math.sqrt(16)) # => 4.0 -# Modül içerisinden spesifik bir fonksiyonu getirebilirsiniz +# Modülden belirli bir fonksiyonları alabilirsiniz from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 -# Modüldeki tüm fonksiyonları dahil edebilirsiniz -# Uyarı: bu önerilmez +# Modüldeki tüm fonksiyonları içe aktarabilirsiniz +# Dikkat: bunu yapmanızı önermem. from math import * -# Modülün adını kısaltabilirsiniz +# Modül isimlerini değiştirebilirsiniz. +# Not: Modül ismini kısaltmanız çok daha iyi olacaktır import math as m -math.sqrt(16) == m.sqrt(16) #=> True +math.sqrt(16) == m.sqrt(16) # => True -# Python modülleri sıradan python dosyalarıdır. Kendinize bir modül -# yazabilirsiniz, ve dahil edebilirsiniz. Modülün adı ile dosya adı -# aynı olmalıdır. +# Python modulleri aslında birer python dosyalarıdır. +# İsterseniz siz de yazabilir ve içe aktarabilirsiniz Modulün +# ismi ile dosyanın ismi aynı olacaktır. -# Modüllerde tanımlanmış fonksiyon ve metodları öğrenebilirsiniz. +# Moduldeki fonksiyon ve değerleri öğrenebilirsiniz. import math dir(math) +#################################################### +## 7. Gelişmiş +#################################################### + +# Oluşturucular uzun uzun kod yazmamanızı sağlayacak ve yardımcı olacaktır +def kare_sayilar(nesne): + for i in nesne: + yield i + i + +# Bir oluşturucu(generator) değerleri anında oluşturur. +# Bir seferde tüm değerleri oluşturup göndermek yerine teker teker her oluşumdan +# sonra geri döndürür. Bu demektir ki, kare_sayilar fonksiyonumuzda 15'ten büyük +# değerler işlenmeyecektir. +# Not: range() da bir oluşturucu(generator)dur. 1-900000000 arası bir liste yapmaya çalıştığınızda +# çok fazla vakit alacaktır. +# Python tarafından belirlenen anahtar kelimelerden kaçınmak için basitçe alt çizgi(_) kullanılabilir. +range_ = range(1, 900000000) +# kare_sayilar'dan dönen değer 30'a ulaştığında durduralım +for i in kare_sayilar(range_): + print(i) + if i >= 30: + break + + +# Dekoratörler +# Bu örnekte, +# Eğer lutfen_soyle True ise dönen değer değişecektir. +from functools import wraps + +def yalvar(hedef_fonksiyon): + @wraps(hedef_fonksiyon) + def metot(*args, **kwargs): + msj, lutfen_soyle = hedef_fonksiyon(*args, **kwargs) + if lutfen_soyle: + return "{} {}".format(msj, "Lütfen! Artık dayanamıyorum :(") + return msj + + return metot + + +@yalvar +def soyle(lutfen_soyle=False): + msj = "Bana soda alır mısın?" + return msj, lutfen_soyle + + +print(soyle()) # Bana soda alır mısın? +print(soyle(lutfen_soyle=True)) # Ban soda alır mısın? Lutfen! Artık dayanamıyorum :( ``` -## Daha fazlası için hazır mısınız? +## Daha Fazlasına Hazır Mısınız? -### Ücretsiz Dökümanlar +### Ücretsiz Online +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) +* [The Official Docs](http://docs.python.org/3/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) +* [Python Course](http://www.python-course.eu/index.php) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) -### Dead Tree +### Kitaplar * [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) * [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) * [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/tr-tr/python3-tr.html.markdown b/tr-tr/python3-tr.html.markdown deleted file mode 100644 index b78d517f..00000000 --- a/tr-tr/python3-tr.html.markdown +++ /dev/null @@ -1,640 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] - - ["Steven Basart", "http://github.com/xksteven"] - - ["Andre Polykanine", "https://github.com/Oire"] - - ["Batuhan Osman T.", "https://github.com/BTaskaya"] -translators: - - ["Eray AYDIN", "http://erayaydin.me/"] -lang: tr-tr -filename: learnpython3-tr.py ---- - -Python,90ların başlarında Guido Van Rossum tarafından oluşturulmuştur. En popüler olan dillerden biridir. Beni Python'a aşık eden sebep onun syntax beraklığı. Çok basit bir çalıştırılabilir söz koddur. - -Not: Bu makale Python 3 içindir. Eğer Python 2.7 öğrenmek istiyorsanız [burayı](http://learnxinyminutes.com/docs/python/) kontrol edebilirsiniz. - -```python - -# Tek satırlık yorum satırı kare(#) işareti ile başlamaktadır. - -""" Çok satırlı olmasını istediğiniz yorumlar - üç adet tırnak(") işareti ile - yapılmaktadır -""" - -#################################################### -## 1. Temel Veri Türleri ve Operatörler -#################################################### - -# Sayılar -3 # => 3 - -# Tahmin edebileceğiniz gibi matematik -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 - -# Bölme işlemi varsayılan olarak onluk döndürür -35 / 5 # => 7.0 - -# Tam sayı bölmeleri, pozitif ve negatif sayılar için aşağıya yuvarlar -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # onluklar için de bu böyledir --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# Onluk kullanırsanız, sonuç da onluk olur -3 * 2.0 # => 6.0 - -# Kalan operatörü -7 % 3 # => 1 - -# Üs (2 üzeri 4) -2**4 # => 16 - -# Parantez ile önceliği değiştirebilirsiniz -(1 + 3) * 2 # => 8 - -# Boolean(Doğru-Yanlış) değerleri standart -True -False - -# 'değil' ile terse çevirme -not True # => False -not False # => True - -# Boolean Operatörleri -# "and" ve "or" büyük küçük harf duyarlıdır -True and False #=> False -False or True #=> True - -# Bool operatörleri ile sayı kullanımı -0 and 2 #=> 0 --5 or 0 #=> -5 -0 == False #=> True -2 == True #=> False -1 == True #=> True - -# Eşitlik kontrolü == -1 == 1 # => True -2 == 1 # => False - -# Eşitsizlik Kontrolü != -1 != 1 # => False -2 != 1 # => True - -# Diğer karşılaştırmalar -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# Zincirleme şeklinde karşılaştırma da yapabilirsiniz! -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# Yazı(Strings) " veya ' işaretleri ile oluşturulabilir -"Bu bir yazı." -'Bu da bir yazı.' - -# Yazılar da eklenebilir! Fakat bunu yapmanızı önermem. -"Merhaba " + "dünya!" # => "Merhaba dünya!" - -# Bir yazı(string) karakter listesi gibi işlenebilir -"Bu bir yazı"[0] # => 'B' - -# .format ile yazıyı biçimlendirebilirsiniz, şu şekilde: -"{} da ayrıca {}".format("yazılar", "işlenebilir") - -# Biçimlendirme işleminde aynı argümanı da birden fazla kullanabilirsiniz. -"{0} çeviktir, {0} hızlıdır, {0} , {1} üzerinden atlayabilir".format("Ahmet", "şeker çubuğu") -#=> "Ahmet çeviktir, Ahmet hızlıdır, Ahmet , şeker çubuğu üzerinden atlayabilir" - -# Argümanın sırasını saymak istemiyorsanız, anahtar kelime kullanabilirsiniz. -"{isim} yemek olarak {yemek} istiyor".format(isim="Ahmet", yemek="patates") #=> "Ahmet yemek olarak patates istiyor" - -# Eğer Python 3 kodunuz ayrıca Python 2.5 ve üstünde çalışmasını istiyorsanız, -# eski stil formatlamayı kullanabilirsiniz: -"%s bu %s yolla da %s" % ("yazılar", "eski", "biçimlendirilebilir") - - -# Hiçbir şey(none) da bir objedir -None # => None - -# Bir değerin none ile eşitlik kontrolü için "==" sembolünü kullanmayın -# Bunun yerine "is" kullanın. Obje türünün eşitliğini kontrol edecektir. -"vb" is None # => False -None is None # => True - -# None, 0, ve boş yazılar/listeler/sözlükler hepsi False değeri döndürü. -# Diğer veriler ise True değeri döndürür -bool(0) # => False -bool("") # => False -bool([]) #=> False -bool({}) #=> False - - -#################################################### -## 2. Değişkenler ve Koleksiyonlar -#################################################### - -# Python bir yazdırma fonksiyonuna sahip -print("Ben Python. Tanıştığıma memnun oldum!") - -# Değişkenlere veri atamak için önce değişkeni oluşturmanıza gerek yok. -# Düzenli bir değişken için hepsi_kucuk_ve_alt_cizgi_ile_ayirin -bir_degisken = 5 -bir_degisken # => 5 - -# Önceden tanımlanmamış değişkene erişmek hata oluşturacaktır. -# Kontrol akışları başlığından hata kontrolünü öğrenebilirsiniz. -bir_bilinmeyen_degisken # NameError hatası oluşturur - -# Listeler ile sıralamaları tutabilirsiniz -li = [] -# Önceden doldurulmuş listeler ile başlayabilirsiniz -diger_li = [4, 5, 6] - -# 'append' ile listenin sonuna ekleme yapabilirsiniz -li.append(1) # li artık [1] oldu -li.append(2) # li artık [1, 2] oldu -li.append(4) # li artık [1, 2, 4] oldu -li.append(3) # li artık [1, 2, 4, 3] oldu -# 'pop' ile listenin son elementini kaldırabilirsiniz -li.pop() # => 3 ve li artık [1, 2, 4] -# Çıkarttığımız tekrardan ekleyelim -li.append(3) # li yeniden [1, 2, 4, 3] oldu. - -# Dizi gibi listeye erişim sağlayın -li[0] # => 1 -# Son elemente bakın -li[-1] # => 3 - -# Listede olmayan bir elemente erişim sağlamaya çalışmak IndexError hatası oluşturur -li[4] # IndexError hatası oluşturur - -# Bir kısmını almak isterseniz. -li[1:3] # => [2, 4] -# Başlangıç belirtmezseniz -li[2:] # => [4, 3] -# Sonu belirtmesseniz -li[:3] # => [1, 2, 4] -# Her ikişer objeyi seçme -li[::2] # =>[1, 4] -# Listeyi tersten almak -li[::-1] # => [3, 4, 2, 1] -# Kombinasyonları kullanarak gelişmiş bir şekilde listenin bir kısmını alabilirsiniz -# li[baslangic:son:adim] - -# "del" ile isteğe bağlı, elementleri listeden kaldırabilirsiniz -del li[2] # li artık [1, 2, 3] oldu - -# Listelerde de ekleme yapabilirsiniz -# Not: değerler üzerinde değişiklik yapılmaz. -li + diger_li # => [1, 2, 3, 4, 5, 6] - -# Listeleri birbirine bağlamak için "extend()" kullanılabilir -li.extend(diger_li) # li artık [1, 2, 3, 4, 5, 6] oldu - -# Listedeki bir elementin olup olmadığı kontrolü "in" ile yapılabilir -1 in li # => True - -# Uzunluğu öğrenmek için "len()" kullanılabilir -len(li) # => 6 - - -# Tüpler listeler gibidir fakat değiştirilemez. -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # TypeError hatası oluşturur - -# Diğer liste işlemlerini tüplerde de uygulayabilirsiniz -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True - -# Tüpleri(veya listeleri) değişkenlere açabilirsiniz -a, b, c = (1, 2, 3) # 'a' artık 1, 'b' artık 2 ve 'c' artık 3 -# Eğer parantez kullanmazsanız varsayılan oalrak tüpler oluşturulur -d, e, f = 4, 5, 6 -# 2 değeri birbirine değiştirmek bu kadar kolay -e, d = d, e # 'd' artık 5 ve 'e' artık 4 - - -# Sözlükler anahtar kodlarla verileri tutar -bos_sozl = {} -# Önceden doldurulmuş sözlük oluşturma -dolu_sozl = {"bir": 1, "iki": 2, "uc": 3} - -# Değere bakmak için [] kullanalım -dolu_sozl["bir"] # => 1 - -# Bütün anahtarları almak için "keys()" kullanılabilir. -# Listelemek için list() kullanacağınız çünkü dönen değerin işlenmesi gerekiyor. Bu konuya daha sonra değineceğiz. -# Not - Sözlük anahtarlarının sıralaması kesin değildir. -# Beklediğiniz çıktı sizinkiyle tam uyuşmuyor olabilir. -list(dolu_sozl.keys()) # => ["uc", "iki", "bir"] - - -# Tüm değerleri almak için "values()" kullanacağız. Dönen değeri biçimlendirmek için de list() kullanmamız gerekiyor -# Not - Sıralama değişebilir. -list(dolu_sozl.values()) # => [3, 2, 1] - - -# Bir anahtarın sözlükte olup olmadığını "in" ile kontrol edebilirsiniz -"bir" in dolu_sozl # => True -1 in dolu_sozl # => False - -# Olmayan bir anahtardan değer elde etmek isterseniz KeyError sorunu oluşacaktır. -dolu_sozl["dort"] # KeyError hatası oluşturur - -# "get()" metodu ile değeri almaya çalışırsanız KeyError sorunundan kurtulursunuz -dolu_sozl.get("bir") # => 1 -dolu_sozl.get("dort") # => None -# "get" metoduna parametre belirterek değerin olmaması durumunda varsayılan bir değer döndürebilirsiniz. -dolu_sozl.get("bir", 4) # => 1 -dolu_sozl.get("dort", 4) # => 4 - -# "setdefault()" metodu sözlükte, belirttiğiniz anahtarın [olmaması] durumunda varsayılan bir değer atayacaktır -dolu_sozl.setdefault("bes", 5) # dolu_sozl["bes"] artık 5 değerine sahip -dolu_sozl.setdefault("bes", 6) # dolu_sozl["bes"] değişmedi, hala 5 değerine sahip - -# Sözlüğe ekleme -dolu_sozl.update({"dort":4}) #=> {"bir": 1, "iki": 2, "uc": 3, "dort": 4} -#dolu_sozl["dort"] = 4 #sözlüğe eklemenin bir diğer yolu - -# Sözlükten anahtar silmek için 'del' kullanılabilir -del dolu_sozl["bir"] # "bir" anahtarını dolu sözlükten silecektir - - -# Setler ... set işte :D -bos_set = set() -# Seti bir veri listesi ile de oluşturabilirsiniz. Evet, biraz sözlük gibi duruyor. Üzgünüm. -bir_set = {1, 1, 2, 2, 3, 4} # bir_set artık {1, 2, 3, 4} - -# Sete yeni setler ekleyebilirsiniz -dolu_set = bir_set - -# Sete bir diğer öğe ekleme -dolu_set.add(5) # dolu_set artık {1, 2, 3, 4, 5} oldu - -# Setlerin çakışan kısımlarını almak için '&' kullanabilirsiniz -diger_set = {3, 4, 5, 6} -dolu_set & diger_set # => {3, 4, 5} - -# '|' ile aynı olan elementleri almayacak şekilde setleri birleştirebilirsiniz -dolu_set | diger_set # => {1, 2, 3, 4, 5, 6} - -# Farklılıkları almak için "-" kullanabilirsiniz -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} - -# Bir değerin olup olmadığının kontrolü için "in" kullanılabilir -2 in dolu_set # => True -10 in dolu_set # => False - - -#################################################### -## 3. Kontrol Akışları ve Temel Soyutlandırma -#################################################### - -# Bir değişken oluşturalım -bir_degisken = 5 - -# Burada bir "if" ifadesi var. Girinti(boşluk,tab) python için önemlidir! -# çıktı olarak "bir_degisken 10 dan küçük" yazar -if bir_degisken > 10: - print("bir_degisken 10 dan büyük") -elif bir_degisken < 10: # Bu 'elif' ifadesi zorunlu değildir. - print("bir_degisken 10 dan küçük") -else: # Bu ifade de zorunlu değil. - print("bir_degisken değeri 10") - - -""" -Döngülerle lsiteleri döngüye alabilirsiniz -çıktı: - köpek bir memeli hayvandır - kedi bir memeli hayvandır - fare bir memeli hayvandır -""" -for hayvan in ["köpek", "kedi, "fare"]: - # format ile kolayca yazıyı biçimlendirelim - print("{} bir memeli hayvandır".format(hayvan)) - -""" -"range(sayi)" bir sayı listesi döndür -0'dan belirttiğiniz sayıyıa kadar -çıktı: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -'While' döngüleri koşul çalıştıkça işlemleri gerçekleştirir. -çıktı: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # Uzun hali x = x + 1 - -# Hataları kontrol altına almak için try/except bloklarını kullanabilirsiniz -try: - # Bir hata oluşturmak için "raise" kullanabilirsiniz - raise IndexError("Bu bir index hatası") -except IndexError as e: - pass # Önemsiz, devam et. -except (TypeError, NameError): - pass # Çoklu bir şekilde hataları kontrol edebilirsiniz, tabi gerekirse. -else: # İsteğe bağlı bir kısım. Eğer hiçbir hata kontrol mekanizması desteklemiyorsa bu blok çalışacaktır - print("Her şey iyi!") # IndexError, TypeError ve NameError harici bir hatada bu blok çalıştı - -# Temel Soyutlandırma, bir objenin işlenmiş halidir. -# Aşağıdaki örnekte; Obje, range fonksiyonuna temel soyutlandırma gönderdi. - -dolu_sozl = {"bir": 1, "iki": 2, "uc": 3} -temel_soyut = dolu_sozl.keys() -print(temel_soyut) #=> range(1,10). Bu obje temel soyutlandırma arayüzü ile oluşturuldu - -# Temel Soyutlandırılmış objeyi döngüye sokabiliriz. -for i in temel_soyut: - print(i) # Çıktısı: bir, iki, uc - -# Fakat, elementin anahtarına değerine. -temel_soyut[1] # TypeError hatası! - -# 'iterable' bir objenin nasıl temel soyutlandırıldığıdır. -iterator = iter(temel_soyut) - -# 'iterator' o obje üzerinde yaptığımız değişiklikleri hatırlayacaktır -# Bir sonraki objeyi almak için __next__ fonksiyonunu kullanabilirsiniz. -iterator.__next__() #=> "bir" - -# Bir önceki __next__ fonksiyonumuzu hatırlayıp bir sonraki kullanımda bu sefer ondan bir sonraki objeyi döndürecektir -iterator.__next__() #=> "iki" -iterator.__next__() #=> "uc" - -# Bütün nesneleri aldıktan sonra bir daha __next__ kullanımınızda, StopIterator hatası oluşturacaktır. -iterator.__next__() # StopIteration hatası - -# iterator'deki tüm nesneleri almak için list() kullanabilirsiniz. -list(dolu_sozl.keys()) #=> Returns ["bir", "iki", "uc"] - - -#################################################### -## 4. Fonksiyonlar -#################################################### - -# "def" ile yeni fonksiyonlar oluşturabilirsiniz -def topla(x, y): - print("x = {} ve y = {}".format(x, y)) - return x + y # Değer döndürmek için 'return' kullanmalısınız - -# Fonksiyonu parametleri ile çağırıyoruz -topla(5, 6) # => çıktı "x = 5 ve y = 6" ve değer olarak 11 döndürür - -# Bir diğer fonksiyon çağırma yöntemi de anahtar değerleri ile belirtmek -topla(y=6, x=5) # Anahtar değeri belirttiğiniz için parametre sıralaması önemsiz. - -# Sınırsız sayıda argüman da alabilirsiniz -def argumanlar(*argumanlar): - return argumanlar - -argumanlar(1, 2, 3) # => (1, 2, 3) - -# Parametrelerin anahtar değerlerini almak isterseniz -def anahtar_par(**anahtarlar): - return anahtar - -# Çalıştırdığımızda -anahtar_par(anah1="deg1", anah2="deg2") # => {"anah1": "deg1", "anah2": "deg2"} - - -# İsterseniz, bu ikisini birden kullanabilirsiniz -def tum_argumanlar(*argumanlar, **anahtarla): - print(argumanlar) - print(anahtarla) -""" -tum_argumanlar(1, 2, a=3, b=4) çıktı: - (1, 2) - {"a": 3, "b": 4} -""" - -# Fonksiyonu çağırırken de aynısını kullanabilirsiniz -argumanlar = (1, 2, 3, 4) -anahtarla = {"a": 3, "b": 4} -tum_argumanlar(*argumanlar) # = foo(1, 2, 3, 4) -tum_argumanlar(**anahtarla) # = foo(a=3, b=4) -tum_argumanlar(*argumanlar, **anahtarla) # = foo(1, 2, 3, 4, a=3, b=4) - - -# Fonksiyonlarda kullanacağımız bir değişken oluşturalım -x = 5 - -def belirleX(sayi): - # Fonksiyon içerisindeki x ile global tanımladığımız x aynı değil - x = sayi # => 43 - print (x) # => 43 - -def globalBelirleX(sayi): - global x - print (x) # => 5 - x = sayi # global olan x değişkeni artık 6 - print (x) # => 6 - -belirleX(43) -globalBelirleX(6) - - -# Sınıf fonksiyonları oluşturma -def toplama_olustur(x): - def topla(y): - return x + y - return topla - -ekle_10 = toplama_olustur(10) -ekle_10(3) # => 13 - -# Bilinmeyen fonksiyon -(lambda x: x > 2)(3) # => True - -# TODO - Fix for iterables -# Belirli sayıdan yükseğini alma fonksiyonu -map(ekle_10, [1, 2, 3]) # => [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] - -# Filtreleme işlemi için liste comprehensions da kullanabiliriz -[ekle_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] - -#################################################### -## 5. Sınıflar -#################################################### - - -# Sınıf oluşturmak için objeden alt sınıf oluşturacağız. -class Insan(object): - - # Sınıf değeri. Sınıfın tüm nesneleri tarafından kullanılabilir - tur = "H. sapiens" - - # Basit başlatıcı, Sınıf çağrıldığında tetiklenecektir. - # Dikkat edin, iki adet alt çizgi(_) bulunmakta. Bunlar - # python tarafından tanımlanan isimlerdir. - # Kendinize ait bir fonksiyon oluştururken __fonksiyon__ kullanmayınız! - def __init__(self, isim): - # Parametreyi sınıfın değerine atayalım - self.isim = isim - - # Bir metot. Bütün metotlar ilk parametre olarak "self "alır. - def soyle(self, mesaj): - return "{isim}: {mesaj}".format(isim=self.isim, mesaj=mesaj) - - # Bir sınıf metotu bütün nesnelere paylaştırılır - # İlk parametre olarak sınıf alırlar - @classmethod - def getir_tur(snf): - return snf.tur - - # Bir statik metot, sınıf ve nesnesiz çağrılır - @staticmethod - def grunt(): - return "*grunt*" - - -# Sınıfı çağıralım -i = Insan(isim="Ahmet") -print(i.soyle("merhaba")) # çıktı "Ahmet: merhaba" - -j = Insan("Ali") -print(j.soyle("selam")) # çıktı "Ali: selam" - -# Sınıf metodumuzu çağıraim -i.getir_tur() # => "H. sapiens" - -# Paylaşılan değeri değiştirelim -Insan.tur = "H. neanderthalensis" -i.getir_tur() # => "H. neanderthalensis" -j.getir_tur() # => "H. neanderthalensis" - -# Statik metodumuzu çağıralım -Insan.grunt() # => "*grunt*" - - -#################################################### -## 6. Moduller -#################################################### - -# Modülleri içe aktarabilirsiniz -import math -print(math.sqrt(16)) # => 4.0 - -# Modülden belirli bir fonksiyonları alabilirsiniz -from math import ceil, floor -print(ceil(3.7)) # => 4.0 -print(floor(3.7)) # => 3.0 - -# Modüldeki tüm fonksiyonları içe aktarabilirsiniz -# Dikkat: bunu yapmanızı önermem. -from math import * - -# Modül isimlerini değiştirebilirsiniz. -# Not: Modül ismini kısaltmanız çok daha iyi olacaktır -import math as m -math.sqrt(16) == m.sqrt(16) # => True - -# Python modulleri aslında birer python dosyalarıdır. -# İsterseniz siz de yazabilir ve içe aktarabilirsiniz Modulün -# ismi ile dosyanın ismi aynı olacaktır. - -# Moduldeki fonksiyon ve değerleri öğrenebilirsiniz. -import math -dir(math) - - -#################################################### -## 7. Gelişmiş -#################################################### - -# Oluşturucular uzun uzun kod yazmamanızı sağlayacak ve yardımcı olacaktır -def kare_sayilar(nesne): - for i in nesne: - yield i + i - -# Bir oluşturucu(generator) değerleri anında oluşturur. -# Bir seferde tüm değerleri oluşturup göndermek yerine teker teker her oluşumdan -# sonra geri döndürür. Bu demektir ki, kare_sayilar fonksiyonumuzda 15'ten büyük -# değerler işlenmeyecektir. -# Not: range() da bir oluşturucu(generator)dur. 1-900000000 arası bir liste yapmaya çalıştığınızda -# çok fazla vakit alacaktır. -# Python tarafından belirlenen anahtar kelimelerden kaçınmak için basitçe alt çizgi(_) kullanılabilir. -range_ = range(1, 900000000) -# kare_sayilar'dan dönen değer 30'a ulaştığında durduralım -for i in kare_sayilar(range_): - print(i) - if i >= 30: - break - - -# Dekoratörler -# Bu örnekte, -# Eğer lutfen_soyle True ise dönen değer değişecektir. -from functools import wraps - - -def yalvar(hedef_fonksiyon): - @wraps(hedef_fonksiyon) - def metot(*args, **kwargs): - msj, lutfen_soyle = hedef_fonksiyon(*args, **kwargs) - if lutfen_soyle: - return "{} {}".format(msj, "Lütfen! Artık dayanamıyorum :(") - return msj - - return metot - - -@yalvar -def soyle(lutfen_soyle=False): - msj = "Bana soda alır mısın?" - return msj, lutfen_soyle - - -print(soyle()) # Bana soda alır mısın? -print(soyle(lutfen_soyle=True)) # Ban soda alır mısın? Lutfen! Artık dayanamıyorum :( -``` - -## Daha Fazlasına Hazır Mısınız? - -### Ücretsiz Online - -* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) -* [Python Course](http://www.python-course.eu/index.php) -* [First Steps With Python](https://realpython.com/learn/python-first-steps/) -* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) -* [30 Python Language Features and Tricks You May Not Know About](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) -* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) -* [Python 3 Computer Science Circles](http://cscircles.cemc.uwaterloo.ca/) - -### Kitaplar - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - diff --git a/tr-tr/pythonlegacy-tr.html.markdown b/tr-tr/pythonlegacy-tr.html.markdown new file mode 100644 index 00000000..cd757625 --- /dev/null +++ b/tr-tr/pythonlegacy-tr.html.markdown @@ -0,0 +1,502 @@ +--- +language: Python 2 (legacy) +filename: learnpythonlegacy-tr.py +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Haydar KULEKCI", "http://scanf.info/"] +lang: tr-tr +--- +Python Guido Van Rossum tarafından 90'ların başında yaratılmıştır. Şu anda +varolanlar arasında en iyi dillerden birisidir. Ben (Louie Dinh) Python +dilinin syntax'ının belirginliğine aşığım. O basit olarak çalıştırılabilir +pseudocode'dur. + +Geri bildirimlerden son derece mutluluk duyarım! Bana [@louiedinh](http://twitter.com/louiedinh) +adresinden ya da louiedinh [at] [google's email service] adresinden ulaşabilirsiniz. + +Çeviri için geri bildirimleri de [@kulekci](http://twitter.com/kulekci) +adresine yapabilirsiniz. + +Not: Bu yazıdaki özellikler Python 2.7 için geçerlidir, ama Python 2.x için de +uygulanabilir. Python 3 için başka bir zaman tekrar bakınız. + + +```python +# Tek satır yorum hash işareti ile başlar. +""" Çoklu satır diziler üç tane çift tırnak + arasında yazılır. Ve yorum olarak da + kullanılabilir +""" + + +#################################################### +## 1. İlkel Veri Tipleri ve Operatörler +#################################################### + +# Sayılar +3 #=> 3 + +# Matematik beklediğiniz gibi +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# Bölünme biraz ilginç. EĞer tam sayılar üzerinde bölünme işlemi yapıyorsanız +# sonuç otomatik olarak kırpılır. +5 / 2 #=> 2 + +# Bölünme işlemini düzenlemek için kayan noktalı sayıları bilmeniz gerekir. +2.0 # Bu bir kayan noktalı sayı +11.0 / 4.0 #=> 2.75 ahhh...daha iyi + +# İşlem önceliğini parantezler ile sağlayabilirsiniz. +(1 + 3) * 2 #=> 8 + +# Boolean değerleri bilindiği gibi +True +False + +# not ile nagatif(mantıksal) değerini alma +not True #=> False +not False #=> True + +# Eşitlik == +1 == 1 #=> True +2 == 1 #=> False + +# Eşitsizlik != +1 != 1 #=> False +2 != 1 #=> True + +# Daha fazla karşılaştırma +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# Karşılaştırma zincirleme yapılabilir! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# Karakter dizisi " veya ' ile oluşturulabilir +"This is a string." +'This is also a string.' + +# Karakter dizileri birbirleri ile eklenebilir +"Hello " + "world!" #=> "Hello world!" + +# A string can be treated like a list of characters +# Bir string'e karakter listesi gibi davranabilirsiniz. +"This is a string"[0] #=> 'T' + +# % karakter dizisini(string) formatlamak için kullanılır, bunun gibi: +"%s can be %s" % ("strings", "interpolated") + +# String'leri formatlamanın yeni bir yöntem ise format metodudur. +# Bu metod tercih edilen yöntemdir. +"{0} can be {1}".format("strings", "formatted") +# Eğer saymak istemiyorsanız anahtar kelime kullanabilirsiniz. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") + +# None bir objedir +None #=> None + +# "==" eşitliğini non objesi ile karşılaştırmak için kullanmayın. +# Onun yerine "is" kullanın. +"etc" is None #=> False +None is None #=> True + +# 'is' operatörü obje kimliği için test etmektedir. Bu ilkel değerler +# için kullanışlı değildir, ama objeleri karşılaştırmak için kullanışlıdır. + +# None, 0 ve boş string/list'ler False olarak değerlendirilir. +# Tüm eşitlikler True döner +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. Değişkenler ve Kolleksiyonlar +#################################################### + +# Ekrana yazdırma oldukça kolaydır. +print "I'm Python. Nice to meet you!" + + +# Değişkenlere bir değer atamadan önce tanımlamaya gerek yoktur. +some_var = 5 # Değişken isimlerinde gelenek küçük karakter ve alt çizgi + # kullanmaktır. +some_var #=> 5 + +# Daha önceden tanımlanmamış ya da assign edilmemeiş bir değişkene erişmeye +# çalıştığınızda bir hata fırlatılacaktır. Hata ayıklama hakkında daha fazla +# bilgi için kontrol akışı kısmına göz atınız. +some_other_var # isim hatası fırlatılır + +# isterseniz "if"i bir ifade gibi kullanabilirsiniz. +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# Listeler +li = [] +# Önceden değerleri tanımlanmış listeler +other_li = [4, 5, 6] + +# Bir listenin sonuna birşeyler eklemek +li.append(1) #li şu anda [1] +li.append(2) #li şu anda [1, 2] +li.append(4) #li şu anda [1, 2, 4] +li.append(3) #li şu anda [1, 2, 4, 3] +# pop ile sondan birşeyler silmek +li.pop() #=> 3 and li is now [1, 2, 4] +# Tekrar sonuna eklemek +li.append(3) # li is now [1, 2, 4, 3] again. + +# Dizi gibi listenin elemanlarına erişmek +li[0] #=> 1 +# Son elemanın değerine ulaşmak +li[-1] #=> 3 + +# Listede bulunmayan bir index'teki elemana erişirken "IndexError" hatası +# fırlatılır +li[4] # IndexError fırlatılır + +# slice syntax'ı ile belli aralıktakı değerlere bakabilirsiniz. +# (Açık ve kapalı aralıklıdır.) +li[1:3] #=> [2, 4] +# Başlangıcı ihmal etme +li[2:] #=> [4, 3] +# Sonu ihmal etme +li[:3] #=> [1, 2, 4] + +# "del" ile istenilen bir elemanı listeden silmek +del li[2] # li is now [1, 2, 3] + +# Listeleri birbiri ile birleştirebilirsiniz. +li + other_li #=> [1, 2, 3, 4, 5, 6] - Not: li ve other_li yanlız bırakılır + +# extend ile listeleri birleştirmek +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] + +# bir değerin liste içerisinde varlığını "in" ile kontrol etmek +1 in li #=> True + +# "len" ile listenin uzunluğunu bulmak +len(li) #=> 6 + +# Tüpler listeler gibidir sadece değişmezler(immutable) +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # TypeError fırlatılır. + +# Litelerde yapılanların hepsini tüplerde de yapılabilir +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# Tüplerin(veya listelerin) içerisindeki değerleri değişkenelere +# atanabilir +a, b, c = (1, 2, 3) # a şu anda 1, b şu anda 2 ve c şu anda 3 +# Eğer parantez kullanmaz iseniz tüpler varsayılan olarak oluşturulur +d, e, f = 4, 5, 6 +# şimdi iki değeri değiş tokuş etmek çok kolaydır. +e, d = d, e # d şimdi 5 ve e şimdi 4 + + +# Sözlükler (Dictionaries) key-value saklanır. +empty_dict = {} +# Sözlüklere önceden değer atama örneği +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Değere ulaşmak için [] kullanılır +filled_dict["one"] #=> 1 + +# Tüm anahtarlara(key) "keys()" metodu ile ulaşılır +filled_dict.keys() #=> ["three", "two", "one"] +# Not - Sözlüklerin anahtarlarının sıralı geleceği garanti değildir +# Sonuçlarınız değer listesini aldığınızda tamamen eşleşmeyebilir + +# Tüm değerleri almak için "values()" kullanabilirsiniz. +filled_dict.values() #=> [3, 2, 1] +# Not - Sıralama ile ilgili anahtarlar ile aynı durum geçerlidir. + +# Bir anahtarın sözlükte oluş olmadığını "in" ile kontrol edilebilir +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# Olmayan bir anahtar çağrıldığında KeyError fırlatılır. +filled_dict["four"] # KeyError + +# "get()" metodu KeyError fırlatılmasını önler +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# get() metodu eğer anahtar mevcut değilse varsayılan bir değer atama +# imknaı sağlar. +filled_dict.get("one", 4) #=> 1 +filled_dict.get("four", 4) #=> 4 + +# "setdefault()" metodu sözlüğe yeni bir key-value eşleşmesi eklemenin +# güvenli bir yoludur. +filled_dict.setdefault("five", 5) #filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) #filled_dict["five"] is still 5 + + +# Sets store ... well sets +empty_set = set() +# Bir demek değer ile bir "set" oluşturmak +some_set = set([1,2,2,3,4]) # some_set is now set([1, 2, 3, 4]) + +# Python 2.7'den beri {}'ler bir "set" tanımlaman için kullanılabilir +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# Bir set'e daha fazla eleman eklemek +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} + +# "&" işareti ile iki set'in kesişimlerini alınabilir +other_set = {3, 4, 5, 6} +filled_set & other_set #=> {3, 4, 5} + +# | işareti ile +filled_set | other_set #=> {1, 2, 3, 4, 5, 6} + +# "-" işareti ile iki set'in farkları alınabilir +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# "in" ile değerin set içerisinde olup olmadığını kontrol edebilirsiniz +2 in filled_set #=> True +10 in filled_set #=> False + + +#################################################### +## 3. Akış Denetimi +#################################################### + +# Bir değişken oluşturmak +some_var = 5 + +# Buradaki bir if ifadesi. Girintiler(Intentation) Python'da önemlidir! +# "some_var is smaller than 10" yazdırılır. +if some_var > 10: + print "some_var is totally bigger than 10." +elif some_var < 10: # elif ifadesi isteğe bağlıdır + print "some_var is smaller than 10." +else: # Bu da isteğe bağlıdır. + print "some_var is indeed 10." + + +""" +For döngüleri listeler üzerinde iterasyon yapar +Ekrana yazdırılan: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # Biçimlendirmeleri string'e katmak için % kullanabilirsiniz + print "%s is a mammal" % animal + +""" +"range(number)" ifadesi sıfırdan verilen sayıya kadar bir sayı listesi döner +Ekrana yazdırılan: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +While döngüsü koşul sağlanmayana kadar devam eder +Ekrana yazdırılan: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Shorthand for x = x + 1 + +# try/except bloğu ile hatalar ayıklanabilir + +# Python 2.6 ve üstü için çalışacaktır: +try: + # "raise" bir hata fırlatmak için kullanılabilir + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass is just a no-op. Usually you would do recovery here. + + +#################################################### +## 4. Fonksiyonlar +#################################################### + + +# Yeni bir fonksiyon oluşturmak için "def" kullanılır +def add(x, y): + print "x is %s and y is %s" % (x, y) + return x + y # Return values with a return statement + +# Fonksiyonu parametre ile çağırmak +add(5, 6) #=> prints out "x is 5 and y is 6" and returns 11 + +# Diğer bir yol fonksiyonları anahtar argümanları ile çağırmak +add(y=6, x=5) # Anahtar argümanlarının sırası farklı da olabilir + +# Değişken sayıda parametresi olan bir fonksiyon tanımlayabilirsiniz +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + +# Değişken sayıda anahtar argümanlı parametre alan fonksiyonlar da +# tanımlayabilirsiniz. +def keyword_args(**kwargs): + return kwargs + +# Şu şekilde kullanılacaktır +keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} + +# Eğer isterseniz ikisini aynı anda da yapabilirsiniz +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# Fonksiyonu çağırırken, args/kwargs'ın tam tersini de yapabilirsiniz! +# Tüpü yaymak için * ve kwargs'ı yaymak için ** kullanın. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # foo(1, 2, 3, 4) ile eşit +all_the_args(**kwargs) # foo(a=3, b=4) ile eşit +all_the_args(*args, **kwargs) # foo(1, 2, 3, 4, a=3, b=4) ile eşit + +# Python first-class fonksiyonlara sahiptir +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) #=> 13 + +# Anonymous fonksiyonlar da vardır +(lambda x: x > 2)(3) #=> True + +# Dahili yüksek seviye fonksiyonlar vardır +map(add_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# Map etme(maps) ve filtreleme(filtres) için liste kullanabiliriz. +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + + +#################################################### +## 5. Sınıflar +#################################################### + +# We subclass from object to get a class. +class Human(object): + + # Bir sınıf özelliği. Bu sınıfın tüm "instance"larına paylaşılmıştır. + species = "H. sapiens" + + # Basic initializer + def __init__(self, name): + # Metoda gelen argümanın değerini sınıfın elemanı olan "name" + # değişkenine atama + self.name = name + + # Bir instance metodu. Tüm metodlar ilk argüman olarak "self" + # parametresini alır + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # Bir sınıf metodu tüm "instance"lar arasında paylaşılır + # İlk argüman olarak sınıfı çağırarak çağrılırlar + @classmethod + def get_species(cls): + return cls.species + + # Bir statik metod bir sınıf ya da instance referansı olmadan çağrılır + @staticmethod + def grunt(): + return "*grunt*" + + +# Bir sınıf örneği oluşturmak +i = Human(name="Ian") +print i.say("hi") # "Ian: hi" çıktısı verir + +j = Human("Joel") +print j.say("hello") # "Joel: hello" çıktısı verir + +# Sınıf metodunu çağıralım +i.get_species() #=> "H. sapiens" + +# Paylaşılan sınıf özellik değiştirelim. +Human.species = "H. neanderthalensis" +i.get_species() #=> "H. neanderthalensis" +j.get_species() #=> "H. neanderthalensis" + +# Statik metodu çağırma +Human.grunt() #=> "*grunt*" + + +#################################################### +## 6. Modüller +#################################################### + +# Modülleri sayfaya dahil edebilirsiniz +import math +print math.sqrt(16) #=> 4.0 + +# Modül içerisinden spesifik bir fonksiyonu getirebilirsiniz +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# Modüldeki tüm fonksiyonları dahil edebilirsiniz +# Uyarı: bu önerilmez +from math import * + +# Modülün adını kısaltabilirsiniz +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Python modülleri sıradan python dosyalarıdır. Kendinize bir modül +# yazabilirsiniz, ve dahil edebilirsiniz. Modülün adı ile dosya adı +# aynı olmalıdır. + +# Modüllerde tanımlanmış fonksiyon ve metodları öğrenebilirsiniz. +import math +dir(math) + + + +``` + +## Daha fazlası için hazır mısınız? + +### Ücretsiz Dökümanlar + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) + +### Dead Tree + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) diff --git a/tr-tr/ruby-tr.html.markdown b/tr-tr/ruby-tr.html.markdown new file mode 100644 index 00000000..7bc21c83 --- /dev/null +++ b/tr-tr/ruby-tr.html.markdown @@ -0,0 +1,1598 @@ +--- +name: ruby +language: ruby +filename: learnruby-tr.rb +contributors: + - ["Seçkin KÜKRER", "https://github.com/LeaveNhA"] +lang: tr-tr +--- + +# Dile nazik bir giriş. + +## Ruby Nedir ? + +Ruby, doğrudan bir Google aramasıyla aklınızdakini bulmanız zor olabilir. İngilizce bu kelime, `Ruby` (IPA: ˈruːbi) "kırmızı taş" anlamına gelen Fransızca kökenli bir kelime olan `rubi`'den gelmektedir. + +Yaratıcısı tarafından, yine esinlenilen bir dil olarak ortaya çıkan `Ruby`, Perl, Smalltalk, Eiffel, Ada, Lisp programlama dillerinin en iyi özelliklerini almıştır. ! [İmperativ]() programlama mentalitesi üzerine kurmayı seçtiği bu teknoloji, günümüzde sektöründe öncü. + + +## Tarihçe + +Ruby 1995’te halka duyurulduğundan beri, dünya çapında programcıların dikkatini çekmeye başlamıştır. 2006 Ruby’nin altın yılı olmuştur. Dünyanın en büyük şehirlerinde aktif kullanıcı grupları ve Ruby ile ilgili konferanslar gerçekleştirilmiştir. + +Daha sonraları `Ruby`, dünya çapında programlama dillerinin büyümesini ve popülaritesini ölçen dizinlerin (TIOBE dizini gibi) çoğunda ilk 10 içinde yer almıştır. Büyümenin çoğu, Ruby ile yazılmış yazılımların popülaritesiyle ilgilidir, özellikle de Ruby on Rails web çatısıyla. + +! [kaynak]() + +## Sektördeki Konumu ve Geleceği ? + +Çoğu uzmana göre, şu anda sadece `Rails` teknolojisi için bir betik dili olarak sıkışmış durumda. + +Bazıları ise, dilin kendi geleceğini, 2020 içinde yayınlanması planlanan `Ruby 3` ile sağlamlaştıracağını ve yeni imkanlar ve sektörek kullanım ve tercihler ile popüleritesinin artacağını düşünüyor. + +## Her Şey Nesne + +Matz'ın incelemiş olduğu diller sonucunda, teknik olarak en iyi sözdizimin kaynağını “Perl’den daha güçlü ama Python’dan daha nesneye yönelik bir betik dili” olarak tanımlamış. + +Her şeyin Nesne olarak görüldüğü bir programlama teknolojisi, bütünlük kavramı açısından herkese kucak açan bir pürüzsüzlük sunuyor. `Ruby`'nin neden tartışmasız, saf bir Nesne yönelimli bir programlama dili olduğuna dair örnekleri aşağıda vereceğim. + +## Diğer Gerçeklemeler + +- [JRuby](http://jruby.org/), JVM’in (Java Virtual Machine) üstünde çalışan Ruby’dir, JVM’in eniyileyen JIT derleyicisi, çöp toplayıcısı, eşzamanlı thread’leri, araç ekosistemi, ve muazzam sayıdaki kütüphanelerinden faydalanır. +- [Rubinius](http://rubini.us/), ‘Ruby’da yazılmış Ruby’dir’. LLVM’in üstüne inşa edilmiştir ve ayrıca diğer dillerin üstüne inşa edebilecekleri şık bir sanal makine de sunar. +- [TruffleRuby](https://github.com/oracle/truffleruby), GraalVM’in üstünde çalışan yüksek performanslı bir Ruby gerçeklemesidir. +- [IronRuby](http://www.ironruby.net/), “.NET Web Çatısı’yla sıkı sıkıya bağlı” bir gerçeklemedir. + +Diğer gerçeklemeler için, lütfen ileri okumaya danışınız. + +```ruby +# Bu karakter ile başlayan satırlar, yorum satırı olarak değerlendirilir. +# Diğer yorum satırı tanımlamaları için tanımlamalar ve ifadeler kısmına danışın. + +## Örnek yapısı; bu örnek dosyadaki her Ruby ifadesi, Ruby yorumlayıcısı +## tarafından yorumlanarak sonucu `=>` ifadesinin sağına yazılır. +## örnek ifade #=> örnek sonuç +## formatındadır. +## Bazen satır aşımını önlemek için +## örnek ifade +## #=> örnek sonuç +## şeklinde yer verilecektir. + +# -------------------------------- +# Veriler ve Temsilleri +# -------------------------------- + +## -- +## Sayılar: +## -- +### Ruby, tamsayı veri tipini destekler. Sayısal değerlerin sisteminizdeki temsili +### bu veri yapısıdır. + +# Tam sayı örneği. +1453 #=> 1453 + +## Okunabilirlik için, binlik ya da ondalık kısmını `_` ile +## ayırmak mümkündür ve bu karakter tümüyle görmezden gelinir. +3_14 #=> 314 + +## Negatif sayılar `-` ile başlıyor. +-3750 #=> -3750 + +## Oktal sayılar +03603 #=> 1923 + +## Onaltılık sayılar +0x23B #=> 571 + +## İkilik sayılar +0b11110000011 #=> 1923 + +## Büyük sayılar temsili +12345678901234567890 #=> 12345678901234567890 + +## Kayan noktalı sayılar + +## Bir kayan-noktalı/Ondalıklı sayı. +3.14 #=> 3.14 + +## Bilimsel notasyon +1.0e3 #=> 1000.0 + +## Bir ipucu, +## üsten önce işaret! +3e+9 #=> 3000000000.0 + +## -- +# Mantıksal Değerler +## -- + +## Mantıksal doğru ifadesi. +true #=> true + +## Mantıksal yanlış ifadesi. +false #=> false + +## -- +# Metinler +## -- + +## Metin sabitleri +'Bu, bir metin ifadesi.' + +## Kaçışlar için +'Kaçışlar için "\\"' #=> "Kaçışlar için \"\\\"" + +## Alternatif ise çift tırnaklı ifadeler. +"Bu da bir metin ifadesi." + +## Kaçışlarda farkı ise, +"Kaçılar için '\\'" #=> "Kaçılar için '\\'" +## bazı kaçış notasyonlarına gerek kalmaması. + +## Bazı notasyon karakterleri + +### Yeni Satır (New Line 0x0a) +"\n" #=> "\n" + +### Boşluk (Space 0x20) +"\s" #=> "\s" + +## -- +# Karakterler +## -- + +## Basitçe önlerine soru işareti getirilmiş +## tek karakter sabitleridir. +?a #=> "a" + + +## -- +# Semboller +## -- +## Ruby'de semboller, temsilleri bakımından +## Clojure'daki semboller ile benzerlerdir. +:sembol #=> :sembol + +## Kendileri, birinci sınıf değerdir. +:türk.class #=> Symbol +## Ve aynı zamanda Unicode desteği vardır. (1.9 sürümünden beri) + + +## -- +# Diziler +## -- +## Basitçe, Ruby dizileri birilerinden virgül ile ayrılmış, +## değer veya değer sahibi referansların köşeli parantezler +## ile çevrelenmesi ile oluşturulur. ([]) +[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +## Metinler için de durum aynı. +["Mustafa", "Kemal", "ATATÜRK"] #=> ["Mustafa", "Kemal", "ATATÜRK"] + +## Aynı zamanda, Ruby dizileri tip bağımsız nesne ardışıklarıdır. +[1881, "Mustafa", "Kemal", "ATATÜRK", 1923, "∞"] +## Aynı zamanda Unicode destekler (1.9 sürümünden beri) + +## -- +# Eşlemeler +## -- +## Ruby eşlemeleri, süslü parantezler içinde virgül ile ayrılan, +## anahtar ve değer ikililieridir. + +## Bir tane de olabilir, +{"izmir" => "kızları"} #=> {"izmir" => "kızları"} + +## Ya da, birden fazla... +{"izmir" => "kızları", "paris" => "sokakları"} #=> {"izmir" => "kızları", "paris" => "sokakları"} + +## Aslında her değeri anahtar veya değer olarak +## yerleştirmek mümkün. + +## Sembolleri, +{:zafer => "30 Ağustos!"} #=> {:zafer=>"30 Ağustos!"} + +## Rakamları bile. +{28101923 => "Efendiler, yarın Cumhuriyeti'i ilân edeceğiz!"} +#=> {28101923=>"Efendiler, yarın Cumhuriyeti'i ilân edeceğiz!"} + +## Semboller için ufak bir sözdizimsel şekerleme mevcut ki, +{istanbul: "beyefendi"} #=> {:istanbul=>"beyefendi"} +## Bu kullanıma göre, sembol anahtarlar ile değerler arasına +## `=>` yerine basitçe sembolün başına gelecek `:` sembolü +## getiriliyor. + + +## -- +# Aralıklar +## -- +## Ruby aralıkları temeliyle başlangıç ve bitiş +## değerleri arasındaki aralığın veriye dönüştürülmesi +## için bir dil olanağıdır. + +## (başlangıç..bitiş) notasyonu kullanılabilir. +(0..10) #=> 0..10 +## REPL'ın bize verdiği ifade sizi yanıltmasın, bu bir aralıktır. +## Meraklılarıyla, dökümanın devamında içindeki değerleri +## gezeceğiz. + +## Range.new notasyonu ile de ilklenebilirler. +Range.new(0, 10) #=> 0..10 + +## -- +# Düzenli İfadeler +## -- +## İki / operatörünün ortasına tanımlanırlar. +//.class #=> Regexp + +## Örnek bir düzenli ifade, a harfi için. +/[a]/ #=> /[a]/ + +# -------------------------------- +# Değelerin Manipüle edilmesi +# -------------------------------- + +## -- +## Rakamlar +## -- + +## Aritmatik, bildiğimiz şekilde. +## !! infix notasyon + +235 + 1218 #=> 1453 +123 - 35 #=> 88 +2 * 2 #=> 4 +1 / 1 #=> 1 + +## Bit tabanlı işlemler. +2 & 5 #=> 0 +3 | 9 #=> 11 +2 ^ 5 #=> 7 +## Aslında C tipi ailesi dillerdeki gibi. Sezgisel bir yaklaşımla, hayatta kalınabilir. +## Ama yine de dökümantasyona başvurulmasını tavsiye ederim. + + +## -- +## Mantıksal +## -- + +## ! operatörü teklidir, ve aldığı değerin mantıksal tersini alır. +!true #=> false +!false #=> true + + +## -- +## Metinler +## -- + +### Boş mu ? +"".empty? #=> true + +### Bir bölümünü alalım. +"Ölürüm TÜRKİYEM!".slice(7, 7) #=> "Türkiye" +## Bir başka şekilde, indis notasyonu ile, +"Ölürüm Türkiye'm!"[7, 7] #=> "Türkiye" + +## Küçük harfe dönüştürelim +"LAY-LAY-LOM sana göre sevmeler...".downcase +#=> "lay-lay-lom sana göre sevmeler..." + +## Büyük harfa dönüştürelim +"beşiktaş".upcase #=> "BEŞIKTAŞ" + +## Karakterlerine ayıralım +"BEŞİKTAŞ".chars #=> ["B", "E", "Ş", "İ", "K", "T", "A", "Ş"] + +## Çevrelemek için +"Ahmet Mete IŞIKARA".center(30) +#=> " Ahmet Mete IŞIKARA " + +## İçerik kontrolü için include metodu +"aşk".include?(?a) #=> true +## argümanı metin tipinde de verebilirdik, ama +## yukarıdaki temsillerde gördüğümüz gibi, +## yorumlayıcı, karakter sabitini metin olarak işliyor zaten. + +## Konumunu alalım. +"Dayı".index("a") #=> 1 +## Elbette, tasarımında sağlıklı kararlar alınmış her +## dil gibi, Ruby'de 0'dan saymaya başlıyor. + +## Metin yerleştirme yapalım +"Ali Baba'nın x çiftliği var.".sub("x", "bir") +#=> "Ali Baba'nın bir çiftliği var." + +## Birden fazla eşleşme için, değiştirme yapalım +"Dal sarkar x kalkar, x kalkar dal sarkar.".gsub("x", "kartal") +#=> "Dal sarkar kartal kalkar, kartal kalkar dal sarkar." + +## Düzenli ifadeler ile, cümledeki sesli harfleri değiştirelim. +"Bir berber bir bere...".gsub(/[ie]/, "*") +#=> "B*r b*rb*r b*r b*r*..." + +## Diğer işlevler için ileri okumadaki kaynağa başvurunuz. + + +## -- +## Eşlemeler +## -- + +## basit bir eşleme ile başlayalım. +{:boy => 1.74} #=> {:boy => 1.74} + +## Belirli bir anahtar, eşlememizde barınıyor mu diye +## kontrol ediyoruz. +{:boy => 1.74}.has_key? :boy +#=> true +## Parantezlerin yokluğu sizi yanıltmasın, +## bu bir fonksiyon çağırısıdır. + +## Eşlemeden veri çekiyoruz +{:boy => 1.74}.fetch :boy +#=> 1.74 + +## Eşlemelere veri ekliyoruz +{:boy => 1.74}.merge!(kilo: 74) +#=> {:boy=>1.74, :kilo=>74} + +## Anahtarlarımıza bakalım +{:boy=>1.74, :kilo=>74}.keys +#=> [:boy, :kilo] + +## Değerlerimize bakalım +{:boy=>1.74, :kilo=>74}.values +#=> [1.74, 74] + +## Dizi olarak almak istersek +{:boy=>1.74, :kilo=>74}.to_a +#=> [[:boy, 1.74], [:kilo, 74]] +## Endişelenmeyin, dönüşümler için koca bir bölüm +## ayırdım. + + +## -- +## Diziler +## -- + +## Örnek bir dizi ile başlayalım. +["Mustafa", "Kemal", "ATATÜRK"] +#=> ["Mustafa", "Kemal", "ATATÜRK"] + +## İlk değeri alıyoruz +["Mustafa", "Kemal", "ATATÜRK"].first +#=> "Mustafa" + +## Son Değeri, +["Mustafa", "Kemal", "ATATÜRK"].last +#=> "ATATÜRK" + +## Indis araması için `fetch` metodu. +["Mustafa", "Kemal", "ATATÜRK"].fetch 1 +#=> "Kemal" + +## Var olamyan bir indis ararsak hata alıyoruz. + +## Fakat seçimli ikinci argüman bize indisin +## bulunamaması halinde döndürülecek değeri +## belirleme imkanı veriyor. +["Mustafa", "Kemal", "ATATÜRK"].fetch 20101927, "Nutuk" +#=> "Nutuk" + +## Birden fazla değer almak için, slice metodunu +## kullanabiliriz +["Fatih", "Sultan", "Mehmet"].slice 1..2 +#=> ["Sultan", "Mehmet"] + +## Ya da, indis notasyonu da kullanılabilir. +["Fatih", "Sultan", "Mehmet"][1..2] +#=> ["Sultan", "Mehmet"] + +## Baştan n tane eleman almak için take metodunu kullanıyoruz +["Fatih", "Sultan", "Mehmet"].take 2 +#=> ["Fatih", "Sultan"] + +## Rastgele bir dizi elemanı elde etmek için sample metodunu +## kullanıyoruz +["Fatih", "Sultan", "Mehmet"].sample +#=> "Fatih" + +## `sample` metodu seçimli bir argüman kabul eder. +## bu argüman rastgele istenen eleman sayısını temsil eder +["Fatih", "Sultan", "Mehmet"].sample 2 +#=> ["Fatih", "Sultan"] + +## Aradığınız eleman, dizide var mı kontrolü için +## include? metodu kullanılıyor +["Fatih", "Sultan", "Mehmet"].include? "Fatih" +#=> true + +## Dizinizdeki elemanları koşul dahilinde seçimlemek için +## select metodunu kullanıyoruz +["Fatih", "Sultan", "Mehmet"].select {|s| s.include? ?a} +#=> ["Fatih", "Sultan"] +## Süzme işleminin koşulu, a karakteri içeren nesneler için olumlu. +## Not: filter metodu, select için bir takma addır. + +## Ters bir yöntem, süzgeçleme için ise; +["Fatih", "Sultan", "Mehmet"].reject {|s| s.include? ?a} +#=> ["Mehmet"] +## koşulumuz aynıydı, seçimleme metodumuzu değiştirdik. + +### Yapısal düzenlemeler için: +## Dizileri ters çevirmek, +["Fatih", "Sultan", "Mehmet"].reverse +#=> ["Mehmet", "Sultan", "Fatih"] + +## Sıralamak için sort metodu, +["İş", "Aşk", "Para"].sort +#=> ["Aşk", "Para", "İş"] + +## Ön koşulla sıralamak için, +["İş", "Aşk", "Para"].sort {|a,b| b <=> a } +#=> ["İş", "Para", "Aşk"] +## Koşulumuz basitçe tersine sıralamak için bir tanımdır. +## ileride karşılaştırma operatörlerini göreceğiz. + +## Tekrarlı elemanların temizlenmesi için +[1,2,3,4,5,6,7,1,2,4,1,5,6,1,2,5].uniq +#=> [1, 2, 3, 4, 5, 6, 7] + +## Dizilerin birleştirilmesi için +[1,2] + [3,4] +#=> [1, 2, 3, 4] +## infix notasyon sizi yanıltmasın, +## tasarımı gereği, her şey sınıflar ve metotlarına çağırım +## olarak yürüyor. +## Kanıtlayalım; +[1,2].+([3,4]) +#=> [1, 2, 3, 4] + +## Peki ya aynı elemanları içerebilecek dizileri birleştirmek +## istersek ? +[1,2] | [2,3,4] +#=> [1, 2, 3, 4] +## | operatörü bizi, nihai sonuçtaki tekrarlı veriden koruyor. + +## Peki ya bir diziyi, eleman bazında diğeriyle +## süzmek istersek ? +[1,2] - [2,3,4] +#=> [1] +## Notasyon sizi yanıltmasın, Küme gibi davranan bir dizi işlevi. + +### Veri Dönüşümleri için: +## Dizideki her elemana uygulamak istediğiniz bir +## dönüşümü, map metodu ile uygulayabilirsiniz, +["Kontak İsmi", + "Kontak Telefon Numarası"].map {|element| "<label>#{element}</label>"} +#=> ["<label>Kontak İsmi</label>", "<label>Kontak Telefon Numarası</label>"] +## HTML konusu için yine LearnXinYminutes'e danışabilirsiniz. + +## Son elde ettiğimiz veriyi birleştirmek için, +["<label>Kontak İsmi</label>", + "<label>Kontak Telefon Numarası</label>"].join "" +#=> "<label>Kontak İsmi</label><label>Kontak Telefon Numarası</label>" + +## Veriyi indirgemek için ise reduce metodu kullanırız, +["<label>Kontak İsmi</label>", + "<label>Kontak Telefon Numarası</label>"] + .reduce("") {|akümülatör, veri| akümülatör + veri} +#=> "<label>Kontak İsmi</label><label>Kontak Telefon Numarası</label>" +## Akümülatör, her operasyondan dönen ara-geçici değer. +## Bu değeri, parantez içinde ilkledik, +## eğer vermeseydik, dizinin ilk elemanı olacaktı. + +## Tabi, daha kolay bir yolu var; +["<label>Kontak İsmi</label>", + "<label>Kontak Telefon Numarası</label>"].reduce(:+) +#=> "<label>Kontak İsmi</label><label>Kontak Telefon Numarası</label>" +## reduce metodu, ikili bir operasyonu (akümülatör için metot!) +## sembol olarak vermenize izin verir ve bu, reduce için +## indirgeme fonksiyonu olarak kullanılır. + +## Nüansları olsa da, son üç Ruby çağırımı aynı sonucu vermektedir. + + +## -- +## Semboller +## -- + +## Ruby sembolleri, çalışma zamanında değiştirilemezler. +## Ama metinsel değerlerden semboller elde etmek mümkündür. +## Bunu dönüşümler kısmında işlemek daha doğru olacak diye düşündüm. + +# -------------------------------- +# Dönüşümler +# -------------------------------- + +## -- +# Rakamlar +## -- + +## Sayısal değerlerin diğer tiplere dönüşümü; + +## Sayısal -> Metinsel +1923.to_s #=> "1923" + +## Sayısal -> Mantıksal +!1923 #=> false +## Farkedebileceğiniz gibi, +## sayısal değerler, mantıksal doğru'ya değerlendiriliyor. + +## Sayısal -> Sembol +## Maalesef, Ruby bile Sayısal değerden Sembol değerlerine +## doğrudan dönüşüm için metot barındırmıyor. +## Bunu yine de başarmak istersek, değeri önce +## Metinsel'e dönüştürerek Sembol dönüşümü için hazırlarız. +1923.to_s.to_sym +#=> :"1923" + +## Sayısal -> Dizi | bölümlenerek +## Yine doğrudan bir dönüşüm yoktur. +## Böyle bir doğrudan dönüşüm teşvik de edilmez. +## Ama ihtiyaç olabilecek bir dönüşüm. +1923.to_s.split('') +#=> ["1", "9", "2", "3"] +## Öncelikle Metinsel dönüşüm yapılır, sonra +## her bir karakter için ayrılır. +## Yine her bir rakamı sayısal bir şekilde elde etmek için +## her birini Metinsel'den Sayısal değere dönüştürecek +## ifade aşağıdaki gibidir. +1923.to_s.split('').map { |i| i.to_i } +#=> [1, 9, 2, 3] + + +## -- +# Mantıksal +## -- + +## Mantıksal -> Metinsel +true.to_s #=> "true" +false.to_s #=> "false" + +## Mantıksal değeler için gerçeklenmiş başka bir dönüşüm +## metodu olmadığı için, bu kısmı dilde ufak bir nüansa ayırmak +## istedim. +## Kaynak için ileri okumaya başvurunuz. + +## Hangi programlama dilinden gelirseniz gelin, +## dilde doğruluk değerleri diye bir küme vardır. +## Hangi değerlerin mantıksal doğru değerine dönüşeceği, +## bu değer yerine geçebileceği +## fikri üzerine kurulu bir küme. +## Ve Ruby'de nil değeri, false dışında, mantıksal yanlış değerine çözümlenen tek şey. +## Bu ön bilgi ile doyduysak, başlayalım. + +!!nil #=> false +!!false #=> false +!!0 #=> true +!!"" #=> true +## Şimdi ne oldu burada ? +## `!!` ifadesi; değilinin değili, yani kendisi. Tek bir farkla. +## Verinin türü değiştiriliyor. Mantıksal olarak yorumlanıyor. +## Yukarıda, nil ve false ifadeleri mantıksal olarak yanlış olarak yorumlanıyor. +## Diğerleri ise mantıksal doğru. + + +## -- +# Metinsel +## -- + +## Metinsel -> Sayısal +## Öncelikle dilde ufak bir tuzağa dikkat çekmek isterim. +"".to_i #=> 0 +"asd".to_i #=> 0 +## Sayısal yorumlaması geçersiz ve boş her metinsel değer, +## 0 rakamına değerlendirilir. + +## Başarılı bir dönüşüm, +"1234".to_i #=> 1234 + +## Sayı sistemini belirleyebileceğiniz seçimli bir argüman +## kabul ediyor, to_i metodu. +"1234".to_i 5 #=> 194 +## 1234 sayısının, beşlik tabandaki karşılığı. + +## Tam sayı dışında doğrudan dönüşümler +## dil olanağı olarak sunulmuş durumda; + +## Kompleks sayı olarak, +"1234".to_c #=> (1234+0i) + +## Ondalık (Kayan-noktalı) sayı olarak, +"1234".to_f #=> 1234.0 + +## Rasyonel sayı olarak, +"1234".to_r #=> (1234/1) + +## Metinsel -> Mantıksal + +## Mantıksal değerin kendisi için tersinin, tersini alırız +!!"seçkin" #=> true + +## Mantıksal tersi için ise tersini, +!"seçkin" #=> false + +## Metinsel -> Sembol +"cengiz".to_sym #=> :cengiz + +## Metinsel -> Dizi +"Cengiz Han".split #=> ["Cengiz", "Han"] + +## split metodu, seçimli argümanının varsayılan değeri +## boşluk karakteridir. + +## Metinsel -> Dizi | bölümlenerek +"Cengiz Han".split "" +#=> ["C", "e", "n", "g", "i", "z", " ", "H", "a", "n"] + + +## -- +# Sembol +## -- + +## Sembol -> Metinsel +:metin.to_s #=> "metin" +## Başka bir dönüşüm için dilin bir teşviki yoktur. + +## -- +# Diziler +## -- + +## Dizi -> Metinsel +[1,2,3,4,5].to_s #=> "[1, 2, 3, 4, 5]" + + +## -- +# Eşlemeler +## -- + +## Eşleme -> Dizi +{a: 1, b: 2, c: 3}.to_a +#=> [[:a, 1], [:b, 2], [:c, 3]] +## Her bir anahtar-değer çifti bir dizi olarak +## değerlendirilir ve elemanları sırasıyla +## anahtar ve değerdir. + +## Eşleme -> Metinsel +{a: 1, b: 2, c: 3}.to_s +#=> "{:a=>1, :b=>2, :c=>3}" +## inspect metodu için bir takma addır. + + +# -------------------------------- +# Tanımlamalar, ifadeler, yorumlama. +# -------------------------------- + +## -- +## Yorumlama +## -- + +## Dökümanın başından beri gördüğümüz bu tek satır yorumlama operatörü +## (#) +## kendinden sonra gelen her şeyin, satır boyunca yorumlama olarak +## değerlendirilmesi gerektiğini Ruby yorumlayıcısına söyler. + +## Ruby, farklı yorumlama imkanları da sağlamaktadır. +## Örneğin; +=begin + Başlangıç ifadesi (=begin), sonlandırma ifadesi (=end) + ile arasında kalan her şeyi yorum satırı olarak ele alır. +=end + +## -- +## Global değişkenler. +## -- + +## Ruby evrensel değişkenleri, kapsamı en geniş değişken türüdür. +## Her yerden erişilebilir... + +## Basitçe dolar sembolü ( $ ) ile başlarlar. +$evrensel_bir_değişken = 42 #=> 42 + +## Bir çok metadoloji ve yöntem ve teknoloji, size +## evrensel değişkenler kullanmanın projenizi karmaşıklaştıracağı +## ve bakımını zorlaştıracağını söyler; Haklıdırlar... + +## -- +## Varlık değişkenleri. +## -- + +## At ( @ ) sembölü ile başlarlar ve isimlerinin de ifade ettiği +## gibi, kendileri bir Sınıf'ın değeridir. + +class Varlık + def initialize() + @varlık_değişkeni = 101 + end + + def göster() + puts "Varlık değişkeni: #@varlık_değişkeni" + end +end + +varlık1 = Varlık.new() + +varlık1.göster() +#=> Varlık değişkeni: 101 + +## Sınıf tanımı şimdilik kafanızı karıştırmasın. +## İlgilenmemiz gereken kısım; +## @varlık_değişkeni = 101 +## ifadesidir. Ve nesne özelinde tanımlama yapar. +## Kapsamı sadece o nesnedir. + +## ! NOT: ilklenmemiş varlık değişkenleri nil ön değeri ile +## yaşam döngüsüne başlar. + +## -- +## Sınıf değişkenleri. +## -- + +## Sınıf değişkenleri iki at ( @@ ) sembölü ile başlarlar. +## Tanımlar, herhangi bir metot içinde +## kullanılmadan önce ilklenmelidirler. +## İlklenmemiş bir Sınıf Değişkenine referansta bulunmak, +## bir hata oluşturur. + +class Sınıf + @@sınıf_nesne_sayısı = 0 + + def initialize() + @@sınıf_nesne_sayısı += 1 + end + + def göster() + puts "Sınıf sayısı: #@@sınıf_nesne_sayısı" + end +end + +sınıf_varlığı1 = Sınıf.new() +sınıf_varlığı2 = Sınıf.new() +sınıf_varlığı3 = Sınıf.new() + +sınıf_varlığı1.göster() +#=> Sınıf sayısı: 3 + + +## -- +## Yerel değişkenler. +## -- + +## Yerel değişkenlerin isimlendirmesi küçük harf +## ya da alt çizgi ( _ ) ile başlar ve kapsamı tanımın +## yapıldığı sınıf, modül, metot yada blok içinde kalır. + +## -- +## Sabitler. +## -- + +## Ruby sabitleri, büyük harf ile tanımlanırlar ve +## kapsamları için iki senaryo mevcuttur; + +## - Sınıf ya da Modül içinde tanımlanırlarsa +## Tanımın yapıldığı blok içinden erişilebilir. + +## - Sınıf ya da Modül dışında yapılan tanımlar ise +## Evrensel bir kapsama sahiptir ve her yerden +## erişilebilirler. + +## Örneğin: + +class Sabit + SABİT = 299_792_458 + + def göster + puts "Sabit değer: #{SABİT}" + end +end + +# Create Objects +sabit = Sabit.new() + +sabit.göster() +#=> Sabit değer: 299792458 + +## İfadenin tanımındaki alt çizgiler sizi yanıltmasın +## binlik ayracı olarak kullandım ve Ruby yorumlayıcısı +## tamamen görmezden geliyor. +## Bknz: Veriler ve Temsiller: Sayılar. + +## -- +## Sözde Değişkenler. +## -- + +## Ruby özel bir dil. +## Öyle ki, Bazı sözde-değişkenler ile +## size, ihtiyacınız olabileceği erişimi sağlar. +## Ama onlara atama yapamazsınız. + +## Sözde değişkenler ve kullanımları +## ile ilgili İleri okumaya başvurunuz. + + +# -------------------------------- +# Konvansiyonlar ve teşvikler. +# -------------------------------- + +## Konvansiyonlar: + +## -- +## İsimlendirme Konvansiyonları: +## Döküman boyunca yaptığım gibi, +## tanımlayıcılar ve erişilebilir tanımlanmış ifadeler +## için lütfen önerildiği gibi İngilizce kullanın. +## İsimlendirme, Bilgisayar bilimlerinde yeterince +## ağır bir zemin ve dilin teşvik ettiği rehber +## ve önerdiği konvansiyonları takip ederek +## bakımı, okuması ve geliştirmesi kolay projeler +## gerçeklemek mümkündür. + +## -- +## Semboller, Metotlar ve Değişkenler için +##-Snake Case ( snake_case ) kullanılması önerilir. + +## -- +## Sınıflar için Camel Case (CamelCase): +## Sınıf isimlendirmeleri için önerildiği gibi, +## Camel Case isimlendirme notasyonuna sadık kalın. + +## -- +## Dosyalar ve Klasörler için Snake Case (snake_case): +## Dosya ve klasörleri isimlendirmek için lütfen +## Snake Case isimlendirme konvansiyonuna sadık kalın. + +## -- +## Dosya Başına Bir Sınıf: +## Her dosyada bir sınıf barındırmaya özen gösterin. + +## --- +## Bu kısımdaki teşvik içerikleri +## rubocop-hq/ruby-style-guide'dan gelmektedir. + +## ! Rehbere göre bu dökümanı düzenle! + +## -- +## Girintileme: +## Girintileme için TAB yerine, iki boşluk kullanın. + +def bir_metot + birşeyler_yap +end +## Yerine; +def bir_metot + birşeyler_yap +end + +## -- +## Satır Başına Karakter: +## Satır başına maksimum 80 karakter olacak şekilde +## dökümanı yapılandırın. + +## -- +## Satır Sonları: +## Unix-Stili satır sonlarını kulanın. +## Eğer Git kullanıyorsanız; +## $ git config --global core.autocrlf true +## ifadesi sizi bu zahmetten kurtaracaktır. + +## -- +## Satır Başına Bir İfade: +## Satır başına bir ifade kullanın. + +puts 'test!'; puts 'test!' +## Yerine; +puts 'test!' +puts 'test!' + +## -- +## Boşluklar ve Operatörler: +## Operatörler, virgüller, ifade ayraçları +## aralarında boşluk bırakın. + +toplam=1+2 +x,z=1,2 +class FooError<StandardError;end +## Yerine; +toplam = 1 + 2 +x , z = 1 , 2 +class FooError < StandardError; end +## Bir kaç istisna hariç +## - Üs operatörü +## - Rasyonel sayı gösteriminde kullanılan eğik çizgi. +## - Güvenli gösterim operatörü. + + +### Daha fazlası için ileri okumadaki +### bu rehbere danışabilirsiniz... + +# -------------------------------- +# Bloklar, Kontrol blokları ve örnekler. +# -------------------------------- + +## -- +## Ruby Blokları: +## Süslü parantezler ya da `do`, `end` ile çevrelenen, +## değişkenleri ortama bağlı işlevlerdir. +## Diğer dillerde !{Closure} ( closure ) karşılığı +## bulur. +## Ruby'de bloklar, ifadeleri gruplamanın bir şeklidir. +## Bloklar tanımlandıklarında çalıştırılmazlar, +## Ruby, bu yönetimi akıllıca yapar. + +## Örneğin; + +## Tanımlamamız +def selamla_sonra_çağır + puts 'Selamlar!' + yield ## tüm sihir burada! +end + +## Şimdi tanımı çağıralım +selamla_sonra_çağır {puts 'Çağrı, gerçekleşti!'} +#= Selamlar! +#= Çağrı, gerçekleşti! +#=> nil +## Çağırım, kendini çağıran kaynağa nil döndürmekte. +## Değerlendirmenin sonucunda, Ruby yorumlayıcısı, +## ifadenin değerini nil olarak çıktılar. +## Fakat, puts çağrıları, girdi/çıktı işlevimizi +## yerine getirir ve metinleri ekrana basar. + +## Blokların argüman almaları da mümkündür: +def selamla_sonra_değer_ile_çağır + puts 'Selamlar!' + yield('Hain Kostok') ## tüm sihir burada! +end + +selamla_sonra_değer_ile_çağır {|isim| puts "Sana da selam, #{isim}!"} +#= Selamlar! +#= Sana da selam, Hain Kostok! +#=> nil + +## Detaylı bilgi için, ileri okumaya başvurunuz. + +## -- +## Eğer ( if ) kontrol ifadesi: +## Algoritmanızda dallanma imkanı sağlar. +## Şablonu: +## if koşul_ifadesi [then] +## yürütülecek_kod +## [elsif bir_diğer_koşul [then] +## yürütülecek_diğer_kod] +## [else +## yürütülecek_bir_diğer_kod] +## end + +## Bu kalıba sadık kalarak, dallanmalarımızı kodlarız. +## Köşeli parantezler, sezgisel olarak anlaşılacağı üzere +## seçimli ifadelerdir. + +## Örnek: +if true + puts 'Koşul ifadesi, buradan devam edecek!' +else + puts 'Buradan değil.' +end +#= Koşul ifadesi, buradan devam edecek! +#=> nil + +## -- +## Eğer ( if ) düzenleyicisi: +## Kompak bir dil olanağıdır. Aynı şekilde, çalıştırılacak kod +## ve bir koşul ifadesi alır. Ve koşul ifadesine bakarak +## ifadenin yürütüleceğine karar verir. +## Şablonu: +## çalıştırılacak_kod if koşul_ifadesi + +## Örnek: + +puts 'Bu ifade yürütülecek!' if true +#= Bu ifade yürütülecek! +#=> nil + + +## -- +## Durum ( case ) kontrol ifadesi: +## Bir koşul ifadesi ve bir ya da daha fazla karşılaştırma ifadesi +## alarak, eşleşen bloğu yürütür. +## Şablonu: +## case koşullanacak_ifade +## [when karşılaştırma_ifadesi [, karşılaştırma_ifadeleri ...] [then] +## yürütülecek_kod ]... +## [else +## eşleşme_olmazsa_yürütülecek_kod ] +## end + +yaş = 27 +case yaş +when 0 .. 2 + puts "bebek" +when 3 .. 6 + puts "küçük çocuk" +when 7 .. 12 + puts "çocuk" +when 13 .. 18 + puts "genç" +else + puts "yetişkin" +end +#= yetişkin +#=> nil + +## -- +## .. Sürece ( while ) kontrol ifadesi: +## Aldığı koşul ifadesini kontrol eder, +## kontrol bloğunu çağırır ve tekrar kontrol eder. +## Koşul ifadesi doğru olduğu sürece, kontrol bloğu +## çağırılmaya devam eder. +## Şablonu: +## while koşul_ifadesi [do] +## yürütülecek_kod +## end + +## Örnek: + +$n = 0 +$sayı = 5 + +while $n < $sayı do + puts("Döngü içinde n = #$n" ) + $n +=1 +end +#= Döngü içinde n = 0 +#= Döngü içinde n = 1 +#= Döngü içinde n = 2 +#= Döngü içinde n = 3 +#= Döngü içinde n = 4 +#=> nil + +## -- +## .. Sürece ( while ) düzenleyicisi: +## Eğer düzenleyecisi gibi, kompak bir dil olanağıdur. +## Kontrol ifadesinin işlevini yerine getirir, +## ama satır içi kullanıma müsade ederek. +## Şablonu: +## çalıştırılacak_kod while koşul_ifadesi +## Yada: +## begin +## çalıştırılacak_kod +## end while koşul_ifadesi + +## -- +## İçin ( for ) kontrol ifadesi: +## N kere, I kere, X kere gibi ifadelerin dildeki kontrol +## karşılığıdır. Çoklu veri üzerinde iterasyonlar yapmanızı +## veri üzerinde operasyonlar yürütmenizi sağlar. +## Şablonu: +## for değişken [, başka_değişken ...] in ifade [do] +## yürütülecek_kod +## end + +## Örnek: +for i in 1..5 + puts i +end +#= 0 +#= 1 +#= 2 +#= 3 +#= 4 +#= 5 +#=> 0..5 + +## Ardışıkları itere etmek için tek yol bu değil tabii. +## İlerleyen kısımda buna yer verilecektir. + +## -- +## Sonlandırıcı ( break ) kontrol ifadesi: +## Bu kontrol ifadesi yürütüldüğünde, çalışma zamanını +## en iç tekrarlı bloktan çıkarır. + +## Örnek: +for i in 1..5 + break if i > 2 + puts i +end +#= 0 +#= 1 +#= 2 +#=> nil +## break kontrol ifadesi, if düzenleyecisi ile çevrelenmiştir. +## if i > 2 +## break +## end +## ifadesi ile eşdeğerdir. +## ifade yürütüldüğü anda, en yakın tekrarlı blok terkedilir. +## Yorumlayıcı, sonraki ifadeden yürütmeye devam eder. + +## Diğer kontrol ifadeleri ve kullanımları için ileri okumaya başvurunuz... + + +# -------------------------------- +# Özel anahtar kelimeler; kullanımları ve örnekleri. +# -------------------------------- + +## -- +## __ENCODING__: +## Bu anahtar kelime size yorumlayıcı kodlama türünü verecektir. + +__ENCODING__ +#=> "#<Encoding:UTF-8>" + +## Platform, araç ve çalışma zamanı yürütme +## yönteminize bağlı olarak alacağınız çıktı +## değişiklik gösterebilir. + +## -- +## __LINE__: +## Geçerli dosyada, yürütme satır numarasını verir. + +__LINE__ +#=> 67 + +## Platform, araç ve çalışma zamanı yürütme +## yönteminize bağlı olarak alacağınız çıktı +## değişiklik gösterebilir. + +## -- +## BEGIN ve END: +## BEGIN: +## Dosyadaki tüm içerikten önce yürütülür. +## END: +## Dosyadaki tüm içeriklerden sonra yürütülür. + +## -- +## alias: +## Herhangi bir tanımlayıcı için takma ad tanımlamanıza +## olanak sağlar. + +$eski = 0 +alias $yeni $eski + +$yeni +#=> 0 + +## -- +## and: +## Düşük öncelikli bir Mantıksal VE operatörü. + +## -- +## begin / end ve rescue: +## İstisnalar begin / end blokları +## arasında ele alınır ve `rescue` anahtar kelimesi ile +## işlenirler. +## İstisnalar ve mantalitesine dair ön girişi +## Teşvik edilen paradigma ve anlatımı kısmında bulabilirsiniz. + +## Hata yönetimi, Ruby'de de özenle işlenmiş bir konudur. + +## Örnek: + +begin + yanlış_bir_hesaplama = 2/0 + puts "Hesaplama sonucu: #{yanlış_bir_hesaplama}" + rescue ZeroDivisionError => hata_nesnesi + puts "Sıfıra bölümle ilgili bir hata yakalandı: #{hata_nesnesi.message}" +end +#= Sıfıra bölümle ilgili bir hata yakalandı: divided by 0 +#=> nil + +## Örneğimizde matematiksel sistemimiz için hatalı bir +## işlem gerçekleştiriyoruz. Sonrasında hatayı ilgili +## hata durumu için belirlediğimi alanda yönetiyoruz. +## Örnekte hatayı çıktılayarak yönettik, gerçek dünyada +## biraz daha kompleks gerçekleşebilir. +## Gerçek dünya örnekleri için ileri okumaya başvurabilirsiniz. + + +## -- +## defined?: +## defined?, argümanını metinsel olarak açıklayan bir dil olanağıdır. + +## Örnek: +RUBY_VERSION +#=> "2.4.0" + +defined? RUBY_VERSION +#=> "constant" + +defined? nil +#=> "nil" + +defined? puts +#=> "method" + + +## -- +## ensure: +## Hata yönetiminin bir parçası olarak dilde görev atfedilen ensure, +## blok içinde, hata olsun ya da olmasın yürütüleceği garanti edilen +## dil ifadeleri için bir imkandır. + +## Örnek: + +begin + yanlış_bir_hesaplama = 2/0 + puts "Hesaplama sonucu: #{yanlış_bir_hesaplama}" + rescue ZeroDivisionError => hata_nesnesi + puts "Sıfıra bölümle ilgili bir hata yakalandı: #{hata_nesnesi.message}" + ensure + puts "Hesaplama bloğu sonlandı!" +end +#= Sıfıra bölümle ilgili bir hata yakalandı: divided by 0 +#= Hesaplama bloğu sonlandı! +#=> nil + + +## -- +## self: +## Nesnenin kendisine erişim sağlayan bir dil olanağı. + +## Örnek: + +dünya = "Dünya!" +#=> "Dünya!" + +dünya +#=> "Dünya!" + +dünya.class +#=> String + +def dünya.selamla + "Merhaba, " + self +end +#=> :selamla + +dünya.selamla +#=> "Merhaba, Dünya!" + +## Nesnenin kendisine bir metot tanımladık, +## bunu yaparken de değerine erişim sağladık. + +## -- +## super: +## Nesne yönelimli programlama (spesifik olarak, obje tabanlı) +## paradigmasına göre, kalıtım konseptinde, türeyen sınıfın +## türetildiği sınıfa erişimi (üst sınıfı, atası, hiyerarşik üstü) +## bu anahtar kelime ile gerçekleşir. + +class A + def initialize(a) + @a = a + end +end + +class B < A + def initialize(a, b) + @b = b + super a + end +end + +b = B.new 1, 2 +#=> #<B:0x00007f852d04c7e8 @b=2, @a=1> +## super ile üst sınıfın ilklenmesi gerçekleştirildi, +## aldığımız çıktıda da @a=1 çıktısıyla gözlemlenebilir. + +## Bu konunun, dilin paradigma teşviği ile ilgili +## olduğunu ve anlamazsanız, Paradigma başlığını bitirdikten +## sonra tekrar bu örneği değerlendirmeniz gerektiğini hatırlatırım. + +## -- +## yield: +## Ruby blokları kısmında anlattık, ama, burada da bir nüanstan +## bahsetmeden geçemeyeceğim. +## Çalıştırılabilir ifadeleri çalıştırmanın birden fazla yolu vardır. +## Fakat yield, en performanslı dil olanağı olarak dökümanda işlenmiş. +## Kaynak için ileri okumaya danışın. + + + +# -------------------------------- +# G/Ç ( I/O ) +# -------------------------------- + +=begin + G/Ç, Girdi/Çıktı ( Input/Output ) kısaltmasıdır. + Temelde, sistemden girdi almak ve çıktı yaratmak amacıyla vardır. + Girdi örnekleri: + - Klavyeden bastığınız herhangi bir tuş. + - Fare hareketleriniz ya da tıklamalarınız. + - Mikrofonunuzun aldığı sesler. + + Çıktı örnekleri: + - Herhangi bir dil ifadesinin sonucu. + - Dijital bir ses dosyasının sese dönüşmesi. + - Ekranda gördükleriniz. + + Fakat endişelenmeyin, G/Ç derken, şu anda + biz sadece Ruby'de, + - Dosya okuma/yazma. + - Ekrana metin yazdırma / Bilgi okuma. + - Ağ soketleri. ( biraz da olsa ) + işlerinden bahsediyor olacağız. +=end + +defined? IO +#=> "constant" + +IO.class +#=> Class + +## IO sınıfı, File ve Socket gibi pratik kullanımı olan sınıfların atasıdır. +## Septikler için; + +File.superclass +#=> IO +## Gözlemlediğiniz üzere, superclass metodu, üst sınıfı veriyor. + +## -- +## Dosya Okuma ve Yazma: +## Ruby'de dosya okuma ve yazma işlemleri için, File +## sınıfını kullanacağız. + +## Dosyaya yazmak için; +File.write 'test.txt', "a,b,c" +#=> 5 +## 5, ifadenin ürettiği dönüş değeridir. +## ve, çıktılanan karakter sayısını verir. + +## Dosyadan okuma için; +## Bu kısım, açıklayıcı olması açısından +## ifadeleri teker teker işleyeceğiz. + +File +#=> File +## Sınıfımız. + +File.readlines 'test.txt' +#=> ["a,b,c"] +## readlines File sınıfının bir metodu ve aldığı argüman dosya yoludur. + +File.readlines('test.txt').first +#=> "a,b,c" +## Dönüş değeri bir diziydi, her bir satır bir eleman olacak şekilde. +## Biz, kendi verilerimizi, kendi ayıracımızla kaydetmeyi seçtik. +## Eğer, `\n` satır ifadesi ile ayırmayı seçseydik, readlines +## metodu zaten işlevi gereği, bize değerleri ayrı ayrı verecekti. + +File.readlines('test.txt').first.split ',' +#=> ["a", "b", "c"] +## verilerimizi aldık. + +## Eğer yeni satır karakterini ayıraç olarak kullansaydık; +File.write 'ntest.txt', ['a', 'b', 'c'].join("\n") +#=> 5 + +File.readlines('ntest.txt').map(&:chomp) +#=> ["a", "b", "c"] +## Bu da genel kullanımlı bir yaklaşımdır. + +## -- +## Ekrana bilgi yazdırma ve Okuma: +## Konsol'a bilgi çıktılamak için, +## önceden tanımlanmış $stdout global nesnesini kullanacağız. +## Pratik kullanımda, prints işlevinden bir farkı yoktur. +## Aynı sonuca ikisi ile de ulaşabilirsiniz. + +$stdout.print "Bu bir çıktı.\n" +#= Bu bir çıktı. +#=> nil + +## Şimdi kullanıcıdan bilgi okuyalım: +$stdin.gets +#! Bu kısımda hiç bir çıktı verilmez ve aksine +#! sizden girdi beklenir. Bir metin yazın ve onaylamak için +#! enter tuşunu kullanın. +#- Bu bir girdi metni! +#=> "Bu bir girdi metni!\n" + +## Aldığımız veriyi temizlenin yolunu biliyoruz. +## Dönüş değerine chomp metodunu uygulamak. +$stdin.gets.chomp +#- Bu bir girdi metni! +#=> "Bu bir girdi metni!" + + +## -- +## Ağ girdi/çıktı yönetimi +## Ruby'de soketler (Socket) +## haricen çalışma zamanına dahil edilir. + +require 'socket' +#=> true + +soket = TCPSocket.new('google.com', 80) +#=> #<TCPSocket:fd 13, AF_INET, 192.168.0.11, 63989> +## Alacağınız çıktı değişiklik gösterebilir. +## Soketi oluşturduk ve bir değişkene atadık. +## Şimdi bunun üzerinden okuma ve yazma işlemlerini +## gerçekleştireceğiz. + +soket.write "GET / HTTP/1.1" +#=> 14 + +soket.write "\r\n\r\n" +#=> 4 +## İki write metodunun sonucu da, sokete yazılan verinin +## uzunluğudur. + +## Şimdi okuma zamanı, soketi açtık, isteğimizi bildirdik. +## Şimdi soket üzerinden aldığımız cevabı ekrana yazdıralım. + +soket.recv 80 +#=> "HTTP/1.1 200 OK\r\nDate: Thu, 03 Sep 2020 10:48:21 GMT\r\nExpires: -1\r\nCache-Control" +## Alacağınız çıktı değişiklik gösterebilir. +## Ancak, başarılı şekilde okuma yaptık. + + + +# -------------------------------- +# Teşviğinde bulunduğu paradigma ve derinlemesine anlatımı. +# -------------------------------- + +## -- +## Nesne Yönelimli Programlama Nedir? +## Kısaca NYP, en basit anlatımıyla; +## nesnelerle programlamadır. +## Nesne paradigması, her programcıya doğal ve sezgisel gelir. +## Bunun sebebi, zaten gerçekliği algılama şeklimize uygun olmasıdır. +## Araba, onu bir araya getiren nesnelerden oluşur, +## tekerlekleri, direksiyonu, kasası, ve diğer parçalarıyla. +## Ama bu, tam tanım değildir. NYP'de, Nesneler, +## Bilgilere ( evet, varlık olarak başka nesneler de sayılabilir ) +## ve bu bilgileri yönetecek ( hesaplamalar gerçekleştirecek +## ya da aksiyonlar alacak -- G/Ç -- gibi ) metotlara sahiptir. + +## Bir nesnenin en net tanımı böyle yapılabilirken, +## NYP, bir gerçek dünya problemi için bir araya getirilmiş +## -- çoğunlukla birden fazla -- sınıfların yapıları, +## ilişkileri ve işlevlerini ele alır. + +## Bir paradigma olarak NYP, bizlere her varlığı nesne olarak +## modellemeyi ve problem uzayımızdaki nesnelerle olan ilişkilerini +## Ruby'de NYP için sağlanan imkanlarla yönetmeyi öğütler. + +## Sınıf içerisinde saklanan bilgiye öznitelik ya da özellik, +## işlevlere ise metot denilir. +## NYP jargonu için ileri okumaya başvurabilirsiniz. + +## -- +## Ruby'de NYP teşviki: + +## Nesneler, Sınıfların gerçeklenmiş halleridir. +## Tam tersi ile, Sınıflar ise, nesnelerin soyut kalıplarıdır. + +## Bir sınıf tanımı yapalım ve gerçekleyelim: + +class Araba +end +#=> nil +## Evet, evet. Tanımımız hiç bir öznitelik ( attributes ) ya da +## metot ( method ) içermiyor. + +## Şimdi bir özellik ekleyelim +class Araba + def initialize(hız) + @hız = hız + end +end + +araba = Araba.new 100 +#=> #<Araba:0x00007f7f300e59c8 @hız=100> + +## En naif haliyle, hız bilgisi saklayan bir araba sınıfı gerçekledik. +## initialize metodu, Ruby imkanları ile, nesne yaşam döngünüzün ilk adımıdır. +## Bu döngüyü aşağıdaki gibi betimlemek mümkündür. +## İlkleme ( initialize ) -> [İşlevlerin çağırımı] -> Sonlandırma +## İlkleme, initialize metodu ile ele alınır, alınacak tüm argümanlar, +## sınıfın iş mantığı doğrultusuyla, bu ilk işlevde yönetilir ve nesne +## kullanıma hazır hale getirilir. + +## Şimdi bir işlev ekleyelim. + +class Araba + def initialize(hız) + @hız = hız + end + + def git! + puts 'Hınn, hınn!' + end +end + +araba = Araba.new 100 +#=> #<Araba:0x00007f7f300e59c8 @hız=100> + +## Şimdi metodu çağırıyoruz. +araba.git! +#= Hınn, hınn! +#=> nil + +## Başlığın amacı sadece Ruby'nin NYP olanaklarını ve +## teşviğini işlemek değil. Paradigmaya bir giriş kazandırmak. +## Bundan dolayı, etkileşim içinde birden fazla sınıf görmeliyiz. + +class Tekerlek + YERLİ = 5 + İTHAL = 1 + + def initialize (tür) + @güç = tür + end + + def döndür! + @güç -= 1 + end +end + +class Araba + def initialize (hız) + @hız = hız + @tekerlekler = (1..4).map {|| Tekerlek.new(Tekerlek::YERLİ)} + end + + def git! + if @tekerlekler.map(&:döndür!).filter {|ömür| ömür < 0}.first then + puts 'Paat!' + else + puts 'Hınnn, hınnn!' + end + end +end + +## nesnemizi oluşturuyoruz +araba = Araba.new 100 + +## altı sefer, araba nesnesinin git! metodunu çağırıyoruz. +(0..6).map {|| araba.git! } +#= Hınnn, hınnn! +#= Hınnn, hınnn! +#= Hınnn, hınnn! +#= Hınnn, hınnn! +#= Hınnn, hınnn! +#= Paat! +#= Paat! + +## İş mantığımıza göre, arabamızın dört tekeri ve ve Yerli olanlar +## 5 birim dayanıklılığa sahip. ;) +## Bu beş birim tükenince, araba gitmek yerine, +## patlak teker çıktısı alıyoruz. + + +## Şimdiye kadar gördüklerimizi bir analiz edelim; +## Araba, sınıfın ismi. Her sınıf, tanımlamasak da, temel bir +## kurucu metot içerecek şekilde dil işleyicisi tarafından +## ele alınıyor. +## Bizim bir tanımımız var ama. +## Hız bilgisi alıyoruz. +## bu bilgi, sınıf özniteliğidir. Sınıf, bu bilgiye kendi içinden erişebilir. +## Bir de, binek araçların dört tekerleği olduğu fikriyle, +## nesne içinde, kurucu metot içinde dört tane Tekerlek nesnesi gerçekliyor +## ve saklıyoruz. +## İş mantığımıza göre onlara erişmemiz gerekiyor. +## git! metodu içinde, erişiyor ve kullanıyoruz. +## metotların sonundaki ünlem işareti bir konvansiyondur, +## metotların saf olmayan çağırımlar gerçeklediği anlamına gelmektedir. +## Kendilerini ( ya da sahip olduğu diğer nesneleri ) değiştirdikleri, +## bir girdi/çıktı gerçekleştirdikleri yada buna benzer yan etki içeren +## bir ifade barındırdıkları anlamına gelir. + +## Sizi temin ederim ki, NYP, bu dökümanı ( hali hazırda ~1560 satır ) +## genel anlatımı için bile ikiye katlayabilir. +## Lütfen detaylı bilgi için ileri okumaya başvurunuz. +``` + +# İleri okumalar. + +Tümüyle İngilizce olan bu ileri okumalara inat, bu detaylı özgün Türkçe içeriği üretmek istedim. +Dilerim, benden sonra katkıda bulunanlar olur. + +- [Ruby Style Guide](https://rubystyle.guide), Ruby stil rehberi. +- [Ruby-Doc üzerinde Proc](https://ruby-doc.org/core-2.4.0/Proc.html), Ruby Blokları ve Proc kavramı için. +- [Ruby-Doc üzerinde String](https://ruby-doc.org/core-2.6/String.html) sınıfı, işlevleri, metotları. +- [Ruby-Doc üzerinde TrueClass](https://ruby-doc.org/core-2.5.1/TrueClass.html#method-i-to_s) Dildeki mantıksal ifadelerin gerçeklemesi olan TrueClass (ve FalseClass için de aynı bağlantı üzerinden içeriğe ulaşılabilir) dönüşüm içeriği kaynağı. +- [Ruby Gerçeklemeleri Listesi](https://github.com/codicoscepticos/ruby-implementations) Ruby'nin farklı platformlardaki gerçeklemeleri. Opal ve Topaz dikkat çekenleridir. +- [The Object-Oriented Thought Process](https://www.amazon.com/Object-Oriented-Thought-Process-Developers-Library/dp/0321861272) kitap, bir paradigma olarak NYP ve düşünce yapısından bahsediyor. Bir paradigma olarak, NYP, türetildiği temel paradigmadan ne almış, başka paradigmalara ne kadar imkan sağlıyor ve paralel paradigma uyumu konusunda tüm sorularınıza cevap bulabilirsiniz. Yazar, belli etmese de, pragmatik bir yaklaşımda. +- [Block Argument](https://docs.ruby-lang.org/en/2.4.0/syntax/methods_rdoc.html#label-Block+Argument) Ruby Blokları ve yield hakkındaki Ruby resmi döküman sayfası ve alt başlığı. +- [A Theory of Objects]() Class-Based Languages başlığında inceleniyorlar. diff --git a/tr-tr/sql-tr.html.markdown b/tr-tr/sql-tr.html.markdown index 54007d32..2e91e9f8 100644 --- a/tr-tr/sql-tr.html.markdown +++ b/tr-tr/sql-tr.html.markdown @@ -1,125 +1,125 @@ ----
-language: SQL
-contributors:
- - ["Metin Yalçınkaya", "https://github.com/mtnylnky"]
-lang: tr-tr
-filename: learnsql-tr.sql
----
-
-
-```sql
--- Yorumlar iki tire ile başlar
-
--- KISITLAR
-Not null -- Bir kolon asla boş olamaz
-default -- Boş olan yerlere varsayılan bir değer atar
-unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması
-primary key -- Bir tablodaki her veri için kimlik bilgisi niteliğindedir
-check -- Bir kolondaki değerlerin belli bir kısıtlamayı sağlamasını sağlar
-
--- Tablo oluşturulur
-CREATE TABLE tablo1 ();
-
--- Tabloyu içerisinde kolonlar ile oluşturma
-CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER);
-
--- TABLO varlığını kontrol eder
-.table
-
--- Veri tabanında olan bütün tabloları görüntüler.
-.schema
-
--- Satır ekle
-INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2");
-
--- Veritabanında tablo üzerindeki verileri görüntüle
--- Sadece 'ad' gibi sınırlı bir veri için
-SELECT ad FROM tablo1;
--- Bütün veriler için
-SELECT * FROM tablo1;
-
--- Veri güncelleme
-UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1";
-
--- Satır sil
-DELETE FROM tablo1 WHERE id = 1;
-DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2";
-
--- Tabloya sonradan kolon ekleme
-ALTER TABLE tablo1 ADD COLUMN email TEXT;
-
--- Tablodaki kolon adı değiştirme
-EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN';
-
--- Tablo adı değiştirme
-ALTER TABLE table1 RENAME TO Table1;
-
--- Tabloyu silme
-DROP TABLE Table1;
-
--- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK
-INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1;
-
--- LIKE KOMUTU
--- Belirli bir kritere göre arama yaparken kullanılır
--- Adı 'A' ile başlayan veriler
-SELECT * FROM tablo1 WHERE adi LIKE "A%";
--- İçinde 'A' olan veriler
-SELECT * FROM tablo1 WHERE adi LIKE "%A%";
-
--- LIMIT KOMUTU
--- Gösterilen satır sayısını sınırlamak için
-SELECT * FROM Tablo1 LIMIT 6;
--- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için
-SELECT * FROM Tablo1 LIMIT 6 OFFSET 3;
-
--- ORDER BY KOMUTU
--- Herhangi bir kolona göre gösterilen değerleri azalan veya artan şekilde sıralamak için
-SELECT kolon FROM tablo1 WHERE yas ORDER BY column1, column2, .. columnN] [ASC | DESC];
-SELECT * FROM Tablo1 ORDER BY yas ASC
-SELECT * FROM Tablo1 ORDER BY yas DESC
-
--- DISTINCT ANAHTAR SÖZCÜĞÜ
--- Bu anahtar sözcükle sadece farklı değerler gösterilir.
-SELECT DISTINCT yas FROM tablo1;
-
--- JOIN KOMUTU
--- CROSS JOIN
--- Cross join bir tablodaki her satırı ikinci tablodaki bir satır ile eşleştirmek için kulanılır.
--- Eğer birinci tabloda x satır ikinci tabloda y satır varsa sonuçta x*y satır olur.
-SELECT ... FROM table1 CROSS JOIN table2 …
-SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2;
-
--- INNER JOIN
--- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir.
-SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression …
-SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad;
-
--- OUTER JOIN
--- Outer join iki tablodaki ortak kolon değerlerinin dışında kalanları kullanarak bir sonuç üretir.
-SELECT isci_num, isim, dept FROM Tablo1 LEFT OUTER JOIN Tablo2 ON Tablo1.id = Tablo2.isci_num;
-
--- ÇEKİRDEK FONKSİYONLAR
-COUNT -- Sayma
-AVG -- Ortalama
-ABS -- Mutlak değer
-SUM -- Toplam
-RANDOM -- Rastgele
-ROUND -- Yuvarlama
-MAX -- Maksimim
-MIN -- Minimum
-UPPER -- Büyük Harf
-LOWER -- Küçük Harf
-LENGTH -- Uzunluk
-CURRENT_TIMESTAMP -- Zaman
-
-SELECT max(yas) FROM Table1;
-SELECT min(yas) FROM Table1;
-SELECT avg(yas) FROM Table1;
-SELECT * From Table1 WHERE yas ==18;
-SELECT sum(yas) FROM Table1;
-SELECT random() AS Random;
-SELECT upper(ad) FROM Table1;
-SELECT lower(ad) FROM Table1;
-SELECT ad, length(ad) FROM Table1;
+--- +language: SQL +contributors: + - ["Metin Yalçınkaya", "https://github.com/mtnylnky"] +lang: tr-tr +filename: learnsql-tr.sql +--- + + +```sql +-- Yorumlar iki tire ile başlar + +-- KISITLAR +Not null -- Bir kolon asla boş olamaz +default -- Boş olan yerlere varsayılan bir değer atar +unique -- Bir kolondaki tüm değerlerin farklı olması kısıtlaması +primary key -- Bir tablodaki her veri için kimlik bilgisi niteliğindedir +check -- Bir kolondaki değerlerin belli bir kısıtlamayı sağlamasını sağlar + +-- Tablo oluşturulur +CREATE TABLE tablo1 (); + +-- Tabloyu içerisinde kolonlar ile oluşturma +CREATE TABLE tablo1(id INTEGER PRIMARY KEY NOT NULL UNIQUE, ad TEXT, soyad TEXT, yas INTEGER); + +-- TABLO varlığını kontrol eder +.table + +-- Veri tabanında olan bütün tabloları görüntüler. +.schema + +-- Satır ekle +INSERT INTO tablo1 ( ad, soyad) VALUES ("Deger1","Deger2"); + +-- Veritabanında tablo üzerindeki verileri görüntüle +-- Sadece 'ad' gibi sınırlı bir veri için +SELECT ad FROM tablo1; +-- Bütün veriler için +SELECT * FROM tablo1; + +-- Veri güncelleme +UPDATE tablo1 SET ad = "deger1-2"; WHERE name = "Deger1"; + +-- Satır sil +DELETE FROM tablo1 WHERE id = 1; +DELETE FROM tablo1 WHERE ad = "Deger1" OR ad = "Deger2"; + +-- Tabloya sonradan kolon ekleme +ALTER TABLE tablo1 ADD COLUMN email TEXT; + +-- Tablodaki kolon adı değiştirme +EXEC sp_rename ' tablo1.[ad]', Ad, 'COLUMN'; + +-- Tablo adı değiştirme +ALTER TABLE table1 RENAME TO Table1; + +-- Tabloyu silme +DROP TABLE Table1; + +-- BİR TABLOYU BAŞKA TABLO KULLANARAK DOLDURMAK +INSERT INTO Tablo2 SELECT id,ad, soyad, email from Tablo1; + +-- LIKE KOMUTU +-- Belirli bir kritere göre arama yaparken kullanılır +-- Adı 'A' ile başlayan veriler +SELECT * FROM tablo1 WHERE adi LIKE "A%"; +-- İçinde 'A' olan veriler +SELECT * FROM tablo1 WHERE adi LIKE "%A%"; + +-- LIMIT KOMUTU +-- Gösterilen satır sayısını sınırlamak için +SELECT * FROM Tablo1 LIMIT 6; +-- Gösterilen satırları belirli bir noktadan başlamak üzere sınırlamak için +SELECT * FROM Tablo1 LIMIT 6 OFFSET 3; + +-- ORDER BY KOMUTU +-- Herhangi bir kolona göre gösterilen değerleri azalan veya artan şekilde sıralamak için +SELECT kolon FROM tablo1 WHERE yas ORDER BY column1, column2, .. columnN] [ASC | DESC]; +SELECT * FROM Tablo1 ORDER BY yas ASC +SELECT * FROM Tablo1 ORDER BY yas DESC + +-- DISTINCT ANAHTAR SÖZCÜĞÜ +-- Bu anahtar sözcükle sadece farklı değerler gösterilir. +SELECT DISTINCT yas FROM tablo1; + +-- JOIN KOMUTU +-- CROSS JOIN +-- Cross join bir tablodaki her satırı ikinci tablodaki bir satır ile eşleştirmek için kulanılır. +-- Eğer birinci tabloda x satır ikinci tabloda y satır varsa sonuçta x*y satır olur. +SELECT ... FROM table1 CROSS JOIN table2 … +SELECT ad, yas FROM Tablo1 CROSS JOIN Tablo2; + +-- INNER JOIN +-- Inner join iki tablodaki ortak kolon değerlerini kullanarak bir sonuç üretir. +SELECT ... FROM table1 [INNER] JOIN table2 ON conditional_expression … +SELECT ad, yas FROM Tablo1 INNER JOIN Tablo2 ON Tablo1.ad = Tablo2.soyad; + +-- OUTER JOIN +-- Outer join iki tablodaki ortak kolon değerlerinin dışında kalanları kullanarak bir sonuç üretir. +SELECT isci_num, isim, dept FROM Tablo1 LEFT OUTER JOIN Tablo2 ON Tablo1.id = Tablo2.isci_num; + +-- ÇEKİRDEK FONKSİYONLAR +COUNT -- Sayma +AVG -- Ortalama +ABS -- Mutlak değer +SUM -- Toplam +RANDOM -- Rastgele +ROUND -- Yuvarlama +MAX -- Maksimim +MIN -- Minimum +UPPER -- Büyük Harf +LOWER -- Küçük Harf +LENGTH -- Uzunluk +CURRENT_TIMESTAMP -- Zaman + +SELECT max(yas) FROM Table1; +SELECT min(yas) FROM Table1; +SELECT avg(yas) FROM Table1; +SELECT * From Table1 WHERE yas ==18; +SELECT sum(yas) FROM Table1; +SELECT random() AS Random; +SELECT upper(ad) FROM Table1; +SELECT lower(ad) FROM Table1; +SELECT ad, length(ad) FROM Table1; ```
\ No newline at end of file diff --git a/typescript.html.markdown b/typescript.html.markdown index cf2111d5..64f5ca5b 100644 --- a/typescript.html.markdown +++ b/typescript.html.markdown @@ -2,6 +2,7 @@ language: TypeScript contributors: - ["Philippe Vlérick", "https://github.com/pvlerick"] + - ["Kiwimoe", "https://github.com/kiwimoe"] filename: learntypescript.ts --- @@ -16,7 +17,7 @@ This article will focus only on TypeScript extra syntax, as opposed to [JavaScript](/docs/javascript). To test TypeScript's compiler, head to the -[Playground] (http://www.typescriptlang.org/Playground) where you will be able +[Playground](https://www.typescriptlang.org/play) where you will be able to type code, have auto completion and directly see the emitted JavaScript. ```ts @@ -48,6 +49,7 @@ let list: Array<number> = [1, 2, 3]; // For enumerations: enum Color { Red, Green, Blue }; let c: Color = Color.Green; +console.log(Color[c]); // "Green" // Lastly, "void" is used in the special case of a function returning nothing function bigHorribleAlert(): void { @@ -114,7 +116,7 @@ class Point { } // Functions - dist() { return Math.sqrt(this.x * this.x + this.y * this.y); } + dist(): number { return Math.sqrt(this.x * this.x + this.y * this.y); } // Static members static origin = new Point(0, 0); @@ -137,7 +139,7 @@ class Point3D extends Point { } // Overwrite - dist() { + dist(): number { let d = super.dist(); return Math.sqrt(d * d + this.z * this.z); } @@ -199,7 +201,7 @@ interface Person { } var p1: Person = { name: "Tyrone", age: 42 }; -p1.age = 25; // Error, p1.x is read-only +p1.age = 25; // Error, p1.age is read-only var p2 = { name: "John", age: 60 }; var p3: Person = p2; // Ok, read-only alias for p2 @@ -237,6 +239,16 @@ if (state.type === "success") { console.error(state.message); } +// Template Literal Types +// Use to create complex string types +type OrderSize = "regular" | "large"; +type OrderItem = "Espresso" | "Cappuccino"; +type Order = `A ${OrderSize} ${OrderItem}`; + +let order1: Order = "A regular Cappuccino"; +let order2: Order = "A large Espresso"; +let order3: Order = "A small Espresso"; // Error + // Iterators and Generators // for..of statement @@ -257,14 +269,29 @@ for (const i in list) { console.log(i); // 0, 1, 2 } +// Type Assertion + +let foo = {} // Creating foo as an empty object +foo.bar = 123 // Error: property 'bar' does not exist on `{}` +foo.baz = 'hello world' // Error: property 'baz' does not exist on `{}` +// Because the inferred type of foo is `{}` (an object with 0 properties), you +// are not allowed to add bar and baz to it. However with type assertion, +// the following will pass: + +interface Foo { + bar: number; + baz: string; +} +let foo = {} as Foo; // Type assertion here +foo.bar = 123; +foo.baz = 'hello world' ``` ## Further Reading * [TypeScript Official website] (http://www.typescriptlang.org/) - * [TypeScript language specifications] (https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md) - * [Anders Hejlsberg - Introducing TypeScript on Channel 9] (http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript) + * [TypeScript language specifications] (https://github.com/microsoft/TypeScript/blob/main/doc/spec-ARCHIVED.md) + * [Learn TypeScript] (https://learntypescript.dev/) * [Source Code on GitHub] (https://github.com/Microsoft/TypeScript) - * [Definitely Typed - repository for type definitions] (http://definitelytyped.org/) diff --git a/uk-ua/c-ua.html.markdown b/uk-ua/c-ua.html.markdown new file mode 100644 index 00000000..56a2b2ad --- /dev/null +++ b/uk-ua/c-ua.html.markdown @@ -0,0 +1,860 @@ +--- +language: C +filename: learnc-ua.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"] +translators: + - ["AstiaSun", "https://github.com/AstiaSun"] +lang: uk-ua +--- + +О, C! Досі мова для сучасних обчислень у високопродуктивних продуктах. + +C це імовірно найбільш низькорівнева мова, яку будуть використовувати більшість програмістів. Проте, вона компенсує це не тільки швидкістю виконання. Як тільки ви оціните її можливість ручного управління пам'яттю, С зможе відвести саме в ті місця, в які вам потрібно було потрапити. + +> **Дещо про прапори компілятора** +> +> За замовчуванням, gcc та clang досить тихо інформують про попередження та помилки +> при компіляції, хоч це і може бути дуже корисною інформацією. Тому рекомендується +> використовувати більш вимогливий компілятор. Ось кілька рекомендацій: +> +> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic` +> +> За інформацією про ці та інші прапори зверніться до головної сторінки man вашого +> компілятора C (наприклад, `man 1 gcc`) або ж просто заґуґліть. + + +```c +// Однорядкові коментарі починаються з // +// Проте вони з'явились тільки після С99. + +/* +Багаторядкові коментарі мають такий вигляд. І працюють в C89. +*/ + +/* +Багаторядкові коментарі не можуть вкладатись один в одний. +/* Будьте обережними */ // коментар закінчується на цьому рядку... +*/ // ...а не на цьому! + +// Константа: #define <keyword> +// Назви констант, як правило, пишуться великими літерами, проте це не вимога +#define DAYS_IN_YEAR 365 + +// Ще одним способом оголосити константи є перелічення констант. +// До речі, всі вирази мають закінчуватись крапкою з комою. +enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +// MON отримає значення 2 автоматично, TUE дорівнюватиме 3 і т.д. + +// Імпортувати заголовки можна за допомогою #include +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// (Заголовки із стандартної бібліотеки С вказуються між <кутовими дужками>.) +// Щоб додати власні заголовки, потрібно використовувати "подвійні лапки" +// замість кутових: +//#include "my_header.h" + +// Сигнатури функцій попередньо оголошуються в .h файлах або на початку .с файлів. +void function_1(); +int function_2(void); + +// Потрібно оголосити 'прототип функції' перед main(), реалізація функцій +// відбувається після функції main(). +int add_two_ints(int x1, int x2); // прототип функції +// Варіант `int add_two_ints(int, int);` теж правильний (не потрібно називати +// аргументи). Рекомендується також називати аргументи в прототипі для +// кращого розуміння. + +// Вхідною точкою програми є функція під назвою main. Вона повертає чисельний тип. +int main(void) { + // реалізація програми +} + +// Аргументи командного рядка, вказані при запуску програми, також передаються +// у функцію main. +// argc - це кількість переданих аргументів +// argv — це масив масивів символів, що містить самі аргументи +// argv[0] - назва програми, argv[1] - перший аргумент, і т.д. +int main (int argc, char** argv) +{ + // printf дозволяє вивести на екран значення, вивід - це форматований рядок, + // в даному випадку %d позначає чисельне значення, \n — це новий рядок + printf("%d\n", 0); // => Виводить 0 + + /////////////////////////////////////// + // Типи + /////////////////////////////////////// + + // Всі змінні повинні бути оголошені на початку поточного блоку області видимості. + // В цьому коді вони оголошуються динамічно. С99-сумісні компілятори + // дозволяють оголошення близько до місця, де значення використовується. + + // int (цілочисельний знаковий тип) зазвичай займає 4 байти + int x_int = 0; + + // short (цілочисельний знаковий тип) зазвичай займає 2 байти + // + short x_short = 0; + + // Символьний тип char гарантовано займає 1 байт + char x_char = 0; + char y_char = 'y'; // Символьні літерали позначаються '' + + // long (цілочисельний знаковий тип) має розмір від 4 до 8 байтів; великі значення + // типу long гарантовано займають 8 байтів + long x_long = 0; + long long x_long_long = 0; + + // Тип float - це зазвичай 32-бітове число з плаваючою крапкою + float x_float = 0.0f; // Суфікс 'f' позначає літерал з плаваючою крапкою + + // Тип double - це зазвийчай 64-бітове число з плаваючою крапкою + double x_double = 0.0; // дійсне число без суфіксів має тип double + + // Цілочисельні типи можуть не мати знаку (бути більше, або ж рівними нулю) + unsigned short ux_short; + unsigned int ux_int; + unsigned long long ux_long_long; + + // Char всередині одинарних лапок інтерпретуються як числа в наборі + // символів комп'ютера. + '0'; // => 48 в таблиці ASCII. + 'A'; // => 65 в таблиці ASCII. + + // sizeof(T) повертає розмір змінної типу Т в байтах + // sizeof(obj) віддає розмір виразу (змінна, літерал, і т.п.) + printf("%zu\n", sizeof(int)); // => 4 (на більшості пристроїв з 4-байтним словом) + + // Якщо аргумент оператора `sizeof` — це вираз, тоді його аргументи не оцінюються + // (крім масивів, розмір яких залежить від змінної). + // Значення, що повертається в цьому випадку, - це константа часу компіляції. + int a = 1; + // size_t - беззнаковий чисельний тип розміром щонайменше 2 байти, який + // використовується для відображення розміру об'єкта. + size_t size = sizeof(a++); // a++ не оцінюється + printf("sizeof(a++) = %zu where a = %d\n", size, a); + // Виводить "sizeof(a++) = 4 where a = 1" (на 32-бітній архітектурі) + + // Масиви повинні бути проініціалізовані з конкретним розміром. + char my_char_array[20]; // Цей масив займає 1 * 20 = 20 байтів + int my_int_array[20]; // Цей масив займає 4 * 20 = 80 байтів + // (припускаючи 4-байтні числа) + + // Таким чином можна проініціалізувати масив нулем: + char my_array[20] = {0}; + // де "{0}" називається "ініціалізатором масиву". + + // Зазначте, можна явно не оголошувати розмір масиву, ЯКЩО ви проініціалізуєте + // масив у тому ж рядку. Тому, наступне оголошення еквівалентне: + char my_array[] = {0}; + // АЛЕ, потрібно визначити розмір масиву під час виконання, як тут: + size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]); + + // ПОПЕРЕДЖЕННЯ якщо ви вирішили використовувати даний підхід, потрібно + // визначити розмір **перед тим**, як ви почнете передавати масив у функцію + // (побачите дискусію пізніше). Масиви перетворюються на вказівники при + // передачі як аргументи у функцію, тому попереднє твердження буде видавати + // хибний результат всередині функції. + + // Індексація по масиву така ж сама, як і в інших мовах програмування або, + // скоріше, як у інших с-подібних мовах. + my_array[0]; // => 0 + + // Масиви незмінні, це просто частина пам'яті! + my_array[1] = 2; + printf("%d\n", my_array[1]); // => 2 + + // Масиви, розмір яких залежить від змінної, в С99 (та в С11 як вибірковий + // функціонал) можуть бути оголошені також. Розмір такого масиву не має бути + // константою під час компіляції: + printf("Enter the array size: "); // спитати користувача розмір масиву + int array_size; + fscanf(stdin, "%d", &array_size); + int var_length_array[array_size]; // оголосити масив + printf("sizeof array = %zu\n", sizeof var_length_array); + + // Приклад: + // > Enter the array size: 10 + // > sizeof array = 40 + + // Рядки - це просто масиви символьних літералів (char), що закінчуються NULL + // (0x00) байтом, представленим у рядках як спеціальний символ '\0'. + // (Не потрібно включати байт NULL в рядкові літерали; компілятор сам вставляє + // його наприкінці масиву.) + char a_string[20] = "This is a string"; + printf("%s\n", a_string); // %s форматує рядок + + printf("%d\n", a_string[16]); // => 0 + // тобто, байт #17 - це 0 (так само, як і 18-ий, 19-ий, та 20-ий) + + // Якщо між одинарними лапками є букви, тоді це символьний літерал. + // Він має тип `int`, а не `char` (так історично склалось). + int cha = 'a'; // добре + char chb = 'a'; // також добре (неявне перетворення з int на char) + + // Багатовимірні масиви: + int multi_array[2][5] = { + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 0} + }; + // Доступ до елементів: + int array_int = multi_array[0][2]; // => 3 + + /////////////////////////////////////// + // Оператори + /////////////////////////////////////// + + // Скорочення для багатьох оголошень: + int i1 = 1, i2 = 2; + float f1 = 1.0, f2 = 2.0; + + int b, c; + b = c = 0; + + // Арифметичні операції + i1 + i2; // => 3 + i2 - i1; // => 1 + i2 * i1; // => 2 + i1 / i2; // => 0 (0.5 округлено до 0) + + // Потрібно перетворити хоча б одну з цілочисельних змінних на float, щоб + // отримати результат з плаваючою крапкою + (float)i1 / i2; // => 0.5f + i1 / (double)i2; // => 0.5 // Так само і для типу double + f1 / f2; // => 0.5, з певною точністю + // Такі обчислення не є точними + + // Ділення за модулем також є + 11 % 3; // => 2, остача від ділення + + // Оператори порівняння ймовірно схожі, проте в С немає логічного типу. + // Натомість використовується int. + // (Або _Bool або bool в C99.) + // 0 - хибно (false), всі інші значення - правда (true). Оператори + // порівняння завжди повертають 0 або 1. + 3 == 2; // => 0 (false) + 3 != 2; // => 1 (true) + 3 > 2; // => 1 + 3 < 2; // => 0 + 2 <= 2; // => 1 + 2 >= 2; // => 1 + + // C - це не Python, порівняння не утворюють ланцюги. + // Попередження: Рядок нижче скомпілюється, але він означає `(0 < a) < 2`. + // В даному випадку, це 1, тому що (0 < 1). + int between_0_and_2 = 0 < a < 2; + // Натомість потрібно використати: + int between_0_and_2 = 0 < a && a < 2; + + // Логічні оператори з числами + !3; // => 0 (Логічне НЕ) + !0; // => 1 + 1 && 1; // => 1 (Логічне І) + 0 && 1; // => 0 + 0 || 1; // => 1 (Логічне АБО) + 0 || 0; // => 0 + + // Тернарний вираз з умовою ( ? : ) + int e = 5; + int f = 10; + int z; + z = (e > f) ? e : f; // => 10 "if e > f return e, else return f." + + // Оператори збільшення та зменшення на 1: + int j = 0; + int s = j++; // Повернути j ПОТІМ збільшити j. (s = 0, j = 1) + s = ++j; // Збільшити j ПОТІМ повернути j. (s = 2, j = 2) + // так само і для j-- та --j + + // Побітові операції! + ~0x0F; // => 0xFFFFFFF0 (побітове заперечення, "перше доповнення", результат + // для 32-бітного int) + 0x0F & 0xF0; // => 0x00 (побітове І) + 0x0F | 0xF0; // => 0xFF (побітове АБО) + 0x04 ^ 0x0F; // => 0x0B (побітове XOR) + 0x01 << 1; // => 0x02 (побітовий зсув вліво (на 1)) + 0x02 >> 1; // => 0x01 (побітовий зсув вправо (на 1)) + + // Будьте обережними при зсуві цілочисельних значень зі знаком. + // Наступні дії дають невизначений результат: + // - зсув на біт, що зберігає знак числа (int a = 1 << 31) + // - зсув вліво на від'ємне число (int a = -1 << 2) + // - зсув на число, що більше за ширину типу + // TODO: LHS + // - зсув на зміщення, що >= ширині типу в лівій частині виразу: + // int a = 1 << 32; // Невизначена поведінка, якщо ширина int 32 біти. + + /////////////////////////////////////// + // Структури розгалуження + /////////////////////////////////////// + + // Оператор умови + if (0) { + printf("I am never run\n"); // ніколи не буде виконано + } else if (0) { + printf("I am also never run\n"); // теж ніколи не буде виконано + } else { + printf("I print\n"); // це буде надруковано + } + + // Цикл з передумовою + int ii = 0; + while (ii < 10) { // БУДЬ-ЯКЕ значення, що менше 10 - правда. + printf("%d, ", ii++); // ii++ збільшує ii на 1 ПІСЛЯ передачі поточного значення. + } // => надрукує "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // Цикл з післяумовою + int kk = 0; + do { + printf("%d, ", kk); + } while (++kk < 10); // ++kk збільшує kk на 1 ПЕРЕД передачою поточного значення. + // => надрукує "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // Цикл з лічильником + int jj; + for (jj=0; jj < 10; jj++) { + printf("%d, ", jj); + } // => виводить "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " + + printf("\n"); + + // *****Додатково*****: + // Цикли та функції обов'язково повинні мати тіло. Якщо тіло не потрібно: + int i; + for (i = 0; i <= 5; i++) { + ; // використовуйте крапку з комою, щоб симулювати тіло (пусте твердження) + } + // Або + for (i = 0; i <= 5; i++); + + // Розгалуження з множинним вибором: switch() + switch (a) { + case 0: // значення повинні бути *константними* виразами і мати вбудований тип + //(наприклад, перелічення) + printf("Hey, 'a' equals 0!\n"); + break; // якщо не використати break, то управління буде передано наступному блоку + case 1: + printf("Huh, 'a' equals 1!\n"); + break; + // Будьте обережними, виконання продовжиться до тих пір, поки + // не зустрінеться наступний "break". + case 3: + case 4: + printf("Look at that.. 'a' is either 3, or 4\n"); + break; + default: + // якщо вираз a не співпадає з описаними значеннями, то виконується + // блок default + fputs("Error!\n", stderr); + exit(-1); + break; + } + /* + Використання "goto" в С + */ + typedef enum { false, true } bool; + // вводимо таке перелічення, оскільки С не має логічного типу до С99 + bool disaster = false; + int i, j; + for(i=0;i<100;++i) + for(j=0;j<100;++j) + { + if((i + j) >= 150) + disaster = true; + if(disaster) + goto error; + } + error : + printf("Error occurred at i = %d & j = %d.\n", i, j); + /* + https://ideone.com/GuPhd6 + Даний приклад виведе "Error occurred at i = 51 & j = 99." + */ + + /////////////////////////////////////// + // Приведення до типів + /////////////////////////////////////// + + // Кожне значенння в С має тип, але можна перевести значення з одного типу в + // інший, якщо потрібно (із деякими обмеженнями). + + int x_hex = 0x01; // Змінним можна присвоювати літерали в шістнадцятковій + // системі числення + + // Приведення до типу призведе до спроби зберегти чисельне значення + printf("%d\n", x_hex); // => Виводить 1 + printf("%d\n", (short) x_hex); // => Виводить 1 + printf("%d\n", (char) x_hex); // => Виводить 1 + + // В данному випадку попередження не виникатиме, якщо значення виходить за межі + // значення типу + printf("%d\n", (unsigned char) 257); // => 1 (максимальне значення char = 255, + // якщо char має довжину 8 біт) + + // Для того, щоб дізнатись максимальний розмір `char`, `signed char` або ж + // `unsigned char`, потрібно використати макроси CHAR_MAX, SCHAR_MAX та UCHAR_MAX + // відповідно з <limits.h>. + + // Вбудовані типи можуть бути приведені до типу із плаваючою крапкою і навпаки. + printf("%f\n", (double) 100); // %f завжди перетворює число на double... + printf("%f\n", (float) 100); // ...навіть, якщо це float. + printf("%d\n", (char)100.0); + + /////////////////////////////////////// + // Вказівники + /////////////////////////////////////// + + // Вказівник - це змінна, що зберігає адресу у пам'яті. Оголошення вказівника + // також потребує інформації про тип об'єкта, на який він вказує. Можна + // отримати адресу пам'яті будь-якої змінної, а потім працювати з нею. + + int x = 0; + printf("%p\n", (void *)&x); // Оператор & повертає адресу змінної у пам'яті + // (%p форматує об'єкт вказівника типу void *) + // => Виводить деяку адресу в пам'яті + + // Для оголошення вказівника потрібно поставити * перед його назвою. + int *px, not_a_pointer; // px - це вказівник на цілочисельне значення (int) + px = &x; // Зберігає адресу змінної x в px + printf("%p\n", (void *)px); // => Виводить адресу в пам'яті + printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); + // => Виводить "8, 4" на звичайній 64-бітній системі + + // Щоб прочитати значення, яке зберігається за адресою, на яку вказує вказівник, + // потрібно поставити знак * перед назвою змінної. + // Так, * використовується одночасно і для оголошення вказівника, і для отримання + // значення за адресою. Звучить заплутано, проте тільки спочатку. + printf("%d\n", *px); // => Виводить 0, значення x + + // Можна також змінити значення, на яке посилається вказівник. + // Тут звернення до адреси обернене у круглі дужки, тому що + // ++ має вищий пріоритет виконання, ніж *. + (*px)++; // Збільшити значення, на яке вказує px, на 1 + printf("%d\n", *px); // => Виводить 1 + printf("%d\n", x); // => Виводить 1 + + // Масиви зручно використовувати для виділення неперервного блоку пам'яті. + int x_array[20]; // оголошує масив з 20 елементів (розмір можна задати лише один раз) + int xx; + for (xx = 0; xx < 20; xx++) { + x_array[xx] = 20 - xx; + } // Ініціалізує x_array значеннями 20, 19, 18,... 2, 1 + + // Оголосити вказівник типу int, який посилається на масив x_array + int* x_ptr = x_array; + // x_ptr тепер вказує на перший елемент масиву (число 20). + // + // Це працює, тому що при зверненні до імені масиву повертається вказівник + // на перший елемент. Наприклад, коли масив передається у функцію або присвоюється + // вказівнику, він неявно приводиться до вказівника. + // Виключення: + // - коли вказівник передається як аргумент із оператором `&`: + int arr[10]; + int (*ptr_to_arr)[10] = &arr; // &arr НЕ має тип `int *`! + // Він має тип "вказівник на масив" (з 10 чисел). + // - коли масив - це рядковий літерал, що використовується для ініціалізації + // масив символів: + char otherarr[] = "foobarbazquirk"; + // - коли масив - це аргумент операторів `sizeof` або `alignof`: + int arraythethird[10]; + int *ptr = arraythethird; // те ж саме, що з int *ptr = &arr[0]; + printf("%zu, %zu\n", sizeof(arraythethird), sizeof(ptr)); + // Ймовірно, виводить "40, 4" або "40, 8" + + // Інкрементація та декрементація вказівника залежить від його типу. + // (так звана арифметика вказівників) + printf("%d\n", *(x_ptr + 1)); // => Виводить 19 + printf("%d\n", x_array[1]); // => Виводить 19 + + // Можна також динамічно виділити послідовні блоки в пам'яті за допомогою + // функції malloc зі стандартної бібліотеки. malloc приймає один аргумент типу + // size_t, що описує кількість байтів для виділення (зазвичай із купи, проте це + // може бути неправдою на вбудованих системах - стандарт С нічого про це не повідомляє). + int *my_ptr = malloc(sizeof(*my_ptr) * 20); + for (xx = 0; xx < 20; xx++) { + *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx + } // Проініціалізувати пам'ять значеннями 20, 19, 18, 17... 2, 1 (як int) + + // Будьте обережними із передачею значень, що надаються користувачем, в malloc! + // Про всяк випадок, використовуйте calloc в таких ситуаціях (який, на відміну від + // malloc, також заповнює пам'ять нулями). + int* my_other_ptr = calloc(20, sizeof(int)); + + // Немає стандартного способу визначити розмір динамічно виділеного масиву в С. + // Через це, якщо масиви будуть часто передаватись в програмі, потрібна інша змінна, + // яка буде відслідковувати кількість елементів в масиві. Детальніше в розділі + // про функції. + size_t size = 10; + int *my_arr = calloc(size, sizeof(int)); + // Додати елемент до масиву. + size++; + my_arr = realloc(my_arr, sizeof(int) * size); + if (my_arr == NULL) { + // Не забувайте перевіряти результат виконання realloc на помилки! + return + } + my_arr[10] = 5; + + // Робота з вказівниками може призводити до неочікуваних і непрогнозованих + // результатів, якщо звернутись до пам'яті, що не була виділена вами. + printf("%d\n", *(my_ptr + 21)); // => Хто зна, що буде виведено. + // Може навіть вилетіти з помилкою. + + // Після закінчення роботи із виділеною за допомогою malloc пам'яттю, її обов'язково + // потрібно звільнити. Інакше ніхто не зможе нею скористатися, аж поки програма не + // завершить свою роботу (така ситуація називається "витоком пам'яті"). + free(my_ptr); + + // Рядки - це масиви символів, проте вони найчастіше представлені як + // вказівник на символ (тобто, вказівник на перший елемент масиву). Вважається + // хорошим підходом використовувати `const char *', посилаючись на об'єкт + // рядка, оскільки його не можна змінити ("foo"[0] = 'a' ЗАБОРОНЕНО). + const char *my_str = "This is my very own string literal"; + printf("%c\n", *my_str); // => 'T' + + // Це не працюватиме, якщо рядок - це масив (потенційно створений за допомогою + // рядкового літерала), що зберігається у частині пам'яті, яку можна перезаписувати: + char foo[] = "foo"; + foo[0] = 'a'; // Дозволяється, foo тепер містить "aoo" + + function_1(); +} // Кінець функції main + +/////////////////////////////////////// +// Функції +/////////////////////////////////////// + +// Синтаксис оголошення функції: +// <тип повернення> <назва функції>(<аргументи>) + +int add_two_ints(int x1, int x2) +{ + return x1 + x2; // Використовуйте return, щоб повернути значення +} + +/* +Дані у функцію передають за значенням. Коли функція викликається, аргументи, що +передаються у функцію, копіюються з оригіналів (окрім масивів). Всі зміни над +значенням аргументів всередині функції не впливають на значення оригіналів. + +Використовуйте вказівники, якщо потрібно редагувати безпосередньо оригінальні +значення аргументів. + +Приклад: замінити рядок на обернений. +*/ + +// void означає, що функція нічого не повертає +void str_reverse(char *str_in) +{ + char tmp; + size_t ii = 0; + size_t len = strlen(str_in); // `strlen()` це частина стандартної бібліотеки С + // Зауважте: довжина, яку повертає `strlen`, не включає + // термінальний NULL байт ('\0') + for (ii = 0; ii < len / 2; ii++) { // в C99 можна напряму оголошувати тип `ii` в циклі + tmp = str_in[ii]; + str_in[ii] = str_in[len - ii - 1]; // ii-й символ з кінця + str_in[len - ii - 1] = tmp; + } +} +// Зауважте: для використання strlen() потрібно завантажити файл заголовку string.h + +/* +char c[] = "This is a test."; +str_reverse(c); +printf("%s\n", c); // => ".tset a si sihT" +*/ +/* +Оскільки можна повертати тільки одну змінну, для зміни значення більшої +кількості змінних можна використовувати виклик за посиланням +*/ +void swapTwoNumbers(int *a, int *b) +{ + int temp = *a; + *a = *b; + *b = temp; +} +/* +int first = 10; +int second = 20; +printf("first: %d\nsecond: %d\n", first, second); +swapTwoNumbers(&first, &second); +printf("first: %d\nsecond: %d\n", first, second); +// змінні обмінюються значеннями +*/ + +/* +Масиви завжди передаються у функції як вказівники, не зважаючи на тип масиву +(статичний чи динамічний). Тому всередині функція не знає про розмір масиву. +*/ +// Розмір масиву завжди має передаватись разом із масивом! +void printIntArray(int *arr, size_t size) { + int i; + for (i = 0; i < size; i++) { + printf("arr[%d] is: %d\n", i, arr[i]); + } +} +/* +int my_arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; +int size = 10; +printIntArray(my_arr, size); +// виведе "arr[0] is: 1" і т.д. +*/ + +// Ключове слово extern використовується, якщо всередині функції потрібно звернутись +// до змінної, що була оголошена поза функцією. +int i = 0; +void testFunc() { + extern int i; // використовуємо зовнішню змінну i +} + +// Зробити зовнішню змінну приватною у вихідному файлі за допомогою static: +static int j = 0; // інші файли, що використовують testFunc2(), + // не матимуть доступу до змінної j +void testFunc2() { + extern int j; +} +// Ключове слово static робить змінну недоступною для коду поза даною одиницею +// компіляції. (На більшості систем, одиниця компіляції - це файл). +// static можна використовувати до глобальних змінних, функцій, локальних +// змінних у функціях. Локальні змінні, проініціалізовані static, поводять +// себе як глобальні змінні, проте тільки в межах даного файлу. Статичні +// змінні ініціалізуються 0, якщо інше значення не було вказане. +// **Як варіант, функції можна зробити приватними оголосивши їх як static** + +/////////////////////////////////////// +// Користувацькі типи та структури +/////////////////////////////////////// + +// Ключове слово typedef використовується, щоб створити псевдонім типу +typedef int my_type; +my_type my_type_var = 0; + +// Структури - це такі собі колекції з даними. Пам'ять для полів виділяється +// послідовно, в порядку їх написання: +struct rectangle { + int width; + int height; +}; + +// Проте це не означає, що +// sizeof(struct rectangle) == sizeof(int) + sizeof(int) +// в зв'язку з вирівнюванням пам'яті [1] + +void function_1() +{ + struct rectangle my_rec; + + // Доступ до полів структури відбувається через . + my_rec.width = 10; + my_rec.height = 20; + + // Можна створити вказівники на структуру + struct rectangle *my_rec_ptr = &my_rec; + + // Звернення до структури через вказівник та зміна значень поля: + (*my_rec_ptr).width = 30; + + // Але є й альтернативний спосіб звернутись до поля через вказівник, використовуючи + // оператор -> (краще читається) + my_rec_ptr->height = 10; // Те ж саме, що (*my_rec_ptr).height = 10; +} + +// Можна використати typedef перед struct +typedef struct rectangle rect; + +int area(rect r) +{ + return r.width * r.height; +} + +// Якщо ваша структура доволі громіздка, можна звертатись до неї через вказівник, +// щоб уникнути копіювання всієї структури: +int areaptr(const rect *r) +{ + return r->width * r->height; +} + +/////////////////////////////////////// +// Вказівники на функції +/////////////////////////////////////// +/* +Під час виконання функції знаходяться за відомими адресами в пам'яті. Вказівники +на функції - це ті ж самі вказівники, що зберігають адресу у пам'яті, проте можуть +використовуватись, щоб викликати функції напряму і передавати обробники (або функції зі +зворотнім зв'язком). Хоча, синтаксис спочатку може бути доволі незрозумілим. + +Приклад: use str_reverse from a pointer +*/ +void str_reverse_through_pointer(char *str_in) { + // Оголосити вказівник на функцію під назвою f. + void (*f)(char *); // Сигнатура повинна точно співпадати із цільовою функцією. + f = &str_reverse; // Присвойте адресу певної функції (визначається під час виконання) + // f = str_reverse; повинно працювати також + (*f)(str_in); // Виклик функції через вказівник + // f(str_in); // Це альтернативний, але теж вірний синтаксис виклику функції. +} + +/* +Якщо сигнатури функцій співпадають, можна присвоїти будь-яку функцію тому ж +самому вказівнику. Вказівники на функції зазвичай використовуються як псевдоніми +для спрощення та покращення читабельності коду. Приклад: +*/ + +typedef void (*my_fnp_type)(char *); + +// Використання при оголошенні змінної вказівника: +// ... +// my_fnp_type f; + + +// Спеціальні символи: +/* +'\a'; // символ попередження (дзвінок) +'\n'; // символ нового рядка +'\t'; // символ табуляції (вирівнювання по лівому краю) +'\v'; // вертикальна табуляція +'\f'; // нова сторінка +'\r'; // повернення каретки +'\b'; // стирання останнього символу +'\0'; // нульовий символ. Зазвичай розташовується в кінці рядка. +// hello\n\0. \0 використовується для позначення кінця рядка. +'\\'; // зворотній слеш +'\?'; // знак питання +'\''; // одинарні лапки +'\"'; // подвійні лапки +'\xhh'; // шістнадцяткове число. Наприклад: '\xb' = символ вертикальної табуляції +'\0oo'; // вісімкове число. Наприклад: '\013' = символ вертикальної табуляції + +// форматування виводу: +"%d"; // ціле число (int) +"%3d"; // ціле число, щонайменше 3 символи (вирівнювання по правому краю) +"%s"; // рядок +"%f"; // число з плаваючою крапкою (float) +"%ld"; // велике ціле число (long) +"%3.2f"; // число з плаваючою крапкою, щонайменше 3 цифри зліва і 2 цифри справа +"%7.4s"; // (аналогічно для рядків) +"%c"; // символ +"%p"; // вказівник. Зазначте: потребує перетворення типу на (void *) перед + // використанням у `printf`. +"%x"; // шістнадцяткове число +"%o"; // вісімкове число +"%%"; // друкує % +*/ + +/////////////////////////////////////// +// Порядок виконання +/////////////////////////////////////// + +//---------------------------------------------------// +// Оператори | Асоціативність// +//---------------------------------------------------// +// () [] -> . | зліва направо // +// ! ~ ++ -- + = *(type)sizeof | справа наліво // +// * / % | зліва направо // +// + - | зліва направо // +// << >> | зліва направо // +// < <= > >= | зліва направо // +// == != | зліва направо // +// & | зліва направо // +// ^ | зліва направо // +// | | зліва направо // +// && | зліва направо // +// || | зліва направо // +// ?: | справа наліво // +// = += -= *= /= %= &= ^= |= <<= >>= | справа наліво // +// , | зліва направо // +//---------------------------------------------------// + +/****************************** Файли заголовків ********************************* + +Файли заголовків важливі в С. Вони розділяють вихідний код та визначення на різні +файли, що робить їх кращими для розуміння. + +Файли заголовків синтаксично подібні до вихідних файлів С, проте описуються у".h" +файлах. Їх можна додати в код за допомогою директиви #include "example.h", якщо +example.h існує в тому ж каталозі, що і файл С. +*/ + +/* +Так можна запобігти тому, що заголовок буде оголошений кілька разів. Така ситуація +виникає у випадку циклічної залежності, тобто коли вміст заголовку вже було +оголошено. +*/ +#ifndef EXAMPLE_H /* якщо EXAMPLE_H ще не оголошено. */ +#define EXAMPLE_H /* Визначити макрос EXAMPLE_H. */ + +/* +Заголовки можна додавати в інші заголовки, таким чином вони разом додаються +у подальшому. +*/ +#include <string.h> + +/* +Макроси можуть бути визначені також у заголовку та використовуватись у файлах, +що містять цей заголовок. +*/ +#define EXAMPLE_NAME "Dennis Ritchie" + +/* Макроси функції також можна визначити. */ +#define ADD(a, b) ((a) + (b)) +/* +Зверніть увагу на круглі дужки навколо аргументів! Важливо переконатись, що +a та b не можна проінтерпретувати інакше. Наприклад: +MUL(x, y) (x * y); +MUL(1 + 2, 3) -> (1 + 2 * 3), що є помилкою +*/ + +/* Struct та typedef можуть використовуватись для узгодженості між файлами. */ +typedef struct Node +{ + int val; + struct Node *next; +} Node; + +/* Так само і перелічення. */ +enum traffic_light_state {GREEN, YELLOW, RED}; + +/* +Прототипи функцій також можна оголосити так, щоб використовувати у кількох +файлах. Але так робити не варто. Краще оголосити їх у С файлі. +*/ +Node createLinkedList(int *vals, int len); + +/* +Окрім вище згаданих випадків, всі інші визначення мають описуватись у С файлах. +*/ + +#endif /* Кінець директиви передкомпіляції if. */ + +``` +## Додаткові матеріали + +Кращим посібником для вивчення С буде книга авторства Деніса Рітчі (творець С) та Браяна Кернігана, +[K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language). +Але обережно з нею, книга старезна і містить неточності (ідеї, що вже вважаються не надто прийнятними). + +Ще одним хорошим ресурсом є книга "Learn C The Hard Way" (наявна тільки англійською). + +На деякі часті запитання дасть відповідь англомовний ресурс [compl.lang.c Frequently Asked Questions](http://c-faq.com). + +Нагадаю, що важливо використовувати правильні інтервали, відступи та загалом мати узгоджений стиль коду. +Зручний для читання код краще, ніж складний код або зроблений нашвидкоруч. За прикладом можна звернутись до +[Linux kernel coding style](https://www.kernel.org/doc/Documentation/process/coding-style.rst). + +Щодо всього іншого, Ґуґл на допомогу! + +[1] [Чому розмір структури не дорівнює сумі розмірів її полів? (англ.)](http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) diff --git a/uk-ua/cypher-ua.html.markdown b/uk-ua/cypher-ua.html.markdown new file mode 100644 index 00000000..0911793b --- /dev/null +++ b/uk-ua/cypher-ua.html.markdown @@ -0,0 +1,254 @@ +--- +language: cypher +filename: LearnCypher-ua.cql +contributors: + - ["Théo Gauchoux", "https://github.com/TheoGauchoux"] +translators: + - ["AstiaSun", "https://github.com/AstiaSun"] +lang: uk-ua +--- + +Cypher - це мова запитів Neo4j для спрощення роботи з графами. Вона повторює синтаксис SQL та перемішує його з таким собі ascii стилем для відображення структури графа. +Цей навчальний матеріал передбачає, що ви вже знайомі із концепцією графів, зобрема що таке вершини та зв'язки між ними. + +[Деталі тут](https://neo4j.com/developer/cypher-query-language/) + + +Вершини +--- + +**Відображує запис у графі.** + +`()` +Таким чином у запиті позначається пуста *вершина*. Використовується зазвичай для того, щоб позначити, що вона є, проте це не так вже й важливо для запиту. + +`(n)` +Це вершина, яка має назву **n**, до неї можна повторно звертатись у запиті. Звернення до вершини **n** починається з нижнього підкреслення та використовує camelCase (верблюжий регіст). + +`(p:Person)` +Можна також додати *ярлик* до вершини, в данному випадку - **Person**. Це як тип / клас / категорія. Назва *ярлика* починається з великої літери та використовує верблюжу нотацію. + +`(p:Person:Manager)` +Вершина може мати кілька *ярликів*. + +`(p:Person {name : 'Théo Gauchoux', age : 22})` +Вершина також може мати різні *властивості*, в данному випадку - **name** та **age**. Також мають починатися з великої літери та використовувати верблюжу нотацію. + +Наступні типи дозволяється використовувати у властивостях: + + - Чиселиний + - Булевий + - Рядок + - Списки попередніх примітивних типів + +*Увага! В Cypher не існує типу, що відображає час. Замість нього можна використовувати рядок із визначеним шаблоном або чисельне відображення певної дати.* + +`p.name` +За допомогою крапки можна звернутись до властивості вершини. + + +Зв'язки (або ребра) +--- + +**Сполучають дві вершини** + +`[:KNOWS]` +Це *зв'язок* з *ярликом* **KNOWS**. Це такий же самий *ярлик* як і у вершини. Починається з великої літери та використовує ВЕРХНІЙ\_РЕГІСТР\_ІЗ\_ЗМІЇНОЮ\_НОТАЦІЄЮ. + +`[k:KNOWS]` +Це той же самий *зв'язок*, до якого можна звертатись через змінну **k**. Можна подалі використовувати у запиті, хоч це і не обов'язково. + +`[k:KNOWS {since:2017}]` +Той же *зв'язок*, але вже із *властивостями* (як у *вершини*), в данному випадку властивість - це **since**. + +`[k:KNOWS*..4]` +Це структурна інформація, яку використовують *шляхи*, які розглянуті нижче. В данному випадку, **\*..4** говорить: "Сумістити шаблон із зв'язком **k**, що повторюватиметься від одного до чотирьох разів." + + +Шляхи +--- + +**Спосіб поєднувати вершини та зв'язки.** + +`(a:Person)-[:KNOWS]-(b:Person)` +Шлях описує, що вершини **a** та **b** знають (knows) один одного. + +`(a:Person)-[:MANAGES]->(b:Person)` +Шлях може бути направленим. Цей описує, що **а** є менеджером **b**. + +`(a:Person)-[:KNOWS]-(b:Person)-[:KNOWS]-(c:Person)` +Можна створювати ланцюги зі зв'язків. Цей шлях описує друга друга (**a** знає **b**, який в свою чергу знає **c**). + +`(a:Person)-[:MANAGES]->(b:Person)-[:MANAGES]->(c:Person)` +Ланцюг, аналогічно, також може бути направленим. Шлях описує, що **a** - бос **b** і супер бос для **c**. + +Шаблони, які часто використовуються (з документації Neo4j): + +``` +// Друг-мого-друга +(user)-[:KNOWS]-(friend)-[:KNOWS]-(foaf) + +// Найкоротший шлях +path = shortestPath( (user)-[:KNOWS*..5]-(other) ) + +// Спільна фільтрація +(user)-[:PURCHASED]->(product)<-[:PURCHASED]-()-[:PURCHASED]->(otherProduct) + +// Навігація по дереву +(root)<-[:PARENT*]-(leaf:Category)-[:ITEM]->(data:Product) + +``` + + +Запити на створення +--- + +Створити нову вершину: +``` +CREATE (a:Person {name:"Théo Gauchoux"}) +RETURN a +``` +*`RETURN` дозволяє повернути результат після виконання запиту. Можна повертати кілька значень, наприклад, `RETURN a, b`.* + +Створити новий зв'язок (із двома вершинами): +``` +CREATE (a:Person)-[k:KNOWS]-(b:Person) +RETURN a,k,b +``` + +Запити на знаходження +--- + +Знайти всі вершини: +``` +MATCH (n) +RETURN n +``` + +Знайти вершини за ярликом: +``` +MATCH (a:Person) +RETURN a +``` + +Знайти вершини за ярликом та властивістю: +``` +MATCH (a:Person {name:"Théo Gauchoux"}) +RETURN a +``` + +Знайти вершини відповідно до зв'язків (ненаправлених): +``` +MATCH (a)-[:KNOWS]-(b) +RETURN a,b +``` + +Знайти вершини відповідно до зв'язків (направлених): +``` +MATCH (a)-[:MANAGES]->(b) +RETURN a,b +``` + +Знайти вершини за допомогою `WHERE`: +``` +MATCH (p:Person {name:"Théo Gauchoux"})-[s:LIVES_IN]->(city:City) +WHERE s.since = 2015 +RETURN p,state +``` + +Можна використовувати вираз `MATCH WHERE` разом із операцією `CREATE`: +``` +MATCH (a), (b) +WHERE a.name = "Jacquie" AND b.name = "Michel" +CREATE (a)-[:KNOWS]-(b) +``` + + +Запити на оновлення +--- + +Оновити окрему властивість вершини: +``` +MATCH (p:Person) +WHERE p.name = "Théo Gauchoux" +SET p.age = 23 +``` + +Оновити всі властивості вершини: +``` +MATCH (p:Person) +WHERE p.name = "Théo Gauchoux" +SET p = {name: "Michel", age: 23} +``` + +Додати нову властивіcть до вершини: +``` +MATCH (p:Person) +WHERE p.name = "Théo Gauchoux" +SET p + = {studies: "IT Engineering"} +``` + +Повісити ярлик на вершину: +``` +MATCH (p:Person) +WHERE p.name = "Théo Gauchoux" +SET p:Internship +``` + + +Запити на видалення +--- + +Видалити окрему вершину (пов'язані ребра повинні бути видалені перед цим): +``` +MATCH (p:Person)-[relationship]-() +WHERE p.name = "Théo Gauchoux" +DELETE relationship, p +``` + +Видалити властивість певної вершини: +``` +MATCH (p:Person) +WHERE p.name = "Théo Gauchoux" +REMOVE p.age +``` + +*Зверніть увагу, що ключове слово `REMOVE` це не те саме, що й `DELETE`!* + +Видалити ярлик певної вершини: +``` +MATCH (p:Person) +WHERE p.name = "Théo Gauchoux" +DELETE p:Person +``` + +Видалити всю базу даних: +``` +MATCH (n) +OPTIONAL MATCH (n)-[r]-() +DELETE n, r +``` + +*Так, це `rm -rf /` на мові Cypher !* + + +Інші корисні запити +--- + +`PROFILE` +Перед виконанням, показати план виконання запитів. + +`COUNT(e)` +Порахувати елементи (вершини та зв'язки), що відповідають **e**. + +`LIMIT x` +Обмежити результат до x перших результатів. + + +Особливі підказки +--- + +- У мові Cypher існують лише однорядкові коментарі, що позначаються двійним слешем : // Коментар +- Можна виконати скрипт Cypher, збережений у файлі **.cql** прямо в Neo4j (прямо як імпорт). Проте, не можна мати мати кілька виразів в цьому файлі (розділених **;**). +- Використовуйте командний рядок Neo4j для написання запитів Cypher, це легко і швидко. +- Cypher планує бути стандартною мовою запитів для всіх графових баз даних (більш відома як **OpenCypher**). diff --git a/uk-ua/go-ua.html.markdown b/uk-ua/go-ua.html.markdown new file mode 100644 index 00000000..6f294b1f --- /dev/null +++ b/uk-ua/go-ua.html.markdown @@ -0,0 +1,449 @@ +--- +name: Go +category: language +language: Go +filename: learngo-ua.go +contributors: + - ["Sonia Keys", "https://github.com/soniakeys"] + - ["Christopher Bess", "https://github.com/cbess"] + - ["Jesse Johnson", "https://github.com/holocronweaver"] + - ["Quint Guvernator", "https://github.com/qguv"] + - ["Jose Donizetti", "https://github.com/josedonizetti"] + - ["Alexej Friesen", "https://github.com/heyalexej"] + - ["Clayton Walker", "https://github.com/cwalk"] + - ["Leonid Shevtsov", "https://github.com/leonid-shevtsov"] +translators: + - ["AstiaSun", "https://github.com/AstiaSun"] +lang: uk-ua +--- + +Go був створений для того, щоб виконати задачу. Це не останній тренд в теорії мов програмування, а спосіб вирішення реальних проблем. + +Він увібрав принципи з імперативних мов зі статичною типізацією. +Go швидко компілюється та виконується, а його багатопоточність легка для +вивчення, оскільки багатоядерні CPU стали буденністю. Ця мова програмування успішно використовується у кодах великих продуктів (~100 мільйонів в Google, Inc.) + +Go має чудову стандартну бібліотеку та чимале ком'юніті. + +```go +// Однорядковий коментар +/* Багато- + рядковий коментар */ + +// Кожен файл вихідного коду має починатись із ключового слова package. +// main - це спеціальна назва, що оголошує виконуваний код, а не бібліотеку. +package main + +// import оголошує бібліотеки, що використовуються в даному файлі. +import ( + "fmt" // Пакет стандартної бібліотеки Go. + "io/ioutil" // Цей пакет реалізує деякі I/O функції утиліт. + m "math" // Бібліотека математичних операцій з локальним псевдонімом m. + "net/http" // Так, веб сервер! + "os" // Функції операційної системи, такі як робота з файловою системою. + "strconv" // Перетворення текстових змінних. +) + +// Оголошення функції. +// Функція main - особлива. Це вхідна точка для виконуваних програм. +// Ви можете любити це, або ж ненавидіти, але Go використовує фігурні дужки. +func main() { + // Println виводить рядок в stdout. + // Ця функція входить у пакет fmt. + fmt.Println("Hello world!") + + // Викликати іншу функцію з цього файлу. + beyondHello() +} + +// Аргументи функцій описуються у круглих дужках. +// Навіть якщо ніякі аргументи не передаються, пусті круглі дужки - обов`язкові. +func beyondHello() { + var x int // Оголошення змінної. Перед використанням змінні обов'язково мають бути оголошені. + x = 3 // Присвоєння значення. + // "Короткі" оголошення використовують := щоб окреслити тип, оголосити та присвоїти значення. + y := 4 + sum, prod := learnMultiple(x, y) // Функція повертає два значення. + fmt.Println("sum:", sum, "prod:", prod) // Просто вивід. + learnTypes() // < y хвилин, потрібно вивчити більше! +} + +/* <- багаторядковий коментар +Функції можуть мати параметри та повертати довільну кількість значень. +В цьому прикладі `x`, `y` - це аргументи, а `sum`, `prod` - це змінні, що повертаються. +Зверніть увагу, що `x` та `sum` мають тип `int`. +*/ +func learnMultiple(x, y int) (sum, prod int) { + return x + y, x * y // Повернути два значення. +} + +// Кілька вбудованих типів та літералів. +func learnTypes() { + // Короткі оголошення зазвичай виконують все, що необхідно. + str := "Вчи Go!" // рядок (string). + + s2 := `"Необроблений" текст +може містити переноси рядків.` // Також має тип рядок. + + // Не ASCII символи. Go використовує UTF-8. + g := 'Σ' // руничний тип, псевдонім для int32, містить позицію юнікод кода. + + f := 3.14195 // float64, IEEE-754 64-бітне число з плаваючою крапкою. + c := 3 + 4i // complex128, комплексні числа, що являють собою два float64. + + // Синтаксис ініціалізації з var. + var u uint = 7 // Беззнаковий цілочисельний тип, проте розмір залежить від імплементації, так само як і int. + var pi float32 = 22. / 7 + + // Синтаксис перетворення типів з коротким оголошенням. + n := byte('\n') // Байт - це переіменований uint8. + + // Розмір масива фіксований протягом часу виконання. + var a4 [4]int // Масив з 4 чисел, всі проініціалізовані 0. + a5 := [...]int{3, 1, 5, 10, 100} // Масив проініціалізованих чисел з фіксованим розміром у + // п'ять елементів, що мають значення 3, 1, 5, 10, та 100. + + // Зрізи мають динамічний розмір. Переваги є і у масивів, й у зрізів, проте + // останні використовуються частіше. + s3 := []int{4, 5, 9} // Порівняйте з a5. Тут немає трьокрапки. + s4 := make([]int, 4) // Виділяє пам'ять для зрізу з 4 чисел, проініціалізованих 0. + var d2 [][]float64 // Декларація, нічого не виділяється. + bs := []byte("a slice") // Синтаксис переведення у інший тип. + + // Оскільки зрізи динамічні, до них можна додавати елементи за необхідністю. + // Для цієї операції використовується вбудована функція append(). + // Перший аргумент - це зріз, до якого додається елемент. Зазвичай + // змінна масиву оновлюється на місці, як у прикладі нижче. + s := []int{1, 2, 3} // В результаті отримуємо зріз із 3 чисел. + s = append(s, 4, 5, 6) // додаємо 3 елементи. Зріз тепер довжини 6. + fmt.Println(s) // Оновлений зріз тепер має значення [1 2 3 4 5 6] + + // Щоб об'єднати два зрізи, замість того, щоб проходитись по всім елементам, + // можна передати посилання на зріз із трьокрапкою, як у прикладі нижче. Таким чином, + // зріз розпакується і його елементи додадуться до зріза s. + s = append(s, []int{7, 8, 9}...) + fmt.Println(s) // Оновлений зріз тепер дорівнює [1 2 3 4 5 6 7 8 9] + + p, q := learnMemory() // Оголошує змінні p, q, що є вказівниками на числа. + fmt.Println(*p, *q) // * іде попереду вказівника. Таким чином, виводяться числа. + + // Асоціативний масив (map) - це динамічно розширюваний тип даних, як хеш + // або словник в інших мовах програмування + m := map[string]int{"three": 3, "four": 4} + m["one"] = 1 + + // В Go змінні, які не використовуються, вважаються помилкою. + // Нижнє підкреслення дозволяє "використати" змінну, але проігнорувати значення. + _, _, _, _, _, _, _, _, _, _ = str, s2, g, f, u, pi, n, a5, s4, bs + // Зазвичай це використовується, щоб проігнорувати значення, що повертає функція. + // Наприклад, в скрипті нашвидкоруч можна проігнорувати помилку, яку повертає + // функція os.Create, вважаючи, що файл буде створений за будь-яких умов. + file, _ := os.Create("output.txt") + fmt.Fprint(file, "Приклад, як відбувається запис у файл.") + file.Close() + + // Вивід значень змінних. + fmt.Println(s, c, a4, s3, d2, m) + + learnFlowControl() // Рухаємось далі. +} + +// Навідміну від більшості інших мов програмування, функції в Go підтримують +// іменоване значення, що повертається. +// Змінні, значення яких повертається функцією, вказуються із зазначенням типу при +// оголошенні функції. Таким чином, можна з легкістю повернути їхні значення в різних +// точках коду, не перелічуючи їх після ключового слова return. +func learnNamedReturns(x, y int) (z int) { + z = x * y + return // z не потрібно вказувати, при оголошенні описано змінну для повернення. +} + +// Go використовує сміттєзбірник. В ньому використовуються вказівники, проте немає +// операцій з вказівниками. Можлива помилка при використовуванні вказівника nil, але не +// при збільшенні значення вказівника (перехід по адресам пам'яті). +func learnMemory() (p, q *int) { + // Іменовані змінні, що повертаються, p та q, мають тип вказівника на чисельне значення. + p = new(int) // Вбудована функція виділяє нову пам'ять. + // Виділена адреса пам'яті чисельного типу int ініціалізовується 0, p більше не nil. + s := make([]int, 20) // Виділити пам'ять для 20 чисел у вигляді суцільного блоку в пам'яті. + s[3] = 7 // Присвоїти значення одному з них. + r := -2 // Оголосити нову локальну змінну. + return &s[3], &r // Оператор & повертає адресу в пам'яті об'єкта. +} + +func expensiveComputation() float64 { + return m.Exp(10) +} + +func learnFlowControl() { + // if твердження вимагає фігурні дужки, але не вимагає округлих. + if true { + fmt.Println("Кажу ж") + } + // Форматування стандартизовано командою командного рядка "go fmt". + if false { + // Pout. + } else { + // Gloat. + } + // Використання перемикача (switch) замість ланцюга if-тверджень. + x := 42.0 + switch x { + case 0: + case 1: + case 42: + // Кейси не "провалюються". Натомість, є ключове слово `fallthrough`: + // https://github.com/golang/go/wiki/Switch#fall-through (англ) + case 43: + // Недоступний. + default: + // Кейс за замовчуванням не обов'язковий. + } + // Як і if, формат оголошення циклу for не вимагає круглих дужок: + // Змінні, оголошені всередині if та for - належать цій області видимості. + for x := 0; x < 3; x++ { // ++ - це твердження. + fmt.Println("iteration", x) + } + // Тут x == 42. + + // For - це єдиний цикл в Go, проте він має кілька різних форм. + for { // Ініціалізація циклу. + break // Упс, помилково зайшли. + continue // Недоступне твердження. + } + + // Можна використовувати діапазони, зрізи, рядки, асоціативні масиви, або ж + // канал для ітерації в циклі. Діапазон (range) повертає один (канал) або два + // значення (масив, зріз, рядок та асоціативний масив). + for key, value := range map[string]int{"one": 1, "two": 2, "three": 3} { + // для кожної пари в асоціативному масиві, надрукувати ключ та значення + fmt.Printf("key=%s, value=%d\n", key, value) + } + // якщо потрібне тільки значення, можна застосувати нижнє підкреслення як ключ + for _, name := range []string{"Bob", "Bill", "Joe"} { + fmt.Printf("Hello, %s\n", name) + } + + // так само, як і з циклом for, оператор := в розгалуженні означає оголосити + // локальну змінну в області видимості if та присвоїти значення. Далі + // значення змінної проходить перевірку y > x. + if y := expensiveComputation(); y > x { + x = y + } + // Літерали функцій - це замикання + xBig := func() bool { + return x > 10000 // Посилання на x, що був оголошений раніше, перед switch. + } + x = 99999 + fmt.Println("xBig:", xBig()) // true + x = 1.3e3 // Тобто, тепер x == 1300 + fmt.Println("xBig:", xBig()) // false тепер. + + // Функція може бути оголошена та викликана в одному рядку, поводячи себе + // як аргумент функції, але за наступних умов: + // 1) літерал функції негайно викликається за допомогою () + // 2) тип значення, що повертається, точно відповідає очікуваному типу аргументу + fmt.Println("Add + double two numbers: ", + func(a, b int) int { + return (a + b) * 2 + }(10, 2)) // Викликаємо з аргументами 10 та 2 + // => Додати + подвоїти два числа: 24 + + // Коли вам це знадобиться, ви полюбите це + goto love +love: + + learnFunctionFactory() // функція, що повертає функцію - це весело(3)(3) + learnDefer() // Швидкий обхід до важливого ключового слова. + learnInterfaces() // Тут на вас чекає крута штука! +} + +func learnFunctionFactory() { + // Два наступних твердження роблять однакові дії, але другий приклад частіше + // застосовується + fmt.Println(sentenceFactory("summer")("A beautiful", "day!")) + + d := sentenceFactory("summer") + fmt.Println(d("A beautiful", "day!")) + fmt.Println(d("A lazy", "afternoon!")) +} + +// Декоратори звична річ для багатьох мов програмування. В Go їх можна реалізувати +// за допомогою літералів функцій, що приймають аргументи. +func sentenceFactory(mystring string) func(before, after string) string { + return func(before, after string) string { + return fmt.Sprintf("%s %s %s", before, mystring, after) // новий рядок + } +} + +func learnDefer() (ok bool) { + // твердження defer змушує функцію посилатись на список. Список + // збережених викликів виконується ПІСЛЯ того, як оточуюча функція закінчує + // виконання. + defer fmt.Println("відкладені твердження виконуються у зворотньому порядку (LIFO).") + defer fmt.Println("\nЦей рядок надрукується першим, тому що") + // Відкладення зазвичай використовується для того, щоб закрити файл. Таким чином, + // функція, що закриває файл, залишається близькою до функції, що відкриває файл. + return true +} + +// Оголошує Stringer як тип інтерфейсу з одним методом, String. +type Stringer interface { + String() string +} + +// Оголошує pair як структуру з двома полями, цілими числами x та y. +type pair struct { + x, y int +} + +// Оголошує метод для типу pair. pair тепер реалізує Stringer, оскільки pair оголосив +// всі методи в цьому інтерфейсі. +func (p pair) String() string { // p тепер називається "приймачем" + // Sprintf - ще одна функція з пакету fmt. + // Крапка використовується, щоб звернутись до полів об'єкту p. + return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func learnInterfaces() { + // Синтаксис з використанням фігурних дужок називається "літералом структури". + // Він застосовується до ініціалізованої структури. Оператор := оголошує + // та ініціалізує p цією структурою. + p := pair{3, 4} + fmt.Println(p.String()) // Викликає метод String об'єкта p типу pair. + var i Stringer // Оголошує і інтерфейсного типу Stringer. + i = p // Допустиме, оскільки pair реалізує Stringer + // Викликає метод String об'єкта і, що має тип Stringer. Виводить те ж саме, що й + // аналогічний метод вище. + fmt.Println(i.String()) + + // Функції з бібліотеки fmt викликають метод String, щоб запросити у об'єкта + // своє представлення, яке можна надрукувати. + fmt.Println(p) // Виводить те ж саме, що й раніше. + fmt.Println(i) // Виводить те ж саме, що й раніше. + + learnVariadicParams("great", "learning", "here!") +} + +// Кількість аргументів функції може бути змінною. +func learnVariadicParams(myStrings ...interface{}) { + // Пройтись по значенням всіх аргументів. + // _ - це ігнорування порядкового номеру аргумента в масиві. + for _, param := range myStrings { + fmt.Println("param:", param) + } + + // Передати значення аргументів як параметр змінної величини. + fmt.Println("params:", fmt.Sprintln(myStrings...)) + + learnErrorHandling() +} + +func learnErrorHandling() { + // Ідіома ", ok"використовується, щоб перевірити виконання команди без помилок. + m := map[int]string{3: "three", 4: "four"} + if x, ok := m[1]; !ok { // ok буде мати значення false, тому що 1 не знаходиться + // в асоціативному масиві. + fmt.Println("немає таких") + } else { + fmt.Print(x) // x буде мати значення 1, якщо 1 знаходиться в m. + } + // Значення помилки повідомляє не тільки, що все добре, але й може розповісти + // більше про проблему. + if _, err := strconv.Atoi("non-int"); err != nil { // _ ігнорує значення + // виводить помилку 'strconv.ParseInt: parsing "non-int": invalid syntax' + fmt.Println(err) + } + // Ми розглянемо інтерфейси дещо пізніше. А поки, розглянемо багатопоточність. + learnConcurrency() +} + +// Канал с - це потокозохищений об'єкт для спілкування між потоками. +func inc(i int, c chan int) { + c <- i + 1 // Оператор <- виконує операцію "надіслати",якщо змінна каналу + // знаходиться зліва від нього. +} + +// inc виконує збільшення значення на 1. Ми використаємо його, щоб збільшувати +// числа рівночасно. +func learnConcurrency() { + // вже знайома функція make, яка раніше використовувалась для виділення пам'яті, + // тут використовується для створення каналу. Make виділяє пам'ять та ініціалізує + // зрізи, асоційовані масиви та канали. Новостворений канал буде передавати + // цілочисельні значення. + c := make(chan int) + // Запустити три одночасні ґорутини. Числа будуть збільшуватись рівночасно, імовірно + // паралельно якщо пристрій здатний до цього та правильно сконфігурований. + // Всі три ґорутини надсилають значення в один канал. + go inc(0, c) // Твердження go запускає нову ґорутину. + go inc(10, c) + go inc(-805, c) + // Читаємо три результати з каналу та друкуємо їх. + // Порядок результатів - невідомий! + fmt.Println(<-c, <-c, <-c) // якщо канал знаходиться справа від оператора <-, + // він виконує функцію "приймача". + + cs := make(chan string) // Ще один канал, який примає рядки. + ccs := make(chan chan string) // Канал каналів рядків. + go func() { c <- 84 }() // Запустимо нову ґорутину, щоб надіслати значення в канал с. + go func() { cs <- "wordy" }() // Надсилаємо "wordy" в канал cs. + // Ключове слово select має синтаксис, подібний до switch, проте кожен кейс + // включає в себе операцію з каналом. Він обирає довільний кейс з наявних, які готові + // комунікувати (передавати дані). + select { + case i := <-c: // Отримане значення може бути присвоєно змінній, + fmt.Printf("it's a %T", i) + case <-cs: // або значення може бути проігнороване. + fmt.Println("it's a string") + case <-ccs: // Пустий канал, не готовий комунікувати. + fmt.Println("Не відбудеться.") + } + // На цьому етапі, значення було прочитане або з с або з cs. Одна з двох + // ґорутин завершилась, але інша все ще заблокована. + + learnWebProgramming() // Go вміє й у веб. Так, ти хочеш зробити це. +} + +// Лиш одна функція з пакету http запускає веб сервер. +func learnWebProgramming() { + + // перший аргумент ListenAndServe - це TCP адреса, який сервер буде слухати. + // Другий аргумент - це інтерфейс, а точніше http.Handler. + go func() { + err := http.ListenAndServe(":8080", pair{}) + fmt.Println(err) // не ігноруйте помилки + }() + + requestServer() +} + +// pair матиме тип http.Handler, якщо реалізувати один його метод, ServeHTTP. +func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Відповідати на запити можна методом, що належить http.ResponseWriter. + w.Write([]byte("Ти вивчив Go за Y хвилин!")) +} + +func requestServer() { + resp, err := http.Get("http://localhost:8080") + fmt.Println(err) + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + fmt.Printf("\nWebserver said: `%s`", string(body)) +} +``` + +## Подальше вивчення + +Основним джерелом всієї інформації про Go залишається [офіційна веб-сторінка](https://go.dev/). Там можна знайти уроки, інтерактивно пограти та багато про що почитати. +Окрім туру, у [документації](https://go.dev/doc/) міститься інформація як писати чистий та ефективний код на Go, документація пакетів та окремих команд, а також історія релізів. + +Надзвичайно рекомендується ознайомитись із визначенням мови. Вона легко читається та на диво коротка (в порівнянні з іншими сучасними мовами). + +Можна погратись з кодом вище на [Go playground](https://go.dev/play/p/tnWMjr16Mm). Спробуй змінити його та запустити із свого браузера. Поміть, що можна використовувати [https://go.dev/play/](https://go.dev/play/) як [REPL](https://uk.wikipedia.org/wiki/REPL) до тестів та коду в твоєму браузері, без встановлення Go. + +В списку для прочитання новачкам в Go - [вихідний код стандартної бібліотеки](https://go.dev/src/). Код всеосяжно задокоментований, тому є найкращим прикладом з боку зручного для прочитання та швидкості розуміння коду на цій мові програмування. Приведений стиль та ідіоми Go. +Крім того, можна просто натиснути на назву функції в [документації](https://go.dev/pkg/), щоб перейти до її реалізації. + +Іншим прекрасним посиланням для вивчення Go є [Go by example](https://gobyexample.com/). + +Go Mobile додає підтримку мобільних платформ (Android та iOS). Можна написати нативний код на Go для мобільних застосунків або написати бібліотеку, що міститиме прив'язки (bindings) з пакету Go, які можуть бути викликані з Java (Android) та Objective-C (iOS). Деталі можна дізнатись на [веб-сторінці Go Mobile](https://github.com/golang/go/wiki/Mobile). diff --git a/uk-ua/javascript-ua.html.markdown b/uk-ua/javascript-ua.html.markdown index 6a64a623..2f17f586 100644 --- a/uk-ua/javascript-ua.html.markdown +++ b/uk-ua/javascript-ua.html.markdown @@ -1,7 +1,7 @@ --- language: javascript contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] - ["clearsense", "https://github.com/clearsense"] filename: javascript-uk.js diff --git a/uk-ua/kotlin-ua.html.markdown b/uk-ua/kotlin-ua.html.markdown new file mode 100644 index 00000000..5e79cc48 --- /dev/null +++ b/uk-ua/kotlin-ua.html.markdown @@ -0,0 +1,464 @@ +--- +language: kotlin +filename: LearnKotlin-uk.kt +lang: uk-ua +contributors: + - ["S Webber", "https://github.com/s-webber"] +translators: + - ["AstiaSun", "https://github.com/AstiaSun"] +--- + +Kotlin - це мова програмування зі статичною типізацією для JVM, Android та браузера. +Вона має 100% сумісність із Java. + +[Детальніше](https://kotlinlang.org/) + +```kotlin +// Однорядкові коментарі починаються з // +/* +Такий вигляд мають багаторядкові коментарі +*/ + +// Ключове слово package працює так само, як і в Java. +package com.learnxinyminutes.kotlin + +/* +Точкою входу для програм на Kotlin є функція під назвою main. +Вона приймає масив із аргументів, що були передані через командний рядок. +Починаючи з Kotlin 1.3, функція main може бути оголошена без параметрів взагалі. +*/ +fun main(args: Array<String>) { + /* + Оголошення змінних відбувається за допомогою ключових слів var або val. + Відмінність між ними полягає в тому, що значення змінних, оголошених через + val, не можна змінювати. Водночас, змінній "var" можна переприсвоїти нове + значення в подальшому. + */ + val fooVal = 10 // більше ми не можемо змінити значення fooVal на інше + var fooVar = 10 + fooVar = 20 // fooVar може змінювати значення + + /* + В більшості випадків Kotlin може визначати, якого типу змінна, тому не + потрібно щоразу точно вказувати її тип. + Тип змінної вказується наступним чином: + */ + val foo: Int = 7 + + /* + Рядки мають аналогічне з Java представлення. Спеціальні символи + позначаються за допомогою зворотнього слеша. + */ + val fooString = "My String Is Here!" + val barString = "Printing on a new line?\nNo Problem!" + val bazString = "Do you want to add a tab?\tNo Problem!" + println(fooString) + println(barString) + println(bazString) + + /* + Необроблений рядок розмежовується за допомогою потрійних лапок ("""). + Необроблені рядки можуть містити переніс рядка (не спеціальний символ \n) та + будь-які інші символи. + */ + val fooRawString = """ +fun helloWorld(val name : String) { + println("Hello, world!") +} +""" + println(fooRawString) + + /* + Рядки можуть містити шаблонні вирази. + Шаблонний вираз починається із символа доллара "$". + */ + val fooTemplateString = "$fooString has ${fooString.length} characters" + println(fooTemplateString) // => My String Is Here! has 18 characters + + /* + Щоб змінна могла мати значення null, потрібно це додатково вказати. + Для цього після оголошеного типу змінної додається спеціальний символ "?". + Отримати значення такої змінної можна використавши оператор "?.". + Оператор "?:" застосовується, щоб оголосити альтернативне значення змінної + у випадку, якщо вона буде рівна null. + */ + var fooNullable: String? = "abc" + println(fooNullable?.length) // => 3 + println(fooNullable?.length ?: -1) // => 3 + fooNullable = null + println(fooNullable?.length) // => null + println(fooNullable?.length ?: -1) // => -1 + + /* + Функції оголошуються з використанням ключового слова fun. + Аргументи функції перелічуються у круглих дужках після назви функції. + Аргументи можуть мати значення за замовчуванням. Тип значення, що повертатиметься + функцією, вказується після оголошення аргументів за необхідністю. + */ + fun hello(name: String = "world"): String { + return "Hello, $name!" + } + println(hello("foo")) // => Hello, foo! + println(hello(name = "bar")) // => Hello, bar! + println(hello()) // => Hello, world! + + /* + Аргументи функції можуть бути помічені ключовим словом vararg. Це дозволяє + приймати довільну кількість аргументів функції зазначеного типу. + */ + fun varargExample(vararg names: Int) { + println("Argument has ${names.size} elements") + } + varargExample() // => Argument has 0 elements + varargExample(1) // => Argument has 1 elements + varargExample(1, 2, 3) // => Argument has 3 elements + + /* + Коли функція складається з одного виразу, фігурні дужки не є обов'язковими. + Тіло функції вказується після оператора "=". + */ + fun odd(x: Int): Boolean = x % 2 == 1 + println(odd(6)) // => false + println(odd(7)) // => true + + // Якщо тип значення, що повертається функцією, може бути однозначно визначено, + // його непотрібно вказувати. + fun even(x: Int) = x % 2 == 0 + println(even(6)) // => true + println(even(7)) // => false + + // Функції можуть приймати інші функції як аргументи, а також повертати інші функції. + fun not(f: (Int) -> Boolean): (Int) -> Boolean { + return {n -> !f.invoke(n)} + } + // Іменовані функції можуть бути вказані як аргументи за допомогою оператора "::". + val notOdd = not(::odd) + val notEven = not(::even) + // Лямбда-вирази також можуть бути аргументами функції. + val notZero = not {n -> n == 0} + /* + Якщо лямбда-вираз приймає лише один параметр, його оголошення може бути пропущене + (разом із ->). Всередині виразу до цього параметра можна звернутись через + змінну "it". + */ + val notPositive = not {it > 0} + for (i in 0..4) { + println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}") + } + + // Ключове слово class використовується для оголошення класів. + class ExampleClass(val x: Int) { + fun memberFunction(y: Int): Int { + return x + y + } + + infix fun infixMemberFunction(y: Int): Int { + return x * y + } + } + /* + Щоб створити новий об'єкт, потрібно викликати конструктор класу. + Зазначте, що в Kotlin немає ключового слова new. + */ + val fooExampleClass = ExampleClass(7) + // Методи класу викликаються через крапку. + println(fooExampleClass.memberFunction(4)) // => 11 + /* + Якщо функція була позначена ключовим словом infix, тоді її можна викликати через + інфіксну нотацію. + */ + println(fooExampleClass infixMemberFunction 4) // => 28 + + /* + Класи даних - це лаконічний спосіб створювати класи, що містимуть тільки дані. + Методи "hashCode"/"equals" та "toString" автоматично генеруються. + */ + data class DataClassExample (val x: Int, val y: Int, val z: Int) + val fooData = DataClassExample(1, 2, 4) + println(fooData) // => DataClassExample(x=1, y=2, z=4) + + // Класи даних також мають функцію "copy". + val fooCopy = fooData.copy(y = 100) + println(fooCopy) // => DataClassExample(x=1, y=100, z=4) + + // Об'єкти можуть бути деструктурувані кількома способами. + val (a, b, c) = fooCopy + println("$a $b $c") // => 1 100 4 + + // деструктурування у циклі for + for ((a, b, c) in listOf(fooData)) { + println("$a $b $c") // => 1 100 4 + } + + val mapData = mapOf("a" to 1, "b" to 2) + // Map.Entry також деструктурувуються + for ((key, value) in mapData) { + println("$key -> $value") + } + + // Функція із "with" працює майже так само як це ж твердження у JavaScript. + data class MutableDataClassExample (var x: Int, var y: Int, var z: Int) + val fooMutableData = MutableDataClassExample(7, 4, 9) + with (fooMutableData) { + x -= 2 + y += 2 + z-- + } + println(fooMutableData) // => MutableDataClassExample(x=5, y=6, z=8) + + /* + Список можна створити використовуючи функцію listOf. + Список буде незмінним, тобто елементи не можна буде додавати або видаляти. + */ + val fooList = listOf("a", "b", "c") + println(fooList.size) // => 3 + println(fooList.first()) // => a + println(fooList.last()) // => c + // доступ до елементів здійснюється через їхні порядковий номер. + println(fooList[1]) // => b + + // Змінні списки можна створити використовуючи функцію mutableListOf. + val fooMutableList = mutableListOf("a", "b", "c") + fooMutableList.add("d") + println(fooMutableList.last()) // => d + println(fooMutableList.size) // => 4 + + // Функція setOf створює об'єкт типу множина. + val fooSet = setOf("a", "b", "c") + println(fooSet.contains("a")) // => true + println(fooSet.contains("z")) // => false + + // mapOf створює асоціативний масив. + val fooMap = mapOf("a" to 8, "b" to 7, "c" to 9) + // Доступ до значень в асоціативних масивах здійснюється через їхні ключі. + println(fooMap["a"]) // => 8 + + /* + Послідовності представлені як колекції лінивих обчислень. Функція generateSequence + створює послідовність. + */ + val fooSequence = generateSequence(1, { it + 1 }) + val x = fooSequence.take(10).toList() + println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + // Приклад використання послідовностей, генерація чисел Фібоначчі: + fun fibonacciSequence(): Sequence<Long> { + var a = 0L + var b = 1L + + fun next(): Long { + val result = a + b + a = b + b = result + return a + } + + return generateSequence(::next) + } + val y = fibonacciSequence().take(10).toList() + println(y) // => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + + // Kotlin має функції вищого порядку для роботи з колекціями. + val z = (1..9).map {it * 3} + .filter {it < 20} + .groupBy {it % 2 == 0} + .mapKeys {if (it.key) "even" else "odd"} + println(z) // => {odd=[3, 9, 15], even=[6, 12, 18]} + + // Цикл for може використовуватись з будь-чим, що має ітератор. + for (c in "hello") { + println(c) + } + + // Принцип роботи циклів "while" не відрізняється від інших мов програмування. + var ctr = 0 + while (ctr < 5) { + println(ctr) + ctr++ + } + do { + println(ctr) + ctr++ + } while (ctr < 10) + + /* + if може бути використаний як вираз, що повертає значення. Тому тернарний + оператор ?: не потрібний в Kotlin. + */ + val num = 5 + val message = if (num % 2 == 0) "even" else "odd" + println("$num is $message") // => 5 is odd + + // "when" використовується як альтернатива ланцюгам "if-else if". + val i = 10 + when { + i < 7 -> println("first block") + fooString.startsWith("hello") -> println("second block") + else -> println("else block") + } + + // "when" може приймати аргумент. + when (i) { + 0, 21 -> println("0 or 21") + in 1..20 -> println("in the range 1 to 20") + else -> println("none of the above") + } + + // "when" також може використовуватись як функція, що повертає значення. + var result = when (i) { + 0, 21 -> "0 or 21" + in 1..20 -> "in the range 1 to 20" + else -> "none of the above" + } + println(result) + + /* + Тип об'єкта можна перевірити використавши оператор is. Якщо перевірка проходить + успішно, тоді можна використовувати об'єкт як данний тип не приводячи до нього + додатково. + */ + fun smartCastExample(x: Any) : Boolean { + if (x is Boolean) { + // x тепер має тип Boolean + return x + } else if (x is Int) { + // x тепер має тип Int + return x > 0 + } else if (x is String) { + // x тепер має тип String + return x.isNotEmpty() + } else { + return false + } + } + println(smartCastExample("Hello, world!")) // => true + println(smartCastExample("")) // => false + println(smartCastExample(5)) // => true + println(smartCastExample(0)) // => false + println(smartCastExample(true)) // => true + + // Smartcast (розумне приведення) також працює з блоком when + fun smartCastWhenExample(x: Any) = when (x) { + is Boolean -> x + is Int -> x > 0 + is String -> x.isNotEmpty() + else -> false + } + + /* + Розширення - це ще один спосіб розширити функціонал класу. + Подібні методи розширення реалізовані у С#. + */ + fun String.remove(c: Char): String { + return this.filter {it != c} + } + println("Hello, world!".remove('l')) // => Heo, word! +} + +// Класи перелічення також подібні до тих типів, що і в Java. +enum class EnumExample { + A, B, C // Константи перелічення розділені комами. +} +fun printEnum() = println(EnumExample.A) // => A + +// Оскільки кожне перелічення - це об'єкт класу enum, воно може бути +// проініціалізоване наступним чином: +enum class EnumExample(val value: Int) { + A(value = 1), + B(value = 2), + C(value = 3) +} +fun printProperty() = println(EnumExample.A.value) // => 1 + +// Кожне перелічення має властивості, які дозволяють отримати його ім'я +// та порядок (позицію) в класі enum: +fun printName() = println(EnumExample.A.name) // => A +fun printPosition() = println(EnumExample.A.ordinal) // => 0 + +/* +Ключове слово object можна використати для створення об'єкту сінглтону. Об'єкт не +можна інстанціювати, проте на його унікальний екземпляр можна посилатись за іменем. +Подібна можливість є в сінглтон об'єктах у Scala. +*/ +object ObjectExample { + fun hello(): String { + return "hello" + } + + override fun toString(): String { + return "Hello, it's me, ${ObjectExample::class.simpleName}" + } +} + + +fun useSingletonObject() { + println(ObjectExample.hello()) // => hello + // В Kotlin, "Any" - це корінь ієрархії класів, так само, як і "Object" у Java. + val someRef: Any = ObjectExample + println(someRef) // => Hello, it's me, ObjectExample +} + + +/* +Оператор перевірки на те, що об'єкт не рівний null, (!!) перетворює будь-яке значення в ненульовий тип і кидає виняток, якщо значення рівне null. +*/ +var b: String? = "abc" +val l = b!!.length + +// Далі - приклади перевизначення методів класу Any в класі-насліднику +data class Counter(var value: Int) { + // перевизначити Counter += Int + operator fun plusAssign(increment: Int) { + this.value += increment + } + + // перевизначити Counter++ та ++Counter + operator fun inc() = Counter(value + 1) + + // перевизначити Counter + Counter + operator fun plus(other: Counter) = Counter(this.value + other.value) + + // перевизначити Counter * Counter + operator fun times(other: Counter) = Counter(this.value * other.value) + + // перевизначити Counter * Int + operator fun times(value: Int) = Counter(this.value * value) + + // перевизначити Counter in Counter + operator fun contains(other: Counter) = other.value == this.value + + // перевизначити Counter[Int] = Int + operator fun set(index: Int, value: Int) { + this.value = index + value + } + + // перевизначити виклик екземпляру Counter + operator fun invoke() = println("The value of the counter is $value") + +} +// Можна також перевизначити оператори через методи розширення. +// перевизначити -Counter +operator fun Counter.unaryMinus() = Counter(-this.value) + +fun operatorOverloadingDemo() { + var counter1 = Counter(0) + var counter2 = Counter(5) + counter1 += 7 + println(counter1) // => Counter(value=7) + println(counter1 + counter2) // => Counter(value=12) + println(counter1 * counter2) // => Counter(value=35) + println(counter2 * 2) // => Counter(value=10) + println(counter1 in Counter(5)) // => false + println(counter1 in Counter(7)) // => true + counter1[26] = 10 + println(counter1) // => Counter(value=36) + counter1() // => The value of the counter is 36 + println(-counter2) // => Counter(value=-5) +} +``` + +### Подальше вивчення + +* [Уроки Kotlin](https://kotlinlang.org/docs/tutorials/) +* [Спробувати попрацювати з Kotlin в браузері](https://play.kotlinlang.org/) +* [Список корисних посилань](http://kotlin.link/) diff --git a/uk-ua/mips-ua.html.markdown b/uk-ua/mips-ua.html.markdown new file mode 100644 index 00000000..2d42e85d --- /dev/null +++ b/uk-ua/mips-ua.html.markdown @@ -0,0 +1,366 @@ +--- +language: "MIPS Assembly" +filename: MIPS.asm +contributors: + - ["Stanley Lim", "https://github.com/Spiderpig86"] +translators: + - ["AstiaSun", "https://github.com/AstiaSun"] +lang: uk-ua +--- + +Мова ассемблера MIPS (англ. Microprocessor without Interlocked Pipeline Stages) була написана для роботи з мікропроцесорами MIPS, парадигма яких була описана в 1981 році [Джоном Геннессі](https://uk.wikipedia.org/wiki/Джон_Лерой_Геннессі). Ці RISC процесори використовуються у таких вбудованих системах, як маршрутизатори та мережеві шлюзи. + +[Детальніше](https://en.wikipedia.org/wiki/MIPS_architecture) + +```asm +# Коментарі позначені як'#' + +# Всі символи після '#' ігноруються лексичним аналізатором асемблера. + +# Зазвичай програми поділяються на .data та .text частини + +.data # У цьому розділі дані зберігаються у пам'яті, виділеній в RAM, подібно до змінних + # в мовах програмування вищого рівня + + # Змінна оголошується наступним чином: [назва]: .[тип] [значення] + # Наприклад: + hello_world: .asciiz "Hello World\n" # Оголосити текстову змінну + num1: .word 42 # word - це чисельний тип 32-бітного розряду + + arr1: .word 1, 2, 3, 4, 5 # Масив чисел + arr2: .byte 'a', 'b' # Масив буквених символів (розмір кожного - 1 байт) + buffer: .space 60 # Виділити місце в RAM + # (не очищується, тобто не заповнюється 0) + + # Розміри типів даних + _byte: .byte 'a' # 1 байт + _halfword: .half 53 # 2 байти + _word: .word 3 # 4 байти + _float: .float 3.14 # 4 байти + _double: .double 7.0 # 8 байтів + + .align 2 # Вирівнювання пам'яті даних, де число + # показує кількість байтів, вирівнених + # у степені 2. (.align 2 означає + # чисельне (word) вирівнювання оскільки + # 2^2 = 4 байти) + +.text # Розділ, що містить інструкції та + # логіку програми + +.globl _main # Оголошує назву інструкції як + # глобальну, тобто, яка є доступною для + # всіх інших файлів + + _main: # програми MIPS виконують інструкції + # послідовно, тобто першочергово код + # буде виконуватись після цієї позначки + + # Виведемо на екран "hello world" + la $a0, hello_world # Завантажує адресу тексту у пам'яті + li $v0, 4 # Завантажує значення системної + # команди (вказуючи тип функціоналу) + syscall # Виконує зазначену системну команду + # з обраним аргументом ($a0) + + # Регістри (використовуються, щоб тримати дані протягом виконання програми) + # $t0 - $t9 # Тимчасові регістри використовуються + # для проміжних обчислень всередині + # підпрограм (не зберігаються між + # викликами функцій) + + # $s0 - $s7 # Збережені регістри, у яких значення + # зберігаються між викликами підпрограм. + # Зазвичай зберігаються у стеку. + + # $a0 - $a3 # Регістри для передачі аргументів для + # підпрограм + # $v0 - $v1 # Регістри для значень, що повертаються + # від викликаної функції + + # Типи інструкції завантаження / збереження + la $t0, label # Скопіювати адресу в пам'яті, де + # зберігається значення змінної label + # в регістр $t0 + lw $t0, label # Скопіювати чисельне значення з пам'яті + lw $t1, 4($s0) # Скопіювати чисельне значення з адреси + # пам'яті регістра зі зміщенням в + # 4 байти (адреса + 4) + lb $t2, label # Скопіювати буквений символ в частину + # нижчого порядку регістра $t2 + lb $t2, 0($s0) # Скопіювати буквений символ з адреси + # в $s0 із зсувом 0 + # Подібне використання і 'lh' для halfwords + + sw $t0, label # Зберегти чисельне значення в адресу в + # пам'яті, що відповідає змінній label + sw $t0, 8($s0) # Зберегти чисельне значення в адресу, + # що зазначена у $s0, та зі зсувом у 8 байтів + # Така ж ідея використання 'sb' та 'sh' для буквених символів та halfwords. + # 'sa' не існує + + +### Математичні операції ### + _math: + # Пам'ятаємо, що попередньо потрібно завантажити дані в пам'ять + lw $t0, num # Із розділа з даними + li $t0, 5 # Або безпосередньо з константи + li $t1, 6 + add $t2, $t0, $t1 # $t2 = $t0 + $t1 + sub $t2, $t0, $t1 # $t2 = $t0 - $t1 + mul $t2, $t0, $t1 # $t2 = $t0 * $t1 + div $t2, $t0, $t1 # $t2 = $t0 / $t1 (Може не підтримуватись + # деякими версіями MARS) + div $t0, $t1 # Виконує $t0 / $t1. Отримати частку можна + # за допомогою команди 'mflo', остаток - 'mfhi' + + # Бітовий зсув + sll $t0, $t0, 2 # Побітовий зсув вліво на 2. Біти вищого порядку + # не зберігаються, нищого - заповнюються 0 + sllv $t0, $t1, $t2 # Зсув вліво зі змінною кількістю у + # регістрі + srl $t0, $t0, 5 # Побітовий зсув вправо на 5 (не зберігає + # біти, біти зліва заповнюються 0) + srlv $t0, $t1, $t2 # Зсув вправо зі змінною кількістю у + # регістрі + sra $t0, $t0, 7 # Побітовий арифметичний зсув вправо + # (зберігає біти) + srav $t0, $t1, $t2 # Зсув вправо зі змінною кількістю у + # регістрі зі збереження значеннь бітів + + # Побітові операції + and $t0, $t1, $t2 # Побітове І (AND) + andi $t0, $t1, 0xFFF # Побітове І з безпосереднім значенням + or $t0, $t1, $t2 # Побітове АБО (OR) + ori $t0, $t1, 0xFFF # Побітове АБО з безпосереднім значенням + xor $t0, $t1, $t2 # Побітова виключна диз'юнкція (XOR) + xori $t0, $t1, 0xFFF # Побітове XOR з безпосереднім значенням + nor $t0, $t1, $t2 # Побітова стрілка Пірса (NOR) + +## Розгалуження ## + _branching: + # В основному інструкції розгалуження мають наступну форму: + # <instr> <reg1> <reg2> <label> + # де label - це назва змінної, в яку ми хочемо перейти, якщо зазначене твердження + # правдиве + + beq $t0, $t1, reg_eq # Перейдемо у розгалуження reg_eq + # якщо $t0 == $t1, інакше - + # виконати наступний рядок + bne $t0, $t1, reg_neq # Розгалужується, якщо $t0 != $t1 + b branch_target # Розгалуження без умови завжди виконується + beqz $t0, req_eq_zero # Розгалужується, якщо $t0 == 0 + bnez $t0, req_neq_zero # Розгалужується, якщо $t0 != 0 + bgt $t0, $t1, t0_gt_t1 # Розгалужується, якщо $t0 > $t1 + bge $t0, $t1, t0_gte_t1 # Розгалужується, якщо $t0 >= $t1 + bgtz $t0, t0_gt0 # Розгалужується, якщо $t0 > 0 + blt $t0, $t1, t0_gt_t1 # Розгалужується, якщо $t0 < $t1 + ble $t0, $t1, t0_gte_t1 # Розгалужується, якщо $t0 <= $t1 + bltz $t0, t0_lt0 # Розгалужується, якщо $t0 < 0 + slt $s0, $t0, $t1 # Інструкція, що посилає сигнал коли + # $t0 < $t1, результат зберігається в $s0 + # (1 - правдиве твердження) + + # Просте твердження якщо (if) + # if (i == j) + # f = g + h; + # f = f - i; + + # Нехай $s0 = f, $s1 = g, $s2 = h, $s3 = i, $s4 = j + bne $s3, $s4, L1 # if (i !=j) + add $s0, $s1, $s2 # f = g + h + + L1: + sub $s0, $s0, $s3 # f = f - i + + # Нижче наведений приклад знаходження максимального значення з 3 чисел + # Пряма трансляція в Java з логіки MIPS: + # if (a > b) + # if (a > c) + # max = a; + # else + # max = c; + # else + # max = b; + # else + # max = c; + + # Нехай $s0 = a, $s1 = b, $s2 = c, $v0 = повернути регістр + ble $s0, $s1, a_LTE_b # якщо (a <= b) розгалуження(a_LTE_b) + ble $s0, $s2, max_C # якщо (a > b && a <=c) розгалуження(max_C) + move $v0, $s0 # інакше [a > b && a > c] max = a + j done # Перейти в кінець програми + + a_LTE_b: # Мітка розгалуження, коли a <= b + ble $s1, $s2, max_C # якщо (a <= b && b <= c) розгалуження(max_C) + move $v0, $s1 # якщо (a <= b && b > c) max = b + j done # Перейти в кінець програми + + max_C: + move $v0, $s2 # max = c + + done: # Кінець програми + +## Цикли ## + _loops: + # Цикл складається з умови виходу та з інструкції переходу після його завершення + li $t0, 0 + while: + bgt $t0, 10, end_while # Коли $t0 менше 10, продовжувати ітерації + addi $t0, $t0, 1 # Збільшити значення + j while # Перейти на початок циклу + end_while: + + # Транспонування 2D матриці + # Припустимо, що $a0 зберігає адресу цілочисельної матриці розмірністю 3 x 3 + li $t0, 0 # Лічильник для i + li $t1, 0 # Лічильник для j + matrix_row: + bgt $t0, 3, matrix_row_end + + matrix_col: + bgt $t1, 3, matrix_col_end + + # ... + + addi $t1, $t1, 1 # Збільшити лічильник стовпця (col) + matrix_col_end: + + # ... + + addi $t0, $t0, 1 + matrix_row_end: + +## Функції ## + _functions: + # Функції - це процедури, що викликаються, приймають аргументи та повертають значення + + main: # Програма починається з головної функції + jal return_1 # jal збереже поточний ПЦ (програмний центр) в $ra, + # а потім перейде до return_1 + + # Як передати аргументи? + # По-перше, ми маємо передати значення аргументів у регістри аргументів + li $a0, 1 + li $a1, 2 + jal sum # Тепер ми можемо викликати функцію + + # Як щодо рекурсії? + # Тут потрібно дещо більше роботи оскільки ми маємо впевнитись, що ми збережемо + # та зчитаємо попередній ПЦ в $ra, оскільки jal автоматично перепише її при виклику + li $a0, 3 + jal fact + + li $v0, 10 + syscall + + # Ця функція повертає 1 + return_1: + li $v0, 1 # Завантажити val в регіст $v0 + jr $ra # Повернутись до попереднього ПЦ і продовжити виконання + + + # Функція з двома аргументами + sum: + add $v0, $a0, $a1 + jr $ra # Повернутись + + # Рекурсивна функція, яка знаходить факторіал + fact: + addi $sp, $sp, -8 # Виділити місце в стеку + sw $s0, ($sp) # Зберегти регістр, що містить поточне число + sw $ra, 4($sp) # Зберегти попередній ПЦ + + li $v0, 1 # Проініціалізувати значення, що повертатиметься + beq $a0, 0, fact_done # Закінчити, якщо параметр 0 + + # Інакше, продовжити рекурсію + move $s0, $a0 # Скопіювати $a0 в $s0 + sub $a0, $a0, 1 + jal fact + + mul $v0, $s0, $v0 # Множення + + fact_done: + lw $s0, ($sp) + lw $ra, ($sp) # Відновити ПЦ + addi $sp, $sp, 8 + + jr $ra + +## Макроси ## + _macros: + # Макроси надзвичайно корисні для заміни блоків коду, що повторюються, за допомогою + # однієї змінної, для покращення читабельності + # Це не заміна функцій. + # Вони мають бути оголошені перед використанням + + # Макрос для виведення нових рядків (оскільки операція досить часто виконується) + .macro println() + la $a0, newline # Значення нового рядка зберігатиметься тут + li $v0, 4 + syscall + .end_macro + + println() # Асемблер скопіює цей блок коду сюди + # перед тим, як виконувати його + + # Можна передавати параметри у макроси. + # Параметри позначаються знаком '%' з довільною назвою + .macro print_int(%num) + li $v0, 1 + lw $a0, %num + syscall + .end_macro + + li $t0, 1 + print_int($t0) + + # Значення також можна передавати безпосередньо в макроси + .macro immediates(%a, %b) + add $t0, %a, %b + .end_macro + + immediates(3, 5) + + # Одночасно із назвами змінних + .macro print(%string) + la $a0, %string + li $v0, 4 + syscall + .end_macro + + print(hello_world) + +## Масиви ## +.data + list: .word 3, 0, 1, 2, 6 # Це масив чисел + char_arr: .asciiz "hello" # Це текстовий масив + buffer: .space 128 # Виділяє блок пам'яті, що + # автоматично не очищується + # Ці блоки пам'яті вирівнені + # вирівнені поруч один з одним + +.text + la $s0, list # Завантажити адресу списку + li $t0, 0 # Лічильник + li $t1, 5 # Довжина списку + + loop: + bgt $t0, $t1, end_loop + + lw $a0, ($s0) + li $v0, 1 + syscall # Вивести число + + addi $s0, $s0, 4 # Розмір числа - 4 байти + addi $t0, $t0, 1 # Збільшити + j loop + end_loop: + +## Включення ## +# Потрібно для імпорту сторонніх файлів у програму (насправді, код з цього файлу +# копіюється та вставляється в місце, де оголошений імпорт) +.include "somefile.asm" + +``` diff --git a/uk-ua/python-ua.html.markdown b/uk-ua/pythonlegacy-ua.html.markdown index 4091e433..e2a6d19e 100644 --- a/uk-ua/python-ua.html.markdown +++ b/uk-ua/pythonlegacy-ua.html.markdown @@ -1,5 +1,5 @@ --- -language: python +language: Python 2 (legacy) lang: uk-ua contributors: - ["Louie Dinh", "http://ldinh.ca"] @@ -10,7 +10,7 @@ contributors: - ["habi", "http://github.com/habi"] translators: - ["Oleh Hromiak", "https://github.com/ogroleg"] -filename: learnpython-ua.py +filename: learnpythonlegacy-ua.py --- Мову Python створив Гвідо ван Россум на початку 90-х. Наразі це одна з diff --git a/uk-ua/ruby-ua.html.markdown b/uk-ua/ruby-ua.html.markdown index 74346dfe..a71c30bc 100644 --- a/uk-ua/ruby-ua.html.markdown +++ b/uk-ua/ruby-ua.html.markdown @@ -622,4 +622,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/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide. -- [Try Ruby](http://tryruby.org) - Learn the basic of Ruby programming language, interactive in the browser. +- [Try Ruby](https://try.ruby-lang.org/) - Learn the basic of Ruby programming language, interactive in the browser. diff --git a/uk-ua/rust-ua.html.markdown b/uk-ua/rust-ua.html.markdown index 4ec2b7c9..4aad0cbb 100644 --- a/uk-ua/rust-ua.html.markdown +++ b/uk-ua/rust-ua.html.markdown @@ -1,5 +1,5 @@ --- -language: rust +language: Rust contributors: - ["P1start", "http://p1start.github.io/"] translators: @@ -233,7 +233,7 @@ fn main() { // Цикл `for` let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } diff --git a/uxntal.html.markdown b/uxntal.html.markdown new file mode 100644 index 00000000..c56e158a --- /dev/null +++ b/uxntal.html.markdown @@ -0,0 +1,174 @@ +--- +language: uxntal +contributors: + - ["Devine Lu Linvega", "https://wiki.xxiivv.com"] +filename: learnuxn.tal +--- + +Uxntal is a stack-machine assembly language targeting the [Uxn virtual machine](https://wiki.xxiivv.com/site/uxn.html). + +Stack machine programming might look at bit odd, as it uses a postfix notation, +which means that operators are always found at the end of an operation. For +instance, one would write 3 4 + instead of 3 + 4. + +The expression written (5 + 10) * 3 in conventional notation would be +written 10 5 + 3 * in reverse Polish notation. + +```forth +( This is a comment ) + +( All programming in Unxtal is done by manipulating the stack ) + +#12 ( push a byte ) +#3456 ( push a short ) + +( Uxn has 32 opcodes, each opcode has 3 possible modes ) + +POP ( pop a byte ) +POP2 ( pop a short ) + +( The modes are: + [2] The short mode consumes two bytes from the stack. + [k] The keep mode does not consume items from the stack. + [r] The return mode makes the operator operate on the return-stack. ) + +#12 #34 ADD ( 46 ) +#12 #34 ADDk ( 12 34 46 ) + +( The modes can be combined ) + +#1234 #5678 ADD2k ( 12 34 56 78 68 ac ) + +( The arithmetic/bitwise opcodes are: + ADD SUB MUL DIV + AND ORA EOR SFT ) + +( New opcodes can be created using macros ) + +%MOD2 { DIV2k MUL2 SUB2 } + +#1234 #0421 MOD2 ( 01 b0 ) + +( ---------------------------------------------------------------------------- ) + +( A short is simply two bytes, each byte can be manipulated ) + +#1234 SWP ( 34 12 ) +#1234 #5678 SWP2 ( 56 78 12 34 ) +#1234 #5678 SWP ( 12 34 78 56 ) + +( Individual bytes of a short can be removed from the stack ) + +#1234 POP ( 12 ) +#1234 NIP ( 34 ) + +( The stack opcodes are: + POP DUP NIP SWP OVR ROT ) + +( ---------------------------------------------------------------------------- ) + +( To compare values on the stack with each other ) + +#12 #34 EQU ( 00 ) +#12 #12 EQU ( 01 ) + +( Logic opcodes will put a flag with a value of either 00 or 01 ) + +#12 #34 LTH +#78 #56 GTH + #0101 EQU2 ( 01 ) + +( The logic opcodes are: + EQU NEQ GTH LTH ) + +( ---------------------------------------------------------------------------- ) + +( Uxn's accessible memory is as follows: + 256 bytes of working stack + 256 bytes of return stack + 65536 bytes of memory + 256 bytes of IO memory ) + +( The addressable memory is between 0000-ffff ) + +#12 #0200 STA ( stored 12 at 0200 in memory ) +#3456 #0201 STA2 ( stored 3456 at 0201 in memory ) +#0200 LDA2 ( 12 34 ) + +( The zero-page can be addressed with a single byte ) + +#1234 #80 STZ2 ( stored 12 at 0080, and 34 at 0081 ) +#80 LDZ2 ( 12 34 ) + +( Devices are ways for Uxn to communicate with the outside world + There is a maximum of 16 devices connected to Uxn at once + Device bytes are called ports, the Console device uses the 10-1f ports + The console's port 18 is called /write ) + +%EMIT { #18 DEO } + +#31 EMIT ( print "1" to console ) + +( A label is equal to a position in the program ) +@parent ( defines a label "parent" ) + &child ( defines a sublabel "parent/child" ) + +( Label positions can be pushed on stack ) +;parent ( push the absolute position, 2 bytes ) +,parent ( push the relative position, 1 byte ) +.parent ( push the zero-page position, 1 byte ) + +( The memory opcodes are: + LDZ STZ LDR STR + LDA STA DEI DEO ) + +( ---------------------------------------------------------------------------- ) + +( Logic allows to create conditionals ) + +#12 #34 NEQ ,skip JCN + #31 EMIT + @skip + +( Logic also allows to create for-loops ) + +#3a #30 +@loop + DUP EMIT ( print "123456789" to console ) + INC GTHk ,loop JCN +POP2 + +( Logic also allows to create while-loops ) + +;word +@while + LDAk EMIT + INC2 LDAk ,while JCN +POP2 +BRK + +@word "vermillion $1 + +( Subroutines can be jumped to with JSR, and returned from with JMP2r ) + +;word ,print-word JSR +BRK + +@print-word ( word* -- ) + @while + LDAk EMIT + INC2 LDAk ,while JCN + POP2 +JMP2r + +@word "cerulean + +( The jump opcodes are: + JMP JCN JSR ) +``` + +## Ready For More? + +* [Uxntal Lessons](https://compudanzas.net/uxn_tutorial.html) +* [Uxntal Assembly](https://wiki.xxiivv.com/site/uxntal.html) +* [Uxntal Resources](https://github.com/hundredrabbits/awesome-uxn) diff --git a/v.html.markdown b/v.html.markdown new file mode 100644 index 00000000..4f698184 --- /dev/null +++ b/v.html.markdown @@ -0,0 +1,229 @@ +--- +language: v +filename: vlang.v +contributors: + - ["Maou Shimazu", "https://github.com/Maou-Shimazu"] +--- + +V is a statically typed compiled programming language +designed for building maintainable software. + +It's similar to Go and its design has also been influenced by +Oberon, Rust, Swift, Kotlin, and Python. + +The language promotes writing +simple and clear code with minimal abstraction. + +Despite being simple, V gives the developer a lot of power. +Anything you can do in other languages, you can do in V. + +```v +// Single Line Comment. +/* + Multi Line Comment +*/ + +struct User { // Cannot be defined in main, explained later. + age int + name string + pos int = -1 // custom default value +} +// struct method +fn (u User) can_register() bool { + return u.age > 16 +} + +struct Parser { + token Token +} + +// c like enums +enum Token { + plus + minus + div + mult +} + +// 1. functions +// language does not use semi colons +fn add(x int, y int) int { + return x + y +} +// can return multiple values +fn foo() (int, int) { + return 2, 3 +} + +// function visibility +pub fn public_function() { // pub can only be used from a named module. +} + +fn private_function() { +} + + + +// Main function +fn main() { + // Anonymous functions can be declared inside other functions: + double_fn := fn (n int) int { + return n + n + } + // 2. Variables: they are immutable by default + // implicitly typed + x := 1 + // x = 2 // error + mut y := 2 + y = 4 + name := "John" + large_number := i64(9999999999999) + println("$x, $y, $name, $large_number") // 1, 4, John, 9999999999999 + + // unpacking values from functions. + a, b := foo() + println("$a, $b") // 2, 3 + c, _ := foo() // ignore values using `_` + println("$c") // 2 + + // Numbers + u := u16(12) + v := 13 + u // v is of type `u16` + r := f32(45.6) + q := r + 3.14 // x is of type `f32` + s := 75 // a is of type `int` + l := 14.7 // b is of type `f64` + e := u + s // c is of type `int` + d := l + r // d is of type `f64` + + // Strings + mut bob := 'Bob' + assert bob[0] == u8(66) // indexing gives a byte, u8(66) == `B` + assert bob[1..3] == 'ob' // slicing gives a string 'ob' + bobby := bob + 'by' // + is used to concatenate strings + println(bobby) // "Bobby" + bob += "by2" // += is used to append to strings + println(bob) // "Bobby2" + + //String values are immutable. You cannot mutate elements: + //mut s := 'hello 🌎' + //s[0] = `H` // not allowed + + //For raw strings, prepend r. Escape handling is not done for raw strings: + rstring := r'hello\nworld' // the `\n` will be preserved as two characters + println(rstring) // "hello\nworld" + + // string interpolation + println('Hello, $bob!') // Hello, Bob! + println('Bob length + 10: ${bob.len + 10}!') // Bob length + 10: 13! + + // 3. Arrays + mut numbers := [1, 2, 3] + println(numbers) // `[1, 2, 3]` + numbers << 4 // append elements with << + println(numbers[3]) // `4` + numbers[1] = 5 + println(numbers) // `[1, 5, 3]` + // numbers << "John" // error: `numbers` is an array of numbers + numbers = [] // array is now empty + arr := []int{len: 5, init: -1} + // `arr == [-1, -1, -1, -1, -1]`, arr.cap == 5 + + number_slices := [0, 10, 20, 30, 40] + println(number_slices[1..4]) // [10, 20, 30] + println(number_slices[..4]) // [0, 10, 20, 30] + println(number_slices[1..]) // [10, 20, 30, 40] + + // 4. structs and enums + // struct User { + // age int + // name string + // pos int = -1 // custom default value + // } + mut users := User{21, 'Bob', 0} + println(users.age) // 21 + + // enum Token { + // plus + // minus + // div + // mult + // } + + // struct Parser { + // token Token + // } + parser := Parser{} + if parser.token == .plus || parser.token == .minus + || parser.token == .div || parser.token == .mult { + // ... + } + + + // 5. Maps + number_map := { + 'one': 1 + 'two': 2 + } + println(number_map) // {'one': 1, 'two': 2} + println(number_map["one"]) // 1 + mut m := map[string]int{} // a map with `string` keys and `int` values + m['one'] = 1 + m['two'] = 2 + println(m['one']) // "1" + println(m['bad_key']) // "0" + m.delete('two') + + // 6. Conditionals + a_number := 10 + b_number := 20 + if a_number < b { + println('$a_number < $b_number') + } else if a_number > b { + println('$a_number > $b_number') + } else { + println('$a_number == $b_number') + } + num := 777 + even_odd := if num % 2 == 0 { 'even' } else { 'odd' } + println(even_odd) + + match even_odd { + 'even' { println('even') } + 'odd' { println('odd') } + else { println('unknown') } + } + + // 7. Loops + loops := [1, 2, 3, 4, 5] + for lp in loops { + println(lp) + } + loop_names := ['Sam', 'Peter'] + for i, lname in loop_names { + println('$i) $lname') + // Output: 0) Sam + // 1) Peter + } + // You can also use break and continue followed by a + // label name to refer to an outer for loop: + outer: for i := 4; true; i++ { + println(i) + for { + if i < 7 { + continue outer + } else { + break outer + } + } + } +} + +``` +## Further reading + +There are more complex concepts to be learnt in V which are available at the +official [V documentation](https://github.com/vlang/v/blob/master/doc/docs.md). + +You can also find more information about the V language at the [official website](https://vlang.io/) +or check it out at the [v playground](https://v-wasm.vercel.app/).
\ No newline at end of file diff --git a/vala.html.markdown b/vala.html.markdown index 393578b0..739e0fda 100755..100644 --- a/vala.html.markdown +++ b/vala.html.markdown @@ -483,10 +483,10 @@ pointer_obj->some_data; // Returns some_data delete pointer_obj; int more = 57; -int* more_pointer = &i; // & = address-of +int* more_pointer = &more; // & = address-of int indirection_demo = more_pointer*; // indirection -// Profiles: affect which Vala features are avaliable and which libraries the +// Profiles: affect which Vala features are available and which libraries the // C-code will use. // - gobject (default) // posix @@ -494,10 +494,10 @@ int indirection_demo = more_pointer*; // indirection // Use "--profile=whatever" when compiling. ``` -* More Vala documentation can be found [here](https://valadoc.org/). +* More [Vala documentation](https://valadoc.org/). * [Alternate construction syntax](https://wiki.gnome.org/Projects/Vala/Tutorial#GObject-Style_Construction) similar to GObject -* More on contract programming [here](http://en.wikipedia.org/wiki/Contract_programming) -* Collections library can be found [here](https://wiki.gnome.org/Projects/Vala/Tutorial#Collections) +* More on [contract programming](http://en.wikipedia.org/wiki/Contract_programming) +* [Collections library](https://wiki.gnome.org/Projects/Vala/Tutorial#Collections) * [Multithreading](https://wiki.gnome.org/Projects/Vala/Tutorial#Multi-Threading) -* Read about building GUIs with GTK+ and Vala [here](http://archive.is/7C7bw). -* D-Bus [integration](https://wiki.gnome.org/Projects/Vala/Tutorial#D-Bus_Integration) +* Read about [building GUIs with GTK+ and Vala](http://archive.is/7C7bw). +* [D-Bus integration](https://wiki.gnome.org/Projects/Vala/Tutorial#D-Bus_Integration) diff --git a/vi-vn/git-vi.html.markdown b/vi-vn/git-vi.html.markdown index 1bcc94a0..47485bd9 100644 --- a/vi-vn/git-vi.html.markdown +++ b/vi-vn/git-vi.html.markdown @@ -1,328 +1,328 @@ ----
-category: tool
-tool: git
-contributors:
+--- +category: tool +tool: git +contributors: - ["Jake Prather", "http://github.com/JakeHP"] - - ["Vinh Nguyen", "https://twitter.com/vinhnx"]
-filename: LearnGit-vi.txt
-lang: vi-vn
----
-
-Git là một hệ quản lý mã nguồn và phiên bản phân tán (distributed version control and source code management system).
-
-Nó làm được điều này là do một loạt các snapshot từ đề án của bạn, và nó hoạt động
-với các snapshot đó để cung cấp cho bạn với chức năng đến phiên bản và
-quản lý mã nguồn của bạn.
-
-## Khái Niệm Versioning
-
-### Version Control là gì?
-
-Version Control là một hệ thống ghi lại những thay đổi ở một tập tin, hay một nhóm các tập tin, theo thời gian.
-
-### So sánh giữa Centralized Versioning và Distributed Versioning
-
-* Quản lý phiên bản tập trung (Centralized Versioning) tập trung vào việc đồng bộ hóa, theo dõi, và lưu trữ tập tin.
-* Quản lý phiên bản phân tán (Distributed Versioning) tập trung vào việc chia sẻ các thay đổi. Mỗi sự thay đổi có một mã định dạng (id) duy nhất.
-* Các hệ phân tán không có cấu trúc định sẵn. Bạn có thể thay đổi một kiểu SVN, hệ phân tán, với git.
-
-[Thông tin thêm](http://git-scm.com/book/en/Getting-Started-About-Version-Control)
-
-### Tại Sao Dùng Git?
-
-* Có thể hoạt động offline.
-* Cộng tác với nhau rất dễ dàng!
-* Phân nhánh dễ dàng!
-* Trộn (Merging)
-* Git nhanh.
-* Git linh hoạt.
-
-## Kiến Trúc Git
-
-
-### Repository
-
-Một nhóm các tập tin, thư mục, các ghi chép trong quá khứ, commit, và heads. Tưởng tượng nó như là một cấu trúc dữ liệu mã nguồn,
-với thuộc tính mà một "nhân tố" mã nguồn cho bạn quyền truy cập đến lịch sử sửa đổi, và một số thứ khác.
-
-Một git repository bao gồm thư mục .git & tree đang làm việc.
-
-### Thư mục .git (thành phần của một repository)
-
-Thư mục .git chứa tất cả các cấu hình, log, nhánh, HEAD, và hơn nữa.
-[Danh Sách Chi Tiết.](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html)
-
-### Tree Đang Làm (thành phần của một repository)
-
-Đây cơ bản là các thư mục và tập tin trong repository của bạn. Nó thường được tham chiếu
-thư mục đang làm việc của bạn
-
-### Chỉ mục (thành phần của một thư mục .git)
-
-Chỉ mục của là một staging area trong git. Nó đơn giản là một lớp riêng biệt với tree đang làm việc của bạn
-từ Git repository. Điều này cho nhà phát triền nhiều lựa chọn hơn trong việc xem xét những gì được gửi đến Git
-repository.
-
-### Commit
-
-Một git commit là một snapshot của một nhóm các thay đổi, hoặc các thao tác Working Tree của bạn.
-Ví dụ, nếu bạn thêm 5 tập tin, và xóa 2 tập tin khác, những thay đổi này sẽ được chứa trong
-một commit (hoặc snapshot). Commit này có thể được đẩy đến các repo khác, hoặc không!
-
-### Nhánh
-
-Nhánh thực chất là một con trỏ đến commit mới nhất mà bạn vừa thực hiện. Khi bạn commit,
-con trỏ này sẽ cập nhật tự động và trỏ đến commit mới nhất.
-
-### HEAD và head (thành phần của thư mục .git)
-
-HEAD là một con trỏ đến branch hiện tại. Một repo chỉ có một HEAD *đang hoạt động*.
-head là một con trỏ đến bất kỳ commit nào. Một repo có thể có nhiều head.
-
-### Các Tài Nguyên Mang Tính Khái Niệm
-
-* [Git For Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/)
-* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html)
-
-
-## Các Lệnh
-
-
-### init
-
-Tạo một repo Git rỗng. Các cài đặt, thông tin lưu trữ... của Git
-được lưu ở một thư mục tên là ".git".
-
-```bash
-$ git init
-```
-
-### config
-
-Để chỉnh tùy chọn. Bất kể là cho repo, hay cho hệ thống, hay điều chỉnh
-toàn cục (global)
-
-
-
-```bash
-# In Ra & Và Gán Một Số Biến Tùy Chỉnh Cơ Bản (Toàn cục - Global)
-$ git config --global user.email
-$ git config --global user.name
-
-$ git config --global user.email "MyEmail@Zoho.com"
-$ git config --global user.name "My Name"
-```
-
-[Tìm hiểu thêm về git config.](http://git-scm.com/docs/git-config)
-
-### help
-
-Để cho bạn lối truy cập nhanh đến một chỉ dẫn cực kỳ chi tiết của từng lệnh. Hoặc chỉ để
-nhắc bạn một số cú pháp.
-
-```bash
-# Xem nhanh các lệnh có sẵn
-$ git help
-
-# Xem tất các các lệnh
-$ git help -a
-
-# Lệnh help riêng biệt - tài liệu người dùng
-# git help <command_here>
-$ git help add
-$ git help commit
-$ git help init
-```
-
-### status
-
-Để hiển thị sự khác nhau giữa tập tin index (cơ bản là repo đang làm việc) và HEAD commit
-hiện tại.
-
-
-```bash
-# Sẽ hiển thị nhánh, các tập tin chưa track (chưa commit), các thay đổi và những khác biệt khác
-$ git status
-
-# Để xem các "tid bits" về git status
-$ git help status
-```
-
-### add
-
-Để thêm các tập vào tree/thư mục/repo hiện tại. Nếu bạn không `git add` các tập tin mới đến
-tree/thư mục hiện tại, chúng sẽ không được kèm theo trong các commit!
-
-```bash
-# thêm một file vào thư mục hiện tại
-$ git add HelloWorld.java
-
-# thêm một file vào một thư mục khác
-$ git add /path/to/file/HelloWorld.c
-
-# Hỗ trợ Regular Expression!
-$ git add ./*.java
-```
-
-### branch
-
-Quản lý nhánh (branch). Bạn có thể xem, sửa, tạo, xóa các nhánh bằng cách dùng lệnh này.
-
-```bash
-# liệt kê các branch đang có và ở remote
-$ git branch -a
-
-# tạo branch mới
-$ git branch myNewBranch
-
-# xóa một branch
-$ git branch -d myBranch
-
-# đặt tên lại một branch
-# git branch -m <oldname> <newname>
-$ git branch -m myBranchName myNewBranchName
-
-# chỉnh sửa diễn giải của một branch
-$ git branch myBranchName --edit-description
-```
-
-### checkout
-
-Cập nhật tất cả các file trong tree hiện tại để cho trùng khớp với phiên bản của index, hoặc tree cụ thể.
-
-```bash
-# Checkout (chuyển) một repo - mặc định là nhánh master
-$ git checkout
-# Checkout một nhánh cụ thể
-$ git checkout branchName
-# Tạo một nhánh mới và chuyển đến nó, tương tự: "git branch <name>; git checkout <name>"
-$ git checkout -b newBranch
-```
-
-### clone
-
-Nhân bản, hoặc sao chép, một repo hiện có thành một thư mục mới. Nó cũng thêm
-các branch có remote-tracking cho mỗi branch trong một repo được nhân bản, mà
-cho phép bạn push đến một remote branch.
-
-```bash
-# Nhân bản learnxinyminutes-docs
-$ git clone https://github.com/adambard/learnxinyminutes-docs.git
-```
-
-### commit
-
-Lưu trữ nội dung hiện tại của index trong một "commit" mới. Điều này cho phép tạo ra thay đổi và một ghi chú tạo ra bởi người dùng.
-
-```bash
-# commit với một ghi chú
-$ git commit -m "Added multiplyNumbers() function to HelloWorld.c"
-```
-
-### diff
-
-Hiển thị sự khác biệt giữa một file trong thư mục hiện tại, index và commits.
-
-```bash
-# Hiển thị sự khác biệt giữa thư mục hiện tại và index
-$ git diff
-
-# Hiển thị khác biệt giữa index và commit mới nhất.
-$ git diff --cached
-
-# Hiển thị khác biệt giữa thư mục đang làm việc và commit mới nhất
-$ git diff HEAD
-```
-
-### grep
-
-Cho phép bạn tìm kiếm nhanh một repo.
-
-Các tinh chỉnh tùy chọn:
-
-```bash
-# Cảm ơn Travis Jeffery vì những lệnh này
-# Đặt số của dòng được hiển thị trong kết quả tìm kiếm grep
-$ git config --global grep.lineNumber true
-
-# Làm cho kết quả tìm kiếm dễ đọc hơn, bao gồm cả gom nhóm
-$ git config --global alias.g "grep --break --heading --line-number"
-```
-
-```bash
-# Tìm "variableName" trong tất cả các file Java
-$ git grep 'variableName' -- '*.java'
-
-# Tìm một dòng mà có chứa "arrayListName" và, "add" hoặc "remove"
-$ git grep -e 'arrayListName' --and \( -e add -e remove \)
-```
-
-Google để xem thêm các ví dụ
-[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja)
-
-### log
-
-Hiển thị các commit đến repo.
-
-```bash
-# Hiện tất cả các commit
-$ git log
-
-# Hiện X commit
-$ git log -n 10
-
-# Chỉ hiện các commit đã merge merge commits
-$ git log --merges
-```
-
-### merge
-
-"Trộn" các thay đổi từ commit bên ngoài vào trong nhánh hiện tại.
-
-```bash
-# Merge branch cụ thể vào branch hiện tại.
-$ git merge branchName
-
-# Luôn khởi tạo một merge commit khi trộn (merge)
-$ git merge --no-ff branchName
-```
-
-### mv
-
-Đặt lại tên hoặc di chuyển một file
-
-```bash
-# Đặt lại tên một file
-$ git mv HelloWorld.c HelloNewWorld.c
-
-# Di chuyển một file
-$ git mv HelloWorld.c ./new/path/HelloWorld.c
-
-# Buộc đặt lại tên hoặc di chuyển
-# "existingFile" đã tồn tại trong thự mục, sẽ bị ghi đè
-$ git mv -f myFile existingFile
-```
-
-### pull
-
-Pull về từ một repo và merge nó vào branch khác.
-
-```bash
-# Cập nhật repo local của bạn, bằng cách merge các thay đổi mới
-# từ remote "origin" và nhánh "master".
-# git pull <remote> <branch>
-# git pull => hoàn toàn mặc định như => git pull origin master
-$ git pull origin master
-
-# Merge các thay đổi từ remote branch và rebase
-# các commit trong branch lên trên local repo, như sau: "git pull <remote> <branch>, git rebase <branch>"
-$ git pull origin master --rebase
-```
-
-### push
-
-push và merge các thay đổi từ một branch đến một remote & branch.
-
+ - ["Vinh Nguyen", "https://twitter.com/vinhnx"] +filename: LearnGit-vi.txt +lang: vi-vn +--- + +Git là một hệ quản lý mã nguồn và phiên bản phân tán (distributed version control and source code management system). + +Nó làm được điều này là do một loạt các snapshot từ đề án của bạn, và nó hoạt động +với các snapshot đó để cung cấp cho bạn với chức năng đến phiên bản và +quản lý mã nguồn của bạn. + +## Khái Niệm Versioning + +### Version Control là gì? + +Version Control là một hệ thống ghi lại những thay đổi ở một tập tin, hay một nhóm các tập tin, theo thời gian. + +### So sánh giữa Centralized Versioning và Distributed Versioning + +* Quản lý phiên bản tập trung (Centralized Versioning) tập trung vào việc đồng bộ hóa, theo dõi, và lưu trữ tập tin. +* Quản lý phiên bản phân tán (Distributed Versioning) tập trung vào việc chia sẻ các thay đổi. Mỗi sự thay đổi có một mã định dạng (id) duy nhất. +* Các hệ phân tán không có cấu trúc định sẵn. Bạn có thể thay đổi một kiểu SVN, hệ phân tán, với git. + +[Thông tin thêm](http://git-scm.com/book/en/Getting-Started-About-Version-Control) + +### Tại Sao Dùng Git? + +* Có thể hoạt động offline. +* Cộng tác với nhau rất dễ dàng! +* Phân nhánh dễ dàng! +* Trộn (Merging) +* Git nhanh. +* Git linh hoạt. + +## Kiến Trúc Git + + +### Repository + +Một nhóm các tập tin, thư mục, các ghi chép trong quá khứ, commit, và heads. Tưởng tượng nó như là một cấu trúc dữ liệu mã nguồn, +với thuộc tính mà một "nhân tố" mã nguồn cho bạn quyền truy cập đến lịch sử sửa đổi, và một số thứ khác. + +Một git repository bao gồm thư mục .git & tree đang làm việc. + +### Thư mục .git (thành phần của một repository) + +Thư mục .git chứa tất cả các cấu hình, log, nhánh, HEAD, và hơn nữa. +[Danh Sách Chi Tiết.](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) + +### Tree Đang Làm (thành phần của một repository) + +Đây cơ bản là các thư mục và tập tin trong repository của bạn. Nó thường được tham chiếu +thư mục đang làm việc của bạn + +### Chỉ mục (thành phần của một thư mục .git) + +Chỉ mục của là một staging area trong git. Nó đơn giản là một lớp riêng biệt với tree đang làm việc của bạn +từ Git repository. Điều này cho nhà phát triền nhiều lựa chọn hơn trong việc xem xét những gì được gửi đến Git +repository. + +### Commit + +Một git commit là một snapshot của một nhóm các thay đổi, hoặc các thao tác Working Tree của bạn. +Ví dụ, nếu bạn thêm 5 tập tin, và xóa 2 tập tin khác, những thay đổi này sẽ được chứa trong +một commit (hoặc snapshot). Commit này có thể được đẩy đến các repo khác, hoặc không! + +### Nhánh + +Nhánh thực chất là một con trỏ đến commit mới nhất mà bạn vừa thực hiện. Khi bạn commit, +con trỏ này sẽ cập nhật tự động và trỏ đến commit mới nhất. + +### HEAD và head (thành phần của thư mục .git) + +HEAD là một con trỏ đến branch hiện tại. Một repo chỉ có một HEAD *đang hoạt động*. +head là một con trỏ đến bất kỳ commit nào. Một repo có thể có nhiều head. + +### Các Tài Nguyên Mang Tính Khái Niệm + +* [Git For Computer Scientists](http://eagain.net/articles/git-for-computer-scientists/) +* [Git For Designers](http://hoth.entp.com/output/git_for_designers.html) + + +## Các Lệnh + + +### init + +Tạo một repo Git rỗng. Các cài đặt, thông tin lưu trữ... của Git +được lưu ở một thư mục tên là ".git". + +```bash +$ git init +``` + +### config + +Để chỉnh tùy chọn. Bất kể là cho repo, hay cho hệ thống, hay điều chỉnh +toàn cục (global) + + + +```bash +# In Ra & Và Gán Một Số Biến Tùy Chỉnh Cơ Bản (Toàn cục - Global) +$ git config --global user.email +$ git config --global user.name + +$ git config --global user.email "MyEmail@Zoho.com" +$ git config --global user.name "My Name" +``` + +[Tìm hiểu thêm về git config.](http://git-scm.com/docs/git-config) + +### help + +Để cho bạn lối truy cập nhanh đến một chỉ dẫn cực kỳ chi tiết của từng lệnh. Hoặc chỉ để +nhắc bạn một số cú pháp. + +```bash +# Xem nhanh các lệnh có sẵn +$ git help + +# Xem tất các các lệnh +$ git help -a + +# Lệnh help riêng biệt - tài liệu người dùng +# git help <command_here> +$ git help add +$ git help commit +$ git help init +``` + +### status + +Để hiển thị sự khác nhau giữa tập tin index (cơ bản là repo đang làm việc) và HEAD commit +hiện tại. + + +```bash +# Sẽ hiển thị nhánh, các tập tin chưa track (chưa commit), các thay đổi và những khác biệt khác +$ git status + +# Để xem các "tid bits" về git status +$ git help status +``` + +### add + +Để thêm các tập vào tree/thư mục/repo hiện tại. Nếu bạn không `git add` các tập tin mới đến +tree/thư mục hiện tại, chúng sẽ không được kèm theo trong các commit! + +```bash +# thêm một file vào thư mục hiện tại +$ git add HelloWorld.java + +# thêm một file vào một thư mục khác +$ git add /path/to/file/HelloWorld.c + +# Hỗ trợ Regular Expression! +$ git add ./*.java +``` + +### branch + +Quản lý nhánh (branch). Bạn có thể xem, sửa, tạo, xóa các nhánh bằng cách dùng lệnh này. + +```bash +# liệt kê các branch đang có và ở remote +$ git branch -a + +# tạo branch mới +$ git branch myNewBranch + +# xóa một branch +$ git branch -d myBranch + +# đặt tên lại một branch +# git branch -m <oldname> <newname> +$ git branch -m myBranchName myNewBranchName + +# chỉnh sửa diễn giải của một branch +$ git branch myBranchName --edit-description +``` + +### checkout + +Cập nhật tất cả các file trong tree hiện tại để cho trùng khớp với phiên bản của index, hoặc tree cụ thể. + +```bash +# Checkout (chuyển) một repo - mặc định là nhánh master +$ git checkout +# Checkout một nhánh cụ thể +$ git checkout branchName +# Tạo một nhánh mới và chuyển đến nó, tương tự: "git branch <name>; git checkout <name>" +$ git checkout -b newBranch +``` + +### clone + +Nhân bản, hoặc sao chép, một repo hiện có thành một thư mục mới. Nó cũng thêm +các branch có remote-tracking cho mỗi branch trong một repo được nhân bản, mà +cho phép bạn push đến một remote branch. + +```bash +# Nhân bản learnxinyminutes-docs +$ git clone https://github.com/adambard/learnxinyminutes-docs.git +``` + +### commit + +Lưu trữ nội dung hiện tại của index trong một "commit" mới. Điều này cho phép tạo ra thay đổi và một ghi chú tạo ra bởi người dùng. + +```bash +# commit với một ghi chú +$ git commit -m "Added multiplyNumbers() function to HelloWorld.c" +``` + +### diff + +Hiển thị sự khác biệt giữa một file trong thư mục hiện tại, index và commits. + +```bash +# Hiển thị sự khác biệt giữa thư mục hiện tại và index +$ git diff + +# Hiển thị khác biệt giữa index và commit mới nhất. +$ git diff --cached + +# Hiển thị khác biệt giữa thư mục đang làm việc và commit mới nhất +$ git diff HEAD +``` + +### grep + +Cho phép bạn tìm kiếm nhanh một repo. + +Các tinh chỉnh tùy chọn: + +```bash +# Cảm ơn Travis Jeffery vì những lệnh này +# Đặt số của dòng được hiển thị trong kết quả tìm kiếm grep +$ git config --global grep.lineNumber true + +# Làm cho kết quả tìm kiếm dễ đọc hơn, bao gồm cả gom nhóm +$ git config --global alias.g "grep --break --heading --line-number" +``` + +```bash +# Tìm "variableName" trong tất cả các file Java +$ git grep 'variableName' -- '*.java' + +# Tìm một dòng mà có chứa "arrayListName" và, "add" hoặc "remove" +$ git grep -e 'arrayListName' --and \( -e add -e remove \) +``` + +Google để xem thêm các ví dụ +[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja) + +### log + +Hiển thị các commit đến repo. + +```bash +# Hiện tất cả các commit +$ git log + +# Hiện X commit +$ git log -n 10 + +# Chỉ hiện các commit đã merge merge commits +$ git log --merges +``` + +### merge + +"Trộn" các thay đổi từ commit bên ngoài vào trong nhánh hiện tại. + +```bash +# Merge branch cụ thể vào branch hiện tại. +$ git merge branchName + +# Luôn khởi tạo một merge commit khi trộn (merge) +$ git merge --no-ff branchName +``` + +### mv + +Đặt lại tên hoặc di chuyển một file + +```bash +# Đặt lại tên một file +$ git mv HelloWorld.c HelloNewWorld.c + +# Di chuyển một file +$ git mv HelloWorld.c ./new/path/HelloWorld.c + +# Buộc đặt lại tên hoặc di chuyển +# "existingFile" đã tồn tại trong thự mục, sẽ bị ghi đè +$ git mv -f myFile existingFile +``` + +### pull + +Pull về từ một repo và merge nó vào branch khác. + +```bash +# Cập nhật repo local của bạn, bằng cách merge các thay đổi mới +# từ remote "origin" và nhánh "master". +# git pull <remote> <branch> +# git pull => hoàn toàn mặc định như => git pull origin master +$ git pull origin master + +# Merge các thay đổi từ remote branch và rebase +# các commit trong branch lên trên local repo, như sau: "git pull <remote> <branch>, git rebase <branch>" +$ git pull origin master --rebase +``` + +### push + +push và merge các thay đổi từ một branch đến một remote & branch. + ```bash # Push và merge các thay đổi từ một repo local đến một # remote có tên là "origin" và nhánh "master". @@ -334,70 +334,68 @@ $ git push origin master $ git push -u origin master # Từ lúc này, bất cứ khi nào bạn muốn push từ cùng một nhánh local đó, sử dụng lối tắt: $ git push -```
-
-### rebase (thận trọng)
-
-Lấy tất cả các thay đổi mà đã được commit trên một nhánh, và replay (?) chúng trên một nhánh khác.
-*Không rebase các commit mà bạn đã push đến một repo công khai*.
-
-```bash
-# Rebase experimentBranch lên master
-# git rebase <basebranch> <topicbranch>
-$ git rebase master experimentBranch
-```
-
-[Đọc Thêm.](http://git-scm.com/book/en/Git-Branching-Rebasing)
-
-### reset (thận trọng)
-
-Thiết lập lạo HEAD hiện tại đến một trạng thái cụ thể. Điều này cho phép bạn làm lại các merges,
-pulls, commits, thêm, and hơn nữa. Nó là một lệnh hay nhưng cũng nguy hiểm nếu bạn không
-biết mình đang làm gì.
-
-```bash
-# Thiết lập lại staging area, để trùng với commit mới nhất (để thư mục không thay đổi)
-$ git reset
-
-# Thiết lập lại staging area, để trùng với commit mới nhất, và ghi đè lên thư mục hiện tại
-$ git reset --hard
-
-# Di chuyển nhánh hiện tại đến một commit cụ thể (để thư mục không thay đổi)
-# tất cả thay đổi vẫn duy trì trong thư mục.
-$ git reset 31f2bb1
-
-# Di chuyển nhánh hiện tại lùi về một commit cụ thể
-# và làm cho thư mục hiện tại trùng (xóa các thay đổi chưa được commit và tất cả các commit
-# sau một commit cụ thể).
-$ git reset --hard 31f2bb1
-```
-
-### rm
-
-Ngược lại với git add, git rm xóa file từ tree đang làm việc.
-
-```bash
-# xóa HelloWorld.c
-$ git rm HelloWorld.c
-
-# Xóa file từ thư mục khác
-$ git rm /pather/to/the/file/HelloWorld.c
-```
-
-## Thông tin thêm
-
-* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1)
-
-* [git-scm - Video Tutorials](http://git-scm.com/videos)
-
-* [git-scm - Documentation](http://git-scm.com/docs)
-
-* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/)
-
-* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf)
-
-* [GitGuys](http://www.gitguys.com/) +``` + +### rebase (thận trọng) + +Lấy tất cả các thay đổi mà đã được commit trên một nhánh, và replay (?) chúng trên một nhánh khác. +*Không rebase các commit mà bạn đã push đến một repo công khai*. + +```bash +# Rebase experimentBranch lên master +# git rebase <basebranch> <topicbranch> +$ git rebase master experimentBranch +``` + +[Đọc Thêm.](http://git-scm.com/book/en/Git-Branching-Rebasing) + +### reset (thận trọng) + +Thiết lập lạo HEAD hiện tại đến một trạng thái cụ thể. Điều này cho phép bạn làm lại các merges, +pulls, commits, thêm, and hơn nữa. Nó là một lệnh hay nhưng cũng nguy hiểm nếu bạn không +biết mình đang làm gì. + +```bash +# Thiết lập lại staging area, để trùng với commit mới nhất (để thư mục không thay đổi) +$ git reset + +# Thiết lập lại staging area, để trùng với commit mới nhất, và ghi đè lên thư mục hiện tại +$ git reset --hard + +# Di chuyển nhánh hiện tại đến một commit cụ thể (để thư mục không thay đổi) +# tất cả thay đổi vẫn duy trì trong thư mục. +$ git reset 31f2bb1 + +# Di chuyển nhánh hiện tại lùi về một commit cụ thể +# và làm cho thư mục hiện tại trùng (xóa các thay đổi chưa được commit và tất cả các commit +# sau một commit cụ thể). +$ git reset --hard 31f2bb1 +``` + +### rm + +Ngược lại với git add, git rm xóa file từ tree đang làm việc. + +```bash +# xóa HelloWorld.c +$ git rm HelloWorld.c + +# Xóa file từ thư mục khác +$ git rm /pather/to/the/file/HelloWorld.c +``` + +## Thông tin thêm + +* [tryGit - A fun interactive way to learn Git.](http://try.github.io/levels/1/challenges/1) + +* [git-scm - Video Tutorials](http://git-scm.com/videos) + +* [git-scm - Documentation](http://git-scm.com/docs) + +* [Atlassian Git - Tutorials & Workflows](https://www.atlassian.com/git/) + +* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) * [Git - the simple guide](http://rogerdudler.github.io/git-guide/index.html) -
+ diff --git a/vi-vn/json-vi.html.markdown b/vi-vn/json-vi.html.markdown index 257216ff..f709b838 100644 --- a/vi-vn/json-vi.html.markdown +++ b/vi-vn/json-vi.html.markdown @@ -37,7 +37,7 @@ kiểu dữ liệu cũng như quy chuẩn cú pháp chặt chẽ sử dụng DTD "các khóa": "phải luôn được đặt trong dấu ngoặc kép", "số": 0, - "chuỗi kí tự": "Xin chàø. Tất cả kí tự unicode đều được chấp nhận, sử dụng với dạng \"kí tự\"." + "chuỗi kí tự": "Xin chàø. Tất cả kí tự unicode đều được chấp nhận, sử dụng với dạng \"kí tự\".", "có đúng không?": true, "không có gì": null, diff --git a/vi-vn/markdown-vi.html.markdown b/vi-vn/markdown-vi.html.markdown index 89b59253..696fe465 100644 --- a/vi-vn/markdown-vi.html.markdown +++ b/vi-vn/markdown-vi.html.markdown @@ -48,6 +48,7 @@ bằng cách thêm số lượng dấu thăng (#) đằng trước chuỗi cần ##### Đây là đầu mục <h5> ###### Đây là đầu mục <h6> ``` + Markdown còn cung cấp cách khác để tạo đầu mục hạng nhất h1 và hạng nhì h2. ```md @@ -79,6 +80,7 @@ Trong cài đặt Markdown để hiển thị file của GitHub,ta còn có gạ ```md ~~Đoạn văn bản này được gạch ngang.~~ ``` + ## Đoạn văn Đoạn văn bao gồm một hay nhiều dòng văn bản liên tiếp nhau được phân cách @@ -153,6 +155,7 @@ Ta không nhất thiết phải điền số thứ thự cho chỉ mục đúng 1. Mục thứ hai 1. Mục thứ ba ``` + (Sẽ hiển thị như ví dụ trước đó) Ta còn có thể sử dụng danh sách con @@ -189,7 +192,7 @@ Ta còn có thể thêm dấu nhảy (hoặc thêm vào bốn dấu cách nữa) ```md my_array.each do |item| - puts item + puts item end ``` @@ -201,12 +204,13 @@ John didn't even know what the `go_to()` function did! Trong Markdown của GitHub, ta còn có thêm cách để hiển thị code: -<pre> -<code class="highlight">```ruby +````md +```ruby def foobar - puts "Hello world!" + puts "Hello world!" end -```</code></pre> +``` +```` The above text doesn't require indenting, plus GitHub will use syntax highlighting of the language you specify after the \`\`\` @@ -231,11 +235,13 @@ Một trong những thứ tốt nhất khi làm việc với Markdown là khả ```md [Click me!](http://test.com/) ``` + Ta còn có thể tạo tiêu đề cho liên kết sử dụng cặp ngoặc nháy bên trong cặp ngoặc tròn ```md [Click me!](http://test.com/ "Link to Test.com") ``` + Đường dẫn tương đối cũng hoạt động. ```md @@ -244,19 +250,23 @@ Ta còn có thể tạo tiêu đề cho liên kết sử dụng cặp ngoặc nh Markdown còn hỗ trợ liên kết kiểu tham chiếu. -<pre><code class="highlight">[<span class="nv">Nhấn vào đây</span>][<span class="ss">link1</span>] để xem thêm! -[<span class="nv">Ngoài ra nhấn vào đây</span>][<span class="ss">foobar</span>] nếu bạn muốn xem qua. +```md +[Nhấn vào đây][link1] để xem thêm! +[Ngoài ra nhấn vào đây][foobar] nếu bạn muốn xem qua. -[<span class="nv">link1</span>]: <span class="sx">http://test.com/</span> <span class="nn">"Tuyệt!"</span> -[<span class="nv">foobar</span>]: <span class="sx">http://foobar.biz/</span> <span class="nn">"Tốt!"</span></code></pre> +[link1]: http://test.com/ "Tuyệt!" +[foobar]: http://foobar.biz/ "Tốt!" +``` Tiêu đề có thể được đóng trong dấu nháy hay ngoặc đơn, hoặc có thể được bỏ qua. Tham chiếu có thể được đặt bất kì đâu trong văn bản và ID của tham chiếu có thể là bất kì gì miễn là nó độc nhất. Ngoài ra còn có kiểu đặt tên ngầm cho phép ta sử dụng đường dẫn làm ID. -<pre><code class="highlight">[<span class="nv">This</span>][] is a link. +```md +[This][] is a link. -[<span class="nv">this</span>]: <span class="sx">http://thisisalink.com/</span></code></pre> +[this]: http://thisisalink.com/ +``` Nhưng nó không được sử dụng rộng rãi. @@ -270,9 +280,11 @@ Hiển thị ảnh tương tự như liên kết nhưng có thêm dấu chấm t Và kiểu tham chiếu cũng hoạt động như vậy. -<pre><code class="highlight">![<span class="nv">Đây là thuộc tính alt.</span>][<span class="ss">myimage</span>] +```md +![Đây là thuộc tính alt.][myimage] -[<span class="nv">myimage</span>]: <span class="sx">relative/urls/cool/image.jpg</span> <span class="nn">"Đây là tiêu đề"</span></code></pre> +[myimage]: relative/urls/cool/image.jpg "Đây là tiêu đề" +``` ## Khác @@ -297,12 +309,13 @@ Khi ta muốn viết *đoạn văn bản này có dấu sao bao quanh* nhưng ta ### Phím bàn phím -Trong Markdown của Github, ta có thể sử dụng thẻ `<kbd>` để thay cho phím trên bàn phím. +Trong Markdown của GitHub, ta có thể sử dụng thẻ `<kbd>` để thay cho phím trên bàn phím. ```md Máy treo? Thử bấm tổ hợp <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> ``` + ### Bảng biểu Bảng biểu được hỗ trợ trên Markdown của GitHub, Jira, Trello, v.v và khá khó viết: @@ -313,6 +326,7 @@ Bảng biểu được hỗ trợ trên Markdown của GitHub, Jira, Trello, v.v | Căn trái | Căn giữa | Căn phải | | blah | blah | blah | ``` + Hoặc có thể sử dụng kết quả dưới đây ```md diff --git a/vi-vn/objective-c-vi.html.markdown b/vi-vn/objective-c-vi.html.markdown index 8bc334ab..b01ce806 100644 --- a/vi-vn/objective-c-vi.html.markdown +++ b/vi-vn/objective-c-vi.html.markdown @@ -1,316 +1,316 @@ ----
-language: Objective-C
-contributors:
- - ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- - ["Yannick Loriot", "https://github.com/YannickL"]
-lang: vi-vn
-filename: LearnObjectiveC-vi.m
----
-
-Objective-C là ngôn ngữ lập trình chính được sử dụng bởi Apple cho các hệ điều hành OS X, iOS và các framework tương ứng của họ, Cocoa và Cocoa Touch.
-Nó là một ngôn ngữ lập trình mục đích tổng quát, hướng đối tượng có bổ sung thêm kiểu truyền thông điệp giống Smalltalk vào ngôn ngữ lập trình C.
-
-```objective-c
-// Chú thích dòng đơn bắt đầu với //
-
-/*
-Chú thích đa dòng trông như thế này.
-*/
-
-// Nhập các headers của framework Foundation với cú pháp #import
-#import <Foundation/Foundation.h>
-#import "MyClass.h"
-
-// Đầu vào chương trình của bạn là một hàm gọi là
-// main với một kiểu trả về kiểu integer.
-int main (int argc, const char * argv[])
-{
- // Tạo một autorelease pool để quản lý bộ nhớ vào chương trình
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
- // Sử dụng hàm NSLog() để in ra các dòng lệnh vào console
- NSLog(@"Hello World!"); // Print the string "Hello World!"
-
- ///////////////////////////////////////
- // Kiểu & Biến (Types & Variables)
- ///////////////////////////////////////
-
- // Khai báo số nguyên
- int myPrimitive1 = 1;
- long myPrimitive2 = 234554664565;
-
- // Khai báo đối tượng
- // Đặt dấu nháy * vào trước tên biến cho khai báo đối tượng strong
- MyClass *myObject1 = nil; // Strong
- id myObject2 = nil; // Weak
- // %@ là một đối tượng
- // 'miêu tả' ('desciption') là thông lệ để trình bày giá trị của các Đối tượng
- NSLog(@"%@ và %@", myObject1, [myObject2 description]); // In ra "(null) và (null)"
-
- // Chuỗi
- NSString *worldString = @"World";
- NSLog(@"Hello %@!", worldString); // In ra "Hello World!"
-
- // Ký tự literals
- NSNumber *theLetterZNumber = @'Z';
- char theLetterZ = [theLetterZNumber charValue];
- NSLog(@"%c", theLetterZ);
-
- // Số nguyên literals
- NSNumber *fortyTwoNumber = @42;
- int fortyTwo = [fortyTwoNumber intValue];
- NSLog(@"%i", fortyTwo);
-
- NSNumber *fortyTwoUnsignedNumber = @42U;
- unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue];
- NSLog(@"%u", fortyTwoUnsigned);
-
- NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
- short fortyTwoShort = [fortyTwoShortNumber shortValue];
- NSLog(@"%hi", fortyTwoShort);
-
- NSNumber *fortyTwoLongNumber = @42L;
- long fortyTwoLong = [fortyTwoLongNumber longValue];
- NSLog(@"%li", fortyTwoLong);
-
- // Dấu phẩy động (floating point) literals
- NSNumber *piFloatNumber = @3.141592654F;
- float piFloat = [piFloatNumber floatValue];
- NSLog(@"%f", piFloat);
-
- NSNumber *piDoubleNumber = @3.1415926535;
- double piDouble = [piDoubleNumber doubleValue];
- NSLog(@"%f", piDouble);
-
- // BOOL literals
- NSNumber *yesNumber = @YES;
- NSNumber *noNumber = @NO;
-
- // Đối tượng Mảng
- NSArray *anArray = @[@1, @2, @3, @4];
- NSNumber *thirdNumber = anArray[2];
- NSLog(@"Third number = %@", thirdNumber); // In ra "Third number = 3"
-
- // Đối tượng Từ điển
- NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
- NSObject *valueObject = aDictionary[@"A Key"];
- NSLog(@"Đối tượng = %@", valueObject); // In ra "Object = (null)"
-
- ///////////////////////////////////////
- // Toán Tử (Operators)
- ///////////////////////////////////////
-
- // Các toán tử cũng hoạt động giống như ngôn ngữ C
- // Ví dụ:
- 2 + 5; // => 7
- 4.2f + 5.1f; // => 9.3f
- 3 == 2; // => 0 (NO)
- 3 != 2; // => 1 (YES)
- 1 && 1; // => 1 (Logical and)
- 0 || 1; // => 1 (Logical or)
- ~0x0F; // => 0xF0 (bitwise negation)
- 0x0F & 0xF0; // => 0x00 (bitwise AND)
- 0x01 << 1; // => 0x02 (bitwise dịch trái (bởi 1))
-
- /////////////////////////////////////////////
- // Cấu Trúc Điều Khiển (Controls Structures)
- /////////////////////////////////////////////
-
- // Câu lệnh If-Else
- if (NO)
- {
- NSLog(@"I am never run");
- } else if (0)
- {
- NSLog(@"I am also never run");
- } else
- {
- NSLog(@"I print");
- }
-
- // Câu lệnh Switch
- switch (2)
- {
- case 0:
- {
- NSLog(@"I am never run");
- } break;
- case 1:
- {
- NSLog(@"I am also never run");
- } break;
- default:
- {
- NSLog(@"I print");
- } break;
- }
-
- // Câu lệnh vòng lặp While
- int ii = 0;
- while (ii < 4)
- {
- NSLog(@"%d,", ii++); // ii++ tăng dần, sau khi sử dụng giá trị của nó.
- } // => in ra "0,"
- // "1,"
- // "2,"
- // "3,"
-
- // Câu lệnh vòng lặp For
- int jj;
- for (jj=0; jj < 4; jj++)
- {
- NSLog(@"%d,", jj);
- } // => in ra "0,"
- // "1,"
- // "2,"
- // "3,"
-
- // Câu lệnh Foreach
- NSArray *values = @[@0, @1, @2, @3];
- for (NSNumber *value in values)
- {
- NSLog(@"%@,", value);
- } // => in ra "0,"
- // "1,"
- // "2,"
- // "3,"
-
- // Câu lệnh Try-Catch-Finally
- @try
- {
- // Your statements here
- @throw [NSException exceptionWithName:@"FileNotFoundException"
- reason:@"Không Tìm Thấy Tập Tin trên Hệ Thống" userInfo:nil];
- } @catch (NSException * e)
- {
- NSLog(@"Exception: %@", e);
- } @finally
- {
- NSLog(@"Finally");
- } // => in ra "Exception: Không Tìm Thấy Tập Tin trên Hệ Thống"
- // "Finally"
-
- ///////////////////////////////////////
- // Đối Tượng (Objects)
- ///////////////////////////////////////
-
- // Tạo một thực thể đối tượng bằng cách phân vùng nhớ và khởi tạo đối tượng đó.
- // Một đối tượng sẽ không thật sự hoạt động cho đến khi cả 2 bước alloc] init] được hoàn thành
- MyClass *myObject = [[MyClass alloc] init];
-
- // Mô hình lập trình hướng đối tượng của Objective-C dựa trên việc truyền thông điệp (message)
- // và các thực thể đối tượng với nhau.
- // Trong Objective-C một đối tượng không đơn thuần gọi phương thức; nó truyền thông điệp.
- [myObject instanceMethodWithParameter:@"Steve Jobs"];
-
- // Dọn dẹp vùng nhớ mà bạn đã dùng ở chương trình
- [pool drain];
-
- // Kết thúc chương trình
- return 0;
-}
-
-///////////////////////////////////////
-// Lớp và Hàm (Classes & Functions)
-///////////////////////////////////////
-
-// Khai báo lớp của bạn ở một tập tin header (MyClass.h):
-// Cú pháp Khai Báo Lớp:
-// @interface ClassName : ParentClassName <ImplementedProtocols>
-// {
-// Khai báo biến thành viên;
-// }
-// -/+ (type) Khai báo method;
-// @end
-@interface MyClass : NSObject <MyProtocol>
-{
- int count;
- id data;
- NSString *name;
-}
-// Ký hiệu (notation) tiện ích để tự động khởi tạo public getter và setter
-@property int count;
-@property (copy) NSString *name; // Sao chép đối tượng trong quá trình gán.
-@property (readonly) id data; // Chỉ khai báo phương thức getter.
-
-// Phương thức
-+/- (return type)methodSignature:(Parameter Type *)parameterName;
-
-// dấu '+' cho phương thức lớp
-+ (NSString *)classMethod;
-
-// dấu '-' cho phương thức thực thể
-- (NSString *)instanceMethodWithParameter:(NSString *)string;
-- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
-
-@end
-
-// Thực thi các phương thức trong một tập tin thực thi (MyClass.m):
-
-@implementation MyClass
-
-// Gọi khi đối tượng được release
-- (void)dealloc
-{
-}
-
-// Phương thức khởi tạo (Constructors) là một cách để tạo các lớp
-// Đây là phương thức khởi tạo mặc định được gọi khi đối tượng được khởi tạo
-- (id)init
-{
- if ((self = [super init]))
- {
- self.count = 1;
- }
- return self;
-}
-
-+ (NSString *)classMethod
-{
- return [[self alloc] init];
-}
-
-- (NSString *)instanceMethodWithParameter:(NSString *)string
-{
- return @"New string";
-}
-
-- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
-{
- return @42;
-}
-
-// Các phương thức được khai báo vào MyProtocol
-- (void)myProtocolMethod
-{
- // câu lệnh
-}
-
-@end
-
-/*
- * Một protocol khai báo các phương thức mà có thể thực thi bởi bất kỳ lớp nào.
- * Các protocol chính chúng không phải là các lớp. Chúng chỉ đơn giản là định ra giao diện (interface)
- * mà các đối tượng khác có trách nhiệm sẽ thực thi.
- */
-@protocol MyProtocol
- - (void)myProtocolMethod;
-@end
-
-
-
-```
-## Xem Thêm
-
-+ [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C)
-
-+ Apple Docs':
- + [Learning Objective-C](http://developer.apple.com/library/ios/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/)
-
- + [Programming With Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html)
-
- + [Object-Oriented Programming with Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/OOP_ObjC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40005149)
-
- + [Coding Guidelines for Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html)
-
-+ [iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started)
+--- +language: Objective-C +contributors: + - ["Eugene Yagrushkin", "www.about.me/yagrushkin"] + - ["Yannick Loriot", "https://github.com/YannickL"] +lang: vi-vn +filename: LearnObjectiveC-vi.m +--- + +Objective-C là ngôn ngữ lập trình chính được sử dụng bởi Apple cho các hệ điều hành macOS, iOS và các framework tương ứng của họ, Cocoa và Cocoa Touch. +Nó là một ngôn ngữ lập trình mục đích tổng quát, hướng đối tượng có bổ sung thêm kiểu truyền thông điệp giống Smalltalk vào ngôn ngữ lập trình C. + +```objective-c +// Chú thích dòng đơn bắt đầu với // + +/* +Chú thích đa dòng trông như thế này. +*/ + +// Nhập các headers của framework Foundation với cú pháp #import +#import <Foundation/Foundation.h> +#import "MyClass.h" + +// Đầu vào chương trình của bạn là một hàm gọi là +// main với một kiểu trả về kiểu integer. +int main (int argc, const char * argv[]) +{ + // Tạo một autorelease pool để quản lý bộ nhớ vào chương trình + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + // Sử dụng hàm NSLog() để in ra các dòng lệnh vào console + NSLog(@"Hello World!"); // Print the string "Hello World!" + + /////////////////////////////////////// + // Kiểu & Biến (Types & Variables) + /////////////////////////////////////// + + // Khai báo số nguyên + int myPrimitive1 = 1; + long myPrimitive2 = 234554664565; + + // Khai báo đối tượng + // Đặt dấu nháy * vào trước tên biến cho khai báo đối tượng strong + MyClass *myObject1 = nil; // Strong + id myObject2 = nil; // Weak + // %@ là một đối tượng + // 'miêu tả' ('desciption') là thông lệ để trình bày giá trị của các Đối tượng + NSLog(@"%@ và %@", myObject1, [myObject2 description]); // In ra "(null) và (null)" + + // Chuỗi + NSString *worldString = @"World"; + NSLog(@"Hello %@!", worldString); // In ra "Hello World!" + + // Ký tự literals + NSNumber *theLetterZNumber = @'Z'; + char theLetterZ = [theLetterZNumber charValue]; + NSLog(@"%c", theLetterZ); + + // Số nguyên literals + NSNumber *fortyTwoNumber = @42; + int fortyTwo = [fortyTwoNumber intValue]; + NSLog(@"%i", fortyTwo); + + NSNumber *fortyTwoUnsignedNumber = @42U; + unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; + NSLog(@"%u", fortyTwoUnsigned); + + NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42]; + short fortyTwoShort = [fortyTwoShortNumber shortValue]; + NSLog(@"%hi", fortyTwoShort); + + NSNumber *fortyTwoLongNumber = @42L; + long fortyTwoLong = [fortyTwoLongNumber longValue]; + NSLog(@"%li", fortyTwoLong); + + // Dấu phẩy động (floating point) literals + NSNumber *piFloatNumber = @3.141592654F; + float piFloat = [piFloatNumber floatValue]; + NSLog(@"%f", piFloat); + + NSNumber *piDoubleNumber = @3.1415926535; + double piDouble = [piDoubleNumber doubleValue]; + NSLog(@"%f", piDouble); + + // BOOL literals + NSNumber *yesNumber = @YES; + NSNumber *noNumber = @NO; + + // Đối tượng Mảng + NSArray *anArray = @[@1, @2, @3, @4]; + NSNumber *thirdNumber = anArray[2]; + NSLog(@"Third number = %@", thirdNumber); // In ra "Third number = 3" + + // Đối tượng Từ điển + NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" }; + NSObject *valueObject = aDictionary[@"A Key"]; + NSLog(@"Đối tượng = %@", valueObject); // In ra "Object = (null)" + + /////////////////////////////////////// + // Toán Tử (Operators) + /////////////////////////////////////// + + // Các toán tử cũng hoạt động giống như ngôn ngữ C + // Ví dụ: + 2 + 5; // => 7 + 4.2f + 5.1f; // => 9.3f + 3 == 2; // => 0 (NO) + 3 != 2; // => 1 (YES) + 1 && 1; // => 1 (Logical and) + 0 || 1; // => 1 (Logical or) + ~0x0F; // => 0xF0 (bitwise negation) + 0x0F & 0xF0; // => 0x00 (bitwise AND) + 0x01 << 1; // => 0x02 (bitwise dịch trái (bởi 1)) + + ///////////////////////////////////////////// + // Cấu Trúc Điều Khiển (Controls Structures) + ///////////////////////////////////////////// + + // Câu lệnh If-Else + if (NO) + { + NSLog(@"I am never run"); + } else if (0) + { + NSLog(@"I am also never run"); + } else + { + NSLog(@"I print"); + } + + // Câu lệnh Switch + switch (2) + { + case 0: + { + NSLog(@"I am never run"); + } break; + case 1: + { + NSLog(@"I am also never run"); + } break; + default: + { + NSLog(@"I print"); + } break; + } + + // Câu lệnh vòng lặp While + int ii = 0; + while (ii < 4) + { + NSLog(@"%d,", ii++); // ii++ tăng dần, sau khi sử dụng giá trị của nó. + } // => in ra "0," + // "1," + // "2," + // "3," + + // Câu lệnh vòng lặp For + int jj; + for (jj=0; jj < 4; jj++) + { + NSLog(@"%d,", jj); + } // => in ra "0," + // "1," + // "2," + // "3," + + // Câu lệnh Foreach + NSArray *values = @[@0, @1, @2, @3]; + for (NSNumber *value in values) + { + NSLog(@"%@,", value); + } // => in ra "0," + // "1," + // "2," + // "3," + + // Câu lệnh Try-Catch-Finally + @try + { + // Your statements here + @throw [NSException exceptionWithName:@"FileNotFoundException" + reason:@"Không Tìm Thấy Tập Tin trên Hệ Thống" userInfo:nil]; + } @catch (NSException * e) + { + NSLog(@"Exception: %@", e); + } @finally + { + NSLog(@"Finally"); + } // => in ra "Exception: Không Tìm Thấy Tập Tin trên Hệ Thống" + // "Finally" + + /////////////////////////////////////// + // Đối Tượng (Objects) + /////////////////////////////////////// + + // Tạo một thực thể đối tượng bằng cách phân vùng nhớ và khởi tạo đối tượng đó. + // Một đối tượng sẽ không thật sự hoạt động cho đến khi cả 2 bước alloc] init] được hoàn thành + MyClass *myObject = [[MyClass alloc] init]; + + // Mô hình lập trình hướng đối tượng của Objective-C dựa trên việc truyền thông điệp (message) + // và các thực thể đối tượng với nhau. + // Trong Objective-C một đối tượng không đơn thuần gọi phương thức; nó truyền thông điệp. + [myObject instanceMethodWithParameter:@"Steve Jobs"]; + + // Dọn dẹp vùng nhớ mà bạn đã dùng ở chương trình + [pool drain]; + + // Kết thúc chương trình + return 0; +} + +/////////////////////////////////////// +// Lớp và Hàm (Classes & Functions) +/////////////////////////////////////// + +// Khai báo lớp của bạn ở một tập tin header (MyClass.h): +// Cú pháp Khai Báo Lớp: +// @interface ClassName : ParentClassName <ImplementedProtocols> +// { +// Khai báo biến thành viên; +// } +// -/+ (type) Khai báo method; +// @end +@interface MyClass : NSObject <MyProtocol> +{ + int count; + id data; + NSString *name; +} +// Ký hiệu (notation) tiện ích để tự động khởi tạo public getter và setter +@property int count; +@property (copy) NSString *name; // Sao chép đối tượng trong quá trình gán. +@property (readonly) id data; // Chỉ khai báo phương thức getter. + +// Phương thức ++/- (return type)methodSignature:(Parameter Type *)parameterName; + +// dấu '+' cho phương thức lớp ++ (NSString *)classMethod; + +// dấu '-' cho phương thức thực thể +- (NSString *)instanceMethodWithParameter:(NSString *)string; +- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number; + +@end + +// Thực thi các phương thức trong một tập tin thực thi (MyClass.m): + +@implementation MyClass + +// Gọi khi đối tượng được release +- (void)dealloc +{ +} + +// Phương thức khởi tạo (Constructors) là một cách để tạo các lớp +// Đây là phương thức khởi tạo mặc định được gọi khi đối tượng được khởi tạo +- (id)init +{ + if ((self = [super init])) + { + self.count = 1; + } + return self; +} + ++ (NSString *)classMethod +{ + return [[self alloc] init]; +} + +- (NSString *)instanceMethodWithParameter:(NSString *)string +{ + return @"New string"; +} + +- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number +{ + return @42; +} + +// Các phương thức được khai báo vào MyProtocol +- (void)myProtocolMethod +{ + // câu lệnh +} + +@end + +/* + * Một protocol khai báo các phương thức mà có thể thực thi bởi bất kỳ lớp nào. + * Các protocol chính chúng không phải là các lớp. Chúng chỉ đơn giản là định ra giao diện (interface) + * mà các đối tượng khác có trách nhiệm sẽ thực thi. + */ +@protocol MyProtocol + - (void)myProtocolMethod; +@end + + + +``` +## Xem Thêm + ++ [Wikipedia Objective-C](http://en.wikipedia.org/wiki/Objective-C) + ++ Apple Docs': + + [Learning Objective-C](http://developer.apple.com/library/ios/referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/) + + + [Programming With Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html) + + + [Object-Oriented Programming with Objective-C](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/OOP_ObjC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40005149) + + + [Coding Guidelines for Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html) + ++ [iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started) diff --git a/vi-vn/python3-vi.html.markdown b/vi-vn/python-vi.html.markdown index f6cce1a3..89e51d5d 100644 --- a/vi-vn/python3-vi.html.markdown +++ b/vi-vn/python-vi.html.markdown @@ -1,6 +1,6 @@ --- -language: python3 -filename: learnpython3-vi.py +language: Python +filename: learnpython-vi.py contributors: - ["Louie Dinh", "http://pythonpracticeprojects.com"] - ["Steven Basart", "http://github.com/xksteven"] @@ -19,7 +19,7 @@ như một loại mã giả (pseudocode) có thể thực thi được. Mọi phản hồi đều sẽ được tích cực ghi nhận! Bạn có thể liên lạc với tôi qua Twitter [@louiedinh](http://twitter.com/louiedinh) hoặc louiedinh [at] [google's email service] -Lưu ý: Bài viết này áp dụng riêng cho Python 3. Truy cập [vào đây](http://learnxinyminutes.com/docs/python/) nếu bạn muốn học phiên bản cũ Python 2.7 +Lưu ý: Bài viết này áp dụng riêng cho Python 3. Truy cập [vào đây](http://learnxinyminutes.com/docs/pythonlegacy/) nếu bạn muốn học phiên bản cũ Python 2.7 ```python diff --git a/vi-vn/xml-vi.html.markdown b/vi-vn/xml-vi.html.markdown new file mode 100644 index 00000000..7a74c154 --- /dev/null +++ b/vi-vn/xml-vi.html.markdown @@ -0,0 +1,170 @@ +--- +language: xml +filename: learnxml.xml +contributors: + - ['João Farias', 'https://github.com/JoaoGFarias'] + - ['Rachel Stiyer', 'https://github.com/rstiyer'] + - ['Deepanshu Utkarsh', 'https://github.com/duci9y'] +translators: + - ['Thanh Duy Phan', 'https://github.com/thanhpd'] +lang: vi-vn +--- + +XML là ngôn ngữ đánh dấu được thiết kế để lưu trữ và truyền tải dữ liệu. Nó có thể được đọc hiểu bởi cả người và máy. + +Không giống như HTML, XML không biểu đạt cách hiển thị hoặc định dạng dữ liệu, chỉ chứa dữ liệu mà thôi. + +Có những sự khác biệt rõ ràng giữa **nội dung** và **các đánh dấu**. Nói vắn tắt thì nội dung có thể là bất cứ gì trong khi các đánh dấu được định nghĩa trước. + +## Một số định nghĩa và giới thiệu + +Các XML Document (Văn bản XML) được cấu thành bởi các _elements (phần tử)_ và chúng có thể có các _attributes (thuộc tính)_ để mô tả, đồng thời cũng có thể chứa các nội dung theo ngữ cảnh và một hoặc nhiều phần tử con. Tất cả XML document phải có một phần tử gốc đóng vai trò tổ tiên cho tất cả các phần tử khác trong văn bản. + +Các trình phân tích cú pháp XML (XML Parser) được thiết kế để phân tích rất chặt chẽ, và sẽ dừng phân tích các văn bản không đúng định dạng. Vì vậy cần đảm bảo tất cả văn bản XML tuân theo [Các luật cú pháp XML](http://www.w3schools.com/xml/xml_syntax.asp). + +```xml +<!-- Đây là một bình luận. Nó không được phép chứa hai dấu gạch ngang (-) liên tiếp --> +<!-- Comments can span + trải dài nhiều dòngmultiple lines --> + +<!-- Element - Phần tử --> +<!-- Một element là thành phần XML cơ bản nhất. Có hai loại, thử nhất là rỗng nô --> +<element1 thuoc-tinh="gia trialue" /> <Các element rỗng không chứa bất kì nội dung gìtent --> +<!-- và không rỗng nội dung: --> +<element2 thuoc-tinh="gia tri">Nội dung</element2> +<!-- Tên của element chỉ được phép chứa chữ cái và chữ số --> + +<empty /> <!-- Một element có thể là một element với tag rỗng… --> +<!-- …không chứa bất cứ nội dung gì và chỉ là markup đơn thuần. --> + +<notempty> <!-- Hoặc nó chứa một tag bắt đầu… --> + <!-- …nội dung… --> +</notempty> <!-- và kết thúc với tag đóng. --> + +<!-- Tên element phân biệt chữ hoa và thường. --> +<element /> +<!-- không giống như --> +<eLEMENT /> + +<!-- Attribute - Thuộc tính --> +<!-- Một thuộc tính là một cặp key-value và tồn tại bên trong element. --> +<element thuoctinh="giatri" thuoctinhkhac="giatrikhac" nhieugiatri="danhsach phanbiet bangdaucach" /> +<!-- Một thuộc tính chỉ xuất hiện một lần trong một element. Nó chỉ chứa một giá trị. + Một cách giải quyết là sử dụng danh sách giá trị được phân biệt bởi dấu cách. --> + +<!-- Nesting element - Phần tử lồng nhau --> +<!-- Nội dung một element có thể chứa các element khác --> +<cha> + <con>Text</con> + <elementrong /> +</cha> +<!-- Danh pháp cây tiêu chuẩn được tuân theo. Mỗi phần tử được gọi là một nút. + Phần tử cấp trên là cha, phần tử cấp dưới là con. + Các element trong cùng một element cha có mức tương đương nhau như anh chị em. --> + +<!-- XML bảo lưu dấu cách. --> +<child> + Văn bản +</child> +<!-- sẽ không giống như --> +<child>Văn bản</child> +``` + +## Một văn bản XML - XML document + +Đây là thứ làm cho XML rất linh hoạt do nó giúp con người cũng đọc được. Văn bản sau đây cho ta biết nó định nghĩa một hiệu sách bản ba quyển sách, trong đó có một cuốn tên Learning XML bởi Erik T. Ray. Tất cả những việc này chưa cần phải sử dụng XML Parser. + +```xml +<?xml version="1.0" encoding="UTF-8"?> +<!-- Đây là phần mở đầu, không bắt buộc cần nhưng nên có --> +<hieusach> + <sach danhmuc="NAUAN"> + <tieude lang="en">Everyday Italian</tieude> + <tacgia>Giada De Laurentiis</tacgia> + <nam>2005</nam> + <giaban>30.00</giaban> + </sach> + <sach danhmuc="TREEM"> + <tieude lang="en">Harry Potter</tieude> + <tacgia>J K. Rowling</tacgia> + <nam>2005</nam> + <giaban>29.99</giaban> + </sach> + <sach danhmuc="WEB"> + <tieude lang="en">Learning XML</tieude> + <tacgia>Erik T. Ray</tacgia> + <nam>2003</nam> + <giaban>39.95</giaban> + </sach> +</hieusach> +``` + +## Tính đúng đắn và việc xác minh + +Một văn bản XML là _đúng đắn (well-formed)_ nếu nó có cú pháp chính xác. Ty nhiên, ta có thể thêm nhiều ràng buộc vào văn bản, sử dụng Document Type Definition (DTD) - Định dạng loại văn bản. Một văn bản mà các phần tử và thuộc tính được khai báo trong một DTĐ và tuân theo ngữ pháp được đưa ra trong DTD đó được gọi là _valid - được chấp nhận_ và tuân theo DTD bên cạnh việc đúng đắn. + +```xml +<!-- Khai báo DTD lấy từ tệp bên ngoài: --> +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE hieusach SYSTEM "Hieusach.dtd"> +<!-- Khai báo hieusach là phần tử gốc và 'Hieusach.dtd' là đường dẫn + tới tệp DTD. --> +<hieusach> + <sach danhmuc="NAUAN"> + <tieude lang="en">Everyday Italian</tieude> + <tacgia>Giada De Laurentiis</tacgia> + <nam>2005</nam> + <giaban>30.00</giaban> + </sach> +</hieusach> + +<!-- Tệp DTD: --> +<!ELEMENT hieusach (sach+)> +<!-- Element hieusach có thể chứa một hoặc nhiều element sach. --> +<!ELEMENT sach (tieude, giaban)> +<!-- Mỗi sach cần có các element con tên tieude và giaban. --> +<!ATTLIST sach danhmuc CDATA "Vanhoc"> +<!-- Mỗi sach cần có một thuộc tính danhmuc. Nếu không có, giá trị mặc định + sẽ là 'Vanhoc'. --> +<!ELEMENT tieude (#PCDATA)> +<!-- Element tieude chỉ được chứa nội dung dữ liệu kĩ tự được phân tích. +Nói cách khác, nó có thể + chỉ chứa văn bản được phân tích bởi parser và không được phép chứa element con + So sánh với CDATA, hay dữ liệu kí tự --> +<!ELEMENT giaban (#PCDATA)> +]> + +<!-- DTD có thể được khai báo bên trong chính tệp XML.--> + +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE hieusach [ +<!ELEMENT hieusach (sach+)> +<!ELEMENT sach (tieude, giaban)> +<!ATTLIST sach danhmuc CDATA "Vanhoc"> +<!ELEMENT tieude (#PCDATA)> +<!ELEMENT giaban (#PCDATA)> +]> + +<hieusach> + <sach danhmuc="NAUAN"> + <tieude lang="en">Everyday Italian</tieude> + <giaban>30.00</giaban> + </sach> +</hieusach> +``` + +## DTD Compatibility and XML Schema Definitions (Tương thích DTD và định nghĩa XML Schema) + +Hỗ trợ cho DTD khá nhiều do chúng đã quá cũ. Tuy nhiên, nhiều tính năng hiện đại của XML như namespace không được hỗ trợ bởi DTD. XML Schema Definition (XSD) - Định nghĩa lược đồ XML được coi như sẽ thay thế DTD để định nghĩa cấu trúc ngữ pháp của văn bản XML. + +## Tra cứu + +- [Validate your XML (Xác minh XML)](http://www.xmlvalidation.com) + +## Đọc thêm + +- [Hướng dẫn XML Schema Definitions](http://www.w3schools.com/schema/) +- [Hướng dẫn DTD](http://www.w3schools.com/xml/xml_dtd_intro.asp) +- [Hướng dẫn XML](http://www.w3schools.com/xml/default.asp) +- [Dùng XPath queries để phân tích cú pháp XML](http://www.w3schools.com/xml/xml_xpath.asp) diff --git a/vim.html.markdown b/vim.html.markdown index 5b84a3ea..fb2fc81f 100644 --- a/vim.html.markdown +++ b/vim.html.markdown @@ -3,6 +3,7 @@ category: tool tool: vim contributors: - ["RadhikaG", "https://github.com/RadhikaG"] + - ["kaymmm", "https://github.com/kaymmm"] filename: LearnVim.txt --- @@ -13,72 +14,77 @@ editor designed for speed and increased productivity, and is ubiquitous in most unix-based systems. It has numerous keybindings for speedy navigation to specific points in the file, and for fast editing. +`vimtutor` is a an excellent application that teaches you how to use `Vim`. It comes with the vim package during installation. You should be able to just run "vimtutor" on the command line to open this tutor. It will guide you through all the major features in `vim`. + + ## Basics of navigating Vim ``` - vim <filename> # Open <filename> in vim - :help <topic> # Open up built-in help docs about <topic> if any exists - :q # Quit vim - :w # Save current file - :wq # Save file and quit vim - ZZ # Save file and quit vim - :q! # Quit vim without saving file - # ! *forces* :q to execute, hence quiting vim without saving - :x # Save file and quit vim, shorter version of :wq - - u # Undo - CTRL+R # Redo - - h # Move left one character - j # Move down one line - k # Move up one line - l # Move right one character - - Ctrl+B # Move back one full screen - Ctrl+F # Move forward one full screen - Ctrl+D # Move forward 1/2 a screen - Ctrl+U # Move back 1/2 a screen + vim <filename> # Open <filename> in vim + :help <topic> # Open up built-in help docs about <topic> if any exists + :q # Quit vim + :w # Save current file + :wq # Save file and quit vim + ZZ # Save file and quit vim + :q! # Quit vim without saving file + # ! *forces* :q to execute, hence quitting vim without saving + ZQ # Quit vim without saving file + :x # Save file(only when the file is modified) and quit vim + + u # Undo + CTRL+R # Redo + + h # Move left one character + j # Move down one line + k # Move up one line + l # Move right one character + + Ctrl+B # Move back one full screen + Ctrl+F # Move forward one full screen + Ctrl+D # Move forward 1/2 a screen + Ctrl+U # Move back 1/2 a screen # Moving within the line - 0 # Move to beginning of line - $ # Move to end of line - ^ # Move to first non-blank character in line + 0 # Move to beginning of line + $ # Move to end of line + ^ # Move to first non-blank character in line # Searching in the text - /word # Highlights all occurrences of word after cursor - ?word # Highlights all occurrences of word before cursor - n # Moves cursor to next occurrence of word after search - N # Moves cursor to previous occerence of word + /word # Highlights all occurrences of word after cursor + ?word # Highlights all occurrences of word before cursor + n # Moves cursor to next occurrence of word after search + N # Moves cursor to previous occurrence of word - :%s/foo/bar/g # Change 'foo' to 'bar' on every line in the file - :s/foo/bar/g # Change 'foo' to 'bar' on the current line - :%s/\n/\r/g # Replace new line characters with new line characters + :%s/foo/bar/g # Change 'foo' to 'bar' on every line in the file + :s/foo/bar/g # Change 'foo' to 'bar' on the current line + :%s/\n/\r/g # Replace new line characters with new line characters + :'<,'>s/foo/bar/g # Change 'foo' to 'bar on every line in the current visual selection # Jumping to characters - f<character> # Jump forward and land on <character> - t<character> # Jump forward and land right before <character> + f<character> # Jump forward and land on <character> + t<character> # Jump forward and land right before <character> # For example, - f< # Jump forward and land on < - t< # Jump forward and land right before < + f< # Jump forward and land on < + t< # Jump forward and land right before < # Moving by word - w # Move forward by one word - b # Move back by one word - e # Move to end of current word + w # Move forward by one word + b # Move back by one word + e # Move to end of current word # Other characters for moving around - gg # Go to the top of the file - G # Go to the bottom of the file - :NUM # Go to line number NUM (NUM is any number) - H # Move to the top of the screen - M # Move to the middle of the screen - L # Move to the bottom of the screen + gg # Go to the top of the file + G # Go to the bottom of the file + :NUM # Go to line number NUM (NUM is any number) + H # Move to the top of the screen + M # Move to the middle of the screen + L # Move to the bottom of the screen ``` ## Help docs: @@ -100,21 +106,28 @@ Vim is based on the concept on **modes**. - Ex Mode - used to drop down to the bottom with the ':' prompt to enter commands ``` - i # Puts vim into insert mode, before the cursor position - a # Puts vim into insert mode, after the cursor position - v # Puts vim into visual mode - : # Puts vim into ex mode - <esc> # 'Escapes' from whichever mode you're in, into Command mode + i # Puts vim into insert mode, before the cursor position + a # Puts vim into insert mode, after the cursor position + v # Puts vim into visual mode + : # Puts vim into ex mode + <esc> # 'Escapes' from whichever mode you're in, into Command mode # Copying and pasting text + # Operations use the vim register by default + # Think of it as vim's private clipboard + + # Yank ~ copy text into vim register + y # Yank whatever is selected + yy # Yank the current line + + # Delete ~ yank text and delete from file + d # Delete whatever is selected + dd # Delete the current line + + p # Paste text in vim register after the current cursor position + P # Paste text in vim register before the current cursor position - y # Yank whatever is selected - yy # Yank the current line - d # Delete whatever is selected - dd # Delete the current line - p # Paste the copied text after the current cursor position - P # Paste the copied text before the current cursor position - x # Deleting character under current cursor position + x # Delete character under current cursor position ``` ## The 'Grammar' of vim @@ -131,63 +144,75 @@ A few important examples of 'Verbs', 'Modifiers', and 'Nouns': ``` # 'Verbs' - d # Delete - c # Change - y # Yank (copy) - v # Visually select + d # Delete + c # Change + y # Yank (copy) + v # Visually select # 'Modifiers' - i # Inside - a # Around - NUM # Number (NUM is any number) - f # Searches for something and lands on it - t # Searches for something and stops before it - / # Finds a string from cursor onwards - ? # Finds a string before cursor + i # Inside + a # Around + NUM # Number (NUM is any number) + f # Searches for something and lands on it + t # Searches for something and stops before it + / # Finds a string from cursor onwards + ? # Finds a string before cursor # 'Nouns' - w # Word - s # Sentence - p # Paragraph - b # Block + w # Word + s # Sentence + p # Paragraph + b # Block # Sample 'sentences' or commands - d2w # Delete 2 words - cis # Change inside sentence - yip # Yank inside paragraph (copy the para you're in) - ct< # Change to open bracket - # Change the text from where you are to the next open bracket - d$ # Delete till end of line + d2w # Delete 2 words + cis # Change inside sentence + yip # Yank inside paragraph (copy the para you're in) + ct< # Change to open bracket + # Change the text from where you are to the next open bracket + d$ # Delete till end of line ``` ## Some shortcuts and tricks <!--TODO: Add more!--> ``` - > # Indent selection by one block - < # Dedent selection by one block - :earlier 15m # Reverts the document back to how it was 15 minutes ago - :later 15m # Reverse above command - ddp # Swap position of consecutive lines, dd then p - . # Repeat previous action - :w !sudo tee % # Save the current file as root - :set syntax=c # Set syntax highlighting to 'c' - :sort # Sort all lines - :sort! # Sort all lines in reverse - :sort u # Sort all lines and remove duplicates - ~ # Toggle letter case of selected text - u # Selected text to lower case - U # Selected text to upper case + > # Indent selection by one block + < # Dedent selection by one block + :earlier 15m # Reverts the document back to how it was 15 minutes ago + :later 15m # Reverse above command + ddp # Swap position of consecutive lines, dd then p + . # Repeat previous action + :w !sudo tee % # Save the current file as root + :set syntax=c # Set syntax highlighting to 'c' + :sort # Sort all lines + :sort! # Sort all lines in reverse + :sort u # Sort all lines and remove duplicates + ~ # Toggle letter case of selected text + u # Selected text to lower case + U # Selected text to upper case + J # Join the current line with the next line # Fold text - zf # Create fold from selected text - zo # Open current fold - zc # Close current fold - zR # Open all folds - zM # Close all folds + zf # Create fold from selected text + zd # Delete fold on the current line + zD # Recursively delete nested or visually selected folds + zE # Eliminate all folds in the window + zo # Open current fold + zO # Recursively open nested or visually selected folds + zc # Close current fold + zC # Recursively close nested or visually selected folds + zR # Open all folds + zM # Close all folds + za # Toggle open/close current fold + zA # Recursively toggle open/close nested fold + [z # Move to the start of the current fold + ]z # Move to the end of the current fold + zj # Move to the start of the next fold + zk # Move to the end of the previous fold ``` ## Macros @@ -198,9 +223,9 @@ you use, until you stop recording. On invoking a macro, it applies the exact same sequence of actions and commands again on the text selection. ``` - qa # Start recording a macro named 'a' - q # Stop recording - @a # Play back the macro + qa # Start recording a macro named 'a' + q # Stop recording + @a # Play back the macro ``` ### Configuring ~/.vimrc diff --git a/vimscript.html.markdown b/vimscript.html.markdown new file mode 100644 index 00000000..04fee6fa --- /dev/null +++ b/vimscript.html.markdown @@ -0,0 +1,658 @@ +--- +language: Vimscript +filename: learnvimscript.vim +contributors: + - ["HiPhish", "http://hiphish.github.io/"] +--- + +```vim +" ############## +" Introduction +" ############## +" +" Vim script (also called VimL) is the subset of Vim's ex-commands which +" supplies a number of features one would expect from a scripting language, +" such as values, variables, functions or loops. Always keep in the back of +" your mind that a Vim script file is just a sequence of ex-commands. It is +" very common for a script to mix programming-language features and raw +" ex-commands. +" +" You can run Vim script directly by entering the commands in command-line mode +" (press `:` to enter command-line mode), or you can write them to a file +" (without the leading `:`) and source it in a running Vim instance (`:source +" path/to/file`). Some files are sourced automatically as part of your +" configuration (see |startup|). This guide assumes that you are familiar +" with ex-commands and will only cover the scripting. Help topics to the +" relevant manual sections are included. +" +" See |usr_41.txt| for the official introduction to Vim script. A comment is +" anything following an unmatched `"` until the end of the line, and `|` +" separates instructions (what `;` does in most other languages). References to +" the manual as surrounded with `|`, such as |help.txt|. + +" This is a comment + +" The vertical line '|' (pipe) separates commands +echo 'Hello' | echo 'world!' + +" Putting a comment after a command usually works +pwd " Displays the current working directory + +" Except for some commands it does not; use the command delimiter before the +" comment (echo assumes that the quotation mark begins a string) +echo 'Hello world!' | " Displays a message + +" Line breaks can be escaped by placing a backslash as the first non-whitespace +" character on the *following* line. Only works in script files, not on the +" command line +echo " Hello + \ world " + +echo [1, + \ 2] + +echo { + \ 'a': 1, + \ 'b': 2 +\} + + +" ####### +" Types +" ####### +" +" For an overview of types see |E712|. For an overview of operators see +" |expression-syntax| + +" Numbers (|expr-number|) +" ####### + +echo 123 | " Decimal +echo 0b1111011 | " Binary +echo 0173 | " Octal +echo 0x7B | " Hexadecimal +echo 123.0 | " Floating-point +echo 1.23e2 | " Floating-point (scientific notation) + +" Note that an *integer* number with a leading `0` is in octal notation. The +" usual arithmetic operations are supported. + +echo 1 + 2 | " Addition +echo 1 - 2 | " Subtraction +echo - 1 | " Negation (unary minus) +echo + 1 | " Unary plus (does nothing really, but still legal) +echo 1 * 2 | " Multiplication +echo 1 / 2 | " Division +echo 1 % 2 | " Modulo (remainder) + +" Booleans (|Boolean|) +" ######## +" +" The number 0 is false, every other number is true. Strings are implicitly +" converted to numbers (see below). There are two pre-defined semantic +" constants. + +echo v:true | " Evaluates to 1 or the string 'v:true' +echo v:false | " Evaluates to 0 or the string 'v:false' + +" Boolean values can result from comparison of two objects. + +echo x == y | " Equality by value +echo x != y | " Inequality +echo x > y | " Greater than +echo x >= y | " Greater than or equal +echo x < y | " Smaller than +echo x <= y | " Smaller than or equal +echo x is y | " Instance identity (lists and dictionaries) +echo x isnot y | " Instance non-identity (lists and dictionaries) + +" Strings are compared based on their alphanumerical ordering +" echo 'a' < 'b'. Case sensitivity depends on the setting of 'ignorecase' +" +" Explicit case-sensitivity is specified by appending '#' (match case) or '?' +" (ignore case) to the operator. Prefer explicitly case sensitivity when writing +" portable scripts. + +echo 'a' < 'B' | " True or false depending on 'ignorecase' +echo 'a' <? 'B' | " True +echo 'a' <# 'B' | " False + +" Regular expression matching +echo "hi" =~ "hello" | " Regular expression match, uses 'ignorecase' +echo "hi" =~# "hello" | " Regular expression match, case sensitive +echo "hi" =~? "hello" | " Regular expression match, case insensitive +echo "hi" !~ "hello" | " Regular expression unmatch, use 'ignorecase' +echo "hi" !~# "hello" | " Regular expression unmatch, case sensitive +echo "hi" !~? "hello" | " Regular expression unmatch, case insensitive + +" Boolean operations are possible. + +echo v:true && v:false | " Logical AND +echo v:true || v:false | " Logical OR +echo ! v:true | " Logical NOT +echo v:true ? 'yes' : 'no' | " Ternary operator + + +" Strings (|String|) +" ####### +" +" An ordered zero-indexed sequence of bytes. The encoding of text into bytes +" depends on the option |'encoding'|. + +" Literal constructors +echo "Hello world\n" | " The last two characters stand for newline +echo 'Hello world\n' | " The last two characters are literal +echo 'Let''s go!' | " Two single quotes become one quote character + +" Single-quote strings take all characters are literal, except two single +" quotes, which are taken to be a single quote in the string itself. See +" |expr-quote| for all possible escape sequences. + +" String concatenation +" The .. operator is preferred, but only supported in since Vim 8.1.1114 +echo 'Hello ' . 'world' | " String concatenation +echo 'Hello ' .. 'world' | " String concatenation (new variant) + +" String indexing +echo 'Hello'[0] | " First byte +echo 'Hello'[1] | " Second byte +echo 'Hellö'[4] | " Returns a byte, not the character 'ö' + +" Substrings (second index is inclusive) +echo 'Hello'[:] | " Copy of entire string +echo 'Hello'[1:3] | " Substring, second to fourth byte +echo 'Hello'[1:-2] | " Substring until second to last byte +echo 'Hello'[1:] | " Substring with starting index +echo 'Hello'[:2] | " Substring with ending index +echo 'Hello'[-2:] | " Substring relative to end of string + +" A negative index is relative to the end of the string. See +" |string-functions| for all string-related functions. + +" Lists (|List|) +" ##### +" +" An ordered zero-indexed heterogeneous sequence of arbitrary Vim script +" objects. + +" Literal constructor +echo [] | " Empty list +echo [1, 2, 'Hello'] | " List with elements +echo [1, 2, 'Hello', ] | " Trailing comma permitted +echo [[1, 2], 'Hello'] | " Lists can be nested arbitrarily + +" List concatenation +echo [1, 2] + [3, 4] | " Creates a new list + +" List indexing, negative is relative to end of list (|list-index|) +echo [1, 2, 3, 4][2] | " Third element +echo [1, 2, 3, 4][-1] | " Last element + +" List slicing (|sublist|) +echo [1, 2, 3, 4][:] | " Shallow copy of entire list +echo [1, 2, 3, 4][:2] | " Sublist until third item (inclusive) +echo [1, 2, 3, 4][2:] | " Sublist from third item (inclusive) +echo [1, 2, 3, 4][:-2] | " Sublist until second-to-last item (inclusive) + +" All slicing operations create new lists. To modify a list in-place use list +" functions (|list-functions|) or assign directly to an item (see below about +" variables). + + +" Dictionaries (|Dictionary|) +" ############ +" +" An unordered sequence of key-value pairs, keys are always strings (numbers +" are implicitly converted to strings). + +" Dictionary literal +echo {} | " Empty dictionary +echo {'a': 1, 'b': 2} | " Dictionary literal +echo {'a': 1, 'b': 2, } | " Trailing comma permitted +echo {'x': {'a': 1, 'b': 2}} | " Nested dictionary + +" Indexing a dictionary +echo {'a': 1, 'b': 2}['a'] | " Literal index +echo {'a': 1, 'b': 2}.a | " Syntactic sugar for simple keys + +" See |dict-functions| for dictionary manipulation functions. + + +" Funcref (|Funcref|) +" ####### +" +" Reference to a function, uses the function name as a string for construction. +" When stored in a variable the name of the variable has the same restrictions +" as a function name (see below). + +echo function('type') | " Reference to function type() +" Note that `funcref('type')` will throw an error because the argument must be +" a user-defined function; see further below for defining your own functions. +echo funcref('type') | " Reference by identity, not name +" A lambda (|lambda|) is an anonymous function; it can only contain one +" expression in its body, which is also its implicit return value. +echo {x -> x * x} | " Anonymous function +echo function('substitute', ['hello']) | " Partial function + + +" Regular expression (|regular-expression|) +" ################## +" +" A regular expression pattern is generally a string, but in some cases you can +" also use a regular expression between a pair of delimiters (usually `/`, but +" you can choose anything). + +" Substitute 'hello' for 'Hello' +substitute/hello/Hello/ + + +" ########################### +" Implicit type conversions +" ########################### +" +" Strings are converted to numbers, and numbers to strings when necessary. A +" number becomes its decimal notation as a string. A string becomes its +" numerical value if it can be parsed to a number, otherwise it becomes zero. + +echo "1" + 1 | " Number +echo "1" .. 1 | " String +echo "0xA" + 1 | " Number + +" Strings are treated like numbers when used as booleans +echo "true" ? 1 : 0 | " This string is parsed to 0, which is false + +" ########### +" Variables +" ########### +" +" Variables are bound within a scope; if no scope is provided a default is +" chosen by Vim. Use `:let` and `:const` to bind a value and `:unlet` to unbind +" it. + +let b:my_var = 1 | " Local to current buffer +let w:my_var = 1 | " Local to current window +let t:my_var = 1 | " Local to current tab page +let g:my_var = 1 | " Global variable +let l:my_var = 1 | " Local to current function (see functions below) +let s:my_var = 1 | " Local to current script file +let a:my_arg = 1 | " Function argument (see functions below) + +" The Vim scope is read-only +echo v:true | " Special built-in Vim variables (|v:var|) + +" Access special Vim memory like variables +let @a = 'Hello' | " Register +let $PATH='' | " Environment variable +let &textwidth = 79 | " Option +let &l:textwidth = 79 | " Local option +let &g:textwidth = 79 | " Global option + +" Access scopes as dictionaries (can be modified like all dictionaries) +" See the |dict-functions|, especially |get()|, for access and manipulation +echo b: | " All buffer variables +echo w: | " All window variables +echo t: | " All tab page variables +echo g: | " All global variables +echo l: | " All local variables +echo s: | " All script variables +echo a: | " All function arguments +echo v: | " All Vim variables + +" Constant variables +const x = 10 | " See |:const|, |:lockvar| + +" Function reference variables have the same restrictions as function names +let IsString = {x -> type(x) == type('')} | " Global: capital letter +let s:isNumber = {x -> type(x) == type(0)} | " Local: any name allowed + +" When omitted the scope `g:` is implied, except in functions, there `l:` is +" implied. + + +" Multiple value binding (list unpacking) +" ####################################### +" +" Assign values of list to multiple variables (number of items must match) +let [x, y] = [1, 2] + +" Assign the remainder to a rest variable (note the semicolon) +let [mother, father; children] = ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily'] + + +" ############## +" Flow control +" ############## + +" Conditional (|:if|, |:elseif|, |:else|, |:endif|) +" ########### +" +" Conditions are set between `if` and `endif`. They can be nested. + +let condition = v:true + +if condition + echo 'First condition' +elseif another_condition + echo 'Second condition' +else + echo 'Fail' +endif + +" Loops (|:for|, |:endfor|, |:while|, |:endwhile|, |:break|, |:continue|) +" ##### +" +" Two types of loops: `:for` and `:while`. Use `:continue` to skip to the next +" iteration, `:break` to break out of the loop. + +" For-loop (|:for|, |:endfor|) +" ======== +" +" For-loops iterate over lists and nothing else. If you want to iterate over +" another sequence you need to use a function which will create a list. + +" Iterate over a list +for person in ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily'] + echo 'Hello ' .. person +endfor + +" Iterate over a nested list by unpacking it +for [x, y] in [[1, 0], [0, 1], [-1, 0], [0, -1]] + echo 'Position: x =' .. x .. ', y = ' .. y +endfor + +" Iterate over a range of numbers +for i in range(10, 0, -1) " Count down from 10 + echo 'T minus' .. i +endfor + +" Iterate over the keys of a dictionary +for symbol in keys({'π': 3.14, 'e': 2.71}) + echo 'The constant ' .. symbol .. ' is a transcendent number' +endfor + +" Iterate over the values of a dictionary +for value in values({'π': 3.14, 'e': 2.71}) + echo 'The value ' .. value .. ' approximates a transcendent number' +endfor + +" Iterate over the keys and values of a dictionary +for [symbol, value] in items({'π': 3.14, 'e': 2.71}) + echo 'The number ' .. symbol .. ' is approximately ' .. value +endfor + +" While-loops (|:while|, |:endwhile|) + +let there_yet = v:true +while !there_yet + echo 'Are we there yet?' +endwhile + + +" Exception handling (|exception-handling|) +" ################## +" +" Throw new exceptions as strings, catch them by pattern-matching a regular +" expression against the string + +" Throw new exception +throw "Wrong arguments" + +" Guard against an exception (the second catch matches any exception) +try + source path/to/file +catch /Cannot open/ + echo 'Looks like that file does not exist' +catch /.*/ + echo 'Something went wrong, but I do not know what' +finally + echo 'I am done trying' +endtry + + +" ########## +" Functions +" ########## + +" Defining functions (|:function|, |:endfunction|) +" ################## + +" Unscoped function names have to start with a capital letter +function! AddNumbersLoudly(x, y) + " Use a: scope to access arguments + echo 'Adding' .. a:x .. 'and' .. a:y | " A side effect + return a:x + a:y | " A return value +endfunction + +" Scoped function names may start with a lower-case letter +function! s:addNumbersLoudly(x, y) + echo 'Adding' .. a:x .. 'and' .. a:y + return a:x + a:y +endfunction + +" Without the exclamation mark it would be an error to re-define a function, +" with the exclamation mark the new definition can replace the old one. Since +" Vim script files can be reloaded several times over the course of a session +" it is best to use the exclamation mark unless you really know what you are +" doing. + +" Function definitions can have special qualifiers following the argument list. + +" Range functions define two implicit arguments, which will be set to the range +" of the ex-command +function! FirstAndLastLine() range + echo [a:firstline, a:lastline] +endfunction + +" Prints the first and last line that match a pattern (|cmdline-ranges|) +/^#!/,/!#$/call FirstAndLastLine() + +" Aborting functions, abort once error occurs (|:func-abort|) +function! SourceMyFile() abort + source my-file.vim | " Try sourcing non-existing file + echo 'This will never be printed' +endfunction + +" Closures, functions carrying values from outer scope (|:func-closure|) +function! MakeAdder(x) + function! Adder(n) closure + return a:n + a:x + endfunction + return funcref('Adder') +endfunction +let AddFive = MakeAdder(5) +echo AddFive(3) | " Prints 8 + +" Dictionary functions, poor man's OOP methods (|Dictionary-function|) +function! Mylen() dict + return len(self.data) | " Implicit variable self +endfunction +let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")} +echo mydict.len() + +" Alternatively, more concise +let mydict = {'data': [0, 1, 2, 3]} +function! mydict.len() + return len(self.data) +endfunction + +" Calling functions (|:call|) +" ################# + +" Call a function for its return value, and possibly for its side effects +let animals = keys({'cow': 'moo', 'dog': 'woof', 'cat': 'meow'}) + +" Call a function for its side effects only, ignore potential return value +call sign_undefine() + +" The call() function calls a function reference and passes parameters as a +" list, and returns the function's result. +echo call(function('get'), [{'a': 1, 'b': 2}, 'c', 3]) | " Prints 3 + +" Recall that Vim script is embedded within the ex-commands, that is why we +" cannot just call a function directly, we have to use the `:call` ex-command. + +" Function namespaces (|write-library-script|, |autoload|) +" ################### + +" Must be defined in autoload/foo/bar.vim +" Namspaced function names do not have to start with a capital letter +function! foo#bar#log(value) + echomsg value +endfunction + +call foo#bar#log('Hello') + + +" ############################# +" Frequently used ex-commands +" ############################# + + +" Sourcing runtime files (|'runtimepath'|) +" ###################### + +" Source first match among runtime paths +runtime plugin/my-plugin.vim + + +" Defining new ex-commands (|40.2|, |:command|) +" ######################## + +" First argument here is the name of the command, rest is the command body +command! SwapAdjacentLines normal! ddp + +" The exclamation mark works the same as with `:function`. User-defined +" commands must start with a capital letter. The `:command` command can take a +" number of attributes (some of which have their own parameters with `=`), such +" as `-nargs`, all of them start with a dash to set them apart from the command +" name. + +command! -nargs=1 Error echoerr <args> + + +" Defining auto-commands (|40.3|, |autocmd|, |autocommand-events|) +" ###################### + +" The arguments are "events", "patterns", rest is "commands" +autocmd BufWritePost $MYVIMRC source $MYVIMRC + +" Events and patterns are separated by commas with no space between. See +" |autocmd-events| for standard events, |User| for custom events. Everything +" else are the ex-commands which will be executed. + +" Auto groups +" =========== +" +" When a file is sourced multiple times the auto-commands are defined anew, +" without deleting the old ones, causing auto-commands to pile up over time. +" Use auto-groups and the following ritual to guard against this. + +augroup auto-source | " The name of the group is arbitrary + autocmd! | " Deletes all auto-commands in the current group + autocmd BufWritePost $MYVIMRC source $MYVIMRC +augroup END | " Switch back to default auto-group + +" It is also possible to assign a group directly. This is useful if the +" definition of the group is in one script and the definition of the +" auto-command is in another script. + +" In one file +augroup auto-source + autocmd! +augroup END + +" In another file +autocmd auto-source BufWritePost $MYVIMRC source $MYVIMRC + +" Executing (run-time macros of sorts) +" #################################### + +" Sometimes we need to construct an ex-command where part of the command is not +" known until runtime. + +let line = 3 | " Line number determined at runtime +execute line .. 'delete' | " Delete a line + +" Executing normal-mode commands +" ############################## +" +" Use `:normal` to play back a sequence of normal mode commands from the +" command-line. Add an exclamation mark to ignore user mappings. + +normal! ggddGp | " Transplant first line to end of buffer + +" Window commands can be used with :normal, or with :wincmd if :normal would +" not work +wincmd L | " Move current window all the way to the right + + +" ########################### +" Frequently used functions +" ########################### + +" Feature check +echo has('nvim') | " Running Neovim +echo has('python3') | " Support for Python 3 plugins +echo has('unix') | " Running on a Unix system +echo has('win32') | " Running on a Windows system + + +" Test if something exists +echo exists('&mouse') | " Option (exists only) +echo exists('+mouse') | " Option (exists and works) +echo exists('$HOSTNAME') | " Environment variable +echo exists('*strftime') | " Built-in function +echo exists('**s:MyFunc') | " User-defined function +echo exists('bufcount') | " Variable (scope optional) +echo exists('my_dict["foo"]') | " Variable (dictionary entry) +echo exists('my_dict["foo"]') | " Variable (dictionary entry) +echo exists(':Make') | " Command +echo exists("#CursorHold") | " Auto-command defined for event +echo exists("#BufReadPre#*.gz") | " Event and pattern +echo exists("#filetypeindent") | " Auto-command group +echo exists("##ColorScheme") | " Auto-command supported for event + +" Various dynamic values (see |expand()|) +echo expand('%') | " Current file name +echo expand('<cword>') | " Current word under cursor +echo expand('%:p') | " Modifier are possible + +" Type tests +" There are unique constants defined for the following types. Older versions +" of Vim lack the type variables, see the reference " documentation for a +" workaround +echo type(my_var) == v:t_number | " Number +echo type(my_var) == v:t_string | " String +echo type(my_var) == v:t_func | " Funcref +echo type(my_var) == v:t_list | " List +echo type(my_var) == v:t_dict | " Dictionary +echo type(my_var) == v:t_float | " Float +echo type(my_var) == v:t_bool | " Explicit Boolean +" For the null object should compare it against itself +echo my_var is v:null + +" Format strings +echo printf('%d in hexadecimal is %X', 123, 123) + + +" ##################### +" Tricks of the trade +" ##################### + +" Source guard +" ############ + +" Prevent a file from being sourced multiple times; users can set the variable +" in their configuration to prevent the plugin from loading at all. +if exists('g:loaded_my_plugin') + finish +endif +let g:loaded_my_plugin = v:true + +" Default values +" ############## + +" Get a default value: if the user defines a variable use it, otherwise use a +" hard-coded default. Uses the fact that a scope is also a dictionary. +let s:greeting = get(g:, 'my_plugin_greeting', 'Hello') +``` diff --git a/visualbasic.html.markdown b/visualbasic.html.markdown index 221c1eb3..b79017dc 100644 --- a/visualbasic.html.markdown +++ b/visualbasic.html.markdown @@ -5,7 +5,7 @@ contributors: filename: learnvisualbasic.vb --- -``` +```visualbasic Module Module1 Sub Main() @@ -102,7 +102,8 @@ Module Module1 Console.WriteLine("Hello, What is your name? ") 'Ask the user their name. username = Console.ReadLine() 'Stores the users name. Console.WriteLine("Hello " + username) 'Output is Hello 'Their name' - Console.ReadLine() 'Outputs the above. + Console.ReadLine() 'Pauses the execution for user to read + 'The above will ask you a question followed by printing your answer. 'Other variables include Integer and we use Integer for whole numbers. End Sub diff --git a/vyper.html.markdown b/vyper.html.markdown index fec1a79f..bad0c31e 100644 --- a/vyper.html.markdown +++ b/vyper.html.markdown @@ -181,7 +181,7 @@ def _changeTaskStatus( \ _status: uint256, \ ): # backslashes (\) allow for multi-line code - # Natspec comments are particularly helpful for documentation and readibility + # Natspec comments are particularly helpful for documentation and readability # Natspec can be included using familiar Pythonic docstring syntax """ @notice @@ -429,16 +429,16 @@ struct Struct: owner: address _balance: uint256 # balance is a reserved keyword, is a member for addresses -exampleStuct: Struct +exampleStruct: Struct @public def foo() -> uint256: - self.exampleStuct = Struct({owner: msg.sender, _balance: 5}) - self.exampleStuct._balance = 10 - self.exampleStuct._balance = 5 # set to new value - clear(self.exampleStuct._balance) - clear(self.exampleStuct) - return self.exampleStuct._balance + self.exampleStruct = Struct({owner: msg.sender, _balance: 5}) + self.exampleStruct._balance = 10 + self.exampleStruct._balance = 5 # set to new value + clear(self.exampleStruct._balance) + clear(self.exampleStruct) + return self.exampleStruct._balance # Data locations: Memory vs. storage vs. calldata - all complex types (arrays, @@ -510,7 +510,7 @@ def increment(x: uint256, y: uint256) -> (uint256, uint256): y += 1 return (x, y) -# Call previous functon +# Call previous function @public @constant def willCall() -> (uint256, uint256): @@ -679,7 +679,7 @@ sha3(concat("ab", "cd")) # returns bytes32 # Step 1. Commit # Place a commitment by sending output of `sha3()` -sha3("a secret"); # btyes32 commit +sha3("a secret"); # bytes32 commit sha3(concat("secret", "other secret", "salt")); # commit multiple things # The `sha3()` calculation should occur off-chain, only the bytes32 # output should be inputted into some `commit()` function diff --git a/wasm.html.markdown b/wasm.html.markdown index 98bfc000..4de7107f 100644 --- a/wasm.html.markdown +++ b/wasm.html.markdown @@ -42,7 +42,7 @@ contributors: ;; To set them to a value, we can use <type>.const: (local.set $int_32 (i32.const 16)) - (local.set $int_32 (i64.const 128)) + (local.set $int_64 (i64.const 128)) (local.set $float_32 (f32.const 3.14)) (local.set $float_64 (f64.const 1.28)) ) @@ -61,7 +61,7 @@ contributors: ;; We have to use the right data type for each operation: ;; (local.set $mult_result (f32.mul (f32.const 2.0) (f32.const 4.0))) ;; WRONG! mult_result is f64! - (local.set $mult_result (f64.mul (f64.const 2.0) (f64.const 4.0))) ;; WRONG! mult_result is f64! + (local.set $mult_result (f64.mul (f64.const 2.0) (f64.const 4.0))) ;; WebAssembly has some builtin operations, like basic math and bitshifting. ;; Notably, it does not have built in trigonometric functions. @@ -222,6 +222,91 @@ contributors: ) ) (export "apply_cos64" (func $apply_cos64)) + + ;; Wasm is a stack-based language, but for returning values more complicated + ;; than an int/float, a separate memory stack has to be manually managed. One + ;; approach is to use a mutable global to store the stack_ptr. We give + ;; ourselves 1MiB of memstack and grow it downwards. + ;; + ;; Below is a demonstration of how this C code **might** be written by hand + ;; + ;; typedef struct { + ;; int a; + ;; int b; + ;; } sum_struct_t; + ;; + ;; sum_struct_t sum_struct_create(int a, int b) { + ;; return (sum_struct_t){a, b}; + ;; } + ;; + ;; int sum_local() { + ;; sum_struct_t s = sum_struct_create(40, 2); + ;; return s.a + s.b; + ;; } + + ;; Unlike C, we must manage our own memory stack. We reserve 1MiB + (global $memstack_ptr (mut i32) (i32.const 65536)) + + ;; Structs can only be returned by reference + (func $sum_struct_create + (param $sum_struct_ptr i32) + (param $var$a i32) + (param $var$b i32) + ;; c// sum_struct_ptr->a = a; + (i32.store + (get_local $sum_struct_ptr) + (get_local $var$a) + ) + + ;; c// sum_struct_ptr->b = b; + (i32.store offset=4 + (get_local $sum_struct_ptr) + (get_local $var$b) + ) + ) + + (func $sum_local (result i32) + (local $var$sum_struct$a i32) + (local $var$sum_struct$b i32) + (local $local_memstack_ptr i32) + + ;; reserve memstack space + (i32.sub + (get_global $memstack_ptr) + (i32.const 8) + ) + tee_local $local_memstack_ptr ;; tee both stores and returns given value + set_global $memstack_ptr + + ;; call the function, storing the result in the memstack + (call $sum_struct_create + ((;$sum_struct_ptr=;) get_local $local_memstack_ptr) + ((;$var$a=;) i32.const 40) + ((;$var$b=;) i32.const 2) + ) + + ;; retrieve values from struct + (set_local $var$sum_struct$a + (i32.load offset=0 (get_local $local_memstack_ptr)) + ) + (set_local $var$sum_struct$b + (i32.load offset=4 (get_local $local_memstack_ptr)) + ) + + ;; unreserve memstack space + (set_global $memstack_ptr + (i32.add + (get_local $local_memstack_ptr) + (i32.const 8) + ) + ) + + (i32.add + (get_local $var$sum_struct$a) + (get_local $var$sum_struct$b) + ) + ) + (export "sum_local" (func $sum_local)) ) ``` diff --git a/wolfram.html.markdown b/wolfram.html.markdown index 5fddbc82..fa8ee078 100644 --- a/wolfram.html.markdown +++ b/wolfram.html.markdown @@ -14,7 +14,7 @@ Wolfram Language has several interfaces: The code in this example can be typed in to any interface and edited with Wolfram Workbench. Loading directly into Mathematica may be awkward because the file contains no cell formatting information (which would make the file a huge mess to read as text) - it can be viewed/edited but may require some setting up. -``` +```mathematica (* This is a comment *) (* In Mathematica instead of using these comments you can create a text cell diff --git a/xml.html.markdown b/xml.html.markdown index b4b54330..630e4c90 100644 --- a/xml.html.markdown +++ b/xml.html.markdown @@ -100,8 +100,9 @@ This is what makes XML versatile. It is human readable too. The following docume A XML document is *well-formed* if it is syntactically correct. However, it is possible to add more constraints to the document, using Document Type Definitions (DTDs). A document whose elements are attributes are declared in a DTD and which follows the grammar specified in that DTD is called *valid* with respect to that DTD, in addition to being well-formed. +Declaring a DTD externally: + ```xml -<!-- Declaring a DTD externally: --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE bookstore SYSTEM "Bookstore.dtd"> <!-- Declares that bookstore is our root element and 'Bookstore.dtd' is the path @@ -114,8 +115,11 @@ A XML document is *well-formed* if it is syntactically correct. However, it is p <price>30.00</price> </book> </bookstore> +``` -<!-- The DTD file: --> +The DTD file (Bookstore.dtd): + +``` <!ELEMENT bookstore (book+)> <!-- The bookstore element may contain one or more child book elements. --> <!ELEMENT book (title, price)> @@ -128,10 +132,11 @@ A XML document is *well-formed* if it is syntactically correct. However, it is p only contain text which is read by the parser and must not contain children. Compare with CDATA, or character data. --> <!ELEMENT price (#PCDATA)> -]> +``` -<!-- The DTD could be declared inside the XML file itself.--> +The DTD could be declared inside the XML file itself: +```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE bookstore [ @@ -160,7 +165,7 @@ Support for DTDs is ubiquitous because they are so old. Unfortunately, modern XM ## Further Reading -* [XML Schema Definitions Tutorial](http://www.w3schools.com/schema/) +* [XML Schema Definitions Tutorial](https://www.w3schools.com/xml/schema_intro.asp) * [DTD Tutorial](http://www.w3schools.com/xml/xml_dtd_intro.asp) * [XML Tutorial](http://www.w3schools.com/xml/default.asp) * [Using XPath queries to parse XML](http://www.w3schools.com/xml/xml_xpath.asp) diff --git a/yaml.html.markdown b/yaml.html.markdown index f1393c09..6901695c 100644 --- a/yaml.html.markdown +++ b/yaml.html.markdown @@ -2,8 +2,10 @@ language: yaml filename: learnyaml.yaml contributors: -- [Adam Brenecki, 'https://github.com/adambrenecki'] + +- [Leigh Brenecki, 'https://leigh.net.au'] - [Suhas SG, 'https://github.com/jargnar'] + --- YAML is a data serialisation language designed to be directly writable and @@ -17,6 +19,7 @@ YAML doesn't allow literal tab characters for indentation. --- # document start # Comments in YAML look like this. +# YAML supports single-line comments. ################ # SCALAR TYPES # @@ -28,11 +31,24 @@ key: value another_key: Another value goes here. a_number_value: 100 scientific_notation: 1e+12 -# The number 1 will be interpreted as a number, not a boolean. if you want -# it to be interpreted as a boolean, use true +hex_notation: 0x123 # evaluates to 291 +octal_notation: 0123 # evaluates to 83 + +# The number 1 will be interpreted as a number, not a boolean. +# If you want it to be interpreted as a boolean, use true. boolean: true null_value: null +another_null_value: ~ key with spaces: value + +# Yes and No (doesn't matter the case) will be evaluated to boolean +# true and false values respectively. +# To use the actual value use single or double quotes. +no: no # evaluates to "no": false +yes: No # evaluates to "yes": false +not_enclosed: yes # evaluates to "not_enclosed": true +enclosed: "yes" # evaluates to "enclosed": yes + # Notice that strings don't need to be quoted. However, they can be. however: 'A string, enclosed in quotes.' 'Keys can be quoted too.': "Useful if you want to put a ':' in your key." @@ -41,25 +57,49 @@ double quotes: "have many: \", \0, \t, \u263A, \x0d\x0a == \r\n, and more." # UTF-8/16/32 characters need to be encoded Superscript two: \u00B2 -# Multiple-line strings can be written either as a 'literal block' (using |), +# Special characters must be enclosed in single or double quotes +special_characters: "[ John ] & { Jane } - <Doe>" + +# Multiple-line strings can be written either as a 'literal block' (using |), # or a 'folded block' (using '>'). +# Literal block turn every newline within the string into a literal newline (\n). +# Folded block removes newlines within the string. literal_block: | - This entire block of text will be the value of the 'literal_block' key, - with line breaks being preserved. + This entire block of text will be the value of the 'literal_block' key, + with line breaks being preserved. - The literal continues until de-dented, and the leading indentation is - stripped. + The literal continues until de-dented, and the leading indentation is + stripped. - Any lines that are 'more-indented' keep the rest of their indentation - - these lines will be indented by 4 spaces. + Any lines that are 'more-indented' keep the rest of their indentation - + these lines will be indented by 4 spaces. folded_style: > - This entire block of text will be the value of 'folded_style', but this - time, all newlines will be replaced with a single space. + This entire block of text will be the value of 'folded_style', but this + time, all newlines will be replaced with a single space. - Blank lines, like above, are converted to a newline character. + Blank lines, like above, are converted to a newline character. - 'More-indented' lines keep their newlines, too - - this text will appear over two lines. + 'More-indented' lines keep their newlines, too - + this text will appear over two lines. + +# |- and >- removes the trailing blank lines (also called literal/block "strip") +literal_strip: |- + This entire block of text will be the value of the 'literal_block' key, + with trailing blank line being stripped. +block_strip: >- + This entire block of text will be the value of 'folded_style', but this + time, all newlines will be replaced with a single space and + trailing blank line being stripped. + +# |+ and >+ keeps trailing blank lines (also called literal/block "keep") +literal_keep: |+ + This entire block of text will be the value of the 'literal_block' key, + with trailing blank line being kept. + +block_keep: >+ + This entire block of text will be the value of 'folded_style', but this + time, all newlines will be replaced with a single space and + trailing blank line being kept. #################### # COLLECTION TYPES # @@ -87,7 +127,7 @@ a_nested_map: # An example ? - Manchester United - Real Madrid -: [2001-01-01, 2002-02-02] +: [ 2001-01-01, 2002-02-02 ] # Sequences (equivalent to lists or arrays) look like this # (note that the '-' counts as indentation): @@ -98,24 +138,26 @@ a_sequence: - Item 4 - key: value another_key: another_value - - - - This is a sequence + - - This is a sequence - inside another sequence - - - Nested sequence indicators - can be collapsed # Since YAML is a superset of JSON, you can also write JSON-style maps and # sequences: -json_map: {"key": "value"} -json_seq: [3, 2, 1, "takeoff"] -and quotes are optional: {key: [3, 2, 1, takeoff]} +json_map: { "key": "value" } +json_seq: [ 3, 2, 1, "takeoff" ] +and quotes are optional: { key: [ 3, 2, 1, takeoff ] } ####################### # EXTRA YAML FEATURES # ####################### # YAML also has a handy feature called 'anchors', which let you easily duplicate -# content across your document. Both of these keys will have the same value: +# content across your document. +# Anchors identified by & character which define the value. +# Aliases identified by * character which acts as "see above" command. +# Both of these keys will have the same value: anchored_content: &anchor_name This string will appear as the value of two keys. other_anchor: *anchor_name @@ -123,28 +165,35 @@ other_anchor: *anchor_name base: &base name: Everyone has same name -# The regexp << is called Merge Key Language-Independent Type. It is used to +# The expression << is called 'Merge Key Language-Independent Type'. It is used to # indicate that all the keys of one or more specified maps should be inserted # into the current map. - -foo: &foo - <<: *base +# NOTE: If key already exists alias will not be merged +foo: + <<: *base # doesn't merge the anchor age: 10 - -bar: &bar - <<: *base + name: John +bar: + <<: *base # base anchor will be merged age: 20 # foo and bar would also have name: Everyone has same name # YAML also has tags, which you can use to explicitly declare types. +# Syntax: !![typeName] [value] +explicit_boolean: !!bool true +explicit_integer: !!int 42 +explicit_float: !!float -42.24 explicit_string: !!str 0.5 +explicit_datetime: !!timestamp 2022-11-17 12:34:56.78 +9 +explicit_null: !!null null + # Some parsers implement language specific tags, like this one for Python's # complex number type. python_complex_number: !!python/complex 1+2j # We can also use yaml complex keys with language specific tags -? !!python/tuple [5, 7] +? !!python/tuple [ 5, 7 ] : Fifty Seven # Would be {(5, 7): 'Fifty Seven'} in Python @@ -154,9 +203,10 @@ python_complex_number: !!python/complex 1+2j # Strings and numbers aren't the only scalars that YAML can understand. # ISO-formatted date and datetime literals are also parsed. -datetime: 2001-12-15T02:59:43.1Z -datetime_with_spaces: 2001-12-14 21:59:43.10 -5 -date: 2002-12-14 +datetime_canonical: 2001-12-15T02:59:43.1Z +datetime_space_separated_with_time_zone: 2001-12-14 21:59:43.10 -5 +date_implicit: 2002-12-14 +date_explicit: !!timestamp 2002-12-14 # The !!binary tag indicates that a string is actually a base64-encoded # representation of a binary blob. @@ -171,7 +221,7 @@ set: ? item1 ? item2 ? item3 -or: {item1, item2, item3} +or: { item1, item2, item3 } # Sets are just maps with null values; the above is equivalent to: set2: @@ -184,5 +234,6 @@ set2: ### More Resources -+ [YAML official website](http://yaml.org/) ++ [YAML official website](https://yaml.org/) + [Online YAML Validator](http://www.yamllint.com/) ++ [JSON ⇆ YAML](https://www.json2yaml.com/) diff --git a/zfs.html.markdown b/zfs.html.markdown index 6795b1fa..3f5a76b5 100644 --- a/zfs.html.markdown +++ b/zfs.html.markdown @@ -3,6 +3,7 @@ category: tool tool: zfs contributors: - ["sarlalian", "http://github.com/sarlalian"] + - ["A1EF", "https://github.com/A1EF"] filename: LearnZfs.txt --- @@ -25,7 +26,6 @@ RAID setup with ZFS, as ZFS expects to directly manage the underlying disks. Types of VDEV's -* stripe (a single disk, no redundancy) * mirror (n-way mirrors supported) * raidz * raidz1 (1-disk parity, similar to RAID 5) @@ -71,7 +71,7 @@ List zpools ```bash # Create a raidz zpool -$ zpool create bucket raidz1 gpt/zfs0 gpt/zfs1 gpt/zfs2 +$ zpool create zroot raidz1 gpt/zfs0 gpt/zfs1 gpt/zfs2 # List ZPools $ zpool list @@ -160,22 +160,22 @@ Create datasets ```bash # Create dataset -$ zfs create tank/root/data +$ zfs create zroot/root/data $ mount | grep data -tank/root/data on /data (zfs, local, nfsv4acls) +zroot/root/data on /data (zfs, local, nfsv4acls) # Create child dataset -$ zfs create tank/root/data/stuff +$ zfs create zroot/root/data/stuff $ mount | grep data -tank/root/data on /data (zfs, local, nfsv4acls) -tank/root/data/stuff on /data/stuff (zfs, local, nfsv4acls) +zroot/root/data on /data (zfs, local, nfsv4acls) +zroot/root/data/stuff on /data/stuff (zfs, local, nfsv4acls) # Create Volume $ zfs create -V zroot/win_vm $ zfs list zroot/win_vm NAME USED AVAIL REFER MOUNTPOINT -tank/win_vm 4.13G 17.9G 64K - +zroot/win_vm 4.13G 17.9G 64K - ``` List datasets @@ -213,28 +213,28 @@ zroot/var/tmp@daily-2015-10-15 Rename datasets ```bash -$ zfs rename tank/root/home tank/root/old_home -$ zfs rename tank/root/new_home tank/root/home +$ zfs rename zroot/root/home zroot/root/old_home +$ zfs rename zroot/root/new_home zroot/root/home ``` Delete dataset ```bash # Datasets cannot be deleted if they have any snapshots -$ zfs destroy tank/root/home +$ zfs destroy zroot/root/home ``` Get / set properties of a dataset ```bash # Get all properties -$ zfs get all zroot/usr/home │157 # Create Volume -NAME PROPERTY VALUE SOURCE │158 $ zfs create -V zroot/win_vm -zroot/home type filesystem - │159 $ zfs list zroot/win_vm -zroot/home creation Mon Oct 20 14:44 2014 - │160 NAME USED AVAIL REFER MOUNTPOINT -zroot/home used 11.9G - │161 tank/win_vm 4.13G 17.9G 64K - -zroot/home available 94.1G - │162 ``` -zroot/home referenced 11.9G - │163 +$ zfs get all zroot/usr/home +NAME PROPERTY VALUE SOURCE +zroot/home type filesystem - +zroot/home creation Mon Oct 20 14:44 2014 - +zroot/home used 11.9G - +zroot/home available 94.1G - +zroot/home referenced 11.9G - zroot/home mounted yes - ... @@ -244,7 +244,7 @@ NAME PROPERTY VALUE SOURCE zroot/home compression off default # Set property on dataset -$ zfs set compression=gzip-9 mypool/lamb +$ zfs set compression=lz4 zroot/lamb # Get a set of properties from all datasets $ zfs list -o name,quota,reservation @@ -283,16 +283,16 @@ Create snapshots ```bash # Create a snapshot of a single dataset -zfs snapshot tank/home/sarlalian@now +zfs snapshot zroot/home/sarlalian@now # Create a snapshot of a dataset and its children -$ zfs snapshot -r tank/home@now +$ zfs snapshot -r zroot/home@now $ zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT -tank/home@now 0 - 26K - -tank/home/sarlalian@now 0 - 259M - -tank/home/alice@now 0 - 156M - -tank/home/bob@now 0 - 156M - +zroot/home@now 0 - 26K - +zroot/home/sarlalian@now 0 - 259M - +zroot/home/alice@now 0 - 156M - +zroot/home/bob@now 0 - 156M - ... ``` @@ -300,10 +300,10 @@ Destroy snapshots ```bash # How to destroy a snapshot -$ zfs destroy tank/home/sarlalian@now +$ zfs destroy zroot/home/sarlalian@now # Delete a snapshot on a parent dataset and its children -$ zfs destroy -r tank/home/sarlalian@now +$ zfs destroy -r zroot/home/sarlalian@now ``` @@ -311,10 +311,10 @@ Renaming Snapshots ```bash # Rename a snapshot -$ zfs rename tank/home/sarlalian@now tank/home/sarlalian@today -$ zfs rename tank/home/sarlalian@now today +$ zfs rename zroot/home/sarlalian@now zroot/home/sarlalian@today +$ zfs rename zroot/home/sarlalian@now today -$ zfs rename -r tank/home@now @yesterday +$ zfs rename -r zroot/home@now @yesterday ``` Accessing snapshots @@ -328,26 +328,26 @@ Sending and Receiving ```bash # Backup a snapshot to a file -$ zfs send tank/home/sarlalian@now | gzip > backup_file.gz +$ zfs send zroot/home/sarlalian@now | gzip > backup_file.gz # Send a snapshot to another dataset -$ zfs send tank/home/sarlalian@now | zfs recv backups/home/sarlalian +$ zfs send zroot/home/sarlalian@now | zfs recv backups/home/sarlalian # Send a snapshot to a remote host -$ zfs send tank/home/sarlalian@now | ssh root@backup_server 'zfs recv tank/home/sarlalian' +$ zfs send zroot/home/sarlalian@now | ssh root@backup_server 'zfs recv zroot/home/sarlalian' # Send full dataset with snapshots to new host -$ zfs send -v -R tank/home@now | ssh root@backup_server 'zfs recv tank/home' +$ zfs send -v -R zroot/home@now | ssh root@backup_server 'zfs recv zroot/home' ``` Cloning Snapshots ```bash # Clone a snapshot -$ zfs clone tank/home/sarlalian@now tank/home/sarlalian_new +$ zfs clone zroot/home/sarlalian@now zroot/home/sarlalian_new # Promoting the clone so it is no longer dependent on the snapshot -$ zfs promote tank/home/sarlalian_new +$ zfs promote zroot/home/sarlalian_new ``` ### Putting it all together diff --git a/zh-cn/asciidoc-cn.html.markdown b/zh-cn/asciidoc-cn.html.markdown new file mode 100644 index 00000000..0709e8c1 --- /dev/null +++ b/zh-cn/asciidoc-cn.html.markdown @@ -0,0 +1,135 @@ +--- +language: asciidoc +filename: asciidoc-cn.adoc +contributors: + - ["Ryan Mavilia", "http://unoriginality.rocks/"] + - ["Abel Salgado Romero", "https://twitter.com/abelsromero"] +translators: + - ["Liu Yihua", "https://github.com/yihuajack"] +lang: zh-cn +--- + +AsciiDoc 是一种类似于 Markdown 的标记语言,它可以用来写从书到博客的任何东西。它由 Stuart Rackham 在 2002 年发明,它的语言很简单,但同时也可以有丰富的定制。 + +文档标题 + +标题是可选的,且不可以包含空行。它必须离正文空出至少一个空行。 + +仅标题 + +``` += 文档标题 + +文档的第一句话。 +``` + +标题和作者 + +``` += 文档标题 +张三 <san.zhang@learnxinyminutes.com> + +文档开始。 +``` + +多名作者的情形 + +``` += 文档标题 +李四 <si@go.com>; 王五 <wu@yo.com>; 赵六 <xzhao@pirate.com> + +有多名作者的文档开始。 +``` + +版本行(需要作者行) + +``` += 文档标题(第一版) +土豆人 <chip@crunchy.com> +v1.0, 2016-01-13 + +这篇关于炸薯条的文章会很有趣。 +``` + +段落 + +``` +段落不需要什么特别操作。 + +在两段之间用一个空行隔开。 + +当你需要换行时,添加一个 + +你就会得到一个换行符! +``` + +文本格式化 + +``` +_用下划线创建斜体_ +*用星号加粗* +*_组合起来用更有趣_* +`用重音符显示等宽字体` +`*加粗等宽字体*` +``` + +节标题 + +``` += 第 0 级 (一般只用于文档标题) + +== 第 1 级 <h2> + +=== 第 2 级 <h3> + +==== 第 3 级 <h4> + +===== 第 4 级 <h5> + +``` + +列表 + +用星号创建无序列表。 + +``` +* 甲 +* 乙 +* 丙 +``` + +用句点创建有序列表。 + +``` +. 项目 1 +. 项目 2 +. 项目 3 +``` + +你可以用额外的星号或句点来嵌套最多五次列表。 + +``` +* 甲 1 +** 甲 2 +*** 甲 3 +**** 甲 4 +***** 甲 5 + +. 甲 1 +.. 甲 2 +... 甲 3 +.... 甲 4 +..... 甲 5 +``` + +## 补充材料 + +处理 AsciiDoc 文档有两种工具: + +1. [AsciiDoc](http://asciidoc.org/): 原版的 Python 实现,在主流 Linux 发行版中已附带,目前处于稳定版本维护模式。 +2. [Asciidoctor](http://asciidoctor.org/): 使用 Ruby 的另一种实现,也可以从 Java 和 JavaScript 中使用。它处于积极的开发中,目标是用新特性和输出格式扩展 AsciiDoc 的语法。 + +以下是 `Asciidoctor` 实现的相关链接: + +* [Markdown - AsciiDoc 语法比较](http://asciidoctor.org/docs/user-manual/#comparison-by-example):并列比较一般 Markdown 和 AsciiDoc 的元素。 +* [入门](http://asciidoctor.org/docs/#get-started-with-asciidoctor):安装和快速启动指南,帮助构建简单的文档。 +* [Asciidoctor 用户手册](http://asciidoctor.org/docs/user-manual/): 完整的单文档指南,包含语法参考、示例、渲染工具等。 diff --git a/zh-cn/awk-cn.html.markdown b/zh-cn/awk-cn.html.markdown index 8ee2db2c..02f1f7d5 100644 --- a/zh-cn/awk-cn.html.markdown +++ b/zh-cn/awk-cn.html.markdown @@ -179,7 +179,7 @@ function string_functions( localvar, arr) { # 都是返回替换的个数 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" # 搜索匹配正则的字符串 # index() 也是搜索, 不支持正则 diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index d85e5b8f..225df06b 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -18,7 +18,7 @@ filename: LearnBash-cn.sh lang: zh-cn --- -Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 Mac OS X 下的默认 shell。 +Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 macOS 下的默认 shell。 以下大多数例子可以作为脚本的一部分运行,也可直接在 shell 下交互执行。 [更多信息](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index e0d6b6fe..db36ebc4 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -1,572 +1,572 @@ ----
-language: c++
-filename: learncpp-cn.cpp
-contributors:
- - ["Steven Basart", "http://github.com/xksteven"]
- - ["Matt Kline", "https://github.com/mrkline"]
-translators:
- - ["Arnie97", "https://github.com/Arnie97"]
-lang: zh-cn
----
-
-C++是一种系统编程语言。用它的发明者,
-[Bjarne Stroustrup的话](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)来说,C++的设计目标是:
-
-- 成为“更好的C语言”
-- 支持数据的抽象与封装
-- 支持面向对象编程
-- 支持泛型编程
-
-C++提供了对硬件的紧密控制(正如C语言一样),
-能够编译为机器语言,由处理器直接执行。
-与此同时,它也提供了泛型、异常和类等高层功能。
-虽然C++的语法可能比某些出现较晚的语言更复杂,它仍然得到了人们的青睞——
-功能与速度的平衡使C++成为了目前应用最广泛的系统编程语言之一。
-
-```c++
-////////////////
-// 与C语言的比较
-////////////////
-
-// C++_几乎_是C语言的一个超集,它与C语言的基本语法有许多相同之处,
-// 例如变量和函数的声明,原生数据类型等等。
-
-// 和C语言一样,在C++中,你的程序会从main()开始执行,
-// 该函数的返回值应当为int型,这个返回值会作为程序的退出状态值。
-// 不过,大多数的编译器(gcc,clang等)也接受 void main() 的函数原型。
-// (参见 http://en.wikipedia.org/wiki/Exit_status 来获取更多信息)
-int main(int argc, char** argv)
-{
- // 和C语言一样,命令行参数通过argc和argv传递。
- // argc代表命令行参数的数量,
- // 而argv是一个包含“C语言风格字符串”(char *)的数组,
- // 其中每个字符串代表一个命令行参数的内容,
- // 首个命令行参数是调用该程序时所使用的名称。
- // 如果你不关心命令行参数的值,argc和argv可以被忽略。
- // 此时,你可以用int main()作为函数原型。
-
- // 退出状态值为0时,表示程序执行成功
- return 0;
-}
-
-// 然而,C++和C语言也有一些区别:
-
-// 在C++中,字符字面量的大小是一个字节。
-sizeof('c') == 1
-
-// 在C语言中,字符字面量的大小与int相同。
-sizeof('c') == sizeof(10)
-
-
-// C++的函数原型与函数定义是严格匹配的
-void func(); // 这个函数不能接受任何参数
-
-// 而在C语言中
-void func(); // 这个函数能接受任意数量的参数
-
-// 在C++中,用nullptr代替C语言中的NULL
-int* ip = nullptr;
-
-// C++也可以使用C语言的标准头文件,
-// 但是需要加上前缀“c”并去掉末尾的“.h”。
-#include <cstdio>
-
-int main()
-{
- printf("Hello, world!\n");
- return 0;
-}
-
-///////////
-// 函数重载
-///////////
-
-// C++支持函数重载,你可以定义一组名称相同而参数不同的函数。
-
-void print(char const* myString)
-{
- printf("String %s\n", myString);
-}
-
-void print(int myInt)
-{
- printf("My int is %d", myInt);
-}
-
-int main()
-{
- print("Hello"); // 解析为 void print(const char*)
- print(15); // 解析为 void print(int)
-}
-
-///////////////////
-// 函数参数的默认值
-///////////////////
-
-// 你可以为函数的参数指定默认值,
-// 它们将会在调用者没有提供相应参数时被使用。
-
-void doSomethingWithInts(int a = 1, int b = 4)
-{
- // 对两个参数进行一些操作
-}
-
-int main()
-{
- doSomethingWithInts(); // a = 1, b = 4
- doSomethingWithInts(20); // a = 20, b = 4
- doSomethingWithInts(20, 5); // a = 20, b = 5
-}
-
-// 默认参数必须放在所有的常规参数之后。
-
-void invalidDeclaration(int a = 1, int b) // 这是错误的!
-{
-}
-
-
-///////////
-// 命名空间
-///////////
-
-// 命名空间为变量、函数和其他声明提供了分离的的作用域。
-// 命名空间可以嵌套使用。
-
-namespace First {
- namespace Nested {
- void foo()
- {
- printf("This is First::Nested::foo\n");
- }
- } // 结束嵌套的命名空间Nested
-} // 结束命名空间First
-
-namespace Second {
- void foo()
- {
- printf("This is Second::foo\n")
- }
-}
-
-void foo()
-{
- printf("This is global foo\n");
-}
-
-int main()
-{
- // 如果没有特别指定,就从“Second”中取得所需的内容。
- using namespace Second;
-
- foo(); // 显示“This is Second::foo”
- First::Nested::foo(); // 显示“This is First::Nested::foo”
- ::foo(); // 显示“This is global foo”
-}
-
-////////////
-// 输入/输出
-////////////
-
-// C++使用“流”来输入输出。<<是流的插入运算符,>>是流提取运算符。
-// cin、cout、和cerr分别代表
-// stdin(标准输入)、stdout(标准输出)和stderr(标准错误)。
-
-#include <iostream> // 引入包含输入/输出流的头文件
-
-using namespace std; // 输入输出流在std命名空间(也就是标准库)中。
-
-int main()
-{
- int myInt;
-
- // 在标准输出(终端/显示器)中显示
- cout << "Enter your favorite number:\n";
- // 从标准输入(键盘)获得一个值
- cin >> myInt;
-
- // cout也提供了格式化功能
- cout << "Your favorite number is " << myInt << "\n";
- // 显示“Your favorite number is <myInt>”
-
- cerr << "Used for error messages";
-}
-
-/////////
-// 字符串
-/////////
-
-// C++中的字符串是对象,它们有很多成员函数
-#include <string>
-
-using namespace std; // 字符串也在std命名空间(标准库)中。
-
-string myString = "Hello";
-string myOtherString = " World";
-
-// + 可以用于连接字符串。
-cout << myString + myOtherString; // "Hello World"
-
-cout << myString + " You"; // "Hello You"
-
-// C++中的字符串是可变的,具有“值语义”。
-myString.append(" Dog");
-cout << myString; // "Hello Dog"
-
-
-/////////////
-// 引用
-/////////////
-
-// 除了支持C语言中的指针类型以外,C++还提供了_引用_。
-// 引用是一种特殊的指针类型,一旦被定义就不能重新赋值,并且不能被设置为空值。
-// 使用引用时的语法与原变量相同:
-// 也就是说,对引用类型进行解引用时,不需要使用*;
-// 赋值时也不需要用&来取地址。
-
-using namespace std;
-
-string foo = "I am foo";
-string bar = "I am bar";
-
-
-string& fooRef = foo; // 建立了一个对foo的引用。
-fooRef += ". Hi!"; // 通过引用来修改foo的值
-cout << fooRef; // "I am foo. Hi!"
-
-// 这句话的并不会改变fooRef的指向,其效果与“foo = bar”相同。
-// 也就是说,在执行这条语句之后,foo == "I am bar"。
-fooRef = bar;
-
-const string& barRef = bar; // 建立指向bar的常量引用。
-// 和C语言中一样,(指针和引用)声明为常量时,对应的值不能被修改。
-barRef += ". Hi!"; // 这是错误的,不能修改一个常量引用的值。
-
-///////////////////
-// 类与面向对象编程
-///////////////////
-
-// 有关类的第一个示例
-#include <iostream>
-
-// 声明一个类。
-// 类通常在头文件(.h或.hpp)中声明。
-class Dog {
- // 成员变量和成员函数默认情况下是私有(private)的。
- std::string name;
- int weight;
-
-// 在这个标签之后,所有声明都是公有(public)的,
-// 直到重新指定“private:”(私有继承)或“protected:”(保护继承)为止
-public:
-
- // 默认的构造器
- Dog();
-
- // 这里是成员函数声明的一个例子。
- // 可以注意到,我们在此处使用了std::string,而不是using namespace std
- // 语句using namespace绝不应当出现在头文件当中。
- void setName(const std::string& dogsName);
-
- void setWeight(int dogsWeight);
-
- // 如果一个函数不对对象的状态进行修改,
- // 应当在声明中加上const。
- // 这样,你就可以对一个以常量方式引用的对象执行该操作。
- // 同时可以注意到,当父类的成员函数需要被子类重写时,
- // 父类中的函数必须被显式声明为_虚函数(virtual)_。
- // 考虑到性能方面的因素,函数默认情况下不会被声明为虚函数。
- virtual void print() const;
-
- // 函数也可以在class body内部定义。
- // 这样定义的函数会自动成为内联函数。
- void bark() const { std::cout << name << " barks!\n" }
-
- // 除了构造器以外,C++还提供了析构器。
- // 当一个对象被删除或者脱离其定义域时,它的析构函数会被调用。
- // 这使得RAII这样的强大范式(参见下文)成为可能。
- // 为了衍生出子类来,基类的析构函数必须定义为虚函数。
- virtual ~Dog();
-
-}; // 在类的定义之后,要加一个分号
-
-// 类的成员函数通常在.cpp文件中实现。
-void Dog::Dog()
-{
- std::cout << "A dog has been constructed\n";
-}
-
-// 对象(例如字符串)应当以引用的形式传递,
-// 对于不需要修改的对象,最好使用常量引用。
-void Dog::setName(const std::string& dogsName)
-{
- name = dogsName;
-}
-
-void Dog::setWeight(int dogsWeight)
-{
- weight = dogsWeight;
-}
-
-// 虚函数的virtual关键字只需要在声明时使用,不需要在定义时重复
-void Dog::print() const
-{
- std::cout << "Dog is " << name << " and weighs " << weight << "kg\n";
-}
-
-void Dog::~Dog()
-{
- std::cout << "Goodbye " << name << "\n";
-}
-
-int main() {
- Dog myDog; // 此时显示“A dog has been constructed”
- myDog.setName("Barkley");
- myDog.setWeight(10);
- myDog.print(); // 显示“Dog is Barkley and weighs 10 kg”
- return 0;
-} // 显示“Goodbye Barkley”
-
-// 继承:
-
-// 这个类继承了Dog类中的公有(public)和保护(protected)对象
-class OwnedDog : public Dog {
-
- void setOwner(const std::string& dogsOwner)
-
- // 重写OwnedDogs类的print方法。
- // 如果你不熟悉子类多态的话,可以参考这个页面中的概述:
- // http://zh.wikipedia.org/wiki/%E5%AD%90%E7%B1%BB%E5%9E%8B
-
- // override关键字是可选的,它确保你所重写的是基类中的方法。
- void print() const override;
-
-private:
- std::string owner;
-};
-
-// 与此同时,在对应的.cpp文件里:
-
-void OwnedDog::setOwner(const std::string& dogsOwner)
-{
- owner = dogsOwner;
-}
-
-void OwnedDog::print() const
-{
- Dog::print(); // 调用基类Dog中的print方法
- // "Dog is <name> and weights <weight>"
-
- std::cout << "Dog is owned by " << owner << "\n";
- // "Dog is owned by <owner>"
-}
-
-/////////////////////
-// 初始化与运算符重载
-/////////////////////
-
-// 在C++中,通过定义一些特殊名称的函数,
-// 你可以重载+、-、*、/等运算符的行为。
-// 当运算符被使用时,这些特殊函数会被调用,从而实现运算符重载。
-
-#include <iostream>
-using namespace std;
-
-class Point {
-public:
- // 可以以这样的方式为成员变量设置默认值。
- double x = 0;
- double y = 0;
-
- // 定义一个默认的构造器。
- // 除了将Point初始化为(0, 0)以外,这个函数什么都不做。
- Point() { };
-
- // 下面使用的语法称为初始化列表,
- // 这是初始化类中成员变量的正确方式。
- Point (double a, double b) :
- x(a),
- y(b)
- { /* 除了初始化成员变量外,什么都不做 */ }
-
- // 重载 + 运算符
- Point operator+(const Point& rhs) const;
-
- // 重载 += 运算符
- Point& operator+=(const Point& rhs);
-
- // 增加 - 和 -= 运算符也是有意义的,但这里不再赘述。
-};
-
-Point Point::operator+(const Point& rhs) const
-{
- // 创建一个新的点,
- // 其横纵坐标分别为这个点与另一点在对应方向上的坐标之和。
- return Point(x + rhs.x, y + rhs.y);
-}
-
-Point& Point::operator+=(const Point& rhs)
-{
- x += rhs.x;
- y += rhs.y;
- return *this;
-}
-
-int main () {
- Point up (0,1);
- Point right (1,0);
- // 这里使用了Point类型的运算符“+”
- // 调用up(Point类型)的“+”方法,并以right作为函数的参数
- Point result = up + right;
- // 显示“Result is upright (1,1)”
- cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
- return 0;
-}
-
-///////////
-// 异常处理
-///////////
-
-// 标准库中提供了一些基本的异常类型
-// (参见http://en.cppreference.com/w/cpp/error/exception)
-// 但是,其他任何类型也可以作为一个异常被拋出
-#include <exception>
-
-// 在_try_代码块中拋出的异常可以被随后的_catch_捕获。
-try {
- // 不要用 _new_关键字在堆上为异常分配空间。
- throw std::exception("A problem occurred");
-}
-// 如果拋出的异常是一个对象,可以用常量引用来捕获它
-catch (const std::exception& ex)
-{
- std::cout << ex.what();
-// 捕获尚未被_catch_处理的所有错误
-} catch (...)
-{
- std::cout << "Unknown exception caught";
- throw; // 重新拋出异常
-}
-
-///////
-// RAII
-///////
-
-// RAII指的是“资源获取就是初始化”(Resource Allocation Is Initialization),
-// 它被视作C++中最强大的编程范式之一。
-// 简单说来,它指的是,用构造函数来获取一个对象的资源,
-// 相应的,借助析构函数来释放对象的资源。
-
-// 为了理解这一范式的用处,让我们考虑某个函数使用文件句柄时的情况:
-void doSomethingWithAFile(const char* filename)
-{
- // 首先,让我们假设一切都会顺利进行。
-
- FILE* fh = fopen(filename, "r"); // 以只读模式打开文件
-
- doSomethingWithTheFile(fh);
- doSomethingElseWithIt(fh);
-
- fclose(fh); // 关闭文件句柄
-}
-
-// 不幸的是,随着错误处理机制的引入,事情会变得复杂。
-// 假设fopen函数有可能执行失败,
-// 而doSomethingWithTheFile和doSomethingElseWithIt会在失败时返回错误代码。
-// (虽然异常是C++中处理错误的推荐方式,
-// 但是某些程序员,尤其是有C语言背景的,并不认可异常捕获机制的作用)。
-// 现在,我们必须检查每个函数调用是否成功执行,并在问题发生的时候关闭文件句柄。
-bool doSomethingWithAFile(const char* filename)
-{
- FILE* fh = fopen(filename, "r"); // 以只读模式打开文件
- if (fh == nullptr) // 当执行失败是,返回的指针是nullptr
- return false; // 向调用者汇报错误
-
- // 假设每个函数会在执行失败时返回false
- if (!doSomethingWithTheFile(fh)) {
- fclose(fh); // 关闭文件句柄,避免造成内存泄漏。
- return false; // 反馈错误
- }
- if (!doSomethingElseWithIt(fh)) {
- fclose(fh); // 关闭文件句柄
- return false; // 反馈错误
- }
-
- fclose(fh); // 关闭文件句柄
- return true; // 指示函数已成功执行
-}
-
-// C语言的程序员通常会借助goto语句简化上面的代码:
-bool doSomethingWithAFile(const char* filename)
-{
- FILE* fh = fopen(filename, "r");
- if (fh == nullptr)
- return false;
-
- if (!doSomethingWithTheFile(fh))
- goto failure;
-
- if (!doSomethingElseWithIt(fh))
- goto failure;
-
- fclose(fh); // 关闭文件
- return true; // 执行成功
-
-failure:
- fclose(fh);
- return false; // 反馈错误
-}
-
-// 如果用异常捕获机制来指示错误的话,
-// 代码会变得清晰一些,但是仍然有优化的余地。
-void doSomethingWithAFile(const char* filename)
-{
- FILE* fh = fopen(filename, "r"); // 以只读模式打开文件
- if (fh == nullptr)
- throw std::exception("Could not open the file.");
-
- try {
- doSomethingWithTheFile(fh);
- doSomethingElseWithIt(fh);
- }
- catch (...) {
- fclose(fh); // 保证出错的时候文件被正确关闭
- throw; // 之后,重新抛出这个异常
- }
-
- fclose(fh); // 关闭文件
- // 所有工作顺利完成
-}
-
-// 相比之下,使用C++中的文件流类(fstream)时,
-// fstream会利用自己的析构器来关闭文件句柄。
-// 只要离开了某一对象的定义域,它的析构函数就会被自动调用。
-void doSomethingWithAFile(const std::string& filename)
-{
- // ifstream是输入文件流(input file stream)的简称
- std::ifstream fh(filename); // 打开一个文件
-
- // 对文件进行一些操作
- doSomethingWithTheFile(fh);
- doSomethingElseWithIt(fh);
-
-} // 文件已经被析构器自动关闭
-
-// 与上面几种方式相比,这种方式有着_明显_的优势:
-// 1. 无论发生了什么情况,资源(此例当中是文件句柄)都会被正确关闭。
-// 只要你正确使用了析构器,就_不会_因为忘记关闭句柄,造成资源的泄漏。
-// 2. 可以注意到,通过这种方式写出来的代码十分简洁。
-// 析构器会在后台关闭文件句柄,不再需要你来操心这些琐事。
-// 3. 这种方式的代码具有异常安全性。
-// 无论在函数中的何处拋出异常,都不会阻碍对文件资源的释放。
-
-// 地道的C++代码应当把RAII的使用扩展到各种类型的资源上,包括:
-// - 用unique_ptr和shared_ptr管理的内存
-// - 各种数据容器,例如标准库中的链表、向量(容量自动扩展的数组)、散列表等;
-// 当它们脱离作用域时,析构器会自动释放其中储存的内容。
-// - 用lock_guard和unique_lock实现的互斥
-```
-扩展阅读:
-
-* [CPP Reference](http://cppreference.com/w/cpp) 提供了最新的语法参考。
-* 可以在 [CPlusPlus](http://cplusplus.com) 找到一些补充资料。
-* 可以在 [TheChernoProject - C ++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb)上找到涵盖语言基础和设置编码环境的教程。
+--- +language: C++ +filename: learncpp-cn.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] +translators: + - ["Arnie97", "https://github.com/Arnie97"] +lang: zh-cn +--- + +C++是一种系统编程语言。用它的发明者, +[Bjarne Stroustrup的话](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)来说,C++的设计目标是: + +- 成为“更好的C语言” +- 支持数据的抽象与封装 +- 支持面向对象编程 +- 支持泛型编程 + +C++提供了对硬件的紧密控制(正如C语言一样), +能够编译为机器语言,由处理器直接执行。 +与此同时,它也提供了泛型、异常和类等高层功能。 +虽然C++的语法可能比某些出现较晚的语言更复杂,它仍然得到了人们的青睞—— +功能与速度的平衡使C++成为了目前应用最广泛的系统编程语言之一。 + +```c++ +//////////////// +// 与C语言的比较 +//////////////// + +// C++_几乎_是C语言的一个超集,它与C语言的基本语法有许多相同之处, +// 例如变量和函数的声明,原生数据类型等等。 + +// 和C语言一样,在C++中,你的程序会从main()开始执行, +// 该函数的返回值应当为int型,这个返回值会作为程序的退出状态值。 +// 不过,大多数的编译器(gcc,clang等)也接受 void main() 的函数原型。 +// (参见 http://en.wikipedia.org/wiki/Exit_status 来获取更多信息) +int main(int argc, char** argv) +{ + // 和C语言一样,命令行参数通过argc和argv传递。 + // argc代表命令行参数的数量, + // 而argv是一个包含“C语言风格字符串”(char *)的数组, + // 其中每个字符串代表一个命令行参数的内容, + // 首个命令行参数是调用该程序时所使用的名称。 + // 如果你不关心命令行参数的值,argc和argv可以被忽略。 + // 此时,你可以用int main()作为函数原型。 + + // 退出状态值为0时,表示程序执行成功 + return 0; +} + +// 然而,C++和C语言也有一些区别: + +// 在C++中,字符字面量的大小是一个字节。 +sizeof('c') == 1 + +// 在C语言中,字符字面量的大小与int相同。 +sizeof('c') == sizeof(10) + + +// C++的函数原型与函数定义是严格匹配的 +void func(); // 这个函数不能接受任何参数 + +// 而在C语言中 +void func(); // 这个函数能接受任意数量的参数 + +// 在C++中,用nullptr代替C语言中的NULL +int* ip = nullptr; + +// C++也可以使用C语言的标准头文件, +// 但是需要加上前缀“c”并去掉末尾的“.h”。 +#include <cstdio> + +int main() +{ + printf("Hello, world!\n"); + return 0; +} + +/////////// +// 函数重载 +/////////// + +// C++支持函数重载,你可以定义一组名称相同而参数不同的函数。 + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("My int is %d", myInt); +} + +int main() +{ + print("Hello"); // 解析为 void print(const char*) + print(15); // 解析为 void print(int) +} + +/////////////////// +// 函数参数的默认值 +/////////////////// + +// 你可以为函数的参数指定默认值, +// 它们将会在调用者没有提供相应参数时被使用。 + +void doSomethingWithInts(int a = 1, int b = 4) +{ + // 对两个参数进行一些操作 +} + +int main() +{ + doSomethingWithInts(); // a = 1, b = 4 + doSomethingWithInts(20); // a = 20, b = 4 + doSomethingWithInts(20, 5); // a = 20, b = 5 +} + +// 默认参数必须放在所有的常规参数之后。 + +void invalidDeclaration(int a = 1, int b) // 这是错误的! +{ +} + + +/////////// +// 命名空间 +/////////// + +// 命名空间为变量、函数和其他声明提供了分离的的作用域。 +// 命名空间可以嵌套使用。 + +namespace First { + namespace Nested { + void foo() + { + printf("This is First::Nested::foo\n"); + } + } // 结束嵌套的命名空间Nested +} // 结束命名空间First + +namespace Second { + void foo() + { + printf("This is Second::foo\n") + } +} + +void foo() +{ + printf("This is global foo\n"); +} + +int main() +{ + // 如果没有特别指定,就从“Second”中取得所需的内容。 + using namespace Second; + + foo(); // 显示“This is Second::foo” + First::Nested::foo(); // 显示“This is First::Nested::foo” + ::foo(); // 显示“This is global foo” +} + +//////////// +// 输入/输出 +//////////// + +// C++使用“流”来输入输出。<<是流的插入运算符,>>是流提取运算符。 +// cin、cout、和cerr分别代表 +// stdin(标准输入)、stdout(标准输出)和stderr(标准错误)。 + +#include <iostream> // 引入包含输入/输出流的头文件 + +using namespace std; // 输入输出流在std命名空间(也就是标准库)中。 + +int main() +{ + int myInt; + + // 在标准输出(终端/显示器)中显示 + cout << "Enter your favorite number:\n"; + // 从标准输入(键盘)获得一个值 + cin >> myInt; + + // cout也提供了格式化功能 + cout << "Your favorite number is " << myInt << "\n"; + // 显示“Your favorite number is <myInt>” + + cerr << "Used for error messages"; +} + +///////// +// 字符串 +///////// + +// C++中的字符串是对象,它们有很多成员函数 +#include <string> + +using namespace std; // 字符串也在std命名空间(标准库)中。 + +string myString = "Hello"; +string myOtherString = " World"; + +// + 可以用于连接字符串。 +cout << myString + myOtherString; // "Hello World" + +cout << myString + " You"; // "Hello You" + +// C++中的字符串是可变的,具有“值语义”。 +myString.append(" Dog"); +cout << myString; // "Hello Dog" + + +///////////// +// 引用 +///////////// + +// 除了支持C语言中的指针类型以外,C++还提供了_引用_。 +// 引用是一种特殊的指针类型,一旦被定义就不能重新赋值,并且不能被设置为空值。 +// 使用引用时的语法与原变量相同: +// 也就是说,对引用类型进行解引用时,不需要使用*; +// 赋值时也不需要用&来取地址。 + +using namespace std; + +string foo = "I am foo"; +string bar = "I am bar"; + + +string& fooRef = foo; // 建立了一个对foo的引用。 +fooRef += ". Hi!"; // 通过引用来修改foo的值 +cout << fooRef; // "I am foo. Hi!" + +// 这句话的并不会改变fooRef的指向,其效果与“foo = bar”相同。 +// 也就是说,在执行这条语句之后,foo == "I am bar"。 +fooRef = bar; + +const string& barRef = bar; // 建立指向bar的常量引用。 +// 和C语言中一样,(指针和引用)声明为常量时,对应的值不能被修改。 +barRef += ". Hi!"; // 这是错误的,不能修改一个常量引用的值。 + +/////////////////// +// 类与面向对象编程 +/////////////////// + +// 有关类的第一个示例 +#include <iostream> + +// 声明一个类。 +// 类通常在头文件(.h或.hpp)中声明。 +class Dog { + // 成员变量和成员函数默认情况下是私有(private)的。 + std::string name; + int weight; + +// 在这个标签之后,所有声明都是公有(public)的, +// 直到重新指定“private:”(私有继承)或“protected:”(保护继承)为止 +public: + + // 默认的构造器 + Dog(); + + // 这里是成员函数声明的一个例子。 + // 可以注意到,我们在此处使用了std::string,而不是using namespace std + // 语句using namespace绝不应当出现在头文件当中。 + void setName(const std::string& dogsName); + + void setWeight(int dogsWeight); + + // 如果一个函数不对对象的状态进行修改, + // 应当在声明中加上const。 + // 这样,你就可以对一个以常量方式引用的对象执行该操作。 + // 同时可以注意到,当父类的成员函数需要被子类重写时, + // 父类中的函数必须被显式声明为_虚函数(virtual)_。 + // 考虑到性能方面的因素,函数默认情况下不会被声明为虚函数。 + virtual void print() const; + + // 函数也可以在class body内部定义。 + // 这样定义的函数会自动成为内联函数。 + void bark() const { std::cout << name << " barks!\n" } + + // 除了构造器以外,C++还提供了析构器。 + // 当一个对象被删除或者脱离其定义域时,它的析构函数会被调用。 + // 这使得RAII这样的强大范式(参见下文)成为可能。 + // 为了衍生出子类来,基类的析构函数必须定义为虚函数。 + virtual ~Dog(); + +}; // 在类的定义之后,要加一个分号 + +// 类的成员函数通常在.cpp文件中实现。 +void Dog::Dog() +{ + std::cout << "A dog has been constructed\n"; +} + +// 对象(例如字符串)应当以引用的形式传递, +// 对于不需要修改的对象,最好使用常量引用。 +void Dog::setName(const std::string& dogsName) +{ + name = dogsName; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// 虚函数的virtual关键字只需要在声明时使用,不需要在定义时重复 +void Dog::print() const +{ + std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; +} + +void Dog::~Dog() +{ + std::cout << "Goodbye " << name << "\n"; +} + +int main() { + Dog myDog; // 此时显示“A dog has been constructed” + myDog.setName("Barkley"); + myDog.setWeight(10); + myDog.print(); // 显示“Dog is Barkley and weighs 10 kg” + return 0; +} // 显示“Goodbye Barkley” + +// 继承: + +// 这个类继承了Dog类中的公有(public)和保护(protected)对象 +class OwnedDog : public Dog { + + void setOwner(const std::string& dogsOwner) + + // 重写OwnedDogs类的print方法。 + // 如果你不熟悉子类多态的话,可以参考这个页面中的概述: + // http://zh.wikipedia.org/wiki/%E5%AD%90%E7%B1%BB%E5%9E%8B + + // override关键字是可选的,它确保你所重写的是基类中的方法。 + void print() const override; + +private: + std::string owner; +}; + +// 与此同时,在对应的.cpp文件里: + +void OwnedDog::setOwner(const std::string& dogsOwner) +{ + owner = dogsOwner; +} + +void OwnedDog::print() const +{ + Dog::print(); // 调用基类Dog中的print方法 + // "Dog is <name> and weights <weight>" + + std::cout << "Dog is owned by " << owner << "\n"; + // "Dog is owned by <owner>" +} + +///////////////////// +// 初始化与运算符重载 +///////////////////// + +// 在C++中,通过定义一些特殊名称的函数, +// 你可以重载+、-、*、/等运算符的行为。 +// 当运算符被使用时,这些特殊函数会被调用,从而实现运算符重载。 + +#include <iostream> +using namespace std; + +class Point { +public: + // 可以以这样的方式为成员变量设置默认值。 + double x = 0; + double y = 0; + + // 定义一个默认的构造器。 + // 除了将Point初始化为(0, 0)以外,这个函数什么都不做。 + Point() { }; + + // 下面使用的语法称为初始化列表, + // 这是初始化类中成员变量的正确方式。 + Point (double a, double b) : + x(a), + y(b) + { /* 除了初始化成员变量外,什么都不做 */ } + + // 重载 + 运算符 + Point operator+(const Point& rhs) const; + + // 重载 += 运算符 + Point& operator+=(const Point& rhs); + + // 增加 - 和 -= 运算符也是有意义的,但这里不再赘述。 +}; + +Point Point::operator+(const Point& rhs) const +{ + // 创建一个新的点, + // 其横纵坐标分别为这个点与另一点在对应方向上的坐标之和。 + return Point(x + rhs.x, y + rhs.y); +} + +Point& Point::operator+=(const Point& rhs) +{ + x += rhs.x; + y += rhs.y; + return *this; +} + +int main () { + Point up (0,1); + Point right (1,0); + // 这里使用了Point类型的运算符“+” + // 调用up(Point类型)的“+”方法,并以right作为函数的参数 + Point result = up + right; + // 显示“Result is upright (1,1)” + cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; + return 0; +} + +/////////// +// 异常处理 +/////////// + +// 标准库中提供了一些基本的异常类型 +// (参见http://en.cppreference.com/w/cpp/error/exception) +// 但是,其他任何类型也可以作为一个异常被拋出 +#include <exception> + +// 在_try_代码块中拋出的异常可以被随后的_catch_捕获。 +try { + // 不要用 _new_关键字在堆上为异常分配空间。 + throw std::exception("A problem occurred"); +} +// 如果拋出的异常是一个对象,可以用常量引用来捕获它 +catch (const std::exception& ex) +{ + std::cout << ex.what(); +// 捕获尚未被_catch_处理的所有错误 +} catch (...) +{ + std::cout << "Unknown exception caught"; + throw; // 重新拋出异常 +} + +/////// +// RAII +/////// + +// RAII指的是“资源获取就是初始化”(Resource Allocation Is Initialization), +// 它被视作C++中最强大的编程范式之一。 +// 简单说来,它指的是,用构造函数来获取一个对象的资源, +// 相应的,借助析构函数来释放对象的资源。 + +// 为了理解这一范式的用处,让我们考虑某个函数使用文件句柄时的情况: +void doSomethingWithAFile(const char* filename) +{ + // 首先,让我们假设一切都会顺利进行。 + + FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 + + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + + fclose(fh); // 关闭文件句柄 +} + +// 不幸的是,随着错误处理机制的引入,事情会变得复杂。 +// 假设fopen函数有可能执行失败, +// 而doSomethingWithTheFile和doSomethingElseWithIt会在失败时返回错误代码。 +// (虽然异常是C++中处理错误的推荐方式, +// 但是某些程序员,尤其是有C语言背景的,并不认可异常捕获机制的作用)。 +// 现在,我们必须检查每个函数调用是否成功执行,并在问题发生的时候关闭文件句柄。 +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 + if (fh == nullptr) // 当执行失败是,返回的指针是nullptr + return false; // 向调用者汇报错误 + + // 假设每个函数会在执行失败时返回false + if (!doSomethingWithTheFile(fh)) { + fclose(fh); // 关闭文件句柄,避免造成内存泄漏。 + return false; // 反馈错误 + } + if (!doSomethingElseWithIt(fh)) { + fclose(fh); // 关闭文件句柄 + return false; // 反馈错误 + } + + fclose(fh); // 关闭文件句柄 + return true; // 指示函数已成功执行 +} + +// C语言的程序员通常会借助goto语句简化上面的代码: +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); + if (fh == nullptr) + return false; + + if (!doSomethingWithTheFile(fh)) + goto failure; + + if (!doSomethingElseWithIt(fh)) + goto failure; + + fclose(fh); // 关闭文件 + return true; // 执行成功 + +failure: + fclose(fh); + return false; // 反馈错误 +} + +// 如果用异常捕获机制来指示错误的话, +// 代码会变得清晰一些,但是仍然有优化的余地。 +void doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 + if (fh == nullptr) + throw std::exception("Could not open the file."); + + try { + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + } + catch (...) { + fclose(fh); // 保证出错的时候文件被正确关闭 + throw; // 之后,重新抛出这个异常 + } + + fclose(fh); // 关闭文件 + // 所有工作顺利完成 +} + +// 相比之下,使用C++中的文件流类(fstream)时, +// fstream会利用自己的析构器来关闭文件句柄。 +// 只要离开了某一对象的定义域,它的析构函数就会被自动调用。 +void doSomethingWithAFile(const std::string& filename) +{ + // ifstream是输入文件流(input file stream)的简称 + std::ifstream fh(filename); // 打开一个文件 + + // 对文件进行一些操作 + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + +} // 文件已经被析构器自动关闭 + +// 与上面几种方式相比,这种方式有着_明显_的优势: +// 1. 无论发生了什么情况,资源(此例当中是文件句柄)都会被正确关闭。 +// 只要你正确使用了析构器,就_不会_因为忘记关闭句柄,造成资源的泄漏。 +// 2. 可以注意到,通过这种方式写出来的代码十分简洁。 +// 析构器会在后台关闭文件句柄,不再需要你来操心这些琐事。 +// 3. 这种方式的代码具有异常安全性。 +// 无论在函数中的何处拋出异常,都不会阻碍对文件资源的释放。 + +// 地道的C++代码应当把RAII的使用扩展到各种类型的资源上,包括: +// - 用unique_ptr和shared_ptr管理的内存 +// - 各种数据容器,例如标准库中的链表、向量(容量自动扩展的数组)、散列表等; +// 当它们脱离作用域时,析构器会自动释放其中储存的内容。 +// - 用lock_guard和unique_lock实现的互斥 +``` +扩展阅读: + +* [CPP Reference](http://cppreference.com/w/cpp) 提供了最新的语法参考。 +* 可以在 [CPlusPlus](http://cplusplus.com) 找到一些补充资料。 +* 可以在 [TheChernoProject - C ++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb)上找到涵盖语言基础和设置编码环境的教程。 diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown index 8566e811..851f2981 100644 --- a/zh-cn/c-cn.html.markdown +++ b/zh-cn/c-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: c +language: C filename: learnc-cn.c contributors: - ["Adam Bard", "http://adambard.com/"] @@ -128,7 +128,7 @@ printf("Enter the array size: "); // 询问用户数组长度 char buf[0x100]; fgets(buf, sizeof buf, stdin); -// stroul 将字符串解析为无符号整数 +// strtoul 将字符串解析为无符号整数 size_t size = strtoul(buf, NULL, 10); int var_length_array[size]; // 声明VLA printf("sizeof array = %zu\n", sizeof var_length_array); @@ -474,7 +474,7 @@ void testFunc() { // 用户自定义类型和结构 /////////////////////////////////////// -// Typedefs可以创建类型别名 +// typedef 可以创建类型别名 typedef int my_type; my_type my_type_var = 0; @@ -612,11 +612,11 @@ typedef void (*my_fnp_type)(char *); 最好找一本 [K&R, aka "The C Programming Language", “C程序设计语言”](https://en.wikipedia.org/wiki/The_C_Programming_Language)。它是关于C最重要的一本书,由C的创作者撰写。不过需要留意的是它比较古老了,因此有些不准确的地方。 -另一个比较好的资源是 [Learn C the hard way](http://c.learncodethehardway.org/book/) +另一个比较好的资源是 [Learn C the hard way](http://learncodethehardway.org/c/) 如果你有问题,请阅读[compl.lang.c Frequently Asked Questions](http://c-faq.com/)。 -使用合适的空格、缩进,保持一致的代码风格非常重要。可读性强的代码比聪明的代码、高速的代码更重要。可以参考下[Linux内核编码风格](https://www.kernel.org/doc/Documentation/CodingStyle) +使用合适的空格、缩进,保持一致的代码风格非常重要。可读性强的代码比聪明的代码、高速的代码更重要。可以参考下[Linux内核编码风格](https://www.kernel.org/doc/Documentation/process/coding-style.rst) 。 除了这些,多多Google吧 diff --git a/zh-cn/clojure-cn.html.markdown b/zh-cn/clojure-cn.html.markdown index fa241384..e98eac2a 100644 --- a/zh-cn/clojure-cn.html.markdown +++ b/zh-cn/clojure-cn.html.markdown @@ -362,7 +362,7 @@ Clojuredocs.org有大多数核心函数的文档,还带了示例哦: [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) 4Clojure是个很赞的用来练习clojure/FP技能的地方: -[http://www.4clojure.com/](http://www.4clojure.com/) +[https://4clojure.oxal.org/](https://4clojure.oxal.org/) Clojure-doc.org (你没看错)有很多入门级的文章: [http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/zh-cn/clojure-macro-cn.html.markdown b/zh-cn/clojure-macro-cn.html.markdown index 23b2f203..85b966e9 100644 --- a/zh-cn/clojure-macro-cn.html.markdown +++ b/zh-cn/clojure-macro-cn.html.markdown @@ -131,7 +131,7 @@ lang: zh-cn ; 然而,如果我们希望它在编译期执行,就需要创建宏 (defmacro inline-2 [form] - (inline-2-helper form))) + (inline-2-helper form)) (macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1))) ; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1) diff --git a/zh-cn/cmake-cn.html.markdown b/zh-cn/cmake-cn.html.markdown new file mode 100644 index 00000000..dd9961ca --- /dev/null +++ b/zh-cn/cmake-cn.html.markdown @@ -0,0 +1,168 @@ +--- +category: tool +tool: cmake +contributors: + - ["Bruno Alano", "https://github.com/brunoalano"] +translators: + - ["tx23", "https://github.com/tx23"] +filename: CMake-cn +lang: zh-cn +--- + +CMake 是一个跨平台且开源的自动化构建系统工具。通过该工具你可以对你的源代码进行测试、编译或创建安装包。 + +CMake 试图去解决Makefile 跨平台的自动配置问题(不同的make解释器有不同的命令),以及链接第三方库时的易用性问题。 + +CMake是一个可扩展的开源系统,它以操作系统和与编译器无关的方式管理构建过程。与其他许多跨平台系统不同的是, +CMake被设计为与本机的构建环境结合使用。它通过被放置于每个源文件目录下的简单配置文件(名为 CMakeLists.txt 的文件) +来生成常规使用的标准构建文件(比如:Unix 下的 makefiles 文件或 Windows MSVC 中的 projects/workspaces)。 + +```cmake +# 在 CMake 中, 这是一条命令 + +# 要运行我们的代码,请执行以下命令: +# - mkdir build && cd build +# - cmake .. +# - make +# +# 通过上述命令,我们将遵循最佳实践在子目录中进行编译 +# 在第二行命令中我们请求Cmake 生成新的依赖于系统的Makefile文件。 +# 最后,我们运行本地的make 命令。 + +#------------------------------------------------------------------------------ +# 基础部分 +#------------------------------------------------------------------------------ +# +# Cmake文件必须被命令为 “CMakeLists.txt” 。 + +# 设置生成Makefile的CMake所需最低版本要求 +cmake_minimum_required (VERSION 2.8) + +# 当版本小于2.8时,需要加入关键字 FATAL_ERROR。 +cmake_minimum_required (VERSION 2.8 FATAL_ERROR) + +# 在这里定义了项目的名称,同时会影响Cmake 生成的目录命名约定。 +# 我们可以将代码的语言作为第二个参数传入。 +project (learncmake C) + +# 设置项目的源目录(仅仅是由于惯例) +set( LEARN_CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) +set( LEARN_CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) + +# 在构建系统中用“semver”风格为我们代码设置当前版本是很有用的。 +set (LEARN_CMAKE_VERSION_MAJOR 1) +set (LEARN_CMAKE_VERSION_MINOR 0) +set (LEARN_CMAKE_VERSION_PATCH 0) + +# 将变量(版本号)发送到源代码头 +configure_file ( + "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" + "${PROJECT_BINARY_DIR}/TutorialConfig.h" +) + +# 包含目录 +# 在 GCC中, 该语句等同于 "-I" 命令 +include_directories( include ) + +# 在哪里安装其他库?注意:在此处提供includes路径,后续检查将解决所有其他问题 +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/modules/" ) + +# 条件 +if ( CONDITION ) + # 输出! + + # 附带信息 + message(STATUS "My message") + + # CMake 警告,继续处理 + message(WARNING "My message") + + # CMake 警告 (dev),继续处理 + message(AUTHOR_WARNING "My message") + + # CMake 错误,继续处理但是会跳过生成 + message(SEND_ERROR "My message") + + # CMake 错误,停止处理和生成 + message(FATAL_ERROR "My message") +endif() + +if( CONDITION ) + +elseif( CONDITION ) + +else( CONDITION ) + +endif( CONDITION ) + +# 循环 +foreach(loop_var arg1 arg2 ...) + COMMAND1(ARGS ...) + COMMAND2(ARGS ...) + ... +endforeach(loop_var) + +foreach(loop_var RANGE total) +foreach(loop_var RANGE start stop [step]) + +foreach(loop_var IN [LISTS [list1 [...]]] + [ITEMS [item1 [...]]]) + +while(condition) + COMMAND1(ARGS ...) + COMMAND2(ARGS ...) + ... +endwhile(condition) + + +# 逻辑运算 +if(FALSE AND (FALSE OR TRUE)) + message("Don't display!") +endif() + +# 将常规,缓存或环境变量设置为给定值。 +# 如果指定了PARENT_SCOPE选项,则将在当前作用域上的作用域中设置变量 +# `set(<variable> <value>... [PARENT_SCOPE])` + +# 如何在带引号和不带引号的参数中引用变量?How to reference variables inside quoted and unquoted arguments? +# 如果未设置变量,变量引用由变量值或空字符串替换。 +${variable_name} + +# 清单 +# 设置源文件列表 +set( LEARN_CMAKE_SOURCES + src/main.c + src/imagem.c + src/pather.c +) + +# 调用编译器 +# +# ${PROJECT_NAME} 即 Learn_CMake +add_executable( ${PROJECT_NAME} ${LEARN_CMAKE_SOURCES} ) + +# 链接库 +target_link_libraries( ${PROJECT_NAME} ${LIBS} m ) + +# 在哪里安装其他库?注意:在此处提供includes路径,后续检查将解决所有其他问题 +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/modules/" ) + +# 编译条件 (gcc ; g++) +if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" ) + message( STATUS "Setting the flags for ${CMAKE_C_COMPILER_ID} compiler" ) + add_definitions( --std=c99 ) +endif() + +# 检查 OS +if( UNIX ) + set( LEARN_CMAKE_DEFINITIONS + "${LEARN_CMAKE_DEFINITIONS} -Wall -Wextra -Werror -Wno-deprecated-declarations -Wno-unused-parameter -Wno-comment" ) +endif() +``` + +### 资源 + ++ [CMake tutorial](https://cmake.org/cmake-tutorial/) ++ [CMake documentation](https://cmake.org/documentation/) ++ [Mastering CMake](http://amzn.com/1930934319/) ++ [An Introduction to Modern CMake](https://cliutils.gitlab.io/modern-cmake/) diff --git a/zh-cn/cobol-cn.html.markdown b/zh-cn/cobol-cn.html.markdown new file mode 100644 index 00000000..08eb36fb --- /dev/null +++ b/zh-cn/cobol-cn.html.markdown @@ -0,0 +1,192 @@ +--- +language: COBOL +filename: learn-cn.COB +contributors: + - ["Hyphz", "http://github.com/hyphz/"] +translators: + - ["GOLGO11", "https://github.com/GOLGO11/"] +lang: zh-cn +--- +COBOL是一门面向商业的语言,它从1960年最初设计以来被修订过数次。它被宣称仍然有超过80%的机构在使用它。 + +```cobol + *COBOL. 最好是按照它1985年的标准来编程。 + *用附带GnuCOBOL编译器的OpenCobolIDE 4.7.6来编译。 + + *COBOL在老版(COBOL-85)和新版(COBOL-2002以及COBOL-2014)之间有明显的差别。 + *老版COBOL要求编码的前一到六列是空着的(它们被用来存储穿孔卡片的序列号... + *第七列的一个“*”符号表示注释的开始。 + *在老版COBOL中,一条以*开头的注释最长只能占一行, + *新版COBOL不需要额外的列来补序列号,并且用“*>" 来注释,允许在行中开始注释 + *老版COBOL也强加了对最大行长度的限制 + *关键字在老版COBOL中必须大写, + *但在新版COBOL中不区分大小写 + *虽然新版COBOL允许你编写大小写混合的代码 + *但是在大多数情况下编写COBOL代码时全用大写字符 + *大多数专业的COBOL开发者都是这么做的。 + *COBOL语句以句点结尾。 + + *COBOL代码被拆成了四个部。 + *各部按顺序,它们是: + *IDENTIFICATION DIVSION.(标识部) + *ENVIRONMENT DIVISION.(环境部) + *DATA DIVISION.(数据部) + *PROCEDURE DIVISION.(过程部) + + *第一步,我们必须给我们的程序一个ID。 + *Identification division 也能包含其他的值, + *但它们都只是程序的元数据。Program-id是唯一一个必须给出的值。 + IDENTIFICATION DIVISION. + PROGRAM-ID. LEARN. + AUTHOR. JOHN DOE. + DATE-WRITTEN. 05/02/2020. + + *让我们来声明一些变量。 + *我们要在DATA DIVISION的WORKING-STORAGE节来完成这个事情。 + *每个数据项(又名变量)从一个级别编号开始。 + *然后是数据项的名字,后边再跟着一个picture关键字, + *来描述这个变量将要包含的数据的类型。 + *几乎所有的COBOL开发者都会把PICTURE简写为PIC。 + *A代表字母,X代表字母和数字,9代表数字。 + + *举例: + 01 MYNAME PIC xxxxxxxxxx. *> 十个字符的字符串。 + + *但是逐个数那些x会导致错误, + *所以以上代码可以,并且应该 + *这样重写: + 01 MYNAME PIC X(10). + + *这是几个更多的例子: + 01 AGE PIC 9(3). *> 数字最多三位 + 01 LAST_NAME PIC X(10). *> 字符串最多十个字符 + + *在COBOL里,一行中多个空格和一个空格的效果是一样的, 所以通常 + *情况下都用多个空格排列代码来便于 + *其他的开发者阅读。 + 01 inyear picture s9(7). *> S 使数字为正数. + *> 括号里意思是重复7次9, + *> 即六位数字(不是数组) + + *现在让我们来写一点儿代码。这是一个简单的Hello World程序。 + IDENTIFICATION DIVISION. + PROGRAM-ID. HELLO. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 THE-MESSAGE PIC X(20). + PROCEDURE DIVSION. + DISPLAY "STARTING PROGRAM". + MOVE "HELLO WORLD" TO THE-MESSAGE. + DISPLAY THE-MESSAGE. + STOP RUN. + + *以上的代码会输出: + *STARTING PROGRAM + *HELLO WORLD + + + + ********用COBOL可以做数学运算*************** + ADD 1 TO AGE GIVING NEW-AGE. + SUBTRACT 1 FROM COUNT. + DIVIDE VAR-1 INTO VAR-2 GIVING VAR-3. + COMPUTE TOTAL-COUNT = COUNT1 PLUS COUNT2. + + + *********PERFORM******************** + *PERFORM关键字允许你跳到代码中其他特殊的代码段, + *当这段特殊的代码被执行完后继续回来执行下面的可执行语句。 + *你必须把PERFORM这个词写完整,不可以缩写它。 + + IDENTIFICATION DIVISION. + PROGRAM-ID. HELLOCOBOL. + + PROCEDURE DIVISION. + FIRST-PARA. + DISPLAY 'THIS IS IN FIRST-PARA'. + PERFORM THIRD-PARA THRU FOURTH-PARA. *>跳过second-para,执行3rd&4th + *> 之后当third和fourth执行完, + *> 回到这里继续往下执行直到遇到STOP RUN. + + SECOND-PARA. + DISPLAY 'THIS IS IN SECOND-PARA'. + STOP RUN. + + THIRD-PARA. + DISPLAY 'THIS IS IN THIRD-PARA'. + + FOURTH-PARA. + DISPLAY 'THIS IS IN FOURTH-PARA'. + + + *当你编译执行以上程序时,它会生成以下结果: + THIS IS IN FIRST-PARA + THIS IS IN THIRD-PARA + THIS IS IN FOURTH-PARA + THIS IS IN SECOND-PARA + + + **********用STRING关键字把变量组合到一起************ + + *现在是时候学习两个类似的COBOL动词了:string和unstring。. + + *string动词经常被用来连接两个或多个字符串(把它们拼在一起)。 + *没什么特别的,Unstring被用来把一个字符串拆分成两个或多个更小的字符串。 + *当你在程序中使用string或unstring时不要忘记使用”delimited by“,这个很重要。 + + IDENTIFICATION DIVISION. + PROGRAM-ID. LEARNING. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 FULL-NAME PIC X(20). + 01 FIRST-NAME PIC X(13) VALUE "BOB GIBBERISH". + 01 LAST-NAME PIC X(5) VALUE "COBB". + PROCEDURE DIVISION. + STRING FIRST-NAME DELIMITED BY SPACE + " " + LAST-NAME DELIMITED BY SIZE + INTO FULL-NAME + END-STRING. + DISPLAY "THE FULL NAME IS: "FULL-NAME. + STOP RUN. + + + *以上代码将会输出: + THE FULL NAME IS: BOB COBB + + + *让我们来看看为什么是这样。 + + *首先,我们在DATA DIVISION声明了所有的变量, + *包括我们想存储string命令生成的新字符串用到的的变量。 + + *这个操作过程在PROCEDURE DIVISION完成。 + *我们从STRING 关键字开始,到END-STRING结束。 + *在它们之间我们列出我们想要组合变量形成更大的主变量的过程。 + *这里,我们组合了FIRST-NAME, 一个空格和LAST-NAME。 + + *跟在FIRST-NAME和LAST-NAME后面的DELIMITED BY短语告诉程序我们想要在各自变量上截取字符的规则。 + *DELIMITED BY SPACE告诉程序从最开始截取字符直到遇到一个空格。 + *DELIMITED BY SIZE告诉程序截取字符的完整长度。 + *我们在FIRST-NAME后面使用DELIMITED BY SPACE,字符串中的GIBBERISH部分就被忽略了。 + + *为了更清楚,改变代码中的第10行如下: + + STRING FIRST-NAME DELIMITED BY SIZE + + *然后重新执行程序. 这次的输出变成: + + THE FULL NAME IS: BOB GIBBERISH COBB + + + + + + +``` + +## 想了解更多吗? + +* [GnuCOBOL](https://sourceforge.net/projects/open-cobol/) + diff --git a/zh-cn/crystal-cn.html.markdown b/zh-cn/crystal-cn.html.markdown index 14805114..b69ce688 100644 --- a/zh-cn/crystal-cn.html.markdown +++ b/zh-cn/crystal-cn.html.markdown @@ -564,4 +564,4 @@ ex #=> "ex2" - [官方网站](https://crystal-lang.org/) - [官方文档](https://crystal-lang.org/docs/overview/) - [在线运行代码](https://play.crystal-lang.org/#/cr) -- [Github仓库](https://github.com/crystal-lang/crystal) +- [GitHub仓库](https://github.com/crystal-lang/crystal) diff --git a/zh-cn/csharp-cn.html.markdown b/zh-cn/csharp-cn.html.markdown index 971c1be9..b6cc70c0 100644 --- a/zh-cn/csharp-cn.html.markdown +++ b/zh-cn/csharp-cn.html.markdown @@ -1,49 +1,68 @@ --- -language: c# +language: C# contributors: - ["Irfan Charania", "https://github.com/irfancharania"] - ["Max Yankov", "https://github.com/golergka"] - ["Melvyn Laïly", "http://x2a.yt"] - ["Shaun McCarthy", "http://www.shaunmccarthy.com"] + - ["Wouter Van Schandevijl", "http://github.com/laoujin"] + - ["Jo Pearce", "http://github.com/jdpearce"] + - ["Chris Zimmerman", "https://github.com/chriszimmerman"] + - ["Shawn McGuire", "https://github.com/bigbash"] translators: - ["Jakukyo Friel", "http://weakish.github.io"] + - ["CatfishWen", "http://catfishwen.github.io"] filename: LearnCSharp-cn.cs lang: zh-cn --- +C#是一种优雅且类型安全的面向对象的语言,使开发人员能够构建运行在跨平台的.NET框架上,安全且健壮的应用程序。 -C#是一个优雅的、类型安全的面向对象语言。使用C#,开发者可以在.NET框架下构建安全、健壮的应用程序。 - -[更多关于C#的介绍](http://msdn.microsoft.com/en-us/library/vstudio/z1zx9t92.aspx) +[更多关于C#的介绍](https://learn.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/) ```c# // 单行注释以 // 开始 /* 多行注释是这样的 */ + /// <summary> -/// XML文档注释 +/// 这是 XML文档注释 +/// 可用于生成外部文档或在 IDE 中提供上下文帮助 /// </summary> +/// <param name="firstParam">这是 firstParam 参数的文档</param> +/// <returns>这是函数返回值的信息</returns> +public void MethodOrClassOrOtherWithParsableHelp(string firstParam) { } -// 声明应用用到的命名空间 +// 声明这段源码使用到的命名空间 +// 下面的命名空间都是标准 .NET Framework 类库的一部分 using System; using System.Collections.Generic; -using System.Data.Entity; using System.Dynamic; using System.Linq; -using System.Linq.Expressions; using System.Net; using System.Threading.Tasks; using System.IO; -// 定义作用域,将代码组织成包 +// 但是这个并不是标准类库: +using System.Data.Entity; +// 为了在下方使用它,你需要添加一个 dll 引用 +// 你可以使用 NuGet 包管理器进行安装 +// `Install-Package EntityFramework` + +// 命名空间 Namespaces 可用于将一定的代码组织为 “包” 或者 “模块” +// 你可以在其他文件中这样引用:using Learning.CSharp; + +// 在 C# 10 以后,你也可以这样定义命名空间。这被称为 file-scoped namespaces(文件范围的命名空间). +// namespace Learning.CSharp; + namespace Learning { // 每个 .cs 文件至少需要包含一个和文件名相同的类 - // 你可以不这么干,但是这样不好。 + // 你可以不这么干,但是这样并不推荐。 public class LearnCSharp { - // 基本语法 - 如果你以前用过 Java 或 C++ 的话,可以直接跳到后文「有趣的特性」 + // 基本语法 - 如果你以前用过 Java 或 C++ 的话,可以直接跳到后文「有趣的特性」 public static void Syntax() { // 使用 Console.WriteLine 打印信息 @@ -53,7 +72,7 @@ namespace Learning " Double: " + 3.14 + " Boolean: " + true); - // 使用 Console.Write 打印,不带换行符号 + // 使用 Console.Write 打印将不会换行 Console.Write("Hello "); Console.Write("World"); @@ -113,7 +132,7 @@ namespace Learning char charFromString = fooString[1]; // => 'e' // 字符串不可修改: fooString[1] = 'X' 是行不通的; - // 根据当前的locale设定比较字符串,大小写不敏感 + // 根据当前的区域格式设置比较字符串,大小写不敏感 string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase); // 基于sprintf的字符串格式化 @@ -123,12 +142,13 @@ namespace Learning DateTime fooDate = DateTime.Now; Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); - // 使用 @ 符号可以创建跨行的字符串。使用 "" 来表示 " + // 逐字字符串 + // 使用 @ 符号可以创建跨行的字符串。使用 "" 来表示 " string bazString = @"Here's some stuff on a new line! ""Wow!"", the masses cried"; - // 使用const或read-only定义常量 - // 常量在编译期演算 + // 使用 const 或 read-only 定义常量 + // 常量在编译阶段演算 const int HOURS_I_WORK_PER_WEEK = 9001; /////////////////////////////////////////////////// @@ -136,7 +156,7 @@ on a new line! ""Wow!"", the masses cried"; /////////////////////////////////////////////////// // 数组 - 从0开始计数 - // 声明数组时需要确定数组长度 + // 声明数组时需要指定数组长度 // 声明数组的格式如下: // <datatype>[] <var name> = new <datatype>[<array size>]; int[] intArray = new int[10]; @@ -155,8 +175,8 @@ on a new line! ""Wow!"", the masses cried"; // List<datatype> <var name> = new List<datatype>(); List<int> intList = new List<int>(); List<string> stringList = new List<string>(); - List<int> z = new List<int> { 9000, 1000, 1337 }; // i - // <>用于泛型 - 参考下文 + List<int> z = new List<int> { 9000, 1000, 1337 }; // 初始化 + // <> 用于泛型 - 参考下文 // 列表无默认值 // 访问列表元素时必须首先添加元素 @@ -164,18 +184,18 @@ on a new line! ""Wow!"", the masses cried"; Console.WriteLine("intList @ 0: " + intList[0]); // 其他数据结构: - // 堆栈/队列 - // 字典 (哈希表的实现) - // 哈希集合 - // 只读集合 - // 元组 (.Net 4+) + // Stack 堆栈 / Queue 队列 + // Dictionary 字典 (哈希表的实现) + // HashSet 哈希集合 + // Read-only Collections 只读集合 + // Tuple 元组 (.Net 4+) /////////////////////////////////////// // 操作符 /////////////////////////////////////// Console.WriteLine("\n->Operators"); - int i1 = 1, i2 = 2; // 多重声明的简写形式 + int i1 = 1, i2 = 2; // 声明多个变量的简写形式 // 算术直截了当 Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3 @@ -214,7 +234,7 @@ on a new line! ""Wow!"", the masses cried"; /////////////////////////////////////// Console.WriteLine("\n->Control Structures"); - // 类似C的if语句 + // 类似 C 的 if 语句 int j = 10; if (j == 10) { @@ -239,7 +259,7 @@ on a new line! ""Wow!"", the masses cried"; int fooWhile = 0; while (fooWhile < 100) { - //迭代 100 次, fooWhile 0->99 + // 迭代 100 次, fooWhile 0->99 fooWhile++; } @@ -247,14 +267,21 @@ on a new line! ""Wow!"", the masses cried"; int fooDoWhile = 0; do { - //迭代 100 次, fooDoWhile 0->99 + // 迭代 100 次, fooDoWhile 0->99 + if (false) + continue; // 跳过本次迭代 + fooDoWhile++; + + if (fooDoWhile == 50) + break; // 结束整个循环 + } while (fooDoWhile < 100); - //for 循环结构 => for(<初始条件>; <条件>; <步>) + // for 循环结构 => for(<初始条件>; <条件>; <步>) for (int fooFor = 0; fooFor < 10; fooFor++) { - //迭代10次, fooFor 0->9 + // 迭代10次, fooFor 0->9 } // foreach循环 @@ -269,7 +296,7 @@ on a new line! ""Wow!"", the masses cried"; } // Switch 语句 - // switch 适用于 byte、short、char和int 数据类型。 + // switch 适用于 byte、short、char 和 int 数据类型。 // 同样适用于可枚举的类型 // 包括字符串类, 以及一些封装了原始值的类: // Character、Byte、Short和Integer。 @@ -307,46 +334,63 @@ on a new line! ""Wow!"", the masses cried"; // 转换字符串为整数 // 转换失败会抛出异常 - int.Parse("123");//返回整数类型的"123" + int.Parse("123"); // 返回整数类型的"123" - // TryParse会尝试转换类型,失败时会返回缺省类型 + // TryParse 会尝试转换类型,失败时会返回缺省类型 // 例如 0 int tryInt; if (int.TryParse("123", out tryInt)) // Funciton is boolean Console.WriteLine(tryInt); // 123 // 转换整数为字符串 - // Convert类提供了一系列便利转换的方法 + // Convert 类提供了一系列方便转换类型的方法 + + // 比如 字符串 与 int 之间 + + // 最佳方法 + bool result = int.TryParse(string, out var integer) + int.Parse(string); + + // 不推荐 Convert.ToString(123); - // or + + // Int 到字符串 tryInt.ToString(); + + // 转换 + // 显式转换 decimal 类型的 15 为 int 类型 + // 然后隐式转换为 long 类型 + long x = (int) 15M; } /////////////////////////////////////// - // 类 + // 类 - 请参阅文件末尾的定义 /////////////////////////////////////// public static void Classes() { // 参看文件尾部的对象声明 - // 使用new初始化对象 + // 使用 new 初始化对象 Bicycle trek = new Bicycle(); // 调用对象的方法 - trek.SpeedUp(3); // 你应该一直使用setter和getter方法 + trek.SpeedUp(3); // 你应该一直使用 setter 和 getter 方法 trek.Cadence = 100; // 查看对象的信息. Console.WriteLine("trek info: " + trek.Info()); - // 实例化一个新的Penny Farthing + // 实例化一个新的 Penny Farthing 对象 PennyFarthing funbike = new PennyFarthing(1, 10); Console.WriteLine("funbike info: " + funbike.Info()); Console.Read(); } // 结束main方法 - // 终端程序 终端程序必须有一个main方法作为入口 + // record 在 C# 9 及以后可用, 这基本上是类的语法糖. record 对象是不可变的 immutable*. + public record ARecord(string Csharp); + + // 终端程序入口 终端程序必须有一个 main 方法作为入口 public static void Main(string[] args) { OtherInterestingFeatures(); @@ -359,11 +403,11 @@ on a new line! ""Wow!"", the masses cried"; // 默认方法签名 public // 可见性 - static // 允许直接调用类,无需先创建实例 - int, //返回值 + static // 允许从类直接调用,无需先创建实例 + int // 返回值类型 MethodSignatures( - int maxCount, // 第一个变量,类型为整型 - int count = 0, // 如果没有传入值,则缺省值为0 + int maxCount, // 第一个参数,类型为整型 + int count = 0, // 如果没有传入值,则缺省值为 0 int another = 3, params string[] otherParams // 捕获其他参数 ) @@ -371,17 +415,22 @@ on a new line! ""Wow!"", the masses cried"; return -1; } - // 方法可以重名,只要签名不一样 - public static void MethodSignature(string maxCount) + // 方法可以重名,只要方法签名不一样 + // 一个只有返回值类型不同的方法 + public static void MethodSignatures( + ref int maxCount, // 通过引用传递 + out int count) { + // 通过 'count' 参数传入的值将在该方法外保留值 15 + count = 15; // 必须在离开方法之前为 out 参数赋值 } - //泛型 - // TKey和TValue类由用用户调用函数时指定。 - // 以下函数模拟了Python的SetDefault + // 泛型 + // TKey 和 TValue 由用户调用方法时指定 + // 以下函数模拟了 Python 的 SetDefault public static TValue SetDefault<TKey, TValue>( - IDictionary<TKey, TValue> dictionary, - TKey key, + IDictionary<TKey, TValue> dictionary, + TKey key, TValue defaultItem) { TValue result; @@ -393,55 +442,125 @@ on a new line! ""Wow!"", the masses cried"; // 你可以限定传入值的范围 public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int> { - // 我们可以进行迭代,因为T是可枚举的 + // 我们可以进行迭代,因为 T 是可枚举的 foreach (var item in toPrint) - // ittm为整数 + // item 为整数 Console.WriteLine(item.ToString()); } + // YIELD + // 使用 "yield" 关键字表明它出现的方法是一个迭代器 Iterator + // (这意味着你可以在 foreach 循环中使用它) + public static IEnumerable<int> YieldCounter(int limit = 10) + { + for (var i = 0; i < limit; i++) + yield return i; + } + + // 你可以这样调用它 + public static void PrintYieldCounterToConsole() + { + foreach (var counter in YieldCounter()) + Console.WriteLine(counter); + } + + // 你可以在一个方法中使用多个 "yield return" + public static IEnumerable<int> ManyYieldCounter() + { + yield return 0; + yield return 1; + yield return 2; + yield return 3; + } + + // 你也可以使用 "yield break" 停止该迭代器 + // 此方法只会返回从 0 到 limit 的一半值。 + public static IEnumerable<int> YieldCounterWithBreak(int limit = 10) + { + for (var i = 0; i < limit; i++) + { + if (i > limit / 2) yield break; + yield return i; + } + } + public static void OtherInterestingFeatures() { - // 可选参数 + // 可选参数 MethodSignatures(3, 1, 3, "Some", "Extra", "Strings"); MethodSignatures(3, another: 3); // 显式指定参数,忽略可选参数 + // 使用 ref 和 out 参数 + int maxCount = 0, count; // ref 参数必须有值 + MethodSignatures(ref maxCount, out count); + // 扩展方法 int i = 3; - i.Print(); // 参见下面的定义 + i.Print(); // 参见下面的定义 - // 可为null的类型 对数据库交互、返回值很有用 + // 可为 null 的类型 对数据库交互、返回值很有用 // 任何值类型 (i.e. 不为类) 添加后缀 ? 后会变为可为null的值 // <类型>? <变量名> = <值> int? nullable = null; // Nullable<int> 的简写形式 Console.WriteLine("Nullable variable: " + nullable); bool hasValue = nullable.HasValue; // 不为null时返回真 + // ?? 是用于指定默认值的语法糖 // 以防变量为null的情况 int notNullable = nullable ?? 0; // 0 + // ?. 是另一个可空类型的操作符 - 简写 null 检查 + nullable?.Print(); // 当可空类型值不为 null 的时候调用 Print() 拓展方法 + // 变量类型推断 - 你可以让编译器推断变量类型: var magic = "编译器确定magic是一个字符串,所以仍然是类型安全的"; - // magic = 9; // 不工作,因为magic是字符串,而不是整数。 + // magic = 9; // 不工作,因为magic是字符串,而不是整数。 // 泛型 // - var phonebook = new Dictionary<string, string>() { + var phonebook = new Dictionary<string, string>() { {"Sarah", "212 555 5555"} // 在电话簿中加入新条目 }; - // 调用上面定义为泛型的SETDEFAULT - Console.WriteLine(SetDefault<string,string>(phonebook, "Shaun", "No Phone")); // 没有电话 - // 你不用指定TKey、TValue,因为它们会被隐式地推导出来 + // 调用上面定义为泛型的 SETDEFAULT + Console.WriteLine(SetDefault<string, string>(phonebook, "Shaun", "No Phone")); // No Phone + // 你不用指定 TKey、TValue 的类型 + // 因为它们会被隐式地推导出来 Console.WriteLine(SetDefault(phonebook, "Sarah", "No Phone")); // 212 555 5555 // lambda表达式 - 允许你用一行代码搞定函数 Func<int, int> square = (x) => x * x; // 最后一项为返回值 Console.WriteLine(square(3)); // 9 - // 可抛弃的资源管理 - 让你很容易地处理未管理的资源 - // 大多数访问未管理资源 (文件操作符、设备上下文, etc.)的对象 - // 都实现了IDisposable接口。 - // using语句会为你清理IDisposable对象。 + // 错误处理 - 应对不确定的世界 + try + { + var funBike = PennyFarthing.CreateWithGears(6); + + // 将不再执行,因为 CreateWithGears 抛出异常 + string some = ""; + if (true) some = null; + some.ToLower(); // 抛出 NullReferenceException + } + catch (NotSupportedException) + { + Console.WriteLine("Not so much fun now!"); + } + catch (Exception ex) // 捕获所有其他异常 + { + throw new ApplicationException("It hit the fan", ex); + // throw; // 重新抛出异常并保留调用堆栈 + } + // catch { } // 捕获所有没有捕获的异常 + finally + { + // 在 try 或 catch 之后执行 + } + + // 可抛弃的资源管理 - 让你很容易地处理未托管的资源 + // 大多数访问未托管资源 (文件句柄、设备上下文, etc.) 的对象 + // 都实现了 IDisposable 接口。 + // using语句会为你清理 IDisposable 对象 using (StreamWriter writer = new StreamWriter("log.txt")) { writer.WriteLine("这里没有什么可疑的东西"); @@ -450,29 +569,23 @@ on a new line! ""Wow!"", the masses cried"; } // 并行框架 - // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx - var websites = new string[] { - "http://www.google.com", "http://www.reddit.com", - "http://www.shaunmccarthy.com" - }; - var responses = new Dictionary<string, string>(); - - // 为每个请求新开一个线程 - // 在运行下一步前合并结果 - Parallel.ForEach(websites, - new ParallelOptions() {MaxDegreeOfParallelism = 3}, // max of 3 threads - website => - { - // Do something that takes a long time on the file - using (var r = WebRequest.Create(new Uri(website)).GetResponse()) + // https://learn.microsoft.com/zh-cn/dotnet/standard/parallel-programming/data-parallelism-task-parallel-library + + var words = new List<string> {"dog", "cat", "horse", "pony"}; + + Parallel.ForEach(words, + new ParallelOptions() { MaxDegreeOfParallelism = 4 }, + word => { - responses[website] = r.ContentType; + Console.WriteLine(word); } - }); + ); - // 直到所有的请求完成后才会运行下面的代码 - foreach (var key in responses.Keys) - Console.WriteLine("{0}:{1}", key, responses[key]); + // 运行它会产生不同的输出 + // 因为每个线程在不同的时间完成 + // 一些可能的输出是: + // cat dog horse pony + // dog horse pony cat // 动态对象(配合其他语言使用很方便) dynamic student = new ExpandoObject(); @@ -486,10 +599,10 @@ on a new line! ""Wow!"", the masses cried"; // IQUERYABLE<T> - 几乎所有的集合都实现了它, // 带给你 Map / Filter / Reduce 风格的方法 var bikes = new List<Bicycle>(); - bikes.Sort(); // Sorts the array + bikes.Sort(); // 排序 array bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // 根据车轮数排序 var result = bikes - .Where(b => b.Wheels > 3) // 筛选 - 可以连锁使用 (返回IQueryable) + .Where(b => b.Wheels > 3) // 筛选 - 可以连锁使用 (返回 IQueryable) .Where(b => b.IsBroken && b.HasTassles) .Select(b => b.ToString()); // Map - 这里我们使用了select,所以结果是IQueryable<string> @@ -502,19 +615,19 @@ on a new line! ""Wow!"", the masses cried"; Console.WriteLine(bikeSummary.Name); // ASPARALLEL - // 邪恶的特性 —— 组合了linq和并行操作 + // 这就是事情开始棘手的地方 —— 组合了 linq 和并行操作 var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name); // 以上代码会并发地运行。会自动新开线程,分别计算结果。 // 适用于多核、大数据量的场景。 - // LINQ - 将IQueryable<T>映射到存储,延缓执行 + // LINQ - 映射一组 IQueryable<T> 对象,并延迟执行 // 例如 LinqToSql 映射数据库, LinqToXml 映射XML文档 var db = new BikeRespository(); - // 执行被延迟了,这对于查询数据库来说很好 + // 执行被延迟了,这对于查询数据库来说非常好 var filter = db.Bikes.Where(b => b.HasTassles); // 不运行查询 if (42 > 6) // 你可以不断地增加筛选,包括有条件的筛选,例如用于“高级搜索”功能 - filter = filter.Where(b => b.IsBroken); // 不运行查询 + filter = filter.Where(b => b.IsBroken); // 不运行查询 var query = filter .OrderBy(b => b.Wheels) @@ -541,15 +654,64 @@ on a new line! ""Wow!"", the masses cried"; Console.WriteLine(obj.ToString()); } } + + + // 委托 和 事件 + public class DelegateTest + { + public static int count = 0; + public static int Increment() + { + // 增加 count 然后返回它 + return ++count; + } + + // 委托是一个方法的引用. + // 要引用 Increment 方法, + // 首先声明一个具有相同签名的委托, + // i.e. 不带参数并返回 int + public delegate int IncrementDelegate(); + + // 事件也可用于触发委托 + // 使用委托类型创建事件 + public static event IncrementDelegate MyEvent; + + static void Main(string[] args) + { + // 通过实例化委托来引用 Increment 方法 + // 并将方法本身作为参数传递 + IncrementDelegate inc = new IncrementDelegate(Increment); + Console.WriteLine(inc()); // => 1 + + // 委托可以用 + 运算符组合 + IncrementDelegate composedInc = inc; + composedInc += inc; + composedInc += inc; + + // composedInc 将执行 Increment 3 次 + Console.WriteLine(composedInc()); // => 4 + + + // 为事件订阅与委托 + MyEvent += new IncrementDelegate(Increment); + MyEvent += new IncrementDelegate(Increment); + + // 触发事件 + // ie. 运行这个事件所有的委托订阅 + Console.WriteLine(MyEvent()); // => 6 + } + } + + // 声明类的语法: // <public/private/protected/internal> class <类名>{ - // //数据字段, 构造器, 内部函数. - / // 在Java中函数被称为方法。 + // // 数据字段, 构造器, 内部函数 + // // 在Java中函数被称为方法 // } public class Bicycle { - // 自行车的字段、变量 + // 自行车的字段/变量 public int Cadence // Public: 任何地方都可以访问 { get // get - 定义获取属性的方法 @@ -558,30 +720,35 @@ on a new line! ""Wow!"", the masses cried"; } set // set - 定义设置属性的方法 { - _cadence = value; // value是被传递给setter的值 + _cadence = value; // value 是被传递给 setter 的值 } } private int _cadence; - protected virtual int Gear // 类和子类可以访问 + protected virtual int Gear // Protected: 类和子类可以访问 { get; // 创建一个自动属性,无需成员字段 set; } - internal int Wheels // Internal:在同一程序集内可以访问 + internal int Wheels // Internal: 在同一程序集内可以访问 { get; - private set; // 可以给get/set方法添加修饰符 + private set; // 可以给 get/set 方法添加修饰符 } - int _speed; // 默认为private: 只可以在这个类内访问,你也可以使用`private`关键词 + int _speed; // 类中的任何内容默认为 private: 只可以在这个类内访问 + // 你也可以使用 `private` 关键词显式指定 public string Name { get; set; } - // enum类型包含一组常量 + // 当您想要一个仅返回表达式结果的只读属性时, + // 属性还具有特殊的语法 + public string LongName => Name + " " + _speed + " speed"; + + // enum 枚举是一种值类型,由一组命名常量组成 // 它将名称映射到值(除非特别说明,是一个整型) - // enmu元素的类型可以是byte、sbyte、short、ushort、int、uint、long、ulong。 - // enum不能包含相同的值。 + // enmu 元素的类型可以是 byte、sbyte、short、ushort、int、uint、long、ulong + // enum 不能包含相同的值 public enum BikeBrand { AIST, @@ -589,13 +756,32 @@ on a new line! ""Wow!"", the masses cried"; Electra = 42, //你可以显式地赋值 Gitane // 43 } - // 我们在Bicycle类中定义的这个类型,所以它是一个内嵌类型。 - // 这个类以外的代码应当使用`Bicycle.Brand`来引用。 + // 我们在 Bicycle 类中定义的这个类型,所以它是一个内嵌类型 + // 这个类以外的代码应当使用 `Bicycle.Brand` 来引用 + + public BikeBrand Brand; // 声明一个 enum 类型之后,我们可以声明这个类型的字段 + + // 使用 FlagsAttribute 定义枚举,表示有多个值可以被匹配 + // 任何从 Attribute 派生的类都可以用来修饰类型、方法、参数等 + // 位运算符 & 和 | 可用于 和/或 操作 + + [Flags] + public enum BikeAccessories + { + None = 0, + Bell = 1, + MudGuards = 2, // 需要手动设定值! + Racks = 4, + Lights = 8, + FullPackage = Bell | MudGuards | Racks | Lights + } - public BikeBrand Brand; // 声明一个enum类型之后,我们可以声明这个类型的字段 + // 用法: aBike.Accessories.HasFlag(Bicycle.BikeAccessories.Bell) + // 在 .NET 4 之前: (aBike.Accessories & Bicycle.BikeAccessories.Bell) == Bicycle.BikeAccessories.Bell + public BikeAccessories Accessories { get; set; } - // 静态方法的类型为自身,不属于特定的对象。 - // 你无需引用对象就可以访问他们。 + // 静态方法属于类型自身,不属于特定的对象 + // 你无需通过对象就可以访问他们 // Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated); static public int BicyclesCreated = 0; @@ -607,7 +793,7 @@ on a new line! ""Wow!"", the masses cried"; // 下面是一个默认的构造器 public Bicycle() { - this.Gear = 1; // 你可以使用关键词this访问对象的成员 + this.Gear = 1; // 你可以使用关键词 this 访问对象的成员 Cadence = 50; // 不过你并不总是需要它 _speed = 5; Name = "Bontrager"; @@ -618,7 +804,7 @@ on a new line! ""Wow!"", the masses cried"; // 另一个构造器的例子(包含参数) public Bicycle(int startCadence, int startSpeed, int startGear, string name, bool hasCardsInSpokes, BikeBrand brand) - : base() // 首先调用base + : base() // 显式调用基类的无参构造方法 { Gear = startGear; Cadence = startCadence; @@ -637,8 +823,9 @@ on a new line! ""Wow!"", the masses cried"; // 函数语法 // <public/private/protected> <返回值> <函数名称>(<参数>) - // 类可以为字段实现 getters 和 setters 方法 for their fields - // 或者可以实现属性(C#推荐使用这个) + // 类可以为其字段实现 getters 和 setters 方法 + // 或者可以使用属性封装字段(C#推荐使用这个) + // 方法的参数可以有默认值 // 在有默认值的情况下,调用方法的时候可以省略相应的参数 public void SpeedUp(int increment = 1) @@ -652,8 +839,8 @@ on a new line! ""Wow!"", the masses cried"; } // 属性可以访问和设置值 - // 当只需要访问数据的时候,考虑使用属性。 - // 属性可以定义get和set,或者是同时定义两者 + // 当只需要外部访问数据的时候,考虑使用属性。 + // 属性可以定义 get 和 set,或者是同时定义两者 private bool _hasTassles; // private variable public bool HasTassles // public accessor { @@ -663,7 +850,7 @@ on a new line! ""Wow!"", the masses cried"; // 你可以在一行之内定义自动属性 // 这个语法会自动创建后备字段 - // 你可以给getter或setter设置访问修饰符 + // 你可以给 getter 或 setter 设置访问修饰符 // 以便限制它们的访问 public bool IsBroken { get; private set; } @@ -671,12 +858,29 @@ on a new line! ""Wow!"", the masses cried"; public int FrameSize { get; - // 你可以给get或set指定访问修饰符 - // 以下代码意味着只有Bicycle类可以调用Framesize的set + // 你可以给 get 或 set 指定访问修饰符 + // 以下代码意味着只有 Bicycle 类可以调用 Framesize 的 set private set; } - //显示对象属性的方法 + // 还可以在对象上定义自定义索引器 + // 尽管这在本例中并不完全有用, you + // 你可以使用 bicycle[0] 返回 "chris" 来获得第一项 + // 或者 bicycle[1] = "lisa" 来设定值 + private string[] passengers = { "chris", "phil", "darren", "regina" }; + + public string this[int i] + { + get { + return passengers[i]; + } + + set { + passengers[i] = value; + } + } + + // 显示对象属性的方法 public virtual string Info() { return "Gear: " + Gear + @@ -698,7 +902,7 @@ on a new line! ""Wow!"", the masses cried"; } // Bicycle类结束 - // PennyFarthing是Bicycle的一个子类 + // PennyFarthing 是 Bicycle 的一个子类 class PennyFarthing : Bicycle { // (Penny Farthings是一种前轮很大的自行车。没有齿轮。) @@ -717,10 +921,17 @@ on a new line! ""Wow!"", the masses cried"; } set { - throw new ArgumentException("你不可能在PennyFarthing上切换齿轮"); + throw new ArgumentException("你不可能在 PennyFarthing 上切换齿轮"); } } + public static PennyFarthing CreateWithGears(int gears) + { + var penny = new PennyFarthing(1, 1); + penny.Gear = gears; // 你不能这样做! + return penny; + } + public override string Info() { string result = "PennyFarthing bicycle "; @@ -732,7 +943,7 @@ on a new line! ""Wow!"", the masses cried"; // 接口只包含成员的签名,而没有实现。 interface IJumpable { - void Jump(int meters); // 所有接口成员是隐式地公开的 + void Jump(int meters); // 所有接口成员是隐式地公开的 public } interface IBreakable @@ -741,6 +952,8 @@ on a new line! ""Wow!"", the masses cried"; } // 类只能继承一个类,但是可以实现任意数量的接口 + // 但是基类名称必须是列表中的第一个,所有接口都在后面 + class MountainBike : Bicycle, IJumpable, IBreakable { int damage = 0; @@ -759,41 +972,374 @@ on a new line! ""Wow!"", the masses cried"; } /// <summary> - /// 连接数据库,一个 LinqToSql的示例。 + /// 连接数据库,一个 LinqToSql 的示例。 /// EntityFramework Code First 很棒 (类似 Ruby的 ActiveRecord, 不过是双向的) - /// http://msdn.microsoft.com/en-us/data/jj193542.aspx + /// https://learn.microsoft.com/zh-cn/ef/ef6/modeling/code-first/workflows/new-database /// </summary> - public class BikeRespository : DbSet + public class BikeRepository : DbContext { - public BikeRespository() + public BikeRepository() : base() { } public DbSet<Bicycle> Bikes { get; set; } } + + // 一个类可以通过 partial 关键字分别写在多个 .cs 文件中 + // A1.cs + public partial class A + { + public static void A1() + { + Console.WriteLine("Method A1 in class A"); + } + } + + // A2.cs + public partial class A + { + public static void A2() + { + Console.WriteLine("Method A2 in class A"); + } + } + + // 使用 partial 类 "A" + public class Program + { + static void Main() + { + A.A1(); + A.A2(); + } + } + + // 通过在字符串前加上 $ 前缀来进行字符串插值 + // 并用 { 大括号 } 包裹要插值的表达式 + // 您还可以将插值字符串和逐字字符串与 $@ 组合起来 + public class Rectangle + { + public int Length { get; set; } + public int Width { get; set; } + } + + class Program + { + static void Main(string[] args) + { + Rectangle rect = new Rectangle { Length = 5, Width = 3 }; + Console.WriteLine($"The length is {rect.Length} and the width is {rect.Width}"); + + string username = "User"; + Console.WriteLine($@"C:\Users\{username}\Desktop"); + } + } + + // C# 6 新特性 + class GlassBall : IJumpable, IBreakable + { + // 自动属性设置初始值 + public int Damage { get; private set; } = 0; + + // 为仅有 getter 的自动属性设定初始值 + public string Name { get; } = "Glass ball"; + + // 在构造函数中初始化的仅有 getter 的自动属性 + public string GenieName { get; } + + public GlassBall(string genieName = null) + { + GenieName = genieName; + } + + public void Jump(int meters) + { + if (meters < 0) + // 新的 nameof() 表达式; 编译器将检查标识符是否存在 + // nameof(x) == "x" + // 预防 例如 参数名称已更改但错误消息中未更新 + throw new ArgumentException("Cannot jump negative amount!", nameof(meters)); + + Damage += meters; + } + + // 表达式主体 expression-bodied 属性 ... + public bool Broken + => Damage > 100; + + // ... 刚发 + public override string ToString() + // 插值字符串 + => $"{Name}. Damage taken: {Damage}"; + + public string SummonGenie() + // Null 条件运算符 + // x?.y 如果 x 为 null 将立即返回 null; y 将不会求值 + => GenieName?.ToUpper(); + } + + static class MagicService + { + private static bool LogException(Exception ex) + { + // 记录某处的异常 + return false; + } + + public static bool CastSpell(string spell) + { + try + { + // 假设我们在这里调用 API + throw new MagicServiceException("Spell failed", 42); + + // Spell succeeded + return true; + } + // 仅当 Code 为 42(Spell failed)时才捕获 + catch(MagicServiceException ex) when (ex.Code == 42) + { + // Spell failed + return false; + } + // 其他异常,或 MagicServiceException 的 Code 不是 42 + catch(Exception ex) when (LogException(ex)) + { + // 永远不会执行到这块代码 + // 堆栈未展开 + } + return false; + // 请注意,捕获 MagicServiceException + // 并在 Code 不是 42 或 117 时重新抛出是不同的 + // 因为最终的 catch-all 块将不会捕获重新抛出的异常 + } + } + + public class MagicServiceException : Exception + { + public int Code { get; } + + public MagicServiceException(string message, int code) : base(message) + { + Code = code; + } + } + + public static class PragmaWarning { + // 过时的属性 + [Obsolete("Use NewMethod instead", false)] + public static void ObsoleteMethod() + { + // obsolete code + } + + public static void NewMethod() + { + // new code + } + + public static void Main() + { + ObsoleteMethod(); // CS0618: 'ObsoleteMethod 已过时:使用 NewMethod 代替' +#pragma warning disable CS0618 + ObsoleteMethod(); // no warning +#pragma warning restore CS0618 + ObsoleteMethod(); // CS0618: 'ObsoleteMethod 已过时:使用 NewMethod 代替' + } + } } // 结束 Namespace + +using System; +// C# 6, 静态引用 +using static System.Math; + +namespace Learning.More.CSharp +{ + class StaticUsing + { + static void Main() + { + // 不使用静态引用时.. + Console.WriteLine("The square root of 4 is {}.", Math.Sqrt(4)); + // 使用时 + Console.WriteLine("The square root of 4 is {}.", Sqrt(4)); + } + } +} + +// C# 7 新特性 +// 使用 Nuget 安装 Microsoft.Net.Compilers 最新版 +// 使用 Nuget 安装 System.ValueTuple 最新版 +using System; +namespace Csharp7 +{ + // 元组 TUPLES, 析构 DECONSTRUCTION 和 弃元 DISCARDS + class TuplesTest + { + public (string, string) GetName() + { + // 元组中的字段默认命名为 Item1、Item2... + var names1 = ("Peter", "Parker"); + Console.WriteLine(names1.Item2); // => Parker + + // 字段可以显式命名 + // 第 1 种声明 + (string FirstName, string LastName) names2 = ("Peter", "Parker"); + + // 第 2 种声明 + var names3 = (First:"Peter", Last:"Parker"); + + Console.WriteLine(names2.FirstName); // => Peter + Console.WriteLine(names3.Last); // => Parker + + return names3; + } + + public string GetLastName() { + var fullName = GetName(); + + // 元组可以被析构 + (string firstName, string lastName) = fullName; + + // 析构获得的字段可以使用 弃元 _ 丢弃 + var (_, last) = fullName; + return last; + } + + // 通过指定析构方法, + // 可以以相同的方式解构任何类型 + public int randomNumber = 4; + public int anotherRandomNumber = 10; + + public void Deconstruct(out int randomNumber, out int anotherRandomNumber) + { + randomNumber = this.randomNumber; + anotherRandomNumber = this.anotherRandomNumber; + } + + static void Main(string[] args) + { + var tt = new TuplesTest(); + (int num1, int num2) = tt; + Console.WriteLine($"num1: {num1}, num2: {num2}"); // => num1: 4, num2: 10 + + Console.WriteLine(tt.GetLastName()); + } + } + + // 模式匹配 + class PatternMatchingTest + { + public static (string, int)? CreateLogMessage(object data) + { + switch(data) + { + // 使用 when 进行附加过滤 + case System.Net.Http.HttpRequestException h when h.Message.Contains("404"): + return (h.Message, 404); + case System.Net.Http.HttpRequestException h when h.Message.Contains("400"): + return (h.Message, 400); + case Exception e: + return (e.Message, 500); + case string s: + return (s, s.Contains("Error") ? 500 : 200); + case null: + return null; + default: + return (data.ToString(), 500); + } + } + } + + // Reference 变量 / ref 局部变量 + // 允许返回对象的引用而不仅仅是其值 + class RefLocalsTest + { + // 返回值前标明 ref + public static ref string FindItem(string[] arr, string el) + { + for(int i=0; i<arr.Length; i++) + { + if(arr[i] == el) { + // 返回引用 + return ref arr[i]; + } + } + throw new Exception("Item not found"); + } + + public static void SomeMethod() + { + string[] arr = {"this", "is", "an", "array"}; + + // 要在所有地方使用 ref + ref string item = ref FindItem(arr, "array"); + item = "apple"; + Console.WriteLine(arr[3]); // => apple + } + } + + // 本地函数 LOCAL FUNCTIONS + class LocalFunctionTest + { + private static int _id = 0; + public int id; + public LocalFunctionTest() + { + id = generateId(); + + // 这个本地函数只能在此作用域中被访问 + int generateId() + { + return _id++; + } + } + + public static void AnotherMethod() + { + var lf1 = new LocalFunctionTest(); + var lf2 = new LocalFunctionTest(); + Console.WriteLine($"{lf1.id}, {lf2.id}"); // => 0, 1 + + int id = generateId(); + // error CS0103: 当前上下文中不存在名称“generateId” + } + } +} + ``` ## 没有涉及到的主题 +✨ 新的, 👍 旧的, 🎈 长期支持的, 🔥 跨平台的, 🎁 只支持Windows的 + + * 特性 Attributes + + * 异步编程 + + * Web 开发 + * ASP.NET Core ✨ + + * 桌面应用开发 Development + * Windows Presentation Foundation (WPF) 👍 🎈 🎁 + * Universal Windows Platform (UWP) ✨ 🎁 + * Uno Platform 🔥 ✨ + * WinForms 👍 🎈 🎁 + * Avalonia 🔥 ✨ + * WinUI ✨ 🎁 - * Flags - * Attributes - * 静态属性 - * Exceptions, Abstraction - * ASP.NET (Web Forms/MVC/WebMatrix) - * Winforms - * Windows Presentation Foundation (WPF) + * 跨平台开发 + * Xamarin.Forms 👍 + * MAUI ✨ ## 扩展阅读 + * [C# language reference](https://docs.microsoft.com/dotnet/csharp/language-reference/) + * [Learn .NET](https://dotnet.microsoft.com/learn) + * [C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions) * [DotNetPerls](http://www.dotnetperls.com) * [C# in Depth](http://manning.com/skeet2) - * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) - * [LINQ](http://shop.oreilly.com/product/9780596519254.do) - * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx) - * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) - * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials) - * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Programming C# 5.0](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ Pocket Reference](http://shop.oreilly.com/product/9780596519254.do) * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) - * [C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx) + * [freeCodeCamp - C# Tutorial for Beginners](https://www.youtube.com/watch?v=GhQdlIFylQ8) diff --git a/zh-cn/css-cn.html.markdown b/zh-cn/css-cn.html.markdown index dc6dcc4f..ec937dfb 100644 --- a/zh-cn/css-cn.html.markdown +++ b/zh-cn/css-cn.html.markdown @@ -132,7 +132,7 @@ div.some-parent.class-name {} font-family: Arial; font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */ font-family: "Courier New", Trebuchet, Arial; /* 如果第一个 - 字体没找到,浏览器会使用第二个字体,一次类推 */ + 字体没找到,浏览器会使用第二个字体,以此类推 */ } ``` diff --git a/zh-cn/docker-cn.html.markdown b/zh-cn/docker-cn.html.markdown new file mode 100644 index 00000000..ff793ae0 --- /dev/null +++ b/zh-cn/docker-cn.html.markdown @@ -0,0 +1,150 @@ +--- +category: tool +tool: docker +lang: zh-cn +filename: docker-cn.bat +contributors: + - ["Ruslan López", "http://javapro.org/"] +translators: + - ["imba-tjd", "https://github.com/imba-tjd/"] +--- + +```bat +:: 下载、安装、运行 hello-world 镜像(image) +docker run hello-world + +:: :: 如果这是第一次运行,你应该能见到这些信息 +:: Unable to find image 'hello-world:latest' locally # 在本地找不到镜像xxx +:: latest: Pulling from library/hello-world +:: 1b930d010525: Pull complete +:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064 +:: Status: Downloaded newer image for hello-world:latest +:: +:: Hello from Docker! # 来自Docker的欢迎 +:: This message shows that your installation appears to be working correctly. # 此信息表明你的安装似乎成功了 +:: +:: To generate this message, Docker took the following steps: # Docker进行了如下步骤来产生此信息 +:: 1. The Docker client contacted the Docker daemon. # Docker客户端联系Docker守护程序 +:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. # Docker守护程序从Docker Hub拉取镜像 +:: (amd64) +:: 3. The Docker daemon created a new container from that image which runs the # Docker守护程序从镜像中创建了一个容器 +:: executable that produces the output you are currently reading. # 运行了产生你正在读的输出的可执行文件 +:: 4. The Docker daemon streamed that output to the Docker client, which sent it # Docker守护程序把输出流式传输给Docker客户端,后者发送到你的终端上 +:: to your terminal. +:: +:: To try something more ambitious, you can run an Ubuntu container with: # 若要尝试更强大的东西,你可以用该命令运行Ubuntu容器 +:: $ docker run -it ubuntu bash +:: +:: Share images, automate workflows, and more with a free Docker ID: # 使用免费的Docker ID来分享镜像,自动化工作流等 +:: https://hub.docker.com/ +:: +:: For more examples and ideas, visit: # 欲获取更多例子和想法,访问 +:: https://docs.docker.com/get-started/ + +:: 现在来看看当前正运行的镜像 +docker ps +:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS +:: NAMES + +:: 看看之前运行过的镜像 +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 +:: 名字(name)是自动生成的,因此它会和你的不同 + +:: 移除(remove)我们之前生成的镜像 +docker rm happy_poincare + +:: 测试是否真的删除了 +docker ps -a +:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS +:: NAMES + +:: 为容器(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 +:: 如你所见,名字现在是我们指定的了 + +:: 从命名过的容器中获取日志(logs) +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 + +:: 在交互模式(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 +``` diff --git a/zh-cn/dynamic-programming-cn.html.markdown b/zh-cn/dynamic-programming-cn.html.markdown index b75c5404..7864c22a 100644 --- a/zh-cn/dynamic-programming-cn.html.markdown +++ b/zh-cn/dynamic-programming-cn.html.markdown @@ -15,7 +15,7 @@ translators: 动态规划是一种实用的技巧,它可以用来解决一系列特定问题。它的思路很简单,如果你对某个给定的输入解决了一个问题,那么你可以保存已有信息,以避免重复计算,节约计算时间。 -记住,只有那些没有办法记住历史的才被迫做更多的苦力。(Fibonacci就是一个显然的例子) +记住,如果忘记历史,就要被迫做更多的苦力。斐波那契数列就是一个显然的例子。 ## 解决问题的方式 diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown index 3f6ccbcf..a429fcbc 100644 --- a/zh-cn/elisp-cn.html.markdown +++ b/zh-cn/elisp-cn.html.markdown @@ -1,345 +1,345 @@ ----
-language: elisp
-contributors:
- - ["Bastien Guerry", "http://bzg.fr"]
-translators:
- - ["Chenbo Li", "http://binarythink.net"]
-filename: learn-emacs-lisp-zh.el
-lang: zh-cn
----
-
-```scheme
-;; 15分钟学会Emacs Lisp (v0.2a)
-;;(作者:bzg,https://github.com/bzg
-;; 译者:lichenbo,http://douban.com/people/lichenbo)
-;;
-;; 请先阅读Peter Norvig的一篇好文:
-;; http://norvig.com/21-days.html
-;; (译者注:中文版请见http://blog.youxu.info/21-days/)
-;;
-;; 之后安装GNU Emacs 24.3:
-;;
-;; Debian: apt-get install emacs (视具体发行版而定)
-;; MacOSX: 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
-;;
-;; 更多信息可以在这里找到:
-;; http://www.gnu.org/software/emacs/#Obtaining
-
-;; 很重要的警告:
-;;
-;; 按照这个教程来学习并不会对你的电脑有任何损坏
-;; 除非你自己在学习的过程中愤怒地把它砸了
-;; 如果出现了这种情况,我不会承担任何责任
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; 打开emacs
-;;
-;; 按'q'消除欢迎界面
-;;
-;; 现在请注意窗口底部的那一个灰色长条
-;;
-;; "*scratch*" 是你现在编辑界面的名字。
-;; 这个编辑界面叫做一个"buffer"。
-;;
-;; 每当你打开Emacs时,都会默认打开这个scratch buffer
-;; 此时你并没有在编辑任何文件,而是在编辑一个buffer
-;; 之后你可以将这个buffer保存到一个文件中。
-;;
-;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令
-;;
-;; Emacs在每个buffer中都有一组内置的命令
-;; 而当你激活某种特定的模式时,就可以使用相应的命令
-;; 这里我们使用`lisp-interaction-mode',
-;; 这样我们就可以使用内置的Emacs Lisp(以下简称Elisp)命令了。
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; 分号是注释开始的标志
-;;
-;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"):
-(+ 2 2)
-
-;; 这个s式的意思是 "对2进行加2操作".
-
-;; s式周围有括号,而且也可以嵌套:
-(+ 2 (+ 1 1))
-
-;; 一个s式可以包含原子符号或者其他s式
-;; 在上面的例子中,1和2是原子符号
-;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式.
-
-;; 在 `lisp-interaction-mode' 中你可以计算s式.
-;; 把光标移到闭括号后,之后按下ctrl+j(以后简写为'C-j')
-
-(+ 3 (+ 1 2))
-;; ^ 光标放到这里
-;; 按下`C-j' 就会输出 6
-
-;; `C-j' 会在buffer中插入当前运算的结果
-
-;; 而`C-xC-e' 则会在emacs最底部显示结果,也就是被称作"minibuffer"的区域
-;; 为了避免把我们的buffer填满无用的结果,我们以后会一直用`C-xC-e'
-
-;; `setq' 可以将一个值赋给一个变量
-(setq my-name "Bastien")
-;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示)
-
-;; `insert' 会在光标处插入字符串:
-(insert "Hello!")
-;; `C-xC-e' 输出 "Hello!"
-
-;; 在这里我们只传给了insert一个参数"Hello!", 但是
-;; 我们也可以传给它更多的参数,比如2个:
-
-(insert "Hello" " world!")
-;; `C-xC-e' 输出 "Hello world!"
-
-;; 你也可以用变量名来代替字符串
-(insert "Hello, I am " my-name)
-;; `C-xC-e' 输出 "Hello, I am Bastien"
-
-;; 你可以把s式嵌入函数中
-(defun hello () (insert "Hello, I am " my-name))
-;; `C-xC-e' 输出 hello
-
-;; 现在执行这个函数
-(hello)
-;; `C-xC-e' 输出 Hello, I am Bastien
-
-;; 函数中空括号的意思是我们不需要接受任何参数
-;; 但是我们不能一直总是用my-name这个变量
-;; 所以我们现在使我们的函数接受一个叫做"name"的参数
-
-(defun hello (name) (insert "Hello " name))
-;; `C-xC-e' 输出 hello
-
-;; 现在我们调用这个函数,并且将"you"作为参数传递
-
-(hello "you")
-;; `C-xC-e' 输出 "Hello you"
-
-;; 成功!
-
-;; 现在我们可以休息一下
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer:
-
-(switch-to-buffer-other-window "*test*")
-;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内
-
-;; 用鼠标单击上面的buffer就会使光标移回。
-;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中
-
-;; 你可以用 `progn'命令将s式结合起来:
-(progn
- (switch-to-buffer-other-window "*test*")
- (hello "you"))
-;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you"
-
-;; 现在为了简洁,我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了
-
-;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。
-
-;; 清除当前buffer也是常用操作之一:
-(progn
- (switch-to-buffer-other-window "*test*")
- (erase-buffer)
- (hello "there"))
-
-;; 也可以回到其他的窗口中
-(progn
- (switch-to-buffer-other-window "*test*")
- (erase-buffer)
- (hello "you")
- (other-window 1))
-
-;; 你可以用 `let' 将一个值和一个局部变量绑定:
-(let ((local-name "you"))
- (switch-to-buffer-other-window "*test*")
- (erase-buffer)
- (hello local-name)
- (other-window 1))
-
-;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。
-
-;; 格式化字符串的方法:
-(format "Hello %s!\n" "visitor")
-
-;; %s 是字符串占位符,这里被"visitor"替代.
-;; \n 是换行符。
-
-;; 现在我们用格式化的方法再重写一下我们的函数:
-(defun hello (name)
- (insert (format "Hello %s!\n" name)))
-
-(hello "you")
-
-;; 我们再用`let'新建另一个函数:
-(defun greeting (name)
- (let ((your-name "Bastien"))
- (insert (format "Hello %s!\n\nI am %s."
- name ; the argument of the function
- your-name ; the let-bound variable "Bastien"
- ))))
-
-;; 之后执行:
-(greeting "you")
-
-;; 有些函数可以和用户交互:
-(read-from-minibuffer "Enter your name: ")
-
-;; 这个函数会返回在执行时用户输入的信息
-
-;; 现在我们让`greeting'函数显示你的名字:
-(defun greeting (from-name)
- (let ((your-name (read-from-minibuffer "Enter your name: ")))
- (insert (format "Hello!\n\nI am %s and you are %s."
- from-name ; the argument of the function
- your-name ; the let-bound var, entered at prompt
- ))))
-
-(greeting "Bastien")
-
-;; 我们让结果在另一个窗口中显示:
-(defun greeting (from-name)
- (let ((your-name (read-from-minibuffer "Enter your name: ")))
- (switch-to-buffer-other-window "*test*")
- (erase-buffer)
- (insert (format "Hello %s!\n\nI am %s." your-name from-name))
- (other-window 1)))
-
-;; 测试一下:
-(greeting "Bastien")
-
-;; 第二节结束,休息一下吧。
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; 我们将一些名字存到列表中:
-(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
-
-;; 用 `car'来取得第一个名字:
-(car list-of-names)
-
-;; 用 `cdr'取得剩下的名字:
-(cdr list-of-names)
-
-;; 用 `push'把名字添加到列表的开头:
-(push "Stephanie" list-of-names)
-
-;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作.
-;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car')
-;; 但还有一些却是有的 (比如 `push').
-
-;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数:
-(mapcar 'hello list-of-names)
-
-;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行:
-(defun greeting ()
- (switch-to-buffer-other-window "*test*")
- (erase-buffer)
- (mapcar 'hello list-of-names)
- (other-window 1))
-
-(greeting)
-
-;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。
-;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello'
-
-;; 现在我们对显示的buffer中的内容进行一些更改:
-
-(defun replace-hello-by-bonjour ()
- (switch-to-buffer-other-window "*test*")
- (goto-char (point-min))
- (while (search-forward "Hello")
- (replace-match "Bonjour"))
- (other-window 1))
-
-;; (goto-char (point-min)) 将光标移到buffer的开始
-;; (search-forward "Hello") 查找字符串"Hello"
-;; (while x y) 当x返回某个值时执行y这个s式
-;; 当x返回`nil' (空), 退出循环
-
-(replace-hello-by-bonjour)
-
-;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour"
-
-;; 你也会得到以下错误提示: "Search failed: Hello".
-;;
-;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在
-;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示
-
-;; (search-forward "Hello" nil t) 可以达到这个要求:
-
-;; `nil' 参数的意思是 : 查找并不限于某个范围内
-;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示
-
-;; 在下面的函数中,我们用到了s式,并且不给出任何错误提示:
-
-(defun hello-to-bonjour ()
- (switch-to-buffer-other-window "*test*")
- (erase-buffer)
- ;; 为`list-of-names'中的每个名字调用hello
- (mapcar 'hello list-of-names)
- (goto-char (point-min))
- ;; 将"Hello" 替换为"Bonjour"
- (while (search-forward "Hello" nil t)
- (replace-match "Bonjour"))
- (other-window 1))
-
-(hello-to-bonjour)
-
-;; 给这些名字加粗:
-
-(defun boldify-names ()
- (switch-to-buffer-other-window "*test*")
- (goto-char (point-min))
- (while (re-search-forward "Bonjour \\(.+\\)!" nil t)
- (add-text-properties (match-beginning 1)
- (match-end 1)
- (list 'face 'bold)))
- (other-window 1))
-
-;; 这个函数使用了 `re-search-forward':
-;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式
-
-;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是:
-;; 字符串 "Bonjour ", 之后跟着
-;; 一组 | \\( ... \\) 结构
-;; 任意字符 | . 的含义
-;; 有可能重复的 | + 的含义
-;; 之后跟着 "!" 这个字符串
-
-;; 准备好了?试试看。
-
-(boldify-names)
-
-;; `add-text-properties' 可以添加文字属性, 比如文字样式
-
-;; 好的,我们成功了!
-
-;; 如果你想对一个变量或者函数有更多的了解:
-;;
-;; C-h v 变量 回车
-;; C-h f 函数 回车
-;;
-;; 阅读Emacs Lisp官方文档:
-;;
-;; C-h i m elisp 回车
-;;
-;; 在线阅读Emacs Lisp文档:
-;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html
-
-;; 感谢以下同学的建议和反馈:
-;; - Wes Hardaker
-;; - notbob
-;; - Kevin Montuori
-;; - Arne Babenhauserheide
-;; - Alan Schmitt
-;; - spacegoing
-```
-
+--- +language: elisp +contributors: + - ["Bastien Guerry", "http://bzg.fr"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +filename: learn-emacs-lisp-zh.el +lang: zh-cn +--- + +```scheme +;; 15分钟学会Emacs Lisp (v0.2a) +;;(作者:bzg,https://github.com/bzg +;; 译者:lichenbo,http://douban.com/people/lichenbo) +;; +;; 请先阅读Peter Norvig的一篇好文: +;; http://norvig.com/21-days.html +;; (译者注:中文版请见http://blog.youxu.info/21-days/) +;; +;; 之后安装GNU Emacs 24.3: +;; +;; Debian: apt-get install emacs (视具体发行版而定) +;; MacOSX: 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 +;; +;; 更多信息可以在这里找到: +;; http://www.gnu.org/software/emacs/#Obtaining + +;; 很重要的警告: +;; +;; 按照这个教程来学习并不会对你的电脑有任何损坏 +;; 除非你自己在学习的过程中愤怒地把它砸了 +;; 如果出现了这种情况,我不会承担任何责任 +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; 打开emacs +;; +;; 按'q'消除欢迎界面 +;; +;; 现在请注意窗口底部的那一个灰色长条 +;; +;; "*scratch*" 是你现在编辑界面的名字。 +;; 这个编辑界面叫做一个"buffer"。 +;; +;; 每当你打开Emacs时,都会默认打开这个scratch buffer +;; 此时你并没有在编辑任何文件,而是在编辑一个buffer +;; 之后你可以将这个buffer保存到一个文件中。 +;; +;; 之后的"Lisp interaction" 则是表明我们可以用的某组命令 +;; +;; Emacs在每个buffer中都有一组内置的命令 +;; 而当你激活某种特定的模式时,就可以使用相应的命令 +;; 这里我们使用`lisp-interaction-mode', +;; 这样我们就可以使用内置的Emacs Lisp(以下简称Elisp)命令了。 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; 分号是注释开始的标志 +;; +;; Elisp 是由符号表达式构成的 (即"s-表达式"或"s式"): +(+ 2 2) + +;; 这个s式的意思是 "对2进行加2操作". + +;; s式周围有括号,而且也可以嵌套: +(+ 2 (+ 1 1)) + +;; 一个s式可以包含原子符号或者其他s式 +;; 在上面的例子中,1和2是原子符号 +;; (+ 2 (+ 1 1)) 和 (+ 1 1) 是s式. + +;; 在 `lisp-interaction-mode' 中你可以计算s式. +;; 把光标移到闭括号后,之后按下ctrl+j(以后简写为'C-j') + +(+ 3 (+ 1 2)) +;; ^ 光标放到这里 +;; 按下`C-j' 就会输出 6 + +;; `C-j' 会在buffer中插入当前运算的结果 + +;; 而`C-xC-e' 则会在emacs最底部显示结果,也就是被称作"minibuffer"的区域 +;; 为了避免把我们的buffer填满无用的结果,我们以后会一直用`C-xC-e' + +;; `setq' 可以将一个值赋给一个变量 +(setq my-name "Bastien") +;; `C-xC-e' 输出 "Bastien" (在 mini-buffer 中显示) + +;; `insert' 会在光标处插入字符串: +(insert "Hello!") +;; `C-xC-e' 输出 "Hello!" + +;; 在这里我们只传给了insert一个参数"Hello!", 但是 +;; 我们也可以传给它更多的参数,比如2个: + +(insert "Hello" " world!") +;; `C-xC-e' 输出 "Hello world!" + +;; 你也可以用变量名来代替字符串 +(insert "Hello, I am " my-name) +;; `C-xC-e' 输出 "Hello, I am Bastien" + +;; 你可以把s式嵌入函数中 +(defun hello () (insert "Hello, I am " my-name)) +;; `C-xC-e' 输出 hello + +;; 现在执行这个函数 +(hello) +;; `C-xC-e' 输出 Hello, I am Bastien + +;; 函数中空括号的意思是我们不需要接受任何参数 +;; 但是我们不能一直总是用my-name这个变量 +;; 所以我们现在使我们的函数接受一个叫做"name"的参数 + +(defun hello (name) (insert "Hello " name)) +;; `C-xC-e' 输出 hello + +;; 现在我们调用这个函数,并且将"you"作为参数传递 + +(hello "you") +;; `C-xC-e' 输出 "Hello you" + +;; 成功! + +;; 现在我们可以休息一下 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; 下面我们在新的窗口中新建一个名为 "*test*" 的buffer: + +(switch-to-buffer-other-window "*test*") +;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内 + +;; 用鼠标单击上面的buffer就会使光标移回。 +;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中 + +;; 你可以用 `progn'命令将s式结合起来: +(progn + (switch-to-buffer-other-window "*test*") + (hello "you")) +;; `C-xC-e' 此时屏幕分为两个窗口,并且在*test* buffer中显示"Hello you" + +;; 现在为了简洁,我们需要在每个s式后面都使用`C-xC-e'来执行,后面就不再说明了 + +;; 记得可以用过鼠标或者`C-xo'回到*scratch*这个buffer。 + +;; 清除当前buffer也是常用操作之一: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "there")) + +;; 也可以回到其他的窗口中 +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "you") + (other-window 1)) + +;; 你可以用 `let' 将一个值和一个局部变量绑定: +(let ((local-name "you")) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello local-name) + (other-window 1)) + +;; 这里我们就不需要使用 `progn' 了, 因为 `let' 也可以将很多s式组合起来。 + +;; 格式化字符串的方法: +(format "Hello %s!\n" "visitor") + +;; %s 是字符串占位符,这里被"visitor"替代. +;; \n 是换行符。 + +;; 现在我们用格式化的方法再重写一下我们的函数: +(defun hello (name) + (insert (format "Hello %s!\n" name))) + +(hello "you") + +;; 我们再用`let'新建另一个函数: +(defun greeting (name) + (let ((your-name "Bastien")) + (insert (format "Hello %s!\n\nI am %s." + name ; the argument of the function + your-name ; the let-bound variable "Bastien" + )))) + +;; 之后执行: +(greeting "you") + +;; 有些函数可以和用户交互: +(read-from-minibuffer "Enter your name: ") + +;; 这个函数会返回在执行时用户输入的信息 + +;; 现在我们让`greeting'函数显示你的名字: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (insert (format "Hello!\n\nI am %s and you are %s." + from-name ; the argument of the function + your-name ; the let-bound var, entered at prompt + )))) + +(greeting "Bastien") + +;; 我们让结果在另一个窗口中显示: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (insert (format "Hello %s!\n\nI am %s." your-name from-name)) + (other-window 1))) + +;; 测试一下: +(greeting "Bastien") + +;; 第二节结束,休息一下吧。 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; 我们将一些名字存到列表中: +(setq list-of-names '("Sarah" "Chloe" "Mathilde")) + +;; 用 `car'来取得第一个名字: +(car list-of-names) + +;; 用 `cdr'取得剩下的名字: +(cdr list-of-names) + +;; 用 `push'把名字添加到列表的开头: +(push "Stephanie" list-of-names) + +;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 却会对列表本身进行操作. +;; 这个区别是很重要的: 有些函数没有任何副作用(比如`car') +;; 但还有一些却是有的 (比如 `push'). + +;; 我们来对`list-of-names'列表中的每一个元素都使用hello函数: +(mapcar 'hello list-of-names) + +;; 将 `greeting' 改进,使的我们能够对`list-of-names'中的所有名字执行: +(defun greeting () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (mapcar 'hello list-of-names) + (other-window 1)) + +(greeting) + +;; 记得我们之前定义的 `hello' 函数吗? 这个函数接受一个参数,名字。 +;; `mapcar' 调用 `hello', 并将`list-of-names'作为参数先后传给`hello' + +;; 现在我们对显示的buffer中的内容进行一些更改: + +(defun replace-hello-by-bonjour () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (search-forward "Hello") + (replace-match "Bonjour")) + (other-window 1)) + +;; (goto-char (point-min)) 将光标移到buffer的开始 +;; (search-forward "Hello") 查找字符串"Hello" +;; (while x y) 当x返回某个值时执行y这个s式 +;; 当x返回`nil' (空), 退出循环 + +(replace-hello-by-bonjour) + +;; 你会看到所有在*test* buffer中出现的"Hello"字样都被换成了"Bonjour" + +;; 你也会得到以下错误提示: "Search failed: Hello". +;; +;; 如果要避免这个错误, 你需要告诉 `search-forward' 这个命令是否在 +;; buffer的某个地方停止查找, 并且在什么都没找到时是否应该不给出错误提示 + +;; (search-forward "Hello" nil t) 可以达到这个要求: + +;; `nil' 参数的意思是 : 查找并不限于某个范围内 +;; `t' 参数的意思是: 当什么都没找到时,不给出错误提示 + +;; 在下面的函数中,我们用到了s式,并且不给出任何错误提示: + +(defun hello-to-bonjour () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + ;; 为`list-of-names'中的每个名字调用hello + (mapcar 'hello list-of-names) + (goto-char (point-min)) + ;; 将"Hello" 替换为"Bonjour" + (while (search-forward "Hello" nil t) + (replace-match "Bonjour")) + (other-window 1)) + +(hello-to-bonjour) + +;; 给这些名字加粗: + +(defun boldify-names () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (re-search-forward "Bonjour \\(.+\\)!" nil t) + (add-text-properties (match-beginning 1) + (match-end 1) + (list 'face 'bold))) + (other-window 1)) + +;; 这个函数使用了 `re-search-forward': +;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式 + +;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是: +;; 字符串 "Bonjour ", 之后跟着 +;; 一组 | \\( ... \\) 结构 +;; 任意字符 | . 的含义 +;; 有可能重复的 | + 的含义 +;; 之后跟着 "!" 这个字符串 + +;; 准备好了?试试看。 + +(boldify-names) + +;; `add-text-properties' 可以添加文字属性, 比如文字样式 + +;; 好的,我们成功了! + +;; 如果你想对一个变量或者函数有更多的了解: +;; +;; C-h v 变量 回车 +;; C-h f 函数 回车 +;; +;; 阅读Emacs Lisp官方文档: +;; +;; C-h i m elisp 回车 +;; +;; 在线阅读Emacs Lisp文档: +;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html + +;; 感谢以下同学的建议和反馈: +;; - Wes Hardaker +;; - notbob +;; - Kevin Montuori +;; - Arne Babenhauserheide +;; - Alan Schmitt +;; - spacegoing +``` + diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index daee8d3c..0ed1d823 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] translators: diff --git a/zh-cn/fortran-cn.html.markdown b/zh-cn/fortran-cn.html.markdown new file mode 100644 index 00000000..ab521e0a --- /dev/null +++ b/zh-cn/fortran-cn.html.markdown @@ -0,0 +1,444 @@ +--- +language: Fortran +filename: learnfortran-cn.f90 +contributors: + - ["Robert Steed", "https://github.com/robochat"] +translators: + - ["Corvusnest", "https://github.com/Corvusnest"] +lang: zh-cn +--- + +Fortran 是最古老的计算机语言之一。它由 IBM 开发于 1950 年用于数值运算(Fortran 为 "Formula +Translation" 的缩写)。虽然该语言已年代久远,但目前仍用于高性能计算,如天气预报。 +该语言仍在持续发展,并且基本保持向下兼容。知名的版本为 Fortran 77, Fortran 90, +Fortran 95, Fortran 2008, Fortran 2015 和 Fortran 2023。 + +这篇概要将讨论 Fortran 2008 的一些特征。因为它是目前所广泛采用的标准版本,并且与最新版本的内容 +也基本相同(而 Fortran 77 则是一个非常不同的版本)。 + +```fortran +! 这是一个注释 + +program example ! 声明一个名为 example 的程序 + + ! 代码只能存在于程序、函数、子程序或模块中 + ! 使用缩进不是必需的,但推荐使用 + + ! 声明变量 + ! ========= + + ! 所有的声明必须在语句和表达式之前 + + implicit none ! 防止动态声明变量(推荐!) + ! implicit none 推荐在每个函数/程序/模块中重新声明... + + ! 注意 - Fortran 中对大小写不敏感 + real z + REAL Z2 + + real :: v, x ! 警告:默认的初始值取决于编译器! + real :: a = 3, b = 2E12, c = 0.01 + integer :: i, j, k = 1, m + real, parameter :: PI = 3.1415926535897931 ! 声明一个常数 + logical :: y = .TRUE., n = .FALSE. ! 布尔类型 + complex :: w = (0, 1) ! 单位虚数 + character(len=3) :: month ! 字符串,长度为 3 个字符 + + real :: array(6) ! 声明一个包含 6 个实数的数组 + real, dimension(4) :: arrayb ! 另一种声明数组的方式 + integer :: arrayc(-10:10) ! 具有自定义索引的数组 + real :: array2d(3, 2) ! 多维数组 + + ! 这些分隔符 '::' 并不总是必需的,但推荐使用 + + ! 还有许多其他的变量属性: + real, pointer :: p ! 声明一个指针 + + integer, parameter :: LP = selected_real_kind(20) + real(kind=LP) :: d ! 长精度变量 + + ! 警告:在声明过程中初始化变量会在函数中造成问题, + ! 因为这会自动暗示 'save' 属性, + ! 在函数调用之间保存变量的值一般情况下, + ! 除了常量外,声明和初始化的代码应该分开! + + ! 字符串 + ! ======= + + character :: a_char = 'i' + character(len=6) :: a_str = "qwerty" + character(len=30) :: str_b + character(len=*), parameter :: a_long_str = "This is a long string." + ! 使用 (len=*) 可以自动计算长度,但只适用于常量 + + str_b = a_str//" keyboard" ! 使用 // 运算符连接字符串 + + ! 赋值和算术 + ! ============= + + Z = 1 ! 对上面声明的变量 z 进行赋值(对大小写不敏感) + j = 10 + 2 - 3 + a = 11.54/(2.3*3.1) + b = 2**3 ! 幂运算 + + ! 流程控制语句和操作符 + ! =================== + + ! 单行 if 语句 + if (z == a) b = 4 ! 条件始终需要在括号中 + + if (z /= a) then ! z 不等于 a + ! 其他的比较操作符包括 < > <= >= == /= + b = 4 + else if (z .GT. a) then ! z 大于 a + ! 文本等价于符号操作符中的 .LT. .GT. .LE. .GE. .EQ. .NE. + b = 6 + else if (z < a) then ! 'then' 必须在本行上 + b = 5 ! 执行块必须在新的一行上 + else + b = 10 + end if ! end 语句后需要 'if'(或可以使用 'endif') + + if (.NOT. (x < c .AND. v >= a .OR. z == z)) then ! 布尔运算符 + inner: if (.TRUE.) then ! 可以对 if 结构命名 + b = 1 + end if inner ! then 必须命名对应的 endif 语句 + end if + + i = 20 + select case (i) + case (0, 1) ! 当 i == 0 或 i == 1 时 + j = 0 + case (2:10) ! 当 i 在 2 到 10 之间(包括边界)时 + j = 1 + case (11:) ! 当 i >= 11 时 + j = 2 + case default + j = 3 + end select + + month = 'jan' + ! 条件可以是整数、逻辑、或字符类型 + ! Select 结构也可以命名 + monthly:select case(month) + case ("jan") + j = 0 + case default + j = -1 + end select monthly + + do i = 2, 10, 2 ! 循环从 2 到 10(包括)以 2 为步长 + innerloop: do j = 1, 3 ! 循环也可以命名 + exit ! 退出循环 + end do innerloop + cycle ! 跳到下一个循环迭代 + end do + + ! 虽然存在 Goto 语句,但它被强烈不推荐 + goto 10 + stop 1 ! 立即停止代码(并返回指定的条件代码) +10 j = 201 ! 这一行被标记为 10 行 + + ! 数组 + ! ===== + array = (/1, 2, 3, 4, 5, 6/) + array = [1, 2, 3, 4, 5, 6] ! 使用 Fortran 2003 的表示法 + arrayb = [10.2, 3e3, 0.41, 4e-5] + array2d = reshape([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], [3, 2]) + + ! Fortran 数组索引从 1 开始 + ! (默认情况下,但对于特定数组可以定义不同的索引) + v = array(1) ! 取数组的第一个元素 + v = array2d(2, 2) + + print *, array(3:5) ! 打印从第三个到第五个元素(包括) + print *, array2d(1, :) ! 打印二维数组的第一列 + + array = array*3 + 2 ! 可以对数组应用数学表达式 + array = array*array ! 数组操作是逐元素进行的 + ! array = array*array2d ! 这两个数组是不兼容的 + + ! 有许多内置函数可用于数组 + c = dot_product(array, array) ! 这是点积 + ! 使用 matmul() 进行矩阵运算 + c = sum(array) + c = maxval(array) + print *, minloc(array) + c = size(array) + print *, shape(array) + m = count(array > 0) + + ! 循环数组(通常使用 product() 函数) + v = 1 + do i = 1, size(array) + v = v*array(i) + end do + + ! 条件性地执行逐元素赋值 + array = [1, 2, 3, 4, 5, 6] + where (array > 3) + array = array + 1 + elsewhere(array == 2) + array = 1 + elsewhere + array = 0 + end where + + ! 隐含 do 循环是创建数组的紧凑方式 + array = [(i, i=1, 6)] ! 创建一个数组 [1,2,3,4,5,6] + array = [(i, i=1, 12, 2)] ! 创建一个数组 [1,3,5,7,9,11] + array = [(i**2, i=1, 6)] ! 创建一个数组 [1,4,9,16,25,36] + array = [(4, 5, i=1, 3)] ! 创建一个数组 [4,5,4,5,4,5] + + ! 输入/输出 + ! ========= + + print *, b ! 将变量 'b' 打印到命令行 + + ! 可以对打印的输出进行格式化 + print "(I6)", 320 ! 打印 ' 320' + print "(I6.4)", 3 ! 打印 ' 0003' + print "(F6.3)", 4.32 ! 打印 ' 4.320' + + ! 字母表示预期的类型,后面的数字表示用于打印值的字符数 + ! 字母可以是 I(整数),F(实数),E(工程表示法), + ! L(逻辑),A(字符串)... + print "(I3)", 3200 ! 打印 '***',因为该数字不适合 + + ! 可以有多个格式规范 + print "(I5,F6.2,E6.2)", 120, 43.41, 43.41 + print "(3I5)", 10, 20, 30 ! 整数的三次重复(字段宽度为 5) + print "(2(I5,F6.2))", 120, 43.42, 340, 65.3 ! 格式重复组合 + + ! 我们还可以从终端读取输入 + read (*, *) v + read (*, "(2F6.2)") v, x ! 读取两个数字 + + ! 写入文件 + open (unit=12, file="records.txt", status="replace") + ! 文件通过 'unit number' 引用,这个数字可以在 9:99 范围内选择 + ! Status 可以是 {'old','replace','new'} 中的一个 + write (12, "(F10.2,F10.2,F10.2)") c, b, a + close (12) + + ! 读取文件 + open (newunit=m, file="records.txt", status="old") + ! 文件通过 'new unit number' 引用,编译器为您选择一个整数 + read (unit=m, fmt="(3F10.2)") a, b, c + close (m) + + ! 还有更多功能可用,超出了本文所讨论的范围, + ! 还有由于与旧版本的 Fortran 的向后兼容性而存在的替代方案 + + ! 内置函数 + ! =========== + + ! Fortran 大约有 200 个语言内部的函数/子程序 + ! 例如 - + call cpu_time(v) ! 将 'v' 设置为以秒为单位的时间 + k = ior(i, j) ! 两个整数的位 OR 运算 + v = log10(x) ! 以 10 为底的对数 + i = floor(b) ! 返回小于或等于 x 的最接近的整数 + v = aimag(w) ! 复数的虚部 + + ! 函数和子程序 + ! ============== + + ! 子程序运行一些代码,并可以对输入值产生副作用或修改输入值 + + call routine(a, c, v) ! 子程序调用 + + ! 函数采用一系列输入参数,并返回一个单个值 + ! 不过,输入参数可能仍会被修改,并且会执行副作用 + + m = func(3, 2, k) ! 函数调用 + + ! 函数调用还可以在表达式中使用 + print *, func2(3, 2, k) + + ! 一个纯函数是一个不修改其输入参数, + ! 也不会引起任何副作用的函数 + m = func3(3, 2, k) + +contains ! 包含程序内部定义的子程序的区域 + + ! Fortran 有几种稍微不同的方式来定义函数 + + integer function func(a, b, c) ! 函数返回一个整数值 + ! implicit none ! 子变量域可以不再声明 implicit none + integer, intent(in) :: a, b, c ! 在函数内部定义输入参数的类型 + + if (a >= 2) then + func = a + b + c ! 返回变量默认为函数名 + return ! 随时可以从函数返回当前值 + end if + func = a + c + + ! 在函数的末尾不需要 return 语句 + end function func + + function func2(a, b, c) result(f) ! 返回变量声明为 'f' + integer, intent(in) :: a, b ! 可以声明和强制约定变量 + ! 不会被函数修改 + integer, intent(inout) :: c + integer :: f ! 函数返回类型在函数内部声明 + integer :: cnt = 0 ! 注意:初始化暗示变量在函数调用之间保存 + ! + + f = a + b - c + c = 4 ! 修改输入变量的值 + cnt = cnt + 1 ! 计算函数调用的次数 + + end function func2 + + pure function func3(a, b, c) ! 纯函数不能有副作用 + integer, intent(in) :: a, b, c + integer :: func3 + + func3 = a*b*c + + end function func3 + + subroutine routine(d, e, f) + real, intent(inout) :: f + real, intent(in) :: d, e + + f = 2*d + 3*e + f + + end subroutine routine + +end program example ! 程序定义结束-------------------------- + +! 函数和子程序在程序列表之外声明,在程序之间以及模块中声明时,需要使用 interface 声明(即使它们在同一源文件中)(见下面)将它们定义在模块或程序的 'contains' 部分更容易 + +elemental real function func4(a) result(res) +! elemental 函数是一个纯函数,它采用标量输入变量, +! 但也可以在数组上独立应用,并返回一个新的数组 + real, intent(in) :: a + + res = a**2 + 1.0 + +end function func4 + +! 模块 +! ======= + +! 模块是在可重用性中将相关的声明、函数和子程序结合在一起的有用方式 + +module fruit + + real :: apple + real :: pear + real :: orange + +end module fruit + +module fruity + ! 声明的顺序必须是:模块、接口、变量 + !(也可以在程序中声明模块和接口) + + use fruit, only: apple, pear ! 使用 fruit 模块中的 apple 和 pear + implicit none ! 导入模块之后 + + private ! 将一些内容私有化(默认为公共) + ! 显式将一些变量/函数声明为公共 + public :: apple, mycar, create_mycar + ! 将一些变量/函数声明为模块私有(本例中是多余的) + private :: func4 + + ! 接口 + ! ======== + ! 在模块内部(最好放在 'contains' 部分)显式声明外部函数/过程 + interface + elemental real function func4(a) result(res) + real, intent(in) :: a + end function func4 + end interface + + ! 可以使用命名接口定义重载函数 + interface myabs + ! 可以使用 'module procedure' 关键字包括模块内已经定义的函数 + module procedure real_abs, complex_abs + end interface + + ! 派生数据类型 + ! ================== + ! 可以创建自定义的结构化数据集合 + type car + character(len=100) :: model + real :: weight !(千克) + real :: dimensions(3) ! 即,长度-宽度-高度(米) + character :: colour + contains + procedure :: info ! 将过程绑定到类型 + end type car + + type(car) :: mycar ! 声明自定义类型的变量 + ! 请查看 create_mycar() 程序的用法 + + ! 注意:模块中没有可以执行的语句 + +contains + + subroutine create_mycar(mycar) + ! 演示派生数据类型的用法 + type(car), intent(out) :: mycar + + ! 使用 '%' 运算符访问类型元素 + mycar%model = "Ford Prefect" + mycar%colour = 'r' + mycar%weight = 1400 + mycar%dimensions(1) = 5.0 ! 默认索引从 1 开始! + mycar%dimensions(2) = 3.0 + mycar%dimensions(3) = 1.5 + + end subroutine create_mycar + + subroutine info(self) + class(car), intent(in) :: self + ! 使用 'class' 关键字将过程绑定到类型 + + print *, "Model : ", self%model + print *, "Colour : ", self%colour + print *, "Weight : ", self%weight + print *, "Dimensions: ", self%dimensions + + end subroutine info + + real pure function real_abs(x) + real, intent(in) :: x + + if (x < 0) then + real_abs = -x + else + real_abs = x + end if + + end function real_abs + + real pure function complex_abs(z) + complex, intent(in) :: z + ! 长行可以使用继续字符 '&' 进行延续 + + complex_abs = sqrt(real(z)**2 + & + aimag(z)**2) + + end function complex_abs + +end module fruity + +``` + +### 更多资源 + +了解更多的 Fortran 信息: + ++ [wikipedia](https://en.wikipedia.org/wiki/Fortran) ++ [Fortran-lang Organization](https://fortran-lang.org/) ++ [Fortran_95_language_features](https://en.wikipedia.org/wiki/Fortran_95_language_features) ++ [fortranwiki.org](http://fortranwiki.org) ++ [www.fortran90.org/](http://www.fortran90.org) ++ [list of Fortran 95 tutorials](http://www.dmoz.org/Computers/Programming/Languages/Fortran/FAQs%2C_Help%2C_and_Tutorials/Fortran_90_and_95/) ++ [Fortran wikibook](https://en.wikibooks.org/wiki/Fortran) ++ [Fortran resources](http://www.fortranplus.co.uk/resources/fortran_resources.pdf) ++ [Mistakes in Fortran 90 Programs That Might Surprise You](http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html) diff --git a/zh-cn/fortran95-cn.html.markdown b/zh-cn/fortran95-cn.html.markdown deleted file mode 100644 index e28d309f..00000000 --- a/zh-cn/fortran95-cn.html.markdown +++ /dev/null @@ -1,435 +0,0 @@ ---- -language: Fortran -filename: learnfortran-cn.f95 -contributors: - - ["Robert Steed", "https://github.com/robochat"] -translators: - - ["Corvusnest", "https://github.com/Corvusnest"] -lang: zh-cn ---- - -Fortran 是最古老的计算机语言之一。它由IBM开发于1950年用于数值运算(Fortran 为 "Formula -Translation" 的缩写)。虽然该语言已年代久远,但目前仍用于高性能计算,如天气预报。 -该语言仍在持续发展,并且基本保持向下兼容。知名的版本为 Fortran 77, Fortran 90, -Fortran 95, Fortran 2003, Fortran 2008 与 Fortran 2015。 - -这篇概要将讨论 Fortran 95 的一些特征。因为它是目前所广泛采用的标准版本,并且与最新版本的内容 -也基本相同(而 Fortran 77 则是一个非常不同的版本)。 - -```fortran - -! 这是一行注释 - - -program example !声明一个叫做 example 的程序 - - ! 代码只能放在程序、函数、子程序或者模块内部 - ! 推荐使用缩进,但不是必须的。 - - ! 声明变量 - ! =================== - - ! 所有的声明必须放在语句与表达式之前 - - implicit none !阻止变量的隐式声明 (推荐!) - ! Implicit none 必须在每一个 函数/程序/模块 中进行声明 - - ! 重要 - Fortran 对大小写不敏感 - real z - REAL Z2 - - real :: v,x ! 警告: 默认值取决于编译器! - real :: a = 3, b=2E12, c = 0.01 - integer :: i, j, k=1, m - real, parameter :: PI = 3.1415926535897931 !声明一个常量 - logical :: y = .TRUE. , n = .FALSE. !布尔值 - complex :: w = (0,1) !sqrt(-1) (译注: 定义复数,此为-1的平方根) - character (len=3) :: month !长度为3的字符串 - - real :: array(6) !声明长度为6的浮点数数组 - real, dimension(4) :: arrayb !声明数组的另一种方法 - integer :: arrayc(-10:10) !有着自定义索引的数组 - real :: array2d(3,2) !多维数组 - - ! 分隔符 '::' 并不总是必要的,但推荐使用 - - ! 还存在很多其他的变量特征: - real, pointer :: p !声明一个指针 - - integer, parameter :: LP = selected_real_kind(20) - real (kind = LP) :: d !长精度变量 - - ! 警告:在声明期间初始化变量将导致在函数内发生问题,因为这将自动具备了 “save” 属性, - ! 因此变量的值在函数的多次调用期间将被存储。一般来说,除了常量,应分开声明与初始化! - - ! 字符串 - ! ======= - - character :: a_char = 'i' - character (len = 6) :: a_str = "qwerty" - character (len = 30) :: str_b - character (len = *), parameter :: a_long_str = "This is a long string." - !可以通过使用 (len=*) 来自动判断长度,但只对常量有效 - - str_b = a_str // " keyboard" !通过 // 操作符来连接字符串 - - - ! 任务与计算 - ! ======================= - - Z = 1 !向之前声明的变量 z 赋值 (大小写不敏感). - j = 10 + 2 - 3 - a = 11.54 / (2.3 * 3.1) - b = 2**3 !幂 - - - ! 控制流程语句 与 操作符 - ! =================================== - - !单行 if 语句 - if (z == a) b = 4 !判别句永远需要放在圆括号内 - - if (z /= a) then !z 不等于 a - ! 其他的比较运算符: < > <= >= == /= - b = 4 - else if (z .GT. a) then !z 大于(Greater) a - ! 文本形式的比较运算符: .LT. .GT. .LE. .GE. .EQ. .NE. - b = 6 - else if (z < a) then !'then' 必须放在该行 - b = 5 !执行部分必须放在新的一行里 - else - b = 10 - end if !结束语句需要 'if' (也可以用 'endif'). - - - if (.NOT. (x < c .AND. v >= a .OR. z == z)) then !布尔操作符 - inner: if (.TRUE.) then !可以为 if 结构命名 - b = 1 - endif inner !接下来必须命名 endif 语句. - endif - - - i = 20 - select case (i) - case (0) !当 i == 0 - j=0 - case (1:10) !当 i 为 1 到 10 之内 ( 1 <= i <= 10 ) - j=1 - case (11:) !当 i>=11 - j=2 - case default - j=3 - end select - - - month = 'jan' - ! 状态值可以为整数、布尔值或者字符类型 - ! Select 结构同样可以被命名 - monthly: select case (month) - case ("jan") - j = 0 - case default - j = -1 - end select monthly - - do i=2,10,2 !从2到10(包含2和10)以2为步进值循环 - innerloop: do j=1,3 !循环同样可以被命名 - exit !跳出循环 - end do innerloop - cycle !重复跳入下一次循环 - enddo - - - ! Goto 语句是存在的,但强烈不建议使用 - goto 10 - stop 1 !立即停止程序 (返回一个设定的状态码). -10 j = 201 !这一行被标注为 10 行 (line 10) - - - ! 数组 - ! ====== - array = (/1,2,3,4,5,6/) - array = [1,2,3,4,5,6] !当使用 Fortran 2003 版本. - arrayb = [10.2,3e3,0.41,4e-5] - array2d = reshape([1.0,2.0,3.0,4.0,5.0,6.0], [3,2]) - - ! Fortran 数组索引起始于 1 - ! (默认下如此,也可以为数组定义不同的索引起始) - v = array(1) !获取数组的第一个元素 - v = array2d(2,2) - - print *, array(3:5) !打印从第3到第五5之内的所有元素 - print *, array2d(1,:) !打印2维数组的第一列 - - array = array*3 + 2 !可为数组设置数学表达式 - array = array*array !数组操作支持元素级(操作) (element-wise) - !array = array*array2d !这两类数组并不是同一个维度的 - - ! 有很多内置的数组操作函数 - c = dot_product(array,array) !点乘 (点积) - ! 用 matmul() 来进行矩阵运算. - c = sum(array) - c = maxval(array) - print *, minloc(array) - c = size(array) - print *, shape(array) - m = count(array > 0) - - ! 遍历一个数组 (一般使用 Product() 函数). - v = 1 - do i = 1, size(array) - v = v*array(i) - end do - - ! 有条件地执行元素级操作 - array = [1,2,3,4,5,6] - where (array > 3) - array = array + 1 - elsewhere (array == 2) - array = 1 - elsewhere - array = 0 - end where - - ! 隐式DO循环可以很方便地创建数组 - array = [ (i, i = 1,6) ] !创建数组 [1,2,3,4,5,6] - array = [ (i, i = 1,12,2) ] !创建数组 [1,3,5,7,9,11] - array = [ (i**2, i = 1,6) ] !创建数组 [1,4,9,16,25,36] - array = [ (4,5, i = 1,3) ] !创建数组 [4,5,4,5,4,5] - - - ! 输入/输出 - ! ============ - - print *, b !向命令行打印变量 'b' - - ! 我们可以格式化输出 - print "(I6)", 320 !打印 ' 320' - print "(I6.4)", 3 !打印 ' 0003' - print "(F6.3)", 4.32 !打印 ' 4.320' - - - ! 该字母与数值规定了给定的数值与字符所用于打印输出的类型与格式 - ! 字母可为 I (整数), F (浮点数), E (工程格式), - ! L (逻辑/布尔值), A (字符) ... - print "(I3)", 3200 !如果数值无法符合格式将打印 '***' - - ! 可以同时设定多种格式 - print "(I5,F6.2,E6.2)", 120, 43.41, 43.41 - print "(3I5)", 10, 20, 30 !连续打印3个整数 (字段宽度 = 5). - print "(2(I5,F6.2))", 120, 43.42, 340, 65.3 !连续分组格式 - - ! 我们也可以从终端读取输入 - read *, v - read "(2F6.2)", v, x !读取2个数值 - - ! 读取文件 - open(unit=11, file="records.txt", status="old") - ! 文件被引用带有一个单位数 'unit', 为一个取值范围在9-99的整数 - ! 'status' 可以为 {'old','replace','new'} 其中之一 - read(unit=11, fmt="(3F10.2)") a, b, c - close(11) - - ! 写入一个文件 - open(unit=12, file="records.txt", status="replace") - write(12, "(F10.2,F10.2,F10.2)") c, b, a - close(12) - ! 在讨论范围之外的还有更多的细节与可用功能,并于老版本的 Fortran 保持兼容 - - - ! 内置函数 - ! ================== - - ! Fortran 拥有大约 200 个内置函数/子程序 - ! 例子 - call cpu_time(v) !以秒为单位设置时间 - k = ior(i,j) !2个整数的位或运算 - v = log10(x) !以10为底的log运算 - i = floor(b) !返回一个最接近的整数小于或等于x (地板数) - v = aimag(w) !复数的虚数部分 - - - ! 函数与子程序 - ! ======================= - - ! 一个子程序会根据输入值运行一些代码并会导致副作用 (side-effects) 或修改输入值 - ! (译者注: 副作用是指对子程序/函数外的环境产生影响,如修改变量) - - call routine(a,c,v) !调用子程序 - - ! 一个函数会根据输入的一系列数值来返回一个单独的值 - ! 但输入值仍然可能被修改以及产生副作用 - - m = func(3,2,k) !调用函数 - - ! 函数可以在表达式内被调用 - Print *, func2(3,2,k) - - ! 一个纯函数不会去修改输入值或产生副作用 - m = func3(3,2,k) - - -contains ! 用于定义程序内部的副程序(sub-programs)的区域 - - ! Fortran 拥有一些不同的方法去定义函数 - - integer function func(a,b,c) !一个返回一个整数的函数 - implicit none !最好也在函数内将含蓄模式关闭 (implicit none) - integer :: a,b,c !输入值类型定义在函数内部 - if (a >= 2) then - func = a + b + c !返回值默认为函数名 - return !可以在函数内任意时间返回当前值 - endif - func = a + c - ! 在函数的结尾不需要返回语句 - end function func - - - function func2(a,b,c) result(f) !将返回值声明为 'f' - implicit none - integer, intent(in) :: a,b !可以声明让变量无法被函数修改 - integer, intent(inout) :: c - integer :: f !函数的返回值类型在函数内声明 - integer :: cnt = 0 !注意 - 隐式的初始化变量将在函数的多次调用间被存储 - f = a + b - c - c = 4 !变动一个输入变量的值 - cnt = cnt + 1 !记录函数的被调用次数 - end function func2 - - - pure function func3(a,b,c) !一个没有副作用的纯函数 - implicit none - integer, intent(in) :: a,b,c - integer :: func3 - func3 = a*b*c - end function func3 - - - subroutine routine(d,e,f) - implicit none - real, intent(inout) :: f - real, intent(in) :: d,e - f = 2*d + 3*e + f - end subroutine routine - - -end program example ! 函数定义完毕 ----------------------- - -! 函数与子程序的外部声明对于生成程序清单来说,需要一个接口声明(即使它们在同一个源文件内)(见下) -! 使用 'contains' 可以很容易地在模块或程序内定义它们 - -elemental real function func4(a) result(res) -! 一个元函数(elemental function) 为一个纯函数使用一个标量输入值 -! 但同时也可以用在一个数组并对其中的元素分别处理,之后返回一个新的数组 - real, intent(in) :: a - res = a**2 + 1.0 -end function func4 - - -! 模块 -! ======= - -! 模块十分适合于存放与复用相关联的一组声明、函数与子程序 - -module fruit - real :: apple - real :: pear - real :: orange -end module fruit - - -module fruity - - ! 声明必须按照顺序: 模块、接口、变量 - ! (同样可在程序内声明模块和接口) - - use fruit, only: apple, pear ! 使用来自于 fruit 模块的 apple 和 pear - implicit none !在模块导入后声明 - - private !使得模块内容为私有(private)(默认为公共 public) - ! 显式声明一些变量/函数为公共 - public :: apple,mycar,create_mycar - ! 声明一些变量/函数为私有(在当前情况下没必要)(译注: 因为前面声明了模块全局 private) - private :: func4 - - ! 接口 - ! ========== - ! 在模块内显式声明一个外部函数/程序 - ! 一般最好将函数/程序放进 'contains' 部分内 - interface - elemental real function func4(a) result(res) - real, intent(in) :: a - end function func4 - end interface - - ! 重载函数可以通过已命名的接口来定义 - interface myabs - ! 可以通过使用 'module procedure' 关键词来包含一个已在模块内定义的函数 - module procedure real_abs, complex_abs - end interface - - ! 派生数据类型 - ! ================== - ! 可创建自定义数据结构 - type car - character (len=100) :: model - real :: weight !(公斤 kg) - real :: dimensions(3) !例: 长宽高(米) - character :: colour - end type car - - type(car) :: mycar !声明一个自定义类型的变量 - ! 用法具体查看 create_mycar() - - ! 注: 模块内没有可执行的语句 - -contains - - subroutine create_mycar(mycar) - ! 展示派生数据类型的使用 - implicit none - type(car),intent(out) :: mycar - - ! 通过 '%' 操作符来访问(派生数据)类型的元素 - mycar%model = "Ford Prefect" - mycar%colour = 'r' - mycar%weight = 1400 - mycar%dimensions(1) = 5.0 !索引默认起始值为 1 ! - mycar%dimensions(2) = 3.0 - mycar%dimensions(3) = 1.5 - - end subroutine - - real function real_abs(x) - real :: x - if (x<0) then - real_abs = -x - else - real_abs = x - end if - end function real_abs - - real function complex_abs(z) - complex :: z - ! 过长的一行代码可通过延续符 '&' 来换行 - complex_abs = sqrt(real(z)**2 + & - aimag(z)**2) - end function complex_abs - - -end module fruity - -``` - -### 更多资源 - -了解更多的 Fortran 信息: - -+ [wikipedia](https://en.wikipedia.org/wiki/Fortran) -+ [Fortran_95_language_features](https://en.wikipedia.org/wiki/Fortran_95_language_features) -+ [fortranwiki.org](http://fortranwiki.org) -+ [www.fortran90.org/](http://www.fortran90.org) -+ [list of Fortran 95 tutorials](http://www.dmoz.org/Computers/Programming/Languages/Fortran/FAQs%2C_Help%2C_and_Tutorials/Fortran_90_and_95/) -+ [Fortran wikibook](https://en.wikibooks.org/wiki/Fortran) -+ [Fortran resources](http://www.fortranplus.co.uk/resources/fortran_resources.pdf) -+ [Mistakes in Fortran 90 Programs That Might Surprise You](http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html) diff --git a/zh-cn/gdscript-cn.html.markdown b/zh-cn/gdscript-cn.html.markdown new file mode 100644 index 00000000..7c731533 --- /dev/null +++ b/zh-cn/gdscript-cn.html.markdown @@ -0,0 +1,317 @@ +--- +language: GDScript +contributors: + - ["Wichamir", "https://github.com/Wichamir/"] +translators: + - ["ShiftWatchOut", "https://github.com/ShiftWatchOut"] +filename: learngdscript-cn.gd +lang: zh-cn +--- + +GDScript 是一种动态类型的脚本语言,专门为免费开源游戏引擎 Godot 制作。 GDScript 的语法类似 Python。 +它的主要优点是易于使用和与引擎深度集成。 它非常适合游戏开发。 + +## 基础 + +```nim +# 单行注释使用 # 号书写。 +""" + 多行 + 注释 + 是 + 使用 + 文档字符串(docstring) + 书写。 +""" + +# 脚本文件本身默认是一个类,文件名为类名,您也可以为其定义其他名称。 +class_name MyClass + +# 继承 +extends Node2D + +# 成员变量 +var x = 8 # 整型 +var y = 1.2 # 浮点型 +var b = true # 布尔型 +var s = "Hello World!" # 字符串 +var a = [1, false, "brown fox"] # 数组(Array) - 类似于 Python 的列表(list), + # 它可以同时保存不同类型的变量。 +var d = { + "key" : "value", + 42 : true +} # 字典包含键值对。 +var p_arr = PoolStringArray(["Hi", "there", "!"]) # 池数组只能包含单一类型。 + # 放入其他类型会被转换为目标类型 + +# 内置向量类型: +var v2 = Vector2(1, 2) +var v3 = Vector3(1, 2, 3) + +# 常量 +const ANSWER_TO_EVERYTHING = 42 +const BREAKFAST = "Spam and eggs!" + +# 枚举 +enum { ZERO, ONE , TWO, THREE } +enum NamedEnum { ONE = 1, TWO, THREE } + +# 导出的变量将在检查器中可见。 +export(int) var age +export(float) var height +export var person_name = "Bob" # 如果设置了默认值,则不需要类型注解。 + +# 函数 +func foo(): + pass # pass 关键字是未书写的代码的占位符 + +func add(first, second): + return first + second + +# 打印值 +func printing(): + print("GDScript ", "简直", "棒呆了") + prints("这", "些", "字", "被", "空", "格", "分", "割") + printt("这", "些", "字", "被", "制", "表", "符", "分", "割") + printraw("这句话将被打印到系统控制台。") + +# 数学 +func doing_math(): + var first = 8 + var second = 4 + print(first + second) # 12 + print(first - second) # 4 + print(first * second) # 32 + print(first / second) # 2 + print(first % second) # 0 + # 还有 +=, -=, *=, /=, %= 等操作符,但并没有 ++ 和 -- . + print(pow(first, 2)) # 64 + print(sqrt(second)) # 2 + printt(PI, TAU, INF, NAN) # 内置常量 + +# 控制流 +func control_flow(): + x = 8 + y = 2 # y 最初被设为一个浮点数, + # 但我们可以利用语言提供的动态类型能力将它的类型变为整型! + + if x < y: + print("x 小于 y") + elif x > y: + print("x 大于 y") + else: + print("x 等于 y") + + var a = true + var b = false + var c = false + if a and b or not c: # 你也可以用 &&, || 和 ! + print("看到这句说明上面的条件判断为真!") + + for i in range(20): # GDScript 有类似 Python 的 range 函数 + print(i) # 所以这句将打印从 0 到 19 的数字 + + for i in 20: # 与 Python 略有不同的是,你可以直接用一个整型数开始循环 + print(i) # 所以这行代码也将打印从 0 到 19 的数字 + + for i in ["two", 3, 1.0]: # 遍历数组 + print(i) + + while x > y: + printt(x, y) + y += 1 + + x = 2 + y = 10 + while x < y: + x += 1 + if x == 6: + continue # continue 语句使 x 等于 6 时,程序跳过这次循环后面的代码,不会打印 6。 + prints("x 等于:", x) + if x == 7: + break # 循环将在 x 等于 7 处跳出,后续所有循环不再执行,因此不会打印 8、9 和 10 + + match x: + 1: + print("match 很像其他语言中的 switch.") + 2: + print("但是,您不需要在每个值之前写一个 case 关键字。") + 3: + print("此外,每种情况都会默认跳出。") + break # 错误!不要在 match 里用 break 语句! + 4: + print("如果您需要跳过后续代码,这里也使用 continue 关键字。") + continue + _: + print("下划线分支,在其他分支都不满足时,在这里书写默认的逻辑。") + + # 三元运算符 (写在一行的 if-else 语句) + prints("x 是", "正值" if x >= 0 else "负值") + +# 类型转换 +func casting_examples(): + var i = 42 + var f = float(42) # 使用变量构造函数强制转换 + var b = i as bool # 或使用 as 关键字 + +# 重载函数 +# 通常,我们只会重载以下划线开头的内置函数, +# 但实际上您可以重载几乎任何函数。 + +# _init 在对象初始化时被调用。 +# 这是对象的构造函数。 +func _init(): + # 在此处初始化对象的内部属性。 + pass + +# _ready 在脚本节点及其子节点进入场景树时被调用。 +func _ready(): + pass + +# _process 在每一帧上都被调用。 +func _process(delta): + # 传递给此函数的 delta 参数是时间,即从上一帧到当前帧经过的秒数。 + print("Delta 时间为:", delta) + +# _physics_process 在每个物理帧上都被调用。 +# 这意味着 delta 应该是恒定的。 +func _physics_process(delta): + # 使用向量加法和乘法进行简单移动。 + var direction = Vector2(1, 0) # 或使用 Vector2.RIGHT + var speed = 100.0 + self.global_position += direction * speed * delta + # self 指向当前类的实例 + +# 重载函数时,您可以使用 . 运算符调用父函数 +# like here: +func get_children(): + # 在这里做一些额外的事情。 + var r = .get_children() # 调用父函数的实现 + return r + +# 内部类 +class InnerClass: + extends Object + + func hello(): + print("来自内部类的 Hello!") + +func use_inner_class(): + var ic = InnerClass.new() + ic.hello() + ic.free() # 可以自行释放内存 +``` + +## 访问场景树中其他节点 + +```nim +extends Node2D + +var sprite # 该变量将用来保存引用。 + +# 您可以在 _ready 中获取对其他节点的引用。 +func _ready() -> void: + # NodePath 对于访问节点很有用。 + # 将 String 传递给其构造函数来创建 NodePath: + var path1 = NodePath("path/to/something") + # 或者使用 NodePath 字面量: + var path2 = @"path/to/something" + # NodePath 示例: + var path3 = @"Sprite" # 相对路径,当前节点的直接子节点 + var path4 = @"Timers/Firerate" # 相对路径,子节点的子节点 + var path5 = @".." # 当前节点的父节点 + var path6 = @"../Enemy" # 当前节点的兄弟节点 + var path7 = @"/root" # 绝对路径,等价于 get_tree().get_root() + var path8 = @"/root/Main/Player/Sprite" # Player 的 Sprite 的绝对路径 + var path9 = @"Timers/Firerate:wait_time" # 访问属性 + var path10 = @"Player:position:x" # 访问子属性 + + # 最后,获取节点引用可以使用以下方法: + sprite = get_node(@"Sprite") as Sprite # 始终转换为您期望的类型 + sprite = get_node("Sprite") as Sprite # 这里 String 被隐式转换为 NodePath + sprite = get_node(path3) as Sprite + sprite = get_node_or_null("Sprite") as Sprite + sprite = $Sprite as Sprite + +func _process(delta): + # 现在我们就可以在别处使用 sprite 里保存的引用了。 + prints("Sprite 有一个全局位置 ", sprite.global_position) + +# 在 _ready 执行之前,使用 onready 关键字为变量赋值。 +# 这是一种常用的语法糖。 +onready var tween = $Tween as Tween + +# 您可以导出这个 NodePath,以便在检查器中给它赋值。 +export var nodepath = @"" +onready var reference = get_node(nodepath) as Node +``` + +## 信号(Signals) + +信号系统是 Godot 对观察者编程模式的实现。例子如下: + +```nim +class_name Player extends Node2D + +var hp = 10 + +signal died() # 定义一个信号 +signal hurt(hp_old, hp_new) # 信号可以带参数 + +func apply_damage(dmg): + var hp_old = hp + hp -= dmg + emit_signal("hurt", hp_old, hp) # 发出信号并传递参数 + if hp <= 0: + emit_signal("died") + +func _ready(): + # 将信号 "died" 连接到 self 中定义的 _on_death 函数 + self.connect("died", self, "_on_death") + +func _on_death(): + self.queue_free() # 死亡时销毁 Player +``` + +## 类型注解 + +GDScript 可以选择性地使用静态类型。 + +```nim +extends Node + +var x: int # 定义带有类型的变量 +var y: float = 4.2 +var z := 1.0 # 使用 := 运算符根据默认值推断类型 + +onready var node_ref_typed := $Child as Node + +export var speed := 50.0 + +const CONSTANT := "Typed constant." + +func _ready() -> void: + # 此函数不返回任何东西 + x = "string" # 错误!不要更改类型! + return + +func join(arg1: String, arg2: String) -> String: + # 此函数接受两个 String 并返回一个 String。 + return arg1 + arg2 + +func get_child_at(index: int) -> Node: + # 此函数接受一个 int 并返回一个 Node + return get_children()[index] + +signal example(arg: int) # 错误!信号不能接受类型参数! +``` + +## 延展阅读 + +* [Godot's Website](https://godotengine.org/) +* [Godot Docs](https://docs.godotengine.org/en/stable/) +* [Getting started with GDScript](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/index.html) +* [NodePath](https://docs.godotengine.org/en/stable/classes/class_nodepath.html) +* [Signals](https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html) +* [GDQuest](https://www.gdquest.com/) +* [GDScript.com](https://gdscript.com/)
\ No newline at end of file diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown index d471ab5d..9dfbbb93 100644 --- a/zh-cn/git-cn.html.markdown +++ b/zh-cn/git-cn.html.markdown @@ -234,7 +234,7 @@ $ git diff HEAD # 在搜索结果中显示行号 $ git config --global grep.lineNumber true -# 是搜索结果可读性更好 +# 使得搜索结果可读性更好 $ git config --global alias.g "grep --break --heading --line-number" ``` @@ -370,5 +370,3 @@ $ git rm /pather/to/the/file/HelloWorld.c * [Atlassian Git - 教程与工作流程](https://www.atlassian.com/git/) * [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) - -* [GitGuys](http://www.gitguys.com/) diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown index 37b4b137..a2b71761 100644 --- a/zh-cn/go-cn.html.markdown +++ b/zh-cn/go-cn.html.markdown @@ -22,7 +22,7 @@ Go语言有非常棒的标准库,还有一个充满热情的社区。 注释 */ // 导入包的子句在每个源文件的开头。 -// Main比较特殊,它用来声明可执行文件,而不是一个库。 +// main比较特殊,它用来声明可执行文件,而不是一个库。 package main // Import语句声明了当前文件引用的包。 @@ -35,12 +35,12 @@ import ( "strconv" // 字符串转换 ) -// 函数声明:Main是程序执行的入口。 +// 函数声明:main是程序执行的入口。 // 不管你喜欢还是不喜欢,反正Go就用了花括号来包住函数体。 func main() { // 往标准输出打印一行。 // 用包名fmt限制打印函数。 - fmt.Println("天坑欢迎你!") + fmt.Println("你好世界") // 调用当前包的另一个函数。 beyondHello() @@ -78,10 +78,10 @@ func learnTypes() { // 非ascii字符。Go使用UTF-8编码。 g := 'Σ' // rune类型,int32的别名,使用UTF-8编码 - f := 3.14195 // float64类型,IEEE-754 64位浮点数 + f := 3.14159 // float64类型,IEEE-754 64位浮点数 c := 3 + 4i // complex128类型,内部使用两个float64表示 - // Var变量可以直接初始化。 + // var变量可以直接初始化。 var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度 var pi float32 = 22. / 7 @@ -141,7 +141,7 @@ func learnTypes() { // 只用写return一个词就能将函数内指定名称的变量返回 func learnNamedReturns(x, y int) (z int) { z = x * y - return // z is implicit here, because we named it earlier. + return // 隐式返回z,因为前面指定了它。 } // Go全面支持垃圾回收。Go有指针,但是不支持指针运算。 @@ -161,7 +161,7 @@ func expensiveComputation() int { } func learnFlowControl() { - // If需要花括号,括号就免了 + // if需要花括号,括号就免了 if true { fmt.Println("这句话肯定被执行") } @@ -392,15 +392,15 @@ func requestServer() { ## 更进一步 -关于Go的一切你都可以在[Go官方网站](http://golang.org/)找到。 +关于Go的一切你都可以在[Go官方网站](https://go.dev/)找到。 在那里你可以获得教程参考,在线试用,和更多的资料。 -在简单的尝试过后,在[官方文档](https://golang.org/doc/)那里你会得到你所需要的所有资料、关于编写代码的规范、库和命令行工具的文档与Go的版本历史。 +在简单的尝试过后,在[官方文档](https://go.dev/doc/)那里你会得到你所需要的所有资料、关于编写代码的规范、库和命令行工具的文档与Go的版本历史。 强烈推荐阅读语言定义部分,很简单而且很简洁!(赶时髦!) -你还可以前往[Go在线体验中心](https://play.golang.org/p/tnWMjr16Mm)进,在浏览器里修改并运行这些代码,一定要试一试哦!你可以将[https://play.golang.org](https://play.golang.org)当作一个[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop),在那里体验语言特性或运行自己的代码,连环境都不用配! +你还可以前往[Go在线体验中心](https://go.dev/play/p/tnWMjr16Mm)进,在浏览器里修改并运行这些代码,一定要试一试哦!你可以将[https://go.dev/play/](https://go.dev/play/)当作一个[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop),在那里体验语言特性或运行自己的代码,连环境都不用配! -学习Go还要阅读Go[标准库的源代码](http://golang.org/src/),全部文档化了,可读性非常好,可以学到go,go style和go idioms。在[文档](http://golang.org/pkg/)中点击函数名,源代码就出来了! +学习Go还要阅读Go[标准库的源代码](https://go.dev/src/),全部文档化了,可读性非常好,可以学到go,go style和go idioms。在[文档](https://go.dev/pkg/)中点击函数名,源代码就出来了! [Go by example](https://gobyexample.com/)也是一个学习的好地方。 diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index c854169e..d653c58c 100644 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -128,7 +128,7 @@ snd ("haskell", 1) -- 1 -- 一个接受两个变量的简单函数 add a b = a + b --- 注意,如果你使用 ghci (Hakell 解释器),你需要使用 `let`,也就是 +-- 注意,如果你使用 ghci (Haskell 解释器),你需要使用 `let`,也就是 -- let add a b = a + b -- 调用函数 diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index 27003f3e..53a423a8 100644 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -190,7 +190,7 @@ public class LearnJava { { //System.out.println(fooWhile); //增加计数器 - //遍历99次, fooWhile 0->99 + //遍历100次, fooWhile 0->99 fooWhile++; } System.out.println("fooWhile Value: " + fooWhile); @@ -201,7 +201,7 @@ public class LearnJava { { //System.out.println(fooDoWhile); //增加计数器 - //遍历99次, fooDoWhile 0->99 + //遍历100次, fooDoWhile 0->99 fooDoWhile++; }while(fooDoWhile < 100); System.out.println("fooDoWhile Value: " + fooDoWhile); @@ -297,8 +297,8 @@ class Bicycle { // Bicycle 类的成员变量和方法 public int cadence; // Public: 任意位置均可访问 private int speed; // Private: 只在同类中可以访问 - protected int gear; // Protected: 可以在同类与子类中可以访问 - String name; // default: 可以在包内中可以访问 + protected int gear; // Protected: 可以在同类与子类中访问 + String name; // default: 可以在包内访问 // 构造函数是初始化一个对象的方式 // 以下是一个默认构造函数 diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 360f7c65..45e30932 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -4,7 +4,7 @@ category: language name: javascript filename: javascript-zh.js contributors: - - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Leigh Brenecki", "https://leigh.net.au"] - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["Chenbo Li", "http://binarythink.net"] @@ -17,8 +17,8 @@ Javascript 于 1995 年由网景公司的 Brendan Eich 发明。最初它作为 不过,Javascript 不仅用于网页浏览器,一个名为 Node.js 的项目提供了面向 Google Chrome V8 引擎的独立运行时环境,它正在变得越来越流行。 很欢迎来自您的反馈,您可以通过下列方式联系到我: -[@adambrenecki](https://twitter.com/adambrenecki), 或者 -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). +[@ExcitedLeigh](https://twitter.com/ExcitedLeigh), 或者 +[l@leigh.net.au](mailto:l@leigh.net.au). ```js // 注释方式和C很像,这是单行注释 diff --git a/zh-cn/json-cn.html.markdown b/zh-cn/json-cn.html.markdown index 73d3eb57..f5842c07 100644 --- a/zh-cn/json-cn.html.markdown +++ b/zh-cn/json-cn.html.markdown @@ -8,24 +8,30 @@ filename: learnjson-cn.json lang: zh-cn --- -因为JSON是一个极其简单的数据交换格式,本教程最有可能成为有史以来最简单的 -Learn X in Y Minutes。 +JSON是一个极其简单的数据交换格式。按[json.org](https://json.org)说的,它对人类易读易写,对机器易解析易生成。 -纯正的JSON实际上没有注释,但是大多数解析器都 -接受C-风格(//, /\* \*/)的注释。为了兼容性,最好不要在其中写这样形式的注释。 +一段JSON可以是下文列出的类型的任意值,但实际一般按以下两种方式之一呈现: + +* 一个键值对的集合(`{ }`)。按不同语言,这可能被理解为对象/记录/结构体/字典/哈希表/有键列表/关联数组 +* 一个有序的值列表(`[ ]`)。按不同语言,这可能被理解为数组/向量/列表/序列 + +纯正的JSON实际上没有注释,但是大多数解析器都接受C-风格(//, /\* \*/)的注释。一些解析器还容许trailing comma,即最后一个数组元素或最后一个对象属性之后的逗号。不过为了兼容性最好避免。 因此,本教程的一切都会是100%有效的JSON。幸亏,它的表达能力很丰富。 支持的数据类型: -- 字符串: "hello", "\"A quote.\"", "\u0abe", "Newline.\n" -- 数字: 23, 0.11, 12e10, 3.141e-10, 1.23e+4 -- 对象: { "key": "value" } -- 数组: ["Values"] -- 其他: true, false, null +* 字符串:`"hello"`、`"\"A quote.\""`、`"\u0abe"`、`"Newline.\n"` +* 数字:`23`、`0.11`、`12e10`、`3.141e-10`、`1.23e+4` +* 对象:`{ "key": "value" }` +* 数组:`["Values"]` +* 其它:`true`、`false`、`null` ```json { + "key": "value", + + "keys": "must always be enclosed in double quotes", "numbers": 0, "strings": "Hellø, wørld. All unicode is allowed, along with \"escaping\".", "has bools?": true, @@ -55,6 +61,23 @@ Learn X in Y Minutes。 ] ], - "that was short": "And, you're done. You now know everything JSON has to offer." + "alternative style": { + "comment": "check this out!" + , "comma position": "doesn't matter, if it's before the next key, it's valid" + , "another comment": "how nice" + }, + + + + "whitespace": "Does not matter.", + + + + "that was short": "And done. You now know everything JSON has to offer." } ``` + +## 进一步阅读 + +* [JSON.org](https://www.json.org/json-zh.html) 完美图解JSON的一切 +* [JSON Tutorial](https://www.youtube.com/watch?v=wI1CWzNtE-M) 简要介绍 diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown index 6736dc2a..6fd10a32 100644 --- a/zh-cn/lua-cn.html.markdown +++ b/zh-cn/lua-cn.html.markdown @@ -391,7 +391,8 @@ dofile('mod2') --> Hi! (再次运行,与require不同) f = loadfile('mod2') -- Calling f() runs mod2.lua. -- loadstring是loadfile的字符串版本。 -g = loadstring('print(343)') --返回一个函数。 +-- (loadstring已弃用, 使用load代替) +g = load('print(343)') --返回一个函数。 g() -- 打印343; 在此之前什么也不打印。 --]] diff --git a/zh-cn/make-cn.html.markdown b/zh-cn/make-cn.html.markdown index 76dde941..641714ef 100644 --- a/zh-cn/make-cn.html.markdown +++ b/zh-cn/make-cn.html.markdown @@ -23,7 +23,7 @@ Makefile 用于定义如何创建目标文件, 比如如何从源码到可执行 ```make # 这行表示注释 -# 文件名一定要交 Makefile, 大小写区分, 使用 `make <target>` 生成 target +# 文件名一定要叫 Makefile, 大小写区分, 使用 `make <target>` 生成 target # 如果想要取别的名字, 可以用 `make -f "filename" <target>`. # 重要的事情 - 只认识 TAB, 空格是不认的, 但是在 GNU Make 3.82 之后, 可以通过 @@ -87,7 +87,7 @@ ex0.txt ex1.txt: maker maker: touch ex0.txt ex1.txt -# 如果定义的 phony target 与文件名重名, 可以用 .PHONY 显示的指明哪些 targets 是 phony +# 如果定义的 phony target 与文件名重名, 可以用 .PHONY 显式地指明哪些 targets 是 phony .PHONY: all maker process # This is a special target. There are several others. @@ -116,7 +116,7 @@ process: ex1.txt file0.txt # 模式匹配 #----------------------------------------------------------------------- -# 可以让 make 知道如何转换某些文件到别格式 +# 可以让 make 知道如何转换某些文件到其他格式 # 比如 从 svg 到 png %.png: %.svg inkscape --export-png $^ @@ -149,7 +149,7 @@ echo: @echo $(name) @echo ${name2} @echo $name # 这个会被蠢蠢的解析成 $(n)ame. - @echo \"$(name3)\" # 为声明的变量或扩展成空字符串. + @echo \"$(name3)\" # 未声明的变量会被处理成空字符串. @echo $(name4) @echo $(name5) # 你可以通过4种方式设置变量. diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 9b3d96ab..23f27dda 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -147,7 +147,6 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以 - 项目 - 项目 - 最后一个项目 - ``` 有序序列可由数字加上点 `.` 来实现 @@ -188,6 +187,7 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以 下面这个选择框将会是选中状态 - [x] 这个任务已经完成 ``` + - [ ] 你看完了这个任务(注:此选择框是无法直接更改的,即禁用状态。) ## 代码块 @@ -204,24 +204,25 @@ GitHub 也支持 Markdown,在 GitHub 的 Markdown 解析器中,我们可以 ```md my_array.each do |item| - puts item + puts item end ``` 内联代码可由反引号 ` 实现 ```md -John 甚至不知道 `go_to()` 方程是干嘛的! +John 甚至不知道 `go_to()` 函数是干嘛的! ``` 在GitHub的 Markdown(GitHub Flavored Markdown)解析器中,你可以使用特殊的语法表示代码块 -<pre> -<code class="highlight">```ruby +````md +```ruby def foobar - puts "Hello world!" + puts "Hello world!" end -```</code></pre> +``` +```` 以上代码不需要缩进,而且 GitHub 会根据\`\`\`后指定的语言来进行语法高亮显示 @@ -246,7 +247,6 @@ Markdown 最棒的地方就是便捷的书写链接。把链接文字放在中 ```md [点我点我!](http://test.com/) - ``` 你也可以在小括号内使用引号,为链接加上一个标题(title) @@ -345,6 +345,7 @@ Markdown同样支持引用形式的链接 | 我是左对齐 | 居个中 | 右对齐 | | 注意 | 冒 | 号 | ``` + 好吧,强行对齐字符是很难的。但是,至少比下面这种写法好一点—— ```md @@ -352,6 +353,7 @@ Markdown同样支持引用形式的链接 :-- | :-: | --: 这真的太丑了 | 药不能 | 停!!!! ``` + 真的是*看着令人头晕* diff --git a/zh-cn/matlab-cn.html.markdown b/zh-cn/matlab-cn.html.markdown index d215755c..bb1ab79a 100644 --- a/zh-cn/matlab-cn.html.markdown +++ b/zh-cn/matlab-cn.html.markdown @@ -1,504 +1,504 @@ ----
-language: Matlab
-filename: matlab-cn.m
-contributors:
- - ["mendozao", "http://github.com/mendozao"]
- - ["jamesscottbrown", "http://jamesscottbrown.com"]
-translators:
- - ["sunxb10", "https://github.com/sunxb10"]
-lang: zh-cn
-
----
-
-MATLAB 是 MATrix LABoratory(矩阵实验室)的缩写。
-它是一种功能强大的数值计算语言,在工程和数学领域中应用广泛。
-
-如果您有任何需要反馈或交流的内容,请联系本教程作者:
-[@the_ozzinator](https://twitter.com/the_ozzinator)
-或 [osvaldo.t.mendoza@gmail.com](mailto:osvaldo.t.mendoza@gmail.com)。
-
-```matlab
-% 以百分号作为注释符
-
-%{
-多行注释
-可以
-这样
-表示
-%}
-
-% 指令可以随意跨行,但需要在跨行处用 '...' 标明:
- a = 1 + 2 + ...
- + 4
-
-% 可以在MATLAB中直接向操作系统发出指令
-!ping google.com
-
-who % 显示内存中的所有变量
-whos % 显示内存中的所有变量以及它们的类型
-clear % 清除内存中的所有变量
-clear('A') % 清除指定的变量
-openvar('A') % 在变量编辑器中编辑指定变量
-
-clc % 清除命令窗口中显示的所有指令
-diary % 将命令窗口中的内容写入本地文件
-ctrl-c % 终止当前计算
-
-edit('myfunction.m') % 在编辑器中打开指定函数或脚本
-type('myfunction.m') % 在命令窗口中打印指定函数或脚本的源码
-
-profile on % 打开 profile 代码分析工具
-profile off % 关闭 profile 代码分析工具
-profile viewer % 查看 profile 代码分析工具的分析结果
-
-help command % 在命令窗口中显示指定命令的帮助文档
-doc command % 在帮助窗口中显示指定命令的帮助文档
-lookfor command % 在所有 MATLAB 内置函数的头部注释块的第一行中搜索指定命令
-lookfor command -all % 在所有 MATLAB 内置函数的整个头部注释块中搜索指定命令
-
-
-% 输出格式
-format short % 浮点数保留 4 位小数
-format long % 浮点数保留 15 位小数
-format bank % 金融格式,浮点数只保留 2 位小数
-fprintf('text') % 在命令窗口中显示 "text"
-disp('text') % 在命令窗口中显示 "text"
-
-
-% 变量与表达式
-myVariable = 4 % 命令窗口中将新创建的变量
-myVariable = 4; % 加上分号可使命令窗口中不显示当前语句执行结果
-4 + 6 % ans = 10
-8 * myVariable % ans = 32
-2 ^ 3 % ans = 8
-a = 2; b = 3;
-c = exp(a)*sin(pi/2) % c = 7.3891
-
-
-% 调用函数有两种方式:
-% 标准函数语法:
-load('myFile.mat', 'y') % 参数放在括号内,以英文逗号分隔
-% 指令语法:
-load myFile.mat y % 不加括号,以空格分隔参数
-% 注意在指令语法中参数不需要加引号:在这种语法下,所有输入参数都只能是文本文字,
-% 不能是变量的具体值,同样也不能是输出变量
-[V,D] = eig(A); % 这条函数调用无法转换成等价的指令语法
-[~,D] = eig(A); % 如果结果中只需要 D 而不需要 V 则可以这样写
-
-
-
-% 逻辑运算
-1 > 5 % 假,ans = 0
-10 >= 10 % 真,ans = 1
-3 ~= 4 % 不等于 -> ans = 1
-3 == 3 % 等于 -> ans = 1
-3 > 1 && 4 > 1 % 与 -> ans = 1
-3 > 1 || 4 > 1 % 或 -> ans = 1
-~1 % 非 -> ans = 0
-
-% 逻辑运算可直接应用于矩阵,运算结果也是矩阵
-A > 5
-% 对矩阵中每个元素做逻辑运算,若为真,则在运算结果的矩阵中对应位置的元素就是 1
-A( A > 5 )
-% 如此返回的向量,其元素就是 A 矩阵中所有逻辑运算为真的元素
-
-% 字符串
-a = 'MyString'
-length(a) % ans = 8
-a(2) % ans = y
-[a,a] % ans = MyStringMyString
-b = '字符串' % MATLAB目前已经可以支持包括中文在内的多种文字
-length(b) % ans = 3
-b(2) % ans = 符
-[b,b] % ans = 字符串字符串
-
-
-% 元组(cell 数组)
-a = {'one', 'two', 'three'}
-a(1) % ans = 'one' - 返回一个元组
-a{1} % ans = one - 返回一个字符串
-
-
-% 结构体
-A.b = {'one','two'};
-A.c = [1 2];
-A.d.e = false;
-
-
-% 向量
-x = [4 32 53 7 1]
-x(2) % ans = 32,MATLAB中向量的下标索引从1开始,不是0
-x(2:3) % ans = 32 53
-x(2:end) % ans = 32 53 7 1
-
-x = [4; 32; 53; 7; 1] % 列向量
-
-x = [1:10] % x = 1 2 3 4 5 6 7 8 9 10
-
-
-% 矩阵
-A = [1 2 3; 4 5 6; 7 8 9]
-% 以分号分隔不同的行,以空格或逗号分隔同一行中的不同元素
-% A =
-
-% 1 2 3
-% 4 5 6
-% 7 8 9
-
-A(2,3) % ans = 6,A(row, column)
-A(6) % ans = 8
-% (隐式地将 A 的三列首尾相接组成一个列向量,然后取其下标为 6 的元素)
-
-
-A(2,3) = 42 % 将第 2 行第 3 列的元素设为 42
-% A =
-
-% 1 2 3
-% 4 5 42
-% 7 8 9
-
-A(2:3,2:3) % 取原矩阵中的一块作为新矩阵
-%ans =
-
-% 5 42
-% 8 9
-
-A(:,1) % 第 1 列的所有元素
-%ans =
-
-% 1
-% 4
-% 7
-
-A(1,:) % 第 1 行的所有元素
-%ans =
-
-% 1 2 3
-
-[A ; A] % 将两个矩阵上下相接构成新矩阵
-%ans =
-
-% 1 2 3
-% 4 5 42
-% 7 8 9
-% 1 2 3
-% 4 5 42
-% 7 8 9
-
-% 等价于
-vertcat(A, A);
-
-
-[A , A] % 将两个矩阵左右相接构成新矩阵
-
-%ans =
-
-% 1 2 3 1 2 3
-% 4 5 42 4 5 42
-% 7 8 9 7 8 9
-
-% 等价于
-horzcat(A, A);
-
-
-A(:, [3 1 2]) % 重新排布原矩阵的各列
-%ans =
-
-% 3 1 2
-% 42 4 5
-% 9 7 8
-
-size(A) % 返回矩阵的行数和列数,ans = 3 3
-
-A(1, :) =[] % 删除矩阵的第 1 行
-A(:, 1) =[] % 删除矩阵的第 1 列
-
-transpose(A) % 矩阵(非共轭)转置,等价于 A.' (注意!有个点)
-ctranspose(A) % 矩阵的共轭转置(对矩阵中的每个元素取共轭复数),等价于 A'
-
-
-% 元素运算 vs. 矩阵运算
-% 单独运算符就是对矩阵整体进行矩阵运算
-% 在运算符加上英文句点就是对矩阵中的元素进行元素计算
-% 示例如下:
-A * B % 矩阵乘法,要求 A 的列数等于 B 的行数
-A .* B % 元素乘法,要求 A 和 B 形状一致,即两矩阵行列数完全一致
- % 元素乘法的结果是与 A 和 B 形状一致的矩阵
- % 其每个元素等于 A 对应位置的元素乘 B 对应位置的元素
-
-% 以下函数中,函数名以 m 结尾的执行矩阵运算,其余执行元素运算:
-exp(A) % 对矩阵中每个元素做指数运算
-expm(A) % 对矩阵整体做指数运算
-sqrt(A) % 对矩阵中每个元素做开方运算
-sqrtm(A) % 对矩阵整体做开方运算(即试图求出一个矩阵,该矩阵与自身的乘积等于 A 矩阵)
-
-
-% 绘图
-x = 0:0.1:2*pi; % 生成一向量,其元素从 0 开始,以 0.1 的间隔一直递增到 2*pi
- % 其中 pi 为圆周率
-y = sin(x);
-plot(x,y)
-xlabel('x axis')
-ylabel('y axis')
-title('Plot of y = sin(x)')
-axis([0 2*pi -1 1]) % x 轴范围是从 0 到 2*pi,y 轴范围是从 -1 到 1
-
-plot(x,y1,'-',x,y2,'--',x,y3,':') % 在同一张图中绘制多条曲线
-legend('Line 1 label', 'Line 2 label') % 为图片加注图例
-% 图例数量应当小于或等于实际绘制的曲线数目,从 plot 绘制的第一条曲线开始对应
-
-% 在同一张图上绘制多条曲线的另一种方法:
-% 使用 hold on,令系统保留前次绘图结果并在其上直接叠加新的曲线,
-% 如果没有 hold on,则每个 plot 都会首先清除之前的绘图结果再进行绘制。
-% 在 hold on 和 hold off 中可以放置任意多的 plot 指令,
-% 它们和 hold on 前最后一个 plot 指令的结果都将显示在同一张图中。
-plot(x, y1)
-hold on
-plot(x, y2)
-plot(x, y3)
-plot(x, y4)
-hold off
-
-loglog(x, y) % 对数—对数绘图
-semilogx(x, y) % 半对数(x 轴对数)绘图
-semilogy(x, y) % 半对数(y 轴对数)绘图
-
-fplot (@(x) x^2, [2,5]) % 绘制函数 x^2 在 [2, 5] 区间的曲线
-
-grid on % 在绘制的图中显示网格,使用 grid off 可取消网格显示
-axis square % 将当前坐标系设定为正方形(保证在图形显示上各轴等长)
-axis equal % 将当前坐标系设定为相等(保证在实际数值上各轴等长)
-
-scatter(x, y); % 散点图
-hist(x); % 直方图
-
-z = sin(x);
-plot3(x,y,z); % 绘制三维曲线
-
-pcolor(A) % 伪彩色图(热图)
-contour(A) % 等高线图
-mesh(A) % 网格曲面图
-
-h = figure % 创建新的图片对象并返回其句柄 h
-figure(h) % 将句柄 h 对应的图片作为当前图片
-close(h) % 关闭句柄 h 对应的图片
-close all % 关闭 MATLAB 中所用打开的图片
-close % 关闭当前图片
-
-shg % 显示图形窗口
-clf clear % 清除图形窗口中的图像,并重置图像属性
-
-% 图像属性可以通过图像句柄进行设定
-% 在创建图像时可以保存图像句柄以便于设置
-% 也可以用 gcf 函数返回当前图像的句柄
-h = plot(x, y); % 在创建图像时显式地保存图像句柄
-set(h, 'Color', 'r')
-% 颜色代码:
-% 'y' 黄色,'m' 洋红,'c' 青色
-% 'r' 红色,'g' 绿色,'b' 蓝色
-% 'w' 白色,'k' 黑色
-set(h, 'Color', [0.5, 0.5, 0.4])
-% 也可以使用 RGB 值指定颜色
-set(h, 'LineStyle', '--')
-% 线型代码:'--' 实线,'---' 虚线,':' 点线,'-.' 点划线,'none' 不划线
-get(h, 'LineStyle')
-% 获取当前句柄的线型
-
-
-% 用 gca 函数返回当前图像的坐标轴句柄
-set(gca, 'XDir', 'reverse'); % 令 x 轴反向
-
-% 用 subplot 指令创建平铺排列的多张子图
-subplot(2,3,1); % 选择 2 x 3 排列的子图中的第 1 张图
-plot(x1); title('First Plot') % 在选中的图中绘图
-subplot(2,3,2); % 选择 2 x 3 排列的子图中的第 2 张图
-plot(x2); title('Second Plot') % 在选中的图中绘图
-
-
-% 要调用函数或脚本,必须保证它们在你的当前工作目录中
-path % 显示当前工作目录
-addpath /path/to/dir % 将指定路径加入到当前工作目录中
-rmpath /path/to/dir % 将指定路径从当前工作目录中删除
-cd /path/to/move/into % 以制定路径作为当前工作目录
-
-
-% 变量可保存到 .mat 格式的本地文件
-save('myFileName.mat') % 保存当前工作空间中的所有变量
-load('myFileName.mat') % 将指定文件中的变量载入到当前工作空间
-
-
-% .m 脚本文件
-% 脚本文件是一个包含多条 MATLAB 指令的外部文件,以 .m 为后缀名
-% 使用脚本文件可以避免在命令窗口中重复输入冗长的指令
-
-
-% .m 函数文件
-% 与脚本文件类似,同样以 .m 作为后缀名
-% 但函数文件可以接受用户输入的参数并返回运算结果
-% 并且函数拥有自己的工作空间(变量域),不必担心变量名称冲突
-% 函数文件的名称应当与其所定义的函数的名称一致
-% 比如下面例子中函数文件就应命名为 double_input.m
-% 使用 'help double_input.m' 可返回函数定义中第一行注释信息
-function output = double_input(x)
- % double_input(x) 返回 x 的 2 倍
- output = 2*x;
-end
-double_input(6) % ans = 12
-
-
-% 同样还可以定义子函数和内嵌函数
-% 子函数与主函数放在同一个函数文件中,且只能被这个主函数调用
-% 内嵌函数放在另一个函数体内,可以直接访问被嵌套函数的各个变量
-
-
-% 使用匿名函数可以不必创建 .m 函数文件
-% 匿名函数适用于快速定义某函数以便传递给另一指令或函数(如绘图、积分、求根、求极值等)
-% 下面示例的匿名函数返回输入参数的平方根,可以使用句柄 sqr 进行调用:
-sqr = @(x) x.^2;
-sqr(10) % ans = 100
-doc function_handle % find out more
-
-
-% 接受用户输入
-a = input('Enter the value: ')
-
-
-% 从文件中读取数据
-fopen(filename)
-% 类似函数还有 xlsread(excel 文件)、importdata(CSV 文件)、imread(图像文件)
-
-
-% 输出
-disp(a) % 在命令窗口中打印变量 a 的值
-disp('Hello World') % 在命令窗口中打印字符串
-fprintf % 按照指定格式在命令窗口中打印内容
-
-% 条件语句(if 和 elseif 语句中的括号并非必需,但推荐加括号避免混淆)
-if (a > 15)
- disp('Greater than 15')
-elseif (a == 23)
- disp('a is 23')
-else
- disp('neither condition met')
-end
-
-% 循环语句
-% 注意:对向量或矩阵使用循环语句进行元素遍历的效率很低!!
-% 注意:只要有可能,就尽量使用向量或矩阵的整体运算取代逐元素循环遍历!!
-% MATLAB 在开发时对向量和矩阵运算做了专门优化,做向量和矩阵整体运算的效率高于循环语句
-for k = 1:5
- disp(k)
-end
-
-k = 0;
-while (k < 5)
- k = k + 1;
-end
-
-
-% 程序运行计时:'tic' 是计时开始,'toc' 是计时结束并打印结果
-tic
-A = rand(1000);
-A*A*A*A*A*A*A;
-toc
-
-
-% 链接 MySQL 数据库
-dbname = 'database_name';
-username = 'root';
-password = 'root';
-driver = 'com.mysql.jdbc.Driver';
-dburl = ['jdbc:mysql://localhost:8889/' dbname];
-javaclasspath('mysql-connector-java-5.1.xx-bin.jar'); % 此处 xx 代表具体版本号
-% 这里的 mysql-connector-java-5.1.xx-bin.jar 可从 http://dev.mysql.com/downloads/connector/j/ 下载
-conn = database(dbname, username, password, driver, dburl);
-sql = ['SELECT * from table_name where id = 22'] % SQL 语句
-a = fetch(conn, sql) % a 即包含所需数据
-
-
-% 常用数学函数
-sin(x)
-cos(x)
-tan(x)
-asin(x)
-acos(x)
-atan(x)
-exp(x)
-sqrt(x)
-log(x)
-log10(x)
-abs(x)
-min(x)
-max(x)
-ceil(x)
-floor(x)
-round(x)
-rem(x)
-rand % 均匀分布的伪随机浮点数
-randi % 均匀分布的伪随机整数
-randn % 正态分布的伪随机浮点数
-
-% 常用常数
-pi
-NaN
-inf
-
-% 求解矩阵方程(如果方程无解,则返回最小二乘近似解)
-% \ 操作符等价于 mldivide 函数,/ 操作符等价于 mrdivide 函数
-x=A\b % 求解 Ax=b,比先求逆再左乘 inv(A)*b 更加高效、准确
-x=b/A % 求解 xA=b
-
-inv(A) % 逆矩阵
-pinv(A) % 伪逆矩阵
-
-
-% 常用矩阵函数
-zeros(m, n) % m x n 阶矩阵,元素全为 0
-ones(m, n) % m x n 阶矩阵,元素全为 1
-diag(A) % 返回矩阵 A 的对角线元素
-diag(x) % 构造一个对角阵,对角线元素就是向量 x 的各元素
-eye(m, n) % m x n 阶单位矩阵
-linspace(x1, x2, n) % 返回介于 x1 和 x2 之间的 n 个等距节点
-inv(A) % 矩阵 A 的逆矩阵
-det(A) % 矩阵 A 的行列式
-eig(A) % 矩阵 A 的特征值和特征向量
-trace(A) % 矩阵 A 的迹(即对角线元素之和),等价于 sum(diag(A))
-isempty(A) % 测试 A 是否为空
-all(A) % 测试 A 中所有元素是否都非 0 或都为真(逻辑值)
-any(A) % 测试 A 中是否有元素非 0 或为真(逻辑值)
-isequal(A, B) % 测试 A 和 B是否相等
-numel(A) % 矩阵 A 的元素个数
-triu(x) % 返回 x 的上三角这部分
-tril(x) % 返回 x 的下三角这部分
-cross(A, B) % 返回 A 和 B 的叉积(矢量积、外积)
-dot(A, B) % 返回 A 和 B 的点积(数量积、内积),要求 A 和 B 必须等长
-transpose(A) % 矩阵(非共轭)转置,等价于 A.' (注意!有个点)
-fliplr(A) % 将一个矩阵左右翻转
-flipud(A) % 将一个矩阵上下翻转
-
-% 矩阵分解
-[L, U, P] = lu(A) % LU 分解:PA = LU,L 是下三角阵,U 是上三角阵,P 是置换阵
-[P, D] = eig(A) % 特征值分解:AP = PD
- % D 是由特征值构成的对角阵,P 的各列就是对应的特征向量
-[U, S, V] = svd(X) % 奇异值分解:XV = US
- % U 和 V 是酉矩阵,S 是由奇异值构成的半正定实数对角阵
-
-% 常用向量函数
-max % 最大值
-min % 最小值
-length % 元素个数
-sort % 按升序排列
-sum % 各元素之和
-prod % 各元素之积
-mode % 众数
-median % 中位数
-mean % 平均值
-std % 标准差
-perms(x) % x 元素的全排列
-
-```
-
-## 相关资料
-
-* 官方网页:[MATLAB - 技术计算语言 - MATLAB & Simulink](https://ww2.mathworks.cn/products/matlab.html)
-* 官方论坛:[MATLAB Answers - MATLAB Central](https://ww2.mathworks.cn/matlabcentral/answers/)
+--- +language: MATLAB +filename: matlab-cn.m +contributors: + - ["mendozao", "http://github.com/mendozao"] + - ["jamesscottbrown", "http://jamesscottbrown.com"] +translators: + - ["sunxb10", "https://github.com/sunxb10"] +lang: zh-cn + +--- + +MATLAB 是 MATrix LABoratory(矩阵实验室)的缩写。 +它是一种功能强大的数值计算语言,在工程和数学领域中应用广泛。 + +如果您有任何需要反馈或交流的内容,请联系本教程作者: +[@the_ozzinator](https://twitter.com/the_ozzinator) +或 [osvaldo.t.mendoza@gmail.com](mailto:osvaldo.t.mendoza@gmail.com)。 + +```matlab +% 以百分号作为注释符 + +%{ +多行注释 +可以 +这样 +表示 +%} + +% 指令可以随意跨行,但需要在跨行处用 '...' 标明: + a = 1 + 2 + ... + + 4 + +% 可以在MATLAB中直接向操作系统发出指令 +!ping google.com + +who % 显示内存中的所有变量 +whos % 显示内存中的所有变量以及它们的类型 +clear % 清除内存中的所有变量 +clear('A') % 清除指定的变量 +openvar('A') % 在变量编辑器中编辑指定变量 + +clc % 清除命令窗口中显示的所有指令 +diary % 将命令窗口中的内容写入本地文件 +ctrl-c % 终止当前计算 + +edit('myfunction.m') % 在编辑器中打开指定函数或脚本 +type('myfunction.m') % 在命令窗口中打印指定函数或脚本的源码 + +profile on % 打开 profile 代码分析工具 +profile off % 关闭 profile 代码分析工具 +profile viewer % 查看 profile 代码分析工具的分析结果 + +help command % 在命令窗口中显示指定命令的帮助文档 +doc command % 在帮助窗口中显示指定命令的帮助文档 +lookfor command % 在所有 MATLAB 内置函数的头部注释块的第一行中搜索指定命令 +lookfor command -all % 在所有 MATLAB 内置函数的整个头部注释块中搜索指定命令 + + +% 输出格式 +format short % 浮点数保留 4 位小数 +format long % 浮点数保留 15 位小数 +format bank % 金融格式,浮点数只保留 2 位小数 +fprintf('text') % 在命令窗口中显示 "text" +disp('text') % 在命令窗口中显示 "text" + + +% 变量与表达式 +myVariable = 4 % 命令窗口中将新创建的变量 +myVariable = 4; % 加上分号可使命令窗口中不显示当前语句执行结果 +4 + 6 % ans = 10 +8 * myVariable % ans = 32 +2 ^ 3 % ans = 8 +a = 2; b = 3; +c = exp(a)*sin(pi/2) % c = 7.3891 + + +% 调用函数有两种方式: +% 标准函数语法: +load('myFile.mat', 'y') % 参数放在括号内,以英文逗号分隔 +% 指令语法: +load myFile.mat y % 不加括号,以空格分隔参数 +% 注意在指令语法中参数不需要加引号:在这种语法下,所有输入参数都只能是文本文字, +% 不能是变量的具体值,同样也不能是输出变量 +[V,D] = eig(A); % 这条函数调用无法转换成等价的指令语法 +[~,D] = eig(A); % 如果结果中只需要 D 而不需要 V 则可以这样写 + + + +% 逻辑运算 +1 > 5 % 假,ans = 0 +10 >= 10 % 真,ans = 1 +3 ~= 4 % 不等于 -> ans = 1 +3 == 3 % 等于 -> ans = 1 +3 > 1 && 4 > 1 % 与 -> ans = 1 +3 > 1 || 4 > 1 % 或 -> ans = 1 +~1 % 非 -> ans = 0 + +% 逻辑运算可直接应用于矩阵,运算结果也是矩阵 +A > 5 +% 对矩阵中每个元素做逻辑运算,若为真,则在运算结果的矩阵中对应位置的元素就是 1 +A( A > 5 ) +% 如此返回的向量,其元素就是 A 矩阵中所有逻辑运算为真的元素 + +% 字符串 +a = 'MyString' +length(a) % ans = 8 +a(2) % ans = y +[a,a] % ans = MyStringMyString +b = '字符串' % MATLAB目前已经可以支持包括中文在内的多种文字 +length(b) % ans = 3 +b(2) % ans = 符 +[b,b] % ans = 字符串字符串 + + +% 元组(cell 数组) +a = {'one', 'two', 'three'} +a(1) % ans = 'one' - 返回一个元组 +a{1} % ans = one - 返回一个字符串 + + +% 结构体 +A.b = {'one','two'}; +A.c = [1 2]; +A.d.e = false; + + +% 向量 +x = [4 32 53 7 1] +x(2) % ans = 32,MATLAB中向量的下标索引从1开始,不是0 +x(2:3) % ans = 32 53 +x(2:end) % ans = 32 53 7 1 + +x = [4; 32; 53; 7; 1] % 列向量 + +x = [1:10] % x = 1 2 3 4 5 6 7 8 9 10 + + +% 矩阵 +A = [1 2 3; 4 5 6; 7 8 9] +% 以分号分隔不同的行,以空格或逗号分隔同一行中的不同元素 +% A = + +% 1 2 3 +% 4 5 6 +% 7 8 9 + +A(2,3) % ans = 6,A(row, column) +A(6) % ans = 8 +% (隐式地将 A 的三列首尾相接组成一个列向量,然后取其下标为 6 的元素) + + +A(2,3) = 42 % 将第 2 行第 3 列的元素设为 42 +% A = + +% 1 2 3 +% 4 5 42 +% 7 8 9 + +A(2:3,2:3) % 取原矩阵中的一块作为新矩阵 +%ans = + +% 5 42 +% 8 9 + +A(:,1) % 第 1 列的所有元素 +%ans = + +% 1 +% 4 +% 7 + +A(1,:) % 第 1 行的所有元素 +%ans = + +% 1 2 3 + +[A ; A] % 将两个矩阵上下相接构成新矩阵 +%ans = + +% 1 2 3 +% 4 5 42 +% 7 8 9 +% 1 2 3 +% 4 5 42 +% 7 8 9 + +% 等价于 +vertcat(A, A); + + +[A , A] % 将两个矩阵左右相接构成新矩阵 + +%ans = + +% 1 2 3 1 2 3 +% 4 5 42 4 5 42 +% 7 8 9 7 8 9 + +% 等价于 +horzcat(A, A); + + +A(:, [3 1 2]) % 重新排布原矩阵的各列 +%ans = + +% 3 1 2 +% 42 4 5 +% 9 7 8 + +size(A) % 返回矩阵的行数和列数,ans = 3 3 + +A(1, :) =[] % 删除矩阵的第 1 行 +A(:, 1) =[] % 删除矩阵的第 1 列 + +transpose(A) % 矩阵(非共轭)转置,等价于 A.' (注意!有个点) +ctranspose(A) % 矩阵的共轭转置(对矩阵中的每个元素取共轭复数),等价于 A' + + +% 元素运算 vs. 矩阵运算 +% 单独运算符就是对矩阵整体进行矩阵运算 +% 在运算符加上英文句点就是对矩阵中的元素进行元素计算 +% 示例如下: +A * B % 矩阵乘法,要求 A 的列数等于 B 的行数 +A .* B % 元素乘法,要求 A 和 B 形状一致,即两矩阵行列数完全一致 + % 元素乘法的结果是与 A 和 B 形状一致的矩阵 + % 其每个元素等于 A 对应位置的元素乘 B 对应位置的元素 + +% 以下函数中,函数名以 m 结尾的执行矩阵运算,其余执行元素运算: +exp(A) % 对矩阵中每个元素做指数运算 +expm(A) % 对矩阵整体做指数运算 +sqrt(A) % 对矩阵中每个元素做开方运算 +sqrtm(A) % 对矩阵整体做开方运算(即试图求出一个矩阵,该矩阵与自身的乘积等于 A 矩阵) + + +% 绘图 +x = 0:0.1:2*pi; % 生成一向量,其元素从 0 开始,以 0.1 的间隔一直递增到 2*pi + % 其中 pi 为圆周率 +y = sin(x); +plot(x,y) +xlabel('x axis') +ylabel('y axis') +title('Plot of y = sin(x)') +axis([0 2*pi -1 1]) % x 轴范围是从 0 到 2*pi,y 轴范围是从 -1 到 1 + +plot(x,y1,'-',x,y2,'--',x,y3,':') % 在同一张图中绘制多条曲线 +legend('Line 1 label', 'Line 2 label') % 为图片加注图例 +% 图例数量应当小于或等于实际绘制的曲线数目,从 plot 绘制的第一条曲线开始对应 + +% 在同一张图上绘制多条曲线的另一种方法: +% 使用 hold on,令系统保留前次绘图结果并在其上直接叠加新的曲线, +% 如果没有 hold on,则每个 plot 都会首先清除之前的绘图结果再进行绘制。 +% 在 hold on 和 hold off 中可以放置任意多的 plot 指令, +% 它们和 hold on 前最后一个 plot 指令的结果都将显示在同一张图中。 +plot(x, y1) +hold on +plot(x, y2) +plot(x, y3) +plot(x, y4) +hold off + +loglog(x, y) % 对数—对数绘图 +semilogx(x, y) % 半对数(x 轴对数)绘图 +semilogy(x, y) % 半对数(y 轴对数)绘图 + +fplot (@(x) x^2, [2,5]) % 绘制函数 x^2 在 [2, 5] 区间的曲线 + +grid on % 在绘制的图中显示网格,使用 grid off 可取消网格显示 +axis square % 将当前坐标系设定为正方形(保证在图形显示上各轴等长) +axis equal % 将当前坐标系设定为相等(保证在实际数值上各轴等长) + +scatter(x, y); % 散点图 +hist(x); % 直方图 + +z = sin(x); +plot3(x,y,z); % 绘制三维曲线 + +pcolor(A) % 伪彩色图(热图) +contour(A) % 等高线图 +mesh(A) % 网格曲面图 + +h = figure % 创建新的图片对象并返回其句柄 h +figure(h) % 将句柄 h 对应的图片作为当前图片 +close(h) % 关闭句柄 h 对应的图片 +close all % 关闭 MATLAB 中所用打开的图片 +close % 关闭当前图片 + +shg % 显示图形窗口 +clf clear % 清除图形窗口中的图像,并重置图像属性 + +% 图像属性可以通过图像句柄进行设定 +% 在创建图像时可以保存图像句柄以便于设置 +% 也可以用 gcf 函数返回当前图像的句柄 +h = plot(x, y); % 在创建图像时显式地保存图像句柄 +set(h, 'Color', 'r') +% 颜色代码: +% 'y' 黄色,'m' 洋红,'c' 青色 +% 'r' 红色,'g' 绿色,'b' 蓝色 +% 'w' 白色,'k' 黑色 +set(h, 'Color', [0.5, 0.5, 0.4]) +% 也可以使用 RGB 值指定颜色 +set(h, 'LineStyle', '--') +% 线型代码:'--' 实线,'---' 虚线,':' 点线,'-.' 点划线,'none' 不划线 +get(h, 'LineStyle') +% 获取当前句柄的线型 + + +% 用 gca 函数返回当前图像的坐标轴句柄 +set(gca, 'XDir', 'reverse'); % 令 x 轴反向 + +% 用 subplot 指令创建平铺排列的多张子图 +subplot(2,3,1); % 选择 2 x 3 排列的子图中的第 1 张图 +plot(x1); title('First Plot') % 在选中的图中绘图 +subplot(2,3,2); % 选择 2 x 3 排列的子图中的第 2 张图 +plot(x2); title('Second Plot') % 在选中的图中绘图 + + +% 要调用函数或脚本,必须保证它们在你的当前工作目录中 +path % 显示当前工作目录 +addpath /path/to/dir % 将指定路径加入到当前工作目录中 +rmpath /path/to/dir % 将指定路径从当前工作目录中删除 +cd /path/to/move/into % 以制定路径作为当前工作目录 + + +% 变量可保存到 .mat 格式的本地文件 +save('myFileName.mat') % 保存当前工作空间中的所有变量 +load('myFileName.mat') % 将指定文件中的变量载入到当前工作空间 + + +% .m 脚本文件 +% 脚本文件是一个包含多条 MATLAB 指令的外部文件,以 .m 为后缀名 +% 使用脚本文件可以避免在命令窗口中重复输入冗长的指令 + + +% .m 函数文件 +% 与脚本文件类似,同样以 .m 作为后缀名 +% 但函数文件可以接受用户输入的参数并返回运算结果 +% 并且函数拥有自己的工作空间(变量域),不必担心变量名称冲突 +% 函数文件的名称应当与其所定义的函数的名称一致 +% 比如下面例子中函数文件就应命名为 double_input.m +% 使用 'help double_input.m' 可返回函数定义中第一行注释信息 +function output = double_input(x) + % double_input(x) 返回 x 的 2 倍 + output = 2*x; +end +double_input(6) % ans = 12 + + +% 同样还可以定义子函数和内嵌函数 +% 子函数与主函数放在同一个函数文件中,且只能被这个主函数调用 +% 内嵌函数放在另一个函数体内,可以直接访问被嵌套函数的各个变量 + + +% 使用匿名函数可以不必创建 .m 函数文件 +% 匿名函数适用于快速定义某函数以便传递给另一指令或函数(如绘图、积分、求根、求极值等) +% 下面示例的匿名函数返回输入参数的平方根,可以使用句柄 sqr 进行调用: +sqr = @(x) x.^2; +sqr(10) % ans = 100 +doc function_handle % find out more + + +% 接受用户输入 +a = input('Enter the value: ') + + +% 从文件中读取数据 +fopen(filename) +% 类似函数还有 xlsread(excel 文件)、importdata(CSV 文件)、imread(图像文件) + + +% 输出 +disp(a) % 在命令窗口中打印变量 a 的值 +disp('Hello World') % 在命令窗口中打印字符串 +fprintf % 按照指定格式在命令窗口中打印内容 + +% 条件语句(if 和 elseif 语句中的括号并非必需,但推荐加括号避免混淆) +if (a > 15) + disp('Greater than 15') +elseif (a == 23) + disp('a is 23') +else + disp('neither condition met') +end + +% 循环语句 +% 注意:对向量或矩阵使用循环语句进行元素遍历的效率很低!! +% 注意:只要有可能,就尽量使用向量或矩阵的整体运算取代逐元素循环遍历!! +% MATLAB 在开发时对向量和矩阵运算做了专门优化,做向量和矩阵整体运算的效率高于循环语句 +for k = 1:5 + disp(k) +end + +k = 0; +while (k < 5) + k = k + 1; +end + + +% 程序运行计时:'tic' 是计时开始,'toc' 是计时结束并打印结果 +tic +A = rand(1000); +A*A*A*A*A*A*A; +toc + + +% 链接 MySQL 数据库 +dbname = 'database_name'; +username = 'root'; +password = 'root'; +driver = 'com.mysql.jdbc.Driver'; +dburl = ['jdbc:mysql://localhost:8889/' dbname]; +javaclasspath('mysql-connector-java-5.1.xx-bin.jar'); % 此处 xx 代表具体版本号 +% 这里的 mysql-connector-java-5.1.xx-bin.jar 可从 http://dev.mysql.com/downloads/connector/j/ 下载 +conn = database(dbname, username, password, driver, dburl); +sql = ['SELECT * from table_name where id = 22'] % SQL 语句 +a = fetch(conn, sql) % a 即包含所需数据 + + +% 常用数学函数 +sin(x) +cos(x) +tan(x) +asin(x) +acos(x) +atan(x) +exp(x) +sqrt(x) +log(x) +log10(x) +abs(x) +min(x) +max(x) +ceil(x) +floor(x) +round(x) +rem(x) +rand % 均匀分布的伪随机浮点数 +randi % 均匀分布的伪随机整数 +randn % 正态分布的伪随机浮点数 + +% 常用常数 +pi +NaN +inf + +% 求解矩阵方程(如果方程无解,则返回最小二乘近似解) +% \ 操作符等价于 mldivide 函数,/ 操作符等价于 mrdivide 函数 +x=A\b % 求解 Ax=b,比先求逆再左乘 inv(A)*b 更加高效、准确 +x=b/A % 求解 xA=b + +inv(A) % 逆矩阵 +pinv(A) % 伪逆矩阵 + + +% 常用矩阵函数 +zeros(m, n) % m x n 阶矩阵,元素全为 0 +ones(m, n) % m x n 阶矩阵,元素全为 1 +diag(A) % 返回矩阵 A 的对角线元素 +diag(x) % 构造一个对角阵,对角线元素就是向量 x 的各元素 +eye(m, n) % m x n 阶单位矩阵 +linspace(x1, x2, n) % 返回介于 x1 和 x2 之间的 n 个等距节点 +inv(A) % 矩阵 A 的逆矩阵 +det(A) % 矩阵 A 的行列式 +eig(A) % 矩阵 A 的特征值和特征向量 +trace(A) % 矩阵 A 的迹(即对角线元素之和),等价于 sum(diag(A)) +isempty(A) % 测试 A 是否为空 +all(A) % 测试 A 中所有元素是否都非 0 或都为真(逻辑值) +any(A) % 测试 A 中是否有元素非 0 或为真(逻辑值) +isequal(A, B) % 测试 A 和 B是否相等 +numel(A) % 矩阵 A 的元素个数 +triu(x) % 返回 x 的上三角这部分 +tril(x) % 返回 x 的下三角这部分 +cross(A, B) % 返回 A 和 B 的叉积(矢量积、外积) +dot(A, B) % 返回 A 和 B 的点积(数量积、内积),要求 A 和 B 必须等长 +transpose(A) % 矩阵(非共轭)转置,等价于 A.' (注意!有个点) +fliplr(A) % 将一个矩阵左右翻转 +flipud(A) % 将一个矩阵上下翻转 + +% 矩阵分解 +[L, U, P] = lu(A) % LU 分解:PA = LU,L 是下三角阵,U 是上三角阵,P 是置换阵 +[P, D] = eig(A) % 特征值分解:AP = PD + % D 是由特征值构成的对角阵,P 的各列就是对应的特征向量 +[U, S, V] = svd(X) % 奇异值分解:XV = US + % U 和 V 是酉矩阵,S 是由奇异值构成的半正定实数对角阵 + +% 常用向量函数 +max % 最大值 +min % 最小值 +length % 元素个数 +sort % 按升序排列 +sum % 各元素之和 +prod % 各元素之积 +mode % 众数 +median % 中位数 +mean % 平均值 +std % 标准差 +perms(x) % x 元素的全排列 + +``` + +## 相关资料 + +* 官方网页:[MATLAB - 技术计算语言 - MATLAB & Simulink](https://ww2.mathworks.cn/products/matlab.html) +* 官方论坛:[MATLAB Answers - MATLAB Central](https://ww2.mathworks.cn/matlabcentral/answers/) diff --git a/zh-cn/mips-cn.html.markdown b/zh-cn/mips-cn.html.markdown new file mode 100644 index 00000000..4f9ea7da --- /dev/null +++ b/zh-cn/mips-cn.html.markdown @@ -0,0 +1,334 @@ +--- +language: "MIPS Assembly" +filename: MIPS-cn.asm +contributors: + - ["Stanley Lim", "https://github.com/Spiderpig86"] +translators: + - ["Liu Yihua", "https://github.com/yihuajack"] +lang: zh-cn +--- + +MIPS(Microprocessor without Interlocked Pipeline Stages)汇编语言是为了配合约翰·雷洛伊·亨尼西于1981年设计的 MIPS 微处理器范式而设计的,这些 RISC 处理器用于嵌入式系统,例如网关和路由器。 + +[阅读更多](https://en.wikipedia.org/wiki/MIPS_architecture) + +```asm +# 注释用一个 '#' 表示 + +# 一行中 '#' 之后的所有文本都会被汇编器的词法分析器忽略 + +# 程序通常包含 .data 和 .text 部分 + +.data # 数据存储在内存中(在RAM中分配) + # 类似于高级语言中的变量 + + # 声明遵循( 标签: .类型 值 )的声明形式 + hello_world: .asciiz "Hello World\n" # 声明一个 null 结束的字符串 + num1: .word 42 # 整数被视为字 + # (32位值) + + arr1: .word 1, 2, 3, 4, 5 # 字数组 + arr2: .byte 'a', 'b' # 字符数组(每个1字节) + buffer: .space 60 # 在 RAM 中分配空间 + # (不清除为0) + + # 数据类型的大小 + _byte: .byte 'a' # 1字节 + _halfword: .half 53 # 2字节 + _word: .word 3 # 4字节 + _float: .float 3.14 # 4字节 + _double: .double 7.0 # 8字节 + + .align 2 # 数据的内存对齐 + # 其中数字(应是2的幂)表示几字节对齐 + # .align 2 表示字对齐(因为 2^2 = 4 字节) + +.text # 这部分包括指令和程序逻辑 +.globl _main # 声明一个全局指令标签 + # 其他文件都可以访问 + + _main: # MIPS 程序按顺序执行指令 + # 这条标签下的代码将首先执行 + + # 打印 "hello world" + la $a0, hello_world # 加载存储在内存中的字符串地址 + li $v0, 4 # 加载 syscall 的值 + # (数字代表要执行哪个 syscall) + syscall # 使用给定的参数($a0)执行指定的 syscall + + # 寄存器(用于在程序执行期间保存数据) + # $t0 - $t9 # 临时寄存器,用于过程内部的中间计算 + # (过程调用时不保存) + + # $s0 - $s7 # 保留寄存器(被保留的寄存器,过程调用时保存) + # 通常保存在栈中 + + # $a0 - $a3 # 参数寄存器,用于传递过程的参数 + # $v0 - $v1 # 返回寄存器,用于向调用过程返回值 + + # 存取指令 + la $t0, label # 将内存中由 label 指定的值的地址复制到寄存器 $t0 中 + lw $t0, label # 从内存中复制一个字 + lw $t1, 4($s0) # 从寄存器中存储的地址复制一个字 + # 偏移量为4字节(地址 + 4) + lb $t2, label # 把一个字节复制到寄存器 $t2 的低阶部分 + lb $t2, 0($s0) # 从 $s0 的源地址复制一个字节 + # 偏移量为0 + # 同理也适用于 'lh' (取半字) + + sw $t0, label # 将字存储到由 label 映射的内存地址中 + sw $t0, 8($s0) # 将字存储到 $s0 指定的地址中 + # 偏移量为8字节 + # 同理也适用于 'sb' (存字)和 'sh' (存半字)。'sa'不存在 + +### 数学 ### + _math: + # 记住要将值加载到寄存器中 + lw $t0, num # 从数据部分 + li $t0, 5 # 或者从一个立即数(常数) + li $t1, 6 + add $t2, $t0, $t1 # $t2 = $t0 + $t1 + sub $t2, $t0, $t1 # $t2 = $t0 - $t1 + mul $t2, $t0, $t1 # $t2 = $t0 * $t1 + div $t2, $t0, $t1 # $t2 = $t0 / $t1 + # (MARS 的某些版本可能不支持) + div $t0, $t1 # 执行 $t0 / $t1。 + # 用 'mflo' 得商,用 'mfhi' 得余数 + + # 移位 + sll $t0, $t0, 2 # 按位左移立即数(常数值)2 + sllv $t0, $t1, $t2 # 根据一个寄存器中的变量值左移相应位 + srl $t0, $t0, 5 # 按位右移 + # (不保留符号,用0符号扩展) + srlv $t0, $t1, $t2 # 根据一个寄存器中的变量值右移相应位 + sra $t0, $t0, 7 # 按算术位右移(保留符号) + srav $t0, $t1, $t2 # 根据一个寄存器中的变量值右移相应算数位 + + # 按位运算符 + and $t0, $t1, $t2 # 按位与 + andi $t0, $t1, 0xFFF # 用立即数按位与 + or $t0, $t1, $t2 # 按位或 + ori $t0, $t1, 0xFFF # 用立即数按位或 + xor $t0, $t1, $t2 # 按位异或 + xori $t0, $t1, 0xFFF # 用立即数按位异或 + nor $t0, $t1, $t2 # 按位或非 + +## 分支 ## + _branching: + # 分支指令的基本格式通常遵循 <指令> <寄存器1> <寄存器2> <标签> + # 如果给定的条件求值为真,则跳转到标签 + # 有时向后编写条件逻辑更容易,如下面的简单的 if 语句示例所示 + + beq $t0, $t1, reg_eq # 如果 $t0 == $t1,则跳转到 reg_eq + # 否则执行下一行 + bne $t0, $t1, reg_neq # 当 $t0 != $t1 时跳转 + b branch_target # 非条件分支,总会执行 + beqz $t0, req_eq_zero # 当 $t0 == 0 时跳转 + bnez $t0, req_neq_zero # 当 $t0 != 0 时跳转 + bgt $t0, $t1, t0_gt_t1 # 当 $t0 > $t1 时跳转 + bge $t0, $t1, t0_gte_t1 # 当 $t0 >= $t1 时跳转 + bgtz $t0, t0_gt0 # 当 $t0 > 0 时跳转 + blt $t0, $t1, t0_gt_t1 # 当 $t0 < $t1 时跳转 + ble $t0, $t1, t0_gte_t1 # 当 $t0 <= $t1 时跳转 + bltz $t0, t0_lt0 # 当 $t0 < 0 时跳转 + slt $s0, $t0, $t1 # 当 $t0 < $t1 时结果为 $s0 (1为真) + + # 简单的 if 语句 + # if (i == j) + # f = g + h; + # f = f - i; + + # 让 $s0 = f, $s1 = g, $s2 = h, $s3 = i, $s4 = j + bne $s3, $s4, L1 # if (i !=j) + add $s0, $s1, $s2 # f = g + h + + L1: + sub $s0, $s0, $s3 # f = f - i + + # 下面是一个求3个数的最大值的例子 + # 从 Java 到 MIPS 逻辑的直接翻译: + # if (a > b) + # if (a > c) + # max = a; + # else + # max = c; + # else + # max = b; + # else + # max = c; + + # 让 $s0 = a, $s1 = b, $s2 = c, $v0 = 返回寄存器 + ble $s0, $s1, a_LTE_b # 如果 (a <= b) 跳转到 (a_LTE_b) + ble $s0, $s2, max_C # 如果 (a > b && a <= c) 跳转到 (max_C) + move $v0, $s0 # 否则 [a > b && a > c] max = a + j done # 跳转到程序结束 + + a_LTE_b: # 当 a <= b 时的标签 + ble $s1, $s2, max_C # 如果 (a <= b && b <= c) 跳转到 (max_C) + move $v0, $s1 # 如果 (a <= b && b > c) max = b + j done # 跳转到 done + + max_C: + move $v0, $s2 # max = c + + done: # 程序结束 + +## 循环 ## + _loops: + # 循环的基本结构是一个退出条件和一个继续执行的跳转指令 + li $t0, 0 + while: + bgt $t0, 10, end_while # 当 $t0 小于 10,不停迭代 + addi $t0, $t0, 1 # 累加值 + j while # 跳转回循环开始 + end_while: + + # 二维矩阵遍历 + # 假设 $a0 存储整数 3 × 3 矩阵的地址 + li $t0, 0 # 计数器 i + li $t1, 0 # 计数器 j + matrix_row: + bgt $t0, 3, matrix_row_end + + matrix_col: + bgt $t1, 3, matrix_col_end + + # 执行一些东西 + + addi $t1, $t1, 1 # 累加列计数器 + matrix_col_end: + + # 执行一些东西 + + addi $t0, $t0, 1 + matrix_row_end: + +## 函数 ## + _functions: + # 函数是可调用的过程,可以接受参数并返回所有用标签表示的值,如前所示 + + main: # 程序以 main 函数开始 + jal return_1 # jal 会把当前程序计数器(PC)存储在 $ra + # 并跳转到 return_1 + + # 如果我们想传入参数呢? + # 首先,我们必须将形参传递给参数寄存器 + li $a0, 1 + li $a1, 2 + jal sum # 现在我们可以调用函数了 + + # 递归怎么样? + # 这需要更多的工作 + # 由于 jal 会自动覆盖每次调用,我们需要确保在 $ra 中保存并恢复之前的程序计数器 + li $a0, 3 + jal fact + + li $v0, 10 + syscall + + # 这个函数返回1 + return_1: + li $v0, 1 # 将值取到返回寄存器 $v0 中 + jr $ra # 跳转回原先的程序计数器继续执行 + + + # 有2个参数的函数 + sum: + add $v0, $a0, $a1 + jr $ra # 返回 + + # 求阶乘的递归函数 + fact: + addi $sp, $sp, -8 # 在栈中分配空间 + sw $s0, ($sp) # 存储保存当前数字的寄存器 + sw $ra, 4($sp) # 存储先前的程序计数器 + + li $v0, 1 # 初始化返回值 + beq $a0, 0, fact_done # 如果参数为0则完成 + + # 否则继续递归 + move $s0, $a0 # 复制 $a0 到 $s0 + sub $a0, $a0, 1 + jal fact + + mul $v0, $s0, $v0 # 做乘法 + + fact_done: + lw $s0, ($sp) + lw $ra, ($sp) # 恢复程序计数器 + addi $sp, $sp, 8 + + jr $ra + +## 宏 ## + _macros: + # 宏可以实现用单个标签替换重复的代码块,这可以增强程序的可读性 + # 它们绝不是函数的替代品 + # 它们必须在使用之前声明 + + # 用于打印换行符的宏(这可以被多次重用) + .macro println() + la $a0, newline # 存储在这里的新行字符串 + li $v0, 4 + syscall + .end_macro + + println() # 汇编器会在运行前复制此代码块 + + # 参数可以通过宏传入。 + # 它们由 '%' 符号表示,可以选择起任意名字 + .macro print_int(%num) + li $v0, 1 + lw $a0, %num + syscall + .end_macro + + li $t0, 1 + print_int($t0) + + # 我们也可以给宏传递立即数 + .macro immediates(%a, %b) + add $t0, %a, %b + .end_macro + + immediates(3, 5) + + # 以及标签 + .macro print(%string) + la $a0, %string + li $v0, 4 + syscall + .end_macro + + print(hello_world) + +## 数组 ## +.data + list: .word 3, 0, 1, 2, 6 # 这是一个字数组 + char_arr: .asciiz "hello" # 这是一个字符数组 + buffer: .space 128 # 在内存中分配块,不会自动清除 + # 这些内存块彼此对齐 + +.text + la $s0, list # 取 list 的地址 + li $t0, 0 # 计数器 + li $t1, 5 # list 的长度 + + loop: + bgt $t0, $t1, end_loop + + lw $a0, ($s0) + li $v0, 1 + syscall # 打印数字 + + addi $s0, $s0, 4 # 字的大小为4字节 + addi $t0, $t0, 1 # 累加 + j loop + end_loop: + +## INCLUDE ## +# 使用 include 语句可以将外部文件导入到程序中 +# (它只是将文件中的代码放入 include 语句的位置) +.include "somefile.asm" + +``` diff --git a/zh-cn/nim-cn.html.markdown b/zh-cn/nim-cn.html.markdown new file mode 100644 index 00000000..fa7d8259 --- /dev/null +++ b/zh-cn/nim-cn.html.markdown @@ -0,0 +1,283 @@ +--- +language: Nim +filename: learnNim-cn.nim +contributors: + - ["Jason J. Ayala P.", "http://JasonAyala.com"] + - ["Dennis Felsing", "https://dennis.felsing.org"] +translators: + - ["lzw-723", "https://github.com/lzw-723"] +lang: zh-cn +--- + +Nim(原名Nimrod)是一种静态类型的命令式编程语言, +它能在不影响运行时效率的情况下为程序员提供强大的功能。 + +Nim语言高效、有表现力、优雅。 + +```nim +# 单行注释以一个#开头 + +#[ + 这是多行注释 + 在Nim语言中,多行注释可以嵌套,以#[开头,以]#结尾 +]# + +discard """ +这也可以作为多行注释使用。 +或者用于无法解析、损坏的代码 +""" + +var # 声明(和赋值)变量 + letter: char = 'n' # 带或不带类型批注 + lang = "N" & "im" + nLength: int = len(lang) + boat: float + truth: bool = false + + let # 使用let*一次性*声明和绑定变量。 + legs = 400 # legs是不可改变的。 + arms = 2_000 # _会被忽略,对long类型非常有用。 + aboutPi = 3.15 + +const # 常量在编译时计算。这确保了 + debug = true # 性能,在编译时表达式中很有用。 + compileBadCode = false + +when compileBadCode: # `when`是编译时的`if` + legs = legs + 1 # 这个错误永远不会被编译。 + const input = readline(stdin) # const在编译时必须是已知的。 + +discard 1 > 2 # 注意:如果表达式的结果未使用, + # 编译器会发出警告。`discard`绕过了这一点。 + + +# +# 数据结构 +# + +# 元组(Tuple) + +var + child: tuple[name: string, age: int] # 元组有*字段名* + today: tuple[sun: string, temp: float] # 和*顺序* + + +child = (name: "Rudiger", age: 2) # 使用字面值()一次性赋值全部 +today.sun = "Overcast" # 也可以单独赋值 +today.temp = 70.1 + +# 序列(Sequence) + +var + drinks: seq[string] + +drinks = @["Water", "Juice", "Chocolate"] # @[V1,..,Vn] 是序列的字面值 + +drinks.add("Milk") + +if "Milk" in drinks: + echo "We have Milk and ", drinks.len - 1, " other drinks" + +let myDrink = drinks[2] + +# +# 自定义类型 +# + +# 定义你自己的类型使得编译器为你工作。 +# 这使得静态类型变得强大和有用。 + +type + Name = string # 类型别名为你提供一个新类型, + Age = int # 该类型可与旧类型互换,但更具描述性。 + Person = tuple[name: Name, age: Age] # 也可以定义数据结构。 + AnotherSyntax = tuple + fieldOne: string + secondField: int + +var + john: Person = (name: "John B.", age: 17) + newage: int = 18 # 在这里使用Age比int要好 + +john.age = newage # 仍然有效,因为int和Age同义 + +type + Cash = distinct int # `distinct`使一个新类型与它的基本类型不兼容。 + Desc = distinct string + +var + money: Cash = 100.Cash # `.Cash`把int转换成我们的类型 + description: Desc = "Interesting".Desc + +when compileBadCode: + john.age = money # 错误!age是int类型、money是Cash类型 + john.name = description # 编译器说:“没门!” + +# +# 更多类型和数据结构 +# + +# 枚举类型只能具有有限数量的值之一 + +type + Color = enum cRed, cBlue, cGreen + Direction = enum # 可选格式 + dNorth + dWest + dEast + dSouth +var + orient = dNorth # `orient`的类型是Direction,值是`dNorth` + pixel = cGreen # `pixel`的类型是Color,值是`cGreen` + +discard dNorth > dEast # Enum通常是“序数”类型 + +# 子范围指定有限的有效范围 + +type + DieFaces = range[1..20] # 只有从1到20的int才是有效值 +var + my_roll: DieFaces = 13 + +when compileBadCode: + my_roll = 23 # 错误! + +# 数组(Array) + +type + RollCounter = array[DieFaces, int] # 数组长度固定 + DirNames = array[Direction, string] # 以任意有序类型索引 + Truths = array[42..44, bool] +var + counter: RollCounter + directions: DirNames + possible: Truths + +possible = [false, false, false] # 数组字面以[V1,..,Vn]表示 +possible[42] = true + +directions[dNorth] = "Ahh. The Great White North!" +directions[dWest] = "No, don't go there." + +my_roll = 13 +counter[my_roll] += 1 +counter[my_roll] += 1 + +var anotherArray = ["Default index", "starts at", "0"] + +# 可用的数据结构包括表、集合、列表、队列、压缩前缀树。 +# http://nim-lang.org/docs/lib.html#collections-and-algorithms + +# +# IO和控制流 +# + +# `case`, `readLine()` + +echo "Read any good books lately?" +case readLine(stdin) +of "no", "No": + echo "Go to your local library." +of "yes", "Yes": + echo "Carry on, then." +else: + echo "That's great; I assume." + +# `while`, `if`, `continue`, `break` + +import strutils as str # http://nim-lang.org/docs/strutils.html +echo "I'm thinking of a number between 41 and 43. Guess which!" +let number: int = 42 +var + raw_guess: string + guess: int +while guess != number: + raw_guess = readLine(stdin) + if raw_guess == "": continue # 跳出循环 + guess = str.parseInt(raw_guess) + if guess == 1001: + echo("AAAAAAGGG!") + break + elif guess > number: + echo("Nope. Too high.") + elif guess < number: + echo(guess, " is too low") + else: + echo("Yeeeeeehaw!") + +# +# 循环(Iteration) +# + +for i, elem in ["Yes", "No", "Maybe so"]: # 也可以是`for elem in` + echo(elem, " is at index: ", i) + +for k, v in items(@[(person: "You", power: 100), (person: "Me", power: 9000)]): + echo v + +let myString = """ +an <example> +`string` to +play with +""" # 多行字符串 + +for line in splitLines(myString): + echo(line) + +for i, c in myString: # 索引和字符。或使用'for j in'只有字符 + if i mod 2 == 0: continue # 紧凑的'if'形式 + elif c == 'X': break + else: echo(c) + +# +# 过程(Procedure) +# + +type Answer = enum aYes, aNo + +proc ask(question: string): Answer = + echo(question, " (y/n)") + while true: + case readLine(stdin) + of "y", "Y", "yes", "Yes": + return Answer.aYes # 枚举类型可以 + of "n", "N", "no", "No": + return Answer.aNo + else: echo("Please be clear: yes or no") + +proc addSugar(amount: int = 2) = # amount默认是2,不返回任何值 + assert(amount > 0 and amount < 9000, "Crazy Sugar") + for a in 1..amount: + echo(a, " sugar...") + +case ask("Would you like sugar in your tea?") +of aYes: + addSugar(3) +of aNo: + echo "Oh do take a little!" + addSugar() +# 这里不需要使用`else` 。只能是`yes`和`no`。 + +# +# 外部函数接口(FFI) +# + +# 因为Nim可以编译为C,使用外部函数接口(FFI)很简单: + +proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.} + +let cmp = strcmp("C?", "Easy!") +``` + +除此以外,Nim通过元编程、性能和编译时特性将自己与其他同类分离开来。 + +## 进阶阅读 + +* [主页](http://nim-lang.org) +* [下载](http://nim-lang.org/download.html) +* [社区](http://nim-lang.org/community.html) +* [常见问题](http://nim-lang.org/question.html) +* [文档](http://nim-lang.org/documentation.html) +* [参考手册](http://nim-lang.org/docs/manual.html) +* [标准库](http://nim-lang.org/docs/lib.html) +* [Rosetta Code](http://rosettacode.org/wiki/Category:Nim) diff --git a/zh-cn/opencv-cn.html.markdown b/zh-cn/opencv-cn.html.markdown new file mode 100644 index 00000000..06b997d5 --- /dev/null +++ b/zh-cn/opencv-cn.html.markdown @@ -0,0 +1,145 @@ +--- +category: tool +tool: OpenCV +filename: learnopencv.py +contributors: + - ["Yogesh Ojha", "http://github.com/yogeshojha"] +translators: + - ["GengchenXU", "https://github.com/GengchenXU"] +lang: zh-cn +--- +### Opencv + +Opencv(开源计算机视觉)是一个编程功能库,主要面向实时计算机视觉。最初由英特尔开发,后来由Willow Garage,然后Itseez(后来被英特尔收购)支持。Opencv 目前支持多种语言,如C++、Python、Java 等 + +#### 安装 +有关在计算机上安装 OpenCV,请参阅这些文章。 + +* Windows 安装说明: [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows]() +* Mac 安装说明 (High Sierra): [https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a]() +* Linux 安装说明 (Ubuntu 18.04): [https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv]() + +### 在这里,我们将专注于 OpenCV 的 python 实现 + +```python +# OpenCV读取图片 +import cv2 +img = cv2.imread('cat.jpg') + +# 显示图片 +# imshow() 函数被用来显示图片 +cv2.imshow('Image',img) +# 第一个参数是窗口的标题,第二个参数是image +# 如果你得到错误,对象类型为None,你的图像路径可能是错误的。请重新检查图像包 +cv2.waitKey(0) +# waitKey() 是一个键盘绑定函数,参数以毫秒为单位。对于GUI事件,必须使用waitKey()函数。 + +# 保存图片 +cv2.imwrite('catgray.png',img) +# 第一个参数是文件名,第二个参数是图像 + +# 转换图像灰度 +gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + +# 从摄像头捕捉视频 +cap = cv2.VideoCapture(0) +#0 是你的相机,如果你有多台相机,你需要输入他们的id +while(True): + # 一帧一帧地获取 + _, frame = cap.read() + cv2.imshow('Frame',frame) + # 当用户按下q ->退出 + if cv2.waitKey(1) & 0xFF == ord('q'): + break +# 相机必须释放 +cap.release() + +# 在文件中播放视频 +cap = cv2.VideoCapture('movie.mp4') +while(cap.isOpened()): + _, frame = cap.read() + # 灰度播放视频 + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + cv2.imshow('frame',gray) + if cv2.waitKey(1) & 0xFF == ord('q'): + break +cap.release() + +# 在OpenCV中画线 +# cv2.line(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness)(注 color颜色rgb参数 thickness粗细) +cv2.line(img,(0,0),(511,511),(255,0,0),5) + +# 画矩形 +# cv2.rectangle(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness) +# 粗细= -1用于填充矩形 +cv2.rectangle(img,(384,0),(510,128),(0,255,0),3) + +# 画圆 +cv2.circle(img,(xCenter,yCenter), radius, (color->r,g,b->0 to 255), thickness) +cv2.circle(img,(200,90), 100, (0,0,255), -1) + +# 画椭圆 +cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1) + +# 在图像上增加文字 +cv2.putText(img,"Hello World!!!", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 2, 255) + +# 合成图像 +img1 = cv2.imread('cat.png') +img2 = cv2.imread('openCV.jpg') +dst = cv2.addWeighted(img1,0.5,img2,0.5,0) + +# 阈值图像 +# 二进制阈值 +_,thresImg = cv2.threshold(img,127,255,cv2.THRESH_BINARY) +# Adaptive Thresholding +adapThres = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2) + +# 模糊的形象 +# 高斯模糊 +blur = cv2.GaussianBlur(img,(5,5),0) +# 模糊中值 +medianBlur = cv2.medianBlur(img,5) + +# Canny 边缘检测 +img = cv2.imread('cat.jpg',0) +edges = cv2.Canny(img,100,200) + +# 用Haar Cascades进行人脸检测 +# 下载 Haar Cascades 在 https://github.com/opencv/opencv/blob/master/data/haarcascades/ +import cv2 +import numpy as np +face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') +eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') + +img = cv2.imread('human.jpg') +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + +aces = face_cascade.detectMultiScale(gray, 1.3, 5) +for (x,y,w,h) in faces: + cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) + roi_gray = gray[y:y+h, x:x+w] + roi_color = img[y:y+h, x:x+w] + eyes = eye_cascade.detectMultiScale(roi_gray) + for (ex,ey,ew,eh) in eyes: + cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) + +cv2.imshow('img',img) +cv2.waitKey(0) + +cv2.destroyAllWindows() +# destroyAllWindows() destroys all windows. +# 如果您希望销毁特定窗口,请传递您创建的窗口的确切名称。 +``` + +### 进一步阅读: + +* Download Cascade from [https://github.com/opencv/opencv/blob/master/data/haarcascades]() +* OpenCV 绘图函数 [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html]() +* 最新的语言参考 [https://opencv.org]() +* 更多的资源 [https://en.wikipedia.org/wiki/OpenCV]() +* 优秀的的 OpenCV 教程 + * [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html]() + * [https://realpython.com/python-opencv-color-spaces]() + * [https://pyimagesearch.com]() + * [https://www.learnopencv.com]() diff --git a/zh-cn/perl-cn.html.markdown b/zh-cn/perl-cn.html.markdown index 5b0d6179..46c54618 100644 --- a/zh-cn/perl-cn.html.markdown +++ b/zh-cn/perl-cn.html.markdown @@ -10,9 +10,9 @@ translators: lang: zh-cn --- -Perl 5是一个功能强大、特性齐全的编程语言,有25年的历史。 +Perl 是一个功能强大、特性齐全的编程语言,有25年的历史。 -Perl 5可以在包括便携式设备和大型机的超过100个平台上运行,既适用于快速原型构建,也适用于大型项目开发。 +Perl 可以在包括便携式设备和大型机的超过100个平台上运行,既适用于快速原型构建,也适用于大型项目开发。 ```perl # 单行注释以#号开头 @@ -146,7 +146,7 @@ perlfaq有很多常见问题和相应回答,也经常有对优秀CPAN模块的 #### 深入阅读 - - [perl-tutorial](http://perl-tutorial.org/) - - [www.perl.com的learn站点](http://www.perl.org/learn.html) - - [perldoc](http://perldoc.perl.org/) - - 以及 perl 内置的: `perldoc perlintro` +- [perl-tutorial](http://perl-tutorial.org/) +- [www.perl.com的learn站点](http://www.perl.org/learn.html) +- [perldoc](http://perldoc.perl.org/) +- 以及 perl 内置的: `perldoc perlintro` diff --git a/zh-cn/powershell-cn.html.markdown b/zh-cn/powershell-cn.html.markdown new file mode 100644 index 00000000..875d2e33 --- /dev/null +++ b/zh-cn/powershell-cn.html.markdown @@ -0,0 +1,325 @@ +--- +category: tool +tool: powershell +contributors: + - ["Wouter Van Schandevijl", "https://github.com/laoujin"] +translators: + - ["Feng Gao", "https://github.com/gaufung"] +filename: LearnPowershell-cn.ps1 +lang: zh-cn +--- + +PowerShell 是 Windows 平台下的脚本语言同时也是配置管理框架,它是建立在微软 .Net Framework 之上,Windows 7 以及之后版本都内置 Poweshell。下面的示例中都是 PoweShell 脚本的一部分或者直接能够在 Shell 交互窗口中执行。 + +与 Bash 最大的不同是你大部分操作的东西是对象而不是普通的文本。 + +[延伸阅读](https://docs.microsoft.com/zh-cn/powershell/scripting/overview) + +如果你不确定你的环境,执行如下操作: + +```powershell +Get-ExecutionPolicy -List +Set-ExecutionPolicy AllSigned +# Execution Policy 包含以下: +# - Restricted: 不会运行脚本。 +# - RemoteSigned: 只会运行受信任的发行商下载的脚本。 +# - AllSigned: 运行需要被信任发行商签名的脚本。 +# - Unrestricted: 运行所有脚本 +help about_Execution_Policies # 查看更多信息 + +# 当前 PowerShell 版本 +$PSVersionTable +``` + +获取帮助 + +```powershell +# 查找命令 +Get-Command about_* # 别名: gcm +Get-Command -Verb Add +Get-Alias ps +Get-Alias -Definition Get-Process + +Get-Help ps | less # 别名: help +ps | Get-Member # 别名: gm + +Show-Command Get-EventLog # GUI 填充参数 + +Update-Help # 管理员运行 +``` + +接下来是教程 + +```powershell +# 正如你看到的,每一行开头是 # 都是注释 + +# 简单的 Hello World 实例 +echo Hello world! +# echo 是 Write-Output (cmdlet) 的别名 +# 大部分 cmdlet 和函数都遵循 "动词-名词" 命名规则。 + +# 每个命令都从新的一行开始或者是一个分号 +echo 'This is the first line'; echo 'This is the second line' + +# 声明一个变量如下: +$aString="Some string" +# 或者像这样: +$aNumber = 5 -as [double] +$aList = 1,2,3,4,5 +$anEmptyList = @() +$aString = $aList -join '--' # 也包含 join 方法 +$aHashtable = @{name1='val1'; name2='val2'} + +# 使用变量: +echo $aString +echo "Interpolation: $aString" +echo "$aString has length of $($aString.Length)" +echo '$aString' +echo @" +This is a Here-String +$aString +"@ +# 注意 ' (单引号) 不是变量的一部分 +# 在这里字符串也可以是单引号 + +# 内置变量: +# 下面是一些有用的内置变量,比如: +echo "Booleans: $TRUE and $FALSE" +echo "Empty value: $NULL" +echo "Last program's return value: $?" +echo "Exit code of last run Windows-based program: $LastExitCode" +echo "The last token in the last line received by the session: $$" +echo "The first token: $^" +echo "Script's PID: $PID" +echo "Full path of current script directory: $PSScriptRoot" +echo 'Full path of current script: ' + $MyInvocation.MyCommand.Path +echo "FUll path of current directory: $Pwd" +echo "Bound arguments in a function, script or code block: $PSBoundParameters" +echo "Unbound arguments: $($Args -join ', ')." +# 更多的内置类型: `help about_Automatic_Variables` + +# 内联其他文件 (点操作符) +. .\otherScriptName.ps1 + + +### 控制流 +# 下面是条件判断结构 +if ($Age -is [string]) { + echo 'But.. $Age cannot be a string!' +} elseif ($Age -lt 12 -and $Age -gt 0) { + echo 'Child (Less than 12. Greater than 0)' +} else { + echo 'Adult' +} + +# Switch 语句比其他语言更强大 +$val = "20" +switch($val) { + { $_ -eq 42 } { "The answer equals 42"; break } + '20' { "Exactly 20"; break } + { $_ -like 's*' } { "Case insensitive"; break } + { $_ -clike 's*'} { "clike, ceq, cne for case sensitive"; break } + { $_ -notmatch '^.*$'} { "Regex matching. cnotmatch, cnotlike, ..."; break } + { 'x' -contains 'x'} { "FALSE! -contains is for lists!"; break } + default { "Others" } +} + +# 经典的 For 循环 +for($i = 1; $i -le 10; $i++) { + "Loop number $i" +} +# 或者可以更简洁 +1..10 | % { "Loop number $_" } + +# PowerShell 还提供其他循环方式 +foreach ($var in 'val1','val2','val3') { echo $var } +# while () {} +# do {} while () +# do {} until () + +# 异常处理 +try {} catch {} finally {} +try {} catch [System.NullReferenceException] { + echo $_.Exception | Format-List -Force +} + + +### Providers +# 列出当前目录下的文件和子目录 +ls # 或者 `dir` +cd ~ # 回到主目录 + +Get-Alias ls # -> Get-ChildItem +# 这些 cmdlet 有更加通用的名称,因为它不仅仅只操作当前目录,这一点和其他脚本语言不同。 +cd HKCU: # 跳转 HKEY_CURRENT_USER 注册表中的值 + +# 获取当前会话中的提供者 +Get-PSProvider + + +### 管道 +# Cmdlets 中的参数用来控制它们的行为: +Get-ChildItem -Filter *.txt -Name # 获取所有 txt 文件名。 +# 需要输入足够多的参数来确保没有歧义。 +ls -fi *.txt -n # -f 是不可以的因为 -Force 同样存在。 +# 使用 `Get-Help Get-ChildItem -Full` 来查看全部参数。 + +# 之前 cmdlet 获取的结果输出可以作为一下个输入。 +# `$_` 指代当前管道处理的对象。 +ls | Where-Object { $_.Name -match 'c' } | Export-CSV export.txt +ls | ? { $_.Name -match 'c' } | ConvertTo-HTML | Out-File export.html + +# 如果对管道的对象感到疑惑,使用 `Get-Member` 来查看该对象的可使用的方法和属性。 +ls | Get-Member +Get-Date | gm + +# ` 是行连续标识符,或者在每一行结尾添加一个 | +Get-Process | Sort-Object ID -Descending | Select-Object -First 10 Name,ID,VM ` + | Stop-Process -WhatIf + +Get-EventLog Application -After (Get-Date).AddHours(-2) | Format-List + +# 使用 % 作为 ForEach-Object 的简称。 +(a,b,c) | ForEach-Object ` + -Begin { "Starting"; $counter = 0 } ` + -Process { "Processing $_"; $counter++ } ` + -End { "Finishing: $counter" } + +# Get-Process 返回包含三列的表 +# 第三列是使用 2 位精度数值表示 VM 属性 +# 计算出来的列也可以表示更多的信息: +# `@{name='lbl';expression={$_}` +ps | Format-Table ID,Name,@{n='VM(MB)';e={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize + + +### 函数 +# [string] 注记是可选的。 +function foo([string]$name) { + echo "Hey $name, have a function" +} + +# 调用你的函数 +foo "Say my name" + +# 函数可以包含命名参数、参数的注记和可解析的文档 +<# +.SYNOPSIS +Setup a new website +.DESCRIPTION +Creates everything your new website needs for much win +.PARAMETER siteName +The name for the new website +.EXAMPLE +New-Website -Name FancySite -Po 5000 +New-Website SiteWithDefaultPort +New-Website siteName 2000 # ERROR! Port argument could not be validated +('name1','name2') | New-Website -Verbose +#> +function New-Website() { + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$true, Mandatory=$true)] + [Alias('name')] + [string]$siteName, + [ValidateSet(3000,5000,8000)] + [int]$port = 3000 + ) + BEGIN { Write-Verbose 'Creating new website(s)' } + PROCESS { echo "name: $siteName, port: $port" } + END { Write-Verbose 'Website(s) created' } +} + + +### 都是 .NET +# PS 中的字符串事实上就是 .NET 的 System.String 类型 +# 所有 .NET 方法和属性都可用 +'string'.ToUpper().Replace('G', 'ggg') +# 或者更加 PowerShell 一点 +'string'.ToUpper() -replace 'G', 'ggg' + +# 不确定这样的话 .NET 方法如何调用 +'string' | gm + +# 调用静态 .NET 方法的语法: +[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') + +# 注意 .NET 方法调用必须使用括号,然而 PS 函数调用不能使用括号; +# 如果你调用 cmdlet/PS 函数使用了括号,就相当于传递了参数列表。 +$writer = New-Object System.IO.StreamWriter($path, $true) +$writer.Write([Environment]::NewLine) +$writer.Dispose() + +### IO +# 从输入读入一个值 +$Name = Read-Host "What's your name?" +echo "Hello, $Name!" +[int]$Age = Read-Host "What's your age?" + +# Test-Path, Split-Path, Join-Path, Resolve-Path +# Get-Content filename # 返回字符串数组 string[] +# Set-Content, Add-Content, Clear-Content +Get-Command ConvertTo-*,ConvertFrom-* + + +### 有用的东西 +# 更新 PATH +$env:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + +# 找到 Python 的 PATH +$env:PATH.Split(";") | Where-Object { $_ -like "*python*"} + +# 改变工作目录而不需要记住之前的路径 +Push-Location c:\temp # 改变工作目录至 c:\temp +Pop-Location # 改变到之前的工作目录 +# 别名: pushd 和 popd + +# 在下载之后解除目录阻塞 +Get-ChildItem -Recurse | Unblock-File + +# Windows 资源管理器打开当前目录 +ii . + +# 按任意键退出 +$host.UI.RawUI.ReadKey() +return + +# 创建快捷方式 +$WshShell = New-Object -comObject WScript.Shell +$Shortcut = $WshShell.CreateShortcut($link) +$Shortcut.TargetPath = $file +$Shortcut.WorkingDirectory = Split-Path $file +$Shortcut.Save() +``` + + +配置你的 PowerShell + +```powershell +# $Profile 是文件 `Microsoft.PowerShell_profile.ps1` 完整路径 +# 下面所有的代码都在 PS 会话开始的时候执行 +if (-not (Test-Path $Profile)) { + New-Item -Type file -Path $Profile -Force + notepad $Profile +} +# 更多信息: `help about_profiles` +# 更多关于 Shell 有用的信息,确保查看下面的 PSReadLine 项目。 +``` + +更多项目 + +* [Channel9](https://channel9.msdn.com/Search?term=powershell%20pipeline#ch9Search&lang-en=en) PowerShell 教程 +* [PSGet](https://github.com/psget/psget) PowerShell NuGet 包 +* [PSReadLine](https://github.com/lzybkr/PSReadLine/) 仿 bash 按行读取( Window10 默认包含) +* [Posh-Git](https://github.com/dahlbyk/posh-git/) Git 命令提示 (推荐!) +* [PSake](https://github.com/psake/psake) 自动构建工作 +* [Pester](https://github.com/pester/Pester) BDD 测试框架 +* [Jump-Location](https://github.com/tkellogg/Jump-Location) Poweshell 中 `cd` 来跳转目录 +* [PowerShell Community Extensions](http://pscx.codeplex.com/) (废弃) + +尚未涉及 + +* WMI: Windows 管理规范 (Get-CimInstance) +* 多任务: Start-Job -scriptBlock {...}, +* 代码签名 +* 远程 (Enter-PSSession/Exit-PSSession; Invoke-Command) diff --git a/zh-cn/pyqt-cn.html.markdown b/zh-cn/pyqt-cn.html.markdown new file mode 100644 index 00000000..04041c83 --- /dev/null +++ b/zh-cn/pyqt-cn.html.markdown @@ -0,0 +1,80 @@ +--- +category: tool +tool: PyQT +filename: learnpyqt.py +contributors: + - ["Nathan Hughes", "https://github.com/sirsharpest"] +translators: + - ["kdxcxs", "https://github.com/kdxcxs"] + - ["lsvih", "https://github.com/lsvih"] + - ["imlonghao", "https://github.com/imlonghao"] +lang: zh-cn +--- + +**Qt** 是一个用 C++ 实现的著名跨平台软件开发框架。只需少量更改有时候甚至不需要更改代码就能在多个软硬件平台上运行,同时拥有原生应用程序的功能和速度。 + + +以下内容改编自 [Aleksey Kholovchuk](https://github.com/vortexxx192) 编写的 C++ 版 QT 简介,并用 pyqt 重构原文代码,实现了部分相同的功能。 + +```python +import sys +from PyQt4 import QtGui + +def window(): + # 创建应用对象 + app = QtGui.QApplication(sys.argv) + # 创建一个 widget,作为 label 的父控件 + w = QtGui.QWidget() + # 在 widget 中添加一个 label 子控件 + b = QtGui.QLabel(w) + # 设置 label 的文字 + b.setText("Hello World!") + # 设置 widget 的尺寸和位置 + w.setGeometry(100, 100, 200, 50) + b.move(50, 20) + # 设置窗口的标题 + w.setWindowTitle("PyQt") + # 显示 widget 及其所有子控件 + w.show() + # 下面让程序跑起来,这行代码会启动事件循环并阻塞直到应用程序退出。 + sys.exit(app.exec_()) +if __name__ == '__main__': + window() +``` + +为了运用 pyqt 中一些更高级的功能,我们需要开始学习使用其他控件。下文演示了如何弹出对话框,该对话框在用户确认操作或输入信息等情况下经常用到。 + +```python +import sys +from PyQt4.QtGui import * +from PyQt4.QtCore import * +def window(): + app = QApplication(sys.argv) + w = QWidget() + # 创建一个按钮并添加到 widget 控件 w + b = QPushButton(w) + b.setText("Press me") + b.move(50, 50) + # 当按钮 b 被点击时调用 showdialog 函数 + # 注意函数调用时没有“()”,这样函数就能以对象的方式传入而非传入执行它所得到的返回值 + # 更多关于 pyqt 函数调用、传参等的内容见 pyqt 的信号机制 + b.clicked.connect(showdialog) + w.setWindowTitle("PyQt Dialog") + w.show() + sys.exit(app.exec_()) + +# 对话框窗口创建函数 +# 当窗口中的按钮被点击时退出本程序 +def showdialog(): + d = QDialog() + b1 = QPushButton("ok", d) + b1.move(50, 50) + d.setWindowTitle("Dialog") + # 这里的模态实现了在对话框弹出时阻塞程序同时屏蔽父窗口 + d.setWindowModality(Qt.ApplicationModal) + # 当按钮被点击时整个进程将会结束 + b1.clicked.connect(sys.exit) + d.exec_() +if __name__ == '__main__': + window() +``` diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown index 65f125d1..127f7ad5 100644 --- a/zh-cn/python-cn.html.markdown +++ b/zh-cn/python-cn.html.markdown @@ -1,302 +1,476 @@ --- -language: python +language: Python contributors: - - ["Louie Dinh", "http://ldinh.ca"] + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] translators: - - ["Chenbo Li", "http://binarythink.net"] -filename: learnpython-zh.py + - ["Geoff Liu", "http://geoffliu.me"] + - ["Maple", "https://github.com/mapleincode"] +filename: learnpython-cn.py lang: zh-cn + --- -Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语言之一 -我喜爱python是因为它有极为清晰的语法,甚至可以说,它就是可以执行的伪代码 +Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计。 +它是如今最常用的编程语言之一。它的语法简洁且优美,几乎就是可执行的伪代码。 -很欢迎来自您的反馈,你可以在[@louiedinh](http://twitter.com/louiedinh) 和 louiedinh [at] [google's email service] 这里找到我 +欢迎大家斧正。英文版原作 Louie Dinh [@louiedinh](http://twitter.com/louiedinh) +邮箱 louiedinh [at] [谷歌的信箱服务]。中文翻译 Geoff Liu。 -注意: 这篇文章针对的版本是Python 2.7,但大多也可使用于其他Python 2的版本 -如果是Python 3,请在网络上寻找其他教程 +注意:这篇教程是基于 Python 3 写的。如果你想学旧版 Python 2,我们特别有[另一篇教程](http://learnxinyminutes.com/docs/pythonlegacy/)。 ```python +# 用井字符开头的是单行注释 -# 单行注释 -""" 多行字符串可以用 - 三个引号包裹,不过这也可以被当做 - 多行注释 +""" 多行字符串用三个引号 + 包裹,也常被用来做多 + 行注释 """ #################################################### -## 1. 原始数据类型和操作符 +## 1. 原始数据类型和运算符 #################################################### -# 数字类型 +# 整数 3 # => 3 -# 简单的算数 -1 + 1 # => 2 -8 - 1 # => 7 +# 算术没有什么出乎意料的 +1 + 1 # => 2 +8 - 1 # => 7 10 * 2 # => 20 -35 / 5 # => 7 -# 整数的除法会自动取整 -5 / 2 # => 2 +# 但是除法例外,会自动转换成浮点数 +35 / 5 # => 7.0 +10.0 / 3 # => 3.3333333333333335 + +# 整数除法的结果都是向下取整 +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # 浮点数也可以 +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# 浮点数的运算结果也是浮点数 +3 * 2.0 # => 6.0 + +# 模除 +7 % 3 # => 1 +# i % j 结果的正负符号会和 j 相同,而不是和 i 相同 +-7 % 3 # => 2 -# 要做精确的除法,我们需要引入浮点数 -2.0 # 浮点数 -11.0 / 4.0 # => 2.75 精确多了 +# x 的 y 次方 +2**4 # => 16 -# 括号具有最高优先级 +# 用括号决定优先级 +1 + 3 * 2 # => 7 (1 + 3) * 2 # => 8 -# 布尔值也是基本的数据类型 -True -False +# 布尔值 (注意: 首字母大写) +True # => True +False # => False -# 用 not 来取非 -not True # => False +# 用 not 取非 +not True # => False not False # => True -# 相等 +# 逻辑运算符,注意 and 和 or 都是小写 +True and False # => False +False or True # => True + +# True 和 False 实质上就是数字 1 和0 +True + True # => 2 +True * 8 # => 8 +False - 5 # => -5 + +# 数值与 True 和 False 之间的比较运算 +0 == False # => True +2 == True # => False +1 == True # => True +-5 != False # => True + +# 使用布尔逻辑运算符对数字类型的值进行运算时,会把数值强制转换为布尔值进行运算 +# 但计算结果会返回它们的强制转换前的值 +# 注意不要把 bool(ints) 与位运算的 "按位与"、"按位或" (&, |) 混淆 +bool(0) # => False +bool(4) # => True +bool(-6) # => True +0 and 2 # => 0 +-5 or 0 # => -5 + +# 用==判断相等 1 == 1 # => True 2 == 1 # => False -# 不等 +# 用!=判断不等 1 != 1 # => False 2 != 1 # => True -# 更多的比较操作符 +# 比较大小 1 < 10 # => True 1 > 10 # => False 2 <= 2 # => True 2 >= 2 # => True -# 比较运算可以连起来写! +# 判断一个值是否在范围里 +1 < 2 and 2 < 3 # => True +2 < 3 and 3 < 2 # => False +# 大小比较可以连起来! 1 < 2 < 3 # => True 2 < 3 < 2 # => False -# 字符串通过 " 或 ' 括起来 -"This is a string." -'This is also a string.' +# (is 对比 ==) is 判断两个变量是否引用同一个对象, +# 而 == 判断两个对象是否含有相同的值 +a = [1, 2, 3, 4] # 变量 a 是一个新的列表, [1, 2, 3, 4] +b = a # 变量 b 赋值了变量 a 的值 +b is a # => True, a 和 b 引用的是同一个对象 +b == a # => True, a 和 b 的对象的值相同 +b = [1, 2, 3, 4] # 变量 b 赋值了一个新的列表, [1, 2, 3, 4] +b is a # => False, a 和 b 引用的不是同一个对象 +b == a # => True, a 和 b 的对象的值相同 -# 字符串通过加号拼接 -"Hello " + "world!" # => "Hello world!" - -# 字符串可以被视为字符的列表 -"This is a string"[0] # => 'T' -# % 可以用来格式化字符串 -"%s can be %s" % ("strings", "interpolated") +# 创建字符串可以使用单引号(')或者双引号(") +"这是个字符串" +'这也是个字符串' -# 也可以用 format 方法来格式化字符串 -# 推荐使用这个方法 -"{0} can be {1}".format("strings", "formatted") -# 也可以用变量名代替数字 -"{name} wants to eat {food}".format(name="Bob", food="lasagna") - -# None 是对象 +# 字符串可以使用加号连接成新的字符串 +"Hello " + "world!" # => "Hello world!" +# 非变量形式的字符串甚至可以在没有加号的情况下连接 +"Hello " "world!" # => "Hello world!" + +# 字符串可以被当作字符列表 +"Hello world!"[0] # => 'H' + +# 你可以获得字符串的长度 +len("This is a string") # => 16 + +# 你可以使用 f-strings 格式化字符串(python3.6+) +name = "Reiko" +f"She said her name is {name}." # => "She said her name is Reiko" +# 你可以在大括号内几乎加入任何 python 表达式,表达式的结果会以字符串的形式返回 +f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long." + +# 用 .format 来格式化字符串 +"{} can be {}".format("strings", "interpolated") +# 可以重复参数以节省时间 +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" +# 如果不想数参数,可以用关键字 +"{name} wants to eat {food}".format(name="Bob", food="lasagna") +# => "Bob wants to eat lasagna" + +# 如果你的 Python3 程序也要在 Python2.5 以下环境运行,也可以用老式的格式化语法 +"%s can be %s the %s way" % ("strings", "interpolated", "old") + +# None是一个对象 None # => None -# 不要用相等 `==` 符号来和None进行比较 -# 要用 `is` +# 当与 None 进行比较时不要用 ==,要用 is。is 是用来比较两个变量是否指向同一个对象。 "etc" is None # => False None is None # => True -# 'is' 可以用来比较对象的相等性 -# 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少 - -# None, 0, 和空字符串都被算作 False -# 其他的均为 True -0 == False # => True -"" == False # => True +# None,0,空字符串,空列表,空字典,空元组都算是 False +# 所有其他值都是 True +bool(0) # => False +bool("") # => False +bool([]) # => False +bool({}) # => False +bool(()) # => False #################################################### ## 2. 变量和集合 #################################################### -# 很方便的输出 -print "I'm Python. Nice to meet you!" +# print是内置的打印函数 +print("I'm Python. Nice to meet you!") + +# 默认情况下,print 函数会在输出结果后加入一个空行作为结尾 +# 可以使用附加参数改变输出结尾 +print("Hello, World", end="!") # => Hello, World! +# 可以很简单的从终端获得输入数据 +input_string_var = input("Enter some data: ") # 返回字符串数值 -# 给变量赋值前不需要事先声明 -some_var = 5 # 一般建议使用小写字母和下划线组合来做为变量名 +# 在给变量赋值前不用提前声明 +# 习惯上变量命名是小写,用下划线分隔单词 +some_var = 5 some_var # => 5 # 访问未赋值的变量会抛出异常 -# 可以查看控制流程一节来了解如何异常处理 -some_other_var # 抛出 NameError +# 参考流程控制一段来学习异常处理 +some_unknown_var # 抛出 NameError -# if 语句可以作为表达式来使用 -"yahoo!" if 3 > 2 else 2 # => "yahoo!" +# "if" 可以用作表达式,它的作用等同于 C 语言的三元运算符 "?:" +"yay!" if 0 > 1 else "nay!" # => "nay!" -# 列表用来保存序列 +# 用列表 (list) 储存序列 li = [] -# 可以直接初始化列表 +# 创建列表时也可以同时赋给元素 other_li = [4, 5, 6] -# 在列表末尾添加元素 -li.append(1) # li 现在是 [1] -li.append(2) # li 现在是 [1, 2] -li.append(4) # li 现在是 [1, 2, 4] -li.append(3) # li 现在是 [1, 2, 4, 3] -# 移除列表末尾元素 -li.pop() # => 3 li 现在是 [1, 2, 4] -# 重新加进去 -li.append(3) # li is now [1, 2, 4, 3] again. - -# 像其他语言访问数组一样访问列表 +# 用append在列表最后追加元素 +li.append(1) # li现在是[1] +li.append(2) # li现在是[1, 2] +li.append(4) # li现在是[1, 2, 4] +li.append(3) # li现在是[1, 2, 4, 3] +# 用pop从列表尾部删除 +li.pop() # => 3 且li现在是[1, 2, 4] +# 把3再放回去 +li.append(3) # li变回[1, 2, 4, 3] + +# 列表存取跟数组一样 li[0] # => 1 -# 访问最后一个元素 +# 取出最后一个元素 li[-1] # => 3 -# 越界会抛出异常 -li[4] # 抛出越界异常 +# 越界存取会造成 IndexError +li[4] # 抛出 IndexError -# 切片语法需要用到列表的索引访问 -# 可以看做数学之中左闭右开区间 -li[1:3] # => [2, 4] -# 省略开头的元素 -li[2:] # => [4, 3] -# 省略末尾的元素 -li[:3] # => [1, 2, 4] +# 列表有切割语法 +li[1:3] # => [2, 4] +# 取尾 +li[2:] # => [4, 3] +# 取头 +li[:3] # => [1, 2, 4] +# 隔一个取一个 +li[::2] # =>[1, 4] +# 倒排列表 +li[::-1] # => [3, 4, 2, 1] +# 可以用三个参数的任何组合来构建切割 +# li[始:终:步伐] -# 删除特定元素 -del li[2] # li 现在是 [1, 2, 3] +# 简单的实现了单层数组的深度复制 +li2 = li[:] # => li2 = [1, 2, 4, 3] ,但 (li2 is li) 会返回 False -# 合并列表 -li + other_li # => [1, 2, 3, 4, 5, 6] - 并不会不改变这两个列表 +# 用 del 删除任何一个元素 +del li[2] # li 现在为 [1, 2, 3] -# 通过拼接来合并列表 -li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6] +# 删除第一个匹配的元素 +li.remove(2) # li 现在为 [1, 3] +li.remove(2) # 抛出错误 ValueError: 2 is not in the list -# 用 in 来返回元素是否在列表中 -1 in li # => True +# 在指定索引处插入一个新的元素 +li.insert(1, 2) # li is now [1, 2, 3] again -# 返回列表长度 -len(li) # => 6 +# 获得列表第一个匹配的值的索引 +li.index(2) # => 1 +li.index(4) # 抛出一个 ValueError: 4 is not in the list +# 列表可以相加 +# 注意:li 和 other_li 的值都不变 +li + other_li # => [1, 2, 3, 4, 5, 6] -# 元组类似于列表,但它是不可改变的 -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # 类型错误 +# 用 "extend()" 拼接列表 +li.extend(other_li) # li 现在是[1, 2, 3, 4, 5, 6] -# 对于大多数的列表操作,也适用于元组 -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True +# 用 "in" 测试列表是否包含值 +1 in li # => True -# 你可以将元组解包赋给多个变量 -a, b, c = (1, 2, 3) # a 是 1,b 是 2,c 是 3 -# 如果不加括号,将会被自动视为元组 -d, e, f = 4, 5, 6 -# 现在我们可以看看交换两个数字是多么容易的事 -e, d = d, e # d 是 5,e 是 4 +# 用 "len()" 取列表长度 +len(li) # => 6 -# 字典用来储存映射关系 +# 元组类似列表,但是不允许修改 +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # 抛出 TypeError + +# 如果元素数量为 1 的元组必须在元素之后加一个逗号 +# 其他元素数量的元组,包括空元组,都不需要 +type((1)) # => <class 'int'> +type((1,)) # => <class 'tuple'> +type(()) # => <class 'tuple'> + +# 列表允许的操作元组大多都可以 +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# 可以把元组合列表解包,赋值给变量 +a, b, c = (1, 2, 3) # 现在 a 是 1,b 是 2,c 是 3 +# 也可以做扩展解包 +a, *b, c = (1, 2, 3, 4) # 现在 a 是 1, b 是 [2, 3], c 是 4 +# 元组周围的括号是可以省略的 +d, e, f = 4, 5, 6 # 元组 4, 5, 6 通过解包被赋值给变量 d, e, f +# 交换两个变量的值就这么简单 +e, d = d, e # 现在 d 是 5,e 是 4 + + +# 字典用来存储 key 到 value 的映射关系 empty_dict = {} -# 字典初始化 +# 初始化的字典 filled_dict = {"one": 1, "two": 2, "three": 3} -# 字典也用中括号访问元素 -filled_dict["one"] # => 1 +# 字典的 key 必须为不可变类型。 这是为了确保 key 被转换为唯一的哈希值以用于快速查询 +# 不可变类型包括整数、浮点、字符串、元组 +invalid_dict = {[1,2,3]: "123"} # => 抛出 TypeError: unhashable type: 'list' +valid_dict = {(1,2,3):[1,2,3]} # 然而 value 可以是任何类型 + +# 用[]取值 +filled_dict["one"] # => 1 + +# 用 keys 获得所有的键。 +# 因为 keys 返回一个可迭代对象,所以我们需要把它包在 "list()" 里才能转换为列表。 +# 我们下面会详细介绍可迭代。 +# 注意: 对于版本 < 3.7 的 python, 字典的 key 的排序是无序的。你的运行结果 +# 可能与下面的例子不符,但是在 3.7 版本,字典中的项会按照他们被插入到字典的顺序进行排序 +list(filled_dict.keys()) # => ["three", "two", "one"] Python 版本 <3.7 +list(filled_dict.keys()) # => ["one", "two", "three"] Python 版本 3.7+ -# 把所有的键保存在列表中 -filled_dict.keys() # => ["three", "two", "one"] -# 键的顺序并不是唯一的,得到的不一定是这个顺序 +# 用 "values()" 获得所有的值。跟 keys 一样也是可迭代对象,要使用 "list()" 才能转换为列表。 +# 注意: 排序顺序和 keys 的情况相同。 -# 把所有的值保存在列表中 -filled_dict.values() # => [3, 2, 1] -# 和键的顺序相同 +list(filled_dict.values()) # => [3, 2, 1] Python 版本 < 3.7 +list(filled_dict.values()) # => [1, 2, 3] Python 版本 3.7+ -# 判断一个键是否存在 -"one" in filled_dict # => True -1 in filled_dict # => False -# 查询一个不存在的键会抛出 KeyError -filled_dict["four"] # KeyError +# 用in测试一个字典是否包含一个键 +"one" in filled_dict # => True +1 in filled_dict # => False -# 用 get 方法来避免 KeyError -filled_dict.get("one") # => 1 -filled_dict.get("four") # => None -# get 方法支持在不存在的时候返回一个默认值 -filled_dict.get("one", 4) # => 1 +# 访问不存在的键会导致 KeyError +filled_dict["four"] # KeyError + +# 用 "get()" 来避免KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# 当键不存在的时候 "get()" 方法可以返回默认值 +filled_dict.get("one", 4) # => 1 filled_dict.get("four", 4) # => 4 -# setdefault 是一个更安全的添加字典元素的方法 -filled_dict.setdefault("five", 5) # filled_dict["five"] 的值为 5 -filled_dict.setdefault("five", 6) # filled_dict["five"] 的值仍然是 5 +# "setdefault()" 方法只有当键不存在的时候插入新值 +filled_dict.setdefault("five", 5) # filled_dict["five"] 设为5 +filled_dict.setdefault("five", 6) # filled_dict["five"] 还是5 + +# 字典赋值 +filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} +filled_dict["four"] = 4 # 另一种赋值方法 +# 用 del 删除项 +del filled_dict["one"] # 从 filled_dict 中把 one 删除 -# 集合储存无顺序的元素 + +# 用 set 表达集合 empty_set = set() -# 初始化一个集合 -some_set = set([1, 2, 2, 3, 4]) # some_set 现在是 set([1, 2, 3, 4]) +# 初始化一个集合,语法跟字典相似。 +some_set = {1, 1, 2, 2, 3, 4} # some_set现在是 {1, 2, 3, 4} + +# 类似字典的 keys,set 的元素也必须是不可变类型 +invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list' +valid_set = {(1,), 1} -# Python 2.7 之后,大括号可以用来表示集合 -filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} +# 可以把集合赋值于变量 +filled_set = some_set -# 向集合添加元素 -filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} +# 为集合添加元素 +filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} +# set 没有重复的元素 +filled_set.add(5) # filled_set 依然是 {1, 2, 3, 4, 5} -# 用 & 来计算集合的交 +# "&" 取交集 other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} +filled_set & other_set # => {3, 4, 5} -# 用 | 来计算集合的并 -filled_set | other_set # => {1, 2, 3, 4, 5, 6} +# "|" 取并集 +filled_set | other_set # => {1, 2, 3, 4, 5, 6} -# 用 - 来计算集合的差 -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} +# "-" 取补集 +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} -# 用 in 来判断元素是否存在于集合中 -2 in filled_set # => True -10 in filled_set # => False +# "^" 取异或集(对称差) +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} +# 判断左边的集合是否是右边集合的超集 +{1, 2} >= {1, 2, 3} # => False + +# 判断左边的集合是否是右边集合的子集 +{1, 2} <= {1, 2, 3} # => True + +# in 测试集合是否包含元素 +2 in filled_set # => True +10 in filled_set # => False + +# 单层集合的深度复制 +filled_set = some_set.copy() # filled_set 是 {1, 2, 3, 4, 5} +filled_set is some_set # => False #################################################### -## 3. 控制流程 +## 3. 流程控制和迭代器 #################################################### -# 新建一个变量 +# 先随便定义一个变量 some_var = 5 -# 这是个 if 语句,在 python 中缩进是很重要的。 -# 下面的代码片段将会输出 "some var is smaller than 10" +# 这是个if语句。注意缩进在Python里是有意义的! +# 缩进要使用 4 个空格而不是 tabs。 +# 这段代码会打印 "some_var is smaller than 10" if some_var > 10: - print "some_var is totally bigger than 10." -elif some_var < 10: # 这个 elif 语句是不必须的 - print "some_var is smaller than 10." -else: # 这个 else 也不是必须的 - print "some_var is indeed 10." + print("some_var is totally bigger than 10.") +elif some_var < 10: # elif 语句是可选的 + print("some_var is smaller than 10.") +else: # else 也是可选的 + print("some_var is indeed 10.") """ -用for循环遍历列表 -输出: +用 for 循环语句遍历列表 +打印: dog is a mammal cat is a mammal mouse is a mammal """ for animal in ["dog", "cat", "mouse"]: - # 你可以用 % 来格式化字符串 - print "%s is a mammal" % animal + # 你可以使用 format() 格式化字符串并插入值 + print("{} is a mammal".format(animal)) """ -`range(number)` 返回从0到给定数字的列表 -输出: +"range(number)" 返回数字列表从 0 到 number 的数字 +打印: 0 1 2 3 """ for i in range(4): - print i + print(i) + +""" +"range(lower, upper)" 会返回一个包含从 lower 到 upper 的数字迭代器 +prints: + 4 + 5 + 6 + 7 +""" +for i in range(4, 8): + print(i) + +""" +"range(lower, upper, step)" 会返回一个,从 lower 到 upper、并且间隔值为 step 的迭代器。 +如果 step 未传入则会使用默认值 1 +prints: + 4 + 6 +""" +for i in range(4, 8, 2): + print(i) + +""" +遍历列表,并且同时返回列表里的每一个元素的索引和数值。 +prints: + 0 dog + 1 cat + 2 mouse +""" +animals = ["dog", "cat", "mouse"] +for i, value in enumerate(animals): + print(i, value) """ -while 循环 -输出: +while 循环直到条件不满足 +打印: 0 1 2 @@ -304,173 +478,571 @@ while 循环 """ x = 0 while x < 4: - print x - x += 1 # x = x + 1 的简写 + print(x) + x += 1 # x = x + 1 的简写 -# 用 try/except 块来处理异常 -# Python 2.6 及以上适用: +# 用 try/except 块处理异常状况 try: - # 用 raise 来抛出异常 + # 用 raise 抛出异常 raise IndexError("This is an index error") except IndexError as e: - pass # pass 就是什么都不做,不过通常这里会做一些恢复工作 + pass # pass 是无操作,但是应该在这里处理错误 +except (TypeError, NameError): + pass # 可以同时处理不同类的错误 +else: # else语句是可选的,必须在所有的except之后 + print("All good!") # 只有当try运行完没有错误的时候这句才会运行 +finally: # 在任何情况下都会执行 + print("We can clean up resources here") + +# 你可以使用 with 语句来代替 try/finally 对操作进行结束的操作 +with open("myfile.txt") as f: + for line in f: + print(line) + +# 写入文件 +contents = {"aa": 12, "bb": 21} +with open("myfile1.txt", "w+") as file: + file.write(str(contents)) # 写入字符串到文件 + +with open("myfile2.txt", "w+") as file: + file.write(json.dumps(contents)) # 写入对象到文件 + +# Reading from a file +with open("myfile1.txt", "r+") as file: + contents = file.read() # 从文件读取字符串 +print(contents) +# print: {"aa": 12, "bb": 21} + +with open("myfile2.txt", "r+") as file: + contents = json.load(file) # 从文件读取 json 对象 +print(contents) +# print: {"aa": 12, "bb": 21} + +# Windows 环境调用 open() 读取文件的默认编码为 ANSI,如果需要读取 utf-8 编码的文件, +# 需要指定 encoding 参数: +# open("myfile3.txt", "r+", encoding = "utf-8") + + +# Python 提供一个叫做可迭代 (iterable) 的基本抽象。一个可迭代对象是可以被当作序列 +# 的对象。比如说上面 range 返回的对象就是可迭代的。 + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) # => dict_keys(['one', 'two', 'three']),是一个实现可迭代接口的对象 + +# 可迭代对象可以遍历 +for i in our_iterable: + print(i) # 打印 one, two, three + +# 但是不可以随机访问 +our_iterable[1] # 抛出TypeError + +# 可迭代对象知道怎么生成迭代器 +our_iterator = iter(our_iterable) + +# 迭代器是一个可以记住遍历的位置的对象 +# 用 "next()" 获得下一个对象 +next(our_iterator) # => "one" + +# 再一次调取 "next()" 时会记得位置 +next(our_iterator) # => "two" +next(our_iterator) # => "three" + +# 当迭代器所有元素都取出后,会抛出 StopIteration +next(our_iterator) # 抛出 StopIteration + +# 我们还可以通过遍历访问所有的值,实际上,for 内部实现了迭代 +our_iterator = iter(our_iterable) +for i in our_iterator: + print(i) # 依次打印 one, two, three + +# 可以用 list 一次取出迭代器或者可迭代对象所有的元素 +list(filled_dict.keys()) # => 返回 ["one", "two", "three"] +list(our_iterator) # => 返回 [] 因为迭代的位置被保存了 #################################################### ## 4. 函数 #################################################### -# 用 def 来新建函数 +# 用def定义新函数 def add(x, y): - print "x is %s and y is %s" % (x, y) - return x + y # 通过 return 来返回值 + print("x is {} and y is {}".format(x, y)) + return x + y # 用 return 语句返回 -# 调用带参数的函数 -add(5, 6) # => 输出 "x is 5 and y is 6" 返回 11 +# 调用函数 +add(5, 6) # => 打印 "x is 5 and y is 6" 并且返回 11 -# 通过关键字赋值来调用函数 -add(y=6, x=5) # 顺序是无所谓的 +# 也可以用关键字参数来调用函数 +add(y=6, x=5) # 关键字参数可以用任何顺序 -# 我们也可以定义接受多个变量的函数,这些变量是按照顺序排列的 + +# 我们可以定义一个可变参数函数 def varargs(*args): return args -varargs(1, 2, 3) # => (1,2,3) +varargs(1, 2, 3) # => (1, 2, 3) -# 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的 +# 我们也可以定义一个关键字可变参数函数 def keyword_args(**kwargs): return kwargs -# 实际效果: -keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} +# 我们来看看结果是什么: +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + -# 你也可以同时将一个函数定义成两种形式 +# 这两种可变参数可以混着用 def all_the_args(*args, **kwargs): - print args - print kwargs + print(args) + print(kwargs) """ all_the_args(1, 2, a=3, b=4) prints: (1, 2) {"a": 3, "b": 4} """ -# 当调用函数的时候,我们也可以进行相反的操作,把元组和字典展开为参数 +# 调用可变参数函数时可以做跟上面相反的,用 * 展开元组,用 ** 展开字典。 args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # 等价于 foo(1, 2, 3, 4) -all_the_args(**kwargs) # 等价于 foo(a=3, b=4) -all_the_args(*args, **kwargs) # 等价于 foo(1, 2, 3, 4, a=3, b=4) +all_the_args(*args) # 相当于 all_the_args(1, 2, 3, 4) +all_the_args(**kwargs) # 相当于 all_the_args(a=3, b=4) +all_the_args(*args, **kwargs) # 相当于 all_the_args(1, 2, 3, 4, a=3, b=4) + +# 使用返回多个数值(返回值为元组类型) +def swap(x, y): + return y, x # 用不带括号的元组的格式来返回多个数值 + # (注意: 括号不需要加,但是也可以加) + +x = 1 +y = 2 +x, y = swap(x, y) # => x = 2, y = 1 +# (x, y) = swap(x,y) # 同上,括号不需要加,但是也可以加 + + +# 函数作用域 +x = 5 -# 函数在 python 中是一等公民 +def setX(num): + # 局部作用域的 x 和全局域的 x 是不同的 + x = num # => 43 + print (x) # => 43 + +def setGlobalX(num): + global x + print (x) # => 5 + x = num # 现在全局域的 x 被赋值 + print (x) # => 6 + +setX(43) +setGlobalX(6) + + +# 函数在 Python 是一等公民 def create_adder(x): def adder(y): return x + y return adder add_10 = create_adder(10) -add_10(3) # => 13 +add_10(3) # => 13 -# 匿名函数 -(lambda x: x > 2)(3) # => True +# 也有匿名函数 +(lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 -# 内置高阶函数 -map(add_10, [1, 2, 3]) # => [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] +# 内置的高阶函数 +list(map(add_10, [1, 2, 3])) # => [11, 12, 13] +list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3] -# 可以用列表方法来对高阶函数进行更巧妙的引用 +list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7] + +# 用列表推导式可以简化映射和过滤。列表推导式的返回值是另一个列表。 [add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +# 你也可以用这种方式实现对集合和字典的构建 +{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + #################################################### -## 5. 类 +## 5. 模块 #################################################### -# 我们新建的类是从 object 类中继承的 -class Human(object): +# 导入模块 +import math +print(math.sqrt(16)) # => 4.0 + +# 你可以导入模块中具体的函数 +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# 你可以导入模块中的所有的函数 +# 警告: 此操作不推荐 +from math import * + +# 你可以对模块名进行简化 +import math as m +math.sqrt(16) == m.sqrt(16) # => True - # 类属性,由所有类的对象共享 +# Python 模块实质上是 Python 文件 +# 你可以自己编写自己的模块,然后导入 +# 模块的名称和文件名相同 + +# 你可以用 "dir()" 查看模块中定义的函数和字段 +import math +dir(math) + +# 当你的脚本文件所在的文件夹也包含了一个名为 math.py 的 Python 文件 +# 这个 math.py 文件会被代替引入,而不是引入 Python 內建模块中的 math +# 出现这个情况的原因是本地文件夹的引入优先级要比 Python 內建库引入优先级要高 + + +#################################################### +## 6. 类 +#################################################### + +# 我们使用 "class" 语句来创建类 +class Human: + + # 一个类的字段。 这个字段共享给这个类的所有实例。 species = "H. sapiens" - # 基本构造函数 + # 构造方法,当实例被初始化时被调用。注意名字前后的双下划线,这是表明这个属性 + # 或方法对 Python 有特殊意义,但是允许用户自行定义。 + # 方法(可能是对象或者属性) 类似: __init__, __str__,__repr__ etc + # 都是特殊的方法 + # 你自己取名时不应该用这种格式 def __init__(self, name): - # 将参数赋给对象成员属性 + # 将参数赋值给实例的 name 字段 self.name = name - # 成员方法,参数要有 self + # 初始化属性 + self._age = 0 + + # 实例方法,第一个参数总是self,也就是这个实例对象 def say(self, msg): - return "%s: %s" % (self.name, msg) + print("{name}: {message}".format(name=self.name, message=msg)) + + # 另一个实例方法 + def sing(self): + return 'yo... yo... microphone check... one two... one two...' - # 类方法由所有类的对象共享 - # 这类方法在调用时,会把类本身传给第一个参数 + # 类方法,被所有此类的实例共用。 + # 第一个参数是这个类对象。 @classmethod def get_species(cls): return cls.species - # 静态方法是不需要类和对象的引用就可以调用的方法 + # 静态方法。调用时没有实例或类的绑定。 @staticmethod def grunt(): return "*grunt*" + # property 有点类似 getter + # 它把方法 age() 转换为同名并且只读的属性 + # 通常情况下,可以不需要编写复杂的 getter 和 setter。 + @property + def age(self): + return self._age + + # 允许属性被修改 + @age.setter + def age(self, age): + self._age = age + + # 允许属性被删除 + @age.deleter + def age(self): + del self._age + +# 当 Python 解释器在读取源文件的时候,就会执行文件中所有的代码 +# 对 __name__ 的检查可以保证这块代码只会在这个模块是主程序的情况下被运行(而不是在引用时运行) +if __name__ == '__main__': + # + i = Human(name="Ian") + i.say("hi") # "Ian: hi" + j = Human("Joel") + j.say("hello") # "Joel: hello" + # i 和 j 都是 Human 实例化后的对象,换一句话说,它们都是 Human 实例 + + # 运行类方法 (classmethod) + i.say(i.get_species()) # "Ian: H. sapiens" + # 修改共享的类属性 + Human.species = "H. neanderthalensis" + i.say(i.get_species()) # => "Ian: H. neanderthalensis" + j.say(j.get_species()) # => "Joel: H. neanderthalensis" + + # 运行静态方法 (staticmethod) + print(Human.grunt()) # => "*grunt*" + + # 实例上也可以执行静态方法 + print(i.grunt()) # => "*grunt*" + + # 更新实例的属性 + i.age = 42 + # 访问实例的属性 + i.say(i.age) # => "Ian: 42" + j.say(j.age) # => "Joel: 0" + # 删除实例的属性 + del i.age + # i.age # => 这会抛出一个错误: AttributeError + + +#################################################### +## 6.1 类的继承 +#################################################### + +# 继承机制允许子类可以继承父类上的方法和变量。 +# 我们可以把 Human 类作为一个基础类或者说叫做父类, +# 然后定义一个名为 Superhero 的子类来继承父类上的比如 "species"、 "name"、 "age" 的属性 +# 和比如 "sing" 、"grunt" 这样的方法,同时,也可以定义它自己独有的属性 + +# 基于 Python 文件模块化的特点,你可以把这个类放在独立的文件中,比如说,human.py。 + +# 要从别的文件导入函数,需要使用以下的语句 +# from "filename-without-extension" import "function-or-class" + +from human import Human + +# 指定父类作为类初始化的参数 +class Superhero(Human): + + # 如果子类需要继承所有父类的定义,并且不需要做任何的修改, + # 你可以直接使用 "pass" 关键字(并且不需要其他任何语句) + # 但是在这个例子中会被注释掉,以用来生成不一样的子类。 + # pass + + # 子类可以重写父类定义的字段 + species = 'Superhuman' + + # 子类会自动的继承父类的构造函数包括它的参数,但同时,子类也可以新增额外的参数或者定义, + # 甚至去覆盖父类的方法比如说构造函数。 + # 这个构造函数从父类 "Human" 上继承了 "name" 参数,同时又新增了 "superpower" 和 + # "movie" 参数: + def __init__(self, name, movie=False, + superpowers=["super strength", "bulletproofing"]): + + # 新增额外类的参数 + self.fictional = True + self.movie = movie + # 注意可变的默认值,因为默认值是共享的 + self.superpowers = superpowers + + # "super" 函数让你可以访问父类中被子类重写的方法 + # 在这个例子中,被重写的是 __init__ 方法 + # 这个语句是用来运行父类的构造函数: + super().__init__(name) + + # 重写父类中的 sing 方法 + def sing(self): + return 'Dun, dun, DUN!' + + # 新增一个额外的方法 + def boast(self): + for power in self.superpowers: + print("I wield the power of {pow}!".format(pow=power)) + + +if __name__ == '__main__': + sup = Superhero(name="Tick") + + # 检查实例类型 + if isinstance(sup, Human): + print('I am human') + if type(sup) is Superhero: + print('I am a superhero') + + # 获取方法解析顺序 MRO,MRO 被用于 getattr() 和 super() + # 这个字段是动态的,并且可以被修改 + print(Superhero.__mro__) # => (<class '__main__.Superhero'>, + # => <class 'human.Human'>, <class 'object'>) + + # 调用父类的方法并且使用子类的属性 + print(sup.get_species()) # => Superhuman -# 实例化一个类 -i = Human(name="Ian") -print i.say("hi") # 输出 "Ian: hi" + # 调用被重写的方法 + print(sup.sing()) # => Dun, dun, DUN! -j = Human("Joel") -print j.say("hello") # 输出 "Joel: hello" + # 调用 Human 的方法 + sup.say('Spoon') # => Tick: Spoon -# 访问类的方法 -i.get_species() # => "H. sapiens" + # 调用 Superhero 独有的方法 + sup.boast() # => I wield the power of super strength! + # => I wield the power of bulletproofing! -# 改变共享属性 -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" + # 继承类的字段 + sup.age = 31 + print(sup.age) # => 31 -# 访问静态变量 -Human.grunt() # => "*grunt*" + # Superhero 独有的字段 + print('Am I Oscar eligible? ' + str(sup.movie)) #################################################### -## 6. 模块 +## 6.2 多重继承 #################################################### -# 我们可以导入其他模块 -import math -print math.sqrt(16) # => 4.0 +# 定义另一个类 +# bat.py +class Bat: -# 我们也可以从一个模块中导入特定的函数 -from math import ceil, floor -print ceil(3.7) # => 4.0 -print floor(3.7) # => 3.0 + species = 'Baty' -# 从模块中导入所有的函数 -# 警告:不推荐使用 -from math import * + def __init__(self, can_fly=True): + self.fly = can_fly -# 简写模块名 -import math as m -math.sqrt(16) == m.sqrt(16) # => True + # 这个类同样有 say 的方法 + def say(self, msg): + msg = '... ... ...' + return msg -# Python的模块其实只是普通的python文件 -# 你也可以创建自己的模块,并且导入它们 -# 模块的名字就和文件的名字相同 + # 新增一个独有的方法 + def sonar(self): + return '))) ... (((' -# 也可以通过下面的方法查看模块中有什么属性和方法 -import math -dir(math) +if __name__ == '__main__': + b = Bat() + print(b.say('hello')) + print(b.fly) + +# 现在我们来定义一个类来同时继承 Superhero 和 Bat +# superhero.py +from superhero import Superhero +from bat import Bat + +# 定义 Batman 作为子类,来同时继承 SuperHero 和 Bat +class Batman(Superhero, Bat): + + def __init__(self, *args, **kwargs): + # 通常要继承属性,你必须调用 super: + # super(Batman, self).__init__(*args, **kwargs) + # 然而在这里我们处理的是多重继承,而 super() 只会返回 MRO 列表的下一个基础类。 + # 因此,我们需要显式调用初始类的 __init__ + # *args 和 **kwargs 传递参数时更加清晰整洁,而对于父类而言像是 “剥了一层洋葱” + Superhero.__init__(self, 'anonymous', movie=True, + superpowers=['Wealthy'], *args, **kwargs) + Bat.__init__(self, *args, can_fly=False, **kwargs) + # 重写了 name 字段 + self.name = 'Sad Affleck' + + def sing(self): + return 'nan nan nan nan nan batman!' + + +if __name__ == '__main__': + sup = Batman() + + # 获取方法解析顺序 MRO,MRO 被用于 getattr() 和 super() + # 这个字段是动态的,并且可以被修改 + print(Batman.__mro__) # => (<class '__main__.Batman'>, + # => <class 'superhero.Superhero'>, + # => <class 'human.Human'>, + # => <class 'bat.Bat'>, <class 'object'>) + # 调用父类的方法并且使用子类的属性 + print(sup.get_species()) # => Superhuman + # 调用被重写的类 + print(sup.sing()) # => nan nan nan nan nan batman! + + # 调用 Human 上的方法,(之所以是 Human 而不是 Bat),是因为继承顺序起了作用 + sup.say('I agree') # => Sad Affleck: I agree + + # 调用仅存在于第二个继承的父类的方法 + print(sup.sonar()) # => ))) ... ((( + + # 继承类的属性 + sup.age = 100 + print(sup.age) # => 100 + + # 从第二个类上继承字段,并且其默认值被重写 + print('Can I fly? ' + str(sup.fly)) # => Can I fly? False + + +#################################################### +## 7. 高级用法 +#################################################### + +# 用生成器(generators)方便地写惰性运算 +def double_numbers(iterable): + for i in iterable: + yield i + i + +# 生成器只有在需要时才计算下一个值。它们每一次循环只生成一个值,而不是把所有的 +# 值全部算好。 +# +# range的返回值也是一个生成器,不然一个1到900000000的列表会花很多时间和内存。 +# +# 如果你想用一个Python的关键字当作变量名,可以加一个下划线来区分。 +range_ = range(1, 900000000) +# 当找到一个 >=30 的结果就会停 +# 这意味着 `double_numbers` 不会生成大于30的数。 +for i in double_numbers(range_): + print(i) + if i >= 30: + break +# 你也可以把一个生成器推导直接转换为列表 +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + + +# 装饰器(decorators) +# 这个例子中,beg装饰say +# beg会先调用say。如果返回的say_please为真,beg会改变返回的字符串。 +from functools import wraps + + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( ``` -## 更多阅读 -希望学到更多?试试下面的链接: -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/2/) +## 想继续学吗? + +### 在线免费材料(英文) + +* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com/) +* [The Official Docs](https://docs.python.org/3/) +* [Hitchhiker’s Guide to Python](https://docs.python-guide.org/en/latest/) +* [Python Course](https://www.python-course.eu/) +* [Free Interactive Python Course](http://www.kikodo.io/) +* [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python) +* [30 Python Language Features and Tricks You May Not Know About](https://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html) +* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/) +* [Python 3 Computer Science Circles](https://cscircles.cemc.uwaterloo.ca/) +* [Dive Into Python 3](https://www.diveintopython3.net/index.html) +* [A Crash Course in Python for Scientists](https://nbviewer.jupyter.org/gist/anonymous/5924718) +* [Python Tutorial for Intermediates](https://pythonbasics.org/) +* [Build a Desktop App with Python](https://pythonpyqt.com/) + +### 书籍(也是英文) + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown deleted file mode 100644 index fd962305..00000000 --- a/zh-cn/python3-cn.html.markdown +++ /dev/null @@ -1,632 +0,0 @@ ---- -language: python3 -contributors: - - ["Louie Dinh", "http://pythonpracticeprojects.com"] - - ["Steven Basart", "http://github.com/xksteven"] - - ["Andre Polykanine", "https://github.com/Oire"] -translators: - - ["Geoff Liu", "http://geoffliu.me"] -filename: learnpython3-cn.py -lang: zh-cn ---- - -Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计。 -它是如今最常用的编程语言之一。它的语法简洁且优美,几乎就是可执行的伪代码。 - -欢迎大家斧正。英文版原作 Louie Dinh [@louiedinh](http://twitter.com/louiedinh) -邮箱 louiedinh [at] [谷歌的信箱服务]。中文翻译 Geoff Liu。 - -注意:这篇教程是基于 Python 3 写的。如果你想学旧版 Python 2,我们特别有[另一篇教程](http://learnxinyminutes.com/docs/python/)。 - -```python - -# 用井字符开头的是单行注释 - -""" 多行字符串用三个引号 - 包裹,也常被用来做多 - 行注释 -""" - -#################################################### -## 1. 原始数据类型和运算符 -#################################################### - -# 整数 -3 # => 3 - -# 算术没有什么出乎意料的 -1 + 1 # => 2 -8 - 1 # => 7 -10 * 2 # => 20 - -# 但是除法例外,会自动转换成浮点数 -35 / 5 # => 7.0 -5 / 3 # => 1.6666666666666667 - -# 整数除法的结果都是向下取整 -5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # 浮点数也可以 --5 // 3 # => -2 --5.0 // 3.0 # => -2.0 - -# 浮点数的运算结果也是浮点数 -3 * 2.0 # => 6.0 - -# 模除 -7 % 3 # => 1 - -# x的y次方 -2**4 # => 16 - -# 用括号决定优先级 -(1 + 3) * 2 # => 8 - -# 布尔值 -True -False - -# 用not取非 -not True # => False -not False # => True - -# 逻辑运算符,注意and和or都是小写 -True and False # => False -False or True # => True - -# 整数也可以当作布尔值 -0 and 2 # => 0 --5 or 0 # => -5 -0 == False # => True -2 == True # => False -1 == True # => True - -# 用==判断相等 -1 == 1 # => True -2 == 1 # => False - -# 用!=判断不等 -1 != 1 # => False -2 != 1 # => True - -# 比较大小 -1 < 10 # => True -1 > 10 # => False -2 <= 2 # => True -2 >= 2 # => True - -# 大小比较可以连起来! -1 < 2 < 3 # => True -2 < 3 < 2 # => False - -# 字符串用单引双引都可以 -"这是个字符串" -'这也是个字符串' - -# 用加号连接字符串 -"Hello " + "world!" # => "Hello world!" - -# 字符串可以被当作字符列表 -"This is a string"[0] # => 'T' - -# 用.format来格式化字符串 -"{} can be {}".format("strings", "interpolated") - -# 可以重复参数以节省时间 -"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") -# => "Jack be nimble, Jack be quick, Jack jump over the candle stick" - -# 如果不想数参数,可以用关键字 -"{name} wants to eat {food}".format(name="Bob", food="lasagna") -# => "Bob wants to eat lasagna" - -# 如果你的Python3程序也要在Python2.5以下环境运行,也可以用老式的格式化语法 -"%s can be %s the %s way" % ("strings", "interpolated", "old") - -# None是一个对象 -None # => None - -# 当与None进行比较时不要用 ==,要用is。is是用来比较两个变量是否指向同一个对象。 -"etc" is None # => False -None is None # => True - -# None,0,空字符串,空列表,空字典都算是False -# 所有其他值都是True -bool(0) # => False -bool("") # => False -bool([]) # => False -bool({}) # => False - - -#################################################### -## 2. 变量和集合 -#################################################### - -# print是内置的打印函数 -print("I'm Python. Nice to meet you!") - -# 在给变量赋值前不用提前声明 -# 传统的变量命名是小写,用下划线分隔单词 -some_var = 5 -some_var # => 5 - -# 访问未赋值的变量会抛出异常 -# 参考流程控制一段来学习异常处理 -some_unknown_var # 抛出NameError - -# 用列表(list)储存序列 -li = [] -# 创建列表时也可以同时赋给元素 -other_li = [4, 5, 6] - -# 用append在列表最后追加元素 -li.append(1) # li现在是[1] -li.append(2) # li现在是[1, 2] -li.append(4) # li现在是[1, 2, 4] -li.append(3) # li现在是[1, 2, 4, 3] -# 用pop从列表尾部删除 -li.pop() # => 3 且li现在是[1, 2, 4] -# 把3再放回去 -li.append(3) # li变回[1, 2, 4, 3] - -# 列表存取跟数组一样 -li[0] # => 1 -# 取出最后一个元素 -li[-1] # => 3 - -# 越界存取会造成IndexError -li[4] # 抛出IndexError - -# 列表有切割语法 -li[1:3] # => [2, 4] -# 取尾 -li[2:] # => [4, 3] -# 取头 -li[:3] # => [1, 2, 4] -# 隔一个取一个 -li[::2] # =>[1, 4] -# 倒排列表 -li[::-1] # => [3, 4, 2, 1] -# 可以用三个参数的任何组合来构建切割 -# li[始:终:步伐] - -# 用del删除任何一个元素 -del li[2] # li is now [1, 2, 3] - -# 列表可以相加 -# 注意:li和other_li的值都不变 -li + other_li # => [1, 2, 3, 4, 5, 6] - -# 用extend拼接列表 -li.extend(other_li) # li现在是[1, 2, 3, 4, 5, 6] - -# 用in测试列表是否包含值 -1 in li # => True - -# 用len取列表长度 -len(li) # => 6 - - -# 元组是不可改变的序列 -tup = (1, 2, 3) -tup[0] # => 1 -tup[0] = 3 # 抛出TypeError - -# 列表允许的操作元组大都可以 -len(tup) # => 3 -tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) -tup[:2] # => (1, 2) -2 in tup # => True - -# 可以把元组合列表解包,赋值给变量 -a, b, c = (1, 2, 3) # 现在a是1,b是2,c是3 -# 元组周围的括号是可以省略的 -d, e, f = 4, 5, 6 -# 交换两个变量的值就这么简单 -e, d = d, e # 现在d是5,e是4 - - -# 用字典表达映射关系 -empty_dict = {} -# 初始化的字典 -filled_dict = {"one": 1, "two": 2, "three": 3} - -# 用[]取值 -filled_dict["one"] # => 1 - - -# 用 keys 获得所有的键。 -# 因为 keys 返回一个可迭代对象,所以在这里把结果包在 list 里。我们下面会详细介绍可迭代。 -# 注意:字典键的顺序是不定的,你得到的结果可能和以下不同。 -list(filled_dict.keys()) # => ["three", "two", "one"] - - -# 用values获得所有的值。跟keys一样,要用list包起来,顺序也可能不同。 -list(filled_dict.values()) # => [3, 2, 1] - - -# 用in测试一个字典是否包含一个键 -"one" in filled_dict # => True -1 in filled_dict # => False - -# 访问不存在的键会导致KeyError -filled_dict["four"] # KeyError - -# 用get来避免KeyError -filled_dict.get("one") # => 1 -filled_dict.get("four") # => None -# 当键不存在的时候get方法可以返回默认值 -filled_dict.get("one", 4) # => 1 -filled_dict.get("four", 4) # => 4 - -# setdefault方法只有当键不存在的时候插入新值 -filled_dict.setdefault("five", 5) # filled_dict["five"]设为5 -filled_dict.setdefault("five", 6) # filled_dict["five"]还是5 - -# 字典赋值 -filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4} -filled_dict["four"] = 4 # 另一种赋值方法 - -# 用del删除 -del filled_dict["one"] # 从filled_dict中把one删除 - - -# 用set表达集合 -empty_set = set() -# 初始化一个集合,语法跟字典相似。 -some_set = {1, 1, 2, 2, 3, 4} # some_set现在是{1, 2, 3, 4} - -# 可以把集合赋值于变量 -filled_set = some_set - -# 为集合添加元素 -filled_set.add(5) # filled_set现在是{1, 2, 3, 4, 5} - -# & 取交集 -other_set = {3, 4, 5, 6} -filled_set & other_set # => {3, 4, 5} - -# | 取并集 -filled_set | other_set # => {1, 2, 3, 4, 5, 6} - -# - 取补集 -{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} - -# in 测试集合是否包含元素 -2 in filled_set # => True -10 in filled_set # => False - - -#################################################### -## 3. 流程控制和迭代器 -#################################################### - -# 先随便定义一个变量 -some_var = 5 - -# 这是个if语句。注意缩进在Python里是有意义的 -# 印出"some_var比10小" -if some_var > 10: - print("some_var比10大") -elif some_var < 10: # elif句是可选的 - print("some_var比10小") -else: # else也是可选的 - print("some_var就是10") - - -""" -用for循环语句遍历列表 -打印: - dog is a mammal - cat is a mammal - mouse is a mammal -""" -for animal in ["dog", "cat", "mouse"]: - print("{} is a mammal".format(animal)) - -""" -"range(number)"返回数字列表从0到给的数字 -打印: - 0 - 1 - 2 - 3 -""" -for i in range(4): - print(i) - -""" -while循环直到条件不满足 -打印: - 0 - 1 - 2 - 3 -""" -x = 0 -while x < 4: - print(x) - x += 1 # x = x + 1 的简写 - -# 用try/except块处理异常状况 -try: - # 用raise抛出异常 - raise IndexError("This is an index error") -except IndexError as e: - pass # pass是无操作,但是应该在这里处理错误 -except (TypeError, NameError): - pass # 可以同时处理不同类的错误 -else: # else语句是可选的,必须在所有的except之后 - print("All good!") # 只有当try运行完没有错误的时候这句才会运行 - - -# Python提供一个叫做可迭代(iterable)的基本抽象。一个可迭代对象是可以被当作序列 -# 的对象。比如说上面range返回的对象就是可迭代的。 - -filled_dict = {"one": 1, "two": 2, "three": 3} -our_iterable = filled_dict.keys() -print(our_iterable) # => dict_keys(['one', 'two', 'three']),是一个实现可迭代接口的对象 - -# 可迭代对象可以遍历 -for i in our_iterable: - print(i) # 打印 one, two, three - -# 但是不可以随机访问 -our_iterable[1] # 抛出TypeError - -# 可迭代对象知道怎么生成迭代器 -our_iterator = iter(our_iterable) - -# 迭代器是一个可以记住遍历的位置的对象 -# 用__next__可以取得下一个元素 -our_iterator.__next__() # => "one" - -# 再一次调取__next__时会记得位置 -our_iterator.__next__() # => "two" -our_iterator.__next__() # => "three" - -# 当迭代器所有元素都取出后,会抛出StopIteration -our_iterator.__next__() # 抛出StopIteration - -# 可以用list一次取出迭代器所有的元素 -list(filled_dict.keys()) # => Returns ["one", "two", "three"] - - - -#################################################### -## 4. 函数 -#################################################### - -# 用def定义新函数 -def add(x, y): - print("x is {} and y is {}".format(x, y)) - return x + y # 用return语句返回 - -# 调用函数 -add(5, 6) # => 印出"x is 5 and y is 6"并且返回11 - -# 也可以用关键字参数来调用函数 -add(y=6, x=5) # 关键字参数可以用任何顺序 - - -# 我们可以定义一个可变参数函数 -def varargs(*args): - return args - -varargs(1, 2, 3) # => (1, 2, 3) - - -# 我们也可以定义一个关键字可变参数函数 -def keyword_args(**kwargs): - return kwargs - -# 我们来看看结果是什么: -keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} - - -# 这两种可变参数可以混着用 -def all_the_args(*args, **kwargs): - print(args) - print(kwargs) -""" -all_the_args(1, 2, a=3, b=4) prints: - (1, 2) - {"a": 3, "b": 4} -""" - -# 调用可变参数函数时可以做跟上面相反的,用*展开序列,用**展开字典。 -args = (1, 2, 3, 4) -kwargs = {"a": 3, "b": 4} -all_the_args(*args) # 相当于 foo(1, 2, 3, 4) -all_the_args(**kwargs) # 相当于 foo(a=3, b=4) -all_the_args(*args, **kwargs) # 相当于 foo(1, 2, 3, 4, a=3, b=4) - - -# 函数作用域 -x = 5 - -def setX(num): - # 局部作用域的x和全局域的x是不同的 - x = num # => 43 - print (x) # => 43 - -def setGlobalX(num): - global x - print (x) # => 5 - x = num # 现在全局域的x被赋值 - print (x) # => 6 - -setX(43) -setGlobalX(6) - - -# 函数在Python是一等公民 -def create_adder(x): - def adder(y): - return x + y - return adder - -add_10 = create_adder(10) -add_10(3) # => 13 - -# 也有匿名函数 -(lambda x: x > 2)(3) # => True - -# 内置的高阶函数 -map(add_10, [1, 2, 3]) # => [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] - -# 用列表推导式可以简化映射和过滤。列表推导式的返回值是另一个列表。 -[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] - -#################################################### -## 5. 类 -#################################################### - - -# 定义一个继承object的类 -class Human(object): - - # 类属性,被所有此类的实例共用。 - species = "H. sapiens" - - # 构造方法,当实例被初始化时被调用。注意名字前后的双下划线,这是表明这个属 - # 性或方法对Python有特殊意义,但是允许用户自行定义。你自己取名时不应该用这 - # 种格式。 - def __init__(self, name): - # Assign the argument to the instance's name attribute - self.name = name - - # 实例方法,第一个参数总是self,就是这个实例对象 - def say(self, msg): - return "{name}: {message}".format(name=self.name, message=msg) - - # 类方法,被所有此类的实例共用。第一个参数是这个类对象。 - @classmethod - def get_species(cls): - return cls.species - - # 静态方法。调用时没有实例或类的绑定。 - @staticmethod - def grunt(): - return "*grunt*" - - -# 构造一个实例 -i = Human(name="Ian") -print(i.say("hi")) # 印出 "Ian: hi" - -j = Human("Joel") -print(j.say("hello")) # 印出 "Joel: hello" - -# 调用一个类方法 -i.get_species() # => "H. sapiens" - -# 改一个共用的类属性 -Human.species = "H. neanderthalensis" -i.get_species() # => "H. neanderthalensis" -j.get_species() # => "H. neanderthalensis" - -# 调用静态方法 -Human.grunt() # => "*grunt*" - - -#################################################### -## 6. 模块 -#################################################### - -# 用import导入模块 -import math -print(math.sqrt(16)) # => 4.0 - -# 也可以从模块中导入个别值 -from math import ceil, floor -print(ceil(3.7)) # => 4.0 -print(floor(3.7)) # => 3.0 - -# 可以导入一个模块中所有值 -# 警告:不建议这么做 -from math import * - -# 如此缩写模块名字 -import math as m -math.sqrt(16) == m.sqrt(16) # => True - -# Python模块其实就是普通的Python文件。你可以自己写,然后导入, -# 模块的名字就是文件的名字。 - -# 你可以这样列出一个模块里所有的值 -import math -dir(math) - - -#################################################### -## 7. 高级用法 -#################################################### - -# 用生成器(generators)方便地写惰性运算 -def double_numbers(iterable): - for i in iterable: - yield i + i - -# 生成器只有在需要时才计算下一个值。它们每一次循环只生成一个值,而不是把所有的 -# 值全部算好。 -# -# range的返回值也是一个生成器,不然一个1到900000000的列表会花很多时间和内存。 -# -# 如果你想用一个Python的关键字当作变量名,可以加一个下划线来区分。 -range_ = range(1, 900000000) -# 当找到一个 >=30 的结果就会停 -# 这意味着 `double_numbers` 不会生成大于30的数。 -for i in double_numbers(range_): - print(i) - if i >= 30: - break - - -# 装饰器(decorators) -# 这个例子中,beg装饰say -# beg会先调用say。如果返回的say_please为真,beg会改变返回的字符串。 -from functools import wraps - - -def beg(target_function): - @wraps(target_function) - def wrapper(*args, **kwargs): - msg, say_please = target_function(*args, **kwargs) - if say_please: - return "{} {}".format(msg, "Please! I am poor :(") - return msg - - return wrapper - - -@beg -def say(say_please=False): - msg = "Can you buy me a beer?" - return msg, say_please - - -print(say()) # Can you buy me a beer? -print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( -``` - -## 想继续学吗? - -### 线上免费材料(英文) - -* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) -* [Dive Into Python](http://www.diveintopython.net/) -* [Ideas for Python Projects](http://pythonpracticeprojects.com) - -* [The Official Docs](http://docs.python.org/3/) -* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) -* [Python Module of the Week](http://pymotw.com/3/) -* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) - -### 书籍(也是英文) - -* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) -* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) - diff --git a/zh-cn/pythonlegacy-cn.html.markdown b/zh-cn/pythonlegacy-cn.html.markdown new file mode 100644 index 00000000..f8aa2332 --- /dev/null +++ b/zh-cn/pythonlegacy-cn.html.markdown @@ -0,0 +1,476 @@ +--- +language: Python 2 (legacy) +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +filename: learnpythonlegacy-zh.py +lang: zh-cn +--- + +Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语言之一 +我喜爱python是因为它有极为清晰的语法,甚至可以说,它就是可以执行的伪代码 + +很欢迎来自您的反馈,你可以在[@louiedinh](http://twitter.com/louiedinh) 和 louiedinh [at] [google's email service] 这里找到我 + +注意: 这篇文章针对的版本是Python 2.7,但大多也可使用于其他Python 2的版本 +如果是Python 3,请在网络上寻找其他教程 + +```python + +# 单行注释 +""" 多行字符串可以用 + 三个引号包裹,不过这也可以被当做 + 多行注释 +""" + +#################################################### +## 1. 原始数据类型和操作符 +#################################################### + +# 数字类型 +3 # => 3 + +# 简单的算数 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7 + +# 整数的除法会自动取整 +5 / 2 # => 2 + +# 要做精确的除法,我们需要引入浮点数 +2.0 # 浮点数 +11.0 / 4.0 # => 2.75 精确多了 + +# 括号具有最高优先级 +(1 + 3) * 2 # => 8 + +# 布尔值也是基本的数据类型 +True +False + +# 用 not 来取非 +not True # => False +not False # => True + +# 相等 +1 == 1 # => True +2 == 1 # => False + +# 不等 +1 != 1 # => False +2 != 1 # => True + +# 更多的比较操作符 +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# 比较运算可以连起来写! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# 字符串通过 " 或 ' 括起来 +"This is a string." +'This is also a string.' + +# 字符串通过加号拼接 +"Hello " + "world!" # => "Hello world!" + +# 字符串可以被视为字符的列表 +"This is a string"[0] # => 'T' + +# % 可以用来格式化字符串 +"%s can be %s" % ("strings", "interpolated") + +# 也可以用 format 方法来格式化字符串 +# 推荐使用这个方法 +"{0} can be {1}".format("strings", "formatted") +# 也可以用变量名代替数字 +"{name} wants to eat {food}".format(name="Bob", food="lasagna") + +# None 是对象 +None # => None + +# 不要用相等 `==` 符号来和None进行比较 +# 要用 `is` +"etc" is None # => False +None is None # => True + +# 'is' 可以用来比较对象的相等性 +# 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少 + +# None, 0, 和空字符串都被算作 False +# 其他的均为 True +0 == False # => True +"" == False # => True + + +#################################################### +## 2. 变量和集合 +#################################################### + +# 很方便的输出 +print "I'm Python. Nice to meet you!" + + +# 给变量赋值前不需要事先声明 +some_var = 5 # 一般建议使用小写字母和下划线组合来做为变量名 +some_var # => 5 + +# 访问未赋值的变量会抛出异常 +# 可以查看控制流程一节来了解如何异常处理 +some_other_var # 抛出 NameError + +# if 语句可以作为表达式来使用 +"yahoo!" if 3 > 2 else 2 # => "yahoo!" + +# 列表用来保存序列 +li = [] +# 可以直接初始化列表 +other_li = [4, 5, 6] + +# 在列表末尾添加元素 +li.append(1) # li 现在是 [1] +li.append(2) # li 现在是 [1, 2] +li.append(4) # li 现在是 [1, 2, 4] +li.append(3) # li 现在是 [1, 2, 4, 3] +# 移除列表末尾元素 +li.pop() # => 3 li 现在是 [1, 2, 4] +# 重新加进去 +li.append(3) # li is now [1, 2, 4, 3] again. + +# 像其他语言访问数组一样访问列表 +li[0] # => 1 +# 访问最后一个元素 +li[-1] # => 3 + +# 越界会抛出异常 +li[4] # 抛出越界异常 + +# 切片语法需要用到列表的索引访问 +# 可以看做数学之中左闭右开区间 +li[1:3] # => [2, 4] +# 省略开头的元素 +li[2:] # => [4, 3] +# 省略末尾的元素 +li[:3] # => [1, 2, 4] + +# 删除特定元素 +del li[2] # li 现在是 [1, 2, 3] + +# 合并列表 +li + other_li # => [1, 2, 3, 4, 5, 6] - 并不会改变这两个列表 + +# 通过拼接来合并列表 +li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6] + +# 用 in 来返回元素是否在列表中 +1 in li # => True + +# 返回列表长度 +len(li) # => 6 + + +# 元组类似于列表,但它是不可改变的 +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # 类型错误 + +# 对于大多数的列表操作,也适用于元组 +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# 你可以将元组解包赋给多个变量 +a, b, c = (1, 2, 3) # a 是 1,b 是 2,c 是 3 +# 如果不加括号,将会被自动视为元组 +d, e, f = 4, 5, 6 +# 现在我们可以看看交换两个数字是多么容易的事 +e, d = d, e # d 是 5,e 是 4 + + +# 字典用来储存映射关系 +empty_dict = {} +# 字典初始化 +filled_dict = {"one": 1, "two": 2, "three": 3} + +# 字典也用中括号访问元素 +filled_dict["one"] # => 1 + +# 把所有的键保存在列表中 +filled_dict.keys() # => ["three", "two", "one"] +# 键的顺序并不是唯一的,得到的不一定是这个顺序 + +# 把所有的值保存在列表中 +filled_dict.values() # => [3, 2, 1] +# 和键的顺序相同 + +# 判断一个键是否存在 +"one" in filled_dict # => True +1 in filled_dict # => False + +# 查询一个不存在的键会抛出 KeyError +filled_dict["four"] # KeyError + +# 用 get 方法来避免 KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# get 方法支持在不存在的时候返回一个默认值 +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 + +# setdefault 是一个更安全的添加字典元素的方法 +filled_dict.setdefault("five", 5) # filled_dict["five"] 的值为 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] 的值仍然是 5 + + +# 集合储存无顺序的元素 +empty_set = set() +# 初始化一个集合 +some_set = set([1, 2, 2, 3, 4]) # some_set 现在是 set([1, 2, 3, 4]) + +# Python 2.7 之后,大括号可以用来表示集合 +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# 向集合添加元素 +filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} + +# 用 & 来计算集合的交 +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# 用 | 来计算集合的并 +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# 用 - 来计算集合的差 +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# 用 in 来判断元素是否存在于集合中 +2 in filled_set # => True +10 in filled_set # => False + + +#################################################### +## 3. 控制流程 +#################################################### + +# 新建一个变量 +some_var = 5 + +# 这是个 if 语句,在 python 中缩进是很重要的。 +# 下面的代码片段将会输出 "some var is smaller than 10" +if some_var > 10: + print "some_var is totally bigger than 10." +elif some_var < 10: # 这个 elif 语句是不必须的 + print "some_var is smaller than 10." +else: # 这个 else 也不是必须的 + print "some_var is indeed 10." + + +""" +用for循环遍历列表 +输出: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # 你可以用 % 来格式化字符串 + print "%s is a mammal" % animal + +""" +`range(number)` 返回从0到给定数字的列表 +输出: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +while 循环 +输出: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # x = x + 1 的简写 + +# 用 try/except 块来处理异常 + +# Python 2.6 及以上适用: +try: + # 用 raise 来抛出异常 + raise IndexError("This is an index error") +except IndexError as e: + pass # pass 就是什么都不做,不过通常这里会做一些恢复工作 + + +#################################################### +## 4. 函数 +#################################################### + +# 用 def 来新建函数 +def add(x, y): + print "x is %s and y is %s" % (x, y) + return x + y # 通过 return 来返回值 + +# 调用带参数的函数 +add(5, 6) # => 输出 "x is 5 and y is 6" 返回 11 + +# 通过关键字赋值来调用函数 +add(y=6, x=5) # 顺序是无所谓的 + +# 我们也可以定义接受多个变量的函数,这些变量是按照顺序排列的 +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1,2,3) + + +# 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的 +def keyword_args(**kwargs): + return kwargs + +# 实际效果: +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + +# 你也可以同时将一个函数定义成两种形式 +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# 当调用函数的时候,我们也可以进行相反的操作,把元组和字典展开为参数 +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # 等价于 foo(1, 2, 3, 4) +all_the_args(**kwargs) # 等价于 foo(a=3, b=4) +all_the_args(*args, **kwargs) # 等价于 foo(1, 2, 3, 4, a=3, b=4) + +# 函数在 python 中是一等公民 +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# 匿名函数 +(lambda x: x > 2)(3) # => True + +# 内置高阶函数 +map(add_10, [1, 2, 3]) # => [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# 可以用列表方法来对高阶函数进行更巧妙的引用 +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +#################################################### +## 5. 类 +#################################################### + +# 我们新建的类是从 object 类中继承的 +class Human(object): + + # 类属性,由所有类的对象共享 + species = "H. sapiens" + + # 基本构造函数 + def __init__(self, name): + # 将参数赋给对象成员属性 + self.name = name + + # 成员方法,参数要有 self + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # 类方法由所有类的对象共享 + # 这类方法在调用时,会把类本身传给第一个参数 + @classmethod + def get_species(cls): + return cls.species + + # 静态方法是不需要类和对象的引用就可以调用的方法 + @staticmethod + def grunt(): + return "*grunt*" + + +# 实例化一个类 +i = Human(name="Ian") +print i.say("hi") # 输出 "Ian: hi" + +j = Human("Joel") +print j.say("hello") # 输出 "Joel: hello" + +# 访问类的方法 +i.get_species() # => "H. sapiens" + +# 改变共享属性 +Human.species = "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" + +# 访问静态变量 +Human.grunt() # => "*grunt*" + + +#################################################### +## 6. 模块 +#################################################### + +# 我们可以导入其他模块 +import math +print math.sqrt(16) # => 4.0 + +# 我们也可以从一个模块中导入特定的函数 +from math import ceil, floor +print ceil(3.7) # => 4.0 +print floor(3.7) # => 3.0 + +# 从模块中导入所有的函数 +# 警告:不推荐使用 +from math import * + +# 简写模块名 +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Python的模块其实只是普通的python文件 +# 你也可以创建自己的模块,并且导入它们 +# 模块的名字就和文件的名字相同 + +# 也可以通过下面的方法查看模块中有什么属性和方法 +import math +dir(math) + + +``` + +## 更多阅读 + +希望学到更多?试试下面的链接: + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) diff --git a/zh-cn/qt-cn.html.markdown b/zh-cn/qt-cn.html.markdown new file mode 100644 index 00000000..1d24f200 --- /dev/null +++ b/zh-cn/qt-cn.html.markdown @@ -0,0 +1,160 @@ +--- +category: tool +tool: Qt Framework +language: C++ +filename: learnqt-cn.cpp +contributors: + - ["Aleksey Kholovchuk", "https://github.com/vortexxx192"] +translators: + - ["GengchenXU", "https://github.com/GengchenXU"] +lang: zh-cn + +--- + +**Qt** Qt是一个广为人知的框架,用于开发跨平台软件,该软件可以在各种软件和硬件平台上运行,代码几乎没有变化,同时具有本机应用程序的能力和速度。虽然**Qt**最初是用*C*++,但也有其他语言的端口: *[PyQt](https://learnxinyminutes.com/docs/pyqt/)*, *QtRuby*, *PHP-Qt*, 等等. + +**Qt** 非常适合使用图形用户界面 (GUI) 创建应用程序。本教程是关于如何用*C++*去实现。 + +```c++ +/* + * 让我们从最经典的开始 + */ + +// Qt框架的所有标头均以大写字母'Q'开头 +#include <QApplication> +#include <QLineEdit> + +int main(int argc, char *argv[]) { + // 创建一个对象来管理应用程序范围内的资源 + QApplication app(argc, argv); + + // 创建行编辑widgets并在屏幕上显示 + QLineEdit lineEdit("Hello world!"); + lineEdit.show(); + + // 启动应用程序的事件循环 + return app.exec(); +} +``` + +**Qt**与 GUI 相关的部分与*widgets*及其之间的*connection*有关。 + +[阅读更多有关widgets的信息](http://doc.qt.io/qt-5/qtwidgets-index.html) + +```c++ +/* + * 让我们创建一个标签和一个按钮。 + * 按下按钮时应显示一个标签。 + * Qt代码本身就可以说明问题。 + */ + +#include <QApplication> +#include <QDialog> +#include <QVBoxLayout> +#include <QPushButton> +#include <QLabel> + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + QDialog dialogWindow; + dialogWindow.show(); + + // 添加垂直布局 + QVBoxLayout layout; + dialogWindow.setLayout(&layout); + + QLabel textLabel("Thanks for pressing that button"); + layout.addWidget(&textLabel); + textLabel.hide(); + + QPushButton button("Press me"); + layout.addWidget(&button); + + // 按下按钮时显示隐藏标签 + QObject::connect(&button, &QPushButton::pressed, + &textLabel, &QLabel::show); + + return app.exec(); +} +``` + +注意,*QObject :: connect*部分。 此方法用于将一个对象的*SIGNAL*连接到另一个对象的*SLOTS*。 + +**Signals** 会被发出当对象发生某些事情时,例如当用户按下QPushButton对象时会发出*push*的信号。 + +**Slots** 是可以响应于接收到的信号而执行的*action*。 + +[阅读有关SLOTS和SIGNALS的更多信息](http://doc.qt.io/qt-5/signalsandslots.html) + + +接下来,让我们了解到我们不仅可以使用标准的wigets,而且可以通过继承扩展其行为。 让我们创建一个按钮并计算其被按下的次数。 为此,我们定义了自己的类* CounterLabel *。 由于特定的Qt体系结构,必须在单独的文件中声明它。 + +```c++ +// counterlabel.hpp + +#ifndef COUNTERLABEL +#define COUNTERLABEL + +#include <QLabel> + +class CounterLabel : public QLabel { + Q_OBJECT // 在每个自定义wiget中必须存在的Qt定义的宏 + +public: + CounterLabel() : counter(0) { + setText("Counter has not been increased yet"); // QLabel方法 + } + +public slots: + // 将响应按钮按下而调用的操作 + void increaseCounter() { + setText(QString("Counter value: %1").arg(QString::number(++counter))); + } + +private: + int counter; +}; + +#endif // COUNTERLABEL +``` + +```c++ +// main.cpp +// 与前面的示例几乎相同 + +#include <QApplication> +#include <QDialog> +#include <QVBoxLayout> +#include <QPushButton> +#include <QString> +#include "counterlabel.hpp" + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + QDialog dialogWindow; + dialogWindow.show(); + + QVBoxLayout layout; + dialogWindow.setLayout(&layout); + + CounterLabel counterLabel; + layout.addWidget(&counterLabel); + + QPushButton button("Push me once more"); + layout.addWidget(&button); + QObject::connect(&button, &QPushButton::pressed, + &counterLabel, &CounterLabel::increaseCounter); + + return app.exec(); +} +``` + +当然,Qt框架比本教程介绍的部分要复杂得多,因此请仔细阅读和练习。 + +## 进一步阅读 +- [Qt 4.8 tutorials](http://doc.qt.io/qt-4.8/tutorials.html) +- [Qt 5 tutorials](http://doc.qt.io/qt-5/qtexamplesandtutorials.html) + +祝你好运,生活愉快! diff --git a/zh-cn/racket-cn.html.markdown b/zh-cn/racket-cn.html.markdown index 8ef3671f..b373e1d9 100644 --- a/zh-cn/racket-cn.html.markdown +++ b/zh-cn/racket-cn.html.markdown @@ -444,7 +444,7 @@ n ; => 6 (set-box! n* (add1 (unbox n*))) (unbox n*) ; => 6 -;; 很多 Racket 诗句类型是不可变的 (对,列表,等),有一些既是可变的 +;; 很多 Racket 数据类型是不可变的 (对,列表,等),有一些既是可变的 ;; 又是不可变的 (字符串,向量,散列表 ;; 等...) diff --git a/zh-cn/raylib-cn.html.markdown b/zh-cn/raylib-cn.html.markdown new file mode 100644 index 00000000..c88aa91e --- /dev/null +++ b/zh-cn/raylib-cn.html.markdown @@ -0,0 +1,147 @@ +--- +category: tool +tool: raylib +lang: zh-cn +filename: learnraylib-cn.c +contributors: + - ["Nikolas Wipper", "https://notnik.cc"] +translators: + - ["lzw-723", "https://github.com/lzw-723"] +--- + +**raylib** 是一个跨平台、易用的图形库,围绕OpenGL 1.1、2.1、3.3和OpenGL ES 2.0构建。 +虽然它是用C语言编写的,却有超过50种不同语言的绑定。本教程将使用C语言。 +更确切地说,是C99。 + +```c +#include <raylib.h> + +int main(void) +{ + const int screenWidth = 800; + const int screenHeight = 450; + + // 在初始化raylib之前,可以设置标志位 + SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); + + // raylib并不要求我们存储任何实例结构 + // 目前raylib一次只能处理一个窗口 + InitWindow(screenWidth, screenHeight, "MyWindow"); + + // 设置我们的游戏以每秒60帧的速度运行 + SetTargetFPS(60); + + // 设置一个关闭窗口的键。 + //可以是0,表示没有键 + SetExitKey(KEY_DELETE); + + // raylib定义了两种类型的相机。Camera3D和Camera2D + // Camera是Camera3D的一个类型化定义 + Camera camera = { + .position = {0.0f, 0.0f, 0.0f}, + .target = {0.0f, 0.0f, 1.0f}, + .up = {0.0f, 1.0f, 0.0f}, + .fovy = 70.0f, + .type = CAMERA_PERSPECTIVE + }; + + + // raylib支持加载各种不同的文件格式的模型、动画、图像和声音。 + Model myModel = LoadModel("my_model.obj"); + Font someFont = LoadFont("some_font.ttf"); + + // 创建一个100x100的渲染纹理 + RenderTexture renderTexture = LoadRenderTexture(100, 100); + + // WindowShouldClose方法检查用户是否正在关闭窗口。 + // 可能用的是快捷方式、窗口控制或之前设置的关闭窗口键 + while (!WindowShouldClose()) + { + + // BeginDrawing方法要在任何绘图操作之前被调用。 + BeginDrawing(); + { + + // 为背景设定某种颜色 + ClearBackground(BLACK); + + if (IsKeyDown(KEY_SPACE)) + DrawCircle(400, 400, 30, GREEN); + + // 简单地绘制文本 + DrawText("Congrats! You created your first window!", + 190, // x + 200, // y + 20, // 字体大小 + LIGHTGRAY + ); + + // 大多数函数都有几个版本 + // 通常后缀为Ex, Pro, V + // 或者是Rec、Wires(仅适用于3D)、Lines(仅适用于2D)。 + DrawTextEx(someFont, + "Text in another font", + (Vector2) {10, 10}, + 20, // 字体大小 + 2, // 间距 + LIGHTGRAY); + + // 绘制3D时需要,有2D的等价方法 + BeginMode3D(camera); + { + + DrawCube((Vector3) {0.0f, 0.0f, 3.0f}, + 1.0f, 1.0f, 1.0f, RED); + + // 绘图时的白色色调将保持原来的颜色 + DrawModel(myModel, (Vector3) {0.0f, 0.0f, 3.0f}, + 1.0f, // 缩放 + WHITE); + + } + // 结束3D模式,这样就可以再次普通绘图 + EndMode3D(); + + // 开始在渲染纹理上绘图 + BeginTextureMode(renderTexture); + { + + // 它的行为与刚才调用的`BeginDrawing()`方法相同 + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + { + + DrawGrid(10, // Slices + 1.0f // 间距 + ); + + } + EndMode3D(); + + } + EndTextureMode(); + + // 渲染有Texture2D字段的纹理 + DrawTexture(renderTexture.texture, 40, 378, BLUE); + + } + EndDrawing(); + } + + // 卸载已载入的对象 + UnloadFont(someFont); + UnloadModel(myModel); + + // 关闭窗口和OpenGL上下文 + CloseWindow(); + + return 0; +} + +``` + +## 延伸阅读 +raylib有一些[不错的例子](https://www.raylib.com/examples.html) +如果你不喜欢C语言你也可以看看[raylib的其他语言绑定](https://github.com/raysan5/raylib/blob/master/BINDINGS.md) diff --git a/zh-cn/red-cn.html.markdown b/zh-cn/red-cn.html.markdown index 85812990..7fee007e 100644 --- a/zh-cn/red-cn.html.markdown +++ b/zh-cn/red-cn.html.markdown @@ -150,11 +150,11 @@ msg: either a > 0 [ ] print ["a 是 " msg lf] -; util +; until ; 循环执行一段代码块,直到满足给定的条件为止。 -; util 没有返回值,所以它不能用在表示式中。 +; UNTIL 在最后一次循环执行完最后一个表达式后,总是返回真值 'true'。 c: 5 -util [ +until [ prin "o" c: c - 1 c = 0 ; 终止循环的条件 @@ -193,15 +193,15 @@ print twice b ; 输出 6 ## 更进一步 -Red 相关的源码信息在 [Red 语言主页](http://www.red-lang.org)。 +Red 相关的源码信息在 [Red 语言主页](https://www.red-lang.org)。 源代码的 [github 库](https://github.com/red/red)。 -Red/System 特性在 [这里](http://static.red-lang.org/red-system-specs-light.html)。 +Red/System 特性在 [这里](https://static.red-lang.org/red-system-specs-light.html)。 想要了解更多关于 Rebol 和 Red 的信息,加入 [Gitter 聊天室](https://gitter.im/red/red)。如果你无法加入,也可以给我们发[邮件](mailto:red-langNO_SPAM@googlegroups.com)。 -也可以在 [Stack Overflow](stackoverflow.com/questions/tagged/red) 上查阅、提交问题。 +也可以在 [Stack Overflow](https://stackoverflow.com/questions/tagged/red) 上查阅、提交问题。 也许你现在就要试一试 Red ?可以在线尝试 [try Rebol and Red site](http://tryrebol.esperconsultancy.nl)。 diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index 9918c022..b0b8b58c 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -430,7 +430,7 @@ def guests(*array) array.each { |guest| puts guest } end -# 结构 +# 解构 # 如果函数返回一个数组,在赋值时可以进行拆分: def foods @@ -449,7 +449,7 @@ end best *ranked_competitors.first(3) #=> Winners are John, Sally, and Dingus. -# 结构操作符也可放在参数里面 +# 解构操作符也可放在参数里面 def best(first, second, third, *others) puts "Winners are #{first}, #{second}, and #{third}." puts "There were #{others.count} other participants." @@ -657,4 +657,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/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online. - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide. -- [Try Ruby](http://tryruby.org) - Learn the basic of Ruby programming language, interactive in the browser. +- [Try Ruby](https://try.ruby-lang.org/) - Learn the basic of Ruby programming language, interactive in the browser. diff --git a/zh-cn/rust-cn.html.markdown b/zh-cn/rust-cn.html.markdown index 5d3fc693..6bed1650 100644 --- a/zh-cn/rust-cn.html.markdown +++ b/zh-cn/rust-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: rust +language: Rust contributors: - ["P1start", "http://p1start.github.io/"] translators: @@ -211,7 +211,7 @@ fn main() { // `for` 循环 let array = [1, 2, 3]; - for i in array.iter() { + for i in array { println!("{}", i); } diff --git a/zh-cn/set-theory-cn.html.markdown b/zh-cn/set-theory-cn.html.markdown new file mode 100644 index 00000000..13ba2c80 --- /dev/null +++ b/zh-cn/set-theory-cn.html.markdown @@ -0,0 +1,138 @@ +--- +category: Algorithms & Data Structures +name: Set theory +contributors: +translators: + - ["Tianchen Xu", "https://github.com/lo0b0o"] +lang: zh-cn +--- +集合论是数学的一个分支,研究集合、它们的运算和它们的性质。 + +* 集合由不重复的项组成。 + +## 基本符号 + +### 运算符 +* 并运算符,`∪`,表示“或”; +* 交运算符,`∩`,表示“且”; +* 差运算符,`\`,表示“不包括”; +* 补运算符,`'`,表示补集; +* 叉积运算符,`×`,表示笛卡尔积。 + +### 限定词 +* 冒号限定词,`:`,表示“使得”; +* 从属限定词,`∈`,表示“属于”; +* 子集限定词,`⊆`,表示“是……的子集”; +* 真子集限定词,`⊂`,表示“是……的真子集”。 + +### 重要的集合 +* `∅`,空集,即不包含任何元素的集合; +* `ℕ`,自然数集; +* `ℤ`,整数集; +* `ℚ`,有理数集; +* `ℝ`,实数集。 + +关于以上集合,有如下几点需要注意: +1. 空集是其本身的子集(并且也是任何其他集合的子集),即便空集不包含任何项; +2. 数学家们对于零是否为自然数的看法通常并不统一,教科书一般会明确说明作者是否认为零是自然数。 + +### 基数 + +集合的基数,或者说大小,由该集合中的项目数量决定。基数运算符为 `|...|`。 + +例如,若 `S = { 1, 2, 4 }`,则 `|S| = 3`。 + +### 空集 + +* 可以在集合符号中使用不成立的条件来构造空集,例如,`∅ = { x : x ≠ x }`,或 `∅ = { x : x ∈ N, x < 0 }`; +* 空集总是唯一的(即,有且只有一个空集); +* 空集是所有集合的子集; +* 空集的基数为 0,即 `|∅| = 0`。 + +## 集合的表示 + +### 集合的逐项构造 + +集合可以通过包含其全部项的列表逐项生成。例如,`S = { a, b, c, d }`。 + +只要构成集合的项清楚,长列表可以用省略号缩短。例如,`E = { 2, 4, 6, 8, ... }` 显然为所有偶数构成的集合,它包含无穷多项,虽然我们只显式写出了其中四项。 + +### 集合构造器 + +集合构造器符号是构造集合的一种更具描述性的方式。它依赖于一个主语和一个谓词,使得 `S = { 主语 : 谓词 }`。 例如, + +``` +A = { x : x 是元音字母 } = { a, e, i, o, u, y} +B = { x : x ∈ N, x < 10 } = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } +C = { x : x = 2k, k ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +有时,谓词可能会 "漏 "到主语中,例如, + +``` +D = { 2x : x ∈ N } = { 0, 2, 4, 6, 8, ... } +``` + +## 关系 + +### 从属关系 + +* 如果值 `a` 包含在集合 `A` 中,那么我们说 `a` 属于 `A`,并用符号表示为 `a ∈ A`。 +* 如果值 `a` 不包含于集合 `A` 中,那么我们说 `a` 不属于 `A`,并用符号表示为 `a ∉ A`。 + +### 相等关系 + +* 如果两个集合包括相同的项,那么我们说这两个集合相等,例如,`A = B`。 +* 集合的相等关系于顺序无关,例如 `{ 1, 2, 3, 4 } = { 2, 3, 1, 4 }`。 +* 集合中的元素不能重复,例如 `{ 1, 2, 2, 3, 4, 3, 4, 2 } = { 1, 2, 3, 4 }`。 +* 集合 `A` 与 `B` 相等当且仅当 `A ⊆ B` 且 `B ⊆ A`。 + +## 特殊集合 + +### 幂集 + +* 令 `A` 为任意集合。幂集指的是包括了 `A` 的所有子集的集合,记作 `P(A)`。如果集合 `A` 由 `2n` 个元素组成,那么 `P(A)` 中有 `2^n` 个元素。 + +``` +P(A) = { x : x ⊆ A } +``` + +## 两个集合的运算 +### 并 + +给定集合 `A` 和 `B`,两个集合的并由出现在 `A` 或 `B` 中的项构成,记作 `A ∪ B`。 + +``` +A ∪ B = { x : x ∈ A ∪ x ∈ B } +``` + +### 交 + +给定集合 `A` 和 `B`,两个集合的交由出现在 `A` 和 `B` 中的项构成,记作 `A ∩ B`。 + +``` +A ∩ B = { x : x ∈ A, x ∈ B } +``` + +### 差 +给定集合 `A` 和 `B`,`A` 对于 `B` 的集合差指的是属于 `A` 但不属于 `B` 的每一项。 + +``` +A \ B = { x : x ∈ A, x ∉ B } +``` + +### 对称差 +给定集合 `A` 和 `B`,对称差指的是属于 `A` 或 `B` 但不属于它们交集的所有项。 + +``` +A △ B = { x : ((x ∈ A) ∩ (x ∉ B)) ∪ ((x ∈ B) ∩ (x ∉ A)) } + +A △ B = (A \ B) ∪ (B \ A) +``` + +### 笛卡尔积 +给定集合 `A` 和 `B`,`A` 和 `B` 的笛卡尔积由 `A` 和 `B` 的项的所有组合构成。 + +``` +A × B = { (x, y) | x ∈ A, y ∈ B } +``` diff --git a/zh-cn/solidity-cn.html.markdown b/zh-cn/solidity-cn.html.markdown index ec684997..12a532bc 100644 --- a/zh-cn/solidity-cn.html.markdown +++ b/zh-cn/solidity-cn.html.markdown @@ -213,7 +213,7 @@ names.length; // 获得数组长度 names.length = 1; // 可以设定长度(仅针对 storage 中的动态数组) // 多维数组 -uint x[][5]; // 5个动态数组元素的数组(和多数语言的顺序相反) +uint[][5] x; // 5个动态数组元素的数组(和多数语言的顺序相反) // 字典类型 (任一类型到其他类型的映射) mapping (string => uint) public balances; diff --git a/zh-cn/sql.html.markdown b/zh-cn/sql-cn.html.markdown index 9d430bd1..9d430bd1 100644 --- a/zh-cn/sql.html.markdown +++ b/zh-cn/sql-cn.html.markdown diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index 18bc52ed..c56a0d33 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -10,7 +10,7 @@ translators: lang: zh-cn --- -Swift 是 Apple 开发的用于 iOS 和 OS X 开发的编程语言。Swift 于2014年 Apple WWDC (全球开发者大会)中被引入,用以与 Objective-C 共存,同时对错误代码更具弹性。Swift 由 Xcode 6 beta 中包含的 LLVM 编译器编译。 +Swift 是 Apple 开发的用于 iOS 和 macOS 开发的编程语言。Swift 于2014年 Apple WWDC (全球开发者大会)中被引入,用以与 Objective-C 共存,同时对错误代码更具弹性。Swift 由 Xcode 6 beta 中包含的 LLVM 编译器编译。 Swift 的官方语言教程 [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) 可以从 iBooks 免费下载. diff --git a/zh-cn/visualbasic-cn.html.markdown b/zh-cn/visualbasic-cn.html.markdown index e30041b3..cda7b864 100644 --- a/zh-cn/visualbasic-cn.html.markdown +++ b/zh-cn/visualbasic-cn.html.markdown @@ -8,7 +8,7 @@ lang: zh-cn filename: learnvisualbasic-cn.vb --- -``` +```visualbasic Module Module1 Sub Main() diff --git a/zh-cn/wolfram-cn.html.markdown b/zh-cn/wolfram-cn.html.markdown new file mode 100644 index 00000000..64990234 --- /dev/null +++ b/zh-cn/wolfram-cn.html.markdown @@ -0,0 +1,140 @@ +--- +language: wolfram +contributors: + - ["hyphz", "http://github.com/hyphz/"] +translators: + - ["wuyudi", "http://github.com/wuyudi/"] +filename: learnwolfram-cn.nb +lang: zh-cn +--- + +Wolfram 语言是最初在 Mathematica 中使用的底层语言,但现在可用于多种场合。 + +Wolfram 语言有几个界面。 + +- Raspberry Pi 上的命令行内核界面(就叫 _The Wolfram Language_),它是交互式运行的,不能产生图形输入。 +- _Mathematica_ 是一个丰富的文本/数学编辑器,内置交互式的 Wolfram: 在 "代码单元 "上按 shift+Return 键可以创建一个输出单元,输出结果,这不是动态的。 +- _Wolfram Workbench_,这是 Eclipse 与 Wolfram 语言后端的界面。 + +本例中的代码可以在任何界面中输入,并使用 Wolfram Workbench 进行编辑。直接加载到 Mathematica 中可能会很不方便,因为该文件不包含单元格格式化信息(这将使该文件作为文本阅读时变得一团糟)--它可以被查看/编辑,但可能需要一些设置。 + +```mathematica +(* 这是一个注释 *) + +(* 在Mathematica中,您可以创建一个文本单元格,用排版好的文本和图像来注释您的代码,而不是使用这些注释 *) + +(* 输入一个表达式返回结果 *) +2*2 (* 4 *) +5+8 (* 13 *) + +(* 调用函数 *) +(* 注意,函数名(和其他所有东西)是区分大小写的 *) +Sin[Pi/2] (* 1 *) + +(* 带有一个参数的函数调用的替代语法 *) +Sin@(Pi/2) (* 1 *) +(Pi/2) // Sin (* 1 *) + +(* WL 中的每一种语法都有一些等价的函数调用,即万物皆函数 *) +Times[2, 2] (* 4 *) +Plus[5, 8] (* 13 *) + +(* 第一次使用一个变量定义它,并使其成为全局变量 *) +x = 5 (* 5 *) +x == 5 (* 返回真,C-style 的赋值和相等测试 *) +x (* 5 *) +x = x + 5 (* 10 *) +x (* 10 *) +Set[x, 20] (* 当我说万物皆函数时 我是认真的 *) +x (* 20 *) + +(* 因为WL是基于计算机代数系统的, *) +(* 可以使用未定义的变量,它们只是阻碍了计算 *) +cow + 5 (* 5 + cow, cow 是未定义的,所以无法进一步计算 *) +cow + 5 + 10 (* 15 + cow, 它将尽力计算 *) +% (* 15 + cow, % 获取最后一次返回的内容 *) +% - cow (* 15, 未定义的变量cow被消去 *) +moo = cow + 5 (* 小心,moo 现在是一个表达式,不是一个数字! *) + +(* 定义一个函数 *) +Double[x_] := x * 2 (* 注意 := 防止对RHS进行即时计算。 + 而 x 后面的 _ 表示没有模式匹配的约束条件*) +Double[10] (* 20 *) +Double[Sin[Pi/2]] (* 2 *) +Double @ Sin @ (Pi/2) (* 2, @-syntax 避免了闭括号的队列 *) +(Pi/2) // Sin // Double(* 2, //-syntax 按执行顺序列举了函数 *) + +(* 对于命令式编程,使用 ; 来分隔语句。 *) +(* 丢弃 LHS 的任何输出并运行 RHS *) +MyFirst[] := (Print@"Hello"; Print@"World") (* 请注意,外侧的小括号是关键 + ;的优先级低于:= *) +MyFirst[] (* 你好,世界 *) + +(* C-Style 的 For 循环,注:在 Mathematica 中使用 For 循环是低效的 *) +PrintTo[x_] := For[y=0, y<x, y++, (Print[y])] (* 开始,测试,自增,循环体 *) +PrintTo[5] (* 0 1 2 3 4 *) + +(* While 循环 *) +x = 0; While[x < 2, (Print@x; x++)] (* 带测试和程序体的 while 循环 *) + +(* If 和 条件 *) +x = 8; If[x==8, Print@"Yes", Print@"No"] (* Condition, true case, else case *) +Switch[x, 2, Print@"Two", 8, Print@"Yes"] (* 值匹配风格切换 *) +Which[x==2, Print@"No", x==8, Print@"Yes"] (* Elif风格切换 *) + +(* 除参数外的变量默认为全局变量,即使在函数内部也是如此 *) +y = 10 (* 10, 全局变量 y *) +PrintTo[5] (* 0 1 2 3 4 *) +y (* 5, 全局的 y 被 PrintTo 内的循环计数器所占用 *) +x = 20 (* 20, 全局变量 x *) +PrintTo[5] (* 0 1 2 3 4 *) +x (* 20, PrintTo 中的 x 是一个参数,并自动局部化 *) + +(* 局部变量使用 Module 元函数声明 *) +(* 带本地变量的版本 *) +BetterPrintTo[x_] := Module[{y}, (For[y=0, y<x, y++, (Print@y)])] +y = 20 (* 全局变量 y *) +BetterPrintTo[5] (* 0 1 2 3 4 *) +y (* 20, 那更好 *) + +(* 实际上,模块允许我们声明任何我们喜欢的作用域 *) +Module[{count}, count=0; (* 声明这个变量count的作用域 *) + (IncCount[] := ++count); (* 这些函数都在该作用域内 *) + (DecCount[] := --count)] +count (* count - 全局变量 count 未定义 *) +IncCount[] (* 1, 使用作用域内的counter变量 *) +IncCount[] (* 2, incCount 升级了它 *) +DecCount[] (* 1, decCount 也是 *) +count (* count - 这个名字依旧不是全局变量 *) + +(* Lists *) +myList = {1, 2, 3, 4} (* {1, 2, 3, 4} *) +myList[[1]] (* 1 - 注意列表索引从 1 开始,而不是从 0 开始。 *) +Map[Double, myList] (* {2, 4, 6, 8} - 函数式列表的 map 函数 *) +Double /@ myList (* {2, 4, 6, 8} - 以上的缩略语法 *) +Scan[Print, myList] (* 1 2 3 4 - 命令式循环 *) +Fold[Plus, 0, myList] (* 10 (0+1+2+3+4) *) +FoldList[Plus, 0, myList] (* {0, 1, 3, 6, 10} - 存值的 Fold *) +Append[myList, 5] (* {1, 2, 3, 4, 5} - 注意 myList 没有更新 *) +Prepend[myList, 5] (* {5, 1, 2, 3, 4} - 如果想让 myList 更新,就加上 "myList = " *) +Join[myList, {3, 4}] (* {1, 2, 3, 4, 3, 4} *) +myList[[2]] = 5 (* {1, 5, 3, 4} - 这确实更新了myList *) + +(* 关联,又称字典/哈希值 *) +myHash = <|"Green" -> 2, "Red" -> 1|> (* 创建一个关联 *) +myHash[["Green"]] (* 2, 使用 *) +myHash[["Green"]] := 5 (* 5, 更新 *) +myHash[["Puce"]] := 3.5 (* 3.5, 扩展 *) +KeyDropFrom[myHash, "Green"] (* 抹去绿色的键 *) +Keys[myHash] (* {Red, Puce} *) +Values[myHash] (* {1, 3.5} *) + +(* 做 Wolfram 的演示时 你不能不展示这个 *) +Manipulate[y^2, {y, 0, 20}] (* 返回一个反应式的用户界面,显示y^2 + 并允许通过滑块在 0-20 之间调整y。 + 只适用于图形前端 *) +``` + +## 想多来点? + +- [Wolfram Language Documentation Center](http://reference.wolfram.com/language/) diff --git a/zh-cn/yaml-cn.html.markdown b/zh-cn/yaml-cn.html.markdown index de933d12..cfa22dfb 100644 --- a/zh-cn/yaml-cn.html.markdown +++ b/zh-cn/yaml-cn.html.markdown @@ -1,29 +1,31 @@ --- language: yaml contributors: - - ["Adam Brenecki", "https://github.com/adambrenecki"] + - ["Leigh Brenecki", "https://github.com/adambrenecki"] translators: - ["Zach Zhang", "https://github.com/checkcheckzz"] - ["Jiang Haiyun", "https://github.com/haiiiiiyun"] + - ["Wen Sun", "https://github.com/HermitSun"] filename: learnyaml-cn.yaml lang: zh-cn --- -YAML 是一个数据序列化语言,被设计成人类直接可写可读的。 +YAML 是一种数据序列化语言,旨在让人类直接可写可读。 -它是 JSON 的严格超集,增加了语法显著换行符和缩进,就像 Python。但和 Python 不一样, -YAML 根本不容许文字制表符。 +它是 JSON 的严格超集,增加了*在语法上有意义的*(syntactically significant)换行符和缩进,就像 Python 一样。但和 Python 的不同之处在于,YAML 不允许使用*文字制表符*(literal tab characters)来表示缩进。 ```yaml -# YAML 中的注解看起来像这样。 +--- # 文档开头 + +# YAML 中的注释看起来像这样。 ################ # 标量类型 # ################ -# 我们的根对象 (它们在整个文件里延续) 将会是一个映射, -# 它等价于在别的语言里的一个字典,哈希表或对象。 +# 我们的根对象 (贯穿整个文档的始终) 是一个映射(map), +# 它等价于其它语言中的一个字典(dictionary),哈希表(hash)或对象(object)。 key: value another_key: Another value goes here. a_number_value: 100 @@ -33,11 +35,16 @@ scientific_notation: 1e+12 boolean: true null_value: null key with spaces: value -# 注意到字符串不需要被括在引号中。但是,它们可以被括起来。 -"Keys can be quoted too.": "Useful if you want to put a ':' in your key." - -# 多行字符串既可以写成像一个'文字块'(使用 |), -# 或像一个'折叠块'(使用 '>')。 +# 注意,字符串可以不括在引号里。当然,也可以括在引号里。 +however: 'A string, enclosed in quotes.' +'Keys can be quoted too.': "Useful if you want to put a ':' in your key." +single quotes: 'have ''one'' escape pattern' +double quotes: "have many: \", \0, \t, \u263A, \x0d\x0a == \r\n, and more." +# UTF-8/16/32字符需要指明编码(通过\u)。 +Superscript two: \u00B2 + +# 多行字符串既可以写成一个'字面量块'(使用 '|'), +# 也可以写成一个'折叠块'(使用 '>')。 literal_block: | This entire block of text will be the value of the 'literal_block' key, with line breaks being preserved. @@ -60,7 +67,7 @@ folded_style: > # 集合类型 # #################### -# 嵌套是通过缩进完成的。推荐使用 2 个空格的缩进(但非必须) +# 嵌套是通过缩进完成的。推荐使用 2 个空格的缩进(但非必须)。 a_nested_map: key: value another_key: Another Value @@ -70,21 +77,22 @@ a_nested_map: # 映射的键不必是字符串。 0.25: a float key -# 键也可以是复合型的,比如多行对象 -# 我们用 ? 后跟一个空格来表示一个复合键的开始。 +# 键也可以是复合(complex)的,比如多行对象 +# 我们用 '?' 后跟一个空格来表示一个复合键的开始。 ? | - This is a key - that has multiple lines + This is a key + that has multiple lines : and this is its value # YAML 也允许使用复杂键语法表示序列间的映射关系。 -# 但有些语言的解析器可能会不支持。 +# 但有些解析器可能会不支持。 # 一个例子: ? - Manchester United - Real Madrid : [ 2001-01-01, 2002-02-02 ] -# 序列 (等价于列表或数组) 看起来像这样: +# 序列 (sequences,等价于列表 list 或数组 array ) 看起来像这样: +# 注意 '-' 也算缩进: a_sequence: - Item 1 - Item 2 @@ -95,6 +103,8 @@ a_sequence: - - This is a sequence - inside another sequence + - - - Nested sequence indicators + - can be collapsed # 因为 YAML 是 JSON 的超集,你也可以写 JSON 风格的映射和序列: json_map: {"key": "value"} @@ -105,7 +115,7 @@ and quotes are optional: {key: [3, 2, 1, takeoff]} # 其余的 YAML 特性 # ####################### -# YAML 还有一个方便的特性叫 '锚',它能让你很容易在文档中进行文本复用。 +# YAML 还有一个方便的特性叫“锚”(anchors)。你可以使用它在文档中轻松地完成文本复用。 # 如下两个键会有相同的值: anchored_content: &anchor_name This string will appear as the value of two keys. other_anchor: *anchor_name @@ -114,8 +124,8 @@ other_anchor: *anchor_name base: &base name: Everyone has same name -# The regexp << is called Merge Key Language-Independent Type. -# 它表明指定映射的所有键值会插入到当前的映射中。 +# '<<'称为语言无关的合并键类型(Merge Key Language-Independent Type). +# 它表明一个或多个指定映射中的所有键值会插入到当前的映射中。 foo: &foo <<: *base @@ -127,22 +137,22 @@ bar: &bar # foo 和 bar 将都含有 name: Everyone has same name -# YAML 还有标签,你可以用它显示地声明类型。 +# YAML 还有标签(tags),你可以用它显式地声明类型。 explicit_string: !!str 0.5 -# 一些解析器实现特定语言的标签,就像这个针对 Python 的复数类型。 +# 一些解析器实现了特定语言的标签,就像这个针对Python的复数类型的标签。 python_complex_number: !!python/complex 1+2j -# 我们也可以在 YAML 的复合键中使用特定语言的标签 +# 我们也可以在 YAML 的复合键中使用特定语言的标签: ? !!python/tuple [5, 7] : Fifty Seven -# 将会是 Python 中的 {(5, 7): 'Fifty Seven'} +# 将会是 Python 中的 {(5, 7): 'Fifty Seven'} #################### # 其余的 YAML 类型 # #################### -# 除了字符串和数字,YAML 还能理解其它标量。 -# ISO 格式的日期和日期时间文本也可以被解析。 +# 除了字符串和数字,YAML 还支持其它标量。 +# ISO 格式的日期和时间字面量也可以被解析。 datetime: 2001-12-15T02:59:43.1Z datetime_with_spaces: 2001-12-14 21:59:43.10 -5 date: 2002-12-14 @@ -155,20 +165,24 @@ gif_file: !!binary | +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= -# YAML 还有一个集合类型,它看起来像这样: +# YAML 还有一个集合(set)类型,它看起来像这样: set: - ? item1 - ? item2 - ? item3 + ? item1 + ? item2 + ? item3 +or: {item1, item2, item3} -# 集合只是值为 null 的映射;上面的集合等价于: +# 集合只是值均为 null 的映射;上面的集合等价于: set2: - item1: null - item2: null - item3: null + item1: null + item2: null + item3: null + +... # 文档结束 ``` ### 更多资源 + [YAML official website](http://yaml.org/) ++ [Online YAML Converter](http://yamlonline.com) + [Online YAML Validator](http://codebeautify.org/yaml-validator) diff --git a/zh-cn/zfs-cn.html.markdown b/zh-cn/zfs-cn.html.markdown index fdf5277e..80688fbe 100644 --- a/zh-cn/zfs-cn.html.markdown +++ b/zh-cn/zfs-cn.html.markdown @@ -288,6 +288,7 @@ tank/home/sarlalian@now 0 - 259M - tank/home/alice@now 0 - 156M - tank/home/bob@now 0 - 156M - ... +``` Destroy snapshots (删除快照) @@ -297,7 +298,6 @@ $ zfs destroy tank/home/sarlalian@now # 删除某一数据集及其子集的快照 $ zfs destroy -r tank/home/sarlalian@now - ``` Renaming Snapshots (重命名) diff --git a/zh-tw/bash-tw.html.markdown b/zh-tw/bash-tw.html.markdown index 78b39f2d..5136d513 100644 --- a/zh-tw/bash-tw.html.markdown +++ b/zh-tw/bash-tw.html.markdown @@ -23,7 +23,7 @@ filename: LearnBash-tw.sh lang: zh-tw --- -Bash 是一個爲 GNU 計劃編寫的 Unix shell,是 Linux 和 Mac OS X 下預設的 shell。 +Bash 是一個爲 GNU 計劃編寫的 Unix shell,是 Linux 和 macOS 下預設的 shell。 以下大多數例子可以作爲腳本的一部分運行,也可直接在 shell 下互動執行。 [更多資訊](http://www.gnu.org/software/bash/manual/bashref.html) diff --git a/zh-tw/dart-tw.html.markdown b/zh-tw/dart-tw.html.markdown new file mode 100644 index 00000000..5a9241c2 --- /dev/null +++ b/zh-tw/dart-tw.html.markdown @@ -0,0 +1,566 @@ +--- +language: dart +lang: zh-tw +filename: learndart-tw.dart +contributors: + - ["Joao Pedrosa", "https://github.com/jpedrosa/"] +translators: + - ["Bob Lu", "https://github.com/LuPoYi/"] +--- + +Dart 是程式語言領域的新人。 +它借鑒了許多其他主流語言,並且不會偏離它的兄弟語言 JavaScript 太多。 +就像 JavaScript 一樣,Dart 的目標是提供良好的瀏覽器整合性。 + +Dart 最有爭議的特性必然是它的可選類型。 + +```javascript +import "dart:collection"; +import "dart:math" as DM; + +// 歡迎進入15分鐘的 Dart 學習。 http://www.dartlang.org/ +// 這是一個可實際執行的範例。你可以用 Dart 執行它 +// 或者線上執行! 可以把程式碼複製/貼上到這個網站。 http://try.dartlang.org/ + +// 函數宣告和方法宣告看起來一樣。 +// 函數宣告可以是巢狀的。宣告使用這種 name() {} 的形式, +// 或者 name() => 單行表示式; 的形式。 +// 右箭頭的宣告形式會直接地返回表示式的結果。 +example1() { + example1nested1() { + example1nested2() => print("Example1 nested 1 nested 2"); + example1nested2(); + } + example1nested1(); +} + +// 匿名函數沒有函數名。 +example2() { + example2nested1(fn) { + fn(); + } + example2nested1(() => print("Example2 nested 1")); +} + +// 當宣告函數類型的參數的時候,宣告中可以包含 +// 函數參數需要的參數,指定所需的參數名即可。 +example3() { + example3nested1(fn(informSomething)) { + fn("Example3 nested 1"); + } + example3planB(fn) { // 或者不宣告函數參數的參數 + fn("Example3 plan B"); + } + example3nested1((s) => print(s)); + example3planB((s) => print(s)); +} + +// 函數有可以訪問到外層變數的閉包。 +var example4Something = "Example4 nested 1"; +example4() { + example4nested1(fn(informSomething)) { + fn(example4Something); + } + example4nested1((s) => print(s)); +} + +// 下面這個包含 sayIt 方法的類別宣告,同樣有一個可以訪問外層變數的閉包, +// 就像前面的函數一樣。 +var example5method = "Example5 sayIt"; +class Example5Class { + sayIt() { + print(example5method); + } +} +example5() { + // 創建一個 Example5Class 類的匿名實例, + // 並呼叫它的 sayIt 方法。 + new Example5Class().sayIt(); +} + +// 類別的宣告使用這種形式 class name { [classBody] }. +// classBody 中可以包含實例方法和變數, +// 還可以包含類別方法和變數。 +class Example6Class { + var example6InstanceVariable = "Example6 instance variable"; + sayIt() { + print(example6InstanceVariable); + } +} +example6() { + new Example6Class().sayIt(); +} + +// 類別方法和變數使用 static 宣告。 +class Example7Class { + static var example7ClassVariable = "Example7 class variable"; + static sayItFromClass() { + print(example7ClassVariable); + } + sayItFromInstance() { + print(example7ClassVariable); + } +} +example7() { + Example7Class.sayItFromClass(); + new Example7Class().sayItFromInstance(); +} + +// 定數非常方便,但是對於在函數/方法的外層的定數有一個限制, +// 類別的外層或外面的定數必須是常數。 +// 字串和數字預設是常數。 +// 但是 array 和 map 不是。他們需要用 "const" 宣告為常數。 +var example8Array = const ["Example8 const array"], + example8Map = const {"someKey": "Example8 const map"}; +example8() { + print(example8Array[0]); + print(example8Map["someKey"]); +} + +// Dart 中的迴圈使用標準的 for () {} 或 while () {} 的形式, +// 以及更加現代的 for (.. in ..) {} 的形式, 或者 +// 以 forEach 開頭並具有許多特性支援函數回呼的形式。 +var example9Array = const ["a", "b"]; +example9() { + for (var i = 0; i < example9Array.length; i++) { + print("Example9 for loop '${example9Array[i]}'"); + } + var i = 0; + while (i < example9Array.length) { + print("Example9 while loop '${example9Array[i]}'"); + i++; + } + for (var e in example9Array) { + print("Example9 for-in loop '${e}'"); + } + example9Array.forEach((e) => print("Example9 forEach loop '${e}'")); +} + +// 透過迴圈遍歷字串中的每個字元或者取出其子字串。 +var example10S = "ab"; +example10() { + for (var i = 0; i < example10S.length; i++) { + print("Example10 String character loop '${example10S[i]}'"); + } + for (var i = 0; i < example10S.length; i++) { + print("Example10 substring loop '${example10S.substring(i, i + 1)}'"); + } +} + +// 支援兩種數字格式 int 和 double。 +example11() { + var i = 1 + 320, d = 3.2 + 0.01; + print("Example11 int ${i}"); + print("Example11 double ${d}"); +} + +// DateTime 提供了日期/時間的方法。 +example12() { + var now = new DateTime.now(); + print("Example12 now '${now}'"); + now = now.add(new Duration(days: 1)); + print("Example12 tomorrow '${now}'"); +} + +// 支援正規表達式。 +example13() { + var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$"); + match(s) { + if (re.hasMatch(s)) { + print("Example13 regexp matches '${s}'"); + } else { + print("Example13 regexp doesn't match '${s}'"); + } + } + match(s1); + match(s2); +} + +// 布林運算式支持隱式轉換以及動態類型 +example14() { + var a = true; + if (a) { + print("Example14 true, a is $a"); + } + a = null; + if (a) { + print("Example14 true, a is $a"); + } else { + print("Example14 false, a is $a"); // 執行到這裡 + } + +// 動態類型的null可以轉換成bool型 + var b; // b是動態類型 + b = "abc"; + try { + if (b) { + print("Example14 true, b is $b"); + } else { + print("Example14 false, b is $b"); + } + } catch (e) { + print("Example14 error, b is $b"); // 這段程式碼可以執行但是會報錯 + } + b = null; + if (b) { + print("Example14 true, b is $b"); + } else { + print("Example14 false, b is $b"); // 執行到這裡 + } + + // 靜態類型的null不能轉換成bool型 + var c = "abc"; + c = null; + // 編譯出錯 + // if (c) { + // print("Example14 true, c is $c"); + // } else { + // print("Example14 false, c is $c"); + // } +} + +// try/catch/finally 和 throw 語句用於例外處理。 +// throw 語句可以使用任何物件作為參數。 +example15() { + try { + try { + throw "Some unexpected error."; + } catch (e) { + print("Example15 an exception: '${e}'"); + throw e; // Re-throw + } + } catch (e) { + print("Example15 catch exception being re-thrown: '${e}'"); + } finally { + print("Example15 Still run finally"); + } +} + +// 想要有效地動態創建長字串, +// 應該使用 StringBuffer。或者 join 一個字串的陣列。 +example16() { + var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e; + for (e in a) { sb.write(e); } + print("Example16 dynamic string created with " + "StringBuffer '${sb.toString()}'"); + print("Example16 join string array '${a.join()}'"); +} + +// 字串連接只需讓相鄰的字串相連, +// 不需要額外的操作運算符號。 +example17() { + print("Example17 " + "concatenate " + "strings " + "just like that"); +} + +// 字串使用單引號或雙引號做分隔,二者並沒有實際的差異。 +// 這種靈活性可以很好地避免內容中需要轉義換行的情況。 +// 例如,字串內容裡的 HTML 屬性使用了雙引號。 +example18() { + print('Example18 <a href="etc">' + "Don't can't I'm Etc" + '</a>'); +} + +// 用三個單引號或三個雙引號表示的字串 +// 可以跨越多行,並且包含換行。 +example19() { + print('''Example19 <a href="etc"> +Example19 Don't can't I'm Etc +Example19 </a>'''); +} + +// 字串可以使用 $ 符號插入內容。 +// 使用 $ { [expression] } 的形式,表示式的值會被插入到字串中。 +// $ 跟著一個變數名會插入變數的值。 +// 如果要在字符串中插入 $ ,可以使用 \$ 的轉義形式取代。 +example20() { + var s1 = "'\${s}'", s2 = "'\$s'"; + print("Example20 \$ interpolation ${s1} or $s2 works."); +} + +// 可選類型允許作為 API 的標註,並且可以輔助 IDE, +// 這樣 IDE 可以更好地提供重構、自動完成和錯誤檢測功能。 +// 目前為止我們還沒有宣告任何類型,並且程式可以執行。 +// 事實上,類型在執行時會被忽略。 +// 類型甚至可以是錯的,並且程式依然可以執行, +// 好像和類型完全無關一樣。 +// 有一個執行時參數可以讓程式進入檢查模式,它會在執行時檢查類型錯誤。 +// 這在開發時很有用,但是由於增加了額外的檢查會使程式變慢, +// 因此應該避免在部署時使用。 +class Example21 { + List<String> _names; + Example21() { + _names = ["a", "b"]; + } + List<String> get names => _names; + set names(List<String> list) { + _names = list; + } + int get length => _names.length; + void add(String name) { + _names.add(name); + } +} + +void example21() { + Example21 o = new Example21(); + o.add("c"); + print("Example21 names '${o.names}' and length '${o.length}'"); + o.names = ["d", "e"]; + print("Example21 names '${o.names}' and length '${o.length}'"); +} + +// 類型的繼承形式是 class name extends AnotherClassName {} 。 +class Example22A { + var _name = "Some Name!"; + get name => _name; +} +class Example22B extends Example22A {} +example22() { + var o = new Example22B(); + print("Example22 class inheritance '${o.name}'"); +} + +// 類型也可以使用 mixin 的形式 : +// class name extends SomeClass with AnotherClassName {}. +// 必需繼承某個類型才能 mixin 另一個類型。 +// 當前 mixin 的模板類型不能有建構子。 +// Mixin 主要是用來和輔助的類型共享方法的, +// 這樣單一繼承就不會影響程式碼重覆使用。 +// Mixin 宣告在類型定義的 "with" 後面。 +class Example23A {} +class Example23Utils { + addTwo(n1, n2) { + return n1 + n2; + } +} +class Example23B extends Example23A with Example23Utils { + addThree(n1, n2, n3) { + return addTwo(n1, n2) + n3; + } +} +example23() { + var o = new Example23B(), r1 = o.addThree(1, 2, 3), + r2 = o.addTwo(1, 2); + print("Example23 addThree(1, 2, 3) results in '${r1}'"); + print("Example23 addTwo(1, 2) results in '${r2}'"); +} + +// 類型的建構子和類型名相同,形式為 +// SomeClass() : super() {}, 其中 ": super()" 的部分是可選的, +// 它用來傳遞參數給父類型的建構子。 +class Example24A { + var _value; + Example24A({value: "someValue"}) { + _value = value; + } + get value => _value; +} +class Example24B extends Example24A { + Example24B({value: "someOtherValue"}) : super(value: value); +} +example24() { + var o1 = new Example24B(), + o2 = new Example24B(value: "evenMore"); + print("Example24 calling super during constructor '${o1.value}'"); + print("Example24 calling super during constructor '${o2.value}'"); +} + +// 對於簡單的類型,有一種設置構造函數參數的快捷方式。 +// 只需要使用 this.parameterName 的前綴, +// 它就會把參數設置為同名的實例變數。 +class Example25 { + var value, anotherValue; + Example25({this.value, this.anotherValue}); +} +example25() { + var o = new Example25(value: "a", anotherValue: "b"); + print("Example25 shortcut for constructor '${o.value}' and " + "'${o.anotherValue}'"); +} + +// 可以在大括號 {} 中宣告命名參數。 +// 大括號 {} 中宣告的參數的順序是隨意的。 +// 在中括號 [] 中宣告的參數也是可選的。 +example26() { + var _name, _surname, _email; + setConfig1({name, surname}) { + _name = name; + _surname = surname; + } + setConfig2(name, [surname, email]) { + _name = name; + _surname = surname; + _email = email; + } + setConfig1(surname: "Doe", name: "John"); + print("Example26 name '${_name}', surname '${_surname}', " + "email '${_email}'"); + setConfig2("Mary", "Jane"); + print("Example26 name '${_name}', surname '${_surname}', " + "email '${_email}'"); +} + +// 使用 final 宣告的變數只能被設置一次。 +// 在類型裡面,final 實例變數可以通過常數的建構子參數設置。 +class Example27 { + final color1, color2; + // 更靈活一點的方法是在冒號 : 後面設置 final 實例變數。 + Example27({this.color1, color2}) : color2 = color2; +} +example27() { + final color = "orange", o = new Example27(color1: "lilac", color2: "white"); + print("Example27 color is '${color}'"); + print("Example27 color is '${o.color1}' and '${o.color2}'"); +} + +// 要導入一個函式庫,使用 import "libraryPath" 的形式,或者如果要導入的是 +// 核心庫使用 import "dart:libraryName" 。還有一個稱為 "pub" 的套件管理工具, +// 它使用 import "package:packageName" 的約定形式。 +// 看下這個文件頂部的 import "dart:collection"; 語法。 +// 導入語句必需在其它程式碼宣告之前出現。 IterableBase 來自於 dart:collection 。 +class Example28 extends IterableBase { + var names; + Example28() { + names = ["a", "b"]; + } + get iterator => names.iterator; +} +example28() { + var o = new Example28(); + o.forEach((name) => print("Example28 '${name}'")); +} + +// 對於控制流程,我們有: +// * 必需帶 break 的標準 switch 語法 +// * if-else 和三元運算子 ..?..:.. +// * 閉包和匿名函數 +// * break, continue 和 return 語法 +example29() { + var v = true ? 30 : 60; + switch (v) { + case 30: + print("Example29 switch statement"); + break; + } + if (v < 30) { + } else if (v > 30) { + } else { + print("Example29 if-else statement"); + } + callItForMe(fn()) { + return fn(); + } + rand() { + v = new DM.Random().nextInt(50); + return v; + } + while (true) { + print("Example29 callItForMe(rand) '${callItForMe(rand)}'"); + if (v != 30) { + break; + } else { + continue; + } + // 不會到這裡。 + } +} + +// 解析 int,把 double 轉成 int,或者使用 ~/ 運算符號在除法計算時僅保留整數位。 +// 讓我們也來場猜數遊戲吧。 +example30() { + var gn, + tooHigh = false, + n, + n2 = (2.0).toInt(), + top = int.parse("123") ~/ n2, + bottom = 0; + top = top ~/ 6; + gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive + print("Example30 Guess a number between 0 and ${top}"); + guessNumber(i) { + if (n == gn) { + print("Example30 Guessed right! The number is ${gn}"); + } else { + tooHigh = n > gn; + print("Example30 Number ${n} is too " + "${tooHigh ? 'high' : 'low'}. Try again"); + } + return n == gn; + } + + n = (top - bottom) ~/ 2; + while (!guessNumber(n)) { + if (tooHigh) { + top = n - 1; + } else { + bottom = n + 1; + } + n = bottom + ((top - bottom) ~/ 2); + } +} + +// 選填位置參數: +// 參數定義使用方括號 [ ],傳入參數是選填的。 +example31() { + findVolume31(int length, int breath, [int height]) { + print('length = $length, breath = $breath, height = $height'); + } + + findVolume31(10,20,30); // 可執行 + findVolume31(10,20); // 也可執行 +} + +// 選填命名參數: +// 參數定義使用大括號 { }, 傳入參數是選填的。 +// 必須傳入參數名稱及參數值,並以 : 分隔 +// 大括號的順序沒有差別 +// 這種類型參數可以幫我們避免多個參數傳入時造成混淆。 +example32() { + findVolume32(int length, int breath, {int height}) { + print('length = $length, breath = $breath, height = $height'); + } + + findVolume32(10,20,height:30); // 可執行 & 參數名稱在這邊有傳入 + findVolume32(10,20); // 也可執行 +} + +// 選填預設參數: +// 與選填命名參數相同,此外,我們為此參數定義的預設值 +// 如果沒有傳入值,就使用預設值 +example33() { + findVolume33(int length, int breath, {int height=10}) { + print('length = $length, breath = $breath, height = $height'); + } + + findVolume33(10,20,height:30); // 可執行 + findVolume33(10,20); // 可執行 +} + +// 程式的唯一入口點是 main 函式。 +// 在程式開始執行 main 函式之前,不會執行任何外部程式碼。 +// 這樣有助於更快加載甚至是延遲加載程式啟動時所需要的部分; +main() { + print("Learn Dart in 15 minutes!"); + [ + example1, example2, example3, example4, example5, + example6, example7, example8, example9, example10, + example11, example12, example13, example14, example15, + example16, example17, example18, example19, example20, + example21, example22, example23, example24, example25, + example26, example27, example28, example29, + example30 // 增加此註解可阻止dart formatter把所有項目都換行 + ].forEach((ef) => ef()); +} + +``` + +## 延伸閱讀 + +Dart 有一個綜合性網站。它涵蓋了 API 參考、入門教學、文章以及更多, +還包括一個有用的線上試用 Dart 頁面。 +* [https://www.dartlang.org](https://www.dartlang.org) +* [https://try.dartlang.org](https://try.dartlang.org) diff --git a/zh-tw/elixir-tw.html.markdown b/zh-tw/elixir-tw.html.markdown index c15f90c1..3dba95b3 100644 --- a/zh-tw/elixir-tw.html.markdown +++ b/zh-tw/elixir-tw.html.markdown @@ -1,5 +1,5 @@ --- -language: elixir +language: Elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] - ["Dzianis Dashkevich", "https://github.com/dskecse"] @@ -19,10 +19,10 @@ Elixir 是一門建構在 Erlang 虛擬機上的現代函數式語言。它完 # 沒有多行註解的功能 # 但你可以連續使用多個單行 -# 用 `iex` 來進入 elixir shell +# 用 `iex` 來進入 Elixir shell # 用 `elixirc` 來編譯你的模組 -# 如果你已成功安裝 elixir 的話,這兩個命令應已在你的 path 下。 +# 如果你已成功安裝 Elixir 的話,這兩個命令應已在你的 path 下。 ## --------------------------- ## -- 基本型別 @@ -50,7 +50,7 @@ elem({1, 2, 3}, 0) #=> 1 head #=> 1 tail #=> [2,3] -# 在 elixir 中,就如同 Erlang 裡一樣,`=` 代表的是模式比對,而非指派。 +# 在 Elixir 中,就如同 Erlang 裡一樣,`=` 代表的是模式比對,而非指派。 # # 這代表將使用左手邊的模式 (pattern) 去與右手邊的值進行比對。 # @@ -80,7 +80,7 @@ string. <<?a, ?b, ?c>> #=> "abc" [?a, ?b, ?c] #=> 'abc' -# `?a` 在 elixir 中會回傳字母 `a` 的 ASCII 整數 +# `?a` 在 Elixir 中會回傳字母 `a` 的 ASCII 整數 ?a #=> 97 # 用 `++` 來合併串列,而合併二進位則要用 `<>` @@ -105,7 +105,7 @@ lower..upper = 1..10 # 可以對 range 進行模式比對 5 * 2 #=> 10 10 / 2 #=> 5.0 -# 在 elixir 中, `/` 運算元永遠回傳浮點數。 +# 在 Elixir 中, `/` 運算元永遠回傳浮點數。 # 若需要回傳整數的除法,用 `div` div(10, 2) #=> 5 @@ -290,7 +290,7 @@ Geometry.area({:circle, 3}) #=> 28.25999999999999801048 # Geometry.area({:circle, "not_a_number"}) #=> ** (FunctionClauseError) no function clause matching in Geometry.area/1 -# 由於不可變特性 (immutability),遞迴在 elixir 中扮演重要的角色。 +# 由於不可變特性 (immutability),遞迴在 Elixir 中扮演重要的角色。 defmodule Recursion do def sum_list([head | tail], acc) do sum_list(tail, acc + head) @@ -356,7 +356,7 @@ end ## -- 平行處理 ## --------------------------- -# Elixir 依靠 actor 模式來進行平行處理。在 elixir 中要寫出平行處理程式, +# Elixir 依靠 actor 模式來進行平行處理。在 Elixir 中要寫出平行處理程式, # 只需要三個基本要素:建立行程,發送訊息及接收訊息。 # 我們用 `spawn` 函式來建立行程,它接收一個函式當參數。 diff --git a/zh-tw/perl-tw.html.markdown b/zh-tw/perl-tw.html.markdown new file mode 100644 index 00000000..55876e2a --- /dev/null +++ b/zh-tw/perl-tw.html.markdown @@ -0,0 +1,328 @@ +--- +name: perl +category: language +language: perl +filename: learnperl-tw.pl +contributors: + - ["Korjavin Ivan", "http://github.com/korjavin"] + - ["Dan Book", "http://github.com/Grinnz"] +translators: + - ["Kang-min Liu", "https://gugod.org"] + - ["Shih-Kai Chiu", "https://twitter.com/zard1989"] +lang: zh-tw +--- + +Perl 5 是一款強大且功能豐富的程式語言,已經持續發展超過 25 年。 + +從大型主機到行動裝置,Perl 5 能在上百種平台執行,適合快速打造產品原型,也適合大 +型專案開發。 + +```perl +# 註解列皆以井字號為開頭 + +#### 嚴謹度 + +use strict; +use warnings; + +# 所有的 perl 程式檔案都應當包含此兩列程式碼。在如變數名稱有拼寫錯誤之時, +# strict 能使編譯過程失敗。而對於像是將未定義值接到字串中等等易犯之錯誤, +# warnings 則能提供適當的警告訊息。 + +#### Perl 變數與其型別 + +# 變數的開頭皆為一印記(sigil),是為一符號,用以標示其型別。 +# 變數名稱唯有以字母或底線開頭,後接字母、數字、底線若干,方為有效。 + +### 在 Perl 語言中,主要的變數型別有三種:$純量、@陣列、%雜湊。 + +## 純量 +# 一個純量變數,只能裝一個值: +my $animal = "camel"; +my $answer = 42; +my $display = "You have $answer ${animal}s.\n"; + +# 純量值可為字串、整數、浮點數。Perl 會自動地在需要之時進行轉換。 + +# 以單引號括住的字串內容與其字面之值完全相同。而以雙引號括住的字串, +# 其中則能內插變數與像是這種表示換列字符 "\n" 的控制碼。 + +## 陣列 +# 一個陣列,可以裝下很多值: +my @animals = ("camel", "llama", "owl"); +my @numbers = (23, 42, 69); +my @mixed = ("camel", 42, 1.23); + +# 陣列元素的存取,需要角括號。前方的印記為 $ 符號,表示只取一個值。 +my $second = $animals[1]; + +# 欲知陣列之大小,在純量語境之下使用陣列便可。例如,將陣列裝到一個純量變數中。 +# 又或者是使用 "scalar" 算符。 + +my $num_animals = @animals; +print "Number of numbers: ", scalar(@numbers), "\n"; + +# 陣列也能夠被安插在雙引號字串之內。各內容元素間隔,預設是一個空白字符。 + +print "We have these numbers: @numbers\n"; + +# 雙引號字串中,若有像電子郵件地址的部分,會被視為是在內插某個陣列的內容物。 +# 請稍加留意。 + +my @example = ('secret', 'array'); +my $oops_email = "foo@example.com"; # 'foosecret array.com' +my $ok_email = 'foo@example.com'; + +## 雜湊 +# 一個雜湊,能裝下許多對的鍵與值: + +my %fruit_color = ("apple", "red", "banana", "yellow"); + +# 善用空白與 "=>" 算符,就能將其排得得好看一些: + +my %fruit_color = ( + apple => "red", + banana => "yellow", +); + +# 雜湊元素的存取,需要大括號。前方的印記仍為 $ 符號,表示只取一個值。 +my $color = $fruit_color{apple}; + +# 以 "keys" 與 "values" 兩個函數,則可一次取得雜湊中的所有鍵、所有值。 +my @fruits = keys %fruit_color; +my @colors = values %fruit_color; + +# 關於純量、陣列、雜湊,在 perldata 文件之中,有更完整的描述。 +# (perldoc perldata) + +#### 參照 + +# 以參照能組出結構更為複雜的資料型別。 +# 像是在陣列中放入雜湊、或是在雜湊裡放入陣列的雜湊。 + +my $array_ref = \@array; +my $hash_ref = \%hash; +my @array_of_arrays = (\@array1, \@array2, \@array3); + +# 匿名陣列與匿名雜湊也是參照 + +my $fruits = ["apple", "banana"]; +my $colors = {apple => "red", banana => "yellow"}; + +# 在參照之前補上適當的印記,是為解參照。 + +my @fruits_array = @$fruits; +my %colors_hash = %$colors; + +# 以箭頭算符,便可在解參照同時存取其中一值。 + +my $first = $array_ref->[0]; +my $value = $hash_ref->{banana}; + +# 欲深入了解參照,詳見 perlreftut 與 perlref 兩份文件 + +#### 條件結構與迴圈結構 + +# Perl 語言中亦具備常見的條件結講與迴圈結構。 + +if ($var) { + ... +} elsif ($var eq 'bar') { + ... +} else { + ... +} + +unless (condition) { + ... +} +# 這算是可讀性較好的 "if (!condition)" + +# 倒裝句型算是某「很 Perl 的」寫法 +print "Yow!" if $zippy; +print "We have no bananas" unless $bananas; + +# while +while (condition) { + ... +} + +my $max = 5; +# 以 for 迴圈,$i 為迭代變數 +for my $i (0 .. $max) { + print "index is $i"; +} + +for my $element (@elements) { + print $element; +} + +map {print} @elements; + +# 迭代變數為 $_ +for (@elements) { + print; +} + +# 對雜湊進行迭代(for 與 foreach 完全相同) + +foreach my $key (keys %hash) { + print $key, ': ', $hash{$key}, "\n"; +} + +# 又是「很 Perl 的」倒裝句法 +print for @elements; + +# 對一雜湊參照之中迭代,逐一走過其鍵與值 +print $hash_ref->{$_} for keys %$hash_ref; + +#### 正規表示式 + +# Perl 中,對正規表示式的支援既廣亦深,在 perlrequick、perlretut 等各處文件中 +# 都有更加完整的文件。不過,簡而言之: + +# 簡易比對 +if (/foo/) { ... } # 若 $_ 內含 "foo" 則為真 +if ($x =~ /foo/) { ... } # 若 $x 內含 "foo" 則為真 + +# 簡易取代 +$x =~ s/foo/bar/; # 將 $x 中第一個出現的 foo 換為 bar +$x =~ s/foo/bar/g; # 將 $x 中所有出現的 foo 換為 bar + +#### 檔案與輸出入 + +# 以 "open" 函式開檔後,便可自檔案輸入或對其輸出 + +# 讀檔: +open(my $in, "<", "input.txt") or die "Can't open input.txt: $!"; + +# 寫檔(若檔案已經存在,舊內容會被清空): +open(my $out, ">", "output.txt") or die "Can't open output.txt: $!"; + +# 寫檔(若檔案已經存在,會寫到檔尾去): +open(my $log, ">>", "my.log") or die "Can't open my.log: $!"; + +# 使用 "<>" 算符,能對檔案代號進行讀取。在純量語境下,會自檔案代號讀一列內容。 +# 而在串列語境下,對讀入整個檔案。每一列都會成為串列中一項元素。 + +my $line = <$in>; +my @lines = <$in>; + +# 以 "print" 函式,則可對檔案代號進行輸出。 + +print $out @lines; +print $log $msg, "\n"; + +#### 函式之撰寫 + +# 撰寫函式很是容易: + +sub logger { + my $logmessage = shift; + + open my $logfile, ">>", "my.log" or die "Could not open my.log: $!"; + + print $logfile $logmessage; +} + +# 之後,使用起來就與內建函式無異: + +logger("We have a logger subroutine!"); + +#### 模組 + +# 所謂模組,就是一組 Perl 程式碼,由一些函式組成,並可讓其他 Perl 程式碼來利用。 +# 為了讓 perl 能找至,通常模組之副檔名 .pm 。 + +package MyModule; +use strict; +use warnings; + +sub trim { + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +1; + +# 自他處利用: + +use MyModule; +MyModule::trim($string); + +# Exporter 模組能將函式出口,好讓它們能被這樣利用: + +use MyModule 'trim'; +trim($string); + +# 有許多 Perl 模組能從 CPAN (https://www.cpan.org) 下載下來,各式各樣的機能讓你 +# 能免於重新發明輪子。不少高人氣模組,如 Exporter,則是與 Perl 一同釋出、散佈。 +# 更多關於 Perl 模組的細節,詳見 perlmod 文件。 + +#### 物件 + +# Perl 中的物件,只是個參照,但同時又知道自己屬於哪個類別(package),於是對自身 +# 調用方法(函式)時方知去何處尋找函式本體。在建構子(通常是 "new")中,都是以 +# "bless" 函式來標記參照與其類別。只不過,若你使用像 Moose 或 Moo 模組的話,這些 +# 都不必自己來(總之請繼續往下讀)。 + +package MyCounter; +use strict; +use warnings; + +sub new { + my $class = shift; + my $self = {count => 0}; + return bless $self, $class; +} + +sub count { + my $self = shift; + return $self->{count}; +} + +sub increment { + my $self = shift; + $self->{count}++; +} + +1; + +# 以箭頭運算符,便可對某類別或某物件呼叫某方法: +use MyCounter; +my $counter = MyCounter->new; +print $counter->count, "\n"; # 0 +$counter->increment; +print $counter->count, "\n"; # 1 + +# CPAN 上的 Moose 與 Moo 模組能助你撰寫類別本體。它們提供了建構子,與簡單易懂的 +# 語法能來宣告屬性。前述的類別改寫之後,如下: + +package MyCounter; +use Moo; # 同時也啟用 strict 與 warnings + +has 'count' => (is => 'rwp', default => 0, init_arg => undef); + +sub increment { + my $self = shift; + $self->_set_count($self->count + 1); +} + +1; + +# 物件導向程式設計於 perlootut 文件中有詳盡的說明。 +# 此外,perlobj 文件中更涵蓋了底層實做之細節。 +``` + +#### 常見問答集 + +perlfaq 是問與答,涵蓋許多常見問題和解法,常常對該用哪些 CPAN 模組有很好的建議。 + +#### 延伸閱讀 + + - [perl-tutorial](http://perl-tutorial.org/) + - [Learn Perl](https://www.perl.org/learn.html) + - [perldoc](http://perldoc.perl.org/) + - 內建函式 : `perldoc perlintro` diff --git a/zh-tw/python-tw.html.markdown b/zh-tw/pythonlegacy-tw.html.markdown index cd7481d7..575897e2 100644 --- a/zh-tw/python-tw.html.markdown +++ b/zh-tw/pythonlegacy-tw.html.markdown @@ -1,5 +1,5 @@ --- -language: python +language: Python 2 (legacy) contributors: - ["Louie Dinh", "http://ldinh.ca"] - ["Amin Bandali", "http://aminbandali.com"] @@ -7,7 +7,7 @@ contributors: - ["evuez", "http://github.com/evuez"] translators: - ["Michael Yeh", "https://hinet60613.github.io/"] -filename: learnpython-tw.py +filename: learnpythonlegacy-tw.py lang: zh-tw --- @@ -16,7 +16,7 @@ Python是在1990年代早期由Guido Van Rossum創建的。它是現在最流行 非常歡迎各位給我們任何回饋! 你可以在[@louiedinh](http://twitter.com/louiedinh) 或 louiedinh [at] [google's email service]聯絡到我。 註: 本篇文章適用的版本為Python 2.7,但大部分的Python 2.X版本應該都適用。 Python 2.7將會在2020年停止維護,因此建議您可以從Python 3開始學Python。 -Python 3.X可以看這篇[Python 3 教學 (英文)](http://learnxinyminutes.com/docs/python3/). +Python 3.X可以看這篇[Python 3 教學 (英文)](http://learnxinyminutes.com/docs/python/). 讓程式碼同時支援Python 2.7和3.X是可以做到的,只要引入 [`__future__` imports](https://docs.python.org/2/library/__future__.html) 模組. diff --git a/zig.html.markdown b/zig.html.markdown new file mode 100644 index 00000000..65fd1e6b --- /dev/null +++ b/zig.html.markdown @@ -0,0 +1,981 @@ +--- +language: zig +filename: learnzig.zig +contributors: + - ["Philippe Pittoli", "https://karchnu.fr/"] +--- + +[Zig][ziglang] aims to be a replacement for the C programming language. + +**WARNING**: this document expects you to understand a few basic concepts in computer science, such as pointers, stack and heap memory, etc. + +**WARNING**: Zig isn't considered as ready for production. Bugs are expected. + +Prior knowledge of C is recommended. + +## Quick overview: Zig compared to C + +- Syntax is mostly the same, with some improvements (less ambiguity). +- Zig introduces namespaces. +- `try` and `catch` mechanism, which is both convenient, efficient and optional. +- Most of the C undefined behaviors (UBs) are fixed. +- Compared to C, raw pointers are safer to use and less likely to be needed. + * The type system distinguishes between a pointer to a single value, or multiple values, etc. + * Slices are preferred, which is a structure with a pointer and a runtime known size, which characterizes most uses of pointers in the first place. +- Some arbitrary language limitations are removed. For example, enumerations, structures and unions can have functions. +- Simple access to SIMD operations (basic maths on vectors). +- Zig provides both low-level features of C and the one provided through compiler extensions. + For example: packed structures. +- An extensive standard library, including data structures and algorithms. +- Cross-compilation capability is provided by default, without any dependency. + Different libc are provided to ease the process. + Cross-compilation works from, and to, any operating system and architecture. + +## Zig language + +```zig +//! Top-level documentation. + +/// Documentation comment. + +// Simple comment. +``` + +### Hello world. + +```zig +// Import standard library, reachable through the "std" constant. +const std = @import("std"); + +// "info" now refers to the "std.log.info" function. +const info = std.log.info; + +// Usual hello world. +// syntax: [pub] fn <function-name>(<arguments>) <return-type> { <body> } +pub fn main() void { + // Contrary to C functions, Zig functions have a fixed number of arguments. + // In C: "printf" takes any number of arguments. + // In Zig: std.log.info takes a format and a list of elements to print. + info("hello world", .{}); // .{} is an empty anonymous tuple. +} +``` + +### Booleans, integers and float. + +```zig +// Booleans. +// Keywords are preferred to operators for boolean operations. +print("{}\n{}\n{}\n", .{ + true and false, + true or false, + !true, +}); + +// Integers. +const one_plus_one: i32 = 1 + 1; +print("1 + 1 = {}\n", .{one_plus_one}); // 2 + +// Floats. +const seven_div_three: f32 = 7.0 / 3.0; +print("7.0 / 3.0 = {}\n", .{seven_div_three}); // 2.33333325e+00 + +// Integers have arbitrary value lengths. +var myvar: u10 = 5; // 10-bit unsigned integer +// Useful for example to read network packets, or complex binary formats. + +// Number representation is greatly improved compared to C. +const one_billion = 1_000_000_000; // Decimal. +const binary_mask = 0b1_1111_1111; // Binary. Ex: network mask. +const permissions = 0o7_5_5; // Octal. Ex: Unix permissions. +const big_address = 0xFF80_0000_0000_0000; // Hexa. Ex: IPv6 address. + + +// Overflow operators: tell the compiler when it's okay to overflow. +var i: u8 = 0; // "i" is an unsigned 8-bit integer +i -= 1; // runtime overflow error (unsigned value always are positive) +i -%= 1; // okay (wrapping operator), i == 255 + +// Saturation operators: values will stick to their lower and upper bounds. +var i: u8 = 200; // "i" is an unsigned 8-bit integer (values: from 0 to 255) +i +| 100 == 255 // u8: won't go higher than 255 +i -| 300 == 0 // unsigned, won't go lower than 0 +i *| 2 == 255 // u8: won't go higher than 255 +i <<| 8 == 255 // u8: won't go higher than 255 +``` + +### Arrays. + +```zig +// An array is a well-defined structure with a length attribute (len). + +// 5-byte array with undefined content (stack garbage). +var array1: [5]u8 = undefined; + +// 5-byte array with defined content. +var array2 = [_]u8{ 1, 2, 3, 4, 5 }; +// [_] means the compiler knows the length at compile-time. + +// 1000-byte array with defined content (0). +var array3 = [_]u8{0} ** 1000; + +// Another 1000-byte array with defined content. +// The content is provided by the "foo" function, called at compile-time and +// allows complex initializations. +var array4 = [_]u8{foo()} ** 1000; + +// In any case, array.len gives the length of the array, +// array1.len and array2.len produce 5, array3.len and array4.len produce 1000. + + +// Modifying and accessing arrays content. + +// Array of 10 32-bit undefined integers. +var some_integers: [10]i32 = undefined; + +some_integers[0] = 30; // first element of the array is now 30 + +var x = some_integers[0]; // "x" now equals to 30, its type is inferred. +var y = some_integers[1]; // Second element of the array isn't defined. + // "y" got a stack garbage value (no runtime error). + +// Array of 10 32-bit undefined integers. +var some_integers: [10]i32 = undefined; + +var z = some_integers[20]; // index > array size, compilation error. + +// At runtime, we loop over the elements of "some_integers" with an index. +// Index i = 20, then we try: +try some_integers[i]; // Runtime error 'index out of bounds'. + // "try" keyword is necessary when accessing an array with + // an index, since there is a potential runtime error. + // More on that later. +``` + +### Multidimensional arrays. + +```zig +const mat4x4 = [4][4]f32{ + [_]f32{ 1.0, 0.0, 0.0, 0.0 }, + [_]f32{ 0.0, 1.0, 0.0, 1.0 }, + [_]f32{ 0.0, 0.0, 1.0, 0.0 }, + [_]f32{ 0.0, 0.0, 0.0, 1.0 }, +}; + +// Access the 2D array then the inner array through indexes. +try expect(mat4x4[1][1] == 1.0); + +// Here we iterate with for loops. +for (mat4x4) |row, row_index| { + for (row) |cell, column_index| { + // ... + } +} +``` + +### Strings. + +```zig +// Simple string constant. +const greetings = "hello"; +// ... which is equivalent to: +const greetings: *const [5:0]u8 = "hello"; +// In words: "greetings" is a constant value, a pointer on a constant array of 5 +// elements (8-bit unsigned integers), with an extra '0' at the end. +// The extra "0" is called a "sentinel value". + +print("string: {s}\n", .{greetings}); + +// This represents rather faithfully C strings. Although, Zig strings are +// structures, no need for "strlen" to compute their size. +// greetings.len == 5 +``` + +### Slices. + +```zig +// A slice is a pointer and a size, an array without compile-time known size. +// Slices have runtime out-of-band verifications. + +const array = [_]u8{1,2,3,4,5}; // [_] = array with compile-time known size. +const slice = array[0..array.len]; // "slice" represents the whole array. + // slice[10] gives a runtime error. +``` + +### Pointers. + +```zig +// Pointer on a value can be created with "&". +const x: i32 = 1; +const pointer: *i32 = &x; // "pointer" is a pointer on the i32 var "x". +print("1 = {}, {}\n", .{x, pointer}); + +// Pointer values are accessed and modified with ".*". +if (pointer.* == 1) { + print("x value == {}\n", .{pointer.*}); +} + +// ".?" is a shortcut for "orelse unreachable". +const foo = pointer.?; // Get the pointed value, otherwise crash. +``` + +### Optional values (?<type>). + +```zig +// An optional is a value than can be of any type or null. + +// Example: "optional_value" can either be "null" or an unsigned 32-bit integer. +var optional_value: ?u32 = null; // optional_value == null +optional_value = 42; // optional_value != null + +// "some_function" returns ?u32 +var x = some_function(); +if (x) |value| { + // In case "some_function" returned a value. + // Do something with 'value'. +} +``` + +### Errors. + +```zig +// Zig provides an unified way to express errors. + +// Errors are defined in error enumerations, example: +const Error = error { + WatchingAnyNetflixTVShow, + BeOnTwitter, +}; + +// Normal enumerations are expressed the same way, but with "enum" keyword. +const SuccessStory = enum { + DoingSport, + ReadABook, +}; + + +// Error union (!). +// Either the value "mylife" is an an error or a normal value. +var mylife: Error!SuccessStory = Error.BeOnTwitter; +// mylife is an error. Sad. + +mylife = SuccessStory.ReadABook; +// Now mylife is an enum. + + +// Zig ships with many pre-defined errors. Example: +const value: anyerror!u32 = error.Broken; + + +// Handling errors. + +// Some error examples. +const Error = error { + UnExpected, + Authentication, +}; + +// "some_function" can either return an "Error" or an integer. +fn some_function() Error!u8 { + return Error.UnExpected; // It returns an error. +} + +// Errors can be "catch" without intermediate variable. +var value = some_function() catch |err| switch(err) { + Error.UnExpected => return err, // Returns the error. + Error.Authentication => unreachable, // Not expected. Crashes the program. + else => unreachable, +}; + +// An error can be "catch" without giving it a name. +const unwrapped = some_function() catch 1234; // "unwrapped" = 1234 + +// "try" is a very handy shortcut for "catch |err| return err". +var value = try some_function(); +// If "some_function" fails, the current function stops and returns the error. +// "value" can only have a valid value, the error already is handled with "try". +``` + +### Control flow. + +```zig +// Conditional branching. + +if (condition) { + ... +} +else { + ... +} + +// Ternary. +var value = if (condition) x else y; + +// Shortcut for "if (x) x else 0" +var value = x orelse 0; + +// If "a" is an optional, which may contain a value. +if (a) |value| { + print("value: {}\n", .{value}); +} +else { + print("'a' is null\n", .{}); +} + +// Get a pointer on the value (if it exists). +if (a) |*value| { value.* += 1; } + + +// Loops. + +// Syntax examples: +// while (condition) statement +// while (condition) : (end-of-iteration-statement) statement +// +// for (iterable) statement +// for (iterable) |capture| statement +// for (iterable) statement else statement + +// Note: loops work the same way over arrays or slices. + +// Simple "while" loop. +while (i < 10) { i += 1; } + +// While loop with a "continue expression" +// (expression executed as the last expression of the loop). +while (i < 10) : (i += 1) { ... } +// Same, with a more complex continue expression (block of code). +while (i * j < 2000) : ({ i *= 2; j *= 3; }) { ... } + +// To iterate over a portion of a slice, reslice. +for (items[0..1]) |value| { sum += value; } + +// Loop over every item of an array (or slice). +for (items) |value| { sum += value; } + +// Iterate and get pointers on values instead of copies. +for (items) |*value| { value.* += 1; } + +// Iterate with an index. +for (items) |value, i| { print("val[{}] = {}\n", .{i, value}); } + +// Iterate with pointer and index. +for (items) |*value, i| { print("val[{}] = {}\n", .{i, value}); value.* += 1; } + + +// Break and continue are supported. +for (items) |value| { + if (value == 0) { continue; } + if (value >= 10) { break; } + // ... +} + +// For loops can also be used as expressions. +// Similar to while loops, when you break from a for loop, +// the else branch is not evaluated. +var sum: i32 = 0; +// The "for" loop has to provide a value, which will be the "else" value. +const result = for (items) |value| { + if (value != null) { + sum += value.?; // "result" will be the last "sum" value. + } +} else 0; // Last value. +``` + +### Labels. + +```zig +// Labels are a way to name an instruction, a location in the code. +// Labels can be used to "continue" or "break" in a nested loop. +outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| { + for ([_]i32{ 1, 2, 3, 4, 5 }) |_| { + count += 1; + continue :outer; // "continue" for the first loop. + } +} // count = 8 +outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| { + for ([_]i32{ 1, 2, 3, 4, 5 }) |_| { + count += 1; + break :outer; // "break" for the first loop. + } +} // count = 1 + + +// Labels can also be used to return a value from a block. +var y: i32 = 5; +const x = blk: { + y += 1; + break :blk y; // Now "x" equals 6. +}; +// Relevant in cases like "for else" expression (explained in the following). + +// For loops can be used as expressions. +// When you break from a for loop, the else branch is not evaluated. +// WARNING: counter-intuitive. +// The "for" loop will run, then the "else" block will run. +// The "else" keyword has to be followed by the value to give to "result". +// See later for another form. +var sum: u8 = 0; +const result = for (items) |value| { + sum += value; +} else 8; // result = 8 + +// In this case, the "else" keyword is followed by a value, too. +// However, the syntax is different: it is labeled. +// Instead of a value, there is a label followed by a block of code, which +// allows to do stuff before returning the value (see the "break" invocation). +const result = for (items) |value| { // First: loop. + sum += value; +} else blk: { // Second: "else" block. + std.log.info("executed AFTER the loop!", .{}); + break :blk sum; // The "sum" value will replace the label "blk". +}; +``` + +### Switch. + +```zig +// As a switch in C, but slightly more advanced. +// Syntax: +// switch (value) { +// pattern => expression, +// pattern => expression, +// else => expression +// }; + +// A switch only checking for simple values. +var x = switch(value) { + Error.UnExpected => return err, + Error.Authentication => unreachable, + else => unreachable, +}; + +// A slightly more advanced switch, accepting a range of values: +const foo: i32 = 0; +const bar = switch (foo) { + 0 => "zero", + 1...std.math.maxInt(i32) => "positive", + else => "negative", +}; +``` + +### Structures. + +```zig +// Structure containing a single value. +const Full = struct { + number: u16, +}; + +// Packed structure, with guaranteed in-memory layout. +const Divided = packed struct { + half1: u8, + quarter3: u4, + quarter4: u4, +}; + +// Point is a constant representing a structure containing two u32, "x" and "y". +// "x" has a default value, which wasn't possible in C. +const Point = struct { + x: u32 = 1, // default value + y: u32, +}; + +// Variable "p" is a new Point, with x = 1 (default value) and y = 2. +var p = Point{ .y = 2 }; + +// Fields are accessed as usual with the dot notation: variable.field. +print("p.x: {}\n", .{p.x}); // 1 +print("p.y: {}\n", .{p.y}); // 2 + + +// A structure can also contain public constants and functions. +const Point = struct { + pub const some_constant = 30; + + x: u32, + y: u32, + + // This function "init" creates a Point and returns it. + pub fn init() Point { + return Point{ .x = 0, .y = 0 }; + } +}; + + +// How to access a structure public constant. +// The value isn't accessed from an "instance" of the structure, but from the +// constant representing the structure definition (Point). +print("constant: {}\n", .{Point.some_constant}); + +// Having an "init" function is rather idiomatic in the standard library. +// More on that later. +var p = Point.init(); +print("p.x: {}\n", .{p.x}); // p.x = 0 +print("p.y: {}\n", .{p.y}); // p.y = 0 + + +// Structures often have functions to modify their state, similar to +// object-oriented programming. +const Point = struct { + const Self = @This(); // Refers to its own type (later called "Point"). + + x: u32, + y: u32, + + // Take a look at the signature. First argument is of type *Self: "self" is + // a pointer on the instance of the structure. + // This allows the same "dot" notation as in OOP, like "instance.set(x,y)". + // See the following example. + pub fn set(self: *Self, x: u32, y: u32) void { + self.x = x; + self.y = y; + } + + // Again, look at the signature. First argument is of type Self (not *Self), + // this isn't a pointer. In this case, "self" refers to the instance of the + // structure, but can't be modified. + pub fn getx(self: Self) u32 { + return self.x; + } + + // PS: two previous functions may be somewhat useless. + // Attributes can be changed directly, no need for accessor functions. + // It was just an example. +}; + +// Let's use the previous structure. +var p = Point{ .x = 0, .y = 0 }; // "p" variable is a Point. + +p.set(10, 30); // x and y attributes of "p" are modified via the "set" function. +print("p.x: {}\n", .{p.x}); // 10 +print("p.y: {}\n", .{p.y}); // 30 + +// In C: +// 1. We would have written something like: point_set(p, 10, 30). +// 2. Since all functions are in the same namespace, it would have been +// very cumbersome to create functions with different names for different +// structures. Many long names, painful to read. +// +// In Zig, structures provide namespaces for their own functions. +// Different structures can have the same names for their functions, +// which brings clarity. +``` + +### Tuples. + +```zig +// A tuple is a list of elements, possibly of different types. + +const foo = .{ "hello", true, 42 }; +// foo.len == 3 +``` + +### Enumerations. + +```zig +const Type = enum { ok, not_ok }; + +const CardinalDirections = enum { North, South, East, West }; +const direction: CardinalDirections = .North; +const x = switch (direction) { + // shorthand for CardinalDirections.North + .North => true, + else => false +}; + +// Switch statements need exhaustiveness. +// WARNING: won't compile. East and West are missing. +const x = switch (direction) { + .North => true, + .South => true, +}; + + +// Switch statements need exhaustiveness. +// Won't compile: East and West are missing. +const x = switch (direction) { + .North => true, + .South => true, + .East, // Its value is the same as the following pattern: false. + .West => false, +}; + + +// Enumerations are like structures: they can have functions. +``` + +### Unions. + +```zig +const Bar = union { + boolean: bool, + int: i16, + float: f32, +}; + +// Both syntaxes are equivalent. +const foo = Bar{ .int = 42 }; +const foo: Bar = .{ .int = 42 }; + +// Unions, like enumerations and structures, can have functions. +``` + +### Tagged unions. + +```zig +// Unions can be declared with an enum tag type, allowing them to be used in +// switch expressions. + +const MaybeEnum = enum { + success, + failure, +}; + +const Maybe = union(MaybeEnum) { + success: u8, + failure: []const u8, +}; + +// First value: success! +const yay = Maybe{ .success = 42 }; +switch (yay) { + .success => |value| std.log.info("success: {}", .{value}), + .failure => |err_msg| std.log.info("failure: {}", .{err_msg}), +} + +// Second value: failure! :( +const nay = Maybe{ .failure = "I was too lazy" }; +switch (nay) { + .success => |value| std.log.info("success: {}", .{value}), + .failure => |err_msg| std.log.info("failure: {}", .{err_msg}), +} +``` + +### Defer and errdefer. + +```zig +// Make sure that an action (single instruction or block of code) is executed +// before the end of the scope (function, block of code). +// Even on error, that action will be executed. +// Useful for memory allocations, and resource management in general. + +pub fn main() void { + // Should be executed at the end of the function. + defer print("third!\n", .{}); + + { + // Last element of its scope: will be executed right away. + defer print("first!\n", .{}); + } + + print("second!\n", .{}); +} + +fn hello_world() void { + defer print("end of function\n", .{}); // after "hello world!" + + print("hello world!\n", .{}); +} + +// errdefer executes the instruction (or block of code) only on error. +fn second_hello_world() !void { + errdefer print("2. something went wrong!\n", .{}); // if "foo" fails. + defer print("1. second hello world\n", .{}); // executed after "foo" + + try foo(); +} +// Defer statements can be seen as stacked: first one is executed last. +``` + +### Memory allocators. +Memory isn't managed directly in the standard library, instead an "allocator" is asked every time an operation on memory is required. +Thus, the standard library lets developers handle memory as they need, through structures called "allocators", handling all memory operations. + +**NOTE**: the choice of the allocator isn't in the scope of this document. +A whole book could be written about it. +However, here are some examples, to get an idea of what you can expect: +- `page_allocator`. + Allocate a whole page of memory each time we ask for some memory. + Very simple, very dumb, very wasteful. +- `GeneralPurposeAllocator`. + Get some memory first and manage some buckets of memory in order to + reduce the number of allocations. + A bit complex. Can be combined with other allocators. + Can detect leaks and provide useful information to find them. +- `FixedBufferAllocator`. + Use a fixed buffer to get its memory, don't ask memory to the kernel. + Very simple, limited and wasteful (can't deallocate), but very fast. +- `ArenaAllocator`. + Allow to free all allocated memory at once. + To use in combinations with another allocator. + Very simple way of avoiding leaks. + +A first example. + +```zig +// "!void" means the function doesn't return any value except for errors. +// In this case we try to allocate memory, and this may fail. +fn foo() !void { + // In this example we use a page allocator. + var allocator = std.heap.page_allocator; + + // "list" is an ArrayList of 8-bit unsigned integers. + // An ArrayList is a contiguous, growable list of elements in memory. + var list = try ArrayList(u8).initAllocated(allocator); + defer list.deinit(); // Free the memory at the end of the scope. Can't leak. + // "defer" allows to express memory release right after its allocation, + // regardless of the complexity of the function (loops, conditions, etc.). + + list.add(5); // Some memory is allocated here, with the provided allocator. + + for (list.items) |item| { + std.debug.print("item: {}\n", .{item}); + } +} +``` + +### Memory allocation combined with error management and defer. + +```zig +fn some_memory_allocation_example() !void { + // Memory allocation may fail, so we "try" to allocate the memory and + // in case there is an error, the current function returns it. + var buf = try page_allocator.alloc(u8, 10); + // Defer memory release right after the allocation. + // Will happen even if an error occurs. + defer page_allocator.free(buf); + + // Second allocation. + // In case of a failure, the first allocation is correctly released. + var buf2 = try page_allocator.alloc(u8, 10); + defer page_allocator.free(buf2); + + // In case of failure, both previous allocations are correctly deallocated. + try foo(); + try bar(); + + // ... +} +``` + +### Memory allocators: a taste of the standard library. + +```zig +// Allocators: 4 main functions to know +// single_value = create (type) +// destroy (single_value) +// slice = alloc (type, size) +// free (slice) + +// Page Allocator +fn page_allocator_fn() !void { + var slice = try std.heap.page_allocator.alloc(u8, 3); + defer std.heap.page_allocator.free(slice); + + // playing_with_a_slice(slice); +} + +// GeneralPurposeAllocator +fn general_purpose_allocator_fn() !void { + // GeneralPurposeAllocator has to be configured. + // In this case, we want to track down memory leaks. + const config = .{.safety = true}; + var gpa = std.heap.GeneralPurposeAllocator(config){}; + defer _ = gpa.deinit(); + + const allocator = gpa.allocator(); + + var slice = try allocator.alloc(u8, 3); + defer allocator.free(slice); + + // playing_with_a_slice(slice); +} + +// FixedBufferAllocator +fn fixed_buffer_allocator_fn() !void { + var buffer = [_]u8{0} ** 1000; // array of 1000 u8, all initialized at zero. + var fba = std.heap.FixedBufferAllocator.init(buffer[0..]); + // Side note: buffer[0..] is a way to create a slice from an array. + // Since the function takes a slice and not an array, this makes + // the type system happy. + + var allocator = fba.allocator(); + + var slice = try allocator.alloc(u8, 3); + // No need for "free", memory cannot be freed with a fixed buffer allocator. + // defer allocator.free(slice); + + // playing_with_a_slice(slice); +} + +// ArenaAllocator +fn arena_allocator_fn() !void { + // Reminder: arena doesn't allocate memory, it uses an inner allocator. + // In this case, we combine the arena allocator with the page allocator. + var arena = std.heap.arena_allocator.init(std.heap.page_allocator); + defer arena.deinit(); // end of function = all allocations are freed. + + var allocator = arena.allocator(); + + const slice = try allocator.alloc(u8, 3); + // No need for "free", memory will be freed anyway. + + // playing_with_a_slice(slice); +} + + +// Combining the general purpose and arena allocators. Both are very useful, +// and their combinations should be in everyone's favorite cookbook. +fn gpa_arena_allocator_fn() !void { + const config = .{.safety = true}; + var gpa = std.heap.GeneralPurposeAllocator(config){}; + defer _ = gpa.deinit(); + + const gpa_allocator = gpa.allocator(); + + var arena = arena_allocator.init(gpa_allocator); + defer arena.deinit(); + + const allocator = arena.allocator(); + + var slice = try allocator.alloc(u8, 3); + defer allocator.free(slice); + + // playing_with_a_slice(slice); +} +``` + +### Comptime. + +```zig +// Comptime is a way to avoid the pre-processor. +// The idea is simple: run code at compilation. + +inline fn max(comptime T: type, a: T, b: T) T { + return if (a > b) a else b; +} + +var res = max(u64, 1, 2); +var res = max(f32, 10.50, 32.19); + + +// Comptime: creating generic structures. + +fn List(comptime T: type) type { + return struct { + items: []T, + + fn init() ... { ... } + fn deinit() ... { ... } + fn do() ... { ... } + }; +} + +const MyList = List(u8); + + +// use +var list = MyList{ + .items = ... // memory allocation +}; + +list.items[0] = 10; +``` + +### Conditional compilation. + +```zig +const available_os = enum { OpenBSD, Linux }; +const myos = available_os.OpenBSD; + + +// The following switch is based on a constant value. +// This means that the only possible outcome is known at compile-time. +// Thus, there is no need to build the rest of the possibilities. +// Similar to the "#ifdef" in C, but without requiring a pre-processor. +const string = switch (myos) { + .OpenBSD => "OpenBSD is awesome!", + .Linux => "Linux rocks!", +}; + +// Also works in this case. +const myprint = switch(myos) { + .OpenBSD => std.debug.print, + .Linux => std.log.info, +} +``` + +### Testing our functions. + +```zig +const std = @import("std"); +const expect = std.testing.expect; + +// Function to test. +pub fn some_function() bool { + return true; +} + +// This "test" block can be run with "zig test". +// It will test the function at compile-time. +test "returns true" { + expect(false == some_function()); +} +``` + +### Compiler built-ins. +The compiler has special functions called "built-ins", starting with an "@". +There are more than a hundred built-ins, allowing very low-level stuff: +- compile-time errors, logging, verifications +- type coercion and conversion, even in an unsafe way +- alignment management +- memory tricks (such as getting the byte offset of a field in a struct) +- calling functions at compile-time +- including C headers to transparently call C functions +- atomic operations +- embed files into the executable (@embedFile) +- frame manipulations (for async functions, for example) +- etc. + +Example: enums aren't integers, they have to be converted with a built-in. + +```zig +const Value = enum { zero, stuff, blah }; +if (@enumToInt(Value.zero) == 0) { ... } +if (@enumToInt(Value.stuff) == 1) { ... } +if (@enumToInt(Value.blah) == 2) { ... } +``` + +### A few "not yourself in the foot" measures in the Zig language. + +- Namespaces: name conflicts are easily avoided. + In practice, that means a unified API between different structures (data types). +- Enumerations aren't integers. Comparing an enumeration to an integer requires a conversion. +- Explicit casts, coercion exists but is limited. + Types are slightly more enforced than in C, just a taste: + Pointers aren't integers, explicit conversion is necessary. + You won't lose precision by accident, implicit coercions are only authorized in cases where no precision can be lost. + Unions cannot be reinterpreted (in a union with an integer and a float, one cannot take a value for another by accident). + Etc. +- Removing most of the C undefined behaviors (UBs), and when the compiler encounters one, it stops. +- Slice and Array structures are preferred to pointers. + Types enforced by the compiler are less prone to errors than pointer manipulations. +- Numerical overflows produce an error, unless explicitly accepted using wrapping operators. +- `try` and `catch` mechanism. + It's both handy, trivially implemented (simple error enumeration), and it takes almost no space nor computation time. +- Unused variables are considered to be errors by the compiler. +- Many pointer types exist in order to represent what is pointed to. + Example: is this a single value or an array, is the length known, etc. +- Structures need a value for their attributes, and it is still possible to give an undefined value (stack garbage), but at least it is explicitly undefined. + + +## Further Reading + +For a start, some concepts are presented on [zig.guide][zigguide]. + +The [official website][zigdoc] provides the reference documentation of the language. The standard library [has its own documentation][zigstd]. + +[ziglang]: https://ziglang.org +[zigguide]: https://zig.guide/ +[zigdoc]: https://ziglang.org/documentation/ +[zigstd]: https://ziglang.org/documentation/master/std/ |