summaryrefslogtreecommitdiffhomepage
path: root/zh-cn
diff options
context:
space:
mode:
Diffstat (limited to 'zh-cn')
-rw-r--r--zh-cn/asciidoc-cn.html.markdown135
-rw-r--r--zh-cn/awk-cn.html.markdown2
-rw-r--r--zh-cn/cmake-cn.html.markdown168
-rw-r--r--zh-cn/docker-cn.html.markdown150
-rw-r--r--zh-cn/dynamic-programming-cn.html.markdown2
-rw-r--r--zh-cn/gdscript-cn.html.markdown314
-rw-r--r--zh-cn/git-cn.html.markdown2
-rw-r--r--zh-cn/go-cn.html.markdown8
-rw-r--r--zh-cn/mips-cn.html.markdown334
-rw-r--r--zh-cn/nim-cn.html.markdown283
-rw-r--r--zh-cn/perl-cn.html.markdown8
-rw-r--r--zh-cn/python-cn.html.markdown740
-rw-r--r--zh-cn/raylib-cn.html.markdown147
-rw-r--r--zh-cn/red-cn.html.markdown12
-rw-r--r--zh-cn/ruby-cn.html.markdown2
-rw-r--r--zh-cn/rust-cn.html.markdown4
-rw-r--r--zh-cn/set-theory-cn.html.markdown138
-rw-r--r--zh-cn/solidity-cn.html.markdown2
-rw-r--r--zh-cn/sql-cn.html.markdown (renamed from zh-cn/sql.html.markdown)0
-rw-r--r--zh-cn/wolfram-cn.html.markdown140
20 files changed, 2407 insertions, 184 deletions
diff --git a/zh-cn/asciidoc-cn.html.markdown b/zh-cn/asciidoc-cn.html.markdown
new file mode 100644
index 00000000..74eed445
--- /dev/null
+++ b/zh-cn/asciidoc-cn.html.markdown
@@ -0,0 +1,135 @@
+---
+language: asciidoc
+filename: asciidoc-cn.md
+contributors:
+ - ["Ryan Mavilia", "http://unoriginality.rocks/"]
+ - ["Abel Salgado Romero", "https://twitter.com/abelsromero"]
+translators:
+ - ["Liu Yihua", "https://github.com/yihuajack"]
+lang: zh-cn
+---
+
+AsciiDoc 是一种类似于 Markdown 的标记语言,它可以用来写从书到博客的任何东西。它由 Stuart Rackham 在 2002 年发明,它的语言很简单,但同时也可以有丰富的定制。
+
+文档标题
+
+标题是可选的,且不可以包含空行。它必须离正文空出至少一个空行。
+
+仅标题
+
+```
+= 文档标题
+
+文档的第一句话。
+```
+
+标题和作者
+
+```
+= 文档标题
+张三 <san.zhang@learnxinyminutes.com>
+
+文档开始。
+```
+
+多名作者的情形
+
+```
+= 文档标题
+李四 <si@go.com>; 王五 <wu@yo.com>; 赵六 <xzhao@pirate.com>
+
+有多名作者的文档开始。
+```
+
+版本行(需要作者行)
+
+```
+= 文档标题(第一版)
+土豆人 <chip@crunchy.com>
+v1.0, 2016-01-13
+
+这篇关于炸薯条的文章会很有趣。
+```
+
+段落
+
+```
+段落不需要什么特别操作。
+
+在两段之间用一个空行隔开。
+
+当你需要换行时,添加一个 +
+你就会得到一个换行符!
+```
+
+文本格式化
+
+```
+_用下划线创建斜体_
+*用星号加粗*
+*_组合起来用更有趣_*
+`用重音符显示等宽字体`
+`*加粗等宽字体*`
+```
+
+节标题
+
+```
+= 第 0 级 (一般只用于文档标题)
+
+== 第 1 级 <h2>
+
+=== 第 2 级 <h3>
+
+==== 第 3 级 <h4>
+
+===== 第 4 级 <h5>
+
+```
+
+列表
+
+用星号创建无序列表。
+
+```
+* 甲
+* 乙
+* 丙
+```
+
+用句点创建有序列表。
+
+```
+. 项目 1
+. 项目 2
+. 项目 3
+```
+
+你可以用额外的星号或句点来嵌套最多五次列表。
+
+```
+* 甲 1
+** 甲 2
+*** 甲 3
+**** 甲 4
+***** 甲 5
+
+. 甲 1
+.. 甲 2
+... 甲 3
+.... 甲 4
+..... 甲 5
+```
+
+## 补充材料
+
+处理 AsciiDoc 文档有两种工具:
+
+1. [AsciiDoc](http://asciidoc.org/): 原版的 Python 实现,在主流 Linux 发行版中已附带,目前处于稳定版本维护模式。
+2. [Asciidoctor](http://asciidoctor.org/): 使用 Ruby 的另一种实现,也可以从 Java 和 JavaScript 中使用。它处于积极的开发中,目标是用新特性和输出格式扩展 AsciiDoc 的语法。
+
+以下是 `Asciidoctor` 实现的相关链接:
+
+* [Markdown - AsciiDoc 语法比较](http://asciidoctor.org/docs/user-manual/#comparison-by-example):并列比较一般 Markdown 和 AsciiDoc 的元素。
+* [入门](http://asciidoctor.org/docs/#get-started-with-asciidoctor):安装和快速启动指南,帮助构建简单的文档。
+* [Asciidoctor 用户手册](http://asciidoctor.org/docs/user-manual/): 完整的单文档指南,包含语法参考、示例、渲染工具等。
diff --git a/zh-cn/awk-cn.html.markdown b/zh-cn/awk-cn.html.markdown
index 8ee2db2c..bac833a6 100644
--- a/zh-cn/awk-cn.html.markdown
+++ b/zh-cn/awk-cn.html.markdown
@@ -179,7 +179,7 @@ function string_functions( localvar, arr) {
# 都是返回替换的个数
localvar = "fooooobar"
sub("fo+", "Meet me at the ", localvar) # localvar => "Meet me at the bar"
- gsub("e+", ".", localvar) # localvar => "m..t m. at th. bar"
+ gsub("e", ".", localvar) # localvar => "m..t m. at th. bar"
# 搜索匹配正则的字符串
# index() 也是搜索, 不支持正则
diff --git a/zh-cn/cmake-cn.html.markdown b/zh-cn/cmake-cn.html.markdown
new file mode 100644
index 00000000..dd9961ca
--- /dev/null
+++ b/zh-cn/cmake-cn.html.markdown
@@ -0,0 +1,168 @@
+---
+category: tool
+tool: cmake
+contributors:
+ - ["Bruno Alano", "https://github.com/brunoalano"]
+translators:
+ - ["tx23", "https://github.com/tx23"]
+filename: CMake-cn
+lang: zh-cn
+---
+
+CMake 是一个跨平台且开源的自动化构建系统工具。通过该工具你可以对你的源代码进行测试、编译或创建安装包。
+
+CMake 试图去解决Makefile 跨平台的自动配置问题(不同的make解释器有不同的命令),以及链接第三方库时的易用性问题。
+
+CMake是一个可扩展的开源系统,它以操作系统和与编译器无关的方式管理构建过程。与其他许多跨平台系统不同的是,
+CMake被设计为与本机的构建环境结合使用。它通过被放置于每个源文件目录下的简单配置文件(名为 CMakeLists.txt 的文件)
+来生成常规使用的标准构建文件(比如:Unix 下的 makefiles 文件或 Windows MSVC 中的 projects/workspaces)。
+
+```cmake
+# 在 CMake 中, 这是一条命令
+
+# 要运行我们的代码,请执行以下命令:
+# - mkdir build && cd build
+# - cmake ..
+# - make
+#
+# 通过上述命令,我们将遵循最佳实践在子目录中进行编译
+# 在第二行命令中我们请求Cmake 生成新的依赖于系统的Makefile文件。
+# 最后,我们运行本地的make 命令。
+
+#------------------------------------------------------------------------------
+# 基础部分
+#------------------------------------------------------------------------------
+#
+# Cmake文件必须被命令为 “CMakeLists.txt” 。
+
+# 设置生成Makefile的CMake所需最低版本要求
+cmake_minimum_required (VERSION 2.8)
+
+# 当版本小于2.8时,需要加入关键字 FATAL_ERROR。
+cmake_minimum_required (VERSION 2.8 FATAL_ERROR)
+
+# 在这里定义了项目的名称,同时会影响Cmake 生成的目录命名约定。
+# 我们可以将代码的语言作为第二个参数传入。
+project (learncmake C)
+
+# 设置项目的源目录(仅仅是由于惯例)
+set( LEARN_CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
+set( LEARN_CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
+
+# 在构建系统中用“semver”风格为我们代码设置当前版本是很有用的。
+set (LEARN_CMAKE_VERSION_MAJOR 1)
+set (LEARN_CMAKE_VERSION_MINOR 0)
+set (LEARN_CMAKE_VERSION_PATCH 0)
+
+# 将变量(版本号)发送到源代码头
+configure_file (
+ "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+ "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+)
+
+# 包含目录
+# 在 GCC中, 该语句等同于 "-I" 命令
+include_directories( include )
+
+# 在哪里安装其他库?注意:在此处提供includes路径,后续检查将解决所有其他问题
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/modules/" )
+
+# 条件
+if ( CONDITION )
+ # 输出!
+
+ # 附带信息
+ message(STATUS "My message")
+
+ # CMake 警告,继续处理
+ message(WARNING "My message")
+
+ # CMake 警告 (dev),继续处理
+ message(AUTHOR_WARNING "My message")
+
+ # CMake 错误,继续处理但是会跳过生成
+ message(SEND_ERROR "My message")
+
+ # CMake 错误,停止处理和生成
+ message(FATAL_ERROR "My message")
+endif()
+
+if( CONDITION )
+
+elseif( CONDITION )
+
+else( CONDITION )
+
+endif( CONDITION )
+
+# 循环
+foreach(loop_var arg1 arg2 ...)
+ COMMAND1(ARGS ...)
+ COMMAND2(ARGS ...)
+ ...
+endforeach(loop_var)
+
+foreach(loop_var RANGE total)
+foreach(loop_var RANGE start stop [step])
+
+foreach(loop_var IN [LISTS [list1 [...]]]
+ [ITEMS [item1 [...]]])
+
+while(condition)
+ COMMAND1(ARGS ...)
+ COMMAND2(ARGS ...)
+ ...
+endwhile(condition)
+
+
+# 逻辑运算
+if(FALSE AND (FALSE OR TRUE))
+ message("Don't display!")
+endif()
+
+# 将常规,缓存或环境变量设置为给定值。
+# 如果指定了PARENT_SCOPE选项,则将在当前作用域上的作用域中设置变量
+# `set(<variable> <value>... [PARENT_SCOPE])`
+
+# 如何在带引号和不带引号的参数中引用变量?How to reference variables inside quoted and unquoted arguments?
+# 如果未设置变量,变量引用由变量值或空字符串替换。
+${variable_name}
+
+# 清单
+# 设置源文件列表
+set( LEARN_CMAKE_SOURCES
+ src/main.c
+ src/imagem.c
+ src/pather.c
+)
+
+# 调用编译器
+#
+# ${PROJECT_NAME} 即 Learn_CMake
+add_executable( ${PROJECT_NAME} ${LEARN_CMAKE_SOURCES} )
+
+# 链接库
+target_link_libraries( ${PROJECT_NAME} ${LIBS} m )
+
+# 在哪里安装其他库?注意:在此处提供includes路径,后续检查将解决所有其他问题
+set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/modules/" )
+
+# 编译条件 (gcc ; g++)
+if ( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" )
+ message( STATUS "Setting the flags for ${CMAKE_C_COMPILER_ID} compiler" )
+ add_definitions( --std=c99 )
+endif()
+
+# 检查 OS
+if( UNIX )
+ set( LEARN_CMAKE_DEFINITIONS
+ "${LEARN_CMAKE_DEFINITIONS} -Wall -Wextra -Werror -Wno-deprecated-declarations -Wno-unused-parameter -Wno-comment" )
+endif()
+```
+
+### 资源
+
++ [CMake tutorial](https://cmake.org/cmake-tutorial/)
++ [CMake documentation](https://cmake.org/documentation/)
++ [Mastering CMake](http://amzn.com/1930934319/)
++ [An Introduction to Modern CMake](https://cliutils.gitlab.io/modern-cmake/)
diff --git a/zh-cn/docker-cn.html.markdown b/zh-cn/docker-cn.html.markdown
new file mode 100644
index 00000000..ff793ae0
--- /dev/null
+++ b/zh-cn/docker-cn.html.markdown
@@ -0,0 +1,150 @@
+---
+category: tool
+tool: docker
+lang: zh-cn
+filename: docker-cn.bat
+contributors:
+ - ["Ruslan López", "http://javapro.org/"]
+translators:
+ - ["imba-tjd", "https://github.com/imba-tjd/"]
+---
+
+```bat
+:: 下载、安装、运行 hello-world 镜像(image)
+docker run hello-world
+
+:: :: 如果这是第一次运行,你应该能见到这些信息
+:: Unable to find image 'hello-world:latest' locally # 在本地找不到镜像xxx
+:: latest: Pulling from library/hello-world
+:: 1b930d010525: Pull complete
+:: Digest: sha256:4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064
+:: Status: Downloaded newer image for hello-world:latest
+::
+:: Hello from Docker! # 来自Docker的欢迎
+:: This message shows that your installation appears to be working correctly. # 此信息表明你的安装似乎成功了
+::
+:: To generate this message, Docker took the following steps: # Docker进行了如下步骤来产生此信息
+:: 1. The Docker client contacted the Docker daemon. # Docker客户端联系Docker守护程序
+:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. # Docker守护程序从Docker Hub拉取镜像
+:: (amd64)
+:: 3. The Docker daemon created a new container from that image which runs the # Docker守护程序从镜像中创建了一个容器
+:: executable that produces the output you are currently reading. # 运行了产生你正在读的输出的可执行文件
+:: 4. The Docker daemon streamed that output to the Docker client, which sent it # Docker守护程序把输出流式传输给Docker客户端,后者发送到你的终端上
+:: to your terminal.
+::
+:: To try something more ambitious, you can run an Ubuntu container with: # 若要尝试更强大的东西,你可以用该命令运行Ubuntu容器
+:: $ docker run -it ubuntu bash
+::
+:: Share images, automate workflows, and more with a free Docker ID: # 使用免费的Docker ID来分享镜像,自动化工作流等
+:: https://hub.docker.com/
+::
+:: For more examples and ideas, visit: # 欲获取更多例子和想法,访问
+:: https://docs.docker.com/get-started/
+
+:: 现在来看看当前正运行的镜像
+docker ps
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+
+:: 看看之前运行过的镜像
+docker ps -a
+
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: 4a76281f9c53 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago
+:: happy_poincare
+:: 名字(name)是自动生成的,因此它会和你的不同
+
+:: 移除(remove)我们之前生成的镜像
+docker rm happy_poincare
+
+:: 测试是否真的删除了
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+
+:: 为容器(container)指定自定义名字
+docker run --name test_container hello-world
+:: Hello from Docker!
+:: This message shows that your installation appears to be working correctly.
+::
+:: To generate this message, Docker took the following steps:
+:: 1. The Docker client contacted the Docker daemon.
+:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
+:: (amd64)
+:: 3. The Docker daemon created a new container from that image which runs the
+:: executable that produces the output you are currently reading.
+:: 4. The Docker daemon streamed that output to the Docker client, which sent it
+:: to your terminal.
+::
+:: To try something more ambitious, you can run an Ubuntu container with:
+:: $ docker run -it ubuntu bash
+::
+:: Share images, automate workflows, and more with a free Docker ID:
+:: https://hub.docker.com/
+::
+:: For more examples and ideas, visit:
+:: https://docs.docker.com/get-started/
+
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: d345fe1a4f41 hello-world "/hello" About a minute ago Exited (0) About a minute ago
+:: test_container
+:: 如你所见,名字现在是我们指定的了
+
+:: 从命名过的容器中获取日志(logs)
+docker logs test_container
+:: Hello from Docker!
+:: This message shows that your installation appears to be working correctly.
+::
+:: To generate this message, Docker took the following steps:
+:: 1. The Docker client contacted the Docker daemon.
+:: 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
+:: (amd64)
+:: 3. The Docker daemon created a new container from that image which runs the
+:: executable that produces the output you are currently reading.
+:: 4. The Docker daemon streamed that output to the Docker client, which sent it
+:: to your terminal.
+::
+:: To try something more ambitious, you can run an Ubuntu container with:
+:: $ docker run -it ubuntu bash
+::
+:: Share images, automate workflows, and more with a free Docker ID:
+:: https://hub.docker.com/
+::
+:: For more examples and ideas, visit:
+:: https://docs.docker.com/get-started/
+
+docker rm test_container
+
+docker run ubuntu
+:: Unable to find image 'ubuntu:latest' locally
+:: latest: Pulling from library/ubuntu
+:: 2746a4a261c9: Pull complete
+:: 4c1d20cdee96: Pull complete 0d3160e1d0de: Pull complete c8e37668deea: Pull complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4
+:: Status: Downloaded newer image for ubuntu:latest
+
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: c19e9e5b000a ubuntu "/bin/bash" 5 seconds ago Exited (0) 4 seconds ago
+:: relaxed_nobel
+
+:: 在交互模式(interactive mode)下运行容器
+docker run -it ubuntu
+:: root@e2cac48323d2:/# uname
+:: Linux
+:: root@e2cac48323d2:/# exit
+:: exit
+
+docker rm relaxed_nobel
+
+docker ps -a
+:: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
+:: NAMES
+:: e2cac48323d2 ubuntu "/bin/bash" 2 minutes ago Exited (0) About a minute ago
+:: nifty_goldwasser
+
+docker rm nifty_goldwasser
+```
diff --git a/zh-cn/dynamic-programming-cn.html.markdown b/zh-cn/dynamic-programming-cn.html.markdown
index b75c5404..7864c22a 100644
--- a/zh-cn/dynamic-programming-cn.html.markdown
+++ b/zh-cn/dynamic-programming-cn.html.markdown
@@ -15,7 +15,7 @@ translators:
动态规划是一种实用的技巧,它可以用来解决一系列特定问题。它的思路很简单,如果你对某个给定的输入解决了一个问题,那么你可以保存已有信息,以避免重复计算,节约计算时间。
-记住,只有那些没有办法记住历史的才被迫做更多的苦力。(Fibonacci就是一个显然的例子)
+记住,如果忘记历史,就要被迫做更多的苦力。斐波那契数列就是一个显然的例子。
## 解决问题的方式
diff --git a/zh-cn/gdscript-cn.html.markdown b/zh-cn/gdscript-cn.html.markdown
new file mode 100644
index 00000000..3405bb8d
--- /dev/null
+++ b/zh-cn/gdscript-cn.html.markdown
@@ -0,0 +1,314 @@
+---
+language: GDScript
+contributors:
+ - ["Wichamir", "https://github.com/Wichamir/"]
+translators:
+ - ["ShiftWatchOut", "https://github.com/ShiftWatchOut"]
+filename: learngdscript-cn.gd
+lang: zh-cn
+---
+
+GDScript 是一种动态类型的脚本语言,专门为免费开源游戏引擎 Godot 制作。 GDScript 的语法类似 Python。
+它的主要优点是易于使用和与引擎深度集成。 它非常适合游戏开发。
+
+## 基础
+
+```nim
+# 单行注释使用 # 号书写。
+"""
+ 多行
+ 注释
+ 是
+ 使用
+ 文档字符串(docstring)
+ 书写。
+"""
+
+# 脚本文件本身默认是一个类,文件名为类名,您也可以为其定义其他名称。
+class_name MyClass
+
+# 继承
+extends Node2D
+
+# 成员变量
+var x = 8 # 整型
+var y = 1.2 # 浮点型
+var b = true # 布尔型
+var s = "Hello World!" # 字符串
+var a = [1, false, "brown fox"] # 数组(Array) - 类似于 Python 的列表(list),
+ # 它可以同时保存不同类型的变量。
+var d = {
+ "key" : "value",
+ 42 : true
+} # 字典包含键值对。
+var p_arr = PoolStringArray(["Hi", "there", "!"]) # 池数组只能包含单一类型。
+ # 放入其他类型会被转换为目标类型
+
+# 内置向量类型:
+var v2 = Vector2(1, 2)
+var v3 = Vector3(1, 2, 3)
+
+# 常量
+const ANSWER_TO_EVERYTHING = 42
+const BREAKFAST = "Spam and eggs!"
+
+# 枚举
+enum { ZERO, ONE , TWO, THREE }
+enum NamedEnum { ONE = 1, TWO, THREE }
+
+# 导出的变量将在检查器中可见。
+export(int) var age
+export(float) var height
+export var person_name = "Bob" # 如果设置了默认值,则不需要类型注解。
+
+# 函数
+func foo():
+ pass # pass 关键字是未书写的代码的占位符
+
+func add(first, second):
+ return first + second
+
+# 打印值
+func printing():
+ print("GDScript ", "简直", "棒呆了")
+ prints("这", "些", "字", "被", "空", "格", "分", "割")
+ printt("这", "些", "字", "被", "制", "表", "符", "分", "割")
+ printraw("这句话将被打印到系统控制台。")
+
+# 数学
+func doing_math():
+ var first = 8
+ var second = 4
+ print(first + second) # 12
+ print(first - second) # 4
+ print(first * second) # 32
+ print(first / second) # 2
+ print(first % second) # 0
+ # 还有 +=, -=, *=, /=, %= 等操作符,但并没有 ++ 和 -- .
+ print(pow(first, 2)) # 64
+ print(sqrt(second)) # 2
+ printt(PI, TAU, INF, NAN) # 内置常量
+
+# 控制流
+func control_flow():
+ x = 8
+ y = 2 # y 最初被设为一个浮点数,
+ # 但我们可以利用语言提供的动态类型能力将它的类型变为整型!
+
+ if x < y:
+ print("x 小于 y")
+ elif x > y:
+ print("x 大于 y")
+ else:
+ print("x 等于 y")
+
+ var a = true
+ var b = false
+ var c = false
+ if a and b or not c: # 你也可以用 &&, || 和 !
+ print("看到这句说明上面的条件判断为真!")
+
+ for i in range(20): # GDScript 有类似 Python 的 range 函数
+ print(i) # 所以这句将打印从 0 到 19 的数字
+
+ for i in ["two", 3, 1.0]: # 遍历数组
+ print(i)
+
+ while x > y:
+ printt(x, y)
+ y += 1
+
+ x = 2
+ y = 10
+ while x < y:
+ x += 1
+ if x == 6:
+ continue # continue 语句使 x 等于 6 时,程序跳过这次循环后面的代码,不会打印 6。
+ prints("x 等于:", x)
+ if x == 7:
+ break # 循环将在 x 等于 7 处跳出,后续所有循环不再执行,因此不会打印 8、9 和 10
+
+ match x:
+ 1:
+ print("match 很像其他语言中的 switch.")
+ 2:
+ print("但是,您不需要在每个值之前写一个 case 关键字。")
+ 3:
+ print("此外,每种情况都会默认跳出。")
+ break # 错误!不要在 match 里用 break 语句!
+ 4:
+ print("如果您需要跳过后续代码,这里也使用 continue 关键字。")
+ continue
+ _:
+ print("下划线分支,在其他分支都不满足时,在这里书写默认的逻辑。")
+
+ # 三元运算符 (写在一行的 if-else 语句)
+ prints("x 是", "正值" if x >= 0 else "负值")
+
+# 类型转换
+func casting_examples():
+ var i = 42
+ var f = float(42) # 使用变量构造函数强制转换
+ var b = i as bool # 或使用 as 关键字
+
+# 重载函数
+# 通常,我们只会重载以下划线开头的内置函数,
+# 但实际上您可以重载几乎任何函数。
+
+# _init 在对象初始化时被调用。
+# 这是对象的构造函数。
+func _init():
+ # 在此处初始化对象的内部属性。
+ pass
+
+# _ready 在脚本节点及其子节点进入场景树时被调用。
+func _ready():
+ pass
+
+# _process 在每一帧上都被调用。
+func _process(delta):
+ # 传递给此函数的 delta 参数是时间,即从上一帧到当前帧经过的秒数。
+ print("Delta 时间为:", delta)
+
+# _physics_process 在每个物理帧上都被调用。
+# 这意味着 delta 应该是恒定的。
+func _physics_process(delta):
+ # 使用向量加法和乘法进行简单移动。
+ var direction = Vector2(1, 0) # 或使用 Vector2.RIGHT
+ var speed = 100.0
+ self.global_position += direction * speed * delta
+ # self 指向当前类的实例
+
+# 重载函数时,您可以使用 . 运算符调用父函数
+# like here:
+func get_children():
+ # 在这里做一些额外的事情。
+ var r = .get_children() # 调用父函数的实现
+ return r
+
+# 内部类
+class InnerClass:
+ extends Object
+
+ func hello():
+ print("来自内部类的 Hello!")
+
+func use_inner_class():
+ var ic = InnerClass.new()
+ ic.hello()
+ ic.free() # 可以自行释放内存
+```
+
+## 访问场景树中其他节点
+
+```nim
+extends Node2D
+
+var sprite # 该变量将用来保存引用。
+
+# 您可以在 _ready 中获取对其他节点的引用。
+func _ready() -> void:
+ # NodePath 对于访问节点很有用。
+ # 将 String 传递给其构造函数来创建 NodePath:
+ var path1 = NodePath("path/to/something")
+ # 或者使用 NodePath 字面量:
+ var path2 = @"path/to/something"
+ # NodePath 示例:
+ var path3 = @"Sprite" # 相对路径,当前节点的直接子节点
+ var path4 = @"Timers/Firerate" # 相对路径,子节点的子节点
+ var path5 = @".." # 当前节点的父节点
+ var path6 = @"../Enemy" # 当前节点的兄弟节点
+ var path7 = @"/root" # 绝对路径,等价于 get_tree().get_root()
+ var path8 = @"/root/Main/Player/Sprite" # Player 的 Sprite 的绝对路径
+ var path9 = @"Timers/Firerate:wait_time" # 访问属性
+ var path10 = @"Player:position:x" # 访问子属性
+
+ # 最后,获取节点引用可以使用以下方法:
+ sprite = get_node(@"Sprite") as Sprite # 始终转换为您期望的类型
+ sprite = get_node("Sprite") as Sprite # 这里 String 被隐式转换为 NodePath
+ sprite = get_node(path3) as Sprite
+ sprite = get_node_or_null("Sprite") as Sprite
+ sprite = $Sprite as Sprite
+
+func _process(delta):
+ # 现在我们就可以在别处使用 sprite 里保存的引用了。
+ prints("Sprite 有一个全局位置 ", sprite.global_position)
+
+# 在 _ready 执行之前,使用 onready 关键字为变量赋值。
+# 这是一种常用的语法糖。
+onready var tween = $Tween as Tween
+
+# 您可以导出这个 NodePath,以便在检查器中给它赋值。
+export var nodepath = @""
+onready var reference = get_node(nodepath) as Node
+```
+
+## 信号(Signals)
+
+信号系统是 Godot 对观察者编程模式的实现。例子如下:
+
+```nim
+class_name Player extends Node2D
+
+var hp = 10
+
+signal died() # 定义一个信号
+signal hurt(hp_old, hp_new) # 信号可以带参数
+
+func apply_damage(dmg):
+ var hp_old = hp
+ hp -= dmg
+ emit_signal("hurt", hp_old, hp) # 发出信号并传递参数
+ if hp <= 0:
+ emit_signal("died")
+
+func _ready():
+ # 将信号 "died" 连接到 self 中定义的 _on_death 函数
+ self.connect("died", self, "_on_death")
+
+func _on_death():
+ self.queue_free() # 死亡时销毁 Player
+```
+
+## 类型注解
+
+GDScript 可以选择性地使用静态类型。
+
+```nim
+extends Node
+
+var x: int # 定义带有类型的变量
+var y: float = 4.2
+var z := 1.0 # 使用 := 运算符根据默认值推断类型
+
+onready var node_ref_typed := $Child as Node
+
+export var speed := 50.0
+
+const CONSTANT := "Typed constant."
+
+func _ready() -> void:
+ # 此函数不返回任何东西
+ x = "string" # 错误!不要更改类型!
+ return
+
+func join(arg1: String, arg2: String) -> String:
+ # 此函数接受两个 String 并返回一个 String。
+ return arg1 + arg2
+
+func get_child_at(index: int) -> Node:
+ # 此函数接受一个 int 并返回一个 Node
+ return get_children()[index]
+
+signal example(arg: int) # 错误!信号不能接受类型参数!
+```
+
+## 延展阅读
+
+* [Godot's Website](https://godotengine.org/)
+* [Godot Docs](https://docs.godotengine.org/en/stable/)
+* [Getting started with GDScript](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/index.html)
+* [NodePath](https://docs.godotengine.org/en/stable/classes/class_nodepath.html)
+* [Signals](https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html)
+* [GDQuest](https://www.gdquest.com/)
+* [GDScript.com](https://gdscript.com/) \ No newline at end of file
diff --git a/zh-cn/git-cn.html.markdown b/zh-cn/git-cn.html.markdown
index 63d740a1..9dfbbb93 100644
--- a/zh-cn/git-cn.html.markdown
+++ b/zh-cn/git-cn.html.markdown
@@ -370,5 +370,3 @@ $ git rm /pather/to/the/file/HelloWorld.c
* [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/go-cn.html.markdown b/zh-cn/go-cn.html.markdown
index 2953acf3..dd52d187 100644
--- a/zh-cn/go-cn.html.markdown
+++ b/zh-cn/go-cn.html.markdown
@@ -35,7 +35,7 @@ import (
"strconv" // 字符串转换
)
-// 函数声明:Main是程序执行的入口。
+// 函数声明:main是程序执行的入口。
// 不管你喜欢还是不喜欢,反正Go就用了花括号来包住函数体。
func main() {
// 往标准输出打印一行。
@@ -81,7 +81,7 @@ func learnTypes() {
f := 3.14195 // float64类型,IEEE-754 64位浮点数
c := 3 + 4i // complex128类型,内部使用两个float64表示
- // Var变量可以直接初始化。
+ // var变量可以直接初始化。
var u uint = 7 // unsigned 无符号变量,但是实现依赖int型变量的长度
var pi float32 = 22. / 7
@@ -141,7 +141,7 @@ func learnTypes() {
// 只用写return一个词就能将函数内指定名称的变量返回
func learnNamedReturns(x, y int) (z int) {
z = x * y
- return // z is implicit here, because we named it earlier.
+ return // 隐式返回z,因为前面指定了它。
}
// Go全面支持垃圾回收。Go有指针,但是不支持指针运算。
@@ -161,7 +161,7 @@ func expensiveComputation() int {
}
func learnFlowControl() {
- // If需要花括号,括号就免了
+ // if需要花括号,括号就免了
if true {
fmt.Println("这句话肯定被执行")
}
diff --git a/zh-cn/mips-cn.html.markdown b/zh-cn/mips-cn.html.markdown
new file mode 100644
index 00000000..4f9ea7da
--- /dev/null
+++ b/zh-cn/mips-cn.html.markdown
@@ -0,0 +1,334 @@
+---
+language: "MIPS Assembly"
+filename: MIPS-cn.asm
+contributors:
+ - ["Stanley Lim", "https://github.com/Spiderpig86"]
+translators:
+ - ["Liu Yihua", "https://github.com/yihuajack"]
+lang: zh-cn
+---
+
+MIPS(Microprocessor without Interlocked Pipeline Stages)汇编语言是为了配合约翰·雷洛伊·亨尼西于1981年设计的 MIPS 微处理器范式而设计的,这些 RISC 处理器用于嵌入式系统,例如网关和路由器。
+
+[阅读更多](https://en.wikipedia.org/wiki/MIPS_architecture)
+
+```asm
+# 注释用一个 '#' 表示
+
+# 一行中 '#' 之后的所有文本都会被汇编器的词法分析器忽略
+
+# 程序通常包含 .data 和 .text 部分
+
+.data # 数据存储在内存中(在RAM中分配)
+ # 类似于高级语言中的变量
+
+ # 声明遵循( 标签: .类型 值 )的声明形式
+ hello_world: .asciiz "Hello World\n" # 声明一个 null 结束的字符串
+ num1: .word 42 # 整数被视为字
+ # (32位值)
+
+ arr1: .word 1, 2, 3, 4, 5 # 字数组
+ arr2: .byte 'a', 'b' # 字符数组(每个1字节)
+ buffer: .space 60 # 在 RAM 中分配空间
+ # (不清除为0)
+
+ # 数据类型的大小
+ _byte: .byte 'a' # 1字节
+ _halfword: .half 53 # 2字节
+ _word: .word 3 # 4字节
+ _float: .float 3.14 # 4字节
+ _double: .double 7.0 # 8字节
+
+ .align 2 # 数据的内存对齐
+ # 其中数字(应是2的幂)表示几字节对齐
+ # .align 2 表示字对齐(因为 2^2 = 4 字节)
+
+.text # 这部分包括指令和程序逻辑
+.globl _main # 声明一个全局指令标签
+ # 其他文件都可以访问
+
+ _main: # MIPS 程序按顺序执行指令
+ # 这条标签下的代码将首先执行
+
+ # 打印 "hello world"
+ la $a0, hello_world # 加载存储在内存中的字符串地址
+ li $v0, 4 # 加载 syscall 的值
+ # (数字代表要执行哪个 syscall)
+ syscall # 使用给定的参数($a0)执行指定的 syscall
+
+ # 寄存器(用于在程序执行期间保存数据)
+ # $t0 - $t9 # 临时寄存器,用于过程内部的中间计算
+ # (过程调用时不保存)
+
+ # $s0 - $s7 # 保留寄存器(被保留的寄存器,过程调用时保存)
+ # 通常保存在栈中
+
+ # $a0 - $a3 # 参数寄存器,用于传递过程的参数
+ # $v0 - $v1 # 返回寄存器,用于向调用过程返回值
+
+ # 存取指令
+ la $t0, label # 将内存中由 label 指定的值的地址复制到寄存器 $t0 中
+ lw $t0, label # 从内存中复制一个字
+ lw $t1, 4($s0) # 从寄存器中存储的地址复制一个字
+ # 偏移量为4字节(地址 + 4)
+ lb $t2, label # 把一个字节复制到寄存器 $t2 的低阶部分
+ lb $t2, 0($s0) # 从 $s0 的源地址复制一个字节
+ # 偏移量为0
+ # 同理也适用于 'lh' (取半字)
+
+ sw $t0, label # 将字存储到由 label 映射的内存地址中
+ sw $t0, 8($s0) # 将字存储到 $s0 指定的地址中
+ # 偏移量为8字节
+ # 同理也适用于 'sb' (存字)和 'sh' (存半字)。'sa'不存在
+
+### 数学 ###
+ _math:
+ # 记住要将值加载到寄存器中
+ lw $t0, num # 从数据部分
+ li $t0, 5 # 或者从一个立即数(常数)
+ li $t1, 6
+ add $t2, $t0, $t1 # $t2 = $t0 + $t1
+ sub $t2, $t0, $t1 # $t2 = $t0 - $t1
+ mul $t2, $t0, $t1 # $t2 = $t0 * $t1
+ div $t2, $t0, $t1 # $t2 = $t0 / $t1
+ # (MARS 的某些版本可能不支持)
+ div $t0, $t1 # 执行 $t0 / $t1。
+ # 用 'mflo' 得商,用 'mfhi' 得余数
+
+ # 移位
+ sll $t0, $t0, 2 # 按位左移立即数(常数值)2
+ sllv $t0, $t1, $t2 # 根据一个寄存器中的变量值左移相应位
+ srl $t0, $t0, 5 # 按位右移
+ # (不保留符号,用0符号扩展)
+ srlv $t0, $t1, $t2 # 根据一个寄存器中的变量值右移相应位
+ sra $t0, $t0, 7 # 按算术位右移(保留符号)
+ srav $t0, $t1, $t2 # 根据一个寄存器中的变量值右移相应算数位
+
+ # 按位运算符
+ and $t0, $t1, $t2 # 按位与
+ andi $t0, $t1, 0xFFF # 用立即数按位与
+ or $t0, $t1, $t2 # 按位或
+ ori $t0, $t1, 0xFFF # 用立即数按位或
+ xor $t0, $t1, $t2 # 按位异或
+ xori $t0, $t1, 0xFFF # 用立即数按位异或
+ nor $t0, $t1, $t2 # 按位或非
+
+## 分支 ##
+ _branching:
+ # 分支指令的基本格式通常遵循 <指令> <寄存器1> <寄存器2> <标签>
+ # 如果给定的条件求值为真,则跳转到标签
+ # 有时向后编写条件逻辑更容易,如下面的简单的 if 语句示例所示
+
+ beq $t0, $t1, reg_eq # 如果 $t0 == $t1,则跳转到 reg_eq
+ # 否则执行下一行
+ bne $t0, $t1, reg_neq # 当 $t0 != $t1 时跳转
+ b branch_target # 非条件分支,总会执行
+ beqz $t0, req_eq_zero # 当 $t0 == 0 时跳转
+ bnez $t0, req_neq_zero # 当 $t0 != 0 时跳转
+ bgt $t0, $t1, t0_gt_t1 # 当 $t0 > $t1 时跳转
+ bge $t0, $t1, t0_gte_t1 # 当 $t0 >= $t1 时跳转
+ bgtz $t0, t0_gt0 # 当 $t0 > 0 时跳转
+ blt $t0, $t1, t0_gt_t1 # 当 $t0 < $t1 时跳转
+ ble $t0, $t1, t0_gte_t1 # 当 $t0 <= $t1 时跳转
+ bltz $t0, t0_lt0 # 当 $t0 < 0 时跳转
+ slt $s0, $t0, $t1 # 当 $t0 < $t1 时结果为 $s0 (1为真)
+
+ # 简单的 if 语句
+ # if (i == j)
+ # f = g + h;
+ # f = f - i;
+
+ # 让 $s0 = f, $s1 = g, $s2 = h, $s3 = i, $s4 = j
+ bne $s3, $s4, L1 # if (i !=j)
+ add $s0, $s1, $s2 # f = g + h
+
+ L1:
+ sub $s0, $s0, $s3 # f = f - i
+
+ # 下面是一个求3个数的最大值的例子
+ # 从 Java 到 MIPS 逻辑的直接翻译:
+ # if (a > b)
+ # if (a > c)
+ # max = a;
+ # else
+ # max = c;
+ # else
+ # max = b;
+ # else
+ # max = c;
+
+ # 让 $s0 = a, $s1 = b, $s2 = c, $v0 = 返回寄存器
+ ble $s0, $s1, a_LTE_b # 如果 (a <= b) 跳转到 (a_LTE_b)
+ ble $s0, $s2, max_C # 如果 (a > b && a <= c) 跳转到 (max_C)
+ move $v0, $s0 # 否则 [a > b && a > c] max = a
+ j done # 跳转到程序结束
+
+ a_LTE_b: # 当 a <= b 时的标签
+ ble $s1, $s2, max_C # 如果 (a <= b && b <= c) 跳转到 (max_C)
+ move $v0, $s1 # 如果 (a <= b && b > c) max = b
+ j done # 跳转到 done
+
+ max_C:
+ move $v0, $s2 # max = c
+
+ done: # 程序结束
+
+## 循环 ##
+ _loops:
+ # 循环的基本结构是一个退出条件和一个继续执行的跳转指令
+ li $t0, 0
+ while:
+ bgt $t0, 10, end_while # 当 $t0 小于 10,不停迭代
+ addi $t0, $t0, 1 # 累加值
+ j while # 跳转回循环开始
+ end_while:
+
+ # 二维矩阵遍历
+ # 假设 $a0 存储整数 3 × 3 矩阵的地址
+ li $t0, 0 # 计数器 i
+ li $t1, 0 # 计数器 j
+ matrix_row:
+ bgt $t0, 3, matrix_row_end
+
+ matrix_col:
+ bgt $t1, 3, matrix_col_end
+
+ # 执行一些东西
+
+ addi $t1, $t1, 1 # 累加列计数器
+ matrix_col_end:
+
+ # 执行一些东西
+
+ addi $t0, $t0, 1
+ matrix_row_end:
+
+## 函数 ##
+ _functions:
+ # 函数是可调用的过程,可以接受参数并返回所有用标签表示的值,如前所示
+
+ main: # 程序以 main 函数开始
+ jal return_1 # jal 会把当前程序计数器(PC)存储在 $ra
+ # 并跳转到 return_1
+
+ # 如果我们想传入参数呢?
+ # 首先,我们必须将形参传递给参数寄存器
+ li $a0, 1
+ li $a1, 2
+ jal sum # 现在我们可以调用函数了
+
+ # 递归怎么样?
+ # 这需要更多的工作
+ # 由于 jal 会自动覆盖每次调用,我们需要确保在 $ra 中保存并恢复之前的程序计数器
+ li $a0, 3
+ jal fact
+
+ li $v0, 10
+ syscall
+
+ # 这个函数返回1
+ return_1:
+ li $v0, 1 # 将值取到返回寄存器 $v0 中
+ jr $ra # 跳转回原先的程序计数器继续执行
+
+
+ # 有2个参数的函数
+ sum:
+ add $v0, $a0, $a1
+ jr $ra # 返回
+
+ # 求阶乘的递归函数
+ fact:
+ addi $sp, $sp, -8 # 在栈中分配空间
+ sw $s0, ($sp) # 存储保存当前数字的寄存器
+ sw $ra, 4($sp) # 存储先前的程序计数器
+
+ li $v0, 1 # 初始化返回值
+ beq $a0, 0, fact_done # 如果参数为0则完成
+
+ # 否则继续递归
+ move $s0, $a0 # 复制 $a0 到 $s0
+ sub $a0, $a0, 1
+ jal fact
+
+ mul $v0, $s0, $v0 # 做乘法
+
+ fact_done:
+ lw $s0, ($sp)
+ lw $ra, ($sp) # 恢复程序计数器
+ addi $sp, $sp, 8
+
+ jr $ra
+
+## 宏 ##
+ _macros:
+ # 宏可以实现用单个标签替换重复的代码块,这可以增强程序的可读性
+ # 它们绝不是函数的替代品
+ # 它们必须在使用之前声明
+
+ # 用于打印换行符的宏(这可以被多次重用)
+ .macro println()
+ la $a0, newline # 存储在这里的新行字符串
+ li $v0, 4
+ syscall
+ .end_macro
+
+ println() # 汇编器会在运行前复制此代码块
+
+ # 参数可以通过宏传入。
+ # 它们由 '%' 符号表示,可以选择起任意名字
+ .macro print_int(%num)
+ li $v0, 1
+ lw $a0, %num
+ syscall
+ .end_macro
+
+ li $t0, 1
+ print_int($t0)
+
+ # 我们也可以给宏传递立即数
+ .macro immediates(%a, %b)
+ add $t0, %a, %b
+ .end_macro
+
+ immediates(3, 5)
+
+ # 以及标签
+ .macro print(%string)
+ la $a0, %string
+ li $v0, 4
+ syscall
+ .end_macro
+
+ print(hello_world)
+
+## 数组 ##
+.data
+ list: .word 3, 0, 1, 2, 6 # 这是一个字数组
+ char_arr: .asciiz "hello" # 这是一个字符数组
+ buffer: .space 128 # 在内存中分配块,不会自动清除
+ # 这些内存块彼此对齐
+
+.text
+ la $s0, list # 取 list 的地址
+ li $t0, 0 # 计数器
+ li $t1, 5 # list 的长度
+
+ loop:
+ bgt $t0, $t1, end_loop
+
+ lw $a0, ($s0)
+ li $v0, 1
+ syscall # 打印数字
+
+ addi $s0, $s0, 4 # 字的大小为4字节
+ addi $t0, $t0, 1 # 累加
+ j loop
+ end_loop:
+
+## INCLUDE ##
+# 使用 include 语句可以将外部文件导入到程序中
+# (它只是将文件中的代码放入 include 语句的位置)
+.include "somefile.asm"
+
+```
diff --git a/zh-cn/nim-cn.html.markdown b/zh-cn/nim-cn.html.markdown
new file mode 100644
index 00000000..dc662b1e
--- /dev/null
+++ b/zh-cn/nim-cn.html.markdown
@@ -0,0 +1,283 @@
+---
+language: Nim
+filename: learnNim-cn.nim
+contributors:
+ - ["Jason J. Ayala P.", "http://JasonAyala.com"]
+ - ["Dennis Felsing", "http://felsin9.de/nnis/"]
+translators:
+ - ["lzw-723", "https://github.com/lzw-723"]
+lang: zh-cn
+---
+
+Nim(原名Nimrod)是一种静态类型的命令式编程语言,
+它能在不影响运行时效率的情况下为程序员提供强大的功能。
+
+Nim语言高效、有表现力、优雅。
+
+```nim
+# 单行注释以一个#开头
+
+#[
+ 这是多行注释
+ 在Nim语言中,多行注释可以嵌套,以#[开头,以]#结尾
+]#
+
+discard """
+这也可以作为多行注释使用。
+或者用于无法解析、损坏的代码
+"""
+
+var # 声明(和赋值)变量
+ letter: char = 'n' # 带或不带类型批注
+ lang = "N" & "im"
+ nLength: int = len(lang)
+ boat: float
+ truth: bool = false
+
+ let # 使用let*一次性*声明和绑定变量。
+ legs = 400 # legs是不可改变的。
+ arms = 2_000 # _会被忽略,对long类型非常有用。
+ aboutPi = 3.15
+
+const # 常量在编译时计算。这确保了
+ debug = true # 性能,在编译时表达式中很有用。
+ compileBadCode = false
+
+when compileBadCode: # `when`是编译时的`if`
+ legs = legs + 1 # 这个错误永远不会被编译。
+ const input = readline(stdin) # const在编译时必须是已知的。
+
+discard 1 > 2 # 注意:如果表达式的结果未使用,
+ # 编译器会发出警告。`discard`绕过了这一点。
+
+
+#
+# 数据结构
+#
+
+# 元组(Tuple)
+
+var
+ child: tuple[name: string, age: int] # 元组有*字段名*
+ today: tuple[sun: string, temp: float] # 和*顺序*
+
+
+child = (name: "Rudiger", age: 2) # 使用字面值()一次性赋值全部
+today.sun = "Overcast" # 也可以单独赋值
+today.temp = 70.1
+
+# 序列(Sequence)
+
+var
+ drinks: seq[string]
+
+drinks = @["Water", "Juice", "Chocolate"] # @[V1,..,Vn] 是序列的字面值
+
+drinks.add("Milk")
+
+if "Milk" in drinks:
+ echo "We have Milk and ", drinks.len - 1, " other drinks"
+
+let myDrink = drinks[2]
+
+#
+# 自定义类型
+#
+
+# 定义你自己的类型使得编译器为你工作。
+# 这使得静态类型变得强大和有用。
+
+type
+ Name = string # 类型别名为你提供一个新类型,
+ Age = int # 该类型可与旧类型互换,但更具描述性。
+ Person = tuple[name: Name, age: Age] # 也可以定义数据结构。
+ AnotherSyntax = tuple
+ fieldOne: string
+ secondField: int
+
+var
+ john: Person = (name: "John B.", age: 17)
+ newage: int = 18 # 在这里使用Age比int要好
+
+john.age = newage # 仍然有效,因为int和Age同义
+
+type
+ Cash = distinct int # `distinct`使一个新类型与它的基本类型不兼容。
+ Desc = distinct string
+
+var
+ money: Cash = 100.Cash # `.Cash`把int转换成我们的类型
+ description: Desc = "Interesting".Desc
+
+when compileBadCode:
+ john.age = money # 错误!age是int类型、money是Cash类型
+ john.name = description # 编译器说:“没门!”
+
+#
+# 更多类型和数据结构
+#
+
+# 枚举类型只能具有有限数量的值之一
+
+type
+ Color = enum cRed, cBlue, cGreen
+ Direction = enum # 可选格式
+ dNorth
+ dWest
+ dEast
+ dSouth
+var
+ orient = dNorth # `orient`的类型是Direction,值是`dNorth`
+ pixel = cGreen # `pixel`的类型是Color,值是`cGreen`
+
+discard dNorth > dEast # Enum通常是“序数”类型
+
+# 子范围指定有限的有效范围
+
+type
+ DieFaces = range[1..20] # 只有从1到20的int才是有效值
+var
+ my_roll: DieFaces = 13
+
+when compileBadCode:
+ my_roll = 23 # 错误!
+
+# 数组(Array)
+
+type
+ RollCounter = array[DieFaces, int] # 数组长度固定
+ DirNames = array[Direction, string] # 以任意有序类型索引
+ Truths = array[42..44, bool]
+var
+ counter: RollCounter
+ directions: DirNames
+ possible: Truths
+
+possible = [false, false, false] # 数组字面以[V1,..,Vn]表示
+possible[42] = true
+
+directions[dNorth] = "Ahh. The Great White North!"
+directions[dWest] = "No, don't go there."
+
+my_roll = 13
+counter[my_roll] += 1
+counter[my_roll] += 1
+
+var anotherArray = ["Default index", "starts at", "0"]
+
+# 可用的数据结构包括表、集合、列表、队列、压缩前缀树。
+# http://nim-lang.org/docs/lib.html#collections-and-algorithms
+
+#
+# IO和控制流
+#
+
+# `case`, `readLine()`
+
+echo "Read any good books lately?"
+case readLine(stdin)
+of "no", "No":
+ echo "Go to your local library."
+of "yes", "Yes":
+ echo "Carry on, then."
+else:
+ echo "That's great; I assume."
+
+# `while`, `if`, `continue`, `break`
+
+import strutils as str # http://nim-lang.org/docs/strutils.html
+echo "I'm thinking of a number between 41 and 43. Guess which!"
+let number: int = 42
+var
+ raw_guess: string
+ guess: int
+while guess != number:
+ raw_guess = readLine(stdin)
+ if raw_guess == "": continue # 跳出循环
+ guess = str.parseInt(raw_guess)
+ if guess == 1001:
+ echo("AAAAAAGGG!")
+ break
+ elif guess > number:
+ echo("Nope. Too high.")
+ elif guess < number:
+ echo(guess, " is too low")
+ else:
+ echo("Yeeeeeehaw!")
+
+#
+# 循环(Iteration)
+#
+
+for i, elem in ["Yes", "No", "Maybe so"]: # 也可以是`for elem in`
+ echo(elem, " is at index: ", i)
+
+for k, v in items(@[(person: "You", power: 100), (person: "Me", power: 9000)]):
+ echo v
+
+let myString = """
+an <example>
+`string` to
+play with
+""" # 多行字符串
+
+for line in splitLines(myString):
+ echo(line)
+
+for i, c in myString: # 索引和字符。或使用'for j in'只有字符
+ if i mod 2 == 0: continue # 紧凑的'if'形式
+ elif c == 'X': break
+ else: echo(c)
+
+#
+# 过程(Procedure)
+#
+
+type Answer = enum aYes, aNo
+
+proc ask(question: string): Answer =
+ echo(question, " (y/n)")
+ while true:
+ case readLine(stdin)
+ of "y", "Y", "yes", "Yes":
+ return Answer.aYes # 枚举类型可以
+ of "n", "N", "no", "No":
+ return Answer.aNo
+ else: echo("Please be clear: yes or no")
+
+proc addSugar(amount: int = 2) = # amount默认是2,不返回任何值
+ assert(amount > 0 and amount < 9000, "Crazy Sugar")
+ for a in 1..amount:
+ echo(a, " sugar...")
+
+case ask("Would you like sugar in your tea?")
+of aYes:
+ addSugar(3)
+of aNo:
+ echo "Oh do take a little!"
+ addSugar()
+# 这里不需要使用`else` 。只能是`yes`和`no`。
+
+#
+# 外部函数接口(FFI)
+#
+
+# 因为Nim可以编译为C,使用外部函数接口(FFI)很简单:
+
+proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.}
+
+let cmp = strcmp("C?", "Easy!")
+```
+
+除此以外,Nim通过元编程、性能和编译时特性将自己与其他同类分离开来。
+
+## 进阶阅读
+
+* [主页](http://nim-lang.org)
+* [下载](http://nim-lang.org/download.html)
+* [社区](http://nim-lang.org/community.html)
+* [常见问题](http://nim-lang.org/question.html)
+* [文档](http://nim-lang.org/documentation.html)
+* [参考手册](http://nim-lang.org/docs/manual.html)
+* [标准库](http://nim-lang.org/docs/lib.html)
+* [Rosetta Code](http://rosettacode.org/wiki/Category:Nim)
diff --git a/zh-cn/perl-cn.html.markdown b/zh-cn/perl-cn.html.markdown
index 4421da6e..46c54618 100644
--- a/zh-cn/perl-cn.html.markdown
+++ b/zh-cn/perl-cn.html.markdown
@@ -146,7 +146,7 @@ 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`
+- [perl-tutorial](http://perl-tutorial.org/)
+- [www.perl.com的learn站点](http://www.perl.org/learn.html)
+- [perldoc](http://perldoc.perl.org/)
+- 以及 perl 内置的: `perldoc perlintro`
diff --git a/zh-cn/python-cn.html.markdown b/zh-cn/python-cn.html.markdown
index 6c5556fc..a4e53c1b 100644
--- a/zh-cn/python-cn.html.markdown
+++ b/zh-cn/python-cn.html.markdown
@@ -6,8 +6,10 @@ contributors:
- ["Andre Polykanine", "https://github.com/Oire"]
translators:
- ["Geoff Liu", "http://geoffliu.me"]
+ - ["Maple", "https://github.com/mapleincode"]
filename: learnpython-cn.py
lang: zh-cn
+
---
Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计。
@@ -19,7 +21,6 @@ Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计。
注意:这篇教程是基于 Python 3 写的。如果你想学旧版 Python 2,我们特别有[另一篇教程](http://learnxinyminutes.com/docs/pythonlegacy/)。
```python
-
# 用井字符开头的是单行注释
""" 多行字符串用三个引号
@@ -35,50 +36,66 @@ Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计。
3 # => 3
# 算术没有什么出乎意料的
-1 + 1 # => 2
-8 - 1 # => 7
+1 + 1 # => 2
+8 - 1 # => 7
10 * 2 # => 20
# 但是除法例外,会自动转换成浮点数
35 / 5 # => 7.0
-5 / 3 # => 1.6666666666666667
+10.0 / 3 # => 3.3333333333333335
# 整数除法的结果都是向下取整
-5 // 3 # => 1
-5.0 // 3.0 # => 1.0 # 浮点数也可以
--5 // 3 # => -2
--5.0 // 3.0 # => -2.0
+5 // 3 # => 1
+5.0 // 3.0 # => 1.0 # 浮点数也可以
+-5 // 3 # => -2
+-5.0 // 3.0 # => -2.0
# 浮点数的运算结果也是浮点数
3 * 2.0 # => 6.0
# 模除
7 % 3 # => 1
+# i % j 结果的正负符号会和 j 相同,而不是和 i 相同
+-7 % 3 # => 2
-# x的y次方
+# x 的 y 次方
2**4 # => 16
# 用括号决定优先级
+1 + 3 * 2 # => 7
(1 + 3) * 2 # => 8
-# 布尔值
-True
-False
+# 布尔值 (注意: 首字母大写)
+True # => True
+False # => False
-# 用not取非
-not True # => False
+# 用 not 取非
+not True # => False
not False # => True
-# 逻辑运算符,注意and和or都是小写
+# 逻辑运算符,注意 and 和 or 都是小写
True and False # => False
False or True # => True
-# 整数也可以当作布尔值
-0 and 2 # => 0
--5 or 0 # => -5
+# True 和 False 实质上就是数字 1 和0
+True + True # => 2
+True * 8 # => 8
+False - 5 # => -5
+
+# 数值与 True 和 False 之间的比较运算
0 == False # => True
2 == True # => False
1 == True # => True
+-5 != False # => True
+
+# 使用布尔逻辑运算符对数字类型的值进行运算时,会把数值强制转换为布尔值进行运算
+# 但计算结果会返回它们的强制转换前的值
+# 注意不要把 bool(ints) 与位运算的 "按位与"、"按位或" (&, |) 混淆
+bool(0) # => False
+bool(4) # => True
+bool(-6) # => True
+0 and 2 # => 0
+-5 or 0 # => -5
# 用==判断相等
1 == 1 # => True
@@ -94,47 +111,71 @@ False or True # => True
2 <= 2 # => True
2 >= 2 # => True
+# 判断一个值是否在范围里
+1 < 2 and 2 < 3 # => True
+2 < 3 and 3 < 2 # => False
# 大小比较可以连起来!
1 < 2 < 3 # => True
2 < 3 < 2 # => False
-# 字符串用单引双引都可以
+# (is 对比 ==) is 判断两个变量是否引用同一个对象,
+# 而 == 判断两个对象是否含有相同的值
+a = [1, 2, 3, 4] # 变量 a 是一个新的列表, [1, 2, 3, 4]
+b = a # 变量 b 赋值了变量 a 的值
+b is a # => True, a 和 b 引用的是同一个对象
+b == a # => True, a 和 b 的对象的值相同
+b = [1, 2, 3, 4] # 变量 b 赋值了一个新的列表, [1, 2, 3, 4]
+b is a # => False, a 和 b 引用的不是同一个对象
+b == a # => True, a 和 b 的对象的值相同
+
+
+# 创建字符串可以使用单引号(')或者双引号(")
"这是个字符串"
'这也是个字符串'
-# 用加号连接字符串
+# 字符串可以使用加号连接成新的字符串
"Hello " + "world!" # => "Hello world!"
+# 非变量形式的字符串甚至可以在没有加号的情况下连接
+"Hello " "world!" # => "Hello world!"
# 字符串可以被当作字符列表
-"This is a string"[0] # => 'T'
+"Hello world!"[0] # => 'H'
-# 用.format来格式化字符串
-"{} can be {}".format("strings", "interpolated")
+# 你可以获得字符串的长度
+len("This is a string") # => 16
+# 你可以使用 f-strings 格式化字符串(python3.6+)
+name = "Reiko"
+f"She said her name is {name}." # => "She said her name is Reiko"
+# 你可以在大括号内几乎加入任何 python 表达式,表达式的结果会以字符串的形式返回
+f"{name} is {len(name)} characters long." # => "Reiko is 5 characters long."
+
+# 用 .format 来格式化字符串
+"{} can be {}".format("strings", "interpolated")
# 可以重复参数以节省时间
"{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"
-
# 如果不想数参数,可以用关键字
"{name} wants to eat {food}".format(name="Bob", food="lasagna")
# => "Bob wants to eat lasagna"
-# 如果你的Python3程序也要在Python2.5以下环境运行,也可以用老式的格式化语法
+# 如果你的 Python3 程序也要在 Python2.5 以下环境运行,也可以用老式的格式化语法
"%s can be %s the %s way" % ("strings", "interpolated", "old")
# None是一个对象
None # => None
-# 当与None进行比较时不要用 ==,要用is。is是用来比较两个变量是否指向同一个对象。
+# 当与 None 进行比较时不要用 ==,要用 is。is 是用来比较两个变量是否指向同一个对象。
"etc" is None # => False
None is None # => True
-# None,0,空字符串,空列表,空字典都算是False
-# 所有其他值都是True
+# None,0,空字符串,空列表,空字典,空元组都算是 False
+# 所有其他值都是 True
bool(0) # => False
bool("") # => False
bool([]) # => False
bool({}) # => False
+bool(()) # => False
####################################################
@@ -144,16 +185,26 @@ bool({}) # => False
# print是内置的打印函数
print("I'm Python. Nice to meet you!")
+# 默认情况下,print 函数会在输出结果后加入一个空行作为结尾
+# 可以使用附加参数改变输出结尾
+print("Hello, World", end="!") # => Hello, World!
+
+# 可以很简单的从终端获得输入数据
+input_string_var = input("Enter some data: ") # 返回字符串数值
+
# 在给变量赋值前不用提前声明
-# 传统的变量命名是小写,用下划线分隔单词
+# 习惯上变量命名是小写,用下划线分隔单词
some_var = 5
some_var # => 5
# 访问未赋值的变量会抛出异常
# 参考流程控制一段来学习异常处理
-some_unknown_var # 抛出NameError
+some_unknown_var # 抛出 NameError
+
+# "if" 可以用作表达式,它的作用等同于 C 语言的三元运算符 "?:"
+"yay!" if 0 > 1 else "nay!" # => "nay!"
-# 用列表(list)储存序列
+# 用列表 (list) 储存序列
li = []
# 创建列表时也可以同时赋给元素
other_li = [4, 5, 6]
@@ -173,128 +224,177 @@ li[0] # => 1
# 取出最后一个元素
li[-1] # => 3
-# 越界存取会造成IndexError
-li[4] # 抛出IndexError
+# 越界存取会造成 IndexError
+li[4] # 抛出 IndexError
# 列表有切割语法
-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]
# 隔一个取一个
-li[::2] # =>[1, 4]
+li[::2] # =>[1, 4]
# 倒排列表
li[::-1] # => [3, 4, 2, 1]
# 可以用三个参数的任何组合来构建切割
# li[始:终:步伐]
-# 用del删除任何一个元素
-del li[2] # li is now [1, 2, 3]
+# 简单的实现了单层数组的深度复制
+li2 = li[:] # => li2 = [1, 2, 4, 3] ,但 (li2 is li) 会返回 False
+
+# 用 del 删除任何一个元素
+del li[2] # li 现在为 [1, 2, 3]
+
+# 删除第一个匹配的元素
+li.remove(2) # li 现在为 [1, 3]
+li.remove(2) # 抛出错误 ValueError: 2 is not in the list
+
+# 在指定索引处插入一个新的元素
+li.insert(1, 2) # li is now [1, 2, 3] again
+
+# 获得列表第一个匹配的值的索引
+li.index(2) # => 1
+li.index(4) # 抛出一个 ValueError: 4 is not in the list
# 列表可以相加
-# 注意:li和other_li的值都不变
+# 注意:li 和 other_li 的值都不变
li + other_li # => [1, 2, 3, 4, 5, 6]
-# 用extend拼接列表
-li.extend(other_li) # li现在是[1, 2, 3, 4, 5, 6]
+# 用 "extend()" 拼接列表
+li.extend(other_li) # li 现在是[1, 2, 3, 4, 5, 6]
-# 用in测试列表是否包含值
+# 用 "in" 测试列表是否包含值
1 in li # => True
-# 用len取列表长度
+# 用 "len()" 取列表长度
len(li) # => 6
-# 元组是不可改变的序列
+# 元组类似列表,但是不允许修改
tup = (1, 2, 3)
tup[0] # => 1
-tup[0] = 3 # 抛出TypeError
+tup[0] = 3 # 抛出 TypeError
+
+# 如果元素数量为 1 的元组必须在元素之后加一个逗号
+# 其他元素数量的元组,包括空元组,都不需要
+type((1)) # => <class 'int'>
+type((1,)) # => <class 'tuple'>
+type(()) # => <class 'tuple'>
-# 列表允许的操作元组大都可以
+# 列表允许的操作元组大多都可以
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
+# 也可以做扩展解包
+a, *b, c = (1, 2, 3, 4) # 现在 a 是 1, b 是 [2, 3], c 是 4
# 元组周围的括号是可以省略的
-d, e, f = 4, 5, 6
+d, e, f = 4, 5, 6 # 元组 4, 5, 6 通过解包被赋值给变量 d, e, f
# 交换两个变量的值就这么简单
-e, d = d, e # 现在d是5,e是4
+e, d = d, e # 现在 d 是 5,e 是 4
-# 用字典表达映射关系
+# 字典用来存储 key 到 value 的映射关系
empty_dict = {}
# 初始化的字典
filled_dict = {"one": 1, "two": 2, "three": 3}
+# 字典的 key 必须为不可变类型。 这是为了确保 key 被转换为唯一的哈希值以用于快速查询
+# 不可变类型包括整数、浮点、字符串、元组
+invalid_dict = {[1,2,3]: "123"} # => 抛出 TypeError: unhashable type: 'list'
+valid_dict = {(1,2,3):[1,2,3]} # 然而 value 可以是任何类型
+
# 用[]取值
filled_dict["one"] # => 1
-
# 用 keys 获得所有的键。
-# 因为 keys 返回一个可迭代对象,所以在这里把结果包在 list 里。我们下面会详细介绍可迭代。
-# 注意:字典键的顺序是不定的,你得到的结果可能和以下不同。
-list(filled_dict.keys()) # => ["three", "two", "one"]
+# 因为 keys 返回一个可迭代对象,所以我们需要把它包在 "list()" 里才能转换为列表。
+# 我们下面会详细介绍可迭代。
+# 注意: 对于版本 < 3.7 的 python, 字典的 key 的排序是无序的。你的运行结果
+# 可能与下面的例子不符,但是在 3.7 版本,字典中的项会按照他们被插入到字典的顺序进行排序
+list(filled_dict.keys()) # => ["three", "two", "one"] Python 版本 <3.7
+list(filled_dict.keys()) # => ["one", "two", "three"] Python 版本 3.7+
+# 用 "values()" 获得所有的值。跟 keys 一样也是可迭代对象,要使用 "list()" 才能转换为列表。
+# 注意: 排序顺序和 keys 的情况相同。
-# 用values获得所有的值。跟keys一样,要用list包起来,顺序也可能不同。
-list(filled_dict.values()) # => [3, 2, 1]
+list(filled_dict.values()) # => [3, 2, 1] Python 版本 < 3.7
+list(filled_dict.values()) # => [1, 2, 3] Python 版本 3.7+
# 用in测试一个字典是否包含一个键
"one" in filled_dict # => True
1 in filled_dict # => False
-# 访问不存在的键会导致KeyError
+# 访问不存在的键会导致 KeyError
filled_dict["four"] # KeyError
-# 用get来避免KeyError
-filled_dict.get("one") # => 1
-filled_dict.get("four") # => None
-# 当键不存在的时候get方法可以返回默认值
+# 用 "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
+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
# 字典赋值
filled_dict.update({"four":4}) # => {"one": 1, "two": 2, "three": 3, "four": 4}
-filled_dict["four"] = 4 # 另一种赋值方法
+filled_dict["four"] = 4 # 另一种赋值方法
-# 用del删除
-del filled_dict["one"] # 从filled_dict中把one删除
+# 用 del 删除项
+del filled_dict["one"] # 从 filled_dict 中把 one 删除
-# 用set表达集合
+# 用 set 表达集合
empty_set = set()
# 初始化一个集合,语法跟字典相似。
-some_set = {1, 1, 2, 2, 3, 4} # some_set现在是{1, 2, 3, 4}
+some_set = {1, 1, 2, 2, 3, 4} # some_set现在是 {1, 2, 3, 4}
+
+# 类似字典的 keys,set 的元素也必须是不可变类型
+invalid_set = {[1], 1} # => Raises a TypeError: unhashable type: 'list'
+valid_set = {(1,), 1}
# 可以把集合赋值于变量
filled_set = some_set
# 为集合添加元素
-filled_set.add(5) # filled_set现在是{1, 2, 3, 4, 5}
+filled_set.add(5) # filled_set 现在是 {1, 2, 3, 4, 5}
+# set 没有重复的元素
+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}
+# "^" 取异或集(对称差)
+{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5}
+
+# 判断左边的集合是否是右边集合的超集
+{1, 2} >= {1, 2, 3} # => False
+
+# 判断左边的集合是否是右边集合的子集
+{1, 2} <= {1, 2, 3} # => True
+
# in 测试集合是否包含元素
2 in filled_set # => True
10 in filled_set # => False
+# 单层集合的深度复制
+filled_set = some_set.copy() # filled_set 是 {1, 2, 3, 4, 5}
+filled_set is some_set # => False
####################################################
## 3. 流程控制和迭代器
@@ -303,28 +403,30 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6}
# 先随便定义一个变量
some_var = 5
-# 这是个if语句。注意缩进在Python里是有意义的
-# 印出"some_var比10小"
+# 这是个if语句。注意缩进在Python里是有意义的!
+# 缩进要使用 4 个空格而不是 tabs。
+# 这段代码会打印 "some_var is smaller than 10"
if some_var > 10:
- print("some_var比10大")
-elif some_var < 10: # elif句是可选的
- print("some_var比10小")
-else: # else也是可选的
- print("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 也是可选的
+ print("some_var is indeed 10.")
"""
-用for循环语句遍历列表
+用 for 循环语句遍历列表
打印:
dog is a mammal
cat is a mammal
mouse is a mammal
"""
for animal in ["dog", "cat", "mouse"]:
+ # 你可以使用 format() 格式化字符串并插入值
print("{} is a mammal".format(animal))
"""
-"range(number)"返回数字列表从0到给的数字
+"range(number)" 返回数字列表从 0 到 number 的数字
打印:
0
1
@@ -333,9 +435,41 @@ for animal in ["dog", "cat", "mouse"]:
"""
for i in range(4):
print(i)
+
+"""
+"range(lower, upper)" 会返回一个包含从 lower 到 upper 的数字迭代器
+prints:
+ 4
+ 5
+ 6
+ 7
+"""
+for i in range(4, 8):
+ print(i)
"""
-while循环直到条件不满足
+"range(lower, upper, step)" 会返回一个,从 lower 到 upper、并且间隔值为 step 的迭代器。
+如果 step 未传入则会使用默认值 1
+prints:
+ 4
+ 6
+"""
+for i in range(4, 8, 2):
+ print(i)
+
+"""
+遍历列表,并且同时返回列表里的每一个元素的索引和数值。
+prints:
+ 0 dog
+ 1 cat
+ 2 mouse
+"""
+animals = ["dog", "cat", "mouse"]
+for i, value in enumerate(animals):
+ print(i, value)
+
+"""
+while 循环直到条件不满足
打印:
0
1
@@ -347,20 +481,51 @@ 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是无操作,但是应该在这里处理错误
+ pass # pass 是无操作,但是应该在这里处理错误
except (TypeError, NameError):
- pass # 可以同时处理不同类的错误
-else: # else语句是可选的,必须在所有的except之后
+ pass # 可以同时处理不同类的错误
+else: # else语句是可选的,必须在所有的except之后
print("All good!") # 只有当try运行完没有错误的时候这句才会运行
+finally: # 在任何情况下都会执行
+ print("We can clean up resources here")
+
+# 你可以使用 with 语句来代替 try/finally 对操作进行结束的操作
+with open("myfile.txt") as f:
+ for line in f:
+ print(line)
+
+# 写入文件
+contents = {"aa": 12, "bb": 21}
+with open("myfile1.txt", "w+") as file:
+ file.write(str(contents)) # 写入字符串到文件
+
+with open("myfile2.txt", "w+") as file:
+ file.write(json.dumps(contents)) # 写入对象到文件
+
+# Reading from a file
+with open("myfile1.txt", "r+") as file:
+ contents = file.read() # 从文件读取字符串
+print(contents)
+# print: {"aa": 12, "bb": 21}
+
+with open("myfile2.txt", "r+") as file:
+ contents = json.load(file) # 从文件读取 json 对象
+print(contents)
+# print: {"aa": 12, "bb": 21}
+
+# Windows 环境调用 open() 读取文件的默认编码为 ANSI,如果需要读取 utf-8 编码的文件,
+# 需要指定 encoding 参数:
+# open("myfile3.txt", "r+", encoding = "utf-8")
-# Python提供一个叫做可迭代(iterable)的基本抽象。一个可迭代对象是可以被当作序列
-# 的对象。比如说上面range返回的对象就是可迭代的。
+# Python 提供一个叫做可迭代 (iterable) 的基本抽象。一个可迭代对象是可以被当作序列
+# 的对象。比如说上面 range 返回的对象就是可迭代的。
filled_dict = {"one": 1, "two": 2, "three": 3}
our_iterable = filled_dict.keys()
@@ -377,19 +542,24 @@ our_iterable[1] # 抛出TypeError
our_iterator = iter(our_iterable)
# 迭代器是一个可以记住遍历的位置的对象
-# 用__next__可以取得下一个元素
-our_iterator.__next__() # => "one"
+# 用 "next()" 获得下一个对象
+next(our_iterator) # => "one"
-# 再一次调取__next__时会记得位置
-our_iterator.__next__() # => "two"
-our_iterator.__next__() # => "three"
+# 再一次调取 "next()" 时会记得位置
+next(our_iterator) # => "two"
+next(our_iterator) # => "three"
-# 当迭代器所有元素都取出后,会抛出StopIteration
-our_iterator.__next__() # 抛出StopIteration
+# 当迭代器所有元素都取出后,会抛出 StopIteration
+next(our_iterator) # 抛出 StopIteration
-# 可以用list一次取出迭代器所有的元素
-list(filled_dict.keys()) # => Returns ["one", "two", "three"]
+# 我们可以通过遍历还访问所有的值,实际上,for 内部实现了迭代
+our_iterator = iter(our_iterable)
+for i in our_iterator:
+ print(i) # 依次打印 one, two, three
+# 可以用 list 一次取出迭代器或者可迭代对象所有的元素
+list(filled_dict.keys()) # => 返回 ["one", "two", "three"]
+list(our_iterator) # => 返回 [] 因为迭代的位置被保存了
####################################################
@@ -399,10 +569,10 @@ list(filled_dict.keys()) # => Returns ["one", "two", "three"]
# 用def定义新函数
def add(x, y):
print("x is {} and y is {}".format(x, y))
- return x + y # 用return语句返回
+ 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) # 关键字参数可以用任何顺序
@@ -433,33 +603,43 @@ 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) # 相当于 all_the_args(1, 2, 3, 4)
all_the_args(**kwargs) # 相当于 all_the_args(a=3, b=4)
all_the_args(*args, **kwargs) # 相当于 all_the_args(1, 2, 3, 4, a=3, b=4)
+# 使用返回多个数值(返回值为元组类型)
+def swap(x, y):
+ return y, x # 用不带括号的元组的格式来返回多个数值
+ # (注意: 括号不需要加,但是也可以加)
+
+x = 1
+y = 2
+x, y = swap(x, y) # => x = 2, y = 1
+# (x, y) = swap(x,y) # 同上,括号不需要加,但是也可以加
+
# 函数作用域
x = 5
def setX(num):
- # 局部作用域的x和全局域的x是不同的
+ # 局部作用域的 x 和全局域的 x 是不同的
x = num # => 43
print (x) # => 43
def setGlobalX(num):
global x
print (x) # => 5
- x = num # 现在全局域的x被赋值
+ x = num # 现在全局域的 x 被赋值
print (x) # => 6
setX(43)
setGlobalX(6)
-# 函数在Python是一等公民
+# 函数在 Python 是一等公民
def create_adder(x):
def adder(y):
return x + y
@@ -469,39 +649,90 @@ add_10 = create_adder(10)
add_10(3) # => 13
# 也有匿名函数
-(lambda x: x > 2)(3) # => True
+(lambda x: x > 2)(3) # => True
+(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5
# 内置的高阶函数
-map(add_10, [1, 2, 3]) # => [11, 12, 13]
-filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
+list(map(add_10, [1, 2, 3])) # => [11, 12, 13]
+list(map(max, [1, 2, 3], [4, 2, 1])) # => [4, 2, 3]
+
+list(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]
+# 你也可以用这种方式实现对集合和字典的构建
+{x for x in 'abcddeef' if x not in 'abc'} # => {'d', 'e', 'f'}
+{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
+
+
####################################################
-## 5. 类
+## 5. 模块
####################################################
+# 导入模块
+import math
+print(math.sqrt(16)) # => 4.0
+
+# 你可以导入模块中具体的函数
+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 文件
+# 你可以自己编写自己的模块,然后导入
+# 模块的名称和文件名相同
+
+# 你可以用 "dir()" 查看模块中定义的函数和字段
+import math
+dir(math)
+
+# 当你的脚本文件所在的文件夹也包含了一个名为 math.py 的 Python 文件
+# 这个 math.p 文件会被代替引入,而不是引入 Python 內建模块中的 math
+# 出现这个情况的原因是本地文件夹的引入优先级要比 Python 內建库引入优先级要高
+
+
+####################################################
+## 6. 类
+####################################################
-# 定义一个继承object的类
-class Human(object):
+# 我们使用 "class" 语句来创建类
+class Human:
- # 类属性,被所有此类的实例共用。
+ # 一个类的字段。 这个字段共享给这个类的所有实例。
species = "H. sapiens"
- # 构造方法,当实例被初始化时被调用。注意名字前后的双下划线,这是表明这个属
- # 性或方法对Python有特殊意义,但是允许用户自行定义。你自己取名时不应该用这
- # 种格式。
+ # 构造方法,当实例被初始化时被调用。注意名字前后的双下划线,这是表明这个属性
+ # 或方法对 Python 有特殊意义,但是允许用户自行定义。
+ # 方法(可能是对象或者属性) 类似: __init__, __str__,__repr__ etc
+ # 都是特殊的方法
+ # 你自己取名时不应该用这种格式
def __init__(self, name):
- # Assign the argument to the instance's name attribute
+ # 将参数赋值给实例的 name 字段
self.name = name
- # 实例方法,第一个参数总是self,就是这个实例对象
+ # 初始化属性
+ self._age = 0
+
+ # 实例方法,第一个参数总是self,也就是这个实例对象
def say(self, msg):
- return "{name}: {message}".format(name=self.name, message=msg)
+ print("{name}: {message}".format(name=self.name, message=msg))
+
+ # 另一个实例方法
+ def sing(self):
+ return 'yo... yo... microphone check... one two... one two...'
- # 类方法,被所有此类的实例共用。第一个参数是这个类对象。
+ # 类方法,被所有此类的实例共用。
+ # 第一个参数是这个类对象。
@classmethod
def get_species(cls):
return cls.species
@@ -511,53 +742,225 @@ class Human(object):
def grunt():
return "*grunt*"
+ # property 有点类似 getter
+ # 它把方法 age() 转换为同名并且只读的属性
+ # 通常情况下,可以不需要编写复杂的 getter 和 setter。
+ @property
+ def age(self):
+ return self._age
+
+ # 允许属性被修改
+ @age.setter
+ def age(self, age):
+ self._age = age
+
+ # 允许属性被删除
+ @age.deleter
+ def age(self):
+ del self._age
+
+# 当 Python 解释器在读取源文件的时候,就会执行文件中所有的代码
+# 对 __name__ 的检查可以保证这块代码只会在执行这个模块是住程序情况下被运行(而不是在引用时运行)
+if __name__ == '__main__':
+ #
+ i = Human(name="Ian")
+ i.say("hi") # "Ian: hi"
+ j = Human("Joel")
+ j.say("hello") # "Joel: hello"
+ # i 和 j 都是 Human 实例化后的对象,换一句话说,它们都是 Human 实例
+
+ # 运行类方法 (classmethod)
+ i.say(i.get_species()) # "Ian: H. sapiens"
+ # 修改共享的类属性
+ Human.species = "H. neanderthalensis"
+ i.say(i.get_species()) # => "Ian: H. neanderthalensis"
+ j.say(j.get_species()) # => "Joel: H. neanderthalensis"
+
+ # 运行静态方法 (staticmethod)
+ print(Human.grunt()) # => "*grunt*"
+
+ # 实例上也可以执行静态方法
+ print(i.grunt()) # => "*grunt*"
+
+ # 更新实例的属性
+ i.age = 42
+ # 访问实例的属性
+ i.say(i.age) # => "Ian: 42"
+ j.say(j.age) # => "Joel: 0"
+ # 删除实例的属性
+ del i.age
+ # i.age # => 这会抛出一个错误: AttributeError
+
+
+####################################################
+## 6.1 类的继承
+####################################################
+
+# 继承机制允许子类可以继承父类上的方法和变量。
+# 我们可以把 Human 类作为一个基础类或者说叫做父类,
+# 然后定义一个名为 Superhero 的子类来继承父类上的比如 "species"、 "name"、 "age" 的属性
+# 和比如 "sing" 、"grunt" 这样的方法,同时,也可以定义它自己独有的属性
+
+# 基于 Python 文件模块化的特点,你可以把这个类放在独立的文件中,比如说,human.py。
+
+# 要从别的文件导入函数,需要使用以下的语句
+# from "filename-without-extension" import "function-or-class"
+
+from human import Human
+
+# 指定父类作为类初始化的参数
+class Superhero(Human):
+
+ # 如果子类需要继承所有父类的定义,并且不需要做任何的修改,
+ # 你可以直接使用 "pass" 关键字(并且不需要其他任何语句)
+ # 但是在这个例子中会被注释掉,以用来生成不一样的子类。
+ # pass
+
+ # 子类可以重写父类定义的字段
+ species = 'Superhuman'
+
+ # 子类会自动的继承父类的构造函数包括它的参数,但同时,子类也可以新增额外的参数或者定义,
+ # 甚至去覆盖父类的方法比如说构造函数。
+ # 这个构造函数从父类 "Human" 上继承了 "name" 参数,同时又新增了 "superpower" 和
+ # "movie" 参数:
+ def __init__(self, name, movie=False,
+ superpowers=["super strength", "bulletproofing"]):
+
+ # 新增额外类的参数
+ self.fictional = True
+ self.movie = movie
+ # 注意可变的默认值,因为默认值是共享的
+ self.superpowers = superpowers
+
+ # "super" 函数让你可以访问父类中被子类重写的方法
+ # 在这个例子中,被重写的是 __init__ 方法
+ # 这个语句是用来运行父类的构造函数:
+ super().__init__(name)
+
+ # 重写父类中的 sing 方法
+ def sing(self):
+ return 'Dun, dun, DUN!'
+
+ # 新增一个额外的方法
+ def boast(self):
+ for power in self.superpowers:
+ print("I wield the power of {pow}!".format(pow=power))
+
+
+if __name__ == '__main__':
+ sup = Superhero(name="Tick")
+
+ # 检查实例类型
+ if isinstance(sup, Human):
+ print('I am human')
+ if type(sup) is Superhero:
+ print('I am a superhero')
-# 构造一个实例
-i = Human(name="Ian")
-print(i.say("hi")) # 印出 "Ian: hi"
+ # 获取方法解析顺序 MRO,MRO 被用于 getattr() 和 super()
+ # 这个字段是动态的,并且可以被修改
+ print(Superhero.__mro__) # => (<class '__main__.Superhero'>,
+ # => <class 'human.Human'>, <class 'object'>)
-j = Human("Joel")
-print(j.say("hello")) # 印出 "Joel: hello"
+ # 调用父类的方法并且使用子类的属性
+ print(sup.get_species()) # => Superhuman
-# 调用一个类方法
-i.get_species() # => "H. sapiens"
+ # 调用被重写的方法
+ print(sup.sing()) # => Dun, dun, DUN!
-# 改一个共用的类属性
-Human.species = "H. neanderthalensis"
-i.get_species() # => "H. neanderthalensis"
-j.get_species() # => "H. neanderthalensis"
+ # 调用 Human 的方法
+ sup.say('Spoon') # => Tick: Spoon
-# 调用静态方法
-Human.grunt() # => "*grunt*"
+ # 调用 Superhero 独有的方法
+ sup.boast() # => I wield the power of super strength!
+ # => I wield the power of bulletproofing!
+
+ # 继承类的字段
+ sup.age = 31
+ print(sup.age) # => 31
+
+ # Superhero 独有的字段
+ print('Am I Oscar eligible? ' + str(sup.movie))
####################################################
-## 6. 模块
+## 6.2 多重继承
####################################################
-# 用import导入模块
-import math
-print(math.sqrt(16)) # => 4.0
+# 定义另一个类
+# bat.py
+class Bat:
-# 也可以从模块中导入个别值
-from math import ceil, floor
-print(ceil(3.7)) # => 4.0
-print(floor(3.7)) # => 3.0
+ species = 'Baty'
-# 可以导入一个模块中所有值
-# 警告:不建议这么做
-from math import *
+ def __init__(self, can_fly=True):
+ self.fly = can_fly
-# 如此缩写模块名字
-import math as m
-math.sqrt(16) == m.sqrt(16) # => True
+ # 这个类同样有 say 的方法
+ def say(self, msg):
+ msg = '... ... ...'
+ return msg
-# Python模块其实就是普通的Python文件。你可以自己写,然后导入,
-# 模块的名字就是文件的名字。
+ # 新增一个独有的方法
+ def sonar(self):
+ return '))) ... ((('
-# 你可以这样列出一个模块里所有的值
-import math
-dir(math)
+if __name__ == '__main__':
+ b = Bat()
+ print(b.say('hello'))
+ print(b.fly)
+
+# 现在我们来定义一个类来同时继承 Superhero 和 Bat
+# superhero.py
+from superhero import Superhero
+from bat import Bat
+
+# 定义 Batman 作为子类,来同时继承 SuperHero 和 Bat
+class Batman(Superhero, Bat):
+
+ def __init__(self, *args, **kwargs):
+ # 通常要继承属性,你必须调用 super:
+ # super(Batman, self).__init__(*args, **kwargs)
+ # 然而在这里我们处理的是多重继承,而 super() 只会返回 MRO 列表的下一个基础类。
+ # 因此,我们需要显式调用初始类的 __init__
+ # *args 和 **kwargs 传递参数时更加清晰整洁,而对于父类而言像是 “剥了一层洋葱”
+ Superhero.__init__(self, 'anonymous', movie=True,
+ superpowers=['Wealthy'], *args, **kwargs)
+ Bat.__init__(self, *args, can_fly=False, **kwargs)
+ # 重写了 name 字段
+ self.name = 'Sad Affleck'
+
+ def sing(self):
+ return 'nan nan nan nan nan batman!'
+
+
+if __name__ == '__main__':
+ sup = Batman()
+
+ # 获取方法解析顺序 MRO,MRO 被用于 getattr() 和 super()
+ # 这个字段是动态的,并且可以被修改
+ print(Batman.__mro__) # => (<class '__main__.Batman'>,
+ # => <class 'superhero.Superhero'>,
+ # => <class 'human.Human'>,
+ # => <class 'bat.Bat'>, <class 'object'>)
+
+ # 调用父类的方法并且使用子类的属性
+ print(sup.get_species()) # => Superhuman
+
+ # 调用被重写的类
+ print(sup.sing()) # => nan nan nan nan nan batman!
+
+ # 调用 Human 上的方法,(之所以是 Human 而不是 Bat),是因为继承顺序起了作用
+ sup.say('I agree') # => Sad Affleck: I agree
+
+ # 调用仅存在于第二个继承的父类的方法
+ print(sup.sonar()) # => ))) ... (((
+
+ # 继承类的属性
+ sup.age = 100
+ print(sup.age) # => 100
+
+ # 从第二个类上继承字段,并且其默认值被重写
+ print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
####################################################
@@ -582,6 +985,10 @@ for i in double_numbers(range_):
print(i)
if i >= 30:
break
+# 你也可以把一个生成器推导直接转换为列表
+values = (-x for x in [1,2,3,4,5])
+gen_to_list = list(values)
+print(gen_to_list) # => [-1, -2, -3, -4, -5]
# 装饰器(decorators)
@@ -611,18 +1018,27 @@ print(say()) # Can you buy me a beer?
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
```
-## 想继续学吗?
-### 线上免费材料(英文)
-* [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)
+### 在线免费材料(英文)
+
+* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com/)
+* [Ideas for Python Projects](http://pythonpracticeprojects.com/)
+* [The Official Docs](https://docs.python.org/3/)
+* [Hitchhiker’s Guide to Python](https://docs.python-guide.org/en/latest/)
+* [Python Course](https://www.python-course.eu/)
+* [Free Interactive Python Course](http://www.kikodo.io/)
+* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
+* [A curated list of awesome Python frameworks, libraries and software](https://github.com/vinta/awesome-python)
+* [30 Python Language Features and Tricks You May Not Know About](https://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html)
+* [Official Style Guide for Python](https://www.python.org/dev/peps/pep-0008/)
+* [Python 3 Computer Science Circles](https://cscircles.cemc.uwaterloo.ca/)
+* [Dive Into Python 3](https://www.diveintopython3.net/index.html)
+* [A Crash Course in Python for Scientists](https://nbviewer.jupyter.org/gist/anonymous/5924718)
+* [Python Tutorial for Intermediates](https://pythonbasics.org/)
+* [Build a Desktop App with Python](https://pythonpyqt.com/)
### 书籍(也是英文)
diff --git a/zh-cn/raylib-cn.html.markdown b/zh-cn/raylib-cn.html.markdown
new file mode 100644
index 00000000..c88aa91e
--- /dev/null
+++ b/zh-cn/raylib-cn.html.markdown
@@ -0,0 +1,147 @@
+---
+category: tool
+tool: raylib
+lang: zh-cn
+filename: learnraylib-cn.c
+contributors:
+ - ["Nikolas Wipper", "https://notnik.cc"]
+translators:
+ - ["lzw-723", "https://github.com/lzw-723"]
+---
+
+**raylib** 是一个跨平台、易用的图形库,围绕OpenGL 1.1、2.1、3.3和OpenGL ES 2.0构建。
+虽然它是用C语言编写的,却有超过50种不同语言的绑定。本教程将使用C语言。
+更确切地说,是C99。
+
+```c
+#include <raylib.h>
+
+int main(void)
+{
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ // 在初始化raylib之前,可以设置标志位
+ SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT);
+
+ // raylib并不要求我们存储任何实例结构
+ // 目前raylib一次只能处理一个窗口
+ InitWindow(screenWidth, screenHeight, "MyWindow");
+
+ // 设置我们的游戏以每秒60帧的速度运行
+ SetTargetFPS(60);
+
+ // 设置一个关闭窗口的键。
+ //可以是0,表示没有键
+ SetExitKey(KEY_DELETE);
+
+ // raylib定义了两种类型的相机。Camera3D和Camera2D
+ // Camera是Camera3D的一个类型化定义
+ Camera camera = {
+ .position = {0.0f, 0.0f, 0.0f},
+ .target = {0.0f, 0.0f, 1.0f},
+ .up = {0.0f, 1.0f, 0.0f},
+ .fovy = 70.0f,
+ .type = CAMERA_PERSPECTIVE
+ };
+
+
+ // raylib支持加载各种不同的文件格式的模型、动画、图像和声音。
+ Model myModel = LoadModel("my_model.obj");
+ Font someFont = LoadFont("some_font.ttf");
+
+ // 创建一个100x100的渲染纹理
+ RenderTexture renderTexture = LoadRenderTexture(100, 100);
+
+ // WindowShouldClose方法检查用户是否正在关闭窗口。
+ // 可能用的是快捷方式、窗口控制或之前设置的关闭窗口键
+ while (!WindowShouldClose())
+ {
+
+ // BeginDrawing方法要在任何绘图操作之前被调用。
+ BeginDrawing();
+ {
+
+ // 为背景设定某种颜色
+ ClearBackground(BLACK);
+
+ if (IsKeyDown(KEY_SPACE))
+ DrawCircle(400, 400, 30, GREEN);
+
+ // 简单地绘制文本
+ DrawText("Congrats! You created your first window!",
+ 190, // x
+ 200, // y
+ 20, // 字体大小
+ LIGHTGRAY
+ );
+
+ // 大多数函数都有几个版本
+ // 通常后缀为Ex, Pro, V
+ // 或者是Rec、Wires(仅适用于3D)、Lines(仅适用于2D)。
+ DrawTextEx(someFont,
+ "Text in another font",
+ (Vector2) {10, 10},
+ 20, // 字体大小
+ 2, // 间距
+ LIGHTGRAY);
+
+ // 绘制3D时需要,有2D的等价方法
+ BeginMode3D(camera);
+ {
+
+ DrawCube((Vector3) {0.0f, 0.0f, 3.0f},
+ 1.0f, 1.0f, 1.0f, RED);
+
+ // 绘图时的白色色调将保持原来的颜色
+ DrawModel(myModel, (Vector3) {0.0f, 0.0f, 3.0f},
+ 1.0f, // 缩放
+ WHITE);
+
+ }
+ // 结束3D模式,这样就可以再次普通绘图
+ EndMode3D();
+
+ // 开始在渲染纹理上绘图
+ BeginTextureMode(renderTexture);
+ {
+
+ // 它的行为与刚才调用的`BeginDrawing()`方法相同
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+ {
+
+ DrawGrid(10, // Slices
+ 1.0f // 间距
+ );
+
+ }
+ EndMode3D();
+
+ }
+ EndTextureMode();
+
+ // 渲染有Texture2D字段的纹理
+ DrawTexture(renderTexture.texture, 40, 378, BLUE);
+
+ }
+ EndDrawing();
+ }
+
+ // 卸载已载入的对象
+ UnloadFont(someFont);
+ UnloadModel(myModel);
+
+ // 关闭窗口和OpenGL上下文
+ CloseWindow();
+
+ return 0;
+}
+
+```
+
+## 延伸阅读
+raylib有一些[不错的例子](https://www.raylib.com/examples.html)
+如果你不喜欢C语言你也可以看看[raylib的其他语言绑定](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)
diff --git a/zh-cn/red-cn.html.markdown b/zh-cn/red-cn.html.markdown
index 85812990..7fee007e 100644
--- a/zh-cn/red-cn.html.markdown
+++ b/zh-cn/red-cn.html.markdown
@@ -150,11 +150,11 @@ msg: either a > 0 [
]
print ["a 是 " msg lf]
-; util
+; until
; 循环执行一段代码块,直到满足给定的条件为止。
-; util 没有返回值,所以它不能用在表示式中。
+; UNTIL 在最后一次循环执行完最后一个表达式后,总是返回真值 'true'。
c: 5
-util [
+until [
prin "o"
c: c - 1
c = 0 ; 终止循环的条件
@@ -193,15 +193,15 @@ print twice b ; 输出 6
## 更进一步
-Red 相关的源码信息在 [Red 语言主页](http://www.red-lang.org)。
+Red 相关的源码信息在 [Red 语言主页](https://www.red-lang.org)。
源代码的 [github 库](https://github.com/red/red)。
-Red/System 特性在 [这里](http://static.red-lang.org/red-system-specs-light.html)。
+Red/System 特性在 [这里](https://static.red-lang.org/red-system-specs-light.html)。
想要了解更多关于 Rebol 和 Red 的信息,加入 [Gitter 聊天室](https://gitter.im/red/red)。如果你无法加入,也可以给我们发[邮件](mailto:red-langNO_SPAM@googlegroups.com)。
-也可以在 [Stack Overflow](stackoverflow.com/questions/tagged/red) 上查阅、提交问题。
+也可以在 [Stack Overflow](https://stackoverflow.com/questions/tagged/red) 上查阅、提交问题。
也许你现在就要试一试 Red ?可以在线尝试 [try Rebol and Red site](http://tryrebol.esperconsultancy.nl)。
diff --git a/zh-cn/ruby-cn.html.markdown b/zh-cn/ruby-cn.html.markdown
index 9918c022..63adab64 100644
--- a/zh-cn/ruby-cn.html.markdown
+++ b/zh-cn/ruby-cn.html.markdown
@@ -657,4 +657,4 @@ Something.new.qux # => 'qux'
- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online.
- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide.
-- [Try Ruby](http://tryruby.org) - Learn the basic of Ruby programming language, interactive in the browser.
+- [Try Ruby](https://try.ruby-lang.org/) - Learn the basic of Ruby programming language, interactive in the browser.
diff --git a/zh-cn/rust-cn.html.markdown b/zh-cn/rust-cn.html.markdown
index 5d3fc693..6bed1650 100644
--- a/zh-cn/rust-cn.html.markdown
+++ b/zh-cn/rust-cn.html.markdown
@@ -1,5 +1,5 @@
---
-language: rust
+language: Rust
contributors:
- ["P1start", "http://p1start.github.io/"]
translators:
@@ -211,7 +211,7 @@ fn main() {
// `for` 循环
let array = [1, 2, 3];
- for i in array.iter() {
+ for i in array {
println!("{}", i);
}
diff --git a/zh-cn/set-theory-cn.html.markdown b/zh-cn/set-theory-cn.html.markdown
new file mode 100644
index 00000000..13ba2c80
--- /dev/null
+++ b/zh-cn/set-theory-cn.html.markdown
@@ -0,0 +1,138 @@
+---
+category: Algorithms & Data Structures
+name: Set theory
+contributors:
+translators:
+ - ["Tianchen Xu", "https://github.com/lo0b0o"]
+lang: zh-cn
+---
+集合论是数学的一个分支,研究集合、它们的运算和它们的性质。
+
+* 集合由不重复的项组成。
+
+## 基本符号
+
+### 运算符
+* 并运算符,`∪`,表示“或”;
+* 交运算符,`∩`,表示“且”;
+* 差运算符,`\`,表示“不包括”;
+* 补运算符,`'`,表示补集;
+* 叉积运算符,`×`,表示笛卡尔积。
+
+### 限定词
+* 冒号限定词,`:`,表示“使得”;
+* 从属限定词,`∈`,表示“属于”;
+* 子集限定词,`⊆`,表示“是……的子集”;
+* 真子集限定词,`⊂`,表示“是……的真子集”。
+
+### 重要的集合
+* `∅`,空集,即不包含任何元素的集合;
+* `ℕ`,自然数集;
+* `ℤ`,整数集;
+* `ℚ`,有理数集;
+* `ℝ`,实数集。
+
+关于以上集合,有如下几点需要注意:
+1. 空集是其本身的子集(并且也是任何其他集合的子集),即便空集不包含任何项;
+2. 数学家们对于零是否为自然数的看法通常并不统一,教科书一般会明确说明作者是否认为零是自然数。
+
+### 基数
+
+集合的基数,或者说大小,由该集合中的项目数量决定。基数运算符为 `|...|`。
+
+例如,若 `S = { 1, 2, 4 }`,则 `|S| = 3`。
+
+### 空集
+
+* 可以在集合符号中使用不成立的条件来构造空集,例如,`∅ = { x : x ≠ x }`,或 `∅ = { x : x ∈ N, x < 0 }`;
+* 空集总是唯一的(即,有且只有一个空集);
+* 空集是所有集合的子集;
+* 空集的基数为 0,即 `|∅| = 0`。
+
+## 集合的表示
+
+### 集合的逐项构造
+
+集合可以通过包含其全部项的列表逐项生成。例如,`S = { a, b, c, d }`。
+
+只要构成集合的项清楚,长列表可以用省略号缩短。例如,`E = { 2, 4, 6, 8, ... }` 显然为所有偶数构成的集合,它包含无穷多项,虽然我们只显式写出了其中四项。
+
+### 集合构造器
+
+集合构造器符号是构造集合的一种更具描述性的方式。它依赖于一个主语和一个谓词,使得 `S = { 主语 : 谓词 }`。 例如,
+
+```
+A = { x : x 是元音字母 } = { a, e, i, o, u, y}
+B = { x : x ∈ N, x < 10 } = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+C = { x : x = 2k, k ∈ N } = { 0, 2, 4, 6, 8, ... }
+```
+
+有时,谓词可能会 "漏 "到主语中,例如,
+
+```
+D = { 2x : x ∈ N } = { 0, 2, 4, 6, 8, ... }
+```
+
+## 关系
+
+### 从属关系
+
+* 如果值 `a` 包含在集合 `A` 中,那么我们说 `a` 属于 `A`,并用符号表示为 `a ∈ A`。
+* 如果值 `a` 不包含于集合 `A` 中,那么我们说 `a` 不属于 `A`,并用符号表示为 `a ∉ A`。
+
+### 相等关系
+
+* 如果两个集合包括相同的项,那么我们说这两个集合相等,例如,`A = B`。
+* 集合的相等关系于顺序无关,例如 `{ 1, 2, 3, 4 } = { 2, 3, 1, 4 }`。
+* 集合中的元素不能重复,例如 `{ 1, 2, 2, 3, 4, 3, 4, 2 } = { 1, 2, 3, 4 }`。
+* 集合 `A` 与 `B` 相等当且仅当 `A ⊆ B` 且 `B ⊆ A`。
+
+## 特殊集合
+
+### 幂集
+
+* 令 `A` 为任意集合。幂集指的是包括了 `A` 的所有子集的集合,记作 `P(A)`。如果集合 `A` 由 `2n` 个元素组成,那么 `P(A)` 中有 `2^n` 个元素。
+
+```
+P(A) = { x : x ⊆ A }
+```
+
+## 两个集合的运算
+### 并
+
+给定集合 `A` 和 `B`,两个集合的并由出现在 `A` 或 `B` 中的项构成,记作 `A ∪ B`。
+
+```
+A ∪ B = { x : x ∈ A ∪ x ∈ B }
+```
+
+### 交
+
+给定集合 `A` 和 `B`,两个集合的交由出现在 `A` 和 `B` 中的项构成,记作 `A ∩ B`。
+
+```
+A ∩ B = { x : x ∈ A, x ∈ B }
+```
+
+### 差
+给定集合 `A` 和 `B`,`A` 对于 `B` 的集合差指的是属于 `A` 但不属于 `B` 的每一项。
+
+```
+A \ B = { x : x ∈ A, x ∉ B }
+```
+
+### 对称差
+给定集合 `A` 和 `B`,对称差指的是属于 `A` 或 `B` 但不属于它们交集的所有项。
+
+```
+A △ B = { x : ((x ∈ A) ∩ (x ∉ B)) ∪ ((x ∈ B) ∩ (x ∉ A)) }
+
+A △ B = (A \ B) ∪ (B \ A)
+```
+
+### 笛卡尔积
+给定集合 `A` 和 `B`,`A` 和 `B` 的笛卡尔积由 `A` 和 `B` 的项的所有组合构成。
+
+```
+A × B = { (x, y) | x ∈ A, y ∈ B }
+```
diff --git a/zh-cn/solidity-cn.html.markdown b/zh-cn/solidity-cn.html.markdown
index ec684997..12a532bc 100644
--- a/zh-cn/solidity-cn.html.markdown
+++ b/zh-cn/solidity-cn.html.markdown
@@ -213,7 +213,7 @@ names.length; // 获得数组长度
names.length = 1; // 可以设定长度(仅针对 storage 中的动态数组)
// 多维数组
-uint x[][5]; // 5个动态数组元素的数组(和多数语言的顺序相反)
+uint[][5] x; // 5个动态数组元素的数组(和多数语言的顺序相反)
// 字典类型 (任一类型到其他类型的映射)
mapping (string => uint) public balances;
diff --git a/zh-cn/sql.html.markdown b/zh-cn/sql-cn.html.markdown
index 9d430bd1..9d430bd1 100644
--- a/zh-cn/sql.html.markdown
+++ b/zh-cn/sql-cn.html.markdown
diff --git a/zh-cn/wolfram-cn.html.markdown b/zh-cn/wolfram-cn.html.markdown
new file mode 100644
index 00000000..9d6ef54f
--- /dev/null
+++ b/zh-cn/wolfram-cn.html.markdown
@@ -0,0 +1,140 @@
+---
+language: wolfram
+contributors:
+ - ["hyphz", "http://github.com/hyphz/"]
+translators:
+ - ["wuyudi", "http://github.com/wuyudi/"]
+filename: learnwolfram-cn.nb
+lang: zh-cn
+---
+
+Wolfram 语言是最初在 Mathematica 中使用的底层语言,但现在可用于多种场合。
+
+Wolfram 语言有几个界面。
+
+- Raspberry Pi 上的命令行内核界面(就叫 _The Wolfram Language_),它是交互式运行的,不能产生图形输入。
+- _Mathematica_ 是一个丰富的文本/数学编辑器,内置交互式的 Wolfram: 在 "代码单元 "上按 shift+Return 键可以创建一个输出单元,输出结果,这不是动态的。
+- _Wolfram Workbench_,这是 Eclipse 与 Wolfram 语言后端的界面。
+
+本例中的代码可以在任何界面中输入,并使用 Wolfram Workbench 进行编辑。直接加载到 Mathematica 中可能会很不方便,因为该文件不包含单元格格式化信息(这将使该文件作为文本阅读时变得一团糟)--它可以被查看/编辑,但可能需要一些设置。
+
+```mma
+(* 这是一个注释 *)
+
+(* 在Mathematica中,您可以创建一个文本单元格,用排版好的文本和图像来注释您的代码,而不是使用这些注释 *)
+
+(* 输入一个表达式返回结果 *)
+2*2 (* 4 *)
+5+8 (* 13 *)
+
+(* 调用函数 *)
+(* 注意,函数名(和其他所有东西)是区分大小写的 *)
+Sin[Pi/2] (* 1 *)
+
+(* 带有一个参数的函数调用的替代语法 *)
+Sin@(Pi/2) (* 1 *)
+(Pi/2) // Sin (* 1 *)
+
+(* WL 中的每一种语法都有一些等价的函数调用,即万物皆函数 *)
+Times[2, 2] (* 4 *)
+Plus[5, 8] (* 13 *)
+
+(* 第一次使用一个变量定义它,并使其成为全局变量 *)
+x = 5 (* 5 *)
+x == 5 (* 返回真,C-style 的赋值和相等测试 *)
+x (* 5 *)
+x = x + 5 (* 10 *)
+x (* 10 *)
+Set[x, 20] (* 当我说万物皆函数时 我是认真的 *)
+x (* 20 *)
+
+(* 因为WL是基于计算机代数系统的, *)
+(* 可以使用未定义的变量,它们只是阻碍了计算 *)
+cow + 5 (* 5 + cow, cow 是未定义的,所以无法进一步计算 *)
+cow + 5 + 10 (* 15 + cow, 它将尽力计算 *)
+% (* 15 + cow, % 获取最后一次返回的内容 *)
+% - cow (* 15, 未定义的变量cow被消去 *)
+moo = cow + 5 (* 小心,moo 现在是一个表达式,不是一个数字! *)
+
+(* 定义一个函数 *)
+Double[x_] := x * 2 (* 注意 := 防止对RHS进行即时计算。
+ 而 x 后面的 _ 表示没有模式匹配的约束条件*)
+Double[10] (* 20 *)
+Double[Sin[Pi/2]] (* 2 *)
+Double @ Sin @ (Pi/2) (* 2, @-syntax 避免了闭括号的队列 *)
+(Pi/2) // Sin // Double(* 2, //-syntax 按执行顺序列举了函数 *)
+
+(* 对于命令式编程,使用 ; 来分隔语句。 *)
+(* 丢弃 LHS 的任何输出并运行 RHS *)
+MyFirst[] := (Print@"Hello"; Print@"World") (* 请注意,外侧的小括号是关键
+ ;的优先级低于:= *)
+MyFirst[] (* 你好,世界 *)
+
+(* C-Style 的 For 循环,注:在 Mathematica 中使用 For 循环是低效的 *)
+PrintTo[x_] := For[y=0, y<x, y++, (Print[y])] (* 开始,测试,自增,循环体 *)
+PrintTo[5] (* 0 1 2 3 4 *)
+
+(* While 循环 *)
+x = 0; While[x < 2, (Print@x; x++)] (* 带测试和程序体的 while 循环 *)
+
+(* If 和 条件 *)
+x = 8; If[x==8, Print@"Yes", Print@"No"] (* Condition, true case, else case *)
+Switch[x, 2, Print@"Two", 8, Print@"Yes"] (* 值匹配风格切换 *)
+Which[x==2, Print@"No", x==8, Print@"Yes"] (* Elif风格切换 *)
+
+(* 除参数外的变量默认为全局变量,即使在函数内部也是如此 *)
+y = 10 (* 10, 全局变量 y *)
+PrintTo[5] (* 0 1 2 3 4 *)
+y (* 5, 全局的 y 被 PrintTo 内的循环计数器所占用 *)
+x = 20 (* 20, 全局变量 x *)
+PrintTo[5] (* 0 1 2 3 4 *)
+x (* 20, PrintTo 中的 x 是一个参数,并自动局部化 *)
+
+(* 局部变量使用 Module 元函数声明 *)
+(* 带本地变量的版本 *)
+BetterPrintTo[x_] := Module[{y}, (For[y=0, y<x, y++, (Print@y)])]
+y = 20 (* 全局变量 y *)
+BetterPrintTo[5] (* 0 1 2 3 4 *)
+y (* 20, 那更好 *)
+
+(* 实际上,模块允许我们声明任何我们喜欢的作用域 *)
+Module[{count}, count=0; (* 声明这个变量count的作用域 *)
+ (IncCount[] := ++count); (* 这些函数都在该作用域内 *)
+ (DecCount[] := --count)]
+count (* count - 全局变量 count 未定义 *)
+IncCount[] (* 1, 使用作用域内的counter变量 *)
+IncCount[] (* 2, incCount 升级了它 *)
+DecCount[] (* 1, decCount 也是 *)
+count (* count - 这个名字依旧不是全局变量 *)
+
+(* Lists *)
+myList = {1, 2, 3, 4} (* {1, 2, 3, 4} *)
+myList[[1]] (* 1 - 注意列表索引从 1 开始,而不是从 0 开始。 *)
+Map[Double, myList] (* {2, 4, 6, 8} - 函数式列表的 map 函数 *)
+Double /@ myList (* {2, 4, 6, 8} - 以上的缩略语法 *)
+Scan[Print, myList] (* 1 2 3 4 - 命令式循环 *)
+Fold[Plus, 0, myList] (* 10 (0+1+2+3+4) *)
+FoldList[Plus, 0, myList] (* {0, 1, 3, 6, 10} - 存值的 Fold *)
+Append[myList, 5] (* {1, 2, 3, 4, 5} - 注意 myList 没有更新 *)
+Prepend[myList, 5] (* {5, 1, 2, 3, 4} - 如果想让 myList 更新,就加上 "myList = " *)
+Join[myList, {3, 4}] (* {1, 2, 3, 4, 3, 4} *)
+myList[[2]] = 5 (* {1, 5, 3, 4} - 这确实更新了myList *)
+
+(* 关联,又称字典/哈希值 *)
+myHash = <|"Green" -> 2, "Red" -> 1|> (* 创建一个关联 *)
+myHash[["Green"]] (* 2, 使用 *)
+myHash[["Green"]] := 5 (* 5, 更新 *)
+myHash[["Puce"]] := 3.5 (* 3.5, 扩展 *)
+KeyDropFrom[myHash, "Green"] (* 抹去绿色的键 *)
+Keys[myHash] (* {Red, Puce} *)
+Values[myHash] (* {1, 3.5} *)
+
+(* 做 Wolfram 的演示时 你不能不展示这个 *)
+Manipulate[y^2, {y, 0, 20}] (* 返回一个反应式的用户界面,显示y^2
+ 并允许通过滑块在 0-20 之间调整y。
+ 只适用于图形前端 *)
+```
+
+## 想多来点?
+
+- [Wolfram Language Documentation Center](http://reference.wolfram.com/language/)