mflatt
2019-3-26 13:23:33

A definition context immediately nested in another can do this when the inner one wants to splice into the outer one. I don’t remember a macro like that offhand to demonstrate, though.


leif
2019-3-26 16:20:53

Is there any way to print out the set of scopes associated with an identifier?


leif
2019-3-26 16:21:24

(I can’t use the macro stepper because the generated code is too big, so I’m trying to do a bit of print line debugging.)


leif
2019-3-26 16:21:34

I suspect @michael.ballantyne or @ryanc might know?


ryanc
2019-3-26 16:24:43

@leif use syntax-debug-info, or try the debug-scopes package


alexknauth
2019-3-26 17:08:09

I’ve used this scope->symbol function (with syntax-debug-info) for debugging, to turn scopes and their jumbles of numbers into letters: https://gist.github.com/AlexKnauth/11cde092aec836aecb21c9634fedd4f3


leif
2019-3-26 17:08:54

@ryanc THanks


samth
2019-3-26 18:49:46

@mbutterick yes


jaz
2019-3-26 18:58:01

@mbutterick Nope


jaz
2019-3-26 18:59:30

Only the first, er, 256[? or was it higher?] characters are represented as immediate values.


jaz
2019-3-26 19:00:17

Oh, I should mention that I’m referring to classic Racket. Not sure how chars are represented in Chez.


jaz
2019-3-26 19:00:44

Oh, sorry


jaz
2019-3-26 19:00:51

Wow — I missed the important part of what you wrote


jaz
2019-3-26 19:01:07

Yes, the integer values are fixnums.


notjack
2019-3-26 19:02:21

would adding fixnum-max-value and fixnum-min-value to racket be a good idea?


jaz
2019-3-26 19:02:43

(And the first 256 aren’t represented as immediates; they’re just interned, so they’re pointers, but they’re always the same pointer.)


jaz
2019-3-26 19:08:39

I think characters are all immediate in Chez.


sorawee
2019-3-26 19:13:36

Is there a way to force module instantiation. I.e., make dynamic-require twice possible?


sorawee
2019-3-26 19:14:10

What I want to do is to run the same program with different (current-compile).


lexi.lambda
2019-3-26 19:15:56

If you want to recompile the module then you need to do more than just reinstantiate. Can you do it in two separate namespaces?


florence
2019-3-26 19:18:50

Even doing it in separate namespaces might not be enough, no? You would also need to do something like set use-compiled-file-paths to empty to avoid current-load/use-compiled from grabbing the file off disk


lexi.lambda
2019-3-26 19:20:14

Well, if the file isn’t compiled on disk then loading it would compile it in-memory, right? So it could work if the namespaces were different. Or does Racket cache that somehow?


florence
2019-3-26 19:20:35

I was assuming it might have been compiled to disk


lexi.lambda
2019-3-26 19:20:56

Yes, in that case you’d also probably want custom-load.


florence
2019-3-26 19:21:15

oh right, you don’t want to recompile the universe


florence
2019-3-26 19:29:55

@sorawee This might do what you want:

(require custom-load
         syntax/modresolve)
(define (path->regexp s)
  (regexp (regexp-quote (path->string s))))
