
@greg @notjack So, quick question about that. When you write a new racket collection, do you link it immediately, or do you use relative paths first, then switch for production? I’m usually stuck with relative paths for a long time before I consider making my module work as a (pushable) racket package.

(maybe because raco link
is nowhere advertised, I just learned about it from your conversation)

@jerome.martin.dev I link immediately. As a rule, I put all racket code I write in packages + collections (usually single-collection packages) and link all packages whose code I intend to edit. So the only time I require things with relative paths is when I’m making small examples that need to span files, like for bug reports and that kind of thing. Those are too tiny to justify the effort of packaging them.

I also keep as much code as possible in some subcollection with private
in its name like foo/private
, then I use#lang reprovide
to define the publicly exposed entrypoint modules of the collection(s)

so when you work on some subcollection that requires another one next to it, let’s say, package fruits
with sub-collections banana
and apple
banana
requires fruits/apple/private
Would that work?

actually what I would do is just put everything in fruits/private
so they’re all adjacent files

fruits/private/apple
, fruits/private/banana
, etc.

yeah ok, keeping the public file to a minimum

it’s less that, it’s more that now I can rearrange the public module hierarchy by just moving a bunch of tiny reprovide
files around - the actual implementation files are all in a flat directory in fruits/private
so changing the exposed hierarchy doesn’t require moving implementation files and folders

effectively, I’ve set up redirects / symlinks at the module level

for instance, in addition to fruits/private/apple
and fruits/private/banana
I would have these files:
;; fruits/main.rkt
#lang reprovide
fruits/apple
fruits/banana
;; fruits/apple.rkt
#lang reprovide
fruits/private/apple
;; fruits/banana.rkt
#lang reprovide
fruits/private/banana

I see. The only issue I have with reprovide
is that there’s no whitelisting mechanism. You can except-out
, but you cannot only-out

I think you can use only-in
for that

also, I tend to move that kind of stuff into the implementation modules by giving them submodules that provide the whitelisted exports

like, fruits/private/apple.rkt
might have this:
(provide apple? make-apple apple-chew)
(module+ for-trusted-clients
(provide unsafe-apple-chew))
... implementation ...

better be careful with apple chewing

it’s a dangerous habit

anyway, then I could have fruits/apple
reprovide only the root module and add fruits/apple/unsafe
which reprovides the for-trusted-clients
submodule

ooh, I see

or I could move them around some other way by putting the reprovide files somewhere else - that’s really the main advantage here, to let me change my mind about what modules go where in the exposed hierarchy without a bunch of headaches

@notjack how would the fruits/apple/unsafe.rkt look like - how do you reprovide submodule?

I can also have two exposed entrypoints that reprovide the same module, which is really useful when you want to change the name of a module without breaking things - you can document that the old name is deprecated but keep it around

@githree like this, I think:
#lang reprovide
(submod fruits/private/apple for-trusted-clients)

(beware: I have only written the above, not compiled it)

thanks - gives an idea though

@notjack what real package would you recommend as a reference for this kind of linking?

@githree alas I have no references, the only project I’ve actually done this on is my private general utils repository

doing things this radically is a recent experiment of mine so it hasn’t made its way into any of my open source projects yet

I guess racket/web-server is a good example https://github.com/racket/web-server

@jerome.martin.dev that’s actually a separate thing where the code is split among multiple packages for dependency reasons

within the web-server-lib/web-server
folder it looks more like a regular collection with code mixed around in various places, some of which are in a private/
subcollection but not all

Yeah, I was saying that because it sometimes uses private collections and no relative paths

oh! yeah, now I see what you mean

poking around some of the private/ files it looks like it follows the pattern where any modules that are not intended to ever be required by modules outside of the private directory are required via relative paths, but everything else is through collection paths

yes

I think that’s about what I used to do, but with more reprovides

Last question: I get the usefulness of doing that public/private separation for libraries. But does it make sense to use the same pattern for programs/executables? Are they even racket packages?

I think so, but I’m not really sure since I don’t make programs / apps / binaries / etc. nearly as often and have less of a feel for it

I’d probably approach that by making my app be a library that exports a main function / macro / lang / whatever that launches the app given some config values

Right now I’m making a program that runs in the CLI, and I’m considering making it a racket package, so that people can install it and use it directly from the racket package repository. But does that even work?

it does, there’s a way to make racket packages expose arbitrary command line tools where using the tool runs some main module specified in package metadata

there’s also raco commands

yeah, I knew about the raco command, but I was wondering if you could expose something that installs itself in the PATH

yup - I think racket-launcher-names
is the relevant info.rkt
key


nice !

it puts things into the same directory where the raco
, racket
, drracket
, etc. programs are (I think) so if that’s in your path you don’t need to add any other dirs to your path

I guess it works like that for scribble

yup!

@notjack piggybacking on your conversation above I need a clarification - if fruits/private/banana.rkt uses apple than with collection link, in fruits/private/apple.rkt it is enough to use (require fruits/private/banana)?

@githree that would work, but I try to avoid requiring /private
things as much as possible so even within fruits/private/apple.rkt
I would rather use (require fruits/banana)
than (require fruits/private/banana)
- the exception being when I really do need to require something that’s not exposed via a public api, like an internal helper module or a common implementation utility or something

ok, gotcha!

let me know how it works for ya if you try this, I’m curious

this conversation comes right in time as I am currently struggling working on a package that has so many relative paths I am lost - before that I only did smaller projects in racket

same for me x)

I’m glad I could help out :)

yeah, thanks @notjack :slightly_smiling_face:

Ok there’s something I don’t get with collections/packages. We’re supposed to put an info.rkt
file in each collection
, right? But the deps
and implies
options require a package
name. How are we supposed to tell a collection that it depends on other collections inside the same package? Maybe update-implies
?

Maybe I’m just overthinking the stuff and I just don’t need to specify any deps

@jerome.martin.dev you don’t need to say that you depend on yourself

also, raco setup --fix-pkg-deps
will fix up your deps

I just spent multiple hours creating sub folders, “info.rkt” and “main.rkt” files everywhere. I’m gonna try running raco pkg install
and CROSS FINGERS

https://racket.slack.com/archives/C06V96CKX/p1529571022000143 It sounds like @notjack is more deliberate about this, than I am. Often I go through stages: 1. Just exploring with one or more .rkt files in dir. 2. Hmm let’s git init
and save some history before trying something. 3. OK this code might be handy to someone, I’ll push it to GitHub as a public repo. 4. OK I’m willing to commit to supporting it. I’ll make a package and add to package catalog. — Often I don’t ever make it to 4. I suppose I could make the Racket package earlier — and just not add to package catalog.

Well… Crossing fingers was not enough. Everything falls appart pretty badly… :disappointed:

my interdependent collections fail to build because they cannot find the others, which are not yet installed because.. well, they’re being built.

everything gets installed first, and then built

unless you have two packages and you’ve only installed one?

I trying to install a multi-collection package, and I get a lot of “standard-module-name-resolver: collection not found”

what does the top-level info.rkt
say? what’s the directory structure?

;; info.rkt
(define collection 'multi)

the tree looks something like this:

virtual-mpu
├── asm-lang
│ ├── assemble.rkt
│ ├── info.rkt
│ ├── main.rkt
│ ├── private
│ │ ├── ...
│ ├── s-record.rkt
│ └── tests
├── cli
│ └── main.rkt
├── emulator
│ ├── main.rkt
│ ├── private
│ │ ├── gui
│ │ │ ├── ...
│ │ └── main.rkt
│ └── terminal.rkt
├── info.rkt
├── LICENSE
├── mpu-lang
│ ├── docs
│ ├── info.rkt
│ ├── main.rkt
│ ├── op-table.rkt
│ ├── private
│ │ ├── ...
│ ├── test.rkt
│ └── tests
├── README.md
└── utils.rkt

and what error messages are you getting?

mostly raco setup: error: during making for <pkgs>/virtual-mpu/asm-lang/private
raco setup: asm-lang/private/s-record.rkt:8:2: collection not found
raco setup: for module path: virtual-mpu/utils
raco setup: collection: "virtual-mpu"

a lot of’em

which means one of my (require virtual-mpu/utils)
is failing

right, there’s no virtual-mpu
collection

virtual-mpu
is just a package name, not a collection name — the collections are the subdirectories

oh, so you mean the main package cannot be its own collection?

you can either have a package represent a single collection

or you can have a package where the subdirectories are each collections

it can’t be both, because then virtual-mpu/cli/main
and cli/main
would be the same thing

so collections are not namespaced?

I’m not sure what you mean

well if I want my collections to be distinguishable from other packages, I’ll need to put them inside another dummy collection, otherwise they’ll be accessible as cli
, mpu
, utils
instead of virtual-mpu/cli
…etc

I find this a bit overwhelming to make so much subfolders

But I guess it’s the way it is. I just need to remember that a package cannot be a collection and have sub-collections at the same time

it sounds like you don’t want a multi-collection package

yeah, that’s what I just realized writing that…

you can just change to (define collection "virtual-mpu")

and keep that directory structure

alright, I still get some errors, especially concerning places where I require emulator/private
(meaning “emulator/private/main.rkt”) that is understood as “emulator/private.rkt”

is this normal behavior?

(private
is a folder but racket tries to use it as a file)

and I get errors everywhere I require mpu
instead of mpu-lang
(because I declared (define collections "mpu")
I supposed it would understand the renaming)

First, if the unquoted path contains no /, then require automatically adds a "/main" to the reference. For example, (require slideshow) is equivalent to (require slideshow/main).

ooooookkk

main.rkt
does not work for sub-collections :disappointed:

I got it compiling :smile:

now I just need to understand how to reprovide an expander with a default s-exp
reader

In other words, how to provide a custom lang so that modules can use it as #lang my-collection/my-language

for a custom reader it’s easy, but how do I provide an expander if I want the reader to be s-exp?

I tried stuff like ;; my-collection/my-language.rkt
#lang s-exp syntax/module-reader
"mpu-lang/lang.rkt"

@jerome.martin.dev to make something work as #lang mylang
, you need to either have (submod mylang reader)
or mylang/language/reader

I have a class inheriting string-snip%
. Is it possible to change the overall style (like adding borders and changing text colors)? Or do I have to reimplement draw
or use image-snip%
, pict-snip%
etc?

I tried to use set-style
directly but nothing changed

@shu—hung If you want to ignore or modify the style that the editor gives the snip, then you’d need to override on-draw
. You can chain to the string-snip%
implementation after adjusting drawing state, because string-snip%
assumes that the editor-imposed style has been installed (if I remember correctly), but be sure to restore any drawing state that you change.

@sersha42 has joined the channel

@mflatt so that is, I can override on-draw
, change relevant settings installed on dc
and call string-snip%’s on-draw
?

Yes

okay thanks :smile: