ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

learnxinyminutes-docs 中的 Elm 速成指南:从语法基础到函数式响应式编程实战

learnxinyminutes-docs 中的 Elm 速成指南:从语法基础到函数式响应式编程实战 文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载Elm 是一门编译为客户端 JavaScript 的函数式响应式编程语言以静态类型、编译器友好错误提示和小而精的语法著称非常适合在浏览器中构建用户界面与游戏。本文以本仓库根目录的 elm.md 教程为骨架逐节展开 Elm 的全部核心语法从算术与字符串到自定义类型、模块与 Ports并结合仓库的元数据规范与多语言译本帮你快速建立对 Elm 语言全貌的系统认知——读完即可看懂大多数 Elm 源码并具备上手elm make、elm reactor、elm repl等工具链的实战能力。文档定位以可运行代码讲解一门语言本仓库learnxinyminutes-docs的核心理念是代码即文档每一篇语言教程本身就是一段完整可运行、带详尽注释的代码讲解随代码逐行展开而不是大段冗长的散文。根目录 elm.md 正是这一理念的典型代表——整篇教程的主体是一个 Elm 代码块所有示例都附有求值结果注释如1 1 -- 2读者可以直接在 REPL 或文件中逐段验证。文档的 frontmatter 元数据也体现了仓库的统一规范--- name: Elm contributors: - [Max Goldstein, http://maxgoldste.in/] filename: learnelm.elm ---name语言的人类可读名称contributors作者与可选的 URL 列表filename本站点将每篇教程的代码提取为可下载文件时使用的文件名这里对应learnelm.elm。仓库的 lint/frontmatter.py 会校验这些键的合法性与类型name、filename为字符串contributors/translators为[作者, URL?]形式的列表CONTRIBUTING.md 则明确了 English 文章必须包含name与contributors字段、翻译需额外添加translators字段的规则。这也解释了为什么你会看到 de/elm.md、cs/elm.md、pt-br/elm.md 等译本在保留原教程内容的同时各自补充了译者信息。基础语法注释、算术、布尔与字符串Elm 的语法与 Haskell 同族先看最基础的表达式。注释单行注释以两个短横线开头多行注释用{- -}包裹且可以嵌套。-- Single line comments start with two dashes. {- Multiline comments can be enclosed in a block like this. {- They can be nested. -} -}算术运算、-、*与常规语言一致/是浮点除法//是整数除法^是幂运算。注意没有小数点的数字字面量既可以是Int也可以是Float由上下文推断1 1 -- 2 8 - 1 -- 7 10 * 2 -- 20 33 / 2 -- 16.5 with floating point division 33 // 2 -- 16 with integer division 5 ^ 2 -- 25布尔值True/False首字母大写不同于 JavaScript 的小写逻辑非用not不相等用/而非!not True -- False not False -- True 1 1 -- True 1 / 1 -- False 1 10 -- True字符串与字符字符串用双引号字符用单引号拼接用This is a string because it uses double quotes. a -- characters in single quotes Hello world! -- Hello world!从语法设计可以看出 Elm 刻意保持语言核心极小没有隐式类型转换、没有 null、没有!这些约定在后面会反复出现——Elm 用显式与类型安全换取编译期可捕捉的错误。核心数据结构List、Tuple 与 RecordList列表列表的所有元素必须是同一类型这是类型系统的第一道约束[the, quick, brown, fox] [1, 2, 3, 4, 5] -- The second example can also be written with two dots. List.range 1 5列表拼接同样用用::cons在头部添加单个元素List.range 1 5 List.range 6 10 List.range 1 10 -- True 0 :: List.range 1 5 -- [0, 1, 2, 3, 4, 5]List.head与List.tail的返回值是Maybe而不是裸值或 null——这是 Elm 处理缺失值的核心哲学与其检查每个值是否为 null不如在类型层面显式处理缺失List.head (List.range 1 5) -- Just 1 List.tail (List.range 1 5) -- Just [2, 3, 4, 5] List.head [] -- NothingList.functionName的命名约定表示该函数位于List模块中Elm 的核心库就是这样按模块组织的。Tuple元组元组的每个元素可以是不同类型但长度固定(elm, 42)访问二元组元素有专门的快捷函数真正的方式稍后在模式匹配中介绍Tuple.first (elm, 42) -- elm Tuple.second (elm, 42) -- 42空元组()unit常被用作占位值它是其类型的唯一取值该类型也叫Unit()Record记录记录像带名字的元组字段顺序无关紧要注意记录的值用等号而非冒号{ x 3, y 7 }字段访问有两种方式点号直接访问或使用点号 字段名构成的访问器函数函数式风格可传入List.map等高阶函数{ x 3, y 7 }.x -- 3 .y { x 3, y 7 } -- 7记录更新是纯函数式的{ person | name George }会返回一份新记录原记录不变且要求该字段已存在。一次可以更新多个字段还能引用当前值——粒子物理模拟是经典场景{ particle | position particle.position particle.velocity, velocity particle.velocity particle.acceleration }控制流if、case 与模式匹配Elm 的if是表达式而非语句else分支必不可少且两个分支必须是同一类型这由编译器强制检查if powerLevel 9000 then WHOA! else mehif可以链式书写用else if表达多路分支if n 0 then n is negative else if n 0 then n is positive else n is zerocase语句用于对不同可能性做模式匹配它是 Elm 中最常用的控制流构造case aList of [] - matches the empty list [x]- matches a list of exactly one item, toString x x::xs - matches a list of at least one item whose head is toString x三个关键语义值得注意模式按书写顺序匹配。若把[x]放在最后它永远不会匹配成功因为x::xs此时xs为空列表也匹配单元素列表匹配不会穿透fall through每个分支独立返回编译器会提示缺失或多余的分支——这就是 Elm 编译器友好错误信息的体现之一。模式匹配与Maybe结合是 Elm 处理可选值的标准范式case List.head aList of Just x - The head is toString x Nothing - The list was empty.函数定义、偏应用、匿名函数与递归Elm 的函数语法极其精简主要依赖空白而非括号与花括号且没有return关键字——函数体就是最后一个表达式。定义函数只需函数名 参数 等号 函数体调用时直接以空格分隔参数无需逗号multiply a b a * b multiply 7 6 -- 42**偏应用部分应用**是函数式编程的核心能力只传入部分参数得到一个新函数double multiply 2常量与函数类似只是没有参数answer 42函数可以作为参数传给其他函数高阶函数例如List.map也可以直接写匿名函数lambda语法为\参数 - 函数体List.map double (List.range 1 4) -- [2, 4, 6, 8] List.map (\a - a * 2) (List.range 1 4) -- [2, 4, 6, 8]函数定义处可以直接做模式匹配当只有一种情况时例如解构元组参数——这是从元组中提取值的常规方式area (width, height) width * height area (6, 7) -- 42用花括号模式匹配记录的字段名用let ... in ...定义中间值volume {width, height, depth} let area width * height in area * depth volume { width 3, height 2, depth 7 } -- 42递归是 Elm 中实现循环的唯一方式语言没有 for/whilefib n if n 2 then 1 else fib (n - 1) fib (n - 2) List.map fib (List.range 0 8) -- [1, 1, 2, 3, 5, 8, 13, 21, 34]用case递归遍历列表的经典写法真实代码中直接使用List.lengthlistLength aList case aList of [] - 0 x::xs - 1 listLength xs优先级规则函数调用先于一切中缀运算符括号用于显式控制优先级cos (degrees 30) ^ 2 sin (degrees 30) ^ 2 -- 1求值顺序为degrees 30→ 三角函数 → 平方 → 最后做加法。这正是三角恒等式cos²θ sin²θ 1的验证。类型与类型注解编译器会推断程序中每个值的类型。类型名一律大写x : T读作x 的类型是 T。你在 Elm REPL 中会看到这些常见类型5 : Int 6.7 : Float hello : String True : Bool函数也有类型-读作到goes to最右侧的类型是返回值其余是参数not : Bool - Bool round : Float - Int定义值时良好的实践是在其上方书写类型注解——注解既是文档又由编译器验证double : Int - Int double x x * 2小写类型是类型变量可以是任何类型只要每次调用保持一致。例如List.map的类型签名可以读作map 的类型是 a 到 b 的函数到 a 的列表到 b 的列表List.map : (a - b) - List a - List bElm 还有三个特殊的小写类型number允许对Int与Float使用算术运算comparable允许对数字与字符串排序如a bappendable可用组合的值。类型别名与自定义类型当你书写一个记录或元组时其类型已经存在。注意记录类型用冒号记录值用等号origin : { x : Float, y : Float, z : Float } origin { x 0, y 0, z 0 }用type alias给已有类型一个更好的名字type alias Point3D { x : Float, y : Float, z : Float }如果别名指向记录别名名可直接作为构造函数使用但它仍是同一个类型因此可以与字面量比较相等otherOrigin : Point3D otherOrigin Point3D 0 0 0 origin otherOrigin -- True与之相对自定义类型custom type创建的是此前不存在的全新类型——它之所以自定义是因为它可以是众多可能性之一每种可能性称为一个类型变体type varianttype Direction North | South | East | West类型变体可以携带其他已知类型的值甚至可以递归引用自身type IntTree Leaf | Node Int IntTree IntTreeLeaf与Node是类型变体变体之后的每个词都是类型。变体既可以当值用也可以当函数用root : IntTree root Node 7 Leaf Leaf自定义类型与类型别名都可以使用类型变量把IntTree泛化为Tree atype Tree a Leaf | Node a (Tree a) (Tree a)在自定义类型上做模式匹配时大写变体精确匹配小写变量匹配任意值下划线_也匹配任意值但表示我不使用它leftmostElement : Tree a - Maybe a leftmostElement tree case tree of Leaf - Nothing Node x Leaf _ - Just x Node _ subtree _ - leftmostElement subtree自定义类型 模式匹配是 Elm 表达领域建模的核心手段Maybe、Result等标准库类型本身就是这么定义出来的编译器穷尽性检查会确保你处理了所有分支。模块与导入核心库按模块组织第三方库同样如此大型项目可以定义自己的模块。module声明放在文件顶部省略时默认处于Main模块module Name where默认导出一切可以显式指定导出列表。一个常见模式是只导出自定义类型本身、而不导出其类型变体——这被称为不透明类型opaque type广泛用于库设计中以隐藏内部实现module Name (MyType, myValue) where导入其他模块以使用其中的代码三种形式各有用处-- 将 Dict 置于作用域可以调用 Dict.insert import Dict -- 同时导入 Dict 模块与 Dict 类型注解里不必写 Dict.Dict仍可调用 Dict.insert import Dict exposing (Dict) -- 导入重命名 import Graphics.Collage as CPorts与外部世界通信的通道port声明表示你将与外部世界JavaScript通信且只允许出现在 Main 模块中**入站端口incoming port**只是一个类型签名用于接收来自 JavaScript 的数据port clientID : Int**出站端口outgoing port**带有定义用于把 Elm 内部数据发送给 JavaScriptport clientOrders : List String port clientOrders [Books, Groceries, Furniture]对应的你需要在 JavaScript 侧设置回调入站端口上接收数据、出站端口上订阅数据。Ports 是 Elm 与现有 JavaScript 生态互操作的桥梁——Elm 本身不直接操作 DOM 副作用之外的系统能力一切进出边界都经由端口显式声明。命令行工具链Elm 自带一整套命令行工具均在终端中运行文档中命令前的$表示 shell 提示符编译文件$ elm make MyFile.elm首次执行时Elm 会安装核心库并创建elm-package.json其中保存着项目信息——这是 Elm 包管理的基础文件。Reactor反应堆一个编译并运行你文件的开发服务器。点击文件名旁的扳手图标可以进入时间旅行调试器time-travelling debugger回溯应用状态变化$ elm reactorREPL在 Read-Eval-Print Loop 中试验简单表达式快速验证上面所有示例$ elm repl包管理Elm 的包以GitHub 用户名 仓库名标识。安装新包并记录到elm-package.json$ elm package install elm-lang/html查看两个版本间的差异$ elm package diff elm-lang/html 1.1.0 2.0.0Elm 的包管理器强制语义化版本semantic versioning次版本号升级永远不会破坏你的构建——这是类型系统作用于包生态的直接红利编译器能依据公共 API 的类型变化自动判定主/次版本号是否合规。仓库内的译本与质量保障由于 Elm 教程质量稳定、内容完整本仓库收录了多个语言的翻译版本便于对照学习德语版 de/elm.md含translators元数据、捷克语版 cs/elm.md、葡萄牙语巴西版 pt-br/elm.md。它们在保留英文原版全部代码示例的同时将注释逐行翻译例如德语版将注释改写为-- Einzeilige Kommentare beginnen mit 2 Bindestrichen.单行注释以两个短横线开头。这种多语言并行的维护方式得益于仓库在 CONTRIBUTING.md 中确立的规范每篇教程以带注释的可运行代码为主体、代码示例优先于文字说明、行宽控制在 80 字符以内并由 lint/frontmatter.py 自动校验每篇文档的 YAML 元数据是否合规。也就是说你读到的这份 Elm 指南不仅内容可验证其长相也是被脚本检查过的。延伸学习建议原文档末尾还列出了一些进阶资源方向这里整理为可执行的下一步官方站点与文档包含安装包下载、文档指南与语法参考、大量可运行示例详见 elm.md 末尾的资源清单原文链接为 elm-lang.org 相关页面核心库文档重点关注默认导入的Basics模块、用于缺失值与错误处理的Maybe及其近亲Result、常用数据结构List/Array/Dict/Set以及 JSON 的编码encode与解码decode模块Elm 架构The Elm ArchitectureElm 之父 Evan Czaplicki 撰写的架构论文讲解如何把代码组织成组件Model–Update–View 三元组是编写真实 Elm 应用的必经之路社区指南面向 JavaScript 开发者的Elm 中的作用域与如何阅读类型注解两篇文章是补齐基础认知的好材料。用一句原文档的收尾话来总结Go out and write some Elm!—— Elm 语言本身出奇地小读完本文你已能大致读懂几乎任何 Elm 源码而它带来的抗错误、易重构的可能性是无限的。下一步就是打开elm repl把本文的每个示例亲手跑一遍。赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐Elm 语言速成指南learnxinyminutes-docs 中的纯函数式 Web 前端编程入门Elm 语言速成指南learnxinyminutes docs 中的纯函数式 Web 前端编程入门 本篇技术指南以 learnxinyminutes docs文档教程OCaml 编程语言速查手册从基础语法到函数式编程实战OCaml 编程语言速查手册从基础语法到函数式编程实战 本篇速查手册围绕 OCaml 语言的核心语法与常用标准库展开内容源自本仓库 source/_post文档教程知识库learnxinyminutes-docs 中的 Common Lisp 快速上手指南从语法基础到宏与 CLOS 的完整实战解析learnxinyminutes docs 中的 Common Lisp 快速上手指南从语法基础到宏与 CLOS 的完整实战解析 Common Lisp 是一文档教程上一篇如何用HSTracker免费提升炉石传说胜率macOS玩家的终极指南下一篇如何用HSTracker免费提升炉石传说胜率macOS玩家的智能游戏助手终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表