免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: sanbiangongzi
打印 上一主题 下一主题

请教基本概念 [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
11 [报告]
发表于 2012-11-16 15:24 |只看该作者
回复 9# NalaGinrut

怎么,scheme被吐槽了不服气? 有什么你语出来, 我倒很想看看你能语出什么东西, 还是根本就语不出来只会吐这几个字显得自己很高。

list操作一套函数,vector操作又一套函数,hashtable操作再一套函数。。。
想对若干元素(无论是list还是vector还是hashtable)进行操作? 除非使用某个scheme实现提供的扩展, 或者roll your own, 否则没门。
无论怎样, 结果都不会是兼容的。

连你看不起的C++中的STL都不会这么搓。
无论是list,vector,map,set,stream还是其他什么东西, 只要能++, *, 就可以for_each。 只要可以 *=, ++ 就可以作为transform的destination。
scheme连这种基本的数据结构操作都要roll your own, 还搞个屁。

不要以为自己知道scheme就很牛叉, 也不要以为"庆幸自己不会C++"会显得自己很牛叉。

论坛徽章:
0
12 [报告]
发表于 2012-11-16 15:28 |只看该作者
回复 11# OwnWaterloo

无所谓,我不觉得自己有多高明,所以也没什么滔滔不绝的东西好语出来

论坛徽章:
0
13 [报告]
发表于 2012-11-16 15:29 |只看该作者
OwnWaterloo 发表于 2012-11-16 15:24
回复 9# NalaGinrut

不要以为自己知道scheme就很牛叉, 也不要以为"庆幸自己不会C++"会显得自己很牛叉。  ...


我可不懂scheme,不然我怎么不敢滔滔不绝呢?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
14 [报告]
发表于 2012-11-16 15:36 |只看该作者
回复 12# NalaGinrut

要说滔滔不绝,能不能先看看4楼?

LZ提setq, 你要用define, 你在哪家scheme里见过setq的?
intern, string, symbol, immutable也是胡乱扯一通。 我都不知道该从哪开始吐槽了。 典型的分不清语意与实现方式。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
15 [报告]
发表于 2012-11-16 15:37 |只看该作者
NalaGinrut 发表于 2012-11-16 15:29
我可不懂scheme,不然我怎么不敢滔滔不绝呢?


那请你自重。

论坛徽章:
0
16 [报告]
发表于 2012-11-16 15:39 |只看该作者
OwnWaterloo 发表于 2012-11-16 15:36
回复 12# NalaGinrut

要说滔滔不绝,能不能先看看4楼?


那没办法啊,你知道我不懂的

论坛徽章:
0
17 [报告]
发表于 2012-11-16 15:39 |只看该作者
OwnWaterloo 发表于 2012-11-16 15:37
那请你自重。


我这不是站在旁边傻笑不敢语啊,你要说我懂Scheme,我哪装的起这么大的B啊

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
18 [报告]
发表于 2012-11-16 16:58 |只看该作者
回复 10# OwnWaterloo

这楼也确实回得很乱。
elisp manual —— (info "(elisp)") —— 里有很系统的描述。
如果只对elisp有兴趣,对扩展emacs没兴趣,只看前几章(到macro为止)以及(info "(elisp) Read and Print")就差不多了。

emacs的C代码确实没法看, 任何一个这种零散的多人维护了20+年的项目都不会好到哪去。
但也没必要看。


给(info "(elisp)")补充一些例子:

首先是eq,测试两参数是否是同一个object。

  1. (describe-function 'eq) ; 在emacs里,将光标移动到右括号,然后C-x C-e
  2. ; eq is a built-in function in `C source code'.  ; 注意这是function, 求值规则是定死了的, 从左到右,依次求值,并将求值结果传入
  3. ; (eq OBJ1 OBJ2)
  4. ; Return t if the two args are the same Lisp object.
复制代码
然后是intern相关的。

  1. (eq (read "a") (read "a"))    ; t
  2. (eq (read "a") (intern "a"))  ; t
复制代码
代码(text形式)中的所有a,经过读取(read "a")得到的都是同一个symbol object。
read和intern都是函数,求值规则也是固定的。 "a"是string, 也是self evaluating form。

与主题关系不大,只是作为补充,对应的是 uninterned symbol。

  1. (eq (read "a") (make-symbol "a")) ; nil
  2. ; make-symbol 函数得到的symbol就与读取得到的不是同一个
  3. (eq (make-symbol "a") (make-symbol "a")) ; nil
  4. ; 以相同字符串多次调用 make-symbol 得到的symbol也不是同一个
  5. (symbol-name (make-symbol "a")) ; "a"
  6. (symbol-name (read "a"))        ; "a"
  7. ; 无论是不是 interned symbol, 它们都是 symbol , 都有 name
  8. ; 而且 (make-symbol "a") 与 (read "a") 得到的 symbol 的name 是相同的

  9. (symbol-name (read "#:a"))      ; "a"
  10. ; #:a 是 uninterned symbol 的read syntax
  11. ; 读取得到的 symbol 的name 依然是 "a"
  12. (eq (read "#:a") (read "#:a"))  ; nil
  13. ; 只是没有 interned , 所以对代码中不同地方出现的 #:a , 得到的是不同的 symbol object
复制代码
与value cell相关的:

  1. ; 测试 symbol 是否有 value cell
  2. (describe-function 'boundp)
  3. ; boundp is a built-in function in `C source code'.
  4. ; (boundp SYMBOL)
  5. ; Return t if SYMBOL's value is not void.

  6. ; 获取 value cell
  7. (describe-function 'symbol-value)
  8. ; symbol-value is a built-in function in `C source code'.
  9. ; (symbol-value SYMBOL)
  10. ; Return SYMBOL's value.  Error if that is void.

  11. ; 设置 value cell
  12. (describe-function 'set)
  13. ; set is a built-in function in `C source code'.
  14. ; (set SYMBOL NEWVAL)
  15. ; Set SYMBOL's value to NEWVAL, and return NEWVAL.

  16. ; 设置 value cell 为空(void与nil不同)
  17. (describe-function 'makunbound)
  18. ; makunbound is a built-in function in `C source code'.
  19. ; (makunbound SYMBOL)
  20. ; Make SYMBOL's value be void.
  21. ; Return SYMBOL.
复制代码
这些都是函数,求值规则依然是固定的。 并且所有symbol都有value cell,都可以用这些函数操作value cell, 无论它们是否被intern。
intern的作用只是为了让代码(text形式)中不同地方的相同字符串"a"能表示同一个symbol object。
对应的unintern的作用就是有些使用(比如写macro的时候)要故意地得到一些unique symbol object,操作它们的value cell(以及其他cell)就不会影响到其他symbol。

因为通常大量使用的都是interned symbol。

  1. (set (read "a") 1) ; 1
  2. ; 于是一个地方将interned symbol "a" 的value cell 设置为1
  3. (eval (read "a")) ;  1
  4. ; 其他地方就可以从同一个(因为interned的关系所以是同一个)symbol中得到value cell

  5. (set (intern "a") 2)
  6. (eval (read "a")) ; 2

  7. (set (read "a") 3)
  8. (eval (intern "a")) ; 3
复制代码
elisp代码执行方式,就是先read,再eval。
假设a.el

  1. (print a)
复制代码
加载a.el的效果就是从a.el(代码文本)中依次读取lisp object,并依次求值。 这里只有一个lisp object, 那相当于(eval (read "(print a)")。
print也是函数, 也会对所有参数求值, 并将求值结果传递给print函数。
print的第1个参数是symbol, 其求值规则是取出value cell。
又因为这是interned symbol, 该symbol与前面被多次设置value cell的是同一个symbol;value cell最后一次被设置的值是3, 所以print函数接受到的参数就是3。


最后,不规则求值的form。 前面故意选的都是规则求值的, 从左到右依次求值,并将求值结果传入。

  1. ; 注意下面的special form,前面的都是function
  2. (describe-function 'quote)
  3. ; quote is a special form in `C source code'.
  4. ; (quote ARG)
  5. ; Return the argument, without evaluating it.  `(quote x)' yields `x'.

  6. ; (describe-function 'setq)
  7. ; setq is a special form in `C source code'.
  8. ; (setq [SYM VAL]...)
  9. ; Set each SYM to the value of its VAL.
  10. ; The symbols SYM are variables; they are literal (not evaluated).
  11. ; The values VAL are expressions; they are evaluated.
复制代码
它们的求值规则就不是固定的了, 但这种form很少。

回到1楼的问题:

  1. (eq (read "b") (quote b)) ; t
  2. ; quote不会对参数求值,而是直接返回参数本身。
  3. ; 并且因为(quote b)中的b是interned symbol的read syntax, 所以两者是同一个symbol object

  4. (boundp (quote b)) ; nil
  5. ; b一开始没有value cell
  6. (setq b 1)
  7. ; setq 不会对b求值, 但会对1求值,只是恰好1是self evaluating,所以看不出区别, 如果改成(setq b (+ 1 0))就能看出区别了。
  8. ; setq 会设置b的value cell为1

  9. (boundp (quote b))       ; t
  10. (symbol-value (quote b)) ; 1
  11. ; 被 setq 设置 value cell的symbol,与boundp以及symbol-value测试的symbol都是同一个

  12. (list b) ; (1)
  13. ; 这里的b也是同一个, 又因为list是函数, 会对b求值, 所以传递给list的实际参数是1, 得到一个1元素的list,首元素是数字1
  14. (list (quote b) b) ; (b 1)
  15. ; 这里的两个b都是同一个, 但quote 不会对b求值而是返回b这个symbol本身,list的实际参数是symbol b本身,以及symbol b的value cell。
复制代码
最后, '这个marker只是quote的一种方便的写法, 读取的时候会将'后的一个表达式包裹到quote中。

  1.                 (read "'a")   ; (quote a)
  2.        (type-of (read "'a"))  ; cons
  3.          (nth 0 (read "'a"))  ; quote
  4. (type-of (nth 0 (read "'a"))) ; symbol
  5.          (nth 1 (read "'a"))  ; a
  6. (type-of (nth 1 (read "'a"))) ; symbol

  7. (list 'a a) ; (a 3)
  8. ; 实际上被求值的是 (list (quote a) a)
  9. ; list的第1个实际参数是 (quote a) 求值的结果, 因为quote的求值规则会直接返回a这个symbol 本身
  10. ; list的第2个实际参数是a求值的结果, a这个symbol的求值规则是取得它的value cell, 最后一次被设置的值是3
复制代码
总之, 如果是函数, 那求值规则就是固定的, 会对每一个参数从左往右依次求值,并将结果作为实际参数传入。
对symbol, 它的求值规则就是取value cell作为结果, 就可以将symbol当作变量使用。
少数operator的求值规则是特殊的, 比如quote, 就会直接返回symbol本身, symbol没有被继续求值的机会。
setq 也不会对 b求值, 而是直接设置b的value cell。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
19 [报告]
发表于 2012-11-16 17:00 |只看该作者
NalaGinrut 发表于 2012-11-16 15:39
那没办法啊,你知道我不懂的

NalaGinrut 发表于 2012-11-16 15:39
我这不是站在旁边傻笑不敢语啊,你要说我懂Scheme,我哪装的起这么大的B啊


敢于承认,孺子可教。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
20 [报告]
发表于 2012-11-16 17:20 |只看该作者
OwnWaterloo 发表于 2012-11-16 16:58
少数operator的求值规则是特殊的, 比如quote, 就会直接返回symbol本身, symbol没有被继续求值的机会。


改一改, quote会直接返回它的参数(由read得到)本身,参数中的任何东西都没有被求值的机会。 只是前面讨论的都是直接quote一个symbol的情况。

比如:
(setq c (+ a b) d '(+ a b))
setq不会对c和d求值,而是设置它们的value cell。 设置的值就是 (+ a b) 以及 '(+ a b)的结果。

+也是个函数, 会对a和b求值, +的实际参数是3和1, 所以c的value cell会被设置为4
(format "%s" c) ;"4"

而'(+ a b)实际被求值的是(quote (+ a b)), quote求值的结果是参数本身,所以d的value cell是一个list而不是number。
(format "%s" d) ; "(+ a b)"


再比如vector(这种lisp 类型,而不是指vector函数), 它的求值规则就是返回vector自身, 不对vector的元素求值。
[a b c d] ; [a b c d]
[a b c d]经过读取后, 得到的就是一个vector object, 元素是4个symbol。 求值结果就是这个vector自身, 它的4个元素没有被求值的机会。

如果想得到一个vector, 元素依次是a b c d的value cell, 可以用vector函数
(vector a b c d) ; [3 1 4 (+ a b)]
读取得到的是一个list, 元素依次是vector a b c d这几个symbol。 list的求值规则是"调用", 将第1个元素作为操作码, 后续元素作为操作数。
又因为vector是一个普通函数, 所以所有操作数都有被求值的机会。

如果想要抑制部分参数被求值: (vector a b c 'd) ; [3 1 4 d]
vector的所有参数依然会被求值, 但d是被包裹在一个quote中的, quote会被求值, 但quote不会对它的参数求值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP