diff options
| -rw-r--r-- | c.html.markdown | 5 | ||||
| -rw-r--r-- | forth.html.markdown | 2 | ||||
| -rw-r--r-- | fr-fr/ruby-fr.html.markdown | 2 | ||||
| -rw-r--r-- | haxe.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/hy-pt.html.markdown | 176 | ||||
| -rw-r--r-- | pt-br/xml-pt.html.markdown | 133 | ||||
| -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/javascript-ru.html.markdown | 543 | ||||
| -rw-r--r-- | scala.html.markdown | 66 | ||||
| -rwxr-xr-x | tcl.html.markdown | 447 | 
16 files changed, 1544 insertions, 220 deletions
diff --git a/c.html.markdown b/c.html.markdown index b5b804af..7670824a 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -386,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 @@ -477,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/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/ruby-fr.html.markdown b/fr-fr/ruby-fr.html.markdown index 75c8d0d3..1564d2b6 100644 --- a/fr-fr/ruby-fr.html.markdown +++ b/fr-fr/ruby-fr.html.markdown @@ -268,7 +268,7 @@ end  # implicitement la valeur de la dernière instruction évaluée  double(2) #=> 4 -# Les paranthèses sont facultative +# Les parenthèses sont facultatives  # lorsqu'il n'y a pas d'ambiguïté sur le résultat  double 3 #=> 6 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/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/hy-pt.html.markdown b/pt-br/hy-pt.html.markdown new file mode 100644 index 00000000..4230579d --- /dev/null +++ b/pt-br/hy-pt.html.markdown @@ -0,0 +1,176 @@ +--- +language: hy +filename: learnhy.hy +contributors: +    - ["Abhishek L", "http://twitter.com/abhishekl"] +translators: +    - ["Miguel Araújo", "https://github.com/miguelarauj1o"] +lang: pt-br +--- + +Hy é um dialeto de Lisp escrito sobre Python. Isto é possível convertendo +código Hy em árvore sintática abstrata python (ast). Portanto, isto permite +hy chamar código python nativo e vice-versa. + +Este tutorial funciona para hy ≥ 0.9.12 + +```clojure +;; Isso dá uma introdução básica em hy, como uma preliminar para o link abaixo +;; http://try-hy.appspot.com +;; +; Comentários em ponto-e-vírgula, como em outros LISPS + +;; s-noções básicas de expressão +; programas Lisp são feitos de expressões simbólicas ou sexps que se assemelham +(some-function args) +; agora o essencial "Olá mundo" +(print "hello world") + +;; Tipos de dados simples +; Todos os tipos de dados simples são exatamente semelhantes aos seus homólogos  +; em python que +42 ; => 42 +3.14 ; => 3.14 +True ; => True +4+10j ; => (4+10j) um número complexo + +; Vamos começar com um pouco de aritmética muito simples +(+ 4 1) ;=> 5 +; o operador é aplicado a todos os argumentos, como outros lisps +(+ 4 1 2 3) ;=> 10 +(- 2 1) ;=> 1 +(* 4 2) ;=> 8 +(/ 4 1) ;=> 4 +(% 4 2) ;=> 0 o operador módulo +; exponenciação é representado pelo operador ** como python +(** 3 2) ;=> 9 +; formas aninhadas vão fazer a coisa esperada +(+ 2 (* 4 2)) ;=> 10 +; também operadores lógicos e ou não e igual etc. faz como esperado +(= 5 4) ;=> False +(not (= 5 4)) ;=> True + +;; variáveis +; variáveis são definidas usando SETV, nomes de variáveis podem usar utf-8, exceto +; for ()[]{}",'`;#| +(setv a 42) +(setv π 3.14159) +(def *foo* 42) +;; outros tipos de dados de armazenamento +; strings, lists, tuples & dicts +; estes são exatamente os mesmos tipos de armazenamento de python +"hello world" ;=> "hello world" +; operações de string funcionam semelhante em python +(+ "hello " "world") ;=> "hello world" +; Listas são criadas usando [], a indexação começa em 0 +(setv mylist [1 2 3 4]) +; tuplas são estruturas de dados imutáveis +(setv mytuple (, 1 2)) +; dicionários são pares de valores-chave +(setv dict1 {"key1" 42 "key2" 21}) +; :nome pode ser utilizado para definir palavras-chave em hy que podem ser utilizados para as chaves +(setv dict2 {:key1 41 :key2 20}) +; usar 'get' para obter o elemento em um índice/key +(get mylist 1) ;=> 2 +(get dict1 "key1") ;=> 42 +; Alternativamente, se foram utilizadas palavras-chave que podem ser chamadas diretamente +(:key1 dict2) ;=> 41 + +;; funções e outras estruturas de programa +; funções são definidas usando defn, o último sexp é devolvido por padrão +(defn greet [name] +  "A simple greeting" ; uma docstring opcional +  (print "hello " name)) + +(greet "bilbo") ;=> "hello bilbo" + +; funções podem ter argumentos opcionais, bem como argumentos-chave +(defn foolists [arg1 &optional [arg2 2]] +  [arg1 arg2]) + +(foolists 3) ;=> [3 2] +(foolists 10 3) ;=> [10 3] + +; funções anônimas são criados usando construtores 'fn' ou 'lambda' +; que são semelhantes para 'defn' +(map (fn [x] (* x x)) [1 2 3 4]) ;=> [1 4 9 16] + +;; operações de sequência +; hy tem algumas utils embutidas para operações de sequência, etc. +; recuperar o primeiro elemento usando 'first' ou 'car' +(setv mylist [1 2 3 4]) +(setv mydict {"a" 1 "b" 2}) +(first mylist) ;=> 1 + +; corte listas usando 'slice' +(slice mylist 1 3) ;=> [2 3] + +; obter elementos de uma lista ou dict usando 'get' +(get mylist 1) ;=> 2 +(get mydict "b") ;=> 2 +; lista de indexação começa a partir de 0, igual em python +; assoc pode definir elementos em chaves/índices +(assoc mylist 2 10) ; faz mylist [1 2 10 4] +(assoc mydict "c" 3) ; faz mydict {"a" 1 "b" 2 "c" 3} +; há toda uma série de outras funções essenciais que torna o trabalho com  +; sequências uma diversão + +;; Python interop +;; importação funciona exatamente como em python +(import datetime) +(import [functools [partial reduce]]) ; importa fun1 e fun2 do module1 +(import [matplotlib.pyplot :as plt]) ; fazendo uma importação em foo como em bar +; todos os métodos de python embutidas etc. são acessíveis a partir hy +; a.foo(arg) is called as (.foo a arg) +(.split (.strip "hello world  ")) ;=> ["hello" "world"] + +;; Condicionais +; (if condition (body-if-true) (body-if-false) +(if (= passcode "moria") +  (print "welcome") +  (print "Speak friend, and Enter!")) + +; aninhe múltiplas cláusulas 'if else if' com cond +(cond + [(= someval 42) +  (print "Life, universe and everything else!")] + [(> someval 42) +  (print "val too large")] + [(< someval 42) +  (print "val too small")]) + +; declarações de grupo com 'do', essas são executadas sequencialmente +; formas como defn tem um 'do' implícito +(do + (setv someval 10) + (print "someval is set to " someval)) ;=> 10 + +; criar ligações lexicais com 'let', todas as variáveis definidas desta forma +; tem escopo local +(let [[nemesis {"superman" "lex luther" +                "sherlock" "moriarty" +                "seinfeld" "newman"}]] +  (for [(, h v) (.items nemesis)] +	(print (.format "{0}'s nemesis was {1}" h v)))) + +;; classes +; classes são definidas da seguinte maneira +(defclass Wizard [object] +  [[--init-- (fn [self spell] +             (setv self.spell spell) ; init a mágica attr +             None)] +   [get-spell (fn [self] +              self.spell)]]) + +;; acesse hylang.org +``` + +### Outras Leituras + +Este tutorial é apenas uma introdução básica para hy/lisp/python. + +Docs Hy: [http://hy.readthedocs.org](http://hy.readthedocs.org) + +Repo Hy no Github: [http://github.com/hylang/hy](http://github.com/hylang/hy) + +Acesso ao freenode irc com #hy, hashtag no twitter: #hylang diff --git a/pt-br/xml-pt.html.markdown b/pt-br/xml-pt.html.markdown new file mode 100644 index 00000000..40ddbc3a --- /dev/null +++ b/pt-br/xml-pt.html.markdown @@ -0,0 +1,133 @@ +--- +language: xml +filename: learnxml.xml +contributors: +	- ["João Farias", "https://github.com/JoaoGFarias"] +translators: +    - ["Miguel Araújo", "https://github.com/miguelarauj1o"] +lang: pt-br +--- + +XML é uma linguagem de marcação projetada para armazenar e transportar dados. + +Ao contrário de HTML, XML não especifica como exibir ou formatar os dados,  +basta carregá-lo. + +* Sintaxe XML + +```xml +<!-- Comentários em XML são feitos desta forma --> + +<?xml version="1.0" encoding="UTF-8"?> +<livraria> +	<livro category="COZINHA"> +		<titulo lang="en">Everyday Italian</titulo> +		<autor>Giada De Laurentiis</autor> +		<year>2005</year> +		<preco>30.00</preco> +	</livro> +	<livro category="CRIANÇAS"> +		<titulo lang="en">Harry Potter</titulo> +		<autor>J K. Rowling</autor> +		<year>2005</year> +		<preco>29.99</preco> +	</livro> +	<livro category="WEB"> +		<titulo lang="en">Learning XML</titulo> +		<autor>Erik T. Ray</autor> +		<year>2003</year> +		<preco>39.95</preco> +	</livro> +</livraria> + +<!-- Um típico arquivo XML é mostrado acima. +	Ele começa com uma declaração, informando alguns metadados (opcional). +	 +	XML usa uma estrutura de árvore. Acima, o nó raiz é "Livraria", que tem +	três nós filhos, todos os 'Livros'. Esses nós tem mais nós filhos,  +	e assim por diante... +	 +	Nós são criados usando tags abre/fecha, filhos são justamente os nós que  +	estão entre estes nós. --> + + +<!-- XML traz dois tipos de dados: +	1 - Atributos -> Isso é metadados sobre um nó. +			Normalmente, o parser XML usa esta informação para armazenar os dados +			corretamente. Caracteriza-se por aparecer em parênteses dentro da tag  +			de abertura. +	2 - Elementos -> É dados puros. +			Isso é o que o analisador irá recuperar a partir do arquivo XML.  +			Elementos aparecem entre as tags de abertura e fechamento,  +			sem parênteses. --> +			 +	 +<!-- Abaixo, um elemento com dois atributos --> +<arquivo type="gif" id="4293">computer.gif</arquivo> + + +``` + +* Documento bem formatado x Validação + +Um documento XML é bem formatado se estiver sintaticamente correto.No entanto, +é possível injetar mais restrições no documento, utilizando definições de  +documentos, tais como DTD e XML Schema. + +Um documento XML que segue uma definição de documento é chamado válido, sobre  +esse documento. + +Com esta ferramenta, você pode verificar os dados XML fora da lógica da aplicação. + +```xml + +<!-- Abaixo, você pode ver uma versão simplificada do documento livraria, +com a adição de definição DTD.--> + +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE note SYSTEM "livraria.dtd"> +<livraria> +	<livro category="COOKING"> +		<titulo >Everyday Italian</titulo> +		<preco>30.00</preco> +	</livro> +</livraria> + +<!-- Este DTD poderia ser algo como:--> + +<!DOCTYPE note +[ +<!ELEMENT livraria (livro+)> +<!ELEMENT livro (titulo,preco)> +<!ATTLIST livro category CDATA "Literature"> +<!ELEMENT titulo (#PCDATA)> +<!ELEMENT preco (#PCDATA)> +]> + + +<!-- O DTD começa com uma declaração. +	Na sequência, o nó raiz é declarado, o que requer uma ou mais crianças nós  +	'Livro'. Cada 'Livro' deve conter exatamente um 'titulo' e um 'preco' e um  +	atributo chamado "categoria", com "Literatura", como o valor padrão. +	Os nós "título" e "preço" contêm um conjunto de dados de caráter analisados.--> + +<!-- O DTD poderia ser declarado dentro do próprio arquivo XML .--> + +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE note +[ +<!ELEMENT livraria (livro+)> +<!ELEMENT livro (titulo,preco)> +<!ATTLIST livro category CDATA "Literature"> +<!ELEMENT titulo (#PCDATA)> +<!ELEMENT preco (#PCDATA)> +]> + +<livraria> +	<livro category="COOKING"> +		<titulo >Everyday Italian</titulo> +		<preco>30.00</preco> +	</livro> +</livraria> +```
\ No newline at end of file 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/javascript-ru.html.markdown b/ru-ru/javascript-ru.html.markdown new file mode 100644 index 00000000..ad66b501 --- /dev/null +++ b/ru-ru/javascript-ru.html.markdown @@ -0,0 +1,543 @@ +--- +language: javascript +contributors: +    - ["Adam Brenecki", "http://adam.brenecki.id.au"] +    - ["Ariel Krakowski", "http://www.learneroo.com"] +translators: +    - ["Maxim Koretskiy", "http://github.com/maximkoretskiy"] +filename: javascript-ru.js +lang: ru-ru +--- + +Javascript был разработан Бренданом Айком из Netcape в 1995. Изначально  +предполагалось, что он станет простым вариантом скриптового языка для сайтов,  +дополняющий к Java, который бы в свою очередь использовался для более сложных  +web-приложений. Но тонкая интегрированность javascript с web-страницей и  +встроенная поддержка в браузерах привели к тому, чтобы он стал более  +распространен в frontend-разработке, чем Java. + +Использование JavaScript не ограничивается браузерами. Проект Node.js,  +предоставляющий независимую среду выполнения на движке Google Chrome V8  +JavaScript, становится все более популярным. + +Обратная связь важна и нужна! Вы можете написаться мне +на [@adambrenecki](https://twitter.com/adambrenecki) или +[adam@brenecki.id.au](mailto:adam@brenecki.id.au). + +```js +// Комментарии оформляются как в C. +// Однострочнные коментарии начинаются с двух слешей, +/* а многострочные с слеша и звездочки +   и заканчиваются звездочеий и слешом */ + +// Выражения разделяются с помощью ; +doStuff(); + +// ... но этого можно и не делать, разделители подставляются автоматически +// после перехода на новую строку за исключением особых случаев +doStuff() + +// Это может приводить к непредсказуемому результату и поэтому мы будем  +// использовать разделители в этом туре. +// Because those cases can cause unexpected results, we'll keep on using +// semicolons in this guide. + +/////////////////////////////////// +// 1. Числа, Строки и Операторы +// 1. Numbers, Strings and Operators + +// В Javasript всего 1 числовой тип - 64-битное число с плавающей точкой +// стандарта IEEE 754) +// Числа имеют 52-битную мантиссу, чего достаточно для хранения хранения целых  +// чисел до 9✕10¹⁵ приблизительно. +3; // = 3 +1.5; // = 1.5 + +// В основном базовая арифметика работает предсказуемо +1 + 1; // = 2 +.1 + .2; // = 0.30000000000000004 +8 - 1; // = 7 +10 * 2; // = 20 +35 / 5; // = 7 + +// Включая нецелочисленное деление +5 / 2; // = 2.5 + +// Двоичные операции тоже есть. Если применить двоичную операцию к float-числу, +// оно будет приведено к 32-битному целому со знаком. +1 << 2; // = 4 + +// (todo:перевести) +// Приоритет выполнения операций можно менять с помощью скобок. +(1 + 3) * 2; // = 8 + +// Есть три особых не реальных числовых значения: +Infinity; // допустим, результат операции 1/0 +-Infinity; //  допустим, результат операции -1/0 +NaN; //  допустим, результат операции 0/0 + +// Так же есть тип булевых данных. +true; +false; + +// Строки создаются с помощью ' или ".  +'abc'; +"Hello, world"; + +// Оператор ! означает отрицание +!true; // = false +!false; // = true + +// Равество это === +1 === 1; // = true +2 === 1; // = false + +// Неравенство это !== +1 !== 1; // = false +2 !== 1; // = true + +// Еще сравнения +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true + +// Строки складываются с помощью + +"Hello " + "world!"; // = "Hello world!" + +// и сравниваются с помощью < и > +"a" < "b"; // = true + +// Приведение типов выполняется при сравнении с ==... +"5" == 5; // = true +null == undefined; // = true + +// ...в отличие от === +"5" === 5; // = false +null === undefined; // = false  + +// Для доступа к конкретному символу строки используйте charAt +"This is a string".charAt(0);  // = 'T' + +// ... или используйте substring  для получения подстроки +"Hello world".substring(0, 5); // = "Hello" + +// length(длина) - свойство, не используйте () +"Hello".length; // = 5 + +// Есть null и undefined +null; // используется что бы указать явно, что значения нет +undefined; // испрользуется чтобы показать, что значения не было установлено  +           // собственно, undefined так и переводится + +// false, null, undefined, NaN, 0 и "" являются falsy-значениями(при приведении  +// в булеву типу становятся false) +// Обратите внимание что 0 приводится к false, а "0" к true,  +// не смотря на то, что "0"==0 + +/////////////////////////////////// +// 2. Переменные, массивы и объекты + +// Переменные объявляются ключевым словом var. Javascript динамически  +// типизируемый, так что указывать тип не нужно.  +// Присвоение значения описывается с помощью оператора = +var someVar = 5; + +// если не указать ключевого слова var, ошибки не будет... +someOtherVar = 10; + +// ...но переменная будет создана в глобальном контексте, в не области  +// видимости, в которой она была объявлена. + +// Переменные объявленные без присвоения значения, содержать undefined +var someThirdVar; // = undefined + +// Для математических операций над переменными есть короткая запись: +someVar += 5; // тоже что someVar = someVar + 5; someVar равно 10 теперь +someVar *= 10; // а теперь -- 100 + +// еще более короткая запись для добавления и вычитания 1 +someVar++; // теперь someVar равно 101 +someVar--; // обратно к 100 + +// Массивы -- упорядоченные списки значений любых типов. +var myArray = ["Hello", 45, true]; + +// Для доступу к элементам массивов используйте квадратные скобки. +// Индексы массивов начинаются с 0 +myArray[1]; // = 45 + +// Массивы мутабельны(изменяемы) и имеют переменную длину.  +myArray.push("World"); // добавить элемент +myArray.length; // = 4 + +// Добавить или изменить значение по конкретному индексу +myArray[3] = "Hello"; + +// Объекты javascript похожи на dictionary или map из других языков  +// программирования. Это неупорядочнные коллекции пар ключ-значение. +var myObj = {key1: "Hello", key2: "World"}; + +// Ключи -- это строки, но кавычки не требуются если названия явлюятся +// корректными javascript идентификаторами. Значения могут быть любого типа. +var myObj = {myKey: "myValue", "my other key": 4}; + +// Доступ к атрибту объекта можно получить с помощью квадратных скобок +myObj["my other key"]; // = 4 + +// ... или используя точечную нотацию, при условии что ключ является  +// корректным идентификатором. +myObj.myKey; // = "myValue" + +// Объекты мутабельны. В существуюещем объекте можно изменить значние  +// или добавить новый атрибут. +myObj.myThirdKey = true; + +// При попытке доступа к атрибуту, который до этого не был создан, будет +// возвращен undefined +myObj.myFourthKey; // = undefined + +/////////////////////////////////// +// 3. Логика и Управляющие структуры + +// Синтаксис управляющих структур очень похож на его реализацию в Java. + +// if работает так как вы ожидаете. +var count = 1; +if (count == 3){ +    // выполнится, если значение count равно 3 +} else if (count == 4){ +    // выполнится, если значение count равно 4 +} else { +    // выполнится, если значение count не будет равно ни 3 ни 4 +} + +// Поведение while тоже вполне предсказуемо +while (true){ +    // Бесконечный цикл +} + +// Циклы do-while похожи на while, но они всегда выполняются хотябы 1 раз. +// Do-while loops are like while loops, except they always run at least once. +var input +do { +    input = getInput(); +} while (!isValid(input)) + +// Цикл for такой же как в C и Java: +// инициализация; условие продолжения; итерация +for (var i = 0; i < 5; i++){ +    // выполнится 5 раз +} + +// && - логическое и, || - логическое или +if (house.size == "big" && house.color == "blue"){ +    house.contains = "bear"; +} +if (color == "red" || color == "blue"){ +    // если цвет или красный или синий +} + +// && и || удобны для установки значений по умолчанию. +// && and || "short circuit", which is useful for setting default values. +var name = otherName || "default"; + +// выражение switch проверяет равество с помощью === +// используйте 'break' после каждого case, +// иначе помимо правильного case выполнятся и все последующие. +grade = '4';    // оценка +switch (grade) { +  case '5': +    console.log("Великолепно"); +    break; +  case '4': +    console.log("Неплохо"); +    break; +  case '3': +    console.log("Можно и лучше"); +    break; +  default: +    console.log("Да уж."); +    break; +} + + +/////////////////////////////////// +// 4. Функции, Область видимости и Замыкания + +// Функции в JavaScript объявляются с помощью ключевого слова function. +function myFunction(thing){ +    return thing.toUpperCase(); // приведение к верхнему регистру +} +myFunction("foo"); // = "FOO" + +// Помните, что значение, которое должно быть возкращено должно начинаться +// на той же строке, где расположено ключевое слово 'return'. В противном случае +// будет возвращено undefined. Такое поведения объясняется автоматической  +// вставкой разделителей ';'. Помните этот факт, если используете +// BSD стиль оформления кода. +// Note that the value to be returned must start on the same line as the +// 'return' keyword, otherwise you'll always return 'undefined' due to +// automatic semicolon insertion. Watch out for this when using Allman style. +function myFunction() +{ +    return // <- разделитель автоматически будет вставлен здесь +    { +        thisIsAn: 'object literal' +    } +} +myFunction(); // = undefined + +// Функции в JavaScript являются объектами, поэтому их можно назначить в  +// переменные с разными названиями и передавать в другие функции, как аргументы, +// на пример, при указании обработчика события. +function myFunction(){ +    // этот фрагмент кода будет вызван через 5 секунд +} +setTimeout(myFunction, 5000); +// Обратите внимание, что setTimeout не является частью языка, однако он  +// доступен в API браузеров и Node.js. + +// Объект функции на самом деле не обязательно объявлять с именем - можно   +// создать анонимную функцию прямо в аргументах другой функции. +setTimeout(function(){ +    // этот фрагмент кода будет вызван через 5 секунд +}, 5000); + +// В JavaScript есть области видимости. У функций есть собственные области  +// видимости, у других блоков их нет. +if (true){ +    var i = 5; +} +i; // = 5, а не undefined, как это было бы в языке, создающем +   // области видисти для блоков кода + +// Это привело к появлению паттерна общего назначения "immediately-executing +// anonymous functions" (сразу выполняющиеся анонимные функции), который +// позволяет предотвратить запись временных переменных в общую облать видимости. +(function(){ +    var temporary = 5; +    // Для доступа к глобальной области видимости можно использовать запись в  +    // некоторый 'глобальный объект', для браузеров это 'window'. Глобальный  +    // объект может называться по-разному в небраузерных средах, таких Node.js. +    window.permanent = 10; +})(); +temporary; // вызывает исключение ReferenceError +permanent; // = 10 + +// Одной из сильных сторон JavaScript являются замыкания. Если функция  +// объявлена в внутри другой функции, внутренняя функция имеет доступ ко всем  +// переменным внешней функции, даже после того, как внешняя функции завершила  +// свое выполнение. +function sayHelloInFiveSeconds(name){ +    var prompt = "Привет, " + name + "!"; +    // Внутренние функции помещаются в локальную область видимости, как-будто  +    // они объявлены с ключевым словом 'var'. +    function inner(){ +        alert(prompt); +    } +    setTimeout(inner, 5000); +    // setTimeout является асинхроннной, и поэтому функция sayHelloInFiveSeconds +    // завершит свое выполнение сразу и setTimeout вызовет inner позже. +    // Однако, так как inner "закрыта внутри" или "замкнута в" +    // sayHelloInFiveSeconds, inner все еще будет иметь доступ к переменной  +    // prompt, когда будет вызвана. +} +sayHelloInFiveSeconds("Вася"); // откроет модальное окно с сообщением +                               // "Привет, Вася" по истечении 5 секунд. + + +/////////////////////////////////// +// 5. Немного еще об Объектах. Конструкторы и Прототипы + +// Объекты могут содержать функции +var myObj = { +    myFunc: function(){ +        return "Hello world!"; +    } +}; +myObj.myFunc(); // = "Hello world!" + +// Когда функции прикрепленные к объекту вызываются, они могут получить доступ  +// к данным объекта, ипользуя ключевое слово this. +myObj = { +    myString: "Hello world!", +    myFunc: function(){ +        return this.myString; +    } +}; +myObj.myFunc(); // = "Hello world!" + +// Содержание this определяется исходя из того, как была вызвана функция, а  +// не места её определения. По этой причине наша функция не будет работать вне +// контекста объекта. +var myFunc = myObj.myFunc; +myFunc(); // = undefined + +// И напротив, функция может быть присвоена объекту и получить доступ к нему +// через this, даже если она не была прикреплена к объекту в момент её создания. +var myOtherFunc = function(){ +    return this.myString.toUpperCase(); +} +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!" + +// Также можно указать контекс выполнения фунции с помощью 'call' или 'apply'. +var anotherFunc = function(s){ +    return this.myString + s; +} +anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" + +// Функция 'apply' очень похожа, но принимает массив со списком аргументов. + +anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" + +// Это может быть удобно, когда работаешь с фунцией принимающей на вход  +// последовательность аргументов и нужно передать их в виде массива. + +Math.min(42, 6, 27); // = 6 +Math.min([42, 6, 27]); // = NaN (uh-oh!) +Math.min.apply(Math, [42, 6, 27]); // = 6 + +// Однако, 'call' и 'apply' не имеют постоянного эффекта. Если вы хотите  +// зафиксировать контекст для функции, используйте bind. + +var boundFunc = anotherFunc.bind(myObj); +boundFunc(" And Hello Saturn!"); // = "Hello World! And Hello Saturn!" + +// bind также можно использовать чтобы частично передать аргументы в  +// функцию (каррировать). + +var product = function(a, b){ return a * b; } +var doubler = product.bind(this, 2); +doubler(8); // = 16 + +// Когда функция вызывается с ключевым словом new, создается новый объект. +// Данный объект становится доступным функции через ключевое слово this.  +// Функции спроектированные вызываться таким способом называются конструкторами. + +var MyConstructor = function(){ +    this.myNumber = 5; +} +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5 + +// Любой объект в JavaScript имеет 'прототип'. Когда вы пытаетесь получить  +// доступ к свойству не объявленному в данном объекте, интерпретатор будет  +// искать его в прототипе. + +// Некоторые реализации JS позволяют получить доступ к прототипу с помощью  +// "волшебного" свойства __proto__. До момента пока оно не являются стандартным,  +// __proto__ полезно лишь для изучения прототипов в JavaScript. Мы разберемся  +// со стандартными способами работы с прототипом несколько позже. +var myObj = { +    myString: "Hello world!" +}; +var myPrototype = { +    meaningOfLife: 42, +    myFunc: function(){ +        return this.myString.toLowerCase() +    } +}; + +myObj.__proto__ = myPrototype; +myObj.meaningOfLife; // = 42 +myObj.myFunc(); // = "hello world!" + +// Естественно, если в свойства нет в прототипе, поиск будет продолжен в  +// прототипе прототипа и так далее. +myPrototype.__proto__ = { +    myBoolean: true +}; +myObj.myBoolean; // = true + +// Ничего не копируется, каждый объект хранит ссылку на свой прототип. Если  +// изменить прототип, все изменения отразятся во всех его потомках. +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43 + +// Как было сказано выше, __proto__ не является стандартом, и нет стандартного +// способа изменить прототип у созданного объекта. Однако, есть два способа  +// создать объект с заданным прототипом. + +// Первый способ - Object.create, был добавлен в JS относительно недавно, и  +// потому не доступен в более ранних реализациях языка. +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43 + +// Второй вариан доступен везде и связан с конструкторами. Конструкторы имеют  +// свойство prototype. Это вовсе не прототип функции конструктора, напротив,  +// это прототип, который присваевается новым объектам, созданным с этим  +// конструктором с помощью ключевого слова new. +MyConstructor.prototype = { +    myNumber: 5, +    getMyNumber: function(){ +        return this.myNumber; +    } +}; +var myNewObj2 = new MyConstructor(); +myNewObj2.getMyNumber(); // = 5 +myNewObj2.myNumber = 6 +myNewObj2.getMyNumber(); // = 6 + +// У встроенных типов таких, как строки и числа, тоже есть конструкторы,  +// создающие эквивалентные объекты-обертки. +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true + +// Правда, они не совсем эквивалентны. +typeof myNumber; // = 'number' +typeof myNumberObj; // = 'object' +myNumber === myNumberObj; // = false +if (0){ +    // Этот фрагмент кода не будет выпонен, так как 0 приводится к false +} +if (Number(0)){ +    // Этот фрагмент кода *будет* выпонен, так как Number(0) приводится к true. +} + +// Однако, оберточные объекты и обычные встроенные типы имеют общие прототипы,  +// следовательно вы можете расширить функциональность строки, например. +String.prototype.firstCharacter = function(){ +    return this.charAt(0); +} +"abc".firstCharacter(); // = "a" + +// Этот факт часто используется для создания полифилов(polyfill) - реализации  +// новых возможностей JS в его более старых версиях для того чтобы их можно было  +// использовать в устаревших браузерах. + +// Например, мы упомянули, что Object.create не доступен во всех версиях  +// JavaScript, но мы можем создать полифилл. +if (Object.create === undefined){ // не переопределяем, если есть +    Object.create = function(proto){ +        // создаем временный конструктор с заданным прототипом +        var Constructor = function(){}; +        Constructor.prototype = proto; +        // создаём новый объект с правильным прототипом +        return new Constructor(); +    } +} +``` + +## Что еще почитать + +[Современный учебник JavaScript](http://learn.javascript.ru/) от Ильи Кантора  +является довольно качественным и глубоким учебным материалом, освещающим все  +особенности современного языка. Помимо учебника на том же домене можно найти  +[перевод спецификации ECMAScript 5.1](http://es5.javascript.ru/) и справочник по  +возможностям языка. + +[JavaScript Garden](http://bonsaiden.github.io/JavaScript-Garden/ru/) позволяет  +довольно быстро изучить основные тонкие места в работе с JS, но фокусируется  +только на таких моментах + +[Справочник](https://developer.mozilla.org/ru/docs/JavaScript) от MDN  +(Mozilla Development Network) содержит информацию о возможностях языка на  +английском. + +Название проекта ["Принципы написания консистентного, идиоматического кода на  +JavaScript"](https://github.com/rwaldron/idiomatic.js/tree/master/translations/ru_RU) +говорит само за себя. + diff --git a/scala.html.markdown b/scala.html.markdown index 544abd5b..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" +}  ///////////////////////////////////////////////// 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)  | 
