theau.poulat
2020-9-22 07:29:47

@theau.poulat has joined the channel


wmblackerby
2020-9-22 15:53:28

@wmblackerby has joined the channel


kian.melhus
2020-9-22 16:39:08

@kian.melhus has joined the channel


chansey97
2020-9-22 20:21:19

I have a question about Racket’s <https://docs.racket-lang.org/reference/load-lang.html|load language>. Is this a bug for require in load language?

For example, I have the following directory structure and files: . ├─load-dir │ │ main.rkt │ │ │ └─a-lib │ a-lib.rkt │ util.rkt │ main.rkt #lang racket/load (require r5rs) (require "./a-lib/a-lib.rkt") a-lib.rkt #lang racket/load (require r5rs) (display "a-lib enter\n") (require "util.rkt") util.rkt #lang racket/load (require r5rs) (display "util enter\n") Then I run the main.rkt in DrRacket, but the following error occurred: a-lib enter . a-lib\a-lib.rkt:5:9: a-lib\a-lib.rkt:5:9: cannot open module file module path: #&lt;path:E:\work-pl\racket\code\module\load-language\load-dir\util.rkt&gt; path: E:\work-pl\racket\code\module\load-language\load-dir\util.rkt system error: The system cannot find the file specified.; errid=2 in: #&lt;path:E:\work-pl\racket\code\module\load-language\load-dir\util.rkt&gt; To my knowledge, the require should be based on the relative path of the current file which being loaded rather than the working directory of the initial file.

Is that right?

Thanks.


sorawee
2020-9-23 00:03:39

Well, racket/load is pretty much the REPL. The concept of “file” is weird there, so I wouldn’t be surprised if it doesn’t work as you expect. The real question is why are you using it? It’s warned pretty clearly in the doc that:

> For these reasons, use racket/load for interactive exploration of top-level forms only, and not for constructing larger programs.


sorawee
2020-9-23 00:04:06

Also, I don’t think this is a #beginners question.


sorawee
2020-9-23 00:04:51

Though I guess no one cares about asking in the right channel anyway, so perhaps it’s fine.


samth
2020-9-23 01:20:32

require through multiple levels of #lang racket/load is not a good idea and is unlikely to work reliably


chansey97
2020-9-23 01:21:05

I use racket/load because racket/load seems to be able to simulate a poor man module system. Scheme’s R5RS specification has no module system, all the programs run at the top level.


samth
2020-9-23 01:22:15

If you want to use load, then just use load for everyting.


chansey97
2020-9-23 01:22:42

For example, I have some pure R5RS Scheme code and I want to play with them in Racket. Or I’d like to write some large portable programs in pure R5RS (splitting a large program into different files).


chansey97
2020-9-23 01:36:05

My current workaround is to create a manifest file for each poor-man module.

Something like: . ├─my-scheme-workspace │ │ poor-man-module.scm │ │ │ └─a-lib │ a-lib.manifest │ a-lib.scm │ util.scm \| │ └─b-lib │ b-lib.manifest │ b-lib.scm │ util.scm │ │ └─my-project │ main.scm │ a-lib.manifest ("a-lib.scm" "util.scm") b-lib.manifest ("b-lib.scm" "util.scm") main.scm (load "../poor-man-module.scm") (load-module "../a-lib") (load-module "../b-lib") ;; ... code here poor-man-module.scm ;; Poor man module system ;; R5RS has no module system, so make a poor man module system. (define (load-module mod) (define (mod-&gt;name mod) (letrec ((mod-&gt;name-iter (lambda (i) (if (char=? (string-ref mod i) #/) (substring mod (+ i 1) (string-length mod)) (mod-&gt;name-iter (- i 1)))))) (mod-&gt;name-iter (- (string-length mod) 2)))) (for-each load (with-input-from-file (string-append mod "/" (mod-&gt;name mod) ".manifest") (lambda () (map (lambda (x) (string-append mod "/" x)) (read))))) ) The code above works fine in plt-r5rs, no Racket features involved.

The advantage of this approach is that the poor man module (yes, they are all top level programs) supports redefinition, as opposed to Racket’s module system.


chansey97
2020-9-23 01:38:00

But #lang racket/load seems more flexible. To be honest, I accidentally found this feature in Racket :joy:.


chansey97
2020-9-23 02:03:17

In fact, I have given up the racket/load approach because it is not portable.

I’m just curious about whether <https://racket.slack.com/archives/C09L257PY/p1600806079027600|the require problem> above is a bug, since load-relative works fine in racket/load.


samth
2020-9-23 02:56:54

Why have manifests and not just a call to load?


chansey97
2020-9-23 03:23:13

@samth There are three main reasons:

  1. A module may involve many sub-files. It is convenient to use the list in the manifest to record these sub-files.

  2. Because of redefinition, the order of sub-files loading is sensitive, so must use a list to record.

  3. The list in the manifest may be reused in multiple places. for example:

Assuming b-lib depends on a-lib, in order to test b-lib, we just create a test.scm in b-lib and (load-module "../a-lib"):

b-lib/test.scm (load "../poor-man-module.scm") (load-module "../a-lib") (load-module "../b-lib") ;; ... code here Otherwise we must: b-lib/test.scm (load "../a-lib/a-lib.scm") (load "../a-lib/util.scm") ;; ... code here When there are many sub-files, the screen will be messy.


samth
2020-9-23 04:12:35

But shouldn’t “a-lib.scm” load the relevant “util.scm” file?


samth
2020-9-23 04:12:44

Anyway, this is why load is bad.


soegaard2
2020-9-23 04:31:29

@chansey97 Not tested, but would using #lang r5rs combined with (#%require ...) work differently?