For the R5RS language, DrRacket has the option to turn Disallow redefinition of initial bindings on or off.
This made me curious: Is it possible to adjust language settings like this without using DrRacket? (e.g., when using Racket from the command line, or Emacs)
If so, in which ways? If not, or not in a reasonable manner, why?
The parameter compile-enforce-module-constants controls whether redefinitions are allowed:
soegaard$ ./racket
Welcome to Racket v6.6.0.3.
-> (compile-enforce-module-constants #f)
-> (module test r5rs (define + -) (display (+ 43 1)) (newline))
-> (require 'test)
42
See more here: http://docs.racket-lang.org/guide/module-set.html
Related
I have a program that uses the at-exp meta-language:
#lang at-exp racket
(define v '#f{str})
(displayln v)
I want to manually type it line-by-line into the Racket REPL. Unfortunately, #lang at-exp racket is not valid in the REPL:
$ racket
Welcome to Racket v6.11.
> #lang at-exp racket
; readline-input:1:0: read: #lang not enabled in the current context [,bt for
; context]
; at-exp: undefined;
; cannot reference undefined identifier
; [,bt for context]
; racket: undefined;
; cannot reference undefined identifier
; [,bt for context]
>
How do I set the meta-language in the Racket REPL?
For the beginners who have ended up here, the short answer is no. The #lang shorthand should only be used in files. If you want to run your example program in the REPL, you could load it using this command.
racket --repl --eval '(enter! (file "your-file.rkt"))'
The more detailed answer is that the #lang shorthand gets re-written behind the scenes into module form.
So for example something like this...
#lang racket
(define v "Hello!")
(displayln v))
Is re-written to what you see below and you could copy and paste this into the repl and then require the module, e.g. in the repl type...
> (module the-hello-module racket
(define v "Hello!")
(displayln v))
> (require 'the-hello-module)
Hello!
But from what I can tell, that re-write is dependent on the languages you're using, so the rewrite is probably not something you want to do manually and I don't think the at-exp metalanguage is something you would be add manually to module form.
I don't know why they're different, but the REPL inside DrRacket can use the #lang shorthand:
Unlike the command-line REPL, the DrRacket REPL adopts the language specified by the #lang line at the top of the definitions panel. DrRacket also uses the REPL itself to print output from the program.
https://beautifulracket.com/explainer/repl.html#a_Rv5YS
So if you have #lang at-exp racket/base in the definitions panel and click "Run" the bottom REPL panel will show Language: at-exp racket/base, etc., and this will work:
> #string-append{this is a test}
"this is a test"
That page also says:
More intricate REPL hacking is possible. For instance, the REPL can be configured to use a custom reader (other than Racket’s default S-expression reader).
https://beautifulracket.com/basic-3/the-repl.html
However, the steps described there are much more involved than I care to get into. I don't know what DrRacket is doing in the background to make #lang at-exp work.
Can someone explain the difference between using drracket with swindle (any of the versions) and firing up the interpreter as: racket -I swindle
Many expressions evaluate the same in both environments, but some don't. For example:
(let-syntax ((let* (syntax-rules () ((let* a b) "You used let*")))) (let* 3 4))
... evaluates to "You used let*" in every scheme-based language I tried in drracket. However, it fails in the interpreter brought up by "racket -I swindle" on the command line with the error
; readline-input:1:20: syntax-rules: unbound identifier;
; also, no #%app syntax transformer is bound in the transformer phase
; at: syntax-rules
; in: (syntax-rules () ((let* a b) "You used let*"))
; [,bt for context]
Your example uses syntax-rules at phase 1 (aka the "for-syntax phase", aka the "transformer phase"), but it appears that the swindle module (unlike racket/base and racket) does not provide any bindings for-syntax. (It looks like swindle uses an old technique to provide phase-1 bindings that works for modules written in the swindle language but not for a REPL started with racket -l swindle.)
One workaround is to evaluate
(require (for-syntax racket/base))
before evaluating your example, and then your example should work as you expect.
I would like to write code that is correct for both untyped Racket and typed/racket...
For now, I've come up with the following not-so-satisfying principle: I insert a dummy syntax definition for ':' at the beginning of the file, so that the annotations are skipped when using untyped racket. And I comment this definition when using typed/racket.
E.g:
#lang racket
; comment the following line for typed/racket
(define-syntax : (syntax-rules () ((_ id type) (void))))
(: fact (-> Integer Integer))
; the rest of the file is common to both racket and typed/racket
(define (fact n) (if (zero? n) 1 (* n (fact (sub1 n)))))
and
#lang typed/racket
; comment the following line for typed/racket
;(define-syntax : (syntax-rules () ((_ id type) (void))))
(: fact (-> Integer Integer))
; the rest of the file is common to both racket and typed/racket
(define (fact n) (if (zero? n) 1 (* n (fact (sub1 n)))))
This way I just need to remove/insert a ';' to switch between racket and typed/racket...
But is there a way to have a code that doesn't need any change to run in racket and typed/racket? I didn't find how to programmatically detect if I'm in racket or typed/racket... Then I guess I would also have to find a way to conditionally define ':' at the top-level... All this doesn't seem the way to go, so, is there a better way ?
Generally, if you want code to work with both #lang racket and #lang typed/racket, just write your code in #lang typed/racket. When you require a module written in #lang typed/racket from a module written in #lang racket, contracts will automatically be inserted between the two modules to enforce the types. You don’t have to do anything special to require a typed module from an untyped one, so from the user’s perspective, they don’t have to care.
The one area where you might need to worry about being in a typed or untyped context is when writing macros. Often, you can expand to the same code in both situations, but sometimes, you have to do things differently depending on whether or not the target code is typed. For that, you can use define-typed/untyped-identifier, which allows specifying two different forms to be used in different contexts.
If you really need to detect whether or not the current expansion context is typed, you can use the large hammer syntax-local-typed-context?. However, the documentation itself recommends avoiding its use:
This is the nuclear option, provided because it is sometimes, but rarely, useful. Avoid.
Given this situation:
(defmacro mac1 ...)
(defun func1 ()
(mac1 ...))
Redefinition of mac1 in the live environment will not affect func1 until it is itself recompiled.
Is there a way to get emacs or lisp to automatically recompile func1 whenever mac1 is recompiled?
Something like this in the source would be acceptable:
(watch
(defmacro mac1 ...))
(on-signal (mac1)
(defun func1 ...))
Not that hard to implement, but I would rather avoid wheel reinvention.
Macros are not necessarily compiled. If you are using SBCL (see manual), there is a variable named sb-ext:*evaluator-mode* which can be set to :interpret so that macro are expanded during evaluation. Other implementations might provide something similar. That allows you to change the definitions of macros without recompiling call sites like you already do with functions.
Alternatively, slime defines a function named slime-who-macroexpands. You'd have to dig a little bit to see how it works and maybe exploit it, either in the Common Lisp environment (swank) or the emacs side.
For example in LispWorks you can do the following. Probably SBCL has a similar facility.
Let's say we have this:
(defmacro foo ()
`(list 1 2 3))
(defun bar () (first (foo)))
(defun baz () (second (foo)))
Now you can ask who calls foo:
CL-USER 11 > (who-calls 'foo)
(BAZ BAR)
This makes it easy to re-compile both functions:
CL-USER 12 > (mapcar 'compile (who-calls 'foo))
;;;*** Warning in BAZ: The definition of BAZ is already compiled.
;;;*** Warning in BAR: The definition of BAR is already compiled.
(BAZ BAR)
Since LispWorks keeps a who-calls database, one can recompile all functions which directly use and depend on other functions/macros.
The editor has the command Edit Callers and Continue Tags Search to find the callers and then to recompile them manually. It should be easy/possible to write an editor command which recompiles all callers.
The reason I don't understand why Emacs 24's new lexical scoping features are that great is that I can't think of any new functionality that couldn't have been implemented without them. For example, the following closure:
(setq lexical-binding t)
(defun f1 (num1)
(lambda (num2)
(setq num1 (* num1 num2))))
(fset 'f2 (f1 5))
==> (closure ((num1 . 5) t) (num2) (setq num1 (* num1 num2)))
(f2 5)
==> 25
(f2 2)
==> 50
Can be implemented with regular dynamic scoping like so:
(defun f1 (num)
(let ((tmpvar (make-symbol "num")))
(set tmpvar num)
`(lambda (num2)
(set ',tmpvar (* (eval ,tmpvar) num2)))))
(fset 'f2 (f1 5))
==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f2 5)
==> 25
(f2 2)
==> 50
(fset 'f3 (f1 9))
==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f3 3)
==> 27
(f3 2)
==> 54
(f2 10)
==> 500
Okay, so not all languages have something analogous to elisp's uninterned symbols, so I understand why lexical scoping is so great in their case. But what about elisp? Can you think of anything that I can do now (as of Emacs 24) that I couldn't do before, thanks to lexical scoping?
You don't need uninterned symbols, use cons instead of make-symbol, car instead of eval, and setcar instead of set and your example will work just as well (and be more efficient).
Note also that the progression from machine-language to ever higher-level languages has been mostly based on making more and more things impossible (or at least much harder). Of course those facilities taken away from the programmers were rarely used and/or considered too dangerous. Think of using uninitialized variables (possible in C, but impossible in Java and many other languages), or jumping into the middle of an instruction.
As for some downside of your example code: not only it's less readable, but the compiler basically won't be able to know that you're constructing code, so it won't be allowed to look inside that "`(lambda ...)" to compile it, expand its macro calls, give you warnings about suspicious elements, ...
There have always been workarounds to simulate lexical binding in Emacs, so it's not so much about being able to do new things.
The manual says:
Lexical binding opens up a lot more opportunities for optimization, so
Emacs Lisp code that makes use of lexical binding is likely to run
faster in future Emacs versions. Such code is also much more friendly
to concurrency, which we want to add to Emacs in the near future.
I think that is the primary benefit.
The flip side to this is that dynamic binding was purposely chosen when Emacs was written for good reasons which still hold true today, and so lexical binding should certainly not be considered the New Way of doing things.
Global variables are generally considered a bad idea in programming, but Emacs is an unusual case where this doesn't really apply, because much of its immense flexibility -- one of the key things that makes Emacs great -- derives directly from dynamic binding. Without dynamic binding, it would not be possible to bend the application to the requirements of the individual user to anything like the extent that Emacs allows.
In my opinion, lexical binding should be used cautiously and only for variables for which another user could not conceivably find a reason to override. By default variables should be defvar'd so that the ability to customize the behaviour (even in ways that the author did not anticipate) is preserved.
I think implementations of OO programming tend to fit well with lexical scope. An object with state maps rather directly to a lexical closure.
I'm sure that the CLOS implementation in common lisp leverages lexical scope heavily. It's hard for me to imagine how that spec could be implemented with dynamic scope only, but I'm sure it's possible.