
Redex seems to be geared towards Reduction Semantics, which I really dig. But suppose you were to define a reduction relation as a Structural Operational Semantics instead. To define the step relation playing SOS’s premise-conclusion game would you rather a) define a reduction relation and encode the premises as side-conditions or b) define a judgment form even though I’ve only seen people use these for typing rules? Or is there a third option I’ve just not stumbled over?

I’d use a judgment form for that. I see people using judgment forms for all sorts of things besides typing rules. For example, in An Introduction to Redex with Abstracting Abstract Machines 1, Van Horn uses them for everything from a lookup relation to operational semantics.

thanks @leafac. (it’s good to hear from you btw.)

I guess I’ll try a judgment form then.

yes, the link you sent me does exactly what I was asking about. A natural semantics is also an SOS.

afaik.

Loops hurt so bad


@robert.postill has joined the channel

@mflatt I can never remember which is preferred: module-path-index-resolve
or resolve-module-path-index
.

I’m thinking of putting a note in the docs, but since I can’t remember which is preferred, I’m not sure which to recommend.

@leif Although I once had in mind that module-path-index-resolve
would be preferred, resolve-module-path-index
does slightly more. So, I found it tricky and not obviously worthwhile to pick on as preferred.

@mflatt Ah, yes, that’s what it was. Thanks.

@samth just noticed, TR doesn’t register a type for vector
in (vector 1 2 3)
. Should I submit a PR to call add-typeof-expr
in the part of tc-app
that’s doing the type checking?

@ben yes

@oldsin has joined the channel

@mflatt How can I construct a module declaration?

Like, I know I can use dynamic-require to instantiate and/or visit it, and I can use namespace-attach-* to attach a declaration of an already declared module.

@leif eval
is the usual way

@lexi.lambda you had some network code (http, maybe?) in here the other day that used some call/thunky form I’d not seen before… I don’t remember it’s name. help?

@samth Ya, but won’t that also eval it? Hence also visiting and instantiating it?

no

@zenspider call/input-url
http://docs.racket-lang.org/net/url.html#%28def._%28%28lib._net%2Furl..rkt%29._call%2Finput-url%29%29

Okay then. If I have a module on my filesystem, is there any way to declare it?

Like, say I want to declare foo.rkt