(define (force-recompile-for-effect mod)
  (parameterize ([current-namespace (make-base-namespace)]
                 [current-load/use-compiled
                  (make-custom-load/use-compiled
                   #:blacklist
                   (let ([p (resolved-module-path-name
                             ((current-module-name-resolver)
                              (resolve-module-path mod)
                              #f
                              #f
                              #f))])
                     (cond  [(path? p) (path->regexp p)]
                            [(pair? p)
                             (if (path? (first p))
                                 (path->regexp (first p))
                                 empty)]
                            [else empty])))])
    (dynamic-require mod #f)))

depending if you only want to recompile for effect or not


florence
2019-3-26 19:31:57

(well, if you want to do this to something in racket/base it wont work, but fixing that just requires some plumbing)


sorawee
2019-3-26 19:32:24

Thanks! I was playing around with your earlier suggestion and the program seems to get stuck at (use-compiled-file-paths '()). Will try your code right now.


florence
2019-3-26 19:32:57

custom-load isn’t in the main distribution i think, you’ll need to install it


florence
2019-3-26 19:33:05

(the pkg has the same name as the collection)


shu--hung
2019-3-26 19:40:41

(use-compiled-file-paths '()) will compile the entire racket (except the VM) from source :wink:


mflatt
2019-3-26 19:51:47

Yes


notjack
2019-3-26 20:52:04

I don’t know. I remember reading through the fixnum docs and not finding any clear answers on what the max and min were, then later I found the (system-type 'word) trick. But that’s not mentioned anywhere in the fixnum docs.


notjack
2019-3-26 20:53:49

The main thing is that I want something that’s documented right next to all the other fixnum operations, so if the representation of fixnums changes for some reason (like say, as some consequence of moving to Chez Scheme) there’s no chance of breaking client code that needs to know the max and min fixnums.


notjack
2019-3-26 20:54:44

It seems entirely possible to me that racket implementation changes could change how the max and min fixnums depend on (system-type 'word).


sorawee
2019-3-26 21:09:38

Oh…. interesting.


notjack
2019-3-26 21:49:32

Yeah that seems like a sensible assumption to me. I just don’t want to have to make such an assumption. It seems way simpler to me to just leave it up to the fixnum module to define what the max and min fixnums are.


notjack
2019-3-26 21:49:48

The “Not My Job” solution.


philip.mcgrath
2019-3-26 22:13:50

I’ve wished I could give a debugging name argument to make-syntax-introducer like the way module scopes are printed.


leif
2019-3-26 22:16:17

@ryanc, @mflatt, & @michael.ballantyne I have the following macro that gives an unbound variable error: https://gist.github.com/LeifAndersen/0e625b56167bbd15a9dfd2745836ae73


leif
2019-3-26 22:16:19

leif
2019-3-26 22:17:12

Basically, module A creates a define-foo, form that creates two macros and has one call another.


leif
2019-3-26 22:17:44

(Which is kind of silly in this example, but my actual code base needs to do this for other reasons.)


leif
2019-3-26 22:18:38

Anyway, module B creates its own define/leif, and uses it plus the define-foo to make a referencer macro.


leif
2019-3-26 22:19:48

Finally, module C Uses the two form (define/leif) and the result from define-foo, but gets an unbound variable.


leif
2019-3-26 22:20:59

I feel like there’s something silly I’m missing here, but I can’t seem to get the example any smaller than that. Would you have any idea what’s causing the unbound identifier error?


philip.mcgrath
2019-3-26 22:22:18

I’ve wanted these constants, and hard-coded them (or what I think they are) into a program, for purposes like working with bitmasks. I would also like constants for the fixnum limits on the platform with the smallest limits. I think Typed Racket must include some version of those for the Fixnum and Index types (“the sets of values included in the types are architecture-dependent, but typechecking is architecture-independent”), but I’m not even sure what predicate corresponds to Index: https://docs.racket-lang.org/ts-reference/type-ref.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fbase-types..rkt%29._.Index%29%29


philip.mcgrath
2019-3-26 22:26:29

When I run raco setup on a sub-collection, does it compile the sub-collection’s “main” module, too? For example, given the hierarchy: fruit/ ├── apple.rkt ├── apple/ │ ├── granny-smith.rkt │ └── ... ├── peach.rkt └── peach/ ├── georgia.rkt └── ... does raco setup fruit/apple compile fruit/apple.rkt, or only fruit/apple/granny-smith.rkt and its siblings?


lexi.lambda
2019-3-26 22:27:12

@leif The code you’ve written is very twisty, but it seems like maybe you wanted this: #lang racket/base (module A racket (require syntax/parse/define) (provide define-foo) (define-syntax-parser define-foo [(_ name body ...) #:with this-syntax-id (datum->syntax #'name 'this-syntax #'here) #'(begin (define-syntax foo2 (syntax-parser [(_ n) #:do [(define this-syntax-id #'n)] body ...])) (define-syntax name (syntax-parser [(_) #`(foo2 #,this-syntax)])))])) (module B racket (require (submod ".." A) syntax/parse/define) (provide (all-defined-out)) (define-syntax-parser define/leif [(_) #:with leif (datum->syntax this-syntax 'leif #'here) #'(define leif 42)]) (define-foo blue #:with leif (datum->syntax this-syntax 'leif #'here) #'leif)) (module C racket (require (submod ".." B)) (define/leif) (blue)) (require 'C)


lexi.lambda
2019-3-26 22:28:05

The differences are all in module A: instead of using #'name as this-syntax inside foo2, it uses the original input syntax to name.


notjack
2019-3-26 22:28:30

I don’t know, but lately I’ve been avoiding this kind of problem by putting all my code in a private/ directory and only writing #lang reprovide modules to expose the public collection-ized API


notjack
2019-3-26 22:28:53

lexi.lambda
2019-3-26 22:29:50

However, there’s a better way. Don’t unhygienically shadow this-syntax. Instead, call syntax-parse again inside of foo2, like this: (module A racket (require syntax/parse/define) (provide define-foo) (define-syntax-parser define-foo [(_ name body ...) #'(begin (define-syntax foo2 (syntax-parser [(_ orig-stx) (syntax-parse #'orig-stx [_ body ...])])) (define-syntax name (syntax-parser [(_) #`(foo2 #,this-syntax)])))]))


leif
2019-3-26 22:30:58

@lexi.lambda ya…it is very twisty. Sorry. All of the versions without the twists didn’t give me the unbound identifier error.


lexi.lambda
2019-3-26 22:30:58

That way the this-syntax syntax parameter will just have the right value, and user code that shadows it will do the right thing.


leif
2019-3-26 22:32:08

It does look like you made some changes in B. but still using the name this-syntax, yes?


lexi.lambda
2019-3-26 22:32:42

Oh, I just put those uses of #'here in B so that the ambiguous binding error would point somewhere useful.


leif
2019-3-26 22:33:03

OH, okay


leif
2019-3-26 22:33:19

That’s actually very cute. Thanks for pointing it out. :smile:


lexi.lambda
2019-3-26 22:34:07

What you were doing before was copying the lexical context from (the literal identifier) blue onto the generated leif identifier.


philip.mcgrath
2019-3-26 22:34:15

I think, though, that fruit/apple.rkt would still need to be re-compiled when fruit/apple/granny-smith.rkt changes, to avoid errors like “bad variable linkage; reference to a variable that has the wrong procedure or structure-type shape.”


leif
2019-3-26 22:34:49

Anyway, I need to shadow this-syntax sadly.


leif
2019-3-26 22:35:03

Because I want this-syntax to be in scope inside of a define-foo.


notjack
2019-3-26 22:35:08

Yes. My only approach to avoid that is to always run raco setup -p mywholepackage


leif
2019-3-26 22:35:34

But because its made with a macro plugging into another macro, the default this-syntax is the outer macro, rather than the original call site.


leif
2019-3-26 22:35:38

(I think)


lexi.lambda
2019-3-26 22:35:48

this-syntax is a syntax parameter, so if you change its value by wrapping something in syntax-parse, any uses lexically inside the syntax-parse will use the new value.


leif
2019-3-26 22:36:41

OH


leif
2019-3-26 22:36:43

I see.


leif
2019-3-26 22:37:13

You literally meant introduce a new syntax-parser inside of the syntax-parser.


lexi.lambda
2019-3-26 22:37:17

Syntax parameters are designed precisely to avoid needing to shadow identifiers in that way. The original paper explains them in a little more detail: http://scheme2011.ucombinator.org/papers/Barzilay2011.pdf


lexi.lambda
2019-3-26 22:37:26

And yes, the second example code I gave does just that.


leif
2019-3-26 22:37:35

(which is of course inside of yet another syntax-parser. ;)


leif
2019-3-26 22:38:44

Okay though, that’s useful. (I didn’t realize that this-syntax was a syntax-parameter. I must’ve missed it in the docs.)


lexi.lambda
2019-3-26 22:39:13

It has to be a syntax parameter, not an unhygienically-introduced binding, because it has a binding.


lexi.lambda
2019-3-26 22:39:59

If it were unhygienically introduced, then this-syntax wouldn’t even be bound outside of syntax-parse, and the scribble docs wouldn’t be able to link to it or even associate documentation with it (since there would be no binding to attach the documentation to).


leif
2019-3-26 22:40:44

That is presuming though that the this-syntax in the docs is the same one from syntax-parse. :wink:


leif
2019-3-26 22:40:50

But I get what you mean, and totally agree.


philip.mcgrath
2019-3-26 22:42:05

That is what I usually do now, but I often have a sub-collection like example/common that is used by both example/foo and example/bar. The immaginary example/foo and example/bar don’t depend on each other, and they don’t peek inside example/common: they just (require example/common). Having to recompile example/bar is slow when developing example/common and example/foo.


notjack
2019-3-26 22:45:11

how slow?


philip.mcgrath
2019-3-26 22:46:33

I haven’t timed it, but the full collection I’m thinking of when I say example is something like 40,000 lines of code.


philip.mcgrath
2019-3-26 22:48:23

In reality, ricoeur/portal also includes a lot of #lang web-server code, and the relative slowness of the #lang web-server compiler is noticeable.


notjack
2019-3-26 22:50:13

I’ve definitely hit similar issues in my workflow, and I don’t really have any solutions


notjack
2019-3-26 22:50:56

the compilation infrastructure for racket is frustrating when it comes to dependency management


leif
2019-3-26 22:55:56

@lexi.lambda Oh fun, when I made the inner syntax-parse, I got this error:


leif
2019-3-26 22:56:01
define-values: not allowed in an expression position
  after encountering unbound identifiers (which is possibly the real problem):
   this
   define-elaborate
   super-new
   base$
   foo$
   define-editor

lexi.lambda
2019-3-26 22:56:59

It looks like somehow those aforementioned identifiers are ending up in a scope where they aren’t bound. But I can’t really say any more without seeing the code.


leif
2019-3-26 22:57:19

Ya, that makes sense.


leif
2019-3-26 22:57:37

While I’d be happy to share the code with you, your eyes would start bleeding.


leif
2019-3-26 22:59:22

(its about 200 lines long, uses splicing-let and splicing-let-syntax, creates submodule pieces (that another macro combines), it creates whole submodules in those submodule pieces. It defines a macro definer, and finally it defines a class type.)


leif
2019-3-26 22:59:51

The sad thing is that most of the real smarts are in other macros…the 200 lines is after I factored out a bunch of code. :confused:


leif
2019-3-26 23:00:02

(I’m sure there’s more I could factor out obviously.)


leif
2019-3-26 23:04:58

Of course though, I’d be happy to point you to it should you decide you’re life needed more unpleasantness in it. :wink:


shu--hung
2019-3-26 23:37:14

To be more accurate, the use-compiled-file-paths parameter instructs where should Racket look for bytecode files.

If it is set to '(), IIUC any new module declaration will need to load (and compile) from source.

Therefore if you dynamically require racket/contract in a namespace from (make-base-namespace), anything outside racket/base that racket/contract depends on will be compiled from source.


lexi.lambda
2019-3-27 01:50:20

Is there any guarantee that two gensyms will have distinct symbolic names if they were generated in the same namespace? And if not, does anything in Racket marshallable to bytecode provide that kind of guarantee?