
Yup, 8.0 is missing some functionality for cross-compilation to work in general, but 8.1 will have it

nice! sounds good. I’ll take a look at the blog post, but I’ll probably wait till 8.1 is out to actually do this. For now I’ll stick with my current setup (run tests etc. in a GitHub Action using Linux, but do the build on the FreeBSD instances)

Hi All,
A new section of my macro tutorial have been written. It’s section 8 in which I in an informal way attempt to go through a “design recipe” for writing simple macros. I’ll make the steps more explicit in section 9.
Comments on both contents and grammar are highly appreciated.
/Jens Axel

Seen on https://docs.racket-lang.org/reference/attaching-contracts-to-values.html?q=contract-out#%28form._%28%28lib._racket%2Fcontract%2Fbase..rkt%29._contract-out%29%29\|contract-out: > The module that defines the provided variable is expected to meet the positive (co-variant) positions of the contract. What does this mean precisely?

I guess it means it must follow the order of the arguments in the header, but what meaning do ‘positive’ and ‘co-variant’ bear here?

Followed by > Each module that imports the provided variable must obey the negative (contra-variant) positions of the contract. So err… I’m not sure anymore

That looks quite good :slightly_smiling_face: Some constructive remarks if I may: • The reminder is not clear: “The idea is to write A…”. Do you mean “The idea is the the user writes A, but the compiler should turn it into B”? • The first figure doesn’t render neatly on my screen. • it’s unclear what it’s doing here. Maybe introduce it? Do we have source=A, and B=…? • There’s nothing after —>eval, is that intended? Maybe "…" • “buried [at a particular place] in a very large syntax object [(or syntax tree)] representing the entire program”: My idea is to be less ambiguous about the “buried” part. It is somewhere in the tree

I believe “positive position” mean “servers” and “negative positions” mean “clients”.


Probably this paragraph should be ‘de-academicized’ :slightly_smiling_face:

Although > The module that defines the provided variable is expected to meet the servers of the contract. isn’t much clearer :wink:

• “allows us to write, A:” I’d say “allows us to write A as:” and same for B below. (I think this is not a proper use of the commas)

well, if the contract is for a function, the module that defines it is expected to meet the “function result” part of the contract, while the module calling the function is expected to meet the “function arguments” part of the contract…

