社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
本章提供了一个对Racket的快速入门作为给这个指南余下部分的背景。有一些Racket经验的读者可以直接跳到《内置的数据类型》部分。
Racket值包括数值、布尔值、字符串和字节字符串。在DrRacket和文档示例中(当你在着色状态下阅读文档时),值表达式显示为绿色。
数值(number)以通常的方式书写,包括分数和虚数:
数值(Number) (later in this guide) explains more about 数值(Numbers).
1 3.14 1/2 6.02e+23 1+2i 9999999999999999999999
布尔值(boolean)用#t表示真,用#f表示假。然而,在条件从句中,所有非#f值被视为真。
布尔值(Boolean) (later in this guide) explains more about 布尔值(boolean).
字符串(string)写在双引号("")之间。在一个字符串中,反斜杠(/)是一个转义字符;例如,一个反斜杠之后的一个双引号包括了字符串中的一个字面上的双引号。除了一个保留的双引号或反斜杠,任何Unicode字符都可以在字符串常量中出现。
字符串(Unicode) (later in this guide) explains more about 字符串(string).
"Hello, world!" "Benjamin "Bugsy" Siegel" "λx:(μα.α→α).xx"
当一个常量在REPL中被求值时,它通常打印与输入语法相同的结果。在某些情况下,打印格式是输入语法的一个标准化版本。在文档和在DrRacket的REPL中,结果打印为蓝色而不是绿色以突出打印结果与输入表达式之间的区别。
> 1.0000 1.0
> "Bugs u0022Figarou0022 Bunny" "Bugs "Figaro" Bunny"
一个程序模块一般被写作
#lang ‹langname› ‹topform›*
‹topform›既是一个‹definition›也是一个‹expr›。REPL也对‹topform›求值。
在语法规范里,文本使用灰色背景,比如#lang,代表文本。除了(、)及[、]之前或之后不需要空格之外,文本与非结束符(像‹ID›)之间必须有空格。注释以;开始,直至这一行结束,空白也做相同处理。
《Racket参考》中的“(parse-comment)”提供有更多的有关注释的不同形式内容。
以后的内容遵从如下惯例:*在程序中表示零个或多个前面元素的重复,+表示一个或多个前面元素的重复,{} 组合一个序列作为一个元素的重复。
表的一个定义:
定义:define (later in this guide) explains more about 定义.
( define ‹id› ‹expr› )
绑定‹id›到‹expr›的结果,而
( define ( ‹id› ‹id›* ) ‹expr›+ )
绑定第一个‹id›到一个函数(也叫一个程序),它通过余下的‹id›以参数作为命名。在函数情况下,该‹expr›是函数的函数体。当函数被调用时,它返回最后一个‹expr›的结果。
(define pie 3) ; 定义pie为3
(define (piece str) ; 定义piece为一个 (substring str 0 pie)) ; 带一个参数的函数 > pie 3
> (piece "key lime") "key"
在底层,一个函数定义实际上与一个非函数定义相同,并且一个函数名不是不需在一个函数调用中使用。一个函数只是另一种类型的值,尽管打印形式不一定比数字或字符串的打印形式更完整。
> piece #<procedure:piece>
> substring #<procedure:substring>
一个函数定义能够包含函数体的多个表达式。在这种情况下,在调用函数时只返回最后一个表达式的值。其它表达式只对一些副作用进行求值,比如打印。
(define (bake flavor) (printf "pre-heating oven...n") (string-append flavor " pie")) > (bake "apple") pre-heating oven...
"apple pie"
Racket程序员更喜欢避免副作用,所以一个定义通常只有一个表达式。然而,重要是去懂得多个表达式在一个定义体内是被允许的,因为它解释了为什么以下nobake函数未在其结果中包含它的参数:
(define (nobake flavor) string-append flavor "jello")
> (nobake "green") "jello"
在nobake中,没有圆括号在string-append flavor "jello"周围,那么它们是三个单独的表达式而不是一个函数调用表达式。表达式string-append和flavor被求值,但结果从未被使用。相反,该函数的结果仅是最终那个表达式的结果,"jello"。
换行和缩进对于解析Racket程序来说并不重要,但大多数Racket程序员使用一套标准的约定来使代码更易读。例如,一个定义的主体通常在这个定义的第一行下面缩进。标识符是在一个没有额外空格的括号内立即写出来的,而闭括号则从不自己独立一行。
当你在一个程序或REPL表达式里键入Enter(回车)键,DrRacket会根据标准风格自动缩进。例如,如果你在键入(define (greet name)后面敲击Enter,那么DrRacket自动为下一行插入两个空格。如果你改变了一个代码区域,你可以在DrRacket里选择它并敲击Tab键,那么DrRacket将重新缩进代码(没有插入任何换行)。象Emacs这样的编辑器提供一个带类似缩进支持的Racket或Scheme模式。
重新缩进不仅使代码更易于阅读,它还会以你希望的方式给你更多的反馈,象你的括号是否匹配等等。例如,如果你在给一个函数的最后参数之后遗漏了一个闭括号,则自动缩进在第一个参数下开始下一行,而不是在"define"关键字下:
(define (halfbake flavor (string-append flavor " creme brulee")))
在这种情况下,缩进有助于突出错误。在其它情况下,当一个开括号没有匹配的闭括号,在缩进的地方可能是正常的,racket和DrRacket都使用源程序的缩进去提示一个括号可能丢失的地方。
Racket对标识符的语法是特别自由的。但排除以下特殊字符。
标识符和绑定 (later in this guide) explains more about 标识符.
( ) [ ] { } " , ' ` ; # |
同时除了产生数字常数的字符序列,几乎任何非空白字符序列形成一个‹id›。例如substring是一个标识符。另外,string-append和a+b是标识符,而不是算术表达式。这里还有几个更多的例子:
+ Hfuhruhurr integer? pass/fail john-jacob-jingleheimer-schmidt a-b-c+1-2-3
我们已经看到过许多函数调用,更传统的术语称之为过程应用程序。函数调用的语法是:
函数调用 (later in this guide) explains more about 函数调用.
( ‹id› 版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/chinazhangyong/article/details/79331815
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!