chansey97
2021-8-2 07:25:48

Does racket support access to a module’s binding by path instead of rename-in ? e.g. (my-module:my-procedure 123)


sorawee
2021-8-2 07:34:44

No, but you can simulate it using prefix-in


sorawee
2021-8-2 07:35:11

E.g.,

(require (prefix-in list: racket/list)) (list:first '(1 2 3))


chansey97
2021-8-2 07:41:33

Thanks! @sorawee


chansey97
2021-8-2 07:50:36

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.


chansey97
2021-8-2 07:54:57

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?


chansey97
2021-8-2 07:56:38

Another approach is OOP, but it seems more heavyweight…


chansey97
2021-8-2 08:07:14

Or using parameter .


sorawee
2021-8-2 08:10:18

That sounds like what unit is for



chansey97
2021-8-2 08:14:18

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.


sorawee
2021-8-2 08:16:14

I don’t disagree with that


popa.bogdanp
2021-8-2 09:02:50

The web-server package allows you to configure certain things using units.


popa.bogdanp
2021-8-2 09:03:12

<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.


laurent.orseau
2021-8-2 09:27:02

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


laurent.orseau
2021-8-2 09:28:24

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


laurent.orseau
2021-8-2 09:30:31

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


chansey97
2021-8-2 12:02:43

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.



laurent.orseau
2021-8-2 14:04:30

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.


chansey97
2021-8-2 14:10:25

@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 .


laurent.orseau
2021-8-2 14:14:32

you can use prefix-in (or rename-in for filtered-in )


laurent.orseau
2021-8-2 14:15:23

Or if you know what these bindings are, and you want to exclude some of them, you can use only-in or except-in


soegaard2
2021-8-2 14:16:47

Would it work to make a new file AB.scm and simply pasting the contents of A.scm and B.scm into AB.scm ?


chansey97
2021-8-2 14:20:29

@laurent.orseau they are scheme files, not a racket module. I just read the docs, include has no except-in argument.


soegaard2
2021-8-2 14:20:55

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!.


chansey97
2021-8-2 14:26:20

@soegaard2 Seems a good solution, if all the procedures defined by lambda:thinking_face:


chansey97
2021-8-2 14:29:49

Oh..no, if B.scm redefined some macros in A.scm?


soegaard2
2021-8-2 14:31:08

Odds are low for that happening. Worry about it, if you see it only.


chansey97
2021-8-2 14:34:02

Yes. I see it…


chansey97
2021-8-2 14:34:47

The B.scm redefined some macros in A.scm,


soegaard2
2021-8-2 14:35:38

Maybe a different strategy is needed?


laurent.orseau
2021-8-2 14:36:05

Can you write an intermediates racket files that does the import-from-scheme-but-provide-to racket?


laurent.orseau
2021-8-2 14:36:23

maybe automatically generated


ben.knoble
2021-8-2 14:36:44

^ Something like (include file) and (provide (all-defined-out)) ?


chansey97
2021-8-2 14:37:49

(include file) doesn’t support redefine, unless in racket/load, but racket/load can not export bindings.


ben.knoble
2021-8-2 14:38:14

two separate files: A.rkt includes only A.scm


ben.knoble
2021-8-2 14:38:45

then you can have one AB.rkt that requires the racket files, using all the exclude-in or whatever you want


ben.knoble
2021-8-2 14:38:49

maybe? this assumes you don’t want the redefinitions to propagate backwards, which i don’t see how to do anyway


soegaard2
2021-8-2 14:39:09

If you only see the problem in one set of files, then I would rewrite those manually.


chansey97
2021-8-2 14:41:00

@ben.knoble Good solution. Let me think about it for a while, because there are some other restrictions.


chansey97
2021-8-2 14:53:43

A.scm will use these redefined procedures in itself. So unfortunately….it may what you said “redefinitions to propagate backwards”.


chansey97
2021-8-2 14:55:24

> 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.


laurent.orseau
2021-8-2 15:01:06

Can you port A.scm and B.scm to racket first, instead?


chansey97
2021-8-2 15:06:57

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.


chansey97
2021-8-2 15:11:03

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.


laurent.orseau
2021-8-2 15:11:46

So you are allowed to modify A.scm then?


chansey97
2021-8-2 15:13:47

I can modify A.scm of course. I just want to know if there is a way to not modify A.scm in Racket.


laurent.orseau
2021-8-2 15:14:06

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?


laurent.orseau
2021-8-2 15:14:25

Well, A.scm is scheme, so that makes things a little more complicated. If it were Racket modules it would be easier.


chansey97
2021-8-2 15:21:23

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).