
I suggested DNS resolution might be a problem because I assumed you owned the server (and possibly made changes to DNS entries). That’s probably not what’s going on with GitHub, though :smile:

Beware, char-whitespace?
recognizes more characters as whitespace than #px"\\s+"
.

@greg Then Chrome using a newer version of http has more weight now :slightly_smiling_face: Not user which one Racket uses. HTTP 1.1?

I think this is an interpreter that does what you want
#lang racket
(struct closure (x body env))
(define (interp p env dyn-env)
(match p
[(? number?) p]
[`(λ (,x) ,b) (closure x b dyn-env)]
[(? symbol?)
(cond
[(assoc p env) => cdr]
[else (error 'unbound-id "~a" p)])]
[`(let ([,x ,v]) ,b)
(interp `((λ (,x) ,b) ,v) env dyn-env)]
[`(println ,x) (println (interp x env dyn-env))]
[`(,a ,b)
(define a-val (interp a env dyn-env))
(define b-val (interp b env dyn-env))
(match a-val
[(closure x body c-env)
(define new-binding (cons x b-val))
(interp body
(cons new-binding c-env)
(cons new-binding env))]
[_ (error 'not-a-procedure)])]))
(interp `(let ([x 100])
(let ([f (λ (_x) (λ (_y) x))])
(let ([f* (f 0)])
(let ([x 200])
(let ([f** (f 0)])
(let ([_ (println (f* 0))])
(let ([_ (println (f** 0))])
0)))))))
'() '())

IIUC HTTP3 ~= QUIC ~= “HTTP connections and stream done via UDP instead of TCP”. I think the main motivation for this was data centers like Google can squeeze out another ~ 10% bandwidth. Plus other benefits like you can maintain an HTTP connection while hopping between transports like e.g. your mobile phone’s wifi or cell tower.

I think it’s probably fine for command-line tools’ defaults to still be HTTP 1.0/1.1 for approximately forever. :slightly_smiling_face:

I think if you really need a Racket web app to use HTTP3, that can be provided by the same reverse proxy server like ngnix that you’re putting in front of the raw Racket web server, anyway (for speed and for HTTPS and now also for HTTP3)?

But that’s just my incomplete knowledge, and opinions based on that. People like Jay or @popa.bogdanp or others may easily have better knowledge and opinions. :slightly_smiling_face:

Anyway. One “theory of the bug” I have is that Chrome is aggressive in expressing its preference for (say) HTTP3, and that causes a different path through GitHub’s CDN that turns out to be “fresher” wrt caching. idk.

@ryanc I’m not familiar with the “Unicode "White_Space” property". Are you aware of any characters for which char-whitespace?
returns #t
that you wouldn’t expect to split on if you were “splitting on whitespace” ?

maybe “OGHAM SPACE MARK” I suppose

I think I’d still lean toward using char-whitespace?

Argh. That does present a problem though given the default would technically change.

I think it makes sense to check for the 5 specific characters recognized by \s
instead of using char-whitespace?
. Even in the ASCII range, I see that \s
omits #\vtab
(for whatever reason) compared to char-whitesace?
.

Ok. I agree it’s a significant advantage to not change the default.

@mflatt is it your understanding that #\page
corresponds to “formfeed” ? For example: (define (is-whitespace? c)
(or (eq? c #\space)
(eq? c #\tab)
(eq? c #\newline)
(eq? c #\return)
(eq? c #\page))) ; form feed
The Racket regexp docs state \s
“Contains space, tab, newline, formfeed, return”

Yes, ASCII 12 is variously know as “page break” and “form feed”.

Right, I meant it would be better to avoid changing the behavior.

I realized something. I was expecting the defining/providing module — the one with the contract-out
— to be where the wrapper function is defined, once. (And the name isn’t apparent in the fully-expanded code of that defining module, was my confusion.)
But now, it occurred to me that it’s the requiring module where the wrapper function actually gets defined: contract-out
provides macros that result in the wrapper function being defined there — in each importing module. Does that sound correct?

Yes

We don’t know the negative blame (so cannot build the wrapper) until we get to the use site

(There is an optimization that’s relevant here where, in some situations the contract system turns an arity-n function into an arity-n+1 function that it defines on the exporting-module side and then it adjusts call sites instead of creating wrappers; not sure if that’s relevant to what you’re thinking about, tho.)

OK. I’ll marinade myself in that for awhile. But that explains a lot. I had totally the wrong mental model for what was going on.

(yuuuuum, maaaaaarinating)

I don’t have a specific practical goal in mind, except curiosity. I don’t expect to grok everything, but it bugged me how confused I was about this. So just absorbing.

nice

OK, well, I have one practical question in the near distance. With the check-syntax change (thanks again!) it’s now possible to build a complete db of definitions and uses across multiple files. That by itself has some good utility, I think.

But I also have this notion it would be nice to support multi-file rename.

And that’s trickier for a bunch of reasons, even modulo contract-out
.

I have spent a little time over the last quarter starting on code that builds a database of fully expanded code

So I’m still thinking but it still may pop up again that it could be helpful for contract-out
to provide some syntax property or hint. idk yet.

with the hope of building a layer on top of that that would hold all of the check syntax annotation information in it

So then we could do this stuff by querying the database (which might trigger real work or not depending on how we design the APIs)

With the goal of making things like jumping to definitions work a lot better

We (Christos and I) didn’t get too too far but here’s our current progress on that goal: https://github.com/rfindler/fully-expanded-store

In Racket Mode I’ve been keeping a “cache” of fully expanded syntax, but. On the one hand, it can grow quite large. On other hand, it seems impossible to serialize to disk, because to do some useful things you need the live namespace in which it was fully expanded? And so I’ve been switching to playing with storing some of the check-syntax results in a db.

It sounds like we’ve been exploring similar things maybe!

Yes, the idea here is to be a platform where you’d store things like the check syntax results in a DB

That gist I shared before is a prototype of that. :slightly_smiling_face:

But my thinking was that the first layer would be the fully expanded syntax and then others might build other useful things on top besides just check sytnax results

I’ve moved it into a little repo but not pushed to GitHub. Even if I pushed it, it would be more for “backup” than “hey use this!”.

The link above is no where near complete

I think it is the right direction to head but it needs a lot more work

That link is a 404 for me. Maybe a private repo?


oh yeah. I invited you. There’s not much there.

There’s no, in principle reason to keep it private. Just shy.

The files in run-example
actually use the code

Most of the time we spent working on it was figuring out the right approach to actually get our hands on the compiled code.

Great! This interpreter uses two environments, a static environment and a dynamic environment, which reflects @greg’s comment: > I think of this as overloading let to mean both lexical scope and dynamic scope, but in Racket we’d normally use let for the former and parameterize for the latter. Thanks!

Also this reflects why @greg’s let + Parameter code can simulate it.

Thanks for the invite. I use Firefox containers and I think I’d opened it one that doesn’t know about my GitHub account. Got it now!


What is the status of “Shallow Typed” Racket?

I wanted to double-check on one point. You’d said: > But my thinking was that the first layer would be the fully expanded syntax and then others might build other useful things on top besides just check sytnax result But I mentioned above something, I’m not sure you noticed? In my experience, the fully-expanded syntax seems impossible to serialize in a fully useful way. The gotchas there seem to be:

(a) You can’t just write
the syntax object. Well, you can, but it can’t be read
later. If you (write (syntax->datum exp-stx-object))
you can read
that back, but you’ve lost all the interesting things like stx props, srcloc, etc.

Compile can do it

The code has it in there.

Oh cool.

I was about to type: (b) Even if you solve (a), to do some things you seem to need not just the stx object, but the live namespace in which it was expanded. e.g. If you want to use identifier-binding
.

But maybe I’m wrong about, too?! :slightly_smiling_face:

I’m not sure about that.

I do think you lose something in the serialization process but I don’t know what exactly

the trick with compile:

you compile a program with a syntax-object literal (constant) in it so serialize

then you eval the compiled code to unserialize

OK. Interesting.

I imagine you lose syntax properties that aren’t marked as “preserved”? But maybe I’m confusing “compiling” with “bytecode marshaling”.

Anyway I do want it to be possible to save the result of full expansion to disk, in a rich enough way to be able to reuse it w/o needing to re-expand. (I was sharing what I thought might be speed bumps — not trying to shoot down the idea. I love the idea.)

Hmm oh actually: > then you eval the compiled code to unserialize Maybe doing so updates the namespace sufficiently to recover the things from the original namespace in which it was originally expanded. I can try some experiments.

What can I say. I like to sit down and have a good think, first. But sometimes, for me, “forensics precedes understanding” is my motto. :slightly_smiling_face:

absolutely!

(the smile was because I’m glad you’re putting energy into this!)

Oh I have already put a lot of energy into many of these topics. I am well into “sunk cost fallacy” territory by now, there is no turning back. :wink:

:slightly_smiling_face:

@samdphillips same as it was 6 months ago. Things keep piling up; I’ll have to pick a weekly hour or two to get it rolling again

I’ll double-check in case I made a mistake, but it seems like the 'module-body-context
syntax property — https://docs.racket-lang.org/reference/Expanding_Top-Level_Forms.html#%28part._modinfo%29 — doesn’t survive the round-trip (writing ((current-compile)
(,#’quote-syntax ,exp-stx) #f)to a file,
read-ing it back in and
eval-ing it in a fresh
make-base-namespace`.) :(

Something else to consider for dynamic binding is concurrency. Racket parameters have distinct values per thread. A new thread inherits the parameter values of the thread that created it, as initial values, but they’re separate and can diverge thereafter. (Although I think that’s a sane general behavior I guess it’s possible to imagine a dynamic binding model where you intentionally don’t want that.)