20

我想动态设置 REPL 中的语言#lang,不使用“-I”命令行参数。但这给了我错误“读取:在当前上下文中未启用#lang”。

是否有我缺少的命令行开关?或者也许我可以使用“,元命令”?我需要这个的原因是因为我希望能够将 Emacs 缓冲区发送到 Racket REPL,但如果文件以#lang.

4

3 回答 3

11

[Edit]

I can't get C-x C-b to work with #lang either.

But a buffer containing #lang can be sent to a REPL started from Geiser with C-c C-a. This is Switch to REPL and Enter Module from the Geiser drop down menu. If I have a buffer for bugsy.rkt:

;; bugsy.rkt
#lang racket
(define k 6)
(define j 7)
(define (f lhs rhs)
   (+ lhs rhs))

Typing C-c C-a gives me this in the REPL:

racket@> ,enter "<filepath>/bugsy.rkt"
racket@bugsy.rkt>

I can then access the module in the REPL:

racket@bugsy.rkt> k
6
racket@bugsy.rkt> (f 3 4)
7

If I want to switch to a different module [or buffer of a file] I can use the ,enter command in the REPL:

racket@bugsy.rkt> ,enter "clyde.rkt"
racket@clyde.rkt> ,enter "bonny.rkt"
racket@bonny.rkt>

There is an example of the ,enter command in the documentation. Look above the Dinosaur.

[Original]

According to the Racket documentation #lang has very simple syntax, the reader essentially bootstraps a language syntax from whatever follows the space character after #lang. This means in some sense that #lang is not in Racket's [or any other language's] syntax. Instead it is a implementation feature of the reader which forms part of the larger "Racket" development ecosystem.

Geiser [and presumably Quack and racket-mode] handle this by parsing #lang in elsip before passing code to the Racket REPL. In Geiser, the work is done in geiser-racket.el.

The parsing function is at line 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"))

And it is called by geiser-racket--geiser-procedure on line 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 " ")))))

That may give you a starting point for rolling your own code if one of the existing Emacs modes does not meet your needs.

于 2014-01-09T16:03:44.107 回答
5
; foo.rkt
#lang whatever
"hi"

基本上是一样的

(module foo whatever
  "hi")

因此,作为一种快速破解,您可能可以切断#lang线路,从中取出 lang,然后在-ing(module ...)之前将缓冲区的其余部分填充到表单中。comint-send-input

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

此外,值得一提的是一些与 Racket 相关的模式:

其中一个可能已经做了你想做的事,或者,你可以窥探它们是如何工作的(每个都采取了不同的方法)。

于 2014-01-09T01:23:48.053 回答
1

我很难用 Racket & Geiser 通过 SICP 来解决这个问题#lang 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 是两个了不起的软件,几乎要放弃了,但努力让它工作是值得的。感谢所有人的出色工作并帮助我们学习。

于 2018-04-02T14:20:11.137 回答