热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么Scheme不支持一流的环境?-Whydoesn'tSchemesupportfirstclassenvironments?

IvebeenreadingthroughSICP(StructureandInterprationofComputerPrograms)andwasreallyexci

I've been reading through SICP (Structure and Interpration of Computer Programs) and was really excited to discover this wonderful special form: "make-environment", which they demonstrate to use in combination with eval as a way of writing modular code (excerpt from section 4.3 on "packages"):

我一直在阅读SICP(计算机程序的结构和插入)并且非常兴奋地发现这个奇妙的特殊形式:“make-environment”,他们证明它与eval一起用作编写模块化代码的一种方式(摘录)关于“包裹”的第4.3节:

(define scientific-library
  (make-environment
   ...
   (define (square-root x)
    ...)))

They then demonstrate how it works with

然后他们演示了它的工作原理

((eval 'square-root scientific-library) 4)

In their example, they then go on to demonstrate exactly the usage that I would want - an elegant, minimalist way of doing the "OO" style in scheme... They "cons" together a "type", which is actually what was returned by the "make-environment" special form (i.e. the vtable), and an arg ("the state")...

在他们的例子中,他们继续展示我想要的用法 - 一种优雅,极简主义的方式在计划中做“OO”风格......他们“合作”一起“类型”,这实际上是什么由“make-environment”特殊形式(即vtable)和arg(“the state”)返回...

I was so excited because this is exactly what I've been looking for as a way to do polymorphic dispatch "by symbol" in Scheme without having to write lots of explicit code or macros.

我非常兴奋,因为这正是我一直在寻找的一种方法,可以在Scheme中“按符号”进行多态调度,而无需编写大量显式代码或宏。

i.e. I want to create an "object" that has, say, two functions, that I call in different contexts... but I don't want to refer to them by "car" and "cdr", I want to both declare and evaluate them by their symbolic names.

即我想创建一个“对象”,其中包含两个函数,我在不同的上下文中调用...但我不想通过“car”和“cdr”来引用它们,我想要同时声明并用它们的象征性名称来评估它们。

Anyway, when I read this I couldn't wait to get home and try it.

无论如何,当我读到这篇文章时,我迫不及待想回家试试看。

Imagine my disappointment then when I experienced the following in both PLT Scheme and Chez Scheme:

想象一下,当我在PLT计划和Chez计划中经历以下事件时,我感到很失望:

> (make-environment (define x 3))
Error: invalid context for definition (define x 3).
> (make-environment)
Error: variable make-environment is not bound.

What happened to "make-environment" as referenced in SICP? It all seemed so elegant, and exactly what I want, yet it doesn't seem to be supported in any modern Scheme interpreters?

在SICP中引用了“make-environment”怎么了?这一切看起来都很优雅,而且正是我想要的,但它似乎并没有得到任何现代Scheme解释器的支持?

What's the rationale? Is it simply that "make-environment" has a different name?

理由是什么?简单地说“制造环境”有不同的名称吗?

More information found later

稍后会发现更多信息

I took at look at the online version:

我看了看在线版:

http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3

I was reading was the first edition of SICP. The second edition appears to have replaced the discussion on packages with a section on non-deterministic programming and the "amp" operator.

我正在阅读的是SICP的第一版。第二版似乎已经用关于非确定性编程和“放大器”运算符的部分取代了关于包的讨论。

4 个解决方案

#1


After more digging around I discovered this informative thread on newsnet:

经过更深入的挖掘后,我在新闻网上发现了这个信息丰富的主题:

"The R5RS EVAL and environment specifiers are a compromise between those who profoundly dislike first-class environments and want a restricted EVAL, and those who can not accept/understand EVAL without a second argument that is an environment."

“R5RS EVAL和环境说明符是那些非常不喜欢一流环境并希望限制EVAL的人与那些不能接受/理解EVAL而没有第二个参数即环境的人之间的妥协。”

Also, found this "work-around":

此外,发现这“解决方案”:

(define-syntax make-environment 
  (syntax-rules () 
    ((_ definition ...) 
     (let ((environment (scheme-report-environment 5))) 
       (eval '(begin definition 
                     ...) 
             environment) 
       environment)))) 


(define arctic 
  (make-environment 
    (define animal 'polarbaer))) 

(taken from this)

(取自此)

However, I ended up adopting a "message passing" style kinda of like the first guy suggested - I return an alist of functions, and have a generic "send" method for invoking a particular function by name... i.e something like this

然而,我最终采用了“消息传递”风格,有点像第一个人建议 - 我返回一个函数列表,并有一个通用的“发送”方法,用于通过名称调用特定的函数...即这样的东西

(define multiply
  (list
    (cons 'differentiate (...))
    (cons 'evaluate (lambda (args) (apply * args)))))

(define lookup
  (lambda (name dict)
    (cdr (assoc name dict))))

; Lookup the method on the object and invoke it
(define send
  (lambda (method arg args)
    ((lookup method arg) args))

((send 'evaluate multiply) args)

I've been reading further and am aware that there's all of CLOS if I really wanted to adopt a fully OO style - but I think even above is somewhat overkill.

我一直在阅读,并且我知道如果我真的想要采用完全OO风格,那么就有所有CLOS - 但我认为即使上面也有点矫枉过正。

#2


Scheme has no first-class environments because of performance reasons. When Scheme was created, it wasn't the fastest language around due to nifty stuff like first-class functions, continuations, etc. Adding first-class environments would have crippled the performance even further. So it was a trade-off made in the early Scheme days.

由于性能原因,Scheme没有一流的环境。当Scheme被创建时,它不是最快的语言,因为它具有诸如一流函数,延续等等的漂亮东西。添加一流的环境会进一步削弱性能。因此,这是在早期的计划日进行的权衡。

#3


They wrote it like that because MIT Scheme does, in fact, have first-class environments, and presumably that's what the writers were planning to teach their class with (since the book was written at MIT).

他们这样写的是因为麻省理工学院计划确实有一流的环境,并且可能是作家们计划教他们班级的(因为这本书是在麻省理工学院写的)。

Check out http://groups.csail.mit.edu/mac/projects/scheme/

查看http://groups.csail.mit.edu/mac/projects/scheme/

However, I've noticed that MIT Scheme, while still somewhat actively developed, lacks many of the features that a really modern Scheme would have, like a foreign function interface or GUI support. You probably wouldn't want to use it for a serious software development project, at least not by itself.

但是,我注意到MIT Scheme虽然仍然有些积极开发,却缺少真正现代Scheme所具有的许多功能,比如外部函数接口或GUI支持。您可能不希望将其用于严肃的软件开发项目,至少不是单独使用它。

#4


Would a classical dispatcher function work? I think this is similar to what you're looking for.

经典的调度员功能会起作用吗?我认为这与您正在寻找的相似。

(define (scientific-library f)
  (define (scientific-square-root x) (some-scientific-square-root x))
  (cond ((eq? f 'square-root) scientific-square-root)
        (else (error "no such function" f))))
(define (fast-library f)
  (define (fast-square-root x) (some-fast-square-root x))
  (cond ((eq? f 'square-root) fast-square-root)
        (else (error "no such function" f))))

((scientific-library 'square-root) 23)
((fast-library 'square-root) 23)

You could even combine the example scientific and fast libraries into one big dispatch method:

您甚至可以将示例科学和快速库组合成一个大型调度方法:

(define (library l f)
  (define (scientific-library f)
    ...)
  (define (fast-library f)
    ...)
  (cond ((eq? l 'scientific) (scientific-library f))
        ((eq? l 'fast) (fast-library f))
        (else (error "no such library" l))))
(library 'fast 'square-root)

推荐阅读
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
author-avatar
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有