Racket 在REPL中使用#lang设置语言

Racket 在REPL中使用#lang设置语言,racket,geiser,Racket,Geiser,我希望使用#lang动态地在REPL中设置语言,而不是使用“-I”命令行参数。但这给了我一个错误“read:#lang未在当前上下文中启用” 有没有我缺少的命令行开关?或者我能用“元命令”吗?我之所以需要它,是因为我希望能够将Emacs缓冲区发送到Racket REPL,但如果文件以#lang开头,则这将无法工作 ; foo.rkt #lang whatever "hi" 基本上与 (module foo whatever "hi") 因此,作为一种快速黑客,您可能会切掉#lang行,从

我希望使用
#lang
动态地在REPL中设置语言,而不是使用“-I”命令行参数。但这给了我一个错误“read:#lang未在当前上下文中启用”

有没有我缺少的命令行开关?或者我能用“元命令”吗?我之所以需要它,是因为我希望能够将Emacs缓冲区发送到Racket REPL,但如果文件以
#lang
开头,则这将无法工作

; foo.rkt
#lang whatever
"hi"
基本上与

(module foo whatever
  "hi")
因此,作为一种快速黑客,您可能会切掉
#lang
行,从中取出lang,然后在
发送输入之前将剩余的缓冲区填充到
(模块…
表单中

更简单的是,如果您不介意将缓冲区保存到磁盘,首先:只需将
发送到REPL缓冲区,输入/path/to/file.rkt
,或者如果您不使用XREPL,则输入
(输入!”/path/to/file.rkt“

另外,值得一提的是一些与球拍相关的模式:

  • (我为此感到内疚)
其中一个可能已经做了你想做的事情,或者,你可以窥探它们的工作原理(每一个都采取了不同的方法)。

[编辑]

我也无法让
C-x C-b
#lang
一起工作

但是包含
#lang
的缓冲区可以发送到从Geiser启动的REPL,该REPL使用
C-C-a
。这是从Geiser下拉菜单切换到REPL并进入模块。如果我有bugsy.rkt的缓冲区:

;; bugsy.rkt
#lang racket
(define k 6)
(define j 7)
(define (f lhs rhs)
   (+ lhs rhs))
在REPL中键入
C-C-a
可以得到以下信息:

racket@> ,enter "<filepath>/bugsy.rkt"
racket@bugsy.rkt>
racket@bugsy.rkt> k
6
racket@bugsy.rkt> (f 3 4)
7
racket@bugsy.rkt> ,enter "clyde.rkt"
racket@clyde.rkt> ,enter "bonny.rkt"
racket@bonny.rkt>
如果我想切换到其他模块[或文件缓冲区],我可以使用
,在REPL中输入
命令:

racket@> ,enter "<filepath>/bugsy.rkt"
racket@bugsy.rkt>
racket@bugsy.rkt> k
6
racket@bugsy.rkt> (f 3 4)
7
racket@bugsy.rkt> ,enter "clyde.rkt"
racket@clyde.rkt> ,enter "bonny.rkt"
racket@bonny.rkt>
文档中有一个
,enter
命令的示例

[原件]

根据Racket文档
#lang
,读者基本上从
#lang
后面空格字符后面的任何内容引导语言语法。这意味着在某种意义上,
#lang
不在Racket[或任何其他语言]的语法中。相反,它是reader的一个实现特性,它构成了更大的“Racket”开发生态系统的一部分

Geiser[大概是江湖郎中和racket模式]在将代码传递给racket REPL之前,通过解析elsip中的
#lang
来处理此问题。在盖瑟,这项工作是在实验室完成的

解析函数位于第132行:

(defun geiser-racket--language ()
  (or (cdr (geiser-racket--explicit-module))
      (save-excursion
        (goto-char (point-min))
        (if (re-search-forward "^#lang +\\([^ ]+\\)" nil t)
            (geiser-syntax--form-from-string (match-string-no-properties 1))))
      "#f"))
它被第166行的盖泽球拍——盖泽过程调用

(defun geiser-racket--geiser-procedure (proc &rest args)
  (case proc
    ((eval compile)
     (format ",geiser-eval %s %s %s"
             (or (car args) "#f")
             (geiser-racket--language)
             (mapconcat 'identity (cdr args) " ")))
    ((load-file compile-file)
     (format ",geiser-load %S" (geiser-racket--find-module)))
    ((no-values) ",geiser-no-values")
    (t (format ",apply geiser:%s (%s)" proc (mapconcat 'identity args " ")))))

如果现有的Emacs模式之一不能满足您的需求,那么这可能会为您提供一个滚动自己代码的起点。

我很难用Racket&Geiser和
#lang SICP
完成SICP。我终于明白了。基于以上所有的好答案,以下是提醒自己该做什么以及为什么要做的评论:

#lang sicp
;;C-c C-a loads #lang module into REPL (save before loading)
;;C-u C-c C-z is faster than C-c C-a
;;https://docs.racket-lang.org/sicp-manual/index.html
;;https://stackoverflow.com/questions/21008623/setting-language-with-lang-in-the-repl
(#%require sicp-pict)
(paint einstein)

Racket和Geiser是两款令人惊异的软件,几乎放弃了,但值得付出努力来实现。感谢大家的出色工作并帮助我们学习。

因此Geiser可以将
#lang
指令转换为Racket REPL中可运行的代码,但这在哪里使用?当然,运行C-C-b、geiser eval buffer并不能做到这一点,它只是直接传递
#lang
,导致与上面相同的错误。(与来自MELPA的最新Geiser一起测试。)@DavorCubranic我已经添加了关于Geiser Repl的更多信息。谢谢,这回答了我真正想要的。虽然我最终可能会使用@GregHendershott的球拍模式,因为它更接近DrRacket体验。在geiser中,我也可以通过[C-u C-C C-z]进入一个模块,你可以在这篇文章中看到解释:,我尝试了
#lang racket
#lang web server/insta
,两者都按预期工作。请注意,我不能在临时缓冲区中执行[C-u C-C-C-z]——我必须首先将缓冲区保存到一个命名文件中。啊,球拍模式,看起来正是我需要的!记录在案:当我写下这个答案时,这个问题没有提到盖瑟。后来,有人编辑了这个问题,添加了一个盖瑟标签,然后根据这个标签写了一个答案。@GregHendershott在球拍模式下,什么是最好的方法?我正在尝试使用
#lang SICP
完成SICP,我很好奇这是否能在球拍模式下轻松实现。1。使用
.rkt
文件创建或切换到缓冲区。2.做
C-C-C
aka
racketrun
。3.利润。