diff options
Diffstat (limited to 'zh-cn')
| -rw-r--r-- | zh-cn/clojure-macro-cn.html.markdown | 152 | ||||
| -rw-r--r-- | zh-cn/common-lisp-cn.html.markdown | 12 | ||||
| -rw-r--r-- | zh-cn/visualbasic-cn.html.markdown | 274 | 
3 files changed, 432 insertions, 6 deletions
| diff --git a/zh-cn/clojure-macro-cn.html.markdown b/zh-cn/clojure-macro-cn.html.markdown new file mode 100644 index 00000000..9324841e --- /dev/null +++ b/zh-cn/clojure-macro-cn.html.markdown @@ -0,0 +1,152 @@ +--- +language: "clojure macros" +filename: learnclojuremacros-zh.clj +contributors: +    - ["Adam Bard", "http://adambard.com/"] +translators: +    - ["Jakukyo Friel", "http://weakish.github.io"] +lang: zh-cn +--- + +和所有Lisp一样,Clojure内在的[同构性](https://en.wikipedia.org/wiki/Homoiconic)使得你可以穷尽语言的特性,编写生成代码的子过程——“宏”。宏是一种按需调制语言的强大方式。 + +小心!可以用函数完成的事用宏去实现可不是什么好事。你应该仅在需要控制参数是否或者何时eval的时候使用宏。 + +你应该熟悉Clojure.确保你了解[Y分钟学Clojure](http://learnxinyminutes.com/docs/zh-cn/clojure-cn/)中的所有内容。 + +```clojure +;; 使用defmacro定义宏。宏应该输出一个可以作为clojure代码演算的列表。 +;; +;; 以下宏的效果和直接写(reverse "Hello World")一致。 + +(defmacro my-first-macro [] +  (list reverse "Hello World")) + +;; 使用macroexpand或macroexpand-1查看宏的结果。 +;; +;; 注意,调用需要引用。 +(macroexpand '(my-first-macro)) +;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World") + +;; 你可以直接eval macroexpand的结果 +(eval (macroexpand '(my-first-macro))) +; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; 不过一般使用以下形式,更简短,更像函数: +(my-first-macro)  ; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; 创建宏的时候可以使用更简短的引用形式来创建列表 +(defmacro my-first-quoted-macro [] +  '(reverse "Hello World")) + +(macroexpand '(my-first-quoted-macro)) +;; -> (reverse "Hello World") +;; 注意reverse不再是一个函数对象,而是一个符号。 + +;; 宏可以传入参数。 +(defmacro inc2 [arg] +  (list + 2 arg)) + +(inc2 2) ; -> 4 + +;; 不过,如果你尝试配合使用引用列表,会导致错误, +;; 因为参数也会被引用。 +;; 为了避免这个问题,clojure提供了引用宏的另一种方式:` +;; 在`之内,你可以使用~获得外圈作用域的变量。 +(defmacro inc2-quoted [arg] +  `(+ 2 ~arg)) + +(inc2-quoted 2) + +;; 你可以使用通常的析构参数。用~@展开列表中的变量。 +(defmacro unless [arg & body] +  `(if (not ~arg) +     (do ~@body))) ; 别忘了 do! + +(macroexpand '(unless true (reverse "Hello World"))) + +;; -> +;; (if (clojure.core/not true) (do (reverse "Hello World"))) + +;; 当第一个参数为假时,(unless)会演算、返回主体。  +;; 否则返回nil。 + +(unless true "Hello") ; -> nil +(unless false "Hello") ; -> "Hello" + +;; 需要小心,宏会搞乱你的变量 +(defmacro define-x [] +  '(do +     (def x 2) +     (list x))) + +(def x 4) +(define-x) ; -> (2) +(list x) ; -> (2) + +;; 使用gensym来获得独有的标识符 +(gensym 'x) ; -> x1281 (or some such thing) + +(defmacro define-x-safely [] +  (let [sym (gensym 'x)] +    `(do +       (def ~sym 2) +       (list ~sym)))) + +(def x 4) +(define-x-safely) ; -> (2) +(list x) ; -> (4) + +;; 你可以在 ` 中使用 # 为每个符号自动生成gensym +(defmacro define-x-hygenically [] +  `(do +     (def x# 2) +     (list x#))) + +(def x 4) +(define-x-hygenically) ; -> (2) +(list x) ; -> (4) + +;; 通常会配合宏使用帮助函数。 +;; 让我们创建一些帮助函数来支持(无聊的)算术语法: + +(declare inline-2-helper) +(defn clean-arg [arg] +  (if (seq? arg) +    (inline-2-helper arg) +    arg)) + +(defn apply-arg +  "Given args [x (+ y)], return (+ x y)" +  [val [op arg]] +  (list op val (clean-arg arg))) + +(defn inline-2-helper +  [[arg1 & ops-and-args]] +  (let [ops (partition 2 ops-and-args)] +    (reduce apply-arg (clean-arg arg1) ops))) + +;; 在创建宏前,我们可以先测试 +(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5)) + +; 然而,如果我们希望它在编译期执行,就需要创建宏 +(defmacro inline-2 [form] +  (inline-2-helper form))) + +(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1))) +; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1) + +(inline-2 (1 + (3 / 2) - (1 / 2) + 1)) +; -> 3 (事实上,结果是3N, 因为数字被转化为带/的有理分数) +``` + +## 扩展阅读 + +[Clojure for the Brave and True](http://www.braveclojure.com/)系列的编写宏 +http://www.braveclojure.com/writing-macros/ + +官方文档 +http://clojure.org/macros + +何时使用宏? +http://dunsmor.com/lisp/onlisp/onlisp_12.html diff --git a/zh-cn/common-lisp-cn.html.markdown b/zh-cn/common-lisp-cn.html.markdown index f005dd58..c4dc3274 100644 --- a/zh-cn/common-lisp-cn.html.markdown +++ b/zh-cn/common-lisp-cn.html.markdown @@ -56,11 +56,11 @@ t  ;还是一个原子,代表逻辑真值。  ;; 有很多不同的Common Lisp的实现;并且大部分的实现是一致(可移植)的。  ;; 对于入门学习来说,CLISP是个不错的选择。 -;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 +;; 可以通过QuickLisp.org的Quicklisp系统管理你的库。 -;; 通常,使用一个文本编辑器和一个的“REPL”来开发Common Lisp; +;; 通常,使用文本编辑器和“REPL”来开发Common Lisp;  ;; (译者注:“REPL”指读取-求值-打印循环)。 -;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 +;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统“现场”操作。  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -329,7 +329,7 @@ nil                  ; 逻辑假,或者空列表  ;; 或者使用`apply`  (apply (lambda () "Hello World") nil) ; => "Hello World" -;; 显示地定义一个函数(译者注:即非匿名的) +;; 显式地定义一个函数(译者注:即非匿名的)  (defun hello-world ()     "Hello World")  (hello-world) ; => "Hello World" @@ -537,7 +537,7 @@ nil                  ; 逻辑假,或者空列表  ;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。  ;; 若要定义一个方法; -;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi +;; 注意,我们计算自行车轮子周长时使用了这样一个公式:C = d * pi  (defmethod circumference ((object bicycle))    (* pi (wheel-size object))) @@ -593,7 +593,7 @@ nil                  ; 逻辑假,或者空列表  ;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的;  ;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 -;; 注意到反引号'`',逗号','以及'@'符号,这三个符号;  +;; 注意反引号'`',逗号','以及'@'这三个符号;   ;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。  ;; 逗号“,”意味着解除引用(unquote,即开始求值);  ;; “@”符号则表示将当前的参数插入到当前整个列表中。 diff --git a/zh-cn/visualbasic-cn.html.markdown b/zh-cn/visualbasic-cn.html.markdown new file mode 100644 index 00000000..95f01ed6 --- /dev/null +++ b/zh-cn/visualbasic-cn.html.markdown @@ -0,0 +1,274 @@ +--- +language: Visual Basic +contributors: +    - ["Brian Martin", "http://brianmartin.biz"] +translators: +    - ["Abner Chou", "http://github.com/NoahDragon"] +lang: zh-cn +filename: learnvisualbasic.vb-cn +--- + +```vb +Module Module1 + +    Sub Main() +        ' 让我们先从简单的终端程序学起。 +        ' 单引号用来生成注释(注意是半角单引号,非全角单引号’) +        ' 为了方便运行此示例代码,我写了个目录索引。 +        ' 可能你还不了解以下代码的意义,但随着教程的深入, +        ' 你会渐渐理解其用法。 +        Console.Title = ("Learn X in Y Minutes") +        Console.WriteLine("NAVIGATION") ' 显示目录 +        Console.WriteLine("") +        Console.ForegroundColor = ConsoleColor.Green +        Console.WriteLine("1. Hello World Output") ' Hello world 输出示例 +        Console.WriteLine("2. Hello World Input") ' Hello world 输入示例 +        Console.WriteLine("3. Calculating Whole Numbers") ' 求整数之和 +        Console.WriteLine("4. Calculating Decimal Numbers") ' 求小数之和 +        Console.WriteLine("5. Working Calculator") ' 计算器 +        Console.WriteLine("6. Using Do While Loops") ' 使用 Do While 循环 +        Console.WriteLine("7. Using For While Loops") ' 使用 For While 循环 +        Console.WriteLine("8. Conditional Statements") ' 条件语句 +        Console.WriteLine("9. Select A Drink") ' 选饮料 +        Console.WriteLine("50. About") ' 关于 +        Console.WriteLine("Please Choose A Number From The Above List") +        Dim selection As String = Console.ReadLine +        Select Case selection +            Case "1" ' Hello world 输出示例 +                Console.Clear() ' 清空屏幕 +                HelloWorldOutput() ' 调用程序块 +            Case "2" ' Hello world 输入示例 +                Console.Clear() +                HelloWorldInput() +            Case "3" ' 求整数之和 +                Console.Clear() +                CalculatingWholeNumbers() +            Case "4" ' 求小数之和 +                Console.Clear() +                CalculatingDecimalNumbers() +            Case "5" ' 计算器 +                Console.Clear() +                WorkingCalculator() +            Case "6" ' 使用 do while 循环 +                Console.Clear() +                UsingDoWhileLoops() +            Case "7" ' 使用 for while 循环 +                Console.Clear() +                UsingForLoops() +            Case "8" ' 条件语句 +                Console.Clear() +                ConditionalStatement() +            Case "9" ' If/Else 条件语句 +                Console.Clear() +                IfElseStatement() ' 选饮料 +            Case "50" ' 关于本程序和作者 +                Console.Clear() +                Console.Title = ("Learn X in Y Minutes :: About") +                MsgBox("This tutorial is by Brian Martin (@BrianMartinn") +                Console.Clear() +                Main() +                Console.ReadLine() + +        End Select +    End Sub + +    ' 一、对应程序目录1,下同 + +    ' 使用 private subs 声明函数。  +    Private Sub HelloWorldOutput() +        ' 程序名 +        Console.Title = "Hello World Ouput | Learn X in Y Minutes" +        ' 使用 Console.Write("") 或者 Console.WriteLine("") 来输出文本到屏幕上 +        ' 对应的 Console.Read() 或 Console.Readline() 用来读取键盘输入 +        Console.WriteLine("Hello World") +        Console.ReadLine()  +        ' Console.WriteLine()后加Console.ReadLine()是为了防止屏幕输出信息一闪而过 +        ' 类似平时常见的“单击任意键继续”的意思。 +    End Sub + +    ' 二 +    Private Sub HelloWorldInput() +        Console.Title = "Hello World YourName | Learn X in Y Minutes" +        ' 变量 +        ' 用来存储用户输入的数据 +        ' 变量声明以 Dim 开始,结尾为 As VariableType (变量类型). + +        ' 此教程中,我们希望知道你的姓名,并让程序记录并输出。 +        Dim username As String +        ' 我们定义username使用字符串类型(String)来记录用户姓名。 +        Console.WriteLine("Hello, What is your name? ") ' 询问用户输入姓名 +        username = Console.ReadLine() ' 存储用户名到变量 username +        Console.WriteLine("Hello " + username) ' 输出将是 Hello + username +        Console.ReadLine() ' 暂停屏幕并显示以上输出 +        ' 以上程序将询问你的姓名,并和你打招呼。 +        ' 其它变量如整型(Integer)我们用整型来处理整数。 +    End Sub + +    ' 三 +    Private Sub CalculatingWholeNumbers() +        Console.Title = "Calculating Whole Numbers | Learn X in Y Minutes" +        Console.Write("First number: ") ' 输入一个整数:1,2,50,104,等等 +        Dim a As Integer = Console.ReadLine() +        Console.Write("Second number: ") ' 输入第二个整数 +        Dim b As Integer = Console.ReadLine() +        Dim c As Integer = a + b +        Console.WriteLine(c) +        Console.ReadLine() +        ' 以上程序将两个整数相加 +    End Sub + +    ' 四 +    Private Sub CalculatingDecimalNumbers() +        Console.Title = "Calculating with Double | Learn X in Y Minutes" +        ' 当然,我们还需要能够处理小数。 +        ' 只需要要将整型(Integer)改为小数(Double)类型即可。 + +        ' 输入一个小数: 1.2, 2.4, 50.1, 104.9,等等 +        Console.Write("First number: ") +        Dim a As Double = Console.ReadLine +        Console.Write("Second number: ") ' 输入第二个数 +        Dim b As Double = Console.ReadLine +        Dim c As Double = a + b +        Console.WriteLine(c) +        Console.ReadLine() +        ' 以上代码能实现两个小数相加 +    End Sub + +    ' 五 +    Private Sub WorkingCalculator() +        Console.Title = "The Working Calculator| Learn X in Y Minutes" +        ' 但是如果你希望有个能够处理加减乘除的计算器呢? +        ' 只需将上面代码复制粘帖即可。 +        Console.Write("First number: ") ' 输入第一个数 +        Dim a As Double = Console.ReadLine +        Console.Write("Second number: ") ' 输入第二个数 +        Dim b As Integer = Console.ReadLine +        Dim c As Integer = a + b +        Dim d As Integer = a * b +        Dim e As Integer = a - b +        Dim f As Integer = a / b + +        ' 通过以下代码我们可以将以上所算的加减乘除结果输出到屏幕上。 +        Console.Write(a.ToString() + " + " + b.ToString()) +        ' 我们希望答案开头能有3个空格,可以使用String.PadLeft(3)方法。 +        Console.WriteLine(" = " + c.ToString.PadLeft(3)) +        Console.Write(a.ToString() + " * " + b.ToString()) +        Console.WriteLine(" = " + d.ToString.PadLeft(3)) +        Console.Write(a.ToString() + " - " + b.ToString()) +        Console.WriteLine(" = " + e.ToString.PadLeft(3)) +        Console.Write(a.ToString() + " / " + b.ToString()) +        Console.WriteLine(" = " + e.ToString.PadLeft(3)) +        Console.ReadLine() + +    End Sub + +    ' 六 +    Private Sub UsingDoWhileLoops() +        ' 如同以上的代码一样 +        ' 这次我们将询问用户是否继续 (Yes or No?) +        ' 我们将使用Do While循环,因为我们不知到用户是否需要使用一次以上。 +        Console.Title = "UsingDoWhileLoops | Learn X in Y Minutes" +        Dim answer As String ' 我们使用字符串变量来存储answer(答案) +        Do ' 循环开始 +            Console.Write("First number: ") +            Dim a As Double = Console.ReadLine +            Console.Write("Second number: ") +            Dim b As Integer = Console.ReadLine +            Dim c As Integer = a + b +            Dim d As Integer = a * b +            Dim e As Integer = a - b +            Dim f As Integer = a / b + +            Console.Write(a.ToString() + " + " + b.ToString()) +            Console.WriteLine(" = " + c.ToString.PadLeft(3)) +            Console.Write(a.ToString() + " * " + b.ToString()) +            Console.WriteLine(" = " + d.ToString.PadLeft(3)) +            Console.Write(a.ToString() + " - " + b.ToString()) +            Console.WriteLine(" = " + e.ToString.PadLeft(3)) +            Console.Write(a.ToString() + " / " + b.ToString()) +            Console.WriteLine(" = " + e.ToString.PadLeft(3)) +            Console.ReadLine() +            ' 询问用户是否继续,注意大小写。  +            Console.Write("Would you like to continue? (yes / no)") +            ' 程序读入用户输入 +            answer = Console.ReadLine() ' added a bracket here +        ' 当用户输入"yes"时,程序将跳转到Do,并再次执行 +        Loop While answer = "yes" + +    End Sub + +    ' 七 +    Private Sub UsingForLoops() +        ' 有一些程序只需要运行一次。 +        ' 这个程序我们将实现从10倒数计数. + +        Console.Title = "Using For Loops | Learn X in Y Minutes" +        ' 声明变量和Step (步长,即递减的速度,如-1,-2,-3等)。  +        For i As Integer = 10 To 0 Step -1  +            Console.WriteLine(i.ToString) ' 将计数结果输出的屏幕 +        Next i ' 计算新的i值 +        Console.WriteLine("Start")  +        Console.ReadLine()  +    End Sub + +    ' 八 +    Private Sub ConditionalStatement() +        Console.Title = "Conditional Statements | Learn X in Y Minutes" +        Dim userName As String = Console.ReadLine +        Console.WriteLine("Hello, What is your name? ") ' 询问用户姓名 +        userName = Console.ReadLine() ' 存储用户姓名 +        If userName = "Adam" Then +            Console.WriteLine("Hello Adam") +            Console.WriteLine("Thanks for creating this useful site") +            Console.ReadLine() +        Else +            Console.WriteLine("Hello " + userName) +            Console.WriteLine("Have you checked out www.learnxinyminutes.com") +            Console.ReadLine() ' 程序停止,并输出以上文本 +        End If +    End Sub + +    ' 九 +    Private Sub IfElseStatement() +    Console.Title = "If / Else Statement | Learn X in Y Minutes" +        ' 有时候我们需要考虑多于两种情况。 +        ' 这时我们就需要使用If/ElesIf条件语句。 +        ' If语句就好似个自动售货机,当用户输入A1,A2,A3,等去选择物品时, +        ' 所有的选择可以合并到一个If语句中 + +        Dim selection As String = Console.ReadLine() ' 读入用户选择 +            Console.WriteLine("A1. for 7Up") ' A1 七喜 +            Console.WriteLine("A2. for Fanta") ' A2 芬达 +            Console.WriteLine("A3. for Dr. Pepper") ' A3 胡椒医生 +            Console.WriteLine("A4. for Diet Coke") ' A4 无糖可乐 +            Console.ReadLine() +            If selection = "A1" Then +                Console.WriteLine("7up") +                Console.ReadLine() +            ElseIf selection = "A2" Then +                Console.WriteLine("fanta") +                Console.ReadLine() +            ElseIf selection = "A3" Then +                Console.WriteLine("dr. pepper") +                Console.ReadLine() +            ElseIf selection = "A4" Then +                Console.WriteLine("diet coke") +                Console.ReadLine() +            Else +                Console.WriteLine("Please select a product") ' 请选择你需要的产品 +                Console.ReadLine() +            End If + +    End Sub + +End Module + +``` + +## 参考 + +我(译注:原作者)在命令行下学习的VB。命令行编程使我能够更好的了解程序编译运行机制,并使学习其它语言变得容易。  + +如果希望进一步学习VB,这里还有更深层次的 <a href="http://www.vbbootcamp.co.uk/" Title="VB教学">VB教学(英文)</a>。  + +所有代码均通过测试。只需复制粘帖到Visual Basic中,并按F5运行即可。  | 
