diff options
-rw-r--r-- | c.html.markdown | 5 | ||||
-rw-r--r-- | de-de/bash-de.html.markdown | 2 | ||||
-rw-r--r-- | de-de/yaml-de.html.markdown | 138 | ||||
-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-- | ja-jp/julia-jp.html.markdown | 761 | ||||
-rw-r--r-- | java.html.markdown | 5 | ||||
-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-- | ru-ru/javascript-ru.html.markdown | 543 | ||||
-rw-r--r-- | scala.html.markdown | 66 | ||||
-rwxr-xr-x | tcl.html.markdown | 447 |
17 files changed, 2439 insertions, 215 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/de-de/bash-de.html.markdown b/de-de/bash-de.html.markdown index ad782e06..fb9cd9d4 100644 --- a/de-de/bash-de.html.markdown +++ b/de-de/bash-de.html.markdown @@ -17,7 +17,7 @@ Beinahe alle der folgenden Beispiele können als Teile eines Shell-Skripts oder ```bash #!/bin/bash -# Die erste Zeile des Scripts nennt sich Shebang in gibt dem System an, wie +# Die erste Zeile des Scripts nennt sich Shebang, dies gibt dem System an, # wie das Script ausgeführt werden soll: http://de.wikipedia.org/wiki/Shebang # Du hast es bestimmt schon mitgekriegt, Kommentare fangen mit # an. Das Shebang ist auch ein Kommentar diff --git a/de-de/yaml-de.html.markdown b/de-de/yaml-de.html.markdown new file mode 100644 index 00000000..88318014 --- /dev/null +++ b/de-de/yaml-de.html.markdown @@ -0,0 +1,138 @@ +--- +language: yaml +filename: learnyaml.yaml +contributors: + - ["Adam Brenecki", "https://github.com/adambrenecki"] +translators: + - ["Ruben M.", https://github.com/switchhax] +--- + +YAML ist eine Sprache zur Datenserialisierung, die sofort von Menschenhand geschrieben und gelesen werden kann. + +YAML ist eine Erweiterung von JSON, mit der Erweiterung von syntaktisch wichtigen Zeilenumbrüche und Einrückung sowie in Python. Anders als in Python erlaubt YAML keine Tabulator-Zeichen. + +```yaml +# Kommentare in YAML schauen so aus. + +################# +# SKALARE TYPEN # +################# + +# Unser Kernobjekt (für das ganze Dokument) wird das Assoziative Datenfeld (Map) sein, +# welches equivalent zu einem Hash oder einem Objekt einer anderen Sprache ist. +Schlüssel: Wert +nochn_Schlüssel: Hier kommt noch ein Wert hin. +eine_Zahl: 100 +wissenschaftliche_Notation: 1e+12 +boolean: true +null_Wert: null +Schlüssel mit Leerzeichen: value +# Strings müssen nicht immer mit Anführungszeichen umgeben sein, können aber: +jedoch: "Ein String in Anführungzeichen" +"Ein Schlüssel in Anführungszeichen": "Nützlich, wenn du einen Doppelpunkt im Schluessel haben willst." + +# Mehrzeilige Strings schreibst du am besten als 'literal block' (| gefolgt vom Text) +# oder ein 'folded block' (> gefolgt vom text). +literal_block: | + Dieser ganze Block an Text ist der Wert vom Schlüssel literal_block, + mit Erhaltung der Zeilenumbrüche. + + Das Literal fährt solange fort bis dieses unverbeult ist und die vorherschende Einrückung wird + gekürzt. + + Zeilen, die weiter eingerückt sind, behalten den Rest ihrer Einrückung - + diese Zeilen sind mit 4 Leerzeichen eingerückt. +folded_style: > + Dieser ganze Block an Text ist der Wert vom Schlüssel folded_style, aber diesmal + werden alle Zeilenumbrüche durch ein Leerzeichen ersetzt. + + Freie Zeilen, wie obendrüber, werden in einen Zeilenumbruch verwandelt. + + Weiter eingerückte Zeilen behalten ihre Zeilenumbrüche - + diese Textpassage wird auf zwei Zeilen sichtbar sein. + +#################### +# COLLECTION TYPEN # +#################### + +# Verschachtelung wird duch Einrückung erzielt. +eine_verschachtelte_map: + schlüssel: wert + nochn_Schlüssel: Noch ein Wert. + noch_eine_verschachtelte_map: + hallo: hallo + +# Schlüssel müssen nicht immer String sein. +0.25: ein Float-Wert als Schluessel + +# Schlüssel können auch mehrzeilig sein, ? symbolisiert den Anfang des Schlüssels +? | + Dies ist ein Schlüssel, + der mehrzeilig ist. +: und dies ist sein Wert + +# YAML erlaubt auch Collections als Schlüssel, doch viele Programmiersprachen +# werden sich beklagen. + +# Folgen (equivalent zu Listen oder Arrays) schauen so aus: +eine_Folge: + - Artikel 1 + - Artikel 2 + - 0.5 # Folgen können verschiedene Typen enthalten. + - Artikel 4 + - schlüssel: wert + nochn_schlüssel: nochn_wert + - + - Dies ist eine Folge + - innerhalb einer Folge + +# Weil YAML eine Erweiterung von JSON ist, können JSON-ähnliche Maps und Folgen +# geschrieben werden: +json_map: {"schlüssel": "wert"} +json_seq: [3, 2, 1, "Start"] + +############################ +# EXTRA YAML EIGENSCHAFTEN # +############################ + +# YAML stellt zusätzlich Verankerung zu Verfügung, welche es einfach machen +# Inhalte im Dokument zu vervielfältigen. Beide Schlüssel werden den selben Wert haben. +verankerter_inhalt: &anker_name Dieser String wird als Wert beider Schlüssel erscheinen. +anderer_anker: *anker_name + +# YAML hat auch Tags, mit denen man explizit Typangaben angibt. +explicit_string: !!str 0.5 +# Manche Parser implementieren sprachspezifische Tags wie dieser hier für Pythons +# komplexe Zahlen. +python_komplexe_Zahlen: !!python/komplex 1+2j + +#################### +# EXTRA YAML TYPEN # +#################### + +# Strings and Zahlen sind nicht die einzigen Skalare, welche YAML versteht. +# ISO-formatierte Datumsangaben and Zeiangaben können ebenso geparsed werden. +DatumZeit: 2001-12-15T02:59:43.1Z +DatumZeit_mit_Leerzeichen: 2001-12-14 21:59:43.10 -5 +Datum: 2002-12-14 + +# Der !!binary Tag zeigt das ein String base64 verschlüsselt ist. +# Representation des Binären Haufens +gif_datei: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + +# YAML bietet auch Mengen (Sets), welche so ausschauen +menge: + ? artikel1 + ? artikel2 + ? artikel3 + +# Wie in Python sind Mengen nicht anderes als Maps nur mit null als Wert; das Beispiel oben drüber ist equivalent zu: +menge: + artikel1: null + artikel2: null + artikel3: null +``` 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/ja-jp/julia-jp.html.markdown b/ja-jp/julia-jp.html.markdown new file mode 100644 index 00000000..0c1d7e49 --- /dev/null +++ b/ja-jp/julia-jp.html.markdown @@ -0,0 +1,761 @@ +--- +language: Julia +contributors: + - ["Leah Hanson", "http://leahhanson.us"] +translators: + - ["Yuichi Motoyama", "https://github.com/yomichi"] +filename: learnjulia-jp.jl +--- + +Julia は科学技術計算向けに作られた、同図像性を持った(homoiconic) プログラミング言語です。 +マクロによる同図像性や第一級関数などの抽象化機能の恩恵を受けつつ、低階層をも扱えますが、 +それでいてPython 並に学習しやすく、使いやすい言語となっています。 + +この文章は、Julia の2013年10月18日現在の開発バージョンを元にしています。 + +```ruby + +# ハッシュ(シャープ)記号から改行までは単一行コメントとなります。 +#= 複数行コメントは、 + '#=' と '=#' とで囲むことで行えます。 + #= + 入れ子構造にすることもできます。 + =# +=# + +#################################################### +## 1. 基本的な型と演算子 +#################################################### + +# Julia ではすべて式となります。 + +# 基本となる数値型がいくつかあります。 +3 # => 3 (Int64) +3.2 # => 3.2 (Float64) +2 + 1im # => 2 + 1im (Complex{Int64}) +2//3 # => 2//3 (Rational{Int64}) + +# 一般的な中置演算子が使用可能です。 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7.0 +5 / 2 # => 2.5 # 整数型同士の割り算の結果は、浮動小数点数型になります +div(5, 2) # => 2 # 整数のまま割り算するには、 div を使います +5 \ 35 # => 7.0 +2 ^ 2 # => 4 # べき乗です。排他的論理和ではありません +12 % 10 # => 2 + +# 丸括弧で演算の優先順位をコントロールできます +(1 + 3) * 2 # => 8 + +# ビット演算 +~2 # => -3 # ビット反転 +3 & 5 # => 1 # ビット積 +2 | 4 # => 6 # ビット和 +2 $ 4 # => 6 # ビット排他的論理和 +2 >>> 1 # => 1 # 右論理シフト +2 >> 1 # => 1 # 右算術シフト +2 << 1 # => 4 # 左シフト + +# bits 関数を使うことで、数の二進表現を得られます。 +bits(12345) +# => "0000000000000000000000000000000000000000000000000011000000111001" +bits(12345.0) +# => "0100000011001000000111001000000000000000000000000000000000000000" + +# ブール値が用意されています +true +false + +# ブール代数 +!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 +# 比較演算子をつなげることもできます +1 < 2 < 3 # => true +2 < 3 < 2 # => false + +# 文字列は " で作れます +"This is a string." + +# 文字リテラルは ' で作れます +'a' + +# 文字列は文字の配列のように添字アクセスできます +"This is a string"[1] # => 'T' # Julia では添字は 1 から始まります +# ただし、UTF8 文字列の場合は添字アクセスではうまくいかないので、 +# イテレーションを行ってください(map 関数や for ループなど) + +# $ を使うことで、文字列に変数や、任意の式を埋め込めます。 +"2 + 2 = $(2 + 2)" # => "2 + 2 = 4" + +# 他にも、printf マクロを使うことでも変数を埋め込めます。 +@printf "%d is less than %f" 4.5 5.3 # 5 is less than 5.300000 + +# 出力も簡単です +println("I'm Julia. Nice to meet you!") + +#################################################### +## 2. 変数と配列、タプル、集合、辞書 +#################################################### + +# 変数の宣言は不要で、いきなり変数に値を代入・束縛できます。 +some_var = 5 # => 5 +some_var # => 5 + +# 値に束縛されていない変数を使おうとするとエラーになります。 +try + some_other_var # => ERROR: some_other_var not defined +catch e + println(e) +end + +# 変数名は数字や記号以外の文字から始めます。 +# その後は、数字やアンダースコア(_), 感嘆符(!)も使えます。 +SomeOtherVar123! = 6 # => 6 + +# Unicode 文字も使えます。 +☃ = 8 # => 8 +# ギリシャ文字などを使うことで数学的な記法が簡単にかけます。 +2 * π # => 6.283185307179586 + +# Julia における命名習慣について: +# +# * 変数名における単語の区切りにはアンダースコアを使っても良いですが、 +# 使わないと読みにくくなる、というわけではない限り、 +# 推奨はされません。 +# +# * 型名は大文字で始め、単語の区切りにはキャメルケースを使います。 +# +# * 関数やマクロの名前は小文字で書きます。 +# 単語の分かち書きにはアンダースコアをつかわず、直接つなげます。 +# +# * 内部で引数を変更する関数は、名前の最後に ! をつけます。 +# この手の関数は、しばしば「破壊的な関数」とか「in-place な関数」とか呼ばれます。 + + +# 配列は、1 から始まる整数によって添字付けられる、値の列です。 +a = Int64[] # => 0-element Int64 Array + +# 一次元配列(列ベクトル)は、角括弧 [] のなかにカンマ , 区切りで値を並べることで作ります。 +b = [4, 5, 6] # => 3-element Int64 Array: [4, 5, 6] +b[1] # => 4 +b[end] # => 6 + +# 二次元配列は、空白区切りで作った行を、セミコロンで区切ることで作ります。 +matrix = [1 2; 3 4] # => 2x2 Int64 Array: [1 2; 3 4] + +# 配列の末尾に値を追加するには push! を、 +# 他の配列を結合するには append! を使います。 +push!(a,1) # => [1] +push!(a,2) # => [1,2] +push!(a,4) # => [1,2,4] +push!(a,3) # => [1,2,4,3] +append!(a,b) # => [1,2,4,3,4,5,6] + +# 配列の末尾から値を削除するには pop! を使います。 +pop!(b) # => 6 and b is now [4,5] + +# 一旦元に戻しておきましょう。 +push!(b,6) # b is now [4,5,6] again. + +a[1] # => 1 # Julia では添字は0 ではなく1 から始まること、お忘れなく! + +# end は最後の添字を表す速記法です。 +# 添字を書く場所ならどこにでも使えます。 +a[end] # => 6 + +# 先頭に対する削除・追加は shift!, unshift! です。 +shift!(a) # => 1 and a is now [2,4,3,4,5,6] +unshift!(a,7) # => [7,2,4,3,4,5,6] + +# ! で終わる関数名は、その引数を変更するということを示します。 +arr = [5,4,6] # => 3-element Int64 Array: [5,4,6] +sort(arr) # => [4,5,6]; arr is still [5,4,6] +sort!(arr) # => [4,5,6]; arr is now [4,5,6] + +# 配列の範囲外アクセスをすると BoundsError が発生します。 +try + a[0] # => ERROR: BoundsError() in getindex at array.jl:270 + a[end+1] # => ERROR: BoundsError() in getindex at array.jl:270 +catch e + println(e) +end + +# エラーが発生すると、どのファイルのどの行で発生したかが表示されます。 +# 標準ライブラリで発生したものでもファイル名と行数が出ます。 +# ソースからビルドした場合など、標準ライブラリのソースが手元にある場合は +# base/ ディレクトリから探し出して見てください。 + +# 配列は範囲オブジェクトから作ることもできます。 +a = [1:5] # => 5-element Int64 Array: [1,2,3,4,5] + +# 添字として範囲オブジェクトを渡すことで、 +# 配列の部分列を得ることもできます。 +a[1:3] # => [1, 2, 3] +a[2:end] # => [2, 3, 4, 5] + +# 添字を用いて配列から値の削除をしたい場合は、splice! を使います。 +arr = [3,4,5] +splice!(arr,2) # => 4 ; arr is now [3,5] + +# 配列の結合は append! です。 +b = [1,2,3] +append!(a,b) # Now a is [1, 2, 3, 4, 5, 1, 2, 3] + +# 配列内に指定した値があるかどうかを調べるのには in を使います。 +in(1, a) # => true + +# length で配列の長さを取得できます。 +length(a) # => 8 + +# 変更不可能 (immutable) な値の組として、タプルが使えます。 +tup = (1, 2, 3) # => (1,2,3) # an (Int64,Int64,Int64) tuple. +tup[1] # => 1 +try: + tup[1] = 3 # => ERROR: no method setindex!((Int64,Int64,Int64),Int64,Int64) +catch e + println(e) +end + +# 配列に関する関数の多くが、タプルでも使えます。 +length(tup) # => 3 +tup[1:2] # => (1,2) +in(2, tup) # => true + +# タプルから値をばらして(unpack して) 複数の変数に代入できます。 +a, b, c = (1, 2, 3) # => (1,2,3) # a is now 1, b is now 2 and c is now 3 + +# 丸括弧なしでもタプルになります。 +d, e, f = 4, 5, 6 # => (4,5,6) + +# ひとつの値だけからなるタプルは、その値自体とは区別されます。 +(1,) == 1 # => false +(1) == 1 # => true + +# 値の交換もタプルを使えば簡単です。 +e, d = d, e # => (5,4) # d is now 5 and e is now 4 + + +# 辞書 (Dict) は、値から値への変換の集合です。 +empty_dict = Dict() # => Dict{Any,Any}() + +# 辞書型リテラルは次のとおりです。 +filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3] +# => Dict{ASCIIString,Int64} + +# [] を使ったアクセスができます。 +filled_dict["one"] # => 1 + +# すべての鍵(添字)は keys で得られます。 +keys(filled_dict) +# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# 必ずしも辞書に追加した順番には並んでいないことに注意してください。 + +# 同様に、values はすべての値を返します。 +values(filled_dict) +# => ValueIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# 鍵と同様に、必ずしも辞書に追加した順番には並んでいないことに注意してください。 + +# in や haskey を使うことで、要素や鍵が辞書の中にあるかを調べられます。 +in(("one", 1), filled_dict) # => true +in(("two", 3), filled_dict) # => false +haskey(filled_dict, "one") # => true +haskey(filled_dict, 1) # => false + +# 存在しない鍵を問い合わせると、エラーが発生します。 +try + filled_dict["four"] # => ERROR: key not found: four in getindex at dict.jl:489 +catch e + println(e) +end + +# get 関数を使い、鍵がなかった場合のデフォルト値を与えておくことで、 +# このエラーを回避できます。 +get(filled_dict,"one",4) # => 1 +get(filled_dict,"four",4) # => 4 + +# 集合 (Set) は一意な値の、順序付けられていない集まりです。 +empty_set = Set() # => Set{Any}() +# 集合の初期化 +filled_set = Set(1,2,2,3,4) # => Set{Int64}(1,2,3,4) + +# 集合への追加 +push!(filled_set,5) # => Set{Int64}(5,4,2,3,1) + +# in で、値が既に存在するかを調べられます。 +in(2, filled_set) # => true +in(10, filled_set) # => false + +# 積集合や和集合、差集合を得る関数も用意されています。 +other_set = Set(3, 4, 5, 6) # => Set{Int64}(6,4,5,3) +intersect(filled_set, other_set) # => Set{Int64}(3,4,5) +union(filled_set, other_set) # => Set{Int64}(1,2,3,4,5,6) +setdiff(Set(1,2,3,4),Set(2,3,5)) # => Set{Int64}(1,4) + + +#################################################### +## 3. 制御構文 +#################################################### + +# まずは変数を作ります。 +some_var = 5 + +# if 構文です。Julia ではインデントに意味はありません。 +if some_var > 10 + println("some_var is totally bigger than 10.") +elseif some_var < 10 # elseif 節は省略可能です。 + println("some_var is smaller than 10.") +else # else 節も省略可能です。 + println("some_var is indeed 10.") +end +# => "some var is smaller than 10" と出力されます。 + +# for ループによって、反復可能なオブジェクトを走査できます。 +# 反復可能なオブジェクトの型として、 +# Range, Array, Set, Dict, String などがあります。 +for animal=["dog", "cat", "mouse"] + println("$animal is a mammal") + # $ を使うことで文字列に変数の値を埋め込めます。 + # You can use $ to interpolate variables or expression into strings +end +# prints: +# dog is a mammal +# cat is a mammal +# mouse is a mammal + +# for = の代わりに for in を使うこともできます +for animal in ["dog", "cat", "mouse"] + println("$animal is a mammal") +end +# prints: +# dog is a mammal +# cat is a mammal +# mouse is a mammal + +# 辞書ではタプルが返ってきます。 +for a in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"] + println("$(a[1]) is a $(a[2])") +end +# prints: +# dog is a mammal +# cat is a mammal +# mouse is a mammal + +# タプルのアンパック代入もできます。 +for (k,v) in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"] + println("$k is a $v") +end +# prints: +# dog is a mammal +# cat is a mammal +# mouse is a mammal + +# while ループは、条件式がtrue となる限り実行され続けます。 +x = 0 +while x < 4 + println(x) + x += 1 # Shorthand for x = x + 1 +end +# prints: +# 0 +# 1 +# 2 +# 3 + +# 例外は try/catch で捕捉できます。 +try + error("help") +catch e + println("caught it $e") +end +# => caught it ErrorException("help") + + +#################################################### +## 4. 関数 +#################################################### + +# function キーワードを次のように使うことで、新しい関数を定義できます。 +#function name(arglist) +# body... +#end +function add(x, y) + println("x is $x and y is $y") + + # 最後に評価された式の値が、関数全体の返り値となります。 + x + y +end + +add(5, 6) # => 11 after printing out "x is 5 and y is 6" + +# 可変長引数関数も定義できます。 +function varargs(args...) + return args + # return キーワードを使うことで、好きな位置で関数から抜けられます。 +end +# => varargs (generic function with 1 method) + +varargs(1,2,3) # => (1,2,3) + +# ... はsplat と呼ばれます +# (訳注:「ピシャッという音(名詞)」「衝撃で平らにする(動詞)」) +# 今回は関数定義で使いましたが、関数呼び出しに使うこともできます。 +# その場合、配列やタプルの要素を開いて、複数の引数へと割り当てることとなります。 +Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # 「整数の配列」の集合 +Set([1,2,3]...) # => Set{Int64}(1,2,3) # 整数の集合 + +x = (1,2,3) # => (1,2,3) +Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # タプルの集合 +Set(x...) # => Set{Int64}(2,3,1) + + +# 引数に初期値を与えることで、オプション引数をもった関数を定義できます。 +function defaults(a,b,x=5,y=6) + return "$a $b and $x $y" +end + +defaults('h','g') # => "h g and 5 6" +defaults('h','g','j') # => "h g and j 6" +defaults('h','g','j','k') # => "h g and j k" +try + defaults('h') # => ERROR: no method defaults(Char,) + defaults() # => ERROR: no methods defaults() +catch e + println(e) +end + +# キーワード引数を持った関数も作れます。 +function keyword_args(;k1=4,name2="hello") # ; が必要なことに注意 + return ["k1"=>k1,"name2"=>name2] +end + +keyword_args(name2="ness") # => ["name2"=>"ness","k1"=>4] +keyword_args(k1="mine") # => ["k1"=>"mine","name2"=>"hello"] +keyword_args() # => ["name2"=>"hello","k1"=>4] + +# もちろん、これらを組み合わせることもできます。 +function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo") + println("normal arg: $normal_arg") + println("optional arg: $optional_positional_arg") + println("keyword arg: $keyword_arg") +end + +all_the_args(1, 3, keyword_arg=4) +# prints: +# normal arg: 1 +# optional arg: 3 +# keyword arg: 4 + +# Julia では関数は第一級関数として、値として扱われます。 +function create_adder(x) + adder = function (y) + return x + y + end + return adder +end + +# ラムダ式によって無名関数をつくれます。 +(x -> x > 2)(3) # => true + +# 先ほどの create_adder と同じもの +function create_adder(x) + y -> x + y +end + +# 中の関数に名前をつけても構いません。 +function create_adder(x) + function adder(y) + x + y + end + adder +end + +add_10 = create_adder(10) +add_10(3) # => 13 + + +# いくつかの高階関数が定義されています。 +map(add_10, [1,2,3]) # => [11, 12, 13] +filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# map の代わりとしてリスト内包表記も使えます。 +[add_10(i) for i=[1, 2, 3]] # => [11, 12, 13] +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] + +#################################################### +## 5. 型 +#################################################### + +# Julia ではすべての値にひとつの型がついています。 +# 変数に、ではなくて値に、です。 +# typeof 関数を使うことで、値が持つ型を取得できます。 +typeof(5) # => Int64 + +# 型自身もまた、第一級の値であり、型を持っています。 +typeof(Int64) # => DataType +typeof(DataType) # => DataType +# DataType は型を表現する型であり、DataType 自身もDataType 型の値です。 + +# 型はドキュメント化や最適化、関数ディスパッチのために使われます。 +# 静的な型チェックは行われません。 + +# 自分で新しい型を定義することもできます。 +# 他の言語で言う、構造体やレコードに近いものになっています。 +# 型定義には type キーワードを使います。 +# type Name +# field::OptionalType +# ... +# end +type Tiger + taillength::Float64 + coatcolor # 型注釈を省略した場合、自動的に :: Any として扱われます。 +end + +# 型を定義すると、その型のプロパティすべてを、定義した順番に +# 引数として持つデフォルトコンストラクタが自動的に作られます。 +tigger = Tiger(3.5,"orange") # => Tiger(3.5,"orange") + +# 型名がそのままコンストラクタ名(関数名)となります。 +sherekhan = typeof(tigger)(5.6,"fire") # => Tiger(5.6,"fire") + +# このような、構造体スタイルの型は、具体型(concrete type)と呼ばれます。 +# 具体型はインスタンス化可能ですが、派生型(subtype)を持つことができません。 +# 具体型の他には抽象型(abstract type)があります。 + +# abstract Name +abstract Cat # 型の階層図の途中の一点を指し示す名前となります。 + +# 抽象型はインスタンス化できませんが、派生型を持つことができます。 +# 例えば、 Number は以下の派生型を持つ抽象型です。 +subtypes(Number) # => 6-element Array{Any,1}: + # Complex{Float16} + # Complex{Float32} + # Complex{Float64} + # Complex{T<:Real} + # ImaginaryUnit + # Real +subtypes(Cat) # => 0-element Array{Any,1} + +# すべての型は、直接的にはただひとつの基本型(supertype) を持ちます。 +# super 関数でこれを取得可能です。 +typeof(5) # => Int64 +super(Int64) # => Signed +super(Signed) # => Real +super(Real) # => Number +super(Number) # => Any +super(super(Signed)) # => Number +super(Any) # => Any +# Int64 を除き、これらはすべて抽象型です。 + +# <: は派生形を表す演算子です。 +# これを使うことで派生型を定義できます。 +type Lion <: Cat # Lion は 抽象型 Cat の派生型 + mane_color + roar::String +end + +# 型名と同じ名前の関数を定義し、既に存在するコンストラクタを呼び出して、 +# 必要とする型の値を返すことによって、 +# デフォルトコンストラクタ以外のコンストラクタを作ることができます。 + +Lion(roar::String) = Lion("green",roar) +# 型定義の外側で定義されたコンストラクタなので、外部コンストラクタと呼ばれます。 + +type Panther <: Cat # Panther も Cat の派生型 + eye_color + Panther() = new("green") + # Panther は内部コンストラクタとしてこれのみを持ち、 + # デフォルトコンストラクタを持たない +end +# 内部コンストラクタを使うことで、どのような値が作られるのかをコントロールすることができます。 +# 出来る限り、外部コンストラクタを使うべきです。 + +#################################################### +## 6. 多重ディスパッチ +#################################################### + +# Julia では、すべての名前付きの関数は総称的関数(generic function) です。 +# これは、関数はいくつかの細かいメソッドの集合である、という意味です。 +# 例えば先の Lion 型のコンストラクタ Lion は、Lion という関数の1つのメソッドです。 + +# コンストラクタ以外の例をみるために、新たに meow 関数を作りましょう。 + +# Lion, Panther, Tiger 型それぞれに対する meow 関数のメソッド定義 +function meow(animal::Lion) + animal.roar # 型のプロパティには . でアクセスできます。 +end + +function meow(animal::Panther) + "grrr" +end + +function meow(animal::Tiger) + "rawwwr" +end + +# meow 関数の実行 +meow(tigger) # => "rawwr" +meow(Lion("brown","ROAAR")) # => "ROAAR" +meow(Panther()) # => "grrr" + +# 型の階層関係を見てみましょう +issubtype(Tiger,Cat) # => false +issubtype(Lion,Cat) # => true +issubtype(Panther,Cat) # => true + +# 抽象型 Cat の派生型を引数にとる関数 +function pet_cat(cat::Cat) + println("The cat says $(meow(cat))") +end + +pet_cat(Lion("42")) # => prints "The cat says 42" +try + pet_cat(tigger) # => ERROR: no method pet_cat(Tiger,) +catch e + println(e) +end + +# オブジェクト指向言語では、一般的にシングルディスパッチが用いられます。 +# つまり、関数に複数あるメソッドのうちにどれが呼ばれるかは、 +# その第一引数(もしくは、 . や -> の前にある値の型)によってのみ決定されます。 +# 一方でJulia では、すべての引数の型が、このメソッド決定に寄与します。 + +# 多変数関数を定義して、この辺りを見て行きましょう。 +function fight(t::Tiger,c::Cat) + println("The $(t.coatcolor) tiger wins!") +end +# => fight (generic function with 1 method) + +fight(tigger,Panther()) # => prints The orange tiger wins! +fight(tigger,Lion("ROAR")) # => prints The orange tiger wins! + +# 第二引数の Cat が実際は Lion だった時に、挙動が変わるようにします。 +fight(t::Tiger,l::Lion) = println("The $(l.mane_color)-maned lion wins!") +# => fight (generic function with 2 methods) + +fight(tigger,Panther()) # => prints The orange tiger wins! +fight(tigger,Lion("ROAR")) # => prints The green-maned lion wins! + +# 別に Tiger だけが戦う必要もないですね。 +fight(l::Lion,c::Cat) = println("The victorious cat says $(meow(c))") +# => fight (generic function with 3 methods) + +fight(Lion("balooga!"),Panther()) # => prints The victorious cat says grrr +try + fight(Panther(),Lion("RAWR")) # => ERROR: no method fight(Panther,Lion) +catch +end + +# 第一引数にも Cat を許しましょう。 +fight(c::Cat,l::Lion) = println("The cat beats the Lion") +# => Warning: New definition +# fight(Cat,Lion) at none:1 +# is ambiguous with +# fight(Lion,Cat) at none:2. +# Make sure +# fight(Lion,Lion) +# is defined first. +#fight (generic function with 4 methods) + +# 警告が出ましたが、これは次の対戦で何が起きるのかが不明瞭だからです。 +fight(Lion("RAR"),Lion("brown","rarrr")) # => prints The victorious cat says rarrr +# Julia のバージョンによっては、結果が違うかもしれません。 + +fight(l::Lion,l2::Lion) = println("The lions come to a tie") +fight(Lion("RAR"),Lion("brown","rarrr")) # => prints The lions come to a tie + + +# Julia が生成する LLVM 内部表現や、アセンブリを調べることもできます。 + +square_area(l) = l * l # square_area (generic function with 1 method) + +square_area(5) #25 + +# square_area に整数を渡すと何が起きる? +code_native(square_area, (Int32,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 # Prologue + # push RBP + # mov RBP, RSP + # Source line: 1 + # movsxd RAX, EDI # l を取得 + # imul RAX, RAX # l*l を計算して RAX に入れる + # pop RBP # Base Pointer を元に戻す + # ret # 終了。RAX の中身が結果 + +code_native(square_area, (Float32,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # Source line: 1 + # vmulss XMM0, XMM0, XMM0 # 単精度浮動小数点数演算 (AVX) + # pop RBP + # ret + +code_native(square_area, (Float64,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # Source line: 1 + # vmulsd XMM0, XMM0, XMM0 # 倍精度浮動小数点数演算 (AVX) + # pop RBP + # ret + # + +# Julia では、浮動小数点数と整数との演算では +# 自動的に浮動小数点数用の命令が生成されることに注意してください。 +# 円の面積を計算してみましょう。 +circle_area(r) = pi * r * r # circle_area (generic function with 1 method) +circle_area(5) # 78.53981633974483 + +code_native(circle_area, (Int32,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # Source line: 1 + # vcvtsi2sd XMM0, XMM0, EDI # Load integer (r) from memory + # movabs RAX, 4593140240 # Load pi + # vmulsd XMM1, XMM0, QWORD PTR [RAX] # pi * r + # vmulsd XMM0, XMM0, XMM1 # (pi * r) * r + # pop RBP + # ret + # + +code_native(circle_area, (Float64,)) + # .section __TEXT,__text,regular,pure_instructions + # Filename: none + # Source line: 1 + # push RBP + # mov RBP, RSP + # movabs RAX, 4593140496 + # Source line: 1 + # vmulsd XMM1, XMM0, QWORD PTR [RAX] + # vmulsd XMM0, XMM1, XMM0 + # pop RBP + # ret + # +``` + +## より勉強するために + +[公式ドキュメント](http://docs.julialang.org/en/latest/manual/) (英語)にはより詳細な解説が記されています。 + +Julia に関して助けが必要ならば、[メーリングリスト](https://groups.google.com/forum/#!forum/julia-users) が役に立ちます。 +みんな非常に親密に教えてくれます。 + diff --git a/java.html.markdown b/java.html.markdown index 4661d4f9..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 --- @@ -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/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) |