From 4ecd73fc9cd766557e10fc2fa0c3351c373ff1a0 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 1 Aug 2013 11:24:23 -0700 Subject: An assortment --- zh-cn/c-cn.html.markdown | 5 +++-- zh-cn/elisp-cn.html.markdown | 10 +++++++--- zh-cn/java-cn.html.markdown | 9 +++++---- zh-cn/javascript.html.markdown | 11 +++++++---- zh-cn/php-cn.html.markdown | 3 ++- 5 files changed, 24 insertions(+), 14 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown index ed55203c..f8a8e0bd 100755 --- a/zh-cn/c-cn.html.markdown +++ b/zh-cn/c-cn.html.markdown @@ -2,9 +2,10 @@ language: c filename: learnc.c contributors: - - ["Adam Bard", "http://adambard.com/"] + - ["Adam Bard", "http://adambard.com/"] translators: - - ["Chenbo Li", "http://binarythink.net/"] + - ["Chenbo Li", "http://binarythink.net/"] +lang: zh-cn --- C语言在今天仍然是高性能计算的主要选择。 diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown index d9a8ce35..c3a2f927 100755 --- a/zh-cn/elisp-cn.html.markdown +++ b/zh-cn/elisp-cn.html.markdown @@ -3,12 +3,15 @@ language: elisp contributors: - ["Bastien Guerry", "http://bzg.fr"] translators: - - ["Chenbo Li", "http://binarythink.net"] + - ["Chenbo Li", "http://binarythink.net"] filename: learn-emacs-lisp.el +lang: zh-cn --- ```scheme -;; 15分钟学会Emacs Lisp (v0.2a) (作者:bzg,https://github.com/bzg 译者:lichenbo,http://douban.com/people/lichenbo) +;; 15分钟学会Emacs Lisp (v0.2a) +;;(作者:bzg,https://github.com/bzg +;; 译者:lichenbo,http://douban.com/people/lichenbo) ;; ;; 请先阅读Peter Norvig的一篇好文: ;; http://norvig.com/21-days.html @@ -301,7 +304,8 @@ filename: learn-emacs-lisp.el (list 'face 'bold))) (other-window 1)) -;; 这个函数使用了 `re-search-forward': 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式 +;; 这个函数使用了 `re-search-forward': +;; 和查找一个字符串不同,你用这个命令可以查找一个模式,即正则表达式 ;; 正则表达式 "Bonjour \\(.+\\)!" 的意思是: ;; 字符串 "Bonjour ", 之后跟着 diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index 4db4e91e..b9ccf61a 100755 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -1,12 +1,13 @@ --- - +name: java +category: language language: java +lang: zh-cn +filename: LearnJava.java contributors: - ["Jake Prather", "http://github.com/JakeHP"] translators: - - ["Chenbo Li", "http://binarythink.net"] -filename: LearnJava.java - + - ["Chenbo Li", "http://binarythink.net"] --- Java是一个通用的程序语言, 包含并发, 基于类的面向对象等特性 diff --git a/zh-cn/javascript.html.markdown b/zh-cn/javascript.html.markdown index dd04c8a5..3b5cfa94 100755 --- a/zh-cn/javascript.html.markdown +++ b/zh-cn/javascript.html.markdown @@ -1,9 +1,12 @@ --- language: javascript -author: Adam Brenecki -author_url: http://adam.brenecki.id.au -translator: Chenbo Li -translator_url: http://binarythink.net +category: language +name: javascript +contributors: + - ["Adam Brenecki", "http://adam.brenecki.id.au"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +lang: zh-cn --- Javascript于1995年由网景公司的Brendan Eich发明。 diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index e3dfe419..3b242ce1 100755 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -4,8 +4,9 @@ contributors: - ["Malcolm Fell", "http://emarref.net/"] - ["Trismegiste", "https://github.com/Trismegiste"] translators: - - ["Chenbo Li", "http://binarythink.net"] + - ["Chenbo Li", "http://binarythink.net"] filename: learnphp.php +lang: zh-cn --- 这份教程所使用的版本是 PHP 5+. -- cgit v1.2.3 From 1a52aefcba5c31bb05b58290380509d6da81045c Mon Sep 17 00:00:00 2001 From: Chenbo Li Date: Fri, 2 Aug 2013 23:40:47 +0800 Subject: add git-cn and rename javascript --- zh-cn/git-cn.html.markdown | 375 ++++++++++++++++++++++++++++++++++ zh-cn/javascript-cn.html.markdown | 415 ++++++++++++++++++++++++++++++++++++++ zh-cn/javascript.html.markdown | 415 -------------------------------------- 3 files changed, 790 insertions(+), 415 deletions(-) create mode 100755 zh-cn/git-cn.html.markdown create mode 100755 zh-cn/javascript-cn.html.markdown delete mode 100755 zh-cn/javascript.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown new file mode 100755 index 00000000..7aab8986 --- /dev/null +++ b/zh-cn/git-cn.html.markdown @@ -0,0 +1,375 @@ +--- +category: tool +tool: git +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +filename: LearnGit.txt +lang: zh-cn +--- + +Git是一个分布式版本控制及源代码管理工具 + +Git可以为你的项目保存若干快照,以此来对整个项目进行版本管理 + +## 版本 + +### 什么是版本控制 + +版本控制系统就是根据时间来记录一个或多个文件的更改情况的系统。 + +### 集中式版本控制 VS 分布式版本控制 + +* 集中式版本控制的主要功能为同步,跟踪以及备份文件 +* 分布式版本控制则更注重共享更改。每一次更改都有唯一的标识 +* 分布式系统没有预定的结构。你也可以用git很轻松的实现SVN风格的集中式系统控制 + +[更多信息](http://git-scm.com/book/en/Getting-Started-About-Version-Control) + +### 为什么要使用Git + +* 可以离线工作 +* 和他人协同工作变得简单 +* 分支很轻松 +* 合并很容易 +* Git系统速度快,也很灵活 + +## Git 架构 + + +### 版本库 + +一系列文件,目录,历史记录,提交记录和头指针。 +可以把它视作每个源代码文件都带有历史记录属性数据结构 + +一个Git版本库包括一个 .git 目录和其工作目录 + +### .git 目录(版本库的一部分) + +.git 目录包含所有的配置、日志、分支信息、头指针等 +[详细列表](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) + +### 工作目录 (版本库的一部分) + +版本库中的目录和文件,可以看做就是你工作时的目录 + +### 索引(.git 目录) + +索引就是git中的 staging 区. 可以算作是把你的工作目录与Git版本库分割开的一层 +这使得开发者能够更灵活的决定要将要在版本库中添加什么内容 + +### 提交 + +一个 git 提交就是一组更改或者对工作目录操作的快照 +比如你添加了5个文件,删除了2个文件,那么这些变化就会被写入一个提交比如你添加了5个文件,删除了2个文件,那么这些变化就会被写入一个提交中 +而这个提交之后也可以被决定是否推送到另一个版本库中 + +### 分支 + +分支其实就是一个指向你最后一次的提交的指针 +当你提交时,这个指针就会自动指向最新的提交 + +### 头指针 与 头(.git 文件夹的作用) + +头指针是一个指向当前分支的指针,一个版本库只有一个当前活动的头指针 +而头则可以指向版本库中任意一个提交,每个版本库也可以有多个头 + +### 其他形象化解释 + +* [给计算机科学家的解释](http://eagain.net/articles/git-for-computer-scientists/) +* [给设计师的解释](http://hoth.entp.com/output/git_for_designers.html) + + +## 命令 + + +### 初始化 + +创建一个新的git版本库。这个版本库的配置、存储等信息会被保存到.git文件夹中 + +```bash +$ git init +``` + +### 配置 + +更改设置。可以是版本库的设置,也可以是系统的或全局的 + + +```bash +# 输出、设置基本的全局变量 +$ git config --global user.email +$ git config --global user.name + +$ git config --global user.email "MyEmail@Zoho.com" +$ git config --global user.name "My Name" +``` + +[关于git的更多设置](http://git-scm.com/docs/git-config) + +### 帮助 + +git内置了对命令非常详细的解释,可以供我们快速查阅 + +```bash +# 查找可用命令 +$ git help + +# 查找所有可用命令 +$ git help -a + +# 在文档当中查找特定的命令 +$ git help <命令> +$ git help add +$ git help commit +$ git help init +``` + +### 状态 + +显示索引文件(也就是当前工作空间)和当前的头指针指向的提交的不同 + + +```bash +# 显示分支,为跟踪文件,更改和其他不同 +$ git status + +# 查看其他的git status的用法 +$ git help status +``` + +### 添加 + +添加文件到当前工作空间中。如果你不使用 `git add` 将文件添加进去, +那么这些文件也不会添加到之后的提交之中 + +```bash +# 添加一个文件 +$ git add HelloWorld.java + +# 添加一个子目录中的文件 +$ git add /path/to/file/HelloWorld.c + +# 支持正则表达式 +$ git add ./*.java +``` + +### 分支 + +管理分支,可以通过下列命令对分支进行增删改查 + +```bash +# 查看所有的分支和远程分支 +$ git branch -a + +# 创建一个新的分支 +$ git branch myNewBranch + +# 删除一个分支 +$ git branch -d myBranch + +# 重命名分支 +# git branch -m <旧名称> <新名称> +$ git branch -m myBranchName myNewBranchName + +# 编辑分支的介绍 +$ git branch myBranchName --edit-description +``` + +### 检出 + +将当前工作空间更新到索引所标识的或者某一特定的工作空间 + +```bash +# 检出一个版本库,默认将更新到master分支 +$ git checkout +# 检出到一个特定的分支 +$ git checkout branchName +# 新建一个分支,并且切换过去,相当于"git branch <名字>; git checkout <名字>" +$ git checkout -b newBranch +``` + +### clone + +这个命令就是将一个版本库拷贝到另一个目录中,同时也将 +分支都拷贝到新的版本库中。这样就可以在新的版本库中提交到远程分支 + +```bash +# clone learnxinyminutes-docs +$ git clone https://github.com/adambard/learnxinyminutes-docs.git +``` + +### commit + +将当前索引的更改保存为一个新的提交,这个提交包括用户做出的更改与信息 + +```bash +# 提交时附带提交信息 +$ git commit -m "Added multiplyNumbers() function to HelloWorld.c" +``` + +### diff + +显示当前工作空间和提交的不同 + +```bash +# 显示工作目录和索引的不同 +$ git diff + +# 显示索引和最近一次提交的不同 +$ git diff --cached + +# 显示宫缩目录和最近一次提交的不同 +$ git diff HEAD +``` + +### grep + +可以在版本库中快速查找 + +可选配置: + +```bash +# 感谢Travis Jeffery提供的以下用法: +# 在搜索结果中显示行号 +$ git config --global grep.lineNumber true + +# 是搜索结果可读性更好 +$ git config --global alias.g "grep --break --heading --line-number" +``` + +```bash +# 在所有的java中查找variableName +$ git grep 'variableName' -- '*.java' + +# 搜索包含 "arrayListName" 和, "add" 或 "remove" 的所有行 +$ git grep -e 'arrayListName' --and \( -e add -e remove \) +``` + +更多的例子可以查看: +[Git Grep Ninja](http://travisjeffery.com/b/2012/02/search-a-git-repo-like-a-ninja) + +### log + +显示这个版本库的所有提交 + +```bash +# 显示所有提交 +$ git log + +# 显示某几条提交信息 +$ git log -n 10 + +# 仅显示合并提交 +$ git log --merges +``` + +### merge + +合并就是将外部的提交合并到自己的分支中 + +```bash +# 将其他分支合并到当前分支 +$ git merge branchName + +# 在合并时创建一个新的合并后的提交 +$ git merge --no-ff branchName +``` + +### mv + +重命名或移动一个文件 + +```bash +# 重命名 +$ git mv HelloWorld.c HelloNewWorld.c + +# 移动 +$ git mv HelloWorld.c ./new/path/HelloWorld.c + +# 强制重命名或移动 +# 这个文件已经存在,将要覆盖掉 +$ git mv -f myFile existingFile +``` + +### pull + +从远端版本库合并到当前分支 + +```bash +# 从远端origin的master分支更新版本库 +# git pull <远端> <分支> +$ git pull origin master +``` + +### push + +把远端的版本库更新 + +```bash +# 把本地的分支更新到远端origin的master分支上 +# git push <远端> <分支> +# git push 相当于 git push origin master +$ git push origin master +``` + +### rebase (谨慎使用) + +将一个分支上所有的提交历史都应用到另一个分支上 +*不要在一个已经公开的远端分支上使用rebase*. + +```bash +# 将experimentBranch应用到master上面 +# git rebase +$ git rebase master experimentBranch +``` + +[更多阅读](http://git-scm.com/book/en/Git-Branching-Rebasing) + +### reset (谨慎使用) + +将当前的头指针复位到一个特定的状态。这样可以使你撤销merge、pull、commits、add等 +这是个很强大的命令,但是在使用时一定要清楚其所产生的后果 + +```bash +# 使 staging 区域恢复到上次提交时的状态,不改变现在的工作目录 +$ git reset + +# 使 staging 区域恢复到上次提交时的状态,覆盖现在的工作目录 +$ git reset --hard + +# 将当前分支恢复到某次提交,不改变现在的工作目录 +# 在工作目录中所有的改变仍然存在 +$ git reset 31f2bb1 + +# 将当前分支恢复到某次提交,覆盖现在的工作目录 +# 并且删除所有未提交的改变和指定提交之后的所有提交 +$ git reset --hard 31f2bb1 +``` + +### rm + +和add相反,从工作空间中去掉某个文件爱你 + +```bash +# 移除 HelloWorld.c +$ git rm HelloWorld.c + +# 移除子目录中的文件 +$ git rm /pather/to/the/file/HelloWorld.c +``` + +## 更多阅读 + +* [tryGit - 学习Git的有趣方式](http://try.github.io/levels/1/challenges/1) + +* [git-scm - 视频教程](http://git-scm.com/videos) + +* [git-scm - 文档](http://git-scm.com/docs) + +* [Atlassian Git - 教程与工作流程](https://www.atlassian.com/git/) + +* [SalesForce Cheat Sheet](https://na1.salesforce.com/help/doc/en/salesforce_git_developer_cheatsheet.pdf) + +* [GitGuys](http://www.gitguys.com/) diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown new file mode 100755 index 00000000..dd04c8a5 --- /dev/null +++ b/zh-cn/javascript-cn.html.markdown @@ -0,0 +1,415 @@ +--- +language: javascript +author: Adam Brenecki +author_url: http://adam.brenecki.id.au +translator: Chenbo Li +translator_url: http://binarythink.net +--- + +Javascript于1995年由网景公司的Brendan Eich发明。 +最初发明的目的是作为一个简单的网站脚本语言,来作为 +复杂网站应用java的补充。但由于javascript和网站结合度很高 +所以javascript逐渐变得比java在前端更为流行了。 + +JavaScript 不仅仅只可以用于浏览器, 也可用于 Node.js 等后台环境。 + +很欢迎来自您的反馈,您可以通过下列方式联系到我: +[@adambrenecki](https://twitter.com/adambrenecki), 或者 +[adam@brenecki.id.au](mailto:adam@brenecki.id.au). + +```js +// 注释方式和C很像,这是单行注释 +/* 这是多行 + 注释 */ + +// 语句可以以分号结束 +doStuff(); + +// ... 但是分号也可以省略,每当遇到一个新行时,分号会自动插入 +doStuff() + +// 我们在这里会去掉分号,但是否添加最后的分号取决于你个人的习惯 +// 及你所在团队的编程风格 + +/////////////////////////////////// +// 1. 数字、字符串与操作符 + +// Javascript 只有一种数字类型 (即 64位 IEEE 754 双精度浮点). +3 // = 3 +1.5 // = 1.5 + +// 所有基本的算数运算 +1 + 1 // = 2 +8 - 1 // = 7 +10 * 2 // = 20 +35 / 5 // = 7 + +// 包括无法整除的除法 +5 / 2 // = 2.5 + +// 位运算也和其他语言一样。当你对浮点数进行位运算时, +// 浮点数会转换为至多 32 位的无符号整数 +1 << 2 // = 4 + +// 括号可以决定优先级 +(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 + +// ...除非你是用 === +"5" === 5 // = false + +// 你可以用charAt来得到字符串中的字符 +"This is a string".charAt(0) + +// 还有两个特殊的值:null和undefined +null // 用来表示刻意设置成的空值 +undefined // 用来表示还没有设置的值 + +// null, undefined, NaN, 0 和 "" 都是假的(false),其他的都视作逻辑真 +// 注意 0 是逻辑假而 "0"是逻辑真, 尽管 0 == "0". + +/////////////////////////////////// +// 2. 变量、数组和对象 + +// 变量需要用 var 这个关键字声明. Javascript是动态类型语言 +// 所以你在声明时无需指定类型。 赋值需要用 = +var someVar = 5 + +// 如果你在声明时没有加var关键字,你也不会得到错误 +someOtherVar = 10 + +// ...但是此时这个变量就会拥有全局的作用域,而非当前作用域 + +// 没有被赋值的变量都会返回undefined这个值 +var someThirdVar // = undefined + +// 对变量进行数学运算有一些简写法 +someVar += 5 // 等价于 someVar = someVar + 5; someVar 现在是 10 +someVar *= 10 // 现在 someVar 是 100 + +// 自增和自减也有简写 +someVar++ // someVar 是 101 +someVar-- // 回到 100 + +// 数组是任意类型组成的有序列表 +var myArray = ["Hello", 45, true] + +// 数组的元素可以用方括号下标来访问 +// 数组的索引从0开始 +myArray[1] // = 45 + +// javascript中的对象相当于其他语言中的字典或映射:是键-值的集合 +{key1: "Hello", key2: "World"} + +// 键是字符串,但是引号也并非是必须的,如果键本身是合法的js标识符 +// 而值则可以是任意类型的值 +var myObj = {myKey: "myValue", "my other key": 4} + +// 对象的访问可以通过下标 +myObj["my other key"] // = 4 + +// ... 或者也可以用 . ,如果属性是合法的标识符 +myObj.myKey // = "myValue" + +// 对象是可变的,键和值也可以被更改或增加 +myObj.myThirdKey = true + +// 如果你想要访问一个还没有被定义的属性,那么会返回undefined +myObj.myFourthKey // = undefined + +/////////////////////////////////// +// 3. 逻辑与控制结构 + +// if语句和其他语言中一样 +var count = 1 +if (count == 3){ + // count 是 3 时执行 +} else if (count == 4) { + // count 是 4 时执行 +} else { + // 其他情况下执行 +} + +// while循环 +while (true) { + // 无限循环 +} + +// Do-while 和 While 循环很像 ,但前者会至少执行一次 +var input +do { + input = getInput() +} while (!isValid(input)) + +// for循环和C、Java中的一样 +// 初始化; 继续执行的条件; 遍历后执行. +for (var i = 0; i < 5; i++){ + // 遍历5次 +} + +// && 是逻辑与, || 是逻辑或 +if (house.size == "big" && house.colour == "blue"){ + house.contains = "bear" +} +if (colour == "red" || colour == "blue"){ + // colour是red或者blue时执行 +} + +// && 和 || 是“短路”语句,在初始化值时会变得有用 +var name = otherName || "default" + +/////////////////////////////////// +// 4. 函数、作用域、闭包 + +// JavaScript 函数由function关键字定义 +function myFunction(thing){ + return thing.toUpperCase() +} +myFunction("foo") // = "FOO" + +// 函数也可以是匿名的: +function(thing){ + return thing.toLowerCase() +} +// (我们无法调用此函数,因为我们不知道这个函数的名字) + +// javascript中的函数也是对象,所以函数也能够赋给一个变量,并且被传递 +// 比如一个事件处理函数: +function myFunction(){ + // this code will be called in 5 seconds' time +} +setTimeout(myFunction, 5000) + +// 你甚至可以直接把一个函数写到另一个函数的参数中 + +setTimeout(function myFunction(){ + // 5秒之后会执行这里的代码 +}, 5000) + +// JavaScript 仅有函数作用于,而其他的语句则没有作用域 +if (true){ + var i = 5 +} +i // = 5 - 并非我们在其他语言中所得到的undefined + +// 这就导致了人们经常用一种叫做“即使执行匿名函数”的模式 +// 这样可以避免一些临时变量扩散到外边去 +function(){ + var temporary = 5 + // 我们可以访问一个全局对象来访问全局作用域 + // 在浏览器中是 'window' 这个对象。 + // 在Node.js中这个对象的名字可能会不同。 + window.permanent = 10 + // 或者,我们也可以把var去掉就行了 + permanent2 = 15 +}() +temporary // 抛出引用异常 +permanent // = 10 +permanent2 // = 15 + +// javascript最强大的功能之一就是闭包 +// 如果一个函数在另一个函数中定义,那么这个函数就拥有外部函数的所有访问权 +function sayHelloInFiveSeconds(name){ + var prompt = "Hello, " + name + "!" + function inner(){ + alert(prompt) + } + setTimeout(inner, 5000) + // setTimeout 是异步的,所以这个函数会马上终止不会等待。 + // 然而,在5秒结束后,inner函数仍然会弹出prompt信息。 +} +sayHelloInFiveSeconds("Adam") // 会在5秒后弹出 "Hello, Adam!" + +/////////////////////////////////// +// 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!" + +// 但这个函数访问的其实是其运行时环境,而非定义时环境 +// 所以如果函数所在的环境不在当前对象的环境中运行时,就运行不成功了 +var myFunc = myObj.myFunc +myFunc() // = undefined + +// 相应的,一个函数也可以被指定为一个对象的方法,并且用过this可以访问 +// 这个对象的成员,即使在定义时并没有绑定任何值 +var myOtherFunc = function(){ + return this.myString.toUpperCase() +} +myObj.myOtherFunc = myOtherFunc +myObj.myOtherFunc() // = "HELLO WORLD!" + +// 当你通过new关键字调用一个函数时,就会生成一个对象 +// 而对象的成员需要通过this来定义。 +// 这样的函数就叫做构造函数 + +var MyConstructor = function(){ + this.myNumber = 5 +} +myNewObj = new MyConstructor() // = {myNumber: 5} +myNewObj.myNumber // = 5 + +// 每一个js对象都有一个原型,当你要访问一个没有定义过的成员时, +// 解释器就回去找这个对象的原型 + +// 有一些JS实现会让你通过一个对象的__proto__方法访问这个原型。 +// 这虽然对理解这个对象很有用,但是这并不是标准的一部分 +// 我们之后会通过标准方式来访问原型。 +var myObj = { + myString: "Hello world!", +} +var myPrototype = { + meaningOfLife: 42, + myFunc: function(){ + return this.myString.toLowerCase() + } +} +myObj.__proto__ = myPrototype +myObj.meaningOfLife // = 42 + +// This works for functions, too. +myObj.myFunc() // = "hello world!" + +// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型。 +myPrototype.__proto__ = { + myBoolean: true +} +myObj.myBoolean // = true + +// 这其中并没有对象的拷贝。每个对象的原型实际上是持有原型对象的引用 +// 这说明当我们改变对象的原型时,会影响到其他以这个原型为原型的对象 +myPrototype.meaningOfLife = 43 +myObj.meaningOfLife // = 43 + +// 我们知道 __proto__ 并非标准规定,实际上也没有办法更改已经指定好的原型。 +// 但是,我们有两种方式可以为新的对象指定原型。 + +// 第一种方式是 Object.create,这个方法是在最近才被添加到Js中的 +// 也因此并不是所有的JS实现都有这个放啊 +var myObj = Object.create(myPrototype) +myObj.meaningOfLife // = 43 + +// 第二种方式可以在任意版本中使用,不过需要通过构造函数。 +// 构造函数有一个属性prototype。但是这 *不是* 构造函数本身的函数 +// 而是通过构造函数和new关键字生成新对象时自动生成的。 +myConstructor.prototype = { + getMyNumber: function(){ + return this.myNumber + } +} +var myNewObj2 = new myConstructor() +myNewObj2.getMyNumber() // = 5 + +// 字符串和数字等内置类型也有通过构造函数来创建的包装类型 +var myNumber = 12 +var myNumberObj = new Number(12) +myNumber == myNumberObj // = true + +// 但是它们并非严格等价 +typeof(myNumber) // = 'number' +typeof(myNumberObj) // = 'object' +myNumber === myNumberObj // = false +if (0){ + // 这段代码不会执行,因为0代表假 +} +if (Number(0)){ + // 这段代码会执行,因为Number(0)代表真 +} + +// 但是,包装类型和内置类型共享一个原型 +// 这样你就可以给内置类型也增加一些功能 +String.prototype.firstCharacter = function(){ + return this.charAt(0) +} +"abc".firstCharacter() // = "a" + +// 这个技巧可以用来用老版本的javascript子集来是实现新版本js的功能 +// 这样就可以在老的浏览器中使用新功能了。 + +// 比如,我们知道Object.create并没有在所有的版本中都实现 +// 但是我们仍然可以通过这个技巧来使用 +if (Object.create === undefined){ // 如果存在则不覆盖 + Object.create = function(proto){ + // 用正确的原型来创建一个临时构造函数 + var Constructor = function(){} + Constructor.prototype = proto + // 之后用它来创建一个新的对象 + return new Constructor() + } +} +``` + +## 更多阅读 + +[Mozilla 开发者 +网络](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 提供了很好的 +Javascript文档,并且由于是wiki,所以你也可以自行编辑来分享你的知识。 +wiki, so as you learn more you can help others out by sharing your own +knowledge. + +MDN的 [A re-introduction to +JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) +覆盖了这里提到的绝大多数话题,大多数只是Javascript这个语言本身。 +如果你想了解Javascript是如何在网页中被应用的,那么可以查看 +[Document Object +Model](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core) + +[Javascript Garden](http://bonsaiden.github.io/JavaScript-Garden/) 是一个深入 +讲解所有Javascript反直觉部分的一本书 + +除了这篇文章的直接贡献者之外,这篇文章也参考了这个网站上 +Louie Dinh 的 Python 教程,以及 Mozilla开发者网络上的[JS +Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) diff --git a/zh-cn/javascript.html.markdown b/zh-cn/javascript.html.markdown deleted file mode 100755 index dd04c8a5..00000000 --- a/zh-cn/javascript.html.markdown +++ /dev/null @@ -1,415 +0,0 @@ ---- -language: javascript -author: Adam Brenecki -author_url: http://adam.brenecki.id.au -translator: Chenbo Li -translator_url: http://binarythink.net ---- - -Javascript于1995年由网景公司的Brendan Eich发明。 -最初发明的目的是作为一个简单的网站脚本语言,来作为 -复杂网站应用java的补充。但由于javascript和网站结合度很高 -所以javascript逐渐变得比java在前端更为流行了。 - -JavaScript 不仅仅只可以用于浏览器, 也可用于 Node.js 等后台环境。 - -很欢迎来自您的反馈,您可以通过下列方式联系到我: -[@adambrenecki](https://twitter.com/adambrenecki), 或者 -[adam@brenecki.id.au](mailto:adam@brenecki.id.au). - -```js -// 注释方式和C很像,这是单行注释 -/* 这是多行 - 注释 */ - -// 语句可以以分号结束 -doStuff(); - -// ... 但是分号也可以省略,每当遇到一个新行时,分号会自动插入 -doStuff() - -// 我们在这里会去掉分号,但是否添加最后的分号取决于你个人的习惯 -// 及你所在团队的编程风格 - -/////////////////////////////////// -// 1. 数字、字符串与操作符 - -// Javascript 只有一种数字类型 (即 64位 IEEE 754 双精度浮点). -3 // = 3 -1.5 // = 1.5 - -// 所有基本的算数运算 -1 + 1 // = 2 -8 - 1 // = 7 -10 * 2 // = 20 -35 / 5 // = 7 - -// 包括无法整除的除法 -5 / 2 // = 2.5 - -// 位运算也和其他语言一样。当你对浮点数进行位运算时, -// 浮点数会转换为至多 32 位的无符号整数 -1 << 2 // = 4 - -// 括号可以决定优先级 -(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 - -// ...除非你是用 === -"5" === 5 // = false - -// 你可以用charAt来得到字符串中的字符 -"This is a string".charAt(0) - -// 还有两个特殊的值:null和undefined -null // 用来表示刻意设置成的空值 -undefined // 用来表示还没有设置的值 - -// null, undefined, NaN, 0 和 "" 都是假的(false),其他的都视作逻辑真 -// 注意 0 是逻辑假而 "0"是逻辑真, 尽管 0 == "0". - -/////////////////////////////////// -// 2. 变量、数组和对象 - -// 变量需要用 var 这个关键字声明. Javascript是动态类型语言 -// 所以你在声明时无需指定类型。 赋值需要用 = -var someVar = 5 - -// 如果你在声明时没有加var关键字,你也不会得到错误 -someOtherVar = 10 - -// ...但是此时这个变量就会拥有全局的作用域,而非当前作用域 - -// 没有被赋值的变量都会返回undefined这个值 -var someThirdVar // = undefined - -// 对变量进行数学运算有一些简写法 -someVar += 5 // 等价于 someVar = someVar + 5; someVar 现在是 10 -someVar *= 10 // 现在 someVar 是 100 - -// 自增和自减也有简写 -someVar++ // someVar 是 101 -someVar-- // 回到 100 - -// 数组是任意类型组成的有序列表 -var myArray = ["Hello", 45, true] - -// 数组的元素可以用方括号下标来访问 -// 数组的索引从0开始 -myArray[1] // = 45 - -// javascript中的对象相当于其他语言中的字典或映射:是键-值的集合 -{key1: "Hello", key2: "World"} - -// 键是字符串,但是引号也并非是必须的,如果键本身是合法的js标识符 -// 而值则可以是任意类型的值 -var myObj = {myKey: "myValue", "my other key": 4} - -// 对象的访问可以通过下标 -myObj["my other key"] // = 4 - -// ... 或者也可以用 . ,如果属性是合法的标识符 -myObj.myKey // = "myValue" - -// 对象是可变的,键和值也可以被更改或增加 -myObj.myThirdKey = true - -// 如果你想要访问一个还没有被定义的属性,那么会返回undefined -myObj.myFourthKey // = undefined - -/////////////////////////////////// -// 3. 逻辑与控制结构 - -// if语句和其他语言中一样 -var count = 1 -if (count == 3){ - // count 是 3 时执行 -} else if (count == 4) { - // count 是 4 时执行 -} else { - // 其他情况下执行 -} - -// while循环 -while (true) { - // 无限循环 -} - -// Do-while 和 While 循环很像 ,但前者会至少执行一次 -var input -do { - input = getInput() -} while (!isValid(input)) - -// for循环和C、Java中的一样 -// 初始化; 继续执行的条件; 遍历后执行. -for (var i = 0; i < 5; i++){ - // 遍历5次 -} - -// && 是逻辑与, || 是逻辑或 -if (house.size == "big" && house.colour == "blue"){ - house.contains = "bear" -} -if (colour == "red" || colour == "blue"){ - // colour是red或者blue时执行 -} - -// && 和 || 是“短路”语句,在初始化值时会变得有用 -var name = otherName || "default" - -/////////////////////////////////// -// 4. 函数、作用域、闭包 - -// JavaScript 函数由function关键字定义 -function myFunction(thing){ - return thing.toUpperCase() -} -myFunction("foo") // = "FOO" - -// 函数也可以是匿名的: -function(thing){ - return thing.toLowerCase() -} -// (我们无法调用此函数,因为我们不知道这个函数的名字) - -// javascript中的函数也是对象,所以函数也能够赋给一个变量,并且被传递 -// 比如一个事件处理函数: -function myFunction(){ - // this code will be called in 5 seconds' time -} -setTimeout(myFunction, 5000) - -// 你甚至可以直接把一个函数写到另一个函数的参数中 - -setTimeout(function myFunction(){ - // 5秒之后会执行这里的代码 -}, 5000) - -// JavaScript 仅有函数作用于,而其他的语句则没有作用域 -if (true){ - var i = 5 -} -i // = 5 - 并非我们在其他语言中所得到的undefined - -// 这就导致了人们经常用一种叫做“即使执行匿名函数”的模式 -// 这样可以避免一些临时变量扩散到外边去 -function(){ - var temporary = 5 - // 我们可以访问一个全局对象来访问全局作用域 - // 在浏览器中是 'window' 这个对象。 - // 在Node.js中这个对象的名字可能会不同。 - window.permanent = 10 - // 或者,我们也可以把var去掉就行了 - permanent2 = 15 -}() -temporary // 抛出引用异常 -permanent // = 10 -permanent2 // = 15 - -// javascript最强大的功能之一就是闭包 -// 如果一个函数在另一个函数中定义,那么这个函数就拥有外部函数的所有访问权 -function sayHelloInFiveSeconds(name){ - var prompt = "Hello, " + name + "!" - function inner(){ - alert(prompt) - } - setTimeout(inner, 5000) - // setTimeout 是异步的,所以这个函数会马上终止不会等待。 - // 然而,在5秒结束后,inner函数仍然会弹出prompt信息。 -} -sayHelloInFiveSeconds("Adam") // 会在5秒后弹出 "Hello, Adam!" - -/////////////////////////////////// -// 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!" - -// 但这个函数访问的其实是其运行时环境,而非定义时环境 -// 所以如果函数所在的环境不在当前对象的环境中运行时,就运行不成功了 -var myFunc = myObj.myFunc -myFunc() // = undefined - -// 相应的,一个函数也可以被指定为一个对象的方法,并且用过this可以访问 -// 这个对象的成员,即使在定义时并没有绑定任何值 -var myOtherFunc = function(){ - return this.myString.toUpperCase() -} -myObj.myOtherFunc = myOtherFunc -myObj.myOtherFunc() // = "HELLO WORLD!" - -// 当你通过new关键字调用一个函数时,就会生成一个对象 -// 而对象的成员需要通过this来定义。 -// 这样的函数就叫做构造函数 - -var MyConstructor = function(){ - this.myNumber = 5 -} -myNewObj = new MyConstructor() // = {myNumber: 5} -myNewObj.myNumber // = 5 - -// 每一个js对象都有一个原型,当你要访问一个没有定义过的成员时, -// 解释器就回去找这个对象的原型 - -// 有一些JS实现会让你通过一个对象的__proto__方法访问这个原型。 -// 这虽然对理解这个对象很有用,但是这并不是标准的一部分 -// 我们之后会通过标准方式来访问原型。 -var myObj = { - myString: "Hello world!", -} -var myPrototype = { - meaningOfLife: 42, - myFunc: function(){ - return this.myString.toLowerCase() - } -} -myObj.__proto__ = myPrototype -myObj.meaningOfLife // = 42 - -// This works for functions, too. -myObj.myFunc() // = "hello world!" - -// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型。 -myPrototype.__proto__ = { - myBoolean: true -} -myObj.myBoolean // = true - -// 这其中并没有对象的拷贝。每个对象的原型实际上是持有原型对象的引用 -// 这说明当我们改变对象的原型时,会影响到其他以这个原型为原型的对象 -myPrototype.meaningOfLife = 43 -myObj.meaningOfLife // = 43 - -// 我们知道 __proto__ 并非标准规定,实际上也没有办法更改已经指定好的原型。 -// 但是,我们有两种方式可以为新的对象指定原型。 - -// 第一种方式是 Object.create,这个方法是在最近才被添加到Js中的 -// 也因此并不是所有的JS实现都有这个放啊 -var myObj = Object.create(myPrototype) -myObj.meaningOfLife // = 43 - -// 第二种方式可以在任意版本中使用,不过需要通过构造函数。 -// 构造函数有一个属性prototype。但是这 *不是* 构造函数本身的函数 -// 而是通过构造函数和new关键字生成新对象时自动生成的。 -myConstructor.prototype = { - getMyNumber: function(){ - return this.myNumber - } -} -var myNewObj2 = new myConstructor() -myNewObj2.getMyNumber() // = 5 - -// 字符串和数字等内置类型也有通过构造函数来创建的包装类型 -var myNumber = 12 -var myNumberObj = new Number(12) -myNumber == myNumberObj // = true - -// 但是它们并非严格等价 -typeof(myNumber) // = 'number' -typeof(myNumberObj) // = 'object' -myNumber === myNumberObj // = false -if (0){ - // 这段代码不会执行,因为0代表假 -} -if (Number(0)){ - // 这段代码会执行,因为Number(0)代表真 -} - -// 但是,包装类型和内置类型共享一个原型 -// 这样你就可以给内置类型也增加一些功能 -String.prototype.firstCharacter = function(){ - return this.charAt(0) -} -"abc".firstCharacter() // = "a" - -// 这个技巧可以用来用老版本的javascript子集来是实现新版本js的功能 -// 这样就可以在老的浏览器中使用新功能了。 - -// 比如,我们知道Object.create并没有在所有的版本中都实现 -// 但是我们仍然可以通过这个技巧来使用 -if (Object.create === undefined){ // 如果存在则不覆盖 - Object.create = function(proto){ - // 用正确的原型来创建一个临时构造函数 - var Constructor = function(){} - Constructor.prototype = proto - // 之后用它来创建一个新的对象 - return new Constructor() - } -} -``` - -## 更多阅读 - -[Mozilla 开发者 -网络](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 提供了很好的 -Javascript文档,并且由于是wiki,所以你也可以自行编辑来分享你的知识。 -wiki, so as you learn more you can help others out by sharing your own -knowledge. - -MDN的 [A re-introduction to -JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) -覆盖了这里提到的绝大多数话题,大多数只是Javascript这个语言本身。 -如果你想了解Javascript是如何在网页中被应用的,那么可以查看 -[Document Object -Model](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core) - -[Javascript Garden](http://bonsaiden.github.io/JavaScript-Garden/) 是一个深入 -讲解所有Javascript反直觉部分的一本书 - -除了这篇文章的直接贡献者之外,这篇文章也参考了这个网站上 -Louie Dinh 的 Python 教程,以及 Mozilla开发者网络上的[JS -Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) -- cgit v1.2.3 From 981fe303f323c91bad1ac23bdd4c49575414c8ec Mon Sep 17 00:00:00 2001 From: Chenbo Li Date: Sat, 3 Aug 2013 14:53:27 +0800 Subject: fix a typo --- zh-cn/git-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown index 7aab8986..8c24f0b8 100755 --- a/zh-cn/git-cn.html.markdown +++ b/zh-cn/git-cn.html.markdown @@ -120,7 +120,7 @@ $ git help $ git help -a # 在文档当中查找特定的命令 -$ git help <命令> +# git help <命令> $ git help add $ git help commit $ git help init -- cgit v1.2.3 From cfff5122a3e6b85c34bb66e7efe8ba3b96562253 Mon Sep 17 00:00:00 2001 From: lpy Date: Sat, 3 Aug 2013 15:16:28 +0800 Subject: Add Haskell zh-cn translation --- zh-cn/haskell-cn.html.markdown | 407 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100755 zh-cn/haskell-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown new file mode 100755 index 00000000..cb0de467 --- /dev/null +++ b/zh-cn/haskell-cn.html.markdown @@ -0,0 +1,407 @@ +--- +language: haskell +filename: learn-haskell.hs +contributors: + - ["Adit Bhargava", "http://adit.io"] +translators: + - ["Peiyong Lin", ""] +lang: zh-cn +--- + +Haskell 被设计成一种实用的纯函数式编程语言。它因为 monads 及其类型系统而出名,但是我回归到它本身因为。Haskell 使得编程对于我而言是一种真正的快乐。 + +```haskell +-- 单行注释以两个破折号开头 +{- 多行注释像这样 + 被一个闭合的块包围 +-} + +---------------------------------------------------- +-- 1. 简单的数据类型和操作符 +---------------------------------------------------- + +-- 你有数字 +3 -- 3 +-- 数学计算就像你所期待的那样 +1 + 1 -- 2 +8 - 1 -- 7 +10 * 2 -- 20 +35 / 5 -- 7.0 + +-- 默认除法不是整除 +35 / 4 -- 8.75 + +-- 整除 +35 `div` 4 -- 8 + +-- 布尔值也简单 +True +False + +-- 布尔操作 +not True -- False +not False -- True +1 == 1 -- True +1 /= 1 -- False +1 < 10 -- True + +-- 在上述的例子中,`not` 是一个接受一个值的函数。 +-- Haskell 不需要括号来调用函数。。。所有的参数 +-- 都只是在函数名之后列出来。因此,通常的函数调用模式是: +-- func arg1 arg2 arg3... +-- 查看关于函数的章节以获得如何写你自己的函数的相关信息。 + +-- 字符串和字符 +"This is a string." +'a' -- 字符 +'对于字符串你不能使用单引号。' -- 错误! + +-- 连结字符串 +"Hello " ++ "world!" -- "Hello world!" + +-- 一个字符串是一系列字符 +"This is a string" !! 0 -- 'T' + + +---------------------------------------------------- +-- 列表和元组 +---------------------------------------------------- + +-- 一个列表中的每一个元素都必须是相同的类型 +-- 下面两个列表一样 +[1, 2, 3, 4, 5] +[1..5] + +-- 在 Haskell 你可以拥有含有无限元素的列表 +[1..] -- 一个含有所有自然数的列表 + +-- 因为 Haskell 有“懒惰计算”,所以无限元素的列表可以正常运作。这意味着 +-- Haskell 可以只在它需要的时候计算。所以你可以请求 +-- 列表中的第1000个元素,Haskell 会返回给你 + +[1..] !! 999 -- 1000 + +-- Haskell 计算了列表中 1 - 1000 个元素。。。但是 +-- 这个无限元素的列表中剩下的元素还不存在! Haskell 不会 +-- 真正地计算它们知道它需要。 + +- 连接两个列表 +[1..5] ++ [6..10] + +-- 往列表头增加元素 +0:[1..5] -- [0, 1, 2, 3, 4, 5] + +-- 列表中的下标 +[0..] !! 5 -- 5 + +-- 更多列表操作 +head [1..5] -- 1 +tail [1..5] -- [2, 3, 4, 5] +init [1..5] -- [1, 2, 3, 4] +last [1..5] -- 5 + +-- 列表推导 +[x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10] + +-- 附带条件 +[x*2 | x <-[1..5], x*2 > 4] -- [6, 8, 10] + +-- 元组中的每一个元素可以是不同类型的,但是一个元组 +-- 的长度是固定的 +-- 一个元组 +("haskell", 1) + +-- 获取元组中的元素 +fst ("haskell", 1) -- "haskell" +snd ("haskell", 1) -- 1 + +---------------------------------------------------- +-- 3. 函数 +---------------------------------------------------- +-- 一个接受两个变量的简单函数 +add a b = a + b + +-- 注意,如果你使用 ghci (Hakell 解释器) +-- 你将需要使用 `let`,也就是 +-- let add a b = a + b + +-- 使用函数 +add 1 2 -- 3 + +-- 你也可以把函数放置在两个参数之间 +-- 附带倒引号: +1 `add` 2 -- 3 + +-- 你也可以定义不带字符的函数!这使得 +-- 你定义自己的操作符!这里有一个操作符 +-- 来做整除 +(//) a b = a `div` b +35 // 4 -- 8 + +-- 守卫:一个简单的方法在函数里做分支 +fib x + | x < 2 = x + | otherwise = fib (x - 1) + fib (x - 2) + +-- 模式匹配是类型的。这里有三种不同的 fib +-- 定义。Haskell 将自动调用第一个 +-- 匹配值的模式的函数。 +fib 1 = 1 +fib 2 = 2 +fib x = fib (x - 1) + fib (x - 2) + +-- 元组的模式匹配: +foo (x, y) = (x + 1, y + 2) + +-- 列表的模式匹配。这里 `x` 是列表中第一个元素, +-- 并且 `xs` 是列表剩余的部分。我们可以写 +-- 自己的 map 函数: +myMap func [] = [] +myMap func (x:xs) = func x:(myMap func xs) + +-- 编写出来的匿名函数带有一个反斜杠,后面跟着 +-- 所有的参数。 +myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7] + +-- 使用 fold (在一些语言称为`inject`)随着一个匿名的 +-- 函数。foldl1 意味着左折叠(fold left), 并且使用列表中第一个值 +-- 作为累加器的初始化值。 +foldl1 (\acc x -> acc + x) [1..5] -- 15 + +---------------------------------------------------- +-- 4. 更多的函数 +---------------------------------------------------- + +-- 柯里化(currying):如果你不传递函数中所有的参数, +-- 它就变成“柯里化的”。这意味着,它返回一个接受剩余参数的函数。 + +add a b = a + b +foo = add 10 -- foo 现在是一个接受一个数并对其加 10 的函数 +foo 5 -- 15 + +-- 另外一种方式去做同样的事 +foo = (+10) +foo 5 -- 15 + +-- 函数组合 +-- (.) 函数把其它函数链接到一起 +-- 举个列子,这里 foo 是一个接受一个值的函数。它对接受的值加 10, +-- 并对结果乘以 5,之后返回最后的值。 +foo = (*5) . (+10) + +-- (5 + 10) * 5 = 75 +foo 5 -- 75 + +-- 修复优先级 +-- Haskell 有另外一个函数称为 `$`。它改变优先级 +-- 使得其左侧的每一个操作先计算然后应用到 +-- 右侧的每一个操作。你可以使用 `.` 和 `$` 来除去很多 +-- 括号: + +-- before +(even (fib 7)) -- true + +-- after +even . fib $ 7 -- true + +---------------------------------------------------- +-- 5. 类型签名 +---------------------------------------------------- + +-- Haskell 有一个非常强壮的类型系统,一切都有一个类型签名。 + +-- 一些基本的类型: +5 :: Integer +"hello" :: String +True :: Bool + +-- 函数也有类型。 +-- `not` 接受一个布尔型返回一个布尔型: +-- not :: Bool -> Bool + +-- 这是接受两个参数的函数: +-- add :: Integer -> Integer -> Integer + +-- 当你定义一个值,在其上写明它的类型是一个好实践: +double :: Integer -> Integer +double x = x * 2 + +---------------------------------------------------- +-- 6. 控制流和 If 语句 +---------------------------------------------------- + +-- if 语句 +haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome" + +-- if 语句也可以有多行,缩进是很重要的 +haskell = if 1 == 1 + then "awesome" + else "awful" + +-- case 语句:这里是你可以怎样去解析命令行参数 +case args of + "help" -> printHelp + "start" -> startProgram + _ -> putStrLn "bad args" + +-- Haskell 没有循环因为它使用递归取代之。 +-- map 应用一个函数到一个数组中的每一个元素 + +map (*2) [1..5] -- [2, 4, 6, 8, 10] + +-- 你可以使用 map 来编写 for 函数 +for array func = map func array + +-- 然后使用它 +for [0..5] $ \i -> show i + +-- 我们也可以像这样写: +for [0..5] show + +-- 你可以使用 foldl 或者 foldr 来分解列表 +-- foldl +foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43 + +-- 这和下面是一样的 +(2 * (2 * (2 * 4 + 1) + 2) + 3) + +-- foldl 是左手边的,foldr 是右手边的- +foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 + +-- 这和下面是一样的 +(2 * 3 + (2 * 2 + (2 * 1 + 4))) + +---------------------------------------------------- +-- 7. 数据类型 +---------------------------------------------------- + +-- 这里展示在 Haskell 中你怎样编写自己的数据类型 + +data Color = Red | Blue | Green + +-- 现在你可以在函数中使用它: + + +say :: Color -> String +say Red = "You are Red!" +say Blue = "You are Blue!" +say Green = "You are Green!" + +-- 你的数据类型也可以有参数: + +data Maybe a = Nothing | Just a + +-- 类型 Maybe 的所有 +Just "hello" -- of type `Maybe String` +Just 1 -- of type `Maybe Int` +Nothing -- of type `Maybe a` for any `a` + +---------------------------------------------------- +-- 8. Haskell IO +---------------------------------------------------- + +-- 虽然在没有解释 monads 的情况下 IO不能被完全地解释, +-- 着手解释到位并不难。 + +-- 当一个 Haskell 程序被执行,函数 `main` 就被调用。 +-- 它必须返回一个类型 `IO ()` 的值。举个列子: + +main :: IO () +main = putStrLn $ "Hello, sky! " ++ (say Blue) +-- putStrLn has type String -> IO () + +-- 如果你能实现你的程序依照函数从 String 到 String,那样编写 IO 是最简单的。 +-- 函数 +-- interact :: (String -> String) -> IO () +-- 输入一些文本,在其上运行一个函数,并打印出输出 + +countLines :: String -> String +countLines = show . length . lines + +main' = interact countLines + +-- 你可以考虑一个 `IO()` 类型的值,当做一系列计算机所完成的动作的代表, +-- 就像一个以命令式语言编写的计算机程序。我们可以使用 `do` 符号来把动作链接到一起。 +-- 举个列子: + +sayHello :: IO () +sayHello = do + putStrLn "What is your name?" + name <- getLine -- this gets a line and gives it the name "input" + putStrLn $ "Hello, " ++ name + +-- 练习:编写只读取一行输入的 `interact` + +-- 然而,`sayHello` 中的代码将不会被执行。唯一被执行的动作是 `main` 的值。 +-- 为了运行 `sayHello`,注释上面 `main` 的定义,并代替它: +-- main = sayHello + +-- 让我们来更好地理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是: +-- getLine :: IO String +-- 你可以考虑一个 `IO a` 类型的值,代表一个当被执行的时候 +-- 将产生一个 `a` 类型的值的计算机程序(除了它所做的任何事之外)。我们可以保存和重用这个值通过 `<-`。 +-- 我们也可以写自己的 `IO String` 类型的动作: + +action :: IO String +action = do + putStrLn "This is a line. Duh" + input1 <- getLine + input2 <- getLine + -- The type of the `do` statement is that of its last line. + -- `return` is not a keyword, but merely a function + return (input1 ++ "\n" ++ input2) -- return :: String -> IO String + +-- 我们可以使用这个动作就像我们使用 `getLine`: + +main'' = do + putStrLn "I will echo two lines!" + result <- action + putStrLn result + putStrLn "This was all, folks!" + +-- `IO` 类型是一个 "monad" 的例子。Haskell 使用一个 monad 来做 IO的方式允许它是一门纯函数式语言。 +-- 任何与外界交互的函数(也就是 IO) 都在它的类型签名处做一个 `IO` 标志 +-- 着让我们推出 什么样的函数是“纯洁的”(不与外界交互,不修改状态) 和 什么样的函数不是 “纯洁的” + +-- 这是一个强有力的特征,因为并发地运行纯函数是简单的;因此,Haskell 中并发是非常简单的。 + + +---------------------------------------------------- +-- 9. The Haskell REPL +---------------------------------------------------- + +-- 键入 `ghci` 开始 repl。 +-- 现在你可以键入 Haskell 代码。 +-- 任何新值都需要通过 `let` 来创建: + +let foo = 5 + +-- 你可以查看任何值的类型,通过命令 `:t`: + +>:t foo +foo :: Integer + +-- 你也可以运行任何 `IO ()`类型的动作 + +> sayHello +What is your name? +Friend! +Hello, Friend! + +``` + +还有很多关于 Haskell,包括类型类和 monads。这些是使得编码 Haskell 是如此有趣的主意。我用一个最后的 Haskell 例子来结束:一个 Haskell 的快排实现: + +```haskell +qsort [] = [] +qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater + where lesser = filter (< p) xs + greater = filter (>= p) xs +``` + +安装 Haskell 是简单的。你可以从[这里](http://www.haskell.org/platform/)获得它。 + +你可以从优秀的 +[Learn you a Haskell](http://learnyouahaskell.com/) 或者 +[Real World Haskell](http://book.realworldhaskell.org/) +找到优雅不少的入门介绍。 \ No newline at end of file -- cgit v1.2.3 From 521940d7080fba907fafc1bb01f96e1de2e79de5 Mon Sep 17 00:00:00 2001 From: Chenbo Li Date: Sat, 3 Aug 2013 22:36:38 +0800 Subject: add python-cn --- zh-cn/python-cn.html.markdown | 475 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100755 zh-cn/python-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown new file mode 100755 index 00000000..259e4ed8 --- /dev/null +++ b/zh-cn/python-cn.html.markdown @@ -0,0 +1,475 @@ +--- +language: python +contributors: + - ["Louie Dinh", "http://ldinh.ca"] +translators: + - ["Chenbo Li", "http://binarythink.net"] +filename: learnpython.py +lang: zh-cn +--- + +Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语言之一 +我喜爱python是因为它有极为清晰的语法,甚至可以说,它就是可以执行的伪代码 + +很欢迎来自您的反馈,你可以在[@louiedinh](http://twitter.com/louiedinh) 和 louiedinh [at] [google's email service] 这里找到我 + +注意: 这篇文章针对的版本是Python 2.7,但大多也可使用于其他Python 2的版本 +如果是Python 3,请在网络上寻找其他教程 + +```python +# 单行注释 +""" 多行字符串可以用 + 三个引号包裹,不过这也可以被当做 + 多行注释 +""" + +#################################################### +## 1. 原始数据类型和操作符 +#################################################### + +# 数字类型 +3 #=> 3 + +# 简单的算数 +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# 整数的除法会自动取整 +5 / 2 #=> 2 + +# 要做精确的除法,我们需要引入浮点数 +2.0 # 浮点数 +11.0 / 4.0 #=> 2.75 好多了 + +# 括号具有最高优先级 +(1 + 3) * 2 #=> 8 + +# 布尔值也是原始数据类型 +True +False + +# 用not来取非 +not True #=> False +not False #=> True + +# 相等 +1 == 1 #=> True +2 == 1 #=> False + +# 不等 +1 != 1 #=> False +2 != 1 #=> True + +# 更多的比较操作符 +1 < 10 #=> True +1 > 10 #=> False +2 <= 2 #=> True +2 >= 2 #=> True + +# 比较运算可以连起来写! +1 < 2 < 3 #=> True +2 < 3 < 2 #=> False + +# 字符串通过"或'括起来 +"This is a string." +'This is also a string.' + +# 字符串通过加号拼接 +"Hello " + "world!" #=> "Hello world!" + +# 字符串可以被视为字符的列表 +"This is a string"[0] #=> 'T' + +# % 可以用来格式化字符串 +"%s can be %s" % ("strings", "interpolated") + +# 也可以用format方法来格式化字符串 +# 推荐使用这个方法 +"{0} can be {1}".format("strings", "formatted") +# 也可以用变量名代替数字 +"{name} wants to eat {food}".format(name="Bob", food="lasagna") + +# None 是对象 +None #=> None + +# 不要用相等 `==` 符号来和None进行比较 +# 要用 `is` +"etc" is None #=> False +None is None #=> True + +# 'is' 可以用来比较对象的相等性 +# 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少 + +# None, 0, 和空字符串都被算作False +# 其他的均为True +0 == False #=> True +"" == False #=> True + + +#################################################### +## 2. 变量和集合 +#################################################### + +# 很方便的输出 +print "I'm Python. Nice to meet you!" + + +# 给变量赋值前不需要事先生命 +some_var = 5 # 规范用小写字母和下划线来做为变量名 +some_var #=> 5 + +# 访问之前为赋值的变量会抛出异常 +# 查看控制流程一节来了解异常处理 +some_other_var # 抛出命名异常 + +# if语句可以作为表达式来使用 +"yahoo!" if 3 > 2 else 2 #=> "yahoo!" + +# 列表用来保存序列 +li = [] +# 可以直接初始化列表 +other_li = [4, 5, 6] + +# 在列表末尾添加元素 +li.append(1) #li 现在是 [1] +li.append(2) #li 现在是 [1, 2] +li.append(4) #li 现在是 [1, 2, 4] +li.append(3) #li 现在是 [1, 2, 4, 3] +# 移除列表末尾元素 +li.pop() #=> 3 and li is now [1, 2, 4] +# 放回来 +li.append(3) # li is now [1, 2, 4, 3] again. + +# 像其他语言访问数组一样访问列表 +li[0] #=> 1 +# 访问最后一个元素 +li[-1] #=> 3 + +# 越界会抛出异常 +li[4] # 抛出越界异常 + +# 切片语法需要用到列表的索引访问 +# 可以看做数学之中左闭右开区间 +li[1:3] #=> [2, 4] +# 省略开头的元素 +li[2:] #=> [4, 3] +# 省略末尾的元素 +li[:3] #=> [1, 2, 4] + +# 删除特定元素 +del li[2] # li 现在是 [1, 2, 3] + +# 合并列表 +li + other_li #=> [1, 2, 3, 4, 5, 6] - 不改变这两个列表 + +# 通过拼接合并列表 +li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6] + +# 用in来返回元素是否在列表中 +1 in li #=> True + +# 返回列表长度 +len(li) #=> 6 + + +# 元组类似于列表,但是他是不可改变的 +tup = (1, 2, 3) +tup[0] #=> 1 +tup[0] = 3 # 类型错误 + +# 对于大多数的列表操作,也适用于元组 +len(tup) #=> 3 +tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) +tup[:2] #=> (1, 2) +2 in tup #=> True + +# 你可以将元组解包赋给多个变量 +a, b, c = (1, 2, 3) # a是1,b是2,c是3 +# 如果不加括号,那么会自动视为元组 +d, e, f = 4, 5, 6 +# 现在我们可以看看交换两个数字是多么容易的事 +e, d = d, e # d是5,e是4 + + +# 字典用来储存映射关系 +empty_dict = {} +# 字典初始化 +filled_dict = {"one": 1, "two": 2, "three": 3} + +# 字典也用中括号访问元素 +filled_dict["one"] #=> 1 + +# 把所有的键保存在列表中 +filled_dict.keys() #=> ["three", "two", "one"] +# 键的顺序并不是唯一的,得到的不一定是这个顺序 + +# 把所有的值保存在列表中 +filled_dict.values() #=> [3, 2, 1] +# 和键的顺序相同 + +# 判断一个键是否存在 +"one" in filled_dict #=> True +1 in filled_dict #=> False + +# 查询一个不存在的键会抛出键异常 +filled_dict["four"] # 键异常 + +# 用get方法来避免键异常 +filled_dict.get("one") #=> 1 +filled_dict.get("four") #=> None +# get方法支持在不存在的时候返回一个默认值 +filled_dict.get("one", 4) #=> 1 +filled_dict.get("four", 4) #=> 4 + +# Setdefault是一个更安全的添加字典元素的方法 +filled_dict.setdefault("five", 5) #filled_dict["five"] 的值为 5 +filled_dict.setdefault("five", 6) #filled_dict["five"] 的值仍然是 5 + + +# 集合储存无顺序的元素 +empty_set = set() +# 出事话一个集合 +some_set = set([1,2,2,3,4]) # filled_set 现在是 set([1, 2, 3, 4]) + +# Python 2.7 之后,大括号可以用来表示集合 +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} + +# 为集合添加元素 +filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} + +# 用&来实现集合的交 +other_set = {3, 4, 5, 6} +filled_set & other_set #=> {3, 4, 5} + +# 用|来实现集合的并 +filled_set | other_set #=> {1, 2, 3, 4, 5, 6} + +# 用-来实现集合的差 +{1,2,3,4} - {2,3,5} #=> {1, 4} + +# 用in来判断元素是否存在于集合中 +2 in filled_set #=> True +10 in filled_set #=> False + + +#################################################### +## 3. 控制流程 +#################################################### + +# 新建一个变量 +some_var = 5 + +# 这是个if语句,在python中缩进是很重要的。 +# 会输出 "some var is smaller than 10" +if some_var > 10: + print "some_var is totally bigger than 10." +elif some_var < 10: # 这个 elif 语句是不必须的 + print "some_var is smaller than 10." +else: # 也不是必须的 + print "some_var is indeed 10." + + +""" +用for循环遍历列表 +输出: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # 你可以用 % 来格式化字符串 + print "%s is a mammal" % animal + +""" +`range(number)` 返回从0到给定数字的列表 +输出: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print i + +""" +While循环 +输出: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print x + x += 1 # Shorthand for x = x + 1 + +# 用 try/except块来处理异常 + +# Python 2.6 及以上适用: +try: + # 用raise来抛出异常 + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass就是什么都不做,不过通常这里会做一些恢复工作 + + +#################################################### +## 4. 函数 +#################################################### + +# 用def来新建函数 +def add(x, y): + print "x is %s and y is %s" % (x, y) + return x + y # Return values with a return statement + +# 调用带参数的函数 +add(5, 6) #=> 输出 "x is 5 and y is 6" 返回 11 + +# 通过关键字赋值来调用函数 +add(y=6, x=5) # 顺序是无所谓的 + +# 我们也可以定义接受多个变量的函数,这些变量是按照顺序排列的 +def varargs(*args): + return args + +varargs(1, 2, 3) #=> (1,2,3) + + +# 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的 +def keyword_args(**kwargs): + return kwargs + +# 实际效果: +keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} + +# 你也可以同时将一个函数定义成两种形式 +def all_the_args(*args, **kwargs): + print args + print kwargs +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# 当调用函数的时候,我们也可以和之前所做的相反,把元组和字典展开为参数 +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalent to foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) + +# Python 有一等函数: +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) #=> 13 + +# 匿名函数 +(lambda x: x > 2)(3) #=> True + +# 内置高阶函数 +map(add_10, [1,2,3]) #=> [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] + +# 可以用列表方法来对高阶函数进行更巧妙的引用 +[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] + +#################################################### +## 5. 类 +#################################################### + +# 我们新建的类是从object类中继承的 +class Human(object): + + # 类属性,由所有类的对象共享 + species = "H. sapiens" + + # 基本构造函数 + def __init__(self, name): + # 将参数赋给对象成员属性 + self.name = name + + # 成员方法,参数要有self + def say(self, msg): + return "%s: %s" % (self.name, msg) + + # 类方法由所有类的对象共享 + # 这类方法在调用时,会把类本身传给第一个参数 + @classmethod + def get_species(cls): + return cls.species + + # 静态方法是不需要类和对象的引用就可以调用的方法 + @staticmethod + def grunt(): + return "*grunt*" + + +# 实例化一个类 +i = Human(name="Ian") +print i.say("hi") # 输出 "Ian: hi" + +j = Human("Joel") +print j.say("hello") # 输出 "Joel: hello" + +# 访问类的方法 +i.get_species() #=> "H. sapiens" + +# 改变共享属性 +Human.species = "H. neanderthalensis" +i.get_species() #=> "H. neanderthalensis" +j.get_species() #=> "H. neanderthalensis" + +# 访问静态变量 +Human.grunt() #=> "*grunt*" + + +#################################################### +## 6. 模块 +#################################################### + +# 我们可以导入其他模块 +import math +print math.sqrt(16) #=> 4 + +# 我们也可以从一个模块中特定的函数 +from math import ceil, floor +print ceil(3.7) #=> 4.0 +print floor(3.7) #=> 3.0 + +# 从模块中导入所有的函数 +# 警告:不推荐使用 +from math import * + +# 简写模块名 +import math as m +math.sqrt(16) == m.sqrt(16) #=> True + +# Python的模块其实只是普通的python文件 +# 你也可以创建自己的模块,并且导入它们 +# 模块的名字就和文件的名字相同 + +# 以可以通过下面的信息找找要成为模块需要什么属性或方法 +import math +dir(math) + + +``` + +## 更多阅读 + +希望学到更多?试试下面的链接: + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [The Official Docs](http://docs.python.org/2.6/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/2/) -- cgit v1.2.3 From ea3d1b6415c4ded7ad4651f70cecf5bf87ce6ae3 Mon Sep 17 00:00:00 2001 From: Linxiangyu Date: Mon, 5 Aug 2013 19:04:42 +0800 Subject: Add ruby-cn --- zh-cn/ruby-cn.html.markdown | 329 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 zh-cn/ruby-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown new file mode 100644 index 00000000..f66d1a03 --- /dev/null +++ b/zh-cn/ruby-cn.html.markdown @@ -0,0 +1,329 @@ +--- +language: ruby +filename: learnruby.rb +contributors: + - ["David Underwood", "http://theflyingdeveloper.com"] + - ["Joel Walden", "http://joelwalden.net"] + - ["Luke Holder", "http://twitter.com/lukeholder"] +translators: + - ["Lin Xiangyu", "https://github.com/oa414"] +--- + +```ruby +# 这是单行注释 + +=begin +这是多行注释 +没人用这个 +你也不该用 +=end + +# 首先,也是最重要的,所有东西都是对象 + +# 数字是对象 + +3.class #=> Fixnum + +3.to_s #=> "3" + + +# 一些基本的算术符号 +1 + 1 #=> 2 +8 - 1 #=> 7 +10 * 2 #=> 20 +35 / 5 #=> 7 + +# 算术符号只是语法糖而已 +# 实际上是调用对象的方法 +1.+(3) #=> 4 +10.* 5 #=> 50 + +# 特殊的只也是对象 +nil # 空 +true # 真 +false # 假 + +nil.class #=> NilClass +true.class #=> TrueClass +false.class #=> FalseClass + +# 相等运算符 +1 == 1 #=> true +2 == 1 #=> false + +# 不等运算符 +1 != 1 #=> false +2 != 1 #=> true +!true #=> false +!false #=> true + +# 除了false自己,nil是唯一的值为false的对象 + +!nil #=> true +!false #=> true +!0 #=> false + +# 更多比较 +1 < 10 #=> true +1 > 10 #=> false +2 <= 2 #=> true +2 >= 2 #=> true + +# 字符串是对象 + +'I am a string'.class #=> String +"I am a string too".class #=> String + +placeholder = "use string interpolation" +"I can #{placeholder} when using double quoted strings" +#=> "I can use string interpolation when using double quoted strings" + + +# 输出值 +puts "I'm printing!" + +# 变量 +x = 25 #=> 25 +x #=> 25 + +# 注意赋值语句返回了赋的值 +# 这意味着你可以用多重赋值语句 + +x = y = 10 #=> 10 +x #=> 10 +y #=> 10 + +# 按照惯例,用snake_case 作为变量名 +snake_case = true + +# 使用具有描述性的运算符 +path_to_project_root = '/good/name/' +path = '/bad/name/' + +# 符号(Symbols,也是对象) +# 符号是不可变的,内部用整数类型表示的可重用的值。通常用它代替字符串来有效地表达有意义的值 + + +:pending.class #=> Symbol + +status = :pending + +status == :pending #=> true + +status == 'pending' #=> false + +status == :approved #=> false + +# 数组 + +# 这是一个数组 +[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] + +# 数组可以包含不同类型的元素 + +array = [1, "hello", false] #=> => [1, "hello", false] + +# 数组可以被索引 +# 从前面开始 +array[0] #=> 1 +array[12] #=> nil + +# 像运算符一样,[var]形式的访问 +# 也就是一个语法糖 +# 实际上是调用对象的[] 方法 +array.[] 0 #=> 1 +array.[] 12 #=> nil + +# 从尾部开始 +array[-1] #=> 5 + +# 同时指定开始的位置和结束的位置 +array[2, 4] #=> [3, 4, 5] + +# 或者指定一个范围 +array[1..3] #=> [2, 3, 4] + +# 像这样往数组增加一个元素 +array << 6 #=> [1, 2, 3, 4, 5, 6] + +# 哈希表是Ruby的键值对的基本数据结构 +# 哈希表由大括号定义 +hash = {'color' => 'green', 'number' => 5} + +hash.keys #=> ['color', 'number'] + +# 哈希表可以通过键快速地查询 +hash['color'] #=> 'green' +hash['number'] #=> 5 + +# 查询一个不存在地键将会返回nil +hash['nothing here'] #=> nil + +# 用 #each 方法来枚举哈希表: +hash.each do |k, v| + puts "#{k} is #{v}" +end + +# 从Ruby 1.9开始, 用符号作为键的时候有特别的记号表示: + +new_hash = { defcon: 3, action: true} + +new_hash.keys #=> [:defcon, :action] + +# 小贴士:数组和哈希表都是可枚举的 +# 它们可以共享一些有用的方法,比如each, map, count, 和more + +# 控制流 + +if true + "if statement" +elsif false + "else if, optional" +else + "else, also optional" +end + +for counter in 1..5 + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +# 然而 +# 没人用for循环 +# 用`each`来代替,就像这样 + +(1..5).each do |counter| + puts "iteration #{counter}" +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +counter = 1 +while counter <= 5 do + puts "iteration #{counter}" + counter += 1 +end +#=> iteration 1 +#=> iteration 2 +#=> iteration 3 +#=> iteration 4 +#=> iteration 5 + +grade = 'B' + +case grade +when 'A' + puts "Way to go kiddo" +when 'B' + puts "Better luck next time" +when 'C' + puts "You can do better" +when 'D' + puts "Scraping through" +when 'F' + puts "You failed!" +else + puts "Alternative grading system, eh?" +end + +# 函数 + +def double(x) + x * 2 +end + +# 函数 (以及所有的方法块) 隐式地返回了最后语句的值 +double(2) #=> 4 + +# 当不存在歧义的时候括号是可有可无的 +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x,y) + x + y +end + +# 方法的参数通过逗号分隔 +sum 3, 4 #=> 7 + +sum sum(3,4), 5 #=> 12 + +# yield +# 所有的方法都有一个隐式的块参数 +# 可以用yield参数调用 + +def surround + puts "{" + yield + puts "}" +end + +surround { puts 'hello world' } + +# { +# hello world +# } + + +# 用class关键字定义一个类 +class Human + + # 一个类变量,它被这个类地所有实例变量共享 + @@species = "H. sapiens" + + # 构造函数 + def initialize(name, age=0) + # 将参数name的值赋给实例变量@name + @name = name + # 如果没有给出age, 那么会采用参数列表中地默认地值 + @age = age + end + + # 基本的 setter 方法 + def name=(name) + @name = name + end + + # 基本地 getter 方法 + def name + @name + end + + # 一个类方法以self.开头 + # 它可以被类调用,但不能被类的实例调用 + def self.say(msg) + puts "#{msg}" + end + + def species + @@species + end + +end + + +# 类的例子 +jim = Human.new("Jim Halpert") + +dwight = Human.new("Dwight K. Schrute") + +# 让我们来调用一些方法 +jim.species #=> "H. sapiens" +jim.name #=> "Jim Halpert" +jim.name = "Jim Halpert II" #=> "Jim Halpert II" +jim.name #=> "Jim Halpert II" +dwight.species #=> "H. sapiens" +dwight.name #=> "Dwight K. Schrute" + +# 调用对象的方法 +Human.say("Hi") #=> "Hi" + +``` -- cgit v1.2.3 From 8d0a2e6b79533856e82a8541b5b866ebd6fdeb4e Mon Sep 17 00:00:00 2001 From: hanguokai Date: Sat, 10 Aug 2013 06:31:51 +0800 Subject: add translation for dart. --- zh-cn/dart-cn.html.markdown | 509 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 zh-cn/dart-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/dart-cn.html.markdown b/zh-cn/dart-cn.html.markdown new file mode 100644 index 00000000..47b1a93b --- /dev/null +++ b/zh-cn/dart-cn.html.markdown @@ -0,0 +1,509 @@ +--- +language: dart +filename: learndart.dart +contributors: + - ["Joao Pedrosa", "https://github.com/jpedrosa/"] +translators: + - ["Guokai Han", "https://github.com/hanguokai/"] +--- + +Dart 是编程语言王国的新人。 +它借鉴了许多其他主流语言,并且不会偏离它的兄弟语言 JavaScript 太多。 +就像 JavaScript,Dart 的目标是提供良好的浏览器集成。 + +Dart 最有争议的特性必然是它的可选类型。 + +```javascript +import "dart:collection"; +import "dart:math" as DM; + +// Welcome to Learn Dart in 15 minutes. http://www.dartlang.org/ +// This is an executable tutorial. You can run it with Dart or on +// the Try Dart! site if you copy/paste it there. http://try.dartlang.org/ + +// Function declaration and method declaration look the same. Function +// declarations can be nested. The declaration takes the form of +// name() {} or name() => singleLineExpression; +// The fat arrow function declaration has an implicit return for the result of +// the expression. +example1() { + example1nested1() { + example1nested2() => print("Example1 nested 1 nested 2"); + example1nested2(); + } + example1nested1(); +} + +// Anonymous functions don't include a name. +example2() { + example2nested1(fn) { + fn(); + } + example2nested1(() => print("Example2 nested 1")); +} + +// When a function parameter is declared, the declaration can include the +// number of parameters the function takes by specifying the names of the +// parameters it takes. +example3() { + example3nested1(fn(informSomething)) { + fn("Example3 nested 1"); + } + example3planB(fn) { // Or don't declare number of parameters. + fn("Example3 plan B"); + } + example3nested1((s) => print(s)); + example3planB((s) => print(s)); +} + +// Functions have closure access to outer variables. +var example4Something = "Example4 nested 1"; +example4() { + example4nested1(fn(informSomething)) { + fn(example4Something); + } + example4nested1((s) => print(s)); +} + +// Class declaration with a sayIt method, which also has closure access +// to the outer variable as though it were a function as seen before. +var example5method = "Example5 sayIt"; +class Example5Class { + sayIt() { + print(example5method); + } +} +example5() { + // Create an anonymous instance of the Example5Class and call the sayIt + // method on it. + new Example5Class().sayIt(); +} + +// Class declaration takes the form of class name { [classBody] }. +// Where classBody can include instance methods and variables, but also +// class methods and variables. +class Example6Class { + var example6InstanceVariable = "Example6 instance variable"; + sayIt() { + print(example6InstanceVariable); + } +} +example6() { + new Example6Class().sayIt(); +} + +// Class methods and variables are declared with "static" terms. +class Example7Class { + static var example7ClassVariable = "Example7 class variable"; + static sayItFromClass() { + print(example7ClassVariable); + } + sayItFromInstance() { + print(example7ClassVariable); + } +} +example7() { + Example7Class.sayItFromClass(); + new Example7Class().sayItFromInstance(); +} + +// Literals are great, but there's a restriction for what literals can be +// outside of function/method bodies. Literals on the outer scope of class +// or outside of class have to be constant. Strings and numbers are constant +// by default. But arrays and maps are not. They can be made constant by +// declaring them "const". +var example8A = const ["Example8 const array"], + example8M = const {"someKey": "Example8 const map"}; +example8() { + print(example8A[0]); + print(example8M["someKey"]); +} + +// Loops in Dart take the form of standard for () {} or while () {} loops, +// slightly more modern for (.. in ..) {}, or functional callbacks with many +// supported features, starting with forEach. +var example9A = const ["a", "b"]; +example9() { + for (var i = 0; i < example9A.length; i++) { + print("Example9 for loop '${example9A[i]}'"); + } + var i = 0; + while (i < example9A.length) { + print("Example9 while loop '${example9A[i]}'"); + i++; + } + for (var e in example9A) { + print("Example9 for-in loop '${e}'"); + } + example9A.forEach((e) => print("Example9 forEach loop '${e}'")); +} + +// To loop over the characters of a string or to extract a substring. +var example10S = "ab"; +example10() { + for (var i = 0; i < example10S.length; i++) { + print("Example10 String character loop '${example10S[i]}'"); + } + for (var i = 0; i < example10S.length; i++) { + print("Example10 substring loop '${example10S.substring(i, i + 1)}'"); + } +} + +// Int and double are the two supported number formats. +example11() { + var i = 1 + 320, d = 3.2 + 0.01; + print("Example11 int ${i}"); + print("Example11 double ${d}"); +} + +// DateTime provides date/time arithmetic. +example12() { + var now = new DateTime.now(); + print("Example12 now '${now}'"); + now = now.add(new Duration(days: 1)); + print("Example12 tomorrow '${now}'"); +} + +// Regular expressions are supported. +example13() { + var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$"); + match(s) { + if (re.hasMatch(s)) { + print("Example13 regexp matches '${s}'"); + } else { + print("Example13 regexp doesn't match '${s}'"); + } + } + match(s1); + match(s2); +} + +// Boolean expressions need to resolve to either true or false, as no +// implicit conversions are supported. +example14() { + var v = true; + if (v) { + print("Example14 value is true"); + } + v = null; + try { + if (v) { + // Never runs + } else { + // Never runs + } + } catch (e) { + print("Example14 null value causes an exception: '${e}'"); + } +} + +// try/catch/finally and throw are used for exception handling. +// throw takes any object as parameter; +example15() { + try { + try { + throw "Some unexpected error."; + } catch (e) { + print("Example15 an exception: '${e}'"); + throw e; // Re-throw + } + } catch (e) { + print("Example15 catch exception being re-thrown: '${e}'"); + } finally { + print("Example15 Still run finally"); + } +} + +// To be efficient when creating a long string dynamically, use +// StringBuffer. Or you could join a string array. +example16() { + var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e; + for (e in a) { sb.write(e); } + print("Example16 dynamic string created with " + "StringBuffer '${sb.toString()}'"); + print("Example16 join string array '${a.join()}'"); +} + +// Strings can be concatenated by just having string literals next to +// one another with no further operator needed. +example17() { + print("Example17 " + "concatenate " + "strings " + "just like that"); +} + +// Strings have single-quote or double-quote for delimiters with no +// actual difference between the two. The given flexibility can be good +// to avoid the need to escape content that matches the delimiter being +// used. For example, double-quotes of HTML attributes if the string +// contains HTML content. +example18() { + print('Example18 ' + "Don't can't I'm Etc" + ''); +} + +// Strings with triple single-quotes or triple double-quotes span +// multiple lines and include line delimiters. +example19() { + print('''Example19 +Example19 Don't can't I'm Etc +Example19 '''); +} + +// Strings have the nice interpolation feature with the $ character. +// With $ { [expression] }, the return of the expression is interpolated. +// $ followed by a variable name interpolates the content of that variable. +// $ can be escaped like so \$ to just add it to the string instead. +example20() { + var s1 = "'\${s}'", s2 = "'\$s'"; + print("Example20 \$ interpolation ${s1} or $s2 works."); +} + +// Optional types allow for the annotation of APIs and come to the aid of +// IDEs so the IDEs can better refactor, auto-complete and check for +// errors. So far we haven't declared any types and the programs have +// worked just fine. In fact, types are disregarded during runtime. +// Types can even be wrong and the program will still be given the +// benefit of the doubt and be run as though the types didn't matter. +// There's a runtime parameter that checks for type errors which is +// the checked mode, which is said to be useful during development time, +// but which is also slower because of the extra checking and is thus +// avoided during deployment runtime. +class Example21 { + List _names; + Example21() { + _names = ["a", "b"]; + } + List get names => _names; + set names(List list) { + _names = list; + } + int get length => _names.length; + void add(String name) { + _names.add(name); + } +} +void example21() { + Example21 o = new Example21(); + o.add("c"); + print("Example21 names '${o.names}' and length '${o.length}'"); + o.names = ["d", "e"]; + print("Example21 names '${o.names}' and length '${o.length}'"); +} + +// Class inheritance takes the form of class name extends AnotherClassName {}. +class Example22A { + var _name = "Some Name!"; + get name => _name; +} +class Example22B extends Example22A {} +example22() { + var o = new Example22B(); + print("Example22 class inheritance '${o.name}'"); +} + +// Class mixin is also available, and takes the form of +// class name extends SomeClass with AnotherClassName {}. +// It's necessary to extend some class to be able to mixin another one. +// The template class of mixin cannot at the moment have a constructor. +// Mixin is mostly used to share methods with distant classes, so the +// single inheritance doesn't get in the way of reusable code. +// Mixins follow the "with" statement during the class declaration. +class Example23A {} +class Example23Utils { + addTwo(n1, n2) { + return n1 + n2; + } +} +class Example23B extends Example23A with Example23Utils { + addThree(n1, n2, n3) { + return addTwo(n1, n2) + n3; + } +} +example23() { + var o = new Example23B(), r1 = o.addThree(1, 2, 3), + r2 = o.addTwo(1, 2); + print("Example23 addThree(1, 2, 3) results in '${r1}'"); + print("Example23 addTwo(1, 2) results in '${r2}'"); +} + +// The Class constructor method uses the same name of the class and +// takes the form of SomeClass() : super() {}, where the ": super()" +// part is optional and it's used to delegate constant parameters to the +// super-parent's constructor. +class Example24A { + var _value; + Example24A({value: "someValue"}) { + _value = value; + } + get value => _value; +} +class Example24B extends Example24A { + Example24B({value: "someOtherValue"}) : super(value: value); +} +example24() { + var o1 = new Example24B(), + o2 = new Example24B(value: "evenMore"); + print("Example24 calling super during constructor '${o1.value}'"); + print("Example24 calling super during constructor '${o2.value}'"); +} + +// There's a shortcut to set constructor parameters in case of simpler classes. +// Just use the this.parameterName prefix and it will set the parameter on +// an instance variable of same name. +class Example25 { + var value, anotherValue; + Example25({this.value, this.anotherValue}); +} +example25() { + var o = new Example25(value: "a", anotherValue: "b"); + print("Example25 shortcut for constructor '${o.value}' and " + "'${o.anotherValue}'"); +} + +// Named parameters are available when declared between {}. +// Parameter order can be optional when declared between {}. +// Parameters can be made optional when declared between []. +example26() { + var _name, _surname, _email; + setConfig1({name, surname}) { + _name = name; + _surname = surname; + } + setConfig2(name, [surname, email]) { + _name = name; + _surname = surname; + _email = email; + } + setConfig1(surname: "Doe", name: "John"); + print("Example26 name '${_name}', surname '${_surname}', " + "email '${_email}'"); + setConfig2("Mary", "Jane"); + print("Example26 name '${_name}', surname '${_surname}', " + "email '${_email}'"); +} + +// Variables declared with final can only be set once. +// In case of classes, final instance variables can be set via constant +// constructor parameter. +class Example27 { + final color1, color2; + // A little flexibility to set final instance variables with syntax + // that follows the : + Example27({this.color1, color2}) : color2 = color2; +} +example27() { + final color = "orange", o = new Example27(color1: "lilac", color2: "white"); + print("Example27 color is '${color}'"); + print("Example27 color is '${o.color1}' and '${o.color2}'"); +} + +// To import a library, use import "libraryPath" or if it's a core library, +// import "dart:libraryName". There's also the "pub" package management with +// its own convention of import "package:packageName". +// See import "dart:collection"; at the top. Imports must come before +// other code declarations. IterableBase comes from dart:collection. +class Example28 extends IterableBase { + var names; + Example28() { + names = ["a", "b"]; + } + get iterator => names.iterator; +} +example28() { + var o = new Example28(); + o.forEach((name) => print("Example28 '${name}'")); +} + +// For control flow we have: +// * standard switch with must break statements +// * if-else if-else and ternary ..?..:.. operator +// * closures and anonymous functions +// * break, continue and return statements +example29() { + var v = true ? 30 : 60; + switch (v) { + case 30: + print("Example29 switch statement"); + break; + } + if (v < 30) { + } else if (v > 30) { + } else { + print("Example29 if-else statement"); + } + callItForMe(fn()) { + return fn(); + } + rand() { + v = new DM.Random().nextInt(50); + return v; + } + while (true) { + print("Example29 callItForMe(rand) '${callItForMe(rand)}'"); + if (v != 30) { + break; + } else { + continue; + } + // Never gets here. + } +} + +// Parse int, convert double to int, or just keep int when dividing numbers +// by using the ~/ operation. Let's play a guess game too. +example30() { + var gn, tooHigh = false, + n, n2 = (2.0).toInt(), top = int.parse("123") ~/ n2, bottom = 0; + top = top ~/ 6; + gn = new DM.Random().nextInt(top + 1); // +1 because nextInt top is exclusive + print("Example30 Guess a number between 0 and ${top}"); + guessNumber(i) { + if (n == gn) { + print("Example30 Guessed right! The number is ${gn}"); + } else { + tooHigh = n > gn; + print("Example30 Number ${n} is too " + "${tooHigh ? 'high' : 'low'}. Try again"); + } + return n == gn; + } + n = (top - bottom) ~/ 2; + while (!guessNumber(n)) { + if (tooHigh) { + top = n - 1; + } else { + bottom = n + 1; + } + n = bottom + ((top - bottom) ~/ 2); + } +} + +// Programs have only one entry point in the main function. +// Nothing is expected to be executed on the outer scope before a program +// starts running with what's in its main function. +// This helps with faster loading and even lazily loading of just what +// the program needs to startup with. +main() { + print("Learn Dart in 15 minutes!"); + [example1, example2, example3, example4, example5, example6, example7, + example8, example9, example10, example11, example12, example13, example14, + example15, example16, example17, example18, example19, example20, + example21, example22, example23, example24, example25, example26, + example27, example28, example29, example30 + ].forEach((ef) => ef()); +} + +``` + +## 延伸阅读 + +Dart 有一个全面的网站。它涵盖了 API 参考、入门向导、文章以及更多, +包括一个有用的 Dart 在线试用。 +http://www.dartlang.org/ +http://try.dartlang.org/ + + + -- cgit v1.2.3 From c5c76b4a5d36b729bd782d3e3695aa1a7083a129 Mon Sep 17 00:00:00 2001 From: hanguokai Date: Sat, 10 Aug 2013 06:35:01 +0800 Subject: add translation for dart. --- zh-cn/dart-cn.html.markdown | 205 +++++++++++++++++++++----------------------- 1 file changed, 97 insertions(+), 108 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/dart-cn.html.markdown b/zh-cn/dart-cn.html.markdown index 47b1a93b..64663b21 100644 --- a/zh-cn/dart-cn.html.markdown +++ b/zh-cn/dart-cn.html.markdown @@ -9,7 +9,7 @@ translators: Dart 是编程语言王国的新人。 它借鉴了许多其他主流语言,并且不会偏离它的兄弟语言 JavaScript 太多。 -就像 JavaScript,Dart 的目标是提供良好的浏览器集成。 +就像 JavaScript 一样,Dart 的目标是提供良好的浏览器集成。 Dart 最有争议的特性必然是它的可选类型。 @@ -17,15 +17,14 @@ Dart 最有争议的特性必然是它的可选类型。 import "dart:collection"; import "dart:math" as DM; -// Welcome to Learn Dart in 15 minutes. http://www.dartlang.org/ -// This is an executable tutorial. You can run it with Dart or on -// the Try Dart! site if you copy/paste it there. http://try.dartlang.org/ +// 欢迎进入15分钟的 Dart 学习。 http://www.dartlang.org/ +// 这是一个可实际执行的向导。你可以用 Dart 运行它 +// 或者在线执行! 可以把代码复制/粘贴到这个网站。 http://try.dartlang.org/ -// Function declaration and method declaration look the same. Function -// declarations can be nested. The declaration takes the form of -// name() {} or name() => singleLineExpression; -// The fat arrow function declaration has an implicit return for the result of -// the expression. +// 函数声明和方法声明看起来一样。 +// 函数声明可以嵌套。声明使用这种 name() {} 的形式, +// 或者 name() => 单行表达式; 的形式。 +// 右箭头的声明形式会隐式地返回表达式的结果。 example1() { example1nested1() { example1nested2() => print("Example1 nested 1 nested 2"); @@ -34,7 +33,7 @@ example1() { example1nested1(); } -// Anonymous functions don't include a name. +// 匿名函数没有函数名。 example2() { example2nested1(fn) { fn(); @@ -42,21 +41,20 @@ example2() { example2nested1(() => print("Example2 nested 1")); } -// When a function parameter is declared, the declaration can include the -// number of parameters the function takes by specifying the names of the -// parameters it takes. +// 当声明函数类型的参数的时候,声明中可以包含 +// 函数参数需要的参数,指定所需的参数名即可。 example3() { example3nested1(fn(informSomething)) { fn("Example3 nested 1"); } - example3planB(fn) { // Or don't declare number of parameters. + example3planB(fn) { // 或者不声明函数参数的参数 fn("Example3 plan B"); } example3nested1((s) => print(s)); example3planB((s) => print(s)); } -// Functions have closure access to outer variables. +// 函数有可以访问到外层变量的闭包。 var example4Something = "Example4 nested 1"; example4() { example4nested1(fn(informSomething)) { @@ -65,8 +63,8 @@ example4() { example4nested1((s) => print(s)); } -// Class declaration with a sayIt method, which also has closure access -// to the outer variable as though it were a function as seen before. +// 下面这个包含 sayIt 方法的类声明,同样有一个可以访问外层变量的闭包, +// 就像前面的函数一样。 var example5method = "Example5 sayIt"; class Example5Class { sayIt() { @@ -74,14 +72,14 @@ class Example5Class { } } example5() { - // Create an anonymous instance of the Example5Class and call the sayIt - // method on it. + // 创建一个 Example5Class 类的匿名实例, + // 并调用它的 sayIt 方法。 new Example5Class().sayIt(); } -// Class declaration takes the form of class name { [classBody] }. -// Where classBody can include instance methods and variables, but also -// class methods and variables. +// 类的声明使用这种形式 class name { [classBody] }. +// classBody 中可以包含实例方法和变量, +// 还可以包含类方法和变量。 class Example6Class { var example6InstanceVariable = "Example6 instance variable"; sayIt() { @@ -92,7 +90,7 @@ example6() { new Example6Class().sayIt(); } -// Class methods and variables are declared with "static" terms. +// 类方法和变量使用 static 关键词声明。 class Example7Class { static var example7ClassVariable = "Example7 class variable"; static sayItFromClass() { @@ -107,11 +105,10 @@ example7() { new Example7Class().sayItFromInstance(); } -// Literals are great, but there's a restriction for what literals can be -// outside of function/method bodies. Literals on the outer scope of class -// or outside of class have to be constant. Strings and numbers are constant -// by default. But arrays and maps are not. They can be made constant by -// declaring them "const". +// 字面量非常方便,但是对于在函数/方法的外层的字面量有一个限制, +// 类的外层或外面的字面量必需是常量。 +// 字符串和数字默认是常量。 +// 但是 array 和 map 不是。他们需要用 "const" 声明为常量。 var example8A = const ["Example8 const array"], example8M = const {"someKey": "Example8 const map"}; example8() { @@ -119,9 +116,9 @@ example8() { print(example8M["someKey"]); } -// Loops in Dart take the form of standard for () {} or while () {} loops, -// slightly more modern for (.. in ..) {}, or functional callbacks with many -// supported features, starting with forEach. +// Dart 中的循环使用标准的 for () {} 或 while () {} 的形式, +// 以及更加现代的 for (.. in ..) {} 的形式, 或者 +// 以 forEach 开头并具有许多特性支持的函数回调的形式。 var example9A = const ["a", "b"]; example9() { for (var i = 0; i < example9A.length; i++) { @@ -138,7 +135,7 @@ example9() { example9A.forEach((e) => print("Example9 forEach loop '${e}'")); } -// To loop over the characters of a string or to extract a substring. +// 遍历字符串中的每个字符或者提取其子串。 var example10S = "ab"; example10() { for (var i = 0; i < example10S.length; i++) { @@ -149,14 +146,14 @@ example10() { } } -// Int and double are the two supported number formats. +// 支持两种数字格式 int 和 double 。 example11() { var i = 1 + 320, d = 3.2 + 0.01; print("Example11 int ${i}"); print("Example11 double ${d}"); } -// DateTime provides date/time arithmetic. +// DateTime 提供了日期/时间的算法。 example12() { var now = new DateTime.now(); print("Example12 now '${now}'"); @@ -164,7 +161,7 @@ example12() { print("Example12 tomorrow '${now}'"); } -// Regular expressions are supported. +// 支持正则表达式。 example13() { var s1 = "some string", s2 = "some", re = new RegExp("^s.+?g\$"); match(s) { @@ -178,8 +175,8 @@ example13() { match(s2); } -// Boolean expressions need to resolve to either true or false, as no -// implicit conversions are supported. +// 布尔表达式必需被解析为 true 或 false, +// 因为不支持隐式转换。 example14() { var v = true; if (v) { @@ -188,17 +185,17 @@ example14() { v = null; try { if (v) { - // Never runs + // 不会执行 } else { - // Never runs + // 不会执行 } } catch (e) { print("Example14 null value causes an exception: '${e}'"); } } -// try/catch/finally and throw are used for exception handling. -// throw takes any object as parameter; +// try/catch/finally 和 throw 语句用于异常处理。 +// throw 语句可以使用任何对象作为参数。 example15() { try { try { @@ -214,8 +211,8 @@ example15() { } } -// To be efficient when creating a long string dynamically, use -// StringBuffer. Or you could join a string array. +// 要想有效地动态创建长字符串, +// 应该使用 StringBuffer。 或者 join 一个字符串的数组。 example16() { var sb = new StringBuffer(), a = ["a", "b", "c", "d"], e; for (e in a) { sb.write(e); } @@ -224,8 +221,8 @@ example16() { print("Example16 join string array '${a.join()}'"); } -// Strings can be concatenated by just having string literals next to -// one another with no further operator needed. +// 字符串连接只需让相邻的字符串字面量挨着, +// 不需要额外的操作符。 example17() { print("Example17 " "concatenate " @@ -233,44 +230,41 @@ example17() { "just like that"); } -// Strings have single-quote or double-quote for delimiters with no -// actual difference between the two. The given flexibility can be good -// to avoid the need to escape content that matches the delimiter being -// used. For example, double-quotes of HTML attributes if the string -// contains HTML content. +// 字符串使用单引号或双引号做分隔符,二者并没有实际的差异。 +// 这种灵活性可以很好地避免内容中需要转义分隔符的情况。 +// 例如,字符串内容里的 HTML 属性使用了双引号。 example18() { print('Example18 ' "Don't can't I'm Etc" ''); } -// Strings with triple single-quotes or triple double-quotes span -// multiple lines and include line delimiters. +// 用三个单引号或三个双引号表示的字符串 +// 可以跨越多行,并且包含行分隔符。 example19() { print('''Example19 Example19 Don't can't I'm Etc Example19 '''); } -// Strings have the nice interpolation feature with the $ character. -// With $ { [expression] }, the return of the expression is interpolated. -// $ followed by a variable name interpolates the content of that variable. -// $ can be escaped like so \$ to just add it to the string instead. +// 字符串可以使用 $ 字符插入内容。 +// 使用 $ { [expression] } 的形式,表达式的值会被插入到字符串中。 +// $ 跟着一个变量名会插入变量的值。 +// 如果要在字符串中插入 $ ,可以使用 \$ 的转义形式代替。 example20() { var s1 = "'\${s}'", s2 = "'\$s'"; print("Example20 \$ interpolation ${s1} or $s2 works."); } -// Optional types allow for the annotation of APIs and come to the aid of -// IDEs so the IDEs can better refactor, auto-complete and check for -// errors. So far we haven't declared any types and the programs have -// worked just fine. In fact, types are disregarded during runtime. -// Types can even be wrong and the program will still be given the -// benefit of the doubt and be run as though the types didn't matter. -// There's a runtime parameter that checks for type errors which is -// the checked mode, which is said to be useful during development time, -// but which is also slower because of the extra checking and is thus -// avoided during deployment runtime. +// 可选类型允许作为 API 的标注,并且可以辅助 IDE, +// 这样 IDE 可以更好地提供重构、自动完成和错误检测功能。 +// 目前为止我们还没有声明任何类型,并且程序运行地很好。 +// 事实上,类型在运行时会被忽略。 +// 类型甚至可以是错的,并且程序依然可以执行, +// 好像和类型完全无关一样。 +// 有一个运行时参数可以让程序进入检查模式,它会在运行时检查类型错误。 +// 这在开发时很有用,但是由于增加了额外的检查会使程序变慢, +// 因此应该避免在部署时使用。 class Example21 { List _names; Example21() { @@ -293,7 +287,7 @@ void example21() { print("Example21 names '${o.names}' and length '${o.length}'"); } -// Class inheritance takes the form of class name extends AnotherClassName {}. +// 类的继承形式是 class name extends AnotherClassName {} 。 class Example22A { var _name = "Some Name!"; get name => _name; @@ -304,13 +298,13 @@ example22() { print("Example22 class inheritance '${o.name}'"); } -// Class mixin is also available, and takes the form of +// 类也可以使用 mixin 的形式 : // class name extends SomeClass with AnotherClassName {}. -// It's necessary to extend some class to be able to mixin another one. -// The template class of mixin cannot at the moment have a constructor. -// Mixin is mostly used to share methods with distant classes, so the -// single inheritance doesn't get in the way of reusable code. -// Mixins follow the "with" statement during the class declaration. +// 必需继承某个类才能 mixin 另一个类。 +// 当前 mixin 的模板类不能有构造函数。 +// Mixin 主要是用来和辅助的类共享方法的, +// 这样单一继承就不会影响代码复用。 +// Mixin 声明在类定义的 "with" 关键词后面。 class Example23A {} class Example23Utils { addTwo(n1, n2) { @@ -329,10 +323,9 @@ example23() { print("Example23 addTwo(1, 2) results in '${r2}'"); } -// The Class constructor method uses the same name of the class and -// takes the form of SomeClass() : super() {}, where the ": super()" -// part is optional and it's used to delegate constant parameters to the -// super-parent's constructor. +// 类的构造函数名和类名相同,形式为 +// SomeClass() : super() {}, 其中 ": super()" 的部分是可选的, +// 它用来传递参数给父类的构造函数。 class Example24A { var _value; Example24A({value: "someValue"}) { @@ -350,9 +343,9 @@ example24() { print("Example24 calling super during constructor '${o2.value}'"); } -// There's a shortcut to set constructor parameters in case of simpler classes. -// Just use the this.parameterName prefix and it will set the parameter on -// an instance variable of same name. +// 对于简单的类,有一种设置构造函数参数的快捷方式。 +// 只需要使用 this.parameterName 的前缀, +// 它就会把参数设置为同名的实例变量。 class Example25 { var value, anotherValue; Example25({this.value, this.anotherValue}); @@ -363,9 +356,9 @@ example25() { "'${o.anotherValue}'"); } -// Named parameters are available when declared between {}. -// Parameter order can be optional when declared between {}. -// Parameters can be made optional when declared between []. +// 可以在大括号 {} 中声明命名参数。 +// 大括号 {} 中声明的参数的顺序是随意的。 +// 在中括号 [] 中声明的参数也是可选的。 example26() { var _name, _surname, _email; setConfig1({name, surname}) { @@ -385,13 +378,11 @@ example26() { "email '${_email}'"); } -// Variables declared with final can only be set once. -// In case of classes, final instance variables can be set via constant -// constructor parameter. +// 使用 final 声明的变量只能被设置一次。 +// 在类里面,final 实例变量可以通过常量的构造函数参数设置。 class Example27 { final color1, color2; - // A little flexibility to set final instance variables with syntax - // that follows the : + // 更灵活一点的方法是在冒号 : 后面设置 final 实例变量。 Example27({this.color1, color2}) : color2 = color2; } example27() { @@ -400,11 +391,11 @@ example27() { print("Example27 color is '${o.color1}' and '${o.color2}'"); } -// To import a library, use import "libraryPath" or if it's a core library, -// import "dart:libraryName". There's also the "pub" package management with -// its own convention of import "package:packageName". -// See import "dart:collection"; at the top. Imports must come before -// other code declarations. IterableBase comes from dart:collection. +// 要导入一个库,使用 import "libraryPath" 的形式,或者如果要导入的是 +// 核心库使用 import "dart:libraryName" 。还有一个称为 "pub" 的包管理工具, +// 它使用 import "package:packageName" 的约定形式。 +// 看下这个文件顶部的 import "dart:collection"; 语句。 +// 导入语句必需在其它代码声明之前出现。IterableBase 来自于 dart:collection 。 class Example28 extends IterableBase { var names; Example28() { @@ -417,11 +408,11 @@ example28() { o.forEach((name) => print("Example28 '${name}'")); } -// For control flow we have: -// * standard switch with must break statements -// * if-else if-else and ternary ..?..:.. operator -// * closures and anonymous functions -// * break, continue and return statements +// 对于控制流语句,我们有: +// * 必需带 break 的标准 switch 语句 +// * if-else 和三元操作符 ..?..:.. +// * 闭包和匿名函数 +// * break, continue 和 return 语句 example29() { var v = true ? 30 : 60; switch (v) { @@ -448,12 +439,12 @@ example29() { } else { continue; } - // Never gets here. + // 不会到这里。 } } -// Parse int, convert double to int, or just keep int when dividing numbers -// by using the ~/ operation. Let's play a guess game too. +// 解析 int,把 double 转成 int,或者使用 ~/ 操作符在除法计算时仅保留整数位。 +// 让我们也来场猜数游戏吧。 example30() { var gn, tooHigh = false, n, n2 = (2.0).toInt(), top = int.parse("123") ~/ n2, bottom = 0; @@ -481,11 +472,9 @@ example30() { } } -// Programs have only one entry point in the main function. -// Nothing is expected to be executed on the outer scope before a program -// starts running with what's in its main function. -// This helps with faster loading and even lazily loading of just what -// the program needs to startup with. +// 程序的唯一入口点是 main 函数。 +// 在程序开始执行 main 函数之前,不期望执行任何外层代码。 +// 这样可以帮助程序更快地加载,甚至仅惰性加载程序启动时需要的部分。 main() { print("Learn Dart in 15 minutes!"); [example1, example2, example3, example4, example5, example6, example7, @@ -500,8 +489,8 @@ main() { ## 延伸阅读 -Dart 有一个全面的网站。它涵盖了 API 参考、入门向导、文章以及更多, -包括一个有用的 Dart 在线试用。 +Dart 有一个综合性网站。它涵盖了 API 参考、入门向导、文章以及更多, +还包括一个有用的在线试用 Dart 页面。 http://www.dartlang.org/ http://try.dartlang.org/ -- cgit v1.2.3 From 2f7a3afda056eeebdccfef9ed1259e2e17639fe8 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 11 Aug 2013 22:46:23 -0700 Subject: Merged some stuff --- zh-cn/dart-cn.html.markdown | 1 + zh-cn/ruby-cn.html.markdown | 1 + 2 files changed, 2 insertions(+) (limited to 'zh-cn') diff --git a/zh-cn/dart-cn.html.markdown b/zh-cn/dart-cn.html.markdown index 64663b21..1b0cceb9 100644 --- a/zh-cn/dart-cn.html.markdown +++ b/zh-cn/dart-cn.html.markdown @@ -1,5 +1,6 @@ --- language: dart +lang: zh-cn filename: learndart.dart contributors: - ["Joao Pedrosa", "https://github.com/jpedrosa/"] diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index f66d1a03..16c0ed67 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -1,6 +1,7 @@ --- language: ruby filename: learnruby.rb +lang: zh-cn contributors: - ["David Underwood", "http://theflyingdeveloper.com"] - ["Joel Walden", "http://joelwalden.net"] -- cgit v1.2.3 From 6bc415464e74328868a61fba7d928ecbd404f319 Mon Sep 17 00:00:00 2001 From: lpy Date: Mon, 12 Aug 2013 11:09:08 +0800 Subject: Add Scala zh-cn translation and add link to Scala documentation in scala.html.markdown --- zh-cn/scala-cn.html.markdown | 411 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 zh-cn/scala-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown new file mode 100644 index 00000000..419f0fb2 --- /dev/null +++ b/zh-cn/scala-cn.html.markdown @@ -0,0 +1,411 @@ +--- +language: Scala +filename: learnscala.scala +contributors: + - ["George Petrov", "http://github.com/petrovg"] + - ["Dominic Bou-Samra", "http://dbousamra.github.com"] +translators: + - ["Peiyong Lin", ""] +filename: learn.scala +lang: zh-cn +--- + +Scala - 一门可拓展性的语言 + +```cpp + +/* + 自行设置: + + 1) 下载 Scala - http://www.scala-lang.org/downloads + 2) unzip/untar 到你喜欢的地方,放在路径中的 bin 目录下 + 3) 在终端输入 scala,开启 Scala 的 REPL,你会看到提示符: + + scala> + + 这就是所谓的 REPL,你现在可以在其中运行命令,让我们做到这一点: +*/ + +println(10) // 打印整数 10 + +println("Boo!") // 打印字符串 "BOO!" + + +// 一些基础 + +// 打印并强制换行 +println("Hello world!") +// 没有强制换行的打印 +print("Hello world") + +// 通过 var 或者 val 来声明变量 +// val 声明是不可变的,var 声明是可修改的。不可变性是好事。 +val x = 10 // x 现在是 10 +x = 20 // 错误: 对 val 声明的变量重新赋值 +var x = 10 +x = 20 // x 现在是 20 + +// 单行注释开始于两个斜杠 +/* +多行注释看起来像这样。 +*/ + +// 布尔值 +true +false + +// 布尔操作 +!true // false +!false // true +true == false // false +10 > 5 // true + +// 数学运算像平常一样 +1 + 1 // 2 +2 - 1 // 1 +5 * 3 // 15 +6 / 2 // 3 + + +// 在 REPL 计算一个命令会返回给你结果的类型和值 + +1 + 7 + +/* 上行的结果是: + + scala> 1 + 7 + res29: Int = 8 + + 这意味着计算 1 + 7 的结果是一个 Int 类型的对象,其值为 8 + + 1+7 的结果是一样的 +*/ + + +// 包括函数在内,每一个事物都是对象。在 REPL 中输入: + +7 // 结果 res30: Int = 7 (res30 是一个生成的结果的 var 命名) + +// 下一行给你一个接收一个 Int 类型并返回该数的平方的函数 +(x:Int) => x * x + +// 你可以分配给函数一个标识符,像这样: +val sq = (x:Int) => x * x + +/* 上面的例子说明 + + sq: Int => Int = + + 意味着这次我们给予了 sq 这样一个显式的名字给一个接受一个 Int 类型值并返回 一个 Int 类型值的函数 + + sq 可以像下面那样被执行: +*/ + +sq(10) // 返回给你:res33: Int = 100. + +// Scala 允许方法和函数返回或者接受其它的函数或者方法作为参数。 + +val add10: Int => Int = _ + 10 // 一个接受一个 Int 类型参数并返回一个 Int 类型值的函数 +List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被应用到每一个元素 + +// 匿名函数可以被使用来代替有命名的函数: +List(1, 2, 3) map (x => x + 10) + +// 下划线标志,如果匿名函数只有一个参数可以被使用来表示该参数变量 +List(1, 2, 3) map (_ + 10) + +// 如果你所应用的匿名块和匿名函数都接受一个参数,那么你甚至可以省略下划线 +List("Dom", "Bob", "Natalia") foreach println + + + +// 数据结构 + +val a = Array(1, 2, 3, 5, 8, 13) +a(0) +a(3) +a(21) // 这会抛出一个异常 + +val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") +m("fork") +m("spoon") +m("bottle") // 这会抛出一个异常 + +val safeM = m.withDefaultValue("no lo se") +safeM("bottle") + +val s = Set(1, 3, 7) +s(0) +s(1) + +/* 查看 map 的文档 + * 点击[这里](http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map) + * 确保你可以读它 + */ + + +// 元组 + +(1, 2) + +(4, 3, 2) + +(1, 2, "three") + +(a, 2, "three") + +// 为什么有这个? + +val divideInts = (x:Int, y:Int) => (x / y, x % y) + +divideInts(10,3) // 函数 divideInts 返回你结果和余数 + +// 要读取元组的元素,使用 _._n,n是从1开始的元素索引 + +val d = divideInts(10,3) + +d._1 + +d._2 + + + +// 选择器 + +s.map(sq) + +val sSquared = s. map(sq) + +sSquared.filter(_ < 10) + +sSquared.reduce (_+_) + +// filter 函数接受一个预测(一个函数,形式为 A -> Boolean) 并选择出所有的元素满足这个预测 + +List(1, 2, 3) filter (_ > 2) // List(3) +List( + Person(name = "Dom", age = 23), + Person(name = "Bob", age = 30) +).filter(_.age > 25) // List(Person("Bob", 30)) + + +// Scala 的 foreach 方法定义在特定的接受一个类型的集合上 +// 返回 Unit(一个 void 方法) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println + + + + +// For 包含 + +for { n <- s } yield sq(n) + +val nSquared2 = for { n <- s } yield sq(n) + +for { n <- nSquared2 if n < 10 } yield n + +for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared + +/* 注意:这些不是 for 循环. 一个 for 循环的语义是 '重复'('repeat'), + 然而,一个 for-包含 定义了一个两个数据结合间的关系 */ + + + +// 循环和迭代 + +1 to 5 +val r = 1 to 5 +r.foreach( println ) + +r foreach println +// 注意:Scala 是相当宽容的当它遇到点和括号 - 分别地学习这些规则。 +// 这帮助你编写读起来像英语的 DSLs 和 APIs + +(5 to 1 by -1) foreach ( println ) + +// while 循环 +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + +while (i < 10) { println("i " + i); i+=1 } // 发生了什么?为什么? + +i // 展示 i 的值。注意到 while 是一个传统意义上的循环 + // 它顺序地执行并且改变循环变量的值。while 非常快,比 Java // 循环快, + // 但是在其上使用选择器和包含更容易理解和并行。 + +// do while 循环 +do { + println("x is still less then 10"); + x += 1 +} while (x < 10) + +// 在 Scala中,尾递归是一种惯用的执行循环的方式。 +// 递归函数需要显示的返回类型,编译器不能推断出类型。 +// 这里它是 Unit。 +def showNumbersInRange(a:Int, b:Int):Unit = { + print(a) + if (a < b) + showNumbersInRange(a + 1, b) +} + + + +// 条件语句 + +val x = 10 + +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") + +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" + +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + + + +// 面向对象特性 + +// 类名是 Dog +class Dog { + //bark 方法,返回字符串 + def bark: String = { + // the body of the method + "Woof, woof!" + } +} + +// 类可以包含几乎其它的构造,包括其它的类, +// 函数,方法,对象,case 类,特性等等。 + + + +// Case 类 + +case class Person(name:String, phoneNumber:String) + +Person("George", "1234") == Person("Kate", "1236") + + + + +// 模式匹配 + +val me = Person("George", "1234") + +me match { case Person(name, number) => { + "We matched someone : " + name + ", phone : " + number }} + +me match { case Person(name, number) => "Match : " + name; case _ => "Hm..." } + +me match { case Person("George", number) => "Match"; case _ => "Hm..." } + +me match { case Person("Kate", number) => "Match"; case _ => "Hm..." } + +me match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } + +val kate = Person("Kate", "1234") + +kate match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } + + + +// 正则表达式 + +val email = "(.*)@(.*)".r // 在字符串上调用 r 会使它变成一个正则表达式 + +val email(user, domain) = "henry@zkpr.com" + +"mrbean@pyahoo.com" match { + case email(name, domain) => "I know your name, " + name +} + + + +// 字符串 + +"Scala 字符串被双引号包围" // +'a' // Scala 字符 +'单引号的字符串不存在' // 错误 +"字符串拥有通常的 Java 方法定义在其上".length +"字符串也有额外的 Scala 方法".reverse + +// 参见: scala.collection.immutable.StringOps + +println("ABCDEF".length) +println("ABCDEF".substring(2, 6)) +println("ABCDEF".replace("C", "3")) + +val n = 45 +println(s"We have $n apples") + +val a = Array(11, 9, 6) +println(s"My second daughter is ${a(2-1)} years old") + +// 一些字符需要被转义,举例来说,字符串中的双引号: +val a = "They stood outside the \"Rose and Crown\"" + +// 三个双引号使得字符串可以跨行并且可以包含引号(无需转义) + +val html = """
+

Press belo', Joe

+ | +
""" + + + +// 应用结果和组织 + +// import +import scala.collection.immutable.List + +// Import 所有的子包 +import scala.collection.immutable._ + +// 在一条语句中 Import 多个类 +import scala.collection.immutable.{List, Map} + +// 使用 '=>' 来重命名一个 import +import scala.collection.immutable{ List => ImmutableList } + +// import 除了一些类的其它所有的类。下面的例子除去了 Map 类和 Set 类: +import scala.collection.immutable.{Map => _, Set => _, _} + +// 在 scala 源文件中,你的程序入口点使用一个拥有单一方法 main 的对象来定义: + +object Application { + def main(args: Array[String]): Unit = { + // stuff goes here. + } +} + +// 文件可以包含多个类和对象。由 scalac 来编译 + + + + +// 输入和输出 + +// 一行一行读取文件 +import scala.io.Source +for(line <- Source.fromPath("myfile.txt").getLines()) + println(line) + +// 使用 Java 的 PrintWriter 来写文件 + + +``` + +## 更多的资源 + +[为没耐心的人准备的 Scala](http://horstmann.com/scala/) + +[Twitter Scala school](http://twitter.github.io/scala_school/) + +[The scala documentation](http://www.scala-lang.org/documentation/) + +加入 [Scala 用户组](https://groups.google.com/forum/#!forum/scala-user) -- cgit v1.2.3 From ec0a187f8160d425c6462fff8d3140f64c50909b Mon Sep 17 00:00:00 2001 From: lpy Date: Mon, 12 Aug 2013 14:11:45 +0800 Subject: Add new link into scala-cn.html.markdown --- zh-cn/scala-cn.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 419f0fb2..9f776090 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -406,6 +406,8 @@ for(line <- Source.fromPath("myfile.txt").getLines()) [Twitter Scala school](http://twitter.github.io/scala_school/) -[The scala documentation](http://www.scala-lang.org/documentation/) +[The Scala documentation](http://www.scala-lang.org/documentation/) + +[在浏览器尝试 Scala](http://scalatutorials.com/tour/) 加入 [Scala 用户组](https://groups.google.com/forum/#!forum/scala-user) -- cgit v1.2.3 From 46ce57a23cfc9518c79c264ba867c6025ca54bdd Mon Sep 17 00:00:00 2001 From: lyuehh Date: Mon, 12 Aug 2013 22:56:50 +0800 Subject: Add Chinese Translation for racket --- zh-cn/racket-cn.html.markdown | 607 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 607 insertions(+) create mode 100644 zh-cn/racket-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/racket-cn.html.markdown b/zh-cn/racket-cn.html.markdown new file mode 100644 index 00000000..9370d300 --- /dev/null +++ b/zh-cn/racket-cn.html.markdown @@ -0,0 +1,607 @@ +--- + +language: racket +filename: learnracket.rkt +contributors: + - ["th3rac25", "https://github.com/voila"] + - ["Eli Barzilay", "https://github.com/elibarzilay"] + - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"] +translators: + - ["lyuehh", "https://github.com/lyuehh"] +--- + +Racket是Lisp/Scheme家族中的一个通用的,多范式的编程语言。 +非常期待您的反馈!你可以通过[@th3rac25](http://twitter.com/th3rac25)或以用户名为th3rac25的Google游戏爱你过服务 + +```racket +#lang racket ; 声明我们使用的语言 + +;;; 注释 + +;; 单行注释以分号开始 + +#| 块注释 + 可以横跨很多行而且... + #| + 可以嵌套 + |# +|# + +;; S表达式注释忽略剩下的表达式 +;; 在调试的时候会非常有用 +#; (被忽略的表达式) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 1. 原始数据类型和操作符 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 数字 +9999999999999999999999 ; 整数 +#b111 ; 二进制数字 => 7 +#o111 ; 八进制数字 => 73 +#x111 ; 十六进制数字 => 273 +3.14 ; 实数 +6.02e+23 +1/2 ; 有理数 +1+2i ; 复数 + +;; 函数调用写作(f x y z ...) +;; 在这里 f 是一个函数, x, y, z, ... 是参数 +;; 如果你想创建一个列表数据的字面量, 使用 ' 来阻止它们 +;; 被求值 +'(+ 1 2) ; => (+ 1 2) +;; 接下来,是一些数学运算 +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(quotient 5 2) ; => 2 +(remainder 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(exact->inexact 1/3) ; => 0.3333333333333333 +(+ 1+2i 2-3i) ; => 3-1i + +;;; 布尔类型 +#t ; 为真 +#f ; 为假,#f 之外的任何值都是真 +(not #t) ; => #f +(and 0 #f (error "doesn't get here")) ; => #f +(or #f 0 (error "doesn't get here")) ; => 0 + +;;; 字符 +#\A ; => #\A +#\λ ; => #\λ +#\u03BB ; => #\λ + +;;; 字符串是字符组成的定长数组 +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ; \是转义字符 +"Foo\tbar\41\x21\u0021\a\r\n" ; 包含C语言的转义字符,和Unicode +"λx:(μα.α→α).xx" ; 字符串可以包含Unicode字符 + +;; 字符串可以相加 +(string-append "Hello " "world!") ; => "Hello world!" + +;; 一个字符串可以看做是一个包含字符的列表 +(string-ref "Apple" 0) ; => #\A + +;; format 可以用来格式化字符串 +(format "~a can be ~a" "strings" "formatted") + +;; 打印字符串非常简单 +(printf "I'm Racket. Nice to meet you!\n") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. 变量 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 你可以使用 define 定义一个变量 +;; 变量的名字可以使用任何字符除了: ()[]{}",'`;#|\ +(define some-var 5) +some-var ; => 5 + +;; 你也可以使用Unicode字符 +(define ⊆ subset?) +(⊆ (set 3 2) (set 1 2 3)) ; => #t + +;; 访问未赋值的变量会引发一个异常 +; x ; => x: undefined ... + +;; 本地绑定: `me' 被绑定到 "Bob",并且只在 let 中生效 +(let ([me "Bob"]) + "Alice" + me) ; => "Bob" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 结构和集合 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 结构体 +(struct dog (name breed age)) +(define my-pet + (dog "lassie" "collie" 5)) +my-pet ; => # +(dog? my-pet) ; => #t +(dog-name my-pet) ; => "lassie" + +;;; 对 (不可变的) +;; `cons' 函数返回对, `car' 和 `cdr' 从对中提取第1个 +;; 和第2个元素 +(cons 1 2) ; => '(1 . 2) +(car (cons 1 2)) ; => 1 +(cdr (cons 1 2)) ; => 2 + +;;; 列表 + +;; 列表由链表构成, 由 `cons' 函数的结果 +;; 和一个 `null' (或者 '()) 构成,后者标记了这个列表的结束 +(cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3) +;; `list' 给列表提供了一个非常方便的可变参数的生成器 +(list 1 2 3) ; => '(1 2 3) +;; 一个单引号也可以用来表示一个列表字面量 +'(1 2 3) ; => '(1 2 3) + +;; 仍然可以使用 `cons' 函数在列表的开始处添加一项 +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;; `append' 函数可以将两个列表合并 +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;; 列表是非常基础的类型,所以有*很多*操作列表的方法 +;; 下面是一些例子: +(map add1 '(1 2 3)) ; => '(2 3 4) +(map + '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(filter even? '(1 2 3 4)) ; => '(2 4) +(count even? '(1 2 3 4)) ; => 2 +(take '(1 2 3 4) 2) ; => '(1 2) +(drop '(1 2 3 4) 2) ; => '(3 4) + +;;; 向量 + +;; 向量是定长的数组 +#(1 2 3) ; => '#(1 2 3) + +;; 使用 `vector-append' 方法将2个向量合并 +(vector-append #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + +;;; Set(翻译成集合也不太合适,所以不翻译了..) + +;; 从一个列表创建一个Set +(list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3) + +;; 使用 `set-add' 函数增加一个成员 +;; (函数式特性: 这里会返回一个扩展后的Set,而不是修改输入的值) +(set-add (set 1 2 3) 4) ; => (set 1 2 3 4) + +;; 使用 `set-remove' 函数移除一个成员 +(set-remove (set 1 2 3) 1) ; => (set 2 3) + +;; 使用 `set-member?' 函数测试成员是否存在 +(set-member? (set 1 2 3) 1) ; => #t +(set-member? (set 1 2 3) 4) ; => #f + +;;; 散列表 + +;; 创建一个不变的散列表 (可变散列表的例子在下面) +(define m (hash 'a 1 'b 2 'c 3)) + +;; 根据键取得值 +(hash-ref m 'a) ; => 1 + +;; 获取一个不存在的键是一个异常 +; (hash-ref m 'd) => 没有找到元素 + +;; 你可以给不存在的键提供一个默认值 +(hash-ref m 'd 0) ; => 0 + +;; 使用 `hash-set' 函数来扩展一个不可变的散列表 +;; (返回的是扩展后的散列表而不是修改它) +(define m2 (hash-set m 'd 4)) +m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3)) + +;; 记住,使用 `hash` 函数创建的散列表是不可变的 +m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' + +;; 使用 `hash-remove' 函数移除一个键值对 (函数式特性,m并不变) +(hash-remove m 'a) ; => '#hash((b . 2) (c . 3)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 函数 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用 `lambda' 创建函数 +;; 函数总是返回它最后一个表达式的值 +(lambda () "Hello World") ; => # +;; 也可以使用 Unicode 字符 `λ' +(λ () "Hello World") ; => 同样的函数 + +;; 使用括号调用一个函数,也可以直接调用一个 lambda 表达式 +((lambda () "Hello World")) ; => "Hello World" +((λ () "Hello World")) ; => "Hello World" + +;; 将函数赋值为一个变量 +(define hello-world (lambda () "Hello World")) +(hello-world) ; => "Hello World" + +;; 你可以使用函数定义的语法糖来简化代码 +(define (hello-world2) "Hello World") + +;; `()`是函数的参数列表 +(define hello + (lambda (name) + (string-append "Hello " name))) +(hello "Steve") ; => "Hello Steve" +;; 同样的,可以使用语法糖来定义: +(define (hello2 name) + (string-append "Hello " name)) + +;; 你也可以使用可变参数, `case-lambda' +(define hello3 + (case-lambda + [() "Hello World"] + [(name) (string-append "Hello " name)])) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" +;; ... 或者给参数指定一个可选的默认值 +(define (hello4 [name "World"]) + (string-append "Hello " name)) + +;; 函数可以将多余的参数放到一个列表里 +(define (count-args . args) + (format "You passed ~a args: ~a" (length args) args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" +;; ... 也可以使用不带语法糖的 `lambda' 形式: +(define count-args2 + (lambda args + (format "You passed ~a args: ~a" (length args) args))) + +;; 你可以混用两种用法 +(define (hello-count name . args) + (format "Hello ~a, you passed ~a extra args" name (length args))) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" +;; ... 不带语法糖的形式: +(define hello-count2 + (lambda (name . args) + (format "Hello ~a, you passed ~a extra args" name (length args)))) + +;; 使用关键字 +(define (hello-k #:name [name "World"] #:greeting [g "Hello"] . args) + (format "~a ~a, ~a extra args" g name (length args))) +(hello-k) ; => "Hello World, 0 extra args" +(hello-k 1 2 3) ; => "Hello World, 3 extra args" +(hello-k #:greeting "Hi") ; => "Hi World, 0 extra args" +(hello-k #:name "Finn" #:greeting "Hey") ; => "Hey Finn, 0 extra args" +(hello-k 1 2 3 #:greeting "Hi" #:name "Finn" 4 5 6) + ; => "Hi Finn, 6 extra args" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. 判断是否相等 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 判断数字使用 `=' +(= 3 3.0) ; => #t +(= 2 1) ; => #f + +;; 判断对象使用 `eq?' +(eq? 3 3) ; => #t +(eq? 3 3.0) ; => #f +(eq? (list 3) (list 3)) ; => #f + +;; 判断集合使用 `equal?' +(equal? (list 'a 'b) (list 'a 'b)) ; => #t +(equal? (list 'a 'b) (list 'b 'a)) ; => #f + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. 控制结构 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 条件判断 + +(if #t ; 测试表达式 + "this is true" ; 为真的表达式 + "this is false") ; 为假的表达式 +; => "this is true" + +;; 注意, 除 `#f` 之外的所有值都认为是真 +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(Groucho Zeppo) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'yep + +;; `cond' 会进行一系列的判断来选择一个结果 +(cond [(> 2 2) (error "wrong!")] + [(< 2 2) (error "wrong again!")] + [else 'ok]) ; => 'ok + +;;; 模式匹配 + +(define (fizzbuzz? n) + (match (list (remainder n 3) (remainder n 5)) + [(list 0 0) 'fizzbuzz] + [(list 0 _) 'fizz] + [(list _ 0) 'buzz] + [_ #f])) + +(fizzbuzz? 15) ; => 'fizzbuzz +(fizzbuzz? 37) ; => #f + +;;; 循环 + +;; 循环可以使用递归(尾递归) +(define (loop i) + (when (< i 10) + (printf "i=~a\n" i) + (loop (add1 i)))) +(loop 5) ; => i=5, i=6, ... + +;; 类似的,可以使用 `let` 定义 +(let loop ((i 0)) + (when (< i 10) + (printf "i=~a\n" i) + (loop (add1 i)))) ; => i=0, i=1, ... + +;; 看上面的例子怎么增加一个新的 `loop' 形式, 但是 Racket 已经有了一个非常 +;; 灵活的 `for' 了: +(for ([i 10]) + (printf "i=~a\n" i)) ; => i=0, i=1, ... +(for ([i (in-range 5 10)]) + (printf "i=~a\n" i)) ; => i=5, i=6, ... + +;;; 其他形式的迭代 +;; `for' 允许在很多数据结构中迭代: +;; 列表, 向量, 字符串, Set, 散列表, 等... + +(for ([i (in-list '(l i s t))]) + (displayln i)) + +(for ([i (in-vector #(v e c t o r))]) + (displayln i)) + +(for ([i (in-string "string")]) + (displayln i)) + +(for ([i (in-set (set 'x 'y 'z))]) + (displayln i)) + +(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))]) + (printf "key:~a value:~a\n" k v)) + +;;; 更多复杂的迭代 + +;; 并行扫描多个序列 (遇到长度小的就停止) +(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j)) +; => 0:x 1:y 2:z + +;; 嵌套循环 +(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j)) +; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z + +;; 带有条件判断的 `for` +(for ([i 1000] + #:when (> i 5) + #:unless (odd? i) + #:break (> i 10)) + (printf "i=~a\n" i)) +; => i=6, i=8, i=10 + +;;; 更多的例子帮助你加深理解.. +;; 和 `for' 循环非常像 -- 收集结果 + +(for/list ([i '(1 2 3)]) + (add1 i)) ; => '(2 3 4) + +(for/list ([i '(1 2 3)] #:when (even? i)) + i) ; => '(2) + +(for/list ([i 10] [j '(x y z)]) + (list i j)) ; => '((0 x) (1 y) (2 z)) + +(for/list ([i 1000] #:when (> i 5) #:unless (odd? i) #:break (> i 10)) + i) ; => '(6 8 10) + +(for/hash ([i '(1 2 3)]) + (values i (number->string i))) +; => '#hash((1 . "1") (2 . "2") (3 . "3")) + +;; 也有很多其他的内置方法来收集循环中的值: +(for/sum ([i 10]) (* i i)) ; => 285 +(for/product ([i (in-range 1 11)]) (* i i)) ; => 13168189440000 +(for/and ([i 10] [j (in-range 10 20)]) (< i j)) ; => #t +(for/or ([i 10] [j (in-range 0 20 2)]) (= i j)) ; => #t +;; 如果需要合并计算结果, 使用 `for/fold' +(for/fold ([sum 0]) ([i '(1 2 3 4)]) (+ sum i)) ; => 10 +;; (这个函数可以在大部分情况下替代普通的命令式循环) + +;;; 异常 + +;; 要捕获一个异常,使用 `with-handlers' 形式 +(with-handlers ([exn:fail? (lambda (exn) 999)]) + (+ 1 "2")) ; => 999 +(with-handlers ([exn:break? (lambda (exn) "no time")]) + (sleep 3) + "phew") ; => "phew", 如果你打断了它,那么结果 => "no time" + +;; 使用 `raise' 抛出一个异常后者其他任何值 +(with-handlers ([number? ; 捕获抛出的数字类型的值 + identity]) ; 将它们作为普通值 + (+ 1 (raise 2))) ; => 2 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. 可变的值 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用 `set!' 给一个已经存在的变量赋一个新值 +(define n 5) +(set! n (add1 n)) +n ; => 6 + +;; 给那些明确的需要变化的值使用 `boxes` (在其他语言里类似指针 +;; 或者引用) +(define n* (box 5)) +(set-box! n* (add1 (unbox n*))) +(unbox n*) ; => 6 + +;; 很多 Racket 诗句类型是不可变的 (对,列表,等),有一些既是可变的 +;; 又是不可变的 (字符串,向量,散列表 +;; 等...) + +;; 使用 `vector' 或者 `make-vector' 创建一个可变的向量 +(define vec (vector 2 2 3 4)) +(define wall (make-vector 100 'bottle-of-beer)) +;; 使用 `vector-set!` 更新一项 +(vector-set! vec 0 1) +(vector-set! wall 99 'down) +vec ; => #(1 2 3 4) + +;; 创建一个空的可变散列表,然后操作它 +(define m3 (make-hash)) +(hash-set! m3 'a 1) +(hash-set! m3 'b 2) +(hash-set! m3 'c 3) +(hash-ref m3 'a) ; => 1 +(hash-ref m3 'd 0) ; => 0 +(hash-remove! m3 'a) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. 模块 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 模块让你将你的代码组织为多个文件,成为可重用的模块, +;; 在这里,我们使用嵌套在本文的整个大模块 +;; 里的子模块(从 "#lang" 这一行开始) + +(module cake racket/base ; 基于 racket/base 定义一个 `cake` 模块 + + (provide print-cake) ; 这个模块导出的函数 + + (define (print-cake n) + (show " ~a " n #\.) + (show " .-~a-. " n #\|) + (show " | ~a | " n #\space) + (show "---~a---" n #\-)) + + (define (show fmt n ch) ; 内部函数 + (printf fmt (make-string n ch)) + (newline))) + +;; 使用 `require` 从模块中得到所有 `provide` 的函数 +(require 'cake) ; 这里的 `'`表示是本地的子模块 +(print-cake 3) +; (show "~a" 1 #\A) ; => 报错, `show' 没有被导出,不存在 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 8. 类和对象 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 创建一个 fish% 类(%是给类绑定用的) +(define fish% + (class object% + (init size) ; 初始化的参数 + (super-new) ; 父类的初始化 + ;; 域 + (define current-size size) + ;; 公共方法 + (define/public (get-size) + current-size) + (define/public (grow amt) + (set! current-size (+ amt current-size))) + (define/public (eat other-fish) + (grow (send other-fish get-size))))) + +;; 创建一个 fish% 类的示例 +(define charlie + (new fish% [size 10])) + +;; 使用 `send' 调用一个对象的方法 +(send charlie get-size) ; => 10 +(send charlie grow 6) +(send charlie get-size) ; => 16 + +;; `fish%' 是一个普通的值,我们可以用它来混入 +(define (add-color c%) + (class c% + (init color) + (super-new) + (define my-color color) + (define/public (get-color) my-color))) +(define colored-fish% (add-color fish%)) +(define charlie2 (new colored-fish% [size 10] [color 'red])) +(send charlie2 get-color) +;; 或者,不带名字 +(send (new (add-color fish%) [size 10] [color 'red]) get-color) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 9. 宏 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 宏让你扩展这门语言的语法 + +;; 让我们定义一个while循环 +(define-syntax-rule (while condition body ...) + (let loop () + (when condition + body ... + (loop)))) + +(let ([i 0]) + (while (< i 10) + (displayln i) + (set! i (add1 i)))) + +;; 宏是安全的,你不能修改现有的变量 +(define-syntax-rule (swap! x y) ; !表示会修改 + (let ([tmp x]) + (set! x y) + (set! y tmp))) + +(define tmp 2) +(define other 3) +(swap! tmp other) +(printf "tmp = ~a; other = ~a\n" tmp other) +;; 变量 `tmp` 被重命名为 `tmp_1` +;; 避免名字冲突 +;; (let ([tmp_1 tmp]) +;; (set! tmp other) +;; (set! other tmp_1)) + +;; 但它们仍然会导致错误代码,比如: +(define-syntax-rule (bad-while condition body ...) + (when condition + body ... + (bad-while condition body ...))) +;; 这个宏会挂掉,它产生了一个无限循环,如果你试图去使用它 +;; 编译器会进入死循环 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 10. 契约 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 契约限制变量从模块中导入 + +(module bank-account racket + (provide (contract-out + [deposit (-> positive? any)] ; 数量一直是正值 + [balance (-> positive?)])) + + (define amount 0) + (define (deposit a) (set! amount (+ amount a))) + (define (balance) amount) + ) + +(require 'bank-account) +(deposit 5) + +(balance) ; => 5 + +;; 客户端尝试存储一个负值时会出错 +;; (deposit -5) ; => deposit: contract violation +;; expected: positive? +;; given: -5 +;; more details.... +``` + +## 进一步阅读 + +想知道更多吗? 尝试 [Getting Started with Racket](http://docs.racket-lang.org/getting-started/) -- cgit v1.2.3 From 73e700e0138d7b4c953d8f5990118d9c55ecfa41 Mon Sep 17 00:00:00 2001 From: lyuehh Date: Mon, 12 Aug 2013 23:02:44 +0800 Subject: fix typo --- zh-cn/racket-cn.html.markdown | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/racket-cn.html.markdown b/zh-cn/racket-cn.html.markdown index 9370d300..e17aedda 100644 --- a/zh-cn/racket-cn.html.markdown +++ b/zh-cn/racket-cn.html.markdown @@ -11,7 +11,7 @@ translators: --- Racket是Lisp/Scheme家族中的一个通用的,多范式的编程语言。 -非常期待您的反馈!你可以通过[@th3rac25](http://twitter.com/th3rac25)或以用户名为th3rac25的Google游戏爱你过服务 +非常期待您的反馈!你可以通过[@th3rac25](http://twitter.com/th3rac25)或以用户名为 th3rac25 的Google邮箱服务和我取得联系 ```racket #lang racket ; 声明我们使用的语言 @@ -125,7 +125,7 @@ my-pet ; => # (dog-name my-pet) ; => "lassie" ;;; 对 (不可变的) -;; `cons' 函数返回对, `car' 和 `cdr' 从对中提取第1个 +;; `cons' 返回对, `car' 和 `cdr' 从对中提取第1个 ;; 和第2个元素 (cons 1 2) ; => '(1 . 2) (car (cons 1 2)) ; => 1 @@ -133,7 +133,7 @@ my-pet ; => # ;;; 列表 -;; 列表由链表构成, 由 `cons' 函数的结果 +;; 列表由链表构成, 由 `cons' 的结果 ;; 和一个 `null' (或者 '()) 构成,后者标记了这个列表的结束 (cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3) ;; `list' 给列表提供了一个非常方便的可变参数的生成器 @@ -141,7 +141,7 @@ my-pet ; => # ;; 一个单引号也可以用来表示一个列表字面量 '(1 2 3) ; => '(1 2 3) -;; 仍然可以使用 `cons' 函数在列表的开始处添加一项 +;; 仍然可以使用 `cons' 在列表的开始处添加一项 (cons 4 '(1 2 3)) ; => '(4 1 2 3) ;; `append' 函数可以将两个列表合并 @@ -169,14 +169,14 @@ my-pet ; => # ;; 从一个列表创建一个Set (list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3) -;; 使用 `set-add' 函数增加一个成员 +;; 使用 `set-add' 增加一个成员 ;; (函数式特性: 这里会返回一个扩展后的Set,而不是修改输入的值) (set-add (set 1 2 3) 4) ; => (set 1 2 3 4) -;; 使用 `set-remove' 函数移除一个成员 +;; 使用 `set-remove' 移除一个成员 (set-remove (set 1 2 3) 1) ; => (set 2 3) -;; 使用 `set-member?' 函数测试成员是否存在 +;; 使用 `set-member?' 测试成员是否存在 (set-member? (set 1 2 3) 1) ; => #t (set-member? (set 1 2 3) 4) ; => #f @@ -194,15 +194,15 @@ my-pet ; => # ;; 你可以给不存在的键提供一个默认值 (hash-ref m 'd 0) ; => 0 -;; 使用 `hash-set' 函数来扩展一个不可变的散列表 +;; 使用 `hash-set' 来扩展一个不可变的散列表 ;; (返回的是扩展后的散列表而不是修改它) (define m2 (hash-set m 'd 4)) m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3)) -;; 记住,使用 `hash` 函数创建的散列表是不可变的 +;; 记住,使用 `hash` 创建的散列表是不可变的 m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' -;; 使用 `hash-remove' 函数移除一个键值对 (函数式特性,m并不变) +;; 使用 `hash-remove' 移除一个键值对 (函数式特性,m并不变) (hash-remove m 'a) ; => '#hash((b . 2) (c . 3)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -437,7 +437,7 @@ m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d' (set! n (add1 n)) n ; => 6 -;; 给那些明确的需要变化的值使用 `boxes` (在其他语言里类似指针 +;; 给那些明确地需要变化的值使用 `boxes` (在其他语言里类似指针 ;; 或者引用) (define n* (box 5)) (set-box! n* (add1 (unbox n*))) -- cgit v1.2.3 From 45ddaf5f46ea2e59bb8d8ad9038182d99a2c9550 Mon Sep 17 00:00:00 2001 From: hbc Date: Mon, 12 Aug 2013 23:13:20 +0800 Subject: Improved some translations, added a line break --- zh-cn/ruby-cn.html.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index 16c0ed67..fcc60162 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -94,7 +94,7 @@ x = y = 10 #=> 10 x #=> 10 y #=> 10 -# 按照惯例,用snake_case 作为变量名 +# 按照惯例,用 snake_case 作为变量名 snake_case = true # 使用具有描述性的运算符 @@ -102,7 +102,8 @@ path_to_project_root = '/good/name/' path = '/bad/name/' # 符号(Symbols,也是对象) -# 符号是不可变的,内部用整数类型表示的可重用的值。通常用它代替字符串来有效地表达有意义的值 +# 符号是不可变的,内部用整数类型表示的可重用的值。 +# 通常用它代替字符串来有效地表示有意义的值。 :pending.class #=> Symbol -- cgit v1.2.3 From bd48b7062c51aff7d27114326f64fde505cea49c Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 12 Aug 2013 09:53:40 -0700 Subject: Updated translation filenames to prevent collisions --- zh-cn/c-cn.html.markdown | 2 +- zh-cn/dart-cn.html.markdown | 2 +- zh-cn/elisp-cn.html.markdown | 2 +- zh-cn/git-cn.html.markdown | 1 - zh-cn/haskell-cn.html.markdown | 4 ++-- zh-cn/java-cn.html.markdown | 2 +- zh-cn/javascript-cn.html.markdown | 1 + zh-cn/php-cn.html.markdown | 2 +- zh-cn/python-cn.html.markdown | 2 +- zh-cn/ruby-cn.html.markdown | 2 +- zh-cn/scala-cn.html.markdown | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown index f8a8e0bd..b4bff8fc 100755 --- a/zh-cn/c-cn.html.markdown +++ b/zh-cn/c-cn.html.markdown @@ -1,6 +1,6 @@ --- language: c -filename: learnc.c +filename: learnc-cn.c contributors: - ["Adam Bard", "http://adambard.com/"] translators: diff --git a/zh-cn/dart-cn.html.markdown b/zh-cn/dart-cn.html.markdown index 1b0cceb9..6a6562bc 100644 --- a/zh-cn/dart-cn.html.markdown +++ b/zh-cn/dart-cn.html.markdown @@ -1,7 +1,7 @@ --- language: dart lang: zh-cn -filename: learndart.dart +filename: learndart-cn.dart contributors: - ["Joao Pedrosa", "https://github.com/jpedrosa/"] translators: diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown index c3a2f927..d303c2e8 100755 --- a/zh-cn/elisp-cn.html.markdown +++ b/zh-cn/elisp-cn.html.markdown @@ -4,7 +4,7 @@ contributors: - ["Bastien Guerry", "http://bzg.fr"] translators: - ["Chenbo Li", "http://binarythink.net"] -filename: learn-emacs-lisp.el +filename: learn-emacs-lisp-zh.el lang: zh-cn --- diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown index 8c24f0b8..86952eba 100755 --- a/zh-cn/git-cn.html.markdown +++ b/zh-cn/git-cn.html.markdown @@ -5,7 +5,6 @@ contributors: - ["Jake Prather", "http://github.com/JakeHP"] translators: - ["Chenbo Li", "http://binarythink.net"] -filename: LearnGit.txt lang: zh-cn --- diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index cb0de467..8d51f144 100755 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -1,6 +1,6 @@ --- language: haskell -filename: learn-haskell.hs +filename: learn-haskell-zh.hs contributors: - ["Adit Bhargava", "http://adit.io"] translators: @@ -404,4 +404,4 @@ qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater 你可以从优秀的 [Learn you a Haskell](http://learnyouahaskell.com/) 或者 [Real World Haskell](http://book.realworldhaskell.org/) -找到优雅不少的入门介绍。 \ No newline at end of file +找到优雅不少的入门介绍。 diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index b9ccf61a..9422ac2f 100755 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -3,7 +3,7 @@ name: java category: language language: java lang: zh-cn -filename: LearnJava.java +filename: LearnJava-zh.java contributors: - ["Jake Prather", "http://github.com/JakeHP"] translators: diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 3b5cfa94..89fc256e 100755 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -2,6 +2,7 @@ language: javascript category: language name: javascript +filename: javascript-zh.js contributors: - ["Adam Brenecki", "http://adam.brenecki.id.au"] translators: diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index 3b242ce1..c6ebb515 100755 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -5,7 +5,7 @@ contributors: - ["Trismegiste", "https://github.com/Trismegiste"] translators: - ["Chenbo Li", "http://binarythink.net"] -filename: learnphp.php +filename: learnphp-zh.php lang: zh-cn --- diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown index 259e4ed8..764eed54 100755 --- a/zh-cn/python-cn.html.markdown +++ b/zh-cn/python-cn.html.markdown @@ -4,7 +4,7 @@ contributors: - ["Louie Dinh", "http://ldinh.ca"] translators: - ["Chenbo Li", "http://binarythink.net"] -filename: learnpython.py +filename: learnpython-zh.py lang: zh-cn --- diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index 16c0ed67..6530b520 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -1,6 +1,6 @@ --- language: ruby -filename: learnruby.rb +filename: learnruby-zh.rb lang: zh-cn contributors: - ["David Underwood", "http://theflyingdeveloper.com"] diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 9f776090..1ce41ac6 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -1,6 +1,6 @@ --- language: Scala -filename: learnscala.scala +filename: learnscala-zh.scala contributors: - ["George Petrov", "http://github.com/petrovg"] - ["Dominic Bou-Samra", "http://dbousamra.github.com"] -- cgit v1.2.3 From 10637b0e77cca3daf5bd79e2d1eed2cb250a4192 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 13 Aug 2013 10:14:57 -0700 Subject: Header changes --- zh-cn/racket-cn.html.markdown | 1 + 1 file changed, 1 insertion(+) (limited to 'zh-cn') diff --git a/zh-cn/racket-cn.html.markdown b/zh-cn/racket-cn.html.markdown index e17aedda..d43511ea 100644 --- a/zh-cn/racket-cn.html.markdown +++ b/zh-cn/racket-cn.html.markdown @@ -1,6 +1,7 @@ --- language: racket +lang: zh-cn filename: learnracket.rkt contributors: - ["th3rac25", "https://github.com/voila"] -- cgit v1.2.3 From c5a3e191405e6722239c951635a2205c93d55bde Mon Sep 17 00:00:00 2001 From: hbc Date: Wed, 14 Aug 2013 08:19:05 +0800 Subject: Improved some translations, made the code more PEP8 --- zh-cn/python-cn.html.markdown | 277 +++++++++++++++++++++--------------------- 1 file changed, 139 insertions(+), 138 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown index 764eed54..51efaac3 100755 --- a/zh-cn/python-cn.html.markdown +++ b/zh-cn/python-cn.html.markdown @@ -17,6 +17,7 @@ Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语 如果是Python 3,请在网络上寻找其他教程 ```python + # 单行注释 """ 多行字符串可以用 三个引号包裹,不过这也可以被当做 @@ -28,84 +29,84 @@ Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语 #################################################### # 数字类型 -3 #=> 3 +3 # => 3 # 简单的算数 -1 + 1 #=> 2 -8 - 1 #=> 7 -10 * 2 #=> 20 -35 / 5 #=> 7 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 +35 / 5 # => 7 # 整数的除法会自动取整 -5 / 2 #=> 2 +5 / 2 # => 2 # 要做精确的除法,我们需要引入浮点数 2.0 # 浮点数 -11.0 / 4.0 #=> 2.75 好多了 +11.0 / 4.0 # => 2.75 精确多了 # 括号具有最高优先级 -(1 + 3) * 2 #=> 8 +(1 + 3) * 2 # => 8 -# 布尔值也是原始数据类型 +# 布尔值也是基本的数据类型 True False -# 用not来取非 -not True #=> False -not False #=> True +# 用 not 来取非 +not True # => False +not False # => True # 相等 -1 == 1 #=> True -2 == 1 #=> False +1 == 1 # => True +2 == 1 # => False # 不等 -1 != 1 #=> False -2 != 1 #=> True +1 != 1 # => False +2 != 1 # => True # 更多的比较操作符 -1 < 10 #=> True -1 > 10 #=> False -2 <= 2 #=> True -2 >= 2 #=> True +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True # 比较运算可以连起来写! -1 < 2 < 3 #=> True -2 < 3 < 2 #=> False +1 < 2 < 3 # => True +2 < 3 < 2 # => False -# 字符串通过"或'括起来 +# 字符串通过 " 或 ' 括起来 "This is a string." 'This is also a string.' # 字符串通过加号拼接 -"Hello " + "world!" #=> "Hello world!" +"Hello " + "world!" # => "Hello world!" # 字符串可以被视为字符的列表 -"This is a string"[0] #=> 'T' +"This is a string"[0] # => 'T' # % 可以用来格式化字符串 "%s can be %s" % ("strings", "interpolated") -# 也可以用format方法来格式化字符串 +# 也可以用 format 方法来格式化字符串 # 推荐使用这个方法 "{0} can be {1}".format("strings", "formatted") # 也可以用变量名代替数字 "{name} wants to eat {food}".format(name="Bob", food="lasagna") # None 是对象 -None #=> None +None # => None # 不要用相等 `==` 符号来和None进行比较 -# 要用 `is` -"etc" is None #=> False -None is None #=> True +# 要用 `is` +"etc" is None # => False +None is None # => True # 'is' 可以用来比较对象的相等性 # 这个操作符在比较原始数据时没多少用,但是比较对象时必不可少 -# None, 0, 和空字符串都被算作False -# 其他的均为True -0 == False #=> True -"" == False #=> True +# None, 0, 和空字符串都被算作 False +# 其他的均为 True +0 == False # => True +"" == False # => True #################################################### @@ -116,16 +117,16 @@ None is None #=> True print "I'm Python. Nice to meet you!" -# 给变量赋值前不需要事先生命 -some_var = 5 # 规范用小写字母和下划线来做为变量名 -some_var #=> 5 +# 给变量赋值前不需要事先声明 +some_var = 5 # 一般建议使用小写字母和下划线组合来做为变量名 +some_var # => 5 -# 访问之前为赋值的变量会抛出异常 -# 查看控制流程一节来了解异常处理 -some_other_var # 抛出命名异常 +# 访问未赋值的变量会抛出异常 +# 可以查看控制流程一节来了解如何异常处理 +some_other_var # 抛出 NameError -# if语句可以作为表达式来使用 -"yahoo!" if 3 > 2 else 2 #=> "yahoo!" +# if 语句可以作为表达式来使用 +"yahoo!" if 3 > 2 else 2 # => "yahoo!" # 列表用来保存序列 li = [] @@ -133,64 +134,64 @@ li = [] other_li = [4, 5, 6] # 在列表末尾添加元素 -li.append(1) #li 现在是 [1] -li.append(2) #li 现在是 [1, 2] -li.append(4) #li 现在是 [1, 2, 4] -li.append(3) #li 现在是 [1, 2, 4, 3] +li.append(1) # li 现在是 [1] +li.append(2) # li 现在是 [1, 2] +li.append(4) # li 现在是 [1, 2, 4] +li.append(3) # li 现在是 [1, 2, 4, 3] # 移除列表末尾元素 -li.pop() #=> 3 and li is now [1, 2, 4] -# 放回来 +li.pop() # => 3 li 现在是 [1, 2, 4] +# 重新加进去 li.append(3) # li is now [1, 2, 4, 3] again. # 像其他语言访问数组一样访问列表 -li[0] #=> 1 +li[0] # => 1 # 访问最后一个元素 -li[-1] #=> 3 +li[-1] # => 3 # 越界会抛出异常 -li[4] # 抛出越界异常 +li[4] # 抛出越界异常 # 切片语法需要用到列表的索引访问 # 可以看做数学之中左闭右开区间 -li[1:3] #=> [2, 4] +li[1:3] # => [2, 4] # 省略开头的元素 -li[2:] #=> [4, 3] +li[2:] # => [4, 3] # 省略末尾的元素 -li[:3] #=> [1, 2, 4] +li[:3] # => [1, 2, 4] # 删除特定元素 -del li[2] # li 现在是 [1, 2, 3] +del li[2] # li 现在是 [1, 2, 3] # 合并列表 -li + other_li #=> [1, 2, 3, 4, 5, 6] - 不改变这两个列表 +li + other_li # => [1, 2, 3, 4, 5, 6] - 并不会不改变这两个列表 -# 通过拼接合并列表 -li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6] +# 通过拼接来合并列表 +li.extend(other_li) # li 是 [1, 2, 3, 4, 5, 6] -# 用in来返回元素是否在列表中 -1 in li #=> True +# 用 in 来返回元素是否在列表中 +1 in li # => True # 返回列表长度 -len(li) #=> 6 +len(li) # => 6 -# 元组类似于列表,但是他是不可改变的 +# 元组类似于列表,但它是不可改变的 tup = (1, 2, 3) -tup[0] #=> 1 +tup[0] # => 1 tup[0] = 3 # 类型错误 # 对于大多数的列表操作,也适用于元组 -len(tup) #=> 3 -tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6) -tup[:2] #=> (1, 2) -2 in tup #=> True +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True # 你可以将元组解包赋给多个变量 -a, b, c = (1, 2, 3) # a是1,b是2,c是3 -# 如果不加括号,那么会自动视为元组 +a, b, c = (1, 2, 3) # a 是 1,b 是 2,c 是 3 +# 如果不加括号,将会被自动视为元组 d, e, f = 4, 5, 6 # 现在我们可以看看交换两个数字是多么容易的事 -e, d = d, e # d是5,e是4 +e, d = d, e # d 是 5,e 是 4 # 字典用来储存映射关系 @@ -199,59 +200,59 @@ empty_dict = {} filled_dict = {"one": 1, "two": 2, "three": 3} # 字典也用中括号访问元素 -filled_dict["one"] #=> 1 +filled_dict["one"] # => 1 # 把所有的键保存在列表中 -filled_dict.keys() #=> ["three", "two", "one"] +filled_dict.keys() # => ["three", "two", "one"] # 键的顺序并不是唯一的,得到的不一定是这个顺序 # 把所有的值保存在列表中 -filled_dict.values() #=> [3, 2, 1] +filled_dict.values() # => [3, 2, 1] # 和键的顺序相同 # 判断一个键是否存在 -"one" in filled_dict #=> True -1 in filled_dict #=> False +"one" in filled_dict # => True +1 in filled_dict # => False -# 查询一个不存在的键会抛出键异常 -filled_dict["four"] # 键异常 +# 查询一个不存在的键会抛出 KeyError +filled_dict["four"] # KeyError -# 用get方法来避免键异常 -filled_dict.get("one") #=> 1 -filled_dict.get("four") #=> None -# get方法支持在不存在的时候返回一个默认值 -filled_dict.get("one", 4) #=> 1 -filled_dict.get("four", 4) #=> 4 +# 用 get 方法来避免 KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# get 方法支持在不存在的时候返回一个默认值 +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 -# Setdefault是一个更安全的添加字典元素的方法 -filled_dict.setdefault("five", 5) #filled_dict["five"] 的值为 5 -filled_dict.setdefault("five", 6) #filled_dict["five"] 的值仍然是 5 +# setdefault 是一个更安全的添加字典元素的方法 +filled_dict.setdefault("five", 5) # filled_dict["five"] 的值为 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] 的值仍然是 5 # 集合储存无顺序的元素 empty_set = set() -# 出事话一个集合 -some_set = set([1,2,2,3,4]) # filled_set 现在是 set([1, 2, 3, 4]) +# 初始化一个集合 +some_set = set([1, 2, 2, 3, 4]) # filled_set 现在是 set([1, 2, 3, 4]) # Python 2.7 之后,大括号可以用来表示集合 -filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} +filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} -# 为集合添加元素 -filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} +# 向集合添加元素 +filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5} -# 用&来实现集合的交 +# 用 & 来计算集合的交 other_set = {3, 4, 5, 6} -filled_set & other_set #=> {3, 4, 5} +filled_set & other_set # => {3, 4, 5} -# 用|来实现集合的并 -filled_set | other_set #=> {1, 2, 3, 4, 5, 6} +# 用 | 来计算集合的并 +filled_set | other_set # => {1, 2, 3, 4, 5, 6} -# 用-来实现集合的差 -{1,2,3,4} - {2,3,5} #=> {1, 4} +# 用 - 来计算集合的差 +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} -# 用in来判断元素是否存在于集合中 -2 in filled_set #=> True -10 in filled_set #=> False +# 用 in 来判断元素是否存在于集合中 +2 in filled_set # => True +10 in filled_set # => False #################################################### @@ -261,13 +262,13 @@ filled_set | other_set #=> {1, 2, 3, 4, 5, 6} # 新建一个变量 some_var = 5 -# 这是个if语句,在python中缩进是很重要的。 -# 会输出 "some var is smaller than 10" +# 这是个 if 语句,在 python 中缩进是很重要的。 +# 下面的代码片段将会输出 "some var is smaller than 10" if some_var > 10: print "some_var is totally bigger than 10." elif some_var < 10: # 这个 elif 语句是不必须的 print "some_var is smaller than 10." -else: # 也不是必须的 +else: # 这个 else 也不是必须的 print "some_var is indeed 10." @@ -281,7 +282,7 @@ else: # 也不是必须的 for animal in ["dog", "cat", "mouse"]: # 你可以用 % 来格式化字符串 print "%s is a mammal" % animal - + """ `range(number)` 返回从0到给定数字的列表 输出: @@ -294,7 +295,7 @@ for i in range(4): print i """ -While循环 +while 循环 输出: 0 1 @@ -304,29 +305,29 @@ While循环 x = 0 while x < 4: print x - x += 1 # Shorthand for x = x + 1 + x += 1 # x = x + 1 的简写 -# 用 try/except块来处理异常 +# 用 try/except 块来处理异常 # Python 2.6 及以上适用: try: - # 用raise来抛出异常 + # 用 raise 来抛出异常 raise IndexError("This is an index error") except IndexError as e: - pass # Pass就是什么都不做,不过通常这里会做一些恢复工作 + pass # pass 就是什么都不做,不过通常这里会做一些恢复工作 #################################################### ## 4. 函数 #################################################### -# 用def来新建函数 +# 用 def 来新建函数 def add(x, y): print "x is %s and y is %s" % (x, y) - return x + y # Return values with a return statement + return x + y # 通过 return 来返回值 # 调用带参数的函数 -add(5, 6) #=> 输出 "x is 5 and y is 6" 返回 11 +add(5, 6) # => 输出 "x is 5 and y is 6" 返回 11 # 通过关键字赋值来调用函数 add(y=6, x=5) # 顺序是无所谓的 @@ -335,7 +336,7 @@ add(y=6, x=5) # 顺序是无所谓的 def varargs(*args): return args -varargs(1, 2, 3) #=> (1,2,3) +varargs(1, 2, 3) # => (1,2,3) # 我们也可以定义接受多个变量的函数,这些变量是按照关键字排列的 @@ -343,7 +344,7 @@ def keyword_args(**kwargs): return kwargs # 实际效果: -keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"} +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} # 你也可以同时将一个函数定义成两种形式 def all_the_args(*args, **kwargs): @@ -355,38 +356,38 @@ all_the_args(1, 2, a=3, b=4) prints: {"a": 3, "b": 4} """ -# 当调用函数的时候,我们也可以和之前所做的相反,把元组和字典展开为参数 +# 当调用函数的时候,我们也可以进行相反的操作,把元组和字典展开为参数 args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalent to foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivalent to foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) +all_the_args(*args) # 等价于 foo(1, 2, 3, 4) +all_the_args(**kwargs) # 等价于 foo(a=3, b=4) +all_the_args(*args, **kwargs) # 等价于 foo(1, 2, 3, 4, a=3, b=4) -# Python 有一等函数: +# 函数在 python 中是一等公民 def create_adder(x): def adder(y): return x + y return adder add_10 = create_adder(10) -add_10(3) #=> 13 +add_10(3) # => 13 # 匿名函数 -(lambda x: x > 2)(3) #=> True +(lambda x: x > 2)(3) # => True # 内置高阶函数 -map(add_10, [1,2,3]) #=> [11, 12, 13] -filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7] +map(add_10, [1, 2, 3]) # => [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] # 可以用列表方法来对高阶函数进行更巧妙的引用 -[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13] -[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7] +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] #################################################### ## 5. 类 #################################################### -# 我们新建的类是从object类中继承的 +# 我们新建的类是从 object 类中继承的 class Human(object): # 类属性,由所有类的对象共享 @@ -397,9 +398,9 @@ class Human(object): # 将参数赋给对象成员属性 self.name = name - # 成员方法,参数要有self + # 成员方法,参数要有 self def say(self, msg): - return "%s: %s" % (self.name, msg) + return "%s: %s" % (self.name, msg) # 类方法由所有类的对象共享 # 这类方法在调用时,会把类本身传给第一个参数 @@ -421,15 +422,15 @@ j = Human("Joel") print j.say("hello") # 输出 "Joel: hello" # 访问类的方法 -i.get_species() #=> "H. sapiens" +i.get_species() # => "H. sapiens" # 改变共享属性 Human.species = "H. neanderthalensis" -i.get_species() #=> "H. neanderthalensis" -j.get_species() #=> "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" # 访问静态变量 -Human.grunt() #=> "*grunt*" +Human.grunt() # => "*grunt*" #################################################### @@ -438,12 +439,12 @@ Human.grunt() #=> "*grunt*" # 我们可以导入其他模块 import math -print math.sqrt(16) #=> 4 +print math.sqrt(16) # => 4 -# 我们也可以从一个模块中特定的函数 +# 我们也可以从一个模块中导入特定的函数 from math import ceil, floor -print ceil(3.7) #=> 4.0 -print floor(3.7) #=> 3.0 +print ceil(3.7) # => 4.0 +print floor(3.7) # => 3.0 # 从模块中导入所有的函数 # 警告:不推荐使用 @@ -451,13 +452,13 @@ from math import * # 简写模块名 import math as m -math.sqrt(16) == m.sqrt(16) #=> True +math.sqrt(16) == m.sqrt(16) # => True # Python的模块其实只是普通的python文件 # 你也可以创建自己的模块,并且导入它们 # 模块的名字就和文件的名字相同 -# 以可以通过下面的信息找找要成为模块需要什么属性或方法 +# 也可以通过下面的方法查看模块中有什么属性和方法 import math dir(math) -- cgit v1.2.3 From 3497a0858a8aec1c0eab850b432f5a0c166df2a0 Mon Sep 17 00:00:00 2001 From: godtao Date: Thu, 15 Aug 2013 19:40:05 +0800 Subject: Add go-zh.html.markdown --- zh-cn/go-zh.html.markdown | 280 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 zh-cn/go-zh.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown new file mode 100644 index 00000000..6a4c09be --- /dev/null +++ b/zh-cn/go-zh.html.markdown @@ -0,0 +1,280 @@ +--- +名字:Go +分类:编程语言 +文件名:learngo.go +贡献者: + - ["Sonia Keys", "https://github.com/soniakeys"] +翻译者: + - ["pantaovay", "https://github.com/pantaovay"] +--- + +发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 + +Go拥有命令式语言的静态类型,编译很快,执行也很快,同时加入了对于目前多核CPU的并发计算支持,也有相应的特性来大规模编程。 + +Go语言有非常棒的标准库,还有一个充满热情的社区。 + +```Go +// 单行注释 +/* 多行 + 注释 */ + +// 导入包的子句在每个源文件的开头。 +// Main比较特殊,它用来声明可执行文件,而不是一个库。 +package main + +// Import语句声明了当前文件引用的包。 +import ( + "fmt" // Go语言标准库中的包 + "net/http" // 一个web服务器包 + "strconv" // 字符串转换 +) + +//函数声明:Main是程序执行的入口。不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 +func main() { + // 往标准输出打印一行。 + // 用包名fmt限制打印函数。 + fmt.Println("Hello world!") + + // 调用当前包的另一个函数。 + beyondHello() +} + +// 函数可以在括号里加参数。 +// 如果没有参数的话,也需要一个空括号。 +func beyondHello() { + var x int // 变量声明,变量必须在使用之前声明。 + x = 3 // 变量赋值。 + // 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。 + y := 4 + sum, prod := learnMultiple(x, y) // 多个返回变量的函数 + fmt.Println("sum:", sum, "prod:", prod) // 简单输出 + learnTypes() // 少于y分钟,学的更多! +} + +// 多变量和多返回值的函数 +func learnMultiple(x, y int) (sum, prod int) { + return x + y, x * y // 返回两个值 +} + +// 内置变量类型和关键词 +func learnTypes() { + // 短声明给你所想。 + s := "Learn Go!" // String类型 + + s2 := `A "raw" string literal +can include line breaks.` // 同样是String类型 + + // 非ascii字符。Go使用UTF-8编码。 + g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 + + f := 3.14195 // float64类型,IEEE-754 64位浮点数 + c := 3 + 4i // complex128类型,内部使用两个float64表示 + + // Var变量可以直接初始化。 + var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度 + var pi float32 = 22. / 7 + + // 字符转换 + n := byte('\n') // byte是uint8的别名 + + // 数组类型编译的时候大小固定。 + var a4 [4] int // 有4个int变量的数组,初始为0 + a3 := [...]int{3, 1, 5} // 有3个int变量的数组,同时进行了初始化 + + // Slice 有动态大小。Array和Slice各有千秋,但是使用slice的地方更多些。 + s3 := []int{4, 5, 9} // 和a3相比,这里没有省略号 + s4 := make([]int, 4) // 分配一个有4个int型变量的slice,全部被初始化为0 + + var d2 [][]float64 // 声明而已,什么都没有分配 + bs := []byte("a slice") // 类型转换的语法 + + p, q := learnMemory() // 声明p,q为int型变量的指针 + fmt.Println(*p, *q) // * 取值 + + // Map是动态可增长关联数组,和其他语言中的hash或者字典相似。 + m := map[string]int{"three": 3, "four": 4} + m["one"] = 1 + + // 在Go语言中未使用的变量在编译的时候会报错,而不是warning。 + // 下划线 _ 可以使你“使用”一个变量,但是丢弃它的值。 + _,_,_,_,_,_,_,_,_ = s2, g, f, u, pi, n, a3, s4, bs + // 输出变量 + fmt.Println(s, c, a4, s3, d2, m) + + learnFlowControl() // 回到流程控制 +} + +// Go全面支持垃圾回收。Go有指针,但是不支持指针运算。 +// 你会因为空指针而犯错,但是不会因为增加指针而犯错。 +func learnMemory() (p, q *int) { + // 返回int型变量指针p和q + p = new(int) // 内置函数new分配内存 + // 自动将分配的int赋值0,p不再是空的了。 + s := make([]int, 20) // 给20个int变量分配一块内存 + s[3] = 7 // 赋值 + r := -2 // 声明另一个局部变量 + return &s[3], &r // & 取址 +} + +func expensiveComputation() int { + return 1e6 +} + +func learnFlowControl() { + // If需要花括号,括号就免了 + if true { + fmt.Println("told ya") + } + // 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了,也不用容忍被人的代码风格。 + if false { + // pout + } else { + // gloat + } + // 如果太多嵌套的if语句,推荐使用switch + x := 1 + switch x { + case 0: + case 1: + // 隐式调用break语句,匹配上一个即停止 + case 2: + // 不会运行 + } + // 和if一样,for也不用括号 + for x := 0; x < 3; x++ { // ++ 自增 + fmt.Println("iteration", x) + } + // x在这里还是1。为什么? + + // for 是go里唯一的循环关键字,不过它有很多变种 + for { // 无限循环 + break // 骗你的 + continue // 不会运行的 + } + // 和for一样,if中的:=先给y赋值,然后再和x作比较。 + if y := expensiveComputation(); y > x { + x = y + } + // 闭包函数 + xBig := func() bool { + return x > 100 // x是上面声明的变量引用 + } + fmt.Println("xBig:", xBig()) // true (上面把y赋给x了) + x /= 1e5 // x变成10 + fmt.Println("xBig:", xBig()) // 现在是false + + // 当你需要goto的时候,你会爱死它的! + goto love +love: + + learnInterfaces() // 好东西来了! +} + +// 定义Stringer为一个接口类型,有一个方法String +type Stringer interface { + String() string +} + +// 定义pair为一个结构体,有x和y两个int型变量。 +type pair struct { + x, y int +} + +// 定义pair类型的方法,实现Stringer接口。 +func (p pair) String() string { // p被叫做“接收器” + // Sprintf是fmt包中的另一个公有函数。 + // 用 . 调用p中的元素。 + return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func learnInterfaces() { + // 花括号用来定义结构体变量,:=在这里将一个结构体变量赋值给p。 + p := pair{3, 4} + fmt.Println(p.String()) // 调用pair类型p的String方法 + var i Stringer // 声明i为Stringer接口类型 + i = p // 有效!因为p实现了Stringer接口(类似java中的塑型) + // 调用i的String方法,输出和上面一样 + fmt.Println(i.String()) + + // fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。(类似java中的序列化) + fmt.Println(p) // 输出和上面一样,自动调用String函数。 + fmt.Println(i) // 输出和上面一样。 + + learnErrorHandling() +} + +func learnErrorHandling() { + // ", ok"用来判断有没有正常工作 + m := map[int]string{3: "three", 4: "four"} + if x, ok := m[1]; !ok { // ok 为false,因为m中没有1 + fmt.Println("no one there") + } else { + fmt.Print(x) // 如果x在map中的话,x就是那个值喽。 + } + // 错误可不只是ok,它还可以给出关于问题的更多细节。 + if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value + // 输出"strconv.ParseInt: parsing "non-int": invalid syntax" + fmt.Println(err) + } + // 待会再说接口吧。同时, + learnConcurrency() +} + +// c是channel类型,一个并发安全的通信对象。 +func inc(i int, c chan int) { + c <- i + 1 // <-把右边的发送到左边的channel。 +} + +// 我们将用inc函数来并发地增加一些数字。 +func learnConcurrency() { + // 用make来声明一个slice,make会分配和初始化slice,map和channel。 + c := make(chan int) + // 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。三个都被发送到同一个channel。 + go inc(0, c) // go is a statement that starts a new goroutine. + go inc(10, c) + go inc(-805, c) + // 从channel中独处结果并打印。 + // 打印出什么东西是不可预知的。 + fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 + + cs := make(chan string) // 操作string的channel + cc := make(chan chan string) // 操作channel的channel + go func() { c <- 84 }() // 开始一个goroutine来发送一个新的数字 + go func() { cs <- "wordy" }() // 发送给cs + // Select类似于switch,但是每个case包括一个channel操作。它随机选择一个准备好通讯的case。 + select { + case i := <-c: // 从channel接收的值可以赋给其他变量 + fmt.Println("it's a", i) + case <-cs: // 或者直接丢弃 + fmt.Println("it's a string") + case <-cc: // 空的,还没作好通讯的准备 + fmt.Println("didn't happen.") + } + // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 + + learnWebProgramming() // Go很适合web编程,我知道你也想学! +} + +// http包中的一个简单的函数就可以开启web服务器。 +func learnWebProgramming() { + // ListenAndServe第一个参数指定了监听端口,第二个参数是一个接口,特定是http.Handler。 + err := http.ListenAndServe(":8080", pair{}) + fmt.Println(err) // 不要无视错误。 +} + +// 使pair实现http.Handler接口的ServeHTTP方法。 +func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // 使用http.ResponseWriter返回数据 + w.Write([]byte("You learned Go in Y minutes!")) +} +``` + +## 更进一步 + +Go的根源在[Go官方网站](http://golang.org/)。 +在那里你可以学习入门教程,通过浏览器交互式地学习,而且可以读到很多东西。 + +强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.) + +学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了! -- cgit v1.2.3 From dffa1b4f7426b61af77b0a13954c0fe49eb4a578 Mon Sep 17 00:00:00 2001 From: Tao Pan Date: Thu, 15 Aug 2013 19:44:39 +0800 Subject: =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zh-cn/go-zh.html.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown index 6a4c09be..25fd1f03 100644 --- a/zh-cn/go-zh.html.markdown +++ b/zh-cn/go-zh.html.markdown @@ -4,13 +4,12 @@ 文件名:learngo.go 贡献者: - ["Sonia Keys", "https://github.com/soniakeys"] -翻译者: - ["pantaovay", "https://github.com/pantaovay"] --- 发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 -Go拥有命令式语言的静态类型,编译很快,执行也很快,同时加入了对于目前多核CPU的并发计算支持,也有相应的特性来大规模编程。 +Go拥有命令式语言的静态类型,编译很快,执行也很快,同时加入了对于目前多核CPU的并发计算支持,也有相应的特性来实现大规模编程。 Go语言有非常棒的标准库,还有一个充满热情的社区。 -- cgit v1.2.3 From 8aa0ab6068a13491ec9cba59bce32911ab9f8061 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 16 Aug 2013 09:44:22 -0700 Subject: Edits --- zh-cn/go-zh.html.markdown | 183 ++++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 89 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown index 25fd1f03..8f7cb2af 100644 --- a/zh-cn/go-zh.html.markdown +++ b/zh-cn/go-zh.html.markdown @@ -29,7 +29,8 @@ import ( "strconv" // 字符串转换 ) -//函数声明:Main是程序执行的入口。不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 +// 函数声明:Main是程序执行的入口。 +// 不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 func main() { // 往标准输出打印一行。 // 用包名fmt限制打印函数。 @@ -65,10 +66,10 @@ func learnTypes() { can include line breaks.` // 同样是String类型 // 非ascii字符。Go使用UTF-8编码。 - g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 + g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 - f := 3.14195 // float64类型,IEEE-754 64位浮点数 - c := 3 + 4i // complex128类型,内部使用两个float64表示 + f := 3.14195 // float64类型,IEEE-754 64位浮点数 + c := 3 + 4i // complex128类型,内部使用两个float64表示 // Var变量可以直接初始化。 var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度 @@ -99,9 +100,9 @@ can include line breaks.` // 同样是String类型 // 下划线 _ 可以使你“使用”一个变量,但是丢弃它的值。 _,_,_,_,_,_,_,_,_ = s2, g, f, u, pi, n, a3, s4, bs // 输出变量 - fmt.Println(s, c, a4, s3, d2, m) + fmt.Println(s, c, a4, s3, d2, m) - learnFlowControl() // 回到流程控制 + learnFlowControl() // 回到流程控制 } // Go全面支持垃圾回收。Go有指针,但是不支持指针运算。 @@ -117,155 +118,159 @@ func learnMemory() (p, q *int) { } func expensiveComputation() int { - return 1e6 + return 1e6 } func learnFlowControl() { // If需要花括号,括号就免了 - if true { - fmt.Println("told ya") - } - // 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了,也不用容忍被人的代码风格。 - if false { - // pout - } else { - // gloat - } + if true { + fmt.Println("told ya") + } + // 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了, + // 也不用容忍被人的代码风格。 + if false { + // pout + } else { + // gloat + } // 如果太多嵌套的if语句,推荐使用switch - x := 1 - switch x { - case 0: - case 1: + x := 1 + switch x { + case 0: + case 1: // 隐式调用break语句,匹配上一个即停止 - case 2: + case 2: // 不会运行 - } + } // 和if一样,for也不用括号 - for x := 0; x < 3; x++ { // ++ 自增 - fmt.Println("iteration", x) - } + for x := 0; x < 3; x++ { // ++ 自增 + fmt.Println("iteration", x) + } // x在这里还是1。为什么? // for 是go里唯一的循环关键字,不过它有很多变种 - for { // 无限循环 - break // 骗你的 - continue // 不会运行的 - } + for { // 无限循环 + break // 骗你的 + continue // 不会运行的 + } // 和for一样,if中的:=先给y赋值,然后再和x作比较。 - if y := expensiveComputation(); y > x { - x = y - } + if y := expensiveComputation(); y > x { + x = y + } // 闭包函数 - xBig := func() bool { - return x > 100 // x是上面声明的变量引用 - } - fmt.Println("xBig:", xBig()) // true (上面把y赋给x了) - x /= 1e5 // x变成10 - fmt.Println("xBig:", xBig()) // 现在是false + xBig := func() bool { + return x > 100 // x是上面声明的变量引用 + } + fmt.Println("xBig:", xBig()) // true (上面把y赋给x了) + x /= 1e5 // x变成10 + fmt.Println("xBig:", xBig()) // 现在是false // 当你需要goto的时候,你会爱死它的! - goto love + goto love love: - learnInterfaces() // 好东西来了! + learnInterfaces() // 好东西来了! } // 定义Stringer为一个接口类型,有一个方法String type Stringer interface { - String() string + String() string } // 定义pair为一个结构体,有x和y两个int型变量。 type pair struct { - x, y int + x, y int } // 定义pair类型的方法,实现Stringer接口。 func (p pair) String() string { // p被叫做“接收器” // Sprintf是fmt包中的另一个公有函数。 // 用 . 调用p中的元素。 - return fmt.Sprintf("(%d, %d)", p.x, p.y) + return fmt.Sprintf("(%d, %d)", p.x, p.y) } func learnInterfaces() { // 花括号用来定义结构体变量,:=在这里将一个结构体变量赋值给p。 - p := pair{3, 4} - fmt.Println(p.String()) // 调用pair类型p的String方法 - var i Stringer // 声明i为Stringer接口类型 - i = p // 有效!因为p实现了Stringer接口(类似java中的塑型) + p := pair{3, 4} + fmt.Println(p.String()) // 调用pair类型p的String方法 + var i Stringer // 声明i为Stringer接口类型 + i = p // 有效!因为p实现了Stringer接口(类似java中的塑型) // 调用i的String方法,输出和上面一样 - fmt.Println(i.String()) + fmt.Println(i.String()) - // fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。(类似java中的序列化) - fmt.Println(p) // 输出和上面一样,自动调用String函数。 - fmt.Println(i) // 输出和上面一样。 + // fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。 + // (类似java中的序列化) + fmt.Println(p) // 输出和上面一样,自动调用String函数。 + fmt.Println(i) // 输出和上面一样。 - learnErrorHandling() + learnErrorHandling() } func learnErrorHandling() { - // ", ok"用来判断有没有正常工作 - m := map[int]string{3: "three", 4: "four"} - if x, ok := m[1]; !ok { // ok 为false,因为m中没有1 - fmt.Println("no one there") - } else { - fmt.Print(x) // 如果x在map中的话,x就是那个值喽。 - } + // ", ok"用来判断有没有正常工作 + m := map[int]string{3: "three", 4: "four"} + if x, ok := m[1]; !ok { // ok 为false,因为m中没有1 + fmt.Println("no one there") + } else { + fmt.Print(x) // 如果x在map中的话,x就是那个值喽。 + } // 错误可不只是ok,它还可以给出关于问题的更多细节。 - if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value - // 输出"strconv.ParseInt: parsing "non-int": invalid syntax" - fmt.Println(err) - } + if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value + // 输出"strconv.ParseInt: parsing "non-int": invalid syntax" + fmt.Println(err) + } // 待会再说接口吧。同时, - learnConcurrency() + learnConcurrency() } // c是channel类型,一个并发安全的通信对象。 func inc(i int, c chan int) { - c <- i + 1 // <-把右边的发送到左边的channel。 + c <- i + 1 // <-把右边的发送到左边的channel。 } // 我们将用inc函数来并发地增加一些数字。 func learnConcurrency() { // 用make来声明一个slice,make会分配和初始化slice,map和channel。 - c := make(chan int) - // 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。三个都被发送到同一个channel。 - go inc(0, c) // go is a statement that starts a new goroutine. - go inc(10, c) - go inc(-805, c) + c := make(chan int) + // 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。 + // 三个都被发送到同一个channel。 + go inc(0, c) // go is a statement that starts a new goroutine. + go inc(10, c) + go inc(-805, c) // 从channel中独处结果并打印。 // 打印出什么东西是不可预知的。 - fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 - - cs := make(chan string) // 操作string的channel - cc := make(chan chan string) // 操作channel的channel - go func() { c <- 84 }() // 开始一个goroutine来发送一个新的数字 - go func() { cs <- "wordy" }() // 发送给cs - // Select类似于switch,但是每个case包括一个channel操作。它随机选择一个准备好通讯的case。 - select { - case i := <-c: // 从channel接收的值可以赋给其他变量 - fmt.Println("it's a", i) - case <-cs: // 或者直接丢弃 - fmt.Println("it's a string") - case <-cc: // 空的,还没作好通讯的准备 - fmt.Println("didn't happen.") - } + fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 + + cs := make(chan string) // 操作string的channel + cc := make(chan chan string) // 操作channel的channel + go func() { c <- 84 }() // 开始一个goroutine来发送一个新的数字 + go func() { cs <- "wordy" }() // 发送给cs + // Select类似于switch,但是每个case包括一个channel操作。 + // 它随机选择一个准备好通讯的case。 + select { + case i := <-c: // 从channel接收的值可以赋给其他变量 + fmt.Println("it's a", i) + case <-cs: // 或者直接丢弃 + fmt.Println("it's a string") + case <-cc: // 空的,还没作好通讯的准备 + fmt.Println("didn't happen.") + } // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 - learnWebProgramming() // Go很适合web编程,我知道你也想学! + learnWebProgramming() // Go很适合web编程,我知道你也想学! } // http包中的一个简单的函数就可以开启web服务器。 func learnWebProgramming() { // ListenAndServe第一个参数指定了监听端口,第二个参数是一个接口,特定是http.Handler。 - err := http.ListenAndServe(":8080", pair{}) - fmt.Println(err) // 不要无视错误。 + err := http.ListenAndServe(":8080", pair{}) + fmt.Println(err) // 不要无视错误。 } // 使pair实现http.Handler接口的ServeHTTP方法。 func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { // 使用http.ResponseWriter返回数据 - w.Write([]byte("You learned Go in Y minutes!")) + w.Write([]byte("You learned Go in Y minutes!")) } ``` -- cgit v1.2.3 From 0fc4b4d5d53a677cfc8c9889af328427c2fa6e24 Mon Sep 17 00:00:00 2001 From: alswl Date: Sat, 24 Aug 2013 23:27:50 +0800 Subject: add xiaoqi's translation --- zh-cn/r-cn.html.markdown | 691 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 691 insertions(+) create mode 100644 zh-cn/r-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown new file mode 100644 index 00000000..1bd83c60 --- /dev/null +++ b/zh-cn/r-cn.html.markdown @@ -0,0 +1,691 @@ + +# Comments start with hashtags. +# 评论以 # 开始 + +# You can't make a multi-line comment per se, +# but you can stack multiple comments like so. +# 你不能在每一个se下执行多个注释, +# 但是你可以像这样把命注释内容堆叠起来. +# in Windows, hit COMMAND-ENTER to execute a line +# 在windows下,点击回车键来执行一条命令 + + +################################################################### +# Stuff you can do without understanding anything about programming +# 素材可以使那些不懂编程的人同样得心用手 +################################################################### + +data() # Browse pre-loaded data sets +data() # 浏览预加载的数据集 +data(rivers) # Lengths of Major North American Rivers +data(rivers) # 北美主要河流的长度(数据集) +ls() # Notice that "rivers" appears in the workspace +ls() # 在工作站中查看”河流“文件夹是否出现 +head(rivers) # peek at the dataset +head(rivers) # 浏览数据集 +# 735 320 325 392 524 450 +length(rivers) # how many rivers were measured? +# 141 +length(rivers) # 测量了多少条河流 +summary(rivers) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 135.0 310.0 425.0 591.2 680.0 3710.0 +#查看”河流“数据集的特征 +# 最小值. 1st Qu. 中位数 平均值 最大值 +# 135.0 310.0 425.0 591.2 680.0 3710.0 +stem(rivers) #stem-and-leaf plot (like a histogram) +stem(rivers) #茎叶图(一种类似于直方图的展现形式) + + + + +# The decimal point is 2 digit(s) to the right of the | +# 小数点向|右边保留两位数字 +# +# 0 | 4 +# 2 | 011223334555566667778888899900001111223333344455555666688888999 +# 4 | 111222333445566779001233344567 +# 6 | 000112233578012234468 +# 8 | 045790018 +# 10 | 04507 +# 12 | 1471 +# 14 | 56 +# 16 | 7 +# 18 | 9 +# 20 | +# 22 | 25 +# 24 | 3 +# 26 | +# 28 | +# 30 | +# 32 | +# 34 | +# 36 | 1 + +stem(log(rivers)) #Notice that the data are neither normal nor log-normal! Take that, Bell Curve fundamentalists. +stem(log(rivers)) #查看数据集的方式既不是标准形式,也不是取log后的结果! 看起来,是钟形曲线形式的基本数据集 + +# The decimal point is 1 digit(s) to the left of the | +# 小数点向|左边保留一位数字 +# +# 48 | 1 +# 50 | +# 52 | 15578 +# 54 | 44571222466689 +# 56 | 023334677000124455789 +# 58 | 00122366666999933445777 +# 60 | 122445567800133459 +# 62 | 112666799035 +# 64 | 00011334581257889 +# 66 | 003683579 +# 68 | 0019156 +# 70 | 079357 +# 72 | 89 +# 74 | 84 +# 76 | 56 +# 78 | 4 +# 80 | +# 82 | 2 + + +hist(rivers, col="#333333", border="white", breaks=25) #play around with these parameters +hist(rivers, col="#333333", border="white", breaks=25) #给river做统计频数直方图,包含了这些参数(名称,颜色,边界,空白) +hist(log(rivers), col="#333333", border="white", breaks=25) #you'll do more plotting later +hist(log(rivers), col="#333333", border="white", breaks=25) #稍后你还可以做更多的绘图,统计频数直方图,包含了这些参数(river数据集的log值,颜色,边界,空白) +hist(rivers, col="#333333", border="white", breaks=25) #play around with these parameters +hist(rivers, col="#333333", border="white", breaks=25) #运行同济频数直方图的这些参数 + +#Here's another neat data set that comes pre-loaded. R has tons of these. data() +#这里还有其他一些简洁的数据集可以被提前加载。R语言包括大量这种类型的数据集 +data(discoveries) +#数据集(发现) +plot(discoveries, col="#333333", lwd=3, xlab="Year", main="Number of important discoveries per year") +#绘图(发现,颜色负值,宽度负值,X轴名称,主题:Number of important discoveries per year) + + + +#rather than leaving the default ordering (by year) we could also sort to see what's typical +#宁可舍弃也不执行排序(按照年份完成)我们可以分类来查看这是那些类型 +sort(discoveries) #给(发现)分类 +# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 +# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 +# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 +# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 + +stem(discoveries, scale=2) +#茎叶图(发现,在原来的基础上降尺度扩大两倍) +# +# The decimal point is at the | +# 小数点在| +# +# 0 | 000000000 +# 1 | 000000000000 +# 2 | 00000000000000000000000000 +# 3 | 00000000000000000000 +# 4 | 000000000000 +# 5 | 0000000 +# 6 | 000000 +# 7 | 0000 +# 8 | 0 +# 9 | 0 +# 10 | 0 +# 11 | +# 12 | 0 + +max(discoveries) +#最大值(发现) +# 12 + +summary(discoveries) +#数据集特征(发现) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 0.0 2.0 3.0 3.1 4.0 12.0 + + + + +#Basic statistical operations don't require any programming knowledge either +#基本的统计学操作也不需要任何编程知识 + +#roll a die a few times +#随机输出数据 +round(runif(7, min=.5, max=6.5)) +#round(产生均匀分布的随机数,进行四舍五入(7个, 最小值为0.5, max=6.5)) +# 1 4 6 1 4 6 4 + +#your numbers will differ from mine unless we set the same random.seed(31337) +#你输出的结果将会与我们给出的不同,除非我们设置了同样的随机种子 random.seed(31337) + + +#draw from a standard Gaussian 9 times +#从标准高斯函数中随机的提取9次结果 +rnorm(9) +# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271 +# [7] -0.59975593 0.57629164 1.08455362 + + + + + + + + + +######################### +# Basic programming stuff +# 基本的编程素材 +######################### + +# NUMBERS + +# "numeric" means double-precision floating-point numbers +#“数值”指的是双精度的浮点数 +5 # 5 +class(5) # "numeric" +#定义(5)为数值型变量 # "numeric" +5e4 # 50000 #handy when dealing with large,small,or variable orders of magnitude +#5×104次方 可以手写输入改变数量级的大小将变量扩大 +6.02e23 # Avogadro's number +#阿伏伽德罗常数 +1.6e-35 # Planck length +#布朗克长度 + +# long-storage integers are written with L +#长存储整数并用L书写 +5L # 5 +#输出5L +class(5L) # "integer" +#(5L)的类型, 整数型 + +# Try ?class for more information on the class() function +#可以自己试一试?用class()功能函数定义更多的信息 +# In fact, you can look up the documentation on `xyz` with ?xyz +#事实上,你可以找一些文件查阅“xyz”以及xyz的差别 +# or see the source for `xyz` by evaluating xyz +#或者通过评估xyz来查看“xyz”的来源 + +# Arithmetic +#算法 +10 + 66 # 76 +53.2 - 4 # 49.2 +2 * 2.0 # 4 +3L / 4 # 0.75 +3 %% 2 # 1 + +# Weird number types +#超自然数的类型 +class(NaN) # "numeric" +class(Inf) # "numeric" +class(-Inf) # "numeric" #used in for example integrate( dnorm(x), 3, Inf ) -- which obviates Z-score tables +#定义以上括号内的数均为数值型变量,利用实例中的整数(正态分布函数(X),3,Inf )消除Z轴列表 + +# but beware, NaN isn't the only weird type... +# 但要注意,NaN并不是仅有的超自然类型。。。 +class(NA) # see below +#定义(NA)下面的部分会理解 +class(NULL) # NULL +#定义(NULL)无效的 + + +# SIMPLE LISTS +#简单的数据集 +c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9 +#输出数值型向量(6 8 7 5 3 0 9) +c('alef', 'bet', 'gimmel', 'dalet', 'he') +#输出字符型变量# "alef" "bet" "gimmel" "dalet" "he" +c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE +#输出逻辑型变量FALSE FALSE FALSE FALSE + +#some more nice built-ins +#一些优雅的内置功能 +5:15 # 5 6 7 8 9 10 11 12 13 14 15 +#从5-15输出,以进度为1递增 + +seq(from=0, to=31337, by=1337) +#输出序列(从0到31337,以1337递增) +# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 +# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 + +letters +#字符型变量,26个 +# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" +# [20] "t" "u" "v" "w" "x" "y" "z" + +month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" +#表示月份的变量 + + +# Access the n'th element of a list with list.name[n] or sometimes list.name[[n]] +#访问数据集名字为[n]的第n个元素 + +letters[18] # "r" +#访问其中的第18个变量 +LETTERS[13] # "M" +#用大写访问其中的第13个变量 +month.name[9] # "September" +#访问名字文件中第9个变量 +c(6, 8, 7, 5, 3, 0, 9)[3] # 7 +#访问向量中的第三个变量 + + + +# CHARACTERS +#特性 +# There's no difference between strings and characters in R +# 字符串和字符在R语言中没有区别 +"Horatio" # "Horatio" +#字符输出"Horatio" +class("Horatio") # "character" +#字符串输出("Horatio") # "character" +substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " +#提取字符串("Fortuna multis dat nimis, nulli satis.", 第9个到15个之前并输出) +gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." +#替换字符春,用ø替换u + + + +# LOGICALS +#逻辑值 + +# booleans +#布尔运算 +class(TRUE) # "logical" +#定义为真,逻辑型 +class(FALSE) # "logical" +#定义为假,逻辑型 +# Behavior is normal +#表现的标准形式 +TRUE == TRUE # TRUE +TRUE == FALSE # FALSE +FALSE != FALSE # FALSE +FALSE != TRUE # TRUE +# Missing data (NA) is logical, too +#缺失数据也是逻辑型的 +class(NA) # "logical" +#定义NA为逻辑型 + + + +# FACTORS +#因子 +# The factor class is for categorical data +#因子是分类数据的定义函数 +# which can be ordered (like childrens' grade levels) +#可以使有序的(就像儿童的等级水平) +# or unordered (like gender) +#也可以是无序的(就像性别) +levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA" +#c("female", "male", "male", "female", "NA", "female")向量,变量是字符型,levels factor()因子的等级水平 + +factor(c("female", "female", "male", "NA", "female")) +# female female male NA female +# Levels: female male NA + +data(infert) #Infertility after Spontaneous and Induced Abortion +#数据集(感染) 自然以及引产导致的不育症 +levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" +#等级(感染与教育程度) 输出 + + + +# VARIABLES +#变量 + +# Lots of way to assign stuff +#许多种方式用来分配素材 +x = 5 # this is possible +#x = 5可能的 +y <- "1" # this is preferred +#y <- "1" 优先级的 +TRUE -> z # this works but is weird +#输出真实的,存在一个超自然数满足条件 + +# We can use coerce variables to different classes +#我们还可以使用枪支变量去进行不同的定义 +as.numeric(y) # 1 +#定义数值型 +as.character(x) # "5" +#字符型 + + +# LOOPS +#循环 + +# We've got for loops +#循环语句 +for (i in 1:4) { + print(i) +} +#定义一个i,从1-4输出 + +# We've got while loops +#我们可以获取循环结构 +a <- 10 +while (a > 4) { + cat(a, "...", sep = "") + a <- a - 1 +} +#把10负值为a,a<4,输出文件(a,"...",sep="" ),跳出继续下一个循环取a=a-1,如此循环,直到a=10终止 +# Keep in mind that for and while loops run slowly in R +#在R语言中牢记 for和它的循环结构 +# Operations on entire vectors (i.e. a whole row, a whole column) +#牢记矢量中附带的操作(例如,整行和整列) +# or apply()-type functions (we'll discuss later) are preferred +#或者优先使用()-函数,稍后会进行讨论 + +# IF/ELSE +#判断分支 + +# Again, pretty standard +#再一次,看这些优雅的标准 +if (4 > 3) { + print("Huzzah! It worked!") +} else { + print("Noooo! This is blatantly illogical!") +} + +# => +# [1] "Huzzah! It worked!" + +# FUNCTIONS +#功能函数 + +# Defined like so: +#定义如下 +jiggle <- function(x) { + x+ rnorm(x, sd=.1) #add in a bit of (controlled) noise + return(x) +} +#把功能函数x负值给jiggle, + +# Called like any other R function: +jiggle(5) # 5±ε. After set.seed(2716057), jiggle(5)==5.005043 + +######################### +# Fun with data: vectors, matrices, data frames, and arrays +# 数据参数:向量,矩阵,数据框,数组, +######################### + +# ONE-DIMENSIONAL +#单维度 +# You can vectorize anything, so long as all components have the same type +#你可以将任何东西矢量化,因此所有的组分都有相同的类型 +vec <- c(8, 9, 10, 11) +vec # 8 9 10 11 +# The class of a vector is the class of its components +#矢量class表示这一组分的类型 +class(vec) # "numeric" +# If you vectorize items of different classes, weird coercions happen +#如果你强制的将不同类型的classes矢量化,会发生超自然形式的函数,例如都转变成数值型、字符型 +c(TRUE, 4) # 1 4 +c("dog", TRUE, 4) # "dog" "TRUE" "4" + +# We ask for specific components like so (R starts counting from 1) +#我们可以找寻特定的组分,例如这个例子(R从1算起) +vec[1] # 8 +# We can also search for the indices of specific components, +#我们也可以从这些特定组分中找寻这些指标 +which(vec %% 2 == 0) # 1 3 +# or grab just the first or last entry in the vector +#抓取矢量中第1个和最后一个字符 +head(vec, 1) # 8 +tail(vec, 1) # 11 +#如果指数结束或不存在即"goes over" 可以获得NA +# If an index "goes over" you'll get NA: +vec[6] # NA +# You can find the length of your vector with length() +#你也可以找到矢量的长度 +length(vec) # 4 + +# You can perform operations on entire vectors or subsets of vectors +#你可以将整个矢量或者子矢量集进行展示 +vec * 4 # 16 20 24 28 +# +vec[2:3] * 5 # 25 30 +# and there are many built-in functions to summarize vectors +#这里有许多内置的功能函数,并且可对矢量特征进行总结 +mean(vec) # 9.5 +var(vec) # 1.666667 +sd(vec) # 1.290994 +max(vec) # 11 +min(vec) # 8 +sum(vec) # 38 + +# TWO-DIMENSIONAL (ALL ONE CLASS) +#二维函数 + +# You can make a matrix out of entries all of the same type like so: +#你可以建立矩阵,保证所有的变量形式相同 +mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6)) +#建立mat矩阵,3行2列,从1到6排列,默认按列排布 +mat +# => +# [,1] [,2] +# [1,] 1 4 +# [2,] 2 5 +# [3,] 3 6 +# Unlike a vector, the class of a matrix is "matrix", no matter what's in it +class(mat) # => "matrix" +# Ask for the first row +#访问第一行的字符 +mat[1,] # 1 4 +# Perform operation on the first column +#优先输入第一列,分别×3输出 +3 * mat[,1] # 3 6 9 +# Ask for a specific cell +#访问特殊的单元,第3行第二列 +mat[3,2] # 6 +# Transpose the whole matrix +#转置整个矩阵,变成2行3列 +t(mat) +# => +# [,1] [,2] [,3] +# [1,] 1 2 3 +# [2,] 4 5 6 + +# cbind() sticks vectors together column-wise to make a matrix +把两个矩阵按列合并,形成新的矩阵 +mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog")) +mat2 +# => +# [,1] [,2] +# [1,] "1" "dog" +# [2,] "2" "cat" +# [3,] "3" "bird" +# [4,] "4" "dog" +class(mat2) # matrix +#定义mat2矩阵 +# Again, note what happened! +#同样的注释 +# Because matrices must contain entries all of the same class, +#矩阵必须包含同样的形式 +# everything got converted to the character class +#每一个变量都可以转化成字符串形式 +c(class(mat2[,1]), class(mat2[,2])) + +# rbind() sticks vectors together row-wise to make a matrix +#按行合并两个向量,建立新的矩阵 +mat3 <- rbind(c(1,2,4,5), c(6,7,0,4)) +mat3 +# => +# [,1] [,2] [,3] [,4] +# [1,] 1 2 4 5 +# [2,] 6 7 0 4 +# Aah, everything of the same class. No coercions. Much better. + +# TWO-DIMENSIONAL (DIFFERENT CLASSES) +##二维函数(不同的变量类型) + +# For columns of different classes, use the data frame +利用数组可以将不同类型放在一起 +dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog")) +#dat<-数据集(c(5,2,1,4), c("dog", "cat", "bird", "dog")) +names(dat) <- c("number", "species") # name the columns +#给每一个向量命名 +class(dat) # "data.frame" +#建立数据集dat +dat +# => +# number species +# 1 5 dog +# 2 2 cat +# 3 1 bird +# 4 4 dog +class(dat$number) # "numeric" +class(dat[,2]) # "factor" +# The data.frame() function converts character vectors to factor vectors +#数据集,将字符特征转化为因子矢量 + +# There are many twisty ways to subset data frames, all subtly unalike +#这里有许多种生成数据集的方法,所有的都很巧妙但又不相似 +dat$number # 5 2 1 4 +dat[,1] # 5 2 1 4 +dat[,"number"] # 5 2 1 4 + +# MULTI-DIMENSIONAL (ALL OF ONE CLASS) +#多维函数 +# Arrays creates n-dimensional tables +#利用数组创造一个n维的表格 +# You can make a two-dimensional table (sort of like a matrix) +#你可以建立一个2维表格(类型和矩阵相似) +array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) +#数组(c(c(1,2,4,5),c(8,9,3,6)),有前两个向量组成,2行4列 +# => +# [,1] [,2] [,3] [,4] +# [1,] 1 4 8 3 +# [2,] 2 5 9 6 +# You can use array to make three-dimensional matrices too +#你也可以利用数组建立一个三维的矩阵 +array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) +# => +# , , 1 +# +# [,1] [,2] +# [1,] 2 8 +# [2,] 300 9 +# [3,] 4 0 +# +# , , 2 +# +# [,1] [,2] +# [1,] 5 66 +# [2,] 60 7 +# [3,] 0 847 + +# LISTS (MULTI-DIMENSIONAL, POSSIBLY RAGGED, OF DIFFERENT TYPES) +#列表(多维的,不同类型的) + +# Finally, R has lists (of vectors) +#R语言有列表的形式 +list1 <- list(time = 1:40) +list1$price = c(rnorm(40,.5*list1$time,4)) # random +list1 + +# You can get items in the list like so +#你可以获得像上面列表的形式 +list1$time +# You can subset list items like vectors +#你也可以获取他们的子集,一种类似于矢量的形式 +list1$price[4] + +######################### +# The apply() family of functions +#apply()函数家族的应用 +######################### + +# Remember mat? +#输出mat矩阵 +mat +# => +# [,1] [,2] +# [1,] 1 4 +# [2,] 2 5 +# [3,] 3 6 +# Use apply(X, MARGIN, FUN) to apply function FUN to a matrix X +#使用(X, MARGIN, FUN)将一个function功能函数根据其特征应用到矩阵x中 +# over rows (MAR = 1) or columns (MAR = 2) +#规定行列,其边界分别为1,2 +# That is, R does FUN to each row (or column) of X, much faster than a +#即就是,R定义一个function使每一行/列的x快于一个for或者while循环 +# for or while loop would do +apply(mat, MAR = 2, myFunc) +# => +# [,1] [,2] +# [1,] 3 15 +# [2,] 7 19 +# [3,] 11 23 +# Other functions: ?lapply, ?sapply +其他的功能函数, + +# Don't feel too intimidated; everyone agrees they are rather confusing +#不要被这些吓到,许多人在此都会容易混淆 +# The plyr package aims to replace (and improve upon!) the *apply() family. +#plyr程序包的作用是用来改进family函数家族 + +install.packages("plyr") +require(plyr) +?plyr + +######################### +# Loading data +######################### + +# "pets.csv" is a file on the internet +#"pets.csv" 是网上的一个文本 +pets <- read.csv("http://learnxinyminutes.com/docs/pets.csv") +#首先读取这个文本 +pets +head(pets, 2) # first two rows +#显示前两行 +tail(pets, 1) # last row +#显示最后一行 + +# To save a data frame or matrix as a .csv file +#以.csv格式来保存数据集或者矩阵 +write.csv(pets, "pets2.csv") # to make a new .csv file +#输出新的文本pets2.csv +# set working directory with setwd(), look it up with getwd() +#改变工作路径setwd(),查找工作路径getwd() + +# Try ?read.csv and ?write.csv for more information +#试着做一做以上学到的,或者运行更多的信息 + +######################### +# Plots +#画图 +######################### + +# Scatterplots! +#散点图 +plot(list1$time, list1$price, main = "fake data") +#作图,横轴list1$time,纵轴list1$price,主题fake data +# Regressions! +#退回 +linearModel <- lm(price ~ time, data = list1) +# 线性模型,数据集为list1,以价格对时间做相关分析模型 +linearModel # outputs result of regression +#输出拟合结果,并退出 +# Plot regression line on existing plot +#将拟合结果展示在图上,颜色设为红色 +abline(linearModel, col = "red") +# Get a variety of nice diagnostics +#也可以获取各种各样漂亮的分析图 +plot(linearModel) + +# Histograms! +#直方图 +hist(rpois(n = 10000, lambda = 5), col = "thistle") +#统计频数直方图() + +# Barplots! +#柱状图 +barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) +#作图,柱的高度负值c(1,4,5,1,2),各个柱子的名称"red","blue","purple","green","yellow" + +# Try the ggplot2 package for more and better graphics +#可以尝试着使用ggplot2程序包来美化图片 +install.packages("ggplot2") +require(ggplot2) +?ggplot2 + + -- cgit v1.2.3 From c7a1136772588e57a3f9c20be9102a80a6f7f3e8 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 27 Aug 2013 21:23:09 -0700 Subject: Edits --- zh-cn/go-zh.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown index 8f7cb2af..0af5bbe3 100644 --- a/zh-cn/go-zh.html.markdown +++ b/zh-cn/go-zh.html.markdown @@ -1,8 +1,8 @@ --- -名字:Go -分类:编程语言 -文件名:learngo.go -贡献者: +language: Go +lang: zh-cn +filename: learngo.go +contributors: - ["Sonia Keys", "https://github.com/soniakeys"] - ["pantaovay", "https://github.com/pantaovay"] --- -- cgit v1.2.3 From 3fb4aa64a11999160842ff9a48c57d885e30ae83 Mon Sep 17 00:00:00 2001 From: Yadong Wen Date: Thu, 5 Sep 2013 22:23:34 +1200 Subject: add Chinese translation of perl.html.markdown --- zh-cn/perl-cn.html.markdown | 151 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 zh-cn/perl-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/perl-cn.html.markdown b/zh-cn/perl-cn.html.markdown new file mode 100644 index 00000000..8f99ccbf --- /dev/null +++ b/zh-cn/perl-cn.html.markdown @@ -0,0 +1,151 @@ +--- +name: perl +category: language +language: perl +filename: learnperl.pl +contributors: + - ["Korjavin Ivan", "http://github.com/korjavin"] +translators: + - ["Yadong Wen", "https://github.com/yadongwen"] +--- + +Perl 5是一个功能强大、特性齐全的编程语言,有25年的历史。 + +Perl 5可以在包括便携式设备和大型机的超过100个平台上运行,既适用于快速原型构建,也适用于大型项目开发。 + +```perl +# 单行注释以#号开头 + + +#### Perl的变量类型 + +# 变量以$号开头。 +# 合法变量名以英文字母或者下划线起始, +# 后接任意数目的字母、数字或下划线。 + +### Perl有三种主要的变量类型:标量、数组和哈希。 + +## 标量 +# 标量类型代表单个值: +my $animal = "camel"; +my $answer = 42; + +# 标量类型值可以是字符串、整型或浮点类型,Perl会根据需要自动进行类型转换。 + +## 数组 +# 数组类型代表一列值: +my @animals = ("camel", "llama", "owl"); +my @numbers = (23, 42, 69); +my @mixed = ("camel", 42, 1.23); + + + +## 哈希 +# 哈希类型代表一个键/值对的集合: + +my %fruit_color = ("apple", "red", "banana", "yellow"); + +# 可以使用空格和“=>”操作符更清晰的定义哈希: + +my %fruit_color = ( + apple => "red", + banana => "yellow", + ); +# perldata中有标量、数组和哈希更详细的介绍。 (perldoc perldata). + +# 可以用引用构建更复杂的数据类型,比如嵌套的列表和哈希。 + +#### 逻辑和循环结构 + +# Perl有大多数常见的逻辑和循环控制结构 + +if ( $var ) { + ... +} elsif ( $var eq 'bar' ) { + ... +} else { + ... +} + +unless ( condition ) { + ... + } +# 上面这个比"if (!condition)"更可读。 + +# 有Perl特色的后置逻辑结构 +print "Yow!" if $zippy; +print "We have no bananas" unless $bananas; + +# while + while ( condition ) { + ... + } + + +# for和foreach +for ($i = 0; $i <= $max; $i++) { + ... + } + +foreach (@array) { + print "This element is $_\n"; + } + + +#### 正则表达式 + +# Perl对正则表达式有深入广泛的支持,perlrequick和perlretut等文档有详细介绍。简单来说: + +# 简单匹配 +if (/foo/) { ... } # 如果 $_ 包含"foo"逻辑为真 +if ($a =~ /foo/) { ... } # 如果 $a 包含"foo"逻辑为真 + +# 简单替换 + +$a =~ s/foo/bar/; # 将$a中的foo替换为bar +$a =~ s/foo/bar/g; # 将$a中所有的foo替换为bar + + +#### 文件和输入输出 + +# 可以使用“open()”函数打开文件用于输入输出。 + +open(my $in, "<", "input.txt") or die "Can't open input.txt: $!"; +open(my $out, ">", "output.txt") or die "Can't open output.txt: $!"; +open(my $log, ">>", "my.log") or die "Can't open my.log: $!"; + +# 可以用"<>"操作符读取一个打开的文件句柄。 在标量语境下会读取一行, +# 在列表环境下会将整个文件读入并将每一行赋给列表的一个元素: + +my $line = <$in>; +my @lines = <$in>; + +#### 子程序 + +# 写子程序很简单: + +sub logger { + my $logmessage = shift; + open my $logfile, ">>", "my.log" or die "Could not open my.log: $!"; + print $logfile $logmessage; +} + +# 现在可以像内置函数一样调用子程序: + +logger("We have a logger subroutine!"); + + +``` + +#### 使用Perl模块 + +Perl模块提供一系列特性来帮助你避免重新发明轮子,CPAN是下载模块的好地方( http://www.cpan.org/ )。Perl发行版本身也包含很多流行的模块。 + +perlfaq有很多常见问题和相应回答,也经常有对优秀CPAN模块的推荐介绍。 + +#### 深入阅读 + + - [perl-tutorial](http://perl-tutorial.org/) + - [www.perl.com的learn站点](http://www.perl.org/learn.html) + - [perldoc](http://perldoc.perl.org/) + - 以及 perl 内置的: `perldoc perlintro` -- cgit v1.2.3 From a933d419e07fd8af6effa89200b581e904c61679 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 8 Sep 2013 21:52:47 -0700 Subject: Some fixes --- zh-cn/go-zh.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown index 0af5bbe3..2cff089b 100644 --- a/zh-cn/go-zh.html.markdown +++ b/zh-cn/go-zh.html.markdown @@ -1,7 +1,7 @@ --- language: Go lang: zh-cn -filename: learngo.go +filename: learngo-cn.go contributors: - ["Sonia Keys", "https://github.com/soniakeys"] - ["pantaovay", "https://github.com/pantaovay"] -- cgit v1.2.3 From 3cf89d514689ca8610c30171424b2ce1908c0465 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 8 Sep 2013 22:05:15 -0700 Subject: Updated new contributions --- zh-cn/perl-cn.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/perl-cn.html.markdown b/zh-cn/perl-cn.html.markdown index 8f99ccbf..5b0d6179 100644 --- a/zh-cn/perl-cn.html.markdown +++ b/zh-cn/perl-cn.html.markdown @@ -2,11 +2,12 @@ name: perl category: language language: perl -filename: learnperl.pl +filename: learnperl-cn.pl contributors: - ["Korjavin Ivan", "http://github.com/korjavin"] translators: - ["Yadong Wen", "https://github.com/yadongwen"] +lang: zh-cn --- Perl 5是一个功能强大、特性齐全的编程语言,有25年的历史。 -- cgit v1.2.3 From b28900b889c27f8500a44d9f9bcad5244f1f79bd Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 8 Sep 2013 22:52:09 -0700 Subject: Fixed up so it builds --- zh-cn/go-zh.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown index 2cff089b..7cc9c171 100644 --- a/zh-cn/go-zh.html.markdown +++ b/zh-cn/go-zh.html.markdown @@ -13,7 +13,7 @@ Go拥有命令式语言的静态类型,编译很快,执行也很快,同时 Go语言有非常棒的标准库,还有一个充满热情的社区。 -```Go +```go // 单行注释 /* 多行 注释 */ -- cgit v1.2.3 From 8782aded63b0b5c2b31d1aad150d02f362c4587e Mon Sep 17 00:00:00 2001 From: alswl Date: Wed, 18 Sep 2013 20:01:47 +0800 Subject: 33% --- zh-cn/r-cn.html.markdown | 153 ++++++++++++++--------------------------------- 1 file changed, 44 insertions(+), 109 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index 1bd83c60..d377703e 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -1,46 +1,28 @@ - -# Comments start with hashtags. # 评论以 # 开始 -# You can't make a multi-line comment per se, -# but you can stack multiple comments like so. -# 你不能在每一个se下执行多个注释, -# 但是你可以像这样把命注释内容堆叠起来. -# in Windows, hit COMMAND-ENTER to execute a line -# 在windows下,点击回车键来执行一条命令 +# R 语言原生不支持 多行注释 +# 但是你可以像这样来多行注释 + +# 在窗口里按回车键可以执行一条命令 ################################################################### -# Stuff you can do without understanding anything about programming -# 素材可以使那些不懂编程的人同样得心用手 +# 不用懂编程就可以开始动手了 ################################################################### -data() # Browse pre-loaded data sets -data() # 浏览预加载的数据集 -data(rivers) # Lengths of Major North American Rivers +data() # 浏览内建的数据集 data(rivers) # 北美主要河流的长度(数据集) -ls() # Notice that "rivers" appears in the workspace -ls() # 在工作站中查看”河流“文件夹是否出现 -head(rivers) # peek at the dataset -head(rivers) # 浏览数据集 +ls() # 在工作空间中查看「河流」是否出现 +head(rivers) # 撇一眼数据集 # 735 320 325 392 524 450 -length(rivers) # how many rivers were measured? +length(rivers) # 我们测量了多少条河流? # 141 -length(rivers) # 测量了多少条河流 summary(rivers) # Min. 1st Qu. Median Mean 3rd Qu. Max. # 135.0 310.0 425.0 591.2 680.0 3710.0 -#查看”河流“数据集的特征 -# 最小值. 1st Qu. 中位数 平均值 最大值 -# 135.0 310.0 425.0 591.2 680.0 3710.0 -stem(rivers) #stem-and-leaf plot (like a histogram) -stem(rivers) #茎叶图(一种类似于直方图的展现形式) - - - - +stem(rivers) # 茎叶图(一种类似于直方图的展现形式) +# # The decimal point is 2 digit(s) to the right of the | -# 小数点向|右边保留两位数字 # # 0 | 4 # 2 | 011223334555566667778888899900001111223333344455555666688888999 @@ -62,11 +44,10 @@ stem(rivers) #茎叶图(一种类似于直方图的展现形式) # 34 | # 36 | 1 -stem(log(rivers)) #Notice that the data are neither normal nor log-normal! Take that, Bell Curve fundamentalists. -stem(log(rivers)) #查看数据集的方式既不是标准形式,也不是取log后的结果! 看起来,是钟形曲线形式的基本数据集 + +stem(log(rivers)) # 查看数据集的方式既不是标准形式,也不是取log后的结果! 看起来,是钟形曲线形式的基本数据集 # The decimal point is 1 digit(s) to the left of the | -# 小数点向|左边保留一位数字 # # 48 | 1 # 50 | @@ -88,35 +69,26 @@ stem(log(rivers)) #查看数据集的方式既不是标准形式,也不是取l # 82 | 2 -hist(rivers, col="#333333", border="white", breaks=25) #play around with these parameters -hist(rivers, col="#333333", border="white", breaks=25) #给river做统计频数直方图,包含了这些参数(名称,颜色,边界,空白) -hist(log(rivers), col="#333333", border="white", breaks=25) #you'll do more plotting later -hist(log(rivers), col="#333333", border="white", breaks=25) #稍后你还可以做更多的绘图,统计频数直方图,包含了这些参数(river数据集的log值,颜色,边界,空白) -hist(rivers, col="#333333", border="white", breaks=25) #play around with these parameters -hist(rivers, col="#333333", border="white", breaks=25) #运行同济频数直方图的这些参数 +hist(rivers, col="#333333", border="white", breaks=25) # 试试用这些参数画画 (译者注:给 river 做统计频数直方图,包含了这些参数:数据源,颜色,边框,空格) +hist(log(rivers), col="#333333", border="white", breaks=25) #你还可以做更多式样的绘图 -#Here's another neat data set that comes pre-loaded. R has tons of these. data() -#这里还有其他一些简洁的数据集可以被提前加载。R语言包括大量这种类型的数据集 +# 还有其他一些简单的数据集可以被用来加载。R 语言包括了大量这种 data() data(discoveries) -#数据集(发现) plot(discoveries, col="#333333", lwd=3, xlab="Year", main="Number of important discoveries per year") -#绘图(发现,颜色负值,宽度负值,X轴名称,主题:Number of important discoveries per year) - +# 译者注:参数为(数据源,颜色,线条宽度,X 轴名称,标题) +plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year", main="Number of important discoveries per year") -#rather than leaving the default ordering (by year) we could also sort to see what's typical -#宁可舍弃也不执行排序(按照年份完成)我们可以分类来查看这是那些类型 -sort(discoveries) #给(发现)分类 +# 除了按照默认的年份排序,我们还可以排序来发现特征 +sort(discoveries) # [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 # [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 # [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 # [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 -stem(discoveries, scale=2) -#茎叶图(发现,在原来的基础上降尺度扩大两倍) -# +stem(discoveries, scale=2) # 译者注:茎叶图(数据,放大系数) +# # The decimal point is at the | -# 小数点在| # # 0 | 000000000 # 1 | 000000000000 @@ -133,32 +105,26 @@ stem(discoveries, scale=2) # 12 | 0 max(discoveries) -#最大值(发现) # 12 summary(discoveries) -#数据集特征(发现) # Min. 1st Qu. Median Mean 3rd Qu. Max. # 0.0 2.0 3.0 3.1 4.0 12.0 -#Basic statistical operations don't require any programming knowledge either #基本的统计学操作也不需要任何编程知识 -#roll a die a few times -#随机输出数据 +#随机生成数据 round(runif(7, min=.5, max=6.5)) -#round(产生均匀分布的随机数,进行四舍五入(7个, 最小值为0.5, max=6.5)) +# 译者注:runif 产生随机数,round 四舍五入 # 1 4 6 1 4 6 4 -#your numbers will differ from mine unless we set the same random.seed(31337) -#你输出的结果将会与我们给出的不同,除非我们设置了同样的随机种子 random.seed(31337) +# 你输出的结果会和我们给出的不同,除非我们设置了相同的随机种子 random.seed(31337) -#draw from a standard Gaussian 9 times -#从标准高斯函数中随机的提取9次结果 +#从标准高斯函数中随机生成 9 次 rnorm(9) # [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271 # [7] -0.59975593 0.57629164 1.08455362 @@ -172,100 +138,69 @@ rnorm(9) ######################### -# Basic programming stuff -# 基本的编程素材 +# 基础编程 ######################### -# NUMBERS +# 数值 -# "numeric" means double-precision floating-point numbers #“数值”指的是双精度的浮点数 5 # 5 class(5) # "numeric" -#定义(5)为数值型变量 # "numeric" -5e4 # 50000 #handy when dealing with large,small,or variable orders of magnitude -#5×104次方 可以手写输入改变数量级的大小将变量扩大 -6.02e23 # Avogadro's number -#阿伏伽德罗常数 -1.6e-35 # Planck length -#布朗克长度 - -# long-storage integers are written with L -#长存储整数并用L书写 +5e4 # 50000 # 用科学技术法方便的处理极大值、极小值或者可变的量级 +6.02e23 # 阿伏伽德罗常数# +1.6e-35 # 布朗克长度 + +# 长整数并用 L 结尾 5L # 5 #输出5L class(5L) # "integer" -#(5L)的类型, 整数型 -# Try ?class for more information on the class() function -#可以自己试一试?用class()功能函数定义更多的信息 -# In fact, you can look up the documentation on `xyz` with ?xyz -#事实上,你可以找一些文件查阅“xyz”以及xyz的差别 -# or see the source for `xyz` by evaluating xyz -#或者通过评估xyz来查看“xyz”的来源 +# 可以自己试一试?用 class() 函数获取更多信息 +# 事实上,你可以找一些文件查阅 `xyz` 以及xyz的差别 +# `xyz` 用来查看源码实现,?xyz 用来看帮助 -# Arithmetic -#算法 +# 算法 10 + 66 # 76 53.2 - 4 # 49.2 2 * 2.0 # 4 3L / 4 # 0.75 3 %% 2 # 1 -# Weird number types -#超自然数的类型 +# 特殊数值类型 class(NaN) # "numeric" class(Inf) # "numeric" -class(-Inf) # "numeric" #used in for example integrate( dnorm(x), 3, Inf ) -- which obviates Z-score tables -#定义以上括号内的数均为数值型变量,利用实例中的整数(正态分布函数(X),3,Inf )消除Z轴列表 +class(-Inf) # "numeric" # 在以下场景中会用到 integrate( dnorm(x), 3, Inf ) -- 消除 Z 轴数据 -# but beware, NaN isn't the only weird type... -# 但要注意,NaN并不是仅有的超自然类型。。。 -class(NA) # see below -#定义(NA)下面的部分会理解 +# 但要注意,NaN 并不是唯一的特殊数值类型…… +class(NA) # 看上面 class(NULL) # NULL -#定义(NULL)无效的 -# SIMPLE LISTS -#简单的数据集 +# 简单列表 c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9 -#输出数值型向量(6 8 7 5 3 0 9) c('alef', 'bet', 'gimmel', 'dalet', 'he') -#输出字符型变量# "alef" "bet" "gimmel" "dalet" "he" c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE -#输出逻辑型变量FALSE FALSE FALSE FALSE -#some more nice built-ins -#一些优雅的内置功能 +# 一些优雅的内置功能 5:15 # 5 6 7 8 9 10 11 12 13 14 15 -#从5-15输出,以进度为1递增 seq(from=0, to=31337, by=1337) -#输出序列(从0到31337,以1337递增) # [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 # [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 letters -#字符型变量,26个 # [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" # [20] "t" "u" "v" "w" "x" "y" "z" month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" -#表示月份的变量 # Access the n'th element of a list with list.name[n] or sometimes list.name[[n]] -#访问数据集名字为[n]的第n个元素 - +# 使用 list.name[n] 来访问第 n 个列表元素,有时候需要使用 list.name[[n]] letters[18] # "r" -#访问其中的第18个变量 LETTERS[13] # "M" -#用大写访问其中的第13个变量 month.name[9] # "September" -#访问名字文件中第9个变量 c(6, 8, 7, 5, 3, 0, 9)[3] # 7 -#访问向量中的第三个变量 -- cgit v1.2.3 From 6b9ac70e5efc9163fd2919b35559e9ea9d7d1703 Mon Sep 17 00:00:00 2001 From: alswl Date: Wed, 18 Sep 2013 21:26:38 +0800 Subject: transalted 50% --- zh-cn/r-cn.html.markdown | 156 +++++++++++++++++------------------------------ 1 file changed, 56 insertions(+), 100 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index d377703e..68867d92 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -18,8 +18,8 @@ head(rivers) # 撇一眼数据集 length(rivers) # 我们测量了多少条河流? # 141 summary(rivers) -# Min. 1st Qu. Median Mean 3rd Qu. Max. -# 135.0 310.0 425.0 591.2 680.0 3710.0 +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 135.0 310.0 425.0 591.2 680.0 3710.0 stem(rivers) # 茎叶图(一种类似于直方图的展现形式) # # The decimal point is 2 digit(s) to the right of the | @@ -34,14 +34,14 @@ stem(rivers) # 茎叶图(一种类似于直方图的展现形式) # 14 | 56 # 16 | 7 # 18 | 9 -# 20 | +# 20 | # 22 | 25 # 24 | 3 -# 26 | -# 28 | -# 30 | -# 32 | -# 34 | +# 26 | +# 28 | +# 30 | +# 32 | +# 34 | # 36 | 1 @@ -50,7 +50,7 @@ stem(log(rivers)) # 查看数据集的方式既不是标准形式,也不是取 # The decimal point is 1 digit(s) to the left of the | # # 48 | 1 -# 50 | +# 50 | # 52 | 15578 # 54 | 44571222466689 # 56 | 023334677000124455789 @@ -65,7 +65,7 @@ stem(log(rivers)) # 查看数据集的方式既不是标准形式,也不是取 # 74 | 84 # 76 | 56 # 78 | 4 -# 80 | +# 80 | # 82 | 2 @@ -101,15 +101,15 @@ stem(discoveries, scale=2) # 译者注:茎叶图(数据,放大系数) # 8 | 0 # 9 | 0 # 10 | 0 -# 11 | +# 11 | # 12 | 0 max(discoveries) # 12 summary(discoveries) -# Min. 1st Qu. Median Mean 3rd Qu. Max. -# 0.0 2.0 3.0 3.1 4.0 12.0 +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 0.0 2.0 3.0 3.1 4.0 12.0 @@ -151,7 +151,7 @@ class(5) # "numeric" 1.6e-35 # 布朗克长度 # 长整数并用 L 结尾 -5L # 5 +5L # 5 #输出5L class(5L) # "integer" @@ -178,7 +178,7 @@ class(NULL) # NULL # 简单列表 c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9 -c('alef', 'bet', 'gimmel', 'dalet', 'he') +c('alef', 'bet', 'gimmel', 'dalet', 'he') c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE # 一些优雅的内置功能 @@ -200,119 +200,80 @@ month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "D letters[18] # "r" LETTERS[13] # "M" month.name[9] # "September" -c(6, 8, 7, 5, 3, 0, 9)[3] # 7 +c(6, 8, 7, 5, 3, 0, 9)[3] # 7 -# CHARACTERS -#特性 -# There's no difference between strings and characters in R -# 字符串和字符在R语言中没有区别 +# 字符串 + +# 字符串和字符在 R 语言中没有区别 "Horatio" # "Horatio" -#字符输出"Horatio" class("Horatio") # "character" -#字符串输出("Horatio") # "character" substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " -#提取字符串("Fortuna multis dat nimis, nulli satis.", 第9个到15个之前并输出) gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." -#替换字符春,用ø替换u -# LOGICALS -#逻辑值 +# 逻辑值 -# booleans -#布尔运算 +# 布尔值 class(TRUE) # "logical" -#定义为真,逻辑型 class(FALSE) # "logical" -#定义为假,逻辑型 -# Behavior is normal -#表现的标准形式 +# 和我们预想的一样 TRUE == TRUE # TRUE TRUE == FALSE # FALSE FALSE != FALSE # FALSE FALSE != TRUE # TRUE -# Missing data (NA) is logical, too -#缺失数据也是逻辑型的 +# 缺失数据(NA)也是逻辑值 class(NA) # "logical" #定义NA为逻辑型 -# FACTORS -#因子 -# The factor class is for categorical data -#因子是分类数据的定义函数 -# which can be ordered (like childrens' grade levels) -#可以使有序的(就像儿童的等级水平) -# or unordered (like gender) -#也可以是无序的(就像性别) -levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA" -#c("female", "male", "male", "female", "NA", "female")向量,变量是字符型,levels factor()因子的等级水平 +# 因子 +# 因子是为数据分类排序设计的(像是排序小朋友们的年级或性别) +levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA" -factor(c("female", "female", "male", "NA", "female")) +factor(c("female", "female", "male", "NA", "female")) # female female male NA female # Levels: female male NA -data(infert) #Infertility after Spontaneous and Induced Abortion -#数据集(感染) 自然以及引产导致的不育症 +data(infert) # 自然以及引产导致的不育症 levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" -#等级(感染与教育程度) 输出 -# VARIABLES -#变量 +# 变量 -# Lots of way to assign stuff -#许多种方式用来分配素材 -x = 5 # this is possible -#x = 5可能的 -y <- "1" # this is preferred -#y <- "1" 优先级的 -TRUE -> z # this works but is weird -#输出真实的,存在一个超自然数满足条件 +# 有许多种方式用来赋值 +x = 5 # 这样可以 +y <- "1" # 更推荐这样 +TRUE -> z # 这样可行,但是很怪 -# We can use coerce variables to different classes -#我们还可以使用枪支变量去进行不同的定义 +#我们还可以使用强制转型 as.numeric(y) # 1 -#定义数值型 as.character(x) # "5" -#字符型 - -# LOOPS -#循环 +# 循环 -# We've got for loops -#循环语句 +# for 循环语句 for (i in 1:4) { print(i) } -#定义一个i,从1-4输出 -# We've got while loops -#我们可以获取循环结构 +# while 循环 a <- 10 while (a > 4) { cat(a, "...", sep = "") a <- a - 1 } -#把10负值为a,a<4,输出文件(a,"...",sep="" ),跳出继续下一个循环取a=a-1,如此循环,直到a=10终止 -# Keep in mind that for and while loops run slowly in R -#在R语言中牢记 for和它的循环结构 -# Operations on entire vectors (i.e. a whole row, a whole column) -#牢记矢量中附带的操作(例如,整行和整列) -# or apply()-type functions (we'll discuss later) are preferred -#或者优先使用()-函数,稍后会进行讨论 + +# 记住,在 R 语言中 for / while 循环都很慢 +# 建议使用 apply()(我们一会介绍)来错做一串数据(比如一列或者一行数据) # IF/ELSE -#判断分支 -# Again, pretty standard -#再一次,看这些优雅的标准 +# 再来看这些优雅的标准 if (4 > 3) { print("Huzzah! It worked!") } else { @@ -322,30 +283,25 @@ if (4 > 3) { # => # [1] "Huzzah! It worked!" -# FUNCTIONS -#功能函数 +# 函数 -# Defined like so: -#定义如下 +# 定义如下 jiggle <- function(x) { - x+ rnorm(x, sd=.1) #add in a bit of (controlled) noise + x + rnorm(x, sd=.1) #add in a bit of (controlled) noise return(x) } -#把功能函数x负值给jiggle, -# Called like any other R function: -jiggle(5) # 5±ε. After set.seed(2716057), jiggle(5)==5.005043 +# 和其他 R 语言函数一样调用 +jiggle(5) # 5±ε. 使用 set.seed(2716057) 后, jiggle(5)==5.005043 ######################### -# Fun with data: vectors, matrices, data frames, and arrays -# 数据参数:向量,矩阵,数据框,数组, +# 数据容器:vectors, matrices, data frames, and arrays ######################### -# ONE-DIMENSIONAL -#单维度 +# 单维度 # You can vectorize anything, so long as all components have the same type #你可以将任何东西矢量化,因此所有的组分都有相同的类型 -vec <- c(8, 9, 10, 11) +vec <- c(8, 9, 10, 11) vec # 8 9 10 11 # The class of a vector is the class of its components #矢量class表示这一组分的类型 @@ -423,10 +379,10 @@ t(mat) mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog")) mat2 # => -# [,1] [,2] -# [1,] "1" "dog" -# [2,] "2" "cat" -# [3,] "3" "bird" +# [,1] [,2] +# [1,] "1" "dog" +# [2,] "2" "cat" +# [3,] "3" "bird" # [4,] "4" "dog" class(mat2) # matrix #定义mat2矩阵 @@ -451,7 +407,7 @@ mat3 # TWO-DIMENSIONAL (DIFFERENT CLASSES) ##二维函数(不同的变量类型) -# For columns of different classes, use the data frame +# For columns of different classes, use the data frame 利用数组可以将不同类型放在一起 dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog")) #dat<-数据集(c(5,2,1,4), c("dog", "cat", "bird", "dog")) @@ -484,7 +440,7 @@ dat[,"number"] # 5 2 1 4 # You can make a two-dimensional table (sort of like a matrix) #你可以建立一个2维表格(类型和矩阵相似) array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) -#数组(c(c(1,2,4,5),c(8,9,3,6)),有前两个向量组成,2行4列 +#数组(c(c(1,2,4,5),c(8,9,3,6)),有前两个向量组成,2行4列 # => # [,1] [,2] [,3] [,4] # [1,] 1 4 8 3 @@ -540,7 +496,7 @@ mat #使用(X, MARGIN, FUN)将一个function功能函数根据其特征应用到矩阵x中 # over rows (MAR = 1) or columns (MAR = 2) #规定行列,其边界分别为1,2 -# That is, R does FUN to each row (or column) of X, much faster than a +# That is, R does FUN to each row (or column) of X, much faster than a #即就是,R定义一个function使每一行/列的x快于一个for或者while循环 # for or while loop would do apply(mat, MAR = 2, myFunc) -- cgit v1.2.3 From 3ff90ab9eb308b688480e6e3440b9e2c33d713e6 Mon Sep 17 00:00:00 2001 From: alswl Date: Wed, 18 Sep 2013 21:51:48 +0800 Subject: transalte 74% --- zh-cn/r-cn.html.markdown | 91 +++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 60 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index 68867d92..9a1414bb 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -299,42 +299,32 @@ jiggle(5) # 5±ε. 使用 set.seed(2716057) 后, jiggle(5)==5.005043 ######################### # 单维度 -# You can vectorize anything, so long as all components have the same type -#你可以将任何东西矢量化,因此所有的组分都有相同的类型 +# 你可以将目前我们学习到的任何类型矢量化,只要它们拥有相同的类型 vec <- c(8, 9, 10, 11) vec # 8 9 10 11 -# The class of a vector is the class of its components -#矢量class表示这一组分的类型 +# 矢量的类型是这一组数据元素的类型 class(vec) # "numeric" # If you vectorize items of different classes, weird coercions happen -#如果你强制的将不同类型的classes矢量化,会发生超自然形式的函数,例如都转变成数值型、字符型 +#如果你强制的将不同类型数值矢量化,会出现特殊值 c(TRUE, 4) # 1 4 c("dog", TRUE, 4) # "dog" "TRUE" "4" -# We ask for specific components like so (R starts counting from 1) -#我们可以找寻特定的组分,例如这个例子(R从1算起) +#我们这样来取内部数据,(R 的下标索引顺序 1 开始) vec[1] # 8 -# We can also search for the indices of specific components, -#我们也可以从这些特定组分中找寻这些指标 +# 我们可以根据条件查找特定数据 which(vec %% 2 == 0) # 1 3 -# or grab just the first or last entry in the vector -#抓取矢量中第1个和最后一个字符 +# 抓取矢量中第一个和最后一个字符 head(vec, 1) # 8 tail(vec, 1) # 11 -#如果指数结束或不存在即"goes over" 可以获得NA -# If an index "goes over" you'll get NA: +#如果下标溢出或不存会得到 NA vec[6] # NA -# You can find the length of your vector with length() -#你也可以找到矢量的长度 +# 你可以使用 length() 获取矢量的长度 length(vec) # 4 -# You can perform operations on entire vectors or subsets of vectors -#你可以将整个矢量或者子矢量集进行展示 +# 你可以直接操作矢量或者矢量的子集 vec * 4 # 16 20 24 28 -# vec[2:3] * 5 # 25 30 -# and there are many built-in functions to summarize vectors -#这里有许多内置的功能函数,并且可对矢量特征进行总结 +# 这里有许多内置的函数,来表现向量 mean(vec) # 9.5 var(vec) # 1.666667 sd(vec) # 1.290994 @@ -342,40 +332,32 @@ max(vec) # 11 min(vec) # 8 sum(vec) # 38 -# TWO-DIMENSIONAL (ALL ONE CLASS) -#二维函数 +# 二维(相同元素类型) -# You can make a matrix out of entries all of the same type like so: -#你可以建立矩阵,保证所有的变量形式相同 +#你可以为同样类型的变量建立矩阵 mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6)) -#建立mat矩阵,3行2列,从1到6排列,默认按列排布 mat # => # [,1] [,2] # [1,] 1 4 # [2,] 2 5 # [3,] 3 6 -# Unlike a vector, the class of a matrix is "matrix", no matter what's in it +# 和 vector 不一样的是,一个矩阵的类型真的是 「matrix」,而不是内部元素的类型 class(mat) # => "matrix" -# Ask for the first row -#访问第一行的字符 +# 访问第一行的字符 mat[1,] # 1 4 -# Perform operation on the first column -#优先输入第一列,分别×3输出 +# 操作第一行数据 3 * mat[,1] # 3 6 9 -# Ask for a specific cell -#访问特殊的单元,第3行第二列 +# 访问一个特定数据 mat[3,2] # 6 -# Transpose the whole matrix -#转置整个矩阵,变成2行3列 +# 转置整个矩阵(译者注:变成 2 行 3 列) t(mat) # => # [,1] [,2] [,3] # [1,] 1 2 3 # [2,] 4 5 6 -# cbind() sticks vectors together column-wise to make a matrix -把两个矩阵按列合并,形成新的矩阵 +# 使用 cbind() 函数把两个矩阵按列合并,形成新的矩阵 mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog")) mat2 # => @@ -385,36 +367,27 @@ mat2 # [3,] "3" "bird" # [4,] "4" "dog" class(mat2) # matrix -#定义mat2矩阵 # Again, note what happened! -#同样的注释 -# Because matrices must contain entries all of the same class, -#矩阵必须包含同样的形式 -# everything got converted to the character class -#每一个变量都可以转化成字符串形式 +# 注意 +# 因为矩阵内部元素必须包含同样的类型 +# 所以现在每一个元素都转化成字符串 c(class(mat2[,1]), class(mat2[,2])) -# rbind() sticks vectors together row-wise to make a matrix -#按行合并两个向量,建立新的矩阵 +# 按行合并两个向量,建立新的矩阵 mat3 <- rbind(c(1,2,4,5), c(6,7,0,4)) mat3 # => # [,1] [,2] [,3] [,4] # [1,] 1 2 4 5 # [2,] 6 7 0 4 -# Aah, everything of the same class. No coercions. Much better. +# 哈哈,数据类型都一样的,没有发生强制转换,生活真美好 -# TWO-DIMENSIONAL (DIFFERENT CLASSES) -##二维函数(不同的变量类型) +# 二维(不同的元素类型) -# For columns of different classes, use the data frame -利用数组可以将不同类型放在一起 +# 利用 data frame 可以将不同类型数据放在一起 dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog")) -#dat<-数据集(c(5,2,1,4), c("dog", "cat", "bird", "dog")) -names(dat) <- c("number", "species") # name the columns -#给每一个向量命名 +names(dat) <- c("number", "species") # 给数据列命名 class(dat) # "data.frame" -#建立数据集dat dat # => # number species @@ -425,18 +398,16 @@ dat class(dat$number) # "numeric" class(dat[,2]) # "factor" # The data.frame() function converts character vectors to factor vectors -#数据集,将字符特征转化为因子矢量 +# data.frame() 会将字符向量转换为 factor 向量 -# There are many twisty ways to subset data frames, all subtly unalike -#这里有许多种生成数据集的方法,所有的都很巧妙但又不相似 +# 有很多精妙的方法来获取 data frame 的子数据集 dat$number # 5 2 1 4 dat[,1] # 5 2 1 4 dat[,"number"] # 5 2 1 4 -# MULTI-DIMENSIONAL (ALL OF ONE CLASS) -#多维函数 -# Arrays creates n-dimensional tables -#利用数组创造一个n维的表格 +# 多维(相同元素类型) + +# 利用数组创造一个 n 维的表格 # You can make a two-dimensional table (sort of like a matrix) #你可以建立一个2维表格(类型和矩阵相似) array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) -- cgit v1.2.3 From bfd1293c4f9daa5ae3ce6dccc24b8b67c3113e07 Mon Sep 17 00:00:00 2001 From: alswl Date: Sun, 29 Sep 2013 23:09:45 +0800 Subject: translate to Chinese 100% --- zh-cn/r-cn.html.markdown | 121 +++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 67 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index 9a1414bb..bfb92ca9 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -1,3 +1,18 @@ +--- +language: R +contributors: + - ["e99n09", "http://github.com/e99n09"] + - ["isomorphismes", "http://twitter.com/isomorphisms"] +translators: + - ["小柒", "http://weibo.com/u/2328126220"] + - ["alswl", "https://github.com/alswl"] +filename: learnr.r +--- + +R 是一门统计语言。它有很多数据分析和挖掘程序包。可以用来统计、分析和制图。 +你也可以在 LaTeX 文档中运行 `R` 命令。 + +```python # 评论以 # 开始 # R 语言原生不支持 多行注释 @@ -397,7 +412,6 @@ dat # 4 4 dog class(dat$number) # "numeric" class(dat[,2]) # "factor" -# The data.frame() function converts character vectors to factor vectors # data.frame() 会将字符向量转换为 factor 向量 # 有很多精妙的方法来获取 data frame 的子数据集 @@ -407,16 +421,14 @@ dat[,"number"] # 5 2 1 4 # 多维(相同元素类型) -# 利用数组创造一个 n 维的表格 +# 使用 arry 创造一个 n 维的表格 # You can make a two-dimensional table (sort of like a matrix) -#你可以建立一个2维表格(类型和矩阵相似) +# 你可以建立一个 2 维表格(有点像矩阵) array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) -#数组(c(c(1,2,4,5),c(8,9,3,6)),有前两个向量组成,2行4列 # => # [,1] [,2] [,3] [,4] # [1,] 1 4 8 3 # [2,] 2 5 9 6 -# You can use array to make three-dimensional matrices too #你也可以利用数组建立一个三维的矩阵 array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) # => @@ -434,29 +446,25 @@ array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) # [2,] 60 7 # [3,] 0 847 -# LISTS (MULTI-DIMENSIONAL, POSSIBLY RAGGED, OF DIFFERENT TYPES) #列表(多维的,不同类型的) -# Finally, R has lists (of vectors) -#R语言有列表的形式 +# R语言有列表的形式 list1 <- list(time = 1:40) -list1$price = c(rnorm(40,.5*list1$time,4)) # random +list1$price = c(rnorm(40,.5*list1$time,4)) # 随机 list1 # You can get items in the list like so -#你可以获得像上面列表的形式 +# 你可以这样获得列表的元素 list1$time # You can subset list items like vectors -#你也可以获取他们的子集,一种类似于矢量的形式 +# 你也可以和矢量一样获取他们的子集 list1$price[4] ######################### -# The apply() family of functions -#apply()函数家族的应用 +# apply()函数家族 ######################### -# Remember mat? -#输出mat矩阵 +# 还记得 mat 么? mat # => # [,1] [,2] @@ -464,90 +472,69 @@ mat # [2,] 2 5 # [3,] 3 6 # Use apply(X, MARGIN, FUN) to apply function FUN to a matrix X -#使用(X, MARGIN, FUN)将一个function功能函数根据其特征应用到矩阵x中 -# over rows (MAR = 1) or columns (MAR = 2) -#规定行列,其边界分别为1,2 +# 使用(X, MARGIN, FUN)将函数 FUN 应用到矩阵 X 的行 (MAR = 1) 或者 列 (MAR = 2) # That is, R does FUN to each row (or column) of X, much faster than a -#即就是,R定义一个function使每一行/列的x快于一个for或者while循环 -# for or while loop would do +# R 在 X 的每一行/列使用 FUN,比循环要快很多 apply(mat, MAR = 2, myFunc) # => # [,1] [,2] # [1,] 3 15 # [2,] 7 19 # [3,] 11 23 -# Other functions: ?lapply, ?sapply -其他的功能函数, +# 还有其他家族函数 ?lapply, ?sapply -# Don't feel too intimidated; everyone agrees they are rather confusing -#不要被这些吓到,许多人在此都会容易混淆 -# The plyr package aims to replace (and improve upon!) the *apply() family. -#plyr程序包的作用是用来改进family函数家族 +# 不要被吓到,虽然许多人在此都被搞混 +# plyr 程序包的作用是用来改进 apply() 函数家族 install.packages("plyr") require(plyr) ?plyr ######################### -# Loading data +# 载入数据 ######################### -# "pets.csv" is a file on the internet -#"pets.csv" 是网上的一个文本 +# "pets.csv" 是网上的一个文本 pets <- read.csv("http://learnxinyminutes.com/docs/pets.csv") -#首先读取这个文本 pets -head(pets, 2) # first two rows -#显示前两行 -tail(pets, 1) # last row -#显示最后一行 - -# To save a data frame or matrix as a .csv file -#以.csv格式来保存数据集或者矩阵 -write.csv(pets, "pets2.csv") # to make a new .csv file -#输出新的文本pets2.csv +head(pets, 2) # 前两行 +tail(pets, 1) # 最后一行 + +# 以 .csv 格式来保存数据集或者矩阵 +write.csv(pets, "pets2.csv") # 保存到新的文件 pets2.csv # set working directory with setwd(), look it up with getwd() -#改变工作路径setwd(),查找工作路径getwd() +# 使用 setwd() 改变工作目录,使用 getwd() 查看当前工作目录 -# Try ?read.csv and ?write.csv for more information -#试着做一做以上学到的,或者运行更多的信息 +# 尝试使用 ?read.csv 和 ?write.csv 来查看更多信息 ######################### -# Plots -#画图 +# 画图 ######################### -# Scatterplots! -#散点图 -plot(list1$time, list1$price, main = "fake data") -#作图,横轴list1$time,纵轴list1$price,主题fake data -# Regressions! -#退回 -linearModel <- lm(price ~ time, data = list1) -# 线性模型,数据集为list1,以价格对时间做相关分析模型 -linearModel # outputs result of regression -#输出拟合结果,并退出 -# Plot regression line on existing plot -#将拟合结果展示在图上,颜色设为红色 +# 散点图 +plot(list1$time, list1$price, main = "fake data") # 译者注:横轴 list1$time,纵轴 wlist1$price,标题 fake data +# 回归图 +linearModel <- lm(price ~ time, data = list1) # 译者注:线性模型,数据集为list1,以价格对时间做相关分析模型 +linearModel # 拟合结果 +# 将拟合结果展示在图上,颜色设为红色 abline(linearModel, col = "red") -# Get a variety of nice diagnostics -#也可以获取各种各样漂亮的分析图 +# 也可以获取各种各样漂亮的分析图 plot(linearModel) -# Histograms! -#直方图 -hist(rpois(n = 10000, lambda = 5), col = "thistle") -#统计频数直方图() +# 直方图 +hist(rpois(n = 10000, lambda = 5), col = "thistle") # 译者注:统计频数直方图 -# Barplots! -#柱状图 +# 柱状图 barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) -#作图,柱的高度负值c(1,4,5,1,2),各个柱子的名称"red","blue","purple","green","yellow" -# Try the ggplot2 package for more and better graphics -#可以尝试着使用ggplot2程序包来美化图片 +# 可以尝试着使用 ggplot2 程序包来美化图片 install.packages("ggplot2") require(ggplot2) ?ggplot2 +``` + +## 获得 R +* 从 [http://www.r-project.org/](http://www.r-project.org/) 获得安装包和图形化界面 +* [RStudio](http://www.rstudio.com/ide/) 是另一个图形化界面 -- cgit v1.2.3 From f308445fe5a3b236880b95229ed180104faeaa25 Mon Sep 17 00:00:00 2001 From: alswl Date: Sun, 29 Sep 2013 23:10:25 +0800 Subject: dos2unix --- zh-cn/r-cn.html.markdown | 1080 +++++++++++++++++++++++----------------------- 1 file changed, 540 insertions(+), 540 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index bfb92ca9..8a542695 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -1,540 +1,540 @@ ---- -language: R -contributors: - - ["e99n09", "http://github.com/e99n09"] - - ["isomorphismes", "http://twitter.com/isomorphisms"] -translators: - - ["小柒", "http://weibo.com/u/2328126220"] - - ["alswl", "https://github.com/alswl"] -filename: learnr.r ---- - -R 是一门统计语言。它有很多数据分析和挖掘程序包。可以用来统计、分析和制图。 -你也可以在 LaTeX 文档中运行 `R` 命令。 - -```python -# 评论以 # 开始 - -# R 语言原生不支持 多行注释 -# 但是你可以像这样来多行注释 - -# 在窗口里按回车键可以执行一条命令 - - -################################################################### -# 不用懂编程就可以开始动手了 -################################################################### - -data() # 浏览内建的数据集 -data(rivers) # 北美主要河流的长度(数据集) -ls() # 在工作空间中查看「河流」是否出现 -head(rivers) # 撇一眼数据集 -# 735 320 325 392 524 450 -length(rivers) # 我们测量了多少条河流? -# 141 -summary(rivers) -# Min. 1st Qu. Median Mean 3rd Qu. Max. -# 135.0 310.0 425.0 591.2 680.0 3710.0 -stem(rivers) # 茎叶图(一种类似于直方图的展现形式) -# -# The decimal point is 2 digit(s) to the right of the | -# -# 0 | 4 -# 2 | 011223334555566667778888899900001111223333344455555666688888999 -# 4 | 111222333445566779001233344567 -# 6 | 000112233578012234468 -# 8 | 045790018 -# 10 | 04507 -# 12 | 1471 -# 14 | 56 -# 16 | 7 -# 18 | 9 -# 20 | -# 22 | 25 -# 24 | 3 -# 26 | -# 28 | -# 30 | -# 32 | -# 34 | -# 36 | 1 - - -stem(log(rivers)) # 查看数据集的方式既不是标准形式,也不是取log后的结果! 看起来,是钟形曲线形式的基本数据集 - -# The decimal point is 1 digit(s) to the left of the | -# -# 48 | 1 -# 50 | -# 52 | 15578 -# 54 | 44571222466689 -# 56 | 023334677000124455789 -# 58 | 00122366666999933445777 -# 60 | 122445567800133459 -# 62 | 112666799035 -# 64 | 00011334581257889 -# 66 | 003683579 -# 68 | 0019156 -# 70 | 079357 -# 72 | 89 -# 74 | 84 -# 76 | 56 -# 78 | 4 -# 80 | -# 82 | 2 - - -hist(rivers, col="#333333", border="white", breaks=25) # 试试用这些参数画画 (译者注:给 river 做统计频数直方图,包含了这些参数:数据源,颜色,边框,空格) -hist(log(rivers), col="#333333", border="white", breaks=25) #你还可以做更多式样的绘图 - -# 还有其他一些简单的数据集可以被用来加载。R 语言包括了大量这种 data() -data(discoveries) -plot(discoveries, col="#333333", lwd=3, xlab="Year", main="Number of important discoveries per year") -# 译者注:参数为(数据源,颜色,线条宽度,X 轴名称,标题) -plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year", main="Number of important discoveries per year") - - -# 除了按照默认的年份排序,我们还可以排序来发现特征 -sort(discoveries) -# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 -# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 -# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 -# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 - -stem(discoveries, scale=2) # 译者注:茎叶图(数据,放大系数) -# -# The decimal point is at the | -# -# 0 | 000000000 -# 1 | 000000000000 -# 2 | 00000000000000000000000000 -# 3 | 00000000000000000000 -# 4 | 000000000000 -# 5 | 0000000 -# 6 | 000000 -# 7 | 0000 -# 8 | 0 -# 9 | 0 -# 10 | 0 -# 11 | -# 12 | 0 - -max(discoveries) -# 12 - -summary(discoveries) -# Min. 1st Qu. Median Mean 3rd Qu. Max. -# 0.0 2.0 3.0 3.1 4.0 12.0 - - - - -#基本的统计学操作也不需要任何编程知识 - -#随机生成数据 -round(runif(7, min=.5, max=6.5)) -# 译者注:runif 产生随机数,round 四舍五入 -# 1 4 6 1 4 6 4 - -# 你输出的结果会和我们给出的不同,除非我们设置了相同的随机种子 random.seed(31337) - - -#从标准高斯函数中随机生成 9 次 -rnorm(9) -# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271 -# [7] -0.59975593 0.57629164 1.08455362 - - - - - - - - - -######################### -# 基础编程 -######################### - -# 数值 - -#“数值”指的是双精度的浮点数 -5 # 5 -class(5) # "numeric" -5e4 # 50000 # 用科学技术法方便的处理极大值、极小值或者可变的量级 -6.02e23 # 阿伏伽德罗常数# -1.6e-35 # 布朗克长度 - -# 长整数并用 L 结尾 -5L # 5 -#输出5L -class(5L) # "integer" - -# 可以自己试一试?用 class() 函数获取更多信息 -# 事实上,你可以找一些文件查阅 `xyz` 以及xyz的差别 -# `xyz` 用来查看源码实现,?xyz 用来看帮助 - -# 算法 -10 + 66 # 76 -53.2 - 4 # 49.2 -2 * 2.0 # 4 -3L / 4 # 0.75 -3 %% 2 # 1 - -# 特殊数值类型 -class(NaN) # "numeric" -class(Inf) # "numeric" -class(-Inf) # "numeric" # 在以下场景中会用到 integrate( dnorm(x), 3, Inf ) -- 消除 Z 轴数据 - -# 但要注意,NaN 并不是唯一的特殊数值类型…… -class(NA) # 看上面 -class(NULL) # NULL - - -# 简单列表 -c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9 -c('alef', 'bet', 'gimmel', 'dalet', 'he') -c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE - -# 一些优雅的内置功能 -5:15 # 5 6 7 8 9 10 11 12 13 14 15 - -seq(from=0, to=31337, by=1337) -# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 -# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 - -letters -# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" -# [20] "t" "u" "v" "w" "x" "y" "z" - -month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" - - -# Access the n'th element of a list with list.name[n] or sometimes list.name[[n]] -# 使用 list.name[n] 来访问第 n 个列表元素,有时候需要使用 list.name[[n]] -letters[18] # "r" -LETTERS[13] # "M" -month.name[9] # "September" -c(6, 8, 7, 5, 3, 0, 9)[3] # 7 - - - -# 字符串 - -# 字符串和字符在 R 语言中没有区别 -"Horatio" # "Horatio" -class("Horatio") # "character" -substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " -gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." - - - -# 逻辑值 - -# 布尔值 -class(TRUE) # "logical" -class(FALSE) # "logical" -# 和我们预想的一样 -TRUE == TRUE # TRUE -TRUE == FALSE # FALSE -FALSE != FALSE # FALSE -FALSE != TRUE # TRUE -# 缺失数据(NA)也是逻辑值 -class(NA) # "logical" -#定义NA为逻辑型 - - - -# 因子 -# 因子是为数据分类排序设计的(像是排序小朋友们的年级或性别) -levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA" - -factor(c("female", "female", "male", "NA", "female")) -# female female male NA female -# Levels: female male NA - -data(infert) # 自然以及引产导致的不育症 -levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" - - - -# 变量 - -# 有许多种方式用来赋值 -x = 5 # 这样可以 -y <- "1" # 更推荐这样 -TRUE -> z # 这样可行,但是很怪 - -#我们还可以使用强制转型 -as.numeric(y) # 1 -as.character(x) # "5" - -# 循环 - -# for 循环语句 -for (i in 1:4) { - print(i) -} - -# while 循环 -a <- 10 -while (a > 4) { - cat(a, "...", sep = "") - a <- a - 1 -} - -# 记住,在 R 语言中 for / while 循环都很慢 -# 建议使用 apply()(我们一会介绍)来错做一串数据(比如一列或者一行数据) - -# IF/ELSE - -# 再来看这些优雅的标准 -if (4 > 3) { - print("Huzzah! It worked!") -} else { - print("Noooo! This is blatantly illogical!") -} - -# => -# [1] "Huzzah! It worked!" - -# 函数 - -# 定义如下 -jiggle <- function(x) { - x + rnorm(x, sd=.1) #add in a bit of (controlled) noise - return(x) -} - -# 和其他 R 语言函数一样调用 -jiggle(5) # 5±ε. 使用 set.seed(2716057) 后, jiggle(5)==5.005043 - -######################### -# 数据容器:vectors, matrices, data frames, and arrays -######################### - -# 单维度 -# 你可以将目前我们学习到的任何类型矢量化,只要它们拥有相同的类型 -vec <- c(8, 9, 10, 11) -vec # 8 9 10 11 -# 矢量的类型是这一组数据元素的类型 -class(vec) # "numeric" -# If you vectorize items of different classes, weird coercions happen -#如果你强制的将不同类型数值矢量化,会出现特殊值 -c(TRUE, 4) # 1 4 -c("dog", TRUE, 4) # "dog" "TRUE" "4" - -#我们这样来取内部数据,(R 的下标索引顺序 1 开始) -vec[1] # 8 -# 我们可以根据条件查找特定数据 -which(vec %% 2 == 0) # 1 3 -# 抓取矢量中第一个和最后一个字符 -head(vec, 1) # 8 -tail(vec, 1) # 11 -#如果下标溢出或不存会得到 NA -vec[6] # NA -# 你可以使用 length() 获取矢量的长度 -length(vec) # 4 - -# 你可以直接操作矢量或者矢量的子集 -vec * 4 # 16 20 24 28 -vec[2:3] * 5 # 25 30 -# 这里有许多内置的函数,来表现向量 -mean(vec) # 9.5 -var(vec) # 1.666667 -sd(vec) # 1.290994 -max(vec) # 11 -min(vec) # 8 -sum(vec) # 38 - -# 二维(相同元素类型) - -#你可以为同样类型的变量建立矩阵 -mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6)) -mat -# => -# [,1] [,2] -# [1,] 1 4 -# [2,] 2 5 -# [3,] 3 6 -# 和 vector 不一样的是,一个矩阵的类型真的是 「matrix」,而不是内部元素的类型 -class(mat) # => "matrix" -# 访问第一行的字符 -mat[1,] # 1 4 -# 操作第一行数据 -3 * mat[,1] # 3 6 9 -# 访问一个特定数据 -mat[3,2] # 6 -# 转置整个矩阵(译者注:变成 2 行 3 列) -t(mat) -# => -# [,1] [,2] [,3] -# [1,] 1 2 3 -# [2,] 4 5 6 - -# 使用 cbind() 函数把两个矩阵按列合并,形成新的矩阵 -mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog")) -mat2 -# => -# [,1] [,2] -# [1,] "1" "dog" -# [2,] "2" "cat" -# [3,] "3" "bird" -# [4,] "4" "dog" -class(mat2) # matrix -# Again, note what happened! -# 注意 -# 因为矩阵内部元素必须包含同样的类型 -# 所以现在每一个元素都转化成字符串 -c(class(mat2[,1]), class(mat2[,2])) - -# 按行合并两个向量,建立新的矩阵 -mat3 <- rbind(c(1,2,4,5), c(6,7,0,4)) -mat3 -# => -# [,1] [,2] [,3] [,4] -# [1,] 1 2 4 5 -# [2,] 6 7 0 4 -# 哈哈,数据类型都一样的,没有发生强制转换,生活真美好 - -# 二维(不同的元素类型) - -# 利用 data frame 可以将不同类型数据放在一起 -dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog")) -names(dat) <- c("number", "species") # 给数据列命名 -class(dat) # "data.frame" -dat -# => -# number species -# 1 5 dog -# 2 2 cat -# 3 1 bird -# 4 4 dog -class(dat$number) # "numeric" -class(dat[,2]) # "factor" -# data.frame() 会将字符向量转换为 factor 向量 - -# 有很多精妙的方法来获取 data frame 的子数据集 -dat$number # 5 2 1 4 -dat[,1] # 5 2 1 4 -dat[,"number"] # 5 2 1 4 - -# 多维(相同元素类型) - -# 使用 arry 创造一个 n 维的表格 -# You can make a two-dimensional table (sort of like a matrix) -# 你可以建立一个 2 维表格(有点像矩阵) -array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) -# => -# [,1] [,2] [,3] [,4] -# [1,] 1 4 8 3 -# [2,] 2 5 9 6 -#你也可以利用数组建立一个三维的矩阵 -array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) -# => -# , , 1 -# -# [,1] [,2] -# [1,] 2 8 -# [2,] 300 9 -# [3,] 4 0 -# -# , , 2 -# -# [,1] [,2] -# [1,] 5 66 -# [2,] 60 7 -# [3,] 0 847 - -#列表(多维的,不同类型的) - -# R语言有列表的形式 -list1 <- list(time = 1:40) -list1$price = c(rnorm(40,.5*list1$time,4)) # 随机 -list1 - -# You can get items in the list like so -# 你可以这样获得列表的元素 -list1$time -# You can subset list items like vectors -# 你也可以和矢量一样获取他们的子集 -list1$price[4] - -######################### -# apply()函数家族 -######################### - -# 还记得 mat 么? -mat -# => -# [,1] [,2] -# [1,] 1 4 -# [2,] 2 5 -# [3,] 3 6 -# Use apply(X, MARGIN, FUN) to apply function FUN to a matrix X -# 使用(X, MARGIN, FUN)将函数 FUN 应用到矩阵 X 的行 (MAR = 1) 或者 列 (MAR = 2) -# That is, R does FUN to each row (or column) of X, much faster than a -# R 在 X 的每一行/列使用 FUN,比循环要快很多 -apply(mat, MAR = 2, myFunc) -# => -# [,1] [,2] -# [1,] 3 15 -# [2,] 7 19 -# [3,] 11 23 -# 还有其他家族函数 ?lapply, ?sapply - -# 不要被吓到,虽然许多人在此都被搞混 -# plyr 程序包的作用是用来改进 apply() 函数家族 - -install.packages("plyr") -require(plyr) -?plyr - -######################### -# 载入数据 -######################### - -# "pets.csv" 是网上的一个文本 -pets <- read.csv("http://learnxinyminutes.com/docs/pets.csv") -pets -head(pets, 2) # 前两行 -tail(pets, 1) # 最后一行 - -# 以 .csv 格式来保存数据集或者矩阵 -write.csv(pets, "pets2.csv") # 保存到新的文件 pets2.csv -# set working directory with setwd(), look it up with getwd() -# 使用 setwd() 改变工作目录,使用 getwd() 查看当前工作目录 - -# 尝试使用 ?read.csv 和 ?write.csv 来查看更多信息 - -######################### -# 画图 -######################### - -# 散点图 -plot(list1$time, list1$price, main = "fake data") # 译者注:横轴 list1$time,纵轴 wlist1$price,标题 fake data -# 回归图 -linearModel <- lm(price ~ time, data = list1) # 译者注:线性模型,数据集为list1,以价格对时间做相关分析模型 -linearModel # 拟合结果 -# 将拟合结果展示在图上,颜色设为红色 -abline(linearModel, col = "red") -# 也可以获取各种各样漂亮的分析图 -plot(linearModel) - -# 直方图 -hist(rpois(n = 10000, lambda = 5), col = "thistle") # 译者注:统计频数直方图 - -# 柱状图 -barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) - -# 可以尝试着使用 ggplot2 程序包来美化图片 -install.packages("ggplot2") -require(ggplot2) -?ggplot2 - -``` - -## 获得 R - -* 从 [http://www.r-project.org/](http://www.r-project.org/) 获得安装包和图形化界面 -* [RStudio](http://www.rstudio.com/ide/) 是另一个图形化界面 +--- +language: R +contributors: + - ["e99n09", "http://github.com/e99n09"] + - ["isomorphismes", "http://twitter.com/isomorphisms"] +translators: + - ["小柒", "http://weibo.com/u/2328126220"] + - ["alswl", "https://github.com/alswl"] +filename: learnr.r +--- + +R 是一门统计语言。它有很多数据分析和挖掘程序包。可以用来统计、分析和制图。 +你也可以在 LaTeX 文档中运行 `R` 命令。 + +```python +# 评论以 # 开始 + +# R 语言原生不支持 多行注释 +# 但是你可以像这样来多行注释 + +# 在窗口里按回车键可以执行一条命令 + + +################################################################### +# 不用懂编程就可以开始动手了 +################################################################### + +data() # 浏览内建的数据集 +data(rivers) # 北美主要河流的长度(数据集) +ls() # 在工作空间中查看「河流」是否出现 +head(rivers) # 撇一眼数据集 +# 735 320 325 392 524 450 +length(rivers) # 我们测量了多少条河流? +# 141 +summary(rivers) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 135.0 310.0 425.0 591.2 680.0 3710.0 +stem(rivers) # 茎叶图(一种类似于直方图的展现形式) +# +# The decimal point is 2 digit(s) to the right of the | +# +# 0 | 4 +# 2 | 011223334555566667778888899900001111223333344455555666688888999 +# 4 | 111222333445566779001233344567 +# 6 | 000112233578012234468 +# 8 | 045790018 +# 10 | 04507 +# 12 | 1471 +# 14 | 56 +# 16 | 7 +# 18 | 9 +# 20 | +# 22 | 25 +# 24 | 3 +# 26 | +# 28 | +# 30 | +# 32 | +# 34 | +# 36 | 1 + + +stem(log(rivers)) # 查看数据集的方式既不是标准形式,也不是取log后的结果! 看起来,是钟形曲线形式的基本数据集 + +# The decimal point is 1 digit(s) to the left of the | +# +# 48 | 1 +# 50 | +# 52 | 15578 +# 54 | 44571222466689 +# 56 | 023334677000124455789 +# 58 | 00122366666999933445777 +# 60 | 122445567800133459 +# 62 | 112666799035 +# 64 | 00011334581257889 +# 66 | 003683579 +# 68 | 0019156 +# 70 | 079357 +# 72 | 89 +# 74 | 84 +# 76 | 56 +# 78 | 4 +# 80 | +# 82 | 2 + + +hist(rivers, col="#333333", border="white", breaks=25) # 试试用这些参数画画 (译者注:给 river 做统计频数直方图,包含了这些参数:数据源,颜色,边框,空格) +hist(log(rivers), col="#333333", border="white", breaks=25) #你还可以做更多式样的绘图 + +# 还有其他一些简单的数据集可以被用来加载。R 语言包括了大量这种 data() +data(discoveries) +plot(discoveries, col="#333333", lwd=3, xlab="Year", main="Number of important discoveries per year") +# 译者注:参数为(数据源,颜色,线条宽度,X 轴名称,标题) +plot(discoveries, col="#333333", lwd=3, type = "h", xlab="Year", main="Number of important discoveries per year") + + +# 除了按照默认的年份排序,我们还可以排序来发现特征 +sort(discoveries) +# [1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 +# [26] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 +# [51] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 +# [76] 4 4 4 4 5 5 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 8 9 10 12 + +stem(discoveries, scale=2) # 译者注:茎叶图(数据,放大系数) +# +# The decimal point is at the | +# +# 0 | 000000000 +# 1 | 000000000000 +# 2 | 00000000000000000000000000 +# 3 | 00000000000000000000 +# 4 | 000000000000 +# 5 | 0000000 +# 6 | 000000 +# 7 | 0000 +# 8 | 0 +# 9 | 0 +# 10 | 0 +# 11 | +# 12 | 0 + +max(discoveries) +# 12 + +summary(discoveries) +# Min. 1st Qu. Median Mean 3rd Qu. Max. +# 0.0 2.0 3.0 3.1 4.0 12.0 + + + + +#基本的统计学操作也不需要任何编程知识 + +#随机生成数据 +round(runif(7, min=.5, max=6.5)) +# 译者注:runif 产生随机数,round 四舍五入 +# 1 4 6 1 4 6 4 + +# 你输出的结果会和我们给出的不同,除非我们设置了相同的随机种子 random.seed(31337) + + +#从标准高斯函数中随机生成 9 次 +rnorm(9) +# [1] 0.07528471 1.03499859 1.34809556 -0.82356087 0.61638975 -1.88757271 +# [7] -0.59975593 0.57629164 1.08455362 + + + + + + + + + +######################### +# 基础编程 +######################### + +# 数值 + +#“数值”指的是双精度的浮点数 +5 # 5 +class(5) # "numeric" +5e4 # 50000 # 用科学技术法方便的处理极大值、极小值或者可变的量级 +6.02e23 # 阿伏伽德罗常数# +1.6e-35 # 布朗克长度 + +# 长整数并用 L 结尾 +5L # 5 +#输出5L +class(5L) # "integer" + +# 可以自己试一试?用 class() 函数获取更多信息 +# 事实上,你可以找一些文件查阅 `xyz` 以及xyz的差别 +# `xyz` 用来查看源码实现,?xyz 用来看帮助 + +# 算法 +10 + 66 # 76 +53.2 - 4 # 49.2 +2 * 2.0 # 4 +3L / 4 # 0.75 +3 %% 2 # 1 + +# 特殊数值类型 +class(NaN) # "numeric" +class(Inf) # "numeric" +class(-Inf) # "numeric" # 在以下场景中会用到 integrate( dnorm(x), 3, Inf ) -- 消除 Z 轴数据 + +# 但要注意,NaN 并不是唯一的特殊数值类型…… +class(NA) # 看上面 +class(NULL) # NULL + + +# 简单列表 +c(6, 8, 7, 5, 3, 0, 9) # 6 8 7 5 3 0 9 +c('alef', 'bet', 'gimmel', 'dalet', 'he') +c('Z', 'o', 'r', 'o') == "Zoro" # FALSE FALSE FALSE FALSE + +# 一些优雅的内置功能 +5:15 # 5 6 7 8 9 10 11 12 13 14 15 + +seq(from=0, to=31337, by=1337) +# [1] 0 1337 2674 4011 5348 6685 8022 9359 10696 12033 13370 14707 +# [13] 16044 17381 18718 20055 21392 22729 24066 25403 26740 28077 29414 30751 + +letters +# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" +# [20] "t" "u" "v" "w" "x" "y" "z" + +month.abb # "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" + + +# Access the n'th element of a list with list.name[n] or sometimes list.name[[n]] +# 使用 list.name[n] 来访问第 n 个列表元素,有时候需要使用 list.name[[n]] +letters[18] # "r" +LETTERS[13] # "M" +month.name[9] # "September" +c(6, 8, 7, 5, 3, 0, 9)[3] # 7 + + + +# 字符串 + +# 字符串和字符在 R 语言中没有区别 +"Horatio" # "Horatio" +class("Horatio") # "character" +substr("Fortuna multis dat nimis, nulli satis.", 9, 15) # "multis " +gsub('u', 'ø', "Fortuna multis dat nimis, nulli satis.") # "Fortøna møltis dat nimis, nølli satis." + + + +# 逻辑值 + +# 布尔值 +class(TRUE) # "logical" +class(FALSE) # "logical" +# 和我们预想的一样 +TRUE == TRUE # TRUE +TRUE == FALSE # FALSE +FALSE != FALSE # FALSE +FALSE != TRUE # TRUE +# 缺失数据(NA)也是逻辑值 +class(NA) # "logical" +#定义NA为逻辑型 + + + +# 因子 +# 因子是为数据分类排序设计的(像是排序小朋友们的年级或性别) +levels(factor(c("female", "male", "male", "female", "NA", "female"))) # "female" "male" "NA" + +factor(c("female", "female", "male", "NA", "female")) +# female female male NA female +# Levels: female male NA + +data(infert) # 自然以及引产导致的不育症 +levels(infert$education) # "0-5yrs" "6-11yrs" "12+ yrs" + + + +# 变量 + +# 有许多种方式用来赋值 +x = 5 # 这样可以 +y <- "1" # 更推荐这样 +TRUE -> z # 这样可行,但是很怪 + +#我们还可以使用强制转型 +as.numeric(y) # 1 +as.character(x) # "5" + +# 循环 + +# for 循环语句 +for (i in 1:4) { + print(i) +} + +# while 循环 +a <- 10 +while (a > 4) { + cat(a, "...", sep = "") + a <- a - 1 +} + +# 记住,在 R 语言中 for / while 循环都很慢 +# 建议使用 apply()(我们一会介绍)来错做一串数据(比如一列或者一行数据) + +# IF/ELSE + +# 再来看这些优雅的标准 +if (4 > 3) { + print("Huzzah! It worked!") +} else { + print("Noooo! This is blatantly illogical!") +} + +# => +# [1] "Huzzah! It worked!" + +# 函数 + +# 定义如下 +jiggle <- function(x) { + x + rnorm(x, sd=.1) #add in a bit of (controlled) noise + return(x) +} + +# 和其他 R 语言函数一样调用 +jiggle(5) # 5±ε. 使用 set.seed(2716057) 后, jiggle(5)==5.005043 + +######################### +# 数据容器:vectors, matrices, data frames, and arrays +######################### + +# 单维度 +# 你可以将目前我们学习到的任何类型矢量化,只要它们拥有相同的类型 +vec <- c(8, 9, 10, 11) +vec # 8 9 10 11 +# 矢量的类型是这一组数据元素的类型 +class(vec) # "numeric" +# If you vectorize items of different classes, weird coercions happen +#如果你强制的将不同类型数值矢量化,会出现特殊值 +c(TRUE, 4) # 1 4 +c("dog", TRUE, 4) # "dog" "TRUE" "4" + +#我们这样来取内部数据,(R 的下标索引顺序 1 开始) +vec[1] # 8 +# 我们可以根据条件查找特定数据 +which(vec %% 2 == 0) # 1 3 +# 抓取矢量中第一个和最后一个字符 +head(vec, 1) # 8 +tail(vec, 1) # 11 +#如果下标溢出或不存会得到 NA +vec[6] # NA +# 你可以使用 length() 获取矢量的长度 +length(vec) # 4 + +# 你可以直接操作矢量或者矢量的子集 +vec * 4 # 16 20 24 28 +vec[2:3] * 5 # 25 30 +# 这里有许多内置的函数,来表现向量 +mean(vec) # 9.5 +var(vec) # 1.666667 +sd(vec) # 1.290994 +max(vec) # 11 +min(vec) # 8 +sum(vec) # 38 + +# 二维(相同元素类型) + +#你可以为同样类型的变量建立矩阵 +mat <- matrix(nrow = 3, ncol = 2, c(1,2,3,4,5,6)) +mat +# => +# [,1] [,2] +# [1,] 1 4 +# [2,] 2 5 +# [3,] 3 6 +# 和 vector 不一样的是,一个矩阵的类型真的是 「matrix」,而不是内部元素的类型 +class(mat) # => "matrix" +# 访问第一行的字符 +mat[1,] # 1 4 +# 操作第一行数据 +3 * mat[,1] # 3 6 9 +# 访问一个特定数据 +mat[3,2] # 6 +# 转置整个矩阵(译者注:变成 2 行 3 列) +t(mat) +# => +# [,1] [,2] [,3] +# [1,] 1 2 3 +# [2,] 4 5 6 + +# 使用 cbind() 函数把两个矩阵按列合并,形成新的矩阵 +mat2 <- cbind(1:4, c("dog", "cat", "bird", "dog")) +mat2 +# => +# [,1] [,2] +# [1,] "1" "dog" +# [2,] "2" "cat" +# [3,] "3" "bird" +# [4,] "4" "dog" +class(mat2) # matrix +# Again, note what happened! +# 注意 +# 因为矩阵内部元素必须包含同样的类型 +# 所以现在每一个元素都转化成字符串 +c(class(mat2[,1]), class(mat2[,2])) + +# 按行合并两个向量,建立新的矩阵 +mat3 <- rbind(c(1,2,4,5), c(6,7,0,4)) +mat3 +# => +# [,1] [,2] [,3] [,4] +# [1,] 1 2 4 5 +# [2,] 6 7 0 4 +# 哈哈,数据类型都一样的,没有发生强制转换,生活真美好 + +# 二维(不同的元素类型) + +# 利用 data frame 可以将不同类型数据放在一起 +dat <- data.frame(c(5,2,1,4), c("dog", "cat", "bird", "dog")) +names(dat) <- c("number", "species") # 给数据列命名 +class(dat) # "data.frame" +dat +# => +# number species +# 1 5 dog +# 2 2 cat +# 3 1 bird +# 4 4 dog +class(dat$number) # "numeric" +class(dat[,2]) # "factor" +# data.frame() 会将字符向量转换为 factor 向量 + +# 有很多精妙的方法来获取 data frame 的子数据集 +dat$number # 5 2 1 4 +dat[,1] # 5 2 1 4 +dat[,"number"] # 5 2 1 4 + +# 多维(相同元素类型) + +# 使用 arry 创造一个 n 维的表格 +# You can make a two-dimensional table (sort of like a matrix) +# 你可以建立一个 2 维表格(有点像矩阵) +array(c(c(1,2,4,5),c(8,9,3,6)), dim=c(2,4)) +# => +# [,1] [,2] [,3] [,4] +# [1,] 1 4 8 3 +# [2,] 2 5 9 6 +#你也可以利用数组建立一个三维的矩阵 +array(c(c(c(2,300,4),c(8,9,0)),c(c(5,60,0),c(66,7,847))), dim=c(3,2,2)) +# => +# , , 1 +# +# [,1] [,2] +# [1,] 2 8 +# [2,] 300 9 +# [3,] 4 0 +# +# , , 2 +# +# [,1] [,2] +# [1,] 5 66 +# [2,] 60 7 +# [3,] 0 847 + +#列表(多维的,不同类型的) + +# R语言有列表的形式 +list1 <- list(time = 1:40) +list1$price = c(rnorm(40,.5*list1$time,4)) # 随机 +list1 + +# You can get items in the list like so +# 你可以这样获得列表的元素 +list1$time +# You can subset list items like vectors +# 你也可以和矢量一样获取他们的子集 +list1$price[4] + +######################### +# apply()函数家族 +######################### + +# 还记得 mat 么? +mat +# => +# [,1] [,2] +# [1,] 1 4 +# [2,] 2 5 +# [3,] 3 6 +# Use apply(X, MARGIN, FUN) to apply function FUN to a matrix X +# 使用(X, MARGIN, FUN)将函数 FUN 应用到矩阵 X 的行 (MAR = 1) 或者 列 (MAR = 2) +# That is, R does FUN to each row (or column) of X, much faster than a +# R 在 X 的每一行/列使用 FUN,比循环要快很多 +apply(mat, MAR = 2, myFunc) +# => +# [,1] [,2] +# [1,] 3 15 +# [2,] 7 19 +# [3,] 11 23 +# 还有其他家族函数 ?lapply, ?sapply + +# 不要被吓到,虽然许多人在此都被搞混 +# plyr 程序包的作用是用来改进 apply() 函数家族 + +install.packages("plyr") +require(plyr) +?plyr + +######################### +# 载入数据 +######################### + +# "pets.csv" 是网上的一个文本 +pets <- read.csv("http://learnxinyminutes.com/docs/pets.csv") +pets +head(pets, 2) # 前两行 +tail(pets, 1) # 最后一行 + +# 以 .csv 格式来保存数据集或者矩阵 +write.csv(pets, "pets2.csv") # 保存到新的文件 pets2.csv +# set working directory with setwd(), look it up with getwd() +# 使用 setwd() 改变工作目录,使用 getwd() 查看当前工作目录 + +# 尝试使用 ?read.csv 和 ?write.csv 来查看更多信息 + +######################### +# 画图 +######################### + +# 散点图 +plot(list1$time, list1$price, main = "fake data") # 译者注:横轴 list1$time,纵轴 wlist1$price,标题 fake data +# 回归图 +linearModel <- lm(price ~ time, data = list1) # 译者注:线性模型,数据集为list1,以价格对时间做相关分析模型 +linearModel # 拟合结果 +# 将拟合结果展示在图上,颜色设为红色 +abline(linearModel, col = "red") +# 也可以获取各种各样漂亮的分析图 +plot(linearModel) + +# 直方图 +hist(rpois(n = 10000, lambda = 5), col = "thistle") # 译者注:统计频数直方图 + +# 柱状图 +barplot(c(1,4,5,1,2), names.arg = c("red","blue","purple","green","yellow")) + +# 可以尝试着使用 ggplot2 程序包来美化图片 +install.packages("ggplot2") +require(ggplot2) +?ggplot2 + +``` + +## 获得 R + +* 从 [http://www.r-project.org/](http://www.r-project.org/) 获得安装包和图形化界面 +* [RStudio](http://www.rstudio.com/ide/) 是另一个图形化界面 -- cgit v1.2.3 From 7ff3de74fe941a220e6fb3e3e3434d90d0d51cc6 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 27 Oct 2013 22:17:56 -0700 Subject: Updates --- zh-cn/r-cn.html.markdown | 1 + 1 file changed, 1 insertion(+) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index 8a542695..ed8c43b6 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -7,6 +7,7 @@ translators: - ["小柒", "http://weibo.com/u/2328126220"] - ["alswl", "https://github.com/alswl"] filename: learnr.r +lang: zh-cn --- R 是一门统计语言。它有很多数据分析和挖掘程序包。可以用来统计、分析和制图。 -- cgit v1.2.3 From 85b5920550b870e2c2e3f12be27a731326da7b2a Mon Sep 17 00:00:00 2001 From: xuchunyang Date: Wed, 20 Nov 2013 23:42:29 +0800 Subject: [bash/zh-cn] chinese bash translation --- zh-cn/bash-cn.html.markdown | 148 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 zh-cn/bash-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown new file mode 100644 index 00000000..beb20479 --- /dev/null +++ b/zh-cn/bash-cn.html.markdown @@ -0,0 +1,148 @@ +--- +category: tool +tool: bash +contributors: + - ["Max Yankov", "https://github.com/golergka"] + - ["Darren Lin", "https://github.com/CogBear"] + - ["Alexandre Medeiros", "http://alemedeiros.sdf.org"] +translators: + - ["Chunyang Xu", "https://github.com/XuChunyang"] +filename: LearnBash-cn.sh +lang: zh-cn +--- + +Bash 是一个为GNU计划编写的Unix shell,是 Linux 和 Mac OS X 下的默认shell。 +以下绝大多数例子可以作为脚本的一部分也可直接在 shell 下执行。 + +[更多信息](http://www.gnu.org/software/bash/manual/bashref.html) + +```bash +#!/bin/sh +# 脚本的第一行叫 shebang,用来告知系统如何执行该脚本: +# 参见: http://en.wikipedia.org/wiki/Shebang_(Unix) +# 相信你已经明白了,注释以 # 开头,shebang 也是注释。 + +# 显示 “Hello world!” +echo Hello, world! + +# 每一句指令以换行或分号隔开: +echo 'This is the first line'; echo 'This is the second line' + +# 声明一个变量: +VARIABLE="Some string" + +# 下面是错误的做法: +VARIABLE = "Some string" +# Bash 会把 VARIABLE 当做一个指令,由于找不到该指令,因此这里会报错。 + + +# 使用变量: +echo $VARIABLE +echo "$VARIABLE" +echo '$VARIABLE' +# 当你分配 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。 +# 如果要使用变量的值, 则要加 $。 +# 注意: ' (单引号) 不会展开变量(即会屏蔽掉变量)。 + + +# 在变量内部进行字符串代换 +echo ${VARIABLE/Some/A} +# 会把 VARIABLE 中首次出现的 "some" 替换成 “A”。 + +# 内置变量: +# 下面的内置变量很有用 +echo "Last program return value: $?" +echo "Script's PID: $$" +echo "Number of arguments: $#" +echo "Scripts arguments: $@" +echo "Scripts arguments separeted in different variables: $1 $2..." + +# 获取输入: +echo "What's your name?" +read NAME # Note that we didn't need to declare new variable +echo Hello, $NAME! + +# 一般的 if 结构看起来像这样: +# 'man test' 查看更多的信息 +if [ $NAME -ne $USER ] +then + echo "Your name is you username" +else + echo "Your name isn't you username" +fi + +# 根据上一个指令执行结果决定是否执行下一个指令 +echo "Always executed" || echo "Only executed if first command fail" +echo "Always executed" && echo "Only executed if first command does NOT fail" + +# 表达式的格式如下: +echo $(( 10 + 5 )) + +# 与其他编程语言不同的是,bash 运行时依赖上下文。比如,使用 ls 时,列出当前目录。 +ls + +# 指令可以带有选项: +ls -l # Lists every file and directory on a separate line + +# 前一个指令的输出可以当作后一个指令的输入。grep 可以查找字符串。 +# 下面的指令可以,列出当前目录下所有的 txt 文件: +ls -l | grep "\.txt" + +# 重定向可以到输出,输入和错误输出。 +python2 hello.py < "input.in" +python2 hello.py > "output.out" +python2 hello.py 2> "error.err" +# > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。 + +# 指令被 $( ) 嵌套在另一个指令内部: +# 以下的指令会打印当前目录下的目录和文件总数 +echo "There are $(ls | wc -l) items here." + +# Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似: +case "$VARIABLE" in + #List patterns for the conditions you want to meet + 0) echo "There is a zero.";; + 1) echo "There is a one.";; + *) echo "It is not null.";; +esac + +# 循环遍历给定的参数序列: +# 变量$VARIABLE 的值会被打印 3 次。 +# 注意 ` ` 和 $( ) 等价。seq 返回长度为 3 的数组。 +for VARIABLE in `seq 3` +do + echo "$VARIABLE" +done + +# 你也可以使用函数 +# 定义函数: +function foo () +{ + echo "Arguments work just like script arguments: $@" + echo "And: $1 $2..." + echo "This is a function" + return 0 +} + +# 更简单的方法 +bar () +{ + echo "Another way to declare functions!" + return 0 +} + +# 调用函数 +foo "My name is" $NAME + +# 有很多有用的指令需要学习: +tail -n 10 file.txt +# 打印 file.txt 的最后 10 行 +head -n 10 file.txt +# 打印 file.txt 的前 10 行 +sort file.txt +# 将 file.txt 按行排序 +uniq -d file.txt +# 报告或忽略重复的行,用选项 -d 打印重复的行 +cut -d ',' -f 1 file.txt +# 仅打印字符 ',' 之前内容(以行为单位) +``` -- cgit v1.2.3 From 22da248750815552de41367700a99eac6342e23f Mon Sep 17 00:00:00 2001 From: xuchunyang Date: Thu, 21 Nov 2013 21:52:41 +0800 Subject: [bash/zh-cn] Better translation --- zh-cn/bash-cn.html.markdown | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index beb20479..e3eed3a6 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -11,8 +11,8 @@ filename: LearnBash-cn.sh lang: zh-cn --- -Bash 是一个为GNU计划编写的Unix shell,是 Linux 和 Mac OS X 下的默认shell。 -以下绝大多数例子可以作为脚本的一部分也可直接在 shell 下执行。 +Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 Mac OS X 下的默认 shell。 +以下大多数例子可以作为脚本的一部分运行也可直接在 shell 下交互执行。 [更多信息](http://www.gnu.org/software/bash/manual/bashref.html) @@ -20,7 +20,7 @@ Bash 是一个为GNU计划编写的Unix shell,是 Linux 和 Mac OS X 下的默 #!/bin/sh # 脚本的第一行叫 shebang,用来告知系统如何执行该脚本: # 参见: http://en.wikipedia.org/wiki/Shebang_(Unix) -# 相信你已经明白了,注释以 # 开头,shebang 也是注释。 +# 如你所见,注释以 # 开头,shebang 也是注释。 # 显示 “Hello world!” echo Hello, world! @@ -57,13 +57,13 @@ echo "Number of arguments: $#" echo "Scripts arguments: $@" echo "Scripts arguments separeted in different variables: $1 $2..." -# 获取输入: +# 读取输入: echo "What's your name?" -read NAME # Note that we didn't need to declare new variable +read NAME # 这里不需要声明新变量 echo Hello, $NAME! -# 一般的 if 结构看起来像这样: -# 'man test' 查看更多的信息 +# 通常的 if 结构看起来像这样: +# 'man test' 可查看更多的信息 if [ $NAME -ne $USER ] then echo "Your name is you username" @@ -82,10 +82,10 @@ echo $(( 10 + 5 )) ls # 指令可以带有选项: -ls -l # Lists every file and directory on a separate line +ls -l # 列出文件和目录的详细信息 -# 前一个指令的输出可以当作后一个指令的输入。grep 可以查找字符串。 -# 下面的指令可以,列出当前目录下所有的 txt 文件: +# 前一个指令的输出可以当作后一个指令的输入。grep 用来匹配字符串。 +# 用下面的指令列出当前目录下所有的 txt 文件: ls -l | grep "\.txt" # 重定向可以到输出,输入和错误输出。 @@ -94,13 +94,13 @@ python2 hello.py > "output.out" python2 hello.py 2> "error.err" # > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。 -# 指令被 $( ) 嵌套在另一个指令内部: +# 一个指令可用 $( ) 嵌套在另一个指令内部: # 以下的指令会打印当前目录下的目录和文件总数 echo "There are $(ls | wc -l) items here." # Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似: case "$VARIABLE" in - #List patterns for the conditions you want to meet + # 列出需要匹配的字符串 0) echo "There is a zero.";; 1) echo "There is a one.";; *) echo "It is not null.";; @@ -144,5 +144,5 @@ sort file.txt uniq -d file.txt # 报告或忽略重复的行,用选项 -d 打印重复的行 cut -d ',' -f 1 file.txt -# 仅打印字符 ',' 之前内容(以行为单位) +# 打印每行中 ',' 之前内容 ``` -- cgit v1.2.3 From c8c937ef308e205b632bd709ce7fdb9761fc4b74 Mon Sep 17 00:00:00 2001 From: lyuehh Date: Sun, 24 Nov 2013 22:47:31 +0800 Subject: add Chinese translate of brainfuck --- zh-cn/brainfuck-cn.html.markdown | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 zh-cn/brainfuck-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/brainfuck-cn.html.markdown b/zh-cn/brainfuck-cn.html.markdown new file mode 100644 index 00000000..a6f3fa09 --- /dev/null +++ b/zh-cn/brainfuck-cn.html.markdown @@ -0,0 +1,70 @@ +--- +language: brainfuck +lang: zh-cn +contributors: + - ["Prajit Ramachandran", "http://prajitr.github.io/"] + - ["Mathias Bynens", "http://mathiasbynens.be/"] +translators: + - ["lyuehh", "https://github.com/lyuehh"] +--- + +Brainfuck 是一个极小的只有8个指令的图灵完全的编程语言。 + +``` +除"><+-.,[]"之外的的任何字符都会被忽略 (不包含双引号)。 + +Brainfuck 包含一个有30,000个单元为0的数组,和 +一个数据指针指向当前的单元。 + +8个指令如下: ++ : 指针指向的单元的值加1 +- : 指针指向的单元的值减1 +> : 将指针移动到下一个单元(右边的元素) +< : 将指针移动到上一个单元(左边的元素) +. : 打印当前单元的内容的ASCII值 (比如 65 = 'A'). +, : 读取一个字符到当前的单元 +[ : 如果当前单元的值是0,则向后调转到对应的]处 +] : 如果当前单元的值不是0,则向前跳转到对应的[处 + +[ 和 ] 组成了一个while循环。很明显,它们必须配对。 + +让我们看一些基本的brainfuck 程序。 + +++++++ [ > ++++++++++ < - ] > +++++ . + +这个程序打印字母'A'。首先,它把 #1 增加到6,使用它来作为循环条件, +然后,进入循环,将指针移动到 #2 ,将 #2 的值增加到10,然后 +移动回 #1,将单元 #1 的值减1,然后继续。循环共进行了6次。 + +这时,我们在 #1,它的值为0,#2 的值为60,我们移动到 +#2,将 #2 的内容加上5,然后将 #2 的内容打印出来,65在 +ASCII中表示'A', 所以'A'就会被打印出来。 + + +, [ > + < - ] > . + +这个程序从用户的输入中读取一个字符,然后把它复制到 #1。 +然后我们开始一个循环,移动到 #2,将 #2 的值加1,再移动回 #1,将 #1 +的值减1,直到 #1的值为0,这样 #2 里就保存了 #1 的旧值,循环结束时我们 +在 #1,这时我们移动到 #2,然后把字符以ASCII打印出来。 + +而且要记住的一点就是,空格在这里只是为了可读性,你可以将他们写成这样: + +,[>+<-]>. + +试着思考一下这段程序是干什么的: + +,>,< [ > [ >+ >+ << -] >> [- << + >>] <<< -] >> + +这段程序从输入接收2个参数,然后将他们相乘。 + +先读取2个输入,然后开始外层循环,以 #1 作为终止条件,然后将指针移动到 +#2,然后开始 #2 的内层循环,将 #3 加1。但是这里有一个小问题,在内层 +循环结束的时候,#2 的值是0了,那么下次执行外层循环的时候,就有问题了。 +为了解决这个问题,我们可以增加 #4 的值,然后把 #4 的值复制到 #2, +最后结果就保存在 #3 中了。 +``` +好了这就是brainfuck了。也没那么难,是吧?为了好玩,你可以写你自己的 +brainfuck程序,或者用其他语言写一个brainfuck的解释器,解释器非常容易 +实现,但是如果你是一个自虐狂的话,你可以尝试用brainfuck写一个brainfuk的 +解释器。 -- cgit v1.2.3 From 5a5b0c32edbee01ccc5a1c71e2cdda2d55fb3c41 Mon Sep 17 00:00:00 2001 From: Mac David Date: Mon, 9 Dec 2013 23:50:19 +0800 Subject: The 1st Edition --- zh-cn/common-lisp.html.markdown | 611 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 zh-cn/common-lisp.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown new file mode 100644 index 00000000..34739497 --- /dev/null +++ b/zh-cn/common-lisp.html.markdown @@ -0,0 +1,611 @@ +--- + +语言: "Common Lisp" +文件名: commonlisp.lisp +贡献者: + - ["Paul Nathan", "https://github.com/pnathan"] +译者: + - ["Mac David", "http://github.com/macdavid313"] +--- + +ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 +这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 + +经典的入门点为[已经完全免费提供的实用Common Lisp编程](http://www.gigamonkeys.com/book/) + +另外还有一本近期内比较热门的 +[Land of Lisp](http://landoflisp.com/). + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; 0. 语法 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 一般形式 + +;; Lisp有两个基本的语法部件:原子,以及S-表达式。 +;; 一般的,一组S-表达式被称为“组合式”。 + +10 ; 一个原子; 它对自身进行求值 + +:THING ;同样是一个原子;它被求值为一个符号 :thing + +t ;还是一个原子,代表逻辑真值。 + +(+ 1 2 3 4) ; 一个S表达式。 + +'(4 :foo t) ;同样是一个S表达式。 + + +;;; 注释 + +;; 一个分号开头的注释表示仅用于此行(单行);两个分号开头的则表示一个所谓标准注释; +;; 三个分号开头的意味着段落注释,而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 + +#| 块注释 + 可以涵盖多行,而且... + #| + 他们可以被嵌套! + |# +|# + +;;; 运行环境 + +;; 有很多不同的Common Lisp的实现;并且大部分的实现是符合标准的。 +;; 对于入门学习来说,CLISP是个不错的选择。 + +;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 + +;; 通常,使用一个文本编辑器和一个同时在运行的“REPL”来开发Common Lisp; +;; (译者注:“REPL”指读取-求值-打印循环)。 +;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; 1. 基本数据类型以及运算符 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 符号 + +'foo ; => FOO 注意到这个符号被自动转换成大写了。 + +;; `intern`由一个给定的字符串而创建相应的符号 + +(intern "AAAA") ; => AAAA + +(intern "aaa") ; => |aaa| + +;;; 数字 +9999999999999999999999 ; 整型数 +#b111 ; 二进制 => 7 +#o111 ; 八进制 => 73 +#x111 ; 十六进制 => 273 +3.14159s0 ; 单精度 +3.14159d0 ; 双精度 +1/2 ; 分数 +#C(1 2) ; 复数 + + +;; 使用函数时,应当写成这样的形式:(f x y z ...); +;; 其中,f是一个函数(名),x, y, z为参数; +;; 如果你想创建一个“字面”意义上(即不求值)的列表, 只需使用单引号 ' , +;; 从而避免接下来的表达式被求值。即,只“引用”这个数据(而不求值)。 +'(+ 1 2) ; => (+ 1 2) +;; 你同样也可以手动地调用一个函数(译者注:即使用函数对象来调用函数): +(funcall #'+ 1 2 3) ; => 6 +;; 一些算术运算符 +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(mod 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) + + ;;; 布尔运算 +t ; 逻辑真(任何不是nil的值都被视为真值) +nil ; 逻辑假,或者空列表 +(not nil) ; => t +(and 0 t) ; => t +(or 0 nil) ; => 0 + + ;;; 字符 +#\A ; => #\A +#\λ ; => #\GREEK_SMALL_LETTER_LAMDA(希腊字母Lambda的小写) +#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA(Unicode形式的小写希腊字母Lambda) + +;;; 字符串被视为一个定长字符数组 +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ;反斜杠用作转义字符 + +;; 字符串可以被连接起来 +(concatenate 'string "Hello " "world!") ; => "Hello world!" + +;; 一个字符串也可被视作一个字符的序列 +(elt "Apple" 0) ; => #\A + +;; `format`被用于格式化字符串 +(format nil "~a can be ~a" "strings" "formatted") + +;; 利用`format`打印到屏幕上是非常简单的(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 +(format t "Common Lisp is groovy. Dude.~%") + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. 变量 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 你可以通过`defparameter`创建一个全局(动态)变量 +;; 除了:()[]{}",'`;#|\ 这些字符,其他任何字符都可被用于变量名 + +;; 动态变量名应该由*号开头与结尾! + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;; 你也可以使用Unicode字符: +(defparameter *AΛB* nil) + + +;; 访问一个在之前从未未绑定的变量是一种不规范的行为(即使依然是可能发生的); +;; 不要尝试那样做。 + + +;; 局部绑定:'me'被绑定到"dance with you"上,当且仅当它在(let ...)内有效。 +;; `let`总是返回在其作用域内最后一个表达式的值 + +(let ((me "dance with you")) + me) +;; => "dance with you" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 结构体和集合 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 结构体 +(defstruct dog name breed age) +(defparameter *rover* + (make-dog :name "rover" + :breed "collie" + :age 5)) +*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) + +(dog-p *rover*) ; => t ;; ewww) +(dog-name *rover*) ; => "rover" + +;; Dog-p,make-dog,以及 dog-name都是由defstruct创建的! + +;;; 点对单元 +;; `cons`可用于生成一个点对单元, 利用`car`以及`cdr`将分别得到第一个和第二个元素 +(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB)) ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB)) ; => VERB + +;;; 列表 + +;; 所有列表都是由点对单元构成、并以'nil'(或者'())结尾的一种被称为“链表”的数据结构 +(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) +;; `list`是一个生成列表的便利途径 +(list 1 2 3) ; => '(1 2 3) +;; 并且,一个引用也可被用做字面意义上的列表值 +'(1 2 3) ; => '(1 2 3) + +;; 同样的,依然可以用`cons`来添加一项到列表的起始位置 +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;; 而`append`也可用于连接两个列表 +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;; 或者使用`concatenate` + +(concatenate 'list '(1 2) '(3 4)) + +;; 列表是一种非常核心的数据类型,所以有非常多的处理列表的函数 +;; 例如: +(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4)) ; => nil +(some #'oddp '(1 2 3 4)) ; => T +(butlast '(subject verb object)) ; => (SUBJECT VERB) + + +;;; 向量 + +;; 向量的字面意义是一个定长数组(译者注:此处所谓字面意义的,即为#(......)的形式,下文还会出现) +#(1 2 3) ; => #(1 2 3) + +;; 使用`concatenate`来将两个向量首尾连接在一起 +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + +;;; 数组 + +;; 向量和字符串只不过是数组的特例 + +;; 二维数组 + +(make-array (list 2 2)) + +;; (make-array '(2 2)) 也是可以的 + +; => #2A((0 0) (0 0)) + +(make-array (list 2 2 2)) + +; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;; 注意:数组的默认初始值是可以指定的 +;; 下面是如何指定的示例: + +(make-array '(2) :initial-element 'unset) + +; => #(UNSET UNSET) + +;; 若想获取数组[1][1][1]上的元素: +(aref (make-array (list 2 2 2)) 1 1 1) + +; => 0 + +;;; 变长向量 + +;; 若将变长向量打印出来,那么它的字面意义上的值和定长向量的是一样的 + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) + :adjustable t :fill-pointer t)) + +*adjvec* ; => #(1 2 3) + +;; 添加新的元素: +(vector-push-extend 4 *adjvec*) ; => 3 + +*adjvec* ; => #(1 2 3 4) + + + +;;; 不怎么严谨地说,集合也可被视为列表 + +(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 +(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) + +;; 然而,你可能想使用一个更好的数据结构,而并非一个链表 + +;;; 在Common Lisp中,你也可以使用“字典”的概念——哈希表 + +;; 创建一个哈希表 +(defparameter *m* (make-hash-table)) + +;; 给定键,设置对应的值 +(setf (gethash 'a *m*) 1) + +;; (通过键)检索对应的值 +(gethash 'a *m*) ; => 1, t + +;; 注意此处有一细节:Common Lisp的`gethash`往往会返回两个值。 +;; (译者注:返回的第一个值表示给定的键所对应的值或者nil,第二个则表示在哈希表中是否存在这个给定的键) +;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil + +;; 由给定的键检索一个不存在的值,则返回nil(译者注:即第一个nil,第二个nil其实是指该键在哈希表中也不存在) + (gethash 'd *m*) ;=> nil, nil + +;; 给定一个键,你可以指定其对应的默认值: +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;; 在此,让我们看一看怎样处理`gethash`的多个返回值。 + +(multiple-value-bind + (a b) + (gethash 'd *m*) + (list a b)) +; => (NIL NIL) + +(multiple-value-bind + (a b) + (gethash 'a *m*) + (list a b)) +; => (1 T) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 函数 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用`lambda`来创建一个匿名函数。 +;; 一个函数总是返回其最后一个表达式的值。 +;; 将一个函数对象打印出来后的形式是多种多样的... + +(lambda () "Hello World") ; => # + +;; 使用`funcall`来调用lambda函数 +(funcall (lambda () "Hello World")) ; => "Hello World" + +;; 或者使用`apply` +(apply (lambda () "Hello World") nil) ; => "Hello World" + +;; 显示地定义一个函数(译者注:即非匿名的) +(defun hello-world () + "Hello World") +(hello-world) ; => "Hello World" + +;; 刚刚上面函数名"hello-world"后的()其实是函数的参数列表 +(defun hello (name) + (format nil "Hello, ~a " name)) + +(hello "Steve") ; => "Hello, Steve" + +;; 函数可以有可选形参并且其默认值都为nil + +(defun hello (name &optional from) + (if from + (format t "Hello, ~a, from ~a" name from) + (format t "Hello, ~a" name))) + + (hello "Jim" "Alpacas") ;; => Hello, Jim, from Alpacas + +;; 你也可以指定那些可选形参的默认值 +(defun hello (name &optional (from "The world")) + (format t "Hello, ~a, from ~a" name from)) + +(hello "Steve") +; => Hello, Steve, from The world + +(hello "Steve" "the alpacas") +; => Hello, Steve, from the alpacas + + +;; 当然,你也可以设置关键字形参; +;; 关键字形参往往比可选形参更具灵活性。 + +(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) + (format t "Hello, ~a ~a, from ~a" honorific name from)) + +(generalized-greeter "Jim") ; => Hello, Mx Jim, from the world + +(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") +; => Hello, Mr Jim, from the alpacas you met last summer + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. 等价性的含义 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 + +;; 若要比较数值是否等价,使用`=` +(= 3 3.0) ; => t +(= 2 1) ; => nil + +;; 若要比较对象的类型,则使用`eql` +;;(译者注:抱歉,请忽略这句翻译;`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) +;; (想要弄清`eql`,其实有必要先了解`eq`) +;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》里的4.8节也提到了两者的区别) +(eql 3 3) ; => t +(eql 3 3.0) ; => nil +(eql (list 3) (list 3)) ; => nil + +;; 对于列表、字符串、以及位向量,使用`equal` +(equal (list 'a 'b) (list 'a 'b)) ; => t +(equal (list 'a 'b) (list 'b 'a)) ; => nil + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. 控制流 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 条件判断语句 + +(if t ; “测试”,即判断语句 + "this is true" ; “下一步”,即判断条件为真时求值的表达式 + "this is false") ; “否则”,即判断条件为假时求值的表达式 +; => "this is true" + +;; 在“测试”(判断)语句中,所有非nil或者非()的值都被视为真值 +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'YEP + +;; `cond`将一系列测试语句串联起来,并对相应的表达式求值 +(cond ((> 2 2) (error "wrong!")) + ((< 2 2) (error "wrong again!")) + (t 'ok)) ; => 'OK + +;; 对于给定值的数据类型,`typecase`会做出相应地判断 +(typecase 1 + (string :string) + (integer :int)) + +; => :int + +;;; 迭代 + +;; 当然,递归是肯定被支持的: + +(defun walker (n) + (if (zerop n) + :walked + (walker (1- n)))) + +(walker) ; => :walked + +;; 而大部分场合下,我们使用`DOLIST`或者`LOOP`来进行迭代 + + +(dolist (i '(1 2 3 4)) + (format t "~a" i)) + +; => 1234 + +(loop for i from 0 below 10 + collect i) + +; => (0 1 2 3 4 5 6 7 8 9) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. 变异 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用`setf`可以对一个已经存在的变量进行赋值; +;; 事实上,刚刚在哈希表的例子中我们已经示范过了。 + +(let ((variable 10)) + (setf variable 2)) + ; => 2 + + +;; 所谓好的Lisp编码风格就是为了减少破坏性函数的使用,防止副作用的发生。 +;;(译者注:很惭愧,确实不明白原作者所说的"Mutation",即这里的“变异”到底指的是什么特性) +;;(毕竟他只给了一个例子,我猜测应该是和词法变量、闭包等特性有关,还望高人指点) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. 类与对象 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 我们就不写什么有关动物的类了,下面给出的是一个很“人文主义”的类 + +(defclass human-powered-conveyance () + ((velocity + :accessor velocity + :initarg :velocity) + (average-efficiency + :accessor average-efficiency + :initarg :average-efficiency)) + (:documentation "A human powered conveyance")) + +;; `defclass`,后面接类名,以及超类列表 +;; 再接着是槽的列表(槽有点像Java里的字段),最后是一些可选的特性,例如文档说明“:documentation” + +;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类); +;; 这种默认行为是可以改变的,但你最好有一定的基础并且知道自己到底在干什么; +;; 参阅《The Art of the Metaobject Protocol》来了解更多信息。 + +(defclass bicycle (human-powered-conveyance) + ((wheel-size + :accessor wheel-size + :initarg :wheel-size + :documentation "Diameter of the wheel.") + (height + :accessor height + :initarg :height))) + +(defclass recumbent (bicycle) + ((chain-type + :accessor chain-type + :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) + ((number-of-rowers + :accessor number-of-rowers + :initarg :number-of-rowers))) + + +;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`如下: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +; [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #: +; Documentation: +; A human powered conveyance +; Direct superclasses: STANDARD-OBJECT +; Direct subclasses: UNICYCLE, BICYCLE, CANOE +; Not yet finalized. +; Direct slots: +; VELOCITY +; Readers: VELOCITY +; Writers: (SETF VELOCITY) +; AVERAGE-EFFICIENCY +; Readers: AVERAGE-EFFICIENCY +; Writers: (SETF AVERAGE-EFFICIENCY) + +;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。 + +;; 若要定义一个方法; +;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi + +(defmethod circumference ((object bicycle)) + (* pi (wheel-size object))) + +;; pi在Common Lisp中已经是一个内置的常量。 + +;; 假设我们已经知道效率值(“efficiency value”)和船桨数大概呈对数关系; +;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 + +;; 下面是一个如何初始化实例的例子: +;; 构造它: + +(defmethod initialize-instance :after ((object canoe) &rest args) + (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) + +;; 接着初构造一个实例并检查平均效率... + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 8. 宏 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 宏可以让你扩展语法 + +;; Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; +;; 如果按照“拼装者”的直觉来看,我们会这样写: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. + +`condition` is tested prior to each execution of `body`" + (let ((block-name (gensym))) + `(tagbody + (unless ,condition + (go ,block-name)) + (progn + ,@body) + ,block-name))) + +;; 让我们来看看它的高级版本: + + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. + +`condition` is tested prior to each execution of `body`" + `(loop while ,condition + do + (progn + ,@body))) + +;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的; +;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 + +;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; +;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 +;; 逗号“,”意味着解除引用(unquote,即开始求值);“@”符号则表示将当前的参数插入到当前整个列表中。 +;;(译者注:这三个符号只不过是语法糖罢了,而要想真正用好、用对,需要下一番功夫) +;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的,建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) + +;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 +;; 这样做是因为,宏是在编译期展开的,而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 + +;; 可以去《实用 Common Lisp 编程》中阅读更多有关宏的内容。 +``` + + +## 拓展阅读 + +[继续阅读《实用 Common Lisp 编程》一书](http://www.gigamonkeys.com/book/) + + +## 致谢 + +非常感谢Scheme社区的人们,我基于他们的成果得以迅速的写出这篇有关Common Lisp的快速入门 +同时也感谢 +- [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 -- cgit v1.2.3 From c09b59955c7408ae38f1b521db2c873afffb43e1 Mon Sep 17 00:00:00 2001 From: Mac David Date: Tue, 10 Dec 2013 00:01:35 +0800 Subject: Error --- zh-cn/common-lisp.html.markdown | 611 ---------------------------------------- 1 file changed, 611 deletions(-) delete mode 100644 zh-cn/common-lisp.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown deleted file mode 100644 index 34739497..00000000 --- a/zh-cn/common-lisp.html.markdown +++ /dev/null @@ -1,611 +0,0 @@ ---- - -语言: "Common Lisp" -文件名: commonlisp.lisp -贡献者: - - ["Paul Nathan", "https://github.com/pnathan"] -译者: - - ["Mac David", "http://github.com/macdavid313"] ---- - -ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 -这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 - -经典的入门点为[已经完全免费提供的实用Common Lisp编程](http://www.gigamonkeys.com/book/) - -另外还有一本近期内比较热门的 -[Land of Lisp](http://landoflisp.com/). - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; 0. 语法 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; 一般形式 - -;; Lisp有两个基本的语法部件:原子,以及S-表达式。 -;; 一般的,一组S-表达式被称为“组合式”。 - -10 ; 一个原子; 它对自身进行求值 - -:THING ;同样是一个原子;它被求值为一个符号 :thing - -t ;还是一个原子,代表逻辑真值。 - -(+ 1 2 3 4) ; 一个S表达式。 - -'(4 :foo t) ;同样是一个S表达式。 - - -;;; 注释 - -;; 一个分号开头的注释表示仅用于此行(单行);两个分号开头的则表示一个所谓标准注释; -;; 三个分号开头的意味着段落注释,而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 - -#| 块注释 - 可以涵盖多行,而且... - #| - 他们可以被嵌套! - |# -|# - -;;; 运行环境 - -;; 有很多不同的Common Lisp的实现;并且大部分的实现是符合标准的。 -;; 对于入门学习来说,CLISP是个不错的选择。 - -;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 - -;; 通常,使用一个文本编辑器和一个同时在运行的“REPL”来开发Common Lisp; -;; (译者注:“REPL”指读取-求值-打印循环)。 -;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; 1. 基本数据类型以及运算符 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; 符号 - -'foo ; => FOO 注意到这个符号被自动转换成大写了。 - -;; `intern`由一个给定的字符串而创建相应的符号 - -(intern "AAAA") ; => AAAA - -(intern "aaa") ; => |aaa| - -;;; 数字 -9999999999999999999999 ; 整型数 -#b111 ; 二进制 => 7 -#o111 ; 八进制 => 73 -#x111 ; 十六进制 => 273 -3.14159s0 ; 单精度 -3.14159d0 ; 双精度 -1/2 ; 分数 -#C(1 2) ; 复数 - - -;; 使用函数时,应当写成这样的形式:(f x y z ...); -;; 其中,f是一个函数(名),x, y, z为参数; -;; 如果你想创建一个“字面”意义上(即不求值)的列表, 只需使用单引号 ' , -;; 从而避免接下来的表达式被求值。即,只“引用”这个数据(而不求值)。 -'(+ 1 2) ; => (+ 1 2) -;; 你同样也可以手动地调用一个函数(译者注:即使用函数对象来调用函数): -(funcall #'+ 1 2 3) ; => 6 -;; 一些算术运算符 -(+ 1 1) ; => 2 -(- 8 1) ; => 7 -(* 10 2) ; => 20 -(expt 2 3) ; => 8 -(mod 5 2) ; => 1 -(/ 35 5) ; => 7 -(/ 1 3) ; => 1/3 -(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) - - ;;; 布尔运算 -t ; 逻辑真(任何不是nil的值都被视为真值) -nil ; 逻辑假,或者空列表 -(not nil) ; => t -(and 0 t) ; => t -(or 0 nil) ; => 0 - - ;;; 字符 -#\A ; => #\A -#\λ ; => #\GREEK_SMALL_LETTER_LAMDA(希腊字母Lambda的小写) -#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA(Unicode形式的小写希腊字母Lambda) - -;;; 字符串被视为一个定长字符数组 -"Hello, world!" -"Benjamin \"Bugsy\" Siegel" ;反斜杠用作转义字符 - -;; 字符串可以被连接起来 -(concatenate 'string "Hello " "world!") ; => "Hello world!" - -;; 一个字符串也可被视作一个字符的序列 -(elt "Apple" 0) ; => #\A - -;; `format`被用于格式化字符串 -(format nil "~a can be ~a" "strings" "formatted") - -;; 利用`format`打印到屏幕上是非常简单的(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 -(format t "Common Lisp is groovy. Dude.~%") - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 2. 变量 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 你可以通过`defparameter`创建一个全局(动态)变量 -;; 除了:()[]{}",'`;#|\ 这些字符,其他任何字符都可被用于变量名 - -;; 动态变量名应该由*号开头与结尾! - -(defparameter *some-var* 5) -*some-var* ; => 5 - -;; 你也可以使用Unicode字符: -(defparameter *AΛB* nil) - - -;; 访问一个在之前从未未绑定的变量是一种不规范的行为(即使依然是可能发生的); -;; 不要尝试那样做。 - - -;; 局部绑定:'me'被绑定到"dance with you"上,当且仅当它在(let ...)内有效。 -;; `let`总是返回在其作用域内最后一个表达式的值 - -(let ((me "dance with you")) - me) -;; => "dance with you" - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 3. 结构体和集合 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 结构体 -(defstruct dog name breed age) -(defparameter *rover* - (make-dog :name "rover" - :breed "collie" - :age 5)) -*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) - -(dog-p *rover*) ; => t ;; ewww) -(dog-name *rover*) ; => "rover" - -;; Dog-p,make-dog,以及 dog-name都是由defstruct创建的! - -;;; 点对单元 -;; `cons`可用于生成一个点对单元, 利用`car`以及`cdr`将分别得到第一个和第二个元素 -(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) -(car (cons 'SUBJECT 'VERB)) ; => SUBJECT -(cdr (cons 'SUBJECT 'VERB)) ; => VERB - -;;; 列表 - -;; 所有列表都是由点对单元构成、并以'nil'(或者'())结尾的一种被称为“链表”的数据结构 -(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) -;; `list`是一个生成列表的便利途径 -(list 1 2 3) ; => '(1 2 3) -;; 并且,一个引用也可被用做字面意义上的列表值 -'(1 2 3) ; => '(1 2 3) - -;; 同样的,依然可以用`cons`来添加一项到列表的起始位置 -(cons 4 '(1 2 3)) ; => '(4 1 2 3) - -;; 而`append`也可用于连接两个列表 -(append '(1 2) '(3 4)) ; => '(1 2 3 4) - -;; 或者使用`concatenate` - -(concatenate 'list '(1 2) '(3 4)) - -;; 列表是一种非常核心的数据类型,所以有非常多的处理列表的函数 -;; 例如: -(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) -(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) -(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) -(every #'evenp '(1 2 3 4)) ; => nil -(some #'oddp '(1 2 3 4)) ; => T -(butlast '(subject verb object)) ; => (SUBJECT VERB) - - -;;; 向量 - -;; 向量的字面意义是一个定长数组(译者注:此处所谓字面意义的,即为#(......)的形式,下文还会出现) -#(1 2 3) ; => #(1 2 3) - -;; 使用`concatenate`来将两个向量首尾连接在一起 -(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) - -;;; 数组 - -;; 向量和字符串只不过是数组的特例 - -;; 二维数组 - -(make-array (list 2 2)) - -;; (make-array '(2 2)) 也是可以的 - -; => #2A((0 0) (0 0)) - -(make-array (list 2 2 2)) - -; => #3A(((0 0) (0 0)) ((0 0) (0 0))) - -;; 注意:数组的默认初始值是可以指定的 -;; 下面是如何指定的示例: - -(make-array '(2) :initial-element 'unset) - -; => #(UNSET UNSET) - -;; 若想获取数组[1][1][1]上的元素: -(aref (make-array (list 2 2 2)) 1 1 1) - -; => 0 - -;;; 变长向量 - -;; 若将变长向量打印出来,那么它的字面意义上的值和定长向量的是一样的 - -(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) - :adjustable t :fill-pointer t)) - -*adjvec* ; => #(1 2 3) - -;; 添加新的元素: -(vector-push-extend 4 *adjvec*) ; => 3 - -*adjvec* ; => #(1 2 3 4) - - - -;;; 不怎么严谨地说,集合也可被视为列表 - -(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) -(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 -(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) -(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) - -;; 然而,你可能想使用一个更好的数据结构,而并非一个链表 - -;;; 在Common Lisp中,你也可以使用“字典”的概念——哈希表 - -;; 创建一个哈希表 -(defparameter *m* (make-hash-table)) - -;; 给定键,设置对应的值 -(setf (gethash 'a *m*) 1) - -;; (通过键)检索对应的值 -(gethash 'a *m*) ; => 1, t - -;; 注意此处有一细节:Common Lisp的`gethash`往往会返回两个值。 -;; (译者注:返回的第一个值表示给定的键所对应的值或者nil,第二个则表示在哈希表中是否存在这个给定的键) -;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil - -;; 由给定的键检索一个不存在的值,则返回nil(译者注:即第一个nil,第二个nil其实是指该键在哈希表中也不存在) - (gethash 'd *m*) ;=> nil, nil - -;; 给定一个键,你可以指定其对应的默认值: -(gethash 'd *m* :not-found) ; => :NOT-FOUND - -;; 在此,让我们看一看怎样处理`gethash`的多个返回值。 - -(multiple-value-bind - (a b) - (gethash 'd *m*) - (list a b)) -; => (NIL NIL) - -(multiple-value-bind - (a b) - (gethash 'a *m*) - (list a b)) -; => (1 T) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 3. 函数 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 使用`lambda`来创建一个匿名函数。 -;; 一个函数总是返回其最后一个表达式的值。 -;; 将一个函数对象打印出来后的形式是多种多样的... - -(lambda () "Hello World") ; => # - -;; 使用`funcall`来调用lambda函数 -(funcall (lambda () "Hello World")) ; => "Hello World" - -;; 或者使用`apply` -(apply (lambda () "Hello World") nil) ; => "Hello World" - -;; 显示地定义一个函数(译者注:即非匿名的) -(defun hello-world () - "Hello World") -(hello-world) ; => "Hello World" - -;; 刚刚上面函数名"hello-world"后的()其实是函数的参数列表 -(defun hello (name) - (format nil "Hello, ~a " name)) - -(hello "Steve") ; => "Hello, Steve" - -;; 函数可以有可选形参并且其默认值都为nil - -(defun hello (name &optional from) - (if from - (format t "Hello, ~a, from ~a" name from) - (format t "Hello, ~a" name))) - - (hello "Jim" "Alpacas") ;; => Hello, Jim, from Alpacas - -;; 你也可以指定那些可选形参的默认值 -(defun hello (name &optional (from "The world")) - (format t "Hello, ~a, from ~a" name from)) - -(hello "Steve") -; => Hello, Steve, from The world - -(hello "Steve" "the alpacas") -; => Hello, Steve, from the alpacas - - -;; 当然,你也可以设置关键字形参; -;; 关键字形参往往比可选形参更具灵活性。 - -(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) - (format t "Hello, ~a ~a, from ~a" honorific name from)) - -(generalized-greeter "Jim") ; => Hello, Mx Jim, from the world - -(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") -; => Hello, Mr Jim, from the alpacas you met last summer - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 4. 等价性的含义 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 - -;; 若要比较数值是否等价,使用`=` -(= 3 3.0) ; => t -(= 2 1) ; => nil - -;; 若要比较对象的类型,则使用`eql` -;;(译者注:抱歉,请忽略这句翻译;`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) -;; (想要弄清`eql`,其实有必要先了解`eq`) -;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》里的4.8节也提到了两者的区别) -(eql 3 3) ; => t -(eql 3 3.0) ; => nil -(eql (list 3) (list 3)) ; => nil - -;; 对于列表、字符串、以及位向量,使用`equal` -(equal (list 'a 'b) (list 'a 'b)) ; => t -(equal (list 'a 'b) (list 'b 'a)) ; => nil - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 5. 控制流 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; 条件判断语句 - -(if t ; “测试”,即判断语句 - "this is true" ; “下一步”,即判断条件为真时求值的表达式 - "this is false") ; “否则”,即判断条件为假时求值的表达式 -; => "this is true" - -;; 在“测试”(判断)语句中,所有非nil或者非()的值都被视为真值 -(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) -(if (member 'Groucho '(Harpo Groucho Zeppo)) - 'yep - 'nope) -; => 'YEP - -;; `cond`将一系列测试语句串联起来,并对相应的表达式求值 -(cond ((> 2 2) (error "wrong!")) - ((< 2 2) (error "wrong again!")) - (t 'ok)) ; => 'OK - -;; 对于给定值的数据类型,`typecase`会做出相应地判断 -(typecase 1 - (string :string) - (integer :int)) - -; => :int - -;;; 迭代 - -;; 当然,递归是肯定被支持的: - -(defun walker (n) - (if (zerop n) - :walked - (walker (1- n)))) - -(walker) ; => :walked - -;; 而大部分场合下,我们使用`DOLIST`或者`LOOP`来进行迭代 - - -(dolist (i '(1 2 3 4)) - (format t "~a" i)) - -; => 1234 - -(loop for i from 0 below 10 - collect i) - -; => (0 1 2 3 4 5 6 7 8 9) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 6. 变异 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 使用`setf`可以对一个已经存在的变量进行赋值; -;; 事实上,刚刚在哈希表的例子中我们已经示范过了。 - -(let ((variable 10)) - (setf variable 2)) - ; => 2 - - -;; 所谓好的Lisp编码风格就是为了减少破坏性函数的使用,防止副作用的发生。 -;;(译者注:很惭愧,确实不明白原作者所说的"Mutation",即这里的“变异”到底指的是什么特性) -;;(毕竟他只给了一个例子,我猜测应该是和词法变量、闭包等特性有关,还望高人指点) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 7. 类与对象 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 我们就不写什么有关动物的类了,下面给出的是一个很“人文主义”的类 - -(defclass human-powered-conveyance () - ((velocity - :accessor velocity - :initarg :velocity) - (average-efficiency - :accessor average-efficiency - :initarg :average-efficiency)) - (:documentation "A human powered conveyance")) - -;; `defclass`,后面接类名,以及超类列表 -;; 再接着是槽的列表(槽有点像Java里的字段),最后是一些可选的特性,例如文档说明“:documentation” - -;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类); -;; 这种默认行为是可以改变的,但你最好有一定的基础并且知道自己到底在干什么; -;; 参阅《The Art of the Metaobject Protocol》来了解更多信息。 - -(defclass bicycle (human-powered-conveyance) - ((wheel-size - :accessor wheel-size - :initarg :wheel-size - :documentation "Diameter of the wheel.") - (height - :accessor height - :initarg :height))) - -(defclass recumbent (bicycle) - ((chain-type - :accessor chain-type - :initarg :chain-type))) - -(defclass unicycle (human-powered-conveyance) nil) - -(defclass canoe (human-powered-conveyance) - ((number-of-rowers - :accessor number-of-rowers - :initarg :number-of-rowers))) - - -;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`如下: - -(describe 'human-powered-conveyance) - -; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE -; [symbol] -; -; HUMAN-POWERED-CONVEYANCE names the standard-class #: -; Documentation: -; A human powered conveyance -; Direct superclasses: STANDARD-OBJECT -; Direct subclasses: UNICYCLE, BICYCLE, CANOE -; Not yet finalized. -; Direct slots: -; VELOCITY -; Readers: VELOCITY -; Writers: (SETF VELOCITY) -; AVERAGE-EFFICIENCY -; Readers: AVERAGE-EFFICIENCY -; Writers: (SETF AVERAGE-EFFICIENCY) - -;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。 - -;; 若要定义一个方法; -;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi - -(defmethod circumference ((object bicycle)) - (* pi (wheel-size object))) - -;; pi在Common Lisp中已经是一个内置的常量。 - -;; 假设我们已经知道效率值(“efficiency value”)和船桨数大概呈对数关系; -;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 - -;; 下面是一个如何初始化实例的例子: -;; 构造它: - -(defmethod initialize-instance :after ((object canoe) &rest args) - (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) - -;; 接着初构造一个实例并检查平均效率... - -(average-efficiency (make-instance 'canoe :number-of-rowers 15)) -; => 2.7725887 - - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 8. 宏 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 宏可以让你扩展语法 - -;; Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; -;; 如果按照“拼装者”的直觉来看,我们会这样写: - -(defmacro while (condition &body body) - "While `condition` is true, `body` is executed. - -`condition` is tested prior to each execution of `body`" - (let ((block-name (gensym))) - `(tagbody - (unless ,condition - (go ,block-name)) - (progn - ,@body) - ,block-name))) - -;; 让我们来看看它的高级版本: - - -(defmacro while (condition &body body) - "While `condition` is true, `body` is executed. - -`condition` is tested prior to each execution of `body`" - `(loop while ,condition - do - (progn - ,@body))) - -;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的; -;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 - -;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; -;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 -;; 逗号“,”意味着解除引用(unquote,即开始求值);“@”符号则表示将当前的参数插入到当前整个列表中。 -;;(译者注:这三个符号只不过是语法糖罢了,而要想真正用好、用对,需要下一番功夫) -;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的,建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) - -;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 -;; 这样做是因为,宏是在编译期展开的,而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 - -;; 可以去《实用 Common Lisp 编程》中阅读更多有关宏的内容。 -``` - - -## 拓展阅读 - -[继续阅读《实用 Common Lisp 编程》一书](http://www.gigamonkeys.com/book/) - - -## 致谢 - -非常感谢Scheme社区的人们,我基于他们的成果得以迅速的写出这篇有关Common Lisp的快速入门 -同时也感谢 -- [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 -- cgit v1.2.3 From 2ba6501acc207925a283cae1fe7d20a613fba03a Mon Sep 17 00:00:00 2001 From: Mac David Date: Tue, 10 Dec 2013 00:02:27 +0800 Subject: 1st edition --- zh-cn/common-lisp.html.markdown | 610 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 610 insertions(+) create mode 100644 zh-cn/common-lisp.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown new file mode 100644 index 00000000..48530fbd --- /dev/null +++ b/zh-cn/common-lisp.html.markdown @@ -0,0 +1,610 @@ +--- +Language: "Common Lisp" +Filename: commonlisp.lisp +Contributors: + - ["Paul Nathan", "https://github.com/pnathan"] +Translator: + - ["Mac David", "http://github.com/macdavid313"] +--- + +ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 +这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 + +经典的入门点为[已经完全免费提供的实用Common Lisp编程](http://www.gigamonkeys.com/book/) + +另外还有一本近期内比较热门的 +[Land of Lisp](http://landoflisp.com/). + +```scheme +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; 0. 语法 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 一般形式 + +;; Lisp有两个基本的语法部件:原子,以及S-表达式。 +;; 一般的,一组S-表达式被称为“组合式”。 + +10 ; 一个原子; 它对自身进行求值 + +:THING ;同样是一个原子;它被求值为一个符号 :thing + +t ;还是一个原子,代表逻辑真值。 + +(+ 1 2 3 4) ; 一个S表达式。 + +'(4 :foo t) ;同样是一个S表达式。 + + +;;; 注释 + +;; 一个分号开头的注释表示仅用于此行(单行);两个分号开头的则表示一个所谓标准注释; +;; 三个分号开头的意味着段落注释,而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 + +#| 块注释 + 可以涵盖多行,而且... + #| + 他们可以被嵌套! + |# +|# + +;;; 运行环境 + +;; 有很多不同的Common Lisp的实现;并且大部分的实现是符合标准的。 +;; 对于入门学习来说,CLISP是个不错的选择。 + +;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 + +;; 通常,使用一个文本编辑器和一个同时在运行的“REPL”来开发Common Lisp; +;; (译者注:“REPL”指读取-求值-打印循环)。 +;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; 1. 基本数据类型以及运算符 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 符号 + +'foo ; => FOO 注意到这个符号被自动转换成大写了。 + +;; `intern`由一个给定的字符串而创建相应的符号 + +(intern "AAAA") ; => AAAA + +(intern "aaa") ; => |aaa| + +;;; 数字 +9999999999999999999999 ; 整型数 +#b111 ; 二进制 => 7 +#o111 ; 八进制 => 73 +#x111 ; 十六进制 => 273 +3.14159s0 ; 单精度 +3.14159d0 ; 双精度 +1/2 ; 分数 +#C(1 2) ; 复数 + + +;; 使用函数时,应当写成这样的形式:(f x y z ...); +;; 其中,f是一个函数(名),x, y, z为参数; +;; 如果你想创建一个“字面”意义上(即不求值)的列表, 只需使用单引号 ' , +;; 从而避免接下来的表达式被求值。即,只“引用”这个数据(而不求值)。 +'(+ 1 2) ; => (+ 1 2) +;; 你同样也可以手动地调用一个函数(译者注:即使用函数对象来调用函数): +(funcall #'+ 1 2 3) ; => 6 +;; 一些算术运算符 +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(mod 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) + + ;;; 布尔运算 +t ; 逻辑真(任何不是nil的值都被视为真值) +nil ; 逻辑假,或者空列表 +(not nil) ; => t +(and 0 t) ; => t +(or 0 nil) ; => 0 + + ;;; 字符 +#\A ; => #\A +#\λ ; => #\GREEK_SMALL_LETTER_LAMDA(希腊字母Lambda的小写) +#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA(Unicode形式的小写希腊字母Lambda) + +;;; 字符串被视为一个定长字符数组 +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ;反斜杠用作转义字符 + +;; 字符串可以被连接起来 +(concatenate 'string "Hello " "world!") ; => "Hello world!" + +;; 一个字符串也可被视作一个字符的序列 +(elt "Apple" 0) ; => #\A + +;; `format`被用于格式化字符串 +(format nil "~a can be ~a" "strings" "formatted") + +;; 利用`format`打印到屏幕上是非常简单的(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 +(format t "Common Lisp is groovy. Dude.~%") + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. 变量 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 你可以通过`defparameter`创建一个全局(动态)变量 +;; 除了:()[]{}",'`;#|\ 这些字符,其他任何字符都可被用于变量名 + +;; 动态变量名应该由*号开头与结尾! + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;; 你也可以使用Unicode字符: +(defparameter *AΛB* nil) + + +;; 访问一个在之前从未未绑定的变量是一种不规范的行为(即使依然是可能发生的); +;; 不要尝试那样做。 + + +;; 局部绑定:'me'被绑定到"dance with you"上,当且仅当它在(let ...)内有效。 +;; `let`总是返回在其作用域内最后一个表达式的值 + +(let ((me "dance with you")) + me) +;; => "dance with you" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 结构体和集合 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 结构体 +(defstruct dog name breed age) +(defparameter *rover* + (make-dog :name "rover" + :breed "collie" + :age 5)) +*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) + +(dog-p *rover*) ; => t ;; ewww) +(dog-name *rover*) ; => "rover" + +;; Dog-p,make-dog,以及 dog-name都是由defstruct创建的! + +;;; 点对单元 +;; `cons`可用于生成一个点对单元, 利用`car`以及`cdr`将分别得到第一个和第二个元素 +(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB)) ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB)) ; => VERB + +;;; 列表 + +;; 所有列表都是由点对单元构成、并以'nil'(或者'())结尾的一种被称为“链表”的数据结构 +(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) +;; `list`是一个生成列表的便利途径 +(list 1 2 3) ; => '(1 2 3) +;; 并且,一个引用也可被用做字面意义上的列表值 +'(1 2 3) ; => '(1 2 3) + +;; 同样的,依然可以用`cons`来添加一项到列表的起始位置 +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;; 而`append`也可用于连接两个列表 +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;; 或者使用`concatenate` + +(concatenate 'list '(1 2) '(3 4)) + +;; 列表是一种非常核心的数据类型,所以有非常多的处理列表的函数 +;; 例如: +(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4)) ; => nil +(some #'oddp '(1 2 3 4)) ; => T +(butlast '(subject verb object)) ; => (SUBJECT VERB) + + +;;; 向量 + +;; 向量的字面意义是一个定长数组(译者注:此处所谓字面意义的,即为#(......)的形式,下文还会出现) +#(1 2 3) ; => #(1 2 3) + +;; 使用`concatenate`来将两个向量首尾连接在一起 +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + +;;; 数组 + +;; 向量和字符串只不过是数组的特例 + +;; 二维数组 + +(make-array (list 2 2)) + +;; (make-array '(2 2)) 也是可以的 + +; => #2A((0 0) (0 0)) + +(make-array (list 2 2 2)) + +; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;; 注意:数组的默认初始值是可以指定的 +;; 下面是如何指定的示例: + +(make-array '(2) :initial-element 'unset) + +; => #(UNSET UNSET) + +;; 若想获取数组[1][1][1]上的元素: +(aref (make-array (list 2 2 2)) 1 1 1) + +; => 0 + +;;; 变长向量 + +;; 若将变长向量打印出来,那么它的字面意义上的值和定长向量的是一样的 + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) + :adjustable t :fill-pointer t)) + +*adjvec* ; => #(1 2 3) + +;; 添加新的元素: +(vector-push-extend 4 *adjvec*) ; => 3 + +*adjvec* ; => #(1 2 3 4) + + + +;;; 不怎么严谨地说,集合也可被视为列表 + +(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 +(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) + +;; 然而,你可能想使用一个更好的数据结构,而并非一个链表 + +;;; 在Common Lisp中,你也可以使用“字典”的概念——哈希表 + +;; 创建一个哈希表 +(defparameter *m* (make-hash-table)) + +;; 给定键,设置对应的值 +(setf (gethash 'a *m*) 1) + +;; (通过键)检索对应的值 +(gethash 'a *m*) ; => 1, t + +;; 注意此处有一细节:Common Lisp的`gethash`往往会返回两个值。 +;; (译者注:返回的第一个值表示给定的键所对应的值或者nil,第二个则表示在哈希表中是否存在这个给定的键) +;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil + +;; 由给定的键检索一个不存在的值,则返回nil(译者注:即第一个nil,第二个nil其实是指该键在哈希表中也不存在) + (gethash 'd *m*) ;=> nil, nil + +;; 给定一个键,你可以指定其对应的默认值: +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;; 在此,让我们看一看怎样处理`gethash`的多个返回值。 + +(multiple-value-bind + (a b) + (gethash 'd *m*) + (list a b)) +; => (NIL NIL) + +(multiple-value-bind + (a b) + (gethash 'a *m*) + (list a b)) +; => (1 T) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 函数 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用`lambda`来创建一个匿名函数。 +;; 一个函数总是返回其最后一个表达式的值。 +;; 将一个函数对象打印出来后的形式是多种多样的... + +(lambda () "Hello World") ; => # + +;; 使用`funcall`来调用lambda函数 +(funcall (lambda () "Hello World")) ; => "Hello World" + +;; 或者使用`apply` +(apply (lambda () "Hello World") nil) ; => "Hello World" + +;; 显示地定义一个函数(译者注:即非匿名的) +(defun hello-world () + "Hello World") +(hello-world) ; => "Hello World" + +;; 刚刚上面函数名"hello-world"后的()其实是函数的参数列表 +(defun hello (name) + (format nil "Hello, ~a " name)) + +(hello "Steve") ; => "Hello, Steve" + +;; 函数可以有可选形参并且其默认值都为nil + +(defun hello (name &optional from) + (if from + (format t "Hello, ~a, from ~a" name from) + (format t "Hello, ~a" name))) + + (hello "Jim" "Alpacas") ;; => Hello, Jim, from Alpacas + +;; 你也可以指定那些可选形参的默认值 +(defun hello (name &optional (from "The world")) + (format t "Hello, ~a, from ~a" name from)) + +(hello "Steve") +; => Hello, Steve, from The world + +(hello "Steve" "the alpacas") +; => Hello, Steve, from the alpacas + + +;; 当然,你也可以设置关键字形参; +;; 关键字形参往往比可选形参更具灵活性。 + +(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) + (format t "Hello, ~a ~a, from ~a" honorific name from)) + +(generalized-greeter "Jim") ; => Hello, Mx Jim, from the world + +(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") +; => Hello, Mr Jim, from the alpacas you met last summer + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. 等价性的含义 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 + +;; 若要比较数值是否等价,使用`=` +(= 3 3.0) ; => t +(= 2 1) ; => nil + +;; 若要比较对象的类型,则使用`eql` +;;(译者注:抱歉,请忽略这句翻译;`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) +;; (想要弄清`eql`,其实有必要先了解`eq`) +;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》里的4.8节也提到了两者的区别) +(eql 3 3) ; => t +(eql 3 3.0) ; => nil +(eql (list 3) (list 3)) ; => nil + +;; 对于列表、字符串、以及位向量,使用`equal` +(equal (list 'a 'b) (list 'a 'b)) ; => t +(equal (list 'a 'b) (list 'b 'a)) ; => nil + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. 控制流 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 条件判断语句 + +(if t ; “测试”,即判断语句 + "this is true" ; “下一步”,即判断条件为真时求值的表达式 + "this is false") ; “否则”,即判断条件为假时求值的表达式 +; => "this is true" + +;; 在“测试”(判断)语句中,所有非nil或者非()的值都被视为真值 +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'YEP + +;; `cond`将一系列测试语句串联起来,并对相应的表达式求值 +(cond ((> 2 2) (error "wrong!")) + ((< 2 2) (error "wrong again!")) + (t 'ok)) ; => 'OK + +;; 对于给定值的数据类型,`typecase`会做出相应地判断 +(typecase 1 + (string :string) + (integer :int)) + +; => :int + +;;; 迭代 + +;; 当然,递归是肯定被支持的: + +(defun walker (n) + (if (zerop n) + :walked + (walker (1- n)))) + +(walker) ; => :walked + +;; 而大部分场合下,我们使用`DOLIST`或者`LOOP`来进行迭代 + + +(dolist (i '(1 2 3 4)) + (format t "~a" i)) + +; => 1234 + +(loop for i from 0 below 10 + collect i) + +; => (0 1 2 3 4 5 6 7 8 9) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. 变异 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用`setf`可以对一个已经存在的变量进行赋值; +;; 事实上,刚刚在哈希表的例子中我们已经示范过了。 + +(let ((variable 10)) + (setf variable 2)) + ; => 2 + + +;; 所谓好的Lisp编码风格就是为了减少破坏性函数的使用,防止副作用的发生。 +;;(译者注:很惭愧,确实不明白原作者所说的"Mutation",即这里的“变异”到底指的是什么特性) +;;(毕竟他只给了一个例子,我猜测应该是和词法变量、闭包等特性有关,还望高人指点) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. 类与对象 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 我们就不写什么有关动物的类了,下面给出的是一个很“人文主义”的类 + +(defclass human-powered-conveyance () + ((velocity + :accessor velocity + :initarg :velocity) + (average-efficiency + :accessor average-efficiency + :initarg :average-efficiency)) + (:documentation "A human powered conveyance")) + +;; `defclass`,后面接类名,以及超类列表 +;; 再接着是槽的列表(槽有点像Java里的字段),最后是一些可选的特性,例如文档说明“:documentation” + +;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类); +;; 这种默认行为是可以改变的,但你最好有一定的基础并且知道自己到底在干什么; +;; 参阅《The Art of the Metaobject Protocol》来了解更多信息。 + +(defclass bicycle (human-powered-conveyance) + ((wheel-size + :accessor wheel-size + :initarg :wheel-size + :documentation "Diameter of the wheel.") + (height + :accessor height + :initarg :height))) + +(defclass recumbent (bicycle) + ((chain-type + :accessor chain-type + :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) + ((number-of-rowers + :accessor number-of-rowers + :initarg :number-of-rowers))) + + +;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`如下: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +; [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #: +; Documentation: +; A human powered conveyance +; Direct superclasses: STANDARD-OBJECT +; Direct subclasses: UNICYCLE, BICYCLE, CANOE +; Not yet finalized. +; Direct slots: +; VELOCITY +; Readers: VELOCITY +; Writers: (SETF VELOCITY) +; AVERAGE-EFFICIENCY +; Readers: AVERAGE-EFFICIENCY +; Writers: (SETF AVERAGE-EFFICIENCY) + +;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。 + +;; 若要定义一个方法; +;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi + +(defmethod circumference ((object bicycle)) + (* pi (wheel-size object))) + +;; pi在Common Lisp中已经是一个内置的常量。 + +;; 假设我们已经知道效率值(“efficiency value”)和船桨数大概呈对数关系; +;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 + +;; 下面是一个如何初始化实例的例子: +;; 构造它: + +(defmethod initialize-instance :after ((object canoe) &rest args) + (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) + +;; 接着初构造一个实例并检查平均效率... + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 8. 宏 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 宏可以让你扩展语法 + +;; Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; +;; 如果按照“拼装者”的直觉来看,我们会这样写: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. + +`condition` is tested prior to each execution of `body`" + (let ((block-name (gensym))) + `(tagbody + (unless ,condition + (go ,block-name)) + (progn + ,@body) + ,block-name))) + +;; 让我们来看看它的高级版本: + + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. + +`condition` is tested prior to each execution of `body`" + `(loop while ,condition + do + (progn + ,@body))) + +;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的; +;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 + +;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; +;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 +;; 逗号“,”意味着解除引用(unquote,即开始求值);“@”符号则表示将当前的参数插入到当前整个列表中。 +;;(译者注:这三个符号只不过是语法糖罢了,而要想真正用好、用对,需要下一番功夫) +;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的,建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) + +;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 +;; 这样做是因为,宏是在编译期展开的,而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 + +;; 可以去《实用 Common Lisp 编程》中阅读更多有关宏的内容。 +``` + + +## 拓展阅读 + +[继续阅读《实用 Common Lisp 编程》一书](http://www.gigamonkeys.com/book/) + + +## 致谢 + +非常感谢Scheme社区的人们,我基于他们的成果得以迅速的写出这篇有关Common Lisp的快速入门 +同时也感谢 +- [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 -- cgit v1.2.3 From 1bb3cea0c2a528c501dd8c2cf597336eb7b07d40 Mon Sep 17 00:00:00 2001 From: Mac David Date: Tue, 10 Dec 2013 00:08:11 +0800 Subject: 1st Edition --- zh-cn/common-lisp.html.markdown | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index 48530fbd..d7534109 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -374,7 +374,8 @@ nil ; 逻辑假,或者空列表 (= 2 1) ; => nil ;; 若要比较对象的类型,则使用`eql` -;;(译者注:抱歉,请忽略这句翻译;`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) +;;(译者注:抱歉,翻译水平实在有限,下面是我个人的补充说明) +;;(`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) ;; (想要弄清`eql`,其实有必要先了解`eq`) ;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》里的4.8节也提到了两者的区别) (eql 3 3) ; => t @@ -589,7 +590,8 @@ nil ; 逻辑假,或者空列表 ;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 ;; 逗号“,”意味着解除引用(unquote,即开始求值);“@”符号则表示将当前的参数插入到当前整个列表中。 ;;(译者注:这三个符号只不过是语法糖罢了,而要想真正用好、用对,需要下一番功夫) -;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的,建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) +;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的) +;;(建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) ;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 ;; 这样做是因为,宏是在编译期展开的,而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 -- cgit v1.2.3 From 86751331c66c4031b76eb6919f3c7b1c3d3c2c8a Mon Sep 17 00:00:00 2001 From: Mac David Date: Tue, 10 Dec 2013 00:10:58 +0800 Subject: temp --- zh-cn/common-lisp.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index d7534109..fe5f81ec 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -10,7 +10,7 @@ Translator: ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 -经典的入门点为[已经完全免费提供的实用Common Lisp编程](http://www.gigamonkeys.com/book/) +经典的入门点为[已经完全免费提供的《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) 另外还有一本近期内比较热门的 [Land of Lisp](http://landoflisp.com/). -- cgit v1.2.3 From 139a9af08c1095bd655a3fc324da093969f78be2 Mon Sep 17 00:00:00 2001 From: Mac David Date: Tue, 10 Dec 2013 00:14:39 +0800 Subject: add Chinese translate of Common Lisp --- zh-cn/common-lisp.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index fe5f81ec..aaa33c83 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -10,7 +10,7 @@ Translator: ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 -经典的入门点为[已经完全免费提供的《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) +经典的入门点为[已完全免费提供的《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) 另外还有一本近期内比较热门的 [Land of Lisp](http://landoflisp.com/). -- cgit v1.2.3 From 48ba096ac73a07aa56799e569ba9a56264319731 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 10 Dec 2013 18:57:05 +0800 Subject: =?UTF-8?q?assign=20=E5=BA=94=E8=AF=A5=E7=BF=BB=E8=AF=91=E6=88=90?= =?UTF-8?q?=20=E8=B5=8B=E5=80=BC=20=EF=BC=8C=E8=80=8C=E9=9D=9E=20=E5=88=86?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zh-cn/bash-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index e3eed3a6..fb55947d 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -40,7 +40,7 @@ VARIABLE = "Some string" echo $VARIABLE echo "$VARIABLE" echo '$VARIABLE' -# 当你分配 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。 +# 当你赋值 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。 # 如果要使用变量的值, 则要加 $。 # 注意: ' (单引号) 不会展开变量(即会屏蔽掉变量)。 -- cgit v1.2.3 From 27ae8bc889a09595898ffa7de5bb3dd6aba50ff6 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 10 Dec 2013 19:01:01 +0800 Subject: =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A0=87=E7=82=B9=E7=AC=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zh-cn/bash-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index e3eed3a6..e9cc7a9c 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -12,7 +12,7 @@ lang: zh-cn --- Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 Mac OS X 下的默认 shell。 -以下大多数例子可以作为脚本的一部分运行也可直接在 shell 下交互执行。 +以下大多数例子可以作为脚本的一部分运行,也可直接在 shell 下交互执行。 [更多信息](http://www.gnu.org/software/bash/manual/bashref.html) -- cgit v1.2.3 From ba78de82349549f521c899dd45493e0d9b20659c Mon Sep 17 00:00:00 2001 From: Mac David Date: Tue, 10 Dec 2013 19:04:35 +0800 Subject: Just update and correct some contents --- zh-cn/common-lisp.html.markdown | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index aaa33c83..acecf60c 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -1,10 +1,10 @@ --- Language: "Common Lisp" Filename: commonlisp.lisp -Contributors: +Contributor: - ["Paul Nathan", "https://github.com/pnathan"] Translator: - - ["Mac David", "http://github.com/macdavid313"] + - ["Mac David", "http://macdavid313.com"] --- ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 @@ -31,9 +31,9 @@ ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范 t ;还是一个原子,代表逻辑真值。 -(+ 1 2 3 4) ; 一个S表达式。 +(+ 1 2 3 4) ; 一个S-表达式。 -'(4 :foo t) ;同样是一个S表达式。 +'(4 :foo t) ;同样是一个S-表达式。 ;;; 注释 @@ -146,7 +146,7 @@ nil ; 逻辑假,或者空列表 (defparameter *AΛB* nil) -;; 访问一个在之前从未未绑定的变量是一种不规范的行为(即使依然是可能发生的); +;; 访问一个在之前从未被绑定的变量是一种不规范的行为(即使依然是可能发生的); ;; 不要尝试那样做。 @@ -211,7 +211,7 @@ nil ; 逻辑假,或者空列表 ;;; 向量 -;; 向量的字面意义是一个定长数组(译者注:此处所谓字面意义的,即为#(......)的形式,下文还会出现) +;; 向量的字面意义是一个定长数组(译者注:此处所谓“字面意义”,即指#(......)的形式,下文还会出现) #(1 2 3) ; => #(1 2 3) ;; 使用`concatenate`来将两个向量首尾连接在一起 @@ -282,10 +282,12 @@ nil ; 逻辑假,或者空列表 (gethash 'a *m*) ; => 1, t ;; 注意此处有一细节:Common Lisp的`gethash`往往会返回两个值。 -;; (译者注:返回的第一个值表示给定的键所对应的值或者nil,第二个则表示在哈希表中是否存在这个给定的键) +;;(译者注:返回的第一个值表示给定的键所对应的值或者nil;) +;;(第二个是一个布尔值,表示在哈希表中是否存在这个给定的键) ;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil -;; 由给定的键检索一个不存在的值,则返回nil(译者注:即第一个nil,第二个nil其实是指该键在哈希表中也不存在) +;; 由给定的键检索一个不存在的值,则返回nil +;;(译者注:这个nil是第一个nil,第二个nil其实是指该键在哈希表中也不存在) (gethash 'd *m*) ;=> nil, nil ;; 给定一个键,你可以指定其对应的默认值: @@ -310,7 +312,7 @@ nil ; 逻辑假,或者空列表 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 使用`lambda`来创建一个匿名函数。 -;; 一个函数总是返回其最后一个表达式的值。 +;; 一个函数总是返回其形式体内最后一个表达式的值。 ;; 将一个函数对象打印出来后的形式是多种多样的... (lambda () "Hello World") ; => # @@ -352,7 +354,7 @@ nil ; 逻辑假,或者空列表 ; => Hello, Steve, from the alpacas -;; 当然,你也可以设置关键字形参; +;; 当然,你也可以设置所谓关键字形参; ;; 关键字形参往往比可选形参更具灵活性。 (defun generalized-greeter (name &key (from "the world") (honorific "Mx")) @@ -377,7 +379,7 @@ nil ; 逻辑假,或者空列表 ;;(译者注:抱歉,翻译水平实在有限,下面是我个人的补充说明) ;;(`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) ;; (想要弄清`eql`,其实有必要先了解`eq`) -;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》里的4.8节也提到了两者的区别) +;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》的4.8节也提到了两者的区别) (eql 3 3) ; => t (eql 3 3.0) ; => nil (eql (list 3) (list 3)) ; => nil @@ -455,7 +457,7 @@ nil ; 逻辑假,或者空列表 ;; 所谓好的Lisp编码风格就是为了减少破坏性函数的使用,防止副作用的发生。 ;;(译者注:很惭愧,确实不明白原作者所说的"Mutation",即这里的“变异”到底指的是什么特性) -;;(毕竟他只给了一个例子,我猜测应该是和词法变量、闭包等特性有关,还望高人指点) +;;(我猜测应该是和词法变量、闭包等特性有关,还望高人指点、修正与完善) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 7. 类与对象 @@ -501,7 +503,7 @@ nil ; 逻辑假,或者空列表 :initarg :number-of-rowers))) -;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`如下: +;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`后结果如下: (describe 'human-powered-conveyance) @@ -533,7 +535,7 @@ nil ; 逻辑假,或者空列表 ;; pi在Common Lisp中已经是一个内置的常量。 -;; 假设我们已经知道效率值(“efficiency value”)和船桨数大概呈对数关系; +;; 假设我们已经知道了效率值(“efficiency value”)和船桨数大概呈对数关系; ;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 ;; 下面是一个如何初始化实例的例子: @@ -548,15 +550,13 @@ nil ; 逻辑假,或者空列表 ; => 2.7725887 - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8. 宏 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 宏可以让你扩展语法 -;; Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; +;; 例如,Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; ;; 如果按照“拼装者”的直觉来看,我们会这样写: (defmacro while (condition &body body) @@ -573,7 +573,6 @@ nil ; 逻辑假,或者空列表 ;; 让我们来看看它的高级版本: - (defmacro while (condition &body body) "While `condition` is true, `body` is executed. @@ -589,7 +588,7 @@ nil ; 逻辑假,或者空列表 ;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; ;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 ;; 逗号“,”意味着解除引用(unquote,即开始求值);“@”符号则表示将当前的参数插入到当前整个列表中。 -;;(译者注:这三个符号只不过是语法糖罢了,而要想真正用好、用对,需要下一番功夫) +;;(译者注:要想真正用好、用对这三个符号,需要下一番功夫) ;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的) ;;(建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) @@ -610,3 +609,6 @@ nil ; 逻辑假,或者空列表 非常感谢Scheme社区的人们,我基于他们的成果得以迅速的写出这篇有关Common Lisp的快速入门 同时也感谢 - [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 + +##译者寄语 +“祝福那些将思想镶嵌在重重括号之内的人们。” \ No newline at end of file -- cgit v1.2.3 From 19e7828719934bbd760f87d6e52d9cf08eb65056 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 10 Dec 2013 19:19:10 +0800 Subject: it should be `some_set` --- zh-cn/python-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown index 51efaac3..deb94cdc 100755 --- a/zh-cn/python-cn.html.markdown +++ b/zh-cn/python-cn.html.markdown @@ -232,7 +232,7 @@ filled_dict.setdefault("five", 6) # filled_dict["five"] 的值仍然是 5 # 集合储存无顺序的元素 empty_set = set() # 初始化一个集合 -some_set = set([1, 2, 2, 3, 4]) # filled_set 现在是 set([1, 2, 3, 4]) +some_set = set([1, 2, 2, 3, 4]) # some_set 现在是 set([1, 2, 3, 4]) # Python 2.7 之后,大括号可以用来表示集合 filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4} -- cgit v1.2.3 From 55e01bd88c3dd44430fe9b11e584b97a5a1011cf Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 10 Dec 2013 22:06:44 +0800 Subject: correct typo --- zh-cn/java-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index 9422ac2f..f7d319e6 100755 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -322,7 +322,7 @@ class Bicycle { // 方法声明的语法: // <作用域> <返回值类型> <方法名>(<参数列表>) public int getCadence() { - retur450635425n cadence; + return cadence; } // void返450635425回值函数没有返回值 -- cgit v1.2.3 From 9573bcce9fa5f4ed931442930199b8bdca6064bb Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 10 Dec 2013 22:11:42 +0800 Subject: typo --- zh-cn/git-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown index 86952eba..1b93d162 100755 --- a/zh-cn/git-cn.html.markdown +++ b/zh-cn/git-cn.html.markdown @@ -219,7 +219,7 @@ $ git diff # 显示索引和最近一次提交的不同 $ git diff --cached -# 显示宫缩目录和最近一次提交的不同 +# 显示工作目录和最近一次提交的不同 $ git diff HEAD ``` -- cgit v1.2.3 From 4e12a861065592acae6b028a399372a13e5dfb21 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 10 Dec 2013 22:17:51 +0800 Subject: fix typo or that is not a typo? I'm not sure, so I request a pull, you make the choice. --- zh-cn/git-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown index 86952eba..6a45bd9e 100755 --- a/zh-cn/git-cn.html.markdown +++ b/zh-cn/git-cn.html.markdown @@ -349,7 +349,7 @@ $ git reset --hard 31f2bb1 ### rm -和add相反,从工作空间中去掉某个文件爱你 +和add相反,从工作空间中去掉某个文件 ```bash # 移除 HelloWorld.c -- cgit v1.2.3 From f9cff00e891225be0a3effc51b3261d5a10f60fb Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Dec 2013 08:31:45 -0800 Subject: Fix problems with zh-cn common lisp --- zh-cn/common-lisp.html.markdown | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index acecf60c..a1b76da5 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -1,10 +1,11 @@ --- -Language: "Common Lisp" -Filename: commonlisp.lisp -Contributor: +language: "Common Lisp" +filename: commonlisp-cn.lisp +contributors: - ["Paul Nathan", "https://github.com/pnathan"] -Translator: +translators: - ["Mac David", "http://macdavid313.com"] +lang: zh-cn --- ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 @@ -611,4 +612,4 @@ nil ; 逻辑假,或者空列表 - [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 ##译者寄语 -“祝福那些将思想镶嵌在重重括号之内的人们。” \ No newline at end of file +“祝福那些将思想镶嵌在重重括号之内的人们。” -- cgit v1.2.3 From 264241659deb4510ee4323684f0c7bd7889d2865 Mon Sep 17 00:00:00 2001 From: Mac David Date: Thu, 12 Dec 2013 01:00:18 +0800 Subject: Just a update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some lines’ words are just too much and I correct that. --- zh-cn/common-lisp.html.markdown | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index acecf60c..72fd4787 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -10,7 +10,11 @@ Translator: ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 +<<<<<<< HEAD 经典的入门点为[已完全免费提供的《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) +======= +经典的入门点为[已经完全免费提供的实用Common Lisp编程](http://www.gigamonkeys.com/book/) +>>>>>>> parent of 8675133... temp 另外还有一本近期内比较热门的 [Land of Lisp](http://landoflisp.com/). @@ -39,7 +43,8 @@ t ;还是一个原子,代表逻辑真值。 ;;; 注释 ;; 一个分号开头的注释表示仅用于此行(单行);两个分号开头的则表示一个所谓标准注释; -;; 三个分号开头的意味着段落注释,而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 +;; 三个分号开头的意味着段落注释; +;; 而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 #| 块注释 可以涵盖多行,而且... @@ -127,7 +132,8 @@ nil ; 逻辑假,或者空列表 ;; `format`被用于格式化字符串 (format nil "~a can be ~a" "strings" "formatted") -;; 利用`format`打印到屏幕上是非常简单的(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 +;; 利用`format`打印到屏幕上是非常简单的 +;;(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 (format t "Common Lisp is groovy. Dude.~%") @@ -211,7 +217,8 @@ nil ; 逻辑假,或者空列表 ;;; 向量 -;; 向量的字面意义是一个定长数组(译者注:此处所谓“字面意义”,即指#(......)的形式,下文还会出现) +;; 向量的字面意义是一个定长数组 +;;(译者注:此处所谓“字面意义”,即指#(......)的形式,下文还会出现) #(1 2 3) ; => #(1 2 3) ;; 使用`concatenate`来将两个向量首尾连接在一起 @@ -366,7 +373,7 @@ nil ; 逻辑假,或者空列表 ; => Hello, Mr Jim, from the alpacas you met last summer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 4. 等价性的含义 +;; 4. 等价性 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 @@ -377,9 +384,11 @@ nil ; 逻辑假,或者空列表 ;; 若要比较对象的类型,则使用`eql` ;;(译者注:抱歉,翻译水平实在有限,下面是我个人的补充说明) -;;(`eql`在二者`eq`等价,或者同为数字与字符下相同的类型,例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) +;;(`eql`在二者`eq`等价,或者同为数字与字符下相同的类型) +;;(例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) ;; (想要弄清`eql`,其实有必要先了解`eq`) -;;(可以去CLHS上分别查看两者的文档,另外,《实用Common Lisp编程》的4.8节也提到了两者的区别) +;;(可以去CLHS上分别查看两者的文档) +;;(另外,《实用Common Lisp编程》的4.8节也提到了两者的区别) (eql 3 3) ; => t (eql 3 3.0) ; => nil (eql (list 3) (list 3)) ; => nil @@ -456,7 +465,7 @@ nil ; 逻辑假,或者空列表 ;; 所谓好的Lisp编码风格就是为了减少破坏性函数的使用,防止副作用的发生。 -;;(译者注:很惭愧,确实不明白原作者所说的"Mutation",即这里的“变异”到底指的是什么特性) +;;(译者注:很惭愧,确实不明白原作者的“变异”到底指的是什么特性) ;;(我猜测应该是和词法变量、闭包等特性有关,还望高人指点、修正与完善) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -475,9 +484,10 @@ nil ; 逻辑假,或者空列表 (:documentation "A human powered conveyance")) ;; `defclass`,后面接类名,以及超类列表 -;; 再接着是槽的列表(槽有点像Java里的字段),最后是一些可选的特性,例如文档说明“:documentation” +;; 再接着是槽的列表(槽有点像Java里的字段),最后是一些可选的特性 +;; 例如文档说明“:documentation” -;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类); +;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类) ;; 这种默认行为是可以改变的,但你最好有一定的基础并且知道自己到底在干什么; ;; 参阅《The Art of the Metaobject Protocol》来了解更多信息。 @@ -587,13 +597,15 @@ nil ; 逻辑假,或者空列表 ;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; ;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 -;; 逗号“,”意味着解除引用(unquote,即开始求值);“@”符号则表示将当前的参数插入到当前整个列表中。 +;; 逗号“,”意味着解除引用(unquote,即开始求值); +;; “@”符号则表示将当前的参数插入到当前整个列表中。 ;;(译者注:要想真正用好、用对这三个符号,需要下一番功夫) ;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的) ;;(建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) ;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 -;; 这样做是因为,宏是在编译期展开的,而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 +;; 这样做是因为,宏是在编译期展开的 +;; 而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 ;; 可以去《实用 Common Lisp 编程》中阅读更多有关宏的内容。 ``` @@ -611,4 +623,4 @@ nil ; 逻辑假,或者空列表 - [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 ##译者寄语 -“祝福那些将思想镶嵌在重重括号之内的人们。” \ No newline at end of file +“祝福那些将思想镶嵌在重重括号之内的人们。” -- cgit v1.2.3 From 48d9eecbfd6b53895c719c4903850cc8a561014c Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Dec 2013 21:27:04 -0800 Subject: Fixed merge conflict --- zh-cn/common-lisp.html.markdown | 4 ---- 1 file changed, 4 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index 9cc24198..e623ad1a 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -11,11 +11,7 @@ lang: zh-cn ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 -<<<<<<< HEAD 经典的入门点为[已完全免费提供的《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) -======= -经典的入门点为[已经完全免费提供的实用Common Lisp编程](http://www.gigamonkeys.com/book/) ->>>>>>> parent of 8675133... temp 另外还有一本近期内比较热门的 [Land of Lisp](http://landoflisp.com/). -- cgit v1.2.3 From a670e63723953e71c32d79023ea05bf1d16915fd Mon Sep 17 00:00:00 2001 From: savior Date: Tue, 17 Dec 2013 21:37:30 +0800 Subject: fix common lisp --- zh-cn/common-lisp.html.markdown | 59 +++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown index e623ad1a..f005dd58 100644 --- a/zh-cn/common-lisp.html.markdown +++ b/zh-cn/common-lisp.html.markdown @@ -5,15 +5,16 @@ contributors: - ["Paul Nathan", "https://github.com/pnathan"] translators: - ["Mac David", "http://macdavid313.com"] + - ["mut0u", "http://github.com/mut0u"] lang: zh-cn --- ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 -经典的入门点为[已完全免费提供的《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) +免费的经典的入门书籍[《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) -另外还有一本近期内比较热门的 +另外还有一本热门的近期出版的 [Land of Lisp](http://landoflisp.com/). ```scheme @@ -23,7 +24,7 @@ ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范 ;;; 一般形式 -;; Lisp有两个基本的语法部件:原子,以及S-表达式。 +;; Lisp有两个基本的语法单元:原子(atom),以及S-表达式。 ;; 一般的,一组S-表达式被称为“组合式”。 10 ; 一个原子; 它对自身进行求值 @@ -52,12 +53,12 @@ t ;还是一个原子,代表逻辑真值。 ;;; 运行环境 -;; 有很多不同的Common Lisp的实现;并且大部分的实现是符合标准的。 +;; 有很多不同的Common Lisp的实现;并且大部分的实现是一致(可移植)的。 ;; 对于入门学习来说,CLISP是个不错的选择。 ;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 -;; 通常,使用一个文本编辑器和一个同时在运行的“REPL”来开发Common Lisp; +;; 通常,使用一个文本编辑器和一个的“REPL”来开发Common Lisp; ;; (译者注:“REPL”指读取-求值-打印循环)。 ;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 @@ -120,10 +121,10 @@ nil ; 逻辑假,或者空列表 "Hello, world!" "Benjamin \"Bugsy\" Siegel" ;反斜杠用作转义字符 -;; 字符串可以被连接起来 +;; 可以拼接字符串 (concatenate 'string "Hello " "world!") ; => "Hello world!" -;; 一个字符串也可被视作一个字符的序列 +;; 一个字符串也可被视作一个字符序列 (elt "Apple" 0) ; => #\A ;; `format`被用于格式化字符串 @@ -138,9 +139,10 @@ nil ; 逻辑假,或者空列表 ;; 2. 变量 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 你可以通过`defparameter`创建一个全局(动态)变量 -;; 除了:()[]{}",'`;#|\ 这些字符,其他任何字符都可被用于变量名 +;; 变量名可以是除了:()[]{}",'`;#|\ 这些字符之外的其他任何字符 ;; 动态变量名应该由*号开头与结尾! +;; (译者注:这个只是一个习惯) (defparameter *some-var* 5) *some-var* ; => 5 @@ -153,7 +155,7 @@ nil ; 逻辑假,或者空列表 ;; 不要尝试那样做。 -;; 局部绑定:'me'被绑定到"dance with you"上,当且仅当它在(let ...)内有效。 +;; 局部绑定:在(let ...)语句内,'me'被绑定到"dance with you"上。 ;; `let`总是返回在其作用域内最后一个表达式的值 (let ((me "dance with you")) @@ -177,7 +179,7 @@ nil ; 逻辑假,或者空列表 ;; Dog-p,make-dog,以及 dog-name都是由defstruct创建的! -;;; 点对单元 +;;; 点对单元(Pairs) ;; `cons`可用于生成一个点对单元, 利用`car`以及`cdr`将分别得到第一个和第二个元素 (cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) (car (cons 'SUBJECT 'VERB)) ; => SUBJECT @@ -185,7 +187,7 @@ nil ; 逻辑假,或者空列表 ;;; 列表 -;; 所有列表都是由点对单元构成、并以'nil'(或者'())结尾的一种被称为“链表”的数据结构 +;; 所有列表都是由点对单元构成的“链表”。它以'nil'(或者'())作为列表的最后一个元素。 (cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) ;; `list`是一个生成列表的便利途径 (list 1 2 3) ; => '(1 2 3) @@ -274,7 +276,7 @@ nil ; 逻辑假,或者空列表 ;; 然而,你可能想使用一个更好的数据结构,而并非一个链表 -;;; 在Common Lisp中,你也可以使用“字典”的概念——哈希表 +;;; 在Common Lisp中,“字典”和哈希表的实现是一样的。 ;; 创建一个哈希表 (defparameter *m* (make-hash-table)) @@ -285,7 +287,7 @@ nil ; 逻辑假,或者空列表 ;; (通过键)检索对应的值 (gethash 'a *m*) ; => 1, t -;; 注意此处有一细节:Common Lisp的`gethash`往往会返回两个值。 +;; 注意此处有一细节:Common Lisp往往返回多个值。`gethash`返回的两个值是t,代表找到了这个元素;返回nil表示没有找到这个元素。 ;;(译者注:返回的第一个值表示给定的键所对应的值或者nil;) ;;(第二个是一个布尔值,表示在哈希表中是否存在这个给定的键) ;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil @@ -370,7 +372,7 @@ nil ; 逻辑假,或者空列表 ; => Hello, Mr Jim, from the alpacas you met last summer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 4. 等价性 +;; 4. 等式 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 @@ -381,9 +383,11 @@ nil ; 逻辑假,或者空列表 ;; 若要比较对象的类型,则使用`eql` ;;(译者注:抱歉,翻译水平实在有限,下面是我个人的补充说明) -;;(`eql`在二者`eq`等价,或者同为数字与字符下相同的类型) +;;(`eq` 返回真,如果对象的内存地址相等) +;;(`eql` 返回真,如果两个对象内存地址相等,或者对象的类型相同,并且值相等) ;;(例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) -;; (想要弄清`eql`,其实有必要先了解`eq`) +;;(想要弄清`eql`,其实有必要先了解`eq`) +;;([可以参考](http://stackoverflow.com/questions/547436/whats-the-difference-between-eq-eql-equal-and-equalp-in-common-lisp)) ;;(可以去CLHS上分别查看两者的文档) ;;(另外,《实用Common Lisp编程》的4.8节也提到了两者的区别) (eql 3 3) ; => t @@ -400,12 +404,12 @@ nil ; 逻辑假,或者空列表 ;;; 条件判断语句 -(if t ; “测试”,即判断语句 - "this is true" ; “下一步”,即判断条件为真时求值的表达式 - "this is false") ; “否则”,即判断条件为假时求值的表达式 +(if t ; “test”,即判断语句 + "this is true" ; “then”,即判断条件为真时求值的表达式 + "this is false") ; “else”,即判断条件为假时求值的表达式 ; => "this is true" -;; 在“测试”(判断)语句中,所有非nil或者非()的值都被视为真值 +;; 在“test”(判断)语句中,所有非nil或者非()的值都被视为真值 (member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) (if (member 'Groucho '(Harpo Groucho Zeppo)) 'yep @@ -450,7 +454,7 @@ nil ; 逻辑假,或者空列表 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 6. 变异 +;; 6. 可变性 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 使用`setf`可以对一个已经存在的变量进行赋值; @@ -461,15 +465,13 @@ nil ; 逻辑假,或者空列表 ; => 2 -;; 所谓好的Lisp编码风格就是为了减少破坏性函数的使用,防止副作用的发生。 -;;(译者注:很惭愧,确实不明白原作者的“变异”到底指的是什么特性) -;;(我猜测应该是和词法变量、闭包等特性有关,还望高人指点、修正与完善) +;; 所谓好的Lisp编码风格就是为了减少使用破坏性函数,防止发生副作用。 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 7. 类与对象 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 我们就不写什么有关动物的类了,下面给出的是一个很“人文主义”的类 +;; 我们就不写什么有关动物的类了,下面给出的人力车的类 (defclass human-powered-conveyance () ((velocity @@ -481,7 +483,7 @@ nil ; 逻辑假,或者空列表 (:documentation "A human powered conveyance")) ;; `defclass`,后面接类名,以及超类列表 -;; 再接着是槽的列表(槽有点像Java里的字段),最后是一些可选的特性 +;; 再接着是槽的列表(槽有点像Java里的成员变量),最后是一些可选的特性 ;; 例如文档说明“:documentation” ;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类) @@ -545,8 +547,7 @@ nil ; 逻辑假,或者空列表 ;; 假设我们已经知道了效率值(“efficiency value”)和船桨数大概呈对数关系; ;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 -;; 下面是一个如何初始化实例的例子: -;; 构造它: +;; 下面是一个Common Lisp构造实例时初始化实例的例子: (defmethod initialize-instance :after ((object canoe) &rest args) (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) @@ -564,7 +565,7 @@ nil ; 逻辑假,或者空列表 ;; 宏可以让你扩展语法 ;; 例如,Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; -;; 如果按照“拼装者”的直觉来看,我们会这样写: +;; 如果按照汇编程序的直觉来看,我们会这样写: (defmacro while (condition &body body) "While `condition` is true, `body` is executed. -- cgit v1.2.3 From 91d1227001ef24276de66cc0f46572b202c00f4b Mon Sep 17 00:00:00 2001 From: cattail Date: Tue, 17 Dec 2013 17:32:35 +0800 Subject: [all/zh-cn] fix incorrect language-specific suffix Also change useless executable file mode. --- zh-cn/c-cn.html.markdown | 0 zh-cn/common-lisp-cn.html.markdown | 624 +++++++++++++++++++++++++++++++++++++ zh-cn/common-lisp.html.markdown | 624 ------------------------------------- zh-cn/elisp-cn.html.markdown | 0 zh-cn/git-cn.html.markdown | 0 zh-cn/go-cn.html.markdown | 284 +++++++++++++++++ zh-cn/go-zh.html.markdown | 284 ----------------- zh-cn/haskell-cn.html.markdown | 0 zh-cn/java-cn.html.markdown | 0 zh-cn/javascript-cn.html.markdown | 0 zh-cn/php-cn.html.markdown | 0 zh-cn/python-cn.html.markdown | 0 12 files changed, 908 insertions(+), 908 deletions(-) mode change 100755 => 100644 zh-cn/c-cn.html.markdown create mode 100644 zh-cn/common-lisp-cn.html.markdown delete mode 100644 zh-cn/common-lisp.html.markdown mode change 100755 => 100644 zh-cn/elisp-cn.html.markdown mode change 100755 => 100644 zh-cn/git-cn.html.markdown create mode 100644 zh-cn/go-cn.html.markdown delete mode 100644 zh-cn/go-zh.html.markdown mode change 100755 => 100644 zh-cn/haskell-cn.html.markdown mode change 100755 => 100644 zh-cn/java-cn.html.markdown mode change 100755 => 100644 zh-cn/javascript-cn.html.markdown mode change 100755 => 100644 zh-cn/php-cn.html.markdown mode change 100755 => 100644 zh-cn/python-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/common-lisp-cn.html.markdown b/zh-cn/common-lisp-cn.html.markdown new file mode 100644 index 00000000..f005dd58 --- /dev/null +++ b/zh-cn/common-lisp-cn.html.markdown @@ -0,0 +1,624 @@ +--- +language: "Common Lisp" +filename: commonlisp-cn.lisp +contributors: + - ["Paul Nathan", "https://github.com/pnathan"] +translators: + - ["Mac David", "http://macdavid313.com"] + - ["mut0u", "http://github.com/mut0u"] +lang: zh-cn +--- + +ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 +这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 + +免费的经典的入门书籍[《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) + +另外还有一本热门的近期出版的 +[Land of Lisp](http://landoflisp.com/). + +```scheme +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; 0. 语法 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 一般形式 + +;; Lisp有两个基本的语法单元:原子(atom),以及S-表达式。 +;; 一般的,一组S-表达式被称为“组合式”。 + +10 ; 一个原子; 它对自身进行求值 + +:THING ;同样是一个原子;它被求值为一个符号 :thing + +t ;还是一个原子,代表逻辑真值。 + +(+ 1 2 3 4) ; 一个S-表达式。 + +'(4 :foo t) ;同样是一个S-表达式。 + + +;;; 注释 + +;; 一个分号开头的注释表示仅用于此行(单行);两个分号开头的则表示一个所谓标准注释; +;; 三个分号开头的意味着段落注释; +;; 而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 + +#| 块注释 + 可以涵盖多行,而且... + #| + 他们可以被嵌套! + |# +|# + +;;; 运行环境 + +;; 有很多不同的Common Lisp的实现;并且大部分的实现是一致(可移植)的。 +;; 对于入门学习来说,CLISP是个不错的选择。 + +;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 + +;; 通常,使用一个文本编辑器和一个的“REPL”来开发Common Lisp; +;; (译者注:“REPL”指读取-求值-打印循环)。 +;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; 1. 基本数据类型以及运算符 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 符号 + +'foo ; => FOO 注意到这个符号被自动转换成大写了。 + +;; `intern`由一个给定的字符串而创建相应的符号 + +(intern "AAAA") ; => AAAA + +(intern "aaa") ; => |aaa| + +;;; 数字 +9999999999999999999999 ; 整型数 +#b111 ; 二进制 => 7 +#o111 ; 八进制 => 73 +#x111 ; 十六进制 => 273 +3.14159s0 ; 单精度 +3.14159d0 ; 双精度 +1/2 ; 分数 +#C(1 2) ; 复数 + + +;; 使用函数时,应当写成这样的形式:(f x y z ...); +;; 其中,f是一个函数(名),x, y, z为参数; +;; 如果你想创建一个“字面”意义上(即不求值)的列表, 只需使用单引号 ' , +;; 从而避免接下来的表达式被求值。即,只“引用”这个数据(而不求值)。 +'(+ 1 2) ; => (+ 1 2) +;; 你同样也可以手动地调用一个函数(译者注:即使用函数对象来调用函数): +(funcall #'+ 1 2 3) ; => 6 +;; 一些算术运算符 +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(mod 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) + + ;;; 布尔运算 +t ; 逻辑真(任何不是nil的值都被视为真值) +nil ; 逻辑假,或者空列表 +(not nil) ; => t +(and 0 t) ; => t +(or 0 nil) ; => 0 + + ;;; 字符 +#\A ; => #\A +#\λ ; => #\GREEK_SMALL_LETTER_LAMDA(希腊字母Lambda的小写) +#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA(Unicode形式的小写希腊字母Lambda) + +;;; 字符串被视为一个定长字符数组 +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ;反斜杠用作转义字符 + +;; 可以拼接字符串 +(concatenate 'string "Hello " "world!") ; => "Hello world!" + +;; 一个字符串也可被视作一个字符序列 +(elt "Apple" 0) ; => #\A + +;; `format`被用于格式化字符串 +(format nil "~a can be ~a" "strings" "formatted") + +;; 利用`format`打印到屏幕上是非常简单的 +;;(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 +(format t "Common Lisp is groovy. Dude.~%") + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2. 变量 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 你可以通过`defparameter`创建一个全局(动态)变量 +;; 变量名可以是除了:()[]{}",'`;#|\ 这些字符之外的其他任何字符 + +;; 动态变量名应该由*号开头与结尾! +;; (译者注:这个只是一个习惯) + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;; 你也可以使用Unicode字符: +(defparameter *AΛB* nil) + + +;; 访问一个在之前从未被绑定的变量是一种不规范的行为(即使依然是可能发生的); +;; 不要尝试那样做。 + + +;; 局部绑定:在(let ...)语句内,'me'被绑定到"dance with you"上。 +;; `let`总是返回在其作用域内最后一个表达式的值 + +(let ((me "dance with you")) + me) +;; => "dance with you" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 结构体和集合 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 结构体 +(defstruct dog name breed age) +(defparameter *rover* + (make-dog :name "rover" + :breed "collie" + :age 5)) +*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) + +(dog-p *rover*) ; => t ;; ewww) +(dog-name *rover*) ; => "rover" + +;; Dog-p,make-dog,以及 dog-name都是由defstruct创建的! + +;;; 点对单元(Pairs) +;; `cons`可用于生成一个点对单元, 利用`car`以及`cdr`将分别得到第一个和第二个元素 +(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB)) ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB)) ; => VERB + +;;; 列表 + +;; 所有列表都是由点对单元构成的“链表”。它以'nil'(或者'())作为列表的最后一个元素。 +(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) +;; `list`是一个生成列表的便利途径 +(list 1 2 3) ; => '(1 2 3) +;; 并且,一个引用也可被用做字面意义上的列表值 +'(1 2 3) ; => '(1 2 3) + +;; 同样的,依然可以用`cons`来添加一项到列表的起始位置 +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;; 而`append`也可用于连接两个列表 +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;; 或者使用`concatenate` + +(concatenate 'list '(1 2) '(3 4)) + +;; 列表是一种非常核心的数据类型,所以有非常多的处理列表的函数 +;; 例如: +(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4)) ; => nil +(some #'oddp '(1 2 3 4)) ; => T +(butlast '(subject verb object)) ; => (SUBJECT VERB) + + +;;; 向量 + +;; 向量的字面意义是一个定长数组 +;;(译者注:此处所谓“字面意义”,即指#(......)的形式,下文还会出现) +#(1 2 3) ; => #(1 2 3) + +;; 使用`concatenate`来将两个向量首尾连接在一起 +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + +;;; 数组 + +;; 向量和字符串只不过是数组的特例 + +;; 二维数组 + +(make-array (list 2 2)) + +;; (make-array '(2 2)) 也是可以的 + +; => #2A((0 0) (0 0)) + +(make-array (list 2 2 2)) + +; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;; 注意:数组的默认初始值是可以指定的 +;; 下面是如何指定的示例: + +(make-array '(2) :initial-element 'unset) + +; => #(UNSET UNSET) + +;; 若想获取数组[1][1][1]上的元素: +(aref (make-array (list 2 2 2)) 1 1 1) + +; => 0 + +;;; 变长向量 + +;; 若将变长向量打印出来,那么它的字面意义上的值和定长向量的是一样的 + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) + :adjustable t :fill-pointer t)) + +*adjvec* ; => #(1 2 3) + +;; 添加新的元素: +(vector-push-extend 4 *adjvec*) ; => 3 + +*adjvec* ; => #(1 2 3 4) + + + +;;; 不怎么严谨地说,集合也可被视为列表 + +(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 +(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) + +;; 然而,你可能想使用一个更好的数据结构,而并非一个链表 + +;;; 在Common Lisp中,“字典”和哈希表的实现是一样的。 + +;; 创建一个哈希表 +(defparameter *m* (make-hash-table)) + +;; 给定键,设置对应的值 +(setf (gethash 'a *m*) 1) + +;; (通过键)检索对应的值 +(gethash 'a *m*) ; => 1, t + +;; 注意此处有一细节:Common Lisp往往返回多个值。`gethash`返回的两个值是t,代表找到了这个元素;返回nil表示没有找到这个元素。 +;;(译者注:返回的第一个值表示给定的键所对应的值或者nil;) +;;(第二个是一个布尔值,表示在哈希表中是否存在这个给定的键) +;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil + +;; 由给定的键检索一个不存在的值,则返回nil +;;(译者注:这个nil是第一个nil,第二个nil其实是指该键在哈希表中也不存在) + (gethash 'd *m*) ;=> nil, nil + +;; 给定一个键,你可以指定其对应的默认值: +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;; 在此,让我们看一看怎样处理`gethash`的多个返回值。 + +(multiple-value-bind + (a b) + (gethash 'd *m*) + (list a b)) +; => (NIL NIL) + +(multiple-value-bind + (a b) + (gethash 'a *m*) + (list a b)) +; => (1 T) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3. 函数 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用`lambda`来创建一个匿名函数。 +;; 一个函数总是返回其形式体内最后一个表达式的值。 +;; 将一个函数对象打印出来后的形式是多种多样的... + +(lambda () "Hello World") ; => # + +;; 使用`funcall`来调用lambda函数 +(funcall (lambda () "Hello World")) ; => "Hello World" + +;; 或者使用`apply` +(apply (lambda () "Hello World") nil) ; => "Hello World" + +;; 显示地定义一个函数(译者注:即非匿名的) +(defun hello-world () + "Hello World") +(hello-world) ; => "Hello World" + +;; 刚刚上面函数名"hello-world"后的()其实是函数的参数列表 +(defun hello (name) + (format nil "Hello, ~a " name)) + +(hello "Steve") ; => "Hello, Steve" + +;; 函数可以有可选形参并且其默认值都为nil + +(defun hello (name &optional from) + (if from + (format t "Hello, ~a, from ~a" name from) + (format t "Hello, ~a" name))) + + (hello "Jim" "Alpacas") ;; => Hello, Jim, from Alpacas + +;; 你也可以指定那些可选形参的默认值 +(defun hello (name &optional (from "The world")) + (format t "Hello, ~a, from ~a" name from)) + +(hello "Steve") +; => Hello, Steve, from The world + +(hello "Steve" "the alpacas") +; => Hello, Steve, from the alpacas + + +;; 当然,你也可以设置所谓关键字形参; +;; 关键字形参往往比可选形参更具灵活性。 + +(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) + (format t "Hello, ~a ~a, from ~a" honorific name from)) + +(generalized-greeter "Jim") ; => Hello, Mx Jim, from the world + +(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") +; => Hello, Mr Jim, from the alpacas you met last summer + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 4. 等式 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 + +;; 若要比较数值是否等价,使用`=` +(= 3 3.0) ; => t +(= 2 1) ; => nil + +;; 若要比较对象的类型,则使用`eql` +;;(译者注:抱歉,翻译水平实在有限,下面是我个人的补充说明) +;;(`eq` 返回真,如果对象的内存地址相等) +;;(`eql` 返回真,如果两个对象内存地址相等,或者对象的类型相同,并且值相等) +;;(例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) +;;(想要弄清`eql`,其实有必要先了解`eq`) +;;([可以参考](http://stackoverflow.com/questions/547436/whats-the-difference-between-eq-eql-equal-and-equalp-in-common-lisp)) +;;(可以去CLHS上分别查看两者的文档) +;;(另外,《实用Common Lisp编程》的4.8节也提到了两者的区别) +(eql 3 3) ; => t +(eql 3 3.0) ; => nil +(eql (list 3) (list 3)) ; => nil + +;; 对于列表、字符串、以及位向量,使用`equal` +(equal (list 'a 'b) (list 'a 'b)) ; => t +(equal (list 'a 'b) (list 'b 'a)) ; => nil + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 5. 控制流 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; 条件判断语句 + +(if t ; “test”,即判断语句 + "this is true" ; “then”,即判断条件为真时求值的表达式 + "this is false") ; “else”,即判断条件为假时求值的表达式 +; => "this is true" + +;; 在“test”(判断)语句中,所有非nil或者非()的值都被视为真值 +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'YEP + +;; `cond`将一系列测试语句串联起来,并对相应的表达式求值 +(cond ((> 2 2) (error "wrong!")) + ((< 2 2) (error "wrong again!")) + (t 'ok)) ; => 'OK + +;; 对于给定值的数据类型,`typecase`会做出相应地判断 +(typecase 1 + (string :string) + (integer :int)) + +; => :int + +;;; 迭代 + +;; 当然,递归是肯定被支持的: + +(defun walker (n) + (if (zerop n) + :walked + (walker (1- n)))) + +(walker) ; => :walked + +;; 而大部分场合下,我们使用`DOLIST`或者`LOOP`来进行迭代 + + +(dolist (i '(1 2 3 4)) + (format t "~a" i)) + +; => 1234 + +(loop for i from 0 below 10 + collect i) + +; => (0 1 2 3 4 5 6 7 8 9) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 6. 可变性 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 使用`setf`可以对一个已经存在的变量进行赋值; +;; 事实上,刚刚在哈希表的例子中我们已经示范过了。 + +(let ((variable 10)) + (setf variable 2)) + ; => 2 + + +;; 所谓好的Lisp编码风格就是为了减少使用破坏性函数,防止发生副作用。 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 7. 类与对象 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 我们就不写什么有关动物的类了,下面给出的人力车的类 + +(defclass human-powered-conveyance () + ((velocity + :accessor velocity + :initarg :velocity) + (average-efficiency + :accessor average-efficiency + :initarg :average-efficiency)) + (:documentation "A human powered conveyance")) + +;; `defclass`,后面接类名,以及超类列表 +;; 再接着是槽的列表(槽有点像Java里的成员变量),最后是一些可选的特性 +;; 例如文档说明“:documentation” + +;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类) +;; 这种默认行为是可以改变的,但你最好有一定的基础并且知道自己到底在干什么; +;; 参阅《The Art of the Metaobject Protocol》来了解更多信息。 + +(defclass bicycle (human-powered-conveyance) + ((wheel-size + :accessor wheel-size + :initarg :wheel-size + :documentation "Diameter of the wheel.") + (height + :accessor height + :initarg :height))) + +(defclass recumbent (bicycle) + ((chain-type + :accessor chain-type + :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) + ((number-of-rowers + :accessor number-of-rowers + :initarg :number-of-rowers))) + + +;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`后结果如下: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +; [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #: +; Documentation: +; A human powered conveyance +; Direct superclasses: STANDARD-OBJECT +; Direct subclasses: UNICYCLE, BICYCLE, CANOE +; Not yet finalized. +; Direct slots: +; VELOCITY +; Readers: VELOCITY +; Writers: (SETF VELOCITY) +; AVERAGE-EFFICIENCY +; Readers: AVERAGE-EFFICIENCY +; Writers: (SETF AVERAGE-EFFICIENCY) + +;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。 + +;; 若要定义一个方法; +;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi + +(defmethod circumference ((object bicycle)) + (* pi (wheel-size object))) + +;; pi在Common Lisp中已经是一个内置的常量。 + +;; 假设我们已经知道了效率值(“efficiency value”)和船桨数大概呈对数关系; +;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 + +;; 下面是一个Common Lisp构造实例时初始化实例的例子: + +(defmethod initialize-instance :after ((object canoe) &rest args) + (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) + +;; 接着初构造一个实例并检查平均效率... + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 8. 宏 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; 宏可以让你扩展语法 + +;; 例如,Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; +;; 如果按照汇编程序的直觉来看,我们会这样写: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. + +`condition` is tested prior to each execution of `body`" + (let ((block-name (gensym))) + `(tagbody + (unless ,condition + (go ,block-name)) + (progn + ,@body) + ,block-name))) + +;; 让我们来看看它的高级版本: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. + +`condition` is tested prior to each execution of `body`" + `(loop while ,condition + do + (progn + ,@body))) + +;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的; +;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 + +;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; +;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 +;; 逗号“,”意味着解除引用(unquote,即开始求值); +;; “@”符号则表示将当前的参数插入到当前整个列表中。 +;;(译者注:要想真正用好、用对这三个符号,需要下一番功夫) +;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的) +;;(建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) + +;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 +;; 这样做是因为,宏是在编译期展开的 +;; 而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 + +;; 可以去《实用 Common Lisp 编程》中阅读更多有关宏的内容。 +``` + + +## 拓展阅读 + +[继续阅读《实用 Common Lisp 编程》一书](http://www.gigamonkeys.com/book/) + + +## 致谢 + +非常感谢Scheme社区的人们,我基于他们的成果得以迅速的写出这篇有关Common Lisp的快速入门 +同时也感谢 +- [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 + +##译者寄语 +“祝福那些将思想镶嵌在重重括号之内的人们。” diff --git a/zh-cn/common-lisp.html.markdown b/zh-cn/common-lisp.html.markdown deleted file mode 100644 index f005dd58..00000000 --- a/zh-cn/common-lisp.html.markdown +++ /dev/null @@ -1,624 +0,0 @@ ---- -language: "Common Lisp" -filename: commonlisp-cn.lisp -contributors: - - ["Paul Nathan", "https://github.com/pnathan"] -translators: - - ["Mac David", "http://macdavid313.com"] - - ["mut0u", "http://github.com/mut0u"] -lang: zh-cn ---- - -ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范式的编程语言。 -这门语言也经常被引用作“可编程的编程语言”(可以写代码的代码)。 - -免费的经典的入门书籍[《实用 Common Lisp 编程》](http://www.gigamonkeys.com/book/) - -另外还有一本热门的近期出版的 -[Land of Lisp](http://landoflisp.com/). - -```scheme -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; 0. 语法 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; 一般形式 - -;; Lisp有两个基本的语法单元:原子(atom),以及S-表达式。 -;; 一般的,一组S-表达式被称为“组合式”。 - -10 ; 一个原子; 它对自身进行求值 - -:THING ;同样是一个原子;它被求值为一个符号 :thing - -t ;还是一个原子,代表逻辑真值。 - -(+ 1 2 3 4) ; 一个S-表达式。 - -'(4 :foo t) ;同样是一个S-表达式。 - - -;;; 注释 - -;; 一个分号开头的注释表示仅用于此行(单行);两个分号开头的则表示一个所谓标准注释; -;; 三个分号开头的意味着段落注释; -;; 而四个分号开头的注释用于文件头注释(译者注:即对该文件的说明)。 - -#| 块注释 - 可以涵盖多行,而且... - #| - 他们可以被嵌套! - |# -|# - -;;; 运行环境 - -;; 有很多不同的Common Lisp的实现;并且大部分的实现是一致(可移植)的。 -;; 对于入门学习来说,CLISP是个不错的选择。 - -;; 可以通过QuickLisp.org's Quicklisp系统可以管理你的库。 - -;; 通常,使用一个文本编辑器和一个的“REPL”来开发Common Lisp; -;; (译者注:“REPL”指读取-求值-打印循环)。 -;; “REPL”允许对程序进行交互式的运行、调试,就好像在系统中这是一场“现场直播”。 - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; 1. 基本数据类型以及运算符 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; 符号 - -'foo ; => FOO 注意到这个符号被自动转换成大写了。 - -;; `intern`由一个给定的字符串而创建相应的符号 - -(intern "AAAA") ; => AAAA - -(intern "aaa") ; => |aaa| - -;;; 数字 -9999999999999999999999 ; 整型数 -#b111 ; 二进制 => 7 -#o111 ; 八进制 => 73 -#x111 ; 十六进制 => 273 -3.14159s0 ; 单精度 -3.14159d0 ; 双精度 -1/2 ; 分数 -#C(1 2) ; 复数 - - -;; 使用函数时,应当写成这样的形式:(f x y z ...); -;; 其中,f是一个函数(名),x, y, z为参数; -;; 如果你想创建一个“字面”意义上(即不求值)的列表, 只需使用单引号 ' , -;; 从而避免接下来的表达式被求值。即,只“引用”这个数据(而不求值)。 -'(+ 1 2) ; => (+ 1 2) -;; 你同样也可以手动地调用一个函数(译者注:即使用函数对象来调用函数): -(funcall #'+ 1 2 3) ; => 6 -;; 一些算术运算符 -(+ 1 1) ; => 2 -(- 8 1) ; => 7 -(* 10 2) ; => 20 -(expt 2 3) ; => 8 -(mod 5 2) ; => 1 -(/ 35 5) ; => 7 -(/ 1 3) ; => 1/3 -(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) - - ;;; 布尔运算 -t ; 逻辑真(任何不是nil的值都被视为真值) -nil ; 逻辑假,或者空列表 -(not nil) ; => t -(and 0 t) ; => t -(or 0 nil) ; => 0 - - ;;; 字符 -#\A ; => #\A -#\λ ; => #\GREEK_SMALL_LETTER_LAMDA(希腊字母Lambda的小写) -#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA(Unicode形式的小写希腊字母Lambda) - -;;; 字符串被视为一个定长字符数组 -"Hello, world!" -"Benjamin \"Bugsy\" Siegel" ;反斜杠用作转义字符 - -;; 可以拼接字符串 -(concatenate 'string "Hello " "world!") ; => "Hello world!" - -;; 一个字符串也可被视作一个字符序列 -(elt "Apple" 0) ; => #\A - -;; `format`被用于格式化字符串 -(format nil "~a can be ~a" "strings" "formatted") - -;; 利用`format`打印到屏幕上是非常简单的 -;;(译者注:注意到第二个参数是t,不同于刚刚的nil);~% 代表换行符 -(format t "Common Lisp is groovy. Dude.~%") - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 2. 变量 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 你可以通过`defparameter`创建一个全局(动态)变量 -;; 变量名可以是除了:()[]{}",'`;#|\ 这些字符之外的其他任何字符 - -;; 动态变量名应该由*号开头与结尾! -;; (译者注:这个只是一个习惯) - -(defparameter *some-var* 5) -*some-var* ; => 5 - -;; 你也可以使用Unicode字符: -(defparameter *AΛB* nil) - - -;; 访问一个在之前从未被绑定的变量是一种不规范的行为(即使依然是可能发生的); -;; 不要尝试那样做。 - - -;; 局部绑定:在(let ...)语句内,'me'被绑定到"dance with you"上。 -;; `let`总是返回在其作用域内最后一个表达式的值 - -(let ((me "dance with you")) - me) -;; => "dance with you" - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 3. 结构体和集合 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 结构体 -(defstruct dog name breed age) -(defparameter *rover* - (make-dog :name "rover" - :breed "collie" - :age 5)) -*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) - -(dog-p *rover*) ; => t ;; ewww) -(dog-name *rover*) ; => "rover" - -;; Dog-p,make-dog,以及 dog-name都是由defstruct创建的! - -;;; 点对单元(Pairs) -;; `cons`可用于生成一个点对单元, 利用`car`以及`cdr`将分别得到第一个和第二个元素 -(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) -(car (cons 'SUBJECT 'VERB)) ; => SUBJECT -(cdr (cons 'SUBJECT 'VERB)) ; => VERB - -;;; 列表 - -;; 所有列表都是由点对单元构成的“链表”。它以'nil'(或者'())作为列表的最后一个元素。 -(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) -;; `list`是一个生成列表的便利途径 -(list 1 2 3) ; => '(1 2 3) -;; 并且,一个引用也可被用做字面意义上的列表值 -'(1 2 3) ; => '(1 2 3) - -;; 同样的,依然可以用`cons`来添加一项到列表的起始位置 -(cons 4 '(1 2 3)) ; => '(4 1 2 3) - -;; 而`append`也可用于连接两个列表 -(append '(1 2) '(3 4)) ; => '(1 2 3 4) - -;; 或者使用`concatenate` - -(concatenate 'list '(1 2) '(3 4)) - -;; 列表是一种非常核心的数据类型,所以有非常多的处理列表的函数 -;; 例如: -(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) -(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) -(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) -(every #'evenp '(1 2 3 4)) ; => nil -(some #'oddp '(1 2 3 4)) ; => T -(butlast '(subject verb object)) ; => (SUBJECT VERB) - - -;;; 向量 - -;; 向量的字面意义是一个定长数组 -;;(译者注:此处所谓“字面意义”,即指#(......)的形式,下文还会出现) -#(1 2 3) ; => #(1 2 3) - -;; 使用`concatenate`来将两个向量首尾连接在一起 -(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) - -;;; 数组 - -;; 向量和字符串只不过是数组的特例 - -;; 二维数组 - -(make-array (list 2 2)) - -;; (make-array '(2 2)) 也是可以的 - -; => #2A((0 0) (0 0)) - -(make-array (list 2 2 2)) - -; => #3A(((0 0) (0 0)) ((0 0) (0 0))) - -;; 注意:数组的默认初始值是可以指定的 -;; 下面是如何指定的示例: - -(make-array '(2) :initial-element 'unset) - -; => #(UNSET UNSET) - -;; 若想获取数组[1][1][1]上的元素: -(aref (make-array (list 2 2 2)) 1 1 1) - -; => 0 - -;;; 变长向量 - -;; 若将变长向量打印出来,那么它的字面意义上的值和定长向量的是一样的 - -(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) - :adjustable t :fill-pointer t)) - -*adjvec* ; => #(1 2 3) - -;; 添加新的元素: -(vector-push-extend 4 *adjvec*) ; => 3 - -*adjvec* ; => #(1 2 3 4) - - - -;;; 不怎么严谨地说,集合也可被视为列表 - -(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) -(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 -(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) -(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) - -;; 然而,你可能想使用一个更好的数据结构,而并非一个链表 - -;;; 在Common Lisp中,“字典”和哈希表的实现是一样的。 - -;; 创建一个哈希表 -(defparameter *m* (make-hash-table)) - -;; 给定键,设置对应的值 -(setf (gethash 'a *m*) 1) - -;; (通过键)检索对应的值 -(gethash 'a *m*) ; => 1, t - -;; 注意此处有一细节:Common Lisp往往返回多个值。`gethash`返回的两个值是t,代表找到了这个元素;返回nil表示没有找到这个元素。 -;;(译者注:返回的第一个值表示给定的键所对应的值或者nil;) -;;(第二个是一个布尔值,表示在哈希表中是否存在这个给定的键) -;; 例如,如果可以找到给定的键所对应的值,则返回一个t,否则返回nil - -;; 由给定的键检索一个不存在的值,则返回nil -;;(译者注:这个nil是第一个nil,第二个nil其实是指该键在哈希表中也不存在) - (gethash 'd *m*) ;=> nil, nil - -;; 给定一个键,你可以指定其对应的默认值: -(gethash 'd *m* :not-found) ; => :NOT-FOUND - -;; 在此,让我们看一看怎样处理`gethash`的多个返回值。 - -(multiple-value-bind - (a b) - (gethash 'd *m*) - (list a b)) -; => (NIL NIL) - -(multiple-value-bind - (a b) - (gethash 'a *m*) - (list a b)) -; => (1 T) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 3. 函数 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 使用`lambda`来创建一个匿名函数。 -;; 一个函数总是返回其形式体内最后一个表达式的值。 -;; 将一个函数对象打印出来后的形式是多种多样的... - -(lambda () "Hello World") ; => # - -;; 使用`funcall`来调用lambda函数 -(funcall (lambda () "Hello World")) ; => "Hello World" - -;; 或者使用`apply` -(apply (lambda () "Hello World") nil) ; => "Hello World" - -;; 显示地定义一个函数(译者注:即非匿名的) -(defun hello-world () - "Hello World") -(hello-world) ; => "Hello World" - -;; 刚刚上面函数名"hello-world"后的()其实是函数的参数列表 -(defun hello (name) - (format nil "Hello, ~a " name)) - -(hello "Steve") ; => "Hello, Steve" - -;; 函数可以有可选形参并且其默认值都为nil - -(defun hello (name &optional from) - (if from - (format t "Hello, ~a, from ~a" name from) - (format t "Hello, ~a" name))) - - (hello "Jim" "Alpacas") ;; => Hello, Jim, from Alpacas - -;; 你也可以指定那些可选形参的默认值 -(defun hello (name &optional (from "The world")) - (format t "Hello, ~a, from ~a" name from)) - -(hello "Steve") -; => Hello, Steve, from The world - -(hello "Steve" "the alpacas") -; => Hello, Steve, from the alpacas - - -;; 当然,你也可以设置所谓关键字形参; -;; 关键字形参往往比可选形参更具灵活性。 - -(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) - (format t "Hello, ~a ~a, from ~a" honorific name from)) - -(generalized-greeter "Jim") ; => Hello, Mx Jim, from the world - -(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") -; => Hello, Mr Jim, from the alpacas you met last summer - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 4. 等式 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; Common Lisp具有一个十分复杂的用于判断等价的系统,下面只是其中一部分的例子 - -;; 若要比较数值是否等价,使用`=` -(= 3 3.0) ; => t -(= 2 1) ; => nil - -;; 若要比较对象的类型,则使用`eql` -;;(译者注:抱歉,翻译水平实在有限,下面是我个人的补充说明) -;;(`eq` 返回真,如果对象的内存地址相等) -;;(`eql` 返回真,如果两个对象内存地址相等,或者对象的类型相同,并且值相等) -;;(例如同为整形数或浮点数,并且他们的值相等时,二者`eql`等价) -;;(想要弄清`eql`,其实有必要先了解`eq`) -;;([可以参考](http://stackoverflow.com/questions/547436/whats-the-difference-between-eq-eql-equal-and-equalp-in-common-lisp)) -;;(可以去CLHS上分别查看两者的文档) -;;(另外,《实用Common Lisp编程》的4.8节也提到了两者的区别) -(eql 3 3) ; => t -(eql 3 3.0) ; => nil -(eql (list 3) (list 3)) ; => nil - -;; 对于列表、字符串、以及位向量,使用`equal` -(equal (list 'a 'b) (list 'a 'b)) ; => t -(equal (list 'a 'b) (list 'b 'a)) ; => nil - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 5. 控制流 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;; 条件判断语句 - -(if t ; “test”,即判断语句 - "this is true" ; “then”,即判断条件为真时求值的表达式 - "this is false") ; “else”,即判断条件为假时求值的表达式 -; => "this is true" - -;; 在“test”(判断)语句中,所有非nil或者非()的值都被视为真值 -(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) -(if (member 'Groucho '(Harpo Groucho Zeppo)) - 'yep - 'nope) -; => 'YEP - -;; `cond`将一系列测试语句串联起来,并对相应的表达式求值 -(cond ((> 2 2) (error "wrong!")) - ((< 2 2) (error "wrong again!")) - (t 'ok)) ; => 'OK - -;; 对于给定值的数据类型,`typecase`会做出相应地判断 -(typecase 1 - (string :string) - (integer :int)) - -; => :int - -;;; 迭代 - -;; 当然,递归是肯定被支持的: - -(defun walker (n) - (if (zerop n) - :walked - (walker (1- n)))) - -(walker) ; => :walked - -;; 而大部分场合下,我们使用`DOLIST`或者`LOOP`来进行迭代 - - -(dolist (i '(1 2 3 4)) - (format t "~a" i)) - -; => 1234 - -(loop for i from 0 below 10 - collect i) - -; => (0 1 2 3 4 5 6 7 8 9) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 6. 可变性 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 使用`setf`可以对一个已经存在的变量进行赋值; -;; 事实上,刚刚在哈希表的例子中我们已经示范过了。 - -(let ((variable 10)) - (setf variable 2)) - ; => 2 - - -;; 所谓好的Lisp编码风格就是为了减少使用破坏性函数,防止发生副作用。 - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 7. 类与对象 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 我们就不写什么有关动物的类了,下面给出的人力车的类 - -(defclass human-powered-conveyance () - ((velocity - :accessor velocity - :initarg :velocity) - (average-efficiency - :accessor average-efficiency - :initarg :average-efficiency)) - (:documentation "A human powered conveyance")) - -;; `defclass`,后面接类名,以及超类列表 -;; 再接着是槽的列表(槽有点像Java里的成员变量),最后是一些可选的特性 -;; 例如文档说明“:documentation” - -;; 如果超类列表为空,则默认该类继承于“standard-object”类(standard-object又是T的子类) -;; 这种默认行为是可以改变的,但你最好有一定的基础并且知道自己到底在干什么; -;; 参阅《The Art of the Metaobject Protocol》来了解更多信息。 - -(defclass bicycle (human-powered-conveyance) - ((wheel-size - :accessor wheel-size - :initarg :wheel-size - :documentation "Diameter of the wheel.") - (height - :accessor height - :initarg :height))) - -(defclass recumbent (bicycle) - ((chain-type - :accessor chain-type - :initarg :chain-type))) - -(defclass unicycle (human-powered-conveyance) nil) - -(defclass canoe (human-powered-conveyance) - ((number-of-rowers - :accessor number-of-rowers - :initarg :number-of-rowers))) - - -;; 在REPL中对human-powered-conveyance类调用`DESCRIBE`后结果如下: - -(describe 'human-powered-conveyance) - -; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE -; [symbol] -; -; HUMAN-POWERED-CONVEYANCE names the standard-class #: -; Documentation: -; A human powered conveyance -; Direct superclasses: STANDARD-OBJECT -; Direct subclasses: UNICYCLE, BICYCLE, CANOE -; Not yet finalized. -; Direct slots: -; VELOCITY -; Readers: VELOCITY -; Writers: (SETF VELOCITY) -; AVERAGE-EFFICIENCY -; Readers: AVERAGE-EFFICIENCY -; Writers: (SETF AVERAGE-EFFICIENCY) - -;; 注意到这些有用的返回信息——Common Lisp一直是一个交互式的系统。 - -;; 若要定义一个方法; -;; 先让我们注意到我们计算自行车轮子周长时使用了这样一个公式:C = d * pi - -(defmethod circumference ((object bicycle)) - (* pi (wheel-size object))) - -;; pi在Common Lisp中已经是一个内置的常量。 - -;; 假设我们已经知道了效率值(“efficiency value”)和船桨数大概呈对数关系; -;; 那么效率值的定义应当在构造器/初始化过程中就被完成。 - -;; 下面是一个Common Lisp构造实例时初始化实例的例子: - -(defmethod initialize-instance :after ((object canoe) &rest args) - (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) - -;; 接着初构造一个实例并检查平均效率... - -(average-efficiency (make-instance 'canoe :number-of-rowers 15)) -; => 2.7725887 - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 8. 宏 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;; 宏可以让你扩展语法 - -;; 例如,Common Lisp并没有自带WHILE循环——所以让我们自己来为他添加一个; -;; 如果按照汇编程序的直觉来看,我们会这样写: - -(defmacro while (condition &body body) - "While `condition` is true, `body` is executed. - -`condition` is tested prior to each execution of `body`" - (let ((block-name (gensym))) - `(tagbody - (unless ,condition - (go ,block-name)) - (progn - ,@body) - ,block-name))) - -;; 让我们来看看它的高级版本: - -(defmacro while (condition &body body) - "While `condition` is true, `body` is executed. - -`condition` is tested prior to each execution of `body`" - `(loop while ,condition - do - (progn - ,@body))) - -;; 然而,在一个比较现代化的编译环境下,这样的WHILE是没有必要的; -;; LOOP形式的循环和这个WHILE同样的好,并且更易于阅读。 - -;; 注意到反引号'`',逗号','以及'@'符号,这三个符号; -;; 反引号'`'是一种所谓“quasiquote”的引用类型的运算符,有了它,之后的逗号“,”才有意义。 -;; 逗号“,”意味着解除引用(unquote,即开始求值); -;; “@”符号则表示将当前的参数插入到当前整个列表中。 -;;(译者注:要想真正用好、用对这三个符号,需要下一番功夫) -;;(甚至光看《实用 Common Lisp 编程》中关于宏的介绍都是不够的) -;;(建议再去读一读Paul Graham的两本著作《ANSI Common Lisp》和《On Lisp》) - -;; 函数`gensym`创建一个唯一的符号——这个符号确保不会出现在其他任何地方。 -;; 这样做是因为,宏是在编译期展开的 -;; 而在宏中声明的变量名极有可能和常规代码中使用的变量名发生冲突。 - -;; 可以去《实用 Common Lisp 编程》中阅读更多有关宏的内容。 -``` - - -## 拓展阅读 - -[继续阅读《实用 Common Lisp 编程》一书](http://www.gigamonkeys.com/book/) - - -## 致谢 - -非常感谢Scheme社区的人们,我基于他们的成果得以迅速的写出这篇有关Common Lisp的快速入门 -同时也感谢 -- [Paul Khuong](https://github.com/pkhuong) ,他提出了很多有用的点评。 - -##译者寄语 -“祝福那些将思想镶嵌在重重括号之内的人们。” diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown new file mode 100644 index 00000000..7cc9c171 --- /dev/null +++ b/zh-cn/go-cn.html.markdown @@ -0,0 +1,284 @@ +--- +language: Go +lang: zh-cn +filename: learngo-cn.go +contributors: + - ["Sonia Keys", "https://github.com/soniakeys"] + - ["pantaovay", "https://github.com/pantaovay"] +--- + +发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 + +Go拥有命令式语言的静态类型,编译很快,执行也很快,同时加入了对于目前多核CPU的并发计算支持,也有相应的特性来实现大规模编程。 + +Go语言有非常棒的标准库,还有一个充满热情的社区。 + +```go +// 单行注释 +/* 多行 + 注释 */ + +// 导入包的子句在每个源文件的开头。 +// Main比较特殊,它用来声明可执行文件,而不是一个库。 +package main + +// Import语句声明了当前文件引用的包。 +import ( + "fmt" // Go语言标准库中的包 + "net/http" // 一个web服务器包 + "strconv" // 字符串转换 +) + +// 函数声明:Main是程序执行的入口。 +// 不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 +func main() { + // 往标准输出打印一行。 + // 用包名fmt限制打印函数。 + fmt.Println("Hello world!") + + // 调用当前包的另一个函数。 + beyondHello() +} + +// 函数可以在括号里加参数。 +// 如果没有参数的话,也需要一个空括号。 +func beyondHello() { + var x int // 变量声明,变量必须在使用之前声明。 + x = 3 // 变量赋值。 + // 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。 + y := 4 + sum, prod := learnMultiple(x, y) // 多个返回变量的函数 + fmt.Println("sum:", sum, "prod:", prod) // 简单输出 + learnTypes() // 少于y分钟,学的更多! +} + +// 多变量和多返回值的函数 +func learnMultiple(x, y int) (sum, prod int) { + return x + y, x * y // 返回两个值 +} + +// 内置变量类型和关键词 +func learnTypes() { + // 短声明给你所想。 + s := "Learn Go!" // String类型 + + s2 := `A "raw" string literal +can include line breaks.` // 同样是String类型 + + // 非ascii字符。Go使用UTF-8编码。 + g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 + + f := 3.14195 // float64类型,IEEE-754 64位浮点数 + c := 3 + 4i // complex128类型,内部使用两个float64表示 + + // Var变量可以直接初始化。 + var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度 + var pi float32 = 22. / 7 + + // 字符转换 + n := byte('\n') // byte是uint8的别名 + + // 数组类型编译的时候大小固定。 + var a4 [4] int // 有4个int变量的数组,初始为0 + a3 := [...]int{3, 1, 5} // 有3个int变量的数组,同时进行了初始化 + + // Slice 有动态大小。Array和Slice各有千秋,但是使用slice的地方更多些。 + s3 := []int{4, 5, 9} // 和a3相比,这里没有省略号 + s4 := make([]int, 4) // 分配一个有4个int型变量的slice,全部被初始化为0 + + var d2 [][]float64 // 声明而已,什么都没有分配 + bs := []byte("a slice") // 类型转换的语法 + + p, q := learnMemory() // 声明p,q为int型变量的指针 + fmt.Println(*p, *q) // * 取值 + + // Map是动态可增长关联数组,和其他语言中的hash或者字典相似。 + m := map[string]int{"three": 3, "four": 4} + m["one"] = 1 + + // 在Go语言中未使用的变量在编译的时候会报错,而不是warning。 + // 下划线 _ 可以使你“使用”一个变量,但是丢弃它的值。 + _,_,_,_,_,_,_,_,_ = s2, g, f, u, pi, n, a3, s4, bs + // 输出变量 + fmt.Println(s, c, a4, s3, d2, m) + + learnFlowControl() // 回到流程控制 +} + +// Go全面支持垃圾回收。Go有指针,但是不支持指针运算。 +// 你会因为空指针而犯错,但是不会因为增加指针而犯错。 +func learnMemory() (p, q *int) { + // 返回int型变量指针p和q + p = new(int) // 内置函数new分配内存 + // 自动将分配的int赋值0,p不再是空的了。 + s := make([]int, 20) // 给20个int变量分配一块内存 + s[3] = 7 // 赋值 + r := -2 // 声明另一个局部变量 + return &s[3], &r // & 取址 +} + +func expensiveComputation() int { + return 1e6 +} + +func learnFlowControl() { + // If需要花括号,括号就免了 + if true { + fmt.Println("told ya") + } + // 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了, + // 也不用容忍被人的代码风格。 + if false { + // pout + } else { + // gloat + } + // 如果太多嵌套的if语句,推荐使用switch + x := 1 + switch x { + case 0: + case 1: + // 隐式调用break语句,匹配上一个即停止 + case 2: + // 不会运行 + } + // 和if一样,for也不用括号 + for x := 0; x < 3; x++ { // ++ 自增 + fmt.Println("iteration", x) + } + // x在这里还是1。为什么? + + // for 是go里唯一的循环关键字,不过它有很多变种 + for { // 无限循环 + break // 骗你的 + continue // 不会运行的 + } + // 和for一样,if中的:=先给y赋值,然后再和x作比较。 + if y := expensiveComputation(); y > x { + x = y + } + // 闭包函数 + xBig := func() bool { + return x > 100 // x是上面声明的变量引用 + } + fmt.Println("xBig:", xBig()) // true (上面把y赋给x了) + x /= 1e5 // x变成10 + fmt.Println("xBig:", xBig()) // 现在是false + + // 当你需要goto的时候,你会爱死它的! + goto love +love: + + learnInterfaces() // 好东西来了! +} + +// 定义Stringer为一个接口类型,有一个方法String +type Stringer interface { + String() string +} + +// 定义pair为一个结构体,有x和y两个int型变量。 +type pair struct { + x, y int +} + +// 定义pair类型的方法,实现Stringer接口。 +func (p pair) String() string { // p被叫做“接收器” + // Sprintf是fmt包中的另一个公有函数。 + // 用 . 调用p中的元素。 + return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func learnInterfaces() { + // 花括号用来定义结构体变量,:=在这里将一个结构体变量赋值给p。 + p := pair{3, 4} + fmt.Println(p.String()) // 调用pair类型p的String方法 + var i Stringer // 声明i为Stringer接口类型 + i = p // 有效!因为p实现了Stringer接口(类似java中的塑型) + // 调用i的String方法,输出和上面一样 + fmt.Println(i.String()) + + // fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。 + // (类似java中的序列化) + fmt.Println(p) // 输出和上面一样,自动调用String函数。 + fmt.Println(i) // 输出和上面一样。 + + learnErrorHandling() +} + +func learnErrorHandling() { + // ", ok"用来判断有没有正常工作 + m := map[int]string{3: "three", 4: "four"} + if x, ok := m[1]; !ok { // ok 为false,因为m中没有1 + fmt.Println("no one there") + } else { + fmt.Print(x) // 如果x在map中的话,x就是那个值喽。 + } + // 错误可不只是ok,它还可以给出关于问题的更多细节。 + if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value + // 输出"strconv.ParseInt: parsing "non-int": invalid syntax" + fmt.Println(err) + } + // 待会再说接口吧。同时, + learnConcurrency() +} + +// c是channel类型,一个并发安全的通信对象。 +func inc(i int, c chan int) { + c <- i + 1 // <-把右边的发送到左边的channel。 +} + +// 我们将用inc函数来并发地增加一些数字。 +func learnConcurrency() { + // 用make来声明一个slice,make会分配和初始化slice,map和channel。 + c := make(chan int) + // 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。 + // 三个都被发送到同一个channel。 + go inc(0, c) // go is a statement that starts a new goroutine. + go inc(10, c) + go inc(-805, c) + // 从channel中独处结果并打印。 + // 打印出什么东西是不可预知的。 + fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 + + cs := make(chan string) // 操作string的channel + cc := make(chan chan string) // 操作channel的channel + go func() { c <- 84 }() // 开始一个goroutine来发送一个新的数字 + go func() { cs <- "wordy" }() // 发送给cs + // Select类似于switch,但是每个case包括一个channel操作。 + // 它随机选择一个准备好通讯的case。 + select { + case i := <-c: // 从channel接收的值可以赋给其他变量 + fmt.Println("it's a", i) + case <-cs: // 或者直接丢弃 + fmt.Println("it's a string") + case <-cc: // 空的,还没作好通讯的准备 + fmt.Println("didn't happen.") + } + // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 + + learnWebProgramming() // Go很适合web编程,我知道你也想学! +} + +// http包中的一个简单的函数就可以开启web服务器。 +func learnWebProgramming() { + // ListenAndServe第一个参数指定了监听端口,第二个参数是一个接口,特定是http.Handler。 + err := http.ListenAndServe(":8080", pair{}) + fmt.Println(err) // 不要无视错误。 +} + +// 使pair实现http.Handler接口的ServeHTTP方法。 +func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // 使用http.ResponseWriter返回数据 + w.Write([]byte("You learned Go in Y minutes!")) +} +``` + +## 更进一步 + +Go的根源在[Go官方网站](http://golang.org/)。 +在那里你可以学习入门教程,通过浏览器交互式地学习,而且可以读到很多东西。 + +强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.) + +学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了! diff --git a/zh-cn/go-zh.html.markdown b/zh-cn/go-zh.html.markdown deleted file mode 100644 index 7cc9c171..00000000 --- a/zh-cn/go-zh.html.markdown +++ /dev/null @@ -1,284 +0,0 @@ ---- -language: Go -lang: zh-cn -filename: learngo-cn.go -contributors: - - ["Sonia Keys", "https://github.com/soniakeys"] - - ["pantaovay", "https://github.com/pantaovay"] ---- - -发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 - -Go拥有命令式语言的静态类型,编译很快,执行也很快,同时加入了对于目前多核CPU的并发计算支持,也有相应的特性来实现大规模编程。 - -Go语言有非常棒的标准库,还有一个充满热情的社区。 - -```go -// 单行注释 -/* 多行 - 注释 */ - -// 导入包的子句在每个源文件的开头。 -// Main比较特殊,它用来声明可执行文件,而不是一个库。 -package main - -// Import语句声明了当前文件引用的包。 -import ( - "fmt" // Go语言标准库中的包 - "net/http" // 一个web服务器包 - "strconv" // 字符串转换 -) - -// 函数声明:Main是程序执行的入口。 -// 不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 -func main() { - // 往标准输出打印一行。 - // 用包名fmt限制打印函数。 - fmt.Println("Hello world!") - - // 调用当前包的另一个函数。 - beyondHello() -} - -// 函数可以在括号里加参数。 -// 如果没有参数的话,也需要一个空括号。 -func beyondHello() { - var x int // 变量声明,变量必须在使用之前声明。 - x = 3 // 变量赋值。 - // 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。 - y := 4 - sum, prod := learnMultiple(x, y) // 多个返回变量的函数 - fmt.Println("sum:", sum, "prod:", prod) // 简单输出 - learnTypes() // 少于y分钟,学的更多! -} - -// 多变量和多返回值的函数 -func learnMultiple(x, y int) (sum, prod int) { - return x + y, x * y // 返回两个值 -} - -// 内置变量类型和关键词 -func learnTypes() { - // 短声明给你所想。 - s := "Learn Go!" // String类型 - - s2 := `A "raw" string literal -can include line breaks.` // 同样是String类型 - - // 非ascii字符。Go使用UTF-8编码。 - g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 - - f := 3.14195 // float64类型,IEEE-754 64位浮点数 - c := 3 + 4i // complex128类型,内部使用两个float64表示 - - // Var变量可以直接初始化。 - var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度 - var pi float32 = 22. / 7 - - // 字符转换 - n := byte('\n') // byte是uint8的别名 - - // 数组类型编译的时候大小固定。 - var a4 [4] int // 有4个int变量的数组,初始为0 - a3 := [...]int{3, 1, 5} // 有3个int变量的数组,同时进行了初始化 - - // Slice 有动态大小。Array和Slice各有千秋,但是使用slice的地方更多些。 - s3 := []int{4, 5, 9} // 和a3相比,这里没有省略号 - s4 := make([]int, 4) // 分配一个有4个int型变量的slice,全部被初始化为0 - - var d2 [][]float64 // 声明而已,什么都没有分配 - bs := []byte("a slice") // 类型转换的语法 - - p, q := learnMemory() // 声明p,q为int型变量的指针 - fmt.Println(*p, *q) // * 取值 - - // Map是动态可增长关联数组,和其他语言中的hash或者字典相似。 - m := map[string]int{"three": 3, "four": 4} - m["one"] = 1 - - // 在Go语言中未使用的变量在编译的时候会报错,而不是warning。 - // 下划线 _ 可以使你“使用”一个变量,但是丢弃它的值。 - _,_,_,_,_,_,_,_,_ = s2, g, f, u, pi, n, a3, s4, bs - // 输出变量 - fmt.Println(s, c, a4, s3, d2, m) - - learnFlowControl() // 回到流程控制 -} - -// Go全面支持垃圾回收。Go有指针,但是不支持指针运算。 -// 你会因为空指针而犯错,但是不会因为增加指针而犯错。 -func learnMemory() (p, q *int) { - // 返回int型变量指针p和q - p = new(int) // 内置函数new分配内存 - // 自动将分配的int赋值0,p不再是空的了。 - s := make([]int, 20) // 给20个int变量分配一块内存 - s[3] = 7 // 赋值 - r := -2 // 声明另一个局部变量 - return &s[3], &r // & 取址 -} - -func expensiveComputation() int { - return 1e6 -} - -func learnFlowControl() { - // If需要花括号,括号就免了 - if true { - fmt.Println("told ya") - } - // 用go fmt 命令可以帮你格式化代码,所以不用怕被人吐槽代码风格了, - // 也不用容忍被人的代码风格。 - if false { - // pout - } else { - // gloat - } - // 如果太多嵌套的if语句,推荐使用switch - x := 1 - switch x { - case 0: - case 1: - // 隐式调用break语句,匹配上一个即停止 - case 2: - // 不会运行 - } - // 和if一样,for也不用括号 - for x := 0; x < 3; x++ { // ++ 自增 - fmt.Println("iteration", x) - } - // x在这里还是1。为什么? - - // for 是go里唯一的循环关键字,不过它有很多变种 - for { // 无限循环 - break // 骗你的 - continue // 不会运行的 - } - // 和for一样,if中的:=先给y赋值,然后再和x作比较。 - if y := expensiveComputation(); y > x { - x = y - } - // 闭包函数 - xBig := func() bool { - return x > 100 // x是上面声明的变量引用 - } - fmt.Println("xBig:", xBig()) // true (上面把y赋给x了) - x /= 1e5 // x变成10 - fmt.Println("xBig:", xBig()) // 现在是false - - // 当你需要goto的时候,你会爱死它的! - goto love -love: - - learnInterfaces() // 好东西来了! -} - -// 定义Stringer为一个接口类型,有一个方法String -type Stringer interface { - String() string -} - -// 定义pair为一个结构体,有x和y两个int型变量。 -type pair struct { - x, y int -} - -// 定义pair类型的方法,实现Stringer接口。 -func (p pair) String() string { // p被叫做“接收器” - // Sprintf是fmt包中的另一个公有函数。 - // 用 . 调用p中的元素。 - return fmt.Sprintf("(%d, %d)", p.x, p.y) -} - -func learnInterfaces() { - // 花括号用来定义结构体变量,:=在这里将一个结构体变量赋值给p。 - p := pair{3, 4} - fmt.Println(p.String()) // 调用pair类型p的String方法 - var i Stringer // 声明i为Stringer接口类型 - i = p // 有效!因为p实现了Stringer接口(类似java中的塑型) - // 调用i的String方法,输出和上面一样 - fmt.Println(i.String()) - - // fmt包中的Println函数向对象要它们的string输出,实现了String方法就可以这样使用了。 - // (类似java中的序列化) - fmt.Println(p) // 输出和上面一样,自动调用String函数。 - fmt.Println(i) // 输出和上面一样。 - - learnErrorHandling() -} - -func learnErrorHandling() { - // ", ok"用来判断有没有正常工作 - m := map[int]string{3: "three", 4: "four"} - if x, ok := m[1]; !ok { // ok 为false,因为m中没有1 - fmt.Println("no one there") - } else { - fmt.Print(x) // 如果x在map中的话,x就是那个值喽。 - } - // 错误可不只是ok,它还可以给出关于问题的更多细节。 - if _, err := strconv.Atoi("non-int"); err != nil { // _ discards value - // 输出"strconv.ParseInt: parsing "non-int": invalid syntax" - fmt.Println(err) - } - // 待会再说接口吧。同时, - learnConcurrency() -} - -// c是channel类型,一个并发安全的通信对象。 -func inc(i int, c chan int) { - c <- i + 1 // <-把右边的发送到左边的channel。 -} - -// 我们将用inc函数来并发地增加一些数字。 -func learnConcurrency() { - // 用make来声明一个slice,make会分配和初始化slice,map和channel。 - c := make(chan int) - // 用go关键字开始三个并发的goroutine,如果机器支持的话,还可能是并行执行。 - // 三个都被发送到同一个channel。 - go inc(0, c) // go is a statement that starts a new goroutine. - go inc(10, c) - go inc(-805, c) - // 从channel中独处结果并打印。 - // 打印出什么东西是不可预知的。 - fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 - - cs := make(chan string) // 操作string的channel - cc := make(chan chan string) // 操作channel的channel - go func() { c <- 84 }() // 开始一个goroutine来发送一个新的数字 - go func() { cs <- "wordy" }() // 发送给cs - // Select类似于switch,但是每个case包括一个channel操作。 - // 它随机选择一个准备好通讯的case。 - select { - case i := <-c: // 从channel接收的值可以赋给其他变量 - fmt.Println("it's a", i) - case <-cs: // 或者直接丢弃 - fmt.Println("it's a string") - case <-cc: // 空的,还没作好通讯的准备 - fmt.Println("didn't happen.") - } - // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 - - learnWebProgramming() // Go很适合web编程,我知道你也想学! -} - -// http包中的一个简单的函数就可以开启web服务器。 -func learnWebProgramming() { - // ListenAndServe第一个参数指定了监听端口,第二个参数是一个接口,特定是http.Handler。 - err := http.ListenAndServe(":8080", pair{}) - fmt.Println(err) // 不要无视错误。 -} - -// 使pair实现http.Handler接口的ServeHTTP方法。 -func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // 使用http.ResponseWriter返回数据 - w.Write([]byte("You learned Go in Y minutes!")) -} -``` - -## 更进一步 - -Go的根源在[Go官方网站](http://golang.org/)。 -在那里你可以学习入门教程,通过浏览器交互式地学习,而且可以读到很多东西。 - -强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.) - -学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了! diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown old mode 100755 new mode 100644 diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown old mode 100755 new mode 100644 -- cgit v1.2.3 From b93df3fee7df0452e144e7900c4076d16df622d8 Mon Sep 17 00:00:00 2001 From: jingege Date: Sat, 4 Jan 2014 16:26:11 +0800 Subject: [clojure/cn]Commit the clojure-cn doc. --- zh-cn/clojure-cn.html.markdown | 362 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 zh-cn/clojure-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/clojure-cn.html.markdown b/zh-cn/clojure-cn.html.markdown new file mode 100644 index 00000000..f65dda9d --- /dev/null +++ b/zh-cn/clojure-cn.html.markdown @@ -0,0 +1,362 @@ +--- +language: clojure +filename: learnclojure-cn.clj +contributors: + - ["Bill Zhang", "http://jingege.github.io/"] +lang: zh-cn +--- + +Clojure是运行在JVM上的Lisp家族中的一员。她比Common Lisp更强调纯[函数式编程](https://en.wikipedia.org/wiki/Functional_programming),且自发布时便包含了一组工具来处理状态。 + +这种组合让她能十分简单且自动地处理并发问题。 + +(你需要使用Clojure 1.2或更新的发行版) + +```clojure +; 注释以分号开始。 + +; Clojure代码由一个个form组成, 即写在小括号里的由空格分开的一组语句。 +; Clojure解释器会把第一个元素当做一个函数或者宏来调用,其余的被认为是参数。 + +; Clojure代码的第一条语句一般是用ns来指定当前的命名空间。 +(ns learnclojure) + +; 更基本的例子: + +; str会使用所有参数来创建一个字符串 +(str "Hello" " " "World") ; => "Hello World" + +; 数学计算比较直观 +(+ 1 1) ; => 2 +(- 2 1) ; => 1 +(* 1 2) ; => 2 +(/ 2 1) ; => 2 + +; 等号是 = +(= 1 1) ; => true +(= 2 1) ; => false + +; 逻辑非 +(not true) ; => false + +; 嵌套的form工作起来应该和你预想的一样 +(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 + +; 类型 +;;;;;;;;;;;;; + +; Clojure使用Java的Object来描述布尔值、字符串和数字 +; 用函数 `class` 来查看具体的类型 +(class 1) ; 整形默认是java.lang.Long类型 +(class 1.); 浮点默认是java.lang.Double类型的 +(class ""); String是java.lang.String类型的,要用双引号引起来 +(class false) ; 布尔值是java.lang.Boolean类型的 +(class nil); "null"被称作nil + +; 如果你想创建一组数据字面量,用单引号(')来阻止form被解析和求值 +'(+ 1 2) ; => (+ 1 2) +; (单引号是quote的简写形式,故上式等价于(quote (+ 1 2))) + +; 可以对一个引用列表求值 +(eval '(+ 1 2)) ; => 3 + +; 集合(Collection)和序列 +;;;;;;;;;;;;;;;;;;; + +; List的底层实现是链表,Vector的底层实现是数组 +; 二者也都是java类 +(class [1 2 3]); => clojure.lang.PersistentVector +(class '(1 2 3)); => clojure.lang.PersistentList + +; list本可以写成(1 2 3), 但必须用引用来避免被解释器当做函数来求值。 +; (list 1 2 3)等价于'(1 2 3) + +; 集合其实就是一组数据 +; List和Vector都是集合: +(coll? '(1 2 3)) ; => true +(coll? [1 2 3]) ; => true + +; 序列 (seqs) 是数据列表的抽象描述 +; 只有列表才可称作序列。 +(seq? '(1 2 3)) ; => true +(seq? [1 2 3]) ; => false + +; 序列被访问时只需要提供一个值,所以序列可以被懒加载 —— 也就意味着可以定义一个无限序列: +(range 4) ; => (0 1 2 3) +(range) ; => (0 1 2 3 4 ...) (无限序列) +(take 4 (range)) ; (0 1 2 3) + +; cons用以向列表或向量的起始位置添加元素 +(cons 4 [1 2 3]) ; => (4 1 2 3) +(cons 4 '(1 2 3)) ; => (4 1 2 3) + +; conj将以最高效的方式向集合中添加元素。 +; 对于列表,数据会在起始位置插入,而对于向量,则在末尾位置插入。 +(conj [1 2 3] 4) ; => [1 2 3 4] +(conj '(1 2 3) 4) ; => (4 1 2 3) + +; 用concat来合并列表或向量 +(concat [1 2] '(3 4)) ; => (1 2 3 4) + +; 用filter来过滤集合中的元素,用map来根据指定的函数来映射得到一个新的集合 +(map inc [1 2 3]) ; => (2 3 4) +(filter even? [1 2 3]) ; => (2) + +; recuce使用函数来规约集合 +(reduce + [1 2 3 4]) +; = (+ (+ (+ 1 2) 3) 4) +; => 10 + +; reduce还能指定一个初始参数 +(reduce conj [] '(3 2 1)) +; = (conj (conj (conj [] 3) 2) 1) +; => [3 2 1] + +; 函数 +;;;;;;;;;;;;;;;;;;;;; + +; 用fn来创建函数。函数的返回值是最后一个表达式的值 +(fn [] "Hello World") ; => fn + +; (你需要再嵌套一组小括号来调用它) +((fn [] "Hello World")) ; => "Hello World" + +; 你可以用def来创建一个变量(var) +(def x 1) +x ; => 1 + +; 将函数定义为一个变量(var) +(def hello-world (fn [] "Hello World")) +(hello-world) ; => "Hello World" + +; 你可用defn来简化函数的定义 +(defn hello-world [] "Hello World") + +; 中括号内的内容是函数的参数。 +(defn hello [name] + (str "Hello " name)) +(hello "Steve") ; => "Hello Steve" + +; 你还可以用这种简写的方式来创建函数: +(def hello2 #(str "Hello " %1)) +(hello2 "Fanny") ; => "Hello Fanny" + +; 函数也可以有多个参数列表。 +(defn hello3 + ([] "Hello World") + ([name] (str "Hello " name))) +(hello3 "Jake") ; => "Hello Jake" +(hello3) ; => "Hello World" + +; 可以定义变参函数,即把&后面的参数全部放入一个序列 +(defn count-args [& args] + (str "You passed " (count args) " args: " args)) +(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)" + +; 可以混用定参和变参(用&来界定) +(defn hello-count [name & args] + (str "Hello " name ", you passed " (count args) " extra args")) +(hello-count "Finn" 1 2 3) +; => "Hello Finn, you passed 3 extra args" + + +; 哈希表 +;;;;;;;;;; + +; 基于hash的map和基于数组的map(即arraymap)实现了相同的接口,hashmap查询起来比较快,但不保证元素的顺序。 +(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap +(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap + +; arraymap在足够大的时候,大多数操作会将其自动转换成hashmap,所以不用担心(对大的arraymap的查询性能)。 + +; map支持很多类型的key,但推荐使用keyword类型 +; keyword类型和字符串类似,但做了一些优化。 +(class :a) ; => clojure.lang.Keyword + +(def stringmap {"a" 1, "b" 2, "c" 3}) +stringmap ; => {"a" 1, "b" 2, "c" 3} + +(def keymap {:a 1, :b 2, :c 3}) +keymap ; => {:a 1, :c 3, :b 2} + +; 顺便说一下,map里的逗号是可有可无的,作用只是提高map的可读性。 + +; 从map中查找元素就像把map名作为函数调用一样。 +(stringmap "a") ; => 1 +(keymap :a) ; => 1 + +; 可以把keyword写在前面来从map中查找元素。 +(:b keymap) ; => 2 + +; 但不要试图用字符串类型的key来这么做。 +;("a" stringmap) +; => Exception: java.lang.String cannot be cast to clojure.lang.IFn + +; 查找不存在的key会返回nil。 +(stringmap "d") ; => nil + +; 用assoc函数来向hashmap里添加元素 +(def newkeymap (assoc keymap :d 4)) +newkeymap ; => {:a 1, :b 2, :c 3, :d 4} + +; 但是要记住的是clojure的数据类型是不可变的! +keymap ; => {:a 1, :b 2, :c 3} + +; 用dissoc来移除元素 +(dissoc keymap :a :b) ; => {:c 3} + +; 集合(Set) +;;;;;; + +(class #{1 2 3}) ; => clojure.lang.PersistentHashSet +(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3} + +; 用conj新增元素 +(conj #{1 2 3} 4) ; => #{1 2 3 4} + +; 用disj移除元素 +(disj #{1 2 3} 1) ; => #{2 3} + +; 把集合当做函数调用来检查元素是否存在: +(#{1 2 3} 1) ; => 1 +(#{1 2 3} 4) ; => nil + +; 在clojure.sets模块下有很多相关函数。 + +; 常用的form +;;;;;;;;;;;;;;;;; + +; clojure里的逻辑控制结构都是用宏(macro)实现的,这在语法上看起来没什么不同。 +(if false "a" "b") ; => "b" +(if false "a") ; => nil + +; 用let来创建临时的绑定变量。 +(let [a 1 b 2] + (> a b)) ; => false + +; 用do将多个语句组合在一起依次执行 +(do + (print "Hello") + "World") ; => "World" (prints "Hello") + +; 函数定义里有一个隐式的do +(defn print-and-say-hello [name] + (print "Saying hello to " name) + (str "Hello " name)) +(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") + +; let也是如此 +(let [name "Urkel"] + (print "Saying hello to " name) + (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") + +; 模块 +;;;;;;;;;;;;;;; + +; 用use来导入模块里的所有函数 +(use 'clojure.set) + +; 然后就可以使用set相关的函数了 +(intersection #{1 2 3} #{2 3 4}) ; => #{2 3} +(difference #{1 2 3} #{2 3 4}) ; => #{1} + +; 你也可以从一个模块里导入一部分函数。 +(use '[clojure.set :only [intersection]]) + +; 用require来导入一个模块 +(require 'clojure.string) + +; 用/来调用模块里的函数 +; 下面是从模块`clojure.string`里调用`blank?`函数。 +(clojure.string/blank? "") ; => true + +; 在`import`里你可以给模块名指定一个较短的别名。 +(require '[clojure.string :as str]) +(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." +; (#""用来表示一个正则表达式) + +; 你可以在一个namespace定义里用`:require`的方式来require(或者use,但最好不要用)模块。 +; 这样的话你无需引用模块列表。 +(ns test + (:require + [clojure.string :as str] + [clojure.set :as set])) + +; Java +;;;;;;;;;;;;;;;;; + +; Java有大量的优秀的库,你肯定想学会如何用clojure来使用这些Java库。 + +; 用import来导入java类 +(import java.util.Date) + +; 也可以在ns定义里导入 +(ns test + (:import java.util.Date + java.util.Calendar)) + +; 用类名末尾加`.`的方式来new一个Java对象 +(Date.) ; + +; 用`.`操作符来调用方法,或者用`.method`的简化方式。 +(. (Date.) getTime) ; +(.getTime (Date.)) ; 和上例一样。 + +; 用`/`调用静态方法 +(System/currentTimeMillis) ; (system is always present) + +; 用`doto`来更方便的使用(可变)类。 +(import java.util.Calendar) +(doto (Calendar/getInstance) + (.set 2000 1 1 0 0 0) + .getTime) ; => A Date. set to 2000-01-01 00:00:00 + +; STM +;;;;;;;;;;;;;;;;; + +; 软件内存事务(Software Transactional Memory)被clojure用来处理持久化的状态。clojure里内置了一些结构来使用STM。 +; atom是最简单的。给它传一个初始值 +(def my-atom (atom {})) + +; 用`swap!`更新atom。 +; `swap!`会以atom的当前值为第一个参数来调用一个指定的函数,`swap`其余的参数作为该函数的第二个参数。 +(swap! my-atom assoc :a 1) ; Sets my-atom to the result of (assoc {} :a 1) +(swap! my-atom assoc :b 2) ; Sets my-atom to the result of (assoc {:a 1} :b 2) + +; 用`@`读取atom的值 +my-atom ;=> Atom<#...> (返回Atom对象) +@my-atom ; => {:a 1 :b 2} + +; 下例是一个使用atom实现的简单计数器 +(def counter (atom 0)) +(defn inc-counter [] + (swap! counter inc)) + +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) +(inc-counter) + +@counter ; => 5 + +; 其他STM相关的结构是ref和agent. +; Refs: http://clojure.org/refs +; Agents: http://clojure.org/agents +``` + +### 进阶读物 + +本文肯定不足以讲述关于clojure的一切,但是希望足以让你迈出第一步。 + +Clojure.org官网有很多文章: +[http://clojure.org/](http://clojure.org/) + +Clojuredocs.org有大多数核心函数的文档,还带了示例哦: +[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) + +4Clojure是个很赞的用来练习clojure/FP技能的地方: +[http://www.4clojure.com/](http://www.4clojure.com/) + +Clojure-doc.org (你没看错)有很多入门级的文章: +[http://clojure-doc.org/](http://clojure-doc.org/) -- cgit v1.2.3 From ca5671a5209336241885eeeed3543c06ea9e2517 Mon Sep 17 00:00:00 2001 From: lidashuang Date: Sun, 5 Jan 2014 04:23:58 +0800 Subject: Update go-cn.html.markdown --- zh-cn/go-cn.html.markdown | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown index 7cc9c171..4a87dc21 100644 --- a/zh-cn/go-cn.html.markdown +++ b/zh-cn/go-cn.html.markdown @@ -5,6 +5,8 @@ filename: learngo-cn.go contributors: - ["Sonia Keys", "https://github.com/soniakeys"] - ["pantaovay", "https://github.com/pantaovay"] + - ["lidashuang", "https://github.com/lidashuang"] + --- 发明Go语言是出于更好地完成工作的需要。Go不是计算机科学的最新发展潮流,但它却提供了解决现实问题的最新最快的方法。 @@ -30,7 +32,7 @@ import ( ) // 函数声明:Main是程序执行的入口。 -// 不管你喜欢还是不喜欢,反正G就用了花括号来包住函数体。 +// 不管你喜欢还是不喜欢,反正Go就用了花括号来包住函数体。 func main() { // 往标准输出打印一行。 // 用包名fmt限制打印函数。 @@ -47,7 +49,7 @@ func beyondHello() { x = 3 // 变量赋值。 // 可以用:=来偷懒,它自动把变量类型、声明和赋值都搞定了。 y := 4 - sum, prod := learnMultiple(x, y) // 多个返回变量的函数 + sum, prod := learnMultiple(x, y) // 返回多个变量的函数 fmt.Println("sum:", sum, "prod:", prod) // 简单输出 learnTypes() // 少于y分钟,学的更多! } @@ -82,7 +84,7 @@ can include line breaks.` // 同样是String类型 var a4 [4] int // 有4个int变量的数组,初始为0 a3 := [...]int{3, 1, 5} // 有3个int变量的数组,同时进行了初始化 - // Slice 有动态大小。Array和Slice各有千秋,但是使用slice的地方更多些。 + // Slice 可以动态的增删。Array和Slice各有千秋,但是使用slice的地方更多些。 s3 := []int{4, 5, 9} // 和a3相比,这里没有省略号 s4 := make([]int, 4) // 分配一个有4个int型变量的slice,全部被初始化为0 @@ -114,7 +116,7 @@ func learnMemory() (p, q *int) { s := make([]int, 20) // 给20个int变量分配一块内存 s[3] = 7 // 赋值 r := -2 // 声明另一个局部变量 - return &s[3], &r // & 取址 + return &s[3], &r // & 取地址 } func expensiveComputation() int { @@ -149,7 +151,7 @@ func learnFlowControl() { // x在这里还是1。为什么? // for 是go里唯一的循环关键字,不过它有很多变种 - for { // 无限循环 + for { // 死循环 break // 骗你的 continue // 不会运行的 } @@ -239,7 +241,7 @@ func learnConcurrency() { go inc(-805, c) // 从channel中独处结果并打印。 // 打印出什么东西是不可预知的。 - fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是接收操作。 + fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是读操作。 cs := make(chan string) // 操作string的channel cc := make(chan chan string) // 操作channel的channel @@ -255,7 +257,7 @@ func learnConcurrency() { case <-cc: // 空的,还没作好通讯的准备 fmt.Println("didn't happen.") } - // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个保持阻塞。 + // 上面c或者cs的值被取到,其中一个goroutine结束,另外一个一直阻塞。 learnWebProgramming() // Go很适合web编程,我知道你也想学! } -- cgit v1.2.3 From a8f49bb1889cf96904a99af7458229d860e1e248 Mon Sep 17 00:00:00 2001 From: lidashuang Date: Sun, 5 Jan 2014 04:35:23 +0800 Subject: Update ruby-cn.html.markdown --- zh-cn/ruby-cn.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index 619e6e92..3c47f3f9 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -6,6 +6,7 @@ contributors: - ["David Underwood", "http://theflyingdeveloper.com"] - ["Joel Walden", "http://joelwalden.net"] - ["Luke Holder", "http://twitter.com/lukeholder"] + - ["lidashuang", "https://github.com/lidashuang"] translators: - ["Lin Xiangyu", "https://github.com/oa414"] --- @@ -173,7 +174,7 @@ new_hash = { defcon: 3, action: true} new_hash.keys #=> [:defcon, :action] # 小贴士:数组和哈希表都是可枚举的 -# 它们可以共享一些有用的方法,比如each, map, count, 和more +# 它们可以共享一些有用的方法,比如each, map, count 等等 # 控制流 -- cgit v1.2.3 From 755c987deca2ceb1aae680fd9b9d73865157a64a Mon Sep 17 00:00:00 2001 From: lidashuang Date: Sun, 5 Jan 2014 22:32:37 +0800 Subject: Update javascript-cn.html.markdown --- zh-cn/javascript-cn.html.markdown | 2 -- 1 file changed, 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 89fc256e..86ad1d07 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -401,8 +401,6 @@ if (Object.create === undefined){ // 如果存在则不覆盖 [Mozilla 开发者 网络](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 提供了很好的 Javascript文档,并且由于是wiki,所以你也可以自行编辑来分享你的知识。 -wiki, so as you learn more you can help others out by sharing your own -knowledge. MDN的 [A re-introduction to JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) -- cgit v1.2.3 From 72de48f9e2a371f28deb7bd41d328d5c41c8e245 Mon Sep 17 00:00:00 2001 From: jingege Date: Mon, 6 Jan 2014 09:30:18 +0800 Subject: [clojure/cn]Wrap some lines to fit the view. --- zh-cn/clojure-cn.html.markdown | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/clojure-cn.html.markdown b/zh-cn/clojure-cn.html.markdown index f65dda9d..d5d8232b 100644 --- a/zh-cn/clojure-cn.html.markdown +++ b/zh-cn/clojure-cn.html.markdown @@ -81,7 +81,7 @@ Clojure是运行在JVM上的Lisp家族中的一员。她比Common Lisp更强调 (seq? '(1 2 3)) ; => true (seq? [1 2 3]) ; => false -; 序列被访问时只需要提供一个值,所以序列可以被懒加载 —— 也就意味着可以定义一个无限序列: +; 序列被访问时只需要提供一个值,所以序列可以被懒加载——也就意味着可以定义一个无限序列: (range 4) ; => (0 1 2 3) (range) ; => (0 1 2 3 4 ...) (无限序列) (take 4 (range)) ; (0 1 2 3) @@ -163,11 +163,13 @@ x ; => 1 ; 哈希表 ;;;;;;;;;; -; 基于hash的map和基于数组的map(即arraymap)实现了相同的接口,hashmap查询起来比较快,但不保证元素的顺序。 +; 基于hash的map和基于数组的map(即arraymap)实现了相同的接口,hashmap查询起来比较快, +; 但不保证元素的顺序。 (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap (class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap -; arraymap在足够大的时候,大多数操作会将其自动转换成hashmap,所以不用担心(对大的arraymap的查询性能)。 +; arraymap在足够大的时候,大多数操作会将其自动转换成hashmap, +; 所以不用担心(对大的arraymap的查询性能)。 ; map支持很多类型的key,但推荐使用keyword类型 ; keyword类型和字符串类似,但做了一些优化。 @@ -275,7 +277,7 @@ keymap ; => {:a 1, :b 2, :c 3} (str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." ; (#""用来表示一个正则表达式) -; 你可以在一个namespace定义里用`:require`的方式来require(或者use,但最好不要用)模块。 +; 你可以在一个namespace定义里用:require的方式来require(或use,但最好不要用)模块。 ; 这样的话你无需引用模块列表。 (ns test (:require @@ -314,12 +316,14 @@ keymap ; => {:a 1, :b 2, :c 3} ; STM ;;;;;;;;;;;;;;;;; -; 软件内存事务(Software Transactional Memory)被clojure用来处理持久化的状态。clojure里内置了一些结构来使用STM。 +; 软件内存事务(Software Transactional Memory)被clojure用来处理持久化的状态。 +; clojure里内置了一些结构来使用STM。 ; atom是最简单的。给它传一个初始值 (def my-atom (atom {})) ; 用`swap!`更新atom。 -; `swap!`会以atom的当前值为第一个参数来调用一个指定的函数,`swap`其余的参数作为该函数的第二个参数。 +; `swap!`会以atom的当前值为第一个参数来调用一个指定的函数, +; `swap`其余的参数作为该函数的第二个参数。 (swap! my-atom assoc :a 1) ; Sets my-atom to the result of (assoc {} :a 1) (swap! my-atom assoc :b 2) ; Sets my-atom to the result of (assoc {:a 1} :b 2) -- cgit v1.2.3 From d2a34d3390e131f738f6f54b95a1101966f4ea5d Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Fri, 17 Jan 2014 14:47:54 +0800 Subject: php: typo --- zh-cn/php-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index c6ebb515..c22d8e12 100644 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -180,7 +180,7 @@ assert($c >= $d); // 下面的比较只有在类型相同、值相同的情况下才为真 assert($c === $d); assert($a !== $d); -assert(1 == '1'); +assert(1 === '1'); assert(1 !== '1'); // 变量可以根据其使用来进行类型转换 -- cgit v1.2.3 From 6c2210e92172b0a5cb5ab9eaf09cbd60a6d73c13 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Fri, 17 Jan 2014 14:50:29 +0800 Subject: php: typo --- zh-cn/php-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index c6ebb515..9c344ef6 100644 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -243,7 +243,7 @@ if ($x === '0') { -// 下面的语法常用语模板中: +// 下面的语法常用于模板中: ?> -- cgit v1.2.3 From f47de5a0972de32050cd1fbc7be0ec8eb9f51636 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Fri, 17 Jan 2014 15:12:05 +0800 Subject: php:typo --- zh-cn/php-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index c6ebb515..e29b6771 100644 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -333,7 +333,7 @@ function my_function () { echo my_function(); // => "Hello" // 函数名需要以字母或者下划线开头, -// 后面可以跟着任意的字幕、下划线、数字. +// 后面可以跟着任意的字母、下划线、数字. function add ($x, $y = 1) { // $y 是可选参数,默认值为 1 $result = $x + $y; -- cgit v1.2.3 From 0b2a283db4bc622aaca3c23daa3c39dfd9297db1 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 29 Jan 2014 23:30:28 -0800 Subject: Updated a lot of filenames --- zh-cn/r-cn.html.markdown | 2 +- zh-cn/racket-cn.html.markdown | 2 +- zh-cn/scala-cn.html.markdown | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/r-cn.html.markdown b/zh-cn/r-cn.html.markdown index ed8c43b6..19c5f25d 100644 --- a/zh-cn/r-cn.html.markdown +++ b/zh-cn/r-cn.html.markdown @@ -6,7 +6,7 @@ contributors: translators: - ["小柒", "http://weibo.com/u/2328126220"] - ["alswl", "https://github.com/alswl"] -filename: learnr.r +filename: learnr-zh.r lang: zh-cn --- diff --git a/zh-cn/racket-cn.html.markdown b/zh-cn/racket-cn.html.markdown index d43511ea..8ef3671f 100644 --- a/zh-cn/racket-cn.html.markdown +++ b/zh-cn/racket-cn.html.markdown @@ -2,7 +2,7 @@ language: racket lang: zh-cn -filename: learnracket.rkt +filename: learnracket-zh.rkt contributors: - ["th3rac25", "https://github.com/voila"] - ["Eli Barzilay", "https://github.com/elibarzilay"] diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 1ce41ac6..24f73bb5 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -6,7 +6,6 @@ contributors: - ["Dominic Bou-Samra", "http://dbousamra.github.com"] translators: - ["Peiyong Lin", ""] -filename: learn.scala lang: zh-cn --- -- cgit v1.2.3 From b3f363fcf206adb7e63cf46598514fc692ef6a45 Mon Sep 17 00:00:00 2001 From: Xavier Yao Date: Wed, 5 Feb 2014 21:49:10 +0800 Subject: Chinese translation for CoffeeScript --- zh-cn/coffeescript-cn.html.markdown | 101 ++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 zh-cn/coffeescript-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/coffeescript-cn.html.markdown b/zh-cn/coffeescript-cn.html.markdown new file mode 100644 index 00000000..8fb96749 --- /dev/null +++ b/zh-cn/coffeescript-cn.html.markdown @@ -0,0 +1,101 @@ +--- +language: coffeescript +contributors: + - ["Tenor Biel", "http://github.com/L8D"] + - ["Xavier Yao"], "http://github.com/xavieryao"] +translators: + - ["Xavier Yao"], "http://github.com/xavieryao"] +filename: coffeescript-cn.coffee +lang: zh-cn +--- + +CoffeeScript是逐句编译为JavaScript的一种小型语言,且没有运行时的解释器。 +作为JavaScript的替代品之一,CoffeeScript旨在编译人类可读、美观优雅且速度不输原生的代码, +且编译后的代码可以在任何JavaScript运行时正确运行。 + +参阅 [CoffeeScript官方网站](http://coffeescript.org/)以获取CoffeeScript的完整教程。 + +``` coffeescript +# CoffeeScript是一种很潮的编程语言, +# 它紧随众多现代编程语言的趋势。 +# 因此正如Ruby和Python,CoffeeScript使用井号标记注释。 + +### +大段落注释以此为例,可以被直接编译为 '/ *' 和 '* /' 包裹的JavaScript代码。 + +在继续之前你需要了解JavaScript的基本概念。 + +示例中 => 后为编译后的JavaScript代码 +### + +# 赋值: +number = 42 #=> var number = 42; +opposite = true #=> var opposite = true; + +# 条件: +number = -42 if opposite #=> if(opposite) { number = -42; } + +# 函数: +square = (x) -> x * x #=> var square = function(x) { return x * x; } + +fill = (container, liquid = "coffee") -> + "Filling the #{container} with #{liquid}..." +#=>var fill; +# +#fill = function(container, liquid) { +# if (liquid == null) { +# liquid = "coffee"; +# } +# return "Filling the " + container + " with " + liquid + "..."; +#}; + +# 区间: +list = [1..5] #=> var list = [1, 2, 3, 4, 5]; + +# 对象: +math = + root: Math.sqrt + square: square + cube: (x) -> x * square x +#=> var math = { +# "root": Math.sqrt, +# "square": square, +# "cube": function(x) { return x * square(x); } +#} + +# Splats: +race = (winner, runners...) -> + print winner, runners +#=>race = function() { +# var runners, winner; +# winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : []; +# return print(winner, runners); +#}; + +# 存在判断: +alert "I knew it!" if elvis? +#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); } + +# 数组推导: +cubes = (math.cube num for num in list) +#=>cubes = (function() { +# var _i, _len, _results; +# _results = []; +# for (_i = 0, _len = list.length; _i < _len; _i++) { +# num = list[_i]; +# _results.push(math.cube(num)); +# } +# return _results; +# })(); + +foods = ['broccoli', 'spinach', 'chocolate'] +eat food for food in foods when food isnt 'chocolate' +#=>foods = ['broccoli', 'spinach', 'chocolate']; +# +#for (_k = 0, _len2 = foods.length; _k < _len2; _k++) { +# food = foods[_k]; +# if (food !== 'chocolate') { +# eat(food); +# } +#} +``` -- cgit v1.2.3 From d7ea420ad4980d16bf61d977dfb6bcfb58286238 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Thu, 6 Feb 2014 02:33:05 +0800 Subject: Chinese (simplified) translation of lua --- zh-cn/lua-cn.html.markdown | 413 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 zh-cn/lua-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown new file mode 100644 index 00000000..95a94c76 --- /dev/null +++ b/zh-cn/lua-cn.html.markdown @@ -0,0 +1,413 @@ +--- +language: lua +lang: zh-cn +contributors: + - ["Tyler Neylon", "http://tylerneylon.com/"] + - ["Rob Hoelz", "http://hoelz.ro"] + - ["Jakukyo Friel", "http://weakish.github.io"] + - ["Craig Roddin", "craig.roddin@gmail.com"] + - ["Amr Tamimi", "https://amrtamimi.com"] +translators: + - ["Jakukyo Friel", "http://weakish.github.io"] +--- + +```lua +-- 单行注释以两个连字符开头 + +--[[ + 多行注释 +--]] + +---------------------------------------------------- +-- 1. 变量和流程控制 +---------------------------------------------------- + +num = 42 -- 所有的数字都是双精度浮点型。 +-- 别害怕,64位的双精度浮点型数字中有52位用于 +-- 保存精确的整型值; 对于52位以内的整型值, +-- 不用担心精度问题。 + +s = 'walternate' -- 和Python一样,字符串不可变。 +t = "也可以用双引号" +u = [[ 多行的字符串 + 以两个方括号 + 开始和结尾。]] +t = nil -- 撤销t的定义; Lua 支持垃圾回收。 + +-- 块使用do/end之类的关键字标识: +while num < 50 do + num = num + 1 -- 不支持 ++ 或 += 运算符。 +end + +-- If语句: +if num > 40 then + print('over 40') +elseif s ~= 'walternate' then -- ~= 表示不等于。 + -- 像Python一样,用 == 检查是否相等 ;字符串同样适用。 + io.write('not over 40\n') -- 默认标准输出。 +else + -- 默认全局变量。 + thisIsGlobal = 5 -- 通常使用驼峰。 + + -- 如何定义局部变量: + local line = io.read() -- 读取标准输入的下一行。 + + -- ..操作符用于连接字符串: + print('Winter is coming, ' .. line) +end + +-- 未定义的变量返回nil。 +-- 这不是错误: +foo = anUnknownVariable -- 现在 foo = nil. + +aBoolValue = false + +--只有nil和false为假; 0和 ''都均为真! +if not aBoolValue then print('twas false') end + +-- 'or'和 'and'短路 +-- 类似于C/js里的 a?b:c 操作符: +ans = aBoolValue and 'yes' or 'no' --> 'no' + +karlSum = 0 +for i = 1, 100 do -- 范围包含两端 + karlSum = karlSum + i +end + +-- 使用 "100, 1, -1" 表示递减的范围: +fredSum = 0 +for j = 100, 1, -1 do fredSum = fredSum + j end + +-- 通常,范围表达式为begin, end[, step]. + +-- 循环的另一种结构: +repeat + print('the way of the future') + num = num - 1 +until num == 0 + +---------------------------------------------------- +-- 2. 函数。 +---------------------------------------------------- + +function fib(n) + if n < 2 then return 1 end + return fib(n - 2) + fib(n - 1) +end + +-- 支持闭包及匿名函数: +function adder(x) + -- 调用adder时,会创建返回的函数, + -- 并且会记住x的值: + return function (y) return x + y end +end +a1 = adder(9) +a2 = adder(36) +print(a1(16)) --> 25 +print(a2(64)) --> 100 + +-- 返回值、函数调用和赋值都可以 +-- 使用长度不匹配的list。 +-- 不匹配的接收方会被赋值nil; +-- 不匹配的发送方会被丢弃。 + +x, y, z = 1, 2, 3, 4 +-- x = 1、y = 2、z = 3, 而 4 会被丢弃。 + +function bar(a, b, c) + print(a, b, c) + return 4, 8, 15, 16, 23, 42 +end + +x, y = bar('zaphod') --> 打印 "zaphod nil nil" +-- 现在 x = 4, y = 8, 而值15..42被丢弃。 + +-- 函数是一等公民,可以是局部的,也可以是全局的。 +-- 以下表达式等价: +function f(x) return x * x end +f = function (x) return x * x end + +-- 这些也是等价的: +local function g(x) return math.sin(x) end +local g; g = function (x) return math.sin(x) end +-- 'local g'使得g可以自引用。 + +-- 顺便提下,三角函数以弧度为单位。 + +-- 用一个字符串参数调用函数,可以省略括号: +print 'hello' --可以工作。 + +-- 调用函数时,如果只有一个table参数, +-- 同样可以省略括号(table详情见下): +print {} -- 一样可以工作。 + +---------------------------------------------------- +-- 3. Table。 +---------------------------------------------------- + +-- Table = Lua唯一的组合数据结构; +-- 它们是关联数组。 +-- 类似于PHP的数组或者js的对象, +-- 它们是哈希表或者字典,也可以当初列表使用。 + +-- 按字典/map的方式使用Table: + +-- Dict字面量默认使用字符串类型的key: +t = {key1 = 'value1', key2 = false} + +-- 字符串key可以使用类似js的点标记: +print(t.key1) -- 打印 'value1'. +t.newKey = {} -- 添加新的键值对。 +t.key2 = nil -- 从table删除 key2。 + +-- 使用任何非nil的值作为key: +u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'} +print(u[6.28]) -- 打印 "tau" + +-- 数字和字符串的key按值匹配的 +-- table按id匹配。 +a = u['@!#'] -- 现在 a = 'qbert'. +b = u[{}] -- 我们或许期待的是 1729, 但是得到的是nil: +-- b = nil ,因为没有找到。 +-- 之所以没找到,是因为我们用的key与保存数据时用的不是同 +-- 一个对象。 +-- 所以字符串和数字是移植性更好的key。 + +-- 只需要一个table参数的函数调用不需要括号: +function h(x) print(x.key1) end +h{key1 = 'Sonmi~451'} -- 打印'Sonmi~451'. + +for key, val in pairs(u) do -- 遍历Table + print(key, val) +end + +-- _G 是一个特殊的table,用于保存所有的全局变量 +print(_G['_G'] == _G) -- 打印'true'. + +-- 按列表/数组的方式使用: + +-- 列表字面量隐式添加整数键: +v = {'value1', 'value2', 1.21, 'gigawatts'} +for i = 1, #v do -- #v 是列表的大小 + print(v[i]) -- 索引从 1 开始!! 太疯狂了! +end +-- 'list'并非真正的类型,v 其实是一个table, +-- 只不过它用连续的整数作为key,可以像list那样去使用。 + +---------------------------------------------------- +-- 3.1 元表(metatable) 和元方法(metamethod)。 +---------------------------------------------------- + +-- table的元表提供了一种机制,支持类似操作符重载的行为。 +-- 稍后我们会看到元表如何支持类似js prototype的行为。 + +f1 = {a = 1, b = 2} -- 表示一个分数 a/b. +f2 = {a = 2, b = 3} + +-- 这会失败: +-- s = f1 + f2 + +metafraction = {} +function metafraction.__add(f1, f2) + sum = {} + sum.b = f1.b * f2.b + sum.a = f1.a * f2.b + f2.a * f1.b + return sum +end + +setmetatable(f1, metafraction) +setmetatable(f2, metafraction) + +s = f1 + f2 -- 调用在f1的元表上的__add(f1, f2) 方法 + +-- f1, f2 没有关于元表的key,这点和js的prototype不一样。 +-- 因此你必须用getmetatable(f1)获取元表。 +-- 元表是一个普通的table, +-- 元表的key是普通的Lua中的key,例如__add。 + +-- 但是下面一行代码会失败,因为s没有元表: +-- t = s + s +-- 下面提供的与类相似的模式可以解决这个问题: + +-- 元表的__index 可以重载用于查找的点操作符: +defaultFavs = {animal = 'gru', food = 'donuts'} +myFavs = {food = 'pizza'} +setmetatable(myFavs, {__index = defaultFavs}) +eatenBy = myFavs.animal -- 可以工作!感谢元表 + +-- 如果在table中直接查找key失败,会使用 +-- 元表的__index 递归地重试。 + +-- __index的值也可以是function(tbl, key) +-- 这样可以支持自定义查找。 + +-- __index、__add等的值,被称为元方法。 +-- 这里是一个table元方法的清单: + +-- __add(a, b) for a + b +-- __sub(a, b) for a - b +-- __mul(a, b) for a * b +-- __div(a, b) for a / b +-- __mod(a, b) for a % b +-- __pow(a, b) for a ^ b +-- __unm(a) for -a +-- __concat(a, b) for a .. b +-- __len(a) for #a +-- __eq(a, b) for a == b +-- __lt(a, b) for a < b +-- __le(a, b) for a <= b +-- __index(a, b) for a.b +-- __newindex(a, b, c) for a.b = c +-- __call(a, ...) for a(...) + +---------------------------------------------------- +-- 3.2 与类相似的table和继承。 +---------------------------------------------------- + +-- Lua没有内建的类;可以通过不同的方法,利用表和元表 +-- 来实现类。 + +-- 下面是一个例子,解释在后面: + +Dog = {} -- 1. + +function Dog:new() -- 2. + newObj = {sound = 'woof'} -- 3. + self.__index = self -- 4. + return setmetatable(newObj, self) -- 5. +end + +function Dog:makeSound() -- 6. + print('I say ' .. self.sound) +end + +mrDog = Dog:new() -- 7. +mrDog:makeSound() -- 'I say woof' -- 8. + +-- 1. Dog看上去像一个类;其实它是一个table。 +-- 2. 函数tablename:fn(...) 等价于 +-- 函数tablename.fn(self, ...) +-- 冒号(:)只是添加了self作为第一个参数。 +-- 阅读7 & 8条 了解self变量是如何得到其值的。 +-- 3. newObj是类Dog的一个实例。 +-- 4. self = 被继承的类。通常self = Dog,不过继承可以改变它。 +-- 如果把newObj的元表和__index都设置为self, +-- newObj就可以得到self的函数。 +-- 5. 备忘:setmetatable返回其第一个参数。 +-- 6. 冒号(:)的作用和第2条一样,不过这里 +-- self是一个实例,而不是类 +-- 7. 等价于Dog.new(Dog),所以在new()中,self = Dog。 +-- 8. 等价于mrDog.makeSound(mrDog); self = mrDog。 + +---------------------------------------------------- + +-- 继承的例子: + +LoudDog = Dog:new() -- 1. + +function LoudDog:makeSound() + s = self.sound .. ' ' -- 2. + print(s .. s .. s) +end + +seymour = LoudDog:new() -- 3. +seymour:makeSound() -- 'woof woof woof' -- 4. + +-- 1. LoudDog获得Dog的方法和变量列表。 +-- 2. 因为new()的缘故,self拥有了一个'sound' key,参见第3条。 +-- 3. 等价于LoudDog.new(LoudDog),转换一下就是 +-- Dog.new(LoudDog),这是因为LoudDog没有'new' key, +-- 但是它的元表中有 __index = Dog。 +-- 结果: seymour的元表是LoudDog,并且 +-- LoudDog.__index = Dog。所以有seymour.key +-- = seymour.key, LoudDog.key, Dog.key +-- 从其中第一个有指定key的table获取。 +-- 4. 在LoudDog可以找到'makeSound'的key; +-- 等价于LoudDog.makeSound(seymour)。 + +-- 如果有必要,子类也可以有new(),与基类相似: +function LoudDog:new() + newObj = {} + -- 初始化newObj + self.__index = self + return setmetatable(newObj, self) +end + +---------------------------------------------------- +-- 4. 模块 +---------------------------------------------------- + + +--[[ 我把这部分给注释了,这样脚本剩下的部分可以运行 + +-- 假设文件mod.lua的内容类似这样: +local M = {} + +local function sayMyName() + print('Hrunkner') +end + +function M.sayHello() + print('Why hello there') + sayMyName() +end + +return M + +-- 另一个文件可以使用mod.lua的功能: +local mod = require('mod') -- 运行文件mod.lua. + +-- require是包含模块的标准做法。 +-- require等价于: (针对没有被缓存的情况;参见后面的内容) +local mod = (function () + +end)() +-- mod.lua被包在一个函数体中,因此mod.lua的局部变量 +-- 对外不可见。 + +-- 下面的代码可以工作,因为在这里mod = mod.lua 中的 M: +mod.sayHello() -- Says hello to Hrunkner. + +-- 这是错误的;sayMyName只在mod.lua中存在: +mod.sayMyName() -- 错误 + +-- require返回的值会被缓存,所以一个文件只会被运行一次, +-- 即使它被require了多次。 + +-- 假设mod2.lua包含代码"print('Hi!')"。 +local a = require('mod2') -- 打印Hi! +local b = require('mod2') -- 不再打印; a=b. + +-- dofile与require类似,但是不缓存: +dofile('mod2') --> Hi! +dofile('mod2') --> Hi! (再次运行,与require不同) + +-- loadfile加载一个lua文件,但是并不运行它。 +f = loadfile('mod2') -- Calling f() runs mod2.lua. + +-- loadstring是loadfile的字符串版本。 +g = loadstring('print(343)') --返回一个函数。 +g() -- 打印343; 在此之前什么也不打印。 + +--]] +``` + +## 参考 + + + +为什么?我非常兴奋地学习lua, 这样我就可以使用[Löve 2D游戏引擎](http://love2d.org/)来编游戏。 + +怎么做?我从[BlackBulletIV的面向程序员的Lua指南](http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/)入门。接着我阅读了官方的[Lua编程](http://www.lua.org/pil/contents.html)一书。 + +lua-users.org上的[Lua简明参考](http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf)应该值得一看。 + +本文没有涉及标准库的内容: + +* string library +* table library +* math library +* io library +* os library + +使用Lua,欢乐常在! -- cgit v1.2.3 From 820a822081ed965be820019fce63b939876b4901 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Wed, 12 Feb 2014 12:03:31 -0800 Subject: Update bash-cn.html.markdown --- zh-cn/bash-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index 2e885833..6afa659a 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -17,7 +17,7 @@ Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 Mac OS X 下的 [更多信息](http://www.gnu.org/software/bash/manual/bashref.html) ```bash -#!/bin/sh +#!/bin/bash # 脚本的第一行叫 shebang,用来告知系统如何执行该脚本: # 参见: http://en.wikipedia.org/wiki/Shebang_(Unix) # 如你所见,注释以 # 开头,shebang 也是注释。 -- cgit v1.2.3 From e0b9cd1a8bea27a950d2b8b26ce7329f51ce801a Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Fri, 14 Feb 2014 21:08:09 +0800 Subject: c-cn: improve translations - improve translations - translate the missing part --- zh-cn/c-cn.html.markdown | 394 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 311 insertions(+), 83 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown index b4bff8fc..ecd2558e 100644 --- a/zh-cn/c-cn.html.markdown +++ b/zh-cn/c-cn.html.markdown @@ -5,37 +5,52 @@ contributors: - ["Adam Bard", "http://adambard.com/"] translators: - ["Chenbo Li", "http://binarythink.net/"] + - ["Jakukyo Friel", "http://weakish.github.io"] lang: zh-cn --- C语言在今天仍然是高性能计算的主要选择。 -C大概是大多数程序员用到的最接近底层的语言了,但是C语言本身不仅可以用来提升程序运行的速度 -注意看看C语言的文档,你就会知道C语言在内存管理方面的强大也是其他语言无法比拟的。 +C大概是大多数程序员用到的最接近底层的语言了,C语言原生的速度就很高了,但是别忘了C的手动内存管理,它会让你将性能发挥到极致。 ```c -// 用“//”来实现单行注释 +// 单行注释以//开始。(仅适用于C99或更新的版本。) /* -多行注释是这个样子的 +多行注释是这个样子的。(C89也适用。) */ +// 常数: #define 关键词 +#define DAYS_IN_YEAR 365 + +// 以枚举的方式定义常数 +enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +// MON自动被定义为2,TUE被定义为3,以此类推。 + // 用#include来导入头文件 #include #include #include -// 函数的标签(signature)应该放在.h文件中,并且引入到程序顶部 -// 也可以直接放到你的.c文件的最上面 -void function_1(); -void function_2(); +// <尖括号>间的文件名是C标准库的头文件。 +// 标准库以外的头文件,使用双引号代替尖括号。 +#include "my_header.h" + +// 函数的签名可以事先在.h文件中定义, +// 也可以直接在.c文件的头部定义。 +void function_1(char c); +void function_2(void); -// c程序的入口是一个返回值为int型的函数,名字叫做main +// 如果函数出现在main()之后,那么必须在main()之前 +// 先声明一个函数原型 +int add_two_ints(int x1, int x2); // 函数原型 + +// 你的程序的入口是一个返回值为整型的main函数 int main() { -// 用printf来实现标准输出,这种输出也可以用格式来控制 -// %d 代表一个整数, \n 代表一个新行 -printf("%d\n", 0); // => 输出 0 +// 用printf打印到标准输出,可以设定格式, +// %d 代表整数, \n 代表换行 +printf("%d\n", 0); // => 打印 0 // 所有的语句都要以分号结束 /////////////////////////////////////// @@ -69,18 +84,29 @@ double x_double = 0.0; // 整数类型也可以有无符号的类型表示。这样这些变量就无法表示负数 // 但是无符号整数所能表示的范围就可以比原来的整数大一些 -unsigned char ux_char; unsigned short ux_short; unsigned int ux_int; unsigned long long ux_long_long; +// 单引号内的字符是机器的字符集中的整数。 +'0' // => 在ASCII字符集中是48 +'A' // => 在ASCII字符集中是65 + // char类型一定会占用1个字节,但是其他的类型却会因具体机器的不同而各异 // sizeof(T) 可以返回T类型在运行的机器上占用多少个字节 // 这样你的代码就可以在各处正确运行了 -// 比如 -printf("%lu\n", sizeof(int)); // => 4 (字长为4的机器上) - -// 数组必须要在开始被初始化为特定的长度 +// sizeof(obj)返回表达式(变量、字面量等)的尺寸 +printf("%zu\n", sizeof(int)); // => 4 (大多数的机器字长为4) + +// 如果`sizeof`的参数是一个表达式,那么这个参数不会被演算(VLA例外,见下) +// 它产生的值是编译期的常数 +int a = 1; +// size_t是一个无符号整型,表示对象的尺寸,至少2个字节 +size_t size = sizeof(a++); // a++ 不会被演算 +printf("sizeof(a++) = %zu where a = %d\n", size, a); +// 打印 "sizeof(a++) = 4 where a = 1" (在32位架构上) + +// 数组必须要被初始化为具体的长度 char my_char_array[20]; // 这个数组占据 1 * 20 = 20 个字节 int my_int_array[20]; // 这个数组占据 4 * 20 = 80 个字节 // (这里我们假设字长为4) @@ -89,48 +115,83 @@ int my_int_array[20]; // 这个数组占据 4 * 20 = 80 个字节 // 可以用下面的方法把数组初始化为0: char my_array[20] = {0}; -// 对数组任意存取就像其他语言的方式 -- 其实是其他的语言像C +// 索引数组和其他语言类似 -- 好吧,其实是其他的语言像C my_array[0]; // => 0 // 数组是可变的,其实就是内存的映射! my_array[1] = 2; printf("%d\n", my_array[1]); // => 2 +// 在C99 (C11中是可选特性),变长数组(VLA)也可以声明长度。 +// 其长度不用是编译期常量。 +printf("Enter the array size: "); // 询问用户数组长度 +char buf[0x100]; +fgets(buf, sizeof buf, stdin); + +// stroul 将字符串解析为无符号整数 +size_t size = strtoul(buf, NULL, 10); +int var_length_array[size]; // 声明VLA +printf("sizeof array = %zu\n", sizeof var_length_array); + +// 上述程序可能的输出为: +// > Enter the array size: 10 +// > sizeof array = 40 + // 字符串就是以 NUL (0x00) 这个字符结尾的字符数组, -// 这个字符可以用'\0'来表示. -// (在字符串字面值中我们不必输入这个字符,编译器会自动添加的) +// NUL可以用'\0'来表示. +// (在字符串字面量中我们不必输入这个字符,编译器会自动添加的) char a_string[20] = "This is a string"; printf("%s\n", a_string); // %s 可以对字符串进行格式化 - /* 也许你会注意到 a_string 实际上只有16个字节长. 第17个字节是一个空字符(NUL) -而第18, 19 和 20 个字符的值是不确定的。 +而第18, 19 和 20 个字符的值是未定义。 */ printf("%d\n", a_string[16]); // => 0 +// byte #17值为0(18,19,20同样为0) + +// 单引号间的字符是字符字面量 +// 它的类型是`int`,而 *不是* `char` +// (由于历史原因) +int cha = 'a'; // 合法 +char chb = 'a'; // 同样合法 (隐式类型转换 + +// 多维数组 +int multi_array[2][5] = { + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 0} + } +// 获取元素 +int array_int = multi_array[0][2]; // => 3 /////////////////////////////////////// // 操作符 /////////////////////////////////////// -int i1 = 1, i2 = 2; // 多个变量声明的简写 +// 多个变量声明的简写 +int i1 = 1, i2 = 2; float f1 = 1.0, f2 = 2.0; -// 算数运算 +int a, b, c; +a = b = c = 0; + +// 算数运算直截了当 i1 + i2; // => 3 i2 - i1; // => 1 i2 * i1; // => 2 -i1 / i2; // => 0 (0.5 会被化整为 0) +i1 / i2; // => 0 (0.5,但会被化整为 0) f1 / f2; // => 0.5, 也许会有很小的误差 +// 浮点数和浮点数运算都是近似值 // 取余运算 11 % 3; // => 2 -// 比较操作符我们也很熟悉, 但是有一点,C中没有布尔类型 +// 你多半会觉得比较操作符很熟悉, 不过C中没有布尔类型 // 而是用整形替代 -// 0 就是 false, 其他的就是 true. (比较操作符的返回值则仅有0和1) +// (C99中有_Bool或bool。) +// 0为假, 其他均为真. (比较操作符的返回值总是返回0或1) 3 == 2; // => 0 (false) 3 != 2; // => 1 (true) 3 > 2; // => 1 @@ -138,7 +199,14 @@ f1 / f2; // => 0.5, 也许会有很小的误差 2 <= 2; // => 1 2 >= 2; // => 1 -// 逻辑运算符需要作用于整数 +// C不是Python —— 连续比较不合法 +int a = 1; +// 错误 +int between_0_and_2 = 0 < a < 2; +// 正确 +int between_0_and_2 = 0 < a && a < 2; + +// 逻辑运算符适用于整数 !3; // => 0 (非) !0; // => 1 1 && 1; // => 1 (且) @@ -146,6 +214,20 @@ f1 / f2; // => 0.5, 也许会有很小的误差 0 || 1; // => 1 (或) 0 || 0; // => 0 +// 条件表达式 ( ? : ) +int a = 5; +int b = 10; +int z; +z = (a > b) ? a : b; // 10 “若a > b返回a,否则返回b。” + +// 增、减 +char *s = "iLoveC" +int j = 0; +s[j++]; // "i" 返回s的第j项,然后增加j的值。 +j = 0; +s[++j]; // => "L" 增加j的值,然后返回s的第j项。 +// j-- 和 --j 同理 + // 位运算 ~0x0F; // => 0xF0 (取反) 0x0F & 0xF0; // => 0x00 (和) @@ -154,6 +236,13 @@ f1 / f2; // => 0.5, 也许会有很小的误差 0x01 << 1; // => 0x02 (左移1位) 0x02 >> 1; // => 0x01 (右移1位) +// 对有符号整数进行移位操作要小心 —— 以下未定义: +// 有符号整数位移至符号位 int a = 1 << 32 +// 左移位一个负数 int a = -1 << 2 +// 移位超过或等于该类型数值的长度 +// int a = 1 << 32; // 假定int32位 + + /////////////////////////////////////// // 控制结构 /////////////////////////////////////// @@ -168,17 +257,17 @@ if (0) { // While循环 int ii = 0; -while (ii < 10) { +while (ii < 10) { // 任何非0的值均为真 printf("%d, ", ii++); // ii++ 在取值过后自增 -} // => 输出 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " +} // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); int kk = 0; do { printf("%d, ", kk); -} while (++kk < 10); // ++kk 先自增,在被取值 -// => 输出 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " +} while (++kk < 10); // ++kk 先自增,再被取值 +// => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); @@ -186,29 +275,55 @@ printf("\n"); int jj; for (jj=0; jj < 10; jj++) { printf("%d, ", jj); -} // => 输出 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " +} // => 打印 "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, " printf("\n"); +// *****注意*****: +// 循环和函数必须有主体部分,如果不需要主体部分: +int i; + for (i = 0; i <= 5; i++) { + ; // 使用分号表达主体(null语句) +} + +// 多重分支:switch() +switch (some_integral_expression) { +case 0: // 标签必须是整数常量表达式 + do_stuff(); + break; // 如果不使用break,控制结构会继续执行下面的标签 +case 1: + do_something_else(); + break; +default: + // 假设 `some_integral_expression` 不匹配任何标签 + fputs("error!\n", stderr); + exit(-1); + break; + } + /////////////////////////////////////// // 类型转换 /////////////////////////////////////// // 在C中每个变量都有类型,你可以将变量的类型进行转换 +// (有一定限制) -int x_hex = 0x01; // 可以用16进制赋值 +int x_hex = 0x01; // 可以用16进制字面量赋值 // 在类型转换时,数字本身的值会被保留下来 -printf("%d\n", x_hex); // => 输出 1 -printf("%d\n", (short) x_hex); // => 输出 1 -printf("%d\n", (char) x_hex); // => 输出 1 +printf("%d\n", x_hex); // => 打印 1 +printf("%d\n", (short) x_hex); // => 打印 1 +printf("%d\n", (char) x_hex); // => 打印 1 // 类型转换时可能会造成溢出,而且不会抛出警告 -printf("%d\n", (char) 257); // => 1 (char的最大值为255) +printf("%d\n", (char) 257); // => 1 (char的最大值为255,假定char为8位长) + +// 使用提供的CHAR_MAX、SCHAR_MAX和UCHAR_MAX宏可以确定`char`、`signed_char`和`unisigned char`的最大值。 + // 整数型和浮点型可以互相转换 -printf("%f\n", (float)100); // %f 表示单精度浮点 -printf("%lf\n", (double)100); // %lf 表示双精度浮点 +printf("%f\n", (float)100); // %f 格式化单精度浮点 +printf("%lf\n", (double)100); // %lf 格式化双精度浮点 printf("%d\n", (char)100.0); /////////////////////////////////////// @@ -216,67 +331,89 @@ printf("%d\n", (char)100.0); /////////////////////////////////////// // 指针变量是用来储存内存地址的变量 -// 指针变量的定义也会告诉你指向的地址的变量的类型 -// 你也可以得到某个变量的地址,并对它们进行操作 +// 指针变量的声明也会告诉它所指向的数据的类型 +// 你可以得到你的变量的地址,并对它们搞乱。 int x = 0; printf("%p\n", &x); // 用 & 来获取变量的地址 -// (%p 表示一个指针) -// => 输出某个内存地址 +// (%p 格式化一个类型为 void *的指针) +// => 打印某个内存地址 -// 指针类型在定义是需要以*结束 -int* px; // px是一个指向int型的指针 +// 指针类型在声明中以*开头 +int* px, not_a_pointer; // px是一个指向int型的指针 px = &x; // 把x的地址保存到px中 -printf("%p\n", px); // => 输出内存中的某个地址 +printf("%p\n", (void *)px); // => 输出内存中的某个地址 +printf("%zu, %zu\n", sizeof(px), sizeof(not_a_pointer)); +// => 在64位系统上打印“8, 4”。 -// 要得到某个指针指向的内容的值,可以在指针前加一个*来取得(去引用) +// 要得到某个指针指向的内容的值,可以在指针前加一个*来取得(取消引用) +// 注意: 是的,这可能让人困惑,'*'在用来声明一个指针的同时取消引用它。 printf("%d\n", *px); // => 输出 0, 即x的值 // 你也可以改变指针所指向的值 -// 此时你需要在*运算符后添加一个括号,因为++比*的优先级更高 -(*px)++; // 把px所指向的值增加2 +// 此时你需要取消引用上添加括号,因为++比*的优先级更高 +(*px)++; // 把px所指向的值增加1 printf("%d\n", *px); // => 输出 1 printf("%d\n", x); // => 输出 1 -int x_array[20]; // 数组是分配一系列连续空间的常用方式 +// 数组是分配一系列连续空间的常用方式 +int x_array[20]; int xx; for (xx=0; xx<20; xx++) { x_array[xx] = 20 - xx; } // 初始化 x_array 为 20, 19, 18,... 2, 1 -// 生命一个变量为指向整型的指针类型,并初始化为指向x_array +// 声明一个整型的指针,并初始化为指向x_array int* x_ptr = x_array; // x_ptr现在指向了数组的第一个元素(即整数20). - -// 事实上数组本身就是指向它的第一个元素的指针 -printf("%d\n", *(x_ptr)); // => 输出 20 -printf("%d\n", x_array[0]); // => 输出 20 +// 这是因为数组通常衰减为指向它们的第一个元素的指针。 +// 例如,当一个数组被传递给一个函数或者绑定到一个指针时, +//它衰减为(隐式转化为)一个指针。 +// 例外: 当数组是`&`操作符的参数: +int arr[10]; +int (*ptr_to_arr)[10] = &arr; // &arr的类型不是`int *`! + // 它的类型是指向数组的指针(数组由10个int组成) +// 或者当数组是字符串字面量(初始化字符数组) +char arr[] = "foobarbazquirk"; +// 或者当它是`sizeof`或`alignof`操作符的参数时: +int arr[10]; +int *ptr = arr; // 等价于 int *ptr = &arr[0]; +printf("%zu, %zu\n", sizeof arr, sizeof ptr); // 应该会输出"40, 4"或"40, 8" // 指针的增减多少是依据它本身的类型而定的 -printf("%d\n", *(x_ptr + 1)); // => 输出 19 -printf("%d\n", x_array[1]); // => 输出 19 +// (这被称为指针算术) +printf("%d\n", *(x_ptr + 1)); // => 打印 19 +printf("%d\n", x_array[1]); // => 打印 19 // 你也可以通过标准库函数malloc来实现动态分配 -// 这个函数接受一个代表容量的参数 -// 系统会从堆区分配指定容量字节大小的空间 -int* my_ptr = (int*) malloc(sizeof(int) * 20); +// 这个函数接受一个代表容量的参数,参数类型为`size_t` +// 系统一般会从堆区分配指定容量字节大小的空间 +// (在一些系统,例如嵌入式系统中这点不一定成立 +// C标准对此未置一词。) +int *my_ptr = malloc(sizeof(*my_ptr) * 20); for (xx=0; xx<20; xx++) { - *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx 也可以 -} // 初始化内存为 20, 19, 18, 17... 2, 1 (as ints) + *(my_ptr + xx) = 20 - xx; // my_ptr[xx] = 20-xx +} // 初始化内存为 20, 19, 18, 17... 2, 1 (类型为int) -// 如果对一些未分配的内存取值则会得到未知的结果 +// 对未分配的内存进行取消引用会产生未定义的结果 printf("%d\n", *(my_ptr + 21)); // => 谁知道会输出什么 -// 当你通过malloc得到一块区域后,你需要释放它 +// malloc分配的区域需要手动释放 // 否则没人能够再次使用这块内存,直到程序结束为止 free(my_ptr); // 字符串通常是字符数组,但是经常用字符指针表示 -// 指针: -char* my_str = "This is my very own string"; - +// (它是指向数组的第一个元素的指针) +// 一个优良的实践是使用`const char *`来引用一个字符串字面量, +// 因为字符串字面量不应当被修改(即"foo"[0] = 'a'犯了大忌) +const char* my_str = "This is my very own string"; printf("%c\n", *my_str); // => 'T' +// 如果字符串是数组,(多半是用字符串字面量初始化的) +// 情况就不一样了,字符串位于可写的内存中 +char foo[] = "foo"; +foo[0] = 'a'; // 这是合法的,foo现在包含"aoo" + function_1(); } // main函数结束 @@ -292,16 +429,21 @@ int add_two_ints(int x1, int x2){ } /* -函数是按值传递的, 但是你可以通过传递参数来传递引用,这样函数就可以更改值 +函数是按值传递的。当调用一个函数的时候,传递给函数的参数 +是原有值的拷贝(数组除外)。你在函数内对参数所进行的操作 +不会改变该参数原有的值。 + +但是你可以通过指针来传递引用,这样函数就可以更改值 例子:字符串本身翻转 */ // 类型为void的函数没有返回值 -void str_reverse(char* str_in){ +void str_reverse(char *str_in){ char tmp; - int ii=0, len = strlen(str_in); // Strlen 是C标准库函数 - for(ii=0; ii ".tset a si sihT" */ +// 如果引用函数之外的变量,必须使用extern关键字 +int i = 0; +void testFunc() { + extern int i; // 使用外部变量 i +} + +// 使用static确保external变量为源文件私有 +static int i = 0; // 其他使用 testFunc()的文件无法访问变量i +void testFunc() { + extern int i; +} +//**你同样可以声明函数为static** + + /////////////////////////////////////// // 用户自定义类型和结构 /////////////////////////////////////// @@ -322,12 +478,16 @@ printf("%s\n", c); // => ".tset a si sihT" typedef int my_type; my_type my_type_var = 0; -// 结构是一系列数据的集合 +// struct是数据的集合,成员依序分配,按照 +// 编写的顺序 struct rectangle { int width; int height; }; +// 一般而言,以下断言不成立: +// sizeof(struct rectangle) == sizeof(int) + sizeof(int) +//这是因为structure成员之间可能存在潜在的间隙(为了对齐)[1] void function_1(){ @@ -338,12 +498,12 @@ void function_1(){ my_rec.height = 20; // 你也可以声明指向结构体的指针 - struct rectangle* my_rec_ptr = &my_rec; + struct rectangle *my_rec_ptr = &my_rec; - // 通过取值来改变结构体的成员... + // 通过取消引用来改变结构体的成员... (*my_rec_ptr).width = 30; - // ... 或者用 -> 操作符作为简写 + // ... 或者用 -> 操作符作为简写提高可读性 my_rec_ptr->height = 10; // Same as (*my_rec_ptr).height = 10; } @@ -354,18 +514,25 @@ int area(rect r){ return r.width * r.height; } +// 如果struct较大,你可以通过指针传递,避免 +// 复制整个struct。 +int area(const rect *r) +{ + return r->width * r->height; +} + /////////////////////////////////////// // 函数指针 /////////////////////////////////////// /* 在运行时,函数本身也被存放到某块内存区域当中 -函数指针就像其他指针一样, 但却可以被用来直接调用函数, -并且可以被四处传递(就像回调函数那样) -但是,定义的语法有可能在一开始会有些误解 +函数指针就像其他指针一样(不过是存储一个内存地址) 但却可以被用来直接调用函数, +并且可以四处传递回调函数 +但是,定义的语法初看令人有些迷惑 例子:通过指针调用str_reverse */ -void str_reverse_through_pointer(char * str_in) { +void str_reverse_through_pointer(char *str_in) { // 定义一个函数指针 f. void (*f)(char *); // 签名一定要与目标函数相同 f = &str_reverse; // 将函数的地址在运行时赋给指针 @@ -374,7 +541,7 @@ void str_reverse_through_pointer(char * str_in) { } /* -只要函数签名是正确的,任何时候都能将正确的函数赋给某个函数指针 +只要函数签名是正确的,任何时候都能将任何函数赋给某个函数指针 为了可读性和简洁性,函数指针经常和typedef搭配使用: */ @@ -384,12 +551,73 @@ typedef void (*my_fnp_type)(char *); // ... // my_fnp_type f; +// 特殊字符 +'\a' // bell +'\n' // 换行 +'\t' // tab +'\v' // vertical tab +'\f' // formfeed +'\r' // 回车 +'\b' // 退格 +'\0' // null,通常置于字符串的最后。 + // hello\n\0. 按照惯例,\0用于标记字符串的末尾。 +'\\' // 反斜杠 +'\?' // 问号 +'\'' // 单引号 +'\"' // 双引号 +'\xhh' // 十六进制数字. 例子: '\xb' = vertical tab +'\ooo' // 十进制数字. 例子: '\013' = vertical tab + +// 打印格式: +"%d" // 整数 +"%3d" // 3位以上整数 (右对齐文本) +"%s" // 字符串 +"%f" // float +"%ld" // long +"%3.2f" // 左3位以上、右2位以上十进制浮 +"%7.4s" // (字符串同样适用) +"%c" // 字母 +"%p" // 指针 +"%x" // 十六进制 +"%o" // 十进制 +"%%" // 打印 % + +/////////////////////////////////////// +// 演算优先级 +/////////////////////////////////////// +//---------------------------------------------------// +// 操作符 | 组合 // +//---------------------------------------------------// +// () [] -> . | 从左到右 // +// ! ~ ++ -- + = *(type)sizeof | 从右到左 // +// * / % | 从左到右 // +// + - | 从左到右 // +// << >> | 从左到右 // +// < <= > >= | 从左到右 // +// == != | 从左到右 // +// & | 从左到右 // +// ^ | 从左到右 // +// | | 从左到右 // +// && | 从左到右 // +// || | 从左到右 // +// ?: | 从右到左 // +// = += -= *= /= %= &= ^= |= <<= >>= | 从右到左 // +// , | 从左到右 // +//---------------------------------------------------// + ``` ## 更多阅读 -最好找一本 [K&R, aka "The C Programming Language", “C程序设计语言”](https://en.wikipedia.org/wiki/The_C_Programming_Language) +最好找一本 [K&R, aka "The C Programming Language", “C程序设计语言”](https://en.wikipedia.org/wiki/The_C_Programming_Language)。它是关于C最重要的一本书,由C的创作者撰写。不过需要留意的是它比较古老了,因此有些不准确的地方。 + -其他一些比较好的资源 [Learn C the hard way](http://c.learncodethehardway.org/book/) +另一个比较好的资源是 [Learn C the hard way](http://c.learncodethehardway.org/book/) +如果你有问题,请阅读[compl.lang.c Frequently Asked Questions](http://c-faq.com/)。 + +使用合适的空格、缩进,保持一致的代码风格非常重要。可读性强的代码比聪明的代码、高速的代码更重要。可以参考下[Linux内核编码风格](https://www.kernel.org/doc/Documentation/CodingStyle) +。 除了这些,多多Google吧 + +[1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member -- cgit v1.2.3 From 4b8b6240154e1bcb87edfd95d3a1eaf22341f450 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Sat, 15 Feb 2014 21:37:58 +0800 Subject: c-cn: typo --- zh-cn/c-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown index ecd2558e..223f6e35 100644 --- a/zh-cn/c-cn.html.markdown +++ b/zh-cn/c-cn.html.markdown @@ -331,8 +331,8 @@ printf("%d\n", (char)100.0); /////////////////////////////////////// // 指针变量是用来储存内存地址的变量 -// 指针变量的声明也会告诉它所指向的数据的类型 -// 你可以得到你的变量的地址,并对它们搞乱。 +// 指针变量的声明也会告诉它所指向的数据的类型 +// 你可以使用得到你的变量的地址,并把它们搞乱,;-) int x = 0; printf("%p\n", &x); // 用 & 来获取变量的地址 -- cgit v1.2.3 From c3b6e57e99bfff589399d3c33350ed00ca48c41d Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Thu, 20 Feb 2014 18:12:26 +0800 Subject: clojure-cn: contributor and translator information The translator add his/her name to contributor instead of translator. --- zh-cn/clojure-cn.html.markdown | 2 ++ 1 file changed, 2 insertions(+) (limited to 'zh-cn') diff --git a/zh-cn/clojure-cn.html.markdown b/zh-cn/clojure-cn.html.markdown index d5d8232b..fa241384 100644 --- a/zh-cn/clojure-cn.html.markdown +++ b/zh-cn/clojure-cn.html.markdown @@ -2,6 +2,8 @@ language: clojure filename: learnclojure-cn.clj contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: - ["Bill Zhang", "http://jingege.github.io/"] lang: zh-cn --- -- cgit v1.2.3 From 0d63865f21f143eb85b65c1cbcaba4769c2cb8cd Mon Sep 17 00:00:00 2001 From: Abner Date: Tue, 25 Feb 2014 17:33:02 -0500 Subject: Create visualbasic-cn.html.markdown First Version of Translate. --- zh-cn/visualbasic-cn.html.markdown | 272 +++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 zh-cn/visualbasic-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/visualbasic-cn.html.markdown b/zh-cn/visualbasic-cn.html.markdown new file mode 100644 index 00000000..fa5db923 --- /dev/null +++ b/zh-cn/visualbasic-cn.html.markdown @@ -0,0 +1,272 @@ +--- +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() + End Sub + + ' 二 + Private Sub HelloWorldInput() + Console.Title = "Hello World YourName | Learn X in Y Minutes" + ' 变量 + ' 用来存储用户输入的数据 + ' 变量声明以 Dim 开始,结尾为 As VariableType (变量类型). + + ' 此教程中,我们希望知道你的姓名,并让程序记录并输出。 + Dim username As String + ' 我们使用字符串类型(String)来记录文本信息。 + Console.WriteLine("Hello, What is your name? ") ' 询问用户输入姓名 + username = Console.ReadLine() 'Stores the users name. + Console.WriteLine("Hello " + username) ' 输出将是 Hello '姓名' + Console.ReadLine() 'Outsputs the above. + ' 以上程序将询问你的姓名,并和你打招呼。 + ' 其它变量如整型(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 'We use the variable "String" as the answer is text + 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" + ' 声明变量和步长(即递减的速度,如-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条件语句。 + ' If语句就好似个自动售货机,当用户输入A1,A2,A3,等去选择物品时, + ' 所有的选择可以合并到一个If语句中 + + Dim selection As String = Console.ReadLine 'Value for selection + 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,这里还有更深层次的 VB教学(英文)。 + +所有代码均通过测试。只需复制粘帖到Visual Basic中,并按F5运行即可。 -- cgit v1.2.3 From b1ad921af57d17631f73316dfca3aa39425bbd72 Mon Sep 17 00:00:00 2001 From: Abner Date: Tue, 25 Feb 2014 17:35:27 -0500 Subject: Slight change the format. --- zh-cn/visualbasic-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/visualbasic-cn.html.markdown b/zh-cn/visualbasic-cn.html.markdown index fa5db923..4459a2cd 100644 --- a/zh-cn/visualbasic-cn.html.markdown +++ b/zh-cn/visualbasic-cn.html.markdown @@ -2,7 +2,7 @@ language: Visual Basic contributors: - ["Brian Martin", "http://brianmartin.biz"] - translators: +translators: - ["Abner Chou", "http://github.com/NoahDragon"] lang: zh-cn filename: learnvisualbasic.vb-cn @@ -74,7 +74,7 @@ Module Module1 ' 一、对应程序目录1,下同 - ' 使用 private subs 来区分程序块. + ' 使用 private subs 声明函数。 Private Sub HelloWorldOutput() ' 程序名 Console.Title = "Hello World Ouput | Learn X in Y Minutes" -- cgit v1.2.3 From e31bfb31f7762aaded54f51d87ee883fb49f5d82 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Wed, 26 Feb 2014 15:51:07 +0800 Subject: clojure-macro: chinese translation --- zh-cn/clojure-macro-cn.html.markdown | 151 +++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 zh-cn/clojure-macro-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/clojure-macro-cn.html.markdown b/zh-cn/clojure-macro-cn.html.markdown new file mode 100644 index 00000000..e1b68a83 --- /dev/null +++ b/zh-cn/clojure-macro-cn.html.markdown @@ -0,0 +1,151 @@ +--- +language: "clojure macros" +filename: learnclojuremacros.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Jakukyo Friel", "http://weakish.github.io"] +--- + +和所有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)) +;; -> (# "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 -- cgit v1.2.3 From c9a51abc13ba6ae2ffe012f8ef443b4e13b54692 Mon Sep 17 00:00:00 2001 From: Abner Date: Wed, 26 Feb 2014 09:39:03 -0500 Subject: Update visualbasic-cn.html.markdown fix some typoes and untranslated comments. change some expression to make user more easily understand. --- zh-cn/visualbasic-cn.html.markdown | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/visualbasic-cn.html.markdown b/zh-cn/visualbasic-cn.html.markdown index 4459a2cd..95f01ed6 100644 --- a/zh-cn/visualbasic-cn.html.markdown +++ b/zh-cn/visualbasic-cn.html.markdown @@ -13,10 +13,10 @@ Module Module1 Sub Main() ' 让我们先从简单的终端程序学起。 - ' 单引号用来生成注释(注意是半角单引号,非全角单引好’) + ' 单引号用来生成注释(注意是半角单引号,非全角单引号’) ' 为了方便运行此示例代码,我写了个目录索引。 - ' 可能你还不了解以下代码的意义,但随着教程的深入,你会 - ' 渐渐理解其用法。 + ' 可能你还不了解以下代码的意义,但随着教程的深入, + ' 你会渐渐理解其用法。 Console.Title = ("Learn X in Y Minutes") Console.WriteLine("NAVIGATION") ' 显示目录 Console.WriteLine("") @@ -26,10 +26,10 @@ Module Module1 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("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("9. Select A Drink") ' 选饮料 Console.WriteLine("50. About") ' 关于 Console.WriteLine("Please Choose A Number From The Above List") Dim selection As String = Console.ReadLine @@ -61,7 +61,7 @@ Module Module1 Case "9" ' If/Else 条件语句 Console.Clear() IfElseStatement() ' 选饮料 - Case "50" ' 关于 + Case "50" ' 关于本程序和作者 Console.Clear() Console.Title = ("Learn X in Y Minutes :: About") MsgBox("This tutorial is by Brian Martin (@BrianMartinn") @@ -81,7 +81,9 @@ Module Module1 ' 使用 Console.Write("") 或者 Console.WriteLine("") 来输出文本到屏幕上 ' 对应的 Console.Read() 或 Console.Readline() 用来读取键盘输入 Console.WriteLine("Hello World") - Console.ReadLine() + Console.ReadLine() + ' Console.WriteLine()后加Console.ReadLine()是为了防止屏幕输出信息一闪而过 + ' 类似平时常见的“单击任意键继续”的意思。 End Sub ' 二 @@ -93,11 +95,11 @@ Module Module1 ' 此教程中,我们希望知道你的姓名,并让程序记录并输出。 Dim username As String - ' 我们使用字符串类型(String)来记录文本信息。 + ' 我们定义username使用字符串类型(String)来记录用户姓名。 Console.WriteLine("Hello, What is your name? ") ' 询问用户输入姓名 - username = Console.ReadLine() 'Stores the users name. - Console.WriteLine("Hello " + username) ' 输出将是 Hello '姓名' - Console.ReadLine() 'Outsputs the above. + username = Console.ReadLine() ' 存储用户名到变量 username + Console.WriteLine("Hello " + username) ' 输出将是 Hello + username + Console.ReadLine() ' 暂停屏幕并显示以上输出 ' 以上程序将询问你的姓名,并和你打招呼。 ' 其它变量如整型(Integer)我们用整型来处理整数。 End Sub @@ -166,7 +168,7 @@ Module Module1 ' 这次我们将询问用户是否继续 (Yes or No?) ' 我们将使用Do While循环,因为我们不知到用户是否需要使用一次以上。 Console.Title = "UsingDoWhileLoops | Learn X in Y Minutes" - Dim answer As String 'We use the variable "String" as the answer is text + Dim answer As String ' 我们使用字符串变量来存储answer(答案) Do ' 循环开始 Console.Write("First number: ") Dim a As Double = Console.ReadLine @@ -201,7 +203,7 @@ Module Module1 ' 这个程序我们将实现从10倒数计数. Console.Title = "Using For Loops | Learn X in Y Minutes" - ' 声明变量和步长(即递减的速度,如-1,-2,-3等)。 + ' 声明变量和Step (步长,即递减的速度,如-1,-2,-3等)。 For i As Integer = 10 To 0 Step -1 Console.WriteLine(i.ToString) ' 将计数结果输出的屏幕 Next i ' 计算新的i值 @@ -230,11 +232,11 @@ Module Module1 Private Sub IfElseStatement() Console.Title = "If / Else Statement | Learn X in Y Minutes" ' 有时候我们需要考虑多于两种情况。 - ' 这时我们就需要使用If条件语句。 + ' 这时我们就需要使用If/ElesIf条件语句。 ' If语句就好似个自动售货机,当用户输入A1,A2,A3,等去选择物品时, ' 所有的选择可以合并到一个If语句中 - Dim selection As String = Console.ReadLine 'Value for selection + 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 胡椒医生 -- cgit v1.2.3 From 41edfb0c104e9a870e1bef5c59c97d8452b74535 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Thu, 27 Feb 2014 14:18:35 -0800 Subject: Update clojure-macro-cn.html.markdown --- zh-cn/clojure-macro-cn.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/clojure-macro-cn.html.markdown b/zh-cn/clojure-macro-cn.html.markdown index e1b68a83..9324841e 100644 --- a/zh-cn/clojure-macro-cn.html.markdown +++ b/zh-cn/clojure-macro-cn.html.markdown @@ -1,10 +1,11 @@ --- language: "clojure macros" -filename: learnclojuremacros.clj +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)使得你可以穷尽语言的特性,编写生成代码的子过程——“宏”。宏是一种按需调制语言的强大方式。 -- cgit v1.2.3 From 08f2ae632429f032f524a94226485cd6d69aa91d Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Mon, 10 Mar 2014 16:53:27 +0800 Subject: common-lisp-cn: refine Chinese translation Typos & refinements. --- zh-cn/common-lisp-cn.html.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'zh-cn') 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,即开始求值); ;; “@”符号则表示将当前的参数插入到当前整个列表中。 -- cgit v1.2.3 From ef16c2025e11b26f0589cd3719e55237abbb8a35 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Fri, 14 Mar 2014 18:18:23 +0000 Subject: Fix syntax errors in coffeescript headers --- zh-cn/coffeescript-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/coffeescript-cn.html.markdown b/zh-cn/coffeescript-cn.html.markdown index 8fb96749..44561541 100644 --- a/zh-cn/coffeescript-cn.html.markdown +++ b/zh-cn/coffeescript-cn.html.markdown @@ -2,9 +2,9 @@ language: coffeescript contributors: - ["Tenor Biel", "http://github.com/L8D"] - - ["Xavier Yao"], "http://github.com/xavieryao"] + - ["Xavier Yao", "http://github.com/xavieryao"] translators: - - ["Xavier Yao"], "http://github.com/xavieryao"] + - ["Xavier Yao", "http://github.com/xavieryao"] filename: coffeescript-cn.coffee lang: zh-cn --- -- cgit v1.2.3 From 4480f889f8d87e6ccbe3c5536c0efd869be3f97f Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Thu, 20 Mar 2014 16:41:52 +0800 Subject: csharp: Chinese translation --- zh-cn/csharp-cn.html.markdown | 797 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 797 insertions(+) create mode 100644 zh-cn/csharp-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/csharp-cn.html.markdown b/zh-cn/csharp-cn.html.markdown new file mode 100644 index 00000000..618050a0 --- /dev/null +++ b/zh-cn/csharp-cn.html.markdown @@ -0,0 +1,797 @@ +--- +language: c# +contributors: + - ["Irfan Charania", "https://github.com/irfancharania"] + - ["Max Yankov", "https://github.com/golergka"] + - ["Melvyn Laïly", "http://x2a.yt"] + - ["Shaun McCarthy", "http://www.shaunmccarthy.com"] +translathors: + - ["Jakukyo Friel", "http://weakish.github.io"] +filename: LearnCSharp-cn.cs +--- + + +C#是一个优雅的、类型安全的面向对象语言。使用C#,开发者可以在.NET框架下构建安全、健壮的应用程序。 + +[更多关于C#的介绍](http://msdn.microsoft.com/en-us/library/vstudio/z1zx9t92.aspx) + +```c# +// 单行注释以 // 开始 +/* +多行注释是这样的 +*/ +/// +/// XML文档注释 +/// + +// 声明应用用到的命名空间 +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Net; +using System.Threading.Tasks; +using System.IO; + +// 定义作用域,将代码组织成包 +namespace Learning +{ + // 每个 .cs 文件至少需要包含一个和文件名相同的类 + // 你可以不这么干,但是这样不好。 + public class LearnCSharp + { + // 基本语法 - 如果你以前用过 Java 或 C++ 的话,可以直接跳到后文「有趣的特性」 + public static void Syntax() + { + // 使用 Console.WriteLine 打印信息 + Console.WriteLine("Hello World"); + Console.WriteLine( + "Integer: " + 10 + + " Double: " + 3.14 + + " Boolean: " + true); + + // 使用 Console.Write 打印,不带换行符号 + Console.Write("Hello "); + Console.Write("World"); + + /////////////////////////////////////////////////// + // 类型和变量 + // + // 使用 定义变量 + /////////////////////////////////////////////////// + + // Sbyte - 有符号 8-bit 整数 + // (-128 <= sbyte <= 127) + sbyte fooSbyte = 100; + + // Byte - 无符号 8-bit 整数 + // (0 <= byte <= 255) + byte fooByte = 100; + + // Short - 16-bit 整数 + // 有符号 - (-32,768 <= short <= 32,767) + // 无符号 - (0 <= ushort <= 65,535) + short fooShort = 10000; + ushort fooUshort = 10000; + + // Integer - 32-bit 整数 + int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647) + uint fooUint = 1; // (0 <= uint <= 4,294,967,295) + + // Long - 64-bit 整数 + long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) + ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615) + // 数字默认为 int 或 uint (取决于尺寸) + // 使用 L 标明变量值类型为long 或 ulong + + // Double - 双精度 64-bit IEEE 754 浮点数 + double fooDouble = 123.4; // 精度: 15-16 位 + + // Float - 单精度 32-bit IEEE 754 浮点数 + float fooFloat = 234.5f; // 精度: 7 位 + // 使用 f 标明变量值类型为float + + // Decimal - 128-bits 数据类型,比其他浮点类型精度更高 + // 适合财务、金融 + decimal fooDecimal = 150.3m; + + // 布尔值 - true & false + bool fooBoolean = true; // 或 false + + // Char - 单个 16-bit Unicode 字符 + char fooChar = 'A'; + + // 字符串 -- 和前面的基本类型不同,字符串不是值,而是引用。 + // 这意味着你可以将字符串设为null。 + string fooString = "\"escape\" quotes and add \n (new lines) and \t (tabs)"; + Console.WriteLine(fooString); + + // 你可以通过索引访问字符串的每个字符: + char charFromString = fooString[1]; // => 'e' + // 字符串不可修改: fooString[1] = 'X' 是行不通的; + + // 根据当前的locale设定比较字符串,大小写不敏感 + string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase); + + // 基于sprintf的字符串格式化 + string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2); + + // 日期和格式 + DateTime fooDate = DateTime.Now; + Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); + + // 使用 @ 符号可以创建跨行的字符串。使用 "" 来表示 " + string bazString = @"Here's some stuff +on a new line! ""Wow!"", the masses cried"; + + // 使用const或read-only定义常量 + // 常量在编译期演算 + const int HOURS_I_WORK_PER_WEEK = 9001; + + /////////////////////////////////////////////////// + // 数据结构 + /////////////////////////////////////////////////// + + // 数组 - 从0开始计数 + // 声明数组时需要确定数组长度 + // 声明数组的格式如下: + // [] = new []; + int[] intArray = new int[10]; + + // 声明并初始化数组的其他方式: + int[] y = { 9000, 1000, 1337 }; + + // 访问数组的元素 + Console.WriteLine("intArray @ 0: " + intArray[0]); + // 数组可以修改 + intArray[1] = 1; + + // 列表 + // 列表比数组更常用,因为列表更灵活。 + // 声明列表的格式如下: + // List = new List(); + List intList = new List(); + List stringList = new List(); + List z = new List { 9000, 1000, 1337 }; // i + // <>用于泛型 - 参考下文 + + // 列表无默认值 + // 访问列表元素时必须首先添加元素 + intList.Add(1); + Console.WriteLine("intList @ 0: " + intList[0]); + + // 其他数据结构: + // 堆栈/队列 + // 字典 (哈希表的实现) + // 哈希集合 + // 只读集合 + // 元组 (.Net 4+) + + /////////////////////////////////////// + // 操作符 + /////////////////////////////////////// + Console.WriteLine("\n->Operators"); + + int i1 = 1, i2 = 2; // 多重声明的简写形式 + + // 算术直截了当 + Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3 + + // 取余 + Console.WriteLine("11%3 = " + (11 % 3)); // => 2 + + // 比较操作符 + Console.WriteLine("3 == 2? " + (3 == 2)); // => false + Console.WriteLine("3 != 2? " + (3 != 2)); // => true + Console.WriteLine("3 > 2? " + (3 > 2)); // => true + Console.WriteLine("3 < 2? " + (3 < 2)); // => false + Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true + Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true + + // 位操作符 + /* + ~ 取反 + << 左移(有符号) + >> 右移(有符号) + & 与 + ^ 异或 + | 或 + */ + + // 自增、自减 + int i = 0; + Console.WriteLine("\n->Inc/Dec-rementation"); + Console.WriteLine(i++); //i = 1. 事后自增 + Console.WriteLine(++i); //i = 2. 事先自增 + Console.WriteLine(i--); //i = 1. 事后自减 + Console.WriteLine(--i); //i = 0. 事先自减 + + /////////////////////////////////////// + // 控制结构 + /////////////////////////////////////// + Console.WriteLine("\n->Control Structures"); + + // 类似C的if语句 + int j = 10; + if (j == 10) + { + Console.WriteLine("I get printed"); + } + else if (j > 10) + { + Console.WriteLine("I don't"); + } + else + { + Console.WriteLine("I also don't"); + } + + // 三元表达式 + // 简单的 if/else 语句可以写成: + // <条件> ? <真> : <假> + string isTrue = (true) ? "True" : "False"; + + // While 循环 + int fooWhile = 0; + while (fooWhile < 100) + { + //迭代 100 次, fooWhile 0->99 + fooWhile++; + } + + // Do While 循环 + int fooDoWhile = 0; + do + { + //迭代 100 次, fooDoWhile 0->99 + fooDoWhile++; + } while (fooDoWhile < 100); + + //for 循环结构 => for(<初始条件>; <条件>; <步>) + for (int fooFor = 0; fooFor < 10; fooFor++) + { + //迭代10次, fooFor 0->9 + } + + // foreach循环 + // foreach 循环结构 => foreach(<迭代器类型> <迭代器> in <可枚举结构>) + // foreach 循环适用于任何实现了 IEnumerable 或 IEnumerable 的对象。 + // .Net 框架下的集合类型(数组, 列表, 字典...) + // 都实现了这些接口 + // (下面的代码中,ToCharArray()可以删除,因为字符串同样实现了IEnumerable) + foreach (char character in "Hello World".ToCharArray()) + { + //迭代字符串中的所有字符 + } + + // Switch 语句 + // switch 适用于 byte、short、char和int 数据类型。 + // 同样适用于可枚举的类型 + // 包括字符串类, 以及一些封装了原始值的类: + // Character、Byte、Short和Integer。 + int month = 3; + string monthString; + switch (month) + { + case 1: + monthString = "January"; + break; + case 2: + monthString = "February"; + break; + case 3: + monthString = "March"; + break; + // 你可以一次匹配多个case语句 + // 但是你在添加case语句后需要使用break + // (否则你需要显式地使用goto case x语句) + case 6: + case 7: + case 8: + monthString = "Summer time!!"; + break; + default: + monthString = "Some other month"; + break; + } + + /////////////////////////////////////// + // 转换、指定数据类型 + /////////////////////////////////////// + + // 转换类型 + + // 转换字符串为整数 + // 转换失败会抛出异常 + int.Parse("123");//返回整数类型的"123" + + // TryParse会尝试转换类型,失败时会返回缺省类型 + // 例如 0 + int tryInt; + if (int.TryParse("123", out tryInt)) // Funciton is boolean + Console.WriteLine(tryInt); // 123 + + // 转换整数为字符串 + // Convert类提供了一系列便利转换的方法 + Convert.ToString(123); + // or + tryInt.ToString(); + } + + /////////////////////////////////////// + // 类 + /////////////////////////////////////// + public static void Classes() + { + // 参看文件尾部的对象声明 + + // 使用new初始化对象 + Bicycle trek = new Bicycle(); + + // 调用对象的方法 + trek.SpeedUp(3); // 你应该一直使用setter和getter方法 + trek.Cadence = 100; + + // 查看对象的信息. + Console.WriteLine("trek info: " + trek.Info()); + + // 实例化一个新的Penny Farthing + PennyFarthing funbike = new PennyFarthing(1, 10); + Console.WriteLine("funbike info: " + funbike.Info()); + + Console.Read(); + } // 结束main方法 + + // 终端程序 终端程序必须有一个main方法作为入口 + public static void Main(string[] args) + { + OtherInterestingFeatures(); + } + + // + // 有趣的特性 + // + + // 默认方法签名 + + public // 可见性 + static // 允许直接调用类,无需先创建实例 + int, //返回值 + MethodSignatures( + int maxCount, // 第一个变量,类型为整型 + int count = 0, // 如果没有传入值,则缺省值为0 + int another = 3, + params string[] otherParams // 捕获其他参数 + ) + { + return -1; + } + + // 方法可以重名,只要签名不一样 + public static void MethodSignature(string maxCount) + { + } + + //泛型 + // TKey和TValue类由用用户调用函数时指定。 + // 以下函数模拟了Python的SetDefault + public static TValue SetDefault( + IDictionary dictionary, + TKey key, + TValue defaultItem) + { + TValue result; + if (!dictionary.TryGetValue(key, out result)) + return dictionary[key] = defaultItem; + return result; + } + + // 你可以限定传入值的范围 + public static void IterateAndPrint(T toPrint) where T: IEnumerable + { + // 我们可以进行迭代,因为T是可枚举的 + foreach (var item in toPrint) + // ittm为整数 + Console.WriteLine(item.ToString()); + } + + public static void OtherInterestingFeatures() + { + // 可选参数 + MethodSignatures(3, 1, 3, "Some", "Extra", "Strings"); + MethodSignatures(3, another: 3); // 显式指定参数,忽略可选参数 + + // 扩展方法 + int i = 3; + i.Print(); // 参见下面的定义 + + // 可为null的类型 对数据库交互、返回值很有用 + // 任何值类型 (i.e. 不为类) 添加后缀 ? 后会变为可为null的值 + // <类型>? <变量名> = <值> + int? nullable = null; // Nullable 的简写形式 + Console.WriteLine("Nullable variable: " + nullable); + bool hasValue = nullable.HasValue; // 不为null时返回真 + // ?? 是用于指定默认值的语法糖 + // 以防变量为null的情况 + int notNullable = nullable ?? 0; // 0 + + // 变量类型推断 - 你可以让编译器推断变量类型: + var magic = "编译器确定magic是一个字符串,所以仍然是类型安全的"; + // magic = 9; // 不工作,因为magic是字符串,而不是整数。 + + // 泛型 + // + var phonebook = new Dictionary() { + {"Sarah", "212 555 5555"} // 在电话簿中加入新条目 + }; + + // 调用上面定义为泛型的SETDEFAULT + Console.WriteLine(SetDefault(phonebook, "Shaun", "No Phone")); // 没有电话 + // 你不用指定TKey、TValue,因为它们会被隐式地推导出来 + Console.WriteLine(SetDefault(phonebook, "Sarah", "No Phone")); // 212 555 5555 + + // lambda表达式 - 允许你用一行代码搞定函数 + Func square = (x) => x * x; // 最后一项为返回值 + Console.WriteLine(square(3)); // 9 + + // 可抛弃的资源管理 - 让你很容易地处理未管理的资源 + // 大多数访问未管理资源 (文件操作符、设备上下文, etc.)的对象 + // 都实现了IDisposable接口。 + // using语句会为你清理IDisposable对象。 + using (StreamWriter writer = new StreamWriter("log.txt")) + { + writer.WriteLine("这里没有什么可疑的东西"); + // 在作用域的结尾,资源会被回收 + // (即使有异常抛出,也一样会回收) + } + + // 并行框架 + // http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx + var websites = new string[] { + "http://www.google.com", "http://www.reddit.com", + "http://www.shaunmccarthy.com" + }; + var responses = new Dictionary(); + + // 为每个请求新开一个线程 + // 在运行下一步前合并结果 + Parallel.ForEach(websites, + new ParallelOptions() {MaxDegreeOfParallelism = 3}, // max of 3 threads + website => + { + // Do something that takes a long time on the file + using (var r = WebRequest.Create(new Uri(website)).GetResponse()) + { + responses[website] = r.ContentType; + } + }); + + // 直到所有的请求完成后才会运行下面的代码 + foreach (var key in responses.Keys) + Console.WriteLine("{0}:{1}", key, responses[key]); + + // 动态对象(配合其他语言使用很方便) + dynamic student = new ExpandoObject(); + student.FirstName = "First Name"; // 不需要先定义类! + + // 你甚至可以添加方法(接受一个字符串,输出一个字符串) + student.Introduce = new Func( + (introduceTo) => string.Format("Hey {0}, this is {1}", student.FirstName, introduceTo)); + Console.WriteLine(student.Introduce("Beth")); + + // IQUERYABLE - 几乎所有的集合都实现了它, + // 带给你 Map / Filter / Reduce 风格的方法 + var bikes = new List(); + bikes.Sort(); // Sorts the array + bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // 根据车轮数排序 + var result = bikes + .Where(b => b.Wheels > 3) // 筛选 - 可以连锁使用 (返回IQueryable) + .Where(b => b.IsBroken && b.HasTassles) + .Select(b => b.ToString()); // Map - 这里我们使用了select,所以结果是IQueryable + + var sum = bikes.Sum(b => b.Wheels); // Reduce - 计算集合中的轮子总数 + + // 创建一个包含基于自行车的一些参数生成的隐式对象的列表 + var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles }); + // 很难演示,但是编译器在代码编译完成前就能推导出以上对象的类型 + foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome)) + Console.WriteLine(bikeSummary.Name); + + // ASPARALLEL + // 邪恶的特性 —— 组合了linq和并行操作 + var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name); + // 以上代码会并发地运行。会自动新开线程,分别计算结果。 + // 适用于多核、大数据量的场景。 + + // LINQ - 将IQueryable映射到存储,延缓执行 + // 例如 LinqToSql 映射数据库, LinqToXml 映射XML文档 + var db = new BikeRespository(); + + // 执行被延迟了,这对于查询数据库来说很好 + var filter = db.Bikes.Where(b => b.HasTassles); // 不运行查询 + if (42 > 6) // 你可以不断地增加筛选,包括有条件的筛选,例如用于“高级搜索”功能 + filter = filter.Where(b => b.IsBroken); // 不运行查询 + + var query = filter + .OrderBy(b => b.Wheels) + .ThenBy(b => b.Name) + .Select(b => b.Name); // 仍然不运行查询 + + // 现在运行查询,运行查询的时候会打开一个读取器,所以你迭代的是一个副本 + foreach (string bike in query) + Console.WriteLine(result); + + + + } + + } // 结束LearnCSharp类 + + // 你可以在同一个 .cs 文件中包含其他类 + + public static class Extensions + { + // 扩展函数 + public static void Print(this object obj) + { + Console.WriteLine(obj.ToString()); + } + } + // 声明类的语法: + // class <类名>{ + // //数据字段, 构造器, 内部函数. + / // 在Java中函数被称为方法。 + // } + + public class Bicycle + { + // 自行车的字段、变量 + public int Cadence // Public: 任何地方都可以访问 + { + get // get - 定义获取属性的方法 + { + return _cadence; + } + set // set - 定义设置属性的方法 + { + _cadence = value; // value是被传递给setter的值 + } + } + private int _cadence; + + protected virtual int Gear // 类和子类可以访问 + { + get; // 创建一个自动属性,无需成员字段 + set; + } + + internal int Wheels // Internal:在同一程序集内可以访问 + { + get; + private set; // 可以给get/set方法添加修饰符 + } + + int _speed; // 默认为private: 只可以在这个类内访问,你也可以使用`private`关键词 + public string Name { get; set; } + + // enum类型包含一组常量 + // 它将名称映射到值(除非特别说明,是一个整型) + // enmu元素的类型可以是byte、sbyte、short、ushort、int、uint、long、ulong。 + // enum不能包含相同的值。 + public enum BikeBrand + { + AIST, + BMC, + Electra = 42, //你可以显式地赋值 + Gitane // 43 + } + // 我们在Bicycle类中定义的这个类型,所以它是一个内嵌类型。 + // 这个类以外的代码应当使用`Bicycle.Brand`来引用。 + + public BikeBrand Brand; // 声明一个enum类型之后,我们可以声明这个类型的字段 + + // 静态方法的类型为自身,不属于特定的对象。 + // 你无需引用对象就可以访问他们。 + // Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated); + static public int BicyclesCreated = 0; + + // 只读值在运行时确定 + // 它们只能在声明或构造器内被赋值 + readonly bool _hasCardsInSpokes = false; // read-only private + + // 构造器是创建类的一种方式 + // 下面是一个默认的构造器 + public Bicycle() + { + this.Gear = 1; // 你可以使用关键词this访问对象的成员 + Cadence = 50; // 不过你并不总是需要它 + _speed = 5; + Name = "Bontrager"; + Brand = BikeBrand.AIST; + BicyclesCreated++; + } + + // 另一个构造器的例子(包含参数) + public Bicycle(int startCadence, int startSpeed, int startGear, + string name, bool hasCardsInSpokes, BikeBrand brand) + : base() // 首先调用base + { + Gear = startGear; + Cadence = startCadence; + _speed = startSpeed; + Name = name; + _hasCardsInSpokes = hasCardsInSpokes; + Brand = brand; + } + + // 构造器可以连锁使用 + public Bicycle(int startCadence, int startSpeed, BikeBrand brand) : + this(startCadence, startSpeed, 0, "big wheels", true, brand) + { + } + + // 函数语法 + // <返回值> <函数名称>(<参数>) + + // 类可以为字段实现 getters 和 setters 方法 for their fields + // 或者可以实现属性(C#推荐使用这个) + // 方法的参数可以有默认值 + // 在有默认值的情况下,调用方法的时候可以省略相应的参数 + public void SpeedUp(int increment = 1) + { + _speed += increment; + } + + public void SlowDown(int decrement = 1) + { + _speed -= decrement; + } + + // 属性可以访问和设置值 + // 当只需要访问数据的时候,考虑使用属性。 + // 属性可以定义get和set,或者是同时定义两者 + private bool _hasTassles; // private variable + public bool HasTassles // public accessor + { + get { return _hasTassles; } + set { _hasTassles = value; } + } + + // 你可以在一行之内定义自动属性 + // 这个语法会自动创建后备字段 + // 你可以给getter或setter设置访问修饰符 + // 以便限制它们的访问 + public bool IsBroken { get; private set; } + + // 属性的实现可以是自动的 + public int FrameSize + { + get; + // 你可以给get或set指定访问修饰符 + // 以下代码意味着只有Bicycle类可以调用Framesize的set + private set; + } + + //显示对象属性的方法 + public virtual string Info() + { + return "Gear: " + Gear + + " Cadence: " + Cadence + + " Speed: " + _speed + + " Name: " + Name + + " Cards in Spokes: " + (_hasCardsInSpokes ? "yes" : "no") + + "\n------------------------------\n" + ; + } + + // 方法可以是静态的。通常用于辅助方法。 + public static bool DidWeCreateEnoughBycles() + { + // 在静态方法中,你只能引用类的静态成员 + return BicyclesCreated > 9000; + } // 如果你的类只需要静态成员,考虑将整个类作为静态类。 + + + } // Bicycle类结束 + + // PennyFarthing是Bicycle的一个子类 + class PennyFarthing : Bicycle + { + // (Penny Farthings是一种前轮很大的自行车。没有齿轮。) + + // 调用父构造器 + public PennyFarthing(int startCadence, int startSpeed) : + base(startCadence, startSpeed, 0, "PennyFarthing", true, BikeBrand.Electra) + { + } + + protected override int Gear + { + get + { + return 0; + } + set + { + throw new ArgumentException("你不可能在PennyFarthing上切换齿轮"); + } + } + + public override string Info() + { + string result = "PennyFarthing bicycle "; + result += base.ToString(); // 调用父方法 + return result; + } + } + + // 接口只包含成员的签名,而没有实现。 + interface IJumpable + { + void Jump(int meters); // 所有接口成员是隐式地公开的 + } + + interface IBreakable + { + bool Broken { get; } // 接口可以包含属性、方法和事件 + } + + // 类只能继承一个类,但是可以实现任意数量的接口 + { + int damage = 0; + + public void Jump(int meters) + { + damage += meters; + } + + public bool Broken + { + get + { + return damage > 100; + } + } + } + + /// + /// 连接数据库,一个 LinqToSql的示例。 + /// EntityFramework Code First 很棒 (类似 Ruby的 ActiveRecord, 不过是双向的) + /// http://msdn.microsoft.com/en-us/data/jj193542.aspx + /// + public class BikeRespository : DbSet + { + public BikeRespository() + : base() + { + } + + public DbSet Bikes { get; set; } + } +} // 结束 Namespace +``` + +## 没有涉及到的主题 + + * Flags + * Attributes + * 静态属性 + * Exceptions, Abstraction + * ASP.NET (Web Forms/MVC/WebMatrix) + * Winforms + * Windows Presentation Foundation (WPF) + +## 扩展阅读 + + * [DotNetPerls](http://www.dotnetperls.com) + * [C# in Depth](http://manning.com/skeet2) + * [Programming C#](http://shop.oreilly.com/product/0636920024064.do) + * [LINQ](http://shop.oreilly.com/product/9780596519254.do) + * [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx) + * [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials) + * [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials) + * [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials) + * [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208) + * [C# Coding Conventions](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx) -- cgit v1.2.3 From bba7307611c5b0e6656c41c284a18249b6f86c86 Mon Sep 17 00:00:00 2001 From: lidashuang Date: Mon, 31 Mar 2014 17:57:19 +0800 Subject: Create elixir-cn.html.markdown --- zh-cn/elixir-cn.html.markdown | 398 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 zh-cn/elixir-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown new file mode 100644 index 00000000..8ea499ff --- /dev/null +++ b/zh-cn/elixir-cn.html.markdown @@ -0,0 +1,398 @@ +--- +language: elixir +contributors: + - ["Joao Marques", "http://github.com/mrshankly"] +filename: learnelixir.ex +--- + +Elixir is a modern functional language built on top of the Erlang VM. +It's fully compatible with Erlang, but features a more standard syntax +and many more features. + +```ruby + +# Single line comments start with a hashtag. + +# There's no multi-line comment, +# but you can stack multiple comments. + +# To use the elixir shell use the `iex` command. +# Compile your modules with the `elixirc` command. + +# Both should be in your path if you installed elixir correctly. + +## --------------------------- +## -- Basic types +## --------------------------- + +# There are numbers +3 # integer +0x1F # integer +3.0 # float + +# Atoms, that are literals, a constant with name. They start with `:`. +:hello # atom + +# Tuples that are stored contiguously in memory. +{1,2,3} # tuple + +# We can access a tuple element with the `elem` function: +elem({1, 2, 3}, 0) #=> 1 + +# Lists that are implemented as linked lists. +[1,2,3] # list + +# We can access the head and tail of a list as follows: +[head | tail] = [1,2,3] +head #=> 1 +tail #=> [2,3] + +# In elixir, just like in Erlang, the `=` denotes pattern matching and +# not an assignment. +# +# This means that the left-hand side (pattern) is matched against a +# right-hand side. +# +# This is how the above example of accessing the head and tail of a list works. + +# A pattern match will error when the sides don't match, in this example +# the tuples have different sizes. +# {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2} + +# There's also binaries +<<1,2,3>> # binary + +# Strings and char lists +"hello" # string +'hello' # char list + +# Multi-line strings +""" +I'm a multi-line +string. +""" +#=> "I'm a multi-line\nstring.\n" + +# Strings are all encoded in UTF-8: +"héllò" #=> "héllò" + +# Strings are really just binaries, and char lists are just lists. +<> #=> "abc" +[?a, ?b, ?c] #=> 'abc' + +# `?a` in elixir returns the ASCII integer for the letter `a` +?a #=> 97 + +# To concatenate lists use `++`, for binaries use `<>` +[1,2,3] ++ [4,5] #=> [1,2,3,4,5] +'hello ' ++ 'world' #=> 'hello world' + +<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>> +"hello " <> "world" #=> "hello world" + +## --------------------------- +## -- Operators +## --------------------------- + +# Some math +1 + 1 #=> 2 +10 - 5 #=> 5 +5 * 2 #=> 10 +10 / 2 #=> 5.0 + +# In elixir the operator `/` always returns a float. + +# To do integer division use `div` +div(10, 2) #=> 5 + +# To get the division remainder use `rem` +rem(10, 3) #=> 1 + +# There's also boolean operators: `or`, `and` and `not`. +# These operators expect a boolean as their first argument. +true and true #=> true +false or true #=> true +# 1 and true #=> ** (ArgumentError) argument error + +# Elixir also provides `||`, `&&` and `!` which accept arguments of any type. +# All values except `false` and `nil` will evaluate to true. +1 || true #=> 1 +false && 1 #=> false +nil && 20 #=> nil + +!true #=> false + +# For comparisons we have: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>` +1 == 1 #=> true +1 != 1 #=> false +1 < 2 #=> true + +# `===` and `!==` are more strict when comparing integers and floats: +1 == 1.0 #=> true +1 === 1.0 #=> false + +# We can also compare two different data types: +1 < :hello #=> true + +# The overall sorting order is defined below: +# number < atom < reference < functions < port < pid < tuple < list < bit string + +# To quote Joe Armstrong on this: "The actual order is not important, +# but that a total ordering is well defined is important." + +## --------------------------- +## -- Control Flow +## --------------------------- + +# `if` expression +if false do + "This will never be seen" +else + "This will" +end + +# There's also `unless` +unless true do + "This will never be seen" +else + "This will" +end + +# Remember pattern matching? Many control-flow structures in elixir rely on it. + +# `case` allows us to compare a value against many patterns: +case {:one, :two} do + {:four, :five} -> + "This won't match" + {:one, x} -> + "This will match and assign `x` to `:two`" + _ -> + "This will match any value" +end + +# It's common practice to assign a value to `_` if we don't need it. +# For example, if only the head of a list matters to us: +[head | _] = [1,2,3] +head #=> 1 + +# For better readability we can do the following: +[head | _tail] = [:a, :b, :c] +head #=> :a + +# `cond` lets us check for many conditions at the same time. +# Use `cond` instead of nesting many `if` expressions. +cond do + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + 1 + 2 == 3 -> + "But I will" +end + +# It is common to see a last condition equal to `true`, which will always match. +cond do + 1 + 1 == 3 -> + "I will never be seen" + 2 * 5 == 12 -> + "Me neither" + true -> + "But I will (this is essentially an else)" +end + +# `try/catch` is used to catch values that are thrown, it also supports an +# `after` clause that is invoked whether or not a value is catched. +try do + throw(:hello) +catch + message -> "Got #{message}." +after + IO.puts("I'm the after clause.") +end +#=> I'm the after clause +# "Got :hello" + +## --------------------------- +## -- Modules and Functions +## --------------------------- + +# Anonymous functions (notice the dot) +square = fn(x) -> x * x end +square.(5) #=> 25 + +# They also accept many clauses and guards. +# Guards let you fine tune pattern matching, +# they are indicated by the `when` keyword: +f = fn + x, y when x > 0 -> x + y + x, y -> x * y +end + +f.(1, 3) #=> 4 +f.(-1, 3) #=> -3 + +# Elixir also provides many built-in functions. +# These are available in the current scope. +is_number(10) #=> true +is_list("hello") #=> false +elem({1,2,3}, 0) #=> 1 + +# You can group several functions into a module. Inside a module use `def` +# to define your functions. +defmodule Math do + def sum(a, b) do + a + b + end + + def square(x) do + x * x + end +end + +Math.sum(1, 2) #=> 3 +Math.square(3) #=> 9 + +# To compile our simple Math module save it as `math.ex` and use `elixirc` +# in your terminal: elixirc math.ex + +# Inside a module we can define functions with `def` and private functions with `defp`. +# A function defined with `def` is available to be invoked from other modules, +# a private function can only be invoked locally. +defmodule PrivateMath do + def sum(a, b) do + do_sum(a, b) + end + + defp do_sum(a, b) do + a + b + end +end + +PrivateMath.sum(1, 2) #=> 3 +# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError) + +# Function declarations also support guards and multiple clauses: +defmodule Geometry do + def area({:rectangle, w, h}) do + w * h + end + + def area({:circle, r}) when is_number(r) do + 3.14 * r * r + end +end + +Geometry.area({:rectangle, 2, 3}) #=> 6 +Geometry.area({:circle, 3}) #=> 28.25999999999999801048 +# Geometry.area({:circle, "not_a_number"}) +#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1 + +# Due to immutability, recursion is a big part of elixir +defmodule Recursion do + def sum_list([head | tail], acc) do + sum_list(tail, acc + head) + end + + def sum_list([], acc) do + acc + end +end + +Recursion.sum_list([1,2,3], 0) #=> 6 + +# Elixir modules support attributes, there are built-in attributes and you +# may also add custom attributes. +defmodule MyMod do + @moduledoc """ + This is a built-in attribute on a example module. + """ + + @my_data 100 # This is a custom attribute. + IO.inspect(@my_data) #=> 100 +end + +## --------------------------- +## -- Records and Exceptions +## --------------------------- + +# Records are basically structures that allow you to associate a name with +# a particular value. +defrecord Person, name: nil, age: 0, height: 0 + +joe_info = Person.new(name: "Joe", age: 30, height: 180) +#=> Person[name: "Joe", age: 30, height: 180] + +# Access the value of name +joe_info.name #=> "Joe" + +# Update the value of age +joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] + +# The `try` block with the `rescue` keyword is used to handle exceptions +try do + raise "some error" +rescue + RuntimeError -> "rescued a runtime error" + _error -> "this will rescue any error" +end + +# All exceptions have a message +try do + raise "some error" +rescue + x in [RuntimeError] -> + x.message +end + +## --------------------------- +## -- Concurrency +## --------------------------- + +# Elixir relies on the actor model for concurrency. All we need to write +# concurrent programs in elixir are three primitives: spawning processes, +# sending messages and receiving messages. + +# To start a new process we use the `spawn` function, which takes a function +# as argument. +f = fn -> 2 * 2 end #=> #Function +spawn(f) #=> #PID<0.40.0> + +# `spawn` returns a pid (process identifier), you can use this pid to send +# messages to the process. To do message passing we use the `<-` operator. +# For all of this to be useful we need to be able to receive messages. This is +# achived with the `receive` mechanism: +defmodule Geometry do + def area_loop do + receive do + {:rectangle, w, h} -> + IO.puts("Area = #{w * h}") + area_loop() + {:circle, r} -> + IO.puts("Area = #{3.14 * r * r}") + area_loop() + end + end +end + +# Compile the module and create a process that evaluates `area_loop` in the shell +pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0> + +# Send a message to `pid` that will match a pattern in the receive statement +pid <- {:rectangle, 2, 3} +#=> Area = 6 +# {:rectangle,2,3} + +pid <- {:circle, 2} +#=> Area = 12.56000000000000049738 +# {:circle,2} + +# The shell is also a process, you can use `self` to get the current pid +self() #=> #PID<0.27.0> +``` + +## References + +* [Getting started guide](http://elixir-lang.org/getting_started/1.html) from [elixir webpage](http://elixir-lang.org) +* [Elixir Documentation](http://elixir-lang.org/docs/master/) +* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) by Fred Hebert +* "Programming Erlang: Software for a Concurrent World" by Joe Armstrong -- cgit v1.2.3 From 708fd4a65b9a3c9dc216f23e1906de2421e657fd Mon Sep 17 00:00:00 2001 From: lidashuang Date: Mon, 31 Mar 2014 19:49:46 +0800 Subject: Update elixir-cn.html.markdown --- zh-cn/elixir-cn.html.markdown | 127 +++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 64 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index 8ea499ff..2c8f5fb5 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -2,88 +2,88 @@ language: elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] + - ["lidashuang", "http://github.com/lidashuang"] filename: learnelixir.ex --- -Elixir is a modern functional language built on top of the Erlang VM. -It's fully compatible with Erlang, but features a more standard syntax -and many more features. +Elixir 是一门构建在Elang VM 之上的函数式编程语言。Elixir 完全兼容 Eralng, +另外还提供了更标准的语法,特性。 -```ruby +```elixir -# Single line comments start with a hashtag. +# 这是单行注释, 注释以井号开头 -# There's no multi-line comment, -# but you can stack multiple comments. +# 没有多行注释 +# 但你可以堆叠多个注释。 -# To use the elixir shell use the `iex` command. -# Compile your modules with the `elixirc` command. +# elixir shell 使用命令 `iex` 进入。 +# 编译模块使用 `elixirc` 命令。 -# Both should be in your path if you installed elixir correctly. +# 如果安装正确,这些命令都会在环境变量里 ## --------------------------- -## -- Basic types +## -- 基本类型 ## --------------------------- -# There are numbers -3 # integer -0x1F # integer -3.0 # float +# 数字 +3 # 整型 +0x1F # 整型 +3.0 # 浮点类型 -# Atoms, that are literals, a constant with name. They start with `:`. +# 原子(Atoms),以 `:`开头 :hello # atom # Tuples that are stored contiguously in memory. {1,2,3} # tuple -# We can access a tuple element with the `elem` function: +# 使用`elem`函数访问元组(tuple)里的元素: elem({1, 2, 3}, 0) #=> 1 -# Lists that are implemented as linked lists. +# 列表(list) [1,2,3] # list -# We can access the head and tail of a list as follows: +# 可以用下面的方法访问列表的头尾元素: [head | tail] = [1,2,3] head #=> 1 tail #=> [2,3] -# In elixir, just like in Erlang, the `=` denotes pattern matching and -# not an assignment. +# 在elixir,就像在Erlang, `=` 表示模式匹配 (pattern matching) +# 不是赋值。 # # This means that the left-hand side (pattern) is matched against a # right-hand side. # # This is how the above example of accessing the head and tail of a list works. -# A pattern match will error when the sides don't match, in this example -# the tuples have different sizes. +# 当左右两边不匹配时,会返回error, 在这个 +# 例子中,元组大小不一样。 # {a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2} -# There's also binaries +# 还有二进制类型 (binaries) <<1,2,3>> # binary -# Strings and char lists +# 字符串(Strings) 和 字符列表(char lists) "hello" # string 'hello' # char list -# Multi-line strings +# 多行字符串 """ I'm a multi-line string. """ #=> "I'm a multi-line\nstring.\n" -# Strings are all encoded in UTF-8: +# 所有的字符串(Strings)以UTF-8编码: "héllò" #=> "héllò" -# Strings are really just binaries, and char lists are just lists. +# 字符串(Strings)本质就是二进制类型(binaries), 字符列表(char lists)本质是列表(lists) <> #=> "abc" [?a, ?b, ?c] #=> 'abc' -# `?a` in elixir returns the ASCII integer for the letter `a` +# 在 elixir中,`?a`返回 `a` 的 ASCII 整型值 ?a #=> 97 -# To concatenate lists use `++`, for binaries use `<>` +# 合并列表使用 `++`, 对于二进制类型则使用 `<>` [1,2,3] ++ [4,5] #=> [1,2,3,4,5] 'hello ' ++ 'world' #=> 'hello world' @@ -91,67 +91,67 @@ string. "hello " <> "world" #=> "hello world" ## --------------------------- -## -- Operators +## -- 操作符(Operators) ## --------------------------- -# Some math +# 一些数学运算 1 + 1 #=> 2 10 - 5 #=> 5 5 * 2 #=> 10 10 / 2 #=> 5.0 -# In elixir the operator `/` always returns a float. +# 在 elixir 操作符 `/` 返回值总是浮点数。 -# To do integer division use `div` +# 做整数除法使用 `div` div(10, 2) #=> 5 -# To get the division remainder use `rem` +# 为了得到余数使用 `rem` rem(10, 3) #=> 1 -# There's also boolean operators: `or`, `and` and `not`. -# These operators expect a boolean as their first argument. +# 还有 boolean 操作符: `or`, `and` and `not`. +# 第一个参数必须是boolean 类型 true and true #=> true false or true #=> true # 1 and true #=> ** (ArgumentError) argument error -# Elixir also provides `||`, `&&` and `!` which accept arguments of any type. -# All values except `false` and `nil` will evaluate to true. +# Elixir 也提供了 `||`, `&&` 和 `!` 可以接受任意的类型 +# 除了`false` 和 `nil` 其它都会被当作true. 1 || true #=> 1 false && 1 #=> false nil && 20 #=> nil !true #=> false -# For comparisons we have: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>` +# 比较有: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` 和 `>` 1 == 1 #=> true 1 != 1 #=> false 1 < 2 #=> true -# `===` and `!==` are more strict when comparing integers and floats: +# `===` 和 `!==` 在比较整型和浮点类型时更为严格: 1 == 1.0 #=> true 1 === 1.0 #=> false -# We can also compare two different data types: +# 我们也可以比较两种不同的类型: 1 < :hello #=> true -# The overall sorting order is defined below: +# 总的排序顺序定义如下: # number < atom < reference < functions < port < pid < tuple < list < bit string # To quote Joe Armstrong on this: "The actual order is not important, # but that a total ordering is well defined is important." ## --------------------------- -## -- Control Flow +## -- 控制结构(Control Flow) ## --------------------------- -# `if` expression +# `if` 表达式 if false do "This will never be seen" else "This will" end -# There's also `unless` +# 还有 `unless` unless true do "This will never be seen" else @@ -170,12 +170,12 @@ case {:one, :two} do "This will match any value" end -# It's common practice to assign a value to `_` if we don't need it. -# For example, if only the head of a list matters to us: +# 模式匹配时,如果不需要某个值,通用的做法是把值 匹配到 `_` +# 例如,我们只需要要列表的头元素: [head | _] = [1,2,3] head #=> 1 -# For better readability we can do the following: +# 下面的方式效果一样,但可读性更好 [head | _tail] = [:a, :b, :c] head #=> :a @@ -213,10 +213,10 @@ end # "Got :hello" ## --------------------------- -## -- Modules and Functions +## -- 模块和函数(Modules and Functions) ## --------------------------- -# Anonymous functions (notice the dot) +# 匿名函数 (注意点) square = fn(x) -> x * x end square.(5) #=> 25 @@ -231,14 +231,13 @@ end f.(1, 3) #=> 4 f.(-1, 3) #=> -3 -# Elixir also provides many built-in functions. -# These are available in the current scope. +# Elixir 提供了很多内建函数 +# 在默认作用域都是可用的 is_number(10) #=> true is_list("hello") #=> false elem({1,2,3}, 0) #=> 1 -# You can group several functions into a module. Inside a module use `def` -# to define your functions. +# 你可以在一个模块里定义多个函数,定义函数使用 `def` defmodule Math do def sum(a, b) do a + b @@ -252,12 +251,12 @@ end Math.sum(1, 2) #=> 3 Math.square(3) #=> 9 -# To compile our simple Math module save it as `math.ex` and use `elixirc` -# in your terminal: elixirc math.ex +# 保存到 `math.ex`,使用 `elixirc` 编译你的 Math 模块 +# 在终端里: elixirc math.ex -# Inside a module we can define functions with `def` and private functions with `defp`. -# A function defined with `def` is available to be invoked from other modules, -# a private function can only be invoked locally. +# 在模块中可以使用`def`定义函数,使用 `defp` 定义私有函数 +# 使用`def` 定义的函数可以被其它模块调用 +# 私有函数只能在本模块内调用 defmodule PrivateMath do def sum(a, b) do do_sum(a, b) @@ -287,7 +286,7 @@ Geometry.area({:circle, 3}) #=> 28.25999999999999801048 # Geometry.area({:circle, "not_a_number"}) #=> ** (FunctionClauseError) no function clause matching in Geometry.area/1 -# Due to immutability, recursion is a big part of elixir +#由于不变性,递归是Elixir的重要组成部分 defmodule Recursion do def sum_list([head | tail], acc) do sum_list(tail, acc + head) @@ -322,7 +321,7 @@ defrecord Person, name: nil, age: 0, height: 0 joe_info = Person.new(name: "Joe", age: 30, height: 180) #=> Person[name: "Joe", age: 30, height: 180] -# Access the value of name +# 访问name的值 joe_info.name #=> "Joe" # Update the value of age @@ -345,7 +344,7 @@ rescue end ## --------------------------- -## -- Concurrency +## -- 并发(Concurrency) ## --------------------------- # Elixir relies on the actor model for concurrency. All we need to write @@ -386,7 +385,7 @@ pid <- {:circle, 2} #=> Area = 12.56000000000000049738 # {:circle,2} -# The shell is also a process, you can use `self` to get the current pid +# shell也是一个进程(process), 你可以使用`self`获取当前 pid self() #=> #PID<0.27.0> ``` -- cgit v1.2.3 From 816ba7d7e6f3e6b7b93275c6041498eabcf41c84 Mon Sep 17 00:00:00 2001 From: lidashuang Date: Mon, 31 Mar 2014 22:12:03 +0800 Subject: Update elixir-cn.html.markdown --- zh-cn/elixir-cn.html.markdown | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index 2c8f5fb5..a2e5f4aa 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -311,7 +311,7 @@ defmodule MyMod do end ## --------------------------- -## -- Records and Exceptions +## -- 记录和异常(Records and Exceptions) ## --------------------------- # Records are basically structures that allow you to associate a name with @@ -324,7 +324,7 @@ joe_info = Person.new(name: "Joe", age: 30, height: 180) # 访问name的值 joe_info.name #=> "Joe" -# Update the value of age +# 更新age的值 joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] # The `try` block with the `rescue` keyword is used to handle exceptions @@ -351,8 +351,7 @@ end # concurrent programs in elixir are three primitives: spawning processes, # sending messages and receiving messages. -# To start a new process we use the `spawn` function, which takes a function -# as argument. +# 启动一个新的进程使用`spawn`函数,接收一个函数作为参数 f = fn -> 2 * 2 end #=> #Function spawn(f) #=> #PID<0.40.0> @@ -373,10 +372,10 @@ defmodule Geometry do end end -# Compile the module and create a process that evaluates `area_loop` in the shell +# 编译这个模块,在shell中创建一个进程,并执行 `area_looop` 函数。 pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0> -# Send a message to `pid` that will match a pattern in the receive statement +# 发送一个消息给 `pid`, 会在receive语句进行模式匹配 pid <- {:rectangle, 2, 3} #=> Area = 6 # {:rectangle,2,3} @@ -389,7 +388,7 @@ pid <- {:circle, 2} self() #=> #PID<0.27.0> ``` -## References +## 参考文献 * [Getting started guide](http://elixir-lang.org/getting_started/1.html) from [elixir webpage](http://elixir-lang.org) * [Elixir Documentation](http://elixir-lang.org/docs/master/) -- cgit v1.2.3 From c9bc93c261e74cfd3f5b9fedaade75aec91ec253 Mon Sep 17 00:00:00 2001 From: lidashuang Date: Mon, 31 Mar 2014 22:24:09 +0800 Subject: Update elixir-cn.html.markdown --- zh-cn/elixir-cn.html.markdown | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index a2e5f4aa..1f8e3e2c 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -299,14 +299,13 @@ end Recursion.sum_list([1,2,3], 0) #=> 6 -# Elixir modules support attributes, there are built-in attributes and you -# may also add custom attributes. +# Elixir 模块支持属性,模块内建了一些属性,你也可以自定义属性 defmodule MyMod do @moduledoc """ - This is a built-in attribute on a example module. + 内置的属性,模块文档 """ - @my_data 100 # This is a custom attribute. + @my_data 100 # 自定义属性 IO.inspect(@my_data) #=> 100 end @@ -327,7 +326,7 @@ joe_info.name #=> "Joe" # 更新age的值 joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180] -# The `try` block with the `rescue` keyword is used to handle exceptions +# 使用 `try` `rescue` 进行异常处理 try do raise "some error" rescue @@ -335,7 +334,7 @@ rescue _error -> "this will rescue any error" end -# All exceptions have a message +# 所有的异常都有一个message try do raise "some error" rescue @@ -347,18 +346,19 @@ end ## -- 并发(Concurrency) ## --------------------------- -# Elixir relies on the actor model for concurrency. All we need to write -# concurrent programs in elixir are three primitives: spawning processes, -# sending messages and receiving messages. +# Elixir 依赖与actor并发模型。在Elixir编写并发程序的三要素: +# 创建进程,发送消息,接收消息 # 启动一个新的进程使用`spawn`函数,接收一个函数作为参数 + f = fn -> 2 * 2 end #=> #Function spawn(f) #=> #PID<0.40.0> -# `spawn` returns a pid (process identifier), you can use this pid to send -# messages to the process. To do message passing we use the `<-` operator. -# For all of this to be useful we need to be able to receive messages. This is -# achived with the `receive` mechanism: + +# `spawn` 函数返回一个pid(进程标识符),你可以使用pid向进程发送消息。 +# 使用 `<-` 操作符发送消息。 +# 我们需要在进程内接收消息,要用到 `receive` 机制。 + defmodule Geometry do def area_loop do receive do -- cgit v1.2.3 From d6bd212e433df381be331a512796b2572d023cb1 Mon Sep 17 00:00:00 2001 From: lidashuang Date: Mon, 31 Mar 2014 23:25:19 +0800 Subject: Update elixir-cn.html.markdown --- zh-cn/elixir-cn.html.markdown | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index 1f8e3e2c..a624f6b1 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -33,7 +33,7 @@ Elixir 是一门构建在Elang VM 之上的函数式编程语言。Elixir 完全 # 原子(Atoms),以 `:`开头 :hello # atom -# Tuples that are stored contiguously in memory. +# 元组(Tuple) 在内存中的存储是连续的 {1,2,3} # tuple # 使用`elem`函数访问元组(tuple)里的元素: @@ -50,10 +50,9 @@ tail #=> [2,3] # 在elixir,就像在Erlang, `=` 表示模式匹配 (pattern matching) # 不是赋值。 # -# This means that the left-hand side (pattern) is matched against a -# right-hand side. -# -# This is how the above example of accessing the head and tail of a list works. +# 这表示会用左边的模式(pattern)匹配右侧 +# +# 这是上面的例子中访问列列表的头部和尾部的就是这样工作的。 # 当左右两边不匹配时,会返回error, 在这个 # 例子中,元组大小不一样。 @@ -137,8 +136,8 @@ nil && 20 #=> nil # 总的排序顺序定义如下: # number < atom < reference < functions < port < pid < tuple < list < bit string -# To quote Joe Armstrong on this: "The actual order is not important, -# but that a total ordering is well defined is important." +# 引用Joe Armstrong :”实际的顺序并不重要, +# 但是,一个整体排序是否经明确界定是非常重要的“。 ## --------------------------- ## -- 控制结构(Control Flow) @@ -158,9 +157,9 @@ else "This will" end -# Remember pattern matching? Many control-flow structures in elixir rely on it. +# 在Elixir中,很多控制结构都依赖于模式匹配 -# `case` allows us to compare a value against many patterns: +# `case` 允许我们把一个值与多种模式进行比较: case {:one, :two} do {:four, :five} -> "This won't match" @@ -179,8 +178,8 @@ head #=> 1 [head | _tail] = [:a, :b, :c] head #=> :a -# `cond` lets us check for many conditions at the same time. -# Use `cond` instead of nesting many `if` expressions. +# `cond` 可以检测多种不同的分支 +# 使用 `cond` 代替多个`if` 表达式嵌套 cond do 1 + 1 == 3 -> "I will never be seen" @@ -190,7 +189,7 @@ cond do "But I will" end -# It is common to see a last condition equal to `true`, which will always match. +# 经常可以看到最后一个条件等于'true',这将总是匹配。 cond do 1 + 1 == 3 -> "I will never be seen" @@ -200,8 +199,9 @@ cond do "But I will (this is essentially an else)" end -# `try/catch` is used to catch values that are thrown, it also supports an -# `after` clause that is invoked whether or not a value is catched. +# `try/catch` 用于捕获被抛出的值, 它也支持 `after` 子句, +# 无论是否值被捕获,after 子句都会被调用 +# `try/catch` try do throw(:hello) catch @@ -220,9 +220,10 @@ end square = fn(x) -> x * x end square.(5) #=> 25 -# They also accept many clauses and guards. -# Guards let you fine tune pattern matching, -# they are indicated by the `when` keyword: + +# 也支持接收多个子句和卫士(guards). +# Guards可以进行模式匹配 +# Guards只有`when` 关键字指明: f = fn x, y when x > 0 -> x + y x, y -> x * y @@ -313,8 +314,7 @@ end ## -- 记录和异常(Records and Exceptions) ## --------------------------- -# Records are basically structures that allow you to associate a name with -# a particular value. +# 记录就是把特定值关联到某个名字的结构体 defrecord Person, name: nil, age: 0, height: 0 joe_info = Person.new(name: "Joe", age: 30, height: 180) -- cgit v1.2.3 From ff4a2728e8469f62f5fc4e8be81dd5fdd46f9195 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Mon, 31 Mar 2014 13:19:56 -0700 Subject: Update elixir-cn.html.markdown Fix header things --- zh-cn/elixir-cn.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index a624f6b1..50f0e350 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -2,8 +2,10 @@ language: elixir contributors: - ["Joao Marques", "http://github.com/mrshankly"] +translators: - ["lidashuang", "http://github.com/lidashuang"] -filename: learnelixir.ex +filename: learnelixir-cn.ex +lang: zh-cn --- Elixir 是一门构建在Elang VM 之上的函数式编程语言。Elixir 完全兼容 Eralng, -- cgit v1.2.3 From 4f71e1574229fea8e37f5e67f3469f768b02d474 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Wed, 2 Apr 2014 23:08:39 +0800 Subject: css: add Chinese (zh_CN) translation --- zh-cn/css-cn.html.markdown | 211 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 zh-cn/css-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/css-cn.html.markdown b/zh-cn/css-cn.html.markdown new file mode 100644 index 00000000..a188ee9b --- /dev/null +++ b/zh-cn/css-cn.html.markdown @@ -0,0 +1,211 @@ +--- +language: css +contributors: + - ["Mohammad Valipour", "https://github.com/mvalipour"] + - ["Marco Scannadinari", "https://github.com/marcoms"] +translators: + - ["Jakukyo Friel", "https://weakish.github.io"] +filename: learncss.css +--- + +早期的web没有样式,只是单纯的文本。通过CSS,可以实现网页样式和内容的分离。 + +简单来说,CSS可以指定HTML页面上的元素所使用的样式。 + +和其他语言一样,CSS有很多版本。最新的版本是CSS 3. CSS 2.0兼容性最好。 + +你可以使用[dabblet](http://dabblet.com/)来在线测试CSS的效果。 + +```css +/* 注释 */ + +/* #################### + ## 选择器 + ####################*/ + +/* 一般而言,CSS的声明语句非常简单。 */ +选择器 { 属性: 值; /* 更多属性...*/ } + +/* 选择器用于指定页面上的元素。 + +针对页面上的所有元素。 */ +* { color:red; } + +/* +假定页面上有这样一个元素 + +
+*/ + +/* 你可以通过类名来指定它 */ +.some-class { } + +/* 给出所有类名 */ +.some-class.class2 { } + +/* 标签名 */ +div { } + +/* id */ +#someId { } + +/* 由于元素包含attr属性,因此也可以通过这个来指定 */ +[attr] { font-size:smaller; } + +/* 以及有特定值的属性 */ +[attr='value'] { font-size:smaller; } + +/* 通过属性的值的开头指定 */ +[attr^='val'] { font-size:smaller; } + +/* 通过属性的值的结尾来指定 */ +[attr$='ue'] { font-size:smaller; } + +/* 通过属性的值的部分来指定 */ +[attr~='lu'] { font-size:smaller; } + + +/* 你可以把这些全部结合起来,注意不同部分间不应该有空格,否则会改变语义 */ +div.some-class[attr$='ue'] { } + +/* 你也可以通过父元素来指定。*/ + +/* 某个元素是另一个元素的直接子元素 */ +div.some-parent > .class-name {} + +/* 或者通过该元素的祖先元素 */ +div.some-parent .class-name {} + +/* 注意,去掉空格后语义就不同了。 +你能说出哪里不同么? */ +div.some-parent.class-name {} + +/* 你可以选择某元素前的相邻元素 */ +.i-am-before + .this-element { } + +/* 某元素之前的同级元素(相邻或不相邻) */ +.i-am-any-before ~ .this-element {} + +/* 伪类允许你基于页面的行为指定元素(而不是基于页面结构) */ + +/* 例如,当鼠标悬停在某个元素上时 */ +:hover {} + +/* 已访问过的链接*/ +:visited {} + +/* 未访问过的链接*/ +:link {} + +/* 当前焦点的input元素 */ +:focus {} + + +/* #################### + ## 属性 + ####################*/ + +选择器 { + + /* 单位 */ + width: 50%; /* 百分比 */ + font-size: 2em; /* 当前字体大小的两倍 */ + width: 200px; /* 像素 */ + font-size: 20pt; /* 点 */ + width: 5cm; /* 厘米 */ + width: 50mm; /* 毫米 */ + width: 5in; /* 英尺 */ + + /* 颜色 */ + background-color: #F6E; /* 短16位 */ + background-color: #F262E2; /* 长16位 */ + background-color: tomato; /* 颜色名称 */ + background-color: rgb(255, 255, 255); /* rgb */ + background-color: rgb(10%, 20%, 50%); /* rgb 百分比 */ + background-color: rgba(255, 0, 0, 0.3); /* rgb 加透明度 */ + + /* 图片 */ + background-image: url(/path-to-image/image.jpg); + + /* 字体 */ + font-family: Arial; + font-family: "Courier New"; /* 使用双引号包裹含空格的字体名称 */ + font-family: "Courier New", Trebuchet, Arial; /* 如果第一个 + 字体没找到,浏览器会使用第二个字体,一次类推 */ +} + +``` + +## 使用 + +CSS文件使用 `.css` 后缀。 + +```xml + + + + + + + +
+
+ +``` + +## 优先级 + +同一个元素可能被多个不同的选择器指定,因此可能会有冲突。 + +假定CSS是这样的: + +```css +/*A*/ +p.class1[attr='value'] + +/*B*/ +p.class1 {} + +/*C*/ +p.class2 {} + +/*D*/ +p {} + +/*E*/ +p { property: value !important; } + +``` + +然后标记语言为: + +```xml +

+

+``` + +那么将会按照下面的顺序应用风格: + + +* `E` 优先级最高,因为它使用了 `!important`,除非很有必要,尽量避免使用这个。 +* `F` 其次,因为它是嵌入的风格。 +* `A` 其次,因为它比其他指令更具体。 +* `C` 其次,虽然它的具体程度和`B`一样,但是它在`B`之后。 +* 接下来是 `B`。 +* 最后是 `D`。 + +## 兼容性 + +CSS2 的绝大部分特性兼容各种浏览器和设备。现在 CSS3 的兼容性也越来越好了。 +但是兼容性问题仍然是需要留意的一个问题。 + +[QuirksMode CSS](http://www.quirksmode.org/css/)是关于这方面最好的资源。 + +## 扩展阅读 + +* [理解CSS的风格优先级: 特定性, 继承和层叠](http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/) +* [QuirksMode CSS](http://www.quirksmode.org/css/) +* [Z-Index - The stacking context](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context) -- cgit v1.2.3 From d2f6623cf67468d502fb4c243931687a879c5813 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Thu, 10 Apr 2014 23:48:34 +0000 Subject: Updated some headers --- zh-cn/csharp-cn.html.markdown | 3 ++- zh-cn/css-cn.html.markdown | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/csharp-cn.html.markdown b/zh-cn/csharp-cn.html.markdown index 618050a0..a3cda5b3 100644 --- a/zh-cn/csharp-cn.html.markdown +++ b/zh-cn/csharp-cn.html.markdown @@ -5,9 +5,10 @@ contributors: - ["Max Yankov", "https://github.com/golergka"] - ["Melvyn Laïly", "http://x2a.yt"] - ["Shaun McCarthy", "http://www.shaunmccarthy.com"] -translathors: +translators: - ["Jakukyo Friel", "http://weakish.github.io"] filename: LearnCSharp-cn.cs +lang: zh-cn --- diff --git a/zh-cn/css-cn.html.markdown b/zh-cn/css-cn.html.markdown index a188ee9b..dc6dcc4f 100644 --- a/zh-cn/css-cn.html.markdown +++ b/zh-cn/css-cn.html.markdown @@ -5,7 +5,8 @@ contributors: - ["Marco Scannadinari", "https://github.com/marcoms"] translators: - ["Jakukyo Friel", "https://weakish.github.io"] -filename: learncss.css +lang: zh-cn +filename: learncss-cn.css --- 早期的web没有样式,只是单纯的文本。通过CSS,可以实现网页样式和内容的分离。 -- cgit v1.2.3 From ca6e9fefcc04a443725f51a214f92543650dbf3b Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Mon, 28 Apr 2014 17:20:58 +0800 Subject: elisp_CN: typo --- zh-cn/elisp-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/elisp-cn.html.markdown b/zh-cn/elisp-cn.html.markdown index d303c2e8..06f38d77 100644 --- a/zh-cn/elisp-cn.html.markdown +++ b/zh-cn/elisp-cn.html.markdown @@ -132,7 +132,7 @@ lang: zh-cn ;; `C-xC-e' 这时屏幕上会显示两个窗口,而光标此时位于*test* buffer内 ;; 用鼠标单击上面的buffer就会使光标移回。 -;; 或者你可以使用 `C-xo' 是的光标跳到另一个窗口中 +;; 或者你可以使用 `C-xo' 使得光标跳到另一个窗口中 ;; 你可以用 `progn'命令将s式结合起来: (progn @@ -219,7 +219,7 @@ lang: zh-cn ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; 我们将一些名字存到列表中; +;; 我们将一些名字存到列表中: (setq list-of-names '("Sarah" "Chloe" "Mathilde")) ;; 用 `car'来取得第一个名字: -- cgit v1.2.3 From 4d626256605cf42ec45d064f7242d4c2146bdf96 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Tue, 29 Apr 2014 15:11:59 +0800 Subject: elixir-cn: fix typos & complete translation --- zh-cn/elixir-cn.html.markdown | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index 50f0e350..7a1ca084 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -54,7 +54,7 @@ tail #=> [2,3] # # 这表示会用左边的模式(pattern)匹配右侧 # -# 这是上面的例子中访问列列表的头部和尾部的就是这样工作的。 +# 上面的例子中访问列表的头部和尾部就是这样工作的。 # 当左右两边不匹配时,会返回error, 在这个 # 例子中,元组大小不一样。 @@ -101,7 +101,7 @@ string. 5 * 2 #=> 10 10 / 2 #=> 5.0 -# 在 elixir 操作符 `/` 返回值总是浮点数。 +# 在 elixir 中,操作符 `/` 返回值总是浮点数。 # 做整数除法使用 `div` div(10, 2) #=> 5 @@ -138,8 +138,8 @@ nil && 20 #=> nil # 总的排序顺序定义如下: # number < atom < reference < functions < port < pid < tuple < list < bit string -# 引用Joe Armstrong :”实际的顺序并不重要, -# 但是,一个整体排序是否经明确界定是非常重要的“。 +# 引用Joe Armstrong :“实际的顺序并不重要, +# 但是,一个整体排序是否经明确界定是非常重要的。” ## --------------------------- ## -- 控制结构(Control Flow) @@ -224,8 +224,8 @@ square.(5) #=> 25 # 也支持接收多个子句和卫士(guards). -# Guards可以进行模式匹配 -# Guards只有`when` 关键字指明: +# Guards 可以进行模式匹配 +# Guards 使用 `when` 关键字指明: f = fn x, y when x > 0 -> x + y x, y -> x * y @@ -273,7 +273,8 @@ end PrivateMath.sum(1, 2) #=> 3 # PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError) -# Function declarations also support guards and multiple clauses: + +# 函数定义同样支持 guards 和 多重子句: defmodule Geometry do def area({:rectangle, w, h}) do w * h @@ -348,7 +349,7 @@ end ## -- 并发(Concurrency) ## --------------------------- -# Elixir 依赖与actor并发模型。在Elixir编写并发程序的三要素: +# Elixir 依赖于 actor并发模型。在Elixir编写并发程序的三要素: # 创建进程,发送消息,接收消息 # 启动一个新的进程使用`spawn`函数,接收一个函数作为参数 -- cgit v1.2.3 From 88be5767a789adc42891da32aa1d7a8abd68404c Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Tue, 6 May 2014 21:24:11 +0800 Subject: elixir-cn: fix typos --- zh-cn/elixir-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/elixir-cn.html.markdown b/zh-cn/elixir-cn.html.markdown index 7a1ca084..daee8d3c 100644 --- a/zh-cn/elixir-cn.html.markdown +++ b/zh-cn/elixir-cn.html.markdown @@ -8,7 +8,7 @@ filename: learnelixir-cn.ex lang: zh-cn --- -Elixir 是一门构建在Elang VM 之上的函数式编程语言。Elixir 完全兼容 Eralng, +Elixir 是一门构建在Erlang VM 之上的函数式编程语言。Elixir 完全兼容 Erlang, 另外还提供了更标准的语法,特性。 ```elixir -- cgit v1.2.3 From 8c64a457a917d22544d1ce27a99d9cfe952e628c Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Mon, 19 May 2014 16:40:03 +0800 Subject: erlang: Chinese translation --- zh-cn/erlang-cn.html.markdown | 261 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 zh-cn/erlang-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/erlang-cn.html.markdown b/zh-cn/erlang-cn.html.markdown new file mode 100644 index 00000000..8d0f42a4 --- /dev/null +++ b/zh-cn/erlang-cn.html.markdown @@ -0,0 +1,261 @@ +--- +language: erlang +lang: zh-cn +contributors: + - ["Giovanni Cappellotto", "http://www.focustheweb.com/"] +translators: + - ["Jakukyo Friel", "http://weakish.github.io"] +filename: erlang-cn.erl +--- + +```erlang +% 百分比符号标明注释的开始。 + +%% 两个符号通常用于注释函数。 + +%%% 三个符号通常用于注释模块。 + +% Erlang 里使用三种标点符号: +% 逗号 (`,`) 分隔函数调用中的参数、数据构建和模式。 +% 句号 (`.`) (后跟空格)分隔函数和 shell 中的表达式。 +% 分号 (`;`) 分隔语句。以下环境中使用语句: +% 函数定义和`case`、`if`、`try..catch`、`receive`表达式。 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 1. 变量和模式匹配 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Num = 42. % 变量必须以大写字母开头。 + +% Erlang 的变量只能赋值一次。如果给变量赋不同的值,会导致错误: +Num = 43. % ** exception error: no match of right hand side value 43 + +% 大多数语言中`=`表示赋值语句,在Erlang中,则表示模式匹配。 +% `Lhs = Rhs`实际上意味着: +% 演算右边(Rhs), 将结果与左边的模式匹配。 +Num = 7 * 6. + +% 浮点数 +Pi = 3.14159. + +% Atoms 用于表示非数字的常量。 +% Atom 以小写字母开始,包含字母、数字、`_`和`@`。 +Hello = hello. +OtherNode = example@node. + +% Atom 中如果包含特殊字符,可以用单引号括起。 +AtomWithSpace = 'some atom with space'. + +% Erlang 的元组类似 C 的 struct. +Point = {point, 10, 45}. + +% 使用模式匹配操作符`=`获取元组的值。 +{point, X, Y} = Point. % X = 10, Y = 45 + +% 我们可以使用`_`存放我们不感兴趣的变量。 +% `_`被称为匿名变量。和其他变量不同, +% 同一个模式中的多个`_`变量不必绑定到相同的值。 +Person = {person, {name, {first, joe}, {last, armstrong}}, {footsize, 42}}. +{_, {_, {_, Who}, _}, _} = Person. % Who = joe + +% 列表使用方括号,元素间使用逗号分隔。 +% 列表的元素可以是任意类型。 +% 列表的第一个元素称为列表的 head,其余元素称为列表的 tail。 +ThingsToBuy = [{apples, 10}, {pears, 6}, {milk, 3}]. + +% 若`T`是一个列表,那么`[H|T]`同样是一个列表,head为`H`,tail为`T`. +% `|`分隔列表的 head 和 tail. +% `[]`是空列表。 +% 我们可以使用模式匹配操作来抽取列表中的元素。 +% 如果我们有一个非空的列表`L`,那么`[X|Y] = L`则 +% 抽取 L 的 head 至 X,tail 至 Y (X、Y需为未定义的变量)。 +[FirstThing|OtherThingsToBuy] = ThingsToBuy. +% FirstThing = {apples, 10} +% OtherThingsToBuy = {pears, 6}, {milk, 3} + +% Erlang 中的字符串其实是由整数组成的数组。字符串使用双引号。 +Name = "Hello". +[72, 101, 108, 108, 111] = "Hello". + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 2. 循序编程 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Module 是 Erlang 代码的基本单位。我们编写的所有函数都储存在 module 中。 +% Module 存储在后缀为 `.erl` 的文件中。 +% Module 必须事先编译。编译好的 module 以 `.beam` 结尾。 +-module(geometry). +-export([area/1]). % module 对外暴露的函数列表 + +% `area`函数包含两个分句,分句间以分号相隔。 +% 最后一个分句以句号加换行结尾。 +% 每个分句由头、体两部门组成。 +% 头部包含函数名称和用括号括起的模式, +% 体部包含一系列表达式,如果头部的模式和调用时的参数匹配,这些表达式会被演算。 +% 模式匹配依照定义时的顺序依次进行。 +area({rectangle, Width, Ht}) -> Width * Ht; +area({circle, R}) -> 3.14159 * R * R. + +% 编译文件为 geometry.erl. +c(geometry). % {ok,geometry} + +% 调用函数时必须使用 module 名和函数名。 +geometry:area({rectangle, 10, 5}). % 50 +geometry:area({circle, 1.4}). % 6.15752 + +% 在 Erlang 中,同一模块中,参数数目不同,名字相同的函数是完全不同的函数。 +-module(lib_misc). +-export([sum/1]). % 对外暴露的`sum`函数接受一个参数:由整数组成的列表。 +sum(L) -> sum(L, 0). +sum([], N) -> N; +sum([H|T], N) -> sum(T, H+N). + +% fun 是匿名函数。它们没有名字,不过可以赋值给变量。 +Double = fun(X) -> 2*X end. % `Double` 指向匿名函数 #Fun +Double(2). % 4 + +% fun 可以作为函数的参数和返回值。 +Mult = fun(Times) -> ( fun(X) -> X * Times end ) end. +Triple = Mult(3). +Triple(5). % 15 + +% 列表解析是创建列表的表达式(不使用fun、map 或 filter)。 +% `[F(X) || X <- L]` 表示 "由 `F(X)` 组成的列表,其中 `X` 取自列表 `L`。 +L = [1,2,3,4,5]. +[2*X || X <- L]. % [2,4,6,8,10] +% 列表解析可以使用生成器,也可以使用过滤器,过滤器用于筛选列表的一部分。 +EvenNumbers = [N || N <- [1, 2, 3, 4], N rem 2 == 0]. % [2, 4] + +% Guard 是用于增强模式匹配的结构。 +% Guard 可用于简单的测试和比较。 +% Guard 可用于函数定义的头部,以`when`关键字开头,或者其他可以使用表达式的地方。 +max(X, Y) when X > Y -> X; +max(X, Y) -> Y. + +% guard 可以由一系列 guard 表达式组成,这些表达式以逗号分隔。 +% `GuardExpr1, GuardExpr2, ..., GuardExprN` 为真,当且仅当每个 guard 表达式均为真。 +is_cat(A) when is_atom(A), A =:= cat -> true; +is_cat(A) -> false. +is_dog(A) when is_atom(A), A =:= dog -> true; +is_dog(A) -> false. + +% guard 序列 `G1; G2; ...; Gn` 为真,当且仅当其中任意一个 guard 表达式为真。 +% one of the guards `G1, G2, ...` evaluates to true. +is_pet(A) when is_dog(A); is_cat(A) -> true; +is_pet(A) -> false. + +% Record 使得可以将元组中的元素绑定到特定的名称。 +% Record 定义可以包含在 Erlang 源代码中,也可以放在后缀为`.hrl`的文件中。 +% Erlang 源代码可以包含这些文件。 +-record(todo, { + status = reminder, % Default value + who = joe, + text +}). + +% 在定义某个 record 之前,我们需要在 shell 中导入 record 的定义。 +% 我们可以使用 shell 函数`rr` (read records 的简称)。 +rr("records.hrl"). % [todo] + +% 创建和更新 record。 +X = #todo{}. +% #todo{status = reminder, who = joe, text = undefined} +X1 = #todo{status = urgent, text = "Fix errata in book"}. +% #todo{status = urgent, who = joe, text = "Fix errata in book"} +X2 = X1#todo{status = done}. +% #todo{status = done,who = joe,text = "Fix errata in book"} + +% `case` 表达式。 +% `filter` 返回由列表`L`中所有满足`P(x)`为真的元素`X`组成的列表。 +filter(P, [H|T]) -> + case P(H) of + true -> [H|filter(P, T)]; + false -> filter(P, T) + end; +filter(P, []) -> []. +filter(fun(X) -> X rem 2 == 0 end, [1, 2, 3, 4]). % [2, 4] + +% `if` 表达式。 +max(X, Y) -> + if + X > Y -> X; + X < Y -> Y; + true -> nil; + end. + +% 警告: `if` 表达式里至少有一个 guard 为真,否则会触发异常。 + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 3. 异常 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% 当遇到内部错误或显式调用时,会触发异常。 +% 显式调用包括 `throw(Exception)`, `exit(Exception)` 或 +% `erlang:error(Exception)`. +generate_exception(1) -> a; +generate_exception(2) -> throw(a); +generate_exception(3) -> exit(a); +generate_exception(4) -> {'EXIT', a}; +generate_exception(5) -> erlang:error(a). + +% Erlang 有两种捕获异常的方法。其一是将调用包裹在`try...catch`表达式中。 +catcher(N) -> + try generate_exception(N) of + Val -> {N, normal, Val} + catch + throw:X -> {N, caught, thrown, X}; + exit:X -> {N, caught, exited, X}; + error:X -> {N, caught, error, X} + end. + +% 另一种方式是将调用包裹在`catch`表达式中。 +% 此时异常会被转化为一个描述错误的元组。 +catcher(N) -> catch generate_exception(N). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% 4. 并发 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Erlang 依赖于 actor并发模型。在 Erlang 编写并发程序的三要素: +% 创建进程,发送消息,接收消息 + +% 启动一个新的进程使用`spawn`函数,接收一个函数作为参数 + +F = fun() -> 2 + 2 end. % #Fun +spawn(F). % <0.44.0> + +% `spawn` 函数返回一个pid(进程标识符),你可以使用pid向进程发送消息。 +% 使用 `!` 操作符发送消息。 +% 我们需要在进程内接收消息,要用到 `receive` 机制。 + +-module(caculateGeometry). +-compile(export_all). +caculateAera() -> + receive + {rectangle, W, H} -> + W * H; + {circle, R} -> + 3.14 * R * R; + _ -> + io:format("We can only caculate area of rectangles or circles.") + end. + +% 编译这个模块,在 shell 中创建一个进程,并执行 `caculateArea` 函数。 +c(caculateGeometry). +CaculateAera = spawn(caculateGeometry, caculateAera, []). +CaculateAera ! {circle, 2}. % 12.56000000000000049738 + +% shell也是一个进程(process), 你可以使用`self`获取当前 pid + +self(). % <0.41.0> + +``` + +## References + +* ["Learn You Some Erlang for great good!"](http://learnyousomeerlang.com/) +* ["Programming Erlang: Software for a Concurrent World" by Joe Armstrong](http://pragprog.com/book/jaerlang/programming-erlang) +* [Erlang/OTP Reference Documentation](http://www.erlang.org/doc/) +* [Erlang - Programming Rules and Conventions](http://www.erlang.se/doc/programming_rules.shtml) -- cgit v1.2.3 From eae9850750d0703e38878bbe50822c0b511a0e32 Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Mon, 19 May 2014 17:05:44 +0800 Subject: erlang: refine Chinese translation. --- zh-cn/erlang-cn.html.markdown | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/erlang-cn.html.markdown b/zh-cn/erlang-cn.html.markdown index 8d0f42a4..32e84278 100644 --- a/zh-cn/erlang-cn.html.markdown +++ b/zh-cn/erlang-cn.html.markdown @@ -141,13 +141,11 @@ is_dog(A) when is_atom(A), A =:= dog -> true; is_dog(A) -> false. % guard 序列 `G1; G2; ...; Gn` 为真,当且仅当其中任意一个 guard 表达式为真。 -% one of the guards `G1, G2, ...` evaluates to true. is_pet(A) when is_dog(A); is_cat(A) -> true; is_pet(A) -> false. -% Record 使得可以将元组中的元素绑定到特定的名称。 -% Record 定义可以包含在 Erlang 源代码中,也可以放在后缀为`.hrl`的文件中。 -% Erlang 源代码可以包含这些文件。 +% Record 可以将元组中的元素绑定到特定的名称。 +% Record 定义可以包含在 Erlang 源代码中,也可以放在后缀为`.hrl`的文件中(Erlang 源代码中 include 这些文件)。 -record(todo, { status = reminder, % Default value who = joe, @@ -192,7 +190,7 @@ max(X, Y) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 当遇到内部错误或显式调用时,会触发异常。 -% 显式调用包括 `throw(Exception)`, `exit(Exception)` 或 +% 显式调用包括 `throw(Exception)`, `exit(Exception)` 和 % `erlang:error(Exception)`. generate_exception(1) -> a; generate_exception(2) -> throw(a); -- cgit v1.2.3 From b0eb92dd5560ebe6f893e2b6088629f1c38d528d Mon Sep 17 00:00:00 2001 From: niuzhist Date: Sat, 31 May 2014 01:15:30 -0700 Subject: JSON: Chinese translation --- zh-cn/json-cn.html.markdown | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 zh-cn/json-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/json-cn.html.markdown b/zh-cn/json-cn.html.markdown new file mode 100644 index 00000000..75966595 --- /dev/null +++ b/zh-cn/json-cn.html.markdown @@ -0,0 +1,51 @@ +--- +language: json +contributors: + - ["Anna Harren", "https://github.com/iirelu"] +translators: + - ["Zach Zhang", "https://github.com/checkcheckzz"] +filename: learnjson-cn.json +lang: zh-cn +--- + +因为JSON是一个极其简单的数据交换形式,这个最有可能将会是曾经最简单 +的Learn X in Y Minutes。 + +最纯正形式的JSON没有实际的注解,但是大多数解析器将会 +接受C-风格(//, /\* \*/)的注解。为了这个目的,但是, +一切都将会是100%有效的JSON。幸亏,它是不言自明的。 + +```json +{ + "numbers": 0, + "strings": "Hellø, wørld. All unicode is allowed, along with \"escaping\".", + "has bools?": true, + "nothingness": null, + + "big number": 1.2e+100, + + "objects": { + "comment": "Most of your structure will come from objects.", + + "array": [0, 1, 2, 3, "Arrays can have anything in them.", 5], + + "another object": { + "comment": "These things can be nested, very useful." + } + }, + + "silliness": [ + { + "sources of potassium": ["bananas"] + }, + [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, "neo"], + [0, 0, 0, 1] + ] + ], + + "that was short": "And, you're done. You know know everything JSON has to offer." +} +``` -- cgit v1.2.3 From 070df0635c70dd214fee43b522c2d55523c182f4 Mon Sep 17 00:00:00 2001 From: niuzhist Date: Sat, 31 May 2014 14:13:23 -0700 Subject: XML: Chinese translation --- zh-cn/xml-cn.html.markdown | 132 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 zh-cn/xml-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/xml-cn.html.markdown b/zh-cn/xml-cn.html.markdown new file mode 100644 index 00000000..0476a0a8 --- /dev/null +++ b/zh-cn/xml-cn.html.markdown @@ -0,0 +1,132 @@ +--- +language: xml +contributors: + - ["João Farias", "https://github.com/JoaoGFarias"] +translators: + - ["Zach Zhang", "https://github.com/checkcheckzz"] +filename: learnxml-cn.xml +lang: zh-cn +--- + +XML是一种标记语言,被设计用来存储数据和传输数据。 + +不像HTML, XML不指定怎样显示或格式化数据,只是携带它。 + + +* XML 语法 + +```xml + + + + + + Everyday Italian + Giada De Laurentiis + 2005 + 30.00 + + + Harry Potter + J K. Rowling + 2005 + 29.99 + + + Learning XML + Erik T. Ray + 2003 + 39.95 + + + + + + + + + + + +computer.gif + + +``` + +* 良好格式的文件 x 验证 + +一个XML文件是良好格式的如果它是语法正确的。 +但是, 使用文件定义,比如DTD和XML概要,在文件中插入更多的限制是可能的。 + +一个遵守一个文件定义的XML文件被叫做有效的,对于那个文件来说。 + +有了这个工具,你能够在应用逻辑之外检查XML数据。 + +```xml + + + + + + + + Everyday Italian + 30.00 + + + + + + + + + + +]> + + + + + + + + + + + + + +]> + + + + Everyday Italian + 30.00 + + + + +``` + + + -- cgit v1.2.3 From c93bb219f50b22105e51082824bdf0c98b3fc2b3 Mon Sep 17 00:00:00 2001 From: niuzhist Date: Sat, 31 May 2014 15:18:05 -0700 Subject: remove white space at the end of both xml files --- zh-cn/xml-cn.html.markdown | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/xml-cn.html.markdown b/zh-cn/xml-cn.html.markdown index 0476a0a8..bf0b074f 100644 --- a/zh-cn/xml-cn.html.markdown +++ b/zh-cn/xml-cn.html.markdown @@ -124,9 +124,4 @@ XML是一种标记语言,被设计用来存储数据和传输数据。 30.00 - - -``` - - - +``` \ No newline at end of file -- cgit v1.2.3 From e8b6055e103d03b62b2c09b04435ac8f0093d327 Mon Sep 17 00:00:00 2001 From: niuzhist Date: Sat, 31 May 2014 18:26:12 -0700 Subject: yaml: Chinese translation --- zh-cn/yaml-cn.html.markdown | 136 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 zh-cn/yaml-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/yaml-cn.html.markdown b/zh-cn/yaml-cn.html.markdown new file mode 100644 index 00000000..8370b224 --- /dev/null +++ b/zh-cn/yaml-cn.html.markdown @@ -0,0 +1,136 @@ +--- +language: yaml +contributors: + - ["Adam Brenecki", "https://github.com/adambrenecki"] +translators: + - ["Zach Zhang", "https://github.com/checkcheckzz"] +filename: learnyaml-cn.yaml +lang: zh-cn +--- + +YAMLһлԣƳֱӿдɶġ + +JSONϸ񳬼﷨зPythonPythonһ +YAMLƱ + + +```yaml +# YAMLеע⿴ + +################ +# # +################ + +# ǵĸ (ļ) һͼ +# ȼڱһֵ䣬 +key: value +another_key: Another value goes here. +a_number_value: 100 +scientific_notation: 1e+12 +boolean: true +null_value: null +key with spaces: value +# ע⵽ַҪáǣǿԱá +"Keys can be quoted too.": "Useful if you want to put a ':' in your key." + +# ַȿдһ'ֿ'(ʹ |) +# һ'۵'(ʹ '>') +literal_block: | + This entire block of text will be the value of the 'literal_block' key, + with line breaks being preserved. + + The literal continues until de-dented, and the leading indentation is + stripped. + + Any lines that are 'more-indented' keep the rest of their indentation - + these lines will be indented by 4 spaces. +folded_style: > + This entire block of text will be the value of 'folded_style', but this + time, all newlines will be replaced with a single space. + + Blank lines, like above, are converted to a newline character. + + 'More-indented' lines keep their newlines, too - + this text will appear over two lines. + +#################### +# # +#################### + +# Ƕͨɵġ +a_nested_map: + key: value + another_key: Another Value + another_nested_map: + hello: hello + +# ͼֵַ +0.25: a float key + +# ֵҲǶж?ֵĿʼ +? | + This is a key + that has multiple lines +: and this is its value + +# YAMLҲֵǼͣǺܶԽᱧԹ + +# (ȼڱ) +a_sequence: + - Item 1 + - Item 2 + - 0.5 # sequences can contain disparate types + - Item 4 + - key: value + another_key: another_value + - + - This is a sequence + - inside another sequence + +# ΪYAMLJSONijҲдJSONĵͼУ +json_map: {"key": "value"} +json_seq: [3, 2, 1, "takeoff"] + +####################### +# YAMLص # +####################### + +# YAMLһص'ê'򵥵ļظݡ +# ֵֵͬ +anchored_content: &anchor_name This string will appear as the value of two keys. +other_anchor: *anchor_name + +# YAMLбǩʾ͡ +explicit_string: !!str 0.5 +# һЩʵضԵıǩΪPythonĸ͡ +python_complex_number: !!python/complex 1+2j + +#################### +# YAML # +#################### + +# ֲַǽеYAMLı +# ISO ʽںʱҲǿԱġ +datetime: 2001-12-15T02:59:43.1Z +datetime_with_spaces: 2001-12-14 21:59:43.10 -5 +date: 2002-12-14 + +# !!binaryǩһַʵһblobbase64ʾ +gif_file: !!binary | + R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 + OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ + +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC + AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= + +# YAMLһͣ +set: + ? item1 + ? item2 + ? item3 + +# PythonһϽnullֵĵͼļϵȼڣ +set2: + item1: null + item2: null + item3: null +``` -- cgit v1.2.3 From 195735fd176b359f98450891ce00a233ccd585a8 Mon Sep 17 00:00:00 2001 From: niuzhist Date: Sat, 31 May 2014 18:34:05 -0700 Subject: fix encoding issue --- zh-cn/yaml-cn.html.markdown | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/yaml-cn.html.markdown b/zh-cn/yaml-cn.html.markdown index 8370b224..bcc41067 100644 --- a/zh-cn/yaml-cn.html.markdown +++ b/zh-cn/yaml-cn.html.markdown @@ -8,21 +8,21 @@ filename: learnyaml-cn.yaml lang: zh-cn --- -YAMLһлԣƳֱӿдɶġ +YAML是一个数据序列化语言,被设计成人类直接可写可读的。 -JSONϸ񳬼﷨зPythonPythonһ -YAMLƱ +它是JSON的严格超集,增加了语法显著换行符和缩进,就像Python。但和Python不一样, +YAML根本不容许文字制表符。 ```yaml -# YAMLеע⿴ +# YAML中的注解看起来像这样。 ################ -# # +# 标量类型 # ################ -# ǵĸ (ļ) һͼ -# ȼڱһֵ䣬 +# 我们的根对象 (它们在整个文件里延续) 将会是一个地图, +# 它等价于在别的语言里的一个字典,哈西表或对象。 key: value another_key: Another value goes here. a_number_value: 100 @@ -30,11 +30,11 @@ scientific_notation: 1e+12 boolean: true null_value: null key with spaces: value -# ע⵽ַҪáǣǿԱá +# 注意到字符串不需要被引用。但是,它们可以被引用。 "Keys can be quoted too.": "Useful if you want to put a ':' in your key." -# ַȿдһ'ֿ'(ʹ |) -# һ'۵'(ʹ '>') +# 多行字符串既可以写成像一个'文字块'(使用 |), +# 或像一个'折叠块'(使用 '>')。 literal_block: | This entire block of text will be the value of the 'literal_block' key, with line breaks being preserved. @@ -54,28 +54,28 @@ folded_style: > this text will appear over two lines. #################### -# # +# 集合类型 # #################### -# Ƕͨɵġ +# 嵌套是通过缩进完成的。 a_nested_map: key: value another_key: Another Value another_nested_map: hello: hello -# ͼֵַ +# 地图不用有字符串键值。 0.25: a float key -# ֵҲǶж?ֵĿʼ +# 键值也可以是多行对象,用?表明键值的开始。 ? | This is a key that has multiple lines : and this is its value -# YAMLҲֵǼͣǺܶԽᱧԹ +# YAML也容许键值是集合类型,但是很多语言将会抱怨。 -# (ȼڱ) +# 序列 (等价于表或数组) 看起来像这样: a_sequence: - Item 1 - Item 2 @@ -87,48 +87,48 @@ a_sequence: - This is a sequence - inside another sequence -# ΪYAMLJSONijҲдJSONĵͼУ +# 因为YAML是JSON的超集,你也可以写JSON风格的地图和序列: json_map: {"key": "value"} json_seq: [3, 2, 1, "takeoff"] ####################### -# YAMLص # +# 其余的YAML特点 # ####################### -# YAMLһص'ê'򵥵ļظݡ -# ֵֵͬ +# YAML还有一个方便的特点叫'锚',它让你简单地在整个文件里重复内容。 +# 两个键值将会有相同的值: anchored_content: &anchor_name This string will appear as the value of two keys. other_anchor: *anchor_name -# YAMLбǩʾ͡ +# YAML还有标签,你可以用它显示地声明类型。 explicit_string: !!str 0.5 -# һЩʵضԵıǩΪPythonĸ͡ +# 一些解析器实现特定语言的标签,就像这个为了Python的复数类型。 python_complex_number: !!python/complex 1+2j #################### -# YAML # +# 其余的YAML类型 # #################### -# ֲַǽеYAMLı -# ISO ʽںʱҲǿԱġ +# 字符串和数字不是仅有的YAML可以理解的标量。 +# ISO 格式的日期和日期时间文字也是可以被解析的。 datetime: 2001-12-15T02:59:43.1Z datetime_with_spaces: 2001-12-14 21:59:43.10 -5 date: 2002-12-14 -# !!binaryǩһַʵһblobbase64ʾ +# 这个!!binary标签表明一个字符串实际上是一个二进制blob的base64编码表示。 gif_file: !!binary | R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= -# YAMLһͣ +# YAML还有一个集合类型,它看起来像这样: set: ? item1 ? item2 ? item3 -# PythonһϽnullֵĵͼļϵȼڣ +# 像Python一样,集合仅是有null数值的地图;上面的集合等价于: set2: item1: null item2: null -- cgit v1.2.3 From 24cffa75360ac915f61369ebaf0db34d6b7fc0e1 Mon Sep 17 00:00:00 2001 From: niuzhist Date: Sun, 1 Jun 2014 09:39:22 -0700 Subject: [yaml/cn]: add last translation --- zh-cn/yaml-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/yaml-cn.html.markdown b/zh-cn/yaml-cn.html.markdown index bcc41067..fc510eb5 100644 --- a/zh-cn/yaml-cn.html.markdown +++ b/zh-cn/yaml-cn.html.markdown @@ -79,7 +79,7 @@ a_nested_map: a_sequence: - Item 1 - Item 2 - - 0.5 # sequences can contain disparate types + - 0.5 # 序列可以包含不同类型。 - Item 4 - key: value another_key: another_value -- cgit v1.2.3 From 1f1c7b616cf07ab1dee784ca8abb2a82d92f5f32 Mon Sep 17 00:00:00 2001 From: Xavier Yao Date: Thu, 5 Jun 2014 22:48:49 +0800 Subject: zh-cn translatation for Swift --- zh-cn/swift-cn.html.markdown | 226 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 zh-cn/swift-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown new file mode 100644 index 00000000..e9dcb858 --- /dev/null +++ b/zh-cn/swift-cn.html.markdown @@ -0,0 +1,226 @@ +--- +language: swift +contributors: + - ["Grant Timmerman", "http://github.com/grant"] +translators: + - ["Xavier Yao", "http://github.com/xavieryao"] +filename: learnswift-cn.swift +--- + +Swift 是Apple 开发的用于iOS 和OS X 开发的编程语言。Swift 于2014年Apple WWDC (全球开发者大会)中被引入,用以与Objective-C 共存,同时对错误代码更具弹性。Swift 由Xcode 6 beta 中包含的LLVM编译器编译。 + +参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/LandingPage/index.html) ——一个完整的Swift 教程 + +```js +// +// 基础 +// + +println("Hello, world") +var myVariable = 42 +let myConstant = 3.1415926 +let explicitDouble: Double = 70 +let label = "some text " + String(myVariable) // Casting +let piText = "Pi = \(myConstant)" // String interpolation +var optionalString: String? = "optional" // Can be nil +optionalString = nil + + +// +// 数组与字典(关联数组) +// + +// 数组 +var shoppingList = ["catfish", "water", "lemons"] +shoppingList[1] = "bottle of water" +let emptyArray = String[]() + +// 字典 +var occupations = [ + "Malcolm": "Captain", + "kaylee": "Mechanic" +] +occupations["Jayne"] = "Public Relations" +let emptyDictionary = Dictionary() + + +// +// 控制流 +// + +// 用于数组的for 循环 +let myArray = [1, 1, 2, 3, 5] +for value in myArray { + if value == 1 { + println("One!") + } else { + println("Not one!") + } +} + +// 用于字典的for 循环 +for (key, value) in dict { + println("\(key): \(value)") +} + +// 用于区间的for 循环 +for i in -1...1 { // [-1, 0, 1] + println(i) +} +// 使用 .. 表示的区间不包含最后一个元素 [-1,0,1) + +// while 循环 +var i = 1 +while i < 1000 { + i *= 2 +} + +// do-while 循环 +do { + println("hello") +} while 1 == 2 + +// Switch +let vegetable = "red pepper" +switch vegetable { +case "celery": + let vegetableComment = "Add some raisins and make ants on a log." +case "cucumber", "watercress": + let vegetableComment = "That would make a good tea sandwich." +case let x where x.hasSuffix("pepper"): + let vegetableComment = "Is it a spicy \(x)?" +default: // 必须 (为了覆盖所有可能的输入) + let vegetableComment = "Everything tastes good in soup." +} + + +// +// 函数 +// + +// 函数是一等类型,这意味着可以在函数中构建函数 +// 并且可以被传递 + +// 函数 +func greet(name: String, day: String) -> String { + return "Hello \(name), today is \(day)." +} +greet("Bob", "Tuesday") + +// 使用多元数组返回多返回值的函数 +func getGasPrices() -> (Double, Double, Double) { + return (3.59, 3.69, 3.79) +} + +// 不定参数 +func setup(numbers: Int...) {} + +// 传递、返回函数 +func makeIncrementer() -> (Int -> Int) { + func addOne(number: Int) -> Int { + return 1 + number + } + return addOne +} +var increment = makeIncrementer() +increment(7) + + +// +// 闭包 +// + +// 函数是特殊的闭包({}) + +// 闭包示例. +// `->` 分隔参数和返回类型 +// `in` 分隔闭包头和闭包体 +numbers.map({ + (number: Int) -> Int in + let result = 3 * number + return result + }) + +// 当类型已知时,可以这样做: +var numbers = [1, 2, 6] +numbers = numbers.map({ number in 3 * number }) +print(numbers) // [3, 6, 18] + + +// +// 类 +// + +// 类的全部方法和属性都是public 的 +// 如果你在一个数据结构中只需储存数据, +// 应使用 `struct` + +// 集成自`Shape` 类的简单的类`Square +class Rect: Shape { + var sideLength: Int = 1 + + // Custom getter and setter property + var perimeter: Int { + get { + return 4 * sideLength + } + set { + sideLength = newValue / 4 + } + } + + init(sideLength: Int) { + super.init() + self.sideLength = sideLength + } + + func shrink() { + if sideLength > 0 { + --sideLength + } + } + + override func getArea() -> Int { + return sideLength * sideLength + } +} +var mySquare = new Square(sideLength: 5) +print(mySquare.getArea()) // 25 +mySquare.shrink() +print(mySquare.sideLength) // 4 + +// 如果你不需要自定义getter 和setter, +// 但仍希望在获取或设置一个属性之前或之后运行 +// 一些代码,你可以使用`willSet` 和 `didSet` + + +// +// 枚举类型 +// + +// 枚举类型可以是某种指定的类型,抑或自成一种类型 +// 像类一样,枚举类型可以包含方法 + +enum Suit { + case Spades, Hearts, Diamonds, Clubs + func getIcon() -> String { + switch self { + case .Spades: return "♤" + case .Hearts: return "♡" + case .Diamonds: return "♢" + case .Clubs: return "♧" + } + } +} + + +// +// 其它 +// + +// `协议(protocol)`: 与Java 的接口(Interface) 类似. +// `扩展(extension)`: 为现有类型添加额外特性 +// 泛型: 与Java 相似。使用`where` 关键字指定 +// 泛型的要求. + +``` \ No newline at end of file -- cgit v1.2.3 From d9e5677d1a820021bd486040a8beeb9942f46603 Mon Sep 17 00:00:00 2001 From: Nami-Doc Date: Thu, 5 Jun 2014 22:45:41 +0200 Subject: Add lang: tag for swift/zh-cn - fixes #640 --- zh-cn/swift-cn.html.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index e9dcb858..c87f9d10 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -1,10 +1,11 @@ --- language: swift +filename: learnswift-cn.swift contributors: - ["Grant Timmerman", "http://github.com/grant"] translators: - ["Xavier Yao", "http://github.com/xavieryao"] -filename: learnswift-cn.swift +lang: zh-cn --- Swift 是Apple 开发的用于iOS 和OS X 开发的编程语言。Swift 于2014年Apple WWDC (全球开发者大会)中被引入,用以与Objective-C 共存,同时对错误代码更具弹性。Swift 由Xcode 6 beta 中包含的LLVM编译器编译。 @@ -223,4 +224,4 @@ enum Suit { // 泛型: 与Java 相似。使用`where` 关键字指定 // 泛型的要求. -``` \ No newline at end of file +``` -- cgit v1.2.3 From ce2e9b93fb80d546fa83cc364aac770a5ae17a0e Mon Sep 17 00:00:00 2001 From: bobozhengsir Date: Fri, 13 Jun 2014 20:01:16 +0800 Subject: Update scala-cn.html.markdown miss a comma at line 372 --- zh-cn/scala-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 24f73bb5..28af8ddc 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -369,7 +369,7 @@ import scala.collection.immutable._ import scala.collection.immutable.{List, Map} // 使用 '=>' 来重命名一个 import -import scala.collection.immutable{ List => ImmutableList } +import scala.collection.immutable.{ List => ImmutableList } // import 除了一些类的其它所有的类。下面的例子除去了 Map 类和 Set 类: import scala.collection.immutable.{Map => _, Set => _, _} -- cgit v1.2.3 From b6f889c9e6761430c72d1b967980d61f494280c5 Mon Sep 17 00:00:00 2001 From: niuzhist Date: Fri, 13 Jun 2014 19:10:37 -0700 Subject: [json/cn]: fix the original typo --- zh-cn/json-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/json-cn.html.markdown b/zh-cn/json-cn.html.markdown index 75966595..3a8db2cf 100644 --- a/zh-cn/json-cn.html.markdown +++ b/zh-cn/json-cn.html.markdown @@ -46,6 +46,6 @@ lang: zh-cn ] ], - "that was short": "And, you're done. You know know everything JSON has to offer." + "that was short": "And, you're done. You now know everything JSON has to offer." } ``` -- cgit v1.2.3 From 03c03f7d19c4bc5af5525543f43dc83a507a25a7 Mon Sep 17 00:00:00 2001 From: Jichao Ouyang Date: Sat, 21 Jun 2014 00:01:09 +0800 Subject: [julia/zh-cn] Chinese translation for Julia --- zh-cn/julia-cn.html.markdown | 729 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 729 insertions(+) create mode 100644 zh-cn/julia-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/julia-cn.html.markdown b/zh-cn/julia-cn.html.markdown new file mode 100644 index 00000000..b7239786 --- /dev/null +++ b/zh-cn/julia-cn.html.markdown @@ -0,0 +1,729 @@ +--- +language: julia +filename: learn-julia-zh.jl +contributors: + - ["Jichao Ouyang", "http://oyanglul.us"] +translators: + - ["Jichao Ouyang"] +lang: zh-cn +--- + +```julia +# 单行注释只需要一个井号 +#= 多行注释 + 只需要以 '#=' 开始 '=#' 结束 + 还可以嵌套. +=# + +#################################################### +## 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 # 用 Int 除 Int 永远返回 Float +div(5, 2) # => 2 # 使用 div 截断小数点 +5 \ 35 # => 7.0 +2 ^ 2 # => 4 # 次方, 不是二进制 xor +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' + +# 可以像取数组取值一样用 index 取出对应字符 +"This is a string"[1] # => 'T' # Julia 的 index 从 1 开始 :( +# 但是对 UTF-8 无效, +# 因此建议使用遍历器 (map, for loops, 等). + +# $ 可用于字符插值: +"2 + 2 = $(2 + 2)" # => "2 + 2 = 4" +# 可以将任何 Julia 表达式放入括号。 + +# 另一种格式化字符串的方式是 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 的命名规约: +# +# * 变量名为小写,单词之间以下划线连接('\_')。 +# +# * 类型名以大写字母开头,单词以 CamelCase 方式连接。 +# +# * 函数与宏的名字小写,无下划线。 +# +# * 会改变输入的函数名末位为 !。 +# 这类函数有时被称为 mutating functions 或 in-place functions. + +# 数组存储一列值,index 从 1 开始。 +a = Int64[] # => 0-element Int64 Array + +# 一维数组可以以逗号分隔值的方式声明。 +b = [4, 5, 6] # => 包含 3 个 Int64 类型元素的数组: [4, 5, 6] +b[1] # => 4 +b[end] # => 6 + +# 二维数组以分号分隔维度。 +matrix = [1 2; 3 4] # => 2x2 Int64 数组: [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 又变成了 [4,5,6]. + +a[1] # => 1 # 永远记住 Julia 的 index 从 1 开始! + +# 用 end 可以直接取到最后索引. 可用作任何索引表达式 +a[end] # => 6 + +# 还支持 shift 和 unshift +shift!(a) # => 返回 1,而 a 现在时 [2,4,3,4,5,6] +unshift!(a,7) # => [7,2,4,3,4,5,6] + +# 以叹号结尾的函数名表示它会改变参数的值 +arr = [5,4,6] # => 包含三个 Int64 元素的数组: [5,4,6] +sort(arr) # => [4,5,6]; arr 还是 [5,4,6] +sort!(arr) # => [4,5,6]; arr 现在是 [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 + +# 错误会指出发生的行号,包括标准库 +# 如果你有 Julia 源代码,你可以找到这些地方 + +# 可以用 range 初始化数组 +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 变成了 [3,5] + +# 用 append! 连接数组 +b = [1,2,3] +append!(a,b) # a 变成了 [1, 2, 3, 4, 5, 1, 2, 3] + +# 检查元素是否在数组中 +in(1, a) # => true + +# 用 length 获得数组长度 +length(a) # => 8 + +# Tuples 是 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 + +# 大多数组的函数同样支持 tuples +length(tup) # => 3 +tup[1:2] # => (1,2) +in(2, tup) # => true + +# 可以将 tuples 元素分别赋给变量 +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) + +# 单元素 tuple 不等于其元素值 +(1,) == 1 # => false +(1) == 1 # => true + +# 交换值 +e, d = d, e # => (5,4) # d is now 5 and e is now 4 + + +# 字典Dictionaries store mappings +empty_dict = Dict() # => Dict{Any,Any}() + +# 也可以用字面量创建字典 +filled_dict = ["one"=> 1, "two"=> 2, "three"=> 3] +# => Dict{ASCIIString,Int64} + +# 用 [] 获得键值 +filled_dict["one"] # => 1 + +# 获得所有键 +keys(filled_dict) +# => KeyIterator{Dict{ASCIIString,Int64}}(["three"=>3,"one"=>1,"two"=>2]) +# 注意,键的顺序不是插入时的顺序 + +# 获得所有值 +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(dictionary,key,default_value) +get(filled_dict,"one",4) # => 1 +get(filled_dict,"four",4) # => 4 + +# 用 Sets 表示无序不可重复的值的集合 +empty_set = Set() # => Set{Any}() +# 初始化一个 Set 并定义其值 +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(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 语句,缩进不是必要的 +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 +# => prints "some var is smaller than 10" + + +# For 循环遍历 +# Iterable 类型包括 Range, Array, Set, Dict, 以及 String. +for animal=["dog", "cat", "mouse"] + println("$animal is a mammal") + # 可用 $ 将 variables 或 expression 转换为字符串into strings +end +# prints: +# dog is a mammal +# cat is a mammal +# mouse is a mammal + +# You can use 'in' instead of '='. +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 循环 +x = 0 +while x < 4 + println(x) + x += 1 # 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) # => 在 "x is 5 and y is 6" 后会打印 11 + +# 还可以定义接收可变长参数的函数 +function varargs(args...) + return args + # 关键字 return 可在函数内部任何地方返回 +end +# => varargs (generic function with 1 method) + +varargs(1,2,3) # => (1,2,3) + +# 省略号 ... 被称为 splat. +# 刚刚用在了函数定义中 +# 还可以用在函数的调用 +# Array 或者 Tuple 的内容会变成参数列表 +Set([1,2,3]) # => Set{Array{Int64,1}}([1,2,3]) # 获得一个 Array 的 Set +Set([1,2,3]...) # => Set{Int64}(1,2,3) # 相当于 Set(1,2,3) + +x = (1,2,3) # => (1,2,3) +Set(x) # => Set{(Int64,Int64,Int64)}((1,2,3)) # 一个 Tuple 的 Set +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") # note the ; + 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 + +# 这是用 "stabby lambda syntax" 创建的匿名函数 +(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] + +# 还可以使用 list comprehensions 替代 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 是代表类型的类型,也代表他自己的类型 + +# 类型可用作文档化,优化,以及调度 +# 并不是静态检查类型 + +# 用户还可以自定义类型 +# 跟其他语言的 records 或 structs 一样 +# 用 `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") + +# struct 类似的类型被称为具体类型 +# 他们可被实例化但不能有子类型 +# 另一种类型是抽象类型 + +# abstract Name +abstract Cat # just a name and point in the type hierarchy + +# 抽象类型不能被实例化,但是可以有子类型 +# 例如,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} + +# 所有的类型都有父类型; 可以用函数 `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") + # Panthers 只有这个构造函数,没有默认构造函数 +end +# 使用内置构造函数,如 Panther,可以让你控制 +# 如何构造类型的值 +# 应该尽可能使用外部构造函数而不是内部构造函数 + +#################################################### +## 6. 多分派 +#################################################### + +# 在Julia中, 所有的具名函数都是类属函数 +# 这意味着他们都是有很大小方法组成的 +# 每个 Lion 的构造函数都是类属函数 Lion 的方法 + +# 我们来看一个非构造函数的例子 + +# 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 + +# 定义一个接收 Cats 的函数 +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! + +# 让我们修改一下传入具体为 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 方法 +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 + + +# Under the hood +# 你还可以看看 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 # Fetch l from memory? + # imul RAX, RAX # Square l and store the result in RAX + # pop RBP # Restore old base pointer + # ret # Result will still be in 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 # Scalar single precision multiply (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 # Scalar double precision multiply (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 + # +``` -- cgit v1.2.3 From 1f4bcf8a7a23cd2ea687e3a197f65508b4d1b919 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 12:58:17 +0800 Subject: Create markdown-cn.html.markdown initiate --- zh-cn/markdown-cn.html.markdown | 246 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 zh-cn/markdown-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown new file mode 100644 index 00000000..9a863bac --- /dev/null +++ b/zh-cn/markdown-cn.html.markdown @@ -0,0 +1,246 @@ +--- +language: markdown +contributors: + - ["Dan Turkel", "http://danturkel.com/"] +filename: markdown.md +--- + +Markdown was created by John Gruber in 2004. It's meant to be an easy to read and write syntax which converts easily to HTML (and now many other formats as well). + +Give me as much feedback as you want! / Feel free to fork and pull request! + + +``` + + + + + + +# This is an

+## This is an

+### This is an

+#### This is an

+##### This is an

+###### This is an
+ + +This is an h1 +============= + +This is an h2 +------------- + + + + +*This text is in italics.* +_And so is this text._ + +**This text is in bold.** +__And so is this text.__ + +***This text is in both.*** +**_As is this!_** +*__And this!__* + + + +~~This text is rendered with strikethrough.~~ + + + +This is a paragraph. I'm typing in a paragraph isn't this fun? + +Now I'm in paragraph 2. +I'm still in paragraph 2 too! + + +I'm in paragraph three! + + + +I end with two spaces (highlight me to see them). + +There's a
above me! + + + +> This is a block quote. You can either +> manually wrap your lines and put a `>` before every line or you can let your lines get really long and wrap on their own. +> It doesn't make a difference so long as they start with a `>`. + +> You can also use more than one level +>> of indentation? +> How neat is that? + + + + +* Item +* Item +* Another item + +or + ++ Item ++ Item ++ One more item + +or + +- Item +- Item +- One last item + + + +1. Item one +2. Item two +3. Item three + + + +1. Item one +1. Item two +1. Item three + + + + +1. Item one +2. Item two +3. Item three + * Sub-item + * Sub-item +4. Item four + + + + + This is code + So is this + + + + my_array.each do |item| + puts item + end + + + +John didn't even know what the `go_to()` function did! + + + +\`\`\`ruby +def foobar + puts "Hello world!" +end +\`\`\` + +<-- The above text doesn't require indenting, plus Github will use syntax +highlighting of the language you specify after the ``` --> + + + + +*** +--- +- - - +**************** + + + + +[Click me!](http://test.com/) + + + +[Click me!](http://test.com/ "Link to Test.com") + + + +[Go to music](/music/). + + + +[Click this link][link1] for more info about it! +[Also check out this link][foobar] if you want to. + +[link1]: http://test.com/ "Cool!" +[foobar]: http://foobar.biz/ "Alright!" + + + + + +[This][] is a link. + +[this]: http://thisisalink.com/ + + + + + + +![This is hover-text (alt text) for my image](http://imgur.com/myimage.jpg "An optional title") + + + +![This is the hover-text.][myimage] + +[myimage]: relative/urls/cool/image.jpg "if you need a title, it's here" + + + + + is equivalent to +[http://testwebsite.com/](http://testwebsite.com/) + + + + + + + +I want to type *this text surrounded by asterisks* but I don't want it to be +in italics, so I do this: \*this text surrounded by asterisks\*. + + + + +| Col1 | Col2 | Col3 | +| :----------- | :------: | ------------: | +| Left-aligned | Centered | Right-aligned | +| blah | blah | blah | + + + +Col 1 | Col2 | Col3 +:-- | :-: | --: +Ugh this is so ugly | make it | stop + + + +``` + +For more info, check out John Gruber's official post of syntax [here](http://daringfireball.net/projects/markdown/syntax) and Adam Pritchard's great cheatsheet [here](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). -- cgit v1.2.3 From 1e18c52f615c05343de77edf0ce364b9c3437764 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 13:00:39 +0800 Subject: Updated the file head --- zh-cn/markdown-cn.html.markdown | 3 +++ 1 file changed, 3 insertions(+) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 9a863bac..68f2e909 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -2,7 +2,10 @@ language: markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] +translators: + - ["Fangzhou Chen", "http://binarythink.net"] filename: markdown.md +lang: zh-cn --- Markdown was created by John Gruber in 2004. It's meant to be an easy to read and write syntax which converts easily to HTML (and now many other formats as well). -- cgit v1.2.3 From 62e5ab350acd1803dea8f52ffd5b437c04cf7f84 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 13:01:14 +0800 Subject: Update markdown-cn.html.markdown --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 68f2e909..1e463287 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -3,7 +3,7 @@ language: markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: - - ["Fangzhou Chen", "http://binarythink.net"] + - ["Fangzhou Chen"] filename: markdown.md lang: zh-cn --- -- cgit v1.2.3 From 821464185ac044a0812584ac794049947d25b736 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 13:24:22 +0800 Subject: 2nd para --- zh-cn/markdown-cn.html.markdown | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 1e463287..f27722ba 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -8,17 +8,16 @@ filename: markdown.md lang: zh-cn --- -Markdown was created by John Gruber in 2004. It's meant to be an easy to read and write syntax which converts easily to HTML (and now many other formats as well). +Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的语法结构,并可以便利地转换成HTML(以及其他很多)格式。 -Give me as much feedback as you want! / Feel free to fork and pull request! +欢迎您多多反馈以及分支和请求合并。 ``` - + - - - - -# This is an

-## This is an

-### This is an

-#### This is an

-##### This is an

-###### This is an
- - -This is an h1 + + + + +# 这是一个

+## 这是一个

+### 这是一个

+#### 这是一个

+##### 这是一个

+###### 这是一个
+ + +这是一个 h1 ============= -This is an h2 +这是一个 h2 ------------- - - + + -*This text is in italics.* -_And so is this text._ +*此文本为斜体。* +_此文本也是。_ -**This text is in bold.** -__And so is this text.__ +**此文本为粗体。** +__此文本也是__ -***This text is in both.*** -**_As is this!_** -*__And this!__* +***此文本是斜体加粗体。*** +**_或者这样。_** +*__这个也是!__* - + -~~This text is rendered with strikethrough.~~ +~~此文本为删除线效果。~~ - + -This is a paragraph. I'm typing in a paragraph isn't this fun? +这是第一段落. 这句话在同一个段落里,好玩么? -Now I'm in paragraph 2. -I'm still in paragraph 2 too! +现在我是第二段落。 +这句话也在第二段落! +这句话在第三段落! -I'm in paragraph three! + - +此段落结尾有两个空格(选中以显示)。 -I end with two spaces (highlight me to see them). +上文有一个
! -There's a
above me! + - +> 这是一个段落引用. 你可以 +> 手动断开你的句子,然后在每句句子前面添加 “>” 字符。或者让你的句子变得很长,以至于他们自动得断开。 +> 只要你的文字以“>” 字符开头,两种方式无异。 -> This is a block quote. You can either -> manually wrap your lines and put a `>` before every line or you can let your lines get really long and wrap on their own. -> It doesn't make a difference so long as they start with a `>`. +> 你也对文本进行 +>> 多层引用 +> 这多机智啊! -> You can also use more than one level ->> of indentation? -> How neat is that? + + - - +* 项目 +* 项目 +* 另一个项目 -* Item -* Item -* Another item +或者 -or ++ 项目 ++ 项目 ++ 另一个项目 -+ Item -+ Item -+ One more item +或者 -or +- 项目 +- 项目 +- 最后一个项目 -- Item -- Item -- One last item + - +1. 项目一 +2. 项目二 +3. 项目三 -1. Item one -2. Item two -3. Item three + - +1. 项目一 +1. 项目二 +1. 项目三 + -1. Item one -1. Item two -1. Item three - + - +1. 项目一 +2. 项目二 +3. 项目三 + * 子项目 + * 子项目 +4. 项目四 -1. Item one -2. Item two -3. Item three - * Sub-item - * Sub-item -4. Item four - - - + + This is code So is this - + my_array.each do |item| puts item end - + John didn't even know what the `go_to()` function did! -- cgit v1.2.3 From e98b62883cd0ef08d72a9da5384df7f5402cb180 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 16:55:29 +0800 Subject: Finally Done --- zh-cn/markdown-cn.html.markdown | 115 ++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 57 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 4f4b4c51..5de5f75b 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -19,10 +19,13 @@ Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的 并不会被Markdown解析器所影响。不过如果你在Markdown文件内创建了HTML元素, 你将无法在HTML元素的内容中使用Markdown语法。--> - + - + + # 这是一个

## 这是一个

### 这是一个

@@ -54,7 +57,7 @@ __此文本也是__ ~~此文本为删除线效果。~~ - + 这是第一段落. 这句话在同一个段落里,好玩么? @@ -70,7 +73,7 @@ __此文本也是__ 上文有一个
! - + > 这是一个段落引用. 你可以 > 手动断开你的句子,然后在每句句子前面添加 “>” 字符。或者让你的句子变得很长,以至于他们自动得断开。 @@ -105,7 +108,8 @@ __此文本也是__ 2. 项目二 3. 项目三 - + 1. 项目一 1. 项目二 @@ -122,7 +126,8 @@ __此文本也是__ 4. 项目四 - + This is code So is this @@ -135,105 +140,101 @@ __此文本也是__ -John didn't even know what the `go_to()` function did! +John 甚至不知道 `go_to()` 方程是干嘛的! - + -\`\`\`ruby +\`\`\`ruby def foobar puts "Hello world!" end -\`\`\` +\`\`\` -<-- The above text doesn't require indenting, plus Github will use syntax -highlighting of the language you specify after the ``` --> + - - + + *** --- - - - **************** - - + + -[Click me!](http://test.com/) +[点我点我!](http://test.com/) - + -[Click me!](http://test.com/ "Link to Test.com") +[点我点我!](http://test.com/ "连接到Test.com") - + -[Go to music](/music/). +[去 music](/music/). - + -[Click this link][link1] for more info about it! -[Also check out this link][foobar] if you want to. +[点此链接][link1]以获取更多信息! +[看一看这个链接][foobar] 如果你愿意的话. [link1]: http://test.com/ "Cool!" [foobar]: http://foobar.biz/ "Alright!" - + - + [This][] is a link. [this]: http://thisisalink.com/ - + - - + + -![This is hover-text (alt text) for my image](http://imgur.com/myimage.jpg "An optional title") +![这是我图像的悬停文本(alt text)](http://imgur.com/myimage.jpg "可选命名") - + -![This is the hover-text.][myimage] +![这是我的悬停文本.][myimage] -[myimage]: relative/urls/cool/image.jpg "if you need a title, it's here" +[myimage]: relative/urls/cool/image.jpg "在此输入标题" - - + + - is equivalent to -[http://testwebsite.com/](http://testwebsite.com/) + 与 +[http://testwebsite.com/](http://testwebsite.com/) 等同 - + - + -I want to type *this text surrounded by asterisks* but I don't want it to be -in italics, so I do this: \*this text surrounded by asterisks\*. +我希望 *将这段文字置于星号之间* 但是我不希望它被 +斜体化, 所以我就: \*这段置文字于星号之间\*。 - - + + -| Col1 | Col2 | Col3 | -| :----------- | :------: | ------------: | -| Left-aligned | Centered | Right-aligned | -| blah | blah | blah | +| 第一列 | 第二列 | 第三列 | +| :---------- | :------: | ---------: | +| 左对齐 | 居个中 | 右对齐 | +| 某某某 | 某某某 | 某某某 | - + -Col 1 | Col2 | Col3 +第一列 | 第二列 | 第三列 :-- | :-: | --: -Ugh this is so ugly | make it | stop +这太丑了 | 药不能 | 停 - + ``` -For more info, check out John Gruber's official post of syntax [here](http://daringfireball.net/projects/markdown/syntax) and Adam Pritchard's great cheatsheet [here](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). +更多信息, 请见John Gruber 关于语法的官方帖子[此处](http://daringfireball.net/projects/markdown/syntax)以及 Adam Pritchard 的摘要笔记 [此处](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). -- cgit v1.2.3 From fd010c57e08336d108d979ecad9a82ef30980ed3 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 17:01:22 +0800 Subject: Proofread and checked style --- zh-cn/markdown-cn.html.markdown | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 5de5f75b..f82ebcea 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -1,25 +1,25 @@ --- -language: markdown +language: Markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: - ["Fangzhou Chen"] -filename: markdown.md +filename: Markdown.md lang: zh-cn --- -Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的语法结构,并可以便利地转换成HTML(以及其他很多)格式。 +Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的语法结构,并可以便利地转换成 HTML(以及其他很多)格式。 欢迎您多多反馈以及分支和请求合并。 ``` - + - @@ -41,7 +41,7 @@ Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的 ------------- - + *此文本为斜体。* _此文本也是。_ @@ -53,7 +53,7 @@ __此文本也是__ **_或者这样。_** *__这个也是!__* - + ~~此文本为删除线效果。~~ @@ -66,7 +66,7 @@ __此文本也是__ 这句话在第三段落! - 此段落结尾有两个空格(选中以显示)。 @@ -108,7 +108,7 @@ __此文本也是__ 2. 项目二 3. 项目三 - 1. 项目一 @@ -126,7 +126,7 @@ __此文本也是__ 4. 项目四 - This is code @@ -150,7 +150,7 @@ def foobar end \`\`\` - + @@ -161,7 +161,7 @@ end **************** - [点我点我!](http://test.com/) @@ -220,10 +220,10 @@ end 斜体化, 所以我就: \*这段置文字于星号之间\*。 - + | 第一列 | 第二列 | 第三列 | -| :---------- | :------: | ---------: | +| :---------- | :------: | ----------: | | 左对齐 | 居个中 | 右对齐 | | 某某某 | 某某某 | 某某某 | @@ -237,4 +237,4 @@ end ``` -更多信息, 请见John Gruber 关于语法的官方帖子[此处](http://daringfireball.net/projects/markdown/syntax)以及 Adam Pritchard 的摘要笔记 [此处](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). +更多信息, 请见John Gruber 关于语法的官方帖子[此处](http://daringfireball.net/projects/Markdown/syntax)以及 Adam Pritchard 的摘要笔记 [此处](https://github.com/adam-p/Markdown-here/wiki/Markdown-Cheatsheet). -- cgit v1.2.3 From 3b55d56287ca64e3f8504a6de01d45a305aef90f Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 17:03:38 +0800 Subject: typo correction --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index f82ebcea..95aef8e2 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -41,7 +41,7 @@ Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的 ------------- - + *此文本为斜体。* _此文本也是。_ -- cgit v1.2.3 From ed8da6c3a70e93958d71e0d4ae79f1ae7f1ab114 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 17:06:11 +0800 Subject: Footnote corrected --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 95aef8e2..d0d84d31 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -237,4 +237,4 @@ end ``` -更多信息, 请见John Gruber 关于语法的官方帖子[此处](http://daringfireball.net/projects/Markdown/syntax)以及 Adam Pritchard 的摘要笔记 [此处](https://github.com/adam-p/Markdown-here/wiki/Markdown-Cheatsheet). +更多信息, 请于[此处](http://daringfireball.net/projects/Markdown/syntax)参见 John Gruber 关于语法的官方帖子,及于[此处](https://github.com/adam-p/Markdown-here/wiki/Markdown-Cheatsheet)。 参见 Adam Pritchard 的摘要笔记。 -- cgit v1.2.3 From 731026a038c7f9322ade73d3b4fee3c22cb84640 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Mon, 7 Jul 2014 17:13:48 +0800 Subject: Update markdown-cn.html.markdown --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index d0d84d31..96b0244c 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -237,4 +237,4 @@ end ``` -更多信息, 请于[此处](http://daringfireball.net/projects/Markdown/syntax)参见 John Gruber 关于语法的官方帖子,及于[此处](https://github.com/adam-p/Markdown-here/wiki/Markdown-Cheatsheet)。 参见 Adam Pritchard 的摘要笔记。 +更多信息, 请于[此处](http://daringfireball.net/projects/Markdown/syntax)参见 John Gruber 关于语法的官方帖子,及于[此处](https://github.com/adam-p/Markdown-here/wiki/Markdown-Cheatsheet) 参见 Adam Pritchard 的摘要笔记。 -- cgit v1.2.3 From d587d9b1c45d545ff9dc7eea99dcb8d649d598f3 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Sat, 26 Jul 2014 01:36:47 +0800 Subject: Changed filename --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 96b0244c..58ef2d6d 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -4,7 +4,7 @@ contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: - ["Fangzhou Chen"] -filename: Markdown.md +filename: Markdown-cn.md lang: zh-cn --- -- cgit v1.2.3 From 8f81fe39d7298233cc5638e48dc57a8f205a169e Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Mon, 28 Jul 2014 01:21:22 +0200 Subject: Update julia-cn.html.markdown Fix frontmatter --- zh-cn/julia-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/julia-cn.html.markdown b/zh-cn/julia-cn.html.markdown index b7239786..b91cd7a3 100644 --- a/zh-cn/julia-cn.html.markdown +++ b/zh-cn/julia-cn.html.markdown @@ -4,7 +4,7 @@ filename: learn-julia-zh.jl contributors: - ["Jichao Ouyang", "http://oyanglul.us"] translators: - - ["Jichao Ouyang"] + - ["Jichao Ouyang", "http://oyanglul.us"] lang: zh-cn --- -- cgit v1.2.3 From c87923fd5ce323cd891407e9abf00db5648c7172 Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 29 Jul 2014 00:23:32 +0200 Subject: Also we don't support julia highlighting yet. --- zh-cn/julia-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/julia-cn.html.markdown b/zh-cn/julia-cn.html.markdown index b91cd7a3..7afc9043 100644 --- a/zh-cn/julia-cn.html.markdown +++ b/zh-cn/julia-cn.html.markdown @@ -8,7 +8,7 @@ translators: lang: zh-cn --- -```julia +```ruby # 单行注释只需要一个井号 #= 多行注释 只需要以 '#=' 开始 '=#' 结束 -- cgit v1.2.3 From 615ee2794184949591f49ff36b3e58c5e166ed39 Mon Sep 17 00:00:00 2001 From: Kevin Fangzhou Chen Date: Tue, 29 Jul 2014 12:08:24 +0800 Subject: updated the filename into learnmarkdown-cn.md --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 58ef2d6d..975ebcb5 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -4,7 +4,7 @@ contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: - ["Fangzhou Chen"] -filename: Markdown-cn.md +filename: learnmarkdown-cn.md lang: zh-cn --- -- cgit v1.2.3 From 7cf0bcb8283a0be92f77b40568355f02ac1811af Mon Sep 17 00:00:00 2001 From: m90 Date: Sat, 9 Aug 2014 21:41:12 +0200 Subject: [javascript/*] typeof is an operand and not a function/method - fix usage / remove parens --- zh-cn/javascript-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 86ad1d07..7dee9cc4 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -363,8 +363,8 @@ var myNumberObj = new Number(12) myNumber == myNumberObj // = true // 但是它们并非严格等价 -typeof(myNumber) // = 'number' -typeof(myNumberObj) // = 'object' +typeof myNumber // = 'number' +typeof myNumberObj // = 'object' myNumber === myNumberObj // = false if (0){ // 这段代码不会执行,因为0代表假 -- cgit v1.2.3 From 4b5cbc91eb40d678c12d5bbb1d9fdbda9d22923d Mon Sep 17 00:00:00 2001 From: James Baxter Date: Tue, 19 Aug 2014 12:56:27 +0100 Subject: Fixed the statement that rune is an alias for uint32 in the translations --- zh-cn/go-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown index 4a87dc21..9f6a8c15 100644 --- a/zh-cn/go-cn.html.markdown +++ b/zh-cn/go-cn.html.markdown @@ -68,7 +68,7 @@ func learnTypes() { can include line breaks.` // 同样是String类型 // 非ascii字符。Go使用UTF-8编码。 - g := 'Σ' // rune类型,uint32的别名,使用UTF-8编码 + g := 'Σ' // rune类型,int32的别名,使用UTF-8编码 f := 3.14195 // float64类型,IEEE-754 64位浮点数 c := 3 + 4i // complex128类型,内部使用两个float64表示 -- cgit v1.2.3 From 64c1ee391f4e03f363fd829ce658fc881bcffb6f Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 5 Sep 2014 20:48:42 -0500 Subject: Add lua-cn filename to close https://github.com/adambard/learnxinyminutes-docs/pull/610/files --- zh-cn/lua-cn.html.markdown | 1 + 1 file changed, 1 insertion(+) (limited to 'zh-cn') diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown index 95a94c76..3ba098ec 100644 --- a/zh-cn/lua-cn.html.markdown +++ b/zh-cn/lua-cn.html.markdown @@ -9,6 +9,7 @@ contributors: - ["Amr Tamimi", "https://amrtamimi.com"] translators: - ["Jakukyo Friel", "http://weakish.github.io"] +filename: lua-cn.lua --- ```lua -- cgit v1.2.3 From b35ccf01af17b52447c98d7101ee932e7f089c52 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 5 Sep 2014 20:59:37 -0500 Subject: Add FZSS's GitHub profile link to close https://github.com/adambard/learnxinyminutes-docs/pull/666 --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 975ebcb5..f1166a04 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -3,7 +3,7 @@ language: Markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: - - ["Fangzhou Chen"] + - ["Fangzhou Chen","https://github.com/FZSS"] filename: learnmarkdown-cn.md lang: zh-cn --- -- cgit v1.2.3 From eab554a7a7f2869ff7dac9f54acce9a7ed55cfa4 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 8 Sep 2014 13:08:28 +0200 Subject: Review docs for added rouge lexers and update those with new highlighters --- zh-cn/common-lisp-cn.html.markdown | 2 +- zh-cn/markdown-cn.html.markdown | 2 +- zh-cn/r-cn.html.markdown | 2 +- zh-cn/scala-cn.html.markdown | 2 +- zh-cn/swift-cn.html.markdown | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/common-lisp-cn.html.markdown b/zh-cn/common-lisp-cn.html.markdown index c4dc3274..b82829a9 100644 --- a/zh-cn/common-lisp-cn.html.markdown +++ b/zh-cn/common-lisp-cn.html.markdown @@ -17,7 +17,7 @@ ANSI Common Lisp 是一个广泛通用于各个工业领域的、支持多种范 另外还有一本热门的近期出版的 [Land of Lisp](http://landoflisp.com/). -```scheme +```common-lisp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 0. 语法 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 975ebcb5..caecdc58 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -13,7 +13,7 @@ Markdown 由 John Gruber 于 2004年创立. 它旨在成为一门容易读写的 欢迎您多多反馈以及分支和请求合并。 -``` +```markdown left + right +add1 = add 1 +add1 2 # => 3 + +# 函式里有一个隐式的 `it` 变数,意谓着你不用宣告它。 +identity = -> it +identity 1 # => 1 + +# 运算子在 LiveScript 里不是一個函数,但你可以简单地将它们转换成函数! +# Enter the operator sectioning: +divide-by-2 = (/ 2) +[2, 4, 8, 16].map(divide-by-2) .reduce (+) + + +# LiveScript 里不只有应用函数,如同其它良好的函数式语言,你可以合并函数获得更多发挥: +double-minus-one = (- 1) . (* 2) + +# 除了普通的数学公式合并 `f . g` 之外,还有 `>>` 和 `<<` 运算子定义函数的合并顺序。 +double-minus-one = (* 2) >> (- 1) +double-minus-one = (- 1) << (* 2) + + +# 说到合并函数的参数, LiveScript 使用 `|>` 和 `<|` 运算子将参数传入: +map = (f, xs) --> xs.map f +[1 2 3] |> map (* 2) # => [2 4 6] + +# 你也可以选择填入值的位置,只需要使用底线 _ 标记: +reduce = (f, xs, initial) --> xs.reduce f, initial +[1 2 3] |> reduce (+), _, 0 # => 6 + + +# 你也能使 _ 让任何函数变成偏函数应用: +div = (left, right) -> left / right +div-by-2 = div _, 2 +div-by-2 4 # => 2 + + +# 最后,也很重要的,LiveScript 拥有後呼叫特性, 它可以是基於回调的代码 +# (你可以试试其它函数式特性的解法,比如 Promises): +readFile = (name, f) -> f name +a <- readFile 'foo' +b <- readFile 'bar' +console.log a + b + +# 等同於: +readFile 'foo', (a) -> readFile 'bar', (b) -> console.log a + b + + +######################################################################## +## 4. 模式、判断和流程控制 +######################################################################## + +# 流程控制可以使用 `if...else` 表达式: +x = if n > 0 then \positive else \negative + +# 除了 `then` 你也可以使用 `=>` +x = if n > 0 => \positive + else \negative + +# 过於复杂的流程可以用 `switch` 表达式代替: +y = {} +x = switch + | (typeof y) is \number => \number + | (typeof y) is \string => \string + | 'length' of y => \array + | otherwise => \object # `otherwise` 和 `_` 是等价的。 + +# 函数主体、宣告式和赋值式可以表式成 `switch`,这可以省去一些代码: +take = (n, [x, ...xs]) --> + | n == 0 => [] + | _ => [x] ++ take (n - 1), xs + + +######################################################################## +## 5. 推导式 +######################################################################## + +# 在 JavaScript 的标准函式库里有一些辅助函数能帮助处理列表及物件 +#(LiveScript 则带有一个 prelude.ls ,作为标准函式库的补充 ), +# 推导式能让你使用优雅的语法且快速地处理这些事: +oneToTwenty = [1 to 20] +evens = [x for x in oneToTwenty when x % 2 == 0] + +# 在推导式里 `when` 和 `unless` 可以当成过滤器使用。 + +# 物件推导式在使用上也是同样的方式,差别在于你使用的是物件而不是阵列: +copy = { [k, v] for k, v of source } + + +######################################################################## +## 6. OOP +######################################################################## + +# 虽然 LiveScript 是一门函数式语言,但有具自一些命令式及面向物件语言的特性。 +# 像是 class 语法和一些借镜於 CoffeeScript 的类别继承语法糖: +class Animal + (@name, kind) -> + @kind = kind + action: (what) -> "*#{@name} (a #{@kind}) #{what}*" + +class Cat extends Animal + (@name) -> super @name, 'cat' + purr: -> @action 'purrs' + +kitten = new Cat 'Mei' +kitten.purr! # => "*Mei (a cat) purrs*" + +# 除了类别的单一继承模式之外,还提供了像混入( Mixins )这种特性。 +# Mixins 在语言里被当成普通物件: +Huggable = + hug: -> @action 'is hugged' + +class SnugglyCat extends Cat implements Huggable + +kitten = new SnugglyCat 'Purr' +kitten.hug! # => "*Mei (a cat) is hugged*" +``` + +## 延伸阅读 + +LiveScript 还有许多强大之处,但这些应该足够启发你写些小型函数式程式了。 +[LiveScript](http://livescript.net/)有更多关于 LiveScript 的资讯 +和线上编译器等着你来试! + +你也可以参考 +[prelude.ls](http://gkz.github.io/prelude-ls/),和一些 `#livescript` +的网路聊天室频道。 -- cgit v1.2.3 From 6de34992770654cdb2c7f8d61bd27131c3cb88db Mon Sep 17 00:00:00 2001 From: sdlyu Date: Fri, 26 Sep 2014 15:13:10 +0800 Subject: Fix typo --- zh-cn/livescript-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/livescript-cn.html.markdown b/zh-cn/livescript-cn.html.markdown index f6643447..c04805c9 100644 --- a/zh-cn/livescript-cn.html.markdown +++ b/zh-cn/livescript-cn.html.markdown @@ -22,7 +22,7 @@ LiveScript 目前已释出稳定版本,开发中的新版本将会加入更多 # 与 CoffeeScript 一样,LiveScript 使用 # 单行注解。 /* -*多行注解与 C 相同。使用注解可以避免被当成 JavaScript 输出。 + 多行注解与 C 相同。使用注解可以避免被当成 JavaScript 输出。 */ ``` ```coffeescript -- cgit v1.2.3 From 0c77c29c88f850d81a884d90a036c50931157782 Mon Sep 17 00:00:00 2001 From: sdlyu Date: Fri, 26 Sep 2014 16:16:19 +0800 Subject: Add translators information. --- zh-cn/livescript-cn.html.markdown | 3 +++ 1 file changed, 3 insertions(+) (limited to 'zh-cn') diff --git a/zh-cn/livescript-cn.html.markdown b/zh-cn/livescript-cn.html.markdown index c04805c9..5a808807 100644 --- a/zh-cn/livescript-cn.html.markdown +++ b/zh-cn/livescript-cn.html.markdown @@ -3,6 +3,9 @@ language: LiveScript filename: learnLivescript.ls contributors: - ["Christina Whyte", "http://github.com/kurisuwhyte/"] +translators: + - ["ShengDa Lyu", "http://github.com/SDLyu/"] +lang: zh-cn --- LiveScript 是一种具有函数式特性且编译成 JavaScript 的语言,能对应 JavaScript 的基本语法。 -- cgit v1.2.3 From 221d72bcb06f1677b61e28dde430ba651fd896df Mon Sep 17 00:00:00 2001 From: sdlyu Date: Mon, 29 Sep 2014 10:30:40 +0800 Subject: Correct typo and rewrite the meaning of := --- zh-cn/livescript-cn.html.markdown | 102 +++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 51 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/livescript-cn.html.markdown b/zh-cn/livescript-cn.html.markdown index 5a808807..fea00bc1 100644 --- a/zh-cn/livescript-cn.html.markdown +++ b/zh-cn/livescript-cn.html.markdown @@ -9,7 +9,7 @@ lang: zh-cn --- LiveScript 是一种具有函数式特性且编译成 JavaScript 的语言,能对应 JavaScript 的基本语法。 -还有些额外的特性如:柯里化,函式组合,模式匹配,还有借镜于 Haskell,F# 和 Scala 的许多特点。 +还有些额外的特性如:柯里化,组合函数,模式匹配,还有借镜于 Haskell,F# 和 Scala 的许多特点。 LiveScript 诞生于 [Coco][],而 Coco 诞生于 [CoffeeScript][]。 LiveScript 目前已释出稳定版本,开发中的新版本将会加入更多特性。 @@ -17,7 +17,7 @@ LiveScript 目前已释出稳定版本,开发中的新版本将会加入更多 [Coco]: http://satyr.github.io/coco/ [CoffeeScript]: http://coffeescript.org/ -非常期待您的反馈,你可以透过 +非常期待您的反馈,你可以通过 [@kurisuwhyte](https://twitter.com/kurisuwhyte) 与我连系 :) @@ -44,11 +44,11 @@ void # 与 `undefined` 等价但更安全(不会被覆写) null -# 最基本的值类型数据是罗辑类型: +# 最基本的值类型数据是罗辑类型: true false -# 罗辑类型的一些别名,等价于前者: +# 罗辑类型的一些别名,等价于前者: on; off yes; no @@ -58,55 +58,55 @@ yes; no 0.4 # 开头的 0 是必要的 -# 可以使用底线及单位后缀提高可读性,编译器自动会略过底线及单位后缀。 +# 可以使用底线及单位后缀提高可读性,编译器会自动略过底线及单位后缀。 12_344km -# 字串与 JS 一样,是一种不可变的字元序列: -"Christina" # 单引号也可以! +# 字串与 JS 一样,是一种不可变的字元序列: +"Christina" # 单引号也可以! """Multi-line strings are okay too.""" -# 在前面加上 \ 符号也可以表示字串: +# 在前面加上 \ 符号也可以表示字串: \keyword # => 'keyword' -# 阵列是值的有序集合。 +# 数组是值的有序集合。 fruits = * \apple * \orange * \pear -# 可以用 [] 简洁地表示阵列: +# 可以用 [] 简洁地表示数组: fruits = [ \apple, \orange, \pear ] -# 你可以更方便地建立字串阵列,并使用空白区隔元素。 +# 你可以更方便地建立字串数组,并使用空白区隔元素。 fruits = <[ apple orange pear ]> -# 以 0 为起始值的数组下标获取元素: +# 以 0 为起始值的数组下标获取元素: fruits[0] # => "apple" -# 物件是无序键值对集合(更多给节将在下面章节讨论) 。 +# 对象是无序键值对集合(更多给节将在下面章节讨论)。 person = name: "Christina" likes: * "kittens" * "and other cute stuff" -# 你也可以用更简洁的方式表示物件: +# 你也可以用更简洁的方式表示对象: person = {name: "Christina", likes: ["kittens", "and other cute stuff"]} -# 可以透过键值获取值: +# 可以通过键值获取值: person.name # => "Christina" person["name"] # => "Christina" -# 正则表达式的使用跟 JavaScript 一样: +# 正则表达式的使用跟 JavaScript 一样: trailing-space = /\s$/ # dashed-words 变成 dashedWords # 你也可以用多行描述表达式!(注解和空白会被忽略) @@ -121,7 +121,7 @@ funRE = // ## 2. 基本运算 ######################################################################## -# 数值运算子与 JavaScript 一样: +# 数值操作符与 JavaScript 一样: 1 + 2 # => 3 2 - 1 # => 1 2 * 3 # => 6 @@ -129,9 +129,9 @@ funRE = // 3 % 2 # => 1 -# 比较运算子大部份也一样,除了 `==` 等价于 JS 中的 `===`, +# 比较操作符大部份也一样,除了 `==` 等价于 JS 中的 `===`, # JS 中的 `==` 在 LiveScript 里等价于 `~=`, -# `===` 能进行物件、阵列和严格比较。 +# `===` 能进行对象、数组和严格比较。 2 == 2 # => true 2 == "2" # => false 2 ~= "2" # => true @@ -143,15 +143,15 @@ funRE = // +0 == -0 # => true +0 === -0 # => false -# 其它关系运算子包括 <、<=、> 和 >= +# 其它关系操作符包括 <、<=、> 和 >= -# 罗辑值可以透过 `or`、`and` 和 `not` 结合: +# 罗辑值可以通过 `or`、`and` 和 `not` 结合: true and false # => false false or true # => true not false # => true -# 集合也有一些便利的运算子 +# 集合也有一些便利的操作符 [1, 2] ++ [3, 4] # => [1, 2, 3, 4] 'a' in <[ a b c ]> # => true 'name' of { name: 'Chris' } # => true @@ -165,25 +165,25 @@ not false # => true add = (left, right) -> left + right add 1, 2 # => 3 -# 加上 ! 防止函数执行后的回传值 +# 加上 ! 防止函数执行后的返回值 two = -> 2 two! # LiveScript 与 JavaScript 一样使用函式作用域,且一样拥有闭包的特性。 -# 与 JavaScript 不同的地方在于,`=` 变数赋值时,左边的运算元永远不用变数宣告。 +# 与 JavaScript 不同的地方在于,`=` 变量赋值时,左边的对象永远不用变量宣告。 -# `:=` 运算子在作用域里允许*重用*变数名并创建新的变数作用域。 +# `:=` 操作符允许*重新賦值*父作用域里的变量。 # 你可以解构函数的参数,从不定长度的参数结构里获取感兴趣的值。 tail = ([head, ...rest]) -> rest tail [1, 2, 3] # => [2, 3] -# 你也可以使用一元或二元运算子转换参数。当然也可以预设传入的参数值。 +# 你也可以使用一元或二元操作符转换参数。当然也可以预设传入的参数值。 foo = (a = 1, b = 2) -> a + b foo! # => 3 -# 你可以以复制的方式传入参数来避免副作用,例如: +# 你可以以拷贝的方式传入参数来避免副作用,例如: copy = (^^target, source) -> for k,v of source => target[k] = v target @@ -192,52 +192,52 @@ copy a, { b: 2 } # => { a: 1, b: 2 } a # => { a: 1 } -# 使用长箭号取代短箭号来柯里化一个函数: +# 使用长箭号取代短箭号来柯里化一个函数: add = (left, right) --> left + right add1 = add 1 add1 2 # => 3 -# 函式里有一个隐式的 `it` 变数,意谓着你不用宣告它。 +# 函式里有一个隐式的 `it` 变量,意谓着你不用宣告它。 identity = -> it identity 1 # => 1 -# 运算子在 LiveScript 里不是一個函数,但你可以简单地将它们转换成函数! -# Enter the operator sectioning: +# 操作符在 LiveScript 里不是一個函数,但你可以简单地将它们转换成函数! +# Enter the operator sectioning: divide-by-2 = (/ 2) [2, 4, 8, 16].map(divide-by-2) .reduce (+) -# LiveScript 里不只有应用函数,如同其它良好的函数式语言,你可以合并函数获得更多发挥: +# LiveScript 里不只有应用函数,如同其它良好的函数式语言,你可以合并函数获得更多发挥: double-minus-one = (- 1) . (* 2) -# 除了普通的数学公式合并 `f . g` 之外,还有 `>>` 和 `<<` 运算子定义函数的合并顺序。 +# 除了普通的数学公式合并 `f . g` 之外,还有 `>>` 和 `<<` 操作符定义函数的合并顺序。 double-minus-one = (* 2) >> (- 1) double-minus-one = (- 1) << (* 2) -# 说到合并函数的参数, LiveScript 使用 `|>` 和 `<|` 运算子将参数传入: +# 说到合并函数的参数, LiveScript 使用 `|>` 和 `<|` 操作符将参数传入: map = (f, xs) --> xs.map f [1 2 3] |> map (* 2) # => [2 4 6] -# 你也可以选择填入值的位置,只需要使用底线 _ 标记: +# 你也可以选择填入值的位置,只需要使用底线 _ 标记: reduce = (f, xs, initial) --> xs.reduce f, initial [1 2 3] |> reduce (+), _, 0 # => 6 -# 你也能使 _ 让任何函数变成偏函数应用: +# 你也能使 _ 让任何函数变成偏函数应用: div = (left, right) -> left / right div-by-2 = div _, 2 div-by-2 4 # => 2 -# 最后,也很重要的,LiveScript 拥有後呼叫特性, 它可以是基於回调的代码 -# (你可以试试其它函数式特性的解法,比如 Promises): +# 最后,也很重要的,LiveScript 拥有後呼叫特性, 可以是基於回调的代码 +# (你可以试试其它函数式特性的解法,比如 Promises): readFile = (name, f) -> f name a <- readFile 'foo' b <- readFile 'bar' console.log a + b -# 等同於: +# 等同於: readFile 'foo', (a) -> readFile 'bar', (b) -> console.log a + b @@ -245,14 +245,14 @@ readFile 'foo', (a) -> readFile 'bar', (b) -> console.log a + b ## 4. 模式、判断和流程控制 ######################################################################## -# 流程控制可以使用 `if...else` 表达式: +# 流程控制可以使用 `if...else` 表达式: x = if n > 0 then \positive else \negative # 除了 `then` 你也可以使用 `=>` x = if n > 0 => \positive else \negative -# 过於复杂的流程可以用 `switch` 表达式代替: +# 过於复杂的流程可以用 `switch` 表达式代替: y = {} x = switch | (typeof y) is \number => \number @@ -260,7 +260,7 @@ x = switch | 'length' of y => \array | otherwise => \object # `otherwise` 和 `_` 是等价的。 -# 函数主体、宣告式和赋值式可以表式成 `switch`,这可以省去一些代码: +# 函数主体、宣告式和赋值式可以表式成 `switch`,这可以省去一些代码: take = (n, [x, ...xs]) --> | n == 0 => [] | _ => [x] ++ take (n - 1), xs @@ -270,15 +270,15 @@ take = (n, [x, ...xs]) --> ## 5. 推导式 ######################################################################## -# 在 JavaScript 的标准函式库里有一些辅助函数能帮助处理列表及物件 +# 在 JavaScript 的标准函式库里有一些辅助函数能帮助处理列表及对象 #(LiveScript 则带有一个 prelude.ls ,作为标准函式库的补充 ), -# 推导式能让你使用优雅的语法且快速地处理这些事: +# 推导式能让你使用优雅的语法且快速地处理这些事: oneToTwenty = [1 to 20] evens = [x for x in oneToTwenty when x % 2 == 0] # 在推导式里 `when` 和 `unless` 可以当成过滤器使用。 -# 物件推导式在使用上也是同样的方式,差别在于你使用的是物件而不是阵列: +# 对象推导式在使用上也是同样的方式,差别在于你使用的是对象而不是数组: copy = { [k, v] for k, v of source } @@ -286,8 +286,8 @@ copy = { [k, v] for k, v of source } ## 6. OOP ######################################################################## -# 虽然 LiveScript 是一门函数式语言,但有具自一些命令式及面向物件语言的特性。 -# 像是 class 语法和一些借镜於 CoffeeScript 的类别继承语法糖: +# 虽然 LiveScript 是一门函数式语言,但具有一些命令式及面向对象的特性。 +# 像是 class 语法和一些借镜於 CoffeeScript 的类别继承语法糖: class Animal (@name, kind) -> @kind = kind @@ -300,8 +300,8 @@ class Cat extends Animal kitten = new Cat 'Mei' kitten.purr! # => "*Mei (a cat) purrs*" -# 除了类别的单一继承模式之外,还提供了像混入( Mixins )这种特性。 -# Mixins 在语言里被当成普通物件: +# 除了类别的单一继承模式之外,还提供了像混入 (Mixins) 这种特性。 +# Mixins 在语言里被当成普通对象: Huggable = hug: -> @action 'is hugged' @@ -315,8 +315,8 @@ kitten.hug! # => "*Mei (a cat) is hugged*" LiveScript 还有许多强大之处,但这些应该足够启发你写些小型函数式程式了。 [LiveScript](http://livescript.net/)有更多关于 LiveScript 的资讯 -和线上编译器等着你来试! +和线上编译器等着你来试! 你也可以参考 [prelude.ls](http://gkz.github.io/prelude-ls/),和一些 `#livescript` -的网路聊天室频道。 +的网络聊天室频道。 -- cgit v1.2.3 From ef6544a8868d3b19a115804b2db3962d91ad7979 Mon Sep 17 00:00:00 2001 From: Geoffrey Liu Date: Sun, 12 Oct 2014 14:24:42 -0700 Subject: Capitalize language names for translations. #137 --- zh-cn/haskell-cn.html.markdown | 2 +- zh-cn/julia-cn.html.markdown | 2 +- zh-cn/lua-cn.html.markdown | 2 +- zh-cn/php-cn.html.markdown | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index 8d51f144..cb7ccdee 100644 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: haskell +language: Haskell filename: learn-haskell-zh.hs contributors: - ["Adit Bhargava", "http://adit.io"] diff --git a/zh-cn/julia-cn.html.markdown b/zh-cn/julia-cn.html.markdown index 7afc9043..1f91d52c 100644 --- a/zh-cn/julia-cn.html.markdown +++ b/zh-cn/julia-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: julia +language: Julia filename: learn-julia-zh.jl contributors: - ["Jichao Ouyang", "http://oyanglul.us"] diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown index 3ba098ec..53a603a2 100644 --- a/zh-cn/lua-cn.html.markdown +++ b/zh-cn/lua-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: lua +language: Lua lang: zh-cn contributors: - ["Tyler Neylon", "http://tylerneylon.com/"] diff --git a/zh-cn/php-cn.html.markdown b/zh-cn/php-cn.html.markdown index 24939681..2def7f1c 100644 --- a/zh-cn/php-cn.html.markdown +++ b/zh-cn/php-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: php +language: PHP contributors: - ["Malcolm Fell", "http://emarref.net/"] - ["Trismegiste", "https://github.com/Trismegiste"] -- cgit v1.2.3 From 6119f4b3072200007990d4b0000fa46de5106951 Mon Sep 17 00:00:00 2001 From: zang Date: Tue, 14 Oct 2014 16:13:22 +0800 Subject: octal is eight in Chinese --- zh-cn/c-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c-cn.html.markdown b/zh-cn/c-cn.html.markdown index 223f6e35..1e10416e 100644 --- a/zh-cn/c-cn.html.markdown +++ b/zh-cn/c-cn.html.markdown @@ -566,7 +566,7 @@ typedef void (*my_fnp_type)(char *); '\'' // 单引号 '\"' // 双引号 '\xhh' // 十六进制数字. 例子: '\xb' = vertical tab -'\ooo' // 十进制数字. 例子: '\013' = vertical tab +'\ooo' // 八进制数字. 例子: '\013' = vertical tab // 打印格式: "%d" // 整数 @@ -579,7 +579,7 @@ typedef void (*my_fnp_type)(char *); "%c" // 字母 "%p" // 指针 "%x" // 十六进制 -"%o" // 十进制 +"%o" // 八进制 "%%" // 打印 % /////////////////////////////////////// -- cgit v1.2.3 From 2ae89e20bc4c61052f122e572e42d48830d4d075 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 24 Oct 2014 00:48:59 -0400 Subject: Add Python3 simplified Chinese version. --- zh-cn/python3-cn.html.markdown | 648 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 648 insertions(+) create mode 100644 zh-cn/python3-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown new file mode 100644 index 00000000..dc09de4f --- /dev/null +++ b/zh-cn/python3-cn.html.markdown @@ -0,0 +1,648 @@ +--- +language: python3 +contributors: + - ["Louie Dinh", "http://pythonpracticeprojects.com"] + - ["Steven Basart", "http://github.com/xksteven"] + - ["Andre Polykanine", "https://github.com/Oire"] +translators: + - ["Geoff Liu", "http://geoffliu.me"] +filename: learnpython3.py +--- + +Python was created by Guido Van Rossum in the early 90's. It is now one of the most popular +languages in existence. I fell in love with Python for its syntactic clarity. It's basically +executable pseudocode. + +Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) or louiedinh [at] [google's email service] + +Note: This article applies to Python 3 specifically. Check out the other tutorial if you want to learn the old Python 2.7 + +```python + +# 用井字符开头的是单行注释 + +""" 多行字符串用三个引号 + 包裹,也常被用来做多 + 行注释 +""" + +#################################################### +## 1. 原始数据类型和运算符 +#################################################### + +# 整数 +3 # => 3 + +# 算术没有什么出乎意料的 +1 + 1 # => 2 +8 - 1 # => 7 +10 * 2 # => 20 + +# 但是除法例外,会自动转换成浮点数 +35 / 5 # => 7.0 +5 / 3 # => 1.6666666666666667 + +# Result of integer division truncated down both for positive and negative. +5 // 3 # => 1 +5.0 // 3.0 # => 1.0 # works on floats too +-5 // 3 # => -2 +-5.0 // 3.0 # => -2.0 + +# 浮点数的运算结果也是浮点数 +3 * 2.0 # => 6.0 + +# Modulo operation +7 % 3 # => 1 + +# x的y次方 +2**4 # => 16 + +# 用括号决定优先级 +(1 + 3) * 2 # => 8 + +# 布尔值 +True +False + +# 用not取非 +not True # => False +not False # => True + +# 逻辑运算符,注意and和or都是小写 +True and False #=> False +False or True #=> True + +# 整数也可以是布尔值 +0 and 2 #=> 0 +-5 or 0 #=> -5 +0 == False #=> True +2 == True #=> False +1 == True #=> True + +# 用==判断相等 +1 == 1 # => True +2 == 1 # => False + +# 用!=判断不等 +1 != 1 # => False +2 != 1 # => True + +# 比较大小 +1 < 10 # => True +1 > 10 # => False +2 <= 2 # => True +2 >= 2 # => True + +# 大小比较可以连起来! +1 < 2 < 3 # => True +2 < 3 < 2 # => False + +# 字符串用单引双引都可以 +"这是个字符串" +'这也是个字符串' + +# 用加好连接字符串 +"Hello " + "world!" # => "Hello world!" + +# A string can be treated like a list of characters +"This is a string"[0] # => 'T' + +# .format can be used to format strings, like this: +"{} can be {}".format("strings", "interpolated") + +# You can repeat the formatting arguments to save some typing. +"{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") +#=> "Jack be nimble, Jack be quick, Jack jump over the candle stick" + +# You can use keywords if you don't want to count. +"{name} wants to eat {food}".format(name="Bob", food="lasagna") #=> "Bob wants to eat lasagna" + +# If your Python 3 code also needs to run on Python 2.5 and below, you can also +# still use the old style of formatting: +"%s can be %s the %s way" % ("strings", "interpolated", "old") + + +# None is an object +None # => None + +# Don't use the equality "==" symbol to compare objects to None +# Use "is" instead. This checks for equality of object identity. +"etc" is None # => False +None is None # => True + +# None, 0, and empty strings/lists/dicts all evaluate to False. +# All other values are True +bool(0) # => False +bool("") # => False +bool([]) #=> False +bool({}) #=> False + + +#################################################### +## 2. Variables and Collections +#################################################### + +# Python has a print function +print("I'm Python. Nice to meet you!") + +# No need to declare variables before assigning to them. +# Convention is to use lower_case_with_underscores +some_var = 5 +some_var # => 5 + +# Accessing a previously unassigned variable is an exception. +# See Control Flow to learn more about exception handling. +some_unknown_var # Raises a NameError + +# Lists store sequences +li = [] +# You can start with a prefilled list +other_li = [4, 5, 6] + +# Add stuff to the end of a list with append +li.append(1) # li is now [1] +li.append(2) # li is now [1, 2] +li.append(4) # li is now [1, 2, 4] +li.append(3) # li is now [1, 2, 4, 3] +# Remove from the end with pop +li.pop() # => 3 and li is now [1, 2, 4] +# Let's put it back +li.append(3) # li is now [1, 2, 4, 3] again. + +# Access a list like you would any array +li[0] # => 1 +# Look at the last element +li[-1] # => 3 + +# Looking out of bounds is an IndexError +li[4] # Raises an IndexError + +# You can look at ranges with slice syntax. +# (It's a closed/open range for you mathy types.) +li[1:3] # => [2, 4] +# Omit the beginning +li[2:] # => [4, 3] +# Omit the end +li[:3] # => [1, 2, 4] +# Select every second entry +li[::2] # =>[1, 4] +# Revert the list +li[::-1] # => [3, 4, 2, 1] +# Use any combination of these to make advanced slices +# li[start:end:step] + +# Remove arbitrary elements from a list with "del" +del li[2] # li is now [1, 2, 3] + +# You can add lists +# Note: values for li and for other_li are not modified. +li + other_li # => [1, 2, 3, 4, 5, 6] + +# Concatenate lists with "extend()" +li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] + +# Check for existence in a list with "in" +1 in li # => True + +# Examine the length with "len()" +len(li) # => 6 + + +# Tuples are like lists but are immutable. +tup = (1, 2, 3) +tup[0] # => 1 +tup[0] = 3 # Raises a TypeError + +# You can do all those list thingies on tuples too +len(tup) # => 3 +tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) +tup[:2] # => (1, 2) +2 in tup # => True + +# You can unpack tuples (or lists) into variables +a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 +# Tuples are created by default if you leave out the parentheses +d, e, f = 4, 5, 6 +# Now look how easy it is to swap two values +e, d = d, e # d is now 5 and e is now 4 + + +# Dictionaries store mappings +empty_dict = {} +# Here is a prefilled dictionary +filled_dict = {"one": 1, "two": 2, "three": 3} + +# Look up values with [] +filled_dict["one"] # => 1 + +# Get all keys as a list with "keys()". +# We need to wrap the call in list() because we are getting back an iterable. We'll talk about those later. +# Note - Dictionary key ordering is not guaranteed. +# Your results might not match this exactly. +list(filled_dict.keys()) # => ["three", "two", "one"] + + +# Get all values as a list with "values()". Once again we need to wrap it in list() to get it out of the iterable. +# Note - Same as above regarding key ordering. +list(filled_dict.values()) # => [3, 2, 1] + + +# Check for existence of keys in a dictionary with "in" +"one" in filled_dict # => True +1 in filled_dict # => False + +# Looking up a non-existing key is a KeyError +filled_dict["four"] # KeyError + +# Use "get()" method to avoid the KeyError +filled_dict.get("one") # => 1 +filled_dict.get("four") # => None +# The get method supports a default argument when the value is missing +filled_dict.get("one", 4) # => 1 +filled_dict.get("four", 4) # => 4 + +# "setdefault()" inserts into a dictionary only if the given key isn't present +filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 +filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 + +# Adding to a dictionary +filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} +#filled_dict["four"] = 4 #another way to add to dict + +# Remove keys from a dictionary with del +del filled_dict["one"] # Removes the key "one" from filled dict + + +# Sets store ... well sets +empty_set = set() +# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry. +some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} + +#Can set new variables to a set +filled_set = some_set + +# Add one more item to the set +filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} + +# Do set intersection with & +other_set = {3, 4, 5, 6} +filled_set & other_set # => {3, 4, 5} + +# Do set union with | +filled_set | other_set # => {1, 2, 3, 4, 5, 6} + +# Do set difference with - +{1, 2, 3, 4} - {2, 3, 5} # => {1, 4} + +# Check for existence in a set with in +2 in filled_set # => True +10 in filled_set # => False + + +#################################################### +## 3. Control Flow and Iterables +#################################################### + +# Let's just make a variable +some_var = 5 + +# Here is an if statement. Indentation is significant in python! +# prints "some_var is smaller than 10" +if some_var > 10: + print("some_var is totally bigger than 10.") +elif some_var < 10: # This elif clause is optional. + print("some_var is smaller than 10.") +else: # This is optional too. + print("some_var is indeed 10.") + + +""" +For loops iterate over lists +prints: + dog is a mammal + cat is a mammal + mouse is a mammal +""" +for animal in ["dog", "cat", "mouse"]: + # You can use format() to interpolate formatted strings + print("{} is a mammal".format(animal)) + +""" +"range(number)" returns a list of numbers +from zero to the given number +prints: + 0 + 1 + 2 + 3 +""" +for i in range(4): + print(i) + +""" +While loops go until a condition is no longer met. +prints: + 0 + 1 + 2 + 3 +""" +x = 0 +while x < 4: + print(x) + x += 1 # Shorthand for x = x + 1 + +# Handle exceptions with a try/except block +try: + # Use "raise" to raise an error + raise IndexError("This is an index error") +except IndexError as e: + pass # Pass is just a no-op. Usually you would do recovery here. +except (TypeError, NameError): + pass # Multiple exceptions can be handled together, if required. +else: # Optional clause to the try/except block. Must follow all except blocks + print("All good!") # Runs only if the code in try raises no exceptions + +# Python offers a fundamental abstraction called the Iterable. +# An iterable is an object that can be treated as a sequence. +# The object returned the range function, is an iterable. + +filled_dict = {"one": 1, "two": 2, "three": 3} +our_iterable = filled_dict.keys() +print(our_iterable) #=> range(1,10). This is an object that implements our Iterable interface + +# We can loop over it. +for i in our_iterable: + print(i) # Prints one, two, three + +# However we cannot address elements by index. +our_iterable[1] # Raises a TypeError + +# An iterable is an object that knows how to create an iterator. +our_iterator = iter(our_iterable) + +# Our iterator is an object that can remember the state as we traverse through it. +# We get the next object by calling the __next__ function. +our_iterator.__next__() #=> "one" + +# It maintains state as we call __next__. +our_iterator.__next__() #=> "two" +our_iterator.__next__() #=> "three" + +# After the iterator has returned all of its data, it gives you a StopIterator Exception +our_iterator.__next__() # Raises StopIteration + +# You can grab all the elements of an iterator by calling list() on it. +list(filled_dict.keys()) #=> Returns ["one", "two", "three"] + + + +#################################################### +## 4. Functions +#################################################### + +# Use "def" to create new functions +def add(x, y): + print("x is {} and y is {}".format(x, y)) + return x + y # Return values with a return statement + +# Calling functions with parameters +add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 + +# Another way to call functions is with keyword arguments +add(y=6, x=5) # Keyword arguments can arrive in any order. + + +# You can define functions that take a variable number of +# positional arguments +def varargs(*args): + return args + +varargs(1, 2, 3) # => (1, 2, 3) + + +# You can define functions that take a variable number of +# keyword arguments, as well +def keyword_args(**kwargs): + return kwargs + +# Let's call it to see what happens +keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} + + +# You can do both at once, if you like +def all_the_args(*args, **kwargs): + print(args) + print(kwargs) +""" +all_the_args(1, 2, a=3, b=4) prints: + (1, 2) + {"a": 3, "b": 4} +""" + +# When calling functions, you can do the opposite of args/kwargs! +# Use * to expand tuples and use ** to expand kwargs. +args = (1, 2, 3, 4) +kwargs = {"a": 3, "b": 4} +all_the_args(*args) # equivalent to foo(1, 2, 3, 4) +all_the_args(**kwargs) # equivalent to foo(a=3, b=4) +all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) + + +# Function Scope +x = 5 + +def setX(num): + # Local var x not the same as global variable x + x = num # => 43 + print (x) # => 43 + +def setGlobalX(num): + global x + print (x) # => 5 + x = num # global var x is now set to 6 + print (x) # => 6 + +setX(43) +setGlobalX(6) + + +# Python has first class functions +def create_adder(x): + def adder(y): + return x + y + return adder + +add_10 = create_adder(10) +add_10(3) # => 13 + +# There are also anonymous functions +(lambda x: x > 2)(3) # => True + +# TODO - Fix for iterables +# There are built-in higher order functions +map(add_10, [1, 2, 3]) # => [11, 12, 13] +filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] + +# We can use list comprehensions for nice maps and filters +# List comprehension stores the output as a list which can itself be a nested list +[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] +[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] + +#################################################### +## 5. Classes +#################################################### + + +# We subclass from object to get a class. +class Human(object): + + # A class attribute. It is shared by all instances of this class + species = "H. sapiens" + + # Basic initializer, this is called when this class is instantiated. + # Note that the double leading and trailing underscores denote objects + # or attributes that are used by python but that live in user-controlled + # namespaces. You should not invent such names on your own. + def __init__(self, name): + # Assign the argument to the instance's name attribute + self.name = name + + # An instance method. All methods take "self" as the first argument + def say(self, msg): + return "{name}: {message}".format(name=self.name, message=msg) + + # A class method is shared among all instances + # They are called with the calling class as the first argument + @classmethod + def get_species(cls): + return cls.species + + # A static method is called without a class or instance reference + @staticmethod + def grunt(): + return "*grunt*" + + +# Instantiate a class +i = Human(name="Ian") +print(i.say("hi")) # prints out "Ian: hi" + +j = Human("Joel") +print(j.say("hello")) # prints out "Joel: hello" + +# Call our class method +i.get_species() # => "H. sapiens" + +# Change the shared attribute +Human.species = "H. neanderthalensis" +i.get_species() # => "H. neanderthalensis" +j.get_species() # => "H. neanderthalensis" + +# Call the static method +Human.grunt() # => "*grunt*" + + +#################################################### +## 6. Modules +#################################################### + +# You can import modules +import math +print(math.sqrt(16)) # => 4 + +# You can get specific functions from a module +from math import ceil, floor +print(ceil(3.7)) # => 4.0 +print(floor(3.7)) # => 3.0 + +# You can import all functions from a module. +# Warning: this is not recommended +from math import * + +# You can shorten module names +import math as m +math.sqrt(16) == m.sqrt(16) # => True + +# Python modules are just ordinary python files. You +# can write your own, and import them. The name of the +# module is the same as the name of the file. + +# You can find out which functions and attributes +# defines a module. +import math +dir(math) + + +#################################################### +## 7. Advanced +#################################################### + +# Generators help you make lazy code +def double_numbers(iterable): + for i in iterable: + yield i + i + +# A generator creates values on the fly. +# Instead of generating and returning all values at once it creates one in each +# iteration. This means values bigger than 15 wont be processed in +# double_numbers. +# Note range is a generator too. Creating a list 1-900000000 would take lot of +# time to be made +# We use a trailing underscore in variable names when we want to use a name that +# would normally collide with a python keyword +range_ = range(1, 900000000) +# will double all numbers until a result >=30 found +for i in double_numbers(range_): + print(i) + if i >= 30: + break + + +# Decorators +# in this example beg wraps say +# Beg will call say. If say_please is True then it will change the returned +# message +from functools import wraps + + +def beg(target_function): + @wraps(target_function) + def wrapper(*args, **kwargs): + msg, say_please = target_function(*args, **kwargs) + if say_please: + return "{} {}".format(msg, "Please! I am poor :(") + return msg + + return wrapper + + +@beg +def say(say_please=False): + msg = "Can you buy me a beer?" + return msg, say_please + + +print(say()) # Can you buy me a beer? +print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( +``` + +## Ready For More? + +### Free Online + +* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) +* [Dive Into Python](http://www.diveintopython.net/) +* [Ideas for Python Projects](http://pythonpracticeprojects.com) + +* [The Official Docs](http://docs.python.org/3/) +* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) +* [Python Module of the Week](http://pymotw.com/3/) +* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) + +### Dead Tree + +* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) +* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) +* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20) + -- cgit v1.2.3 From d7d131f4406ac86c50b563797c4432dc79e244ec Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 24 Oct 2014 01:05:33 -0400 Subject: Fix a typo, plus section headings --- zh-cn/python3-cn.html.markdown | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index dc09de4f..74e997ec 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -51,7 +51,7 @@ Note: This article applies to Python 3 specifically. Check out the other tutoria # 浮点数的运算结果也是浮点数 3 * 2.0 # => 6.0 -# Modulo operation +# 模除 7 % 3 # => 1 # x的y次方 @@ -72,7 +72,7 @@ not False # => True True and False #=> False False or True #=> True -# 整数也可以是布尔值 +# 整数也可以当作布尔值 0 and 2 #=> 0 -5 or 0 #=> -5 0 == False #=> True @@ -101,10 +101,10 @@ False or True #=> True "这是个字符串" '这也是个字符串' -# 用加好连接字符串 +# 用加号连接字符串 "Hello " + "world!" # => "Hello world!" -# A string can be treated like a list of characters +# 字符串可以被当作字符列表 "This is a string"[0] # => 'T' # .format can be used to format strings, like this: @@ -139,7 +139,7 @@ bool({}) #=> False #################################################### -## 2. Variables and Collections +## 2. 变量和集合 #################################################### # Python has a print function @@ -300,7 +300,7 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6} #################################################### -## 3. Control Flow and Iterables +## 3. 流程控制和迭代器 #################################################### # Let's just make a variable @@ -398,7 +398,7 @@ list(filled_dict.keys()) #=> Returns ["one", "two", "three"] #################################################### -## 4. Functions +## 4. 函数 #################################################### # Use "def" to create new functions @@ -490,7 +490,7 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] [x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] #################################################### -## 5. Classes +## 5. 类 #################################################### @@ -544,7 +544,7 @@ Human.grunt() # => "*grunt*" #################################################### -## 6. Modules +## 6. 模块 #################################################### # You can import modules @@ -575,7 +575,7 @@ dir(math) #################################################### -## 7. Advanced +## 7. 高级用法 #################################################### # Generators help you make lazy code -- cgit v1.2.3 From c917dc75ac25641b86ecd2d14928175c3d1cc684 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 24 Oct 2014 11:24:51 -0400 Subject: Finish most lines in section 1 --- zh-cn/python3-cn.html.markdown | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 74e997ec..e297a7ce 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -42,9 +42,9 @@ Note: This article applies to Python 3 specifically. Check out the other tutoria 35 / 5 # => 7.0 5 / 3 # => 1.6666666666666667 -# Result of integer division truncated down both for positive and negative. +# 整数除法的结果都是向下取整 5 // 3 # => 1 -5.0 // 3.0 # => 1.0 # works on floats too +5.0 // 3.0 # => 1.0 # 浮点数也可以 -5 // 3 # => -2 -5.0 // 3.0 # => -2.0 @@ -107,22 +107,20 @@ False or True #=> True # 字符串可以被当作字符列表 "This is a string"[0] # => 'T' -# .format can be used to format strings, like this: +# 用.format来格式化字符串 "{} can be {}".format("strings", "interpolated") -# You can repeat the formatting arguments to save some typing. +# 可以重复参数以节省时间 "{0} be nimble, {0} be quick, {0} jump over the {1}".format("Jack", "candle stick") #=> "Jack be nimble, Jack be quick, Jack jump over the candle stick" -# You can use keywords if you don't want to count. +# 如果不想数参数,可以用关键字 "{name} wants to eat {food}".format(name="Bob", food="lasagna") #=> "Bob wants to eat lasagna" -# If your Python 3 code also needs to run on Python 2.5 and below, you can also -# still use the old style of formatting: +# 如果你的Python3程序也要在Python2.5以下环境运行,也可以用老式的格式化语法 "%s can be %s the %s way" % ("strings", "interpolated", "old") - -# None is an object +# None是一个对象 None # => None # Don't use the equality "==" symbol to compare objects to None @@ -130,8 +128,8 @@ None # => None "etc" is None # => False None is None # => True -# None, 0, and empty strings/lists/dicts all evaluate to False. -# All other values are True +# None,0,空字符串,空列表,空关联数组都算是False +# 所有其他值都是True bool(0) # => False bool("") # => False bool([]) #=> False -- cgit v1.2.3 From ba5c351f216ca63e4f46230db683224fd6d26355 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 31 Oct 2014 15:40:49 -0600 Subject: A bit of section 2, 3, 4 --- zh-cn/python3-cn.html.markdown | 90 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index e297a7ce..78ecb4af 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -140,60 +140,60 @@ bool({}) #=> False ## 2. 变量和集合 #################################################### -# Python has a print function +# print是内置的打印函数 print("I'm Python. Nice to meet you!") -# No need to declare variables before assigning to them. -# Convention is to use lower_case_with_underscores +# 在给变量赋值前不用提前声明 +# 传统的变量命名是小写,用下划线分隔单词 some_var = 5 some_var # => 5 -# Accessing a previously unassigned variable is an exception. -# See Control Flow to learn more about exception handling. -some_unknown_var # Raises a NameError +# 存取未赋值的变量会抛出异常 +# 下面流程控制一段更深入讲解异常处理 +some_unknown_var # 抛出NameError -# Lists store sequences +# 用列表(list)储存序列 li = [] -# You can start with a prefilled list +# 创建列表时也可以同时赋给元素 other_li = [4, 5, 6] -# Add stuff to the end of a list with append -li.append(1) # li is now [1] -li.append(2) # li is now [1, 2] -li.append(4) # li is now [1, 2, 4] -li.append(3) # li is now [1, 2, 4, 3] -# Remove from the end with pop -li.pop() # => 3 and li is now [1, 2, 4] -# Let's put it back -li.append(3) # li is now [1, 2, 4, 3] again. - -# Access a list like you would any array +# 用append在列表最后追加元素 +li.append(1) # li现在是[1] +li.append(2) # li现在是[1, 2] +li.append(4) # li现在是[1, 2, 4] +li.append(3) # li现在是[1, 2, 4, 3] +# 用pop从列表尾部删除 +li.pop() # => 3 且li现在是[1, 2, 4] +# 把3再放回去 +li.append(3) # li变回[1, 2, 4, 3] + +# 列表取值跟数组一样 li[0] # => 1 -# Look at the last element +# 取出最后一个元素 li[-1] # => 3 -# Looking out of bounds is an IndexError -li[4] # Raises an IndexError +# 越界读取会造成IndexError +li[4] # 抛出IndexError -# You can look at ranges with slice syntax. +# 列表的切割语法 # (It's a closed/open range for you mathy types.) li[1:3] # => [2, 4] -# Omit the beginning +# 取尾 li[2:] # => [4, 3] -# Omit the end +# 取头 li[:3] # => [1, 2, 4] -# Select every second entry +# 每两个取一个 li[::2] # =>[1, 4] -# Revert the list +# 倒排列表 li[::-1] # => [3, 4, 2, 1] # Use any combination of these to make advanced slices # li[start:end:step] -# Remove arbitrary elements from a list with "del" +# 用del删除任何一个元素 del li[2] # li is now [1, 2, 3] -# You can add lists -# Note: values for li and for other_li are not modified. +# 列表可以相加 +# 注意:li和other_li的值都不变 li + other_li # => [1, 2, 3, 4, 5, 6] # Concatenate lists with "extend()" @@ -211,7 +211,7 @@ tup = (1, 2, 3) tup[0] # => 1 tup[0] = 3 # Raises a TypeError -# You can do all those list thingies on tuples too +# 列表允许的操作元组也可以 len(tup) # => 3 tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) tup[:2] # => (1, 2) @@ -301,17 +301,17 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6} ## 3. 流程控制和迭代器 #################################################### -# Let's just make a variable +# 先随便定义一个变量 some_var = 5 -# Here is an if statement. Indentation is significant in python! -# prints "some_var is smaller than 10" +# 这是个if语句。注意缩进在Python里是有意义的 +# 印出"some_var比10小" if some_var > 10: - print("some_var is totally bigger than 10.") -elif some_var < 10: # This elif clause is optional. - print("some_var is smaller than 10.") -else: # This is optional too. - print("some_var is indeed 10.") + print("some_var比10大") +elif some_var < 10: # elif句是可选的 + print("some_var比10小") +else: # else也是可选的 + print("some_var就是10") """ @@ -399,16 +399,16 @@ list(filled_dict.keys()) #=> Returns ["one", "two", "three"] ## 4. 函数 #################################################### -# Use "def" to create new functions +# 用def定义新函数 def add(x, y): print("x is {} and y is {}".format(x, y)) - return x + y # Return values with a return statement + return x + y # 用return语句返回 -# Calling functions with parameters -add(5, 6) # => prints out "x is 5 and y is 6" and returns 11 +# 调用函数 +add(5, 6) # => 印出"x is 5 and y is 6"并且返回11 -# Another way to call functions is with keyword arguments -add(y=6, x=5) # Keyword arguments can arrive in any order. +# 也可以用关键字参数来调用函数 +add(y=6, x=5) # 关键字参数可以用任何顺序 # You can define functions that take a variable number of -- cgit v1.2.3 From 2444690e5fae22d5f09f3f4966996785353fd3af Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 31 Oct 2014 15:52:20 -0600 Subject: All of section 6 --- zh-cn/python3-cn.html.markdown | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 78ecb4af..efdfc158 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -545,29 +545,27 @@ Human.grunt() # => "*grunt*" ## 6. 模块 #################################################### -# You can import modules +# 用import导入模块 import math print(math.sqrt(16)) # => 4 -# You can get specific functions from a module +# 也可以从模块中导入个别值 from math import ceil, floor print(ceil(3.7)) # => 4.0 print(floor(3.7)) # => 3.0 -# You can import all functions from a module. -# Warning: this is not recommended +# 可以导入一个模块中所有值 +# 警告:不建议这么做 from math import * -# You can shorten module names +# 如此缩写模块名字 import math as m math.sqrt(16) == m.sqrt(16) # => True -# Python modules are just ordinary python files. You -# can write your own, and import them. The name of the -# module is the same as the name of the file. +# Python模块其实就是普通的Python文件。你可以自己写,然后导入, +# 模块的名字就是文件的名字。 -# You can find out which functions and attributes -# defines a module. +# 你可以这样列出一个模块里所有的值 import math dir(math) -- cgit v1.2.3 From fb89673ef1063c3446462d3249246929d492ea76 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 31 Oct 2014 16:01:10 -0600 Subject: Minor changes --- zh-cn/python3-cn.html.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index efdfc158..6ad23600 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -148,8 +148,8 @@ print("I'm Python. Nice to meet you!") some_var = 5 some_var # => 5 -# 存取未赋值的变量会抛出异常 -# 下面流程控制一段更深入讲解异常处理 +# 访问未赋值的变量会抛出异常 +# 参考流程控制一段来学习异常处理 some_unknown_var # 抛出NameError # 用列表(list)储存序列 @@ -167,22 +167,22 @@ li.pop() # => 3 且li现在是[1, 2, 4] # 把3再放回去 li.append(3) # li变回[1, 2, 4, 3] -# 列表取值跟数组一样 +# 列表存取跟数组一样 li[0] # => 1 # 取出最后一个元素 li[-1] # => 3 -# 越界读取会造成IndexError +# 越界存取会造成IndexError li[4] # 抛出IndexError -# 列表的切割语法 +# 列表有切割语法 # (It's a closed/open range for you mathy types.) li[1:3] # => [2, 4] # 取尾 li[2:] # => [4, 3] # 取头 li[:3] # => [1, 2, 4] -# 每两个取一个 +# 隔一个取一个 li[::2] # =>[1, 4] # 倒排列表 li[::-1] # => [3, 4, 2, 1] -- cgit v1.2.3 From d234d1c8945a7a4fdc812be65de89ca0c6aa52b6 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 31 Oct 2014 17:20:50 -0600 Subject: Finish sections 2 and 3 --- zh-cn/python3-cn.html.markdown | 153 ++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 79 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 6ad23600..2c1c03f8 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -9,13 +9,13 @@ translators: filename: learnpython3.py --- -Python was created by Guido Van Rossum in the early 90's. It is now one of the most popular -languages in existence. I fell in love with Python for its syntactic clarity. It's basically -executable pseudocode. +Python是由吉多·范罗苏姆(Guido Van Rossum)在90年代早期设计。它是如今最常用的编程 +语言之一。它的语法简洁且优美,几乎就是可执行的伪代码。 -Feedback would be highly appreciated! You can reach me at [@louiedinh](http://twitter.com/louiedinh) or louiedinh [at] [google's email service] +欢迎大家斧正。英文版原作Louie Dinh [@louiedinh](http://twitter.com/louiedinh) +或着Email louiedinh [at] [谷歌的信箱服务]。中文翻译Geoff Liu。 -Note: This article applies to Python 3 specifically. Check out the other tutorial if you want to learn the old Python 2.7 +注意:这篇教程是特别为Python3写的。如果你想学旧版Python2,我们特别有另一篇教程。 ```python @@ -128,7 +128,7 @@ None # => None "etc" is None # => False None is None # => True -# None,0,空字符串,空列表,空关联数组都算是False +# None,0,空字符串,空列表,空字典都算是False # 所有其他值都是True bool(0) # => False bool("") # => False @@ -176,7 +176,6 @@ li[-1] # => 3 li[4] # 抛出IndexError # 列表有切割语法 -# (It's a closed/open range for you mathy types.) li[1:3] # => [2, 4] # 取尾 li[2:] # => [4, 3] @@ -196,103 +195,101 @@ del li[2] # li is now [1, 2, 3] # 注意:li和other_li的值都不变 li + other_li # => [1, 2, 3, 4, 5, 6] -# Concatenate lists with "extend()" -li.extend(other_li) # Now li is [1, 2, 3, 4, 5, 6] +# 用extend拼接列表 +li.extend(other_li) # li现在是[1, 2, 3, 4, 5, 6] -# Check for existence in a list with "in" +# 用in测试列表是否包含值 1 in li # => True -# Examine the length with "len()" +# 用len取列表长度 len(li) # => 6 -# Tuples are like lists but are immutable. +# 元组是不可改变的序列 tup = (1, 2, 3) tup[0] # => 1 -tup[0] = 3 # Raises a TypeError +tup[0] = 3 # 抛出TypeError -# 列表允许的操作元组也可以 +# 列表允许的操作元组大都可以 len(tup) # => 3 tup + (4, 5, 6) # => (1, 2, 3, 4, 5, 6) tup[:2] # => (1, 2) 2 in tup # => True -# You can unpack tuples (or lists) into variables -a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3 -# Tuples are created by default if you leave out the parentheses +# 可以把元组合列表解包,赋值给变量 +a, b, c = (1, 2, 3) # 现在a是1,b是2,c是3 +# 元组周围的括号是可以省略的 d, e, f = 4, 5, 6 -# Now look how easy it is to swap two values -e, d = d, e # d is now 5 and e is now 4 +# 交换两个变量的值就这么简单 +e, d = d, e # 现在d是5,e是4 -# Dictionaries store mappings +# 用字典表达映射关系 empty_dict = {} -# Here is a prefilled dictionary +# 初始化的字典 filled_dict = {"one": 1, "two": 2, "three": 3} -# Look up values with [] +# 用[]取值 filled_dict["one"] # => 1 -# Get all keys as a list with "keys()". -# We need to wrap the call in list() because we are getting back an iterable. We'll talk about those later. -# Note - Dictionary key ordering is not guaranteed. -# Your results might not match this exactly. + +# 用keys获得所有的键。因为keys返回一个可迭代对象,所以在这里把结果包在list里。我们下面会详细介绍可迭代。 +# 注意:字典键的顺序是不定的,你得到的结果可能和以下不同。 list(filled_dict.keys()) # => ["three", "two", "one"] -# Get all values as a list with "values()". Once again we need to wrap it in list() to get it out of the iterable. -# Note - Same as above regarding key ordering. +# 用values获得所有的值。跟keys一样,要用list包起来,顺序也可能不同。 list(filled_dict.values()) # => [3, 2, 1] -# Check for existence of keys in a dictionary with "in" +# 用in测试一个字典是否包含一个键 "one" in filled_dict # => True 1 in filled_dict # => False -# Looking up a non-existing key is a KeyError +# 访问不存在的键会导致KeyError filled_dict["four"] # KeyError -# Use "get()" method to avoid the KeyError +# 用get来避免KeyError filled_dict.get("one") # => 1 filled_dict.get("four") # => None -# The get method supports a default argument when the value is missing +# 当键不存在的时候get方法可以返回默认值 filled_dict.get("one", 4) # => 1 filled_dict.get("four", 4) # => 4 -# "setdefault()" inserts into a dictionary only if the given key isn't present -filled_dict.setdefault("five", 5) # filled_dict["five"] is set to 5 -filled_dict.setdefault("five", 6) # filled_dict["five"] is still 5 +# setdefault方法只有当键不存在的时候插入新值 +filled_dict.setdefault("five", 5) # filled_dict["five"]设为5 +filled_dict.setdefault("five", 6) # filled_dict["five"]还是5 -# Adding to a dictionary +# 字典赋值 filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4} -#filled_dict["four"] = 4 #another way to add to dict +filled_dict["four"] = 4 # 另一种赋值方法 -# Remove keys from a dictionary with del -del filled_dict["one"] # Removes the key "one" from filled dict +# 用del删除 +del filled_dict["one"] # 从filled_dict中把one删除 -# Sets store ... well sets +# 用set表达集合 empty_set = set() -# Initialize a set with a bunch of values. Yeah, it looks a bit like a dict. Sorry. -some_set = {1, 1, 2, 2, 3, 4} # some_set is now {1, 2, 3, 4} +# 初始化一个集合,语法跟字典相似。 +some_set = {1, 1, 2, 2, 3, 4} # some_set现在是{1, 2, 3, 4} -#Can set new variables to a set +# 可以把集合赋值于变量 filled_set = some_set -# Add one more item to the set -filled_set.add(5) # filled_set is now {1, 2, 3, 4, 5} +# 为集合添加元素 +filled_set.add(5) # filled_set现在是{1, 2, 3, 4, 5} -# Do set intersection with & +# & 取交集 other_set = {3, 4, 5, 6} filled_set & other_set # => {3, 4, 5} -# Do set union with | +# | 取并集 filled_set | other_set # => {1, 2, 3, 4, 5, 6} -# Do set difference with - +# - 取补集 {1, 2, 3, 4} - {2, 3, 5} # => {1, 4} -# Check for existence in a set with in +# in 测试集合是否包含元素 2 in filled_set # => True 10 in filled_set # => False @@ -315,20 +312,18 @@ else: # else也是可选的 """ -For loops iterate over lists -prints: +用for循环语句遍历列表 +打印: dog is a mammal cat is a mammal mouse is a mammal """ for animal in ["dog", "cat", "mouse"]: - # You can use format() to interpolate formatted strings print("{} is a mammal".format(animal)) """ -"range(number)" returns a list of numbers -from zero to the given number -prints: +"range(number)"返回数字列表从0到给的数字 +打印: 0 1 2 @@ -338,8 +333,8 @@ for i in range(4): print(i) """ -While loops go until a condition is no longer met. -prints: +while循环直到条件不满足 +打印: 0 1 2 @@ -348,49 +343,49 @@ prints: x = 0 while x < 4: print(x) - x += 1 # Shorthand for x = x + 1 + x += 1 # x = x + 1 的简写 -# Handle exceptions with a try/except block +# try/except块处理异常状况 try: - # Use "raise" to raise an error + # 用raise来抛出异常 raise IndexError("This is an index error") except IndexError as e: - pass # Pass is just a no-op. Usually you would do recovery here. + pass # pass是无操作,但是应该在这里处理错误 except (TypeError, NameError): - pass # Multiple exceptions can be handled together, if required. -else: # Optional clause to the try/except block. Must follow all except blocks - print("All good!") # Runs only if the code in try raises no exceptions + pass # 可以同时处理不同类的错误 +else: # else语句是可选的,必须在所有的except之后 + print("All good!") # 只有当try运行完没有错误的时候这句才会运行 + -# Python offers a fundamental abstraction called the Iterable. -# An iterable is an object that can be treated as a sequence. -# The object returned the range function, is an iterable. +# Python提供一个叫做可迭代(iterable)的基本抽象。一个可迭代对象是可以被当作序列 +# 的对象。比如说上面range返回的对象就是可迭代的。 filled_dict = {"one": 1, "two": 2, "three": 3} our_iterable = filled_dict.keys() -print(our_iterable) #=> range(1,10). This is an object that implements our Iterable interface +print(our_iterable) # => range(1,10) 是一个实现可迭代接口的对象 -# We can loop over it. +# 可迭代对象可以遍历 for i in our_iterable: - print(i) # Prints one, two, three + print(i) # 打印 one, two, three -# However we cannot address elements by index. -our_iterable[1] # Raises a TypeError +# 但是不可以随机访问 +our_iterable[1] # 抛出TypeError -# An iterable is an object that knows how to create an iterator. +# 可迭代对象知道怎么生成迭代器 our_iterator = iter(our_iterable) -# Our iterator is an object that can remember the state as we traverse through it. -# We get the next object by calling the __next__ function. +# 迭代器是一个可以记住遍历的位置的对象 +# 用__next__可以取得下一个元素 our_iterator.__next__() #=> "one" -# It maintains state as we call __next__. +# 再一次调取__next__时会记得位置 our_iterator.__next__() #=> "two" our_iterator.__next__() #=> "three" -# After the iterator has returned all of its data, it gives you a StopIterator Exception -our_iterator.__next__() # Raises StopIteration +# 当迭代器所有元素都取出后,会抛出StopIteration +our_iterator.__next__() # 抛出StopIteration -# You can grab all the elements of an iterator by calling list() on it. +# 可以用list一次取出迭代器所有的元素 list(filled_dict.keys()) #=> Returns ["one", "two", "three"] -- cgit v1.2.3 From ce381ce958b45d5249e597b51703b5ef65247310 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Tue, 4 Nov 2014 13:15:57 -0700 Subject: Functions section --- zh-cn/python3-cn.html.markdown | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 2c1c03f8..a490ea40 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -406,24 +406,22 @@ add(5, 6) # => 印出"x is 5 and y is 6"并且返回11 add(y=6, x=5) # 关键字参数可以用任何顺序 -# You can define functions that take a variable number of -# positional arguments +# 我们可以定义一个可变参数函数 def varargs(*args): return args varargs(1, 2, 3) # => (1, 2, 3) -# You can define functions that take a variable number of -# keyword arguments, as well +# 我们也可以定义一个关键字可变参数函数 def keyword_args(**kwargs): return kwargs -# Let's call it to see what happens +# 我们来看看结果是什么: keyword_args(big="foot", loch="ness") # => {"big": "foot", "loch": "ness"} -# You can do both at once, if you like +# 这两种可变参数可以混着用 def all_the_args(*args, **kwargs): print(args) print(kwargs) @@ -433,8 +431,7 @@ all_the_args(1, 2, a=3, b=4) prints: {"a": 3, "b": 4} """ -# When calling functions, you can do the opposite of args/kwargs! -# Use * to expand tuples and use ** to expand kwargs. +# 调用可变参数函数时可以做跟上面相反的,用*展开序列,用**展开字典。 args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} all_the_args(*args) # equivalent to foo(1, 2, 3, 4) @@ -442,25 +439,25 @@ all_the_args(**kwargs) # equivalent to foo(a=3, b=4) all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) -# Function Scope +# 函数作用域 x = 5 def setX(num): - # Local var x not the same as global variable x + # 局部作用域的x和全局域的x是不同的 x = num # => 43 print (x) # => 43 def setGlobalX(num): global x print (x) # => 5 - x = num # global var x is now set to 6 + x = num # 现在全局域的x被赋值 print (x) # => 6 setX(43) setGlobalX(6) -# Python has first class functions +# 函数在Python是一等公民 def create_adder(x): def adder(y): return x + y @@ -469,16 +466,14 @@ def create_adder(x): add_10 = create_adder(10) add_10(3) # => 13 -# There are also anonymous functions +# 也有匿名函数 (lambda x: x > 2)(3) # => True -# TODO - Fix for iterables -# There are built-in higher order functions +# 内置的高阶函数 map(add_10, [1, 2, 3]) # => [11, 12, 13] filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] -# We can use list comprehensions for nice maps and filters -# List comprehension stores the output as a list which can itself be a nested list +# 用列表推导式可以简化映射和过滤。列表推导式的返回值是另一个列表。 [add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] -- cgit v1.2.3 From 191a0c705010634fd2b091bce5653da72bbfcf4a Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Wed, 5 Nov 2014 12:36:28 -0700 Subject: Only one section left! --- zh-cn/python3-cn.html.markdown | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index a490ea40..1f294ebb 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -345,9 +345,9 @@ while x < 4: print(x) x += 1 # x = x + 1 的简写 -# try/except块处理异常状况 +# 用try/except块处理异常状况 try: - # 用raise来抛出异常 + # 用raise抛出异常 raise IndexError("This is an index error") except IndexError as e: pass # pass是无操作,但是应该在这里处理错误 @@ -564,31 +564,28 @@ dir(math) ## 7. 高级用法 #################################################### -# Generators help you make lazy code +# 用生成器(generators)方便地写惰性运算 def double_numbers(iterable): for i in iterable: yield i + i -# A generator creates values on the fly. -# Instead of generating and returning all values at once it creates one in each -# iteration. This means values bigger than 15 wont be processed in -# double_numbers. -# Note range is a generator too. Creating a list 1-900000000 would take lot of -# time to be made -# We use a trailing underscore in variable names when we want to use a name that -# would normally collide with a python keyword +# 生成器只有在需要时才计算下一个值。它们每一次循环只生成一个值,而不是把所有的 +# 值全部算好。这意味着double_numbers不会生成大于15的数字。 +# +# range的返回值也是一个生成器,不然一个1到900000000的列表会花很多时间和内存。 +# +# 如果你想用一个Python的关键字当作变量名,可以加一个下划线来区分。 range_ = range(1, 900000000) -# will double all numbers until a result >=30 found +# 当找到一个 >=30 的结果就会停 for i in double_numbers(range_): print(i) if i >= 30: break -# Decorators -# in this example beg wraps say -# Beg will call say. If say_please is True then it will change the returned -# message +# 装饰器(decorators) +# 这个例子中,beg装饰say +# beg会先调用say。如果返回的say_please为真,beg会改变返回的字符串。 from functools import wraps @@ -613,9 +610,9 @@ print(say()) # Can you buy me a beer? print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( ``` -## Ready For More? +## 想继续学吗? -### Free Online +### 线上免费材料(英文) * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) @@ -626,7 +623,7 @@ print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :( * [Python Module of the Week](http://pymotw.com/3/) * [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) -### Dead Tree +### 书籍(也是英文) * [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20) * [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20) -- cgit v1.2.3 From cd4c3a4ad8de2668ed6caad2df40dc470a80a4a0 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Wed, 5 Nov 2014 13:05:47 -0700 Subject: Done with Chinese, mostly --- zh-cn/python3-cn.html.markdown | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 1f294ebb..4059c876 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -123,8 +123,7 @@ False or True #=> True # None是一个对象 None # => None -# Don't use the equality "==" symbol to compare objects to None -# Use "is" instead. This checks for equality of object identity. +# 当与None进行比较时不要用 ==,要用is。is是用来比较两个变量是否指向同一个对象。 "etc" is None # => False None is None # => True @@ -482,52 +481,50 @@ filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] #################################################### -# We subclass from object to get a class. +# 定义一个继承object的类 class Human(object): - # A class attribute. It is shared by all instances of this class + # 类属性,被所有此类的实例共用。 species = "H. sapiens" - # Basic initializer, this is called when this class is instantiated. - # Note that the double leading and trailing underscores denote objects - # or attributes that are used by python but that live in user-controlled - # namespaces. You should not invent such names on your own. + # 构造方法,当实例被初始化时被调用。注意名字前后的双下划线,这是表明这个属 + # 性或方法对Python有特殊意义,但是允许用户自行定义。你自己取名时不应该用这 + # 种格式。 def __init__(self, name): # Assign the argument to the instance's name attribute self.name = name - # An instance method. All methods take "self" as the first argument + # 实例方法,第一个参数总是self,就是这个实例对象 def say(self, msg): return "{name}: {message}".format(name=self.name, message=msg) - # A class method is shared among all instances - # They are called with the calling class as the first argument + # 类方法,被所有此类的实例共用。第一个参数是这个类对象。 @classmethod def get_species(cls): return cls.species - # A static method is called without a class or instance reference + # 静态方法。调用时没有实例或类的绑定。 @staticmethod def grunt(): return "*grunt*" -# Instantiate a class +# 构造一个实例 i = Human(name="Ian") -print(i.say("hi")) # prints out "Ian: hi" +print(i.say("hi")) # 印出 "Ian: hi" j = Human("Joel") -print(j.say("hello")) # prints out "Joel: hello" +print(j.say("hello")) # 印出 "Joel: hello" -# Call our class method +# 调用一个类方法 i.get_species() # => "H. sapiens" -# Change the shared attribute +# 改一个共用的类属性 Human.species = "H. neanderthalensis" i.get_species() # => "H. neanderthalensis" j.get_species() # => "H. neanderthalensis" -# Call the static method +# 调用静态方法 Human.grunt() # => "*grunt*" -- cgit v1.2.3 From 1d665b9c0734ac606c2f8fa8b71c22c1d7ac377b Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Wed, 5 Nov 2014 13:12:35 -0700 Subject: Missed a few lines --- zh-cn/python3-cn.html.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 4059c876..1b3f5086 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -184,8 +184,8 @@ li[:3] # => [1, 2, 4] li[::2] # =>[1, 4] # 倒排列表 li[::-1] # => [3, 4, 2, 1] -# Use any combination of these to make advanced slices -# li[start:end:step] +# 可以用三个参数的任何组合来构建切割 +# li[始:终:步伐] # 用del删除任何一个元素 del li[2] # li is now [1, 2, 3] @@ -433,9 +433,9 @@ all_the_args(1, 2, a=3, b=4) prints: # 调用可变参数函数时可以做跟上面相反的,用*展开序列,用**展开字典。 args = (1, 2, 3, 4) kwargs = {"a": 3, "b": 4} -all_the_args(*args) # equivalent to foo(1, 2, 3, 4) -all_the_args(**kwargs) # equivalent to foo(a=3, b=4) -all_the_args(*args, **kwargs) # equivalent to foo(1, 2, 3, 4, a=3, b=4) +all_the_args(*args) # 相当于 foo(1, 2, 3, 4) +all_the_args(**kwargs) # 相当于 foo(a=3, b=4) +all_the_args(*args, **kwargs) # 相当于 foo(1, 2, 3, 4, a=3, b=4) # 函数作用域 -- cgit v1.2.3 From e45b3f5bdbcbbb02fa304beafda8676a7227354c Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Thu, 6 Nov 2014 16:09:45 +0200 Subject: Update python3-cn.html.markdown --- zh-cn/python3-cn.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/python3-cn.html.markdown b/zh-cn/python3-cn.html.markdown index 1b3f5086..c223297c 100644 --- a/zh-cn/python3-cn.html.markdown +++ b/zh-cn/python3-cn.html.markdown @@ -6,7 +6,8 @@ contributors: - ["Andre Polykanine", "https://github.com/Oire"] translators: - ["Geoff Liu", "http://geoffliu.me"] -filename: learnpython3.py +filename: learnpython3-cn.py +lang: zh-cn --- Python是由吉多·范罗苏姆(Guido Van Rossum)在90年代早期设计。它是如今最常用的编程 -- cgit v1.2.3 From 453b6254c5809c2227de29b2b6f99f7db5a8c6de Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Fri, 14 Nov 2014 17:07:42 +0200 Subject: Update markdown-cn.html.markdown --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index eecb8c5b..1c577efb 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -1,5 +1,5 @@ --- -language: Markdown +language: markdown contributors: - ["Dan Turkel", "http://danturkel.com/"] translators: -- cgit v1.2.3 From 4f2f0116edb8b4a83dba19e9fe61229e8d88d29e Mon Sep 17 00:00:00 2001 From: Jakukyo Friel Date: Wed, 10 Dec 2014 22:57:59 +0800 Subject: lua-cn: typos and refinements. --- zh-cn/lua-cn.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/lua-cn.html.markdown b/zh-cn/lua-cn.html.markdown index 53a603a2..098d0ab5 100644 --- a/zh-cn/lua-cn.html.markdown +++ b/zh-cn/lua-cn.html.markdown @@ -63,8 +63,8 @@ foo = anUnknownVariable -- 现在 foo = nil. aBoolValue = false ---只有nil和false为假; 0和 ''都均为真! -if not aBoolValue then print('twas false') end +--只有nil和false为假; 0和 ''均为真! +if not aBoolValue then print('false') end -- 'or'和 'and'短路 -- 类似于C/js里的 a?b:c 操作符: @@ -149,7 +149,7 @@ print {} -- 一样可以工作。 -- Table = Lua唯一的组合数据结构; -- 它们是关联数组。 -- 类似于PHP的数组或者js的对象, --- 它们是哈希表或者字典,也可以当初列表使用。 +-- 它们是哈希表或者字典,也可以当列表使用。 -- 按字典/map的方式使用Table: -- cgit v1.2.3 From 6263dda6de1f9163a80a3ceab2a05666149e6a79 Mon Sep 17 00:00:00 2001 From: sunxb10 Date: Sat, 3 Jan 2015 20:49:39 +0800 Subject: Chinese translation of MATLAB tutorial --- zh-cn/matlab-cn.html.markdown | 491 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 zh-cn/matlab-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/matlab-cn.html.markdown b/zh-cn/matlab-cn.html.markdown new file mode 100644 index 00000000..77ba765a --- /dev/null +++ b/zh-cn/matlab-cn.html.markdown @@ -0,0 +1,491 @@ +--- +language: Matlab +contributors: + - ["mendozao", "http://github.com/mendozao"] + - ["jamesscottbrown", "http://jamesscottbrown.com"] +translators: + - ["sunxb10", "https://github.com/sunxb10"] +lang: zh-cn +--- + +MATLAB 是 MATrix LABoratory (矩阵实验室)的缩写,它是一种功能强大的数值计算语言,在工程和数学领域中应用广泛。 + +如果您有任何需要反馈或交流的内容,请联系本教程作者[@the_ozzinator](https://twitter.com/the_ozzinator)、[osvaldo.t.mendoza@gmail.com](mailto:osvaldo.t.mendoza@gmail.com)。 + +```matlab +% 以百分号作为注释符 + +%{ +多行注释 +可以 +这样 +表示 +%} + +% 指令可以随意跨行,但需要在跨行处用 '...' 标明: + a = 1 + 2 + ... + + 4 + +% 可以在MATLAB中直接向操作系统发出指令 +!ping google.com + +who % 显示内存中的所有变量 +whos % 显示内存中的所有变量以及它们的类型 +clear % 清除内存中的所有变量 +clear('A') % 清除指定的变量 +openvar('A') % 在变量编辑器中编辑指定变量 + +clc % 清除命令窗口中显示的所有指令 +diary % 将命令窗口中的内容写入本地文件 +ctrl-c % 终止当前计算 + +edit('myfunction.m') % 在编辑器中打开指定函数或脚本 +type('myfunction.m') % 在命令窗口中打印指定函数或脚本的源码 + +profile on % 打开 profile 代码分析工具 +profile of % 关闭 profile 代码分析工具 +profile viewer % 查看 profile 代码分析工具的分析结果 + +help command % 在命令窗口中显示指定命令的帮助文档 +doc command % 在帮助窗口中显示指定命令的帮助文档 +lookfor command % 在所有 MATLAB 内置函数的头部注释块的第一行中搜索指定命令 +lookfor command -all % 在所有 MATLAB 内置函数的整个头部注释块中搜索指定命令 + + +% 输出格式 +format short % 浮点数保留 4 位小数 +format long % 浮点数保留 15 位小数 +format bank % 金融格式,浮点数只保留 2 位小数 +fprintf('text') % 在命令窗口中显示 "text" +disp('text') % 在命令窗口中显示 "text" + + +% 变量与表达式 +myVariable = 4 % 命令窗口中将新创建的变量 +myVariable = 4; % 加上分号可使命令窗口中不显示当前语句执行结果 +4 + 6 % ans = 10 +8 * myVariable % ans = 32 +2 ^ 3 % ans = 8 +a = 2; b = 3; +c = exp(a)*sin(pi/2) % c = 7.3891 + + +% 调用函数有两种方式: +% 标准函数语法: +load('myFile.mat', 'y') % 参数放在括号内,以英文逗号分隔 +% 指令语法: +load myFile.mat y % 不加括号,以空格分隔参数 +% 注意在指令语法中参数不需要加引号:在这种语法下,所有输入参数都只能是文本文字, +% 不能是变量的具体值,同样也不能是输出变量 +[V,D] = eig(A); % 这条函数调用无法转换成等价的指令语法 +[~,D] = eig(A); % 如果结果中只需要 D 而不需要 V 则可以这样写 + + + +% 逻辑运算 +1 > 5 % 假,ans = 0 +10 >= 10 % 真,ans = 1 +3 ~= 4 % 不等于 -> ans = 1 +3 == 3 % 等于 -> ans = 1 +3 > 1 && 4 > 1 % 与 -> ans = 1 +3 > 1 || 4 > 1 % 或 -> ans = 1 +~1 % 非 -> ans = 0 + +% 逻辑运算可直接应用于矩阵,运算结果也是矩阵 +A > 5 +% 对矩阵中每个元素做逻辑运算,若为真,则在运算结果的矩阵中对应位置的元素就是 1 +A( A > 5 ) +% 如此返回的向量,其元素就是 A 矩阵中所有逻辑运算为真的元素 + +% 字符串 +a = 'MyString' +length(a) % ans = 8 +a(2) % ans = y +[a,a] % ans = MyStringMyString +b = '字符串' % MATLAB目前已经可以支持包括中文在内的多种文字 +length(b) % ans = 3 +b(2) % ans = 符 +[b,b] % ans = 字符串字符串 + + +% 元组(cell 数组) +a = {'one', 'two', 'three'} +a(1) % ans = 'one' - 返回一个元组 +char(a(1)) % ans = one - 返回一个字符串 + + +% 结构体 +A.b = {'one','two'}; +A.c = [1 2]; +A.d.e = false; + + +% 向量 +x = [4 32 53 7 1] +x(2) % ans = 32,MATLAB中向量的下标索引从1开始,不是0 +x(2:3) % ans = 32 53 +x(2:end) % ans = 32 53 7 1 + +x = [4; 32; 53; 7; 1] % 列向量 + +x = [1:10] % x = 1 2 3 4 5 6 7 8 9 10 + + +% 矩阵 +A = [1 2 3; 4 5 6; 7 8 9] +% 以分号分隔不同的行,以空格或逗号分隔同一行中的不同元素 +% A = + +% 1 2 3 +% 4 5 6 +% 7 8 9 + +A(2,3) % ans = 6,A(row, column) +A(6) % ans = 8 +% (隐式地将 A 的三列首尾相接组成一个列向量,然后取其下标为 6 的元素) + + +A(2,3) = 42 % 将第 2 行第 3 列的元素设为 42 +% A = + +% 1 2 3 +% 4 5 42 +% 7 8 9 + +A(2:3,2:3) % 取原矩阵中的一块作为新矩阵 +%ans = + +% 5 42 +% 8 9 + +A(:,1) % 第 1 列的所有元素 +%ans = + +% 1 +% 4 +% 7 + +A(1,:) % 第 1 行的所有元素 +%ans = + +% 1 2 3 + +[A ; A] % 将两个矩阵上下相接构成新矩阵 +%ans = + +% 1 2 3 +% 4 5 42 +% 7 8 9 +% 1 2 3 +% 4 5 42 +% 7 8 9 + +% 等价于 +vertcat(A, A); + + +[A , A] % 将两个矩阵左右相接构成新矩阵 + +%ans = + +% 1 2 3 1 2 3 +% 4 5 42 4 5 42 +% 7 8 9 7 8 9 + +% 等价于 +horzcat(A, A); + + +A(:, [3 1 2]) % 重新排布原矩阵的各列 +%ans = + +% 3 1 2 +% 42 4 5 +% 9 7 8 + +size(A) % 返回矩阵的行数和列数,ans = 3 3 + +A(1, :) =[] % 删除矩阵的第 1 行 +A(:, 1) =[] % 删除矩阵的第 1 列 + +transpose(A) % 矩阵转置,等价于 A' +ctranspose(A) % 矩阵的共轭转置(对矩阵中的每个元素取共轭复数) + + +% 元素运算 vs. 矩阵运算 +% 单独运算符就是对矩阵整体进行矩阵运算 +% 在运算符加上英文句点就是对矩阵中的元素进行元素计算 +% 示例如下: +A * B % 矩阵乘法,要求 A 的列数等于 B 的行数 +A .* B % 元素乘法,要求 A 和 B 形状一致(A 的行数等于 B 的行数, A 的列数等于 B 的列数) +% 元素乘法的结果是与 A 和 B 形状一致的矩阵,其每个元素等于 A 对应位置的元素乘 B 对应位置的元素 + +% 以下函数中,函数名以 m 结尾的执行矩阵运算,其余执行元素运算: +exp(A) % 对矩阵中每个元素做指数运算 +expm(A) % 对矩阵整体做指数运算 +sqrt(A) % 对矩阵中每个元素做开方运算 +sqrtm(A) % 对矩阵整体做开放运算(即试图求出一个矩阵,该矩阵与自身的乘积等于 A 矩阵) + + +% 绘图 +x = 0:.10:2*pi; % 生成一向量,其元素从 0 开始,以 0.1 的间隔一直递增到 2*pi(pi 就是圆周率) +y = sin(x); +plot(x,y) +xlabel('x axis') +ylabel('y axis') +title('Plot of y = sin(x)') +axis([0 2*pi -1 1]) % x 轴范围是从 0 到 2*pi,y 轴范围是从 -1 到 1 + +plot(x,y1,'-',x,y2,'--',x,y3,':') % 在同一张图中绘制多条曲线 +legend('Line 1 label', 'Line 2 label') % 为图片加注图例 +% 图例数量应当小于或等于实际绘制的曲线数目,从 plot 绘制的第一条曲线开始对应 + +% 在同一张图上绘制多条曲线的另一种方法: +% 使用 hold on,令系统保留前次绘图结果并在其上直接叠加新的曲线, +% 如果没有 hold on,则每个 plot 都会首先清除之前的绘图结果再进行绘制。 +% 在 hold on 和 hold off 中可以放置任意多的 plot 指令, +% 它们和 hold on 前最后一个 plot 指令的结果都将显示在同一张图中。 +plot(x, y1) +hold on +plot(x, y2) +plot(x, y3) +plot(x, y4) +hold off + +loglog(x, y) % 对数—对数绘图 +semilogx(x, y) % 半对数(x 轴对数)绘图 +semilogy(x, y) % 半对数(y 轴对数)绘图 + +fplot (@(x) x^2, [2,5]) % 绘制函数 x^2 在 [2, 5] 区间的曲线 + +grid on % 在绘制的图中显示网格,使用 grid off 可取消网格显示 +axis square % 将当前坐标系设定为正方形(保证在图形显示上各轴等长) +axis equal % 将当前坐标系设定为相等(保证在实际数值上各轴等长) + +scatter(x, y); % 散点图 +hist(x); % 直方图 + +z = sin(x); +plot3(x,y,z); % 绘制三维曲线 + +pcolor(A) % 伪彩色图(热图) +contour(A) % 等高线图 +mesh(A) % 网格曲面图 + +h = figure % 创建新的图片对象并返回其句柄 h +figure(h) % 将句柄 h 对应的图片作为当前图片 +close(h) % 关闭句柄 h 对应的图片 +close all % 关闭 MATLAB 中所用打开的图片 +close % 关闭当前图片 + +shg % 显示图形窗口 +clf clear % 清除图形窗口中的图像,并重置图像属性 + +% 图像属性可以通过图像句柄进行设定 +% 在创建图像时可以保存图像句柄以便于设置 +% 也可以用 gcf 函数返回当前图像的句柄 +h = plot(x, y); % 在创建图像时显式地保存图像句柄 +set(h, 'Color', 'r') +% 颜色代码:'y' 黄色,'m' 洋红色,'c' 青色,'r' 红色,'g' 绿色,'b' 蓝色,'w' 白色,'k' 黑色 +set(h, 'Color', [0.5, 0.5, 0.4]) +% 也可以使用 RGB 值指定颜色 +set(h, 'LineStyle', '--') +% 线型代码:'--' 实线,'---' 虚线,':' 点线,'-.' 点划线,'none' 不划线 +get(h, 'LineStyle') +% 获取当前句柄的线型 + + +% 用 gca 函数返回当前图像的坐标轴句柄 +set(gca, 'XDir', 'reverse'); % 令 x 轴反向 + +% 用 subplot 指令创建平铺排列的多张子图 +subplot(2,3,1); % 选择 2 x 3 排列的子图中的第 1 张图 +plot(x1); title('First Plot') % 在选中的图中绘图 +subplot(2,3,2); % 选择 2 x 3 排列的子图中的第 2 张图 +plot(x2); title('Second Plot') % 在选中的图中绘图 + + +% 要调用函数或脚本,必须保证它们在你的当前工作目录中 +path % 显示当前工作目录 +addpath /path/to/dir % 将指定路径加入到当前工作目录中 +rmpath /path/to/dir % 将指定路径从当前工作目录中删除 +cd /path/to/move/into % 以制定路径作为当前工作目录 + + +% 变量可保存到 .mat 格式的本地文件 +save('myFileName.mat') % 保存当前工作空间中的所有变量 +load('myFileName.mat') % 将指定文件中的变量载入到当前工作空间 + + +% .m 脚本文件 +% 脚本文件是一个包含多条 MATLAB 指令的外部文件,以 .m 为后缀名 +% 使用脚本文件可以避免在命令窗口中重复输入冗长的指令 + + +% .m 函数文件 +% 与脚本文件类似,同样以 .m 作为后缀名 +% 但函数文件可以接受用户输入的参数并返回运算结果 +% 并且函数拥有自己的工作空间(变量域),不必担心变量名称冲突 +% 函数文件的名称应当与其所定义的函数的名称一致(比如下面例子中函数文件就应命名为 double_input.m) +% 使用 'help double_input.m' 可返回函数定义中第一行注释信息 +function output = double_input(x) + % double_input(x) 返回 x 的 2 倍 + output = 2*x; +end +double_input(6) % ans = 12 + + +% 同样还可以定义子函数和内嵌函数 +% 子函数与主函数放在同一个函数文件中,且只能被这个主函数调用 +% 内嵌函数放在另一个函数体内,可以直接访问被嵌套函数的各个变量 + + +% 使用匿名函数可以不必创建 .m 函数文件 +% 匿名函数适用于快速定义某函数以便传递给另一指令或函数(如绘图、积分、求根、求极值等) +% 下面示例的匿名函数返回输入参数的平方根,可以使用句柄 sqr 进行调用: +sqr = @(x) x.^2; +sqr(10) % ans = 100 +doc function_handle % find out more + + +% 接受用户输入 +a = input('Enter the value: ') + + +% 从文件中读取数据 +fopen(filename) +% 类似函数还有 xlsread(excel 文件)、importdata(CSV 文件)、imread(图像文件) + + +% 输出 +disp(a) % 在命令窗口中打印变量 a 的值 +disp('Hello World') % 在命令窗口中打印字符串 +fprintf % 按照指定格式在命令窗口中打印内容 + +% 条件语句(if 和 elseif 语句中的括号并非必需,但推荐加括号避免混淆) +if (a > 15) + disp('Greater than 15') +elseif (a == 23) + disp('a is 23') +else + disp('neither condition met') +end + +% 循环语句 +% 注意:对向量或矩阵使用循环语句进行元素遍历的效率很低!! +% 注意:只要有可能,就尽量使用向量或矩阵的整体运算取代逐元素循环遍历!! +% MATLAB 在开发时对向量和矩阵运算做了专门优化,做向量和矩阵整体运算的效率高于循环语句 +for k = 1:5 + disp(k) +end + +k = 0; +while (k < 5) + k = k + 1; +end + + +% 程序运行计时:'tic' 是计时开始,'toc' 是计时结束并打印结果 +tic +A = rand(1000); +A*A*A*A*A*A*A; +toc + + +% 链接 MySQL 数据库 +dbname = 'database_name'; +username = 'root'; +password = 'root'; +driver = 'com.mysql.jdbc.Driver'; +dburl = ['jdbc:mysql://localhost:8889/' dbname]; +javaclasspath('mysql-connector-java-5.1.xx-bin.jar'); % 此处 xx 代表具体版本号 +% 这里的 mysql-connector-java-5.1.xx-bin.jar 可从 http://dev.mysql.com/downloads/connector/j/ 下载 +conn = database(dbname, username, password, driver, dburl); +sql = ['SELECT * from table_name where id = 22'] % SQL 语句 +a = fetch(conn, sql) % a 即包含所需数据 + + +% 常用数学函数 +sin(x) +cos(x) +tan(x) +asin(x) +acos(x) +atan(x) +exp(x) +sqrt(x) +log(x) +log10(x) +abs(x) +min(x) +max(x) +ceil(x) +floor(x) +round(x) +rem(x) +rand % 均匀分布的伪随机浮点数 +randi % 均匀分布的伪随机整数 +randn % 正态分布的伪随机浮点数 + +% 常用常数 +pi +NaN +inf + +% 求解矩阵方程(如果方程无解,则返回最小二乘近似解) +% \ 操作符等价于 mldivide 函数,/ 操作符等价于 mrdivide 函数 +x=A\b % 求解 Ax=b,比先求逆再左乘 inv(A)*b 更加高效、准确 +x=b/A % 求解 xA=b + +inv(A) % 逆矩阵 +pinv(A) % 伪逆矩阵 + + +% 常用矩阵函数 +zeros(m, n) % m x n 阶矩阵,元素全为 0 +ones(m, n) % m x n 阶矩阵,元素全为 1 +diag(A) % 返回矩阵 A 的对角线元素 +diag(x) % 构造一个对角阵,对角线元素就是向量 x 的各元素 +eye(m, n) % m x n 阶单位矩阵 +linspace(x1, x2, n) % 返回介于 x1 和 x2 之间的 n 个等距节点 +inv(A) % 矩阵 A 的逆矩阵 +det(A) % 矩阵 A 的行列式 +eig(A) % 矩阵 A 的特征值和特征向量 +trace(A) % 矩阵 A 的迹(即对角线元素之和),等价于 sum(diag(A)) +isempty(A) % 测试 A 是否为空 +all(A) % 测试 A 中所有元素是否都非 0 或都为真(逻辑值) +any(A) % 测试 A 中是否有元素非 0 或为真(逻辑值) +isequal(A, B) % 测试 A 和 B是否相等 +numel(A) % 矩阵 A 的元素个数 +triu(x) % 返回 x 的上三角这部分 +tril(x) % 返回 x 的下三角这部分 +cross(A, B) % 返回 A 和 B 的叉积(矢量积、外积) +dot(A, B) % 返回 A 和 B 的点积(数量积、内积),要求 A 和 B 必须等长 +transpose(A) % A 的转置,等价于 A' +fliplr(A) % 将一个矩阵左右翻转 +flipud(A) % 将一个矩阵上下翻转 + +% 矩阵分解 +[L, U, P] = lu(A) % LU 分解:PA = LU,L 是下三角阵,U 是上三角阵,P 是置换阵 +[P, D] = eig(A) % 特征值分解:AP = PD,D 是由特征值构成的对角阵,P 的各列就是对应的特征向量 +[U, S, V] = svd(X) % 奇异值分解:XV = US,U 和 V 是酉矩阵,S 是由奇异值构成的半正定实数对角阵 + +% 常用向量函数 +max % 最大值 +min % 最小值 +length % 元素个数 +sort % 按升序排列 +sum % 各元素之和 +prod % 各元素之积 +mode % 众数 +median % 中位数 +mean % 平均值 +std % 标准差 +perms(x) % x 元素的全排列 + +``` + +## 相关资料 + +* 官方网页:[http://http://www.mathworks.com/products/matlab/](http://www.mathworks.com/products/matlab/) +* 官方论坛:[http://www.mathworks.com/matlabcentral/answers/](http://www.mathworks.com/matlabcentral/answers/) -- cgit v1.2.3 From 40c38c125b94430b518d7e402d595694149b7c53 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Sun, 18 Jan 2015 13:07:31 -0700 Subject: [Java/cn] Fix inc/dec operator explanation --- zh-cn/java-cn.html.markdown | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index f7d319e6..f08d3507 100644 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -124,7 +124,7 @@ public class LearnJava { // HashMaps /////////////////////////////////////// - // 操作符 + // 操作符 /////////////////////////////////////// System.out.println("\n->Operators"); @@ -161,10 +161,13 @@ public class LearnJava { // 自增 int i = 0; System.out.println("\n->Inc/Dec-rementation"); - System.out.println(i++); //i = 1 后自增 - System.out.println(++i); //i = 2 前自增 - System.out.println(i--); //i = 1 后自减 - System.out.println(--i); //i = 0 前自减 + // ++ 和 -- 操作符使变量加或减1。放在变量前面或者后面的区别是整个表达 + // 式的返回值。操作符在前面时,先加减,后取值。操作符在后面时,先取值 + // 后加减。 + System.out.println(i++); // 后自增 i = 1, 输出0 + System.out.println(++i); // 前自增 i = 2, 输出2 + System.out.println(i--); // 后自减 i = 1, 输出2 + System.out.println(--i); // 前自减 i = 0, 输出0 /////////////////////////////////////// // 控制结构 @@ -192,7 +195,7 @@ public class LearnJava { } System.out.println("fooWhile Value: " + fooWhile); - // Do While循环 + // Do While循环 int fooDoWhile = 0; do { -- cgit v1.2.3 From f74fd2657a6233702a46926ec79d87e46b4fa65f Mon Sep 17 00:00:00 2001 From: TheDmitry Date: Wed, 28 Jan 2015 11:24:31 +0300 Subject: [swift/en,cn,ru]Updating the getting started guide weblink. --- zh-cn/swift-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index b9696c72..35f73dee 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -10,7 +10,7 @@ lang: zh-cn Swift 是Apple 开发的用于iOS 和OS X 开发的编程语言。Swift 于2014年Apple WWDC (全球开发者大会)中被引入,用以与Objective-C 共存,同时对错误代码更具弹性。Swift 由Xcode 6 beta 中包含的LLVM编译器编译。 -参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/LandingPage/index.html) ——一个完整的Swift 教程 +参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) ——一个完整的Swift 教程 ```swift // -- cgit v1.2.3 From 433ad37e75858dd9bdab26cbc5eeec87a1b79a61 Mon Sep 17 00:00:00 2001 From: AaronJan Date: Sat, 21 Feb 2015 21:35:43 +0800 Subject: fixed typo, little polishing --- zh-cn/javascript-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 7dee9cc4..a00af0c1 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -342,7 +342,7 @@ myObj.meaningOfLife // = 43 // 但是,我们有两种方式可以为新的对象指定原型。 // 第一种方式是 Object.create,这个方法是在最近才被添加到Js中的 -// 也因此并不是所有的JS实现都有这个放啊 +// 也因此并不是所有的JS实现都有这个方法 var myObj = Object.create(myPrototype) myObj.meaningOfLife // = 43 @@ -384,7 +384,7 @@ String.prototype.firstCharacter = function(){ // 这样就可以在老的浏览器中使用新功能了。 // 比如,我们知道Object.create并没有在所有的版本中都实现 -// 但是我们仍然可以通过这个技巧来使用 +// 但是我们仍然可以通过以下兼容代码来实现: if (Object.create === undefined){ // 如果存在则不覆盖 Object.create = function(proto){ // 用正确的原型来创建一个临时构造函数 -- cgit v1.2.3 From 532424ee35b8fbb25dfbd331fb515b5ac9f346d3 Mon Sep 17 00:00:00 2001 From: Joey Huang Date: Sat, 28 Feb 2015 19:29:09 +0800 Subject: make full translation of swift language --- zh-cn/swift-cn.html.markdown | 583 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 471 insertions(+), 112 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index 35f73dee..ee48d635 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -5,223 +5,582 @@ contributors: - ["Grant Timmerman", "http://github.com/grant"] translators: - ["Xavier Yao", "http://github.com/xavieryao"] + - ["Joey Huang", "http://github.com/kamidox"] lang: zh-cn --- Swift 是Apple 开发的用于iOS 和OS X 开发的编程语言。Swift 于2014年Apple WWDC (全球开发者大会)中被引入,用以与Objective-C 共存,同时对错误代码更具弹性。Swift 由Xcode 6 beta 中包含的LLVM编译器编译。 -参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) ——一个完整的Swift 教程 +Swift 的官方语言教程 [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) 可以从 iBooks 免费下载. + +亦可参阅:Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) ——一个完整的Swift 教程 ```swift -// -// 基础 +// 导入外部模块 +import UIKit + +// +// MARK: 基础 // +// XCODE 支持给注释代码作标记,这些标记会列在 XCODE 的跳转栏里,支持的标记为 +// MARK: 普通标记 +// TODO: TODO 标记 +// FIXME: FIXME 票房 + println("Hello, world") + +// 变量 (var) 的值设置后可以随意改变 +// 常量 (let) 的值设置后不能改变 var myVariable = 42 +let øπΩ = "value" // 可以支持 unicode 变量名 let myConstant = 3.1415926 -let explicitDouble: Double = 70 -let label = "some text " + String(myVariable) // Casting -let piText = "Pi = \(myConstant)" // String interpolation -var optionalString: String? = "optional" // Can be nil -optionalString = nil +let explicitDouble: Double = 70 // 明确指定变量类型为 Double ,否则编译器将自动推断变量类型 +let weak = "keyword"; let override = "another keyword" // 语句之间可以用分号隔开,语句未尾不需要分号 +let intValue = 0007 // 7 +let largeIntValue = 77_000 // 77000 +let label = "some text " + String(myVariable) // 类型转换 +let piText = "Pi = \(π), Pi 2 = \(π * 2)" // 格式化字符串 + +// 条件编译 +// 使用 -D 定义编译开关 +#if false + println("Not printed") + let buildValue = 3 +#else + let buildValue = 7 +#endif +println("Build value: \(buildValue)") // Build value: 7 + +/* + Optionals 是 Swift 的新特性,它允许你存储两种状态的值给 Optional 变量:有效值或 None + + Swift 要求所有的 Optinal 属性都必须有明确的值,如果为空,则必须明确设定为 nil + + Optional 是个枚举类型 +*/ +var someOptionalString: String? = "optional" // 可以是 nil +// 下面的语句和上面完全等价,上面的写法更推荐,因为它更简洁,它是 Swift 提供的语法糖 +var someOptionalString2: Optional = "optional" + +if someOptionalString != nil { + // 变量不为空 + if someOptionalString!.hasPrefix("opt") { + println("has the prefix") + } + + let empty = someOptionalString?.isEmpty +} +someOptionalString = nil + +// 显式解包 optional 变量 +var unwrappedString: String! = "Value is expected." +// 下面语句和上面完全等价,! 是个前缀运算符,这也是个语法糖 +var unwrappedString2: ImplicitlyUnwrappedOptional = "Value is expected." + +if let someOptionalStringConstant = someOptionalString { + // 由于变量 someOptinalString 有值,不为空,所以 if 条件为真 + if !someOptionalStringConstant.hasPrefix("ok") { + // does not have the prefix + } +} + +// Swift 支持可保存任何数据类型的变量 +// AnyObject == id +// 和 Objective-C `id` 不一样, AnyObject 可以保存任何类型的亦是(Class, Int, struct, 等) +var anyObjectVar: AnyObject = 7 +anyObjectVar = "Changed value to a string, not good practice, but possible." + +/* + 这里是注释 + + /* + 支持嵌套的注释 + */ +*/ // -// 数组与字典(关联数组) +// Mark: 数组与字典(关联数组) // -// 数组 +/* + Array 和 Dictionary 是结构体,不是类,即他们作为函数参数时,是用值传递而不是指针传递. 一样可以用 `var` 和 `let` 来定义变量和常量。 +*/ + +// Array var shoppingList = ["catfish", "water", "lemons"] shoppingList[1] = "bottle of water" -let emptyArray = String[]() +let emptyArray = [String]() // 使用 let 定义常量,此时 emptyArray 数组不能添加或删除内容 +let emptyArray2 = Array() // 与上一语句等价,上一语句更常用 +var emptyMutableArray = [String]() // 使用 var 定义变量,可以向 emptyMutableArray 添加数组元素 // 字典 var occupations = [ - "Malcolm": "Captain", - "kaylee": "Mechanic" + "Malcolm": "Captain", + "kaylee": "Mechanic" ] -occupations["Jayne"] = "Public Relations" -let emptyDictionary = Dictionary() +occupations["Jayne"] = "Public Relations" // 个性字典,如果 key 不存在,自动添加一个字典元素 +let emptyDictionary = [String: Float]() // 使用 let 定义字典常量,字典常量不能个性里面的值 +let emptyDictionary2 = Dictionary() // 与上一语句类型,上一语句更常用 +var emptyMutableDictionary = [String: Float]() // 使用 var 定义字典变量 // -// 控制流 +// MARK: 控制流 // -// 用于数组的for 循环 +// 数组的 for 循环 let myArray = [1, 1, 2, 3, 5] for value in myArray { - if value == 1 { - println("One!") - } else { - println("Not one!") - } + if value == 1 { + println("One!") + } else { + println("Not one!") + } } -// 用于字典的for 循环 +// 字典的 for 循环 +var dict = ["one": 1, "two": 2] for (key, value) in dict { - println("\(key): \(value)") + println("\(key): \(value)") } -// 用于区间的for 循环 -for i in -1...1 { // [-1, 0, 1] - println(i) +// 区间的 loop 循环:其中 `...` 表示闭环区间,即[-1, 3];`..<` 表示半开闭区间,即[-1,3) +for i in -1...shoppingList.count { + println(i) } -// 使用 .. 表示的区间不包含最后一个元素 [-1,0,1) +shoppingList[1...2] = ["steak", "peacons"] +// 可以使用 `..<` 来去掉最后一个元素 // while 循环 var i = 1 while i < 1000 { - i *= 2 + i *= 2 } // do-while 循环 do { - println("hello") + println("hello") } while 1 == 2 -// Switch +// Switch 语句 +// Swift 里的 Switch 语句功能异常强大,结合枚举类型,可以实现非常简洁的代码,可以把 switch 语句想象成 `if` 的语法糖 +// 它支持字符串,类实例或原生数据类型 (Int, Double, etc) let vegetable = "red pepper" switch vegetable { case "celery": - let vegetableComment = "Add some raisins and make ants on a log." + let vegetableComment = "Add some raisins and make ants on a log." case "cucumber", "watercress": - let vegetableComment = "That would make a good tea sandwich." -case let x where x.hasSuffix("pepper"): - let vegetableComment = "Is it a spicy \(x)?" -default: // 必须 (为了覆盖所有可能的输入) - let vegetableComment = "Everything tastes good in soup." + let vegetableComment = "That would make a good tea sandwich." +case let localScopeValue where localScopeValue.hasSuffix("pepper"): + let vegetableComment = "Is it a spicy \(localScopeValue)?" +default: // 在 Swift 里,switch 语句的 case 必须处理所有可能的情况,如果 case 无法全部处理,则必须包含 default语句 + let vegetableComment = "Everything tastes good in soup." } // -// 函数 +// MARK: 函数 // -// 函数是一等类型,这意味着可以在函数中构建函数 -// 并且可以被传递 +// 函数是一个 first-class 类型,他们可以嵌套,可以作为函数参数传递 -// 函数 +// 函数文档可使用 reStructedText 格式直接写在函数的头部 +/** + A greet operation + + - A bullet in docs + - Another bullet in the docs + + :param: name A name + :param: day A day + :returns: A string containing the name and day value. +*/ func greet(name: String, day: String) -> String { - return "Hello \(name), today is \(day)." + return "Hello \(name), today is \(day)." } greet("Bob", "Tuesday") -// 使用多元数组返回多返回值的函数 -func getGasPrices() -> (Double, Double, Double) { - return (3.59, 3.69, 3.79) +// 函数参数前带 `#` 号表示外部参数包和内部参数名使用同一个。第二个参数表示外部参数名使用 `externalParamName` ,内部参数名使用 `localParamName` +func greet2(#requiredName: String, externalParamName localParamName: String) -> String { + return "Hello \(requiredName), the day is \(localParamName)" } +greet2(requiredName:"John", externalParamName: "Sunday") // 调用时,使用命名参数来指定参数的值 -// 不定参数 -func setup(numbers: Int...) {} +// 函数可以通过元组 (tuple) 返回多个值 +func getGasPrices() -> (Double, Double, Double) { + return (3.59, 3.69, 3.79) +} +let pricesTuple = getGasPrices() +let price = pricesTuple.2 // 3.79 +// 通过下划线 (_) 来忽略不关心的值 +let (_, price1, _) = pricesTuple // price1 == 3.69 +println(price1 == pricesTuple.1) // true +println("Gas price: \(price)") + +// 可变参数 +func setup(numbers: Int...) { + // 可变参数是个数组 + let number = numbers[0] + let argCount = numbers.count +} -// 传递、返回函数 +// 函数作为参数传递以及函数作为返回值返回 func makeIncrementer() -> (Int -> Int) { - func addOne(number: Int) -> Int { - return 1 + number - } - return addOne + func addOne(number: Int) -> Int { + return 1 + number + } + return addOne } var increment = makeIncrementer() increment(7) +// 强制进行指针传递 (引用传递),使用 `inout` 关键字修饰函数参数 +func swapTwoInts(inout a: Int, inout b: Int) { + let tempA = a + a = b + b = tempA +} +var someIntA = 7 +var someIntB = 3 +swapTwoInts(&someIntA, &someIntB) +println(someIntB) // 7 + // -// 闭包 +// MARK: 闭包 // +var numbers = [1, 2, 6] -// 函数是特殊的闭包({}) +// 函数是闭包的一个特例 -// 闭包示例. -// `->` 分隔参数和返回类型 -// `in` 分隔闭包头和闭包体 +// 闭包实例 +// `->` 分隔了闭包的参数和返回值 +// `in` 分隔了闭包头 (包括参数及返回值) 和闭包体 +// 下面例子中,`map` 的参数是一个函数类型,它的功能是把数组里的元素作为参数,逐个调用 `map` 参数传递进来的函数。 numbers.map({ - (number: Int) -> Int in - let result = 3 * number - return result - }) + (number: Int) -> Int in + let result = 3 * number + return result +}) -// 当类型已知时,可以这样做: -var numbers = [1, 2, 6] +// 当闭包的参数类型和返回值都是己知的情况下,且只有一个语句作为其返回值时,我们可以简化闭包的写法 numbers = numbers.map({ number in 3 * number }) +// 我们也可以使用 $0, $1 ... 来指代第1个,第2个 ... 参数 +// numbers = numbers.map({ $0 * 3 }) + +print(numbers) // [3, 6, 18] + +// 简洁的闭包 +numbers = sorted(numbers) { $0 > $1 } + +print(numbers) // [18, 6, 3] + +// 超级简洁的闭包,因为 `<` 是个操作符函数 +numbers = sorted(numbers, < ) + print(numbers) // [3, 6, 18] // -// 类 +// MARK: 结构体 // -// 类的全部方法和属性都是public 的 -// 如果你在一个数据结构中只需储存数据, -// 应使用 `struct` +// 结构体和类非常类似,可以有属性和方法 -// 集成自`Shape` 类的简单的类`Square -class Rect: Shape { - var sideLength: Int = 1 - - // Custom getter and setter property - var perimeter: Int { - get { - return 4 * sideLength - } - set { - sideLength = newValue / 4 +struct NamesTable { + let names = [String]() + + // 自定义下标运算符 + subscript(index: Int) -> String { + return names[index] } - } +} + +// 结构体有一个自动生成的隐含的命名构造函数 +let namesTable = NamesTable(names: ["Me", "Them"]) +let name = namesTable[1] +println("Name is \(name)") // Name is Them + +// +// MARK: 类 +// - init(sideLength: Int) { - super.init() - self.sideLength = sideLength - } +// 类和结构体的有三个访问控制级别,他们分别是 internal (默认), public, private +// internal: 模块内部可以访问 +// public: 其他模块可以访问 +// private: 只有定义这个类或结构体的源文件才能访问 - func shrink() { - if sideLength > 0 { - --sideLength +public class Shape { + public func getArea() -> Int { + return 0; + } +} + +// 类的所有方法和属性都是 public 的 +// 如果你只是需要把数据保存在一个结构化的实例里面,你应该用结构体 + +internal class Rect: Shape { + // 值属性 (Stored properties) + var sideLength: Int = 1 + + // 计算属性 (Computed properties) + private var perimeter: Int { + get { + return 4 * sideLength + } + set { + // `newValue` 是个隐含的变量,它代表设置进来的值 + sideLength = newValue / 4 + } + } + + // 延时加载的属性,只有这个属性第一次被引用时才进行加载,而不是定义时就加载 + // subShape值为 nil ,走到 suShape 第一次被引用时才初始化 + lazy var subShape = Rect(sideLength: 4) + + // 监控属性值的变化。当我们需要在属性值改变时做一些事情 + // 可以使用 `willSet` 和 `didSet` 来设置监控函数 + // `willSet`: 值改变之前被调用 + // `didSet`: 值改变之后被调用 + var identifier: String = "defaultID" { + // `willSet` 的参数是即将设置的新值,参数名可以指定,如果没有指定,就是 `newValue` + willSet(someIdentifier) { + println(someIdentifier) + } + // `didSet` 的参数是已经被覆盖掉的旧的值,参数名也可以指定,如果没有指定,就是 `oldValue` + didSet { + println(oldValue) + } + } + + // 命名构造函数 (designated inits),它必须初始化所有的成员变量, + // 然后调用父类的全名构造函数继续初始化父类的所有变量。 + init(sideLength: Int) { + self.sideLength = sideLength + // 必须显式地在构造函数最后调用父类的构造函数 super.init + super.init() + } + + func shrink() { + if sideLength > 0 { + --sideLength + } } - } + + // 函数重载 + override func getArea() -> Int { + return sideLength * sideLength + } +} - override func getArea() -> Int { - return sideLength * sideLength - } +// 类 `Square` 从 `Rect` 继承 +class Square: Rect { + // 便捷构造函数 (convenience inits) 是调用自己的命名构造函数 (designated inits) 的构造函数 + // Square 自动继承了父类的命名构造函数 + convenience init() { + self.init(sideLength: 5) + } + // 关于构造函数的继承,有以下几个规则: + // 1. 如果你没有实现任何命名构造函数,那么你就继承了父类的所有命名构造函数 + // 2. 如果你重载了父类的所有命名构造函数,那么你就自动继承了所有的父类快捷构造函数 + // 3. 如果你没有实现任何构造函数,那么你继承了父类的所有构造函数,包括命名构造函数和便捷构造函数 } -var mySquare = new Square(sideLength: 5) -print(mySquare.getArea()) // 25 + +var mySquare = Square() +println(mySquare.getArea()) // 25 mySquare.shrink() -print(mySquare.sideLength) // 4 +println(mySquare.sideLength) // 4 + +// 类型转换 +let aShape = mySquare as Shape + +// 使用三个等号来比较是不是同一个实例 +if mySquare === aShape { + println("Yep, it's mySquare") +} + +class Circle: Shape { + var radius: Int + override func getArea() -> Int { + return 3 * radius * radius + } + + // optional 构造函数,可能会返回 nil + init?(radius: Int) { + self.radius = radius + super.init() + + if radius <= 0 { + return nil + } + } +} -// 如果你不需要自定义getter 和setter, -// 但仍希望在获取或设置一个属性之前或之后运行 -// 一些代码,你可以使用`willSet` 和 `didSet` +// 根据 Swift 类型推断,myCircle是 Optional 类型的变量 +var myCircle = Circle(radius: 1) +println(myCircle?.getArea()) // Optional(3) +println(myCircle!.getArea()) // 3 +var myEmptyCircle = Circle(radius: -1) +println(myEmptyCircle?.getArea()) // "nil" +if let circle = myEmptyCircle { + // 此语句不会输出,因为 myEmptyCircle 变量值为 nil + println("circle is not nil") +} // -// 枚举类型 +// MARK: 枚举 // -// 枚举类型可以是某种指定的类型,抑或自成一种类型 -// 像类一样,枚举类型可以包含方法 +// 枚举可以像类一样,拥有方法 enum Suit { - case Spades, Hearts, Diamonds, Clubs - func getIcon() -> String { - switch self { - case .Spades: return "♤" - case .Hearts: return "♡" - case .Diamonds: return "♢" - case .Clubs: return "♧" + case Spades, Hearts, Diamonds, Clubs + func getIcon() -> String { + switch self { + case .Spades: return "♤" + case .Hearts: return "♡" + case .Diamonds: return "♢" + case .Clubs: return "♧" + } } - } } +// 当变量类型明确指定为某个枚举类型时,赋值时可以省略枚举类型 +var suitValue: Suit = .Hearts + +// 非整型的枚举类型需要在定义时赋值 +enum BookName: String { + case John = "John" + case Luke = "Luke" +} +println("Name: \(BookName.John.rawValue)") + +// 与特定数据类型关联的枚举 +enum Furniture { + // 和 Int 型数据关联的枚举记录 + case Desk(height: Int) + // 和 String, Int 关联的枚举记录 + case Chair(brand: String, height: Int) + + func description() -> String { + switch self { + case .Desk(let height): + return "Desk with \(height) cm" + case .Chair(let brand, let height): + return "Chair of \(brand) with \(height) cm" + } + } +} + +var desk: Furniture = .Desk(height: 80) +println(desk.description()) // "Desk with 80 cm" +var chair = Furniture.Chair(brand: "Foo", height: 40) +println(chair.description()) // "Chair of Foo with 40 cm" + // -// 其它 +// MARK: 协议 +// 与 Java 的 interface 类似 // -// `协议(protocol)`: 与Java 的接口(Interface) 类似. -// `扩展(extension)`: 为现有类型添加额外特性 -// 泛型: 与Java 相似。使用`where` 关键字指定 -// 泛型的要求. +// 协议可以让遵循同一协议的类型实例拥有相同的属性,方法,类方法,操作符或下标运算符 +// 定义一个协议,这个协议饮食 enabled 计算属性且包含 buildShape 方法 +protocol ShapeGenerator { + var enabled: Bool { get set } + func buildShape() -> Shape +} + +// 协议声明时可以添加 @objc 前缀,添加 @objc 前缀后, +// 可以使用 is, as, as? 等来检查协议兼容性 +// 需要注意,添加 @objc 前缀后,协议就只能被类来实现, +// 结构体和枚举不能实现加了 @objc 的前缀 +// 只有添加了 @objc 前缀的协议才能声明 optional 方法 +// 一个类实现一个带 optional 方法的协议时,可以实现或不实现这个方法 +// optional 方法可以使用 optional 规则来调用 +@objc protocol TransformShape { + optional func reshaped() + optional func canReshape() -> Bool +} + +class MyShape: Rect { + var delegate: TransformShape? + + func grow() { + sideLength += 2 + + // 在 optional 属性,方法或下标运算符后面加一个问号,可以优雅地忽略 nil 值,返回 nil。 + // 这样就不会引起运行时错误 (runtime error) + if let allow = self.delegate?.canReshape?() { + // test for delegate then for method + self.delegate?.reshaped?() + } + } +} + + +// +// MARK: 其它 +// + +// 扩展: 给一个已经存在的数据类型添加功能 + +// 给 Square 类添加 `Printable` 协议的实现,现在其支持 `Printable` 协议 +extension Square: Printable { + var description: String { + return "Area: \(self.getArea()) - ID: \(self.identifier)" + } +} + +println("Square: \(mySquare)") + +// 也可以给系统内置类型添加功能支持 +extension Int { + var customProperty: String { + return "This is \(self)" + } + + func multiplyBy(num: Int) -> Int { + return num * self + } +} + +println(7.customProperty) // "This is 7" +println(14.multiplyBy(3)) // 42 + +// 泛型: 和 Java 及 C# 的泛型类似,使用 `where` 关键字来限制类型。 +// 如果只有一个类型限制,可以省略 `where` 关键字 +func findIndex(array: [T], valueToFind: T) -> Int? { + for (index, value) in enumerate(array) { + if value == valueToFind { + return index + } + } + return nil +} +let foundAtIndex = findIndex([1, 2, 3, 4], 3) +println(foundAtIndex == 2) // true + +// 自定义运算符: +// 自定义运算符可以以下面的字符打头: +// / = - + * % < > ! & | ^ . ~ +// 甚至是 Unicode 的数学运算符等 +prefix operator !!! {} + +// 定义一个前缀运算符,使矩形的连长放大三位 +prefix func !!! (inout shape: Square) -> Square { + shape.sideLength *= 3 + return shape +} + +// 当前值 +println(mySquare.sideLength) // 4 + +// 使用自定义的 !!! 运算符来把矩形边长放大三位 +!!!mySquare +println(mySquare.sideLength) // 12 ``` + -- cgit v1.2.3 From 4ca7856bc7ca61d4d3ed3ab01d1ff9cb9ab16519 Mon Sep 17 00:00:00 2001 From: Joey Huang Date: Mon, 2 Mar 2015 22:47:02 +0800 Subject: correct typo --- zh-cn/swift-cn.html.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index ee48d635..531b9862 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -34,6 +34,7 @@ println("Hello, world") // 常量 (let) 的值设置后不能改变 var myVariable = 42 let øπΩ = "value" // 可以支持 unicode 变量名 +let π = 3.1415926 let myConstant = 3.1415926 let explicitDouble: Double = 70 // 明确指定变量类型为 Double ,否则编译器将自动推断变量类型 let weak = "keyword"; let override = "another keyword" // 语句之间可以用分号隔开,语句未尾不需要分号 @@ -336,8 +337,8 @@ internal class Rect: Shape { } } - // 延时加载的属性,只有这个属性第一次被引用时才进行加载,而不是定义时就加载 - // subShape值为 nil ,走到 suShape 第一次被引用时才初始化 + // 延时加载的属性,只有这个属性第一次被引用时才进行初始化,而不是定义时就初始化 + // subShape 值为 nil ,直到 subShape 第一次被引用时才初始化为一个 Rect 实例 lazy var subShape = Rect(sideLength: 4) // 监控属性值的变化。当我们需要在属性值改变时做一些事情 @@ -486,8 +487,8 @@ println(chair.description()) // "Chair of Foo with 40 cm" // 与 Java 的 interface 类似 // -// 协议可以让遵循同一协议的类型实例拥有相同的属性,方法,类方法,操作符或下标运算符 -// 定义一个协议,这个协议饮食 enabled 计算属性且包含 buildShape 方法 +// 协议可以让遵循同一协议的类型实例拥有相同的属性,方法,类方法,操作符或下标运算符等 +// 下面代码定义一个协议,这个协议包含一个名为 enabled 的计算属性且包含 buildShape 方法 protocol ShapeGenerator { var enabled: Bool { get set } func buildShape() -> Shape -- cgit v1.2.3 From cf65d3c08475f436dbebcfbfe9ddcace55f467dd Mon Sep 17 00:00:00 2001 From: Joey Huang Date: Mon, 2 Mar 2015 23:28:35 +0800 Subject: correct more typo --- zh-cn/swift-cn.html.markdown | 48 ++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index 531b9862..d5883464 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -9,7 +9,7 @@ translators: lang: zh-cn --- -Swift 是Apple 开发的用于iOS 和OS X 开发的编程语言。Swift 于2014年Apple WWDC (全球开发者大会)中被引入,用以与Objective-C 共存,同时对错误代码更具弹性。Swift 由Xcode 6 beta 中包含的LLVM编译器编译。 +Swift 是 Apple 开发的用于 iOS 和 OS X 开发的编程语言。Swift 于2014年 Apple WWDC (全球开发者大会)中被引入,用以与 Objective-C 共存,同时对错误代码更具弹性。Swift 由 Xcode 6 beta 中包含的 LLVM 编译器编译。 Swift 的官方语言教程 [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) 可以从 iBooks 免费下载. @@ -26,7 +26,7 @@ import UIKit // XCODE 支持给注释代码作标记,这些标记会列在 XCODE 的跳转栏里,支持的标记为 // MARK: 普通标记 // TODO: TODO 标记 -// FIXME: FIXME 票房 +// FIXME: FIXME 标记 println("Hello, world") @@ -61,7 +61,7 @@ println("Build value: \(buildValue)") // Build value: 7 Optional 是个枚举类型 */ var someOptionalString: String? = "optional" // 可以是 nil -// 下面的语句和上面完全等价,上面的写法更推荐,因为它更简洁,它是 Swift 提供的语法糖 +// 下面的语句和上面完全等价,上面的写法更推荐,因为它更简洁,问号 (?) 是 Swift 提供的语法糖 var someOptionalString2: Optional = "optional" if someOptionalString != nil { @@ -76,7 +76,7 @@ someOptionalString = nil // 显式解包 optional 变量 var unwrappedString: String! = "Value is expected." -// 下面语句和上面完全等价,! 是个前缀运算符,这也是个语法糖 +// 下面语句和上面完全等价,感叹号 (!) 是个后缀运算符,这也是个语法糖 var unwrappedString2: ImplicitlyUnwrappedOptional = "Value is expected." if let someOptionalStringConstant = someOptionalString { @@ -88,7 +88,7 @@ if let someOptionalStringConstant = someOptionalString { // Swift 支持可保存任何数据类型的变量 // AnyObject == id -// 和 Objective-C `id` 不一样, AnyObject 可以保存任何类型的亦是(Class, Int, struct, 等) +// 和 Objective-C `id` 不一样, AnyObject 可以保存任何类型的值 (Class, Int, struct, 等) var anyObjectVar: AnyObject = 7 anyObjectVar = "Changed value to a string, not good practice, but possible." @@ -106,7 +106,8 @@ anyObjectVar = "Changed value to a string, not good practice, but possible." // /* - Array 和 Dictionary 是结构体,不是类,即他们作为函数参数时,是用值传递而不是指针传递. 一样可以用 `var` 和 `let` 来定义变量和常量。 + Array 和 Dictionary 是结构体,不是类,他们作为函数参数时,是用值传递而不是指针传递。 + 可以用 `var` 和 `let` 来定义变量和常量。 */ // Array @@ -121,9 +122,9 @@ var occupations = [ "Malcolm": "Captain", "kaylee": "Mechanic" ] -occupations["Jayne"] = "Public Relations" // 个性字典,如果 key 不存在,自动添加一个字典元素 -let emptyDictionary = [String: Float]() // 使用 let 定义字典常量,字典常量不能个性里面的值 -let emptyDictionary2 = Dictionary() // 与上一语句类型,上一语句更常用 +occupations["Jayne"] = "Public Relations" // 修改字典,如果 key 不存在,自动添加一个字典元素 +let emptyDictionary = [String: Float]() // 使用 let 定义字典常量,字典常量不能修改里面的值 +let emptyDictionary2 = Dictionary() // 与上一语句类型等价,上一语句更常用 var emptyMutableDictionary = [String: Float]() // 使用 var 定义字典变量 @@ -203,7 +204,8 @@ func greet(name: String, day: String) -> String { } greet("Bob", "Tuesday") -// 函数参数前带 `#` 号表示外部参数包和内部参数名使用同一个。第二个参数表示外部参数名使用 `externalParamName` ,内部参数名使用 `localParamName` +// 函数参数前带 `#` 表示外部参数名和内部参数名使用同一个名称。 +// 第二个参数表示外部参数名使用 `externalParamName` ,内部参数名使用 `localParamName` func greet2(#requiredName: String, externalParamName localParamName: String) -> String { return "Hello \(requiredName), the day is \(localParamName)" } @@ -227,7 +229,7 @@ func setup(numbers: Int...) { let argCount = numbers.count } -// 函数作为参数传递以及函数作为返回值返回 +// 函数变量以及函数作为返回值返回 func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number @@ -268,13 +270,15 @@ numbers.map({ // 当闭包的参数类型和返回值都是己知的情况下,且只有一个语句作为其返回值时,我们可以简化闭包的写法 numbers = numbers.map({ number in 3 * number }) -// 我们也可以使用 $0, $1 ... 来指代第1个,第2个 ... 参数 +// 我们也可以使用 $0, $1 来指代第 1 个,第 2 个参数,上面的语句最终可简写为如下形式 // numbers = numbers.map({ $0 * 3 }) print(numbers) // [3, 6, 18] // 简洁的闭包 numbers = sorted(numbers) { $0 > $1 } +// 函数的最后一个参数可以放在括号之外,上面的语句是这个语句的简写形式 +// numbers = sorted(numbers, { $0 > $1 }) print(numbers) // [18, 6, 3] @@ -320,7 +324,7 @@ public class Shape { } // 类的所有方法和属性都是 public 的 -// 如果你只是需要把数据保存在一个结构化的实例里面,你应该用结构体 +// 如果你只是需要把数据保存在一个结构化的实例里面,应该用结构体 internal class Rect: Shape { // 值属性 (Stored properties) @@ -332,7 +336,7 @@ internal class Rect: Shape { return 4 * sideLength } set { - // `newValue` 是个隐含的变量,它代表设置进来的值 + // `newValue` 是个隐含的变量,它表示将要设置进来的新值 sideLength = newValue / 4 } } @@ -341,8 +345,8 @@ internal class Rect: Shape { // subShape 值为 nil ,直到 subShape 第一次被引用时才初始化为一个 Rect 实例 lazy var subShape = Rect(sideLength: 4) - // 监控属性值的变化。当我们需要在属性值改变时做一些事情 - // 可以使用 `willSet` 和 `didSet` 来设置监控函数 + // 监控属性值的变化。 + // 当我们需要在属性值改变时做一些事情,可以使用 `willSet` 和 `didSet` 来设置监控函数 // `willSet`: 值改变之前被调用 // `didSet`: 值改变之后被调用 var identifier: String = "defaultID" { @@ -357,7 +361,7 @@ internal class Rect: Shape { } // 命名构造函数 (designated inits),它必须初始化所有的成员变量, - // 然后调用父类的全名构造函数继续初始化父类的所有变量。 + // 然后调用父类的命名构造函数继续初始化父类的所有变量。 init(sideLength: Int) { self.sideLength = sideLength // 必须显式地在构造函数最后调用父类的构造函数 super.init @@ -370,7 +374,7 @@ internal class Rect: Shape { } } - // 函数重载 + // 函数重载使用 override 关键字 override func getArea() -> Int { return sideLength * sideLength } @@ -419,7 +423,7 @@ class Circle: Shape { } } -// 根据 Swift 类型推断,myCircle是 Optional 类型的变量 +// 根据 Swift 类型推断,myCircle 是 Optional 类型的变量 var myCircle = Circle(radius: 1) println(myCircle?.getArea()) // Optional(3) println(myCircle!.getArea()) // 3 @@ -515,7 +519,7 @@ class MyShape: Rect { // 在 optional 属性,方法或下标运算符后面加一个问号,可以优雅地忽略 nil 值,返回 nil。 // 这样就不会引起运行时错误 (runtime error) if let allow = self.delegate?.canReshape?() { - // test for delegate then for method + // 注意语句中的问号 self.delegate?.reshaped?() } } @@ -535,7 +539,7 @@ extension Square: Printable { } } -println("Square: \(mySquare)") +println("Square: \(mySquare)") // Area: 16 - ID: defaultID // 也可以给系统内置类型添加功能支持 extension Int { @@ -570,7 +574,7 @@ println(foundAtIndex == 2) // true // 甚至是 Unicode 的数学运算符等 prefix operator !!! {} -// 定义一个前缀运算符,使矩形的连长放大三位 +// 定义一个前缀运算符,使矩形的边长放大三位 prefix func !!! (inout shape: Square) -> Square { shape.sideLength *= 3 return shape -- cgit v1.2.3 From d05baf5bd02cf6c7270e35ee79964764848d8f1b Mon Sep 17 00:00:00 2001 From: Joey Huang Date: Tue, 3 Mar 2015 01:04:19 +0800 Subject: correct typo --- zh-cn/swift-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index d5883464..d55f1aef 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -574,7 +574,7 @@ println(foundAtIndex == 2) // true // 甚至是 Unicode 的数学运算符等 prefix operator !!! {} -// 定义一个前缀运算符,使矩形的边长放大三位 +// 定义一个前缀运算符,使矩形的边长放大倍 prefix func !!! (inout shape: Square) -> Square { shape.sideLength *= 3 return shape -- cgit v1.2.3 From be4d069c58489afcd09d7b41b8b7cd27a7ef635f Mon Sep 17 00:00:00 2001 From: Joey Huang Date: Tue, 3 Mar 2015 09:26:58 +0800 Subject: correct typo --- zh-cn/swift-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/swift-cn.html.markdown b/zh-cn/swift-cn.html.markdown index d55f1aef..28001e3f 100644 --- a/zh-cn/swift-cn.html.markdown +++ b/zh-cn/swift-cn.html.markdown @@ -574,7 +574,7 @@ println(foundAtIndex == 2) // true // 甚至是 Unicode 的数学运算符等 prefix operator !!! {} -// 定义一个前缀运算符,使矩形的边长放大倍 +// 定义一个前缀运算符,使矩形的边长放大三倍 prefix func !!! (inout shape: Square) -> Square { shape.sideLength *= 3 return shape @@ -583,7 +583,7 @@ prefix func !!! (inout shape: Square) -> Square { // 当前值 println(mySquare.sideLength) // 4 -// 使用自定义的 !!! 运算符来把矩形边长放大三位 +// 使用自定义的 !!! 运算符来把矩形边长放大三倍 !!!mySquare println(mySquare.sideLength) // 12 -- cgit v1.2.3 From 5e0964e2eee068b872fb0d61b5398997e0b76670 Mon Sep 17 00:00:00 2001 From: jasonqu Date: Fri, 6 Mar 2015 17:42:44 +0800 Subject: [javascript/zh] Translation tracking --- zh-cn/javascript-cn.html.markdown | 514 ++++++++++++++++++++++---------------- 1 file changed, 298 insertions(+), 216 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index a00af0c1..cde3fa35 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -5,17 +5,19 @@ name: javascript filename: javascript-zh.js contributors: - ["Adam Brenecki", "http://adam.brenecki.id.au"] + - ["Ariel Krakowski", "http://www.learneroo.com"] translators: - ["Chenbo Li", "http://binarythink.net"] + - ["Guodong Qu", "https://github.com/jasonqu"] lang: zh-cn --- Javascript于1995年由网景公司的Brendan Eich发明。 最初发明的目的是作为一个简单的网站脚本语言,来作为 -复杂网站应用java的补充。但由于javascript和网站结合度很高 -所以javascript逐渐变得比java在前端更为流行了。 +复杂网站应用java的补充。但由于它与网页结合度很高并且由浏览器内置支持, +所以javascript变得比java在前端更为流行了。 -JavaScript 不仅仅只可以用于浏览器, 也可用于 Node.js 等后台环境。 +不过 JavaScript 可不仅仅只用于浏览器: Node.js,一个基于Google Chrome V8引擎的独立运行时环境,也越来越流行。 很欢迎来自您的反馈,您可以通过下列方式联系到我: [@adambrenecki](https://twitter.com/adambrenecki), 或者 @@ -29,145 +31,167 @@ JavaScript 不仅仅只可以用于浏览器, 也可用于 Node.js 等后台环 // 语句可以以分号结束 doStuff(); -// ... 但是分号也可以省略,每当遇到一个新行时,分号会自动插入 +// ... 但是分号也可以省略,每当遇到一个新行时,分号会自动插入(除了一些特殊情况)。 doStuff() -// 我们在这里会去掉分号,但是否添加最后的分号取决于你个人的习惯 -// 及你所在团队的编程风格 +// 因为这些特殊情况会导致意外的结果,所以我们在这里保留分号。 /////////////////////////////////// // 1. 数字、字符串与操作符 -// Javascript 只有一种数字类型 (即 64位 IEEE 754 双精度浮点). -3 // = 3 -1.5 // = 1.5 +// Javascript 只有一种数字类型(即 64位 IEEE 754 双精度浮点 double)。 +// double 有 52 位表示尾数,足以精确存储大到 9✕10¹⁵ 的整数。 +3; // = 3 +1.5; // = 1.5 -// 所有基本的算数运算 -1 + 1 // = 2 -8 - 1 // = 7 -10 * 2 // = 20 -35 / 5 // = 7 +// 所有基本的算数运算都如你预期。 +1 + 1; // = 2 +0.1 + 0.2; // = 0.30000000000000004 +8 - 1; // = 7 +10 * 2; // = 20 +35 / 5; // = 7 -// 包括无法整除的除法 -5 / 2 // = 2.5 +// 包括无法整除的除法。 +5 / 2; // = 2.5 -// 位运算也和其他语言一样。当你对浮点数进行位运算时, -// 浮点数会转换为至多 32 位的无符号整数 -1 << 2 // = 4 +// 位运算也和其他语言一样;当你对浮点数进行位运算时, +// 浮点数会转换为*至多* 32 位的无符号整数。 +1 << 2; // = 4 -// 括号可以决定优先级 -(1 + 3) * 2 // = 8 +// 括号可以决定优先级。 +(1 + 3) * 2; // = 8 // 有三种非数字的数字类型 -Infinity // 1/0 的结果 --Infinity // -1/0 的结果 -NaN // 0/0 的结果 +Infinity; // 1/0 的结果 +-Infinity; // -1/0 的结果 +NaN; // 0/0 的结果 -// 也有布尔值 -true -false +// 也有布尔值。 +true; +false; -// 可以通过单引号或双引号来构造字符串 -'abc' -"Hello, world" +// 可以通过单引号或双引号来构造字符串。 +'abc'; +"Hello, world"; // 用!来取非 -!true // = false -!false // = true +!true; // = false +!false; // = true -// 相等 == -1 == 1 // = true -2 == 1 // = false +// 相等 === +1 === 1; // = true +2 === 1; // = false // 不等 != -1 != 1 // = false -2 != 1 // = true +1 !== 1; // = false +2 !== 1; // = true // 更多的比较操作符 -1 < 10 // = true -1 > 10 // = false -2 <= 2 // = true -2 >= 2 // = true +1 < 10; // = true +1 > 10; // = false +2 <= 2; // = true +2 >= 2; // = true // 字符串用+连接 -"Hello " + "world!" // = "Hello world!" +"Hello " + "world!"; // = "Hello world!" // 字符串也可以用 < 、> 来比较 -"a" < "b" // = true +"a" < "b"; // = true -// 比较时会进行类型转换... -"5" == 5 // = true +// 使用“==”比较时会进行类型转换... +"5" == 5; // = true +null == undefined; // = true // ...除非你是用 === -"5" === 5 // = false +"5" === 5; // = false +null === undefined; // = false -// 你可以用charAt来得到字符串中的字符 -"This is a string".charAt(0) +// ...但会导致奇怪的行为 +13 + !0; // 14 +"13" + !0; // '13true' -// 还有两个特殊的值:null和undefined -null // 用来表示刻意设置成的空值 -undefined // 用来表示还没有设置的值 +// 你可以用`charAt`来得到字符串中的字符 +"This is a string".charAt(0); // = 'T' -// null, undefined, NaN, 0 和 "" 都是假的(false),其他的都视作逻辑真 -// 注意 0 是逻辑假而 "0"是逻辑真, 尽管 0 == "0". +// ...或使用 `substring` 来获取更大的部分。 +"Hello world".substring(0, 5); // = "Hello" + +// `length` 是一个属性,所以不要使用 (). +"Hello".length; // = 5 + +// 还有两个特殊的值:`null`和`undefined` +null; // 用来表示刻意设置的空值 +undefined; // 用来表示还没有设置的值(尽管`undefined`自身实际是一个值) + +// false, null, undefined, NaN, 0 和 "" 都是假的;其他的都视作逻辑真 +// 注意 0 是逻辑假而 "0"是逻辑真,尽管 0 == "0"。 /////////////////////////////////// // 2. 变量、数组和对象 -// 变量需要用 var 这个关键字声明. Javascript是动态类型语言 -// 所以你在声明时无需指定类型。 赋值需要用 = -var someVar = 5 +// 变量需要用`var`关键字声明。Javascript是动态类型语言, +// 所以你无需指定类型。 赋值需要用 `=` +var someVar = 5; -// 如果你在声明时没有加var关键字,你也不会得到错误 -someOtherVar = 10 +// 如果你在声明时没有加var关键字,你也不会得到错误... +someOtherVar = 10; -// ...但是此时这个变量就会拥有全局的作用域,而非当前作用域 +// ...但是此时这个变量就会在全局作用域被创建,而非你定义的当前作用域 -// 没有被赋值的变量都会返回undefined这个值 -var someThirdVar // = undefined +// 没有被赋值的变量都会被设置为undefined +var someThirdVar; // = undefined -// 对变量进行数学运算有一些简写法 -someVar += 5 // 等价于 someVar = someVar + 5; someVar 现在是 10 -someVar *= 10 // 现在 someVar 是 100 +// 对变量进行数学运算有一些简写法: +someVar += 5; // 等价于 someVar = someVar + 5; someVar 现在是 10 +someVar *= 10; // 现在 someVar 是 100 // 自增和自减也有简写 -someVar++ // someVar 是 101 -someVar-- // 回到 100 +someVar++; // someVar 是 101 +someVar--; // 回到 100 // 数组是任意类型组成的有序列表 -var myArray = ["Hello", 45, true] +var myArray = ["Hello", 45, true]; + +// 数组的元素可以用方括号下标来访问。 +// 数组的索引从0开始。 +myArray[1]; // = 45 -// 数组的元素可以用方括号下标来访问 -// 数组的索引从0开始 -myArray[1] // = 45 +// 数组是可变的,并拥有变量 length。 +myArray.push("World"); +myArray.length; // = 4 -// javascript中的对象相当于其他语言中的字典或映射:是键-值的集合 -{key1: "Hello", key2: "World"} +// 在指定下标添加/修改 +myArray[3] = "Hello"; -// 键是字符串,但是引号也并非是必须的,如果键本身是合法的js标识符 -// 而值则可以是任意类型的值 -var myObj = {myKey: "myValue", "my other key": 4} +// javascript中的对象相当于其他语言中的“字典”或“映射”:是键-值对的无序集合。 +var myObj = {key1: "Hello", key2: "World"}; -// 对象的访问可以通过下标 -myObj["my other key"] // = 4 +// 键是字符串,但如果键本身是合法的js标识符,则引号并非是必须的。 +// 值可以是任意类型。 +var myObj = {myKey: "myValue", "my other key": 4}; + +// 对象属性的访问可以通过下标 +myObj["my other key"]; // = 4 // ... 或者也可以用 . ,如果属性是合法的标识符 -myObj.myKey // = "myValue" +myObj.myKey; // = "myValue" -// 对象是可变的,键和值也可以被更改或增加 -myObj.myThirdKey = true +// 对象是可变的;值也可以被更改或增加新的键 +myObj.myThirdKey = true; -// 如果你想要访问一个还没有被定义的属性,那么会返回undefined -myObj.myFourthKey // = undefined +// 如果你想要获取一个还没有被定义的值,那么会返回undefined +myObj.myFourthKey; // = undefined /////////////////////////////////// // 3. 逻辑与控制结构 -// if语句和其他语言中一样 -var count = 1 +// 本节介绍的语法与Java的语法几乎完全相同 + +// `if`语句和其他语言中一样。 +var count = 1; if (count == 3){ // count 是 3 时执行 -} else if (count == 4) { +} else if (count == 4){ // count 是 4 时执行 } else { // 其他情况下执行 @@ -179,219 +203,273 @@ while (true) { } // Do-while 和 While 循环很像 ,但前者会至少执行一次 -var input +var input; do { - input = getInput() + input = getInput(); } while (!isValid(input)) -// for循环和C、Java中的一样 -// 初始化; 继续执行的条件; 遍历后执行. +// `for`循环和C、Java中的一样: +// 初始化; 继续执行的条件; 迭代。 for (var i = 0; i < 5; i++){ // 遍历5次 } // && 是逻辑与, || 是逻辑或 if (house.size == "big" && house.colour == "blue"){ - house.contains = "bear" + house.contains = "bear"; } if (colour == "red" || colour == "blue"){ // colour是red或者blue时执行 } -// && 和 || 是“短路”语句,在初始化值时会变得有用 -var name = otherName || "default" +// && 和 || 是“短路”语句,它在设定初始化值时特别有用 +var name = otherName || "default"; + +// `switch`语句使用`===`检查相等性。 +// 在每一个case结束时使用 'break' +// 否则其后的case语句也将被执行。 +grade = 'B'; +switch (grade) { + case 'A': + console.log("Great job"); + break; + case 'B': + console.log("OK job"); + break; + case 'C': + console.log("You can do better"); + break; + default: + console.log("Oy vey"); + break; +} /////////////////////////////////// // 4. 函数、作用域、闭包 -// JavaScript 函数由function关键字定义 +// JavaScript 函数由`function`关键字定义 function myFunction(thing){ - return thing.toUpperCase() + return thing.toUpperCase(); } -myFunction("foo") // = "FOO" - -// 函数也可以是匿名的: -function(thing){ - return thing.toLowerCase() +myFunction("foo"); // = "FOO" + +// 注意被返回的值必须开始于`return`关键字的那一行, +// 否则由于自动的分号补齐,你将返回`undefined`。 +// 在使用Allman风格的时候要注意. +function myFunction() +{ + return // <- 分号自动插在这里 + { + thisIsAn: 'object literal' + } } -// (我们无法调用此函数,因为我们不知道这个函数的名字) +myFunction(); // = undefined -// javascript中的函数也是对象,所以函数也能够赋给一个变量,并且被传递 -// 比如一个事件处理函数: +// javascript中函数是一等对象,所以函数也能够赋给一个变量, +// 并且被作为参数传递 —— 比如一个事件处理函数: function myFunction(){ // this code will be called in 5 seconds' time } -setTimeout(myFunction, 5000) - -// 你甚至可以直接把一个函数写到另一个函数的参数中 +setTimeout(myFunction, 5000); +// 注意:setTimeout不是js语言的一部分,而是由浏览器和Node.js提供的。 -setTimeout(function myFunction(){ - // 5秒之后会执行这里的代码 -}, 5000) +// 函数对象甚至不需要声明名称 —— 你可以直接把一个函数定义写到另一个函数的参数中 +setTimeout(function(){ + // this code will be called in 5 seconds' time +}, 5000); -// JavaScript 仅有函数作用于,而其他的语句则没有作用域 +// JavaScript 有函数作用域;函数有其自己的作用域而其他的代码块则没有。 if (true){ - var i = 5 + var i = 5; } -i // = 5 - 并非我们在其他语言中所得到的undefined - -// 这就导致了人们经常用一种叫做“即使执行匿名函数”的模式 -// 这样可以避免一些临时变量扩散到外边去 -function(){ - var temporary = 5 - // 我们可以访问一个全局对象来访问全局作用域 - // 在浏览器中是 'window' 这个对象。 - // 在Node.js中这个对象的名字可能会不同。 - window.permanent = 10 - // 或者,我们也可以把var去掉就行了 - permanent2 = 15 -}() -temporary // 抛出引用异常 -permanent // = 10 -permanent2 // = 15 - -// javascript最强大的功能之一就是闭包 -// 如果一个函数在另一个函数中定义,那么这个函数就拥有外部函数的所有访问权 +i; // = 5 - 并非我们在其他语言中所期望得到的undefined + +// 这就导致了人们经常使用的“立即执行匿名函数”的模式, +// 这样可以避免一些临时变量扩散到全局作用域去。 +(function(){ + var temporary = 5; + // 我们可以访问修改全局对象("global object")来访问全局作用域, + // 在web浏览器中是`window`这个对象。 + // 在其他环境如Node.js中这个对象的名字可能会不同。 + window.permanent = 10; +})(); +temporary; // 抛出引用异常ReferenceError +permanent; // = 10 + +// javascript最强大的功能之一就是闭包。 +// 如果一个函数在另一个函数中定义,那么这个内部函数就拥有外部函数的所有变量的访问权, +// 即使在外部函数结束之后。 function sayHelloInFiveSeconds(name){ - var prompt = "Hello, " + name + "!" + var prompt = "Hello, " + name + "!"; + // 内部函数默认是放在局部作用域的, + // 就像是用`var`声明的。 function inner(){ - alert(prompt) + alert(prompt); } - setTimeout(inner, 5000) - // setTimeout 是异步的,所以这个函数会马上终止不会等待。 - // 然而,在5秒结束后,inner函数仍然会弹出prompt信息。 + setTimeout(inner, 5000); + // setTimeout是异步的,所以 sayHelloInFiveSeconds 函数会立即退出, + // 而 setTimeout 会在后面调用inner + // 然而,由于inner是由sayHelloInFiveSeconds“闭合包含”的, + // 所以inner在其最终被调用时仍然能够访问`prompt`变量。 } -sayHelloInFiveSeconds("Adam") // 会在5秒后弹出 "Hello, Adam!" +sayHelloInFiveSeconds("Adam"); // 会在5秒后弹出 "Hello, Adam!" + /////////////////////////////////// // 5. 对象、构造函数与原型 -// 对象包含方法 +// 对象可以包含方法。 var myObj = { myFunc: function(){ - return "Hello world!" + return "Hello world!"; } -} -myObj.myFunc() // = "Hello world!" +}; +myObj.myFunc(); // = "Hello world!" -// 当对象中的函数被调用时,这个函数就可以通过this关键字访问这个对象 +// 当对象中的函数被调用时,这个函数可以通过`this`关键字访问其依附的这个对象。 myObj = { myString: "Hello world!", myFunc: function(){ - return this.myString + return this.myString; } -} -myObj.myFunc() // = "Hello world!" +}; +myObj.myFunc(); // = "Hello world!" -// 但这个函数访问的其实是其运行时环境,而非定义时环境 -// 所以如果函数所在的环境不在当前对象的环境中运行时,就运行不成功了 -var myFunc = myObj.myFunc -myFunc() // = undefined +// 但这个函数访问的其实是其运行时环境,而非定义时环境,即取决于函数是如何调用的。 +// 所以如果函数被调用时不在这个对象的上下文中,就不会运行成功了。 +var myFunc = myObj.myFunc; +myFunc(); // = undefined -// 相应的,一个函数也可以被指定为一个对象的方法,并且用过this可以访问 -// 这个对象的成员,即使在定义时并没有绑定任何值 +// 相应的,一个函数也可以被指定为一个对象的方法,并且可以通过`this`访问 +// 这个对象的成员,即使在行数被定义时并没有依附在对象上。 var myOtherFunc = function(){ - return this.myString.toUpperCase() + return this.myString.toUpperCase(); +} +myObj.myOtherFunc = myOtherFunc; +myObj.myOtherFunc(); // = "HELLO WORLD!" + +// 当我们通过`call`或者`apply`调用函数的时候,也可以为其指定一个执行上下文。 +var anotherFunc = function(s){ + return this.myString + s; } -myObj.myOtherFunc = myOtherFunc -myObj.myOtherFunc() // = "HELLO WORLD!" +anotherFunc.call(myObj, " And Hello Moon!"); // = "Hello World! And Hello Moon!" -// 当你通过new关键字调用一个函数时,就会生成一个对象 -// 而对象的成员需要通过this来定义。 -// 这样的函数就叫做构造函数 +// `apply`函数几乎完全一样,只是要求一个array来传递参数列表。 +anotherFunc.apply(myObj, [" And Hello Sun!"]); // = "Hello World! And Hello Sun!" +// 当一个函数接受一系列参数,而你想传入一个array时特别有用。 +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 + this.myNumber = 5; } -myNewObj = new MyConstructor() // = {myNumber: 5} -myNewObj.myNumber // = 5 +myNewObj = new MyConstructor(); // = {myNumber: 5} +myNewObj.myNumber; // = 5 -// 每一个js对象都有一个原型,当你要访问一个没有定义过的成员时, -// 解释器就回去找这个对象的原型 +// 每一个js对象都有一个‘原型’。当你要访问一个实际对象中没有定义的一个属性时, +// 解释器就回去找这个对象的原型。 -// 有一些JS实现会让你通过一个对象的__proto__方法访问这个原型。 -// 这虽然对理解这个对象很有用,但是这并不是标准的一部分 -// 我们之后会通过标准方式来访问原型。 +// 一些JS实现会让你通过`__proto__`属性访问一个对象的原型。 +// 这虽然对理解原型很有用,但是它并不是标准的一部分; +// 我们后面会介绍使用原型的标准方式。 var myObj = { - myString: "Hello world!", -} + myString: "Hello world!" +}; var myPrototype = { meaningOfLife: 42, myFunc: function(){ return this.myString.toLowerCase() } -} -myObj.__proto__ = myPrototype -myObj.meaningOfLife // = 42 +}; -// This works for functions, too. +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中的 -// 也因此并不是所有的JS实现都有这个方法 -var myObj = Object.create(myPrototype) -myObj.meaningOfLife // = 43 - -// 第二种方式可以在任意版本中使用,不过需要通过构造函数。 -// 构造函数有一个属性prototype。但是这 *不是* 构造函数本身的函数 -// 而是通过构造函数和new关键字生成新对象时自动生成的。 -myConstructor.prototype = { +}; +myObj.myBoolean; // = true + +// 这其中并没有对象的拷贝;每个对象实际上是持有原型对象的引用。 +// 这意味着当我们改变对象的原型时,会影响到其他以这个原型为原型的对象。 +myPrototype.meaningOfLife = 43; +myObj.meaningOfLife; // = 43 + +// 我们知道 `__proto__` 并非标准规定,实际上也没有标准办法来修改一个已存在对象的原型。 +// 然而,我们有两种方式为指定原型创建一个新的对象。 + +// 第一种方式是 Object.create,这个方法是在最近才被添加到Js中的, +// 因此并不是所有的JS实现都有这个方法 +var myObj = Object.create(myPrototype); +myObj.meaningOfLife; // = 43 + +// 第二种方式可以在任意版本中使用,不过必须通过构造函数。 +// 构造函数有一个属性prototype。但是它 *不是* 构造函数本身的原型;相反, +// 是通过构造函数和new关键字创建的新对象的原型。 +MyConstructor.prototype = { + myNumber: 5, getMyNumber: function(){ - return this.myNumber + return this.myNumber; } -} -var myNewObj2 = new myConstructor() -myNewObj2.getMyNumber() // = 5 +}; +var myNewObj2 = new MyConstructor(); +myNewObj2.getMyNumber(); // = 5 +myNewObj2.myNumber = 6 +myNewObj2.getMyNumber(); // = 6 // 字符串和数字等内置类型也有通过构造函数来创建的包装类型 -var myNumber = 12 -var myNumberObj = new Number(12) -myNumber == myNumberObj // = true +var myNumber = 12; +var myNumberObj = new Number(12); +myNumber == myNumberObj; // = true // 但是它们并非严格等价 -typeof myNumber // = 'number' -typeof myNumberObj // = 'object' -myNumber === myNumberObj // = false +typeof myNumber; // = 'number' +typeof myNumberObj; // = 'object' +myNumber === myNumberObj; // = false if (0){ // 这段代码不会执行,因为0代表假 } if (Number(0)){ - // 这段代码会执行,因为Number(0)代表真 + // 这段代码*会*执行,因为Number(0)代表真 } -// 但是,包装类型和内置类型共享一个原型 -// 这样你就可以给内置类型也增加一些功能 +// 不过,包装类型和内置类型共享一个原型, +// 所以你实际可以给内置类型也增加一些功能,例如对string: String.prototype.firstCharacter = function(){ - return this.charAt(0) + return this.charAt(0); } -"abc".firstCharacter() // = "a" +"abc".firstCharacter(); // = "a" -// 这个技巧可以用来用老版本的javascript子集来是实现新版本js的功能 +// 这个技巧经常用在“代码填充”中,来为老版本的javascript子集增加新版本js的特性, // 这样就可以在老的浏览器中使用新功能了。 -// 比如,我们知道Object.create并没有在所有的版本中都实现 -// 但是我们仍然可以通过以下兼容代码来实现: +// 比如,我们知道Object.create并没有在所有的版本中都实现, +// 但是我们仍然可以通过“代码填充”来实现兼容: if (Object.create === undefined){ // 如果存在则不覆盖 Object.create = function(proto){ // 用正确的原型来创建一个临时构造函数 - var Constructor = function(){} - Constructor.prototype = proto + var Constructor = function(){}; + Constructor.prototype = proto; // 之后用它来创建一个新的对象 - return new Constructor() + return new Constructor(); } } ``` @@ -399,19 +477,23 @@ if (Object.create === undefined){ // 如果存在则不覆盖 ## 更多阅读 [Mozilla 开发者 -网络](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 提供了很好的 -Javascript文档,并且由于是wiki,所以你也可以自行编辑来分享你的知识。 +网络](https://developer.mozilla.org/en-US/docs/Web/JavaScript) 提供了优秀的介绍 +Javascript如何在浏览器中使用的文档。而且它是wiki,所以你也可以自行编辑来分享你的知识。 MDN的 [A re-introduction to JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) -覆盖了这里提到的绝大多数话题,大多数只是Javascript这个语言本身。 +覆盖了这里提到的绝大多数话题的细节。该导引的大多数内容被限定在只是Javascript这个语言本身; 如果你想了解Javascript是如何在网页中被应用的,那么可以查看 [Document Object Model](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core) +[Learn Javascript by Example and with Challenges](http://www.learneroo.com/modules/64/nodes/350) 是本参考的另一个版本,并包含了挑战习题。 + [Javascript Garden](http://bonsaiden.github.io/JavaScript-Garden/) 是一个深入 -讲解所有Javascript反直觉部分的一本书 +讲解所有Javascript反直觉部分的导引。 + +[JavaScript: The Definitive Guide](http://www.amazon.com/gp/product/0596805527/) 是一个经典的指导参考书。 除了这篇文章的直接贡献者之外,这篇文章也参考了这个网站上 Louie Dinh 的 Python 教程,以及 Mozilla开发者网络上的[JS -Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) +Tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript)。 -- cgit v1.2.3 From bcc7428194d68047f7baffbe40d0adb3d9b2b3aa Mon Sep 17 00:00:00 2001 From: Goddamned Qu Date: Sun, 8 Mar 2015 12:04:20 +0800 Subject: Update javascript-cn.html.markdown add missing translation --- zh-cn/javascript-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index cde3fa35..64b0aadc 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -268,14 +268,14 @@ myFunction(); // = undefined // javascript中函数是一等对象,所以函数也能够赋给一个变量, // 并且被作为参数传递 —— 比如一个事件处理函数: function myFunction(){ - // this code will be called in 5 seconds' time + // 这段代码将在5秒钟后被调用 } setTimeout(myFunction, 5000); // 注意:setTimeout不是js语言的一部分,而是由浏览器和Node.js提供的。 // 函数对象甚至不需要声明名称 —— 你可以直接把一个函数定义写到另一个函数的参数中 setTimeout(function(){ - // this code will be called in 5 seconds' time + // 这段代码将在5秒钟后被调用 }, 5000); // JavaScript 有函数作用域;函数有其自己的作用域而其他的代码块则没有。 -- cgit v1.2.3 From 7c3de408077a494d644ad926a198fc7e31f7ab82 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Sat, 14 Mar 2015 12:42:52 +0800 Subject: [c++/cn] translation started. --- zh-cn/c++-cn.html.markdown | 579 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 579 insertions(+) create mode 100644 zh-cn/c++-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown new file mode 100644 index 00000000..f1bdf158 --- /dev/null +++ b/zh-cn/c++-cn.html.markdown @@ -0,0 +1,579 @@ +--- +language: c++ +filename: learncpp.cpp +contributors: + - ["Steven Basart", "http://github.com/xksteven"] + - ["Matt Kline", "https://github.com/mrkline"] +translators: + - ["Arnie97", "https://github.com/Arnie97"] +lang: zh-cn +--- + +C++是一種系統編程語言。用它的發明者, +[Bjarne Stroustrup的話](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)來說,C++的設計目標是: + +- 成爲「更好的C語言」 +- 支持數據的抽象與封裝 +- 支持面向對象編程 +- 支持泛型編程 + +C++提供了對硬件的緊密控制(正如C語言一樣), +能夠編譯爲機器語言,由處理器直接執行。 +與此同時,它也提供了泛型、異常和類等高層功能。 +雖然C++的語法可能比某些出現較晚的語言更複雜,它仍然得到了人們的青睞—— +功能與速度的平衡使C++成爲了目前應用最廣泛的系統編程語言之一。 + +```c++ +//////////////// +// 與C語言的比較 +//////////////// + +// C++_幾乎_是C語言的一個超集,它與C語言的基本語法有許多相同之處, +// 例如變量和函數的聲明,原生數據類型等等。 + +// 和C語言一樣,在C++中,你的程序會從main()開始執行, +// 該函數的返回值應當爲int型,這個返回值會作爲程序的退出狀態值。 +// 不過,大多數的編譯器(gcc,clang等)也接受 void main() 的函數原型。 +// (參見 http://en.wikipedia.org/wiki/Exit_status 來獲取更多信息) +int main(int argc, char** argv) +{ + // 和C語言一樣,命令行參數通過argc和argv傳遞。 + // argc代表命令行參數的數量, + // 而argv是一個包含“C語言風格字符串”(char *)的數組, + // 其中每個字符串代表一個命令行參數的內容, + // 首個命令行參數是調用該程序時所使用的名稱。 + // 如果你不關心命令行參數的值,argc和argv可以被忽略。 + // 此時,你可以用int main()作爲函數原型。 + + // 退出狀態值爲0時,表示程序執行成功 + return 0; +} + +// 然而,C++和C語言也有一些區別: + +// 在C++中,字符字面量的大小是一個字節。 +sizeof('c') == 1 + +// 在C語言中,字符字面量的大小與int相同。 +sizeof('c') == sizeof(10) + + +// C++的函數原型與函數定義是嚴格匹配的 +void func(); // 這個函數不能接受任何參數 + +// 而在C語言中 +void func(); // 這個函數能接受任意數量的參數 + +// 在C++中,用nullptr代替C語言中的NULL +int* ip = nullptr; + +// C++也可以使用C語言的標準頭文件, +// 但是需要加上前綴“c”並去掉末尾的“.h”。 +#include + +int main() +{ + printf("Hello, world!\n"); + return 0; +} + +/////////// +// 函數重載 +/////////// + +// C++支持函數重載,provided each function takes different parameters. + +void print(char const* myString) +{ + printf("String %s\n", myString); +} + +void print(int myInt) +{ + printf("My int is %d", myInt); +} + +int main() +{ + print("Hello"); // 解析爲 void print(const char*) + print(15); // 解析爲 void print(int) +} + +/////////////////// +// 函數參數的默認值 +/////////////////// + +// 你可以爲函數的參數指定默認值, +// 它們將會在調用者沒有提供相應參數時被使用。 + +void doSomethingWithInts(int a = 1, int b = 4) +{ + // 對兩個參數進行一些操作 +} + +int main() +{ + doSomethingWithInts(); // a = 1, b = 4 + doSomethingWithInts(20); // a = 20, b = 4 + doSomethingWithInts(20, 5); // a = 20, b = 5 +} + +// 默認參數必須放在所有的常規參數之後。 + +void invalidDeclaration(int a = 1, int b) // 這是錯誤的! +{ +} + + +/////////// +// 命名空間 +/////////// + +// 命名空間爲變量、函數和其他聲明提供了【separate】的作用域。 +// 命名空間可以嵌套使用。 + +namespace First { + namespace Nested { + void foo() + { + printf("This is First::Nested::foo\n"); + } + } // end namespace Nested +} // end namespace First + +namespace Second { + void foo() + { + printf("This is Second::foo\n") + } +} + +void foo() +{ + printf("This is global foo\n"); +} + +int main() +{ + // 如果沒有特別指定,所有【對象】都使用【取自】"Second"中的【聲明】。 + using namespace Second; + + foo(); // 顯示 "This is Second::foo" + First::Nested::foo(); // 顯示 "This is First::Nested::foo" + ::foo(); // 顯示 "This is global foo" +} + +//////////// +// 輸入/輸出 +//////////// + +// C++使用“流”來輸入輸出。 +// cin、cout、和cerr分別代表stdin(標準輸入)、stdout(標準輸出)和stderr(標準錯誤)。 +// <<是流的插入運算符,>>是流提取運算符。 + +#include // Include for I/O streams + +using namespace std; // 輸入輸出流在std命名空間(也就是標準庫)中。 + +int main() +{ + int myInt; + + // 在標準輸出(終端/顯示器)中顯示 + cout << "Enter your favorite number:\n"; + // 從標準輸入(鍵盤)獲得一個值 + cin >> myInt; + + // cout can also be formatted + cout << "Your favorite number is " << myInt << "\n"; + // 顯示 "Your favorite number is " + + cerr << "Used for error messages"; +} + +///////// +// 字符串 +///////// + +// C++中的字符串是對象,它們有很多成員函數 +#include + +using namespace std; // 字符串也在std命名空間(標準庫)中。 + +string myString = "Hello"; +string myOtherString = " World"; + +// + 可以用於連接字符串。 +cout << myString + myOtherString; // "Hello World" + +cout << myString + " You"; // "Hello You" + +// C++中的字符串是可變的,具有“值語義”。 +myString.append(" Dog"); +cout << myString; // "Hello Dog" + + +///////////// +// 引用 +///////////// + +// 除了支持C語言中的指針類型以外,C++還提供了_引用_。 +// 引用是一種特殊的指針類型,一旦被定義就不能重新賦值,並且引用不能被設置爲空值。 +// 使用引用時的語法與原變量相同: +// 也就是說,對引用類型進行解引用時,不需要使用*; +// 賦值時也不需要用&來取地址。 + +using namespace std; + +string foo = "I am foo"; +string bar = "I am bar"; + + +string& fooRef = foo; // 建立了一個對foo的引用。 +fooRef += ". Hi!"; // 通過引用來修改foo的值 +cout << fooRef; // "I am foo. Hi!" + +// 這句話的並不會改變fooRef的指向,其效果與“foo = bar”相同。 +// 也就是說,在執行這條語句之後,foo == "I am bar"。 +fooRef = bar; + +const string& barRef = bar; // 建立指向bar的【const ref】。 +// 和C語言中一樣,聲明爲常數的值(包括指針和引用)不能被修改。 +barRef += ". Hi!"; // 這是錯誤的,【const ref】不能被修改。 + +/////////////////// +// 類與面向對象編程 +/////////////////// + +// 有關類的第一個示例 +#include + +// 聲明一個類。 +// 類通常在頭文件(.h或.hpp)中聲明。 +class Dog { + // 成員變量和成員函數默認情況下是私有(private)的。 + std::string name; + int weight; + +// 在這個標籤之後,所有聲明都是公有(public)的, +// 直到重新指定“private:”(私有繼承)或“protected:”(保護繼承)爲止 +public: + + // 默認的構造器 + Dog(); + + // Member function declarations (implementations to follow) + // Note that we use std::string here instead of placing + // using namespace std; + // above. + // Never put a "using namespace" statement in a header. + void setName(const std::string& dogsName); + + void setWeight(int dogsWeight); + + // Functions that do not modify the state of the object + // should be marked as const. + // This allows you to call them if given a const reference to the object. + // Also note the functions must be explicitly declared as _virtual_ + // in order to be overridden in derived classes. + // Functions are not virtual by default for performance reasons. + virtual void print() const; + + // 函數也可以在class body內部定義。 + // 這樣定義的函數會自動成爲內聯函數。 + void bark() const { std::cout << name << " barks!\n" } + + // 除了構造器以外,C++還提供了析構器。 + // These are called when an object is deleted or falls out of scope. + // 這使得如同下文中的RAII這樣的強大範式成爲可能。 + // Destructors must be virtual to allow classes to be derived from this one. + virtual ~Dog(); + +}; // 在類的定義後必須加一個分號 + +// 類的成員函數通常在.cpp文件中實現。 +void Dog::Dog() +{ + std::cout << "A dog has been constructed\n"; +} + +// 對象(例如字符串)應當以引用的形式傳遞, +// 不需要修改的對象則應當作爲【const ref】。 +void Dog::setName(const std::string& dogsName) +{ + name = dogsName; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// Notice that "virtual" is only needed in the declaration, not the definition. +void Dog::print() const +{ + std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; +} + +void Dog::~Dog() +{ + cout << "Goodbye " << name << "\n"; +} + +int main() { + Dog myDog; // 此時顯示“A dog has been constructed” + myDog.setName("Barkley"); + myDog.setWeight(10); + myDog.printDog(); // 顯示“Dog is Barkley and weighs 10 kg” + return 0; +} // 顯示“Goodbye Barkley” + +// 繼承: + +// 這個類繼承了Dog類中的公有(public)和保護(protected)對象 +class OwnedDog : public Dog { + + void setOwner(const std::string& dogsOwner) + + // 重寫OwnedDogs類的print方法。 + // 如果你不熟悉子類多態的話,可以參考這個頁面中的概述: + // http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping + + // override關鍵字是可選的,它確保你是在重寫基類中的方法。 + void print() const override; + +private: + std::string owner; +}; + +// 與此同時,在對應的.cpp文件裏: + +void OwnedDog::setOwner(const std::string& dogsOwner) +{ + owner = dogsOwner; +} + +void OwnedDog::print() const +{ + Dog::print(); // 調用基類Dog中的print方法 + // "Dog is and weights " + + std::cout << "Dog is owned by " << owner << "\n"; + // "Dog is owned by " +} + +///////////////////// +// 初始化與運算符重載 +///////////////////// + +// 在C++中,你可以重載+、-、*、/等運算符的行爲。 +// This is done by defining a function +// which is called whenever the operator is used. + +#include +using namespace std; + +class Point { +public: + // 可以以這樣的方式爲成員變量設置默認值。 + double x = 0; + double y = 0; + + // Define a default constructor which does nothing + // but initialize the Point to the default value (0, 0) + Point() { }; + + // The following syntax is known as an initialization list + // and is the proper way to initialize class member values + Point (double a, double b) : + x(a), + y(b) + { /* Do nothing except initialize the values */ } + + // 重載 + 運算符 + Point operator+(const Point& rhs) const; + + // 重載 += 運算符 + Point& operator+=(const Point& rhs); + + // 增加 - 和 -= 運算符也是有意義的,這裏不再贅述。 +}; + +Point Point::operator+(const Point& rhs) const +{ + // Create a new point that is the sum of this one and rhs. + return Point(x + rhs.x, y + rhs.y); +} + +Point& Point::operator+=(const Point& rhs) +{ + x += rhs.x; + y += rhs.y; + return *this; +} + +int main () { + Point up (0,1); + Point right (1,0); + // 這裏調用了Point類型的運算符“+” + // 調用up(Point類型)的“+”方法,並以right作爲函數的參數 + Point result = up + right; + // 顯示“Result is upright (1,1)” + cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; + return 0; +} + +/////////// +// 異常處理 +/////////// + +// 標準庫中提供了a few exception types +// (參見http://en.cppreference.com/w/cpp/error/exception) +// but any type can be thrown an as exception +#include + +// All exceptions thrown inside the _try_ block can be caught by subsequent +// _catch_ handlers. +try { + // Do not allocate exceptions on the heap using _new_. + throw std::exception("A problem occurred"); +} +// Catch exceptions by const reference if they are objects +catch (const std::exception& ex) +{ + std::cout << ex.what(); +// Catches any exception not caught by previous _catch_ blocks +} catch (...) +{ + std::cout << "Unknown exception caught"; + throw; // Re-throws the exception +} + +/////// +// RAII +/////// + +// RAII指的是“资源获取就是初始化”(Resource Allocation Is Initialization)。 +// It is often considered the most powerful paradigm in C++, +// and is the simple concept that a constructor for an object +// acquires that object's resources and the destructor releases them. + +// 爲了理解這一範式的用處,讓我們考慮某個函數使用文件句柄時的情況: +void doSomethingWithAFile(const char* filename) +{ + // 首先,讓我們假設一切都會順利進行。 + + FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 + + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + + fclose(fh); // 關閉文件句柄 +} + +// 不幸的是,隨着錯誤處理機制的引入,事情會變得複雜。 +// 假設fopen有可能執行失敗, +// 而doSomethingWithTheFile和doSomethingElseWithIt會在失敗時返回錯誤代碼。 +// (雖然【Exceptions】是處理錯誤的推薦方式, +// 但是某些程序員,尤其是有C語言背景的,並不認可【exceptions】的效用)。 +// 現在,我們必須檢查每個函數調用是否成功執行,並在問題發生的時候關閉文件句柄。 +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 + if (fh == nullptr) // 當執行失敗是,返回的指針是nullptr + return false; // 向調用者彙報錯誤 + + // 假設每個函數會在執行失敗時返回false + if (!doSomethingWithTheFile(fh)) { + fclose(fh); // Close the file handle so it doesn't leak. + return false; // 反饋錯誤 + } + if (!doSomethingElseWithIt(fh)) { + fclose(fh); // Close the file handle so it doesn't leak. + return false; // 反饋錯誤 + } + + fclose(fh); // Close the file handle so it doesn't leak. + return true; // 指示函數已成功執行 +} + +// C語言的程序員通常會借助goto語句簡化上面的代碼: +bool doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); + if (fh == nullptr) + return false; + + if (!doSomethingWithTheFile(fh)) + goto failure; + + if (!doSomethingElseWithIt(fh)) + goto failure; + + fclose(fh); // 關閉文件 + return true; // 執行成功 + +failure: + fclose(fh); + return false; // 反饋錯誤 +} + +// If the functions indicate errors using exceptions, +// things are a little cleaner, but still sub-optimal. +void doSomethingWithAFile(const char* filename) +{ + FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 + if (fh == nullptr) + throw std::exception("Could not open the file."); + + try { + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + } + catch (...) { + fclose(fh); // 保證出錯的時候文件被正確關閉 + throw; // Then re-throw the exception. + } + + fclose(fh); // 關閉文件 + // 所有工作順利完成 +} + +// Compare this to the use of C++'s file stream class (fstream) +// fstream利用自己的析構器來關閉文件句柄。 +// Recall from above that destructors are automatically called +// whenver an object falls out of scope. +void doSomethingWithAFile(const std::string& filename) +{ + // ifstream is short for input file stream + std::ifstream fh(filename); // Open the file + + // 對文件進行一些操作 + doSomethingWithTheFile(fh); + doSomethingElseWithIt(fh); + +} // 文件已經被析構器自動關閉 + +// 與上面幾種方式相比,這種方式有着_明顯_的優勢: +// 1. 無論發生了什麼情況,資源(此例當中是文件句柄)都會被正確關閉。 +// 只要你正確使用了析構器,就_不會_因爲忘記關閉句柄,造成資源的泄漏。 +// 2. Note that the code is much cleaner. +// The destructor handles closing the file behind the scenes +// without you having to worry about it. +// 3. The code is exception safe. +// An exception can be thrown anywhere in the function and cleanup +// will still occur. + +// All idiomatic C++ code uses RAII extensively for all resources. +// Additional examples include +// - Memory using unique_ptr and shared_ptr +// - Containers - the standard library linked list, +// vector (i.e. self-resizing array), hash maps, and so on +// all automatically destroy their contents when they fall out of scope. +// - Mutexes using lock_guard and unique_lock +``` +擴展閱讀: + + 提供了最新的語法參考。 + +可以在 找到一些補充資料。 -- cgit v1.2.3 From b3d7a178e729c142eb6890a815c13137d4d35314 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Sat, 14 Mar 2015 13:16:34 +0800 Subject: [c++/cn] mark all parts still in progress. --- zh-cn/c++-cn.html.markdown | 117 ++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 60 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index f1bdf158..9a952d85 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -39,7 +39,7 @@ int main(int argc, char** argv) { // 和C語言一樣,命令行參數通過argc和argv傳遞。 // argc代表命令行參數的數量, - // 而argv是一個包含“C語言風格字符串”(char *)的數組, + // 而argv是一個包含「C語言風格字符串」(char *)的數組, // 其中每個字符串代表一個命令行參數的內容, // 首個命令行參數是調用該程序時所使用的名稱。 // 如果你不關心命令行參數的值,argc和argv可以被忽略。 @@ -68,7 +68,7 @@ void func(); // 這個函數能接受任意數量的參數 int* ip = nullptr; // C++也可以使用C語言的標準頭文件, -// 但是需要加上前綴“c”並去掉末尾的“.h”。 +// 但是需要加上前綴「c」並去掉末尾的「.h」。 #include int main() @@ -81,7 +81,7 @@ int main() // 函數重載 /////////// -// C++支持函數重載,provided each function takes different parameters. +// C++支持函數重載,【provided each function takes different parameters.】 void print(char const* myString) { @@ -138,8 +138,8 @@ namespace First { { printf("This is First::Nested::foo\n"); } - } // end namespace Nested -} // end namespace First + } // 結束嵌套的命名空間Nested +} // 結束命名空間First namespace Second { void foo() @@ -155,23 +155,23 @@ void foo() int main() { - // 如果沒有特別指定,所有【對象】都使用【取自】"Second"中的【聲明】。 + // 如果沒有特別指定,就從「Second」中取得所需的內容。 using namespace Second; - foo(); // 顯示 "This is Second::foo" - First::Nested::foo(); // 顯示 "This is First::Nested::foo" - ::foo(); // 顯示 "This is global foo" + foo(); // 顯示「This is Second::foo」 + First::Nested::foo(); // 顯示「This is First::Nested::foo」 + ::foo(); // 顯示「This is global foo」 } //////////// // 輸入/輸出 //////////// -// C++使用“流”來輸入輸出。 +// C++使用「流」來輸入輸出。 // cin、cout、和cerr分別代表stdin(標準輸入)、stdout(標準輸出)和stderr(標準錯誤)。 // <<是流的插入運算符,>>是流提取運算符。 -#include // Include for I/O streams +#include // 引入包含輸入/輸出流的頭文件 using namespace std; // 輸入輸出流在std命名空間(也就是標準庫)中。 @@ -184,9 +184,9 @@ int main() // 從標準輸入(鍵盤)獲得一個值 cin >> myInt; - // cout can also be formatted + // cout也提供了格式化功能 cout << "Your favorite number is " << myInt << "\n"; - // 顯示 "Your favorite number is " + // 顯示「Your favorite number is 」 cerr << "Used for error messages"; } @@ -208,7 +208,7 @@ cout << myString + myOtherString; // "Hello World" cout << myString + " You"; // "Hello You" -// C++中的字符串是可變的,具有“值語義”。 +// C++中的字符串是可變的,具有「值語義」。 myString.append(" Dog"); cout << myString; // "Hello Dog" @@ -218,7 +218,7 @@ cout << myString; // "Hello Dog" ///////////// // 除了支持C語言中的指針類型以外,C++還提供了_引用_。 -// 引用是一種特殊的指針類型,一旦被定義就不能重新賦值,並且引用不能被設置爲空值。 +// 引用是一種特殊的指針類型,一旦被定義就不能重新賦值,並且不能被設置爲空值。 // 使用引用時的語法與原變量相同: // 也就是說,對引用類型進行解引用時,不需要使用*; // 賦值時也不需要用&來取地址。 @@ -233,7 +233,7 @@ string& fooRef = foo; // 建立了一個對foo的引用。 fooRef += ". Hi!"; // 通過引用來修改foo的值 cout << fooRef; // "I am foo. Hi!" -// 這句話的並不會改變fooRef的指向,其效果與“foo = bar”相同。 +// 這句話的並不會改變fooRef的指向,其效果與「foo = bar」相同。 // 也就是說,在執行這條語句之後,foo == "I am bar"。 fooRef = bar; @@ -256,13 +256,13 @@ class Dog { int weight; // 在這個標籤之後,所有聲明都是公有(public)的, -// 直到重新指定“private:”(私有繼承)或“protected:”(保護繼承)爲止 +// 直到重新指定「private:」(私有繼承)或「protected:」(保護繼承)爲止 public: // 默認的構造器 Dog(); - // Member function declarations (implementations to follow) + // 【Member function declarations (implementations to follow) // Note that we use std::string here instead of placing // using namespace std; // above. @@ -271,7 +271,7 @@ public: void setWeight(int dogsWeight); - // Functions that do not modify the state of the object + // 【Functions that do not modify the state of the object // should be marked as const. // This allows you to call them if given a const reference to the object. // Also note the functions must be explicitly declared as _virtual_ @@ -284,12 +284,12 @@ public: void bark() const { std::cout << name << " barks!\n" } // 除了構造器以外,C++還提供了析構器。 - // These are called when an object is deleted or falls out of scope. - // 這使得如同下文中的RAII這樣的強大範式成爲可能。 - // Destructors must be virtual to allow classes to be derived from this one. + // 當一個對象被刪除或者【falls out of scope】時,它的析構器會被調用。 + // 這使得RAII這樣的強大範式(參見下文)成爲可能。 + // 析構器【must be virtual to allow classes to be derived from this one. virtual ~Dog(); -}; // 在類的定義後必須加一個分號 +}; // 在類的定義之後,要加一個分號 // 類的成員函數通常在.cpp文件中實現。 void Dog::Dog() @@ -309,7 +309,7 @@ void Dog::setWeight(int dogsWeight) weight = dogsWeight; } -// Notice that "virtual" is only needed in the declaration, not the definition. +// 【Notice that "virtual" is only needed in the declaration, not the definition. void Dog::print() const { std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; @@ -321,12 +321,12 @@ void Dog::~Dog() } int main() { - Dog myDog; // 此時顯示“A dog has been constructed” + Dog myDog; // 此時顯示「A dog has been constructed」 myDog.setName("Barkley"); myDog.setWeight(10); - myDog.printDog(); // 顯示“Dog is Barkley and weighs 10 kg” + myDog.printDog(); // 顯示「Dog is Barkley and weighs 10 kg」 return 0; -} // 顯示“Goodbye Barkley” +} // 顯示「Goodbye Barkley」 // 繼承: @@ -367,7 +367,7 @@ void OwnedDog::print() const ///////////////////// // 在C++中,你可以重載+、-、*、/等運算符的行爲。 -// This is done by defining a function +// 【This is done by defining a function // which is called whenever the operator is used. #include @@ -379,16 +379,16 @@ public: double x = 0; double y = 0; - // Define a default constructor which does nothing + // 【Define a default constructor which does nothing // but initialize the Point to the default value (0, 0) Point() { }; - // The following syntax is known as an initialization list + // 【The following syntax is known as an initialization list // and is the proper way to initialize class member values Point (double a, double b) : x(a), y(b) - { /* Do nothing except initialize the values */ } + { /* 【Do nothing except initialize the values */ } // 重載 + 運算符 Point operator+(const Point& rhs) const; @@ -401,7 +401,7 @@ public: Point Point::operator+(const Point& rhs) const { - // Create a new point that is the sum of this one and rhs. + // 【Create a new point that is the sum of this one and rhs. return Point(x + rhs.x, y + rhs.y); } @@ -415,10 +415,10 @@ Point& Point::operator+=(const Point& rhs) int main () { Point up (0,1); Point right (1,0); - // 這裏調用了Point類型的運算符“+” - // 調用up(Point類型)的“+”方法,並以right作爲函數的參數 + // 這裏調用了Point類型的運算符「+」 + // 調用up(Point類型)的「+」方法,並以right作爲函數的參數 Point result = up + right; - // 顯示“Result is upright (1,1)” + // 顯示「Result is upright (1,1)」 cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; return 0; } @@ -429,32 +429,31 @@ int main () { // 標準庫中提供了a few exception types // (參見http://en.cppreference.com/w/cpp/error/exception) -// but any type can be thrown an as exception +// 【but any type can be thrown an as exception #include -// All exceptions thrown inside the _try_ block can be caught by subsequent -// _catch_ handlers. +// 在_try_代碼塊中拋出的異常可以被隨後的_catch_捕獲。 try { - // Do not allocate exceptions on the heap using _new_. + // 【Do not allocate exceptions on the heap using _new_. throw std::exception("A problem occurred"); } -// Catch exceptions by const reference if they are objects +// 【Catch exceptions by const reference if they are objects catch (const std::exception& ex) { std::cout << ex.what(); -// Catches any exception not caught by previous _catch_ blocks +// 捕獲尚未被_catch_處理的所有錯誤 } catch (...) { std::cout << "Unknown exception caught"; - throw; // Re-throws the exception + throw; // 重新拋出異常 } /////// // RAII /////// -// RAII指的是“资源获取就是初始化”(Resource Allocation Is Initialization)。 -// It is often considered the most powerful paradigm in C++, +// RAII指的是「资源获取就是初始化」(Resource Allocation Is Initialization)。 +// 【It is often considered the most powerful paradigm in C++, // and is the simple concept that a constructor for an object // acquires that object's resources and the destructor releases them. @@ -472,10 +471,10 @@ void doSomethingWithAFile(const char* filename) } // 不幸的是,隨着錯誤處理機制的引入,事情會變得複雜。 -// 假設fopen有可能執行失敗, +// 假設fopen函數有可能執行失敗, // 而doSomethingWithTheFile和doSomethingElseWithIt會在失敗時返回錯誤代碼。 -// (雖然【Exceptions】是處理錯誤的推薦方式, -// 但是某些程序員,尤其是有C語言背景的,並不認可【exceptions】的效用)。 +// (雖然異常是C++中處理錯誤的推薦方式, +// 但是某些程序員,尤其是有C語言背景的,並不認可異常捕獲機制的作用)。 // 現在,我們必須檢查每個函數調用是否成功執行,並在問題發生的時候關閉文件句柄。 bool doSomethingWithAFile(const char* filename) { @@ -518,7 +517,7 @@ failure: return false; // 反饋錯誤 } -// If the functions indicate errors using exceptions, +// 【If the functions indicate errors using exceptions, // things are a little cleaner, but still sub-optimal. void doSomethingWithAFile(const char* filename) { @@ -539,13 +538,13 @@ void doSomethingWithAFile(const char* filename) // 所有工作順利完成 } -// Compare this to the use of C++'s file stream class (fstream) +// 【Compare this to the use of C++'s file stream class (fstream) // fstream利用自己的析構器來關閉文件句柄。 -// Recall from above that destructors are automatically called +// 【Recall from above that destructors are automatically called // whenver an object falls out of scope. void doSomethingWithAFile(const std::string& filename) { - // ifstream is short for input file stream + // ifstream是輸入文件流(input file stream)的簡稱 std::ifstream fh(filename); // Open the file // 對文件進行一些操作 @@ -557,20 +556,18 @@ void doSomethingWithAFile(const std::string& filename) // 與上面幾種方式相比,這種方式有着_明顯_的優勢: // 1. 無論發生了什麼情況,資源(此例當中是文件句柄)都會被正確關閉。 // 只要你正確使用了析構器,就_不會_因爲忘記關閉句柄,造成資源的泄漏。 -// 2. Note that the code is much cleaner. +// 2. 【Note that the code is much cleaner. // The destructor handles closing the file behind the scenes // without you having to worry about it. -// 3. The code is exception safe. +// 3. 【The code is exception safe. // An exception can be thrown anywhere in the function and cleanup // will still occur. -// All idiomatic C++ code uses RAII extensively for all resources. -// Additional examples include -// - Memory using unique_ptr and shared_ptr -// - Containers - the standard library linked list, -// vector (i.e. self-resizing array), hash maps, and so on -// all automatically destroy their contents when they fall out of scope. -// - Mutexes using lock_guard and unique_lock +// 地道的C++代碼應當把RAII的使用擴展到所有類型的資源上,包括: +// - 用unique_ptr和shared_ptr管理的內存 +// - 容器,例如標準庫中的鏈表、向量(容量自動擴展的數組)、散列表等; +// 【all automatically destroy their contents when they fall out of scope. +// - 用lock_guard和unique_lock實現的互斥 ``` 擴展閱讀: -- cgit v1.2.3 From cfb4d5922d485f68b9ed3ba7a9e2f1add14cba3c Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Thu, 19 Mar 2015 00:31:33 +0800 Subject: Complete most parts of translation. --- zh-cn/c++-cn.html.markdown | 92 ++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 39 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index 9a952d85..24d2a1b8 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -167,9 +167,9 @@ int main() // 輸入/輸出 //////////// -// C++使用「流」來輸入輸出。 -// cin、cout、和cerr分別代表stdin(標準輸入)、stdout(標準輸出)和stderr(標準錯誤)。 -// <<是流的插入運算符,>>是流提取運算符。 +// C++使用「流」來輸入輸出。<<是流的插入運算符,>>是流提取運算符。 +// cin、cout、和cerr分別代表 +// stdin(標準輸入)、stdout(標準輸出)和stderr(標準錯誤)。 #include // 引入包含輸入/輸出流的頭文件 @@ -237,9 +237,9 @@ cout << fooRef; // "I am foo. Hi!" // 也就是說,在執行這條語句之後,foo == "I am bar"。 fooRef = bar; -const string& barRef = bar; // 建立指向bar的【const ref】。 -// 和C語言中一樣,聲明爲常數的值(包括指針和引用)不能被修改。 -barRef += ". Hi!"; // 這是錯誤的,【const ref】不能被修改。 +const string& barRef = bar; // 建立指向bar的常量引用。 +// 和C語言中一樣,(指針和引用)聲明爲常量時,對應的值不能被修改。 +barRef += ". Hi!"; // 這是錯誤的,不能修改一個常量引用的值。 /////////////////// // 類與面向對象編程 @@ -262,21 +262,19 @@ public: // 默認的構造器 Dog(); - // 【Member function declarations (implementations to follow) - // Note that we use std::string here instead of placing - // using namespace std; - // above. - // Never put a "using namespace" statement in a header. + // 這裏是成員函數聲明的一個例子。 + // 可以注意到,我們在此處使用了std::string,而不是using namespace std + // 語句using namespace絕不應當出現在頭文件當中。 void setName(const std::string& dogsName); void setWeight(int dogsWeight); - // 【Functions that do not modify the state of the object - // should be marked as const. - // This allows you to call them if given a const reference to the object. - // Also note the functions must be explicitly declared as _virtual_ - // in order to be overridden in derived classes. - // Functions are not virtual by default for performance reasons. + // 如果一個函數不對對象的狀態進行修改, + // 應當在聲明中加上const。 + // 這樣,你就可以對一個以常量方式引用的對象執行該操作。 + // 同時可以注意到,當父類的成員函數需要被子類重寫時, + // 父類中的函數必須被顯式聲明爲_虛函數(virtual)_。 + // 考慮到性能方面的因素,函數默認情況下不會被聲明爲虛函數。 virtual void print() const; // 函數也可以在class body內部定義。 @@ -284,13 +282,15 @@ public: void bark() const { std::cout << name << " barks!\n" } // 除了構造器以外,C++還提供了析構器。 - // 當一個對象被刪除或者【falls out of scope】時,它的析構器會被調用。 + // 當一個對象被刪除或者脫離其定義域時時,它的析構函數會被調用。 // 這使得RAII這樣的強大範式(參見下文)成爲可能。 - // 析構器【must be virtual to allow classes to be derived from this one. + // 爲了衍生出子類來,基類的析構函數必須定義爲虛函數。 virtual ~Dog(); }; // 在類的定義之後,要加一個分號 +}; // 記住,在類的定義之後,要加一個分號! + // 類的成員函數通常在.cpp文件中實現。 void Dog::Dog() { @@ -298,7 +298,7 @@ void Dog::Dog() } // 對象(例如字符串)應當以引用的形式傳遞, -// 不需要修改的對象則應當作爲【const ref】。 +// 對於不需要修改的對象,最好使用常量引用。 void Dog::setName(const std::string& dogsName) { name = dogsName; @@ -309,7 +309,23 @@ void Dog::setWeight(int dogsWeight) weight = dogsWeight; } -// 【Notice that "virtual" is only needed in the declaration, not the definition. +// 虛函數的virtual關鍵字只需要在聲明時使用,不需要在定義時出現 +void Dog::print() const +{ + std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; +} + +void Dog::~Dog() +{ + cout << "Goodbye " << name << "\n"; +} + +void Dog::setWeight(int dogsWeight) +{ + weight = dogsWeight; +} + +// 虛函數的virtual關鍵字只需要在聲明時使用,不需要在定義時重複 void Dog::print() const { std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; @@ -427,17 +443,17 @@ int main () { // 異常處理 /////////// -// 標準庫中提供了a few exception types +// 標準庫中提供了一些基本的異常類型 // (參見http://en.cppreference.com/w/cpp/error/exception) -// 【but any type can be thrown an as exception +// 但是,其他任何類型也可以作爲一個異常被拋出 #include // 在_try_代碼塊中拋出的異常可以被隨後的_catch_捕獲。 try { - // 【Do not allocate exceptions on the heap using _new_. + // 不要用 _new_關鍵字在堆上爲異常分配空間。 throw std::exception("A problem occurred"); } -// 【Catch exceptions by const reference if they are objects +// 如果拋出的異常是一個對象,可以用常量引用來捕獲它 catch (const std::exception& ex) { std::cout << ex.what(); @@ -452,10 +468,10 @@ catch (const std::exception& ex) // RAII /////// -// RAII指的是「资源获取就是初始化」(Resource Allocation Is Initialization)。 -// 【It is often considered the most powerful paradigm in C++, -// and is the simple concept that a constructor for an object -// acquires that object's resources and the destructor releases them. +// RAII指的是「资源获取就是初始化」(Resource Allocation Is Initialization), +// 它被視作C++中最強大的編程範式之一。 +// 簡單說來,它指的是,用構造函數來獲取一個對象的資源, +// 相應的,借助析構函數來釋放對象的資源。 // 爲了理解這一範式的用處,讓我們考慮某個函數使用文件句柄時的情況: void doSomethingWithAFile(const char* filename) @@ -517,8 +533,8 @@ failure: return false; // 反饋錯誤 } -// 【If the functions indicate errors using exceptions, -// things are a little cleaner, but still sub-optimal. +// 如果用異常捕獲機制來指示錯誤的話, +// 代碼會變得清晰一些,但是仍然有優化的餘地。 void doSomethingWithAFile(const char* filename) { FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 @@ -556,17 +572,15 @@ void doSomethingWithAFile(const std::string& filename) // 與上面幾種方式相比,這種方式有着_明顯_的優勢: // 1. 無論發生了什麼情況,資源(此例當中是文件句柄)都會被正確關閉。 // 只要你正確使用了析構器,就_不會_因爲忘記關閉句柄,造成資源的泄漏。 -// 2. 【Note that the code is much cleaner. -// The destructor handles closing the file behind the scenes -// without you having to worry about it. +// 2. 可以注意到,通過這種方式寫出來的代碼十分簡潔。 +// 析構器會在後臺關閉文件句柄,不再需要你來操心這些瑣事。 // 3. 【The code is exception safe. -// An exception can be thrown anywhere in the function and cleanup -// will still occur. +// 無論在函數中的何處拋出異常,都不會阻礙對文件資源的釋放。 -// 地道的C++代碼應當把RAII的使用擴展到所有類型的資源上,包括: +// 地道的C++代碼應當把RAII的使用擴展到各種類型的資源上,包括: // - 用unique_ptr和shared_ptr管理的內存 -// - 容器,例如標準庫中的鏈表、向量(容量自動擴展的數組)、散列表等; -// 【all automatically destroy their contents when they fall out of scope. +// - 各種數據容器,例如標準庫中的鏈表、向量(容量自動擴展的數組)、散列表等; +// 當它們脫離作用域時,析構器會自動釋放其中儲存的內容。 // - 用lock_guard和unique_lock實現的互斥 ``` 擴展閱讀: -- cgit v1.2.3 From cfe726561dd27cf74aaf966eae4cf6f5b5556812 Mon Sep 17 00:00:00 2001 From: yukirock Date: Thu, 19 Mar 2015 18:36:10 +1100 Subject: Improve zh-ch translation. --- zh-cn/haskell-cn.html.markdown | 234 ++++++++++++++++++++--------------------- 1 file changed, 116 insertions(+), 118 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index cb7ccdee..fae8a456 100644 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -5,24 +5,24 @@ contributors: - ["Adit Bhargava", "http://adit.io"] translators: - ["Peiyong Lin", ""] + - ["chad luo", "http://yuki.rocks"] lang: zh-cn --- -Haskell 被设计成一种实用的纯函数式编程语言。它因为 monads 及其类型系统而出名,但是我回归到它本身因为。Haskell 使得编程对于我而言是一种真正的快乐。 +Haskell 是一门实用的函数式编程语言,因其 Monads 与类型系统而闻名。而我使用它则是因为它异常优雅。用 Haskell 编程令我感到非常快乐。 ```haskell --- 单行注释以两个破折号开头 -{- 多行注释像这样 - 被一个闭合的块包围 +-- 单行注释以两个减号开头 +{- 多行注释像这样被一个闭合的块包围 -} ---------------------------------------------------- -- 1. 简单的数据类型和操作符 ---------------------------------------------------- --- 你有数字 +-- 数字 3 -- 3 --- 数学计算就像你所期待的那样 +-- 数学计算 1 + 1 -- 2 8 - 1 -- 7 10 * 2 -- 20 @@ -34,7 +34,7 @@ Haskell 被设计成一种实用的纯函数式编程语言。它因为 monads -- 整除 35 `div` 4 -- 8 --- 布尔值也简单 +-- 布尔值 True False @@ -45,73 +45,80 @@ not False -- True 1 /= 1 -- False 1 < 10 -- True --- 在上述的例子中,`not` 是一个接受一个值的函数。 --- Haskell 不需要括号来调用函数。。。所有的参数 --- 都只是在函数名之后列出来。因此,通常的函数调用模式是: +-- 在上面的例子中,`not` 是一个接受一个参数的函数。 +-- Haskell 不需要括号来调用函数。所有的参数都只是在函数名之后列出来。 +-- 因此,通常的函数调用模式是: -- func arg1 arg2 arg3... --- 查看关于函数的章节以获得如何写你自己的函数的相关信息。 +-- 你可以查看函数部分了解如何自行编写。 -- 字符串和字符 -"This is a string." +"This is a string." -- 字符串 'a' -- 字符 '对于字符串你不能使用单引号。' -- 错误! --- 连结字符串 +-- 连接字符串 "Hello " ++ "world!" -- "Hello world!" -- 一个字符串是一系列字符 +['H', 'e', 'l', 'l', 'o'] -- "Hello" "This is a string" !! 0 -- 'T' ---------------------------------------------------- --- 列表和元组 +-- 数组和元组 ---------------------------------------------------- --- 一个列表中的每一个元素都必须是相同的类型 --- 下面两个列表一样 +-- 一个数组中的每一个元素都必须是相同的类型 +-- 下面两个数组等价: [1, 2, 3, 4, 5] [1..5] --- 在 Haskell 你可以拥有含有无限元素的列表 -[1..] -- 一个含有所有自然数的列表 +-- 区间也可以这样 +['A'..'F'] -- "ABCDEF" --- 因为 Haskell 有“懒惰计算”,所以无限元素的列表可以正常运作。这意味着 --- Haskell 可以只在它需要的时候计算。所以你可以请求 --- 列表中的第1000个元素,Haskell 会返回给你 +-- 你可以在区间中指定步进 +[0,2..10] -- [0, 2, 4, 6, 8, 10] +[5..1] -- 这样不行,因为 Haskell 默认递增 +[5,4..1] -- [5, 4, 3, 2, 1] + +-- 数组下标 +[0..] !! 5 -- 5 + +-- 在 Haskell 你可以使用无限数组 +[1..] -- 一个含有所有自然数的数组 + +-- 无限数组的原理是,Haskell 有“惰性求值”。 +-- 这意味着 Haskell 只在需要时才会计算。 +-- 所以当你获取数组的第 1000 项元素时,Haskell 会返回给你: [1..] !! 999 -- 1000 --- Haskell 计算了列表中 1 - 1000 个元素。。。但是 --- 这个无限元素的列表中剩下的元素还不存在! Haskell 不会 --- 真正地计算它们知道它需要。 +-- Haskell 计算了数组中第 1 至 1000 项元素,但这个无限数组中剩下的元素还不存在。 +-- Haskell 只有在需要时才会计算它们。 -- 连接两个列表 +-- 连接两个数组 [1..5] ++ [6..10] --- 往列表头增加元素 +-- 往数组头增加元素 0:[1..5] -- [0, 1, 2, 3, 4, 5] --- 列表中的下标 -[0..] !! 5 -- 5 - --- 更多列表操作 +-- 其它数组操作 head [1..5] -- 1 tail [1..5] -- [2, 3, 4, 5] init [1..5] -- [1, 2, 3, 4] last [1..5] -- 5 --- 列表推导 +-- 数组推导 [x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10] -- 附带条件 [x*2 | x <-[1..5], x*2 > 4] -- [6, 8, 10] --- 元组中的每一个元素可以是不同类型的,但是一个元组 --- 的长度是固定的 +-- 元组中的每一个元素可以是不同类型,但是一个元组的长度是固定的 -- 一个元组 ("haskell", 1) --- 获取元组中的元素 +-- 获取元组中的元素(例如,一个含有 2 个元素的元祖) fst ("haskell", 1) -- "haskell" snd ("haskell", 1) -- 1 @@ -121,31 +128,28 @@ snd ("haskell", 1) -- 1 -- 一个接受两个变量的简单函数 add a b = a + b --- 注意,如果你使用 ghci (Hakell 解释器) --- 你将需要使用 `let`,也就是 +-- 注意,如果你使用 ghci (Hakell 解释器),你需要使用 `let`,也就是 -- let add a b = a + b --- 使用函数 +-- 调用函数 add 1 2 -- 3 --- 你也可以把函数放置在两个参数之间 --- 附带倒引号: +-- 你也可以使用反引号中置函数名: 1 `add` 2 -- 3 --- 你也可以定义不带字符的函数!这使得 --- 你定义自己的操作符!这里有一个操作符 --- 来做整除 +-- 你也可以定义不带字母的函数名,这样你可以定义自己的操作符 +-- 这里有一个做整除的操作符 (//) a b = a `div` b 35 // 4 -- 8 --- 守卫:一个简单的方法在函数里做分支 +-- Guard:一个在函数中做条件判断的简单方法 fib x | x < 2 = x | otherwise = fib (x - 1) + fib (x - 2) --- 模式匹配是类型的。这里有三种不同的 fib --- 定义。Haskell 将自动调用第一个 --- 匹配值的模式的函数。 +-- 模式匹配与 Guard 类似 +-- 这里给出了三个不同的 fib 定义 +-- Haskell 会自动调用第一个符合参数模式的声明 fib 1 = 1 fib 2 = 2 fib x = fib (x - 1) + fib (x - 2) @@ -153,76 +157,76 @@ fib x = fib (x - 1) + fib (x - 2) -- 元组的模式匹配: foo (x, y) = (x + 1, y + 2) --- 列表的模式匹配。这里 `x` 是列表中第一个元素, --- 并且 `xs` 是列表剩余的部分。我们可以写 --- 自己的 map 函数: +-- 数组的模式匹配 +-- 这里 `x` 是列表中第一个元素,`xs` 是列表剩余的部分 +-- 我们可以实现自己的 map 函数: myMap func [] = [] myMap func (x:xs) = func x:(myMap func xs) --- 编写出来的匿名函数带有一个反斜杠,后面跟着 --- 所有的参数。 +-- 匿名函数带有一个反斜杠,后面跟着所有的参数。 myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7] --- 使用 fold (在一些语言称为`inject`)随着一个匿名的 --- 函数。foldl1 意味着左折叠(fold left), 并且使用列表中第一个值 --- 作为累加器的初始化值。 +-- 在 fold(在一些语言称 为`inject`)中使用匿名函数 +-- foldl1 意味着左折叠 (fold left), 并且使用列表中第一个值作为累加器的初始值 foldl1 (\acc x -> acc + x) [1..5] -- 15 ---------------------------------------------------- --- 4. 更多的函数 +-- 4. 其它函数 ---------------------------------------------------- --- 柯里化(currying):如果你不传递函数中所有的参数, --- 它就变成“柯里化的”。这意味着,它返回一个接受剩余参数的函数。 - +-- 部分调用: +-- 如果你调用函数时没有给出所有参数,它就被“部分调用” +-- 它将返回一个接受余下参数的函数 add a b = a + b foo = add 10 -- foo 现在是一个接受一个数并对其加 10 的函数 foo 5 -- 15 --- 另外一种方式去做同样的事 +-- 另一种等价写法 foo = (+10) foo 5 -- 15 -- 函数组合 -- (.) 函数把其它函数链接到一起 --- 举个列子,这里 foo 是一个接受一个值的函数。它对接受的值加 10, --- 并对结果乘以 5,之后返回最后的值。 +-- 例如,这里 foo 是一个接受一个值的函数。 +-- 它对接受的值加 10,并对结果乘以 5,之后返回最后的值。 foo = (*5) . (+10) -- (5 + 10) * 5 = 75 foo 5 -- 75 --- 修复优先级 --- Haskell 有另外一个函数称为 `$`。它改变优先级 --- 使得其左侧的每一个操作先计算然后应用到 --- 右侧的每一个操作。你可以使用 `.` 和 `$` 来除去很多 --- 括号: +-- 修正优先级 +-- Haskell 有另外一个函数 `$` 可以改变优先级 +-- `$` 使得 Haskell 先计算其右边的部分,然后调用左边的部分 +-- 你可以使用 `$` 来移除多余的括号 --- before +-- 修改前 (even (fib 7)) -- true --- after +-- 修改后 even . fib $ 7 -- true +-- 等价地 +even $ fib 7 -- true + ---------------------------------------------------- --- 5. 类型签名 +-- 5. 类型声明 ---------------------------------------------------- --- Haskell 有一个非常强壮的类型系统,一切都有一个类型签名。 +-- Haskell 有一个非常强大的类型系统,一切都有一个类型声明。 -- 一些基本的类型: 5 :: Integer "hello" :: String True :: Bool --- 函数也有类型。 +-- 函数也有类型 -- `not` 接受一个布尔型返回一个布尔型: -- not :: Bool -> Bool -- 这是接受两个参数的函数: -- add :: Integer -> Integer -> Integer --- 当你定义一个值,在其上写明它的类型是一个好实践: +-- 当你定义一个值,声明其类型是一个好做法: double :: Integer -> Integer double x = x * 2 @@ -230,29 +234,30 @@ double x = x * 2 -- 6. 控制流和 If 语句 ---------------------------------------------------- --- if 语句 +-- if 语句: haskell = if 1 == 1 then "awesome" else "awful" -- haskell = "awesome" --- if 语句也可以有多行,缩进是很重要的 +-- if 语句也可以有多行,注意缩进: haskell = if 1 == 1 then "awesome" else "awful" --- case 语句:这里是你可以怎样去解析命令行参数 +-- case 语句 +-- 解析命令行参数: case args of "help" -> printHelp "start" -> startProgram _ -> putStrLn "bad args" --- Haskell 没有循环因为它使用递归取代之。 --- map 应用一个函数到一个数组中的每一个元素 +-- Haskell 没有循环,它使用递归 +-- map 对一个数组中的每一个元素调用一个函数: map (*2) [1..5] -- [2, 4, 6, 8, 10] --- 你可以使用 map 来编写 for 函数 +-- 你可以使用 map 来编写 for 函数: for array func = map func array --- 然后使用它 +-- 调用: for [0..5] $ \i -> show i -- 我们也可以像这样写: @@ -262,36 +267,32 @@ for [0..5] show -- foldl foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43 --- 这和下面是一样的 +-- 等价于: (2 * (2 * (2 * 4 + 1) + 2) + 3) --- foldl 是左手边的,foldr 是右手边的- +-- foldl 从左开始,foldr 从右: foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 --- 这和下面是一样的 +-- 现在它等价于: (2 * 3 + (2 * 2 + (2 * 1 + 4))) ---------------------------------------------------- -- 7. 数据类型 ---------------------------------------------------- --- 这里展示在 Haskell 中你怎样编写自己的数据类型 - +-- 在 Haskell 中声明你自己的数据类型: data Color = Red | Blue | Green -- 现在你可以在函数中使用它: - - say :: Color -> String say Red = "You are Red!" say Blue = "You are Blue!" say Green = "You are Green!" -- 你的数据类型也可以有参数: - data Maybe a = Nothing | Just a --- 类型 Maybe 的所有 +-- 这些都是 Maybe 类型: Just "hello" -- of type `Maybe String` Just 1 -- of type `Maybe Int` Nothing -- of type `Maybe a` for any `a` @@ -300,58 +301,54 @@ Nothing -- of type `Maybe a` for any `a` -- 8. Haskell IO ---------------------------------------------------- --- 虽然在没有解释 monads 的情况下 IO不能被完全地解释, --- 着手解释到位并不难。 - --- 当一个 Haskell 程序被执行,函数 `main` 就被调用。 --- 它必须返回一个类型 `IO ()` 的值。举个列子: +-- 虽然不解释 Monads 就无法完全解释 IO,但大致了解并不难。 +-- 当执行一个 Haskell 程序时,函数 `main` 就被调用。 +-- 它必须返回一个类型 `IO ()` 的值。例如: main :: IO () main = putStrLn $ "Hello, sky! " ++ (say Blue) --- putStrLn has type String -> IO () +-- putStrLn 的类型是 String -> IO () --- 如果你能实现你的程序依照函数从 String 到 String,那样编写 IO 是最简单的。 +-- 如果你的程序输入 String 返回 String,那样编写 IO 是最简单的。 -- 函数 -- interact :: (String -> String) -> IO () --- 输入一些文本,在其上运行一个函数,并打印出输出 +-- 输入一些文本,对其调用一个函数,并打印输出。 countLines :: String -> String countLines = show . length . lines main' = interact countLines --- 你可以考虑一个 `IO()` 类型的值,当做一系列计算机所完成的动作的代表, --- 就像一个以命令式语言编写的计算机程序。我们可以使用 `do` 符号来把动作链接到一起。 +-- 你可以认为一个 `IO ()` 类型的值是表示计算机做的一系列操作,类似命令式语言。 +-- 我们可以使用 `do` 声明来把动作连接到一起。 -- 举个列子: - sayHello :: IO () sayHello = do putStrLn "What is your name?" - name <- getLine -- this gets a line and gives it the name "input" + name <- getLine -- 这里接受一行输入并绑定至 "name" putStrLn $ "Hello, " ++ name -- 练习:编写只读取一行输入的 `interact` -- 然而,`sayHello` 中的代码将不会被执行。唯一被执行的动作是 `main` 的值。 --- 为了运行 `sayHello`,注释上面 `main` 的定义,并代替它: +-- 为了运行 `sayHello`,注释上面 `main` 的定义,替换为: -- main = sayHello --- 让我们来更好地理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是: +-- 让我们来更进一步理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是: -- getLine :: IO String --- 你可以考虑一个 `IO a` 类型的值,代表一个当被执行的时候 --- 将产生一个 `a` 类型的值的计算机程序(除了它所做的任何事之外)。我们可以保存和重用这个值通过 `<-`。 --- 我们也可以写自己的 `IO String` 类型的动作: - +-- 你可以认为一个 `IO a` 类型的值代表了一个运行时会生成一个 `a` 类型值的程序(可能还有其它行为)。 +-- 我们可以通过 `<-` 保存和重用这个值。 +-- 我们也可以实现自己的 `IO String` 类型函数: action :: IO String action = do putStrLn "This is a line. Duh" input1 <- getLine input2 <- getLine - -- The type of the `do` statement is that of its last line. - -- `return` is not a keyword, but merely a function + -- `do` 语句的类型是它的最后一行 + -- `return` 不是关键字,只是一个普通函数 return (input1 ++ "\n" ++ input2) -- return :: String -> IO String --- 我们可以使用这个动作就像我们使用 `getLine`: +-- 我们可以像调用 `getLine` 一样调用它: main'' = do putStrLn "I will echo two lines!" @@ -359,18 +356,19 @@ main'' = do putStrLn result putStrLn "This was all, folks!" --- `IO` 类型是一个 "monad" 的例子。Haskell 使用一个 monad 来做 IO的方式允许它是一门纯函数式语言。 --- 任何与外界交互的函数(也就是 IO) 都在它的类型签名处做一个 `IO` 标志 --- 着让我们推出 什么样的函数是“纯洁的”(不与外界交互,不修改状态) 和 什么样的函数不是 “纯洁的” +-- `IO` 类型是一个 "Monad" 的例子。 +-- Haskell 通过使用 Monad 使得其本身为纯函数式语言。 +-- 任何与外界交互的函数(即 IO)都在它的类型声明中标记为 `IO` +-- 这告诉我们什么样的函数是“纯洁的”(不与外界交互,不修改状态) ,什么样的函数不是 “纯洁的” --- 这是一个强有力的特征,因为并发地运行纯函数是简单的;因此,Haskell 中并发是非常简单的。 +-- 这个功能非常强大,因为纯函数并发非常容易,由此在 Haskell 中做并发非常容易。 ---------------------------------------------------- --- 9. The Haskell REPL +-- 9. Haskell REPL ---------------------------------------------------- --- 键入 `ghci` 开始 repl。 +-- 键入 `ghci` 开始 REPL。 -- 现在你可以键入 Haskell 代码。 -- 任何新值都需要通过 `let` 来创建: @@ -390,7 +388,7 @@ Hello, Friend! ``` -还有很多关于 Haskell,包括类型类和 monads。这些是使得编码 Haskell 是如此有趣的主意。我用一个最后的 Haskell 例子来结束:一个 Haskell 的快排实现: +Haskell 还有许多内容,包括类型类 (typeclasses) 与 Monads。这些都是令 Haskell 编程非常有趣的好东西。我们最后给出 Haskell 的一个例子,一个快速排序的实现: ```haskell qsort [] = [] @@ -399,9 +397,9 @@ qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater greater = filter (>= p) xs ``` -安装 Haskell 是简单的。你可以从[这里](http://www.haskell.org/platform/)获得它。 +安装 Haskell 很简单。你可以[从这里获得](http://www.haskell.org/platform/)。 你可以从优秀的 [Learn you a Haskell](http://learnyouahaskell.com/) 或者 [Real World Haskell](http://book.realworldhaskell.org/) -找到优雅不少的入门介绍。 +找到更平缓的入门介绍。 -- cgit v1.2.3 From f94fd7356adcf034f97256d2ce575f240a50d4b8 Mon Sep 17 00:00:00 2001 From: chadluo Date: Mon, 23 Mar 2015 01:54:46 +1100 Subject: fixed translation --- zh-cn/haskell-cn.html.markdown | 117 ++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 61 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/haskell-cn.html.markdown b/zh-cn/haskell-cn.html.markdown index fae8a456..8904970f 100644 --- a/zh-cn/haskell-cn.html.markdown +++ b/zh-cn/haskell-cn.html.markdown @@ -13,7 +13,8 @@ Haskell 是一门实用的函数式编程语言,因其 Monads 与类型系统 ```haskell -- 单行注释以两个减号开头 -{- 多行注释像这样被一个闭合的块包围 +{- 多行注释像这样 + 被一个闭合的块包围 -} ---------------------------------------------------- @@ -46,9 +47,9 @@ not False -- True 1 < 10 -- True -- 在上面的例子中,`not` 是一个接受一个参数的函数。 --- Haskell 不需要括号来调用函数。所有的参数都只是在函数名之后列出来。 +-- Haskell 不需要括号来调用函数,所有的参数都只是在函数名之后列出来 -- 因此,通常的函数调用模式是: --- func arg1 arg2 arg3... +-- func arg1 arg2 arg3... -- 你可以查看函数部分了解如何自行编写。 -- 字符串和字符 @@ -65,11 +66,11 @@ not False -- True ---------------------------------------------------- --- 数组和元组 +-- 列表和元组 ---------------------------------------------------- --- 一个数组中的每一个元素都必须是相同的类型 --- 下面两个数组等价: +-- 一个列表中的每一个元素都必须是相同的类型。 +-- 下面两个列表等价 [1, 2, 3, 4, 5] [1..5] @@ -81,34 +82,32 @@ not False -- True [5..1] -- 这样不行,因为 Haskell 默认递增 [5,4..1] -- [5, 4, 3, 2, 1] --- 数组下标 +-- 列表下标 [0..] !! 5 -- 5 --- 在 Haskell 你可以使用无限数组 -[1..] -- 一个含有所有自然数的数组 +-- 在 Haskell 你可以使用无限列表 +[1..] -- 一个含有所有自然数的列表 --- 无限数组的原理是,Haskell 有“惰性求值”。 +-- 无限列表的原理是,Haskell 有“惰性求值”。 -- 这意味着 Haskell 只在需要时才会计算。 --- 所以当你获取数组的第 1000 项元素时,Haskell 会返回给你: - +-- 所以当你获取列表的第 1000 项元素时,Haskell 会返回给你: [1..] !! 999 -- 1000 - --- Haskell 计算了数组中第 1 至 1000 项元素,但这个无限数组中剩下的元素还不存在。 +-- Haskell 计算了列表中第 1 至 1000 项元素,但这个无限列表中剩下的元素还不存在。 -- Haskell 只有在需要时才会计算它们。 --- 连接两个数组 +-- 连接两个列表 [1..5] ++ [6..10] --- 往数组头增加元素 +-- 往列表头增加元素 0:[1..5] -- [0, 1, 2, 3, 4, 5] --- 其它数组操作 +-- 其它列表操作 head [1..5] -- 1 tail [1..5] -- [2, 3, 4, 5] init [1..5] -- [1, 2, 3, 4] last [1..5] -- 5 --- 数组推导 +-- 列表推导 (list comprehension) [x*2 | x <- [1..5]] -- [2, 4, 6, 8, 10] -- 附带条件 @@ -125,6 +124,7 @@ snd ("haskell", 1) -- 1 ---------------------------------------------------- -- 3. 函数 ---------------------------------------------------- + -- 一个接受两个变量的简单函数 add a b = a + b @@ -137,7 +137,7 @@ add 1 2 -- 3 -- 你也可以使用反引号中置函数名: 1 `add` 2 -- 3 --- 你也可以定义不带字母的函数名,这样你可以定义自己的操作符 +-- 你也可以定义不带字母的函数名,这样你可以定义自己的操作符。 -- 这里有一个做整除的操作符 (//) a b = a `div` b 35 // 4 -- 8 @@ -147,36 +147,36 @@ fib x | x < 2 = x | otherwise = fib (x - 1) + fib (x - 2) --- 模式匹配与 Guard 类似 --- 这里给出了三个不同的 fib 定义 +-- 模式匹配与 Guard 类似。 +-- 这里给出了三个不同的 fib 定义。 -- Haskell 会自动调用第一个符合参数模式的声明 fib 1 = 1 fib 2 = 2 fib x = fib (x - 1) + fib (x - 2) --- 元组的模式匹配: +-- 元组的模式匹配 foo (x, y) = (x + 1, y + 2) --- 数组的模式匹配 --- 这里 `x` 是列表中第一个元素,`xs` 是列表剩余的部分 +-- 列表的模式匹配 +-- 这里 `x` 是列表中第一个元素,`xs` 是列表剩余的部分。 -- 我们可以实现自己的 map 函数: myMap func [] = [] myMap func (x:xs) = func x:(myMap func xs) --- 匿名函数带有一个反斜杠,后面跟着所有的参数。 +-- 匿名函数带有一个反斜杠,后面跟着所有的参数 myMap (\x -> x + 2) [1..5] -- [3, 4, 5, 6, 7] -- 在 fold(在一些语言称 为`inject`)中使用匿名函数 --- foldl1 意味着左折叠 (fold left), 并且使用列表中第一个值作为累加器的初始值 +-- foldl1 意味着左折叠 (fold left), 并且使用列表中第一个值作为累加器的初始值。 foldl1 (\acc x -> acc + x) [1..5] -- 15 ---------------------------------------------------- -- 4. 其它函数 ---------------------------------------------------- --- 部分调用: --- 如果你调用函数时没有给出所有参数,它就被“部分调用” --- 它将返回一个接受余下参数的函数 +-- 部分调用 +-- 如果你调用函数时没有给出所有参数,它就被“部分调用”。 +-- 它将返回一个接受余下参数的函数。 add a b = a + b foo = add 10 -- foo 现在是一个接受一个数并对其加 10 的函数 foo 5 -- 15 @@ -185,8 +185,8 @@ foo 5 -- 15 foo = (+10) foo 5 -- 15 --- 函数组合 --- (.) 函数把其它函数链接到一起 +-- 函列表合 +-- (.) 函数把其它函数链接到一起。 -- 例如,这里 foo 是一个接受一个值的函数。 -- 它对接受的值加 10,并对结果乘以 5,之后返回最后的值。 foo = (*5) . (+10) @@ -195,9 +195,9 @@ foo = (*5) . (+10) foo 5 -- 75 -- 修正优先级 --- Haskell 有另外一个函数 `$` 可以改变优先级 --- `$` 使得 Haskell 先计算其右边的部分,然后调用左边的部分 --- 你可以使用 `$` 来移除多余的括号 +-- Haskell 有另外一个函数 `$` 可以改变优先级。 +-- `$` 使得 Haskell 先计算其右边的部分,然后调用左边的部分。 +-- 你可以使用 `$` 来移除多余的括号。 -- 修改前 (even (fib 7)) -- true @@ -220,13 +220,13 @@ even $ fib 7 -- true True :: Bool -- 函数也有类型 --- `not` 接受一个布尔型返回一个布尔型: +-- `not` 接受一个布尔型返回一个布尔型 -- not :: Bool -> Bool --- 这是接受两个参数的函数: +-- 这是接受两个参数的函数 -- add :: Integer -> Integer -> Integer --- 当你定义一个值,声明其类型是一个好做法: +-- 当你定义一个值,声明其类型是一个好做法 double :: Integer -> Integer double x = x * 2 @@ -250,30 +250,29 @@ case args of _ -> putStrLn "bad args" -- Haskell 没有循环,它使用递归 --- map 对一个数组中的每一个元素调用一个函数: - +-- map 对一个列表中的每一个元素调用一个函数 map (*2) [1..5] -- [2, 4, 6, 8, 10] --- 你可以使用 map 来编写 for 函数: +-- 你可以使用 map 来编写 for 函数 for array func = map func array --- 调用: +-- 调用 for [0..5] $ \i -> show i --- 我们也可以像这样写: +-- 我们也可以像这样写 for [0..5] show -- 你可以使用 foldl 或者 foldr 来分解列表 -- foldl foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43 --- 等价于: +-- 等价于 (2 * (2 * (2 * 4 + 1) + 2) + 3) --- foldl 从左开始,foldr 从右: +-- foldl 从左开始,foldr 从右 foldr (\x y -> 2*x + y) 4 [1,2,3] -- 16 --- 现在它等价于: +-- 现在它等价于 (2 * 3 + (2 * 2 + (2 * 1 + 4))) ---------------------------------------------------- @@ -293,9 +292,9 @@ say Green = "You are Green!" data Maybe a = Nothing | Just a -- 这些都是 Maybe 类型: -Just "hello" -- of type `Maybe String` -Just 1 -- of type `Maybe Int` -Nothing -- of type `Maybe a` for any `a` +Just "hello" -- `Maybe String` 类型 +Just 1 -- `Maybe Int` 类型 +Nothing -- 对任意 `a` 为 `Maybe a` 类型 ---------------------------------------------------- -- 8. Haskell IO @@ -321,7 +320,7 @@ main' = interact countLines -- 你可以认为一个 `IO ()` 类型的值是表示计算机做的一系列操作,类似命令式语言。 -- 我们可以使用 `do` 声明来把动作连接到一起。 --- 举个列子: +-- 举个列子 sayHello :: IO () sayHello = do putStrLn "What is your name?" @@ -336,7 +335,8 @@ sayHello = do -- 让我们来更进一步理解刚才所使用的函数 `getLine` 是怎样工作的。它的类型是: -- getLine :: IO String --- 你可以认为一个 `IO a` 类型的值代表了一个运行时会生成一个 `a` 类型值的程序(可能还有其它行为)。 +-- 你可以认为一个 `IO a` 类型的值代表了一个运行时会生成一个 `a` 类型值的程序。 +-- (可能伴随其它行为) -- 我们可以通过 `<-` 保存和重用这个值。 -- 我们也可以实现自己的 `IO String` 类型函数: action :: IO String @@ -348,8 +348,7 @@ action = do -- `return` 不是关键字,只是一个普通函数 return (input1 ++ "\n" ++ input2) -- return :: String -> IO String --- 我们可以像调用 `getLine` 一样调用它: - +-- 我们可以像调用 `getLine` 一样调用它 main'' = do putStrLn "I will echo two lines!" result <- action @@ -358,29 +357,25 @@ main'' = do -- `IO` 类型是一个 "Monad" 的例子。 -- Haskell 通过使用 Monad 使得其本身为纯函数式语言。 --- 任何与外界交互的函数(即 IO)都在它的类型声明中标记为 `IO` --- 这告诉我们什么样的函数是“纯洁的”(不与外界交互,不修改状态) ,什么样的函数不是 “纯洁的” - +-- 任何与外界交互的函数(即 IO)都在它的类型声明中标记为 `IO`。 +-- 这告诉我们什么样的函数是“纯洁的”(不与外界交互,不修改状态) , +-- 什么样的函数不是 “纯洁的”。 -- 这个功能非常强大,因为纯函数并发非常容易,由此在 Haskell 中做并发非常容易。 - ---------------------------------------------------- -- 9. Haskell REPL ---------------------------------------------------- -- 键入 `ghci` 开始 REPL。 -- 现在你可以键入 Haskell 代码。 --- 任何新值都需要通过 `let` 来创建: - +-- 任何新值都需要通过 `let` 来创建 let foo = 5 --- 你可以查看任何值的类型,通过命令 `:t`: - +-- 你可以通过命令 `:t` 查看任何值的类型 >:t foo foo :: Integer -- 你也可以运行任何 `IO ()`类型的动作 - > sayHello What is your name? Friend! -- cgit v1.2.3 From cb69cff1be0b22942a29a076d7cabec3fbb5467f Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Sat, 11 Apr 2015 12:31:11 +0800 Subject: [c++/cn] Complete the whole translation. --- zh-cn/c++-cn.html.markdown | 410 ++++++++++++++++++++++----------------------- 1 file changed, 205 insertions(+), 205 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index 24d2a1b8..cbf89c38 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -9,66 +9,66 @@ translators: lang: zh-cn --- -C++是一種系統編程語言。用它的發明者, -[Bjarne Stroustrup的話](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)來說,C++的設計目標是: +C++是一种系统编程语言。用它的发明者, +[Bjarne Stroustrup的话](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote)来说,C++的设计目标是: -- 成爲「更好的C語言」 -- 支持數據的抽象與封裝 -- 支持面向對象編程 -- 支持泛型編程 +- 成为“更好的C语言” +- 支持数据的抽象与封装 +- 支持面向对象编程 +- 支持泛型编程 -C++提供了對硬件的緊密控制(正如C語言一樣), -能夠編譯爲機器語言,由處理器直接執行。 -與此同時,它也提供了泛型、異常和類等高層功能。 -雖然C++的語法可能比某些出現較晚的語言更複雜,它仍然得到了人們的青睞—— -功能與速度的平衡使C++成爲了目前應用最廣泛的系統編程語言之一。 +C++提供了对硬件的紧密控制(正如C语言一样), +能够编译为机器语言,由处理器直接执行。 +与此同时,它也提供了泛型、异常和类等高层功能。 +虽然C++的语法可能比某些出现较晚的语言更复杂,它仍然得到了人们的青睞—— +功能与速度的平衡使C++成为了目前应用最广泛的系统编程语言之一。 ```c++ //////////////// -// 與C語言的比較 +// 与C语言的比较 //////////////// -// C++_幾乎_是C語言的一個超集,它與C語言的基本語法有許多相同之處, -// 例如變量和函數的聲明,原生數據類型等等。 +// C++_几乎_是C语言的一个超集,它与C语言的基本语法有许多相同之处, +// 例如变量和函数的声明,原生数据类型等等。 -// 和C語言一樣,在C++中,你的程序會從main()開始執行, -// 該函數的返回值應當爲int型,這個返回值會作爲程序的退出狀態值。 -// 不過,大多數的編譯器(gcc,clang等)也接受 void main() 的函數原型。 -// (參見 http://en.wikipedia.org/wiki/Exit_status 來獲取更多信息) +// 和C语言一样,在C++中,你的程序会从main()开始执行, +// 该函数的返回值应当为int型,这个返回值会作为程序的退出状态值。 +// 不过,大多数的编译器(gcc,clang等)也接受 void main() 的函数原型。 +// (参见 http://en.wikipedia.org/wiki/Exit_status 来获取更多信息) int main(int argc, char** argv) { - // 和C語言一樣,命令行參數通過argc和argv傳遞。 - // argc代表命令行參數的數量, - // 而argv是一個包含「C語言風格字符串」(char *)的數組, - // 其中每個字符串代表一個命令行參數的內容, - // 首個命令行參數是調用該程序時所使用的名稱。 - // 如果你不關心命令行參數的值,argc和argv可以被忽略。 - // 此時,你可以用int main()作爲函數原型。 - - // 退出狀態值爲0時,表示程序執行成功 + // 和C语言一样,命令行参数通过argc和argv传递。 + // argc代表命令行参数的数量, + // 而argv是一个包含“C语言风格字符串”(char *)的数组, + // 其中每个字符串代表一个命令行参数的内容, + // 首个命令行参数是调用该程序时所使用的名称。 + // 如果你不关心命令行参数的值,argc和argv可以被忽略。 + // 此时,你可以用int main()作为函数原型。 + + // 退出状态值为0时,表示程序执行成功 return 0; } -// 然而,C++和C語言也有一些區別: +// 然而,C++和C语言也有一些区别: -// 在C++中,字符字面量的大小是一個字節。 +// 在C++中,字符字面量的大小是一个字节。 sizeof('c') == 1 -// 在C語言中,字符字面量的大小與int相同。 +// 在C语言中,字符字面量的大小与int相同。 sizeof('c') == sizeof(10) -// C++的函數原型與函數定義是嚴格匹配的 -void func(); // 這個函數不能接受任何參數 +// C++的函数原型与函数定义是严格匹配的 +void func(); // 这个函数不能接受任何参数 -// 而在C語言中 -void func(); // 這個函數能接受任意數量的參數 +// 而在C语言中 +void func(); // 这个函数能接受任意数量的参数 -// 在C++中,用nullptr代替C語言中的NULL +// 在C++中,用nullptr代替C语言中的NULL int* ip = nullptr; -// C++也可以使用C語言的標準頭文件, -// 但是需要加上前綴「c」並去掉末尾的「.h」。 +// C++也可以使用C语言的标准头文件, +// 但是需要加上前缀“c”并去掉末尾的“.h”。 #include int main() @@ -78,10 +78,10 @@ int main() } /////////// -// 函數重載 +// 函数重载 /////////// -// C++支持函數重載,【provided each function takes different parameters.】 +// C++支持函数重载,你可以定义一组名称相同而参数不同的函数。 void print(char const* myString) { @@ -95,20 +95,20 @@ void print(int myInt) int main() { - print("Hello"); // 解析爲 void print(const char*) - print(15); // 解析爲 void print(int) + print("Hello"); // 解析为 void print(const char*) + print(15); // 解析为 void print(int) } /////////////////// -// 函數參數的默認值 +// 函数参数的默认值 /////////////////// -// 你可以爲函數的參數指定默認值, -// 它們將會在調用者沒有提供相應參數時被使用。 +// 你可以为函数的参数指定默认值, +// 它们将会在调用者没有提供相应参数时被使用。 void doSomethingWithInts(int a = 1, int b = 4) { - // 對兩個參數進行一些操作 + // 对两个参数进行一些操作 } int main() @@ -118,19 +118,19 @@ int main() doSomethingWithInts(20, 5); // a = 20, b = 5 } -// 默認參數必須放在所有的常規參數之後。 +// 默认参数必须放在所有的常规参数之后。 -void invalidDeclaration(int a = 1, int b) // 這是錯誤的! +void invalidDeclaration(int a = 1, int b) // 这是错误的! { } /////////// -// 命名空間 +// 命名空间 /////////// -// 命名空間爲變量、函數和其他聲明提供了【separate】的作用域。 -// 命名空間可以嵌套使用。 +// 命名空间为变量、函数和其他声明提供了分离的的作用域。 +// 命名空间可以嵌套使用。 namespace First { namespace Nested { @@ -138,8 +138,8 @@ namespace First { { printf("This is First::Nested::foo\n"); } - } // 結束嵌套的命名空間Nested -} // 結束命名空間First + } // 结束嵌套的命名空间Nested +} // 结束命名空间First namespace Second { void foo() @@ -155,38 +155,38 @@ void foo() int main() { - // 如果沒有特別指定,就從「Second」中取得所需的內容。 + // 如果没有特别指定,就从“Second”中取得所需的内容。 using namespace Second; - foo(); // 顯示「This is Second::foo」 - First::Nested::foo(); // 顯示「This is First::Nested::foo」 - ::foo(); // 顯示「This is global foo」 + foo(); // 显示“This is Second::foo” + First::Nested::foo(); // 显示“This is First::Nested::foo” + ::foo(); // 显示“This is global foo” } //////////// -// 輸入/輸出 +// 输入/输出 //////////// -// C++使用「流」來輸入輸出。<<是流的插入運算符,>>是流提取運算符。 -// cin、cout、和cerr分別代表 -// stdin(標準輸入)、stdout(標準輸出)和stderr(標準錯誤)。 +// C++使用“流”来输入输出。<<是流的插入运算符,>>是流提取运算符。 +// cin、cout、和cerr分别代表 +// stdin(标准输入)、stdout(标准输出)和stderr(标准错误)。 -#include // 引入包含輸入/輸出流的頭文件 +#include // 引入包含输入/输出流的头文件 -using namespace std; // 輸入輸出流在std命名空間(也就是標準庫)中。 +using namespace std; // 输入输出流在std命名空间(也就是标准库)中。 int main() { int myInt; - // 在標準輸出(終端/顯示器)中顯示 + // 在标准输出(终端/显示器)中显示 cout << "Enter your favorite number:\n"; - // 從標準輸入(鍵盤)獲得一個值 + // 从标准输入(键盘)获得一个值 cin >> myInt; // cout也提供了格式化功能 cout << "Your favorite number is " << myInt << "\n"; - // 顯示「Your favorite number is 」 + // 显示“Your favorite number is ” cerr << "Used for error messages"; } @@ -195,20 +195,20 @@ int main() // 字符串 ///////// -// C++中的字符串是對象,它們有很多成員函數 +// C++中的字符串是对象,它们有很多成员函数 #include -using namespace std; // 字符串也在std命名空間(標準庫)中。 +using namespace std; // 字符串也在std命名空间(标准库)中。 string myString = "Hello"; string myOtherString = " World"; -// + 可以用於連接字符串。 +// + 可以用于连接字符串。 cout << myString + myOtherString; // "Hello World" cout << myString + " You"; // "Hello You" -// C++中的字符串是可變的,具有「值語義」。 +// C++中的字符串是可变的,具有“值语义”。 myString.append(" Dog"); cout << myString; // "Hello Dog" @@ -217,11 +217,11 @@ cout << myString; // "Hello Dog" // 引用 ///////////// -// 除了支持C語言中的指針類型以外,C++還提供了_引用_。 -// 引用是一種特殊的指針類型,一旦被定義就不能重新賦值,並且不能被設置爲空值。 -// 使用引用時的語法與原變量相同: -// 也就是說,對引用類型進行解引用時,不需要使用*; -// 賦值時也不需要用&來取地址。 +// 除了支持C语言中的指针类型以外,C++还提供了_引用_。 +// 引用是一种特殊的指针类型,一旦被定义就不能重新赋值,并且不能被设置为空值。 +// 使用引用时的语法与原变量相同: +// 也就是说,对引用类型进行解引用时,不需要使用*; +// 赋值时也不需要用&来取地址。 using namespace std; @@ -229,76 +229,76 @@ string foo = "I am foo"; string bar = "I am bar"; -string& fooRef = foo; // 建立了一個對foo的引用。 -fooRef += ". Hi!"; // 通過引用來修改foo的值 +string& fooRef = foo; // 建立了一个对foo的引用。 +fooRef += ". Hi!"; // 通过引用来修改foo的值 cout << fooRef; // "I am foo. Hi!" -// 這句話的並不會改變fooRef的指向,其效果與「foo = bar」相同。 -// 也就是說,在執行這條語句之後,foo == "I am bar"。 +// 这句话的并不会改变fooRef的指向,其效果与“foo = bar”相同。 +// 也就是说,在执行这条语句之后,foo == "I am bar"。 fooRef = bar; const string& barRef = bar; // 建立指向bar的常量引用。 -// 和C語言中一樣,(指針和引用)聲明爲常量時,對應的值不能被修改。 -barRef += ". Hi!"; // 這是錯誤的,不能修改一個常量引用的值。 +// 和C语言中一样,(指针和引用)声明为常量时,对应的值不能被修改。 +barRef += ". Hi!"; // 这是错误的,不能修改一个常量引用的值。 /////////////////// -// 類與面向對象編程 +// 类与面向对象编程 /////////////////// -// 有關類的第一個示例 +// 有关类的第一个示例 #include -// 聲明一個類。 -// 類通常在頭文件(.h或.hpp)中聲明。 +// 声明一个类。 +// 类通常在头文件(.h或.hpp)中声明。 class Dog { - // 成員變量和成員函數默認情況下是私有(private)的。 + // 成员变量和成员函数默认情况下是私有(private)的。 std::string name; int weight; -// 在這個標籤之後,所有聲明都是公有(public)的, -// 直到重新指定「private:」(私有繼承)或「protected:」(保護繼承)爲止 +// 在这个标签之后,所有声明都是公有(public)的, +// 直到重新指定“private:”(私有继承)或“protected:”(保护继承)为止 public: - // 默認的構造器 + // 默认的构造器 Dog(); - // 這裏是成員函數聲明的一個例子。 - // 可以注意到,我們在此處使用了std::string,而不是using namespace std - // 語句using namespace絕不應當出現在頭文件當中。 + // 这里是成员函数声明的一个例子。 + // 可以注意到,我们在此处使用了std::string,而不是using namespace std + // 语句using namespace绝不应当出现在头文件当中。 void setName(const std::string& dogsName); void setWeight(int dogsWeight); - // 如果一個函數不對對象的狀態進行修改, - // 應當在聲明中加上const。 - // 這樣,你就可以對一個以常量方式引用的對象執行該操作。 - // 同時可以注意到,當父類的成員函數需要被子類重寫時, - // 父類中的函數必須被顯式聲明爲_虛函數(virtual)_。 - // 考慮到性能方面的因素,函數默認情況下不會被聲明爲虛函數。 + // 如果一个函数不对对象的状态进行修改, + // 应当在声明中加上const。 + // 这样,你就可以对一个以常量方式引用的对象执行该操作。 + // 同时可以注意到,当父类的成员函数需要被子类重写时, + // 父类中的函数必须被显式声明为_虚函数(virtual)_。 + // 考虑到性能方面的因素,函数默认情况下不会被声明为虚函数。 virtual void print() const; - // 函數也可以在class body內部定義。 - // 這樣定義的函數會自動成爲內聯函數。 + // 函数也可以在class body内部定义。 + // 这样定义的函数会自动成为内联函数。 void bark() const { std::cout << name << " barks!\n" } - // 除了構造器以外,C++還提供了析構器。 - // 當一個對象被刪除或者脫離其定義域時時,它的析構函數會被調用。 - // 這使得RAII這樣的強大範式(參見下文)成爲可能。 - // 爲了衍生出子類來,基類的析構函數必須定義爲虛函數。 + // 除了构造器以外,C++还提供了析构器。 + // 当一个对象被删除或者脱离其定义域时时,它的析构函数会被调用。 + // 这使得RAII这样的强大范式(参见下文)成为可能。 + // 为了衍生出子类来,基类的析构函数必须定义为虚函数。 virtual ~Dog(); -}; // 在類的定義之後,要加一個分號 +}; // 在类的定义之后,要加一个分号 -}; // 記住,在類的定義之後,要加一個分號! +}; // 记住,在类的定义之后,要加一个分号! -// 類的成員函數通常在.cpp文件中實現。 +// 类的成员函数通常在.cpp文件中实现。 void Dog::Dog() { std::cout << "A dog has been constructed\n"; } -// 對象(例如字符串)應當以引用的形式傳遞, -// 對於不需要修改的對象,最好使用常量引用。 +// 对象(例如字符串)应当以引用的形式传递, +// 对于不需要修改的对象,最好使用常量引用。 void Dog::setName(const std::string& dogsName) { name = dogsName; @@ -309,7 +309,7 @@ void Dog::setWeight(int dogsWeight) weight = dogsWeight; } -// 虛函數的virtual關鍵字只需要在聲明時使用,不需要在定義時出現 +// 虚函数的virtual关键字只需要在声明时使用,不需要在定义时出现 void Dog::print() const { std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; @@ -325,7 +325,7 @@ void Dog::setWeight(int dogsWeight) weight = dogsWeight; } -// 虛函數的virtual關鍵字只需要在聲明時使用,不需要在定義時重複 +// 虚函数的virtual关键字只需要在声明时使用,不需要在定义时重复 void Dog::print() const { std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; @@ -337,32 +337,32 @@ void Dog::~Dog() } int main() { - Dog myDog; // 此時顯示「A dog has been constructed」 + Dog myDog; // 此时显示“A dog has been constructed” myDog.setName("Barkley"); myDog.setWeight(10); - myDog.printDog(); // 顯示「Dog is Barkley and weighs 10 kg」 + myDog.printDog(); // 显示“Dog is Barkley and weighs 10 kg” return 0; -} // 顯示「Goodbye Barkley」 +} // 显示“Goodbye Barkley” -// 繼承: +// 继承: -// 這個類繼承了Dog類中的公有(public)和保護(protected)對象 +// 这个类继承了Dog类中的公有(public)和保护(protected)对象 class OwnedDog : public Dog { void setOwner(const std::string& dogsOwner) - // 重寫OwnedDogs類的print方法。 - // 如果你不熟悉子類多態的話,可以參考這個頁面中的概述: + // 重写OwnedDogs类的print方法。 + // 如果你不熟悉子类多态的话,可以参考这个页面中的概述: // http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping - // override關鍵字是可選的,它確保你是在重寫基類中的方法。 + // override关键字是可选的,它确保你所重写的是基类中的方法。 void print() const override; private: std::string owner; }; -// 與此同時,在對應的.cpp文件裏: +// 与此同时,在对应的.cpp文件里: void OwnedDog::setOwner(const std::string& dogsOwner) { @@ -371,7 +371,7 @@ void OwnedDog::setOwner(const std::string& dogsOwner) void OwnedDog::print() const { - Dog::print(); // 調用基類Dog中的print方法 + Dog::print(); // 调用基类Dog中的print方法 // "Dog is and weights " std::cout << "Dog is owned by " << owner << "\n"; @@ -379,45 +379,46 @@ void OwnedDog::print() const } ///////////////////// -// 初始化與運算符重載 +// 初始化与运算符重载 ///////////////////// -// 在C++中,你可以重載+、-、*、/等運算符的行爲。 -// 【This is done by defining a function -// which is called whenever the operator is used. +// 在C++中,通过定义一些特殊名称的函数, +// 你可以重载+、-、*、/等运算符的行为。 +// 当运算符被使用时,这些特殊函数会被调用,从而实现运算符重载。 #include using namespace std; class Point { public: - // 可以以這樣的方式爲成員變量設置默認值。 + // 可以以这样的方式为成员变量设置默认值。 double x = 0; double y = 0; - // 【Define a default constructor which does nothing - // but initialize the Point to the default value (0, 0) + // 定义一个默认的构造器。 + // 除了将Point初始化为(0, 0)以外,这个函数什么都不做。 Point() { }; - // 【The following syntax is known as an initialization list - // and is the proper way to initialize class member values + // 下面使用的语法称为初始化列表, + // 这是初始化类中成员变量的正确方式。 Point (double a, double b) : x(a), y(b) - { /* 【Do nothing except initialize the values */ } + { /* 除了初始化成员变量外,什么都不做 */ } - // 重載 + 運算符 + // 重载 + 运算符 Point operator+(const Point& rhs) const; - // 重載 += 運算符 + // 重载 += 运算符 Point& operator+=(const Point& rhs); - // 增加 - 和 -= 運算符也是有意義的,這裏不再贅述。 + // 增加 - 和 -= 运算符也是有意义的,但这里不再赘述。 }; Point Point::operator+(const Point& rhs) const { - // 【Create a new point that is the sum of this one and rhs. + // 创建一个新的点, + // 其横纵坐标分别为这个点与另一点在对应方向上的坐标之和。 return Point(x + rhs.x, y + rhs.y); } @@ -431,88 +432,88 @@ Point& Point::operator+=(const Point& rhs) int main () { Point up (0,1); Point right (1,0); - // 這裏調用了Point類型的運算符「+」 - // 調用up(Point類型)的「+」方法,並以right作爲函數的參數 + // 这里使用了Point类型的运算符“+” + // 调用up(Point类型)的“+”方法,并以right作为函数的参数 Point result = up + right; - // 顯示「Result is upright (1,1)」 + // 显示“Result is upright (1,1)” cout << "Result is upright (" << result.x << ',' << result.y << ")\n"; return 0; } /////////// -// 異常處理 +// 异常处理 /////////// -// 標準庫中提供了一些基本的異常類型 -// (參見http://en.cppreference.com/w/cpp/error/exception) -// 但是,其他任何類型也可以作爲一個異常被拋出 +// 标准库中提供了一些基本的异常类型 +// (参见http://en.cppreference.com/w/cpp/error/exception) +// 但是,其他任何类型也可以作为一个异常被拋出 #include -// 在_try_代碼塊中拋出的異常可以被隨後的_catch_捕獲。 +// 在_try_代码块中拋出的异常可以被随后的_catch_捕获。 try { - // 不要用 _new_關鍵字在堆上爲異常分配空間。 + // 不要用 _new_关键字在堆上为异常分配空间。 throw std::exception("A problem occurred"); } -// 如果拋出的異常是一個對象,可以用常量引用來捕獲它 +// 如果拋出的异常是一个对象,可以用常量引用来捕获它 catch (const std::exception& ex) { std::cout << ex.what(); -// 捕獲尚未被_catch_處理的所有錯誤 +// 捕获尚未被_catch_处理的所有错误 } catch (...) { std::cout << "Unknown exception caught"; - throw; // 重新拋出異常 + throw; // 重新拋出异常 } /////// // RAII /////// -// RAII指的是「资源获取就是初始化」(Resource Allocation Is Initialization), -// 它被視作C++中最強大的編程範式之一。 -// 簡單說來,它指的是,用構造函數來獲取一個對象的資源, -// 相應的,借助析構函數來釋放對象的資源。 +// RAII指的是“资源获取就是初始化”(Resource Allocation Is Initialization), +// 它被视作C++中最强大的编程范式之一。 +// 简单说来,它指的是,用构造函数来获取一个对象的资源, +// 相应的,借助析构函数来释放对象的资源。 -// 爲了理解這一範式的用處,讓我們考慮某個函數使用文件句柄時的情況: +// 为了理解这一范式的用处,让我们考虑某个函数使用文件句柄时的情况: void doSomethingWithAFile(const char* filename) { - // 首先,讓我們假設一切都會順利進行。 + // 首先,让我们假设一切都会顺利进行。 - FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 + FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 doSomethingWithTheFile(fh); doSomethingElseWithIt(fh); - fclose(fh); // 關閉文件句柄 + fclose(fh); // 关闭文件句柄 } -// 不幸的是,隨着錯誤處理機制的引入,事情會變得複雜。 -// 假設fopen函數有可能執行失敗, -// 而doSomethingWithTheFile和doSomethingElseWithIt會在失敗時返回錯誤代碼。 -// (雖然異常是C++中處理錯誤的推薦方式, -// 但是某些程序員,尤其是有C語言背景的,並不認可異常捕獲機制的作用)。 -// 現在,我們必須檢查每個函數調用是否成功執行,並在問題發生的時候關閉文件句柄。 +// 不幸的是,随着错误处理机制的引入,事情会变得复杂。 +// 假设fopen函数有可能执行失败, +// 而doSomethingWithTheFile和doSomethingElseWithIt会在失败时返回错误代码。 +// (虽然异常是C++中处理错误的推荐方式, +// 但是某些程序员,尤其是有C语言背景的,并不认可异常捕获机制的作用)。 +// 现在,我们必须检查每个函数调用是否成功执行,并在问题发生的时候关闭文件句柄。 bool doSomethingWithAFile(const char* filename) { - FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 - if (fh == nullptr) // 當執行失敗是,返回的指針是nullptr - return false; // 向調用者彙報錯誤 + FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 + if (fh == nullptr) // 当执行失败是,返回的指针是nullptr + return false; // 向调用者汇报错误 - // 假設每個函數會在執行失敗時返回false + // 假设每个函数会在执行失败时返回false if (!doSomethingWithTheFile(fh)) { - fclose(fh); // Close the file handle so it doesn't leak. - return false; // 反饋錯誤 + fclose(fh); // 关闭文件句柄,避免造成内存泄漏。 + return false; // 反馈错误 } if (!doSomethingElseWithIt(fh)) { - fclose(fh); // Close the file handle so it doesn't leak. - return false; // 反饋錯誤 + fclose(fh); // 关闭文件句柄 + return false; // 反馈错误 } - fclose(fh); // Close the file handle so it doesn't leak. - return true; // 指示函數已成功執行 + fclose(fh); // 关闭文件句柄 + return true; // 指示函数已成功执行 } -// C語言的程序員通常會借助goto語句簡化上面的代碼: +// C语言的程序员通常会借助goto语句简化上面的代码: bool doSomethingWithAFile(const char* filename) { FILE* fh = fopen(filename, "r"); @@ -525,19 +526,19 @@ bool doSomethingWithAFile(const char* filename) if (!doSomethingElseWithIt(fh)) goto failure; - fclose(fh); // 關閉文件 - return true; // 執行成功 + fclose(fh); // 关闭文件 + return true; // 执行成功 failure: fclose(fh); - return false; // 反饋錯誤 + return false; // 反馈错误 } -// 如果用異常捕獲機制來指示錯誤的話, -// 代碼會變得清晰一些,但是仍然有優化的餘地。 +// 如果用异常捕获机制来指示错误的话, +// 代码会变得清晰一些,但是仍然有优化的餘地。 void doSomethingWithAFile(const char* filename) { - FILE* fh = fopen(filename, "r"); // 以只讀模式打開文件 + FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 if (fh == nullptr) throw std::exception("Could not open the file."); @@ -546,45 +547,44 @@ void doSomethingWithAFile(const char* filename) doSomethingElseWithIt(fh); } catch (...) { - fclose(fh); // 保證出錯的時候文件被正確關閉 + fclose(fh); // 保证出错的时候文件被正确关闭 throw; // Then re-throw the exception. } - fclose(fh); // 關閉文件 - // 所有工作順利完成 + fclose(fh); // 关闭文件 + // 所有工作顺利完成 } -// 【Compare this to the use of C++'s file stream class (fstream) -// fstream利用自己的析構器來關閉文件句柄。 -// 【Recall from above that destructors are automatically called -// whenver an object falls out of scope. +// 相比之下,使用C++中的文件流类(fstream)时, +// fstream会利用自己的析构器来关闭文件句柄。 +// 只要离开了某一对象的定义域,它的析构函数就会被自动调用。 void doSomethingWithAFile(const std::string& filename) { - // ifstream是輸入文件流(input file stream)的簡稱 - std::ifstream fh(filename); // Open the file + // ifstream是输入文件流(input file stream)的简称 + std::ifstream fh(filename); // 打开一个文件 - // 對文件進行一些操作 + // 对文件进行一些操作 doSomethingWithTheFile(fh); doSomethingElseWithIt(fh); -} // 文件已經被析構器自動關閉 - -// 與上面幾種方式相比,這種方式有着_明顯_的優勢: -// 1. 無論發生了什麼情況,資源(此例當中是文件句柄)都會被正確關閉。 -// 只要你正確使用了析構器,就_不會_因爲忘記關閉句柄,造成資源的泄漏。 -// 2. 可以注意到,通過這種方式寫出來的代碼十分簡潔。 -// 析構器會在後臺關閉文件句柄,不再需要你來操心這些瑣事。 -// 3. 【The code is exception safe. -// 無論在函數中的何處拋出異常,都不會阻礙對文件資源的釋放。 - -// 地道的C++代碼應當把RAII的使用擴展到各種類型的資源上,包括: -// - 用unique_ptr和shared_ptr管理的內存 -// - 各種數據容器,例如標準庫中的鏈表、向量(容量自動擴展的數組)、散列表等; -// 當它們脫離作用域時,析構器會自動釋放其中儲存的內容。 -// - 用lock_guard和unique_lock實現的互斥 +} // 文件已经被析构器自动关闭 + +// 与上面几种方式相比,这种方式有着_明显_的优势: +// 1. 无论发生了什么情况,资源(此例当中是文件句柄)都会被正确关闭。 +// 只要你正确使用了析构器,就_不会_因为忘记关闭句柄,造成资源的泄漏。 +// 2. 可以注意到,通过这种方式写出来的代码十分简洁。 +// 析构器会在后臺关闭文件句柄,不再需要你来操心这些琐事。 +// 3. 这种方式的代码具有异常安全性。 +// 无论在函数中的何处拋出异常,都不会阻碍对文件资源的释放。 + +// 地道的C++代码应当把RAII的使用扩展到各种类型的资源上,包括: +// - 用unique_ptr和shared_ptr管理的内存 +// - 各种数据容器,例如标准库中的链表、向量(容量自动扩展的数组)、散列表等; +// 当它们脱离作用域时,析构器会自动释放其中储存的内容。 +// - 用lock_guard和unique_lock实现的互斥 ``` -擴展閱讀: +扩展阅读: - 提供了最新的語法參考。 + 提供了最新的语法参考。 -可以在 找到一些補充資料。 +可以在 找到一些补充资料。 -- cgit v1.2.3 From c38d8d93135561e8c0afbe20a5b16b39917ee06c Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Sat, 11 Apr 2015 12:40:47 +0800 Subject: [c++/cn] Update the translated file name. --- zh-cn/c++-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index cbf89c38..eed20721 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -1,6 +1,6 @@ --- language: c++ -filename: learncpp.cpp +filename: learncpp-cn.cpp contributors: - ["Steven Basart", "http://github.com/xksteven"] - ["Matt Kline", "https://github.com/mrkline"] -- cgit v1.2.3 From b95c6b0dae6b91d1c88c337863e8fe182e326b4e Mon Sep 17 00:00:00 2001 From: yejinchang Date: Wed, 15 Apr 2015 15:54:53 +0800 Subject: translate scala doc into chinese --- zh-cn/scala-cn.html.markdown | 553 +++++++++++++++++++++++++++++-------------- 1 file changed, 378 insertions(+), 175 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 58f5cd47..5d5d93c7 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -4,8 +4,10 @@ filename: learnscala-zh.scala contributors: - ["George Petrov", "http://github.com/petrovg"] - ["Dominic Bou-Samra", "http://dbousamra.github.com"] + - ["Geoff Liu", "http://geoffliu.me"] translators: - ["Peiyong Lin", ""] + - ["Jinchang Ye", "http://github.com/alwayswithme"] lang: zh-cn --- @@ -17,23 +19,31 @@ Scala - 一门可拓展性的语言 自行设置: 1) 下载 Scala - http://www.scala-lang.org/downloads - 2) unzip/untar 到你喜欢的地方,放在路径中的 bin 目录下 - 3) 在终端输入 scala,开启 Scala 的 REPL,你会看到提示符: + 2) unzip/untar 到您喜欢的地方,并把 bin 子目录添加到 path 环境变量 + 3) 在终端输入 scala,启动 Scala 的 REPL,您会看到提示符: scala> - 这就是所谓的 REPL,你现在可以在其中运行命令,让我们做到这一点: + 这就是所谓的 REPL (读取-求值-输出循环,英语: Read-Eval-Print Loop), + 您可以在其中输入合法的表达式,结果会被打印。 + 在教程中我们会进一步解释 Scala 文件是怎样的,但现在先了解一点基础。 */ -println(10) // 打印整数 10 -println("Boo!") // 打印字符串 "BOO!" +///////////////////////////////////////////////// +// 1. 基础 +///////////////////////////////////////////////// +// 单行注释开始于两个斜杠 -// 一些基础 +/* + 多行注释,如您之前所见,看起来像这样 +*/ // 打印并强制换行 println("Hello world!") +println(10) + // 没有强制换行的打印 print("Hello world") @@ -41,13 +51,19 @@ print("Hello world") // val 声明是不可变的,var 声明是可修改的。不可变性是好事。 val x = 10 // x 现在是 10 x = 20 // 错误: 对 val 声明的变量重新赋值 -var x = 10 -x = 20 // x 现在是 20 +var y = 10 +y = 20 // y 现在是 20 -// 单行注释开始于两个斜杠 -/* -多行注释看起来像这样。 +/* + Scala 是静态语言,但注意上面的声明方式,我们没有指定类型。 + 这是因为类型推导的语言特性。大多数情况, Scala 编译器可以推测变量的类型, + 所以您不需要每次都输入。可以像这样明确声明变量类型: */ +val z: Int = 10 +val a: Double = 1.0 + +// 注意从 Int 到 Double 的自动转型,结果是 10.0, 不是 10 +val b: Double = 10 // 布尔值 true @@ -64,9 +80,11 @@ true == false // false 2 - 1 // 1 5 * 3 // 15 6 / 2 // 3 +6 / 4 // 1 +6.0 / 4 // 1.5 -// 在 REPL 计算一个命令会返回给你结果的类型和值 +// 在 REPL 计算一个表达式会返回给您结果的类型和值 1 + 7 @@ -77,58 +95,190 @@ true == false // false 这意味着计算 1 + 7 的结果是一个 Int 类型的对象,其值为 8 - 1+7 的结果是一样的 + 注意 "res29" 是一个连续生成的变量名,用以存储您输入的表达式结果, + 您看到的输入可能不一样。 */ +"Scala strings are surrounded by double quotes" +'a' // Scala 的字符 +// '不存在单引号字符串' <= 这会导致错误 -// 包括函数在内,每一个事物都是对象。在 REPL 中输入: +// 字符串定义了常见的 Java 方法 +"hello world".length +"hello world".substring(2, 6) +"hello world".replace("C", "3") -7 // 结果 res30: Int = 7 (res30 是一个生成的结果的 var 命名) +// 也有一些额外的 Scala 方法,另请参见:scala.collection.immutable.StringOps +"hello world".take(5) +"hello world".drop(5) -// 下一行给你一个接收一个 Int 类型并返回该数的平方的函数 -(x:Int) => x * x +// 字符串改写:留意前缀 "s" +val n = 45 +s"We have $n apples" // => "We have 45 apples" -// 你可以分配给函数一个标识符,像这样: -val sq = (x:Int) => x * x +// 在要改写的字符串中使用表达式也是可以的 +val a = Array(11, 9, 6) +s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old." +s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples." +s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4" -/* 上面的例子说明 - - sq: Int => Int = +// 添加 "f" 前缀对要改写的字符串进行格式化 +f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25" +f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454" - 意味着这次我们给予了 sq 这样一个显式的名字给一个接受一个 Int 类型值并返回 一个 Int 类型值的函数 +// 未处理的字符串,忽略特殊字符。 +raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r." - sq 可以像下面那样被执行: -*/ +// 一些字符需要转义,比如字符串中的双引号 +"They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown"" -sq(10) // 返回给你:res33: Int = 100. +// 三个双引号可以使字符串跨越多行,并包含引号 +val html = """
+

Press belo', Joe

+ +
""" -// Scala 允许方法和函数返回或者接受其它的函数或者方法作为参数。 -val add10: Int => Int = _ + 10 // 一个接受一个 Int 类型参数并返回一个 Int 类型值的函数 -List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被应用到每一个元素 +///////////////////////////////////////////////// +// 2. 函数 +///////////////////////////////////////////////// + +// 函数可以这样定义: +// +// def functionName(args...): ReturnType = { body... } +// +// 如果您以前学习过传统的编程语言,注意 return 关键字的省略。 +// 在 Scala 中, 函数代码块最后一条表达式就是返回值。 +def sumOfSquares(x: Int, y: Int): Int = { + val x2 = x * x + val y2 = y * y + x2 + y2 +} -// 匿名函数可以被使用来代替有命名的函数: -List(1, 2, 3) map (x => x + 10) +// 如果函数体是单行表达式,{ } 可以省略: +def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y -// 下划线标志,如果匿名函数只有一个参数可以被使用来表示该参数变量 -List(1, 2, 3) map (_ + 10) +// 函数调用的语法是熟知的: +sumOfSquares(3, 4) // => 25 -// 如果你所应用的匿名块和匿名函数都接受一个参数,那么你甚至可以省略下划线 -List("Dom", "Bob", "Natalia") foreach println +// 在多数情况下 (递归函数是需要注意的例外), 函数返回值可以省略, +// 变量所用的类型推导一样会应用到函数返回值中: +def sq(x: Int) = x * x // 编译器会推断得知返回值是 Int + +// 函数可以有默认参数 +def addWithDefault(x: Int, y: Int = 5) = x + y +addWithDefault(1, 2) // => 3 +addWithDefault(1) // => 6 + + +// 匿名函数是这样的: +(x:Int) => x * x + +// 和 def 不同,如果语义清晰,匿名函数的输入类型也可以省略。 +// 类型 "Int => Int" 意味着这个函数接收一个 Int 并返回一个 Int。 +val sq: Int => Int = x => x * x + +// 匿名函数的调用也是类似的: +sq(10) // => 100 + +// 如果您的匿名函数有一到两个参数,每一个参数仅使用一次, +// Scala 提供一个更简洁的方式来定义他们。这样的匿名函数极为常见, +// 在数据结构部分会明显可见。 +val addOne: Int => Int = _ + 1 +val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3) + +addOne(5) // => 6 +weirdSum(2, 4) // => 16 + + +// return 关键字是存在的,但它从最里面包裹了 return 的 def 函数中返回。 +// 警告: 在 Scala 中使用 return 容易出错,应该避免使用。 +// 在匿名函数中没有效果,例如: +def foo(x: Int): Int = { + val anonFunc: Int => Int = { z => + if (z > 5) + return z // 这一行令 z 成为 foo 函数的返回值! + else + z + 2 // 这一行是 anonFunc 函数的返回值 + } + anonFunc(x) // 这一行是 foo 函数的返回值 +} + +/* + * 译者注:此处是指匿名函数中的 return z 成为最后执行的语句, + * 在 anonFunc(x) 下面的表达式(假设存在)不再执行。如果 anonFunc + * 是用 def 定义的函数, return z 仅返回到 anonFunc(x) , + * 在 anonFunc(x) 下面的表达式(假设存在)会继续执行。 + */ +///////////////////////////////////////////////// +// 3. 控制语句 +///////////////////////////////////////////////// -// 数据结构 +1 to 5 +val r = 1 to 5 +r.foreach( println ) + +r foreach println +// 留意: Scala 对点和括号的要求比较宽松,对这些规则加以区分。 +// 这有助于写出读起来像英语的 DSL(领域特定语言) 和 API(应用编程接口)。 + +(5 to 1 by -1) foreach ( println ) + +// while 循环 +var i = 0 +while (i < 10) { println("i " + i); i+=1 } + +while (i < 10) { println("i " + i); i+=1 } // 没错,再执行一次,发生了什么?为什么? + +i // 显示 i 的值。注意 while 是经典的循环方式,它连续执行并改变循环中的变量。 + // while 执行很快,比 Java 的循环快,但像上面所看到的那样用组合子和推导式 + // 更易于理解和并行化。 + +// do while 循环 +do { + println("x is still less than 10"); + x += 1 +} while (x < 10) + +// Scala 中尾递归是一种符合语言习惯的递归方式。 +// 递归函数需要清晰的返回类型,编译器不能推断得知。 +// 这是一个 Unit。 +def showNumbersInRange(a:Int, b:Int):Unit = { + print(a) + if (a < b) + showNumbersInRange(a + 1, b) +} +showNumbersInRange(1,14) + + +// 条件语句 + +val x = 10 + +if (x == 1) println("yeah") +if (x == 10) println("yeah") +if (x == 11) println("yeah") +if (x == 11) println ("yeah") else println("nay") + +println(if (x == 10) "yeah" else "nope") +val text = if (x == 10) "yeah" else "nope" + + +///////////////////////////////////////////////// +// 4. 数据结构 +///////////////////////////////////////////////// val a = Array(1, 2, 3, 5, 8, 13) a(0) a(3) -a(21) // 这会抛出一个异常 +a(21) // 抛出异常 val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") m("fork") m("spoon") -m("bottle") // 这会抛出一个异常 +m("bottle") // 抛出异常 val safeM = m.withDefaultValue("no lo se") safeM("bottle") @@ -137,9 +287,9 @@ val s = Set(1, 3, 7) s(0) s(1) -/* 查看 map 的文档 - * 点击[这里](http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map) - * 确保你可以读它 +/* 这里查看 map 的文档 - + * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map + * 并确保你会阅读 */ @@ -157,7 +307,7 @@ s(1) val divideInts = (x:Int, y:Int) => (x / y, x % y) -divideInts(10,3) // 函数 divideInts 返回你结果和余数 +divideInts(10,3) // 函数 divideInts 返回您结果和余数 // 要读取元组的元素,使用 _._n,n是从1开始的元素索引 @@ -168,234 +318,287 @@ d._1 d._2 +///////////////////////////////////////////////// +// 5. 面向对象编程 +///////////////////////////////////////////////// -// 选择器 - -s.map(sq) - -val sSquared = s. map(sq) - -sSquared.filter(_ < 10) +/* + 旁白: 教程中到现在为止我们所做的一切只是简单的表达式(值,函数等)。 + 这些表达示可以输入到命令行解释器中作为快速测试,但它们无法单一的存在于 Scala + 文件。举个例子,您不能在 Scala 文件上简单的写上 "val x = 5"。而 Scala 允许存 + 在的顶级结构是: -sSquared.reduce (_+_) + - objects + - classes + - case classes + - traits -// filter 函数接受一个预测(一个函数,形式为 A -> Boolean) 并选择出所有的元素满足这个预测 + 现在来解释这些是什么。 +*/ -List(1, 2, 3) filter (_ > 2) // List(3) -List( - Person(name = "Dom", age = 23), - Person(name = "Bob", age = 30) -).filter(_.age > 25) // List(Person("Bob", 30)) +// 类和其他语言的类相似,构造器参数在类名后声明,初始化在类结构体中完成。 +class Dog(br: String) { + // 构造器代码在此 + var breed: String = br + // 定义名为 bark 的方法,返回字符串 + def bark = "Woof, woof!" -// Scala 的 foreach 方法定义在特定的接受一个类型的集合上 -// 返回 Unit(一个 void 方法) -aListOfNumbers foreach (x => println(x)) -aListOfNumbers foreach println + // 值和方法作用域假定为 public。"protected" 和 "private" 关键字也是可用的。 + private def sleep(hours: Int) = + println(s"I'm sleeping for $hours hours") + // 抽象方法是没有方法体的方法。如果取消下面那行注释,Dog 类需要被声明为 abstract + // abstract class Dog(...) { ... } + // def chaseAfter(what: String): String +} +val mydog = new Dog("greyhound") +println(mydog.breed) // => "greyhound" +println(mydog.bark) // => "Woof, woof!" -// For 包含 +// "object" 关键字创造一种类型和该类型的单例。 +// Scala 的 class 常常也含有一个 “伴生对象”,class 中包含每个实例的行为,所有实例 +// 共用的行为则放入 object 中。两者的区别和其他语言中方法和静态方法类似。 +// 请注意 object 和 class 可以同名。 +object Dog { + def allKnownBreeds = List("pitbull", "shepherd", "retriever") + def createDog(breed: String) = new Dog(breed) +} -for { n <- s } yield sq(n) -val nSquared2 = for { n <- s } yield sq(n) +// Case 类是有额外内建功能的类。Scala 初学者常遇到的问题之一便是何时用类 +// 和何时用 case 类。界线比较模糊,但通常类倾向于封装,多态和行为。类中的值 +// 的作用域一般为 private , 只有方向是暴露的。case 类的主要目的是放置不可变 +// 数据。它们通常只有几个方法,且方法几乎没有副作用。 +case class Person(name: String, phoneNumber: String) -for { n <- nSquared2 if n < 10 } yield n +// 创造新实例,注意 case 类不需要 "new" 关键字 +val george = Person("George", "1234") +val kate = Person("Kate", "4567") -for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared +// 使用 case 类,您可以轻松得到一些功能,像 getters: +george.phoneNumber // => "1234" -/* 注意:这些不是 for 循环. 一个 for 循环的语义是 '重复'('repeat'), - 然而,一个 for-包含 定义了一个两个数据结合间的关系 */ +// 每个字段的相等性(无需覆盖 .equals) +Person("George", "1234") == Person("Kate", "1236") // => false +// 简单的拷贝方式 +// otherGeorge == Person("george", "9876") +val otherGeorge = george.copy(phoneNumber = "9876") +// 还有很多。case 类同时可以用于模式匹配,接下来会看到。 -// 循环和迭代 -1 to 5 -val r = 1 to 5 -r.foreach( println ) +// 敬请期待 Traits ! -r foreach println -// 注意:Scala 是相当宽容的当它遇到点和括号 - 分别地学习这些规则。 -// 这帮助你编写读起来像英语的 DSLs 和 APIs -(5 to 1 by -1) foreach ( println ) +///////////////////////////////////////////////// +// 6. 模式匹配 +///////////////////////////////////////////////// -// while 循环 -var i = 0 -while (i < 10) { println("i " + i); i+=1 } - -while (i < 10) { println("i " + i); i+=1 } // 发生了什么?为什么? - -i // 展示 i 的值。注意到 while 是一个传统意义上的循环 - // 它顺序地执行并且改变循环变量的值。while 非常快,比 Java // 循环快, - // 但是在其上使用选择器和包含更容易理解和并行。 - -// do while 循环 -do { - println("x is still less then 10"); - x += 1 -} while (x < 10) +// 模式匹配是一个强大和常用的 Scala 特性。这是用模式匹配一个 case 类的例子。 +// 留意:不像其他语言, Scala 的 case 不需要 break, 其他语言中 switch 语句的 +// fall-through 现象不会发生。 -// 在 Scala中,尾递归是一种惯用的执行循环的方式。 -// 递归函数需要显示的返回类型,编译器不能推断出类型。 -// 这里它是 Unit。 -def showNumbersInRange(a:Int, b:Int):Unit = { - print(a) - if (a < b) - showNumbersInRange(a + 1, b) +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 } +val email = "(.*)@(.*)".r // 定义下一个例子会用到的正则 +// 模式匹配看起来和 C语言家族的 switch 语句相似,但更为强大。 +// Scala 中您可以很多东西: +def matchEverything(obj: Any): String = obj match { + // 匹配值: + case "Hello world" => "Got the string Hello world" -// 条件语句 - -val x = 10 - -if (x == 1) println("yeah") -if (x == 10) println("yeah") -if (x == 11) println("yeah") -if (x == 11) println ("yeah") else println("nay") + // 匹配类型: + case x: Double => "Got a Double: " + x -println(if (x == 10) "yeah" else "nope") -val text = if (x == 10) "yeah" else "nope" + // 匹配时指定条件 + case x: Int if x > 10000 => "Got a pretty big number!" -var i = 0 -while (i < 10) { println("i " + i); i+=1 } + // 像之前一样匹配 case 类: + case Person(name, number) => s"Got contact info for $name!" + // 匹配正则表达式: + case email(name, domain) => s"Got email address $name@$domain" + // 匹配元组: + case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c" -// 面向对象特性 + // 匹配数据结构: + case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c" -// 类名是 Dog -class Dog { - //bark 方法,返回字符串 - def bark: String = { - // the body of the method - "Woof, woof!" - } + // 模式可以嵌套 + case List(List((1, 2,"YAY"))) => "Got a list of list of tuple" } -// 类可以包含几乎其它的构造,包括其它的类, -// 函数,方法,对象,case 类,特性等等。 - - +// 事实上,你可以对任何有 "unapply" 方法的对象进行模式匹配。 +// 这个特性如此强大以致于 Scala 允许定义一个函数作为模式匹配: +val patternFunc: Person => String = { + case Person("George", number) => s"George's number: $number" + case Person(name, number) => s"Random person's number: $number" +} -// Case 类 -case class Person(name:String, phoneNumber:String) +///////////////////////////////////////////////// +// 7. 函数式编程 +///////////////////////////////////////////////// -Person("George", "1234") == Person("Kate", "1236") +// Scala 允许方法和函数作为其他方法和函数的参数和返回值。 +val add10: Int => Int = _ + 10 // 一个接受一个 Int 类型参数并返回一个 Int 类型值的函数 +List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被应用到每一个元素 +// 匿名函数可以被使用来代替有命名的函数: +List(1, 2, 3) map (x => x + 10) +// 下划线标志,如果匿名函数只有一个参数可以被使用来表示该参数变量 +List(1, 2, 3) map (_ + 10) -// 模式匹配 +// 如果您所应用的匿名块和匿名函数都接受一个参数,那么你甚至可以省略下划线 +List("Dom", "Bob", "Natalia") foreach println -val me = Person("George", "1234") -me match { case Person(name, number) => { - "We matched someone : " + name + ", phone : " + number }} +// 组合子 -me match { case Person(name, number) => "Match : " + name; case _ => "Hm..." } +// 译注: val sq: Int => Int = x => x * x +s.map(sq) -me match { case Person("George", number) => "Match"; case _ => "Hm..." } +val sSquared = s. map(sq) -me match { case Person("Kate", number) => "Match"; case _ => "Hm..." } +sSquared.filter(_ < 10) -me match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } +sSquared.reduce (_+_) -val kate = Person("Kate", "1234") +// filter 函数接受一个 predicate (函数从 A -> Boolean)并选择 +// 所有满足 predicate 的元素 +List(1, 2, 3) filter (_ > 2) // List(3) +case class Person(name:String, age:Int) +List( + Person(name = "Dom", age = 23), + Person(name = "Bob", age = 30) +).filter(_.age > 25) // List(Person("Bob", 30)) -kate match { case Person("Kate", _) => "Girl"; case Person("George", _) => "Boy" } +// Scala 的 foreach 方法定义在特定集合中,接受一个类型并返回 Unit (void 方法) +val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) +aListOfNumbers foreach (x => println(x)) +aListOfNumbers foreach println +// For 推导式 -// 正则表达式 +for { n <- s } yield sq(n) -val email = "(.*)@(.*)".r // 在字符串上调用 r 会使它变成一个正则表达式 +val nSquared2 = for { n <- s } yield sq(n) -val email(user, domain) = "henry@zkpr.com" +for { n <- nSquared2 if n < 10 } yield n -"mrbean@pyahoo.com" match { - case email(name, domain) => "I know your name, " + name -} +for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared +/* 注意,这些不是 for 循环,for 循环的语义是‘重复’,然而 for 推导式定义 + 两个数据集合的关系。 */ -// 字符串 +///////////////////////////////////////////////// +// 8. 隐式转换 +///////////////////////////////////////////////// -"Scala 字符串被双引号包围" // -'a' // Scala 字符 -'单引号的字符串不存在' // 错误 -"字符串拥有通常的 Java 方法定义在其上".length -"字符串也有额外的 Scala 方法".reverse +/* 警告 警告: 隐式转换是 Scala 中一套强大的特性,因此容易被滥用。 + * Scala 初学者在理解它们的工作原理和最佳实践之前,应抵制使用它的诱惑。 + * 我们加入这一章节仅因为它们在 Scala 的库中太过常见,导致没有用隐式转换的库 + * 就不可能做有意义的事情。这章节主要让你理解和使用隐式转换,而不是自己声明。 + */ -// 参见: scala.collection.immutable.StringOps +// 任何值(val, 函数,对象等)可以被声明为隐式的,你可以猜到的,通过加上 "implicit" +// 关键字。请注意这些例子中,我们用到第5部分的 Dog 类。 +implicit val myImplicitInt = 100 +implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed) -println("ABCDEF".length) -println("ABCDEF".substring(2, 6)) -println("ABCDEF".replace("C", "3")) +// implicit 关键字本身不改变值的行为,所以上面的值可以照常使用。 +myImplicitInt + 2 // => 102 +myImplicitFunction("Pitbull").breed // => "Golden Pitbull" -val n = 45 -println(s"We have $n apples") +// 区别在于,当另一段代码“需要”隐式值时,这些值现在有资格作为隐式值。 +// 一种情况是隐式函数参数。 +def sendGreetings(toWhom: String)(implicit howMany: Int) = + s"Hello $toWhom, $howMany blessings to you and yours!" -val a = Array(11, 9, 6) -println(s"My second daughter is ${a(2-1)} years old") +// 如果提供值给 “howMany”,函数正常运行 +sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!" -// 一些字符需要被转义,举例来说,字符串中的双引号: -val a = "They stood outside the \"Rose and Crown\"" +// 如果省略隐式参数,会传一个和参数类型相同的隐式值, +// 在这个例子中, 是 “myImplicitInt": +sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!" -// 三个双引号使得字符串可以跨行并且可以包含引号(无需转义) +// 隐式的函数参数使我们可以模拟其他函数式语言的 type 类(type classes)。 +// 它经常被用到所以有特定的简写。这两行代码是一样的: +def foo[T](implicit c: C[T]) = ... +def foo[T : C] = ... -val html = """
-

Press belo', Joe

- | -
""" +// 编译器寻找隐式值另一种情况是你调用方法时 +// obj.method(...) +// 但 "obj" 没有一个名为 "method" 的方法。这样的话,如果存在一个将类型 A +// 转变为 B 的隐式转换,A 是 obj 的类型,B有一个叫 "method" 的方法,这样 +// 转换就会被应用。所以作用域里有上面的 myImplicitFunction, 我们可以这样做: +"Retriever".breed // => "Golden Retriever" +"Sheperd".bark // => "Woof, woof!" +// 这里字符串先被上面的函数转换为 Dog 对象,然后调用合适的方法。 +// 这是相当强大的特性,但再次提醒,请勿轻率使用。 +// 事实上,当你定义上面的隐式函数时,编译器会作出警告,除非你真的了解 +// 你正在做什么否则不要使用。 -// 应用结果和组织 +///////////////////////////////////////////////// +// 9. 杂项 +///////////////////////////////////////////////// -// import +// 导入类 import scala.collection.immutable.List -// Import 所有的子包 +// 导入所有子包 import scala.collection.immutable._ -// 在一条语句中 Import 多个类 +// 一条语句导入多个类 import scala.collection.immutable.{List, Map} -// 使用 '=>' 来重命名一个 import +// 使用 ‘=>’ 对导入进行重命名 import scala.collection.immutable.{ List => ImmutableList } -// import 除了一些类的其它所有的类。下面的例子除去了 Map 类和 Set 类: +// 导入所有类,排除其中一些。下面的语句排除了 Map 和 Set: import scala.collection.immutable.{Map => _, Set => _, _} -// 在 scala 源文件中,你的程序入口点使用一个拥有单一方法 main 的对象来定义: - +// 在 Scala 文件用 object 和单一的 main 方法定义程序入口: object Application { def main(args: Array[String]): Unit = { // stuff goes here. } } -// 文件可以包含多个类和对象。由 scalac 来编译 +// 文件可以包含多个 class 和 object,用 scalac 编译源文件 -// 输入和输出 +// 输入输出 -// 一行一行读取文件 +// 按行读文件 import scala.io.Source -for(line <- Source.fromPath("myfile.txt").getLines()) +for(line <- Source.fromFile("myfile.txt").getLines()) println(line) -// 使用 Java 的 PrintWriter 来写文件 - +// 用 Java 的 PrintWriter 写文件 +val writer = new PrintWriter("myfile.txt") +writer.write("Writing line for line" + util.Properties.lineSeparator) +writer.write("Another line here" + util.Properties.lineSeparator) +writer.close() ``` -- cgit v1.2.3 From 8f0027683d316d0b614be8841a76453fb4cfb347 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Wed, 15 Apr 2015 18:09:34 +0800 Subject: Some bug fixes. --- zh-cn/c++-cn.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index eed20721..46a34141 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -535,7 +535,7 @@ failure: } // 如果用异常捕获机制来指示错误的话, -// 代码会变得清晰一些,但是仍然有优化的餘地。 +// 代码会变得清晰一些,但是仍然有优化的余地。 void doSomethingWithAFile(const char* filename) { FILE* fh = fopen(filename, "r"); // 以只读模式打开文件 @@ -548,7 +548,7 @@ void doSomethingWithAFile(const char* filename) } catch (...) { fclose(fh); // 保证出错的时候文件被正确关闭 - throw; // Then re-throw the exception. + throw; // 之后,重新抛出这个异常 } fclose(fh); // 关闭文件 @@ -573,7 +573,7 @@ void doSomethingWithAFile(const std::string& filename) // 1. 无论发生了什么情况,资源(此例当中是文件句柄)都会被正确关闭。 // 只要你正确使用了析构器,就_不会_因为忘记关闭句柄,造成资源的泄漏。 // 2. 可以注意到,通过这种方式写出来的代码十分简洁。 -// 析构器会在后臺关闭文件句柄,不再需要你来操心这些琐事。 +// 析构器会在后台关闭文件句柄,不再需要你来操心这些琐事。 // 3. 这种方式的代码具有异常安全性。 // 无论在函数中的何处拋出异常,都不会阻碍对文件资源的释放。 -- cgit v1.2.3 From 60b56e777efa1b5c24cf5104556a2eb7aa6fbed2 Mon Sep 17 00:00:00 2001 From: yejinchang Date: Wed, 15 Apr 2015 18:12:21 +0800 Subject: fix minor mistake --- zh-cn/scala-cn.html.markdown | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 5d5d93c7..f292271e 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -191,7 +191,7 @@ addOne(5) // => 6 weirdSum(2, 4) // => 16 -// return 关键字是存在的,但它从最里面包裹了 return 的 def 函数中返回。 +// return 关键字是存在的,但它只从最里面包裹了 return 的 def 函数中返回。 // 警告: 在 Scala 中使用 return 容易出错,应该避免使用。 // 在匿名函数中没有效果,例如: def foo(x: Int): Int = { @@ -304,13 +304,11 @@ s(1) (a, 2, "three") // 为什么有这个? - val divideInts = (x:Int, y:Int) => (x / y, x % y) divideInts(10,3) // 函数 divideInts 返回您结果和余数 // 要读取元组的元素,使用 _._n,n是从1开始的元素索引 - val d = divideInts(10,3) d._1 @@ -360,7 +358,7 @@ println(mydog.bark) // => "Woof, woof!" // "object" 关键字创造一种类型和该类型的单例。 // Scala 的 class 常常也含有一个 “伴生对象”,class 中包含每个实例的行为,所有实例 -// 共用的行为则放入 object 中。两者的区别和其他语言中方法和静态方法类似。 +// 共用的行为则放入 object 中。两者的区别和其他语言中类方法和静态方法类似。 // 请注意 object 和 class 可以同名。 object Dog { def allKnownBreeds = List("pitbull", "shepherd", "retriever") @@ -374,14 +372,14 @@ object Dog { // 数据。它们通常只有几个方法,且方法几乎没有副作用。 case class Person(name: String, phoneNumber: String) -// 创造新实例,注意 case 类不需要 "new" 关键字 +// 创造新实例,注意 case 类不需要使用 "new" 关键字 val george = Person("George", "1234") val kate = Person("Kate", "4567") // 使用 case 类,您可以轻松得到一些功能,像 getters: george.phoneNumber // => "1234" -// 每个字段的相等性(无需覆盖 .equals) +// 每个字段的相等性比较(无需覆盖 .equals) Person("George", "1234") == Person("Kate", "1236") // => false // 简单的拷贝方式 @@ -412,7 +410,7 @@ def matchPerson(person: Person): String = person match { val email = "(.*)@(.*)".r // 定义下一个例子会用到的正则 // 模式匹配看起来和 C语言家族的 switch 语句相似,但更为强大。 -// Scala 中您可以很多东西: +// Scala 中您可以匹配很多东西: def matchEverything(obj: Any): String = obj match { // 匹配值: case "Hello world" => "Got the string Hello world" -- cgit v1.2.3 From 4adbf231c805afdf68fed3a5e2aba9c90fd4c0c1 Mon Sep 17 00:00:00 2001 From: yejinchang Date: Thu, 16 Apr 2015 17:53:40 +0800 Subject: make corrections --- zh-cn/scala-cn.html.markdown | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index f292271e..343982ff 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -8,10 +8,11 @@ contributors: translators: - ["Peiyong Lin", ""] - ["Jinchang Ye", "http://github.com/alwayswithme"] + - ["Guodong Qu", "https://github.com/jasonqu"] lang: zh-cn --- -Scala - 一门可拓展性的语言 +Scala - 一门可拓展的语言 ```scala @@ -103,7 +104,7 @@ true == false // false 'a' // Scala 的字符 // '不存在单引号字符串' <= 这会导致错误 -// 字符串定义了常见的 Java 方法 +// String 有常见的 Java 字符串方法 "hello world".length "hello world".substring(2, 6) "hello world".replace("C", "3") @@ -174,14 +175,14 @@ addWithDefault(1) // => 6 // 匿名函数是这样的: (x:Int) => x * x -// 和 def 不同,如果语义清晰,匿名函数的输入类型也可以省略。 +// 和 def 不同,如果语义清晰,匿名函数的参数类型也可以省略。 // 类型 "Int => Int" 意味着这个函数接收一个 Int 并返回一个 Int。 val sq: Int => Int = x => x * x // 匿名函数的调用也是类似的: sq(10) // => 100 -// 如果您的匿名函数有一到两个参数,每一个参数仅使用一次, +// 如果您的匿名函数中每个参数仅使用一次, // Scala 提供一个更简洁的方式来定义他们。这样的匿名函数极为常见, // 在数据结构部分会明显可见。 val addOne: Int => Int = _ + 1 @@ -221,7 +222,7 @@ val r = 1 to 5 r.foreach( println ) r foreach println -// 留意: Scala 对点和括号的要求比较宽松,对这些规则加以区分。 +// 附注: Scala 对点和括号的要求想当宽松,注意其规则是不同的。 // 这有助于写出读起来像英语的 DSL(领域特定语言) 和 API(应用编程接口)。 (5 to 1 by -1) foreach ( println ) @@ -306,7 +307,7 @@ s(1) // 为什么有这个? val divideInts = (x:Int, y:Int) => (x / y, x % y) -divideInts(10,3) // 函数 divideInts 返回您结果和余数 +divideInts(10,3) // 函数 divideInts 同时返回结果和余数 // 要读取元组的元素,使用 _._n,n是从1开始的元素索引 val d = divideInts(10,3) @@ -322,9 +323,9 @@ d._2 /* 旁白: 教程中到现在为止我们所做的一切只是简单的表达式(值,函数等)。 - 这些表达示可以输入到命令行解释器中作为快速测试,但它们无法单一的存在于 Scala - 文件。举个例子,您不能在 Scala 文件上简单的写上 "val x = 5"。而 Scala 允许存 - 在的顶级结构是: + 这些表达式可以输入到命令行解释器中作为快速测试,但它们不能独立存在于 Scala + 文件。举个例子,您不能在 Scala 文件上简单的写上 "val x = 5"。相反 Scala 文件 + 允许的顶级结构是: - objects - classes @@ -346,7 +347,7 @@ class Dog(br: String) { private def sleep(hours: Int) = println(s"I'm sleeping for $hours hours") - // 抽象方法是没有方法体的方法。如果取消下面那行注释,Dog 类需要被声明为 abstract + // 抽象方法是没有方法体的方法。如果取消下面那行注释,Dog 类必须被声明为 abstract // abstract class Dog(...) { ... } // def chaseAfter(what: String): String } @@ -397,7 +398,7 @@ val otherGeorge = george.copy(phoneNumber = "9876") ///////////////////////////////////////////////// // 模式匹配是一个强大和常用的 Scala 特性。这是用模式匹配一个 case 类的例子。 -// 留意:不像其他语言, Scala 的 case 不需要 break, 其他语言中 switch 语句的 +// 附注:不像其他语言, Scala 的 case 不需要 break, 其他语言中 switch 语句的 // fall-through 现象不会发生。 def matchPerson(person: Person): String = person match { @@ -457,7 +458,7 @@ List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被应用到每一个元素 // 匿名函数可以被使用来代替有命名的函数: List(1, 2, 3) map (x => x + 10) -// 下划线标志,如果匿名函数只有一个参数可以被使用来表示该参数变量 +// 如果匿名函数只有一个参数可以用下划线作为变量 List(1, 2, 3) map (_ + 10) // 如果您所应用的匿名块和匿名函数都接受一个参数,那么你甚至可以省略下划线 @@ -475,7 +476,7 @@ sSquared.filter(_ < 10) sSquared.reduce (_+_) -// filter 函数接受一个 predicate (函数从 A -> Boolean)并选择 +// filter 函数接受一个 predicate (函数根据条件 A 返回 Boolean)并选择 // 所有满足 predicate 的元素 List(1, 2, 3) filter (_ > 2) // List(3) case class Person(name:String, age:Int) @@ -514,8 +515,8 @@ for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared * 就不可能做有意义的事情。这章节主要让你理解和使用隐式转换,而不是自己声明。 */ -// 任何值(val, 函数,对象等)可以被声明为隐式的,你可以猜到的,通过加上 "implicit" -// 关键字。请注意这些例子中,我们用到第5部分的 Dog 类。 +// 可以通过 "implicit" 声明任何值(val, 函数,对象等)为隐式值, +// 请注意这些例子中,我们用到第5部分的 Dog 类。 implicit val myImplicitInt = 100 implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed) @@ -542,13 +543,13 @@ def foo[T : C] = ... // 编译器寻找隐式值另一种情况是你调用方法时 // obj.method(...) -// 但 "obj" 没有一个名为 "method" 的方法。这样的话,如果存在一个将类型 A -// 转变为 B 的隐式转换,A 是 obj 的类型,B有一个叫 "method" 的方法,这样 +// 但 "obj" 没有一个名为 "method" 的方法。这样的话,如果有一个参数类型为 A +// 返回值类型为 B 的隐式转换,obj 的类型是 A,B 有一个方法叫 "method" ,这样 // 转换就会被应用。所以作用域里有上面的 myImplicitFunction, 我们可以这样做: "Retriever".breed // => "Golden Retriever" "Sheperd".bark // => "Woof, woof!" -// 这里字符串先被上面的函数转换为 Dog 对象,然后调用合适的方法。 +// 这里字符串先被上面的函数转换为 Dog 对象,然后调用相应的方法。 // 这是相当强大的特性,但再次提醒,请勿轻率使用。 // 事实上,当你定义上面的隐式函数时,编译器会作出警告,除非你真的了解 // 你正在做什么否则不要使用。 @@ -585,7 +586,7 @@ object Application { -// 输入输出 +// 输入和输出 // 按行读文件 import scala.io.Source -- cgit v1.2.3 From c8c6924dccf3184b0c2c60226291de3cae4c1380 Mon Sep 17 00:00:00 2001 From: alwayswithme Date: Fri, 17 Apr 2015 14:55:01 +0800 Subject: resolve translation errors --- zh-cn/scala-cn.html.markdown | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/scala-cn.html.markdown b/zh-cn/scala-cn.html.markdown index 343982ff..508dd58e 100644 --- a/zh-cn/scala-cn.html.markdown +++ b/zh-cn/scala-cn.html.markdown @@ -97,7 +97,7 @@ true == false // false 这意味着计算 1 + 7 的结果是一个 Int 类型的对象,其值为 8 注意 "res29" 是一个连续生成的变量名,用以存储您输入的表达式结果, - 您看到的输入可能不一样。 + 您看到的输出可能不一样。 */ "Scala strings are surrounded by double quotes" @@ -486,7 +486,9 @@ List( ).filter(_.age > 25) // List(Person("Bob", 30)) -// Scala 的 foreach 方法定义在特定集合中,接受一个类型并返回 Unit (void 方法) +// Scala 的 foreach 方法定义在某些集合中,接受一个函数并返回 Unit (void 方法) +// 另请参见: +// http://www.scala-lang.org/api/current/index.html#scala.collection.IterableLike@foreach(f:A=>Unit):Unit val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) aListOfNumbers foreach (x => println(x)) aListOfNumbers foreach println -- cgit v1.2.3 From c5212932b9e7fb2d42eb74049877488678b85967 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Fri, 17 Apr 2015 22:19:13 +0800 Subject: More bug fixes. --- zh-cn/c++-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index 46a34141..e5c5d5df 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -282,7 +282,7 @@ public: void bark() const { std::cout << name << " barks!\n" } // 除了构造器以外,C++还提供了析构器。 - // 当一个对象被删除或者脱离其定义域时时,它的析构函数会被调用。 + // 当一个对象被删除或者脱离其定义域时,它的析构函数会被调用。 // 这使得RAII这样的强大范式(参见下文)成为可能。 // 为了衍生出子类来,基类的析构函数必须定义为虚函数。 virtual ~Dog(); @@ -353,7 +353,7 @@ class OwnedDog : public Dog { // 重写OwnedDogs类的print方法。 // 如果你不熟悉子类多态的话,可以参考这个页面中的概述: - // http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Subtyping + // http://zh.wikipedia.org/wiki/%E5%AD%90%E7%B1%BB%E5%9E%8B // override关键字是可选的,它确保你所重写的是基类中的方法。 void print() const override; -- cgit v1.2.3 From 7bab2c5e8d0301ca3480cbac92ecee99233f6677 Mon Sep 17 00:00:00 2001 From: Arnie97 Date: Fri, 17 Apr 2015 22:51:02 +0800 Subject: Remove duplicate code. --- zh-cn/c++-cn.html.markdown | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/c++-cn.html.markdown b/zh-cn/c++-cn.html.markdown index e5c5d5df..e1551e2b 100644 --- a/zh-cn/c++-cn.html.markdown +++ b/zh-cn/c++-cn.html.markdown @@ -289,8 +289,6 @@ public: }; // 在类的定义之后,要加一个分号 -}; // 记住,在类的定义之后,要加一个分号! - // 类的成员函数通常在.cpp文件中实现。 void Dog::Dog() { @@ -309,22 +307,6 @@ void Dog::setWeight(int dogsWeight) weight = dogsWeight; } -// 虚函数的virtual关键字只需要在声明时使用,不需要在定义时出现 -void Dog::print() const -{ - std::cout << "Dog is " << name << " and weighs " << weight << "kg\n"; -} - -void Dog::~Dog() -{ - cout << "Goodbye " << name << "\n"; -} - -void Dog::setWeight(int dogsWeight) -{ - weight = dogsWeight; -} - // 虚函数的virtual关键字只需要在声明时使用,不需要在定义时重复 void Dog::print() const { -- cgit v1.2.3 From 10ece6fabbed6787c63520004c1491220011afe4 Mon Sep 17 00:00:00 2001 From: Geoff Liu Date: Fri, 24 Apr 2015 11:34:48 -0600 Subject: Fix issue #959 --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index 1c577efb..b1143dac 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -127,7 +127,7 @@ __此文本也是__ +或者一个制表符(tab)实现--> This is code So is this -- cgit v1.2.3 From 18a45cf7a37eb971383e3fcf65a565292e82224b Mon Sep 17 00:00:00 2001 From: Alwayswithme Date: Wed, 20 May 2015 00:14:10 +0800 Subject: update bash-cn --- zh-cn/bash-cn.html.markdown | 147 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 139 insertions(+), 8 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index 6afa659a..13f85bb7 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -5,7 +5,14 @@ contributors: - ["Max Yankov", "https://github.com/golergka"] - ["Darren Lin", "https://github.com/CogBear"] - ["Alexandre Medeiros", "http://alemedeiros.sdf.org"] + - ["Denis Arh", "https://github.com/darh"] + - ["akirahirose", "https://twitter.com/akirahirose"] + - ["Anton Strömkvist", "http://lutic.org/"] + - ["Rahil Momin", "https://github.com/iamrahil"] + - ["Gregrory Kielian", "https://github.com/gskielian"] + - ["Etan Reisner", "https://github.com/deryni"] translators: + - ["Jinchang Ye", "https://github.com/Alwayswithme"] - ["Chunyang Xu", "https://github.com/XuChunyang"] filename: LearnBash-cn.sh lang: zh-cn @@ -35,6 +42,10 @@ VARIABLE="Some string" VARIABLE = "Some string" # Bash 会把 VARIABLE 当做一个指令,由于找不到该指令,因此这里会报错。 +# 也不可以这样: +Variable= 'Some string' +# Bash 会认为 'Some string' 是一条指令,由于找不到该指令,这里再次报错。 +# (这个例子中 'Variable=' 这部分的赋值仅对 'Some string' 指令起作用。) # 使用变量: echo $VARIABLE @@ -49,6 +60,16 @@ echo '$VARIABLE' echo ${VARIABLE/Some/A} # 会把 VARIABLE 中首次出现的 "some" 替换成 “A”。 +# 变量的截取 +Length=7 +echo ${Variable:0:Length} +# 这样会仅返回变量值的前7个字符 + +# 变量的默认值 +echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"} +# 对 null (Foo=) 和空串 (Foo="") 起作用; 零(Foo=0)时返回0 +# 注意这仅返回默认值而不是改变变量的值 + # 内置变量: # 下面的内置变量很有用 echo "Last program return value: $?" @@ -75,6 +96,17 @@ fi echo "Always executed" || echo "Only executed if first command fail" echo "Always executed" && echo "Only executed if first command does NOT fail" +# 在 if 语句中使用 && 和 || 需要多对方括号 +if [ $Name == "Steve" ] && [ $Age -eq 15 ] +then + echo "This will run if $Name is Steve AND $Age is 15." +fi + +if [ $Name == "Daniya" ] || [ $Name == "Zach" ] +then + echo "This will run if $Name is Daniya OR Zach." +fi + # 表达式的格式如下: echo $(( 10 + 5 )) @@ -88,16 +120,52 @@ ls -l # 列出文件和目录的详细信息 # 用下面的指令列出当前目录下所有的 txt 文件: ls -l | grep "\.txt" +# 重定向输入和输出(标准输入,标准输出,标准错误)。 +# 以 ^EOF$ 作为结束标记从标准输入读取数据并覆盖 hello.py : +cat > hello.py << EOF +#!/usr/bin/env python +from __future__ import print_function +import sys +print("#stdout", file=sys.stdout) +print("#stderr", file=sys.stderr) +for line in sys.stdin: + print(line, file=sys.stdout) +EOF + # 重定向可以到输出,输入和错误输出。 -python2 hello.py < "input.in" -python2 hello.py > "output.out" -python2 hello.py 2> "error.err" +python hello.py < "input.in" +python hello.py > "output.out" +python hello.py 2> "error.err" +python hello.py > "output-and-error.log" 2>&1 +python hello.py > /dev/null 2>&1 # > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。 +python hello.py >> "output.out" 2>> "error.err" + +# 覆盖 output.out , 追加 error.err 并统计行数 +info bash 'Basic Shell Features' 'Redirections' > output.out 2>> error.err +wc -l output.out error.err + +# 运行指令并打印文件描述符 (比如 /dev/fd/123) +# 具体可查看: man fd +echo <(echo "#helloworld") + +# 以 "#helloworld" 覆盖 output.out: +cat > output.out <(echo "#helloworld") +echo "#helloworld" > output.out +echo "#helloworld" | cat > output.out +echo "#helloworld" | tee output.out >/dev/null + +# 清理临时文件并显示详情(增加 '-i' 选项启用交互模式) +rm -v output.out error.err output-and-error.log # 一个指令可用 $( ) 嵌套在另一个指令内部: # 以下的指令会打印当前目录下的目录和文件总数 echo "There are $(ls | wc -l) items here." +# 反引号 `` 起相同作用,但不允许嵌套 +# 优先使用 $( ). +echo "There are `ls | wc -l` items here." + # Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似: case "$VARIABLE" in # 列出需要匹配的字符串 @@ -114,6 +182,33 @@ do echo "$VARIABLE" done +# 或传统的 “for循环” : +for ((a=1; a <= 3; a++)) +do + echo $a +done + +# 也可以用于文件 +# 用 cat 输出 file1 和 file2 内容 +for Variable in file1 file2 +do + cat "$Variable" +done + +# 或作用于其他命令的输出 +# 对 ls 输出的文件执行 cat 指令。 +for Output in $(ls) +do + cat "$Output" +done + +# while 循环: +while [ true ] +do + echo "loop body here..." + break +done + # 你也可以使用函数 # 定义函数: function foo () @@ -135,14 +230,50 @@ bar () foo "My name is" $NAME # 有很多有用的指令需要学习: -tail -n 10 file.txt # 打印 file.txt 的最后 10 行 -head -n 10 file.txt +tail -n 10 file.txt # 打印 file.txt 的前 10 行 -sort file.txt +head -n 10 file.txt # 将 file.txt 按行排序 -uniq -d file.txt +sort file.txt # 报告或忽略重复的行,用选项 -d 打印重复的行 -cut -d ',' -f 1 file.txt +uniq -d file.txt # 打印每行中 ',' 之前内容 +cut -d ',' -f 1 file.txt +# 将 file.txt 文件所有 'okay' 替换为 'great', (兼容正则表达式) +sed -i 's/okay/great/g' file.txt +# 将 file.txt 中匹配正则的行打印到标准输出 +# 这里打印以 "foo" 开头, "bar" 结尾的行 +grep "^foo.*bar$" file.txt +# 使用选项 "-c" 统计行数 +grep -c "^foo.*bar$" file.txt +# 如果只是要按字面形式搜索字符串而不是按正则表达式,使用 fgrep (或 grep -F) +fgrep "^foo.*bar$" file.txt + + +# 以 bash 内建的 'help' 指令阅读 Bash 自带文档: +help +help help +help for +help return +help source +help . + +# 用 mam 指令阅读相关的 Bash 手册 +apropos bash +man 1 bash +man bash + +# 用 info 指令查阅命令的 info 文档 (info 中输入 ? 显示帮助信息) +apropos info | grep '^info.*(' +man info +info info +info 5 info + +# 阅读 Bash 的 info 文档: +info bash +info bash 'Bash Features' +info bash 6 +info --apropos bash + ``` -- cgit v1.2.3 From 7a4538374c4b86a355573039cc5426a32e936d11 Mon Sep 17 00:00:00 2001 From: ryan ouyang Date: Thu, 28 May 2015 13:07:01 +0800 Subject: Update type error of chinese translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Line 344: From "行数" to "函数" --- zh-cn/javascript-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index 64b0aadc..b450ab84 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -341,7 +341,7 @@ var myFunc = myObj.myFunc; myFunc(); // = undefined // 相应的,一个函数也可以被指定为一个对象的方法,并且可以通过`this`访问 -// 这个对象的成员,即使在行数被定义时并没有依附在对象上。 +// 这个对象的成员,即使在函数被定义时并没有依附在对象上。 var myOtherFunc = function(){ return this.myString.toUpperCase(); } -- cgit v1.2.3 From 59b719015a5fadf6a1d12854a19b0196c8481ec8 Mon Sep 17 00:00:00 2001 From: Alwayswithme Date: Tue, 2 Jun 2015 15:55:12 +0800 Subject: minor revision --- zh-cn/bash-cn.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index 13f85bb7..63bec888 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -45,7 +45,7 @@ VARIABLE = "Some string" # 也不可以这样: Variable= 'Some string' # Bash 会认为 'Some string' 是一条指令,由于找不到该指令,这里再次报错。 -# (这个例子中 'Variable=' 这部分的赋值仅对 'Some string' 指令起作用。) +# (这个例子中 'Variable=' 这部分会被当作仅对 'Some string' 起作用的赋值。) # 使用变量: echo $VARIABLE @@ -264,7 +264,7 @@ apropos bash man 1 bash man bash -# 用 info 指令查阅命令的 info 文档 (info 中输入 ? 显示帮助信息) +# 用 info 指令查阅命令的 info 文档 (info 中按 ? 显示帮助信息) apropos info | grep '^info.*(' man info info info -- cgit v1.2.3 From da0d1819f85489990418713f565013f51811bdb9 Mon Sep 17 00:00:00 2001 From: Alwayswithme Date: Tue, 2 Jun 2015 16:38:11 +0800 Subject: only capitalize first character of the variable --- zh-cn/bash-cn.html.markdown | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index 63bec888..1b79f326 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -36,11 +36,11 @@ echo Hello, world! echo 'This is the first line'; echo 'This is the second line' # 声明一个变量: -VARIABLE="Some string" +Variable="Some string" # 下面是错误的做法: -VARIABLE = "Some string" -# Bash 会把 VARIABLE 当做一个指令,由于找不到该指令,因此这里会报错。 +Variable = "Some string" +# Bash 会把 Variable 当做一个指令,由于找不到该指令,因此这里会报错。 # 也不可以这样: Variable= 'Some string' @@ -48,17 +48,17 @@ Variable= 'Some string' # (这个例子中 'Variable=' 这部分会被当作仅对 'Some string' 起作用的赋值。) # 使用变量: -echo $VARIABLE -echo "$VARIABLE" -echo '$VARIABLE' +echo $Variable +echo "$Variable" +echo '$Variable' # 当你赋值 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。 # 如果要使用变量的值, 则要加 $。 # 注意: ' (单引号) 不会展开变量(即会屏蔽掉变量)。 # 在变量内部进行字符串代换 -echo ${VARIABLE/Some/A} -# 会把 VARIABLE 中首次出现的 "some" 替换成 “A”。 +echo ${Variable/Some/A} +# 会把 Variable 中首次出现的 "some" 替换成 “A”。 # 变量的截取 Length=7 @@ -80,12 +80,12 @@ echo "Scripts arguments separeted in different variables: $1 $2..." # 读取输入: echo "What's your name?" -read NAME # 这里不需要声明新变量 -echo Hello, $NAME! +read Name # 这里不需要声明新变量 +echo Hello, $Name! # 通常的 if 结构看起来像这样: # 'man test' 可查看更多的信息 -if [ $NAME -ne $USER ] +if [ $Name -ne $USER ] then echo "Your name is you username" else @@ -167,7 +167,7 @@ echo "There are $(ls | wc -l) items here." echo "There are `ls | wc -l` items here." # Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似: -case "$VARIABLE" in +case "$Variable" in # 列出需要匹配的字符串 0) echo "There is a zero.";; 1) echo "There is a one.";; @@ -175,11 +175,11 @@ case "$VARIABLE" in esac # 循环遍历给定的参数序列: -# 变量$VARIABLE 的值会被打印 3 次。 +# 变量$Variable 的值会被打印 3 次。 # 注意 ` ` 和 $( ) 等价。seq 返回长度为 3 的数组。 -for VARIABLE in `seq 3` +for Variable in `seq 3` do - echo "$VARIABLE" + echo "$Variable" done # 或传统的 “for循环” : @@ -227,7 +227,7 @@ bar () } # 调用函数 -foo "My name is" $NAME +foo "My name is" $Name # 有很多有用的指令需要学习: # 打印 file.txt 的最后 10 行 -- cgit v1.2.3 From ee7f99fc461afad7d4aba4ac4226bdf7102abee4 Mon Sep 17 00:00:00 2001 From: Alwayswithme Date: Tue, 2 Jun 2015 17:02:23 +0800 Subject: command sync with english version --- zh-cn/bash-cn.html.markdown | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index 1b79f326..558d9110 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -30,7 +30,7 @@ Bash 是一个为 GNU 计划编写的 Unix shell,是 Linux 和 Mac OS X 下的 # 如你所见,注释以 # 开头,shebang 也是注释。 # 显示 “Hello world!” -echo Hello, world! +echo Hello world! # 每一句指令以换行或分号隔开: echo 'This is the first line'; echo 'This is the second line' @@ -76,7 +76,7 @@ echo "Last program return value: $?" echo "Script's PID: $$" echo "Number of arguments: $#" echo "Scripts arguments: $@" -echo "Scripts arguments separeted in different variables: $1 $2..." +echo "Scripts arguments separated in different variables: $1 $2..." # 读取输入: echo "What's your name?" @@ -87,13 +87,13 @@ echo Hello, $Name! # 'man test' 可查看更多的信息 if [ $Name -ne $USER ] then - echo "Your name is you username" + echo "Your name isn't your username" else - echo "Your name isn't you username" + echo "Your name is your username" fi # 根据上一个指令执行结果决定是否执行下一个指令 -echo "Always executed" || echo "Only executed if first command fail" +echo "Always executed" || echo "Only executed if first command fails" echo "Always executed" && echo "Only executed if first command does NOT fail" # 在 if 语句中使用 && 和 || 需要多对方括号 @@ -176,8 +176,7 @@ esac # 循环遍历给定的参数序列: # 变量$Variable 的值会被打印 3 次。 -# 注意 ` ` 和 $( ) 等价。seq 返回长度为 3 的数组。 -for Variable in `seq 3` +for Variable in {1..3} do echo "$Variable" done @@ -275,5 +274,4 @@ info bash info bash 'Bash Features' info bash 6 info --apropos bash - ``` -- cgit v1.2.3 From 6b109e1460e11cb1030f4832ee67e89283cc6808 Mon Sep 17 00:00:00 2001 From: Todd Gao Date: Thu, 18 Jun 2015 22:20:30 +0800 Subject: cp original file to zh-cn/ --- zh-cn/groovy-cn.html.markdown | 427 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 zh-cn/groovy-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/groovy-cn.html.markdown b/zh-cn/groovy-cn.html.markdown new file mode 100644 index 00000000..519f36ce --- /dev/null +++ b/zh-cn/groovy-cn.html.markdown @@ -0,0 +1,427 @@ +--- +language: Groovy +filename: learngroovy.groovy +contributors: + - ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"] +filename: learngroovy.groovy +--- + +Groovy - A dynamic language for the Java platform [Read more here.](http://www.groovy-lang.org/) + +```groovy + +/* + Set yourself up: + + 1) Install GVM - http://gvmtool.net/ + 2) Install Groovy: gvm install groovy + 3) Start the groovy console by typing: groovyConsole + +*/ + +// Single line comments start with two forward slashes +/* +Multi line comments look like this. +*/ + +// Hello World +println "Hello world!" + +/* + Variables: + + You can assign values to variables for later use +*/ + +def x = 1 +println x + +x = new java.util.Date() +println x + +x = -3.1499392 +println x + +x = false +println x + +x = "Groovy!" +println x + +/* + Collections and maps +*/ + +//Creating an empty list +def technologies = [] + +/*** Adding a elements to the list ***/ + +// As with Java +technologies.add("Grails") + +// Left shift adds, and returns the list +technologies << "Groovy" + +// Add multiple elements +technologies.addAll(["Gradle","Griffon"]) + +/*** Removing elements from the list ***/ + +// As with Java +technologies.remove("Griffon") + +// Subtraction works also +technologies = technologies - 'Grails' + +/*** Iterating Lists ***/ + +// Iterate over elements of a list +technologies.each { println "Technology: $it"} +technologies.eachWithIndex { it, i -> println "$i: $it"} + +/*** Checking List contents ***/ + +//Evaluate if a list contains element(s) (boolean) +contained = technologies.contains( 'Groovy' ) + +// Or +contained = 'Groovy' in technologies + +// Check for multiple contents +technologies.containsAll(['Groovy','Grails']) + +/*** Sorting Lists ***/ + +// Sort a list (mutates original list) +technologies.sort() + +// To sort without mutating original, you can do: +sortedTechnologies = technologies.sort( false ) + +/*** Manipulating Lists ***/ + +//Replace all elements in the list +Collections.replaceAll(technologies, 'Gradle', 'gradle') + +//Shuffle a list +Collections.shuffle(technologies, new Random()) + +//Clear a list +technologies.clear() + +//Creating an empty map +def devMap = [:] + +//Add values +devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy'] +devMap.put('lastName','Perez') + +//Iterate over elements of a map +devMap.each { println "$it.key: $it.value" } +devMap.eachWithIndex { it, i -> println "$i: $it"} + +//Evaluate if a map contains a key +assert devMap.containsKey('name') + +//Evaluate if a map contains a value +assert devMap.containsValue('Roberto') + +//Get the keys of a map +println devMap.keySet() + +//Get the values of a map +println devMap.values() + +/* + Groovy Beans + + GroovyBeans are JavaBeans but using a much simpler syntax + + When Groovy is compiled to bytecode, the following rules are used. + + * If the name is declared with an access modifier (public, private or + protected) then a field is generated. + + * A name declared with no access modifier generates a private field with + public getter and setter (i.e. a property). + + * If a property is declared final the private field is created final and no + setter is generated. + + * You can declare a property and also declare your own getter or setter. + + * You can declare a property and a field of the same name, the property will + use that field then. + + * If you want a private or protected property you have to provide your own + getter and setter which must be declared private or protected. + + * If you access a property from within the class the property is defined in + at compile time with implicit or explicit this (for example this.foo, or + simply foo), Groovy will access the field directly instead of going though + the getter and setter. + + * If you access a property that does not exist using the explicit or + implicit foo, then Groovy will access the property through the meta class, + which may fail at runtime. + +*/ + +class Foo { + // read only property + final String name = "Roberto" + + // read only property with public getter and protected setter + String language + protected void setLanguage(String language) { this.language = language } + + // dynamically typed property + def lastName +} + +/* + Logical Branching and Looping +*/ + +//Groovy supports the usual if - else syntax +def x = 3 + +if(x==1) { + println "One" +} else if(x==2) { + println "Two" +} else { + println "X greater than Two" +} + +//Groovy also supports the ternary operator: +def y = 10 +def x = (y > 1) ? "worked" : "failed" +assert x == "worked" + +//For loop +//Iterate over a range +def x = 0 +for (i in 0 .. 30) { + x += i +} + +//Iterate over a list +x = 0 +for( i in [5,3,2,1] ) { + x += i +} + +//Iterate over an array +array = (0..20).toArray() +x = 0 +for (i in array) { + x += i +} + +//Iterate over a map +def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy'] +x = 0 +for ( e in map ) { + x += e.value +} + +/* + Operators + + Operator Overloading for a list of the common operators that Groovy supports: + http://www.groovy-lang.org/operators.html#Operator-Overloading + + Helpful groovy operators +*/ +//Spread operator: invoke an action on all items of an aggregate object. +def technologies = ['Groovy','Grails','Gradle'] +technologies*.toUpperCase() // = to technologies.collect { it?.toUpperCase() } + +//Safe navigation operator: used to avoid a NullPointerException. +def user = User.get(1) +def username = user?.username + + +/* + Closures + A Groovy Closure is like a "code block" or a method pointer. It is a piece of + code that is defined and then executed at a later point. + + More info at: http://www.groovy-lang.org/closures.html +*/ +//Example: +def clos = { println "Hello World!" } + +println "Executing the Closure:" +clos() + +//Passing parameters to a closure +def sum = { a, b -> println a+b } +sum(2,4) + +//Closures may refer to variables not listed in their parameter list. +def x = 5 +def multiplyBy = { num -> num * x } +println multiplyBy(10) + +// If you have a Closure that takes a single argument, you may omit the +// parameter definition of the Closure +def clos = { print it } +clos( "hi" ) + +/* + Groovy can memorize closure results [1][2][3] +*/ +def cl = {a, b -> + sleep(3000) // simulate some time consuming processing + a + b +} + +mem = cl.memoize() + +def callClosure(a, b) { + def start = System.currentTimeMillis() + mem(a, b) + println "Inputs(a = $a, b = $b) - took ${System.currentTimeMillis() - start} msecs." +} + +callClosure(1, 2) +callClosure(1, 2) +callClosure(2, 3) +callClosure(2, 3) +callClosure(3, 4) +callClosure(3, 4) +callClosure(1, 2) +callClosure(2, 3) +callClosure(3, 4) + +/* + Expando + + The Expando class is a dynamic bean so we can add properties and we can add + closures as methods to an instance of this class + + http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html +*/ + def user = new Expando(name:"Roberto") + assert 'Roberto' == user.name + + user.lastName = 'Pérez' + assert 'Pérez' == user.lastName + + user.showInfo = { out -> + out << "Name: $name" + out << ", Last name: $lastName" + } + + def sw = new StringWriter() + println user.showInfo(sw) + + +/* + Metaprogramming (MOP) +*/ + +//Using ExpandoMetaClass to add behaviour +String.metaClass.testAdd = { + println "we added this" +} + +String x = "test" +x?.testAdd() + +//Intercepting method calls +class Test implements GroovyInterceptable { + def sum(Integer x, Integer y) { x + y } + + def invokeMethod(String name, args) { + System.out.println "Invoke method $name with args: $args" + } +} + +def test = new Test() +test?.sum(2,3) +test?.multiply(2,3) + +//Groovy supports propertyMissing for dealing with property resolution attempts. +class Foo { + def propertyMissing(String name) { name } +} +def f = new Foo() + +assertEquals "boo", f.boo + +/* + TypeChecked and CompileStatic + Groovy, by nature, is and will always be a dynamic language but it supports + typechecked and compilestatic + + More info: http://www.infoq.com/articles/new-groovy-20 +*/ +//TypeChecked +import groovy.transform.TypeChecked + +void testMethod() {} + +@TypeChecked +void test() { + testMeethod() + + def name = "Roberto" + + println naameee + +} + +//Another example: +import groovy.transform.TypeChecked + +@TypeChecked +Integer test() { + Integer num = "1" + + Integer[] numbers = [1,2,3,4] + + Date date = numbers[1] + + return "Test" + +} + +//CompileStatic example: +import groovy.transform.CompileStatic + +@CompileStatic +int sum(int x, int y) { + x + y +} + +assert sum(2,5) == 7 + + +``` + +## Further resources + +[Groovy documentation](http://www.groovy-lang.org/documentation.html) + +[Groovy web console](http://groovyconsole.appspot.com/) + +Join a [Groovy user group](http://www.groovy-lang.org/usergroups.html) + +## Books + +* [Groovy Goodness] (https://leanpub.com/groovy-goodness-notebook) + +* [Groovy in Action] (http://manning.com/koenig2/) + +* [Programming Groovy 2: Dynamic Productivity for the Java Developer] (http://shop.oreilly.com/product/9781937785307.do) + +[1] http://roshandawrani.wordpress.com/2010/10/18/groovy-new-feature-closures-can-now-memorize-their-results/ +[2] http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize +[3] http://mrhaki.blogspot.mx/2011/05/groovy-goodness-cache-closure-results.html + + + -- cgit v1.2.3 From 021c80723e3b28d81c852b6fd58b6ec9e34670ff Mon Sep 17 00:00:00 2001 From: Todd Gao Date: Fri, 19 Jun 2015 10:58:39 +0800 Subject: zh-cn translation for groovy --- zh-cn/groovy-cn.html.markdown | 203 ++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 105 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/groovy-cn.html.markdown b/zh-cn/groovy-cn.html.markdown index 519f36ce..ccd48a4c 100644 --- a/zh-cn/groovy-cn.html.markdown +++ b/zh-cn/groovy-cn.html.markdown @@ -1,36 +1,38 @@ --- language: Groovy -filename: learngroovy.groovy +filename: learngroovy-cn.groovy contributors: - ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"] -filename: learngroovy.groovy +translators: + - ["Todd Gao", "http://github.com/7c00"] +lang: zh-cn --- -Groovy - A dynamic language for the Java platform [Read more here.](http://www.groovy-lang.org/) +Groovy - Java平台的动态语言。[了解更多。](http://www.groovy-lang.org/) ```groovy /* - Set yourself up: + 安装: - 1) Install GVM - http://gvmtool.net/ - 2) Install Groovy: gvm install groovy - 3) Start the groovy console by typing: groovyConsole + 1) 安装 GVM - http://gvmtool.net/ + 2) 安装 Groovy: gvm install groovy + 3) 启动 groovy 控制台,键入: groovyConsole */ -// Single line comments start with two forward slashes +// 双斜线开始的是单行注释 /* -Multi line comments look like this. +像这样的是多行注释 */ // Hello World println "Hello world!" /* - Variables: + 变量: - You can assign values to variables for later use + 可以给变量赋值,稍后再用 */ def x = 1 @@ -49,142 +51,137 @@ x = "Groovy!" println x /* - Collections and maps + 集合和map */ -//Creating an empty list +//创建一个空的列表 def technologies = [] -/*** Adding a elements to the list ***/ +/*** 往列表中增加一个元素 ***/ -// As with Java +// 和Java一样 technologies.add("Grails") -// Left shift adds, and returns the list +// 左移添加,返回该列表 technologies << "Groovy" -// Add multiple elements +// 增加多个元素 technologies.addAll(["Gradle","Griffon"]) -/*** Removing elements from the list ***/ +/*** 从列表中删除元素 ***/ -// As with Java +// 和Java一样 technologies.remove("Griffon") -// Subtraction works also +// 减法也行 technologies = technologies - 'Grails' -/*** Iterating Lists ***/ +/*** 遍历列表 ***/ -// Iterate over elements of a list +// 遍历列表中的元素 technologies.each { println "Technology: $it"} technologies.eachWithIndex { it, i -> println "$i: $it"} -/*** Checking List contents ***/ +/*** 检查列表内容 ***/ -//Evaluate if a list contains element(s) (boolean) +//判断列表是否包含某元素,返回boolean contained = technologies.contains( 'Groovy' ) -// Or +// 或 contained = 'Groovy' in technologies -// Check for multiple contents +// 检查多个元素 technologies.containsAll(['Groovy','Grails']) -/*** Sorting Lists ***/ +/*** 排序列表 ***/ -// Sort a list (mutates original list) +// 排序列表(修改原列表) technologies.sort() -// To sort without mutating original, you can do: +// 要想不修改原列表,可以这样: sortedTechnologies = technologies.sort( false ) -/*** Manipulating Lists ***/ +/*** 操作列表 ***/ -//Replace all elements in the list +//替换列表元素 Collections.replaceAll(technologies, 'Gradle', 'gradle') -//Shuffle a list +//打乱列表 Collections.shuffle(technologies, new Random()) -//Clear a list +//清空列表 technologies.clear() -//Creating an empty map +//创建空的map def devMap = [:] -//Add values +//增加值 devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy'] devMap.put('lastName','Perez') -//Iterate over elements of a map +//遍历map元素 devMap.each { println "$it.key: $it.value" } devMap.eachWithIndex { it, i -> println "$i: $it"} -//Evaluate if a map contains a key +//判断map是否包含某键 assert devMap.containsKey('name') -//Evaluate if a map contains a value +//判断map是否包含某值 assert devMap.containsValue('Roberto') -//Get the keys of a map +//取得map所有的键 println devMap.keySet() -//Get the values of a map +//取得map所有的值 println devMap.values() /* Groovy Beans - GroovyBeans are JavaBeans but using a much simpler syntax + GroovyBeans 是 JavaBeans,但使用了更简单的语法 - When Groovy is compiled to bytecode, the following rules are used. + Groovy 被编译为字节码时,遵循下列规则。 - * If the name is declared with an access modifier (public, private or - protected) then a field is generated. + * 如果一个名字声明时带有访问修饰符(public, private, 或者 protected), + 则会生成一个字段(field)。 - * A name declared with no access modifier generates a private field with - public getter and setter (i.e. a property). + * 名字声明时没有访问修饰符,则会生成一个带有public getter和setter的 + private字段,即属性(property)。 - * If a property is declared final the private field is created final and no - setter is generated. + * 如果一个属性声明为final,则会创建一个final的private字段,但不会生成setter。 - * You can declare a property and also declare your own getter or setter. + * 可以声明一个属性的同时定义自己的getter和setter。 - * You can declare a property and a field of the same name, the property will - use that field then. + * 可以声明具有相同名字的属性和字段,该属性会使用该字段。 - * If you want a private or protected property you have to provide your own - getter and setter which must be declared private or protected. + * 如果要定义private或protected属性,必须提供声明为private或protected的getter + 和setter。 - * If you access a property from within the class the property is defined in - at compile time with implicit or explicit this (for example this.foo, or - simply foo), Groovy will access the field directly instead of going though - the getter and setter. + * 如果使用显式或隐式的 this(例如 this.foo, 或者 foo)访问类的在编译时定义的属性, + Groovy会直接访问对应字段,而不是使用getter或者setter - * If you access a property that does not exist using the explicit or - implicit foo, then Groovy will access the property through the meta class, - which may fail at runtime. + * 如果使用显式或隐式的 foo 访问一个不存在的属性,Groovy会通过元类(meta class) + 访问它,这可能导致运行时错误。 */ class Foo { - // read only property + // 只读属性 final String name = "Roberto" - // read only property with public getter and protected setter + // 只读属性,有public getter和protected setter String language protected void setLanguage(String language) { this.language = language } - // dynamically typed property + // 动态类型属性 def lastName } /* - Logical Branching and Looping + 逻辑分支和循环 */ -//Groovy supports the usual if - else syntax +//Groovy支持常见的if - else语法 def x = 3 if(x==1) { @@ -195,32 +192,32 @@ if(x==1) { println "X greater than Two" } -//Groovy also supports the ternary operator: +//Groovy也支持三元运算符 def y = 10 def x = (y > 1) ? "worked" : "failed" assert x == "worked" -//For loop -//Iterate over a range +//for循环 +//使用区间(range)遍历 def x = 0 for (i in 0 .. 30) { x += i } -//Iterate over a list +//遍历列表 x = 0 for( i in [5,3,2,1] ) { x += i } -//Iterate over an array +//遍历数组 array = (0..20).toArray() x = 0 for (i in array) { x += i } -//Iterate over a map +//遍历map def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy'] x = 0 for ( e in map ) { @@ -228,54 +225,52 @@ for ( e in map ) { } /* - Operators + 运算符 - Operator Overloading for a list of the common operators that Groovy supports: + Groovy中下列运算符支持重载: http://www.groovy-lang.org/operators.html#Operator-Overloading - Helpful groovy operators + 实用的groovy运算符 */ -//Spread operator: invoke an action on all items of an aggregate object. +//展开(spread)运算符:对聚合对象的所有元素施加操作 def technologies = ['Groovy','Grails','Gradle'] -technologies*.toUpperCase() // = to technologies.collect { it?.toUpperCase() } +technologies*.toUpperCase() // 相当于 technologies.collect { it?.toUpperCase() } -//Safe navigation operator: used to avoid a NullPointerException. +//安全导航(safe navigation)运算符:用来避免NullPointerException def user = User.get(1) def username = user?.username /* - Closures - A Groovy Closure is like a "code block" or a method pointer. It is a piece of - code that is defined and then executed at a later point. + 闭包 + Groovy闭包好比代码块或者方法指针,它是一段定义稍后执行的代码。 - More info at: http://www.groovy-lang.org/closures.html + 更多信息见:http://www.groovy-lang.org/closures.html */ -//Example: +//例子: def clos = { println "Hello World!" } println "Executing the Closure:" clos() -//Passing parameters to a closure +//传参数给闭包 def sum = { a, b -> println a+b } sum(2,4) -//Closures may refer to variables not listed in their parameter list. +//闭包可以引用参数列表以外的变量 def x = 5 def multiplyBy = { num -> num * x } println multiplyBy(10) -// If you have a Closure that takes a single argument, you may omit the -// parameter definition of the Closure +// 只有一个参数的闭包可以省略参数的定义 def clos = { print it } clos( "hi" ) /* - Groovy can memorize closure results [1][2][3] + Groovy可以记忆闭包结果 [1][2][3] */ def cl = {a, b -> - sleep(3000) // simulate some time consuming processing + sleep(3000) // 模拟费时操作 a + b } @@ -300,8 +295,7 @@ callClosure(3, 4) /* Expando - The Expando class is a dynamic bean so we can add properties and we can add - closures as methods to an instance of this class + Expando类是一种动态bean类,可以给它的实例添加属性和添加闭包作为方法 http://mrhaki.blogspot.mx/2009/10/groovy-goodness-expando-as-dynamic-bean.html */ @@ -321,10 +315,10 @@ callClosure(3, 4) /* - Metaprogramming (MOP) + 元编程(MOP) */ -//Using ExpandoMetaClass to add behaviour +//使用ExpandoMetaClass增加行为 String.metaClass.testAdd = { println "we added this" } @@ -332,7 +326,7 @@ String.metaClass.testAdd = { String x = "test" x?.testAdd() -//Intercepting method calls +//方法调用注入 class Test implements GroovyInterceptable { def sum(Integer x, Integer y) { x + y } @@ -345,7 +339,7 @@ def test = new Test() test?.sum(2,3) test?.multiply(2,3) -//Groovy supports propertyMissing for dealing with property resolution attempts. +//Groovy支持propertyMissing,来处理属性解析尝试 class Foo { def propertyMissing(String name) { name } } @@ -354,13 +348,12 @@ def f = new Foo() assertEquals "boo", f.boo /* - TypeChecked and CompileStatic - Groovy, by nature, is and will always be a dynamic language but it supports - typechecked and compilestatic + 类型检查和静态编译 + Groovy天生是并将永远是一门静态语言,但也支持类型检查和静态编译 - More info: http://www.infoq.com/articles/new-groovy-20 + 更多: http://www.infoq.com/articles/new-groovy-20 */ -//TypeChecked +//类型检查 import groovy.transform.TypeChecked void testMethod() {} @@ -375,7 +368,7 @@ void test() { } -//Another example: +//另一例子 import groovy.transform.TypeChecked @TypeChecked @@ -390,7 +383,7 @@ Integer test() { } -//CompileStatic example: +//静态编译例子 import groovy.transform.CompileStatic @CompileStatic @@ -403,15 +396,15 @@ assert sum(2,5) == 7 ``` -## Further resources +## 进阶资源 -[Groovy documentation](http://www.groovy-lang.org/documentation.html) +[Groovy文档](http://www.groovy-lang.org/documentation.html) [Groovy web console](http://groovyconsole.appspot.com/) -Join a [Groovy user group](http://www.groovy-lang.org/usergroups.html) +加入[Groovy用户组](http://www.groovy-lang.org/usergroups.html) -## Books +## 图书 * [Groovy Goodness] (https://leanpub.com/groovy-goodness-notebook) -- cgit v1.2.3 From a6a498efab8b3ed2e8062a97e0fd47fb181b98f4 Mon Sep 17 00:00:00 2001 From: Todd Gao Date: Fri, 19 Jun 2015 12:16:41 +0800 Subject: update Chinese translation --- zh-cn/groovy-cn.html.markdown | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/groovy-cn.html.markdown b/zh-cn/groovy-cn.html.markdown index ccd48a4c..562a0284 100644 --- a/zh-cn/groovy-cn.html.markdown +++ b/zh-cn/groovy-cn.html.markdown @@ -32,7 +32,7 @@ println "Hello world!" /* 变量: - 可以给变量赋值,稍后再用 + 可以给变量赋值,以便稍后使用 */ def x = 1 @@ -51,7 +51,7 @@ x = "Groovy!" println x /* - 集合和map + 集合和映射 */ //创建一个空的列表 @@ -73,7 +73,7 @@ technologies.addAll(["Gradle","Griffon"]) // 和Java一样 technologies.remove("Griffon") -// 减法也行 +// 减号也行 technologies = technologies - 'Grails' /*** 遍历列表 ***/ @@ -93,7 +93,7 @@ contained = 'Groovy' in technologies // 检查多个元素 technologies.containsAll(['Groovy','Grails']) -/*** 排序列表 ***/ +/*** 列表排序 ***/ // 排序列表(修改原列表) technologies.sort() @@ -101,7 +101,7 @@ technologies.sort() // 要想不修改原列表,可以这样: sortedTechnologies = technologies.sort( false ) -/*** 操作列表 ***/ +/*** 列表操作 ***/ //替换列表元素 Collections.replaceAll(technologies, 'Gradle', 'gradle') @@ -112,27 +112,27 @@ Collections.shuffle(technologies, new Random()) //清空列表 technologies.clear() -//创建空的map +//创建空的映射 def devMap = [:] //增加值 devMap = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy'] devMap.put('lastName','Perez') -//遍历map元素 +//遍历映射元素 devMap.each { println "$it.key: $it.value" } devMap.eachWithIndex { it, i -> println "$i: $it"} -//判断map是否包含某键 +//判断映射是否包含某键 assert devMap.containsKey('name') -//判断map是否包含某值 +//判断映射是否包含某值 assert devMap.containsValue('Roberto') -//取得map所有的键 +//取得映射所有的键 println devMap.keySet() -//取得map所有的值 +//取得映射所有的值 println devMap.values() /* @@ -217,7 +217,7 @@ for (i in array) { x += i } -//遍历map +//遍历映射 def map = ['name':'Roberto', 'framework':'Grails', 'language':'Groovy'] x = 0 for ( e in map ) { @@ -227,7 +227,7 @@ for ( e in map ) { /* 运算符 - Groovy中下列运算符支持重载: + 在Groovy中以下常用运算符支持重载: http://www.groovy-lang.org/operators.html#Operator-Overloading 实用的groovy运算符 @@ -243,7 +243,7 @@ def username = user?.username /* 闭包 - Groovy闭包好比代码块或者方法指针,它是一段定义稍后执行的代码。 + Groovy闭包好比代码块或者方法指针,它是一段代码定义,可以以后执行。 更多信息见:http://www.groovy-lang.org/closures.html */ @@ -326,7 +326,7 @@ String.metaClass.testAdd = { String x = "test" x?.testAdd() -//方法调用注入 +//拦截方法调用 class Test implements GroovyInterceptable { def sum(Integer x, Integer y) { x + y } @@ -349,7 +349,7 @@ assertEquals "boo", f.boo /* 类型检查和静态编译 - Groovy天生是并将永远是一门静态语言,但也支持类型检查和静态编译 + Groovy天生是并将永远是一门动态语言,但也支持类型检查和静态编译 更多: http://www.infoq.com/articles/new-groovy-20 */ -- cgit v1.2.3 From abcb4e25de06ce4b295b1999fd251d76f60d5fc5 Mon Sep 17 00:00:00 2001 From: Guangming Mao Date: Wed, 8 Jul 2015 20:51:09 +0800 Subject: rust/zh Add chinese translation for rust --- zh-cn/rust-cn.html.markdown | 296 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 zh-cn/rust-cn.html.markdown (limited to 'zh-cn') diff --git a/zh-cn/rust-cn.html.markdown b/zh-cn/rust-cn.html.markdown new file mode 100644 index 00000000..f50c1566 --- /dev/null +++ b/zh-cn/rust-cn.html.markdown @@ -0,0 +1,296 @@ +--- +language: rust +contributors: + - ["P1start", "http://p1start.github.io/"] +translators: + - ["Guangming Mao", "http://maogm.com"] +filename: learnrust-cn.rs +lang: zh-cn +--- + +Rust 是由 Mozilla 研究院开发的编程语言。Rust 将底层的性能控制和高级语言的便利性和安全保障结合在了一起。 + +而 Rust 并不需要一个垃圾回收器或者运行时即可实现这个目的,这使得 Rust 库可以成为一种 C 语言的替代品。 + +Rust 第一版(0.1 版)发布于 2012 年 1 月,3 年以来一直在紧锣密鼓地迭代。 +因为更新太频繁,一般建议使用每夜构建版而不是稳定版,直到最近 1.0 版本的发布。 + +2015 年 3 月 15 日,Rust 1.0 发布,完美向后兼容,最新的每夜构建版提供了缩短编译时间等新特性。 +Rust 采用了持续迭代模型,每 6 周一个发布版。Rust 1.1 beta 版在 1.0 发布时同时发布。 + +尽管 Rust 相对来说是一门底层语言,它提供了一些常见于高级语言的函数式编程的特性。这让 Rust 不仅高效,并且易用。 + +```rust +// 这是注释,单行注释... +/* ...这是多行注释 */ + +/////////////// +// 1. 基础 // +/////////////// + +// 函数 (Functions) +// `i32` 是有符号 32 位整数类型(32-bit signed integers) +fn add2(x: i32, y: i32) -> i32 { + // 隐式返回 (不要分号) + x + y +} + +// 主函数(Main function) +fn main() { + // 数字 (Numbers) // + + // 不可变绑定 + let x: i32 = 1; + + // 整形/浮点型数 后缀 + let y: i32 = 13i32; + let f: f64 = 1.3f64; + + // 类型推导 + // 大部分时间,Rust 编译器会推导变量类型,所以不必把类型显式写出来。 + // 这个教程里面很多地方都显式写了类型,但是只是为了示范。 + // 绝大部分时间可以交给类型推导。 + let implicit_x = 1; + let implicit_f = 1.3; + + // 算术运算 + let sum = x + y + 13; + + // 可变变量 + let mut mutable = 1; + mutable = 4; + mutable += 2; + + // 字符串 (Strings) // + + // 字符串字面量 + let x: &str = "hello world!"; + + // 输出 + println!("{} {}", f, x); // 1.3 hello world + + // 一个 `String` – 在堆上分配空间的字符串 + let s: String = "hello world".to_string(); + + // 字符串分片(slice) - 另一个字符串的不可变视图 + // 基本上就是指向一个字符串的不可变指针,它不包含字符串里任何类容,只是一个指向某个东西的指针 + // 比如这里就是 `s` + let s_slice: &str = &s; + + println!("{} {}", s, s_slice); // hello world hello world + + // 数组 (Vectors/arrays) // + + // 长度固定的数组 (array) + let four_ints: [i32; 4] = [1, 2, 3, 4]; + + // 变长数组 (vector) + let mut vector: Vec = vec![1, 2, 3, 4]; + vector.push(5); + + // 分片 - 某个数组(vector/array)的不可变视图 + // 和字符串分片基本一样,只不过是针对数组的 + let slice: &[i32] = &vector; + + // 使用 `{:?}` 按调试样式输出 + println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] + + // 元组 (Tuples) // + + // 元组是固定大小的一组值,可以是不同类型 + let x: (i32, &str, f64) = (1, "hello", 3.4); + + // 解构 `let` + let (a, b, c) = x; + println!("{} {} {}", a, b, c); // 1 hello 3.4 + + // 索引 + println!("{}", x.1); // hello + + ////////////// + // 2. 类型 (Type) // + ////////////// + + // 结构体(Sturct) + struct Point { + x: i32, + y: i32, + } + + let origin: Point = Point { x: 0, y: 0 }; + + // 匿名成员结构体,又叫“元组结构体”(‘tuple struct’) + struct Point2(i32, i32); + + let origin2 = Point2(0, 0); + + // 基础的 C 风格枚举类型(enum) + enum Direction { + Left, + Right, + Up, + Down, + } + + let up = Direction::Up; + + // 有成员的枚举类型 + enum OptionalI32 { + AnI32(i32), + Nothing, + } + + let two: OptionalI32 = OptionalI32::AnI32(2); + let nothing = OptionalI32::Nothing; + + // 泛型 (Generics) // + + struct Foo { bar: T } + + // 这个在标准库里面有实现,叫 `Option` + enum Optional { + SomeVal(T), + NoVal, + } + + // 方法 (Methods) // + + impl Foo { + // 方法需要一个显式的 `self` 参数 + fn get_bar(self) -> T { + self.bar + } + } + + let a_foo = Foo { bar: 1 }; + println!("{}", a_foo.get_bar()); // 1 + + // 接口(Traits) (其他语言里叫 interfaces 或 typeclasses) // + + trait Frobnicate { + fn frobnicate(self) -> Option; + } + + impl Frobnicate for Foo { + fn frobnicate(self) -> Option { + Some(self.bar) + } + } + + let another_foo = Foo { bar: 1 }; + println!("{:?}", another_foo.frobnicate()); // Some(1) + + /////////////////////////////////// + // 3. 模板匹配 (Pattern matching) // + /////////////////////////////////// + + let foo = OptionalI32::AnI32(1); + match foo { + OptionalI32::AnI32(n) => println!("it’s an i32: {}", n), + OptionalI32::Nothing => println!("it’s nothing!"), + } + + // 高级模板匹配 + struct FooBar { x: i32, y: OptionalI32 } + let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) }; + + match bar { + FooBar { x: 0, y: OptionalI32::AnI32(0) } => + println!("The numbers are zero!"), + FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m => + println!("The numbers are the same"), + FooBar { x: n, y: OptionalI32::AnI32(m) } => + println!("Different numbers: {} {}", n, m), + FooBar { x: _, y: OptionalI32::Nothing } => + println!("The second number is Nothing!"), + } + + /////////////////////////////// + // 4. 条件控制 (Control flow) // + /////////////////////////////// + + // `for` 循环 + let array = [1, 2, 3]; + for i in array.iter() { + println!("{}", i); + } + + // 区间 (Ranges) + for i in 0u32..10 { + print!("{} ", i); + } + println!(""); + // 输出 `0 1 2 3 4 5 6 7 8 9 ` + + // `if` + if 1 == 1 { + println!("Maths is working!"); + } else { + println!("Oh no..."); + } + + // `if` 可以当表达式 + let value = if true { + "good" + } else { + "bad" + }; + + // `while` 循环 + while 1 == 1 { + println!("The universe is operating normally."); + } + + // 无限循环 + loop { + println!("Hello!"); + } + + //////////////////////////////////////////////// + // 5. 内存安全和指针 (Memory safety & pointers) // + //////////////////////////////////////////////// + + // 独占指针 (Owned pointer) - 同一时刻只能有一个对象能“拥有”这个指针 + // 意味着 `Box` 离开他的作用域后,会被安全的释放 + let mut mine: Box = Box::new(3); + *mine = 5; // 解引用 + // `now_its_mine` 获取了 `mine` 的所有权。换句话说,`mine` 移动 (move) 了 + let mut now_its_mine = mine; + *now_its_mine += 2; + + println!("{}", now_its_mine); // 7 + // println!("{}", mine); // 编译报错,因为现在 `now_its_mine` 独占那个指针 + + // 引用 (Reference) – 引用其他数据的不可变指针 + // 当引用指向某个值,我们称为“借用”这个值,因为是被不可变的借用,所以不能被修改,也不能移动 + // 借用一直持续到生命周期结束,即离开作用域 + let mut var = 4; + var = 3; + let ref_var: &i32 = &var; + + println!("{}", var); //不像 `box`, `var` 还可以继续使用 + println!("{}", *ref_var); + // var = 5; // 编译报错,因为 `var` 被借用了 + // *ref_var = 6; // 编译报错,因为 `ref_var` 是不可变引用 + + // 可变引用 (Mutable reference) + // 当一个变量被可变地借用时,也不可使用 + let mut var2 = 4; + let ref_var2: &mut i32 = &mut var2; + *ref_var2 += 2; + + println!("{}", *ref_var2); // 6 + // var2 = 2; // 编译报错,因为 `var2` 被借用了 +} +``` + +## 更深入的资料 + +Rust 还有很多很多其他类容 - 这只是 Rust 最基础的东西,帮助你了解 Rust 里面最重要的东西。 +如果想深入学习 Rust,可以去阅读 +[The Rust Programming Language](http://doc.rust-lang.org/book/index.html) +或者上 reddit [/r/rust](http://reddit.com/r/rust) 订阅。 +同时 irc.mozilla.org 的 #rust 频道上的小伙伴们也非常欢迎新来的朋友。 + +你可以在这个在线编译器 [Rust playpen](http://play.rust-lang.org) 上尝试 Rust 的一些特性 +或者上[官方网站](http://rust-lang.org). -- cgit v1.2.3 From cf26b05a233950c4ae30e0915b6892399c7f0151 Mon Sep 17 00:00:00 2001 From: Guangming Mao Date: Wed, 15 Jul 2015 16:01:37 +0800 Subject: Refine some sentences and fix some typos --- zh-cn/rust-cn.html.markdown | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/rust-cn.html.markdown b/zh-cn/rust-cn.html.markdown index f50c1566..17a897df 100644 --- a/zh-cn/rust-cn.html.markdown +++ b/zh-cn/rust-cn.html.markdown @@ -8,7 +8,7 @@ filename: learnrust-cn.rs lang: zh-cn --- -Rust 是由 Mozilla 研究院开发的编程语言。Rust 将底层的性能控制和高级语言的便利性和安全保障结合在了一起。 +Rust 是由 Mozilla 研究院开发的编程语言。Rust 将底层的性能控制与高级语言的便利性和安全保障结合在了一起。 而 Rust 并不需要一个垃圾回收器或者运行时即可实现这个目的,这使得 Rust 库可以成为一种 C 语言的替代品。 @@ -73,7 +73,7 @@ fn main() { let s: String = "hello world".to_string(); // 字符串分片(slice) - 另一个字符串的不可变视图 - // 基本上就是指向一个字符串的不可变指针,它不包含字符串里任何类容,只是一个指向某个东西的指针 + // 基本上就是指向一个字符串的不可变指针,它不包含字符串里任何内容,只是一个指向某个东西的指针 // 比如这里就是 `s` let s_slice: &str = &s; @@ -181,7 +181,7 @@ fn main() { println!("{:?}", another_foo.frobnicate()); // Some(1) /////////////////////////////////// - // 3. 模板匹配 (Pattern matching) // + // 3. 模式匹配 (Pattern matching) // /////////////////////////////////// let foo = OptionalI32::AnI32(1); @@ -190,7 +190,7 @@ fn main() { OptionalI32::Nothing => println!("it’s nothing!"), } - // 高级模板匹配 + // 高级模式匹配 struct FooBar { x: i32, y: OptionalI32 } let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) }; @@ -206,7 +206,7 @@ fn main() { } /////////////////////////////// - // 4. 条件控制 (Control flow) // + // 4. 流程控制 (Control flow) // /////////////////////////////// // `for` 循环 @@ -251,7 +251,7 @@ fn main() { //////////////////////////////////////////////// // 独占指针 (Owned pointer) - 同一时刻只能有一个对象能“拥有”这个指针 - // 意味着 `Box` 离开他的作用域后,会被安全的释放 + // 意味着 `Box` 离开他的作用域后,会被安全地释放 let mut mine: Box = Box::new(3); *mine = 5; // 解引用 // `now_its_mine` 获取了 `mine` 的所有权。换句话说,`mine` 移动 (move) 了 @@ -286,8 +286,8 @@ fn main() { ## 更深入的资料 -Rust 还有很多很多其他类容 - 这只是 Rust 最基础的东西,帮助你了解 Rust 里面最重要的东西。 -如果想深入学习 Rust,可以去阅读 +Rust 还有很多很多其他内容 - 这只是 Rust 最基本的功能,帮助你了解 Rust 里面最重要的东西。 +如果想深入学习 Rust,可以去读 [The Rust Programming Language](http://doc.rust-lang.org/book/index.html) 或者上 reddit [/r/rust](http://reddit.com/r/rust) 订阅。 同时 irc.mozilla.org 的 #rust 频道上的小伙伴们也非常欢迎新来的朋友。 -- cgit v1.2.3 From 14c628e1d914a72c81daae92d204eb8892e12889 Mon Sep 17 00:00:00 2001 From: ftwbzhao Date: Fri, 7 Aug 2015 14:30:45 +0800 Subject: Update ruby-cn.html.markdown --- zh-cn/ruby-cn.html.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown index 99250b43..14d38137 100644 --- a/zh-cn/ruby-cn.html.markdown +++ b/zh-cn/ruby-cn.html.markdown @@ -7,6 +7,7 @@ contributors: - ["Joel Walden", "http://joelwalden.net"] - ["Luke Holder", "http://twitter.com/lukeholder"] - ["lidashuang", "https://github.com/lidashuang"] + - ["ftwbzhao", "https://github.com/ftwbzhao"] translators: - ["Lin Xiangyu", "https://github.com/oa414"] --- @@ -120,11 +121,11 @@ status == :approved #=> false # 数组 # 这是一个数组 -[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] # 数组可以包含不同类型的元素 -array = [1, "hello", false] #=> => [1, "hello", false] +[1, "hello", false] #=> [1, "hello", false] # 数组可以被索引 # 从前面开始 @@ -140,8 +141,8 @@ array.[] 12 #=> nil # 从尾部开始 array[-1] #=> 5 -# 同时指定开始的位置和结束的位置 -array[2, 4] #=> [3, 4, 5] +# 同时指定开始的位置和长度 +array[2, 3] #=> [3, 4, 5] # 或者指定一个范围 array[1..3] #=> [2, 3, 4] -- cgit v1.2.3 From 63a314bd07660f33664708cc3b9e6f02ca895931 Mon Sep 17 00:00:00 2001 From: ftwbzhao Date: Fri, 7 Aug 2015 15:44:47 +0800 Subject: Update go-cn.html.markdown --- zh-cn/go-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown index 9f6a8c15..3a461efe 100644 --- a/zh-cn/go-cn.html.markdown +++ b/zh-cn/go-cn.html.markdown @@ -283,4 +283,4 @@ Go的根源在[Go官方网站](http://golang.org/)。 强烈推荐阅读语言定义部分,很简单而且很简洁!(as language definitions go these days.) -学习Go还要阅读Go标准库的源代码,全部文档化了,可读性非常好,可以学到go,go style和go idioms。在文档中点击函数名,源代码就出来了! +学习Go还要阅读Go[标准库的源代码](http://golang.org/src/),全部文档化了,可读性非常好,可以学到go,go style和go idioms。在[文档](http://golang.org/pkg/)中点击函数名,源代码就出来了! -- cgit v1.2.3 From cfb6c3a35ff52d706d337986d62104ecdb424d88 Mon Sep 17 00:00:00 2001 From: sdcuike <303286730@qq.com> Date: Fri, 7 Aug 2015 23:06:17 +0800 Subject: =?UTF-8?q?=20~=20=20=20=20=20=20=20=E5=8F=96=E5=8F=8D=EF=BC=8C?= =?UTF-8?q?=E6=B1=82=E5=8F=8D=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zh-cn/java-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/java-cn.html.markdown b/zh-cn/java-cn.html.markdown index f08d3507..12afa59a 100644 --- a/zh-cn/java-cn.html.markdown +++ b/zh-cn/java-cn.html.markdown @@ -149,7 +149,7 @@ public class LearnJava { // 位运算操作符 /* - ~ 补 + ~ 取反,求反码 << 带符号左移 >> 带符号右移 >>> 无符号右移 -- cgit v1.2.3 From 2d79a2be127a4e7e98dcc0dd68c0ea87d7278934 Mon Sep 17 00:00:00 2001 From: runfastlynda Date: Mon, 10 Aug 2015 19:56:54 +0800 Subject: input typo fixed --- zh-cn/javascript-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index b450ab84..dfeb2012 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -402,7 +402,7 @@ myObj.meaningOfLife; // = 42 // 函数也可以工作。 myObj.myFunc() // = "hello world!" -// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型,以此类堆。 +// 当然,如果你要访问的成员在原型当中也没有定义的话,解释器就会去找原型的原型,以此类推。 myPrototype.__proto__ = { myBoolean: true }; -- cgit v1.2.3 From d06bdd72a3f2f9cb4ec3e60b7d227602f37d3fbc Mon Sep 17 00:00:00 2001 From: ftwbzhao Date: Thu, 10 Sep 2015 14:48:14 +0800 Subject: two spaces --- zh-cn/markdown-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/markdown-cn.html.markdown b/zh-cn/markdown-cn.html.markdown index b1143dac..b633714d 100644 --- a/zh-cn/markdown-cn.html.markdown +++ b/zh-cn/markdown-cn.html.markdown @@ -69,7 +69,7 @@ __此文本也是__ -此段落结尾有两个空格(选中以显示)。 +此段落结尾有两个空格(选中以显示)。 上文有一个
! -- cgit v1.2.3 From 6aa3563465b3b9f2a9fc963f8d0b609c99d6be38 Mon Sep 17 00:00:00 2001 From: livehl Date: Thu, 10 Sep 2015 16:37:07 +0800 Subject: =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 哎,强迫症,看到一半特意过来改了 --- zh-cn/bash-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/bash-cn.html.markdown b/zh-cn/bash-cn.html.markdown index 558d9110..d85e5b8f 100644 --- a/zh-cn/bash-cn.html.markdown +++ b/zh-cn/bash-cn.html.markdown @@ -258,7 +258,7 @@ help return help source help . -# 用 mam 指令阅读相关的 Bash 手册 +# 用 man 指令阅读相关的 Bash 手册 apropos bash man 1 bash man bash -- cgit v1.2.3 From daa37af85646b1fa936777bfdcb9662836b66e5e Mon Sep 17 00:00:00 2001 From: Junjie Tao Date: Mon, 14 Sep 2015 21:43:02 +0800 Subject: A tiny bug --- zh-cn/go-cn.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/go-cn.html.markdown b/zh-cn/go-cn.html.markdown index 3a461efe..49224085 100644 --- a/zh-cn/go-cn.html.markdown +++ b/zh-cn/go-cn.html.markdown @@ -239,7 +239,7 @@ func learnConcurrency() { go inc(0, c) // go is a statement that starts a new goroutine. go inc(10, c) go inc(-805, c) - // 从channel中独处结果并打印。 + // 从channel中读取结果并打印。 // 打印出什么东西是不可预知的。 fmt.Println(<-c, <-c, <-c) // channel在右边的时候,<-是读操作。 -- cgit v1.2.3 From b1984042c845a73333972715e88a3d7a2e8cfdd7 Mon Sep 17 00:00:00 2001 From: Guntbert Reiter Date: Sun, 4 Oct 2015 16:44:24 +0200 Subject: Put demonstrative condition into ternary expression It should be made clear that the part before the ternary operator is indeed a condition, most often created as some comparison expression. --- zh-cn/csharp-cn.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zh-cn') diff --git a/zh-cn/csharp-cn.html.markdown b/zh-cn/csharp-cn.html.markdown index a3cda5b3..971c1be9 100644 --- a/zh-cn/csharp-cn.html.markdown +++ b/zh-cn/csharp-cn.html.markdown @@ -232,7 +232,8 @@ on a new line! ""Wow!"", the masses cried"; // 三元表达式 // 简单的 if/else 语句可以写成: // <条件> ? <真> : <假> - string isTrue = (true) ? "True" : "False"; + int toCompare = 17; + string isTrue = toCompare == 17 ? "True" : "False"; // While 循环 int fooWhile = 0; -- cgit v1.2.3 From e848adf9d53e8af5863497438753d704d30f7c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerson=20L=C3=A1zaro?= Date: Mon, 5 Oct 2015 15:20:35 -0500 Subject: Fix for issue #1248 [fa-ir, zh-cn, ko-kr, es-es, ru-ru, fr-fr, de-de] --- zh-cn/javascript-cn.html.markdown | 3 --- 1 file changed, 3 deletions(-) (limited to 'zh-cn') diff --git a/zh-cn/javascript-cn.html.markdown b/zh-cn/javascript-cn.html.markdown index dfeb2012..bdef0099 100644 --- a/zh-cn/javascript-cn.html.markdown +++ b/zh-cn/javascript-cn.html.markdown @@ -447,9 +447,6 @@ myNumber === myNumberObj; // = false if (0){ // 这段代码不会执行,因为0代表假 } -if (Number(0)){ - // 这段代码*会*执行,因为Number(0)代表真 -} // 不过,包装类型和内置类型共享一个原型, // 所以你实际可以给内置类型也增加一些功能,例如对string: -- cgit v1.2.3