mflatt
2017-10-14 13:56:02

@lexi.lambda The short answer is that identifier-binding doesn’t implicitly switch to “macro result” view in the same way that syntax-local-bind-syntaxes or syntax-local-value does. If you make the macro return x*, then you get an out-of-context error in either variant of your example. Equivalently, (identifier-binding (syntax-local-introduce x*)) produces 'lexical and both cases. Overall, the intent is that x* as a result of the macro should be bound. To achieve that goal, syntax-local-bind-syntaxes includes an implicit syntax-local-introduce on its argument, as does syntax-local-value and other syntax-local-... functions. The identifier-binding function does not include an implicit syntax-local-introduce. That’s why you get #f in the first example; the binding has macro-introduction marks, but the identifier passed to identifier-binding does not. In the second example, you’re effectively canceling the macro-introduction mark for the binding (by using syntax-local-introduce to make the identifier look like it came from the macro use), and then looking up a binding from an identifier with more scopes still finds the binding. To make a long story short, use syntax-local-introduce on the argument to identifier-binding if you want to see a bindings that as it will visible in the example, and its kindof an accident that you get 'lexical in your second example. The documentation should be made more clear which operations implicitly switch to macro-result view (with an implicit syntax-local-introduce) and which ones don’t.


lexi.lambda
2017-10-14 16:02:56

@mflatt Thank you for that explanation. I admit that I find it pretty difficult and confusing to remember all the subtle differences between different syntax functions and how they adjust scopes. Is that what the syntax-local- prefix actually means? Functions that include an implicit syntax-local-introduce?


mflatt
2017-10-14 16:05:33

I don’t think it’s as simple as having a syntax-local- prefix. I expected to sort this out better with the expander rewrite, but it was too easy to just do whatever the current functions do without thinking about it more.


lexi.lambda
2017-10-14 16:08:39

Okay. The actual problem I was trying to solve when I ran into this is that I was binding some identifiers into a definition context, then calling local-expand on some syntax using the context, and the identifiers in the resulting syntax were not free-identifier=? to the identifiers I had.


lexi.lambda
2017-10-14 16:10:04

Adding the syntax-local-introduce before binding the identifiers fixed the issue, but I’ll try moving it to someplace after the binding and see if that still works, since that seems closer to the right thing to do based on your explanation.


drdeeglaze
2017-10-14 20:33:07

Switched cat from radius to width/height, and added an option to not inset when the whiskers are wider than the face.


drdeeglaze
2017-10-14 20:34:00

I want to make a gui interface now, where I can fiddle with all the parameters to standard-cat and see what it looks like real time.


drdeeglaze
2017-10-14 20:38:21

basically I want to play with the ear positioning, arc length, and extents, and then the whisker length and droop.


drdeeglaze
2017-10-14 20:39:07

it’s not rackety until it has 20 optional keyword arguments


michael.ballantyne
2017-10-14 20:39:09

@lexi.lambda Is there any chance the identifiers that were not free-identifier=? to your binders were accessed from a syntax property set within the local expansion but accessed outside? Local-expand in effect does a syntax-local-introduce on its argument and return. Ran into this issue with turnstile with my own conversion to definition contexts there. Need to syntax-local-introduce when adding the property and when accessing the property.


lexi.lambda
2017-10-14 20:40:46

Yep, I thought about that, and that was my theory. Normally I wouldn’t need to do that sort of low-level mucking about with identifiers, but I had to do that because type variables are represented as identifiers, and I needed to do some type substitution.


lexi.lambda
2017-10-14 20:41:18

The trouble is that it goes in as a syntax object to be expanded and comes out as a property.


lexi.lambda
2017-10-14 20:42:29

Also, hello @michael.ballantyne, I didn’t realize you were in slack. :wave:


michael.ballantyne
2017-10-14 20:43:16

So did you solve your problem, or is there still a difficulty?


michael.ballantyne
2017-10-14 20:44:59

(@lexi.lambda)


michael.ballantyne
2017-10-14 20:45:00

Question


lexi.lambda
2017-10-14 20:45:33

I got it working by adding a syntax-local-introduce in the right spot. So far it seems to work fine.


michael.ballantyne
2017-10-14 20:47:49

Question for everyone: is it expected behavior that racket will use compiled files for dependencies built by raco make even when the source file has been modified since? If so, why? Seems like it would be friendlier to check the timestamps transitive dependencies like raco make does, but I guess I could see that being too expensive.


samth
2017-10-14 23:43:21

@michael.ballantyne No, that’s not the expected behavior, and racket shouldn’t be doing that


samth
2017-10-14 23:44:25

