samth
2021-3-20 08:17:58

What takes forever to build?


laurent.orseau
2021-3-20 14:17:54

Is there a standard way to combine dynamic-require with a strong make-security-guard? I want to deny as much as possible, but dynamic-require still needs to use 'exists and 'read , but I’d like the code (apart from the requires) to not access the file system at all. Or is a sandbox the right tool here? (but I don’t want an evaluator, just a dynamic-require)


mflatt
2021-3-20 14:31:47

A sandbox does solve various problems with loading code, such as allowing read access to installed collections. But a sandbox might get in the way if you want the loaded code to use modules that you’ve already instantiated in a namespace.


laurent.orseau
2021-3-20 14:35:27

That may be a problem indeed. I guess I’ll go with allowing ’exists and ’read. Since I disable network access, that may be sufficient


sschwarzer
2021-3-20 18:03:14

I’m adding contracts to a module that worked before without contracts. Now, when I add a contract to a struct sort-spec (defined as (sort-spec (order field) #:transparent)), I get an error from another module that requires the module with the contracts: task-group.rkt:20:24: struct: parent struct type not defined; identifier does not name struct type information at: sort-spec in: (struct task-group-spec sort-spec (tag-key) #:transparent) context...: /home/.../collects/racket/private/define-struct.rkt:153:2 /home/.../collects/syntax/wrap-modbeg.rkt:46:4 The contract I added for sort-spec is (contract-out [sort-spec (-> symbol? symbol? sort-spec?)]) The child struct task-group-spec is defined as (task-group-spec sort-spec (tag-key) #:transparent).

I wonder what’s going on here and how to fix it?


sorawee
2021-3-20 18:05:59

Can you give a program that results in an error?


sschwarzer
2021-3-20 18:06:46

Let me try to make a simple program …


sschwarzer
2021-3-20 18:10:18

This program is enough: #lang racket/base (require "task.rkt" "task-group.rkt") The code of the modules (without the contracts) is here: https://git.sr.ht/~sschwarzer/todoreport-racket/tree/main/item/task.rkt https://git.sr.ht/~sschwarzer/todoreport-racket/tree/main/item/task-group.rkt


sschwarzer
2021-3-20 18:11:17

The provide section with the contracts is this: (provide (contract-out [sort-spec (-> symbol? symbol? sort-spec?)] [sort-spec-field (-> sort-spec? symbol?)] [sort-tasks (-> (listof task?) (listof sort-spec?) (listof task?))] [string->task (-> string? task?)] [string->tasks (-> string? (listof task?))] [task->string (-> task? string?)] [task-field (-> task? (or/c symbol? sort-spec?) any/c)] [tasks->string (-> (listof task?) string?)]) ;sort-spec sort-spec? value-sort-func )


sschwarzer
2021-3-20 18:11:47

The error occurred after adding the contract for sort-spec.


sschwarzer
2021-3-20 18:13:45

This is the first time I define contracts, so this might be a beginner mistake. :slightly_smiling_face:


jaz
2021-3-20 18:15:09

My guess, from just a glance, is that, while you’re providing sort-spec as a function (a constructor of the struct), you’re not providing the struct info itself.


sschwarzer
2021-3-20 18:16:02

@jaz How would I provide the struct info?


sorawee
2021-3-20 18:19:36

When you said:

> The provide section with the contracts is this: What file are you adding the contracts to?


sorawee
2021-3-20 18:20:07

task.rkt?


sschwarzer
2021-3-20 18:20:10

To task.rkt


sschwarzer
2021-3-20 18:20:12

Yes


sorawee
2021-3-20 18:24:51

OK, I can reproduce the error. I need to download an old version of Racket to test if it has always been an error like this. My fear is that I might have introduced a bug when I changed contract-out at some point.


sschwarzer
2021-3-20 18:25:34

In case it helps, I use Racket 8.0 cs.


jaz
2021-3-20 18:26:59

@sorawee Isn’t it just that, when the contract is added, this clause: [sort-spec (-> symbol? symbol? sort-spec?)] just provides the contractor and not the struct type transformer?


jaz
2021-3-20 18:27:44

Which has been a pain point (at least for me) for a long time.


sorawee
2021-3-20 18:28:44

I don’t know! And even if it does, it doesn’t look like @sschwarzer uses the compile-time binding of sort-spec anywhere else…


jaz
2021-3-20 18:30:04

The use is in task-group.rkt , where sort-spec is the parent struct type of task-group-spec. If that file is only importing the constructor, then the struct definition won’t work.


sschwarzer
2021-3-20 18:30:20

@jaz I guess by contractor you mean constructor? Can I provide the struct type transformer (whatever this is :wink:) somehow as a workaround?


jaz
2021-3-20 18:30:40

Sorry — yes, that was a typo.


sorawee
2021-3-20 18:30:58

Ah, indeed


jaz
2021-3-20 18:32:17

The easiest way to handle this case (which will work if you don’t need to make the struct type transformer public) would be to create two separate modules — one that exports the sort-spec struct without contracts and one that exports the contracted definitions that you want. Then, task-group.rkt would require the former.


sschwarzer
2021-3-20 18:34:17

@jaz Then it’s probably easier for now to leave out the contract for sort-spec for now. :slightly_smiling_face:


sorawee
2021-3-20 18:34:18

I think using things like struct/contract will also work



jaz
2021-3-20 18:35:36

Oh, good point.


sorawee
2021-3-20 18:35:47

struct-guard/c can also be used.


sschwarzer
2021-3-20 18:35:59

@jaz Is the struct type transformer the macro that converts the struct definition as written in the source code to the constructor, predicate, accessors etc.?


jaz
2021-3-20 18:36:43

sorawee
2021-3-20 18:37:30

So, when you (provide sort-spec), you are providing two things at once:

  1. The constructor sort-spec
  2. The information about sort-spec at compile-time.

sorawee
2021-3-20 18:38:19

In your:

(struct task-group-spec sort-spec ; `tag-key` is a string for the tag key, say, "due". `#f` if `field` isn't a ; 'tags field. (tag-key) #:transparent) you are using the information of sort-spec at compile-time.


sorawee
2021-3-20 18:39:14

So there are a couple of ways to fix this problem.


sschwarzer
2021-3-20 18:40:35

@sorawee struct/contract for defining sort-spec works.


jaz
2021-3-20 18:41:53

I assume the contract boundary in that case is the constructor/accessor/mutator itself, right?


jaz
2021-3-20 18:42:55

Meaning that the contract would be enforced even within the defining module.


sorawee
2021-3-20 18:43:01

Yep


sschwarzer
2021-3-20 18:43:38

@jaz As for define/contract , right?


jaz
2021-3-20 18:43:45

Yep


jaz
2021-3-20 18:44:16

Whereas, when you use provide/contract you make the module the contract boundary.


sorawee
2021-3-20 18:44:37

Oh oh oh


sschwarzer
2021-3-20 18:44:51

@sorawee In case you enter a ticket on Github, can you give me the id, so I can add the URL to a comment? Also, if you want to mention me on Github, my Github account is also sschwarzer .


sorawee
2021-3-20 18:44:52

I completely forgot that contract-out supports struct


jaz
2021-3-20 18:45:30

It does, but does it allow opacity/partial opacity?


jaz
2021-3-20 18:45:54

Just because I want to export the constructor does not mean I want to export the accessors.


sorawee
2021-3-20 18:46:03

That’s a good point.


sschwarzer
2021-3-20 18:46:17

I simply thought that the constructor behaves like a function and would follow the same rules when using contract-out. :slightly_smiling_face:


jaz
2021-3-20 18:46:32

(In my case, when I want to export the struct type info, it’s for match expansion reasons.)


jaz
2021-3-20 18:46:56

I’ve run into this same issue many times over.


sschwarzer
2021-3-20 18:47:00

@jaz Yes, about the accessors. I may only want to use them internally in the module where the struct is defined.


sorawee
2021-3-20 18:47:21

Just to finish what I was typing before:

Another possibility is that, you can explicitly decouple the compile-time information of sort-spec from the constructor sort-spec. This can be done by specifying an option to struct (I believe it’s #:name but I could be wrong) and provide both. Then, change the task-group-spec definition to use the new compile-time information.


sschwarzer
2021-3-20 18:49:08

@sorawee @jaz Just for info: struct/contract doesn’t offer all the arguments as struct (according to the documentation), so it’s not always a usable workaround (apart from where the contracts are enforced). For my particular case, struct/contract should be ok for now.


sorawee
2021-3-20 18:50:37

Actually, I’d advise against struct/contract. I forgot that the struct clause in contract-out exists. That would be a better choice for your program, I think.


sschwarzer
2021-3-20 18:54:37

@sorawee Ah, I see, in https://docs.racket-lang.org/guide/contracts-struct.html . I hadn’t read this part of the docs yet or forgot it. :slightly_smiling_face: So I’ll try to use this.

Does that mean that contract-out isn’t supposed to be used with struct constructors (used as a function, like I did) to begin with?


sorawee
2021-3-20 18:55:54

Yeah, that’s the part that I am not sure. Perhaps contract-out could be smarter and reattach the compile-time information.


sorawee
2021-3-20 18:57:06

I just tested against Racket 7.7, which is the version before I modified the interaction between contract-out and structs. The program fails similarly, so I think it has always been failing.


sschwarzer
2021-3-20 18:57:36

I had read the contract documentation in the Racket Guide when I started with Racket, but at that time I had very little actual experience and forgot most of the chapter. Now I’m adding contracts and was reading the Guide again and applying it.


sschwarzer
2021-3-20 18:59:54

@sorawee So maybe the limitation should be documented (if it isn’t already and I missed it)? On the other hand, if it’s not too difficult to export the compile-time info, this should of course be easier for users. On the other hand, if that’s tricky it maybe better to stick with the API specifically for structs.


sschwarzer
2021-3-20 19:07:58

@sorawee @jaz Thanks for your help. :+1:


sorawee
2021-3-20 19:09:02

(require racket/contract) (provide (contract-out [sort-tasks (-> (listof task?) (listof sort-spec?) (listof task?))] [string->task (-> string? task?)] [string->tasks (-> string? (listof task?))] [task->string (-> task? string?)] [task-field (-> task? (or/c symbol? sort-spec?) any/c)] [tasks->string (-> (listof task?) string?)]) value-sort-func (rename-out [sort-spec-contracted sort-spec] [sort-spec-field-contracted sort-spec-field])) (module sort-spec racket/base (provide (struct-out sort-spec)) (struct sort-spec (; 'asc for ascending order, 'desc for descending order order ; Task field to sort by, say, 'creation-date field) #:transparent)) (module sort-spec-contracted racket/base (require racket/contract (submod ".." sort-spec)) (provide (contract-out (struct sort-spec ([order symbol?] [field symbol?]))))) (require 'sort-spec (only-in 'sort-spec-contracted [sort-spec sort-spec-contracted] [sort-spec-field sort-spec-field-contracted]) racket/list racket/match racket/port racket/string)


sorawee
2021-3-20 19:10:00

Here’s an approach that @jaz mentioned earlier, I believe, and this will be the closest to what you intended to do earlier.


sorawee
2021-3-20 19:12:05

The submodule sort-spec simply provides sort-spec uncontracted, so that the main module can use sort-spec uncontracted.

The submodule sort-spec-contracted adds full contracts to sort-spec.

The main module has an access to both the contracted and uncontracted versions. You can use uncontracted version internally in the module, but when you want to provide them out, you use the contracted version, and you can do so partially (don’t need to provide all accessors)


sorawee
2021-3-20 19:13:03

Racket should definitely provide a syntactic construct that helps with this process.


sschwarzer
2021-3-20 19:13:58

@sorawee Far too much code for what I would like to have. :wink: I’ll have a look at the struct section in the contracts documentation and use that.


sschwarzer
2021-3-20 19:15:04

If the documented contracts struct stuff doesn’t work with inheritance either, I can still fall back to not using contracts for the struct constructor.


samth
2021-3-20 21:10:44

If all you want to do is provide the constructor with the struct info but not one of the accessors then struct-out plus except-out should be pretty simple


sorawee
2021-3-20 21:15:58

Unfortunately, except-out doesn’t seem to work with contract-out.


sorawee
2021-3-20 21:16:08

Also, would be nice to have only-out


sorawee
2021-3-20 21:23:57

> Unfortunately,  except-out doesn’t seem to work with contract-out. Seems to be due to how the contracted id is not free-id=? with the exception ids.


sschwarzer
2021-3-20 22:59:37

Is there a naming convention for Racket to denote a name is used only internally in a module? (I know that the visibility to clients is controlled by provide , but I would like to make the internal use for some names also visible in these names.)


kellysmith12.21
2021-3-20 23:15:01

I’ve never seen private bindings spelled differently, in Racket.


kellysmith12.21
2021-3-20 23:16:49

You could borrow the preceding underscore from Python: my-public-function and _my-private-function. (or, I suppose you could make that a preceding dash, since Racket is traditionally kebab-case)


sschwarzer
2021-3-20 23:17:31

Or maybe a /private suffix (or other term)?


kellysmith12.21
2021-3-20 23:18:04

That makes it clear what you mean, so that’s great.


sschwarzer
2021-3-20 23:50:15

I wonder if I understand the struct form in contract-out. My provide is (provide (contract-out ;[sort-spec (-> symbol? symbol? sort-spec?)] [sort-spec-field (-> sort-spec? symbol?)] [sort-tasks (-> (listof task?) (listof sort-spec?) (listof task?))] [string->task (-> string? task?)] [string->tasks (-> string? (listof task?))] [task->string (-> task? string?)] [task-field (-> task? (or/c symbol? sort-spec?) any/c)] [tasks->string (-> (listof task?) string?)] (struct sort-spec (order symbol?) (field symbol?))) value-sort-func ) (although only the (struct sort-spec ...) should be interesting here.

Further down in the module, sort-spec is defined as ; Order-symbol Task-field-symbol -> Sort-spec (struct sort-spec (; 'asc for ascending order, 'desc for descending order order ; Task field to sort by, say, 'creation-date field) #:transparent) When requiring the module, I get the message task.rkt:18:23: contract-out: malformed struct field at: order in: (contract-out (sort-spec-field (-> sort-spec? symbol?)) (sort-tasks (-> (listof task?) (listof sort-spec?) (listof task?))) (string->task (-> string? task?)) (string->tasks (-> string? (listof task?))) (task->string (-> task? string?)) (task-field (-> t... context...: /home/.../collects/racket/contract/private/provide.rkt:596:14: try-next /home/.../collects/racket/contract/private/provide.rkt:548:0: true-provide/contract /home/.../collects/racket/contract/private/out.rkt:11:3 /home/.../collects/racket/provide-transform.rkt:65:2: pre-expand-export /home/.../collects/racket/private/reqprov.rkt:732:2 /home/.../collects/syntax/wrap-modbeg.rkt:46:4


sorawee
2021-3-20 23:50:56

You need another parenthesis


sorawee
2021-3-20 23:51:12

(struct sort-spec ((order symbol?) (field symbol?)))


sschwarzer
2021-3-20 23:52:48

Thanks, that’s better. :slightly_smiling_face: Now I get /home/.../collects/racket/contract/private/provide.rkt:382:8: module: identifier already defined at: provide/contract-id-sort-spec-field in: (define-syntaxes (provide/contract-id-sort-spec-field) (make-provide/contract-arrow-transformer (quote-syntax provide/contract-id-sort-spec-field) (quote-syntax idZ66) (quote-syntax sort-spec-field) (quote-syntax idX64) (quote-syntax idY65) #s(valid-app...


sorawee
2021-3-20 23:53:50

Perhaps comment out [sort-spec-field (-> sort-spec? symbol?)]?


sschwarzer
2021-3-20 23:55:39

Yes, that works. :+1: My understanding is that this should be implied by the struct in contract-out?


james.ng251
2021-3-21 05:10:04

james.ng251
2021-3-21 05:10:47

I’m using drRacket. Anyone know why the windows 10 version racket 8.0 not working when testing images ?


sorawee
2021-3-21 05:11:04

This is a known issue that was fixed already


sorawee
2021-3-21 05:11:47

sorawee
2021-3-21 05:12:37

So you can either downgrade to 7.9 or download a snapshot version (http://snapshot.racket-lang.org/) if you can’t wait for a new version.


james.ng251
2021-3-21 05:15:56

thanks so uninstall/reinstall 7.9 huh.


jesse697
2021-3-21 05:43:19

@samth what I wanted to say was that taking a minimal Racket and then installing the handful of packages I need. They end up pulling in a lot of dependencies, so I end up fetching and building a lot of what you find in a full Racket install anyway.