diff --git "a/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/README.md" "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..5fbdb41e8eebb2f2a8165ea3eaeec64bd2f9dca0 --- /dev/null +++ "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/README.md" @@ -0,0 +1,99 @@ +# 基本概念 + +欢迎学习洛书编程语言!本章介绍洛书语言的基础概念,包括安装配置、语法基础和程序结构。这些内容是学习洛书的基础,建议按顺序学习。 + +## 本章内容 + +### [获取与安装](获取与安装.md) +学习如何获取和安装洛书开发环境,包括: +- Playground 在线体验 +- Release 版本下载 +- SDK 开发工具包 +- 开发环境配置 + +### [工程结构](工程结构.md) +了解洛书的包运行机制和程序入口,包括: +- 包的概念和结构 +- 程序入口方式 +- main{} 语法糖 +- 作用域和命名空间 + +### [注释、关键字、标识符](注释、关键字、标识符.md) +掌握洛书的基础语法元素,包括: +- 注释语法规则 +- 关键字列表 +- 标识符命名规范 +- 运算符概览 + +### [程序结构](程序结构.md) +深入理解洛书的程序组织方式,包括: +- 全局和局部作用域 +- 变量声明和初始化 +- 命名空间管理 +- 作用域最佳实践 + +### [表达式](表达式.md) +学习洛书的表达式系统,包括: +- 左表达式和右表达式 +- 复合表达式 +- 运算符优先级 +- 特殊表达式形式 + +## 学习建议 + +### 初学者路径 +1. 先在 [Playground](https://losu.tech/playground) 中体验洛书语法 +2. 学习 [基础语法元素](注释、关键字、标识符.md) +3. 理解 [程序结构](程序结构.md) 和作用域概念 +4. 掌握 [表达式](表达式.md) 的使用方法 +5. 了解 [工程结构](工程结构.md) 为后续开发做准备 + +### 有经验的程序员 +可以快速浏览各节内容,重点关注洛书的独特特性: +- 类型注释系统 +- 管道运算符 +- 并发编程模型 +- 包管理机制 + +## 快速参考 + +### 基本语法 +```losu +import std + +# 全局变量 +global APP_NAME = '洛书应用' + +# 函数定义 +def greet(name) { + return '你好, ' & name & '!' +} + +# 程序入口 +main { + let message = greet('洛书用户') + println(message) +} +``` + +### 常用关键字 +- **变量声明**: `let`, `var`, `global` +- **函数相关**: `def`, `lambda`, `return` +- **流程控制**: `if`, `elif`, `else`, `while`, `for` +- **逻辑运算**: `and`, `or`, `not`, `true`, `false` + +### 运算符 +- **算术**: `+`, `-`, `*`, `/`, `%`, `**` +- **比较**: `==`, `!=`, `<`, `<=`, `>`, `>=` +- **特殊**: `&` (字符串拼接), `::` (成员访问), `:>` (管道) + +## 下一步 + +完成本章学习后,建议继续学习: +- [数据类型](../2-数据类型/README.md) - 了解洛书的类型系统 +- [语句](../3-语句/README.md) - 学习控制流语句 +- [并发编程](../4-并发编程/README.md) - 掌握洛书的并发特性 + +--- + +**开始学习**: [获取与安装 →](获取与安装.md) \ No newline at end of file diff --git "a/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\345\267\245\347\250\213\347\273\223\346\236\204.md" "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\345\267\245\347\250\213\347\273\223\346\236\204.md" new file mode 100644 index 0000000000000000000000000000000000000000..f682963b5498d949938da88febd331dbb6237ddd --- /dev/null +++ "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\345\267\245\347\250\213\347\273\223\346\236\204.md" @@ -0,0 +1,184 @@ +# 工程结构 + +洛书语言采用基于包(package)的模块化设计,支持灵活的工程组织方式。本节详细介绍洛书的包运行机制和程序入口的概念。 + +## 包的概念 + +在洛书中,**包(package)**是代码组织的基本单位。每个包都是一个包含 `main.losu` 文件的目录,这个文件作为包的入口点。 + +### 包的基本结构 + +``` +mypackage/ +├── main.losu # 包的入口文件(必需) +├── utils.losu # 其他模块文件(可选) +├── config.losu # 配置模块(可选) +└── subpackage/ # 子包目录(可选) + └── main.losu # 子包入口 +``` + +### 包的运行机制 + +洛书的包运行机制遵循以下规则: + +1. **入口文件**:每个包必须有一个 `main.losu` 文件作为入口点 +2. **自动加载**:运行包时,洛书会自动执行 `main.losu` 文件 +3. **模块导出**:包可以通过 `return {}` 语句导出功能给其他包使用 +4. **依赖管理**:包可以导入其他包,形成依赖关系 + +### main{} 语法糖 + +`main{}` 实际上是 `return{}` 的语法糖,但有重要的语义区别: + +- **return{}**:用于包的导出,将内容导出给其他包使用 +- **main{}**:用于程序入口,表示程序的主要执行逻辑 +- **唯一性**:一个文件中只能有一个 `main{}` 块 + +## 作用域和命名空间 + +洛书的作用域分为全局作用域和局部作用域: + +### 全局作用域 + +使用 `global` 关键字声明的变量属于全局作用域: + +```losu +import std + +# 全局变量声明 +global let APP_VERSION = '1.0.0' +global let DEBUG_MODE = true + +# 全局变量可以在任何地方访问 +main { + println('版本:', APP_VERSION) + println('调试模式:', DEBUG_MODE) +} +``` + +### 局部作用域 + +使用 `let` 或 `var` 声明的变量属于局部作用域: + +```losu +import std + +main { + let localVar = '局部变量' + var anotherLocal = 42 + + # 局部变量只在当前作用域内有效 + println('局部变量:', localVar) + println('另一个局部变量:', anotherLocal) +} + +# 这里无法访问 localVar 和 anotherLocal +``` + +### 作用域嵌套 + +洛书支持作用域的嵌套,内层作用域可以访问外层作用域的变量: + +```losu +import std + +global let OUTER_VAR = '外层变量' + +main { + let middleVar = '中层变量' + + # 模拟内层作用域(通过函数) + def innerFunction() { + let innerVar = '内层变量' + + # 可以访问所有外层变量 + println('全局:', OUTER_VAR) + println('中层:', middleVar) + println('内层:', innerVar) + } + + innerFunction() +} +``` + +## 命名空间管理 + +洛书使用 `::` 操作符进行命名空间访问: + +```losu +import std + +# 访问标准库的函数 +main { + # 使用完整的命名空间路径 + let currentPath = std::path() + println('当前路径:', currentPath) + + # 也可以直接使用导入的函数 + println('直接调用 println') +} +``` + +## 练习 + +### 练习 1:简单程序结构 + +创建一个简单的计算器程序,演示基本的程序结构。 + +
+查看答案 + +```losu +import std + +# 简单的计算器程序 +let num1 = 15 +let num2 = 8 + +println('=== 简单计算器 ===') +println('数字1:', num1) +println('数字2:', num2) +println('加法:', num1 + num2) +println('减法:', num1 - num2) +println('乘法:', num1 * num2) +println('除法:', num1 / num2) +``` + +
+ +### 练习 2:使用 main{} 的程序 + +创建一个使用 `main{}` 入口的程序,包含全局变量和函数定义。 + +
+查看答案 + +```losu +import std + +# 全局配置 +global let PROGRAM_NAME = '洛书演示程序' +global let VERSION = '1.0' + +# 工具函数 +def greetUser(name) { + return '欢迎使用洛书, ' & name & '!' +} + +# 程序主入口 +main { + println('=== 程序信息 ===') + println('程序名:', PROGRAM_NAME) + println('版本:', VERSION) + + let userName = '开发者' + let greeting = greetUser(userName) + println(greeting) + + println('程序运行完成') +} +``` + +
+ +**上一章**:[获取与安装 ←](获取与安装.md) | **下一章**:[注释、关键字、标识符 →](注释、关键字、标识符.md) \ No newline at end of file diff --git "a/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\346\263\250\351\207\212\343\200\201\345\205\263\351\224\256\345\255\227\343\200\201\346\240\207\350\257\206\347\254\246.md" "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\346\263\250\351\207\212\343\200\201\345\205\263\351\224\256\345\255\227\343\200\201\346\240\207\350\257\206\347\254\246.md" new file mode 100644 index 0000000000000000000000000000000000000000..ca97527d48da207941e6feb67df436413672d4e0 --- /dev/null +++ "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\346\263\250\351\207\212\343\200\201\345\205\263\351\224\256\345\255\227\343\200\201\346\240\207\350\257\206\347\254\246.md" @@ -0,0 +1,366 @@ +# 注释、关键字、标识符 + +本节介绍洛书语言的基础语法元素:注释的使用方法、关键字列表和标识符的命名规范。这些是编写洛书程序的基础知识。 + +## 注释语法 + +洛书使用 `#` 符号进行注释。注释是程序中不被执行的文本,用于解释代码的功能和逻辑。 + +### 单行注释 + +洛书只支持单行注释,使用 `#` 符号: + +```losu +# 这是一个完整的单行注释 +import std + +println('Hello, World!') # 这是行末注释 + +# 程序的主要功能 +let result = 10 + 20 # 计算两个数的和 +println('结果:', result) # 输出计算结果 +``` + +### 多行注释的实现 + +虽然洛书没有块注释语法,但可以使用多个单行注释来实现多行说明: + +```losu +import std + +# =================================== +# 这是一个多行注释的示例 +# 作者:洛书开发者 +# 日期:2024年 +# =================================== + +println('多行注释演示') +``` + +> [!NOTE] +> 良好的注释习惯是编写可维护代码的重要组成部分。注释应该解释"为什么"而不仅仅是"是什么"。 + +## 关键字 + +洛书语言包含一系列保留的关键字,这些关键字具有特殊的语法意义,不能用作普通的标识符。 + +### 逻辑运算关键字 + +用于逻辑运算和布尔值表示: + +- `and` - 逻辑与运算符 +- `or` - 逻辑或运算符 +- `not` - 逻辑非运算符 +- `true` - 布尔真值 +- `false` - 布尔假值 + +```losu +import std + +let isActive = true +let isComplete = false + +println('活跃且完成:', isActive and isComplete) # false +println('活跃或完成:', isActive or isComplete) # true +println('非活跃:', not isActive) # false +``` + +### 变量声明关键字 + +用于声明不同作用域的变量: + +- `let` - 局部变量声明 +- `var` - 局部变量声明(与 let 等价) +- `global` - 全局变量声明 + +```losu +import std + +# 全局变量声明 +global APP_NAME = '洛书应用' +global VERSION = '1.0' + +main { + # 局部变量声明 + let userName = '张三' + var userAge = 25 # var 和 let 完全等价 + + println('应用:', APP_NAME) + println('版本:', VERSION) + println('用户:', userName, '年龄:', userAge) +} +``` + +### 函数相关关键字 + +用于函数定义和控制: + +- `def` - 函数定义 +- `lambda` - 匿名函数 +- `return` - 函数返回 +- `yield` - 协程让步 + +```losu +import std + +# 普通函数定义 +def add(a, b) { + return a + b +} + +# Lambda 表达式 +let multiply = { + (x, y) { + return x * y + } +} + +main { + println('加法:', add(5, 3)) + println('乘法:', multiply(4, 6)) +} +``` + +### 流程控制关键字 + +用于程序流程控制: + +- `if` - 条件判断 +- `elif` - 条件分支 +- `else` - 默认分支 +- `while` - 循环 +- `for` - 遍历循环 +- `break` - 跳出循环 +- `continue` - 继续下次循环 +- `match` - 模式匹配 +- `case` - 匹配分支 + +```losu +import std + +main { + let score = 85 + + if (score >= 90) { + println('优秀') + } elif (score >= 80) { + println('良好') + } else { + println('需要努力') + } +} +``` + +### 其他重要关键字 + +- `import` - 模块导入 +- `main` - 主函数标记 +- `class` - 类定义 +- `except` - 异常处理 +- `raise` - 抛出异常 + +## 标识符命名规则 + +标识符是用来命名变量、函数、类等程序元素的名称。洛书的标识符命名规则既灵活又严格。 + +### 基本命名规则 + +1. **首字符限制**:必须是字母(a-z, A-Z)、下划线(_)或 Unicode 字符 +2. **后续字符**:可以是字母、数字(0-9)、下划线或 Unicode 字符 +3. **大小写敏感**:`name` 和 `Name` 是完全不同的标识符 +4. **关键字限制**:不能直接使用关键字作为标识符 + +### 有效标识符示例 + +```losu +import std + +main { + # 基本英文标识符 + let userName = '用户名' + let user_age = 25 + let _privateData = '私有数据' + let counter1 = 0 + + # Unicode 标识符(支持中文) + let 姓名 = '张三' + let 年龄 = 30 + let 用户ID = 12345 + + println('英文标识符:', userName, user_age) + println('中文标识符:', 姓名, 年龄) +} +``` + +### 使用关键字作为标识符 + +当需要使用关键字作为标识符时,可以使用 `!` 前缀进行转义: + +```losu +import std + +main { + # 创建包含关键字的对象 + let studentInfo = { + class: '三年级', # class 是关键字 + for: '学习编程' # for 是关键字 + } + + # 访问时需要使用 ! 前缀 + println('班级:', studentInfo.!class) + println('目的:', studentInfo.!for) +} +``` + +### 推荐的命名约定 + +虽然洛书支持多种命名风格,但建议遵循一致的约定: + +```losu +import std + +# 变量和函数:小驼峰或下划线风格 +let userName = '张三' +let user_name = '李四' + +# 常量:全大写下划线 +global MAX_RETRY_COUNT = 3 +global DEFAULT_TIMEOUT = 30 + +# 私有变量:下划线开头 +let _internalState = '内部状态' + +main { + println('用户名:', userName) + println('最大重试次数:', MAX_RETRY_COUNT) + println('内部状态:', _internalState) +} +``` + +## 运算符概览 + +洛书支持丰富的运算符,用于各种计算和操作: + +### 算术运算符 + +- `+` 加法 +- `-` 减法 +- `*` 乘法 +- `/` 除法 +- `%` 取模 +- `**` 幂运算 + +### 比较运算符 + +- `==` 相等 +- `!=` 不等 +- `<` 小于 +- `<=` 小于等于 +- `>` 大于 +- `>=` 大于等于 + +### 特殊运算符 + +- `&` 字符串拼接 +- `::` 成员访问 +- `:>` 右管道运算符 + +```losu +import std + +main { + # 算术运算演示 + let a = 15 + let b = 4 + println('算术运算:', a + b, a - b, a * b, a / b) + + # 字符串拼接 + let greeting = '你好' & ', ' & '洛书!' + println('拼接结果:', greeting) + + # 管道运算符 + let result = '洛书语言' :> println # 等价于 println('洛书语言') +} +``` + +## 练习 + +### 练习 1:标识符验证 + +创建程序演示各种有效的标识符命名方式。 + +
+查看答案 + +```losu +import std + +main { + # 各种有效的标识符 + let validName = '有效标识符' + let _privateVar = '私有变量' + let userName123 = '用户名123' + let 中文变量名 = '中文标识符' + + # 使用关键字作为对象属性 + let config = { + class: '配置类', + for: '用途说明' + } + + println('=== 标识符测试 ===') + println('基本标识符:', validName) + println('私有变量:', _privateVar) + println('包含数字:', userName123) + println('中文标识符:', 中文变量名) + println('关键字属性:', config.!class, config.!for) +} +``` + +
+ +### 练习 2:注释和运算符 + +编写一个带有详细注释的计算程序,演示各种运算符的使用。 + +
+查看答案 + +```losu +import std + +# =================================== +# 洛书运算符演示程序 +# 功能:展示各种运算符的使用方法 +# =================================== + +main { + # 定义测试数据 + let x = 12 + let y = 5 + + println('=== 运算符演示 ===') + println('操作数: x =', x, ', y =', y) + + # 算术运算符测试 + println('加法:', x + y) # 17 + println('减法:', x - y) # 7 + println('乘法:', x * y) # 60 + println('除法:', x / y) # 2.4 + println('取模:', x % y) # 2 + println('幂运算:', x ** 2) # 144 + + # 比较运算符测试 + println('相等:', x == y) # false + println('大于:', x > y) # true + println('小于等于:', x <= y) # false + + # 字符串拼接 + let message = '结果是: ' & (x + y) + println('拼接:', message) +} +``` + +
+ +**上一章**:[工程结构 ←](工程结构.md) | **下一章**:[程序结构 →](程序结构.md) \ No newline at end of file diff --git "a/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\347\250\213\345\272\217\347\273\223\346\236\204.md" "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\347\250\213\345\272\217\347\273\223\346\236\204.md" new file mode 100644 index 0000000000000000000000000000000000000000..f2fe99cb331887a370e8c5a24077682ebefe8031 --- /dev/null +++ "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\347\250\213\345\272\217\347\273\223\346\236\204.md" @@ -0,0 +1,266 @@ +# 程序结构 + +洛书语言的程序结构清晰而灵活,支持全局和局部作用域的概念,以及完善的命名空间管理。本节详细介绍洛书程序的组织方式和作用域规则。 + +## 作用域概念 + +作用域(Scope)决定了变量和函数的可见性和生命周期。洛书支持两种主要的作用域:全局作用域和局部作用域。 + +### 全局作用域 + +全局作用域中的变量在整个程序中都可以访问。使用 `global` 关键字声明全局变量: + +```losu +import std + +# 全局变量声明 +global let APP_NAME = '洛书应用程序' +global let VERSION = '1.0.0' +global let DEBUG_MODE = true + +# 全局变量可以在程序的任何地方访问 +main { + println('应用名称:', APP_NAME) + println('版本号:', VERSION) + println('调试模式:', DEBUG_MODE) +} +``` + +### 全局变量的特点 + +1. **程序级可见性**:在整个程序中都可以访问 +2. **生命周期长**:从声明开始直到程序结束 +3. **初始化要求**:全局变量必须在声明时初始化 +4. **命名约定**:建议使用大写字母和下划线 + +### 局部作用域 + +局部作用域中的变量只在特定的代码块中可见。使用 `let` 或 `var` 关键字声明局部变量: + +```losu +import std + +main { + # 局部变量声明 + let userName = '张三' + var userAge = 25 # var 和 let 完全等价 + let isActive = true + + println('用户信息:', userName, userAge, isActive) + + # 局部变量只在当前作用域内有效 +} + +# 这里无法访问 userName、userAge 和 isActive +``` + +### 作用域嵌套 + +洛书支持作用域的嵌套,内层作用域可以访问外层作用域的变量: + +```losu +import std + +global let GLOBAL_CONFIG = '全局配置' + +main { + let outerVar = '外层变量' + + def innerFunction() { + let innerVar = '内层变量' + + # 内层可以访问所有外层变量 + println('全局变量:', GLOBAL_CONFIG) + println('外层变量:', outerVar) + println('内层变量:', innerVar) + } + + innerFunction() + + # 这里无法访问 innerVar + println('外层访问:', outerVar) +} +``` + +## 命名空间 + +命名空间用于组织和管理代码中的标识符,避免命名冲突。洛书使用 `::` 操作符进行命名空间访问。 + +### 命名空间 + +- 洛书的标准库函数都位于 `std` 命名空间中。 +- 通过模块和包的机制,可以创建自定义的命名空间: + +```losu +import std + +main { + # 使用完整的命名空间路径 + let currentPath = std::path() + println('当前路径:', currentPath) + + # 导入后可以直接使用 + println('直接调用 println 函数') +} +``` + +## 变量声明和初始化 + +洛书提供了灵活的变量声明方式,支持不同的初始化模式。 + +### 基本声明语法 + +```losu +import std + +main { + # 基本变量声明 + let name = '洛书' + let age = 1 + let isNew = true + + # let 和 var 等价 + var count = 0 + var message = '消息' + + println('基本变量:', name, age, isNew) + println('var 变量:', count, message) +} +``` + +### 全局变量的声明规则 + +全局变量有特殊的声明规则,支持多种声明方式: + +```losu +import std + +# 基本全局变量声明,如果要在声明时赋值,必须使用let/var关键字 +global let APP_TITLE = '洛书语言' +global var MAX_USERS = 1000 + +# 若不在声明时时赋值,则不能使用let/var关键字 +global CURRENT_USER +CURRENT_USER = '当前用户' + +main { + # 为未初始化的全局变量赋值 + CURRENT_USER = '当前用户' + + println('应用标题:', APP_TITLE) + println('最大用户数:', MAX_USERS) + println('当前用户:', CURRENT_USER) +} +``` + +## 函数作用域 + +函数创建自己的局部作用域,函数参数和内部变量都属于函数的局部作用域: + +```losu +import std + +global let MULTIPLIER = 2 + +def calculateValue(input, factor) { + # 函数参数 input 和 factor 是局部变量 + let localResult = input * factor * MULTIPLIER + let tempValue = localResult + 10 + + return tempValue +} + +main { + let result = calculateValue(5, 3) + println('计算结果:', result) + + # 这里无法访问 localResult 和 tempValue + println('全局乘数:', MULTIPLIER) +} +``` + +## 作用域最佳实践 + +### 变量命名约定 + +```losu +import std + +# 全局常量:大写下划线 +global let MAX_RETRY_COUNT = 3 +global let DEFAULT_TIMEOUT = 30 + +# 全局变量:大写开头 +global let CurrentUser = '未登录' + +main { + # 局部变量:小写开头 + let userName = '张三' + let userAge = 25 + + # 私有变量:下划线开头 + let _internalState = '内部状态' + + # 临时变量:简短命名 + let temp = userName & '_temp' + + println('用户:', userName, '年龄:', userAge) + println('临时值:', temp) +} +``` + +### 作用域管理原则 + +1. **最小作用域原则**:变量应该在最小的必要作用域中声明 +2. **避免全局污染**:尽量减少全局变量的使用 +3. **清晰的命名**:使用有意义的变量名 +4. **适当的生命周期**:变量的生命周期应该与其用途匹配 + +## 练习 + +### 练习 1:命名空间使用 + +创建一个使用命名空间的工具程序。 + +
+查看答案 + +```losu +import std + +# 创建一个数学工具命名空间 +let mathUtils = { + add: { + (a, b) { + return a + b + } + }, + + multiply: { + (a, b) { + return a * b + } + }, + + square: { + (x) { + return x * x + } + } +} + +main { + let num1 = 8 + let num2 = 3 + + println('=== 数学工具演示 ===') + println('数字:', num1, '和', num2) + println('加法:', mathUtils.add(num1, num2)) + println('乘法:', mathUtils.multiply(num1, num2)) + println('平方:', mathUtils.square(num1)) +} +``` + +
+ +**上一章**:[注释、关键字、标识符 ←](注释、关键字、标识符.md) | **下一章**:[表达式 →](表达式.md) \ No newline at end of file diff --git "a/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\350\216\267\345\217\226\344\270\216\345\256\211\350\243\205.md" "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\350\216\267\345\217\226\344\270\216\345\256\211\350\243\205.md" new file mode 100644 index 0000000000000000000000000000000000000000..75b74f30e3129b614ccc0381d005b31e10d76db7 --- /dev/null +++ "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\350\216\267\345\217\226\344\270\216\345\256\211\350\243\205.md" @@ -0,0 +1,73 @@ +# 获取与安装 + +洛书(Losu)是一门现代化的动态类型编程语言,具有简洁的语法和强大的表达能力。本节将介绍如何获取和安装洛书开发环境。 + +## 获取方式 + +洛书提供了三种主要的获取方式,适合不同需求的用户: + +### Playground 在线体验 + +洛书提供了功能完整的在线 Playground,这是最快速的体验方式:- **LosuOnline-Playground**:[在线playground地址](https://losu.tech/playground/) + +- **即时体验**:无需安装,直接在浏览器中编写和运行洛书代码 +- **实时反馈**:代码修改后立即看到运行结果 +- **代码分享**:可以将代码片段分享给其他人 +- **语法高亮**:完整的语法高亮和错误提示 + +> [!TIP] +> 对于初学者,建议先在 Playground 中熟悉语法,再考虑本地安装。 + +### Release 版本下载 + +从[官方发布页面](https://losu.tech/index-new/#download)可以下载预编译的洛书解释器: + +- **稳定版本**:经过充分测试的稳定发布版本 +- **多平台支持**:支持 Windows和Linux操作系统 +- **绿色安装**:解压即用,无需复杂的安装过程 + +### SDK 开发工具包 + +完整的 [SDK](https://gitee.com/chen-chaochen/lpk) 适合需要深度开发的用户: + +- **完整工具链**:包含解释器、编译器、调试器等全套工具 +- **标准库源码**:可以查看和学习标准库的实现 +- **开发文档**:详细的 API 文档和开发指南 +- **示例项目**:丰富的示例代码和最佳实践 + +## 安装步骤 + +### Windows 系统安装 + +1. **下载解释器**:从官方页面下载 Windows 版本 +2. **解压文件**:解压到合适的目录(如 `C:\losu`) +3. **配置环境**:将解释器目录添加到系统 PATH 环境变量 +4. **验证安装**:打开命令提示符,运行 `losu --version` + +### Linux 系统安装 + +1. **下载解释器**:选择对应系统架构的版本 +2. **解压安装**:解压到 `/usr/local/bin` 或其他 PATH 目录 +3. **设置权限**:运行 `chmod +x losu` 添加执行权限 +4. **验证安装**:在终端运行 `losu --version` 确认安装成功 + +## 第一个程序 + +创建一个简单的洛书程序来验证安装: + +```losu +import std + +println('Hello, Losu!') +println('洛书安装成功!') +``` + +将代码保存为 `main.losu`,然后运行: + +```bash +losu main.losu +``` + +如果看到正确的输出,说明洛书已经成功安装并可以正常使用。 + +**下一章**:[工程结构 →](工程结构.md) \ No newline at end of file diff --git "a/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\350\241\250\350\276\276\345\274\217.md" "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\350\241\250\350\276\276\345\274\217.md" new file mode 100644 index 0000000000000000000000000000000000000000..7ae0d1c76d3056e00d88c223a440a6fef70ffcaf --- /dev/null +++ "b/grammars/1-\345\237\272\346\234\254\346\246\202\345\277\265/\350\241\250\350\276\276\345\274\217.md" @@ -0,0 +1,356 @@ +# 表达式 + +表达式是洛书语言的核心组成部分,用于计算值和执行操作。洛书区分左表达式(L-value)和右表达式(R-value),这种区分对于理解赋值和引用机制非常重要。 + +## 表达式的基本概念 + +表达式是由操作数和运算符组成的计算单元,它们可以被求值并产生结果。洛书中的表达式具有丰富的类型和灵活的组合方式。 + +### 基本表达式类型 + +```losu +import std + +main { + # 字面量表达式 + let number = 42 + let text = '洛书语言' + let flag = true + + # 变量表达式 + let result = number + + # 运算表达式 + let sum = 10 + 20 + let product = 5 * 6 + + println('字面量:', number, text, flag) + println('运算结果:', sum, product) +} +``` + +## 左表达式(L-value) + +左表达式是可以出现在赋值语句左边的表达式,它们表示内存中的存储位置,可以被赋值。 + +### 变量作为左表达式 + +```losu +import std + +main { + # 变量声明和赋值 + let userName = '初始值' # userName 是左表达式 + var counter = 0 # counter 是左表达式 + + # 重新赋值 + userName = '新用户名' # userName 作为左表达式被赋值 + counter = 10 # counter 作为左表达式被赋值 + + println('用户名:', userName) + println('计数器:', counter) +} +``` + +### 对象属性作为左表达式 + +```losu +import std + +main { + # 创建对象 + let user = { + name: '张三', + age: 25, + email: 'zhangsan@example.com' + } + + # 对象属性作为左表达式 + user.name = '李四' # user.name 是左表达式 + user.age = 30 # user.age 是左表达式 + + println('更新后的用户:', user.name, user.age) +} +``` + +### 数组元素作为左表达式 + +```losu +import std + +main { + # 创建数组 + let numbers = [1, 2, 3, 4, 5] + + # 数组元素作为左表达式 + numbers[0] = 10 # numbers[0] 是左表达式 + numbers[2] = 30 # numbers[2] 是左表达式 + + println('修改后的数组:', numbers) +} +``` + +## 右表达式(R-value) + +右表达式是产生值的表达式,它们可以出现在赋值语句的右边,但不能被直接赋值。 + +### 计算表达式作为右表达式 + +```losu +import std + +main { + let a = 10 + let b = 20 + + # 算术表达式作为右表达式 + let sum = a + b # a + b 是右表达式 + let difference = a - b # a - b 是右表达式 + let product = a * b # a * b 是右表达式 + + println('计算结果:', sum, difference, product) +} +``` + +### 函数调用作为右表达式 + +```losu +import std + +def getGreeting(name) { + return '你好, ' & name & '!' +} + +main { + let userName = '洛书用户' + + # 函数调用作为右表达式 + let message = getGreeting(userName) # getGreeting(userName) 是右表达式 + + println('问候消息:', message) +} +``` + +### 字面量作为右表达式 + +```losu +import std + +main { + # 各种字面量都是右表达式 + let number = 42 # 42 是右表达式 + let text = '洛书' # '洛书' 是右表达式 + let flag = true # true 是右表达式 + let array = [1, 2, 3] # [1, 2, 3] 是右表达式 + + println('字面量值:', number, text, flag) +} +``` + +## 复合表达式 + +洛书支持复杂的表达式组合,可以构建功能强大的计算逻辑。 + +### 算术复合表达式 + +```losu +import std + +main { + let x = 5 + let y = 3 + let z = 2 + + # 复合算术表达式 + let result1 = x + y * z # 乘法优先级高于加法 + let result2 = (x + y) * z # 括号改变优先级 + let result3 = x ** y + z # 幂运算优先级最高 + + println('复合表达式结果:') + println('x + y * z =', result1) # 5 + 3 * 2 = 11 + println('(x + y) * z =', result2) # (5 + 3) * 2 = 16 + println('x ** y + z =', result3) # 5 ** 3 + 2 = 127 +} +``` + +### 逻辑复合表达式 + +```losu +import std + +main { + let age = 25 + let hasLicense = true + let hasExperience = false + + # 复合逻辑表达式 + let canDrive = age >= 18 and hasLicense + let isQualified = canDrive and (hasExperience or age >= 21) + + println('驾驶资格检查:') + println('年龄:', age) + println('有驾照:', hasLicense) + println('有经验:', hasExperience) + println('可以驾驶:', canDrive) + println('完全合格:', isQualified) +} +``` + +## 表达式的求值顺序 + +洛书遵循标准的运算符优先级和结合性规则。 + +### 运算符优先级 + +```losu +import std + +main { + # 演示运算符优先级 + let a = 2 + let b = 3 + let c = 4 + + println('优先级演示:') + println('a + b * c =', a + b * c) # 2 + 3 * 4 = 14 + println('a * b + c =', a * b + c) # 2 * 3 + 4 = 10 + println('a ** b + c =', a ** b + c) # 2 ** 3 + 4 = 12 + println('a + b ** c =', a + b ** c) # 2 + 3 ** 4 = 83 +} +``` + +### 括号的使用 + +```losu +import std + +main { + let x = 10 + let y = 5 + let z = 2 + + # 使用括号明确求值顺序 + let result1 = x / y + z # 10 / 5 + 2 = 4 + let result2 = x / (y + z) # 10 / (5 + 2) = 1.43 + + println('括号的影响:') + println('x / y + z =', result1) + println('x / (y + z) =', result2) +} +``` + +## 特殊表达式 + +洛书提供了一些特殊的表达式形式,用于特定的操作场景。 + +### 管道表达式 + +```losu +import std + +main { + # 右管道运算符 :> + let message = '洛书语言' + message :> println # 等价于 println(message) + + # 链式管道操作 + let result = 'Hello' :> println +} +``` + +### 条件表达式 + +```losu +import std + +main { + let score = 85 + let age = 20 + + # 使用 if 作为表达式 + let grade = if (score >= 90) { + '优秀' + } elif (score >= 80) { + '良好' + } else { + '及格' + } + + println('成绩:', score, '等级:', grade) +} +``` + +## 练习 + +### 练习 1:左右表达式区分 + +创建程序演示左表达式和右表达式的区别。 + +
+查看答案 + +```losu +import std + +main { + # 左表达式示例 + let userName = '张三' # userName 是左表达式 + let userInfo = { + name: '李四', + age: 25 + } + + # 右表达式示例 + let greeting = '你好, ' & userName # '你好, ' & userName 是右表达式 + let sum = 10 + 20 # 10 + 20 是右表达式 + + # 左表达式被赋值 + userName = '王五' # userName 作为左表达式 + userInfo.name = '赵六' # userInfo.name 作为左表达式 + + println('=== 左右表达式演示 ===') + println('用户名:', userName) + println('用户信息:', userInfo.name, userInfo.age) + println('问候语:', greeting) + println('计算结果:', sum) +} +``` + +
+ +### 练习 2:复合表达式计算 + +编写程序演示复杂表达式的计算和优先级。 + +
+查看答案 + +```losu +import std + +main { + let a = 4 + let b = 3 + let c = 2 + + println('=== 复合表达式计算 ===') + println('变量: a =', a, ', b =', b, ', c =', c) + + # 算术表达式优先级 + println('a + b * c =', a + b * c) # 4 + 3 * 2 = 10 + println('(a + b) * c =', (a + b) * c) # (4 + 3) * 2 = 14 + println('a ** b - c =', a ** b - c) # 4 ** 3 - 2 = 62 + + # 逻辑表达式组合 + let isValid = a > b and b > c + let isSpecial = a == 4 or b == 5 + + println('逻辑表达式:') + println('a > b and b > c =', isValid) + println('a == 4 or b == 5 =', isSpecial) +} +``` + +
+ +**上一章**:[程序结构 ←](程序结构.md) | **下一章**:[2-数据类型 →](../2-数据类型/README.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/README.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..fba3333e8d3ebbf4a00bb229de37caa433d69f23 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/README.md" @@ -0,0 +1,233 @@ +# 数据类型 + +洛书语言拥有丰富的数据类型系统,支持动态类型和可选的类型注释。本章将详细介绍洛书的所有数据类型及其使用方法。 + +## 本章内容 + +### [类型注释](类型注释.md) +洛书的类型注释系统,包括: +- 类型注释语法 +- 基本类型注释 +- 函数类型注释 +- 联合类型和可选参数 + +### [逻辑类型](逻辑类型.md) +true 和 false 类型,包括: +- 逻辑值的独特类型设计 +- 逻辑运算符(and、or、not) +- 短路求值 +- 真值判断规则 + +### [数值类型](数值类型.md) +统一的 number 类型,包括: +- 整数和浮点数字面量 +- 数值子类型注释 +- 算术运算和比较 +- 数值转换和特殊值 + +### [字符串类型](字符串类型.md) +string 类型和文本处理,包括: +- 字符串字面量和转义字符 +- 字符串拼接操作 +- 字符串操作函数 +- JSON 字符串处理 + +### [函数类型](函数类型.md) +function 类型和函数编程,包括: +- 函数定义和调用 +- Lambda 表达式 +- 高阶函数和闭包 +- 递归函数 + +### [基本容器](基本容器.md) +unit 类型基础,包括: +- unit 类型概述 +- 成员访问和修改 +- 嵌套结构 +- 实际应用场景 + +### [数组变体](容器类型/数组变体.md) +array 类型和有序集合,包括: +- 数组创建和访问 +- 数组修改和遍历 +- 多维数组 +- 数组操作函数 + +### [对象变体](容器类型/对象变体.md) +object 类型和结构化数据,包括: +- 对象创建和属性访问 +- 对象方法和组合 +- 对象数组和集合操作 +- 实际应用场景 + +### [模块变体](容器类型/模块变体.md) +module 类型和代码组织,包括: +- 模块创建和导出 +- 模块导入和使用 +- 命名空间管理 +- 模块组合和测试 + +### [类变体](容器类型/类变体/) +class 类型和面向对象编程,包括: +- [基本用法](容器类型/类变体/基本用法.md) - 类定义、实例化和方法 +- [重载](容器类型/类变体/重载.md) - 方法重载和参数处理 +- [继承](容器类型/类变体/继承.md) - 类继承和方法重写 +- [反射](容器类型/类变体/反射.md) - 运行时类型检查和动态操作 + +## 洛书类型系统概览 + +洛书是一门动态类型语言,变量的类型在运行时确定。同时,洛书提供了可选的类型注释系统,帮助开发者编写更安全、更清晰的代码。 + +### 基本类型 + +洛书的基本数据类型包括: + +- **逻辑类型**:`true` 和 `false`(独立类型) +- **数值类型**:`number`(统一的数值类型) +- **字符串类型**:`string`(UTF-8 文本) +- **函数类型**:`function`(一等公民) + +### 容器类型 + +洛书的容器类型基于 `unit` 类型,包括: + +- **基本容器**:`unit` - 键值对存储 +- **数组变体**:`array` - 有序元素集合 +- **对象变体**:`object` - 结构化数据 +- **模块变体**:`module` - 模块封装 +- **类变体**:`class` - 面向对象编程 + +### 类型检查 + +使用 `typeof()` 函数可以获取变量的类型: + +```losu +import std + +main { + let num = 42 + let text = 'Hello' + let flag = true + let arr = [1, 2, 3] + let obj = {x: 10, y: 20} + + println('数字类型:', typeof(num)) # number + println('字符串类型:', typeof(text)) # string + println('逻辑类型:', typeof(flag)) # true + println('数组类型:', typeof(arr)) # array + println('对象类型:', typeof(obj)) # unit +} +``` + +### 类型转换 + +洛书提供了类型转换函数: + +```losu +import std + +main { + # 转换为数字 + let numFromStr = int('123') + let floatFromStr = float('3.14') + + # 转换为字符串 + let strFromNum = str(456) + let strFromBool = str(true) + + println('字符串转整数:', numFromStr) + println('字符串转浮点数:', floatFromStr) + println('数字转字符串:', strFromNum) + println('布尔转字符串:', strFromBool) +} +``` + +## 运算符与类型 + +不同类型支持不同的运算符: + +| 运算符 | 数值类型 | 字符串类型 | 逻辑类型 | 容器类型 | +|--------|----------|------------|----------|----------| +| `+` `-` `*` `/` `%` `**` | ✅ | ❌ | ❌ | ❌ | +| `&` | ❌ | ✅ | ❌ | ❌ | +| `==` `!=` | ✅ | ✅ | ✅ | ✅ | +| `<` `<=` `>` `>=` | ✅ | ✅ | ❌ | ❌ | +| `and` `or` `not` | ✅ | ✅ | ✅ | ✅ | + +## 学习建议 + +建议按以下顺序学习本章内容: + +1. **类型注释** - 理解洛书的类型系统基础 +2. **基本类型** - 掌握逻辑、数值、字符串、函数类型 +3. **容器类型** - 学习复杂数据结构的使用 +4. **实际应用** - 通过练习巩固理解 + +每个类型都有其特定的用法和最佳实践,通过实际编程练习可以更好地掌握这些概念。 + +## 关键字表 + +洛书语言中与数据类型相关的关键字: + +| 关键字 | 用途 | 示例 | +|--------|------|------| +| `let` | 声明不可变变量 | `let name = '张三'` | +| `var` | 声明可变变量 | `var count = 0` | +| `def` | 定义函数 | `def add(a, b) { return a + b }` | +| `lambda` | 创建匿名函数 | `let f = lambda x: x * 2` | +| `class` | 定义类 | `class Person { ... }` | +| `global` | 声明全局类 | `global class User { ... }` | +| `init` | 类构造函数 | `init(self, name) { ... }` | +| `del` | 类析构函数 | `del(self) { ... }` | +| `self` | 类实例引用 | `self.name = name` | +| `return` | 函数返回值 | `return result` | +| `typeof` | 获取类型 | `typeof(value)` | +| `sizeof` | 获取大小 | `sizeof(array)` | + +## 运算符表 + +### 类型相关运算符 + +| 运算符 | 用途 | 示例 | +|--------|------|------| +| `@` | 指定变体类型 | `{}@'array'` | +| `.` | 成员访问(自动传self) | `obj.method()` | +| `::` | 成员访问(手动传self) | `module::func(self)` | +| `[]` | 索引访问 | `arr[0]`, `obj['key']` | +| `()` | 函数调用 | `func(args)` | +| `_` | 可变参数占位符 | `_[1]`, `_[2]` | + +## 快速参考 + +### 类型注释语法 +```losu +let name: `string` = 'Alice' +let age: `number` = 25 +let active: `true | false` = true +let numbers: `array` = [1, 2, 3] +``` + +### 常用类型检查 +```losu +println('类型:', typeof(variable)) +if (typeof(value) == 'string') { ... } +``` + +### 类型转换 +```losu +let num = int('123') # 字符串转整数 +let text = str(456) # 数字转字符串 +let decimal = float('3.14') # 字符串转浮点数 +``` + +### 变体创建 +```losu +let obj = {}@'object' # 对象变体 +let arr = {}@'array' # 数组变体 +let mod = {}@'module' # 模块变体 +let cls = {}@'class' # 类变体 +``` + +--- + +**上一章**:[← 基本概念](../1-基本概念/README.md) | **下一章**:[类型注释 →](类型注释.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\207\275\346\225\260\347\261\273\345\236\213.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\207\275\346\225\260\347\261\273\345\236\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..58c39534906a027d8a1fbf66baf3af57f2aff065 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\207\275\346\225\260\347\261\273\345\236\213.md" @@ -0,0 +1,364 @@ +# 函数类型 + +函数类型(function)是洛书语言中用于封装可执行代码的数据类型。洛书提供了多种函数定义方式,包括传统的函数定义、lambda表达式和可变参数函数,满足不同场景的编程需求。 + +## 函数的概念 + +洛书中的函数具有以下特点: + +1. **一等公民**:函数可以作为值传递、存储和操作 +2. **多种定义方式**:支持传统定义、lambda表达式和语法糖 +3. **可变参数**:支持可变数量的参数传递 +4. **尾随参数**:支持unit类型的尾随参数语法糖 + +## 基本函数定义 + +### 传统函数定义 + +```losu +import std + +def add(a, b) { + return a + b +} + +def greet(name) { + println('Hello,', name) +} + +main { + let result = add(10, 20) + println('结果:', result) + + greet('洛书') +} +``` + +### 函数作为值 + +```losu +import std + +def multiply(x, y) { + return x * y +} + +main { + # 函数可以赋值给变量 + let operation = multiply + + let result = operation(5, 6) + println('乘法结果:', result) +} +``` + +## Lambda表达式 + +洛书支持多种lambda表达式的写法,提供了灵活的函数定义方式: + +### 写法一:块语法 + +使用花括号包围参数列表和函数体的传统写法: + +```losu +import std + +main { + let add = { + (a, b) { + return a + b + } + } + + println('加法结果:', add(3, 4)) +} +``` + +### 写法二:简洁语法 + +使用 `lambda` 关键字的简洁表达式写法: + +```losu +import std + +main { + let sub = lambda a, b: a - b + + println('减法结果:', sub(10, 3)) +} +``` + +### 写法三:可变参数语法糖 + +使用 `_` 占位符的可变参数写法,特别适合简单的操作: + +```losu +import std + +main { + let mul = { + println('参数信息:', _) + return _[1] * _[2] + } + + println('乘法结果:', mul(4, 5)) +} +``` + +> [!IMPORTANT] +> 在可变参数语法中: +> - `_[0]` 存放参数个数 +> - `_[1]`, `_[2]`, ... 存放具体参数值 +> - `_` 本身表示整个参数数组 +> - 使用 `...` 作为可变参数的占位符 + +## 函数的语法糖 + +### 尾随参数语法糖 + +当函数的最后一个参数是unit类型时,可以使用尾随参数语法,将该参数放在函数调用的花括号中: + +```losu +import std + +def processData(name, config) { + println('处理数据:', name) + println('配置:', config) +} + +main { + # 尾随参数语法:最后一个unit类型参数可以放在{}中 + processData('用户数据') { + debug: true, + timeout: 5000 + } +} +``` + +### 单参数unit函数的简化语法 + +当函数只有一个unit类型参数时,可以省略括号,直接使用花括号: + +```losu +import std + +def configure(settings) { + println('应用配置:', settings) +} + +main { + # 省略括号的写法 + configure { + theme: 'dark', + language: 'zh-CN' + } +} +``` + +这种语法糖使得配置类函数的调用更加简洁和直观,特别适合DSL(领域特定语言)的构建。 + +## 可变参数函数 + +### 定义可变参数函数 + +```losu +import std + +def sum(...) { + let total = 0 + let count = _[0] + + for (i in 1, count) { + total = total + _[i] + } + + return total +} + +main { + println('求和结果:', sum(1, 2, 3, 4, 5)) + println('求和结果:', sum(10, 20)) +} +``` + +### 可变参数的处理 + +```losu +import std + +def printAll(...) { + let count = _[0] + println('参数个数:', count) + + for (i in 1, count) { + println('参数', i, ':', _[i]) + } +} + +main { + printAll('hello', 42, true, 'world') +} +``` + +## 高阶函数 + +### 函数作为参数 + +```losu +import std + +def apply(func, a, b) { + return func(a, b) +} + +def add(x, y) { + return x + y +} + +def multiply(x, y) { + return x * y +} + +main { + println('应用加法:', apply(add, 5, 3)) + println('应用乘法:', apply(multiply, 5, 3)) +} +``` + +### 函数作为返回值 + +```losu +import std + +def createMultiplier(factor) { + return { + (x) { + return x * factor + } + } +} + +main { + let double = createMultiplier(2) + let triple = createMultiplier(3) + + println('双倍:', double(5)) + println('三倍:', triple(5)) +} +``` + +## 练习 + +### 练习 1:多种Lambda表达式 + +使用三种不同的lambda表达式写法实现计算器功能。 + +?> **练习要求** +分别使用块语法、简洁语法和可变参数语法糖实现加法、减法、乘法运算。 + +
+点击查看答案 + +```losu +import std + +main { + # 写法1:块语法 + let add = { + (a, b) { + return a + b + } + } + + # 写法2:简洁语法 + let subtract = lambda a, b: a - b + + # 写法3:可变参数语法糖 + let multiply = { + println('参数个数:', _[0]) + return _[1] * _[2] + } + + # 测试各种运算 + let a = 12 + let b = 4 + + println('=== Lambda表达式计算器 ===') + println('加法 (块语法):', a, '+', b, '=', add(a, b)) + println('减法 (简洁语法):', a, '-', b, '=', subtract(a, b)) + println('乘法 (可变参数):') + println('结果:', multiply(a, b)) +} +``` + +
+ +### 练习 2:函数语法糖和高阶函数 + +创建使用尾随参数语法糖的配置函数和高阶函数。 + +?> **练习要求** +实现一个配置处理函数,使用尾随参数语法糖,并创建一个高阶函数来处理数组。 + +
+点击查看答案 + +```losu +import std + +# 使用尾随参数的配置函数 +def processConfig(name, settings) { + println('处理配置:', name) + println('调试模式:', settings.debug) + println('端口:', settings.port) + println('主题:', settings.theme) +} + +# 单参数unit函数 +def applySettings(config) { + println('应用设置:') + println(' 语言:', config.language) + println(' 区域:', config.region) +} + +# 高阶函数:接受函数作为参数 +def processArray(arr, processor) { + println('处理数组,长度:', sizeof(arr)) + for (item, v in arr) { + processor(item) + } +} + +main { + println('=== 函数语法糖演示 ===') + + # 使用尾随参数语法糖 + processConfig('应用配置') { + debug: true, + port: 3000, + theme: 'dark' + } + + # 单参数unit函数省略括号 + applySettings { + language: 'zh-CN', + region: 'Asia/Shanghai' + } + + # 高阶函数使用 + let numbers = [1, 2, 3, 4, 5] + let printer = lambda x: println(' 处理数字:', x) + + println('=== 高阶函数演示 ===') + processArray(numbers, printer) + + # 使用lambda表达式作为参数 + processArray(['a', 'b', 'c'], lambda s: println(' 处理字符串:', s)) +} +``` + +
+ +--- + +**上一章**:[← 字符串类型](字符串类型.md) | **下一章**:[特殊类型 →](特殊类型.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\255\227\347\254\246\344\270\262\347\261\273\345\236\213.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\255\227\347\254\246\344\270\262\347\261\273\345\236\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..917f53417a29d43d20636a1da0af211f560b7584 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\255\227\347\254\246\344\270\262\347\261\273\345\236\213.md" @@ -0,0 +1,322 @@ +# 字符串类型 + +洛书语言的字符串类型 `string` 用于处理文本数据。洛书字符串支持 UTF-8 编码,提供了丰富的字符串操作功能,包括拼接、格式化、JSON 处理等。 + +## 字符串字面量 + +洛书支持多种字符串字面量的表示方法: + +### 基本字符串 + +```losu +import std + +main { + # 基本字符串字面量 + let greeting = 'Hello, World!' + let name = "洛书语言" + let empty = '' + + println('问候语:', greeting) + println('语言名:', name) + println('空字符串长度:', sizeof(empty)) + + # 字符串类型检查 + println('greeting 类型:', typeof(greeting)) +} +``` + +### 转义字符 + +洛书字符串支持常见的转义字符: + +```losu +import std + +main { + # 转义字符示例 + let newline = '第一行\n第二行' + let tab = '列1\t列2\t列3' + let quote = '他说:"你好!"' + let backslash = '路径: C:\\Users\\Name' + + println('换行符:') + println(newline) + println('制表符:', tab) + println('引号:', quote) + println('反斜杠:', backslash) +} +``` + +### 原始字符串 + +使用反引号可以创建原始字符串,其中的转义字符不会被处理: + +```losu +import std + +main { + # 原始字符串(如果支持) + let rawString = `这是原始字符串\n不会换行` + let jsonString = `{"name": "洛书", "version": "1.0"}` + + println('原始字符串:', rawString) + println('JSON 字符串:', jsonString) +} +``` + +## 字符串拼接 + +洛书使用 `&` 运算符进行字符串拼接: + +### 基本拼接 + +```losu +import std + +main { + let firstName = '张' + let lastName = '三' + let fullName = firstName & lastName + + println('姓:', firstName) + println('名:', lastName) + println('全名:', fullName) + + # 多个字符串拼接 + let greeting = '你好, ' & fullName & '!' + println('问候:', greeting) +} +``` + +### 字符串与其他类型拼接 + +需要注意的是,字符串只能与字符串拼接,其他类型需要先转换: + +```losu +import std + +main { + let name = '洛书' + let version = 1 + let isStable = true + + # 需要显式转换 + let info = name & ' 版本 ' & str(version) + println('版本信息:', info) + + # 或者使用 println 的多参数特性 + println('详细信息:', name, '版本', version, '稳定版:', isStable) +} +``` + +## 字符串操作 + +洛书提供了丰富的字符串操作函数: + +### 长度和索引 + +```losu +import std + +main { + let text = '洛书编程语言' + + println('字符串:', text) + println('长度:', sizeof(text)) + + # 字符串索引访问(如果支持) + if (sizeof(text) > 0) { + println('第一个字符:', text[0]) + println('最后一个字符:', text[sizeof(text) - 1]) + } +} +``` + +### 字符串查找和替换 + +```losu +import std + +main { + let sentence = '洛书是一门现代编程语言' + let keyword = '编程' + + println('原句:', sentence) + println('关键词:', keyword) + + # 查找子字符串(如果支持相关函数) + println('包含关键词:', contains(sentence, keyword)) + + # 字符串替换(如果支持) + let newSentence = replace(sentence, '编程', '脚本') + println('替换后:', newSentence) +} +``` + +## 字符串格式化 + +洛书支持多种字符串格式化方式: + +### 使用拼接进行格式化 + +```losu +import std + +main { + let name = '张三' + let age = 25 + let city = '北京' + + # 基本格式化 + let profile = '姓名: ' & name & ', 年龄: ' & str(age) & ', 城市: ' & city + println(profile) + + # 多行格式化 + let detailedProfile = '用户信息:\n' & + ' 姓名: ' & name & '\n' & + ' 年龄: ' & str(age) & '\n' & + ' 城市: ' & city + println(detailedProfile) +} +``` + +> [!IMPORTANT] +> 洛书中字符串都用单引号或双引号表示,并且内部转义字符都支持 JSON 格式。 + +## 字符串比较 + +字符串支持各种比较操作: + +```losu +import std + +main { + let str1 = 'apple' + let str2 = 'banana' + let str3 = 'apple' + + println('=== 字符串比较 ===') + println('str1:', str1) + println('str2:', str2) + println('str3:', str3) + + println('str1 == str2:', str1 == str2) # false + println('str1 == str3:', str1 == str3) # true + println('str1 != str2:', str1 != str2) # true + println('str1 < str2:', str1 < str2) # true (字典序) + println('str1 > str2:', str1 > str2) # false +} +``` + +## 字符串和数组 + +字符串在某些方面可以像数组一样操作: + +```losu +import std + +main { + let text = 'Hello' + + println('字符串:', text) + println('长度:', sizeof(text)) + + # 遍历字符串(如果支持) + println('字符遍历:') + for (i in 0, sizeof(text)) { + if (i < sizeof(text)) { + println('位置', i, ':', text[i]) + } + } +} +``` + +## 练习 + +### 练习 1:字符串基本操作 + +编写程序演示字符串的创建、拼接和基本操作。 + +
+查看答案 + +```losu +import std + +main { + # 字符串创建 + let firstName = '李' + let lastName = '明' + let age = 28 + + println('=== 字符串基本操作 ===') + println('姓:', firstName) + println('名:', lastName) + println('年龄:', age) + + # 字符串拼接 + let fullName = firstName & lastName + let introduction = '我是' & fullName & ',今年' & str(age) & '岁。' + + println('全名:', fullName) + println('自我介绍:', introduction) + + # 字符串长度 + println('全名长度:', sizeof(fullName)) + println('介绍长度:', sizeof(introduction)) + + # 字符串比较 + let anotherName = '李明' + println('姓名相同:', fullName == anotherName) +} +``` + +
+ +### 练习 2:字符串格式化 + +创建一个简单的信息格式化程序。 + +
+查看答案 + +```losu +import std + +main { + # 商品信息 + let productName = '洛书编程教程' + let originalPrice = 128.00 + let discountRate = 0.15 + let quantity = 3 + + println('=== 购物清单 ===') + + # 计算价格 + let discountAmount = originalPrice * discountRate + let finalPrice = originalPrice - discountAmount + let totalAmount = finalPrice * quantity + + # 格式化输出 + let itemInfo = '商品: ' & productName & '\n' & + '原价: ¥' & str(originalPrice) & '\n' & + '折扣: ' & str(discountRate * 100) & '%\n' & + '现价: ¥' & str(finalPrice) & '\n' & + '数量: ' & str(quantity) & '\n' & + '总计: ¥' & str(totalAmount) + + println(itemInfo) + + # 简单的收据格式 + println('\n=== 收据 ===') + println('感谢购买 ' & productName) + println('您节省了 ¥' & str(discountAmount * quantity)) +} +``` + +
+ +--- + +**上一章**:[← 数值类型](数值类型.md) | **下一章**:[函数类型 →](函数类型.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\345\237\272\346\234\254\345\256\271\345\231\250.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\345\237\272\346\234\254\345\256\271\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..9ec8858626549924226936b5fc183ed5b1c169a8 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\345\237\272\346\234\254\345\256\271\345\231\250.md" @@ -0,0 +1,413 @@ +# 基本容器 + +洛书语言的容器类型基于 `unit` 类型构建。`unit` 是洛书中最基础的复合数据类型,它可以存储键值对,支持动态添加和删除成员。所有其他容器类型(array、object、module、class)都是 `unit` 的特化形式。 + +## unit 类型概述 + +`unit` 类型具有以下特点: + +1. **键值存储**:以键值对的形式存储数据 +2. **动态结构**:可以在运行时添加或删除成员 +3. **混合类型**:可以存储不同类型的值 +4. **基础类型**:是其他容器类型的基础 +5. **变体支持**:可以通过 `@` 操作符创建不同的变体 + +## unit 变体创建 + +洛书中的所有容器类型本质上都是 `unit` 类型,通过 `@` 操作符指定变体类型: + +### 基本变体创建语法 + +```losu +import std + +main { + # 创建不同变体的 unit + let basicUnit = {} # 基本 unit + let objectVariant = {}@'object' # 对象变体 + let arrayVariant = {}@'array' # 数组变体 + let moduleVariant = {}@'module' # 模块变体 + let classVariant = {}@'class' # 类变体 + + println('基本 unit 类型:', typeof(basicUnit)) + println('对象变体类型:', typeof(objectVariant)) + println('数组变体类型:', typeof(arrayVariant)) + println('模块变体类型:', typeof(moduleVariant)) + println('类变体类型:', typeof(classVariant)) +} +``` + +### 基本 unit 创建 + +```losu +import std + +main { + # 创建空的 unit + let emptyUnit = {} + + # 创建带初始值的 unit + let userInfo = { + name: '张三', + age: 25, + city: '北京', + active: true + } + + println('空 unit:', emptyUnit) + println('用户信息:', userInfo) + println('unit 类型:', typeof(userInfo)) +} +``` + +## 成员访问 + +unit 的成员可以通过点号操作符或方括号操作符访问: + +### 点号访问 + +```losu +import std + +main { + let person = { + name: '李四', + age: 30, + email: 'lisi@example.com' + } + + println('=== 点号访问 ===') + println('姓名:', person.name) + println('年龄:', person.age) + println('邮箱:', person.email) +} +``` + +### 方括号访问 + +```losu +import std + +main { + let config = { + host: 'localhost', + port: 8080, + debug: true + } + + println('=== 方括号访问 ===') + println('主机:', config['host']) + println('端口:', config['port']) + println('调试:', config['debug']) + + # 动态键名访问 + let keyName = 'host' + println('动态访问:', config[keyName]) +} +``` + +## 成员修改 + +unit 的成员可以动态修改和添加: + +### 修改现有成员 + +```losu +import std + +main { + let student = { + name: '王五', + grade: 85, + subject: '数学' + } + + println('修改前:', student.name, student.grade) + + # 修改现有成员 + student.name = '王小五' + student.grade = 92 + + println('修改后:', student.name, student.grade) +} +``` + +### 添加新成员 + +```losu +import std + +main { + let product = { + name: '洛书教程', + price: 99.99 + } + + println('添加前:', product) + + # 添加新成员 + product.category = '编程' + product.inStock = true + product.rating = 4.8 + + println('添加后:') + println('名称:', product.name) + println('价格:', product.price) + println('分类:', product.category) + println('库存:', product.inStock) + println('评分:', product.rating) +} +``` + +## 嵌套 unit + +unit 可以嵌套,创建复杂的数据结构: + +```losu +import std + +main { + let company = { + name: '洛书科技', + founded: 2024, + address: { + country: '中国', + city: '北京', + street: '中关村大街1号' + }, + employees: { + total: 100, + departments: { + engineering: 60, + marketing: 25, + hr: 15 + } + } + } + + println('=== 嵌套 unit 演示 ===') + println('公司名:', company.name) + println('成立年份:', company.founded) + println('城市:', company.address.city) + println('工程部人数:', company.employees.departments.engineering) +} +``` + +## unit 操作函数 + +洛书可以用 `for` 关键字来遍历 unit: + +### 遍历 unit + +```losu +import std + +main { + let scores = { + math: 95, + english: 88, + physics: 92, + chemistry: 90 + } + + println('=== unit 遍历 ===') + println('学科成绩:') + + # 遍历键值对 + for (k, v in scores) { + println(k & ':', v) + } +} +``` + +## unit 的类型注释 + +可以为 unit 添加类型注释: + +```losu +import std + +main { + # 基本 unit 类型注释 + let config: `unit` = { + appName: '洛书应用', + version: '1.0', + debug: true + } + + let config2: `object` = { + appName: '洛书应用', + version: '1.0', + }@'object' + + println(typeof(config)) + println(typeof(config2)) +} +``` + +## 练习 + +### 练习 1:unit 变体创建和操作 + +创建不同类型的 unit 变体并进行基本操作。 + +?> **练习要求** +使用 `@` 操作符创建不同的 unit 变体,并演示它们的类型差异。 + +
+点击查看答案 + +```losu +import std + +main { + # 创建不同变体的 unit + let basicUnit = { + name: '基本单元', + type: 'basic' + } + + let objectVariant = { + name: '对象变体', + value: 100 + }@'object' + + let arrayVariant = { + [0]: '第一个元素', + [1]: '第二个元素', + length: 2 + }@'array' + + let moduleVariant = { + version: '1.0', + author: '洛书团队' + }@'module' + + println('=== unit 变体演示 ===') + println('基本 unit 类型:', typeof(basicUnit)) + println('对象变体类型:', typeof(objectVariant)) + println('数组变体类型:', typeof(arrayVariant)) + println('模块变体类型:', typeof(moduleVariant)) + + # 访问属性 + println('基本 unit 名称:', basicUnit.name) + println('对象变体名称:', objectVariant.name) + println('数组变体第一个元素:', arrayVariant[0]) + println('模块变体版本:', moduleVariant.version) + + # 修改属性 + basicUnit.status = 'active' + objectVariant.value = 200 + arrayVariant[2] = '第三个元素' + + println('修改后基本 unit 状态:', basicUnit.status) + println('修改后对象变体值:', objectVariant.value) + println('修改后数组变体第三个元素:', arrayVariant[2]) +} +``` + +
+ +### 练习 2:复杂嵌套结构和动态操作 + +创建复杂的嵌套 unit 结构并进行动态操作。 + +?> **练习要求** +创建一个包含多层嵌套的配置系统,支持动态添加和修改配置项。 + +
+点击查看答案 + +```losu +import std + +main { + # 创建复杂的应用配置系统 + let appConfig = { + app: { + name: '洛书应用', + version: '2.0.0', + debug: false + }, + server: { + host: 'localhost', + port: 3000, + ssl: { + enabled: false, + cert: '', + key: '' + } + }, + database: { + type: 'sqlite', + connection: { + host: 'localhost', + port: 5432, + name: 'losu_db' + }, + pool: { + min: 2, + max: 10 + } + }, + features: { + auth: true, + logging: true, + cache: false + } + } + + println('=== 应用配置系统 ===') + println('应用名称:', appConfig.app.name) + println('版本:', appConfig.app.version) + println('服务器端口:', appConfig.server.port) + println('数据库类型:', appConfig.database.type) + + # 动态修改配置 + appConfig.app.debug = true + appConfig.server.port = 8080 + appConfig.server.ssl.enabled = true + appConfig.server.ssl.cert = '/path/to/cert.pem' + + println('=== 配置更新后 ===') + println('调试模式:', appConfig.app.debug) + println('新端口:', appConfig.server.port) + println('SSL启用:', appConfig.server.ssl.enabled) + + # 动态添加新配置 + appConfig.monitoring = { + enabled: true, + interval: 60, + alerts: { + email: true, + sms: false + } + } + + appConfig.features.backup = true + appConfig.database.backup = { + enabled: true, + schedule: 'daily', + retention: 30 + } + + println('=== 新增配置 ===') + println('监控启用:', appConfig.monitoring.enabled) + println('监控间隔:', appConfig.monitoring.interval) + println('邮件告警:', appConfig.monitoring.alerts.email) + println('备份功能:', appConfig.features.backup) + println('备份计划:', appConfig.database.backup.schedule) + + # 配置统计 + println('=== 配置统计 ===') + println('顶级配置项数:', sizeof(appConfig)) + println('服务器配置项数:', sizeof(appConfig.server)) + println('数据库配置项数:', sizeof(appConfig.database)) +} +``` + +
+ +--- + +**上一章**:[← 特殊类型](../特殊类型.md) | **下一章**:[数组变体 →](数组变体.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\345\257\271\350\261\241\345\217\230\344\275\223.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\345\257\271\350\261\241\345\217\230\344\275\223.md" new file mode 100644 index 0000000000000000000000000000000000000000..32bf0e26b783841580ab8b38f06254e76ab2c647 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\345\257\271\350\261\241\345\217\230\344\275\223.md" @@ -0,0 +1,273 @@ +# 对象变体 + +对象变体(object)是洛书语言中用于表示结构化数据的容器类型。对象是基于 `unit` 类型的特化形式,专门用于创建具有固定结构和行为的数据实体。对象变体提供了更加面向对象的编程方式。 + +## 对象创建 + +洛书中的对象可以通过多种方式创建: + +### 字面量创建 + +```losu +import std + +main { + # 创建简单对象 + let person = { + name: '张三', + age: 25, + city: '北京', + isActive: true + }@'object' + + # 创建嵌套对象 + let employee = { + id: 1001, + profile: { + name: '李四', + age: 30, + department: '技术部' + }, + skills: ['洛书', 'Python', 'JavaScript'], + salary: 15000 + }@'object' + + println('人员信息:', person.name, person.age) + println('员工部门:', employee.profile.department) + println('对象类型:', typeof(person)) +} +``` + +### 对象变体的特殊功能 + +对象变体支持析构函数,提供了自动资源管理: + +```losu +import std + +main { + # 创建带析构函数的对象 + let smartObject = { + name: "智能对象", + value: 100, + + # 析构函数 + "__del__": { + println("对象", name, "被销毁") + } + }@'object' + + println('对象类型:', typeof(smartObject)) + println('对象名称:', smartObject.name) + println('对象值:', smartObject.value) + + # 修改对象属性 + smartObject.value = 200 + println('修改后的值:', smartObject.value) + + # 对象在作用域结束时会自动调用析构函数 +} +``` + +### 运算符访问的区别 + +对象变体和模块变体在成员访问上有重要区别: + +```losu +import std + +main { + let objectExample = { + name: "对象示例", + func: { + println("对象方法被调用") + } + }@'object' + + let moduleExample = { + name: "模块示例", + func: { + println("模块方法被调用") + } + }@'module' + + println('=== 访问方式对比 ===') + + # "." 运算符访问(对象和模块都支持) + println('对象用.访问:', objectExample.name) + println('模块用.访问:', moduleExample.name) + + # "::" 运算符访问(主要用于模块) + println('模块用::访问名称:', moduleExample::name) + + # 方法调用 + objectExample.func() # 对象方法调用 + moduleExample::func() # 模块方法调用(推荐用::) +} +``` + +### 构造函数模式 + +```losu +import std + +def createUser(name, email, role) { + return { + name: name, + email: email, + role: role, + createdAt: '2024-01-15', + isActive: true, + + # 析构函数 + "__del__": { + println("用户", name, "对象被清理") + } + }@'object' +} + +def getUserInfo(user) { + return user.name & ' (' & user.email & ') - ' & user.role +} + +def activateUser(user) { + user.isActive = true + return '用户已激活' +} + +main { + let user1 = createUser('王五', 'wangwu@example.com', '管理员') + let user2 = createUser('赵六', 'zhaoliu@example.com', '用户') + + println('=== 用户管理系统 ===') + println('用户1信息:', getUserInfo(user1)) + println('用户2信息:', getUserInfo(user2)) + println('用户1状态:', user1.isActive) + + println(activateUser(user2)) + println('用户2状态:', user2.isActive) +} +``` + +## 对象属性访问 + +对象的属性可以通过点号访问: + +### 点号访问 + +```losu +import std + +main { + let product = { + id: 'P001', + name: '洛书编程指南', + price: 89.99, + category: '编程书籍', + inStock: true, + tags: ['编程', '教程', '洛书'] + }@'object' + + println('=== 产品信息 ===') + println('产品ID:', product.id) + println('产品名称:', product.name) + println('价格:', product.price) + println('分类:', product.category) + println('库存状态:', product.inStock) + println('标签数量:', sizeof(product.tags)) +} +``` + +## 对象组合 + +对象可以包含其他对象,形成复杂的数据结构: + +### 嵌套对象 + +```losu +import std + +main { + let company = { + name: '公司', + founded: 2024, + + address: { + country: '中国', + city: '北京', + street: '中关村大街1号', + zipCode: '100080' + }@'object', + + departments: { + engineering: { + name: '工程部', + headCount: 50, + budget: 5000000 + }@'object', + marketing: { + name: '市场部', + headCount: 20, + budget: 2000000 + }@'object', + hr: { + name: '人力资源部', + headCount: 10, + budget: 1000000 + }@'object' + } + }@'object' + + println('=== 公司信息系统 ===') + println('公司名称:', company.name) + println('成立年份:', company.founded) + println('工程部预算:', company.departments.engineering.budget) +} +``` + +## 对象克隆和合并 + +### 对象属性复制 + +```losu +import std + +def cloneObject(original) { + let clone = {} + return clone +} + +def mergeObjects(obj1, obj2) { + let merged = {} + return merged +} + +main { + let baseConfig = { + host: 'localhost', + port: 3000, + debug: false + }@'object' + + let devConfig = { + debug: true, + logLevel: 'verbose' + }@'object' + + println('=== 对象操作演示 ===') + println('基础配置:', baseConfig.host, baseConfig.port, baseConfig.debug) + println('开发配置:', devConfig.debug, devConfig.logLevel) + + # 手动合并示例 + let finalConfig = { + host: baseConfig.host, + port: baseConfig.port, + debug: devConfig.debug, + logLevel: devConfig.logLevel + }@'object' + + println('最终配置:', finalConfig.host, finalConfig.port, finalConfig.debug, finalConfig.logLevel) +} +``` + +**上一章**:[← 数组变体](数组变体.md) | **下一章**:[模块变体 →](模块变体.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\346\225\260\347\273\204\345\217\230\344\275\223.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\346\225\260\347\273\204\345\217\230\344\275\223.md" new file mode 100644 index 0000000000000000000000000000000000000000..63ccd791352dcea6123a4e1a15fa3119b3001a5c --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\346\225\260\347\273\204\345\217\230\344\275\223.md" @@ -0,0 +1,298 @@ +# 数组变体 + +数组变体(array)是洛书语言中用于存储有序元素集合的容器类型。数组是基于 `unit` 类型的特化形式,提供了索引访问、顺序遍历和动态大小调整等功能。 + +## 数组创建 + +洛书提供了多种创建数组的方式: + +### 字面量创建 + +```losu +import std + +main { + # 创建空数组 + let emptyArray = [] + + # 创建带初始值的数组 + let numbers = [1, 2, 3, 4, 5] + let strings = ['hello', 'world', 'losu'] + let mixed = [1, 'text', true, 3.14] + + println('空数组:', emptyArray) + println('数字数组:', numbers) + println('字符串数组:', strings) + println('混合数组:', mixed) + println('数组类型:', typeof(numbers)) +} +``` + +### 使用 unit 变体创建 + +数组也可以通过 unit 变体的方式创建,这种方式可以同时设置键值对和索引: + +```losu +import std + +main { + # 使用 unit 变体创建数组 + let customArray = { + hello: "world", + [1]: 1, + [2]: 2, + [3]: 3 + }@'array' + + println('自定义数组类型:', typeof(customArray)) + println('通过键访问:', customArray.hello) + println('通过索引访问:', customArray[1]) + println('数组大小:', sizeof(customArray)) +} +``` + +## 数组访问 + +数组元素可以通过索引访问,索引从 0 开始: + +### 基本索引访问 + +```losu +import std + +main { + let fruits = ['苹果', '香蕉', '橙子', '葡萄'] + + println('=== 数组访问演示 ===') + println('第一个水果:', fruits[0]) + println('第二个水果:', fruits[1]) + println('第三个水果:', fruits[2]) + println('第四个水果:', fruits[3]) + + # 数组长度 + println('水果总数:', sizeof(fruits)) +} +``` + +## 数组修改 + +数组支持动态修改元素和调整大小: + +### 修改元素 + +```losu +import std + +main { + let scores = [85, 90, 78, 92] + + println('修改前:', scores) + + # 修改特定索引的元素 + scores[0] = 88 + scores[2] = 82 + + println('修改后:', scores) +} +``` + +### 添加元素 + +在数组中添加元素直接在对应的索引位置添加元素即可,数组的长度会**自动扩充**。 + +```losu +import std + +main { + let todoList = ['learn', 'write'] + + println('tasks:', todoList) + + # 添加新任务 + todoList[2] = 'test' + todoList[3] = 'docs' + + for (i in 0, sizeof(todoList) - 1) { + println('updated:', todoList[i]) + } + println('total:', sizeof(todoList)) +} +``` + +## 数组遍历 + +洛书提供了多种遍历数组的方式: + +### 索引遍历 + +```losu +import std + +main { + let languages = ['洛书', 'Python', 'JavaScript', 'C++'] + + println('=== 索引遍历 ===') + for (i in 0, sizeof(languages)) { + if (i < sizeof(languages)) { + println('语言', i + 1, ':', languages[i]) + } + } +} +``` + +### 元素遍历 + +```losu +import std + +main { + let numbers = [10, 20, 30, 40, 50] + + println('=== 元素遍历 ===') + for (num in 0, sizeof(numbers) - 1) { + println('数字:', numbers[num]) + } +} +``` + +## 多维数组 + +洛书支持多维数组,即数组的数组: + +### 二维数组 + +```losu +import std + +main { + # 创建二维数组(矩阵) + let matrix = [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9] + ] + + println('=== 二维数组演示 ===') + println('矩阵:') + for (i in 0, sizeof(matrix)) { + if (i < sizeof(matrix)) { + let row = matrix[i] + println('第', i + 1, '行:', row) + } + } + + # 访问特定元素 + println('第2行第3列元素:', matrix[1][2]) +} +``` + +### 不规则数组 + +```losu +import std + +main { + # 创建不规则数组 + let irregularArray = [ + [1, 2], + [3, 4, 5, 6], + [7], + [8, 9, 10] + ] + + println('=== 不规则数组演示 ===') + for (i in 0, sizeof(irregularArray)) { + if (i < sizeof(irregularArray)) { + let subArray = irregularArray[i] + println('子数组', i, '(长度', sizeof(subArray), '):', subArray) + } + } +} +``` + +## 数组类型注释 + +可以为数组添加类型注释: + +```losu +import std + +main { + # 基本数组类型注释 + let numbers: `array` = [1, 2, 3, 4, 5] + let strings: `array` = ['a', 'b', 'c'] + + # 更具体的类型注释(如果支持) + let scores: `array` = [85, 90, 78, 92] + let names: `array` = ['Alice', 'Bob', 'Charlie'] + + println('数字数组:', numbers) + println('字符串数组:', strings) + println('分数数组:', scores) + println('姓名数组:', names) +} +``` + +## 练习 + +### 练习 1:基本数组操作 + +创建和操作数组,实现基本的增删改查功能。 + +
+查看答案 + +```losu +import std + +main { + # 创建初始数组 + let inventory = ['苹果', '香蕉', '橙子'] + + println('=== 库存管理系统 ===') + println('初始库存:', inventory) + + # 添加新商品 + inventory = inventory + ['葡萄'] + inventory = inventory + ['草莓'] + println('添加商品后:', inventory) + + # 修改商品 + inventory[1] = '芒果' # 将香蕉改为芒果 + println('修改商品后:', inventory) + + # 查找商品 + let target = '橙子' + let found = false + let foundIndex = -1 + + for (i in 0, sizeof(inventory)) { + if (i < sizeof(inventory) and inventory[i] == target) { + found = true + foundIndex = i + } + } + + if (found) { + println('找到', target, '在索引', foundIndex) + } else { + println('未找到', target) + } + + # 显示最终库存 + println('最终库存:') + for (i in 0, sizeof(inventory)) { + if (i < sizeof(inventory)) { + println(' ', i + 1, '.', inventory[i]) + } + } + + println('库存总数:', sizeof(inventory)) +} +``` + +
+ +--- + +**上一章**:[← 基本容器](基本容器.md) | **下一章**:[对象变体 →](对象变体.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\346\250\241\345\235\227\345\217\230\344\275\223.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\346\250\241\345\235\227\345\217\230\344\275\223.md" new file mode 100644 index 0000000000000000000000000000000000000000..7c3fbb36ab887930a302ed52b34e4a7006e4e24c --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\346\250\241\345\235\227\345\217\230\344\275\223.md" @@ -0,0 +1,236 @@ +# 模块变体 + +模块变体(module)是洛书语言中基于 `unit` 类型的特化形式,专门用于代码组织和封装。模块变体提供了命名空间隔离和接口导出功能,是构建可重用代码单元的重要工具。 + +## 模块变体概述 + +洛书中的模块变体具有以下特点: + +1. **基于unit类型**:模块变体本质上是unit类型,使用 `@'module'` 创建 +2. **封装性**:模块内部的实现细节可以隐藏 +3. **可重用性**:模块可以在不同地方被导入和使用 +4. **命名空间**:模块提供独立的命名空间,避免命名冲突 +5. **无析构函数**:模块变体不支持析构函数,专注于功能封装 +6. **运算符差异**:`.` 运算符会自动传递self,`::` 运算符不会自动传递self + +## 模块变体创建 + +### 使用 @'module' 创建模块变体 + +模块变体可以通过 `@'module'` 语法直接创建,形如:`let mathModule = { ... } @'module'` + +```losu +import std +import math + +main { + # 创建数学工具模块变体 + let mathModule = { + PI: 3.14159, + + add: { + (self, a, b) { + return a + b + } + }, + + multiply: { + (self, a, b) { + return a * b + } + }, + + circle: { + area: { + (self, radius) { + return 3.14 * radius * radius + } + }, + + circumference: { + (self, radius) { + return 2 * 3.14 * radius + } + } + } + }@'module' + + println('模块类型:', typeof(mathModule)) + println('PI 值:', mathModule.PI) + + # 使用 . 运算符调用(自动传递self) + println('加法结果:', mathModule.add(5, 3)) + println('乘法结果:', mathModule.multiply(4, 6)) + println('圆面积:', mathModule.circle.area(5)) +} +``` + +### 模块变体的运算符差异 + +模块变体的一个重要特点是 `.` 和 `::` 运算符的行为差异: + +```losu +import std + +main { + let testModule = { + name: '测试模块', + + func: { + (self) { + println('模块名称:', self.name) + return '函数调用成功' + } + }, + + getValue: { + (self, key) { + return self[key] or '未找到' + } + } + }@'module' + + println('=== 运算符差异演示 ===') + + # 使用 . 运算符(自动传递self) + println('使用 . 运算符:') + println(testModule.func()) + println('获取值:', testModule.getValue('name')) + + # 使用 :: 运算符(手动传递self) + println('使用 :: 运算符:') + println(testModule::func(testModule)) + println('获取值:', testModule::getValue(testModule, 'name')) +} +``` + +## 模块导入方式 + +### 全局导入 + +```losu +import std +import os # 内置模块全局导入 + +main { + println('=== 全局导入演示 ===') + println('标准库可用') + # 使用 std 和 os 模块的功能 +} +``` + +### 局部导入 + +```losu +import std + +main { + # 导入用户自定义模块文件 + let utils = std::!import('utils') + let config = std::!import('config') + + println('=== 局部导入演示 ===') + + # 使用导入的模块 + if (utils) { + println('工具模块已导入') + } + + if (config) { + println('配置模块已导入') + } +} +``` + +## 模块组合 + +### 复合模块变体 + +```losu +import std + +main { + # 创建应用主模块变体 + let app = { + version: '1.0.0', + + # 内嵌其他模块功能 + math: { + add: { + (self, a, b) { + return a + b + } + }, + + multiply: { + (self, a, b) { + return a * b + } + } + }, + + utils: { + isEmpty: { + (self, value) { + if (typeof(value) == 'string') { + return value == '' + } elif (typeof(value) == 'array') { + return sizeof(value) == 0 + } else { + return false + } + } + } + }, + + # 应用特定功能 + initialize: { + (self, env) { + return { + message: '应用已初始化', + version: self.version, + env: env + } + } + }, + + # 组合多个模块的功能 + processData: { + (self, data) { + if (self.utils.isEmpty(data)) { + return '数据为空' + } + + let sum = 0 + for (item in 0, sizeof(data)) { + sum = self.math.add(sum, item) + } + + return { + count: sizeof(data), + sum: sum, + average: sum / sizeof(data) + } + } + } + }@'module' + + println('=== 复合模块演示 ===') + + let initResult = app.initialize('development') + println('初始化结果:', initResult.message) + println('版本:', initResult.version) + println('环境:', initResult.env) + + let testData = [1, 2, 3, 4, 5] + let result = app.processData(testData) + println('数据处理结果:') + println(' 数量:', result.count) + println(' 总和:', result.sum) + println(' 平均值:', result.average) +} +``` + +--- + +**上一章**:[对象变体 ←](对象变体.md) | **下一章**:[类变体基本用法 →](类变体/基本用法.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\345\217\215\345\260\204.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\345\217\215\345\260\204.md" new file mode 100644 index 0000000000000000000000000000000000000000..fd4ecd408b6c664d4c38956ecb22284c5add0c7c --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\345\217\215\345\260\204.md" @@ -0,0 +1,133 @@ +# 反射 + +反射是程序在运行时检查、访问和修改自身结构和行为的能力。在洛书语言中,反射主要用于局部类的重载和动态类型操作。 + +## 反射概念 + +洛书中的反射功能包括: + +1. **类型检查**:运行时获取对象的类型信息 +2. **类原型获取**:通过对象实例获取类的原型 +3. **动态实例创建**:使用 `__reflect__` 创建同类型实例 +4. **局部类重载**:方便局部类进行运算符重载 +5. **动态访问**:通过字符串名称访问属性和方法 + +## __reflect__ 的使用 + +`__reflect__` 方法用于通过对象实例获取类的原型,特别适用于局部类的重载。它支持传统的 `class` 关键字定义的类和使用 `@'class'` 语法创建的类变体。 + +### 使用 @'class' 语法的反射 + +```losu +import std + +main { + # 使用 @'class' 创建类变体 + let Point = { + __init__: { # 注意,这里使用的是 __init__,只有在class里构造函数时才能直接使用init + (self, x, y) { + self.x = x + self.y = y + return self + } + }, + + # 使用反射进行运算符重载 + "+": { + (self, other) { + # 通过self获取类原型并创建新实例 + return self::__reflect__(self.x + other.x, self.y + other.y) + } + }, + + toString: { + (self) { + return "Point(" & str(self.x) & ", " & str(self.y) & ")" + } + } + }@'class' + + let p1 = Point(1, 2) + let p2 = Point(3, 4) + let p3 = p1 + p2 # 使用重载的加法运算符 + + println("=== @'class' 反射演示 ===") + println("p1:", p1.toString()) + println("p2:", p2.toString()) + println("p3:", p3.toString()) + println("p3类型:", typeof(p3)) +} +``` + +### 传统 class 关键字的反射 + +```losu +import std + +main { + class Point { # 局部类 + init(self, x, y) { + self.x = x + self.y = y + } + + # 使用反射进行运算符重载 + "+"(self, other) { + # 正确的反射写法:通过self获取类原型并创建新实例 + return self::__reflect__(self.x + other.x, self.y + other.y) + } + + def toString(self) { + return "Point(" & str(self.x) & ", " & str(self.y) & ")" + } + } + + let p1 = Point(3, 4) + let p2 = Point(1, 2) + let p3 = p1 + p2 # 使用重载的加法运算符 + + println("=== 传统 class 反射演示 ===") + println("p1:", p1.toString()) + println("p2:", p2.toString()) + println("p3:", p3.toString()) + println("p3类型:", typeof(p3)) +} +``` + +### 反射的工作原理 + +`__reflect__` 方法的本质是通过对象实例去获取类的原型,然后用该原型创建新的实例: + +```losu +import std + +main { + class Calculator { + init(self, value) { + self.value = value + } + + # 乘法重载使用反射 + "*"(self, other) { + let newValue = self.value * other.value + return self::__reflect__(newValue) + } + + def getValue(self) { + return self.value + } + } + + let calc1 = Calculator(5) + let calc2 = Calculator(3) + let result = calc1 * calc2 + + println("计算结果:", result.getValue()) + println("结果类型:", typeof(result)) +} +``` + +--- + +**上一章**:[类变体继承 ←](继承.md) +**下一章**:[语句 →](../../../3-语句/README.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\345\237\272\346\234\254\347\224\250\346\263\225.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\345\237\272\346\234\254\347\224\250\346\263\225.md" new file mode 100644 index 0000000000000000000000000000000000000000..6582c1d081ee1ca40c293d7f5435f46dd7123150 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\345\237\272\346\234\254\347\224\250\346\263\225.md" @@ -0,0 +1,346 @@ +# 基本用法 + +类变体(class)是洛书语言中面向对象编程的核心特性。类变体提供了完整的面向对象编程支持,包括构造函数、析构函数、静态成员、成员函数等。 + +## 类变体的特点 + +洛书中的类变体具有以下特点: + +1. **基于unit类型**:类变体本质上是unit类型,可以使用 `@'class'` 创建 +2. **必须有构造函数**:类变体必须定义 `init` 构造函数 +3. **支持析构函数**:可以定义 `del` 析构函数进行资源清理 +4. **静态成员**:支持多种静态成员声明方式 +5. **成员函数**:支持实例方法定义 +6. **作用域控制**:可以是局部类或全局类 +7. **多种创建方式**:支持 `class` 关键字和 `@'class'` 语法 + +## 类变体创建方式 + +### 使用 @'class' 创建类变体 + +类变体本质上是unit类型的特化形式,可以直接使用 `@'class'` 语法创建: + +```losu +import std + +main { + # 方式1:使用 @'class' 创建类变体 + let PersonClass = { + # 构造函数(必须) + init: { + (self, name, age) { + self.name = name + self.age = age + return self + } + }, + + # 成员函数 + greet: { + (self) { + println("Hello, I'm", self.name, "and I'm", self.age, "years old") + } + }, + + # 析构函数(可选) + del: { + (self) { + println("Person", self.name, "is being destroyed") + } + } + }@'class' + + println('类变体类型:', typeof(PersonClass)) + + # 创建实例 + let person = PersonClass.init(PersonClass, "张三", 25) + person.greet() +} +``` + +### 使用继承的 @'class' 创建 + +```losu +import std + +main { + # 基类 + let Animal = { + init: { + (self, name) { + self.name = name + return self + } + }, + + speak: { + (self) { + println(self.name, "makes a sound") + } + } + }@'class' + + # 派生类,使用 __super__ 实现继承 + let Dog = { + "__super__": Animal, + + init: { + (self, name, breed) { + # 调用父类构造函数 + Animal.init(self, name) + self.breed = breed + return self + } + }, + + speak: { + (self) { + println(self.name, "the", self.breed, "barks: Woof!") + } + }, + + wagTail: { + (self) { + println(self.name, "wags tail happily") + } + } + }@'class' + + println('=== 继承演示 ===') + let dog = Dog.init(Dog, "旺财", "金毛") + dog.speak() + dog.wagTail() +} +``` + +### 传统 class 关键字定义 + +使用 `global class` 关键字定义全局可访问的类: + +```losu +import std + +global class People { + init(self, name, age) { # 必须有构造函数init + self.name = name + self.age = age + } + + # 静态成员有三种声明方式 + var name # 方式1:var声明 + id = 1 # 方式2:直接赋值 + var index = 2 # 方式3:var声明并赋值 + + # 成员函数 + def sayhello(self) { + println("hello", self.name) + } + + # 析构函数 + del(self) { + println("delete", self.name) + } +} + +main { + let p = People("张三", 18) + p.sayhello() + # 对象在作用域结束时自动调用析构函数 +} +``` + +### 局部类定义 + +不使用 `global` 关键字的类只在当前文件作用域内有效: + +```losu +import std + +main { + class LocalPerson { + init(self, name) { + self.name = name + } + + def greet(self) { + println("Hi, I'm", self.name) + } + } + + let person = LocalPerson("李四") + person.greet() +} +``` + +## 类的属性 + +### 公共属性和私有属性 + +```losu +import std + +main { + # 定义具有公共和私有属性的类 + class Counter { + init(self, maxValue, count) { + self.count = count + self.maxValue = maxValue + } + # 公共只读属性 + created = { + return '2024-01-15' + } + + # 公共方法 + getValue = { + return count + } + + increment = { + (self, count, maxValue) { + if (count < maxValue) { + count = count + 1 + return count + } else { + return '已达到最大值' + } + } + } + + decrement = { + (self, count) { + if (count > 0) { + count = count - 1 + return count + } else { + return '已达到最小值' + } + } + } + + reset = { + (self, count) { + count = 0 + return '计数器已重置' + } + } + + setMax = { + (self, newMax, maxValue) { + if (newMax > 0) { + maxValue = newMax + return '最大值设置为: ' & str(maxValue) + } else { + return '最大值必须大于0' + } + } + } + } + + let counter = Counter(5) + + let a = 100 + let b = 200 + + println('=== 计数器演示 ===') + println('初始值:', counter.getValue()) + println('递增:', counter.increment(a, b)) + println('递增:', counter.increment(a, b)) + println('递减:', counter.decrement(a, b)) + println('当前值:', counter.getValue()) + println(counter.setMax(50)) +} +``` + +> [!NOTE] +> 注意,当使用 `@'class'` 关键字定义类时,函数和成员构造结构为 `function: {}` ;当使用 `class` 关键字定义类时,函数和成员构造结构为 `function = {}` ,即class构造器里需要用 `=` 赋值。 + +## 练习 + +### 练习 1:创建基本类 + +创建一个表示图书的类,包含基本属性和方法。 + +
+查看答案 + +```losu +import std + +main { + # 使用 @'class' 创建图书类 + let Book = { + # 必须的构造函数 + init: { + (self, title, author, pages) { + self.title = title + self.author = author + self.pages = pages + return self + } + }, + + # 静态成员 - 记录图书总数 + totalBooks: 0, + + # 静态成员 - 默认分类 + category: "未分类", + + # 成员方法 - 获取图书信息 + getInfo: { + (self) { + return "《" , self.title , "》 - " , self.author , ",共" , str(self.pages) , "页" + } + }, + + # 成员方法 - 模拟阅读 + read: { + (self) { + println("正在阅读《" , self.title , "》,作者:" , self.author) + } + }, + + # 成员方法 - 设置分类 + setCategory: { + (self, newCategory) { + self.category = newCategory + println("《" , self.title , "》已设置为" , newCategory , "类别") + } + }, + + # 析构函数 + del: { + (self) { + println("图书《" , self.title , "》已从图书馆移除") + } + } + }@'class' + + println('=== 图书管理系统 ===') + println('图书类型:', typeof(Book)) + + # 创建图书实例 + let book1 = Book.init(Book, "洛书编程指南", "张三", 280) + let book2 = Book.init(Book, "数据结构与算法", "李四", 450) + + # 测试成员方法 + println(book1.getInfo()) + println(book2.getInfo()) + + book1.read() + book1.setCategory("编程技术") + + book2.read() + book2.setCategory("计算机科学") + + # 查看静态成员 + println("图书总数:", Book.totalBooks) + + # 作用域结束时会自动调用析构函数 +} +``` + +--- + +**上一章**:[模块变体 ←](../模块变体.md) +**下一章**:[类变体重载 →](重载.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\347\273\247\346\211\277.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\347\273\247\346\211\277.md" new file mode 100644 index 0000000000000000000000000000000000000000..0df13ab7993bdee9b586e4b6ede09733c91efcbe --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\347\273\247\346\211\277.md" @@ -0,0 +1,168 @@ +# 继承 + +继承是面向对象编程中的重要概念,允许一个类基于另一个类来定义,从而复用代码和建立类之间的层次关系。洛书语言提供了完整的类继承支持。 + +## 继承概念 + +洛书中的继承具有以下特点: + +1. **语法继承**:使用括号语法指定父类 +2. **构造函数继承**:构造函数一般不会自动继承,需要重写 +3. **析构函数继承**:如果不重写则会继承父类的析构函数 +4. **方法继承**:子类自动继承父类的所有方法 +5. **super调用**:支持调用父类的构造函数和方法 + +## 基本继承语法 + +### 标准继承 + +使用括号语法指定父类,子类会自动继承父类的所有方法: + +```losu +import std + +global class People { + init(self, name, age) { + self.name = name + self.age = age + } + + var name + id = 1 + var index = 2 + + def sayhello(self) { + println("hello", self.name) + } + + del(self) { + println("delete", self.name) + } +} + +# 继承语法:在类名后用括号指定父类 +global class Student(People) { + init(self, name, age, studentId) { + # 调用父类构造函数的两种方式: + + # 方式1:当能拿到父类名时(推荐) + People::__init__(self, name, age) + + # 方式2:当拿不到父类名时(继承的对象可能是表达式) + # self::__super__::__init__(self, name, age) + + self.studentId = studentId + } + + def study(self) { + println(self.name, "正在学习,学号:", self.studentId) + } +} + +main { + let student = Student("张三", 18, "S001") + student.sayhello() # 继承的方法 + student.study() # 子类的方法 +} +``` + +### 使用 @'class' 和 __super__ 的继承 + +当使用 `@'class'` 语法创建类变体时,可以通过 `__super__` 属性实现继承: + +```losu +import std + +main { + # 基类 + let People = { + init: { + (self, name, age) { + + self.name = name + self.age = age + return self + } + }, + + introduce: { + (self) { + println("我是", self.name, ",今年", self.age, "岁") + } + } + }@'class' + + # 通过设置 __super__ 属性实现继承 + let Student = { + "__super__": People, + + init: { + (self, name, age, studentId) { + # 调用父类构造函数 + People.init(self, name, age) + self.studentId = studentId + return self + } + }, + + introduce: { + (self) { + println("我是学生", self.name, ",今年", self.age, "岁,学号:", self.studentId) + } + }, + + study: { + (self) { + println(self.name, "正在学习") + } + } + }@'class' + + println('=== @class 继承演示 ===') + let student = Student.init(Student, "李四", 20, "S002") + student.introduce() + student.study() +} +``` + +### 传统 class 关键字继承 + +使用传统的 `global class` 语法实现继承: + +```losu +import std + +global class People { + init(self, name, age) { + self.name = name + self.age = age + } + + def introduce(self) { + println("我是", self.name, ",今年", self.age, "岁") + } +} + +main { + # 通过设置 __super__ 属性实现动态继承 + var dynamicStudent = { + "__super__": People, + studentId: "S003" + }@"class" + + # 这种方式下,构造函数会被自动继承 + println("动态继承类创建成功") +} +``` + +## 继承中的错误处理 + +> [!WARNING] +> 如果继承中出现了错误,那么继承的对象是不会被析构的。这意味着在继承过程中如果发生异常或错误,父类对象可能不会正确调用析构函数,可能导致资源泄漏。因此在设计继承关系时需要特别注意错误处理。 + +
+ +--- + +**上一章**:[类变体重载 ←](重载.md) +**下一章**:[类变体反射 →](反射.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\351\207\215\350\275\275.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\351\207\215\350\275\275.md" new file mode 100644 index 0000000000000000000000000000000000000000..bcd1e19a98a195ca18a22a23989adb02fe09077c --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\345\256\271\345\231\250\347\261\273\345\236\213/\347\261\273\345\217\230\344\275\223/\351\207\215\350\275\275.md" @@ -0,0 +1,369 @@ +# 重载 + +运算符重载是洛书语言类变体的重要特性,允许为自定义类型定义运算符行为。通过重载运算符,可以让自定义类的对象支持各种运算操作,使代码更加直观和易读。 + +## 重载概述 + +洛书中的运算符重载具有以下特点: + +1. **支持的运算符**:`+`、`-`、`*`、`/`、`%`、`**`、`[]`、`()`、`&` +2. **字符串函数名**:使用字符串作为函数名来定义重载 +3. **一元和二元支持**:部分运算符支持一元和二元两种形式 +4. **自动参数传递**:运算符重载函数会自动接收相应的参数 +5. **返回值灵活**:可以返回任意类型的值 + +## 基本运算符重载 + +### 算术运算符重载 + +```losu +import std + +global class Point { + init(self, x, y) { + self.x = x + self.y = y + } + + # 加法运算符重载 + "+"(self, other) { + return Point(self.x + other.x, self.y + other.y) + } + + # 减法运算符重载(支持一元和二元) + "-"(self, other) { + if (other) { + # 二元减法 + println("执行二元减法") + return Point(self.x - other.x, self.y - other.y) + } else { + # 一元取负 + println("执行一元取负") + return Point(-self.x, -self.y) + } + } + + # 乘法运算符重载(标量乘法) + "*"(self, scalar) { + return Point(self.x * scalar, self.y * scalar) + } + + # 除法运算符重载 + "/"(self, scalar) { + if (scalar != 0) { + return Point(self.x / scalar, self.y / scalar) + } else { + println("错误:除零") + return self + } + } + + # 字符串连接运算符重载 + "&"(self, other) { + return "Point(" & str(self.x) & ", " & str(self.y) & ") & " & str(other) + } + + # 显示方法 + def toString(self) { + return "Point(" & str(self.x) & ", " & str(self.y) & ")" + } +} + +main { + let p1 = Point(3, 4) + let p2 = Point(1, 2) + + println('=== 算术运算符重载演示 ===') + println('p1:', p1.toString()) + println('p2:', p2.toString()) + + # 测试加法重载 + let p3 = p1 + p2 + println('p1 + p2 =', p3.toString()) + + # 测试减法重载 + let p4 = p1 - p2 + println('p1 - p2 =', p4.toString()) + + # 测试一元取负 + let p5 = -p1 + println('-p1 =', p5.toString()) + + # 测试乘法重载 + let p6 = p1 * 2 + println('p1 * 2 =', p6.toString()) + + # 测试除法重载 + let p7 = p1 / 2 + println('p1 / 2 =', p7.toString()) + + # 测试字符串连接重载 + println('p1 & "test" =', p1 & "test") +} +``` + +### 特殊运算符重载 + +```losu +import std + +global class Vector { + init(self, elements) { + self.elements = elements + } + + # 索引访问运算符重载 + "[]"(self, index) { + if (index >= 0 and index < sizeof(self.elements)) { + return self.elements[index] + } else { + println("索引越界:", index) + return 0 + } + } + + # 函数调用运算符重载 + "()"(self, operation) { + if (operation == "sum") { + let total = 0 + for (element in 0, sizeof(self.elements) - 1) { + total = total + element + } + return total + } elif (operation == "length") { + return sizeof(self.elements) + } elif (operation == "print") { + println("Vector:", self.elements) + return true + } else { + println("未知操作:", operation) + return false + } + } + + # 幂运算符重载(向量的模长) + "**"(self, power) { + if (power == 2) { + let sumSquares = 0 + for (element in 0, sizeof(self.elements) - 1) { + sumSquares = sumSquares + element * element + } + return sumSquares # 返回模长的平方 + } else { + println("只支持2次幂运算") + return 0 + } + } +} + +main { + let v1 = Vector([3, 4, 5]) + let v2 = Vector([2, 2, 2]) + + println('=== 特殊运算符重载演示 ===') + + # 测试索引访问重载 + println('v1[0] =', v1[0]) + println('v1[1] =', v1[1]) + println('v1[2] =', v1[2]) + println('v1[5] =', v1[5]) # 越界测试 + + # 测试函数调用重载 + v1("print") + println('向量和:', v1("sum")) + println('向量长度:', v1("length")) + println('未知操作:', v1("unknown")) + + # 测试幂运算重载 + println('向量模长平方:', v1 ** 2) +} +``` + +## 练习 + +### 练习 1:实现基本运算符重载 + +创建一个分数类,实现基本的算术运算符重载。 + +?> **练习要求** +实现一个 Fraction 类,支持分数的加、减、乘、除运算,以及约分功能。 + +
+点击查看答案 + +```losu +import std + +global class Fraction { + init(self, numerator, denominator) { + if (denominator == 0) { + println("错误:分母不能为0") + self.numerator = 0 + self.denominator = 1 + } else { + # 简化分数(求最大公约数) + let gcd = self.gcd(numerator, denominator) + self.numerator = numerator / gcd + self.denominator = denominator / gcd + + # 确保分母为正 + if (self.denominator < 0) { + self.numerator = -self.numerator + self.denominator = -self.denominator + } + } + } + + # 求最大公约数的辅助方法 + def gcd(self, a, b) { + a = a < 0 and -a or a # 取绝对值 + b = b < 0 and -b or b + while (b != 0) { + let temp = b + b = a % b + a = temp + } + return a + } + + # 加法重载 + "+"(self, other) { + if (typeof(other) == 'number') { + return Fraction(self.numerator + other * self.denominator, self.denominator) + } else { + let num = self.numerator * other.denominator + other.numerator * self.denominator + let den = self.denominator * other.denominator + return Fraction(num, den) + } + } + + # 减法重载 + "-"(self, other) { + if (other) { + # 二元减法 + if (typeof(other) == 'number') { + return Fraction(self.numerator - other * self.denominator, self.denominator) + } else { + let num = self.numerator * other.denominator - other.numerator * self.denominator + let den = self.denominator * other.denominator + return Fraction(num, den) + } + } else { + # 一元取负 + return Fraction(-self.numerator, self.denominator) + } + } + + # 乘法重载 + "*"(self, other) { + if (typeof(other) == 'number') { + return Fraction(self.numerator * other, self.denominator) + } else { + return Fraction(self.numerator * other.numerator, self.denominator * other.denominator) + } + } + + # 除法重载 + "/"(self, other) { + if (typeof(other) == 'number') { + if (other != 0) { + return Fraction(self.numerator, self.denominator * other) + } else { + println("错误:除零") + return self + } + } else { + if (other.numerator != 0) { + return Fraction(self.numerator * other.denominator, self.denominator * other.numerator) + } else { + println("错误:除零分数") + return self + } + } + } + + # 函数调用重载 + "()"(self, operation) { + if (operation == "decimal") { + return self.numerator / self.denominator + } elif (operation == "print") { + if (self.denominator == 1) { + println(str(self.numerator)) + } else { + println(str(self.numerator) & "/" & str(self.denominator)) + } + return true + } elif (operation == "reciprocal") { + if (self.numerator != 0) { + return Fraction(self.denominator, self.numerator) + } else { + println("错误:零没有倒数") + return self + } + } else { + println("未知分数操作:", operation) + return false + } + } + + # 字符串表示 + def toString(self) { + if (self.denominator == 1) { + return str(self.numerator) + } else { + return str(self.numerator) & "/" & str(self.denominator) + } + } +} + +main { + let f1 = Fraction(3, 4) + let f2 = Fraction(2, 3) + let f3 = Fraction(6, 8) # 应该简化为 3/4 + + println('=== 分数运算符重载演示 ===') + + println('f1 =', f1.toString()) + println('f2 =', f2.toString()) + println('f3 =', f3.toString(), '(自动简化)') + + # 测试加法 + let f4 = f1 + f2 + println('f1 + f2 =', f4.toString()) + + # 测试减法 + let f5 = f1 - f2 + println('f1 - f2 =', f5.toString()) + + # 测试乘法 + let f6 = f1 * f2 + println('f1 * f2 =', f6.toString()) + + # 测试除法 + let f7 = f1 / f2 + println('f1 / f2 =', f7.toString()) + + # 测试与整数运算 + let f8 = f1 + 2 + println('f1 + 2 =', f8.toString()) + + let f9 = f1 * 3 + println('f1 * 3 =', f9.toString()) + + # 测试特殊操作 + println('f1 的小数值:', f1("decimal")) + let f10 = f1("reciprocal") + println('f1 的倒数:', f10.toString()) + + # 测试一元取负 + let f11 = -f1 + println('-f1 =', f11.toString()) +} +``` + +
+ +--- + +**上一章**:[类变体基本用法 ←](基本用法.md) +**下一章**:[类变体继承 →](继承.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\346\225\260\345\200\274\347\261\273\345\236\213.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\346\225\260\345\200\274\347\261\273\345\236\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..ca82759d9b88917e707dab1a04b3dfe98d9a7900 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\346\225\260\345\200\274\347\261\273\345\236\213.md" @@ -0,0 +1,366 @@ +# 数值类型 + +洛书语言使用统一的 `number` 类型来表示所有数值,包括整数和浮点数。这种设计简化了数值处理,同时提供了灵活的类型注释来区分不同的数值子类型。 + +## 数值类型概述 + +洛书的数值类型具有以下特点: + +1. **统一类型**:所有数值都是 `number` 类型 +2. **动态精度**:根据值的特点自动选择合适的内部表示 +3. **类型注释**:可以使用 `number` 和 `number` 进行精确注释 +4. **自动转换**:整数和浮点数之间可以自动转换 +5. **多进制支持**:支持十进制、十六进制、二进制、八进制字面量 + +### 基本数值字面量 + +```losu +import std + +main { + # 整数字面量 + let integer = 42 + let negative = -17 + let zero = 0 + + # 浮点数字面量 + let decimal = 3.14159 + let scientific = 1.23e-4 + let negativeFloat = -2.718 + + println('整数:', integer, negative, zero) + println('浮点数:', decimal, scientific, negativeFloat) + println('类型检查:', typeof(integer), typeof(decimal)) +} +``` + +### 多进制数值字面量 + +洛书支持多种进制的数值字面量,方便在不同场景下使用: + +```losu +import std + +main { + # 十进制(默认) + let decimal = 42 + + # 十六进制(0x前缀) + let hexadecimal = 0x2A + + # 二进制(0b前缀) + let binary = 0b101010 + + # 八进制(0o前缀) + let octal = 0o52 + + println('十进制:', decimal) + println('十六进制:', hexadecimal) + println('二进制:', binary) + println('八进制:', octal) + + # 验证它们都表示相同的值 + println('都等于42:', decimal == hexadecimal and hexadecimal == binary and binary == octal) +} +``` + +## 数值子类型注释 + +虽然洛书内部使用统一的 `number` 类型,但可以通过类型注释来表达更精确的意图: + +### 整数类型注释 + +```losu +import std + +main { + # 整数类型注释 + let count: `number` = 100 + let age: `number` = 25 + let temperature: `number` = -5 + + println('计数:', count) + println('年龄:', age) + println('温度:', temperature) + + # 类型检查 + println('count 类型:', typeof(count)) +} +``` + +### 浮点数类型注释 + +```losu +import std + +main { + # 浮点数类型注释 + let pi: `number` = 3.14159 + let rate: `number` = 0.05 + let precision: `number` = 1e-10 + + println('圆周率:', pi) + println('利率:', rate) + println('精度:', precision) + + # 类型检查 + println('pi 类型:', typeof(pi)) +} +``` + +## 算术运算 + +洛书支持完整的算术运算符集合: + +### 基本算术运算 + +```losu +import std + +main { + let a = 15 + let b = 4 + + println('=== 基本算术运算 ===') + println('a =', a, ', b =', b) + println('加法: a + b =', a + b) # 19 + println('减法: a - b =', a - b) # 11 + println('乘法: a * b =', a * b) # 60 + println('除法: a / b =', a / b) # 3.75 + println('取模: a % b =', a % b) # 3 + println('幂运算: a ** b =', a ** b) # 50625 +} +``` + +### 混合运算 + +整数和浮点数可以混合运算,结果类型根据操作数自动确定: + +```losu +import std + +main { + let intValue = 10 + let floatValue = 3.5 + + println('=== 混合运算 ===') + println('整数:', intValue, '浮点数:', floatValue) + println('整数 + 浮点数 =', intValue + floatValue) # 13.5 + println('整数 * 浮点数 =', intValue * floatValue) # 35.0 + println('整数 / 浮点数 =', intValue / floatValue) # 2.857... +} +``` + +## 数值比较 + +数值类型支持完整的比较运算: + +```losu +import std + +main { + let x = 10 + let y = 20 + let z = 10.0 + + println('=== 数值比较 ===') + println('x =', x, ', y =', y, ', z =', z) + println('x == y:', x == y) # false + println('x == z:', x == z) # true (整数与浮点数比较) + println('x != y:', x != y) # true + println('x < y:', x < y) # true + println('x <= z:', x <= z) # true + println('y > x:', y > x) # true + println('y >= x:', y >= x) # true +} +``` + +## 数学函数 + +洛书标准库提供了丰富的数学函数(需要导入数学模块): + +```losu +import std + +main { + let angle = 1.57 # 约等于 π/2 + let number = 16 + + println('=== 数学运算示例 ===') + println('角度:', angle) + println('数字:', number) + + # 基本数学运算 + println('绝对值 abs(-5):', abs(-5)) + println('最大值 max(10, 20):', max(10, 20)) + println('最小值 min(10, 20):', min(10, 20)) + + # 幂和根运算 + println('平方根 sqrt(16):', sqrt(number)) + println('立方根 cbrt(8):', cbrt(8)) +} +``` + +## 数值转换 + +洛书提供了显式的数值转换函数: + +```losu +import std + +main { + # 字符串转数值 + let strNumber = '123' + let strFloat = '3.14' + + let intFromStr = int(strNumber) + let floatFromStr = float(strFloat) + + println('=== 数值转换 ===') + println('字符串转整数:', strNumber, '->', intFromStr) + println('字符串转浮点数:', strFloat, '->', floatFromStr) + + # 数值转字符串 + let numValue = 42 + let floatValue = 3.14159 + + println('数值转字符串:', numValue, '->', str(numValue)) + println('浮点数转字符串:', floatValue, '->', str(floatValue)) +} +``` +> [!WARNING] +> 洛书语言在数值运算中不允许将0作为除数,否则会报错。只有当 `/` 运算符被重载时,0才有可能被作为除数。 + +## 数值精度 + +在进行浮点数运算时需要注意精度问题: + +```losu +import std +import math + +main { + # 浮点数精度示例 + let a = 0.1 + let b = 0.2 + let sum = a + b + + println('=== 浮点数精度 ===') + println('0.1 + 0.2 =', sum) + println('是否等于 0.3:', sum == 0.3) + + # 精度比较的正确方法 + let epsilon = 1e-10 + let difference = abs(sum - 0.3) + println('差值:', difference) + println('在精度范围内相等:', difference < epsilon) +} +``` + +## 练习 + +### 练习 1:多进制数值和基本运算 + +编写程序演示多进制数值字面量和基本运算。 + +?> **练习要求** +创建程序使用不同进制的数值字面量,并进行基本的算术运算。 + +
+点击查看答案 + +```losu +import std + +main { + # 使用不同进制表示相同的数值 + let decimal = 42 + let hex = 0x2A + let binary = 0b101010 + let octal = 0o52 + + println('=== 多进制数值演示 ===') + println('十进制:', decimal) + println('十六进制:', hex) + println('二进制:', binary) + println('八进制:', octal) + + # 验证它们相等 + println('都等于42:', decimal == hex and hex == binary and binary == octal) + + # 基本运算 + let sum = decimal + hex + let product = binary * 2 + let quotient = octal / 2 + + println('加法运算:', decimal, '+', hex, '=', sum) + println('乘法运算:', binary, '* 2 =', product) + println('除法运算:', octal, '/ 2 =', quotient) + + # 类型检查 + println('所有数值的类型都是:', typeof(decimal)) +} +``` + +
+ +### 练习 2:数值转换和精度处理 + +创建程序演示数值转换和浮点数精度处理。 + +?> **练习要求** +实现字符串与数值的相互转换,并处理浮点数精度问题。 + +
+点击查看答案 + +```losu +import std +import math + +main { + # 字符串转数值 + let intStr = '123' + let floatStr = '3.14159' + let hexStr = '0xFF' # 注意:可能需要特殊处理 + + let intValue = int(intStr) + let floatValue = float(floatStr) + + println('=== 数值转换演示 ===') + println('字符串转整数:', intStr, '->', intValue) + println('字符串转浮点数:', floatStr, '->', floatValue) + + # 数值转字符串 + let num = 42.5 + let numStr = str(num) + println('数值转字符串:', num, '->', numStr) + + # 浮点数精度问题 + let a = 0.1 + let b = 0.2 + let sum = a + b + + println('=== 浮点数精度演示 ===') + println('0.1 + 0.2 =', sum) + println('是否等于0.3:', sum == 0.3) + + # 精度比较的正确方法 + let epsilon = 1e-10 + let difference = abs(sum - 0.3) + println('与0.3的差值:', difference) + println('在精度范围内相等:', difference < epsilon) + + # 数学运算 + let base = 2 + let exponent = 8 + let power = base ** exponent + println('幂运算:', base, '**', exponent, '=', power) +} +``` + +
+ +--- + +**上一章**:[← 逻辑类型](逻辑类型.md) | **下一章**:[字符串类型 →](字符串类型.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\347\211\271\346\256\212\347\261\273\345\236\213.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\347\211\271\346\256\212\347\261\273\345\236\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..aee15a7b1b8b56cd2b0d6ad586f3ea298427083e --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\347\211\271\346\256\212\347\261\273\345\236\213.md" @@ -0,0 +1,55 @@ +# 特殊类型 + +在洛书语言的类型系统中,除了常规的基础类型和容器类型外,还存在一种特殊的类型——**指针类型**(pointer)。这种类型的设计体现了洛书语言既保持高级语言简洁性,又不失底层交互能力的设计理念。 + +## 指针的本质与设计哲学 + +指针是一种指向内存中特定位置的特殊数据类型。在传统的系统编程语言中,指针往往是复杂性和错误的重要源头。洛书语言采用了一种独特的设计策略:**将指针的复杂性封装在语言内核之外,为脚本开发者提供安全、简洁的接口**。 + +### 洛书指针的特性 + +1. **脚本层面的只读性**:在洛书脚本中,指针变量是完全只读的,开发者无法通过任何语法直接创建或修改指针 +2. **内核外部创建**:所有指针变量都由 API 函数在洛书内核外部创建,然后以对象形式传递给内核 +3. **透明的内存管理**:指针的生命周期和内存管理完全由洛书运行时自动处理 + +## 指针的自动性管理 + +洛书语言的指针设计核心在于**自动性**——开发者无需关心指针的创建、管理和销毁过程。这种自动性体现在以下几个方面: + +### 自动创建 + +```losu +# 指针变量通过 API 函数自动创建 +# 开发者只需接收,无需手动分配内存 +let dataPointer = someApiFunction() # API 函数返回指针对象 +``` + +### 自动管理 + +洛书运行时自动跟踪指针的使用情况,确保: + +- **内存安全**:防止野指针和内存泄漏 +- **类型安全**:确保指针指向的数据类型正确 +- **生命周期管理**:自动处理指针的创建和销毁 + +### 自动释放 + +当指针变量离开作用域或不再被引用时,洛书运行时会自动: + +- 清理相关的内存资源 +- 断开与外部 API 的连接 +- 确保没有内存泄漏 + +## 指针类型检查 + +在洛书中,可以通过类型检查函数 `typeof()` 识别指针类型。 + +--- + +洛书的指针类型设计展示了如何在保持语言简洁性的同时,不失去与底层系统交互的能力。这种"**自动而透明**"的设计理念,让洛书既适合初学者快速上手,也能满足高级开发者的复杂需求。 + +通过将指针的复杂性封装在语言边界之外,洛书实现了"**简单的事情简单做,复杂的事情也能做**"的设计目标,为开发者提供了一个既安全又强大的编程环境。 + +--- + +**上一章**:[函数类型 ←](函数类型.md) | **下一章**:[容器类型 →](容器类型/基本容器.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\347\261\273\345\236\213\346\263\250\351\207\212.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\347\261\273\345\236\213\346\263\250\351\207\212.md" new file mode 100644 index 0000000000000000000000000000000000000000..f902999ffe11bcbcb17419a968192fe314985839 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\347\261\273\345\236\213\346\263\250\351\207\212.md" @@ -0,0 +1,383 @@ +# 类型注释 + +洛书语言提供了强大而灵活的类型注释系统。虽然洛书是动态类型语言,但类型注释可以提供编译时检查、代码文档和IDE支持,帮助开发者编写更安全、更清晰的代码。 + +## 类型注释语法 + +洛书的类型注释使用反引号(`)包围类型信息,这种设计使得类型信息与代码逻辑清晰分离: + +```losu +import std + +# 基本语法:变量名: `类型` = 值 +let name: `string` = 'Alice' +let age: `number` = 25 +let isActive: `true | false` = true + +main { + println('姓名:', name) + println('年龄:', age) + println('状态:', isActive) +} +``` + +### 类型注释的位置 + +类型注释可以出现在多个位置: + +```losu +import std + +# 变量声明时的类型注释 +let userName: `string` = '洛书用户' +global let MAX_COUNT: `number` = 100 + +# 函数参数和返回值的类型注释 +def greet(name: `string`): `string` { + return '你好, ' & name & '!' +} + +main { + let message = greet(userName) + println(message) +} +``` + +## 基本类型注释 + +洛书支持以下基本类型的注释: + +### 逻辑类型注释 + +```losu +import std + +main { + # 精确的逻辑类型注释 + let alwaysTrue: `true` = true # 只能是 true + let alwaysFalse: `false` = false # 只能是 false + let boolValue: `true | false` = true # 可以是 true 或 false + + println('逻辑类型演示:') + println('总是真:', alwaysTrue) + println('总是假:', alwaysFalse) + println('布尔值:', boolValue) +} +``` + +### 数值类型注释 + +```losu +import std + +main { + # 通用数值类型 + let basicNumber: `number` = 42 + let decimal: `number` = 3.14 + + # 精确的数值子类型 + let intValue: `number` = 100 + let floatValue: `number` = 2.718 + + println('数值类型演示:') + println('基本数字:', basicNumber) + println('小数:', decimal) + println('整数:', intValue) + println('浮点数:', floatValue) +} +``` + +### 字符串类型注释 + +```losu +import std + +main { + # 字符串类型注释 + let message: `string` = '洛书语言' + let emptyString: `string` = '' + + println('字符串类型演示:') + println('消息:', message) + println('空字符串长度:', sizeof(emptyString)) +} +``` + +## 函数类型注释 + +函数类型注释是洛书类型系统的重要组成部分,用于描述函数的参数类型和返回值类型。 + +### 基本函数注释 + +```losu +import std + +# 带有完整类型注释的函数 +def add(a: `number`, b: `number`): `number` { + return a + b +} + +def formatName(firstName: `string`, lastName: `string`): `string` { + return firstName & ' ' & lastName +} + +def isPositive(num: `number`): `true | false` { + return num > 0 +} + +main { + println('加法结果:', add(10, 20)) + println('格式化姓名:', formatName('张', '三')) + println('是否为正数:', isPositive(-5)) +} +``` + +### Lambda 函数类型注释 + +```losu +import std + +main { + # Lambda 函数的类型注释 + let double: `(number) -> number` = { + (x) { + return x * 2 + } + } + + let concat: `(string, string) -> string` = { + (a, b) { + return a & b + } + } + + println('翻倍函数:', double(5)) + println('拼接函数:', concat('Hello', ' World')) +} +``` + +## 容器类型注释 + +容器类型注释用于描述数组、对象等复合数据结构。 + +### 数组类型注释 + +```losu +import std + +main { + # 基本数组类型 + let numbers: `array` = [1, 2, 3, 4, 5] + + # 带泛型的数组类型 + let strings: `array` = ['apple', 'banana', 'cherry'] + let integers: `array>` = [10, 20, 30] + + println('数组演示:') + println('数字数组:', numbers) + println('字符串数组:', strings) + println('整数数组:', integers) +} +``` + +### 对象类型注释 + +```losu +import std + +main { + # 基本对象类型 + let person: `object` = { + name: '张三', + age: 25, + city: '北京' + } + + # 单元类型(通用容器) + let config: `unit` = { + appName: '洛书应用', + version: 1.0, + debug: true + } + + println('对象演示:') + println('人员信息:', person.name, person.age) + println('配置信息:', config.appName, config.version) +} +``` + +## 联合类型 + +联合类型允许变量具有多种可能的类型,使用 `|` 符号分隔: + +```losu +import std + +# 联合类型函数 +def processValue(value: `string | number`) { + if (typeof(value) == 'string') { + println('处理字符串:', value) + } elif (typeof(value) == 'number') { + println('处理数字:', value) + } +} + +# 可选返回值 +def findItem(id: `number`): `object | false` { + if (id == 1) { + return {name: '项目1', value: 100} + } else { + return false + } +} + +main { + # 测试联合类型 + processValue('洛书') + processValue(42) + + let item = findItem(1) + if (item != false) { + println('找到项目:', item.name) + } else { + println('项目不存在') + } +} +``` + +## 可选参数和默认值 + +函数参数可以有默认值,配合类型注释使用: + +```losu +import std + +def createUser( + name: `string`, + age: `number` = 18, + active: `true | false` = true +): `object` { + return { + name: name, + age: age, + active: active + } +} + +def greet( + name: `string`, + prefix: `string` = '你好' +): `string` { + return prefix & ', ' & name & '!' +} + +main { + # 使用默认参数 + let user1 = createUser('Alice') + let user2 = createUser('Bob', 25, false) + + println('用户1:', user1.name, user1.age, user1.active) + println('用户2:', user2.name, user2.age, user2.active) + + println(greet('洛书')) + println(greet('世界', '欢迎')) +} +``` + +## 类型注释的作用 + +类型注释在洛书中发挥多重作用: + +1. **编译时检查** - 在代码解析时发现类型错误 +2. **代码文档** - 清晰表达变量和函数的预期类型 +3. **IDE支持** - 提供更好的代码补全和错误提示 +4. **团队协作** - 统一团队对数据结构的理解 + +> [!IMPORTANT] +> 类型注释是可选的,但强烈建议在复杂项目中使用,特别是公共API和关键函数。 + +> [!TIP] +> 合理使用类型注释可以显著提高代码的可读性和维护性,同时减少运行时错误。 + +## 练习 + +### 练习 1:基本类型注释 + +为变量添加合适的类型注释。 + +
+查看答案 + +```losu +import std + +main { + # 基本类型注释 + let studentName: `string` = '李明' + let studentAge: `number` = 20 + let isGraduated: `true | false` = false + let gpa: `number` = 3.75 + + println('=== 学生信息 ===') + println('姓名:', studentName) + println('年龄:', studentAge) + println('已毕业:', isGraduated) + println('GPA:', gpa) +} +``` + +
+ +### 练习 2:函数类型注释 + +编写带有完整类型注释的计算函数。 + +
+查看答案 + +```losu +import std + +# 计算圆面积 +def calculateCircleArea(radius: `number`): `number` { + return 3.14159 * radius * radius +} + +# 检查成绩等级 +def getGrade(score: `number`): `string` { + if (score >= 90) { + return 'A' + } elif (score >= 80) { + return 'B' + } elif (score >= 70) { + return 'C' + } elif (score >= 60) { + return 'D' + } else { + return 'F' + } +} + +# 格式化用户信息 +def formatUser( + name: `string`, + age: `number`, + title: `string` = '用户' +): `string` { + return title & ': ' & name & ' (' & age & '岁)' +} + +main { + println('=== 函数类型注释演示 ===') + println('圆面积:', calculateCircleArea(5)) + println('成绩等级:', getGrade(85)) + println(formatUser('王五', 28)) + println(formatUser('赵六', 35, '管理员')) +} +``` + +
+ +--- + +**上一章**:[← 数据类型概览](README.md) | **下一章**:[逻辑类型 →](逻辑类型.md) \ No newline at end of file diff --git "a/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\351\200\273\350\276\221\347\261\273\345\236\213.md" "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\351\200\273\350\276\221\347\261\273\345\236\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..d0781ca6a2c25e2057b887f491d9547093930237 --- /dev/null +++ "b/grammars/2-\346\225\260\346\215\256\347\261\273\345\236\213/\351\200\273\350\276\221\347\261\273\345\236\213.md" @@ -0,0 +1,252 @@ +# 逻辑类型 + +洛书语言的逻辑类型包括 `true` 和 `false` 两个值。与其他语言不同,洛书将 `true` 和 `false` 视为独立的类型,而不是同一个布尔类型的两个值。这种设计提供了更精确的类型控制。 + +## 逻辑值的类型 + +洛书的逻辑类型设计独特,`true` 和 `false` 是两个不同的类型: + +```losu +import std + +main { + let isTrue = true + let isFalse = false + + println('true 的类型:', typeof(isTrue)) # true + println('false 的类型:', typeof(isFalse)) # false + println('类型是否相同:', typeof(isTrue) == typeof(isFalse)) # false +} +``` + +### 精确的类型注释 + +可以为逻辑值指定精确的类型注释: + +```losu +import std + +main { + # 精确的逻辑类型注释 + let alwaysTrue: `true` = true # 只能是 true + let alwaysFalse: `false` = false # 只能是 false + let boolValue: `true | false` = true # 可以是 true 或 false + + println('逻辑类型演示:') + println('总是真:', alwaysTrue) + println('总是假:', alwaysFalse) + println('布尔值:', boolValue) +} +``` + +## 逻辑运算符 + +洛书支持三种基本的逻辑运算符:`and`、`or` 和 `not`。 + +### 逻辑与 (and) + +逻辑与运算符 `and` 只有当两个操作数都为真时才返回真: + +```losu +import std + +main { + println('=== 逻辑与运算 ===') + println('true and true:', true and true) # true + println('true and false:', true and false) # false + println('false and true:', false and true) # false + println('false and false:', false and false) # false + + # 实际应用示例 + let age = 20 + let hasLicense = true + let canDrive = age >= 18 and hasLicense + + println('年龄:', age, '有驾照:', hasLicense) + println('可以开车:', canDrive) +} +``` + +### 逻辑或 (or) + +逻辑或运算符 `or` 只要有一个操作数为真就返回真: + +```losu +import std + +main { + println('=== 逻辑或运算 ===') + println('true or true:', true or true) # true + println('true or false:', true or false) # true + println('false or true:', false or true) # true + println('false or false:', false or false) # false + + # 实际应用示例 + let isWeekend = false + let isHoliday = true + let canRest = isWeekend or isHoliday + + println('是周末:', isWeekend, '是假日:', isHoliday) + println('可以休息:', canRest) +} +``` + +### 逻辑非 (not) + +逻辑非运算符 `not` 将真值变为假值,假值变为真值: + +```losu +import std + +main { + println('=== 逻辑非运算 ===') + println('not true:', not true) # false + println('not false:', not false) # true + + # 实际应用示例 + let isLoggedIn = false + let needLogin = not isLoggedIn + + println('已登录:', isLoggedIn) + println('需要登录:', needLogin) +} +``` + +## 短路求值 + +洛书的逻辑运算符支持短路求值,洛书使用 and 和 or 结合来进行短路求值: + +```losu +import std + +main { + println('=== 短路求值演示 ===') + + let a = 1 + let b = 2 + let c = a > b and b or a # c取a和b之间的较小值 + println('c:', c) # 1 +} +``` + +## 真值判断 + +在洛书中,以下值被视为假值,其他所有值都被视为真值: + +- `false` +- `0`(数值零) +- `''`(空字符串) +- `[]`(空数组) +- `{}`(空对象) + +```losu +import std + +main { + println('=== 真值判断 ===') + + # 测试各种值的真假性 + let values = [true, false, 1, 0, 'hello', '', [1, 2], []] + + for (value, v in values) { + if (value) { + println(value, '是真值') + } else { + println(value, '是假值') + } + } +} +``` + +## 复合逻辑表达式 + +可以组合多个逻辑运算符创建复杂的条件: + +```losu +import std + +main { + let age = 25 + let hasExperience = true + let hasLicense = true + let hasRecommendation = false + + # 复合逻辑条件 + let isQualified = (age >= 18 and hasLicense) and + (hasExperience or hasRecommendation) + + println('=== 资格检查 ===') + println('年龄:', age) + println('有驾照:', hasLicense) + println('有经验:', hasExperience) + println('有推荐:', hasRecommendation) + println('符合资格:', isQualified) +} +``` + +## 运算符优先级 + +逻辑运算符的优先级从高到低为:`not` > `and` > `or` + +```losu +import std + +main { + println('=== 运算符优先级 ===') + + # 演示运算符优先级 + let result1 = true or false and false # true or (false and false) = true + let result2 = not false or false # (not false) or false = true + let result3 = true and false or true # (true and false) or true = true + + println('true or false and false =', result1) + println('not false or false =', result2) + println('true and false or true =', result3) + + # 使用括号改变优先级 + let result4 = (true or false) and false # (true or false) and false = false + println('(true or false) and false =', result4) +} +``` + +## 练习 + +### 练习 1:逻辑运算真值表 + +编写程序展示所有逻辑运算的真值表。 + +
+查看答案 + +```losu +import std + +main { + println('=== 逻辑运算真值表 ===') + + # AND 运算真值表 + println('AND 运算:') + println('true and true =', true and true) + println('true and false =', true and false) + println('false and true =', false and true) + println('false and false =', false and false) + + # OR 运算真值表 + println('\nOR 运算:') + println('true or true =', true or true) + println('true or false =', true or false) + println('false or true =', false or true) + println('false or false =', false or false) + + # NOT 运算 + println('\nNOT 运算:') + println('not true =', not true) + println('not false =', not false) +} +``` + +
+ +--- + +**上一章**:[← 类型注释](类型注释.md) | **下一章**:[数值类型 →](数值类型.md) \ No newline at end of file diff --git "a/grammars/3-\350\257\255\345\217\245/README.md" "b/grammars/3-\350\257\255\345\217\245/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..f2b1061f28221cfbffa7bfc8f380d77fcff92365 --- /dev/null +++ "b/grammars/3-\350\257\255\345\217\245/README.md" @@ -0,0 +1,218 @@ +# 语句 + +语句是洛书程序的基本执行单元,用于控制程序的执行流程。洛书提供了丰富的语句类型,包括分支语句和循环语句,支持复杂的程序逻辑控制。 + +## 本章内容 + +### 分支语句 +控制程序的条件执行: + +#### [if 语句](分支/if.md) +条件分支控制,包括: +- 基本 if 语句 +- if-elif-else 结构 +- 嵌套条件判断 +- 条件表达式 + +#### [match 语句](分支/match.md) +模式匹配控制,包括: +- 基本 match 语法 +- 模式匹配规则 +- 多值匹配 +- 默认分支处理 + +### 循环语句 +控制程序的重复执行: + +#### [while 循环](循环/while.md) +条件循环控制,包括: +- 基本 while 语法 +- 循环条件设计 +- break 和 continue +- 无限循环处理 + +#### [for 区间循环](循环/for-range.md) +数值区间遍历,包括: +- 基本区间语法 +- 步长控制 +- 逆序遍历 +- 嵌套区间循环 + +#### [for 容器循环](循环/for-container.md) +容器元素遍历,包括: +- 数组遍历 +- 对象遍历 +- 键值对遍历 +- 复杂容器遍历 + +## 语句概述 + +洛书的语句系统设计简洁而强大,支持现代编程语言的所有基本控制结构。 + +### 语句分类 + +1. **分支语句**:根据条件选择执行路径 + - `if` - 条件判断 + - `match` - 模式匹配 + +2. **循环语句**:重复执行代码块 + - `while` - 条件循环 + - `for` - 遍历循环 + +3. **控制语句**:改变执行流程 + - `break` - 跳出循环 + - `continue` - 继续下次循环 + - `return` - 函数返回 + +### 语句语法特点 + +洛书的语句语法具有以下特点: + +1. **条件表达式**:使用括号包围条件表达式 +2. **代码块**:使用大括号定义代码块 +3. **简洁语法**:避免冗余的关键字 +4. **一致性**:所有语句遵循相似的语法模式 + +```losu +import std + +main { + let score = 85 + + # 分支语句示例 + if (score >= 90) { + println('优秀') + } elif (score >= 80) { + println('良好') + } else { + println('及格') + } + + # 循环语句示例 + for (i in 1, 6) { + println('计数:', i) + } + + let numbers = [1, 2, 3, 4, 5] + for (num in numbers) { + println('数字:', num) + } +} +``` + +## 控制流程 + +### 顺序执行 + +默认情况下,语句按照编写顺序依次执行: + +```losu +import std + +main { + println('第一步') + println('第二步') + println('第三步') +} +``` + +### 条件执行 + +使用分支语句根据条件选择执行路径: + +```losu +import std + +main { + let weather = '晴天' + + if (weather == '晴天') { + println('适合出门') + } else { + println('在家休息') + } +} +``` + +### 重复执行 + +使用循环语句重复执行代码: + +```losu +import std + +main { + # 重复打印 + for (i in 1, 4) { + println('重复执行第', i, '次') + } +} +``` + +## 语句嵌套 + +洛书支持语句的任意嵌套,可以构建复杂的控制逻辑: + +```losu +import std + +main { + let students = [ + {name: '张三', score: 95}, + {name: '李四', score: 82}, + {name: '王五', score: 76} + ] + + println('=== 成绩评定 ===') + + for (student in students) { + println('学生:', student.name) + + if (student.score >= 90) { + println('等级: 优秀') + } elif (student.score >= 80) { + println('等级: 良好') + } else { + println('等级: 及格') + } + + println('---') + } +} +``` + +## 最佳实践 + +### 代码可读性 + +1. **适当缩进**:保持一致的缩进风格 +2. **清晰条件**:使用有意义的条件表达式 +3. **避免深度嵌套**:过深的嵌套影响可读性 + +### 性能考虑 + +1. **循环优化**:避免在循环中进行重复计算 +2. **条件顺序**:将最可能的条件放在前面 +3. **提前退出**:使用 break 和 continue 优化循环 + +### 错误处理 + +1. **边界检查**:在访问数组或对象前检查边界 +2. **空值检查**:处理可能为空的值 +3. **异常情况**:为异常情况提供合适的处理 + +## 学习路径 + +建议按以下顺序学习语句: + +1. **if 语句** - 掌握基本的条件控制 +2. **while 循环** - 理解循环的基本概念 +3. **for 循环** - 学习遍历和区间操作 +4. **match 语句** - 掌握模式匹配 +5. **综合应用** - 结合多种语句解决实际问题 + +每种语句都有其适用场景,通过大量练习可以培养选择合适语句的直觉。 + +--- + +**开始学习**:[if 语句 →](分支/if.md) \ No newline at end of file diff --git "a/grammars/3-\350\257\255\345\217\245/\345\210\206\346\224\257/if.md" "b/grammars/3-\350\257\255\345\217\245/\345\210\206\346\224\257/if.md" new file mode 100644 index 0000000000000000000000000000000000000000..b849002d981162e0a04e7a3a2341b3d881116b18 --- /dev/null +++ "b/grammars/3-\350\257\255\345\217\245/\345\210\206\346\224\257/if.md" @@ -0,0 +1,269 @@ +# if 分支语句 + +if 分支语句是洛书语言中用于条件判断和分支执行的控制结构。它允许程序根据不同的条件执行不同的代码块。 + +## 基本语法 + +洛书的 if 语句支持以下几种形式: + +```losu +# 基本if语句 +if (条件) { + # 代码块 +} + +# if-else语句 +if (条件) { + # 条件为真时执行 +} else { + # 条件为假时执行 +} + +# if-elif-else语句 +if (条件1) { + # 条件1为真时执行 +} elif (条件2) { + # 条件2为真时执行 +} else { + # 所有条件都为假时执行 +} +``` + +> [!IMPORTANT] +> 洛书使用 `elif` 而不是 `else if` 来表示多重条件判断。 + +## 基本示例 + +```losu +import std + +main { + let score = 85 + + println('学生分数:', score) + + if (score >= 90) { + println('等级: 优秀') + } elif (score >= 80) { + println('等级: 良好') + } elif (score >= 60) { + println('等级: 及格') + } else { + println('等级: 不及格') + } +} +``` + +## 条件表达式 + +### 比较运算符 + +```losu +import std + +main { + let a = 10 + let b = 20 + + println('a =', a, ', b =', b) + + if (a == b) { + println('a 等于 b') + } + + if (a != b) { + println('a 不等于 b') + } + + if (a < b) { + println('a 小于 b') + } + + if (a <= b) { + println('a 小于等于 b') + } +} +``` + +### 逻辑运算符 + +```losu +import std + +main { + let age = 25 + let hasLicense = true + let hasExperience = false + + println('年龄:', age) + println('有驾照:', hasLicense) + println('有经验:', hasExperience) + + # and 运算符 + if (age >= 18 and hasLicense) { + println('可以开车') + } + + # or 运算符 + if (hasLicense or hasExperience) { + println('具备驾驶条件之一') + } + + # not 运算符 + if (not hasExperience) { + println('需要培训') + } +} +``` + +## 嵌套if语句 + +```losu +import std + +main { + let weather = 'sunny' + let temperature = 25 + + println('天气:', weather) + println('温度:', temperature) + + if (weather == 'sunny') { + println('天气晴朗') + + if (temperature > 30) { + println('建议: 注意防晒') + } elif (temperature > 20) { + println('建议: 适合外出') + } else { + println('建议: 添加衣物') + } + } else { + println('天气不佳') + + if (weather == 'rainy') { + println('建议: 带伞出行') + } + } +} +``` + +## 条件表达式 + +在洛书中,if语句也可以通过表达式替换: + +```losu +import std + +main { + let score = 92 + + # 使用条件表达式 + let grade = score >= 90 and '优秀' or score >= 80 and '良好' or '一般' + + println('分数:', score) + println('等级:', grade) + + let status = score >= 60 and '及格' or '不及格' + println('状态:', status) +} +``` + +## 类型检查 + +```losu +import std + +main { + let value1 = 42 + let value2 = 'hello' + let value3 = true + let value4 = [1, 2, 3] + + # 检查不同类型 + if (typeof(value1) == 'number') { + println(value1, '是数字') + } + + if (typeof(value2) == 'string') { + println(value2, '是字符串') + } + + if (typeof(value3) == 'boolean') { + println(value3, '是布尔值') + } + + if (typeof(value4) == 'array') { + println(value4, '是数组') + } +} +``` + +## 练习 + +### 练习 1:数字分类 + +编写程序判断一个数字是正数、负数还是零。 + +
+查看答案 + +```losu +import std + +main { + let numbers = [5, -3, 0, 12, -8] + + println('=== 数字分类 ===') + + for (num in numbers) { + if (num > 0) { + println(num, '是正数') + } elif (num < 0) { + println(num, '是负数') + } else { + println(num, '是零') + } + } +} +``` + +
+ +### 练习 2:用户权限检查 + +根据用户角色和状态判断访问权限。 + +
+查看答案 + +```losu +import std + +main { + let user = { + name: '张三', + role: 'admin', + active: true, + loginCount: 5 + } + + println('用户:', user.name) + println('角色:', user.role) + println('状态:', user.active) + + if (not user.active) { + println('访问被拒绝: 账户已禁用') + } elif (user.role == 'admin') { + println('访问权限: 管理员权限') + } elif (user.role == 'user' and user.loginCount > 0) { + println('访问权限: 普通用户权限') + } else { + println('访问被拒绝: 权限不足') + } +} +``` + +
+ +**上一章**:[← 语句概述](../README.md) | **下一章**:[match语句 →](match.md) \ No newline at end of file diff --git "a/grammars/3-\350\257\255\345\217\245/\345\210\206\346\224\257/match.md" "b/grammars/3-\350\257\255\345\217\245/\345\210\206\346\224\257/match.md" new file mode 100644 index 0000000000000000000000000000000000000000..14339e417f512d0b7a34cf7fea488be99e0a5343 --- /dev/null +++ "b/grammars/3-\350\257\255\345\217\245/\345\210\206\346\224\257/match.md" @@ -0,0 +1,307 @@ +# match 分支语句 + +match 分支语句是洛书语言中用于模式匹配和多分支选择的控制结构。它提供了比 if-elif-else 更简洁和强大的分支处理方式,特别适合处理多个离散值的匹配。 + +> [!NOTE] +> match 语句可以匹配值、变量、表达式 + +## match 语句语法 + +洛书的 match 语句语法如下: + +```losu +match(表达式) { + case 值1: 语句1 + case 值2: 语句2 + case 值3: 语句3 + else: 默认语句 +} +``` + +> [!IMPORTANT] +> 注意:match 语句使用 `case` 关键字匹配具体值,使用 `else` 而不是 `default` 作为默认分支。 + +## 基本示例 + +### 数值匹配 + +```losu +import std + +main { + let day = 3 + + println('今天是星期', day) + + match(day) { + case 1: println('星期一 - 新的一周开始') + case 2: println('星期二 - 继续努力') + case 3: println('星期三 - 周中时光') + case 4: println('星期四 - 快到周末了') + case 5: println('星期五 - 感谢上帝是周五') + else: println('周末时光') + } +} +``` + +> [!WARNING] +> match 语句中的 case 后的代码不能有 `{}` 括号,只能直接写语句。 + +## 字符串匹配 + +```losu +import std + +main { + let command = 'start' + + println('执行命令:', command) + + match(command) { + case 'start': println('启动系统') + case 'stop': println('停止系统') + case 'restart': println('重启系统') + case 'status': println('查看状态') + else: println('未知命令') + } +} +``` + +## 成绩等级匹配 + +虽然 match 主要用于精确匹配,但可以结合条件表达式使用: + +```losu +import std + +main { + let score = 85 + let grade = '' + + # 使用条件表达式确定等级 + if (score >= 90) { + grade = 'A' + } elif (score >= 80) { + grade = 'B' + } elif (score >= 70) { + grade = 'C' + } elif (score >= 60) { + grade = 'D' + } else { + grade = 'F' + } + + println('分数:', score, '等级:', grade) + + # 使用 match 处理等级 + match(grade) { + case 'A': println('优秀!继续保持') + case 'B': println('良好,还有提升空间') + case 'C': println('一般,需要更加努力') + case 'D': println('及格,但需要改进') + case 'F': println('不及格,需要重修') + else: println('无效等级') + } +} +``` + +## 类型匹配 + +```losu +import std + +main { + let values = [42, 'hello', true, [1, 2, 3]] + + println('=== 类型匹配 ===') + + for (key, value in values) { + println('值:', value, '类型:', key) + + match(key) { + case 'number': println(' 这是一个数字') + case 'string': println(' 这是一个字符串') + case 'true': println(' 这是布尔值 true') + case 'false': println(' 这是布尔值 false') + case 'array': println(' 这是一个数组,长度:', sizeof(value)) + case 'unit': println(' 这是一个对象') + else: println(' 未知类型') + } + println('---') + } +} +``` + +## 嵌套 match 语句 + +match 语句可以嵌套使用,处理更复杂的逻辑: + +```losu +import std + +main { + let userType = 'admin' + let action = 'delete' + + println('用户类型:', userType, '操作:', action) + + match(userType) { + case 'admin': + println('管理员用户') + match(action) { + case 'read': println(' 允许: 读取数据') + case 'write': println(' 允许: 写入数据') + case 'delete': println(' 允许: 删除数据') + case 'config': println(' 允许: 修改配置') + else: println(' 拒绝: 未知操作') + } + case 'user': + println('普通用户') + match(action) { + case 'read': println(' 允许: 读取数据') + case 'write': println(' 允许: 写入数据') + case 'delete': println(' 拒绝: 无删除权限') + case 'config': println(' 拒绝: 无配置权限') + else: println(' 拒绝: 未知操作') + } + case 'guest': + println('访客用户') + match(action) { + case 'read': println(' 允许: 读取数据') + case 'write': println(' 拒绝: 无写入权限') + case 'delete': println(' 拒绝: 无删除权限') + case 'config': println(' 拒绝: 无配置权限') + else: println(' 拒绝: 未知操作') + } + else: + println('未知用户类型') + println(' 拒绝: 所有操作') + } +} +``` + +## 练习 + +### 练习 1:计算器操作 + +使用 match 语句实现简单的计算器操作选择。 + +?> **练习要求** +创建一个计算器程序,使用 match 语句处理不同的运算符。 + +
+点击查看答案 + +```losu +import std + +def calculate(a, b, operation) { + match(operation) { + case '+': return a + b + case '-': return a - b + case '*': return a * b + case '/': + if (b != 0) { + return a / b + } else { + return 'Error: Division by zero' + } + case '%': return a % b + case '**': return a ** b + else: return 'Error: Unknown operation' + } +} + +main { + let operations = ['+', '-', '*', '/', '%', '**', '?'] + let a = 10 + let b = 3 + + println('数字 a =', a, ', b =', b) + println('=== 计算器操作 ===') + + for (k, v in operations) { + let result = calculate(a, b, v) + println('操作:', a, v, b, '= ', result) + } +} +``` + +
+ +### 练习 2:HTTP状态码处理 + +根据HTTP状态码显示相应的消息和处理建议。 + +?> **练习要求** +创建一个HTTP状态码处理器,根据不同的状态码显示相应的消息和建议。 + +
+点击查看答案 + +```losu +import std + +def getStatusMessage(code) { + match(code) { + case 200: return '成功: 请求已成功处理' + case 201: return '已创建: 资源已成功创建' + case 301: return '永久重定向: 资源已永久移动' + case 302: return '临时重定向: 资源临时移动' + case 400: return '错误请求: 请求语法错误' + case 401: return '未授权: 需要身份验证' + case 403: return '禁止访问: 没有访问权限' + case 404: return '未找到: 请求的资源不存在' + case 500: return '服务器错误: 内部服务器错误' + case 502: return '网关错误: 无效的网关响应' + case 503: return '服务不可用: 服务器暂时过载' + else: return '未知状态码: ' & str(code) + } +} + +def getStatusCategory(code) { + if (code >= 200 and code < 300) { + return '成功' + } elif (code >= 300 and code < 400) { + return '重定向' + } elif (code >= 400 and code < 500) { + return '客户端错误' + } elif (code >= 500 and code < 600) { + return '服务器错误' + } else { + return '未知类别' + } +} + +main { + let statusCodes = [200, 201, 301, 400, 401, 403, 404, 500, 502, 503, 999] + + println('=== HTTP状态码处理器 ===') + + for (k, code in statusCodes) { + let message = getStatusMessage(code) + let category = getStatusCategory(code) + + println('状态码:', code) + println(' 类别:', category) + println(' 消息:', message) + + # 根据状态码类别给出建议 + match(category) { + case '成功': println(' 建议: 继续正常处理') + case '重定向': println(' 建议: 跟随重定向链接') + case '客户端错误': println(' 建议: 检查请求参数和权限') + case '服务器错误': println(' 建议: 稍后重试或联系管理员') + else: println(' 建议: 查阅相关文档') + } + println('---') + } +} +``` + +
+ +--- + +**上一章**:[if 语句 ←](if.md) +**下一章**:[循环语句 →](../循环/while.md) \ No newline at end of file diff --git "a/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/for-range.md" "b/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/for-range.md" new file mode 100644 index 0000000000000000000000000000000000000000..2e9699df6a203e7eb479c4465d54deddbdfe56bf --- /dev/null +++ "b/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/for-range.md" @@ -0,0 +1,191 @@ +# for 区间循环 + +for 区间循环是洛书语言中用于在指定数值范围内进行迭代的循环语句。它使用简洁的语法来遍历连续的整数序列,是处理计数循环的主要方式。 + +## 基本语法 + +洛书的 for 区间循环语法如下: + +```losu +for (变量名 in 起始值, 结束值) { + # 循环体代码 +} +``` + +> [!IMPORTANT] +> 区间循环是**包含结束值**的,即如果写 `for (i in 1, 5)`,会执行 i = 1, 2, 3, 4, 5 共5次循环。 + +## 基本示例 + +```losu +import std + +main { + println('=== 基本区间循环 ===') + + # 从1到5的循环 + for (i in 1, 5) { + println('当前数字:', i) + } + + println('循环结束') +} +``` + +## 常见用法 + +### 数组索引遍历 + +```losu +import std + +main { + let fruits = ['苹果', '香蕉', '橙子', '葡萄'] + + println('=== 数组索引遍历 ===') + println('水果列表:') + + # 注意:数组索引从0开始,所以是 0 到 sizeof(fruits)-1 + for (i in 0, sizeof(fruits) - 1) { + println('索引', i, ':', fruits[i]) + } +} +``` + +### 数学计算 + +```losu +import std + +main { + println('=== 计算1到10的和 ===') + + let sum = 0 + for (i in 1, 10) { + sum = sum + i + } + + println('1到10的和为:', sum) +} +``` + +### 嵌套循环 + +```losu +import std + +main { + println('=== 乘法表 ===') + + for (i in 1, 3) { + for (j in 1, 3) { + let result = i * j + println(i, '×', j, '=', result) + } + println('---') + } +} +``` + +## 循环控制 + +### break 语句 + +```losu +import std + +main { + println('=== 查找第一个大于15的平方数 ===') + + for (i in 1, 10) { + let square = i * i + println(i, '的平方是', square) + + if (square > 15) { + println('找到了!') + break + } + } +} +``` + +### continue 语句 + +```losu +import std + +main { + println('=== 打印1到10中的奇数 ===') + + for (i in 1, 10) { + if (i % 2 == 0) { + continue # 跳过偶数 + } + println('奇数:', i) + } +} +``` + +## 练习 + +### 练习 1:计算阶乘 + +编写程序计算5的阶乘(5! = 5 × 4 × 3 × 2 × 1)。 + +
+查看答案 + +```losu +import std + +main { + let n = 5 + let factorial = 1 + + println('计算', n, '的阶乘') + + for (i in 1, n) { + factorial = factorial * i + println('当前结果:', factorial) + } + + println(n, '! =', factorial) +} +``` + +
+ +### 练习 2:找出1到20中的质数 + +编写程序找出1到20之间的所有质数。 + +
+查看答案 + +```losu +import std + +main { + println('1到20中的质数:') + + for (num in 2, 20) { + let isPrime = true + + # 检查是否为质数 + for (i in 2, num - 1) { + if (num % i == 0) { + isPrime = false + break + } + } + + if (isPrime) { + println(num, '是质数') + } + } +} +``` + +
+ +**上一章**:[← while循环](while.md) | **下一章**:[for-unit循环 →](for-unit.md) \ No newline at end of file diff --git "a/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/for-unit.md" "b/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/for-unit.md" new file mode 100644 index 0000000000000000000000000000000000000000..26502dc51c5de62cef68108f0efcebf7a6dfcad0 --- /dev/null +++ "b/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/for-unit.md" @@ -0,0 +1,128 @@ +# for 容器循环 + +for 容器循环是洛书语言中用于遍历容器元素的循环语句。洛书只支持一种容器遍历语法:双变量遍历(获取键值对或索引值对)。 + +## 基本语法 + +```losu +# 双变量遍历(获取键值对或索引值对) +for (key, value in unit) { + # 循环体代码 +} +``` + +> [!IMPORTANT] +> 容器循环中的"容器"指的是洛书的 unit 类型,包括[容器类型](../../2-数据类型/README.md)中的所有类型。 + +## unit 对象遍历 + +unit 是洛书的基础容器类型,支持键值对遍历: + +### 键值对遍历 + +```losu +import std + +main { + let person = { + name: '张三', + age: 25, + city: '北京', + active: true + } + + println('=== unit 键值对遍历 ===') + for (key, value in person) { + println(key & ':', value) + } +} +``` + +## 数组遍历 + +数组也是 unit 类型的一种形式,支持索引值对遍历和纯值遍历: + +### 索引值对遍历 + +```losu +import std + +main { + let fruits = ['苹果', '香蕉', '橙子', '葡萄'] + + println('=== 数组索引值遍历 ===') + for (index, fruit in fruits) { + println('索引', index, ':', fruit) + } +} +``` + +## 练习 + +### 练习 1:统计字符出现次数 + +遍历一个字符数组,统计每个字符出现的次数。 + +
+查看答案 + +```losu +import std + +main { + let chars = ['a', 'b', 'a', 'c', 'b', 'a'] + let counts = {} + + println('=== 字符统计 ===') + + for (char in chars) { + if (counts[char]) { + counts[char] = counts[char] + 1 + } else { + counts[char] = 1 + } + } + + for (char, count in counts) { + println('字符', char, '出现', count, '次') + } +} +``` + +
+ +### 练习 2:查找最大值和最小值 + +在一个数字数组中找出最大值和最小值。 + +
+查看答案 + +```losu +import std + +main { + let numbers = [45, 23, 67, 12, 89, 34, 56] + let max = numbers[0] + let min = numbers[0] + + println('=== 查找最大值和最小值 ===') + println('原数组:', numbers) + + for (num in numbers) { + if (num > max) { + max = num + } + if (num < min) { + min = num + } + } + + println('最大值:', max) + println('最小值:', min) +} +``` + +
+ +**上一章**:[← for-unit循环](for-unit.md) | **下一章**:[并发编程 →](../../4-并发编程/README.md) \ No newline at end of file diff --git "a/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/while.md" "b/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/while.md" new file mode 100644 index 0000000000000000000000000000000000000000..a1b5b1c8177e59792e416cfabdc38df7c007040c --- /dev/null +++ "b/grammars/3-\350\257\255\345\217\245/\345\276\252\347\216\257/while.md" @@ -0,0 +1,231 @@ +# while 循环 + +while 循环是洛书语言中用于重复执行代码块的控制结构。它会在指定条件为真时持续执行循环体,直到条件变为假为止。 + +## 基本语法 + +洛书的 while 循环语法如下: + +```losu +while (条件表达式) { + # 循环体代码 +} +``` + +> [!IMPORTANT] +> while 循环会先检查条件,如果条件为假,循环体一次都不会执行。 + +## 基本示例 + +```losu +import std + +main { + println('=== 基本while循环 ===') + + let count = 1 + while (count <= 5) { + println('计数:', count) + count = count + 1 + } + + println('循环结束,最终count:', count) +} +``` + +## 常见用法 + +### 累加计算 + +```losu +import std + +main { + println('=== 计算1到10的和 ===') + + let sum = 0 + let i = 1 + + while (i <= 10) { + sum = sum + i + i = i + 1 + } + + println('1到10的和为:', sum) +} +``` + +### 条件查找 + +```losu +import std + +main { + let numbers = [2, 4, 7, 8, 12, 15] + let target = 8 + let index = 0 + let found = false + + println('=== 查找数字', target, '===') + + while (index < sizeof(numbers) and not found) { + if (numbers[index] == target) { + found = true + println('找到了!位置:', index) + } else { + println('检查位置', index, ':', numbers[index]) + index = index + 1 + } + } + + if (not found) { + println('未找到目标数字') + } +} +``` + +## 循环控制 + +### break 语句 + +```losu +import std + +main { + println('=== 使用break退出循环 ===') + + let count = 1 + while (true) { # 无限循环 + println('当前计数:', count) + + if (count >= 3) { + println('达到目标,退出循环') + break + } + + count = count + 1 + } + + println('循环结束') +} +``` + +### continue 语句 + +```losu +import std + +main { + println('=== 使用continue跳过偶数 ===') + + let i = 0 + while (i < 10) { + i = i + 1 + + if (i % 2 == 0) { + continue # 跳过偶数 + } + + println('奇数:', i) + } +} +``` + +## 嵌套循环 + +```losu +import std + +main { + println('=== 嵌套while循环 ===') + + let i = 1 + while (i <= 3) { + println('外层循环:', i) + + let j = 1 + while (j <= 2) { + println(' 内层循环:', j) + j = j + 1 + } + + i = i + 1 + } +} +``` + +## 练习 + +### 练习 1:计算阶乘 + +使用while循环计算一个数的阶乘。 + +
+查看答案 + +```losu +import std + +main { + let n = 5 + let factorial = 1 + let i = 1 + + println('计算', n, '的阶乘') + + while (i <= n) { + factorial = factorial * i + println(i, '! =', factorial) + i = i + 1 + } + + println('最终结果:', n, '! =', factorial) +} +``` + +
+ +### 练习 2:猜数字游戏 + +实现一个简单的猜数字游戏逻辑。 + +
+查看答案 + +```losu +import std + +main { + let secretNumber = 7 + let guesses = [5, 8, 6, 7] # 模拟用户猜测 + let guessIndex = 0 + let found = false + + println('=== 猜数字游戏 ===') + println('我想了一个1-10之间的数字') + + while (guessIndex < sizeof(guesses) and not found) { + let guess = guesses[guessIndex] + println('你猜:', guess) + + if (guess == secretNumber) { + found = true + println('恭喜!猜对了!') + } elif (guess < secretNumber) { + println('太小了') + } else { + println('太大了') + } + + guessIndex = guessIndex + 1 + } + + if (not found) { + println('游戏结束,答案是:', secretNumber) + } +} +``` + +
+ +**上一章**:[← match语句](../分支/match.md) | **下一章**:[for区间循环 →](for-range.md) \ No newline at end of file diff --git "a/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/README.md" "b/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..29d0d579ea68b2fdf25d028e71bcd3a53e60a350 --- /dev/null +++ "b/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/README.md" @@ -0,0 +1,325 @@ +# 4. 并发编程 + +洛书语言内置了强大的并发编程支持,通过洛书线程(losu thread)提供了轻量级的并发执行能力。本章将详细介绍洛书的并发编程模型和相关操作。 + +## 本章内容 + +- [洛书线程](洛书线程.md) - 洛书线程的概念和特性 +- [基本操作](基本操作.md) - 创建、让出、取消、等待、休眠、同步 + +## 洛书并发模型概览 + +洛书采用了独特的混合态线程模型,结合了协程的轻量级特性和线程的并行能力: + +```mermaid +graph TD + A[洛书并发模型] --> B[洛书线程] + A --> C[混合态执行] + A --> D[内置同步] + + B --> B1[轻量级创建] + B --> B2[地位平等] + B --> B3[协作式调度] + + C --> C1[协程模式] + C --> C2[物理线程托管] + C --> C3[自动切换] + + D --> D1[自动同步机制] + D --> D2[无需手动锁] + D --> D3[数据竞争保护] +``` + +## 洛书线程特性 + +### 1. 轻量级和高效 + +洛书线程比传统操作系统线程更轻量级,创建和切换开销很小: + +```losu +import std + +main { + println('主线程开始') + + # 创建多个轻量级线程 + for (i in 1,5) { + async(true) { + println('线程', i, '执行') + yield # 让出执行权 + println('线程', i, '继续执行') + } + } + + println('主线程结束') +} +``` + +### 2. 地位平等 + +所有洛书线程都是地位平等的,没有主线程和子线程的概念: + +```losu +import std + +main { + let t1 = async(true) { + println('线程1开始') + yield + println('线程1结束') + } + + let t2 = async(true) { + println('线程2开始') + yield + println('线程2结束') + } + + println('主函数执行') + yield + println('主函数继续') +} +``` + +### 3. 协作式调度 + +洛书线程采用协作式调度,线程需要主动让出执行权: + +```losu +import std + +main { + async(true) { + for (i in 1,3) { + println('工作线程:', i) + yield # 主动让出 + } + } + + for (i in 1,3) { + println('主线程:', i) + yield # 主动让出 + } +} +``` + +## 内置同步机制 + +洛书语言的一个重要特性是内置了同步机制,无需手动使用锁: + +```losu +import std + +main { + global let counter = 0 + + # 多个线程同时修改全局变量 + let t1 = async(true) { + for (i in 1,5) { + counter = counter + 1 + println('线程1: counter =', counter) + yield + } + } + + let t2 = async(true) { + for (i in 1,5) { + counter = counter + 1 + println('线程2: counter =', counter) + yield + } + } + + # 等待所有线程完成 + await(t1) + await(t2) + + println('最终 counter =', counter) # 应该是10 +} +``` + +## 并发编程最佳实践 + +### 1. 合理使用yield + +```losu +import std + +main { + # ✅ 好的实践:在适当的地方让出 + async(true) { + for (i in 1,100) { + # 执行一些工作 + let result = i * i + + # 每10次迭代让出一次 + if (i % 10 == 0) { + yield + } + } + } + + # ❌ 避免:从不让出(可能导致其他线程饿死) + # async(true) { + # while (true) { + # # 大量计算,从不yield + # } + # } + + # ❌ 避免:过度让出(影响性能) + # async(true) { + # for (i in 1,100) { + # yield # 每次都让出,过度了 + # # 简单操作 + # } + # } +} +``` + +### 2. 正确使用await + +```losu +import std + +main { + # 创建需要等待的任务 + let importantTask = async(true) { + println('重要任务开始') + sleep(100) # 模拟耗时操作 + println('重要任务完成') + return '任务结果' + } + + # 创建可以并行执行的任务 + async(true) { + println('并行任务执行') + yield + println('并行任务完成') + } + + # 等待重要任务完成 + let result = await(importantTask) + println('获得结果:', result) +} +``` + +### 3. 避免长时间阻塞 + +```losu +import std + +main { + # ✅ 好的实践:分解长时间任务 + async(true) { + let data = [/* 大量数据 */] + let batchSize = 100 + + for (i in 0, sizeof(data)-1) { + # 处理数据 + processItem(data[i]) + + # 每处理一批数据就让出 + if ((i + 1) % batchSize == 0) { + yield + } + } + } +} + +def processItem(item) { + # 处理单个数据项 + return item * 2 +} +``` + +## 错误处理和调试 + +### 线程错误处理 + +```losu +import std + +main { + let t1 = async(true) { + except error { + # 可能出错的操作 + let result = 10 / 0 + return result + } { + println('线程1发生错误:', error) + return false + } + } + + let result = await(t1) + if (result == false) { + println('线程1执行失败') + } else { + println('线程1结果:', result) + } +} +``` + +### 调试并发程序 + +```losu +import std + +main { + global debugMode = true + + def debugLog(message) { + if (debugMode) { + println('[DEBUG]', message) + } + } + + let t1 = async(true) { + debugLog('线程1开始') + for (i in 1,3) { + debugLog('线程1执行步骤' & i) + yield + } + debugLog('线程1结束') + } + + let t2 = async(true) { + debugLog('线程2开始') + for (i in 1,3) { + debugLog('线程2执行步骤' & i) + yield + } + debugLog('线程2结束') + } + + debugLog('主线程等待') + await(t1) + await(t2) + debugLog('所有线程完成') +} +``` + +## 学习路径建议 + +> [!TIP] +> **初学者**:建议先理解洛书线程的基本概念,然后学习基本操作。重点掌握async、yield、await的使用方法。 + +> [!NOTE] +> **有经验的程序员**:可以重点关注洛书独特的混合态线程模型和内置同步机制。这些特性使得洛书的并发编程比传统语言更简单安全。 + +## 本章学习目标 + +学完本章后,您将能够: + +- ✅ 理解洛书线程的概念和特性 +- ✅ 掌握线程的创建、管理和同步 +- ✅ 使用async创建异步任务 +- ✅ 正确使用yield进行协作式调度 +- ✅ 使用await等待线程完成 +- ✅ 理解混合态线程模型的优势 +- ✅ 编写安全高效的并发程序 +- ✅ 调试和优化并发代码 + +--- +**上一章**:[← for-unit循环](../3-语句/循环/for-unit.md) | +**下一章**:[洛书线程 →](洛书线程.md) \ No newline at end of file diff --git "a/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/\345\237\272\346\234\254\346\223\215\344\275\234.md" "b/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/\345\237\272\346\234\254\346\223\215\344\275\234.md" new file mode 100644 index 0000000000000000000000000000000000000000..23fc54205ecc8d373f89a140071acd3b6aca5495 --- /dev/null +++ "b/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/\345\237\272\346\234\254\346\223\215\344\275\234.md" @@ -0,0 +1,349 @@ +# 基本操作 + +洛书线程提供了一系列基本操作来控制线程的执行流程,包括创建、让出、取消、等待、休眠等。这些操作使得开发者能够精确控制并发程序的行为。 + +> [!WARNING] +> 要使用多线程,必须将程序写入 `main{}` 块中,并使用 `async` 函数创建线程。 + +## 创建线程(async) + +`async` 函数用于创建新的洛书线程,其原型是std库中的`std::async`函数: + +```losu +import std + +main { + println('=== 线程创建演示 ===') + + # 创建线程并立即执行 + async(true) { + println('新线程: 我被创建了') + } + + # 创建线程并获取线程对象 + let thread = async(true) { + println('新线程: 我有线程对象') + } + + println('主线程: 线程对象', thread) +} +``` + +## 让出控制权(yield) + +`yield` 函数让当前线程主动让出CPU控制权: + +```losu +import std + +main { + println('=== 线程让出演示 ===') + + async(true) { + println('线程1: 开始执行') + yield # 让出控制权 + println('线程1: 恢复执行') + } + + async(true) { + println('线程2: 开始执行') + yield # 让出控制权 + println('线程2: 恢复执行') + } + + println('主线程: 创建完成') + yield # 主线程也让出控制权 + println('主线程: 恢复执行') +} +``` + +## 等待线程(await) + +`await` 函数等待指定线程执行完毕: + +```losu +import std + +main { + println('=== 线程等待演示 ===') + + let worker = async(true) { + for (i in 1, 3) { + println('工作线程: 步骤', i) + yield + } + println('工作线程: 任务完成') + } + + println('主线程: 等待工作线程完成') + let result = await(worker) + println('主线程: 工作线程已完成,结果:', result) +} +``` + +当设置 `await` 函数的第二个参数为 `true` 时,`await` 会进入 peek 模式,即判断当前的线程是否执行完毕。若线程执行完毕时,`await` 会返回线程的返回值 unit,否则返回 false。 + +```losu +import std + +main { + println('=== 线程等待演示 ===') + + let worker = async(true) { + for (i in 1, 3) { + println('工作线程: 步骤', i) + yield + } + println('工作线程: 任务完成') + } + + println('主线程: 等待工作线程完成') + let result = await(worker, true) + println('主线程: 对线程进行 peek ,结果:', result) + sleep(1000) + let result2 = await(worker, true) + println('主线程: 工作线程已完成,结果:', result2) +} +``` + +## 取消线程(cancel) + +`cancel` 函数取消指定的线程: + +```losu +import std + +main { + println('=== 线程取消演示 ===') + + let longTask = async(true) { + for (i in 1, 10) { + println('长任务: 步骤', i) + yield + } + println('长任务: 全部完成') + } + + # 让长任务执行几步 + for (i in 1, 3) { + println('主线程: 让长任务执行') + yield + } + + # 取消长任务 + println('主线程: 取消长任务') + cancel(longTask) + + println('主线程: 任务已取消') +} +``` + +## 休眠(sleep) + +`sleep` 函数让当前线程休眠指定的毫秒数: + +```losu +import std + +main { + println('=== 线程休眠演示 ===') + + async(true) { + for (i in 1, 3) { + println('线程1: 计数', i) + sleep(100) # 休眠100毫秒 + yield + } + println('线程1: 完成') + } + + async(true) { + for (i in 1, 3) { + println('线程2: 计数', i) + sleep(200) # 休眠200毫秒 + yield + } + println('线程2: 完成') + } + + println('主线程: 等待所有线程完成') +} +``` + +## 同步机制 + +洛书内置了自动同步机制,多个线程可以安全地访问共享变量: + +```losu +import std + +main { + println('=== 同步机制演示 ===') + + global counter = 0 + + let thread1 = async(true) { + for (i in 1, 5) { + counter = counter + 1 + println('线程1: counter =', counter) + yield + } + } + + let thread2 = async(true) { + for (i in 1, 5) { + counter = counter + 1 + println('线程2: counter =', counter) + yield + } + } + + await(thread1) + await(thread2) + + println('最终结果: counter =', counter) +} +``` + +## 复杂示例 + +### 生产者-消费者模式 + +```losu +import std + +main { + println('=== 生产者-消费者演示 ===') + + global buffer = [] + global maxSize = 3 + + # 生产者线程 + let producer = async(true) { + for (i in 1, 5) { + if (sizeof(buffer) < maxSize) { + buffer = buffer + [i] + println('生产者: 生产了', i, '缓冲区:', buffer) + } else { + println('生产者: 缓冲区满了,等待') + } + yield + } + println('生产者: 完成') + } + + # 消费者线程 + let consumer = async(true) { + for (i in 1, 5) { + if (sizeof(buffer) > 0) { + let item = buffer[0] + # 简单移除第一个元素(实际实现可能需要更复杂的数组操作) + println('消费者: 消费了', item, '缓冲区大小:', sizeof(buffer)) + } else { + println('消费者: 缓冲区空了,等待') + } + yield + } + println('消费者: 完成') + } + + await(producer) + await(consumer) + println('演示完成') +} +``` + +## 练习 + +### 练习 1:计数器竞争 + +创建多个线程同时修改一个计数器,观察同步效果。 + +
+查看答案 + +```losu +import std + +main { + println('=== 计数器竞争演示 ===') + + global let sharedCounter = 0 + + let incrementer1 = async(true) { + for (i in 1, 3) { + sharedCounter = sharedCounter + 1 + println('递增器1: 计数器 =', sharedCounter) + yield + } + } + + let incrementer2 = async(true) { + for (i in 1, 3) { + sharedCounter = sharedCounter + 1 + println('递增器2: 计数器 =', sharedCounter) + yield + } + } + + await(incrementer1) + await(incrementer2) + + println('最终计数器值:', sharedCounter) +} +``` + +
+ +### 练习 2:任务调度 + +创建一个简单的任务调度系统,演示线程的创建、等待和取消。 + +
+查看答案 + +```losu +import std + +main { + println('=== 任务调度演示 ===') + + # 创建短任务 + let shortTask = async(true) { + for (i in 1, 2) { + println('短任务: 步骤', i) + yield + } + println('短任务: 完成') + } + + # 创建长任务 + let longTask = async(true) { + for (i in 1, 6) { + println('长任务: 步骤', i) + yield + } + println('长任务: 完成') + } + + # 等待短任务完成 + println('调度器: 等待短任务') + await(shortTask) + + # 让长任务执行一会儿 + println('调度器: 让长任务执行') + yield + yield + + # 取消长任务 + println('调度器: 取消长任务') + cancel(longTask) + + println('调度器: 任务调度完成') +} +``` + +
+ +**上一章**:[← 洛书线程](洛书线程.md) | +**下一章**:[工程结构 →](../5-工程结构/README.md) \ No newline at end of file diff --git "a/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/\346\264\233\344\271\246\347\272\277\347\250\213.md" "b/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/\346\264\233\344\271\246\347\272\277\347\250\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..4bf57a535c3f84520e9db370767d4fb293f51d4a --- /dev/null +++ "b/grammars/4-\345\271\266\345\217\221\347\274\226\347\250\213/\346\264\233\344\271\246\347\272\277\347\250\213.md" @@ -0,0 +1,159 @@ +# 洛书线程 + +洛书线程(losu thread)是洛书语言中的轻量级并发执行单元。洛书采用混合态线程模型,结合了用户态线程的轻量性和内核态线程的并行能力,为开发者提供了高效且易用的并发编程体验。 + +## 线程模型 + +洛书采用 1:M:N 混合线程模型: + +1. **1个主入口**:程序从 main 函数开始执行 +2. **M个洛书线程**:用户态的轻量级线程,支持协作式调度 +3. **N个操作系统线程**:在需要时将洛书线程映射到OS线程上执行 + +> [!IMPORTANT] +> 洛书线程是协作式调度的,这意味着线程需要主动让出控制权,不会在临界区被强制抢占,从而简化了同步机制。 + +## 线程特点 + +### 轻量级 +- 创建和切换开销小 +- 内存占用少 +- 支持大量并发线程 + +### 协作式调度 +- 线程主动让出控制权 +- 减少竞态条件 +- 简化同步机制 + +### 内置同步 +- 编译器自动处理变量访问同步 +- 无需手动使用互斥锁 +- 避免死锁和竞态条件 + +## 基本概念 + +### 线程状态 +洛书线程有以下几种状态: + +1. **就绪(READY)**:等待执行的线程 +2. **运行(RUNNING)**:正在执行的线程 +3. **挂起(YIELD)**:主动让出CPU的线程 +4. **终止(END)**:执行完毕的线程 + +### 线程事件 +线程让出时可以指定事件类型: + +1. **none**:无特定事件,下个周期直接恢复 +2. **await**:等待其他线程完成 +3. **tick**:定时器事件 +4. **callback**:回调事件 + +## 线程创建 + +使用 `async` 函数创建洛书线程: + +```losu +import std + +main { + println('主线程开始') + + # 创建异步线程 + async(true) { + println('异步线程执行') + println('异步线程结束') + } + + println('主线程结束') +} +``` + +## 线程标识 + +`async` 函数返回线程对象,可以用于后续操作: + +```losu +import std + +main { + println('创建线程') + + let thread1 = async(true) { + println('线程1执行') + } + + let thread2 = async(true) { + println('线程2执行') + } + + println('线程对象:', thread1) + println('线程对象:', thread2) +} +``` + +## 练习 + +### 练习 1:基本线程创建 + +创建多个线程并观察执行顺序。 + +
+查看答案 + +```losu +import std + +main { + println('=== 多线程演示 ===') + + async(true) { + println('线程A: 开始执行') + println('线程A: 执行中') + println('线程A: 执行完毕') + } + + async(true) { + println('线程B: 开始执行') + println('线程B: 执行中') + println('线程B: 执行完毕') + } + + println('主线程: 所有线程已创建') +} +``` + +
+ +### 练习 2:线程计数 + +创建多个线程,每个线程执行简单的计数任务。 + +
+查看答案 + +```losu +import std + +main { + println('=== 线程计数演示 ===') + + async(true) { + for (i in 1, 3) { + println('线程1: 计数', i) + } + } + + async(true) { + for (i in 1, 3) { + println('线程2: 计数', i) + } + } + + println('主线程: 计数任务已分配') +} +``` + +
+ +**上一章**:[← 并发编程概述](README.md) | +**下一章**:[基本操作 →](基本操作.md) \ No newline at end of file diff --git "a/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/README.md" "b/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..08e73976ebff60f2a6893db22f5787235ede78a1 --- /dev/null +++ "b/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/README.md" @@ -0,0 +1,355 @@ +# 5. 工程结构 + +洛书语言提供了灵活而强大的工程结构管理机制,包括包与导入系统和程序入口定义。本章将详细介绍如何组织和管理洛书项目的结构。 + +## 本章内容 + +- [包与导入](包与导入.md) - 模块化编程和代码复用 +- [程序入口](程序入口.md) - 程序的启动和执行机制 + +## 洛书工程结构概览 + +洛书的工程结构设计遵循现代编程语言的最佳实践,支持模块化开发和代码复用: + +```mermaid +graph TD + A[洛书工程结构] --> B[包系统] + A --> C[导入机制] + A --> D[程序入口] + + B --> B1[内置包] + B --> B2[用户包] + B --> B3[外置包] + + C --> C1[全局导入] + C --> C2[局部导入] + C --> C3[命名空间] + + D --> D1[简单程序] + D --> D2[复杂程序] + D --> D3[main函数] +``` + +## 包系统设计理念 + +洛书的包系统基于以下设计理念: + +### 1. 目录即包 + +在洛书中,包是以目录的形式存在的,每个包目录必须包含一个 `main.losu` 文件作为入口点: + +``` +myproject/ +├── main.losu # 程序入口 +├── utils/ # 工具包 +│ ├── main.losu # 包入口 +│ ├── string.losu # 字符串工具 +│ └── math.losu # 数学工具 +├── models/ # 数据模型包 +│ ├── main.losu # 包入口 +│ ├── user.losu # 用户模型 +│ └── product.losu # 产品模型 +└── lib/ # 第三方库 + └── external/ + └── main.losu +``` + +### 2. 显式导出 + +包必须通过 `return{}` 语句显式导出其接口: + +```losu +# utils/main.losu +import std + +# 导入包内的其他模块 +let stringUtils = !import('./string') +let mathUtils = !import('./math') + +# 显式导出包接口 +return { + string: stringUtils, + math: mathUtils, + version: '1.0.0' +} +``` + +### 3. 分层导入 + +洛书支持两种导入方式: + +- **全局导入** (`import`):用于内置包,导入到全局命名空间 +- **局部导入** (`std::!import`):用于用户包和外置包,返回包对象 + +```losu +# 全局导入内置包 +import std +import os +import fs + +# 局部导入用户包 +let utils = std::!import('utils') +let models = std::!import('models') + +# 局部导入外置包(使用@前缀) +let externalLib = std::!import('@external-package') +``` + +## 包的类型 + +### 内置包 + +内置包是洛书语言自带的标准库包,可以直接使用 `import` 语句导入: + +```losu +import std # 标准库 +import os # 操作系统接口 +import fs # 文件系统 +import math # 数学库 +import time # 时间处理 +import cstr # 字符串处理 + +main { + println('使用内置包') + println('当前时间:', time::now()) + println('数学常数π:', math::PI) +} +``` + +### 用户包 + +用户包是项目中自定义的包,需要使用 `std::!import` 导入: + +```losu +# 创建用户包 myutils/main.losu +import std + +def formatNumber(num) { + return 'Number: ' & num +} + +def formatString(str) { + return 'String: "' & str & '"' +} + +return { + formatNumber: formatNumber, + formatString: formatString +} +``` + +```losu +# 使用用户包 +import std + +let myutils = std::!import('myutils') + +main { + println(myutils.formatNumber(42)) + println(myutils.formatString('hello')) +} +``` + +### 外置包 + +外置包是第三方提供的包,使用 `@` 前缀标识: + +```losu +import std + +# 导入外置包 +let httpClient = std::!import('@http-client') +let jsonParser = std::!import('@json-parser') + +main { + let response = httpClient.get('https://api.example.com/data') + let data = jsonParser.parse(response.body) + println('获取到数据:', data) +} +``` + +## 命名空间管理 + +洛书提供了 `namespace` 函数来管理命名空间: + +```losu +import std + +# 导入包到命名空间 +let mathLib = std::!import('math-extended') +namespace(mathLib) + +# 导入多个包 +let utils = std::!import('utils') +let helpers = std::!import('helpers') + +# 将多个包合并到命名空间 +namespace(utils) +namespace(helpers) + +main { + # 现在可以直接使用包中的函数 + let result = advancedCalculation(10, 20) # 来自mathLib + let formatted = formatResult(result) # 来自utils或helpers + println(formatted) +} +``` + +## 包的版本管理 + +虽然洛书本身不强制版本管理,但推荐在包中包含版本信息: + +```losu +# mypackage/main.losu +import std + +return { + version: '2.1.0', + author: 'Your Name', + description: 'A useful package', + + # 包的功能 + functions: { + doSomething: doSomething, + doSomethingElse: doSomethingElse + }, + + # 包的常量 + constants: { + MAX_SIZE: 1000, + DEFAULT_TIMEOUT: 30 + } +} + +def doSomething() { + return 'something done' +} + +def doSomethingElse() { + return 'something else done' +} +``` + +## 循环依赖处理 + +洛书会自动检测和处理循环依赖,但建议避免循环依赖的设计: + +```losu +# ❌ 避免循环依赖 +# packageA 依赖 packageB +# packageB 依赖 packageA + +# ✅ 推荐的依赖结构 +# 使用共同的基础包 +# packageA 和 packageB 都依赖 common +# 或者重新设计包的职责分离 +``` + +## 最佳实践 + +### 1. 包的组织原则 + +```losu +# ✅ 按功能组织包 +project/ +├── auth/ # 认证相关 +├── database/ # 数据库操作 +├── api/ # API接口 +├── utils/ # 通用工具 +└── models/ # 数据模型 + +# ✅ 清晰的包接口 +# package/main.losu +return { + # 公开接口 + publicFunction1: publicFunction1, + publicFunction2: publicFunction2, + + # 常量 + CONSTANTS: { + MAX_RETRY: 3, + TIMEOUT: 5000 + } + + # 不导出私有函数 + # privateFunction 不在这里 +} +``` + +### 2. 导入的最佳实践 + +```losu +import std + +# ✅ 在文件顶部集中导入 +import os +import fs + +let utils = std::!import('utils') +let config = std::!import('config') + +# ✅ 使用有意义的变量名 +let httpClient = std::!import('http-client') +let jsonParser = std::!import('json-parser') + +# ❌ 避免在函数内部导入(除非必要) +def someFunction() { + # let localImport = std::!import('something') # 不推荐 +} +``` + +### 3. 程序入口的选择 + +```losu +# ✅ 简单脚本 - 直接执行 +import std +println('Hello World') + +# ✅ 应用程序 - 使用main块 +import std + +def setupApplication() { + # 初始化代码 +} + +main { + setupApplication() + # 主程序逻辑 +} + +# ✅ 库包 - 使用return导出 +import std + +def libraryFunction() { + # 库函数 +} + +return { + libraryFunction: libraryFunction +} +``` + +## 学习路径建议 + +> [!TIP] +> **初学者**:建议先学习简单的导入和程序入口,然后逐步了解包的创建和管理。重点掌握内置包的使用和简单用户包的创建。 + +> [!NOTE] +> **有经验的程序员**:可以重点关注洛书独特的包系统设计,特别是全局导入vs局部导入的区别,以及main块的使用场景。 + +## 本章学习目标 + +学完本章后,您将能够: + +- ✅ 理解洛书的包系统设计理念 +- ✅ 正确使用内置包、用户包和外置包 +- ✅ 掌握全局导入和局部导入的区别 +- ✅ 创建和管理自己的包 +- ✅ 选择合适的程序入口方式 +- ✅ 使用命名空间管理功能 +- ✅ 组织大型项目的代码结构 +- ✅ 避免常见的依赖问题 + +--- +**上一章**:[← 基本操作](../4-并发编程/基本操作.md) | +**下一章**:[包与导入 →](包与导入.md) \ No newline at end of file diff --git "a/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/\345\214\205\344\270\216\345\257\274\345\205\245.md" "b/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/\345\214\205\344\270\216\345\257\274\345\205\245.md" new file mode 100644 index 0000000000000000000000000000000000000000..261b69fe48a90222205bc5c45636c4cd915d6464 --- /dev/null +++ "b/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/\345\214\205\344\270\216\345\257\274\345\205\245.md" @@ -0,0 +1,216 @@ +# 包与导入 + +洛书语言提供了灵活的包管理和导入机制,支持内置包的全局导入和用户自定义包的局部导入。这种设计既保证了核心功能的便捷使用,又提供了模块化开发的灵活性。 + +## 导入机制概述 + +洛书支持两种导入方式: + +1. **全局导入**:使用 `import` 关键字导入内置包 +2. **局部导入**:使用 `std::!import()` 函数导入用户自定义包或外置包 + +> [!IMPORTANT] +> 全局导入只执行一次,局部导入支持多次导入,文件会使用最后导入的包。 + +## 全局导入 + +### 导入内置包 + +内置包导入后,是与洛书虚拟体一体的。 + +```losu +# 导入标准库 +import std + +# 导入操作系统相关功能 +import os + +main { + println('标准库已导入') + # 可以直接使用 std 库的功能 +} +``` + +内置包有三种导入方式: + +```losu +import std # 导入一个包,并创建全局变量与命名空间。其具有全局唯一性,即在多个文件导入时,只导入一次 +import std as global # 导入一个包,仅创建全局变量 +import std as namespace # 导入一个包,仅创建命名空间 +``` + +> [!NOTE] +> 包在被导入后,可以被设置为 `false` ,随后可以再次导入包,以实现热更新机制。包被设置为 `false` 后,其命名空间不再可被访问。举如下的一个例子: +> ```losu +> import std +> +> std = false +> +> main { +> println("Hello World!") # 此处会正常运行 +> async(true) { +> for (i in 1, 3) { +> std::println("Hello World!") # 此处会报错 +> } +> } +> } +> ``` + +### 多个内置包导入 + +```losu +import std +import os +import math + +main { + println('多个内置包已导入') + # 所有导入的包都可以直接使用 +} +``` + +## 局部导入 + +### 导入用户自定义包 + +```losu +import std + +main { + # 导入用户自定义的数学包 + let math = std::!import('math') + + # 使用导入的包 + let result = math.add(10, 20) + println('计算结果:', result) +} +``` + +### 导入外置包 + +洛书中导入外置包与导入自定义包语法相同,只需要将包名放在 `std::!import()` 中即可。需要注意的是,当外置包与内置包名相同时,内置包的优先级高于外置包。 + +## 包的结构 + +### 包目录结构 + +洛书的包以目录形式存在,入口点是 `main.losu` 文件: + +``` +mypackage/ +├── main.losu # 包的入口文件 +├── utils.losu # 其他模块文件 +└── config.losu # 配置文件 +``` + +### 包的导出 + +包需要使用 `return{}` 在最外层导出内容: + +```losu +# math/main.losu - 数学工具包 +import std + +# 私有函数 +let _validate = { + (a, b) { + return typeof(a) == 'number' and typeof(b) == 'number' + } +} + +# 导出包的内容 +return { + name: '数学工具包', + version: '1.0', + + add: { + (a, b) { + if (_validate(a, b)) { + return a + b + } else { + return 0 + } + } + }, + + multiply: { + (a, b) { + if (_validate(a, b)) { + return a * b + } else { + return 0 + } + } + }, + + getInfo: { + return '这是' , math.name , ' v' , math.version + } +} +``` + +## 使用导入的包 + +### 基本使用 + +```losu +import std + +main { + # 导入自定义包 + let myMath = std::!import('math') + + println('包信息:', myMath.getInfo()) + + # 使用包的功能 + let sum = myMath.add(15, 25) + let product = myMath.multiply(6, 7) + + println('加法结果:', sum) + println('乘法结果:', product) +} +``` + +### 多次导入 + +```losu +import std + +main { + # 第一次导入 + let math1 = std::!import('math') + println('第一次导入:', math1.name) + + # 第二次导入(会使用最新的包) + let math2 = std::!import('math') + println('第二次导入:', math2.name) + + # 两次导入的结果相同 + println('是否相同:', math1.name == math2.name) +} +``` + +## 包的命名空间 + +### 避免命名冲突 + +```losu +import std + +main { + # 导入不同的包,使用不同的变量名 + let stringUtils = std::!import('string-utils') + let mathUtils = std::!import('math-utils') + let fileUtils = std::!import('file-utils') + + # 使用时通过变量名区分 + let text = stringUtils.upper('hello') + let number = mathUtils.square(5) + + println('文本处理:', text) + println('数学计算:', number) +} +``` + +**上一章**:[← 工程结构概述](README.md) | +**下一章**:[程序入口 →](程序入口.md) \ No newline at end of file diff --git "a/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/\347\250\213\345\272\217\345\205\245\345\217\243.md" "b/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/\347\250\213\345\272\217\345\205\245\345\217\243.md" new file mode 100644 index 0000000000000000000000000000000000000000..bc22d391edeb849466a1a6f886fe65222315e213 --- /dev/null +++ "b/grammars/5-\345\267\245\347\250\213\347\273\223\346\236\204/\347\250\213\345\272\217\345\205\245\345\217\243.md" @@ -0,0 +1,219 @@ +# 程序入口 + +洛书语言提供了灵活的程序入口机制,支持简单的同步代码执行和复杂的异步程序结构。根据程序的复杂程度,开发者可以选择不同的入口方式。 + +## 入口方式概述 + +洛书支持两种主要的程序入口方式: + +1. **直接执行**:适合简单程序,代码直接在文件中顺序执行 +2. **main函数入口**:适合复杂程序,使用 `main{}` 作为程序入口点 + +> [!IMPORTANT] +> `main{}` 实际上是 `return{}` 的语法糖,只能有一个 main 块。 + +## 直接执行方式 + +### 简单程序 + +对于简单的程序,可以直接在文件中编写代码: + +```losu +import std + +# 直接执行的代码 +let a = 10 +let b = 20 +let c = a + b + +println('a =', a) +println('b =', b) +println('c =', c) +println('计算完成') +``` + +### 顺序执行 + +代码按照编写顺序依次执行: + +```losu +import std + +println('步骤1: 初始化') +let numbers = [1, 2, 3, 4, 5] + +println('步骤2: 处理数据') +let sum = 0 +for (num, v in numbers) { + sum = sum + num +} + +println('步骤3: 输出结果') +println('数组:', numbers) +println('总和:', sum) +println('平均值:', sum / sizeof(numbers)) +``` + +## main函数入口 + +### 基本结构 + +对于复杂程序,建议使用 `main{}` 作为入口点: + +```losu +import std + +# 全局变量和函数定义 +global let appName = '洛书应用' +global let version = '1.0' + +let helper = { + greet: { + (name) { + return '欢迎使用 ' , appName , ', ' , name + } + } +} + +# 程序入口点 +main { + println('=== 应用启动 ===') + println('应用名称:', appName) + println('版本:', version) + + let userName = '用户' + println(helper.greet('userName')) + + println('=== 应用结束 ===') +} +``` + +> [!IMPORTANT] +> 在洛书中,a.b(1)等价于 a::b(a,1)。即在上面的示例中,`helper.greet('userName')` 等价于 `helper::greet(helper, 'userName')`。要注意区分"::"和"."的使用情形 + +### 异步程序入口 + +main函数特别适合需要并发执行的复杂程序: + +```losu +import std + +global let taskCount = 0 + +main { + println('=== 异步程序启动 ===') + + # 创建多个异步任务 + let task1 = async(true) { + for (i in 1, 3) { + taskCount = taskCount + 1 + println('任务1: 步骤', i, '总计数:', taskCount) + yield + } + println('任务1: 完成') + } + + let task2 = async(true) { + for (i in 1, 3) { + taskCount = taskCount + 1 + println('任务2: 步骤', i, '总计数:', taskCount) + yield + } + println('任务2: 完成') + } + + # 等待所有任务完成 + await(task1) + await(task2) + + println('=== 所有任务完成 ===') + println('最终计数:', taskCount) +} +``` + +### 包导出结构 + +当文件作为包被导入时,使用 `return{}` 导出: + +```losu +import std + +# 包的内部实现 +let _privateData = { + initialized: false, + counter: 0 +} + +let _privateFunction = { + () { + _privateData.counter = _privateData.counter + 1 + return _privateData.counter + } +} + +# 包的公共接口 +return { + name: '示例包', + version: '1.0', + + initialize: { + if (not _privateData.initialized) { + _privateData.initialized = true + println('包已初始化') + } + }, + + getNextId: { + return _privateFunction() + }, + + getStatus: { + return { + initialized: _privateData.initialized, + counter: _privateData.counter + } + } +} +``` + +## 练习 + +### 练习 1:简单计算器程序 + +创建一个简单的计算器程序,演示直接执行方式。 + +
+查看答案 + +```losu +import std + +println('=== 简单计算器 ===') + +# 定义操作数 +let num1 = 15 +let num2 = 4 + +println('数字1:', num1) +println('数字2:', num2) +println('---') + +# 执行各种运算 +let sum = num1 + num2 +let difference = num1 - num2 +let product = num1 * num2 +let quotient = num1 / num2 + +# 输出结果 +println('加法:', num1, '+', num2, '=', sum) +println('减法:', num1, '-', num2, '=', difference) +println('乘法:', num1, '*', num2, '=', product) +println('除法:', num1, '/', num2, '=', quotient) + +println('=== 计算完成 ===') +``` + +
+ +**上一章**:[← 包与导入](包与导入.md) | +**下一章**:[基本样例 →](../6-基本样例/README.md) \ No newline at end of file diff --git "a/grammars/6-\345\237\272\346\234\254\346\240\267\344\276\213/README.md" "b/grammars/6-\345\237\272\346\234\254\346\240\267\344\276\213/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..2304b323789c6cdad77a0c9b20fa31f1bf63f9d0 --- /dev/null +++ "b/grammars/6-\345\237\272\346\234\254\346\240\267\344\276\213/README.md" @@ -0,0 +1,11 @@ +# 6. 基本样例 + +本章通过一系列完整的算法题和应用示例,展示洛书语言的语法特性和编程技巧。这些样例涵盖了数据结构、算法、并发编程、工程结构等各个方面,帮助您全面掌握洛书编程。 + +## 本章内容 + +- [算法实现](algorithms.md) - 经典算法的洛书实现 + +--- + +**下一步**:[算法实现 →](algorithms.md) \ No newline at end of file diff --git "a/grammars/6-\345\237\272\346\234\254\346\240\267\344\276\213/algorithms.md" "b/grammars/6-\345\237\272\346\234\254\346\240\267\344\276\213/algorithms.md" new file mode 100644 index 0000000000000000000000000000000000000000..6ec4b497a8eac06c1a85ab337e216c07334c2228 --- /dev/null +++ "b/grammars/6-\345\237\272\346\234\254\346\240\267\344\276\213/algorithms.md" @@ -0,0 +1,291 @@ +# 算法示例 + +本章提供了一系列使用洛书语言实现的经典算法示例,展示了洛书语言在算法实现方面的表达能力和简洁性。 + +## 排序算法 + +### 冒泡排序 + +```losu +import std + +main { + let numbers = [64, 34, 25, 12, 22, 11, 90] + + println('=== 冒泡排序 ===') + println('原数组:', numbers) + + let n = sizeof(numbers) + + # 冒泡排序实现 + for (i in 0, n - 2) { + for (j in 0, n - 2 - i) { + if (numbers[j] > numbers[j + 1]) { + # 交换元素 + let temp = numbers[j] + numbers[j] = numbers[j + 1] + numbers[j + 1] = temp + } + } + } + + println('排序后:', numbers) +} +``` + +### 选择排序 + +```losu +import std + +main { + let numbers = [29, 10, 14, 37, 13] + + println('=== 选择排序 ===') + println('原数组:', numbers) + + let n = sizeof(numbers) + + # 选择排序实现 + for (i in 0, n - 2) { + let minIndex = i + + # 找到最小元素的索引 + for (j in i + 1, n - 1) { + if (numbers[j] < numbers[minIndex]) { + minIndex = j + } + } + + # 交换元素 + if (minIndex != i) { + let temp = numbers[i] + numbers[i] = numbers[minIndex] + numbers[minIndex] = temp + } + } + + println('排序后:', numbers) +} +``` + +## 搜索算法 + +### 线性搜索 + +```losu +import std + +main { + let numbers = [2, 4, 6, 8, 10, 12, 14] + let target = 8 + + println('=== 线性搜索 ===') + println('数组:', numbers) + println('目标:', target) + + let found = false + let position = -1 + + for (i in 0, sizeof(numbers) - 1) { + if (numbers[i] == target) { + found = true + position = i + break + } + } + + if (found) { + println('找到了!位置:', position) + } else { + println('未找到目标元素') + } +} +``` + +### 二分搜索 + +```losu +import std + +main { + let numbers = [1, 3, 5, 7, 9, 11, 13, 15] + let target = 7 + + println('=== 二分搜索 ===') + println('数组:', numbers) + println('目标:', target) + + let left = 0 + let right = sizeof(numbers) - 1 + let found = false + let position = -1 + + while (left <= right and not found) { + let mid = (left + right) / 2 + + if (numbers[mid] == target) { + found = true + position = mid + } elif (numbers[mid] < target) { + left = mid + 1 + } else { + right = mid - 1 + } + } + + if (found) { + println('找到了!位置:', position) + } else { + println('未找到目标元素') + } +} +``` + +## 数学算法 + +### 斐波那契数列 + +```losu +import std + +main { + let n = 10 + + println('=== 斐波那契数列 ===') + println('计算前', n, '项') + + if (n <= 0) { + println('请输入正整数') + } elif (n == 1) { + println('F(1) = 0') + } elif (n == 2) { + println('F(1) = 0') + println('F(2) = 1') + } else { + let a = 0 + let b = 1 + + println('F(1) =', a) + println('F(2) =', b) + + for (i in 3, n) { + let c = a + b + println('F(' & str(i) & ') =', c) + a = b + b = c + } + } +} +``` + +### 最大公约数(欧几里得算法) + +```losu +import std + +main { + let a = 48 + let b = 18 + + println('=== 最大公约数 ===') + println('数字1:', a) + println('数字2:', b) + + # 保存原始值用于输出 + let originalA = a + let originalB = b + + # 欧几里得算法 + while (b != 0) { + let temp = b + b = a % b + a = temp + } + + println('最大公约数:', a) + println('验证:', originalA, '÷', a, '=', originalA / a) + println('验证:', originalB, '÷', a, '=', originalB / a) +} +``` + +## 练习 + +### 练习 1:插入排序 + +实现插入排序算法。 + +
+查看答案 + +```losu +import std + +main { + let numbers = [5, 2, 4, 6, 1, 3] + + println('=== 插入排序 ===') + println('原数组:', numbers) + + let n = sizeof(numbers) + + # 插入排序实现 + for (i in 1, n - 1) { + let key = numbers[i] + let j = i - 1 + + # 将大于key的元素向后移动 + while (j >= 0 and numbers[j] > key) { + numbers[j + 1] = numbers[j] + j = j - 1 + } + + numbers[j + 1] = key + println('第', i, '轮:', numbers) + } + + println('最终结果:', numbers) +} +``` + +
+ +### 练习 2:质数判断 + +编写程序判断一个数是否为质数。 + +
+查看答案 + +```losu +import std + +main { + let numbers = [2, 3, 4, 17, 25, 29, 30] + + println('=== 质数判断 ===') + + for (num, v in numbers) { + let isPrime = true + + if (num < 2) { + isPrime = false + } else { + for (i in 2, num - 1) { + if (num % i == 0) { + isPrime = false + break + } + } + } + + if (isPrime) { + println(num, '是质数') + } else { + println(num, '不是质数') + } + } +} +``` + +
\ No newline at end of file diff --git a/grammars/README.md b/grammars/README.md new file mode 100644 index 0000000000000000000000000000000000000000..02948ce8a80b0534b8cf1d04429ba7b67efbe063 --- /dev/null +++ b/grammars/README.md @@ -0,0 +1,63 @@ +# Losu编程语言语法手册 + +欢迎使用Losu编程语言!这是一款超轻量、高性能、跨平台的嵌入式脚本语言,可以运行在Windows、Linux、MCU上。 + +## Hello, World! + +```losu +import std + +println('Hello World!') +println('Hello Losu Language!') +``` + +## 手册目录 + +### [1. 基本概念](1-基本概念/README.md) +- [获取与安装](1-基本概念/获取与安装.md) +- [工程结构](1-基本概念/工程结构.md) +- [注释、关键字、标识符](1-基本概念/注释、关键字、标识符.md) +- [程序结构](1-基本概念/程序结构.md) +- [表达式](1-基本概念/表达式.md) + , +### [2. 数据类型与类型注释](2-数据类型/README.md) +- [类型注释系统](2-数据类型/类型注释.md) +- [逻辑类型 false/true](2-数据类型/逻辑类型.md) +- [数值类型 number](2-数据类型/数值类型.md) +- [字符串类型 string](2-数据类型/字符串类型.md) +- [函数类型 function](2-数据类型/函数类型.md) +- [容器类型 unit](2-数据类型/容器类型/README.md) + - [基本容器 unit](2-数据类型/容器类型/基本容器.md) + - [数组变体 array](2-数据类型/容器类型/数组变体.md) + - [对象变体 object](2-数据类型/容器类型/对象变体.md) + - [模块变体 module](2-数据类型/容器类型/模块变体.md) + - [类变体 class](2-数据类型/容器类型/类变体/README.md) + - [基本用法](2-数据类型/容器类型/类变体/基本用法.md) + - [重载](2-数据类型/容器类型/类变体/重载.md) + - [继承](2-数据类型/容器类型/类变体/继承.md) + - [反射](2-数据类型/容器类型/类变体/反射.md) +- [特殊类型](2-数据类型/特殊类型.md) + +### [3. 语句](3-语句/README.md) +- [分支语句](3-语句/分支/README.md) + - [if语句](3-语句/分支/if.md) + - [match语句](3-语句/分支/match.md) +- [循环语句](3-语句/循环/README.md) + - [while循环](3-语句/循环/while.md) + - [for区间循环](3-语句/循环/for-range.md) + - [for容器循环](3-语句/循环/for-unit.md) + +### [4. 并发编程](4-并发编程/README.md) +- [洛书线程](4-并发编程/洛书线程.md) +- [基本操作](4-并发编程/基本操作.md) + +### [5. 工程结构](5-工程结构/README.md) +- [包与导入](5-工程结构/包与导入.md) +- [程序入口](5-工程结构/程序入口.md) + +### [6. 基本样例](6-基本样例/README.md) +- [算法实现](6-基本样例/algorithms.md) + +--- + +**下一步**:[开始学习基本概念 →](1-基本概念/README.md) \ No newline at end of file diff --git a/losu.exe b/losu.exe new file mode 100644 index 0000000000000000000000000000000000000000..428fb26385cd1b43cbd4ac2e2402d72afaa674bd Binary files /dev/null and b/losu.exe differ diff --git a/main.losu b/main.losu index d0d1a06c2e24124fb9bead8abc4dceb202f6a1ca..8491f8fddd1d1747f4dad17017347aa00c1c8f7d 100644 --- a/main.losu +++ b/main.losu @@ -1,5 +1,6 @@ -import std -return { => - println('Hello World!') - println('Hello Losu Language!') +import std + +main { + println("Hello World!") + println("Hello Losu!") } \ No newline at end of file