or, perhaps to be more clear, if a.rkt depends on b.rkt and both have zo files, and then you modify b.rkt, then the zo for a.rkt will still be used since a.rkt is not newer than the zo file


samth
2017-10-14 23:45:20

but if you modify b.rkt and then run a.rkt, it will not use the zo file for b.rkt


samth
2017-10-15 00:23:53

@mflatt (or maybe someone else) I’d like to provide an argument to resolve-module-path-index that produces a module path with the same semantics as calling dynamic-require on the MPI directly


samth
2017-10-15 00:24:26

I got somewhere with (resolved-module-path-name (current-module-declare-name)) but that doesn’t work when running raco make


mflatt
2017-10-15 01:16:53

@samth I don’t understand the question. Can you provide a more complete example?


samth
2017-10-15 01:17:50

@mflatt Currently, I have this function:


samth
2017-10-15 01:17:55
(define (do-requires [ns (current-namespace)])
  (parameterize ([current-namespace ns])
    (for ([m (in-list to-require)]
          #:when m)
      (dynamic-require (module-path-index-join '(submod "." #%type-decl) m)
                       #f))))

samth
2017-10-15 01:18:21

I want to write a similar function, but which generates a list of (require ...) syntax objects


samth
2017-10-15 01:18:37

I’ve written this: (define (get-requires) (for/list ([m (in-list to-require)] #:when m) ;; FIXME: is this really the right code? #`(require (only-in (submod #,(resolve-module-path-index m (resolved-module-path-name (current-module-declare-name))) #%type-decl)))))


samth
2017-10-15 01:19:14

which works when the code that uses it is run with racket, but not with raco make or raco expand


samth
2017-10-15 01:20:05

the elements of the list to-require are generated by (variable-reference->module-path-index (#%variable-reference)) in other modules


samth
2017-10-15 01:42:21

I’m trying to arrange for the submodules of a Typed Racket module that declare types or contracts to have requires for the same submodules in the modules that the outer module depends on


mflatt
2017-10-15 01:55:33

My first thought is (variable-reference->module-path-index (#%variable-reference)) in place of (resolved-module-path-name (current-module-declare-name)), but I’m not sure that’s the right idea.


samth
2017-10-15 01:57:38

Won’t that point to the inside of the Typed Racket implementation, where that function is?


mflatt
2017-10-15 02:00:04

I though you were trying to do something like that. If you want to be relative to the context where the require appears, I’m not following well enough to see why "." doesn’t work.


mflatt
2017-10-15 02:00:59

Well, maybe I see…


samth
2017-10-15 02:01:51

If I have modules a.rkt and b.rkt, where b requires a, then in the #%type-decl submodule of b I want to generate a require for the #%type-decl submodule of a


samth
2017-10-15 02:02:41

and the MPI in the code (named m) points to a


mflatt
2017-10-15 02:05:43

Is the issue that m in get-requires might be a submodule path, so you can’t just wrap it with submod?


samth
2017-10-15 02:06:52

I tried just putting m directly in the submod form but apparently require can’t take a module-path-index (which is what m is) directly


samth
2017-10-15 02:07:20

certainly (submod #,m #%type-decl) would be the nicest thing to be able to write there


mflatt
2017-10-15 02:08:02

I’m not clear on where m came from that it’s a module path index, but then it seems like (module-path-join '(submod "." #%type-decl) m) would be what you want.


samth
2017-10-15 02:09:04

Do you mean module-path-index-join?


mflatt
2017-10-15 02:09:09

Yes


samth
2017-10-15 02:09:34

m comes from a call to (variable-reference->module-path-index (#%variable-reference)) in the other module (a in my example)


samth
2017-10-15 02:13:20

That produces a similar error to one I had earlier: ?: bad syntax for require sub-form in: #<module-path-index:((submod "." #%type-decl) "x.rkt")>


samth
2017-10-15 02:17:03

However, that was enough to get me to this:


samth
2017-10-15 02:17:15
(define (get-requires)
  (for/list ([m (in-list to-require)]
             #:when m)
    ;; FIXME: is this really the right code?
    #`(require (only-in #,(cons 'submod (resolved-module-path-name (module-path-index-resolve (module-path-index-join '(submod "." #%type-decl) m))))))))

samth
2017-10-15 02:17:41

which I think will make unportable zo files but should be enough to allow me to make progress on this


samth
2017-10-15 02:17:54

Thanks!


mflatt
2017-10-15 02:23:54

I agree that’s not the right thing. How about (collapse-module-path-index (module-path-index-join '(submod "." #%type-decl) m))?


samth
2017-10-15 02:31:44

That seems to work!


ryanc
2017-10-15 02:51:12

@michael.ballantyne See the custom-load package. It provides a compiled-load handler that implements recursive timestamp checking.