Does racket support access to a module’s binding by path instead of rename-in
? e.g. (my-module:my-procedure 123)
No, but you can simulate it using prefix-in
E.g.,
(require (prefix-in list: racket/list))
(list:first '(1 2 3))
Thanks! @sorawee
Is there any Racket idiom about switching implementations? For example, suppose I have two modules moduleA.rkt
and moduleB.rkt
, they have the same interfaces (i.e. procedures). moduleC.rkt
will use these interfaces, but I don’t want to rely on concrete implementations (i.e. in moduleC.rkt
I don’t want (require "moduleA.rkt")
or (require "moduleB.rkt")
). I hope that end users can choose these two implementations. Thanks.
In SML, they have module signatures and functors. It seems that the correspondence of these features (SML signatures and functors) is unit system in Racket? So we must use unit system?
Another approach is OOP, but it seems more heavyweight…
Or using parameter
.
That sounds like what unit
is for
unit is great, but it seems very few people know how to use… I haven’t seen any package that uses unit system
as a user configuration.
I don’t disagree with that
The web-server package allows you to configure certain things using units.
<https://docs.racket-lang.org/reference/struct-generics.html|Generics >are also available and more commonly used, though they’re not exactly what you asked for.
You can also mimic units by having an “interface” file that provides identifiers (with setters, or as parameters), and the “implementation” files set these identifiers to their values
This can be combined with dynamic-require
so you don’t rely on a particular implementation, and the latter can even be chosen while the program runs
The “interface” file can also just export a struct and an empty singleton, and the “implementation” files instantiate the struct with functions and stuff and set the singleton to an instance
Does Racket have any mechanism that allows us to “redefine” in a module? https://docs.racket-lang.org/reference/load-lang.html\|racket/load seems a solution, but bindings cannot be exported from the module using provide.
Related, but maybe not what you are looking for: https://docs.racket-lang.org/reference/eval.html#%28def._%28%28quote._~23~25kernel%29._compile-enforce-module-constants%29%29
What do you mean by redefine? Possibly not what you’re asking, but dynamic-require
returns values, which don’t need to be bound to specific ids in the calling module.
@soegaard2 Thanks. But this is beyond the scope of my knowledge.
@laurent.orseau I mean, for example, I have two .scm
files: A.scm
and B.scm
(Yes, they are Scheme files, but they 100% compatible with racket). I’d like to include
these two files in a Racket module and export some bindings of them. Unfortunately B.scm
redefined some procedures in A.scm
.
you can use prefix-in
(or rename-in
for filtered-in
)
Or if you know what these bindings are, and you want to exclude some of them, you can use only-in
or except-in
Would it work to make a new file AB.scm and simply pasting the contents of A.scm and B.scm into AB.scm ?
@laurent.orseau they are scheme files, not a racket module. I just read the docs, include
has no except-in
argument.
Just thinking aloud: The problem you experience is that (define a “A”) is “constant”.
However, in
(define a "A") (set! a a)
the variable a
is no longer a constant.
So… maybe you could define a variant of define, say, define!
that simply expands to
(begin (define a "A") (set! a a))
And then use some trickery to make define
in A.scm and B.scm to use define!
.
@soegaard2 Seems a good solution, if all the procedures defined by lambda:thinking_face:
Oh..no, if B.scm
redefined some macros in A.scm
?
Odds are low for that happening. Worry about it, if you see it only.
Yes. I see it…
The B.scm
redefined some macros in A.scm
,
Maybe a different strategy is needed?
Can you write an intermediates racket files that does the import-from-scheme-but-provide-to racket?
maybe automatically generated
^ Something like (include file)
and (provide (all-defined-out))
?
(include file)
doesn’t support redefine, unless in racket/load
, but racket/load
can not export bindings.
two separate files: A.rkt
includes only A.scm
…
then you can have one AB.rkt
that require
s the racket files, using all the exclude-in
or whatever you want
maybe? this assumes you don’t want the redefinitions to propagate backwards, which i don’t see how to do anyway
If you only see the problem in one set of files, then I would rewrite those manually.
@ben.knoble Good solution. Let me think about it for a while, because there are some other restrictions.
A.scm
will use these redefined procedures in itself. So unfortunately….it may what you said “redefinitions to propagate backwards”.
> Maybe a different strategy is needed? Yes. May have to “make a new file AB.scm and simply pasting the contents of A.scm and B.scm into AB.scm” as just you said.
Can you port A.scm and B.scm to racket first, instead?
A.scm is a whole project. B.scm want to modify some A.scm’s code to add some features. For example (a real example which I am doing): A.scm = mk.scm (minikanren core) B.scm = tabling.scm (adding tabling feature to mk.scm, tabling.scm redefined some procedures and macros in mk.scm)
What should we do if we’d like to port it to Racket? It seems that the only way is to merge them manually, i.e. mk.scm + mk.scm => mk-with-tabling.rkt, by copy/paste. Racket doesn’t support incremental modification (redefine) in a module.
From a development perspective, mk.scm and tabling.scm should be merged, they are one whole concept. But from the perspective of teaching/learning, spliting mk.scm and tabling.scm has benefit, because we can easily see which codes need to be modified when adding tabling features.
So you are allowed to modify A.scm then?
I can modify A.scm of course. I just want to know if there is a way to not modify A.scm in Racket.
If so, if it’s for teaching purposes, then you could put the forms you want to replace (with B’s) into A2.scm, and then just comment out a require from either A2.scm or from B.scm?
Well, A.scm is scheme, so that makes things a little more complicated. If it were Racket modules it would be easier.
Scheme is running in top level and it supports incremental modification (i.e. redefine). Racket also has a top level REPL and racket/load
, which can support incremental modification as well. But I want more. I hope Racket module also supports incremental modification (just in one module, no need incremental modification between modules).