diff options
| author | Geoff Liu <g@geoffliu.me> | 2015-01-18 13:07:39 -0700 | 
|---|---|---|
| committer | Geoff Liu <g@geoffliu.me> | 2015-01-18 13:07:39 -0700 | 
| commit | 31faf1a6a1c35802cf3676ec1a7f54d86411b566 (patch) | |
| tree | 5ccca54b8837fec9a8d6d60d2bda6db4162078e7 | |
| parent | 40c38c125b94430b518d7e402d595694149b7c53 (diff) | |
| parent | c053f1559bb357d9e8ced2452096bf3a95cc7ddb (diff) | |
Merge branch 'master' of github.com:geoffliu/learnxinyminutes-docs
| -rw-r--r-- | README.markdown | 5 | ||||
| -rw-r--r-- | c.html.markdown | 14 | ||||
| -rw-r--r-- | csharp.html.markdown | 17 | ||||
| -rw-r--r-- | forth.html.markdown | 2 | ||||
| -rw-r--r-- | fr-fr/brainfuck-fr.html.markdown | 2 | ||||
| -rw-r--r-- | haxe.html.markdown | 2 | ||||
| -rw-r--r-- | hy.html.markdown | 2 | ||||
| -rw-r--r-- | java.html.markdown | 13 | ||||
| -rw-r--r-- | livescript.html.markdown | 8 | ||||
| -rw-r--r-- | perl6.html.markdown | 360 | ||||
| -rw-r--r-- | pogo.html.markdown | 2 | ||||
| -rw-r--r-- | pt-br/clojure-pt.html.markdown | 384 | ||||
| -rw-r--r-- | pt-br/swift-pt.html.markdown | 500 | ||||
| -rw-r--r-- | python.html.markdown | 2 | ||||
| -rw-r--r-- | python3.html.markdown | 1 | ||||
| -rw-r--r-- | ru-ru/go-ru.html.markdown | 2 | ||||
| -rw-r--r-- | ru-ru/lua-ru.html.markdown | 425 | ||||
| -rw-r--r-- | scala.html.markdown | 68 | ||||
| -rw-r--r-- | swift.html.markdown | 69 | ||||
| -rwxr-xr-x | tcl.html.markdown | 447 | ||||
| -rw-r--r-- | zh-cn/lua-cn.html.markdown | 6 | 
21 files changed, 2080 insertions, 251 deletions
| diff --git a/README.markdown b/README.markdown index 4e24bbe6..774797d5 100644 --- a/README.markdown +++ b/README.markdown @@ -22,6 +22,11 @@ Send a pull request or open an issue any time of day or night.  **(e.g. [python/en] for English Python).** This will help everyone pick out things they  care about. +We're happy for any contribution in any form, but if you're making more than one major change +(i.e. translations for two different languages) it would be super cool of you to make a +separate pull request for each one so that someone can review them more effectively and/or +individually. +  ### Style Guidelines  * **Keep lines under 80 chars** diff --git a/c.html.markdown b/c.html.markdown index f44da38e..7670824a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -26,13 +26,15 @@ Multi-line comments look like this. They work in C89 as well.  Multi-line comments don't nest /* Be careful */  // comment ends on this line...  */ // ...not this one! -  // Constants: #define <keyword> +// Constants: #define <keyword>  #define DAYS_IN_YEAR 365 -  // Enumeration constants are also ways to declare constants. -  enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +// 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};  // MON gets 2 automatically, TUE gets 3, etc. +  // Import headers with #include  #include <stdlib.h>  #include <stdio.h> @@ -57,7 +59,6 @@ int main() {    // print output using printf, for "print formatted"    // %d is an integer, \n is a newline    printf("%d\n", 0); // => Prints 0 -  // All statements must end with a semicolon    ///////////////////////////////////////    // Types @@ -385,7 +386,8 @@ int main() {    // or when it's the argument of the `sizeof` or `alignof` operator:    int arraythethird[10];    int *ptr = arraythethird; // equivalent with int *ptr = &arr[0]; -  printf("%zu, %zu\n", sizeof arraythethird, sizeof ptr); // probably prints "40, 4" or "40, 8" +  printf("%zu, %zu\n", sizeof arraythethird, sizeof ptr); +  // probably prints "40, 4" or "40, 8"    // Pointers are incremented and decremented based on their type @@ -476,7 +478,7 @@ void testFunc() {  }  //make external variables private to source file with static: -static int j = 0; //other files using testFunc() cannot access variable i +static int j = 0; //other files using testFunc2() cannot access variable j  void testFunc2() {    extern int j;  } diff --git a/csharp.html.markdown b/csharp.html.markdown index f6708590..47dd9683 100644 --- a/csharp.html.markdown +++ b/csharp.html.markdown @@ -678,6 +678,23 @@ on a new line! ""Wow!"", the masses cried";              private set;          } +        // It's also possible to define custom Indexers on objects. +        // All though this is not entirely useful in this example, you +        // could do bicycle[0] which yields "chris" to get the first passenger or +        // bicycle[1] = "lisa" to set the passenger. (of this apparent quattrocycle) +        private string[] passengers = { "chris", "phil", "darren", "regina" } + +        public string this[int i] +        { +            get { +                return passengers[i]; +            } + +            set { +                return passengers[i] = value; +            } +        } +          //Method to display the attribute values of this Object.          public virtual string Info()          { diff --git a/forth.html.markdown b/forth.html.markdown index 570e12ed..f7c0bf34 100644 --- a/forth.html.markdown +++ b/forth.html.markdown @@ -12,7 +12,7 @@ such as Open Firmware. It's also used by NASA.  Note: This article focuses predominantly on the Gforth implementation of  Forth, but most of what is written here should work elsewhere. -```forth +```  \ This is a comment  ( This is also a comment but it's only used when defining words ) diff --git a/fr-fr/brainfuck-fr.html.markdown b/fr-fr/brainfuck-fr.html.markdown index 3882734d..545e407e 100644 --- a/fr-fr/brainfuck-fr.html.markdown +++ b/fr-fr/brainfuck-fr.html.markdown @@ -13,7 +13,7 @@ Brainfuck (sans majuscule à part au début d’une phrase) est un langage  Turing-complet extrêmement simple avec seulement 8 commandes.  ``` -Tout caractère en dehors de "><+-.,[]" (en dehors des guillements) est ignoré. +Tout caractère en dehors de "><+-.,[]" (en dehors des guillemets) est ignoré.  Brainfuck est représenté par un tableau de 30 000 cellules initialisées à 0 et  un pointeur de données pointant sur la cellule courante. diff --git a/haxe.html.markdown b/haxe.html.markdown index 6a868f09..8599de8d 100644 --- a/haxe.html.markdown +++ b/haxe.html.markdown @@ -484,7 +484,7 @@ class LearnHaxe3{          // we can read this variable          trace(foo_instance.public_read + " is the value for foo_instance.public_read");          // but not write it -        // foo_instance.public_write = 4; // this will throw an error if uncommented: +        // foo_instance.public_read = 4; // this will throw an error if uncommented:          // trace(foo_instance.public_write); // as will this.          trace(foo_instance + " is the value for foo_instance"); // calls the toString method diff --git a/hy.html.markdown b/hy.html.markdown index 04bd05c9..9beaff0c 100644 --- a/hy.html.markdown +++ b/hy.html.markdown @@ -83,7 +83,7 @@ True ; => True  (greet "bilbo") ;=> "hello bilbo"  ; functions can take optional arguments as well as keyword arguments -(defn foolist [arg1 &optional [arg2 2]] +(defn foolists [arg1 &optional [arg2 2]]    [arg1 arg2])  (foolists 3) ;=> [3 2] diff --git a/java.html.markdown b/java.html.markdown index f08c4679..3dd65679 100644 --- a/java.html.markdown +++ b/java.html.markdown @@ -4,6 +4,7 @@ language: java  contributors:      - ["Jake Prather", "http://github.com/JakeHP"]      - ["Madison Dickson", "http://github.com/mix3d"] +    - ["Jakukyo Friel", "http://weakish.github.io"]  filename: LearnJava.java  --- @@ -49,7 +50,7 @@ public class LearnJava {          // Types & Variables          /////////////////////////////////////// -        // Declare a variable using <type> <name> [ +        // Declare a variable using <type> <name>          // Byte - 8-bit signed two's complement integer          // (-128 <= byte <= 127)          byte fooByte = 100; @@ -268,9 +269,9 @@ public class LearnJava {          System.out.println(bar); // Prints A, because the statement is true -        /////////////////////////////////////// -        // Converting Data Types And Typcasting -        /////////////////////////////////////// +        //////////////////////////////////////// +        // Converting Data Types And Typecasting +        ////////////////////////////////////////          // Converting data @@ -433,10 +434,12 @@ public interface Digestible {  //We can now create a class that implements both of these interfaces  public class Fruit implements Edible, Digestible { +    @Override  	public void eat() {  		//...  	} +    @Override  	public void digest() {  		//...   	} @@ -445,10 +448,12 @@ public class Fruit implements Edible, Digestible {  //In java, you can extend only one class, but you can implement many interfaces.  //For example:  public class ExampleClass extends ExampleClassParent implements InterfaceOne, InterfaceTwo { +    @Override  	public void InterfaceOneMethod() {  	} +    @Override  	public void InterfaceTwoMethod() {  	} diff --git a/livescript.html.markdown b/livescript.html.markdown index 429b91cb..e64f7719 100644 --- a/livescript.html.markdown +++ b/livescript.html.markdown @@ -219,8 +219,8 @@ identity 1      # => 1  # Operators are not functions in LiveScript, but you can easily turn  # them into one! Enter the operator sectioning: -divide-by-2 = (/ 2) -[2, 4, 8, 16].map(divide-by-2) .reduce (+) +divide-by-two = (/ 2) +[2, 4, 8, 16].map(divide-by-two) .reduce (+)  # Not only of function application lives LiveScript, as in any good @@ -248,8 +248,8 @@ reduce = (f, xs, initial) --> xs.reduce f, initial  # The underscore is also used in regular partial application, which you  # can use for any function:  div = (left, right) -> left / right -div-by-2 = div _, 2 -div-by-2 4      # => 2 +div-by-two = div _, 2 +div-by-two 4      # => 2  # Last, but not least, LiveScript has back-calls, which might help diff --git a/perl6.html.markdown b/perl6.html.markdown index b178de1e..13f383fe 100644 --- a/perl6.html.markdown +++ b/perl6.html.markdown @@ -35,7 +35,8 @@ my $variable;  ## * Scalars. They represent a single value. They start with a `$`  my $str = 'String'; -my $str2 = "String"; # double quotes allow for interpolation +# 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 : @@ -66,23 +67,13 @@ my @keys = 0, 2;  @array[@keys] = @letters; # Assign using an array  say @array; #=> a 6 b -# There are two more kinds of lists: Parcel and Arrays. -# Parcels are immutable lists (you can't modify a list that's not assigned). -# This is a parcel: -(1, 2, 3); # Not assigned to anything. Changing an element would provoke an error -# This is a list: -my @a = (1, 2, 3); # Assigned to `@a`. Changing elements is okay! - -# Lists flatten (in list context). You'll see below how to apply item context -#  or use arrays to have real nested lists. - - -## * Hashes. Key-Value Pairs. -# Hashes are actually arrays of Pairs (`Key => Value`), -#  except they get "flattened", removing duplicated keys. +## * Hashes, or key-value Pairs. +# Hashes are actually arrays of Pairs +# (you can construct a Pair object using the syntax `Key => Value`), +#  except they get "flattened" (hash context), removing duplicated keys.  my %hash = 1 => 2,             3 => 4; -my %hash = autoquoted => "key", # keys *can* get auto-quoted +my %hash = autoquoted => "key", # keys get auto-quoted              "some other" => "value", # trailing commas are okay              ;  my %hash = <key1 value1 key2 value2>; # you can also create a hash @@ -112,30 +103,6 @@ sub say-hello-to(Str $name) { # You can provide the type of an argument      say "Hello, $name !";  } -# Since you can omit parenthesis to call a function with no arguments, -#  you need "&" in the name to capture `say-hello`. -my &s = &say-hello; -my &other-s = sub { say "Anonymous function !" } - -# A sub can have a "slurpy" parameter, or "doesn't-matter-how-many" -sub as-many($head, *@rest) { # `*@` (slurpy) will basically "take everything else". -                             # Note: you can have parameters *before* (like here) -                             # a slurpy one, but not *after*. -  say @rest.join(' / ') ~ " !"; -} -say as-many('Happy', 'Happy', 'Birthday'); #=> Happy / Birthday ! -                                           # Note that the splat did not consume -                                           #  the parameter before. - -## 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 -  ## It can also have optional arguments:  sub with-optional($arg?) { # the "?" marks the argument optional    say "I might return `(Any)` if I don't have an argument passed, @@ -154,23 +121,20 @@ hello-to; #=> Hello, World !  hello-to(); #=> Hello, World !  hello-to('You'); #=> Hello, You ! -## You can also, by using a syntax akin to the one of hashes (yay unification !), +## 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" (Perl's "null"-like value).  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 paramater. +#  and you'll have a single Pair object as a positional paramater, +#  which means this fails: +with-named(1, 'named' => 6);  with-named(2, :named(5)); #=> 7 -with-named(3, :4named); #=> 7 -                        # (special colon pair syntax for numbers, -                        # to be used with s// and such, see later) - -with-named(3); # warns, because we tried to use the undefined $named in a `+`: -               # by default, named arguments are *optional*  # To make a named argument mandatory, you can use `?`'s inverse, `!`  sub with-mandatory-named(:$str!)  { @@ -187,11 +151,6 @@ sub takes-a-bool($name, :$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 -# or you can use the "adverb" form: -takes-a-bool('config'):bool; #=> config takes True -takes-a-bool('config'):!bool; #=> config takes False -# You'll learn to love (or maybe hate, eh) that syntax later. -  ## You can also provide your named arguments with defaults:  sub named-def(:$def = 5) { @@ -201,8 +160,29 @@ named-def; #=> 5  named-def(:10def); #=> 10  named-def(def => 15); #=> 15 -# -- Note: we're going to learn *more* on subs really soon, -#  but we need to grasp a few more things to understand their real power. Ready? +# Since you can omit parenthesis to call a function with no arguments, +#  you need "&" in the name to capture `say-hello`. +my &s = &say-hello; +my &other-s = sub { say "Anonymous function !" } + +# A sub can have a "slurpy" parameter, or "doesn't-matter-how-many" +sub as-many($head, *@rest) { # `*@` (slurpy) will basically "take everything else". +                             # Note: you can have parameters *before* (like here) +                             # a slurpy one, but not *after*. +  say @rest.join(' / ') ~ " !"; +} +say as-many('Happy', 'Happy', 'Birthday'); #=> Happy / Birthday ! +                                           # Note that the splat did not consume +                                           #  the parameter before. + +## 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  # In Perl 6, values are actually stored in "containers". @@ -220,23 +200,19 @@ sub mutate($n is rw) {  # A sub itself returns a container, which means it can be marked as rw:  my $x = 42; -sub mod() is rw { $x } -mod() = 52; # in this case, the parentheses are mandatory -            # (else Perl 6 thinks `mod` is a "term") +sub x-store() is rw { $x } +x-store() = 52; # in this case, the parentheses are mandatory +                # (else Perl 6 thinks `mod` is an identifier)  say $x; #=> 52  ### Control Flow Structures - -# You don't need to put parenthesis around the condition, -# but that also means you always have to use brackets (`{ }`) for their body: -  ## Conditionals  # - `if`  # Before talking about `if`, we need to know which values are "Truthy"  #  (represent True), and which are "Falsey" (or "Falsy") -- represent False. -# Only these values are Falsey: (), 0, "0", Nil, A type (like `Str` or `Int`), +# Only these values are Falsey: (), 0, "0", "", Nil, A type (like `Str` or `Int`),  #  and of course False itself.  # Every other value is Truthy.  if True { @@ -247,30 +223,38 @@ unless False {    say "It's not false !";  } +# As you can see, you don't need parentheses around conditions. +# However, you do need the brackets around the "body" block: +# if (true) say; # This doesn't work ! +  # You can also use their postfix versions, with the keyword after:  say "Quite truthy" if True; -# if (true) say; # This doesn't work ! -  # - Ternary conditional, "?? !!" (like `x ? y : z` in some other languages)  my $a = $condition ?? $value-if-true !! $value-if-false;  # - `given`-`when` looks like other languages `switch`, but much more  # powerful thanks to smart matching and thanks to Perl 6's "topic variable", $_. +#  # This 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" { -  when /foo/ { # Don't worry about smart matching -- just know `when` uses it. +  say $_; #=> foo bar +  when /foo/ { # Don't worry about smart matching yet – just know `when` uses it.                 # This is equivalent to `if $_ ~~ /foo/`.      say "Yay !";    }    when $_.chars > 50 { # smart matching anything with True (`$a ~~ True`) is True,                         # so you can also put "normal" conditionals. +                       # This when is equivalent to this `if`: +                       #  if ($_.chars > 50) ~~ True {...}      say "Quite a long string !";    }    default { # same as `when *` (using the Whatever Star) @@ -281,7 +265,7 @@ given "foo bar" {  ## Looping constructs  # - `loop` is an infinite loop if you don't pass it arguments, -# but can also be a c-style `for`: +# 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 @@ -296,7 +280,7 @@ loop (my $i = 0; $i < 5; $i++) {  # - `for` - Passes through an array  for @array -> $variable { -  say "I've found $variable !"; +  say "I've got $variable !";  }  # As we saw with given, for's default "current iteration" variable is `$_`. @@ -316,22 +300,15 @@ for @array {    last if $_ == 5; # Or break out of a loop (like `break` in C-like languages).  } -# Note - the "lambda" `->` syntax isn't reserved to `for`: +# The "pointy block" syntax isn't specific to for. +# It's just a way to express a block in Perl6.  if long-computation() -> $result {    say "The result is $result";  } -## Loops can also have a label, and be jumped to through these. -OUTER: while 1 { -  say "hey"; -  while 1 { -    OUTER.last; # All the control keywords must be called on the label itself -  } -} -  # Now that you've seen how to traverse a list, you need to be aware of something:  # List context (@) flattens. If you traverse nested lists, you'll actually be traversing a -#  shallow list (except if some sub-list were put in item context ($)). +#  shallow list.  for 1, 2, (3, (4, ((5)))) {    say "Got $_.";  } #=> Got 1. Got 2. Got 3. Got 4. Got 5. @@ -348,9 +325,14 @@ for [1, 2, 3, 4] {    say "Got $_.";  } #=> Got 1 2 3 4. -# The other difference between `$()` and `[]` is that `[]` always returns a mutable Array -#  whereas `$()` will return a Parcel when given a Parcel. +# You need to be aware of when flattening happens exactly. +# The general guideline is that argument lists flatten, but not method calls. +# Also note that `.list` and array assignment flatten (`@ary = ...`) flatten. +((1,2), 3, (4,5)).map({...}); # iterates over three elements (method call) +map {...}, ((1,2),3,(4,5));   # iterates over five elements (argument list is flattened) +(@a, @b, @c).pick(1);         # picks one of three arrays (method call) +pick 1, @a, @b, @c;           # flattens argument list and pick one element  ### Operators @@ -394,9 +376,6 @@ $arg ~~ &bool-returning-function; # `True` if the function, passed `$arg`  1 ~~ True; # smart-matching against a boolean always returns that boolean             # (and will warn). -# - `===` is value identity and uses `.WHICH` on the objects to compare them -# - `=:=` is container identity and uses `VAR()` on the objects to compare them -  # You also, of course, have `<`, `<=`, `>`, `>=`.  # Their string equivalent are also avaiable : `lt`, `le`, `gt`, `ge`.  3 > 4; @@ -559,6 +538,21 @@ map(sub ($a, $b) { $a + $b + 3 }, @array); # (here with `sub`)  # Note : those are sorted lexicographically.  # `{ $^b / $^a }` is like `-> $a, $b { $b / $a }` +## About types... +# Perl6 is gradually typed. This means you can specify the type +#  of your variables/arguments/return types, or you can omit them +#  and they'll default to "Any". +# You obviously get access to a few base types, like Int and Str. +# The constructs for declaring types are "class", "role", +#  which you'll see later. + +# For now, let us examinate "subset": +# a "subset" 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" keyword: +subset VeryBigInteger of Int where * > 500; +  ## Multiple Dispatch  # 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 a `where`: @@ -567,20 +561,19 @@ map(sub ($a, $b) { $a + $b + 3 }, @array); # (here with `sub`)  multi sub sayit(Int $n) { # note the `multi` keyword here    say "Number: $n";  } -multi sayit(Str $s) } # the `sub` is the default +multi sayit(Str $s) } # a multi is a `sub` by default    say "String: $s";  }  sayit("foo"); # prints "String: foo"  sayit(True); # fails at *compile time* with               # "calling 'sayit' will never work with arguments of types ..." -# with arbitrary precondition: +# with arbitrary precondition (remember subsets?):  multi is-big(Int $n where * > 50) { "Yes !" } # using a closure  multi is-big(Int $ where 10..50) { "Quite." } # Using smart-matching                                                # (could use a regexp, etc)  multi is-big(Int $) { "No" } -# You can also name these checks, by creating "subsets":  subset Even of Int where * %% 2;  multi odd-or-even(Even) { "Even" } # The main case using the type. @@ -724,7 +717,7 @@ role PrintableVal {    }  } -# you "use" a mixin with "does" : +# you "import" a mixin (a "role") with "does":  class Item does PrintableVal {    has $.val; @@ -1083,9 +1076,7 @@ postcircumfix:<{ }>(%h, $key, :delete); # (you can call operators like that)  # It's a prefix meta-operator that takes a binary functions and  #  one or many lists. If it doesn't get passed any argument,  #  it either return a "default value" for this operator -#  (a value that wouldn't change the result if passed as one -#   of the element of the list to be passed to the operator), -#  or `Any` if there's none (examples below). +#  (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) @@ -1107,9 +1098,7 @@ say [//] Nil, Any, False, 1, 5; #=> False  # Default value examples:  say [*] (); #=> 1   say [+] (); #=> 0  -            # In both cases, they're results that, were they in the lists, -            #  wouldn't have any impact on the final value -            #  (since N*1=N and N+0=N). +            # meaningless values, since N*1=N and N+0=N.  say [//];   #=> (Any)              # There's no "default value" for `//`. @@ -1163,90 +1152,6 @@ say @fib[^10]; #=> 1 1 2 3 5 8 13 21 34 55  # That's why `@primes[^100]` will take a long time the first time you print  #  it, then be instant. - -## * Sort comparison -# They return one value of the `Order` enum : `Less`, `Same` and `More` -#  (which numerify to -1, 0 or +1). -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 -# Like `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 Flop -# The flip flop operators (`ff` and `fff`, equivalent to P5's `..`/`...`). -#  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`. -# Like for ranges, you can exclude the iteration when it became `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" -                        #  (explained in details below). -    .say -  } -   -  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 this printing 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 -} - -  ### Regular Expressions  # 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. @@ -1470,6 +1375,105 @@ multi MAIN('import', File, Str :$as) { ... } # omitting parameter name  # 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 +### + +# It's considered 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 bloat it up + +## Operators + + +## * Sort comparison +# They return one value of the `Order` enum : `Less`, `Same` and `More` +#  (which numerify to -1, 0 or +1). +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 +# Like `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 Flop +# The flip flop operators (`ff` and `fff`, equivalent to P5's `..`/`...`). +#  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`. +# Like for ranges, you can exclude the iteration when it became `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" +                        #  (explained in details below). +    .say +  } +   +  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 this printing 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 +} + + +# - `===` is value identity and uses `.WHICH` on the objects to compare them +# - `=:=` is container identity and uses `VAR()` on the objects to compare them +  ```  If you want to go further, you can: @@ -1477,5 +1481,5 @@ If you want to go further, you can:   - Read the [Perl 6 Advent Calendar](http://perl6advent.wordpress.com/). This is probably the greatest source of Perl 6 information, snippets and such.   - 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 [Synopses](perlcabal.org/syn). They explain it from an implementor point-of-view, but it's still very interesting. + - 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/pogo.html.markdown b/pogo.html.markdown index 60a83edd..aa5d49f3 100644 --- a/pogo.html.markdown +++ b/pogo.html.markdown @@ -199,4 +199,4 @@ That's it.  Download [Node.js](http://nodejs.org/) and `npm install pogo`. -There is plenty of documentation on [http://pogoscript.org/](http://pogoscript.org/), inlcuding a [cheat sheet](http://pogoscript.org/cheatsheet.html), a [guide](http://pogoscript.org/guide/), and how [Pogoscript translates to Javascript](http://featurist.github.io/pogo-examples/). Get in touch on the [google group](http://groups.google.com/group/pogoscript) if you have questions! +There is plenty of documentation on [http://pogoscript.org/](http://pogoscript.org/), including a [cheat sheet](http://pogoscript.org/cheatsheet.html), a [guide](http://pogoscript.org/guide/), and how [Pogoscript translates to Javascript](http://featurist.github.io/pogo-examples/). Get in touch on the [google group](http://groups.google.com/group/pogoscript) if you have questions! diff --git a/pt-br/clojure-pt.html.markdown b/pt-br/clojure-pt.html.markdown new file mode 100644 index 00000000..7e8b3f7b --- /dev/null +++ b/pt-br/clojure-pt.html.markdown @@ -0,0 +1,384 @@ +--- +language: clojure +filename: learnclojure-pt.clj +contributors: +    - ["Adam Bard", "http://adambard.com/"] +translators: +    - ["Mariane Siqueira Machado", "https://twitter.com/mariane_sm"] +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. + +Essa combinação permite gerenciar processamento concorrente de maneira muito simples, e frequentemente de maneira automática. + +(Sua versão de clojure precisa ser pelo menos 1.2) + + +```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. + +; 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. + +: A primeira chamada de um arquivo deve ser ns, para configurar o namespace (espaço de nomes) +(ns learnclojure) + +; Alguns exemplos básicos: + +; str cria uma string concatenando seus argumentos +(str "Hello" " " "World") ; => "Hello World" + +; Cálculos são feitos de forma direta e intuitiva +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 + +; Você pode comparar igualdade utilizando = +(= 1 1) ; => true +(= 2 1) ; => false + +; Negação para operações lógicas +(not true) ; => false + +; Aninhar "forms" funciona como esperado +(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 + +; 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 +(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))) + +; É 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 + +; 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) + +; "Coleções" são apenas grupos de dados +; Listas e vetores são ambos 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. +(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) + +; Use cons para adicionar um item no 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. +(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 +(concat [1 2] '(3 4)) ; => (1 2 3 4) + +; Use filter, map para interagir com coleções +(map inc [1 2 3]) ; => (2 3 4) +(filter even? [1 2 3]) ; => (2) + +; Use reduce para reduzi-los +(reduce + [1 2 3 4]) +; = (+ (+ (+ 1 2) 3) 4) +; => 10 + +; 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 + +; (É necessário colocar parênteses para chamá-los) +((fn [] "Hello World")) ; => "Hello World" + +; Você pode atribuir valores a variáveis utilizando def +(def x 1) +x ; => 1 + +; Atribua uma função para uma var +(def hello-world (fn [] "Hello World")) +(hello-world) ; => "Hello World" + +; Você pode abreviar esse processo usando defn +(defn hello-world [] "Hello World") + +; O [] é uma lista de argumentos para um função. +(defn hello [name] +  (str "Hello " name)) +(hello "Steve") ; => "Hello Steve" + +; Você pode ainda usar essa abreviação para criar funcões: +(def hello2 #(str "Hello " %1)) +(hello2 "Fanny") ; => "Hello Fanny" + +; 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)" + +; 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" + + +; 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. +(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 + + +; 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. +(class :a) ; => clojure.lang.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} + +; A propósito, vírgulas são sempre tratadas como espaçoes em branco e não fazem nada. + +; Recupere o valor de um mapa chamando ele como uma função +(stringmap "a") ; => 1 +(keymap :a) ; => 1 + +; Uma palavra-chave pode ser usada pra recuperar os valores de um mapa +(:b keymap) ; => 2 + +; Não tente isso com strings +;("a" stringmap) +; => Exception: java.lang.String cannot be cast to clojure.lang.IFn + +; Buscar uma chave não presente retorna nil +(stringmap "d") ; => nil + +; 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, tipos em Clojure são sempre imutáveis! +keymap ; => {:a 1, :b 2, :c 3} + +; Use dissoc para remover chaves +(dissoc keymap :a :b) ; => {:c 3} + +; Conjuntos +;;;;;; + +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} + +; Adicione um membro com conj +(conj #{1 2 3} 4) ; => #{1 2 3 4} + +; Remova um membro com disj +(disj #{1 2 3} 1) ; => #{2 3} + +; Test por existência usando set como função: +(#{1 2 3} 1) ; => 1 +(#{1 2 3} 4) ; => nil + +; Existem muitas outras funções no namespace clojure.sets + +; 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 + +; Use let para criar um novo escopo associando sîmbolos a valores (bindings) +(let [a 1 b 2] +  (> a b)) ; => false + +; Agrupe comandos juntos com "do" +(do +  (print "Hello") +  "World") ; => "World" (prints "Hello") + +; 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") + +; 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 +(use 'clojure.set) + +; Agora nós podemos usar operações com conjuntos +(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 +(require 'clojure.string) + +; Use / para chamar funções de um módulo +; 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 +(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) + +; 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. +(ns test +  (:require +    [clojure.string :as str] +    [clojure.set :as set])) + +; Java +;;;;;;;;;;;;;;;;; + +; Java tem uma biblioteca padrão enorme e muito útil,  +; portanto é importante aprender como utiliza-la. + +; Use import para carregar um modulo java +(import java.util.Date) + +; Você pode importar usando ns também. +(ns test +  (:import java.util.Date +           java.util.Calendar)) + +; Use o nome da clase com um "." no final para criar uma nova instância +(Date.) ; <a date object> + +; Use . para chamar métodos. Ou, use o atalho ".method" +(. (Date.) getTime) ; <a timestamp> +(.getTime (Date.)) ; exatamente a mesma coisa. + +; Use / para chamar métodos estáticos +(System/currentTimeMillis) ; <a timestamp> (o módulo System está sempre presente) + +; 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. + +; O atom é o mais simples. Passe pra ele um valor inicial +(def my-atom (atom {})) + +; Atualize o atom com um swap!. +; swap! pega uma funçnao and chama ela com o valor atual do atom +; como primeiro argumento, e qualquer argumento restante como o segundo +(swap! my-atom assoc :a 1) ; Coloca o valor do átomo my-atom como o resultado de  (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Coloca o valor do átomo my-atom como o resultado de (assoc {:a 1} :b 2) + +; Use '@' para desreferenciar um atom e acessar seu valor +my-atom  ;=> Atom<#...> (Retorna o objeto do Atom) +@my-atom ; => {:a 1 :b 2} + +; Abaixo um contador simples usando um atom +(def counter (atom 0)) +(defn inc-counter [] +  (swap! counter inc)) + +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) + +@counter ; => 5 + +; Outras construção STM são refs e agents. +; 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. + +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): +[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/) + +Clojure-doc.org tem um bom número de artigos para iniciantes: +[http://clojure-doc.org/](http://clojure-doc.org/) diff --git a/pt-br/swift-pt.html.markdown b/pt-br/swift-pt.html.markdown new file mode 100644 index 00000000..a29490b0 --- /dev/null +++ b/pt-br/swift-pt.html.markdown @@ -0,0 +1,500 @@ +--- +language: swift +contributors: +    - ["Grant Timmerman", "http://github.com/grant"], +    - ["Christopher Bess", "http://github.com/cbess"] +translators: +    - ["Mariane Siqueira Machado", "https://twitter.com/mariane_sm"] +lang: pt-br +filename: learnswift.swift +--- + +Swift é uma linguagem de programação para desenvolvimento de aplicações no iOS e OS X 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. + +O livro oficial [Swift Programming Language] (https://itunes.apple.com/us/book/swift-programming-language/id881256329) da +Apple já está disponível via IBooks (apenas em inglês). + +Confira também o tutorial completo de Swift da Apple [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/LandingPage/index.html), também disponível apenas em inglês. + +```swift +// importa um módulo +import UIKit + +// +// MARK: Noções básicas +// + +// Xcode supporta anotações para seu código e lista elas na barra de atalhos +// MARK: Marca uma sessão +// TODO: Faça algo logo +// FIXME: Conserte esse código + +println("Hello, world") + +// Valores em variáveis (var) podem ter seu valor alterado depois de declarados. +// Valores em constantes (let) NÃO podem ser alterados depois de declarados. + +var myVariable = 42 +let øπΩ = "value" // nomes de variáveis em unicode +let π = 3.1415926 +let convenience = "keyword" // nome de variável contextual +let weak = "keyword"; let override = "another keyword" // comandos podem ser separados por uma ponto e vírgula +let `class` = "keyword" // Crases permitem que palavras-chave seja usadas como nome de variáveis +let explicitDouble: Double = 70 +let intValue = 0007 // 7 +let largeIntValue = 77_000 // 77000 +let label = "some text " + String(myVariable) // Coerção +let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Interpolação de strings + +// Constrói valores específicos +// Utiliza configuração de build -D +#if false +    println("Not printed") +    let buildValue = 3 +#else +    let buildValue = 7 +#endif +println("Build value: \(buildValue)") // Build value: 7 + +/* +    Optionals fazem parte da linguagem e permitem que você armazene um  +    valor `Some` (algo) ou `None` (nada). +     +    Como Swift requer que todas as propriedades tenham valores, até mesmo nil deve +    ser explicitamente armazenado como um valor Optional. + +    Optional<T> é uma enum. +*/ +var someOptionalString: String? = "optional" // Pode ser nil +// o mesmo acima, mas ? é um operador pós-fixado (açúcar sintático) +var someOptionalString2: Optional<String> = "optional" + +if someOptionalString != nil { +    // Eu não sou nil +    if someOptionalString!.hasPrefix("opt") { +        println("has the prefix") +    } +     +    let empty = someOptionalString?.isEmpty +} +someOptionalString = nil + +// Optional implicitamente desempacotado (unwrapped) +var unwrappedString: String! = "Valor é esperado." +// o mesmo acima, mas ? é um operador pósfixado (açúcar sintático) +var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Valor é esperado." + +if let someOptionalStringConstant = someOptionalString { +    // Tem `Some` (algum) valor, não nil +    if !someOptionalStringConstant.hasPrefix("ok") { +        // não possui o prefixo +    } +} + +// Swift tem suporte para armazenar um valor de qualquer tipo. +// AnyObject == id +// Ao contrário de Objective-C `id`, AnyObject funciona com qualquer valor (Class, Int, struct, etc) +var anyObjectVar: AnyObject = 7 +anyObjectVar = "Mudou o valor para string, não é uma boa prática, mas é possível." + +/* +Comentário aqui +    /* +        Comentários aninhados também são suportados +    */ +*/ + +// +// MARK: Coleções +// + +/* +    Tipos Array e Dicionário são structs. Portanto `let` e `var` +    também indicam se são mutáveis (var) ou imutáveis (let) quando declarados +    com esses tipos. +*/ + +// Array +var shoppingList = ["catfish", "water", "lemons"] +shoppingList[1] = "bottle of water" +let emptyArray = [String]() // imutável +var emptyMutableArray = [String]() // mutável + + +// Dicionário +var occupations = [ +    "Malcolm": "Captain", +    "kaylee": "Mechanic" +] +occupations["Jayne"] = "Public Relations" +let emptyDictionary = [String: Float]() // imutável +var emptyMutableDictionary = [String: Float]() // mutável + + +// +// MARK: Controle de fluxo +// + +// laço for (array) +let myArray = [1, 1, 2, 3, 5] +for value in myArray { +    if value == 1 { +        println("One!") +    } else { +        println("Not one!") +    } +} + +// laço for (dicionário) +var dict = ["one": 1, "two": 2] +for (key, value) in dict { +    println("\(key): \(value)") +} + +// laço for (alcance) +for i in -1...shoppingList.count { +    println(i) +} +shoppingList[1...2] = ["steak", "peacons"] +// use ..< para excluir o último número + +// laço while (enquanto) +var i = 1 +while i < 1000 { +    i *= 2 +} + +// laço do-while +do { +    println("hello") +} while 1 == 2 + +// Switch +let vegetable = "red pepper" +switch vegetable { +case "celery": +    let vegetableComment = "Add some raisins and make ants on a log." +case "cucumber", "watercress": +    let vegetableComment = "That would make a good tea sandwich." +case let x where x.hasSuffix("pepper"): +    let vegetableComment = "Is it a spicy \(x)?" +default: // required (in order to cover all possible input) +    let vegetableComment = "Everything tastes good in soup." +} + + +// +// MARK: Funções +// + +// Funções são tipos de primeira classe, o que significa que eles podem ser aninhados +// em funções e podem ser passados como parâmetros + +// Funções Swift com cabeçalhos doc (formato como reStructedText) +/** +Uma operação de saudação + +- Um bullet em documentos +- Outro bullet + +:param: nome A nome +:param: dia A dia +:returns: Uma string contendo o nome e o dia. +*/ +func greet(name: String, day: String) -> String { +    return "Hello \(name), today is \(day)." +} +greet("Bob", "Tuesday") + +// Função que retorna múltiplos items em uma tupla +func getGasPrices() -> (Double, Double, Double) { +    return (3.59, 3.69, 3.79) +} +let pricesTuple = getGasPrices() +let price = pricesTuple.2 // 3.79 +// Ignore valores de Tuplas (ou outros valores) usando _ (underscore) +let (_, price1, _) = pricesTuple // price1 == 3.69 +println(price1 == pricesTuple.1) // true +println("Gas price: \(price)") + +// Número variável de argumentos +func setup(numbers: Int...) { +    // its an array +    let number = numbers[0] +    let argCount = numbers.count +} + +// Passando e retornando funções +func makeIncrementer() -> (Int -> Int) { +    func addOne(number: Int) -> Int { +        return 1 + number +    } +    return addOne +} +var increment = makeIncrementer() +increment(7) + +// passagem por referência +func swapTwoInts(inout a: Int, inout b: Int) { +    let tempA = a +    a = b +    b = tempA +} +var someIntA = 7 +var someIntB = 3 +swapTwoInts(&someIntA, &someIntB) +println(someIntB) // 7 + + +// +// MARK: Closures +// +var numbers = [1, 2, 6] + +// Funções são casos especiais de closures ({}) + +// Exemplo de closure. +// `->` separa argumentos e tipo de retorno +// `in` separa o cabeçalho do closure do seu corpo +numbers.map({ +    (number: Int) -> Int in +    let result = 3 * number +    return result +}) + +// Quando o tipo é conhecido, como abaixo, nós podemos fazer o seguinte +numbers = numbers.map({ number in 3 * number }) +// Ou até mesmo isso +//numbers = numbers.map({ $0 * 3 }) + +print(numbers) // [3, 6, 18] + +// Closure restante +numbers = sorted(numbers) { $0 > $1 } + +print(numbers) // [18, 6, 3] + +// Super atalho, já que o operador < infere os tipos + +numbers = sorted(numbers, < ) + +print(numbers) // [3, 6, 18] + +// +// MARK: Estruturas +// + +// Estruturas e classes tem funcionalidades muito similares +struct NamesTable { +    let names: [String] +     +    // Custom subscript +    subscript(index: Int) -> String { +        return names[index] +    } +} + +// Estruturas possuem um inicializador auto-gerado automático (implícito) +let namesTable = NamesTable(names: ["Me", "Them"]) +//let name = namesTable[2] +//println("Name is \(name)") // Name is Them + +// +// MARK: Classes +// + +// Classes, Estruturas e seus membros possuem três níveis de modificadores de acesso +// Eles são: internal (default), public, private + +public class Shape { +    public func getArea() -> Int { +        return 0; +    } +} + +// Todos os métodos e propriedades de uma classe são públicos. +// Se você só precisa armazenar dados em um objeto estruturado, use `struct` + +internal class Rect: Shape { +    var sideLength: Int = 1 +     +    // Getter e setter personalizado +    private var perimeter: Int { +        get { +            return 4 * sideLength +        } +        set { +            // `newValue` é uma variável implicita disponível para os setters +            sideLength = newValue / 4 +        } +    } +     +    // Carregue uma propriedade sob demanda (lazy) +    // subShape permanece nil (não inicializado) até seu getter ser chamado +    lazy var subShape = Rect(sideLength: 4) +     +    // Se você não precisa de um getter e setter personalizado, +    // mas ainda quer roda código antes e depois de configurar  +    // uma propriedade, você  pode usar `willSet` e `didSet` +    var identifier: String = "defaultID" { +        // o argumento `willSet` será o nome da variável para o novo valor +        willSet(someIdentifier) { +            print(someIdentifier) +        } +    } +     +    init(sideLength: Int) { +        self.sideLength = sideLength +         // sempre chame super.init por último quand inicializar propriedades personalizadas (custom) +        super.init() +    } +     +    func shrink() { +        if sideLength > 0 { +            --sideLength +        } +    } +     +    override func getArea() -> Int { +        return sideLength * sideLength +    } +} + +// Uma classe básica `Square` que estende `Rect`  +class Square: Rect { +    convenience init() { +        self.init(sideLength: 5) +    } +} + +var mySquare = Square() +print(mySquare.getArea()) // 25 +mySquare.shrink() +print(mySquare.sideLength) // 4 + +// Compara instâncias, não é o mesmo que == o qual compara objetos +if mySquare === mySquare { +    println("Yep, it's mySquare") +} + + +// +// MARK: Enums +// + +// Enums podem opcionalmente ser de um tipo específico ou não. +// Podem conter métodos do mesmo jeito que classes. + +enum Suit { +    case Spades, Hearts, Diamonds, Clubs +    func getIcon() -> String { +        switch self { +        case .Spades: return "♤" +        case .Hearts: return "♡" +        case .Diamonds: return "♢" +        case .Clubs: return "♧" +        } +    } +} + + +// +// MARK: Protocolos +// + +// `protocol` pode requerer que os tipos que se adequam tenham +// propriedades de instância, métodos, operadores e subscripts. +protocol ShapeGenerator { +    var enabled: Bool { get set } +    func buildShape() -> Shape +} + +// Protocolos declarados com @objc permitem funções opcionais, +// que permitem verificar a confomidade +@objc protocol TransformShape { +    optional func reshaped() +    optional func canReshape() -> Bool +} + +class MyShape: Rect { +    var delegate: TransformShape? +     +    func grow() { +        sideLength += 2 +         +        if let allow = self.delegate?.canReshape?() { +            // test for delegate then for method +            // testa por delegação e então por método +            self.delegate?.reshaped?() +        } +    } +} + + +// +// MARK: Outros +// + +// `extension`s: Adicionam uma funcionalidade extra para um tipo já existente. + +// Square agora "segue" o protocolo `Printable`  +extension Square: Printable { +    var description: String { +        return "Area: \(self.getArea()) - ID: \(self.identifier)" +    } +} + +println("Square: \(mySquare)") + +// Você pode também estender tipos embutidos (built-in) +extension Int { +    var customProperty: String { +        return "This is \(self)" +    } +     +    func multiplyBy(num: Int) -> Int { +        return num * self +    } +} + +println(7.customProperty) // "This is 7" +println(14.multiplyBy(2)) // 42 + +// Generics: Similar com Java e C#. Use a palavra-chave `where` para +// especificar os requisitos do generics. + +func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? { +    for (index, value) in enumerate(array) { +        if value == valueToFind { +            return index +        } +    } +    return nil +} +let foundAtIndex = findIndex([1, 2, 3, 4], 3) +println(foundAtIndex == 2) // true + +// Operadores: +// Operadores personalizados (custom) podem começar com os seguintes caracteres: +//      / = - + * % < > ! & | ^ . ~ +// ou +// Unicode math, símbolo, seta, e caracteres tipográficos ou de desenho. +prefix operator !!! {} + +// Um operador de prefixo que triplica o comprimento do lado do quadrado +// quando usado +prefix func !!! (inout shape: Square) -> Square { +    shape.sideLength *= 3 +    return shape +} + +// valor atual +println(mySquare.sideLength) // 4 + +// Troca o comprimento do lado usando um operador personalizado !!!, aumenta o lado por 3 +!!!mySquare +println(mySquare.sideLength) // 12 + +``` diff --git a/python.html.markdown b/python.html.markdown index 53381f32..da04d381 100644 --- a/python.html.markdown +++ b/python.html.markdown @@ -264,7 +264,7 @@ 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 => 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 diff --git a/python3.html.markdown b/python3.html.markdown index 0b4feccc..6b1d3156 100644 --- a/python3.html.markdown +++ b/python3.html.markdown @@ -635,7 +635,6 @@ print(say(say_please=True))  # Can you buy me a beer? Please! I am poor :(  * [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)  ### Dead Tree diff --git a/ru-ru/go-ru.html.markdown b/ru-ru/go-ru.html.markdown index 44a22b45..e06ae9bd 100644 --- a/ru-ru/go-ru.html.markdown +++ b/ru-ru/go-ru.html.markdown @@ -65,7 +65,7 @@ func beyondHello() {      learnTypes()                            // < y minutes, learn more!  } -// Функция имеющая входные параметры и возврат нескольких значений. +// Функция, имеющая входные параметры и возвращающая несколько значений.  func learnMultiple(x, y int) (sum, prod int) {      return x + y, x * y // Возврат двух значений.  } diff --git a/ru-ru/lua-ru.html.markdown b/ru-ru/lua-ru.html.markdown new file mode 100644 index 00000000..6f515975 --- /dev/null +++ b/ru-ru/lua-ru.html.markdown @@ -0,0 +1,425 @@ +--- +language: lua +filename: learnlua-ru.lua +contributors: +    - ["Tyler Neylon", "http://tylerneylon.com/"] +translators: +    - ["Max Solomonov", "https://vk.com/solomonovmaksim"] +    - ["Max Truhonin", "https://vk.com/maximmax42"] +    - ["Konstantin Gromyko", "https://vk.com/id0x1765d79"] +    - ["Stanislav Gromov", "https://vk.com/id156354391"] +lang: ru-ru +--- + +```lua +-- Два дефиса начинают однострочный комментарий. + +--[[ +    Добавление двух квадратных скобок +    делает комментарий многострочным. +--]] +-------------------------------------------------------------------------------- +-- 1. Переменные, циклы и условия. +-------------------------------------------------------------------------------- + +num = 42  -- Все числа имеют тип double. +-- Не волнуйтесь, в 64-битных double 52 бита +-- отведено под хранение целой части числа; +-- точность не является проблемой для +-- целочисленных значений, занимающих меньше 52 бит. + +s = 'walternate'  -- Неизменные строки, как в Python. +t = "Двойные кавычки также приветствуются" +u = [[ Двойные квадратные скобки +       начинают и заканчивают +       многострочные значения.]] +t = nil  -- Удаляет определение переменной t; в Lua есть сборка мусора. + +-- Блоки обозначаются ключевыми словами, такими как do/end: +while num < 50 do +  num = num + 1  -- Операторов ++ и += нет. +end + +-- Ветвление "если": +if num > 40 then +  print('больше 40') +elseif s ~= 'walternate' then  -- ~= обозначает "не равно". +  -- Проверка равенства это ==, как в Python; работает для строк. +  io.write('не больше 40\n')  -- По умолчанию вывод в stdout. +else +  -- По умолчанию переменные являются глобальными. +  thisIsGlobal = 5  -- Стиль CamelСase является общим. + +  -- Как сделать переменную локальной: +  local line = io.read()  -- Считывает введённую строку. + +  -- Для конкатенации строк используется оператор .. : +  print('Зима пришла, ' .. line) +end + +-- Неопределённые переменные возвращают nil. +-- Этот пример не является ошибочным: +foo = anUnknownVariable  -- Теперь foo = nil. + +aBoolValue = false + +-- Только значения nil и false являются ложными; 0 и '' являются истинными! +if not aBoolValue then print('это значение ложно') end + +-- Для 'or' и 'and' действует принцип "какой оператор дальше, +-- тот и применяется". Это действует аналогично оператору a?b:c в C/js: +ans = aBoolValue and 'yes' or 'no'  --> 'no' + +karlSum = 0 +for i = 1, 100 do  -- Здесь указан диапазон, ограниченный с двух сторон. +  karlSum = karlSum + i +end + +-- Используйте "100, 1, -1" как нисходящий диапазон: +fredSum = 0 +for j = 100, 1, -1 do fredSum = fredSum + j end + +-- В основном, диапазон устроен так: начало, конец[, шаг]. + +-- Другая конструкция цикла: +repeat +  print('путь будущего') +  num = num - 1 +until num == 0 + +-------------------------------------------------------------------------------- +-- 2. Функции. +-------------------------------------------------------------------------------- + +function fib(n) +  if n < 2 then return n end +  return fib(n - 2) + fib(n - 1) +end + +-- Вложенные и анонимные функции являются нормой: +function adder(x) +  -- Возращаемая функция создаётся, когда вызывается функция adder, +  -- и запоминает значение переменной x: +  return function (y) return x + y end +end +a1 = adder(9) +a2 = adder(36) +print(a1(16))  --> 25 +print(a2(64))  --> 100 + +-- Возвраты, вызовы функций и присвоения работают со списками, +-- которые могут иметь разную длину. +-- Лишние получатели принимают значение nil, а лишние значения игнорируются. + +x, y, z = 1, 2, 3, 4 +-- Теперь x = 1, y = 2, z = 3, а 4 просто отбрасывается. + +function bar(a, b, c) +  print(a, b, c) +  return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod')  --> выводит "zaphod  nil nil" +-- Теперь x = 4, y = 8, а значения 15..42 отбрасываются. + +-- Функции могут быть локальными и глобальными. Эти строки делают одно и то же: +function f(x) return x * x end +f = function (x) return x * x end + +-- Эти тоже: +local function g(x) return math.sin(x) end +local g = function(x) return math.sin(x) end +-- Эквивалентно для local function g(x)..., однако ссылки на g +-- в теле функции не будут работать, как ожидалось. +local g; g  = function (x) return math.sin(x) end +-- 'local g' будет прототипом функции. + +-- Кстати, тригонометрические функции работают с радианами. + +-- Вызов функции с одним строковым параметром не требует круглых скобок: +print 'hello'  -- Работает без ошибок. + +-- Вызов функции с одним табличным параметром также +-- не требует круглых скобок (про таблицы в след. части): +print {} -- Тоже сработает. + +-------------------------------------------------------------------------------- +-- 3. Таблицы. +-------------------------------------------------------------------------------- + +-- Таблица = единственная составная структура данных в Lua; +-- представляет собой ассоциативный массив. +-- Подобно массивам в PHP или объектам в JS, они представляют собой +-- хеш-таблицы, которые также можно использовать в качестве списков. + + +-- Использование словарей: + +-- Литералы имеют ключ по умолчанию: +t = {key1 = 'value1', key2 = false} + +-- Строковые ключи используются, как в точечной нотации в JS: +print(t.key1)  -- Печатает 'value1'. +t.newKey = {}  -- Добавляет новую пару ключ/значение. +t.key2 = nil   -- Удаляет key2 из таблицы. + +-- Литеральная нотация для любого значения ключа (кроме nil): +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28])  -- пишет "tau" + +-- Ключ соответствует значению для чисел и строк, но при +-- использовании таблицы в качестве ключа берётся её экземпляр. +a = u['@!#']  -- Теперь a = 'qbert'. +b = u[{}]     -- Вы могли ожидать 1729, но получится nil: +-- b = nil, т.к. ключ не будет найден. +-- Это произойдёт потому, что за ключ мы использовали не тот же самый объект, +-- который был использован для сохранения оригинального значения. +-- Поэтому строки и числа удобнее использовать в качестве ключей. + +-- Вызов функции с одной таблицей в качестве аргумента +-- не требует круглых скобок: +function h(x) print(x.key1) end +h{key1 = 'Sonmi~451'}  -- Печатает 'Sonmi~451'. + +for key, val in pairs(u) do  -- Цикл по таблице. +  print(key, val) +end + +-- _G - это таблица со всеми глобалями. +print(_G['_G'] == _G)  -- Печатает 'true'. + +-- Использование таблиц, как списков / массивов: + +-- Список значений с неявно заданными целочисленными ключами: +v = {'value1', 'value2', 1.21, 'gigawatts'} +for i = 1, #v do  -- #v - размер списка v. +  print(v[i])  -- Нумерация начинается с 1 !! +end + +-- Список не является отдельным типом. v - всего лишь таблица +-- с последовательными целочисленными ключами, воспринимаемая как список. + +-------------------------------------------------------------------------------- +-- 3.1 Метатаблицы и метаметоды. +-------------------------------------------------------------------------------- + +-- Таблицу можно связать с метатаблицей, задав ей поведение, как при +-- перегрузке операторов. Позже мы увидим, что метатаблицы поддерживают +-- поведение, как в js-прототипах. +f1 = {a = 1, b = 2}  -- Представляет дробь a/b. +f2 = {a = 2, b = 3} + +-- Это не сработает: +-- s = f1 + f2 + +metafraction = {} +function metafraction.__add(f1, f2) +  local 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  -- вызвать __add(f1, f2) на метатаблице от f1 + +-- f1, f2 не имеют ключа для своих метатаблиц в отличии от прототипов в js, +-- нужно получить его через getmetatable(f1). Метатаблица - обычная таблица +-- поэтому с ключами, известными для Lua (например, __add). + +-- Но следущая строка будет ошибочной т.к в s нет метатаблицы: +-- t = s + s +-- Похожий на классы подход, приведенный ниже, поможет это исправить. + +-- __index перегружает в метатаблице просмотр через точку: +defaultFavs = {animal = 'gru', food = 'donuts'} +myFavs = {food = 'pizza'} +setmetatable(myFavs, {__index = defaultFavs}) +eatenBy = myFavs.animal  -- работает! спасибо, мета-таблица. + +-------------------------------------------------------------------------------- +-- При неудаче прямой табличный поиск попытается использовать +-- значение __index в метатаблице, причём это рекурсивно. + +-- Значение __index также может быть функцией +-- function(tbl, key) для настраиваемого поиска. + +-- Значения типа __index, __add, ... называются метаметодами. +-- Ниже приведён полный список метаметодов. + +-- __add(a, b)                          для a + b +-- __sub(a, b)                          для a - b +-- __mul(a, b)                          для a * b +-- __div(a, b)                          для a / b +-- __mod(a, b)                          для a % b +-- __pow(a, b)                          для a ^ b +-- __unm(a)                             для -a +-- __concat(a, b)                       для a .. b +-- __len(a)                             для #a +-- __eq(a, b)                           для a == b +-- __lt(a, b)                           для a < b +-- __le(a, b)                           для a <= b +-- __index(a, b) <функция или таблица>  для a.b +-- __newindex(a, b, c)                  для a.b = c +-- __call(a, ...)                       для a(...) + +-------------------------------------------------------------------------------- +-- 3.2 Классоподобные таблицы и наследование. +-------------------------------------------------------------------------------- + +-- В Lua нет поддержки классов на уровне языка, +-- однако существуют разные способы их создания с помощью +-- таблиц и метатаблиц. + +-- Ниже приведён один из таких способов. + +Dog = {}                                   -- 1. + +function Dog:new()                         -- 2. +  local 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 похоже на класс, но на самом деле это таблица. +-- 2. "function tablename:fn(...)" - то же самое, что и +--    "function tablename.fn(self, ...)", просто : добавляет первый аргумент +--    перед собой. См. пункты 7 и 8, чтобы понять, как self получает значение. +-- 3. newObj - это экземпляр класса Dog. +-- 4. "self" - экземпляр класса. Зачастую self = Dog, но с помощью наследования +--    это можно изменить. newObj получит свои функции, когда мы установим +--    метатаблицу для newObj и __index для self на саму себя. +-- 5. Напоминание: setmetatable возвращает первый аргумент. +-- 6. : работает, как в пункте 2, но в этот раз мы ожидаем, +--    что self будет экземпляром, а не классом. +-- 7. То же самое, что и Dog.new(Dog), поэтому self = Dog в new(). +-- 8. То же самое, что mrDog.makeSound(mrDog); self = mrDog. +-------------------------------------------------------------------------------- + +-- Пример наследования: + +LoudDog = Dog:new()                           -- 1. + +function LoudDog:makeSound() +  local s = self.sound .. ' '                 -- 2. +  print(s .. s .. s) +end + +seymour = LoudDog:new()                       -- 3. +seymour:makeSound()  -- 'woof woof woof'      -- 4. + +-------------------------------------------------------------------------------- +-- 1. LoudDog получит методы и переменные класса Dog. +-- 2. В self будет ключ 'sound' из new(), см. пункт 3. +-- 3. То же самое, что и "LoudDog.new(LoudDog)", конвертированное +--    в "Dog.new(LoudDog)", поскольку в LoudDog нет ключа 'new', +--    но в его метатаблице есть "__index = Dog". +--    Результат: Метатаблицей для seymour стала LoudDog, +--    а "LoudDog.__index = Dog". Поэтому seymour.key будет равно +--    seymour.key, LoudDog.key, Dog.key, в зависимости от того, +--    какая таблица будет первой с заданным ключом. +-- 4. Ключ 'makeSound' находится в LoudDog; +--    то же самое, что и "LoudDog.makeSound(seymour)". + +-- При необходимости функция new() в подклассе +-- может быть похожа на аналог в базовом классе. +function LoudDog:new() +  local newObj = {} +  -- установить newObj +  self.__index = self +  return setmetatable(newObj, self) +end + +-------------------------------------------------------------------------------- +-- 4. Модули. +-------------------------------------------------------------------------------- + + +--[[ Я закомментировал этот раздел, чтобы остальная часть скрипта осталась +--   работоспособной. +``` + +```lua +-- Предположим, файл mod.lua будет выглядеть так: +local M = {} + +local function sayMyName() +  print('Hrunkner') +end + +function M.sayHello() +  print('Привет, ') +  sayMyName() +end + +return M + +-- Другой файл может использовать функционал mod.lua: +local mod = require('mod')  -- Запустим файл mod.lua. + +-- require - стандартный способ подключения модулей. +-- require ведёт себя так:     (если не кэшировано, см. ниже) +local mod = (function () +  <содержимое mod.lua> +end)() +-- Файл mod.lua воспринимается, как тело функции, поэтому +-- все локальные переменные и функции внутри него не видны за его пределами. + +-- Это работает, так как здесь mod = M в mod.lua: +mod.sayHello()  -- Выведет "Привет, Hrunkner". + +-- Это будет ошибочным; sayMyName доступна только в mod.lua: +mod.sayMyName()  -- ошибка + +-- Значения, возвращаемые require, кэшируются, +-- поэтому содержимое файла выполняется только 1 раз, +-- даже если он подключается с помощью require много раз. + +-- Предположим, mod2.lua содержит "print('Hi!')". +local a = require('mod2')  -- Выведет "Hi!" +local b = require('mod2')  -- Ничего не выведет; a=b. + +-- dofile, в отличии от require, работает без кэширования: +dofile('mod2')  --> Hi! +dofile('mod2')  --> Hi! (запустится снова) + +-- loadfile загружает файл, но не запускает его. +f = loadfile('mod2')  -- Вызов f() запустит содержимое mod2.lua. + +-- loadstring - это loadfile для строк. +g = loadstring('print(343)')  -- Вернет функцию. +g()  -- Напишет 343. + +--]] + +``` +## Примечание (от автора) + +Мне было интересно изучить Lua, чтобы делать игры при помощи <a href="http://love2d.org/">игрового движка LÖVE</a>. + +Я начинал с <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV's Lua for programmers</a>. +Затем я прочитал официальную <a href="http://www.lua.org/pil/contents.html">Документацию по Lua</a>. + +Также может быть полезной <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Краткая справка по Lua</a> на lua-users.org. + +Ещё из основных тем не охвачены стандартные библиотеки: + +* <a href="http://lua-users.org/wiki/StringLibraryTutorial">библиотека string</a> +* <a href="http://lua-users.org/wiki/TableLibraryTutorial">библиотека table</a> +* <a href="http://lua-users.org/wiki/MathLibraryTutorial">библиотека math</a> +* <a href="http://lua-users.org/wiki/IoLibraryTutorial">библиотека io</a> +* <a href="http://lua-users.org/wiki/OsLibraryTutorial">библиотека os</a> + +Кстати, весь файл написан на Lua; сохраните его как learn.lua и запустите при помощи "lua learn.lua" ! + +Изначально эта статья была написана для tylerneylon.com. +Также она доступна как <a href="https://gist.github.com/tylerneylon/5853042">github gist</a>. Удачи с Lua! diff --git a/scala.html.markdown b/scala.html.markdown index 5a478f2a..61c735e3 100644 --- a/scala.html.markdown +++ b/scala.html.markdown @@ -198,8 +198,10 @@ weirdSum(2, 4)  // => 16  // The return keyword exists in Scala, but it only returns from the inner-most -// def that surrounds it. It has no effect on anonymous functions. For example: -def foo(x: Int) = { +// 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: +def foo(x: Int): Int = {    val anonFunc: Int => Int = { z =>      if (z > 5)        return z  // This line makes z the return value of foo! @@ -405,41 +407,55 @@ val otherGeorge = george.copy(phoneNumber = "9876")  // 6. Pattern Matching  ///////////////////////////////////////////////// -val me = Person("George", "1234") +// Pattern matching is a powerful and commonly used feature in Scala. Here's how +// you pattern match a case class. NB: Unlike other languages, Scala cases do +// not need breaks, fall-through does not happen. -me match { case Person(name, number) => { -            "We matched someone : " + name + ", phone : " + number }} - -me match { case Person(name, number) => "Match : " + name; case _ => "Hm..." } +def matchPerson(person: Person): String = person match { +  // Then you specify the patterns: +  case Person("George", number) => "We found George! His number is " + number +  case Person("Kate", number) => "We found Kate! Her number is " + number +  case Person(name, number) => "We matched someone : " + name + ", phone : " + number +} -me match { case Person("George", number) => "Match"; case _ => "Hm..." } +val email = "(.*)@(.*)".r  // Define a regex for the next example. -me match { case Person("Kate", number) => "Match"; case _ => "Hm..." } +// Pattern matching might look familiar to the switch statements in the C family +// of languages, but this is much more powerful. In Scala, you can match much +// more: +def matchEverything(obj: Any): String = obj match { +  // You can match values: +  case "Hello world" => "Got the string Hello world" -me match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } +  // You can match by type: +  case x: Double => "Got a Double: " + x -val kate = Person("Kate", "1234") +  // You can specify conditions: +  case x: Int if x > 10000 => "Got a pretty big number!" -kate match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } +  // You can match case classes as before: +  case Person(name, number) => s"Got contact info for $name!" +  // You can match regular expressions: +  case email(name, domain) => s"Got email address $name@$domain" +  // You can match tuples: +  case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c" -// Regular expressions -val email = "(.*)@(.*)".r  // Invoking r on String makes it a Regex -val serialKey = """(\d{5})-(\d{5})-(\d{5})-(\d{5})""".r // Using verbatim (multiline) syntax +  // You can match data structures: +  case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c" -val matcher = (value: String) => { -  println(value match { -	case email(name, domain) => s"It was an email: $name" -	case serialKey(p1, p2, p3, p4) => s"Serial key: $p1, $p2, $p3, $p4" -	case _ => s"No match on '$value'" // default if no match found -  }) +  // You can nest patterns: +  case List(List((1, 2,"YAY"))) => "Got a list of list of tuple"  } -matcher("mrbean@pyahoo.com") // => "It was an email: mrbean" -matcher("nope..") // => "No match on 'nope..'" -matcher("52917") // => "No match on '52917'" -matcher("52752-16432-22178-47917") // => "Serial key: 52752, 16432, 22178, 47917" +// In fact, you can pattern match any object with an "unapply" method. This +// feature is so powerful that Scala lets you define whole functions as +// patterns: +val patternFunc: Person => String = { +  case Person("George", number") => s"George's number: $number" +  case Person(name, number) => s"Random person's number: $number" +}  ///////////////////////////////////////////////// @@ -476,7 +492,7 @@ sSquared.reduce (_+_)  // The filter function takes a predicate (a function from A -> Boolean) and  // selects all elements which satisfy the predicate  List(1, 2, 3) filter (_ > 2) // List(3) -case class Person(name:String, phoneNumber:String) +case class Person(name:String, age:Int)  List(    Person(name = "Dom", age = 23),    Person(name = "Bob", age = 30) diff --git a/swift.html.markdown b/swift.html.markdown index 005e511c..0d1d2df4 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -6,7 +6,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 beta. +Swift is a programming language for iOS and OS X development created by Apple. Designed to coexist with Objective-C and to be more resilient against erroneous code, Swift was introduced in 2014 at Apple's developer conference WWDC. It is built with the LLVM compiler included in Xcode 6+.  The official [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) book from Apple is now available via iBooks. @@ -23,7 +23,7 @@ import UIKit  // Xcode supports landmarks to annotate your code and lists them in the jump bar  // MARK: Section mark  // TODO: Do something soon -// FIXME Fix this code +// FIXME: Fix this code  println("Hello, world") @@ -55,8 +55,8 @@ println("Build value: \(buildValue)") // Build value: 7  /*      Optionals are a Swift language feature that allows you to store a `Some` or      `None` value. -     -    Because Swift requires every property to have a value, even nil must be  + +    Because Swift requires every property to have a value, even nil must be      explicitly stored as an Optional value.      Optional<T> is an enum. @@ -94,7 +94,8 @@ var anyObjectVar: AnyObject = 7  anyObjectVar = "Changed value to a string, not good practice, but possible."  /* -Comment here +    Comment here +          /*          Nested comments are also supported      */ @@ -112,8 +113,9 @@ Comment here  // Array  var shoppingList = ["catfish", "water", "lemons"]  shoppingList[1] = "bottle of water" -let emptyArray = [String]() // immutable -var emptyMutableArray = [String]() // mutable +let emptyArray = [String]() // let == immutable +let emptyArray2 = Array<String>() // same as above +var emptyMutableArray = [String]() // var == mutable  // Dictionary @@ -122,8 +124,9 @@ var occupations = [      "kaylee": "Mechanic"  ]  occupations["Jayne"] = "Public Relations" -let emptyDictionary = [String: Float]() // immutable -var emptyMutableDictionary = [String: Float]() // mutable +let emptyDictionary = [String: Float]() // let == immutable +let emptyDictionary2 = Dictionary<String, Float>() // same as above +var emptyMutableDictionary = [String: Float]() // var == mutable  // @@ -165,14 +168,16 @@ do {  } while 1 == 2  // Switch +// Very powerful, think `if` statements with syntax candy +// They support String, object instances, and primitives (Int, Double, etc)  let vegetable = "red pepper"  switch vegetable {  case "celery":      let vegetableComment = "Add some raisins and make ants on a log."  case "cucumber", "watercress":      let vegetableComment = "That would make a good tea sandwich." -case let x where x.hasSuffix("pepper"): -    let vegetableComment = "Is it a spicy \(x)?" +case let localScopeValue where localScopeValue.hasSuffix("pepper"): +    let vegetableComment = "Is it a spicy \(localScopeValue)?"  default: // required (in order to cover all possible input)      let vegetableComment = "Everything tastes good in soup."  } @@ -186,21 +191,28 @@ default: // required (in order to cover all possible input)  // in functions and can be passed around  // Function with Swift header docs (format as reStructedText) +  /** -A greet operation +    A greet operation -- A bullet in docs -- Another bullet in the docs +    - A bullet in docs +    - Another bullet in the docs -:param: name A name -:param: day A day -:returns: A string containing the name and day value. +    :param: name A name +    :param: day A day +    :returns: A string containing the name and day value.  */  func greet(name: String, day: String) -> String {      return "Hello \(name), today is \(day)."  }  greet("Bob", "Tuesday") +// similar to above except for the function parameter behaviors +func greet2(#requiredName: String, externalParamName localParamName: String) -> String { +    return "Hello \(requiredName), the day is \(localParamName)" +} +greet2(requiredName:"John", externalParamName: "Sunday") +  // Function that returns multiple items in a tuple  func getGasPrices() -> (Double, Double, Double) {      return (3.59, 3.69, 3.79) @@ -281,7 +293,7 @@ print(numbers) // [3, 6, 18]  // Structures and classes have very similar capabilites  struct NamesTable { -    let names: [String] +    let names = [String]()      // Custom subscript      subscript(index: Int) -> String { @@ -291,8 +303,8 @@ struct NamesTable {  // Structures have an auto-generated (implicit) designated initializer  let namesTable = NamesTable(names: ["Me", "Them"]) -//let name = namesTable[2] -//println("Name is \(name)") // Name is Them +let name = namesTable[1] +println("Name is \(name)") // Name is Them  //  // MARK: Classes @@ -341,7 +353,7 @@ internal class Rect: Shape {      init(sideLength: Int) {          self.sideLength = sideLength -         // always super.init last when init custom properties +        // always super.init last when init custom properties          super.init()      } @@ -368,6 +380,9 @@ print(mySquare.getArea()) // 25  mySquare.shrink()  print(mySquare.sideLength) // 4 +// cast instance +let aShape = mySquare as Shape +  // compare instances, not the same as == which compares objects (equal to)  if mySquare === mySquare {      println("Yep, it's mySquare") @@ -393,6 +408,17 @@ enum Suit {      }  } +// Enum values allow short hand syntax, no need to type the enum type +// when the variable is explicitly declared +var suitValue: Suit = .Hearts + +// Non-Integer enums require direct raw value assignments +enum BookName: String { +    case John = "John" +    case Luke = "Luke" +} +println("Name: \(BookName.John.rawValue)") +  //  // MARK: Protocols @@ -490,5 +516,4 @@ println(mySquare.sideLength) // 4  // change side length using custom !!! operator, increases size by 3  !!!mySquare  println(mySquare.sideLength) // 12 -  ``` diff --git a/tcl.html.markdown b/tcl.html.markdown new file mode 100755 index 00000000..f2d92fcd --- /dev/null +++ b/tcl.html.markdown @@ -0,0 +1,447 @@ +--- +language: Tcl +contributors: +    - ["Poor Yorick", "http://pooryorick.com/"] +filename: learntcl.tcl +--- + +Tcl was created by [John Ousterhout](http://wiki.tcl.tk/John Ousterout) as a +reusable scripting language for chip design tools he was creating.  In 1997 he +was awarded the [ACM Software System +Award](http://en.wikipedia.org/wiki/ACM_Software_System_Award) for Tcl.  Tcl +can be used both as an embeddable scripting language and as a general +programming language.  It can also be used as a portable C library, even in +cases where no scripting capability is needed, as it provides data structures +such as dynamic strings, lists, and hash tables.  The C library also provides +portable functionality for loading dynamic libraries, string formatting and +code conversion, filesystem operations, network operations, and more.   +Various features of Tcl stand out: + +* Convenient cross-platform networking API + +* Fully virtualized filesystem + +* Stackable I/O channels + +* Asynchronous to the core + +* Full coroutines + +* A threading model recognized as robust and easy to use + + +If Lisp is a list processor, then Tcl is a string processor.  All values are +strings.  A list is a string format.  A procedure definition is a string +format.  To achieve performance, Tcl internally caches structured +representations of these values.  The list commands, for example, operate on +the internal cached representation, and Tcl takes care of updating the string +representation if it is ever actually needed in the script.  The copy-on-write +design of Tcl allows script authors can pass around large data values without +actually incurring additional memory overhead.  Procedures are automatically +byte-compiled unless they use the more dynamic commands such as "uplevel", +"upvar", and "trace". + +Tcl is a pleasure to program in.  It will appeal to hacker types who find Lisp, +Forth, or Smalltalk interesting, as well as to engineers and scientists who +just want to get down to business with a tool that bends to their will.  Its +discipline of exposing all programmatic functionality as commands, including +things like loops and mathematical operations that are usually baked into the +syntax of other languages, allows it to fade into the background of whatever +domain-specific functionality a project needs. It's syntax, which is even +lighter that that of Lisp, just gets out of the way. + + + + + +```tcl +#! /bin/env tclsh + +################################################################################ +## 1. Guidelines  +################################################################################ + +# Tcl is not Bash or C!  This needs to be said because standard shell quoting +# habits almost work in Tcl and it is common for people to pick up Tcl and try +# to get by with syntax they know from another language.  It works at first, +# but soon leads to frustration with more complex scripts. +  +# Braces are just a quoting mechanism, not a code block constructor or a list +# constructor.  Tcl doesn't have either of those things.  Braces are used, +# though, to escape special characters in procedure bodies and in strings that +# are formatted as lists. + + +################################################################################ +## 2. Syntax  +################################################################################ + +# Every line is a command.  The first word is the name of the command, and +# subsequent words are arguments to the command. Words are delimited by +# whitespace.  Since every word is a string, in the simple case no special +# markup such as quotes, braces, or backslash, is necessary.  Even when quotes +# are used, they are not a string constructor, but just another escaping +# character. + +set greeting1 Sal  +set greeting2 ut +set greeting3 ations + + +#semicolon also delimits commands +set greeting1 Sal; set greeting2 ut; set greeting3 ations  + + +# Dollar sign introduces variable substitution +set greeting $greeting1$greeting2$greeting3 + + +# Bracket introduces command substitution.  The result of the command is +# substituted in place of the bracketed script.  When the "set" command is +# given only the name of a variable, it returns the value of that variable. +set greeting $greeting1$greeting2[set greeting3] + + +# Command substitution should really be called script substitution, because an +# entire script, not just a command, can be placed between the brackets. The +# "incr" command increments the value of a variable and returns its value. +set greeting $greeting[ +	incr i +	incr i +	incr i +] + + +# backslash suppresses the special meaning of characters +set amount \$16.42 + + +# backslash adds special meaning to certain characters +puts lots\nof\n\n\n\n\n\nnewlines + + +# A word enclosed in braces is not subject to any special interpretation or +# substitutions, except that a backslash before a brace is not counted when look#ing for the closing brace +set somevar { +    This is a literal $ sign, and this \} escaped +    brace remains uninterpreted +}  + + +# In a word enclosed in double quotes, whitespace characters lose their special +# meaning  +set name Neo +set greeting "Hello, $name" + + +#variable names can be any string +set {first name} New + + +# The brace form of variable substitution handles more complex variable names +set greeting "Hello, ${first name}" + + +# The "set" command can always be used instead of variable substitution +set greeting "Hello, [set {first name}]" + + +# To promote the words within a word to individual words of the current +# command, use the expansion operator, "{*}". +set {*}{name Neo} + +# is equivalent to +set name Neo + + +# An array is a special variable that is a container for other variables. +set person(name) Neo +set person(gender) male +set greeting "Hello, $person(name)" + + +# A namespace holds commands and variables +namespace eval people { +    namespace eval person1 { +        set name Neo +    } +} + + +#The full name of a variable includes its enclosing namespace(s), delimited by two colons: +set greeting "Hello $people::person::name" + + + +################################################################################ +## 3. A Few Notes  +################################################################################ + +# All other functionality is implemented via commands.  From this point on, +# there is no new syntax.  Everything else there is to learn about Tcl is about +# the behaviour of individual commands, and what meaning they assign to their +# arguments. + + +# To end up with an interpreter that can do nothing, delete the global +# namespace.  It's not very useful to do such a thing, but it illustrates the +# nature of Tcl. +namespace delete :: + + +# Because of name resolution behaviour, its safer to use the "variable" command to declare or to assign a value to a namespace. +namespace eval people { +    namespace eval person1 { +        variable name Neo +    } +} + + +# The full name of a variable can always be used, if desired. +set people::person1::name Neo + + + +################################################################################ +## 4. Commands  +################################################################################ + +# Math can be done with the "expr" command. +set a 3 +set b 4 +set c [expr {$a + $b}] + +# Since "expr" performs variable substitution on its own, brace the expression +# to prevent Tcl from performing variable substitution first.  See +# "http://wiki.tcl.tk/Brace%20your%20#%20expr-essions" for details. + + +# The "expr" command understands variable and command substitution +set c [expr {$a + [set b]}] + + +# The "expr" command provides a set of mathematical functions +set c [expr {pow($a,$b)}] + + +# Mathematical operators are available as commands in the ::tcl::mathop +# namespace +::tcl::mathop::+ 5 3 + +# Commands can be imported from other namespaces +namespace import ::tcl::mathop::+ +set result [+ 5 3] + + +# New commands can be created via the "proc" command. +proc greet name { +    return "Hello, $name!" +} + +#multiple parameters can be specified +proc greet {greeting name} { +    return "$greeting, $name!" +} + + +# As noted earlier, braces do not construct a code block.  Every value, even +# the third argument of the "proc" command, is a string.  The previous command +# rewritten to not use braces at all: +proc greet greeting\ name return\ \"Hello,\ \$name! + + + +# When the last parameter is the literal value, "args", it collects all extra +# arguments when the command is invoked +proc fold {cmd args} { +    set res 0 +    foreach arg $args { +        set res [cmd $res $arg] +    } +} +fold ::tcl::mathop::* 5 3 3 ;# ->  45 + + +# Conditional execution is implemented as a command +if {3 > 4} { +    puts {This will never happen} +} elseif {4 > 4} { +    puts {This will also never happen} +} else { +    puts {This will always happen} +} + + +# Loops are implemented as commands.  The first, second, and third +# arguments of the "for" command are treated as mathematical expressions +for {set i 0} {$i < 10} {incr i} { +    set res [expr {$res + $i}] +} + + +# The first argument of the "while" command is also treated as a mathematical +# expression +set i 0 +while {$i < 10} { +    incr i 2 +} + + +# A list is a specially-formatted string.  In the simple case, whitespace is sufficient to delimit values +set amounts 10\ 33\ 18  +set amount [lindex $amounts 1] + + +# Braces and backslash can be used to format more complex values in a list.  A +# list looks exactly like a script, except that the newline character and the +# semicolon character lose their special meanings.  This feature makes Tcl +# homoiconic.  There are three items in the following list. +set values { + +    one\ two + +    {three four} + +    five\{six + +} + + +# Since a list is a string, string operations could be performed on it, at the +# risk of corrupting the formatting of the list. +set values {one two three four} +set values [string map {two \{} $values] ;# $values is no-longer a \ +    properly-formatted listwell-formed list + + +# The sure-fire way to get a properly-formmated list is to use "list" commands +set values [list one \{ three four] +lappend values { } ;# add a single space as an item in the list + + +# Use "eval" to evaluate a value as a script +eval { +    set name Neo +    set greeting "Hello, $name" +} + + +# A list can always be passed to "eval" as a script composed of a single +# command. +eval {set name Neo} +eval [list set greeting "Hello, $name"] + + +# Therefore, when using "eval", use [list] to build up a desired command  +set command {set name} +lappend command {Archibald Sorbisol} +eval $command + + +# A common mistake is not to use list functions when building up a command +set command {set name} +append command { Archibald Sorbisol} +eval $command ;# There is an error here, because there are too many arguments \ +    to "set" in {set name Archibald Sorbisol} + + +# This mistake can easily occur with the "subst" command. +set replacement {Archibald Sorbisol} +set command {set name $replacement} +set command [subst $command]  +eval $command ;# The same error as before:  to many arguments to "set" in \ +    {set name Archibald Sorbisol} + + +# The proper way is to format the substituted value using use the "list" +# command. +set replacement [list {Archibald Sorbisol}] +set command {set name $replacement} +set command [subst $command]  +eval $command + + +# It is extremely common to see the "list" command being used to properly +# format values that are substituted into Tcl script templates.  There are  +# several examples of this, below. + + +# The "apply" command evaluates a string as a command. +set cmd {{greeting name} { +    return "$greeting, $name!" +}} +apply $cmd Whaddup Neo + + +# The "uplevel" command evaluates a script in some enclosing scope. +proc greet {} { +	uplevel {puts "$greeting, $name"} +} + +proc set_double {varname value} { +	if {[string is double $value]} { +		uplevel [list variable $varname $value] +	} else { +		error [list {not a double} $value] +	} +} + + +# The "upvar" command links a variable in the current scope to a variable in +# some enclosing scope +proc set_double {varname value} { +	if {[string is double $value]} { +		upvar 1 $varname var +		set var $value +	} else { +		error [list {not a double} $value] +	} +} + + +#get rid of the built-in "while" command. +rename ::while {} + + +# Define a new while command with the "proc" command.  More sophisticated error +# handling is left as an exercise. +proc while {condition script} { +    if {[uplevel 1 [list expr $condition]]} { +        uplevel 1 $script +        tailcall [namespace which while] $condition $script +    } +} + + +# The "coroutine" command creates a separate call stack, along with a command +# to enter that call stack. The "yield" command suspends execution in that +# stack.  +proc countdown {} { +	#send something back to the initial "coroutine" command +	yield + +	set count 3  +	while {$count > 1} { +		yield [incr count -1] +	} +	return 0 +} +coroutine countdown1 countdown +coroutine countdown2 countdown +puts [countdown 1] ;# -> 2  +puts [countdown 2] ;# -> 2  +puts [countdown 1] ;# -> 1  +puts [countdown 1] ;# -> 0  +puts [coundown 1] ;# -> invalid command name "countdown1" +puts [countdown 2] ;# -> 1  + + +``` + +## Reference + +[Official Tcl Documentation](http://www.tcl.tk/man/tcl/) + +[Tcl Wiki](http://wiki.tcl.tk) + +[Tcl Subreddit](http://www.reddit.com/r/Tcl) diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown index 53a603a2..098d0ab5 100644 --- a/zh-cn/lua-cn.html.markdown +++ b/zh-cn/lua-cn.html.markdown @@ -63,8 +63,8 @@ foo = anUnknownVariable  -- 现在 foo = nil.  aBoolValue = false  ---只有nil和false为假; 0和 ''都均为真!  -if not aBoolValue then print('twas false') end  +--只有nil和false为假; 0和 ''均为真!  +if not aBoolValue then print('false') end   -- 'or'和 'and'短路   -- 类似于C/js里的 a?b:c 操作符:  @@ -149,7 +149,7 @@ print {} -- 一样可以工作。  -- Table = Lua唯一的组合数据结构;   --         它们是关联数组。   -- 类似于PHP的数组或者js的对象,  --- 它们是哈希表或者字典,也可以当初列表使用。  +-- 它们是哈希表或者字典,也可以当列表使用。   -- 按字典/map的方式使用Table:  | 