> (eval '(module m racket (display 1)))
> (require 'm)
1
>

Fair.

that was it… thanks. I’m using port->string (post-pure-port (string->url ...
and not sure how it’ll differ but I want to poke

That does work for anonymous modules (so to speak), but I’m not sure how to get that to work for ones that are on the filesystem. I mean, I could read
it first, but then wouldn’t it be a different module?

@zenspider port->string
already closes the port, so I think it should be equivalent.

I want to build a simple webapp for the server side of a client I already wrote in racket. is there something like ruby’s sinatra I can start with?

the web-server
package.

@leif why do you want to avoid visiting it?

@leif I thought dynamic require (void)
does the declaration


huh. why do I already have that installed? I guess it is an auto-install

it’s part of the main distribution.

oh… but the doco says package. hrm

@leif as @shu—hung suggests, (dynamic-require "foo.rkt" (void))
may be what you want, if you’re ok with visiting the module

@samth Because I don’t want to run the module, nor do I want to expand the module.

@zenspider the main distribution is a set of packages. base
is minimal racket.

@leif declaration involves expansion

Mm…good point.

Remind me the difference between visiting and expanding in this case then?

@zenspider the main distribution has a lot of things in it. you can see them here: https://pkgs.racket-lang.org/package/main-distribution


so lisp.sh uses serve/servlet
and web-server
suggests stuffer chains… I assume the lisp.sh thing is more straightforward

I think I just never noticed rackunit and the like listing as packages in the doco

@zenspider which docs for web-server
suggest stuffer chains?

@zenspider you probably want to look here, not at the place #lang web-server
deep links to. http://docs.racket-lang.org/web-server/index.html


@samth #lang web-server
indexes into a weird spot for beginners.

@samth I searched for web-server, clicked on the module result, and that drops you into section 3: stateless servers

the example at the top of that is a stuffer chain

@lexi.lambda that’s (partly) because #lang web-server
isn’t really for beginners

it ought to have a different name

“That is, the expander instantiates any variables defined in the module within begin-for-syntax, and it also evaluates all expressions for define-syntaxes transformer bindings.”

If that is the case, and declaring a module requires visiting it…

@samth #lang web-server/stateless
? or #lang web-server/continuation
? not that it can be changed now.

#lang web-server/gah

then its not at all clear how declaring a module and visiting a module differ. Like, is it possible to visit a module without declaring it, but not the other way around?

maybe the module link should drop into section 1 ?

@zenspider the web server library is pretty old. if you stick to a good subset of it, it works pretty nicely. but there’s some weird stuff in there.

@leif it is also possible that some module is copied from another namespace

I think in that case declaration will happen, but maybe not visiting

@zenspider it would be nice to write a small layer on top of the web server that gives it a more consistent, modern interface. I started doing that at one point, but then I got roped into writing my programming language.

me too

haha

@shu—hung that makes sense.

iirc there’s some low-level functions that actually does the declaration work

“…and now I have 43 problems”

@leif https://docs.racket-lang.org/reference/Module_Names_and_Loading.html?q=current-module-name-resolve#%28def._%28%28quote._~23~25kernel%29._current-module-name-resolver%29%29 the two-argument mode of current-module-name-resolve
does it

So then its safe to say that the ‘first’ time a module is declared, it must be visited, but any further declarations do not require further visits (but can optionally still do it.)

@leif the eval example does not visit the module

@zenspider here’s a tiny example of one of my uses of the web server, which uses the most modern-feeling bits, I think. https://github.com/lexi-lambda/imgcap/blob/ae4a303c577b6d451a9f8d274b6f1907291b6530/imgcap/main.rkt

if I’m keeping an in-memory db… is there some hook or signal or something I can register to save to disk before the process quits? I don’t see anything on serve/servlet

@shu—hung Okay, thank you.

@lexi.lambda awesome. thanks


@shu—hung So it seems like all declaring a module is…is applying that parameter’s function…

Which makes a lot more sense. :slightly_smiling_face:

So now, if that is the case, I just need to find a way to call that function directly.

(Since I wan’t to declare a module on the filesystem without visiting it.)

ella is pretty

@samth I have a bunch of utility functions and things sitting around that I’ve basically copied between various web-server projects because I haven’t felt like I have enough to put them into a package. Then I got stuck because I decided my web framework needed an ORM, and then I decided it would be really nice to have return-type polymorphism…

I have some stuff that does signed/encrypted session storage using libcrypto, rails-style “flashes”, bindings to recaptcha, match expanders for HTML forms, a short-id generator, and a simple HTML sanitizer. Also some sendgrid integration for sending emails, but that’s probably pretty half-baked.

hrm… exit-handler
isn’t like at-exit
in that it adds a thunk to run at exit… instead, it assumes the entire exit process and doesn’t actually exit… what am I not getting?

AND! doesn’t actually run if via the cmdline?!?

(unless I manually call (exit)
)

should I be using (executable-yield-handler)
instead?

@zenspider my guess is that the exit handler isn’t really what you want. maybe you want a plumber? http://docs.racket-lang.org/reference/plumbers.html

yeah. that is strange. if I use executable-yield-handler
it does NOT get called if I call (exit)
… too tangled (yet not tangled enough?)

I’ll poke at plumbers

honestly… plumbers don’t make much sense to me.
> There is no guarantee that a flush callback will be called before a process terminates—either because the plumber is not the original plumber that is flushed by the default exit handler […]

ah. I shouldn’t make one. just use current-plumber

@zenspider my understanding is that the reason things like exit-handler
, executable-yield-handler
, and current-plumber
can be changed is to support things like DrRacket, but most programs will not touch them.

you certainly don’t want (exit)
in DrRacket to exit DrRacket.

@zenspider Also, plumbers are for optimistic resource cleanup, where it’s acceptable if attempting to clean up the resource is abandoned. Custodian shutdown hooks are for things that absolutely must happen during cleanup, and as such they’re unsafe to use due to deadlocking / concurrency problems and you should be very careful about doing IO in them.

if you’re writing stuff to disk you most definitely want a plumber flush callback

is there a way to hook cancelling the web server in the repl?

I can catch exit on the cmdline just fine… but that isn’t as clean as just running the code in the repl and then C-c C-c

looks like it calls bye, then shutdown-server… but that doesn’t have hooks

@samth I wound up expanding ella’s macros to include (_ method route (e args ...) ...)
(arb code in body) and (_ method route e)
(bare name)

such that:
(get #rx"/incr" (incr params))
(get #rx"/incr2" incr)
(get #rx"/incr3"
(set! db (cons (length db) db)) ...)

Cool

I haven’t touched that code in a while as you can see

I am guessing I’ll mostly use the middle form

So I’m happy to take any changes you make

cool… question for you… is that first form in the examples file supposed to work at all? I’m guessing no?

I was tempted to extend the macro to regexp-ify a bare word

@leif: rereading the doc again, now I’m not sure whether module declaration is actually performed by the default module name resolver

the doc seems to say that when a module is declared, the current module name resolver will be invoked, not “the current module name resolver is invoked to declare a module”

@shu—hung lol, thanks.

Which I guess leads back to my original question. How can I declare a module (without visiting it)?

Which I suspect @mflatt probably knows.

@leif There’s no way to avoid running expand-time code in a module
form if you start with the module in S-expression form. If you have a module in compiled form, you can eval
the compiled module to declare it without running any phase of the module. (And if you want the declared name to correspond to a file, set current-module-declare-name
.)

If you have a file that contains a module, then you probably want to set current-module-declare-name
and current-load-relative-directory
while you use load
.

@zenspider that first form is indeed supposed to work. did it break?

@samth it didn’t work for me… but I don’t remember how/why.

could be user error :stuck_out_tongue: