Chez Scheme遵從R6RS 規(guī)范
chez scheme 中輸入 (apropos 'scheme) (apropos 'env)
(apropos 'print)
(pp (apropos-list 'print))
(apropos-list "str")
模糊查詢全局 symbol
(feng: 管理與編程相似... 稍有不周,就是bug,)
在Chez Scheme中色冀,我們可以使用檢查器查看導出過程的源代碼啃匿。讓我們加載我的chez-stats
庫并檢查mean
(inspect mean)
chez scheme 重要的一個宏mat 在 mat.ms 中.
(eval-when (load eval)
(define-syntax mat
(lambda (x)
(syntax-case x (parameters)
[(_ x (parameters [param val ...] ...) e ...)
#'(let f ([p* (list param ...)] [v** (list (list val ...) ...)])
(if (null? p*)
(mat x e ...)
(let ([p (car p*)])
(for-each
(lambda (v)
(parameterize ([p v])
(f (cdr p*) (cdr v**))))
(car v**)))))]
[(_ x e ...)
(with-syntax ([(source ...)
(map (lambda (clause)
(let ([a (syntax->annotation clause)])
(and (annotation? a) (annotation-source a))))
#'(e ...))])
#'(mat-run 'x '(e source) ...))]))))
Chez Scheme 從頭到尾都是 Kent 一個人的作品叽粹。它的工作原理是從 Scheme 源程序一直編譯到機器代碼铺浇,而不依賴任何其他語言的編譯器。它甚至不依賴第三方的匯編器敛熬,所有三種體系構架(Intel, ARM, SPARC)的匯編器肺稀,都是 Kent 自己寫的。為什么這樣做呢应民?因為幾乎沒有其它人的編譯器代碼能夠達到他的標準话原。連 Intel 自己給自己的處理器寫的匯編器,都不能滿足他的要求诲锹。
ppc32.ss 是PowerPC 沒有32位 .因為年輕 1993年發(fā)布的
arm32.ss 是 arm cpu
x86.ss 和 x86
chez scheme 一級目錄 (2021年5月27日)
.
├── BUILDING
├── CHARTER.md
├── CONTRIBUTING.md
├── LICENSE
├── LOG
├── NOTICE
├── README.md
├── bintar
├── boot
├── c ;運行時 垃圾收集
├── checkin
├── configure
├── csug
├── examples
├── lz4
├── makefiles
├── mats ;測試文件夾
├── nanopass ;編譯框架
├── newrelease
├── pkg
├── release_notes
├── rpm
├── s ;scheme ss 文件
├── scheme.1.in
├── stex
├── unicode
├── wininstall
├── workarea
└── zlib
cmacros.ss
(define-syntax define-who
(lambda (x)
(syntax-case x ()
[(k (id . args) b1 b2 ...)
#'(k id (lambda args b1 b2 ...))]
[(k #(prefix id) e)
(and (identifier? #'prefix) (identifier? #'id))
(with-implicit (k who)
(with-syntax ([ext-id (construct-name #'id #'prefix #'id)])
#'(define ext-id (let ([who 'id]) (rec id e)))))]
[(k id e)
(identifier? #'id)
(with-implicit (k who)
#'(define id (let ([who 'id]) e)))])))
Manufacturing Automated Test System mats?
https://open.163.com/newview/movie/free?pid=EEV1GO9MG&mid=AEV1GO9OS
好的編譯課程
pre-defined or built-in 相當重要.. 內置的函數. lisp的7個原生操作符. 還有clojure啟動起來就包含的核心庫函數.
If you looked up the primitive operations of BSL, you saw that primitive
(sometimes called pre-defined or built-in) operations can consume strings and produce numbers:
http://htdp.org/2021-5-4/Book/part_prologue.html 好書..
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-2.html 規(guī)范
What all this means for you is that functions provide a rather economic way of computing lots of interesting values with a single expression. Indeed, programs are functions; and once you understand functions well, you know almost everything there is to know about programming. Given their importance, let’s recap what we know about functions so far:
-
First,
(define (FunctionName InputName) BodyExpression)
https://www.zhihu.com/question/292102918
如果查找BSL的基元操作繁仁,您會發(fā)現基元(有時稱為預定義或內置)操作可以使用字符串并生成數字:
https://www.cnblogs.com/lsgxeva/p/9432975.html
1.1. 基本類型
Scheme程序操作對象(object),有時也被成為值(value)归园。Scheme對象被組織為叫做類型(type)的值的集合黄虱。本節(jié)將給你Scheme語言十分重要的類型的一個概述。更多的類型將在后面章節(jié)進行描述庸诱。
注意:由于Scheme采用隱式類型捻浦,所以本報告中術語類型的使用與其它語言文本中本術語的使用不同说敏,尤其是與那些顯式語言中的不同逝薪。
布爾(Booleans) 布爾類型是一個真值,可以是真或假攻臀。在Scheme中钠四,對象“假”被寫作#f
盗扒。對象“真”被寫作#t
。然而形导,在大部分需要一個真值的情況下环疼,凡是不同于#f
的對象被看作真。
數值(Numbers) Scheme廣泛支持各類數值數據結構朵耕,包括任意精度的整數,有理數淋叶,復數和各種類型的非精確數阎曹。第3章給了Scheme數值塔結構的概述。
字符(Characters) Scheme字符多半等價于一個文本字符。更精確地說处嫌,它們同構與Unicode字符編碼標準的標量值(scalar values)栅贴。
字符串(Strings) 字符串是確定長度字符的有限序列,因此它代表任意的Unicode文本熏迹。
符號(Symbols) 符號是一個表示為字符串的對象檐薯,即它的名字。不同于字符串注暗,兩個名字拼寫一樣的符號永遠無法區(qū)分坛缕。符號在許多應用中十分有用;比如:它們可以像其它語言中枚舉值那樣使用捆昏。
點對(Pairs)和表(lists) 一個點對是兩個元素的數據結構赚楚。點對最常用的用法是(逐一串聯地)表示表,在這種表結構中骗卜,第一個元素(即“car”)表示表的第一個元素宠页,第二個元素(即“cdr”)表示表的剩余部分。Scheme還有一個著名的空表寇仓,它是表中一串點對的最后一個cdr举户。
向量(Vectors) 像表一樣,向量是任意對象有限序列的線性數據結構遍烦。然而敛摘,表的元素循環(huán)地通過鏈式的點對進行訪問,向量的元素通過整數索引進行標識乳愉。所以兄淫,比起表,向量更適合做元素的隨機訪問蔓姚。
過程(Procedures) 在Scheme中過程是值捕虽。
1.2. 表達式(Expressions)
Scheme代碼中最重要的元素是表達式。表達式可以被計算(evaluated)坡脐,產生一個值(value)泄私。(實際上,是任意數量的值—參見5.8節(jié)备闲。)最基本的表達式就是字面的表達式:
#t ? #t
23 ? 23
這表明表達式#t
的結果就是#t
晌端,也就是“真”的值,同時恬砂,表達式23計算得出一個表示數字23的對象咧纠。
復合表達式通過在子表達式周圍放置小括號來組合。第一個子表達式表示一個運算泻骤;剩余的子表達式是運算的操作數:
(+ 23 42) ? 65
(+ 14 (* 23 42)) ? 980
上面例子中的第一個例子漆羔,+
是內置的表示加法的運算的名字梧奢,23和42是操作數。表達式(+ 23 42)
讀作“23和42的和”演痒。復合表達式可以被嵌套—第二個例子讀作“14和23和42的積的和”亲轨。
正如這些例子所展示的,Scheme中的復合表達式使用相同的前綴表示法(prefix notation)書寫鸟顺。所以惦蚊,括號在表達這種結構的時候是必要的。所以讯嫂,在數學表示和大部分語言中允許的“多余的”括號在Scheme中是不被允許的蹦锋。
正如其它許多語言,空白符(包括換行符)在表達式中分隔子表達式的時候不是很重要端姚,它也可以用來表示結構晕粪。
1.3. 變量(variable)和綁定(binding)
Scheme允許標識符(identifier)代表一個包含值得位置。這些標識符叫做變量渐裸。在許多情況下巫湘,尤其是這個位置的值在創(chuàng)建之后再也不被修改的時候,認為變量直接代表這個值是非常有用的昏鹃。
(let ((x 23)
(y 42))
(+ x y)) ? 65
在這種情況下尚氛,以let
開頭的表達式是一種綁定結構。跟在let
之后的括號結構列出了和表達式一起的變量:和23一起的變量x
洞渤,以及和42一起的變量y
阅嘶。let
表達式將x
綁定到23,將y
綁定到42载迄。這些綁定在let
表達式的內部(body)是有效的讯柔,如上面的(+ x y)
,也僅僅在那是有效的护昧。
1.4. 定義
let
表達式綁定的變量是局部的(local)魂迄,因為綁定只在let
的內部可見。Scheme同樣允許創(chuàng)建標識符的頂層綁定惋耙,方法如下:
(define x 23)
(define y 42)
(+ x y) ? 65
(這些實際上是在頂層程序或庫的內部的“頂層”捣炬;參見下面的1.12節(jié)。)
開始的兩個括號結構是定義绽榛,它們創(chuàng)造了頂層的綁定湿酸,綁定x
到23,綁定y
到42灭美。定義不是表達式推溃,它不能出現在所有需要一個表達式出現的地方。而且冲粤,定義沒有值美莫。
綁定遵從程序的詞法結構:當存在相同名字的綁定的時候页眯,一個變量參考離它最近的綁定梯捕,從它出現的地方開始厢呵,并且以從內而外的方式進行,如果在沿途沒有發(fā)現局部綁定的話就使用頂層綁定:
(define x 23)
(define y 42)
(let ((y 43))
(+ x y)) ? 66
(let ((y 43))
(let ((y 44))
(+ x y))) ? 67
1.5. 形式(Forms)
盡管定義不是表達式傀顾,但是復合表達式和定義有相同的語法形式:
(define x 23)
(* x 2)
盡管第一行包含一個定義襟铭,第二行包含一個表達式,但它們的不同依賴于define
和*
的綁定短曾。在純粹的語法層次上寒砖,兩者都是形式,形式是Scheme程序一個語法部分的名字嫉拐。特別地哩都,23是形式(define x 23)
的一個子形式(subform)。
1.6. 過程
定義也可以被用作定義一個過程:
(define (f x)
(+ x 42))
(f 23) ? 65
簡單地說婉徘,過程是一個表達式對象的抽象漠嵌。在上面這個例子中,第一個定義定義了一個叫f
的過程盖呼。(注意f x
周圍的括號儒鹿,這表示這是一個過程的定義。)表達式(f 23)
是一個過程調用几晤,大概意思是“將x
綁定到23計算(+ x 42)
(過程的內部)的值”约炎。
由于過程是一個對象,所以它們可以被傳遞給其它過程:
(define (f x)
(+ x 42))
(define (g p x)
(p x))
(g f 23) ? 65
在上面這個例子中蟹瘾,g
的內部被視為p
綁定到f
圾浅,x
綁定到23,這等價于(f 23)
憾朴,最終結果是65狸捕。
實際上,Scheme許多預定義的操作不是通過語法提供的伊脓,而是值是過程的變量府寒。比如,在其它語言中受到特殊對待的+
操作报腔,在Scheme中只是一個普通的標識符株搔,這個標識符綁定到一過程,這個過程將數字對象加起來纯蛾。*
和許多其它的操作也是一樣的:
(define (h op x y)
(op x y))
(h + 23 42) ? 65
(h * 23 42) ? 966
過程定義不是定義過程的唯一方法纤房。一個lambda表達式可以在不指定一個名字的情況下以對象的形式生成一個過程:
((lambda (x) (+ x 42)) 23) ? 65
這個例子中的整個表達式是一個過程調用;(lambda (x) (+ x 42))
翻诉,相當于一個輸入一個數字并加上42的過程炮姨。
1.7. 過程調用和語法關鍵詞(syntactic keywords)
盡管(+ 23 42)
, (f 23)
和((lambda (x) (+ x 42)) 23)
都是過程調用的例子捌刮,但lambda
和let
表達式不是。這時因為盡管let
是一個標識符舒岸,但它不是一個變量绅作,而是一個語法關鍵詞。以一個語法關鍵詞作為第一個子表達式的形式遵從關鍵詞決定的特殊規(guī)則蛾派。define
標識符是一個定義俄认,也是一個語法關鍵詞。因此洪乍,定義也不是一個過程調用眯杏。
lambda
關鍵詞的規(guī)則規(guī)定第一個子形式是一個參數的表,其余的子形式是過程的內部壳澳。在let
表達式中岂贩,第一個子形式是一個綁定規(guī)格的表,其余子形式構成表達式的內部巷波。
通過在形式的第一個位置查找語法關鍵詞的方法萎津,過程調用通常可以和這些特殊形式區(qū)別開來:如果第一個位置不包含一個語法關鍵詞褥紫,則這個表達式是一個過程調用姜性。(所謂的標識符的宏(identifier macros)允許創(chuàng)建另外的特殊形式,但相當不常見髓考。)Scheme語法關鍵詞的集合是非常小的部念,這通常使這項任務變得相當簡單“惫剑可是儡炼,創(chuàng)建新的語法關鍵詞的綁定也是有可能的,見下面的1.9節(jié)查蓉。
1.8. 賦值(Assignment)
Scheme變量通過定義或let
或lambda
表達式進行的綁定不是直接綁定在各自綁定時指定的對象上乌询,而是包含這些對象的位置上。這些位置的內容隨后可通過賦值破壞性地改寫:
(let ((x 23))
(set! x 42)
x) ? 42
在這種情況下豌研,let
的內部包括兩個表達式妹田,這兩個表達式被順序地求值,最后一個表達式的值會成為整個let
表達式的值鹃共。表達式(set! x 42)
是一個賦值鬼佣,表示“用42代替x
所指向位置的對象”。因此霜浴,x
以前的值晶衷,23,被42代替了。
1.9. 衍生形式(Derived forms)和宏(macros)
在本報告中晌纫,許多特殊的形式可被轉換成更基本的特殊形式税迷。比如,一個let
表達式可以被轉換成一個過程調用和一個lambda表達式锹漱。下面兩個表達式是等價的:
(let ((x 23)
(y 42))
(+ x y)) ? 65
((lambda (x y) (+ x y)) 23 42) ? 65
像let
表達式這樣的特殊形式叫做衍生形式箭养,因為它們的語義可以通過語法轉換衍生自其它類型的形式。一些過程定義也是衍生形式凌蔬。下面的兩個定義是等價的:
(define (f x)
(+ x 42))
(define f
(lambda (x)
(+ x 42)))
在Scheme中露懒,一個程序通過綁定語法關鍵詞到宏以定義它自己的衍生形式是可能的:
(define-syntax def
(syntax-rules ()
((def f (p ...) body)
(define (f p ...)
body))))
(def f (x)
(+ x 42))
define-syntax
結構指定一個符合(def f (p ...) body)
模式的括號結構闯冷,其中f
砂心,p
和body
是模式變量,被轉換成(define (f p ...) body)
蛇耀。因此辩诞,這個例子中的def
形式將被轉換成下面的語句:
(define (f x)
(+ x 42))
創(chuàng)建新的語法關鍵詞的能力使得Scheme異常靈活和負有表現力,允許許多內建在其它語言的特性在Scheme中以衍生形式出現纺涤。
1.10. 語法數據(Syntactic data)和數據值(datum values)
Scheme對象的一個子集叫做數據值译暂。這些包括布爾,數據對象撩炊,字符外永,符號,和字符串還有表和向量拧咳,它們的元素是數據伯顶。每一個數據值都可以以語法數據的形式被表現成字面形式,語法數據可以在不丟失信息的情況下導出和讀入骆膝。一個數據值可以被表示成多個不同的語法數據祭衩。而且,每一個數據值可以被平凡地轉換成一個一個字面表達式阅签,這種轉換通過在程序中加上一個'
在其對應的語法數據前:
'23 ? 23
'#t ? #t
'foo ? foo
'(1 2 3) ? (1 2 3)
'#(1 2 3) ? #(1 2 3)
在數字對象和布爾中掐暮,前一個例子中的'
是不必要的。語法數據foo
表示一個名字是“foo”的符號政钟,且'foo
是一個符號作為其值對的字面表達式路克。(1 2 3)
是一個元素是1,2和3的表的語法數據养交,且'(1 2 3)
是一個值是表的字面表達式精算。同樣,#(1 2 3)
是一個元素是1层坠,2和3的向量殖妇,且'#(1 2 3)
是對應的字面量。
語法數據是Scheme形式的超集破花。因此谦趣,數據可以被用作以數據對象的形式表示Scheme形式疲吸。特別地,符號可以被用作表示標識符前鹅。
'(+ 23 42) ? (+ 23 42)
'(define (f x) (+ x 42))
? (define (f x) (+ x 42))
這方便了操作Scheme源代碼程序的編寫摘悴,尤其是解釋和程序轉換。
1.11. 繼續(xù)(Continuations)
在Scheme表達式被求值的時候舰绘,總有一個繼續(xù)在等待這個結果蹂喻。繼續(xù)表示計算的一整個(默認的)未來。比如捂寿,不正式地說口四,表達式
(+ 1 3)
中3的繼續(xù)給它加上了1。一般地秦陋,這些普遍存在的繼續(xù)是隱藏在背后的蔓彩,程序員不需要對它們考慮太多〔蹈牛可是赤嚼,偶爾,一個程序員需要顯示地處理繼續(xù)顺又。過程call-with-current-continuation
(見11.15節(jié))允許Scheme程序員通過創(chuàng)建一個接管當前繼續(xù)的過程來處理這些更卒。過程call-with-current-continuation
傳入一個過程,并以一個逃逸過程作為參數稚照,立刻調用這個過程蹂空。隨后,這個逃逸過程可以用一個參數調用锐锣,這個參數會成為call-with-current-continuation
的結果腌闯。也就是說,這個逃逸過程放棄了它自己的繼續(xù)雕憔,恢復了call-with-current-continuation
調用的繼續(xù)姿骏。
在下面這個例子中,一個代表加1到其參數的逃逸過程被綁定到escape
上斤彼,且然后以參數3被調用分瘦。escape
調用的繼續(xù)被放棄,取而代之的是3被傳遞給加1這個繼續(xù):
(+ 1 (call-with-current-continuation
(lambda (escape)
(+ 2 (escape 3)))))
? 4
一個逃逸過程有無限的生存期:它可以在它捕獲的繼續(xù)被調用之后被調用琉苇,且它可以被調用多次嘲玫。這使得call-with-current-continuation
相對于特定的非本地跳轉,如其它語言的異常并扇,顯得異常強大去团。
1.12. 庫
Scheme代碼可以被組織在叫做庫的組件中。每個庫包含定義和表達式。它可以從其它的庫中導入定義土陪,也可以向其它庫中導出定義昼汗。
下面叫做(hello)
的庫導出一個叫做hello-world
的定義,且導入基礎庫(base library)(見第11章)和簡單I/O庫(simple I/O library)(見庫的第8.3小節(jié))鬼雀。hello-world
導出的是一個在單獨的行上顯示Hello World的過程顷窒。
(library (hello)
(export hello-world)
(import (rnrs base)
(rnrs io simple))
(define (hello-world)
(display "Hello World")
(newline)))
1.13. 頂層程序
一個Scheme程序被一個頂層程序調用。像庫一樣源哩,一個頂層程序包括導入鞋吉,定義和表達式,且指定一個執(zhí)行的入口励烦。因此谓着,一個頂層程序通過它導入的庫的傳遞閉包定義了一個Scheme程序。
下面的程序通過來自(rnrs programs (6))
庫(見庫的第10章)的command-line
過程從命令行獲得第一個參數崩侠。它然后用open-file-input-port
(見庫的第8.2小節(jié))打開一個文件漆魔,產生一個端口(port),也就是作為一個數據源的文件的一個連接却音,并調用get-bytes-all
過程以獲得文件的二進制數據。程序然后使用put-bytes
輸出文件的內容到標準輸出:
(譯注:以下的示例程序已根據勘誤表進行了修正矢炼。)
#!r6rs
(import (rnrs base)
(rnrs io ports)
(rnrs programs))
(let ((p (standard-output-port)))
(put-bytevector p
(call-with-port
(open-file-input-port
(cadr (command-line)))
get-bytevector-all))
(close-port p))
2. 需求等級
本報告中的關鍵詞“必須(must)”, “必須不(must not)”, “應該(should)”, “不應該(should not)”, “推薦的(recommended)”, “可以(may)”和“可選的(optional)”按照RFC211914描述的進行解釋系瓢。特別地:
必須 這個詞意味著一個陳述是規(guī)范的一個絕對必要條件。
必須不 這個短語意味著一個陳述是規(guī)范絕對禁止的句灌。
應該 這個詞夷陋,或形容詞“推薦的”,意味著有合適的理由的時候胰锌,在特定的情況下可以忽略這個陳述骗绕,但應當理解其含義,并在選擇不同的做法前要仔細權衡资昧。
不應該 這個短語酬土,或短語“不推薦”,意味著有合適的理由的時候格带,在特定的情況下撤缴,一個陳述的行為是可接受的,但應當理解其含義叽唱,且選擇本陳述的描述前應當仔細權衡屈呕。
可以 這個詞,或形容詞“可選的”棺亭,意味著一個條目是真正可選的虎眨。
尤其,本報告偶爾使用“應該”去指定本報告規(guī)范之外但是實際上無法被一個實現檢測到的情況;見5.4小節(jié)嗽桩。在這種情況下钟鸵,一個特定的實現允許程序員忽略本報告的建議甚至表現出其它合理的行為。然而涤躲,由于本報告沒有指定這種行為棺耍,這些程序可能是不可移植的,也就是說种樱,它們的執(zhí)行在不同的實現上可能產生不同的結果蒙袍。
此外,本報告偶爾使用短語“不要求”來指示絕對必要條件的缺失嫩挤。
3. 數字(Numbers)
本章描繪Scheme的數字模型害幅。區(qū)別如下對象的不同是重要的:數學上的數字,嘗試去建模這些數字的Scheme對象岂昭,用于實現這些數字的機器表示和用于書寫數字的符號以现。在本報告中,術語數字表示數學上的數字约啊,術語數字對象(number object)表示代表一個數字的Scheme對象邑遏。本報告使用類型復數(complex),實數(real)恰矩,有理數(rational)和整數(integer)同時表示數學上的數字和數字對象记盒。定長數(fixnum)和浮點數(flonum)類型表示這些數字對象的特殊子集,由通常的機器表示決定外傅,這些會在下面說明纪吮。
3.1. 數值塔(Numeracal tower)
數字可以被組織在一個子集的塔中,在這個塔中萎胰,每一層是上一層的子集:
number
complex
real
rational
integer
比如碾盟,5是一個整數。因此技竟,5也是一個有理數冰肴,實數和復數。為5建模的數字對象也一樣灵奖。
數字對象也被組織為一個對應的子類型的塔嚼沿,這些類型被謂詞(predicates)number?
, complex?
, real?
, rational?
和integer?
定義;見11.7.4.1節(jié)瓷患。整形數字對象也被叫做整數對象(integer objects)骡尽。
包含一個數字的子集和它在計算機中的表示是沒有簡單的關系的。比如擅编,整數5可以有多個表示攀细。Scheme的數值操作將數字對象當作抽象數據對待箫踩,盡可能和它們的表示相獨立。盡管Scheme的實現可以使用不同的數字表示方法谭贪,但這些對于偶爾編些簡單程序的程序員來說不應該是明顯可見的境钟。
3.2. 精確性(Exactness)
區(qū)分一個已知的精確等于一個數字的數字對象和那些在計算過程中有近似和誤差的數字對象是有用的。比如俭识,數據結構的索引操作可能需要精確地了解索引慨削,符號代數系統中的多項式系數也應如此。另一方面套媚,測量的結果在本質上就是不精確的缚态,無理數可以被近似地表示為有理數,這也是不精確的近似堤瘤。為了在需要精確數的地方使用非精確數玫芦,Scheme顯式區(qū)分精確(exact)和非精確(inexact)數。這種區(qū)分和類型的劃分是正交的(orthogonal)關系本辐。
如果一個數值被寫作精確的常量桥帆,或是完全通過精確運算從精確數得出,它就是精確的慎皱。一個精確的數字對象明顯地與一個數學上的數字相一致老虫。
同樣地,如果一個數值被寫作非精確的常量宝冕,或者是由非精確的成分得出的张遭,或者是由非精確的運算得出的,它就是非精確的地梨。也就是說,非精確性是數值的一種可傳染的特性缔恳。
精確算術在下面的場景是可靠的:一個精確數對象被傳遞到11.7.1節(jié)描述的任意一個算術過程宝剖,并返回一個精確數對象,這個結果是數學上正確的歉甚。然而在涉及到非精確數的計算的時候万细,這通常是不正確的,這時因為像浮點算法的近似方法可能被使用纸泄,但是赖钞,讓結果盡可能接近數學上的理想結果是每個實現的職責。
3.3. 定長數和浮點數
一個定長數是一個精確的整數對象聘裁,這個整數對象在精確的整數對象的一個特定的實現相關的子范圍(subrange)雪营。(庫的第11.2小節(jié)描繪了一個計算定長數的庫。)同樣地衡便,每個實現應當指定一個非精確實數對象的子集作為浮點數献起,并將特定的外部表示轉換成浮點數洋访。(庫的第11.3小節(jié)描繪了一個計算浮點數的庫。)注意谴餐,這并不意味著實現必須使用浮點表示姻政。
3.4. 實現要求
Scheme的實現必須支持3.1節(jié)給出的子類型的整個塔的數字對象。此外岂嗓,實現必須支持幾乎無限(Practically unlimited)大小和精度的精確整數對象和精確有理數對象汁展,并實現特定的過程(在11.7.1節(jié)列出),當給它們精確參數的時候這些過程總是返回精確結果厌殉。(“幾乎無限”意味著這些數字的大小和精度應當僅受可用內存大小的限制食绿。)
實現可以只支持任意類型非精確數字對象的一個有限的值域(range),但需要遵從本節(jié)的要求年枕。比如炫欺,一個實現可以限制非精確實數對象的值域(且因此限制非精確整數和有理數對象的值域)在浮點格式的動態(tài)值域內。此外熏兄,在使用這種值域限制的實現中品洛,非精確整數對象和有理數之間的差異很可能會很大。
一個實現可以為非精確數字使用浮點或其它近似表示方法摩桶。本報告推薦但不要求實現遵從IEEE的浮點格式標準桥状,使用其他表示方法的實現應當在精度上達到或超過這些浮點標準15。
特別地硝清,使用浮點數表示法的Scheme實現必須遵循以下規(guī)則:浮點數結果的表示精度必須達到或超過參與該運算的任意非精確參數的表示精度辅斟。只要有可能,像sqrt
這樣潛在的非精確操作當傳遞一個精確的參數時芦拿,應該返回一個精確的結果(比如精確數4的平方根應當是精確的2)士飒。可是蔗崎,這不是必須的酵幕。另一方面,如果參數是精確數的運算會產生非精確的結果(如通過sqrt)缓苛,且該結果被表示為浮點數芳撒,那么就必須使用當前可用的精度最高的浮點數格式;不過未桥,如果該結果是用其他形式表示的笔刹,那么該表示方法在精度上就必須達到或超過當前可用的精度最高的浮點數格式。
避免使用量級或有效數字大到實現無法表示的非精確數是程序員的責任冬耿。
3.5. 無窮大(Infinities)和非數(NaNs)
一些Scheme實現舌菜,尤其是那些遵從IEEE浮點格式標準的實現區(qū)別叫做正無窮大,負無窮大和非數的特殊數字對象淆党。
正無窮大被認為是一個非精確的實數(但不是有理數)對象酷师,它表示大于所以有理數對象表示的數字的一個模糊的數字讶凉。負無窮大被認為是一個非精確的實數(但不是有理數)對象,它表示小于所以有理數對象表示的數字的一個模糊的數字山孔。
一個非數被認為是一個非精確數(但不是一個實數)對象懂讯,它是如此不確定以至于它可以表示任何數,包括正負無窮大台颠,且甚至可能大于正無窮大或小于負無窮大褐望。
3.6. 可區(qū)別的-0.0
一些Scheme實現,尤其是那些遵從IEEE浮點格式標準的實現區(qū)別數字對象0.0和-0.0串前。也就是說瘫里,正的和負的非精確的零。本報告有時會指定在這些數字對象上的特定算術操作的行為荡碾。這些說明會被寫作“如果-0.0的話是不一樣的”或“實現區(qū)分-0.0”谨读。