Welcome to DrRacket, version 8.13 [cs].
Language: r6rs, with debugging; memory limit: 8192 MB.
. lambda: unbound identifier;
also, no #%app syntax transformer is bound in the transformer phase in: lambda
Interactions disabled: r6rs does not support a REPL (no #%top-interaction)
Explanation: Racket implements what is called âexplicit phasingâ, which requires you to specify precisely what to import at which phase. Most other Râ¶RS implementations instead adopt a strategy called âimplicit phasingâ, effectively making each export available at all phases. This is a caveat portable Râ¶RS programs must account for.
yes the original code working racket code was using for-syntax. (i'm porting code from Racket to R6RS modules,also code from Kawa and Guile modules to Racket/R6RS)
all the 2 answers works, strangely can not find the doc for (import (for clause and adding or not (6) that should be RnRS version does not matter.
The reference on Râ¶RS is just, well, Râ¶RS itself. You should read that to find language specification. For example, library forms are specified in Chapter 7.
yes i did not noticed it in R6RS. Also as porting code from Kawa/R7RS but i can't find the (import (for ... feature anymore in R7RS doc.
Did they really remove it or again i missed it?
The phase system (or any kind of serious macro system) is nonexistent in Râ·RS-small; not sure about Râ·RS-large, but I think they favor implicit phasing, and existing Râ·RS implementations likely adopt that.
now in R6RS with Racket i have this part of code that no more works, i'm not sure it is the same probleme, seems not, and this was workin in Racket,Guile/R6RS,Kawa/R7RS:
#!r6rs
(library (def)
(export def
if-defined)
(import (rnrs base (6)) ;; i added version (6) but original discourse answer was without
(rnrs syntax-case (6))
(for (rnrs base (6)) expand) ; import at expand phase (not run phase)
(for (rnrs syntax-case (6)) expand)
(for (only (racket) identifier-binding) expand))
(define-syntax if-defined
(lambda (stx)
(syntax-case stx ()
[(_ id iftrue iffalse)
(let ([exist-id (identifier-binding #'id)])
;;(display "id=") (display #'id) (newline)
;;(display "if-defined : exist-id=") (display exist-id) (newline) (newline)
(if exist-id #'iftrue #'iffalse))])))
;; scheme@(guile-user)> (def (foo) (when #t (return "hello") "bye"))
;; scheme@(guile-user)> (foo)
;; "hello"
;; (def x)
(define-syntax def
(lambda (stx)
(syntax-case stx ()
;; multiple definitions without values assigned
;; (def (x y z))
;; TODO: remove? redundant with (declare x y z)
((_ (var1 ...)) #`(begin (define var1 '()) ...))
;; (def (foo) (when #t (return "hello") "bye"))
;; ((_ (<name> <arg> ...) <body> <body>* ...)
;; (let ((ret-id (datum->syntax stx 'return)))
;; #`(define (<name> <arg> ...)
;; (call/cc (lambda (#,ret-id) <body> <body>* ...)))))
((_ (<name> <arg> ...) <body> <body>* ...)
(let ((ret-id (datum->syntax stx 'return))
(ret-rec-id (datum->syntax stx 'return-rec)))
#`(define (<name> <arg> ...)
(call/cc (lambda (#,ret-rec-id)
(apply (rec <name> (lambda (<arg> ...)
(call/cc (lambda (#,ret-id) <body> <body>* ...)))) (list <arg> ...)))))))
;; single definition without a value assigned
;; (def x)
((_ var) #`(define var '()))
;; (def x 7)
((_ var expr) #`(define var expr))
((_ err ...) #`(syntax-error "Bad def form"))
)))
) ; end library
the problem is with 'def' ,not 'if-defined' which is not used in this file,
i got this error when running the test example:
the goal is to allow 'return' and 'return-rec' in a 'define'-ed procedure, this used to works still many years in Racket/Guile/Kawa....
Welcome to DrRacket, version 8.13 [cs].
Language: r6rs, with debugging; memory limit: 8192 MB.
> datum->syntax
#<procedure:r6rs:datum->syntax>
> (def (foo) (when #t (return "hello") "bye"))
. . datum->syntax: expected argument of type <identifier?>; given: #<syntax:46-interactions from an unsaved editor:5:2 (def (foo) (when #t (return "hello") "bye"))>
> when
. . when: undefined;
cannot reference an identifier before its definition
> (def (bar) '())
. . datum->syntax: expected argument of type <identifier?>; given: #<syntax:46-interactions from an unsaved editor:10:2 (def (bar) (quote ()))>
> def
. def: bad syntax in: def
seems datum->syntax act differently in R6RS/Racket than before in Racket and no more accept my arguments.
The error says the first argument of (R^RS) datum->syntax must be an identifier.
You gave it a syntax object with (def (foo) ...).
The R6RS docs:
(datum->syntax template-id datum)ââ procedure
Template-id must be a template identifier and datum should be a datum value. The datum->syntax procedure returns a syntax-object representation of datum that contains the same contextual information as template-id, with the effect that the syntax object behaves as if it were introduced into the code when template-id was introduced.
i had read the doc. Code worked without modification in Racket, Guile but without R6RS because the R6RS implementation of Guile has some problems,Kawa with R7RS support from kawa. Now when i modify it by changing stx in (syntax stx) there is no more error but it fails later:
Welcome to DrRacket, version 8.13 [cs].
Language: r6rs, with debugging; memory limit: 8192 MB.
> (def (foo) (when #t (return "hello") "bye"))
def.scm : def : ret-id = .#<syntax return>
def.scm : def : ret-rec-id = .#<syntax return-rec>
> (foo)
. . return: undefined;
cannot reference an identifier before its definition
i try to port my code to R6RS or R7RS to make it more easy to port to other scheme implementation but perheaps this special procedure can not be done in R6RS. Kawa and Guile are not completely R6RS compatible so there is some mix scheme/R6RS and perheaps RAcket/R6RS is good and reject this code.
The identifier stx appears in your code and has the context of the macro definition.
I think, your intention was to use the context of the macro call.
The macro call is (def ...) so you can use the (car (syntax-e stx)) to get the def identifier.
Note:
The #lang r6rs implementation is a strict implementation of the R6RS specification.
That means, that it implements R6RS without any extensions. The plus side is that a program that runs in #lang r6rs will run on all other R6RS implementions.
Most R6RS implementations are more lax and implement extenstions to the specification.
One such example is allowing the first argument of datum->syntax to be a non-identifier.
Arguing that a program runs in Kawa or Guile doesn't imply that the program in question follows the R6RS specification.
Compare the situation to the identifier problem from the other day. Most implementations allow more identifiers than a strict reading of the specification does.
i did not wrote the code myself ,someone else do it. I just modify it to allow return-rec (that return from all recursive calls)
what do you mean by 'syntax-e' ? i suppose there is a typo but i do not know how to correct it.
yes about kawa and guile, i have been warned to do not use guile/r6rs so i use guile module system ,about kawa i'm not even know if there is a support for r6rs , only it worked with a r7rs-like syntax in kawa.Sorry for the confusion in the previous post about that.
The Racket function syntax-e unpacks a syntax object.
The function syntax->datum repeatedly calls syntax-e.
Checking R6RS I see it has no syntax-e.
So use pattern matching to get the def identifier instead.
the procedure foo has well escaped with return and return value "hello" without executing "bye".
I did not see why in R6RS it make so much difference in datum->syntax ?
i could try importing datum->syntax from Racket, should not be possible in R6RS , this is a whole system, i understand the notion syntax is different in R6RS than Racket (unless internally there is some equivalence....)
Other solution keep this Racket module def and use it in R6RS code, as a module perheaps it should have more chance to coexist...
Third solution ,drop support for R6RS , this the partial way i do it in Guile (bug in Guile R6RS) and Kawa (mox R7RS/Kawa) anyway the code performed well in Racket/Guile/Kawa. I just modularize it in Guile and Kawa and tried to make it R6RS the module way for portability.
Well if i make it modularized in Racket this is enought for me to be satisfied.
If there is no side effect i will continue porting the code to R6RS and mixing non-compatible procedures written in Racket. I think this one was the hardest one ,there should not be too much others.
better way is to install the Racket module def with the GUI install package or in command line and import it in the R6RS code, then the R6RS code can be installed with plt-r6rs:
main.rkt in def directory:
#lang reprovide
"def.scm"
;; install reprovide lang package !