• In your backward-transformer, in with-syntax ([(backward form ...
the backward
is being matched. Do you mean it to be a literal or maybe _
? • Then in the example you make it match to begin
, but don’t you mean backwards
here also?

Ahh, I see, thanks Alex! That didn’t even occur to me (that this is what it meant)

• auxilliary -> auxiliary

• possibly “until the final program runs [(run time, evaluation phase)]” • “and they use” -> “and then use” • “we will instead mark our definition of backward-transformer, so …”: ill-place comma. But not very clear anyway. How about “we will instead tell the compiler that our definition of backward-transformer is available at compile time instead of at run time” • “is what we need.” -> “is what we need to make it work:” • “in practise the common case is to define both at the same time.” I thought you mean both available at compile time and at run time. Maybe instead: “We can combine begin-for-syntax
and define
into define-syntax
”

It could be a good idea to tell a little more about the special meaning of the first identifier in the pattern, in particular because you make it match with begin
earlier, and now, with define-syntax
it can only be backwards

• “This can be especially confusing[~,~] if the person who use[s] the macro[~,~] and the author of the macro [aren’t] the same.” (sorry, I guess I’m in pedantic reviewer mode right now :smile: ) • “to pick the input apart” Not sure what this means

I like it!

Thanks for the comments. Pedantic reviewer mode was just what I needed :slightly_smiling_face:

I’ll revise the text accordingly.
I forgot to remove the first page from the pdf (I need something in my CSS in order not to get an extra page).
In (with-syntax ([(backward form ...) ...)
I normally write (with-syntax ([(_backward form ...) ...)
I agree I need to say something about that matching the first identifier, but I plan to postpone it to a section on macros expanding to output containing a use of the same macro. As far as I know, that’s the only situation, using the macro name in the first pattern can bite you.

> It could be a good idea to tell a little more about the special meaning of the first identifier in the pattern, in particular because you make it match with begin
earlier, and now, with define-syntax
it can only be backwards.
I need to find where it is matched with begin
that’s not intentional.

Found it - yes, that should have been backwards.

Thinking aloud: The nice thing about this approach, like src doc is that the docs are better in sync with the code

my habit has been to use raco setup --check-pkg-deps <collection-name>

@robby Today’s not-urgent idea/question: We’d discussed jump-to-definition should treat contract-out wrappers as definition points. Jump there. User can jump again, transitively, if they want.

I’m starting to wonder similar about require
and provide
forms that rename the identifier (rename
, prefix
flavors, etc.). Those also are “definition-like inflection points”.

One motivation: If a user wants to rename something, those renaming forms are inflection points that “break the chain”.

If say they’re renaming the original actual definition, then they want to name things “downstream” but not past those renaming form inflection points.

Conversely, they might want to rename uses on “the other side”, in which case they do need to change the identifier in that renaming form.

The contract ones work, I think, because the fully expanded form makes it look like new definitions. These don’t, I believe, so this one would need direct support in traversals.rkt.

As usual I might be explaining this badly. Although there are many such forms, maybe I should make a simple example to illustrate?

But there’s not currently information being calculated in traversals for renaming across file boundaries

I think an example would be great!

Yes, I figured that. Interestingly there is some annotation stuff for prefix-in requires, which is cool, but not really the general case.

Yeah.

(Not that it already “ought” to be doing the general case, it’s not immediately obvious what needs to be done.)

I’ll make a few examples, maybe just post in a gist or github issue. With multi files, and chains of provide
and require
, a bit awkward to do here in Slack.

Mainly I wanted to get a quick ballpark reaction from you. thanks!

Thanks!

I think it would be great.

As a user of DrRacket and racket-mode, I basically always want the actual definition when I “jump to definition”, as opposed to the contract or the re-provide etc. There are various situations where I currently end up with the re-provide and it’s always frustrating.

For the contract, I would be more likely to want that inline when I reference the name, either as a tooltip or in a different pane showing the contract and/or other information about the value.

I have the opposite experience.

I am happy when I “jump through” the contract

But I use keystrokes and not menus so there is a lot less “cost” to jumping a second time

Do you usually stop at the contract, or then jump again? And do you want to know the contract as well as the definition?

I agree about tooltips

I sometimes am aiming at the contract and sometimes not.

So it is a way for me keep on going (or not)

When you’re aiming at the contract, are you trying to figure out how to use the function?

no, I usually use the docs for that

sometimes tho

More like I’m trying to change the contract (or double check it)

we’re getting into vague territory tho, where I’m not going to have good answers :slightly_smiling_face:

Well I think vague answers about what people use these operations for are better than just thinking about it a priori.

I’m saying that you’re asking me questions that are more specific than I can be confident to answer.

I’m confident about the “I want to see or not the contract so I jump again or not and I’m happy about it”

The rest, no so much.

In terms of the tooling, and say a database that captures some of this information, I think it’s fine to err on the side of “more granular”. Whether to jump incrementally or transitively can be more of a user-level configuration, probably.

Whereas w/o the granularity, some things are impossible.

Certainly making both things possible seems very valuable.

Like at the moment I’m interested in how a reliably multi-file/module “rename” command could even work.

(Status quo, Racket Mode still attempts to jump directly “through” the contract wrapper to the actual definition. I’m not planning to touch any of that until/unless this whole analysis db thing pans out.)

multi-file rename: it might make sense to scope that to a pkg (or pkgs)

So we’d have something that lists the occurrences of some exported name in all files in a particular pkg.

For sure. Renaming past a pkg boundary ~= breaking the package. :slightly_smiling_face:

It might also make sense to do it based on collections

I hate versioning systems and vehemently oppose things like renaming existing public functions. :slightly_smiling_face:

Anyway some of these questions, like contract-out wrappers, and all the renaming/pefixing requires/provides…. It’s almost like “equality” or “identity” isn’t always obvious. I had no idea. :stuck_out_tongue:

Sesame Street taught me “one of these things is not like the other”, but I feel it let me down, dammit.

:slightly_smiling_face:

I’ve put the gist here: https://gist.github.com/sschwarzer/5aaf9f203c552f1bf13a167dd08ded11
If you want to have a look, feel free. Note that this is a summary of things I took away from the threads I started. I deliberately don’t want to add too many details, but if you see bad practices or outright errors, I’m thankful for feedback.

Instead of having with-handlers
wrapping your whole program, you might want to instead adjust error-display-handler
at the beginning of your program. Something like:
(let ([this-handler (error-display-handler)])
(error-display-handler
(λ (msg e)
(this-handler
(regexp-replace #px"^.*?: " msg "")
e))))

Also, raco pkg install ../<working-dir>
can be simplified to raco pkg install
(assuming that you are in <working-dir>
)

I added the error-display-handler
to the notes. I’m not sure yet which approach to use, but I plan to use the change of the error message.
As for the raco pkg install
invocation, I keep the verbose version (for explicitness) in the notes, despite usually using the invocation without the working directory argument. But I’ll probably will use raco setup
now anyway unless I need to install the package without it being installed. :slightly_smiling_face:

I like to have a simple Makefile
for each project so I can just type make setup
or make test
. That way I don’t need to recall the details. Also a couple targets are handy mainly for CI, make install
and make check-deps
.
For some project, if a target like test
needs to be a bit different — I can set that up once and not need to recall that either.
As you can tell I enjoy not needing to recall details. :)
One example: https://github.com/greghendershott/vestige/blob/master/Makefile

@greg I think we should just fix raco pkg
to do those things

For sure if you mean things like raco pkg <command>
wrappers that do things like raco setup
with deps checks, and so on. I agree.

I think I’ll still keep doing little Makefiles because I have projects that aren’t packages, yet, or ever. So I still like being able to type my little “make do-what-I-mean” phrases that just-work. ¯_(ツ)_/¯

But those aren’t mutually exclusive, for sure!

I was also thinking of adding a makefile. I use them for several other projects. :slightly_smiling_face:

I use Makefiles for the racket applications i’ve written. I usually have dist and clean targets in addition to a default target that just compiles the app.

@greg yes, that’s what I mean, but also I want to persuade you (and everyone else) to make all the racket code you write a package and also it should be easy to create extra raco
commands to do useful things instead of using make
— similar to how people use npm

Fair point, a little casual project can still be a Racket package — even if it’s not (or never will be) published on the Racket package server.

That could probably be true for everything I do. (With the possible outlier exception of Racket Mode (is it a Racket pkg, an Emacs pkg, both, neither, floor wax and/or desert topping) Regardless, an outlier.).

Right. I think it’s not either easy enough or beneficial enough right now, but that’s something we should work to change.

And I still think Racket mode should be a Racket package even if it isn’t primarily updated via the pkg mechanism.

I am more comfortable adding npm commands because they are local to the project, whereas in Racket, raco commands are always “global”,

Well that doesn’t need to be a fact of nature …

A raco.rkt
file in the project directory that contains raco commands? That would be pretty cool

In particular if inheritance via require is possible

Can you clarify what you mean by inheritance?

just that if a bunch of raco commands are defined in another file, you can require this file and get the commands. You can redefine what you want, just like with modules

Say in folder Dir, you have a raco.rkt
that contains some raco commands, local to this directory. Then one level down you may have another raco.rkt
that just requires ../raco.rkt
and maybe add some other commands, etc.

Tangentially I was thinking having a “project” scope for racket would be nice.

mumble I’d rather have an “indentation time” and a way to declare indentation levels for macros.

I agree that those terms are not helpful in the documentation and edits would help

@m373h4n has joined the channel

I am not sure this always works

Some dep changes can evade that check I believe

I can’t recall the specifics. Maybe docs?

something like npx
would also be very, very useful

(it’s like raco commands except npx whatever
looks for a package named whatever
and downloads it on the fly to run the command)

Actually if I spent the 15minutes to read the docs, maybe a directory scope would do what I want.

Probably directory scope is not quite what you want, but I once tried to sell Sage on something built around those pieces: https://groups.google.com/g/racket-dev/c/dHAFwzlFwNA/m/_m3GAcUZAgAJ

It’s close (I think), except it’s trying to install everything I already have. I’ll take a look at that thread.

That thread is about how to avoid installing everything that you “already have” although that’s not necessarily something to avoid

From the “hack on config.rktd” method I have something that seems to be working except that installing a package still wants to touch the “global” documentation sqlite file

(“working” == “seems to do what I need, not necessarily robust as others may like”)

I would definitely be interested in seeing the code if you posted it somewhere

And that problem seems like exactly the sort of thing that @mflatt meant about finding what needs to be fixed next

I did most of this initially by-hand editing the configs. Just wrote it up and minimally tested. After running and setting the config environment variable I can run raco pkg install
and it installs into the _raco-env
directory.
https://gist.github.com/samdphillips/8afaf8f2332e1ba57c4dc634097c2a8a

I just wanted to check my understanding of the module system: say I have two modules, A and B, where B requires A twice, at phases 0 and 1. Is it the case that A is evaluated exactly once, even though it’s required twice?

No, A will be evaluated twice.

Ah, so a module is evaluated separately for every place it’s required?

You can read Matthew’s 2002 paper You Want it When, or our Scheme Workshop 2009 paper about Typed Racket, or our PLDI 2011 paper about Typed Racket, which all roughly cover the same ground about this.

Or watch the video of my Papers We Love presentation of Matthew’s paper.


and yes, as long as you meant “phase” instead of “place”.