文档说明 表示0个或者多个 +表示一个或者多个 {}表示括号内的东西当做一个元素处理
2.2.1定义
(define <id> <expr>):绑定id到expr的结果
(define (<id> <id>) <expr>+):绑定第一个id为函数名(过程名),剩下的为参数名。<expr>+为函数体。当函数被调用时,它返回最后一个表达式的值。
函数本质上也是一种值,只不过打印出来的是简略形式。number,string是完整的形式。
2.2.2代码缩进
换行和缩进对racket来说并没有意义,但是大部分racket程序员用标准的代码风格来是程序更具有可读性。比如,方法体经常在定义的下一行并且缩进。标识符直接写在开括号的后面,没有额外的空格,闭括号不写在当前行。
当你在DrRacket里面的程序或者repl表达式里输入回车,DrRacket都会自动缩进代码到标准格式。比如,当你输入(define (greet name)然后敲击回车,DrRacket自动为下一行插入了两个空格。如果你移动了代码区域,输入tab将会重新缩进代码。像Emacs这样的编辑器,也提供了racket或者scheme模式来支持相似的缩进功能。
缩进不只是让代码更容易阅读,通过你代码的缩进方式还可以提供额外的反馈表明括号匹配。比如,你在参数定义的最后遗漏了闭括号。那么自动缩进在第一个参数的下方,正确的时候应该在define关键字下方。
在这种情况下,缩进可以帮助我们发现错误。
2.2.3标识符
除了( ) [ ] { } " , ' ` ; # | \ 和数字之外的所有字符都可以作为标识符。
2.2.4 函数调用
racket 有很多预定义的内部函数
substring 提取子串
string-append 连接字符串
string-length 获得字符串长度
string? 判断是否字符串
sqrt 平方根
number?判断是否数字
equal? 比较是否相等
2.2.5条件if and or cond
(if <expr> <expr> <expr>)
第一个<expr>总是执行的,如果她是非#f值,那么么第二个<expr>执行并返回值,否则第三个<expr>执行。
if可以内嵌其它的表达式,但是可读性比较差,涉及到多个条件的时候,可以使用and或者or。
and or 都是短路表单式。
cond 表达式 (cond { [‹expr›‹expr›]} )
方括号的含义和括号一样,只是为了可读性
2.2.6 函数调用
(<expr> <expr>*)
第一个表达式是一个<id>,像string-append +,但是它可以是任何可以被求值成函数的东西。单传入第一个表单式不是一个函数,会返回“expected a procedure”的错误。(函数式语言的精髓所在)
2.2.7匿名函数lambda
(lambda (‹id›*) ‹expr›+)
当我们处理只使用一次的函数时,可以使用匿名函数。lambda函数的另外一个作用是作为函数的返回值。racket是词法作用域的语言,函数创建时的变量将被函数记录。(闭包特性)。以下两个函数等价。
(define (louder s) (string-append s "!"))
(define louder (lambda (s) (string-append s "!")))
2.2.8 局部绑定 define let let*
(define(‹id›‹id›) ‹definition› ‹expr›+)
(lambda(‹id›) ‹definition› ‹expr›+)
局部定义在函数体之前。
(let ( {[ ‹id› ‹expr› ]}* ) ‹expr›+)
每一个绑定的表达式都被方括号围绕。而且绑定表达式之后的语句是let的方法体。在每一个绑定表达式里,id都与expr的结果绑定,并在方法体力使用。
let的作用范围只在方法体之内,所以绑定子句没发无相引用。但是使用let*就可以。
网友评论