pocmatos
2018-1-18 10:36:00

What’s the best way to calculate the startup time of a racket program? I notice that when I do racket myprogram.rkt x y z, sometimes it looks like my program only really starts after 7secs or so. That’s a lot. My program takes less than that to complete.


abmclin
2018-1-18 18:14:10

More raco pkg questions; what’s the usefulness of the --scope-dir option? When I use it for installing a pkg, I noticed that the package dependency resolution process seems to ignore the installation and user scopes and raco pkg will try to download pkgs that are already installed in installation scope. That seems to reduce the utility of --scope-dir so I was wondering what use cases --scope-dir is meant to support.


blerner
2018-1-18 21:49:39

quick date manipulation question in Racket: is there a function that lets me compute e.g. “February 27, 2018 plus 3 days yields March 2, 2018”? I’d like to be able to fold starting from an initial date and some list of deltas (2 days later, 1 day later, 4 days later, etc) and compute all the valid dates along the way


blerner
2018-1-18 21:50:05

(I don’t care about string manipulation; I assume the racket/date library’s date->string function will suffice from there)


lexi.lambda
2018-1-18 21:50:24

consider using the gregor library instead of racket/date / srfi/19


blerner
2018-1-18 21:51:20

that’ll do it, thanks


leif
2018-1-18 23:43:48

I am trying to get an identifier whose binding is a particular module. And it seems like combining module->namespace with namespace-symbol->identifier does the trick at phase 0. But at phase 1 I am getting the same #%top undefined error.



leif
2018-1-18 23:44:21

leif
2018-1-18 23:44:43

Obviously if you remove the begin-for-syntax Its properly bound.


leif
2018-1-18 23:45:12

I wonder if I’m still doing overly strange stuff @mflatt?


leif
2018-1-18 23:52:58

Also, if I do a syntax-shift-phase-level by -1, it is able to find the binding again.


leif
2018-1-18 23:54:13

Which makes me think that the one of those two namespace functions aren’t properly shifting the phases given that they’re in a begin-for-syntax.


mflatt
2018-1-18 23:58:23

@leif While running at phase N for N > 0, identifier-binding implicitly checks bindings at phase N–1 (because the expectation is that you’re using identifier-binding at compile time to inspect run-time code), while namespace operations work at the current phase N (because the expectation is that you’re dynamically loading code at the current phase). So that’s why shifting by –1 does what you want. Another possibility is to supply the current phase to identifier-binding, where (variable-reference->phase (#%variable-reference)) is one way to get the current phase.


leif
2018-1-19 00:01:45

I guess that makes sense. But then why does the following macro complain about the match identifier being unbound?:

(define-syntax (my-m stx)
  (dynamic-require 'racket/match 0)
  (define x
   (parameterize ([current-namespace (module->namespace 'racket/match)])
     (namespace-symbol->identifier 'match)))
  x)

mflatt
2018-1-19 00:13:44

Since the namespace operations in the macro happen at phase 1, the match identifier will have a binding at phase 1 and not at phase 0.


leif
2018-1-19 00:16:23

That would make sense, but if I shift it down a phase with: (define x (syntax-shift-phase-level (parameterize ([current-namespace (module->namespace 'racket/match)]) (namespace-symbol->identifier 'match)) -1))


leif
2018-1-19 00:16:45

then I get an error saying the module is not available: require: namespace mismatch; reference to a module that is not available reference phase: 0 referenced module: "/Users/leif/racket/racket/collects/racket/match/match.rkt" referenced phase level: 0 in: match context...: /Users/leif/racket/racket/collects/syntax/wrap-modbeg.rkt:46:4 standard-module-name-resolver


mflatt
2018-1-19 00:20:23

Yes, that is a correct error. Since you’re manipulating the phase of the syntax object, you’re breaking the connection between the instantiation of the source module and the reference to that module.


mflatt
2018-1-19 00:22:49

But, for example, if you (require match) in a phase–0 position (such as in the same place where my-m is defined), then match will be available.


leif
2018-1-19 00:25:39

That would make sense. I however don’t want to do that because (as I understand it), that would bring match in as an identifier for the rest of the module.


leif
2018-1-19 00:26:13

I did try a dynamic-require in the template, but that gave the same error.


mflatt
2018-1-19 00:26:26

A (require (only-in match)) would make the module available without binding anything


leif
2018-1-19 00:26:45

OH!!!


leif
2018-1-19 00:26:47

That’s a great idea.


leif
2018-1-19 00:26:49

Thanks.


mflatt
2018-1-19 00:27:21

Or something like (namespace-require '(for-template racket/match)) in the macro


leif
2018-1-19 00:29:13

Oh cool, that worked, thanks: (define-syntax (my-m stx) (dynamic-require 'racket/match 0) (define x (syntax-shift-phase-level (parameterize ([current-namespace (module->namespace 'racket/match)]) (namespace-symbol->identifier 'match)) -1)) (namespace-require '(for-template racket/match)) #`(#,x '(1 2 3) [_ 'yay]))


leif
2018-1-19 00:29:53

Actually…never mind.


leif
2018-1-19 00:30:01

Because the identifier is still bound there: (identifier-binding #’match)


leif
2018-1-19 00:30:55

That is, if I do: (my-m) (identifier-binding #'match) under that, I get the binding to racket/match


leif
2018-1-19 00:33:23

Oh, also doing the (namespace-require '(for-template racket/match)) only works in the terminal, not drracket. That’s odd…


mflatt
2018-1-19 00:36:39

Ok, re-expansion (as in DrRacket) won’t work, because the macro side-effect won’t happen for the re-expansion. I guess you get the idea, anyway.


leif
2018-1-19 00:38:11

Ah, okay.


leif
2018-1-19 00:38:28

So probably put it in the template and have it do it, or something like that.


leif
2018-1-19 00:38:30

Anyway, thanks.


lexi.lambda
2018-1-19 01:14:04

@leif @mflatt I’m probably missing something here, but why doesn’t syntax-local-lift-require do the trick?


leif
2018-1-19 01:17:18

@lexi.lambda Because I…err…didn’t know of its existence. :slightly_smiling_face:


leif
2018-1-19 01:17:25

Thanks for pointing it out to me. :heart:


marioepugh
2018-1-19 01:22:30

@marioepugh has joined the channel


lexi.lambda
2018-1-19 01:23:36

leif
2018-1-19 01:27:05

Oh cool, thanks.


leif
2018-1-19 01:28:00

Sadly, when I use take syntax-local-lift-require out of the toy example and put it in my actual project, I get an ambiguous binding error: editest.rkt:3:22: vertical-block$:elaborate: identifier's binding is ambiguous context...: #(78302 module) #(78303 module editest 0) #(78313 macro) #(78316 local) #(78317 intdef) matching binding...: #<module-path-index:(editor)> #(78302 module) #(78303 module editest 0) matching binding...: #<module-path-index:(editor/stdlib)> #(78303 module editest 0) #(78313 macro) in: vertical-block$:elaborate context...: standard-module-name-resolver


leif
2018-1-19 01:28:06

So now I get to detangle that.


leif
2018-1-19 01:28:11

Anyway, thanks @lexi.lambda


lexi.lambda
2018-1-19 01:28:44

I’d try and make sure you’re using syntax-local-introduce appropriately and stripping all the other scopes.


marioepugh
2018-1-19 01:29:25

Can someone help me with this, I am struggling.


marioepugh
2018-1-19 01:29:32

We are asked to help out with a new software for manipulating images. The team needs us to write a function that will detect if an image is larger than some other image. An image is larger than another image when both the width and height of the first image is larger than the width and height of the second image.

Design a function called image>? that consumes two images and returns #true when the height and width of the first image is larger than the height and width of the second image.


marioepugh
2018-1-19 01:30:29

I am attempting to learn racket and trying to write this code but cant grasp it. Any help would be awesome. Thanks


leif
2018-1-19 01:31:47

@lexi.lambda syntax-local-introduce didn’t work, but: (datum->syntax #f (syntax->datum #'modname)) did.


leif
2018-1-19 01:32:01

I’m sure there’s a better way to strip away other lexical information though. :slightly_smiling_face:


leif
2018-1-19 01:32:05

Anyway, thanks again.


lexi.lambda
2018-1-19 01:32:08

@leif yes, that’s what I mean by “stripping the other scopes”


lexi.lambda
2018-1-19 01:32:21

but I think you probably want to do that plus syntax-local-introduce


lexi.lambda
2018-1-19 01:32:46

(that is, call syntax-local-introduce on the result of the call to syntax-local-lift-require to avoid the macro-introduction scope)


lexi.lambda
2018-1-19 01:32:56

but that’s maybe not really necessary


leif
2018-1-19 01:33:06

Oh, interesting…


leif
2018-1-19 01:33:14

Well I’ll keep that in mind.


leif
2018-1-19 01:33:32

I honestly haven’t been able to find a good intuition as to when I need syntax-local-introduce and when I don’t.


lexi.lambda
2018-1-19 01:33:35

The #%namespaced form uses a function that strips the lexical information but preserves source locations: https://github.com/lexi-lambda/racket/blob/0ef4118f876eb2d565be7d5345690e789ab698b1/racket/collects/racket/private/namespaced-transformer.rkt#L9-L23


leif
2018-1-19 01:33:43

(And when I do but the error is not immediately obvious…)


lexi.lambda
2018-1-19 01:33:53

I only understood syntax-local-introduce after I learned about the sets-of-scopes expander.


leif
2018-1-19 01:34:00

That makes sense.


leif
2018-1-19 01:34:16

I don’t care about source locations in this instance, but thanks. :slightly_smiling_face:


leif
2018-1-19 01:34:30

(I don’t care because no user will ever see them. :wink: )


leif
2018-1-19 01:34:41

I mean, I know what syntax-local-introduce does.


leif
2018-1-19 01:34:47

It makes perfect sense what it does.


lexi.lambda
2018-1-19 01:35:01

@marioepugh That sounds like homework, so we will probably not answer directly, but we might be able to help if you describe specifically what you are confused about.


leif
2018-1-19 01:35:03

I just haven’t been able to get a good intuition of when I need to use it, you know?


lexi.lambda
2018-1-19 01:35:34

It’s definitely subtle. But I know too much now, and I can’t remember not knowing it.


lexi.lambda
2018-1-19 01:36:36

The main instances in which I get confused about syntax-local-introduce these days are when certain functions implicitly apply syntax-local-introduce in ways that don’t seem well-documented.


leif
2018-1-19 01:36:39

Ya, that makes sense.


leif
2018-1-19 01:37:33

Also, I tend to agree with @michael.ballantyne that ideally syntax-local-introduce should be an internal detail.


leif
2018-1-19 01:37:49

It just…can’t…because its hard to create the theory for it.


leif
2018-1-19 01:38:01

(Given how powerful racket’s macro system is.)


lexi.lambda
2018-1-19 01:38:12

I think Racket’s macro system suffers a little bit from a variety of functions that try to have a “do what I mean” feel to them, which works okay for simple macros, but you need to understand what’s going on under the covers to do really weird things, and the implicit behavior makes it harder to reason about.


lexi.lambda
2018-1-19 01:38:27

Like how identifier-binding implicitly shifts the phase, as you bumped into earlier.


leif
2018-1-19 01:38:29

But sure, how did you get a good intuition for when you need it?


leif
2018-1-19 01:38:48

Like, I get when you need to use custom syntax introducers, as well as custom syntax delta introducers.


leif
2018-1-19 01:39:04

Its just specifically flipping the macro scope. :wink:


leif
2018-1-19 01:39:32

@lexi.lambda Oh yes, I absolutely agree.


lexi.lambda
2018-1-19 01:39:45

Right. And I’m not sure there is more to it than that, in isolation. I guess the hard part is learning when you need/want the macro scope and when you don’t?


leif
2018-1-19 01:39:59

There is so many useful things that are just…weird.


leif
2018-1-19 01:40:14

And either they’re not documented, or they are, but its a wall of technical details.


leif
2018-1-19 01:40:32

mmm…good point.


leif
2018-1-19 01:40:37

Well in that case I have that.


leif
2018-1-19 01:41:07

I just guess I don’t find it satisfying. Oh well.¯_(ツ)_/¯


lexi.lambda
2018-1-19 01:41:45

The name of syntax-local-introduce is sort of indicative of this DWIM intent, I think… the name is not “syntax-local-flip-macro-introduction-scope” because, in simple situations, you use syntax-local-introduce to really introduce a binding into the surrounding scope? So it’s named in such a way that the scope-flipping is supposed to be an implementation detail.


leif
2018-1-19 01:42:12

Ehh…


lexi.lambda
2018-1-19 01:42:21

But I never managed to build an intuition for it until I understood what it actually did (i.e. flipped the scope), so I don’t think that abstraction is very watertight.


leif
2018-1-19 01:42:22

But even in simple case, its better to use #:with …


lexi.lambda
2018-1-19 01:42:43

#:with doesn’t adjust scopes at all, though? I don’t follow… what is the relationship?


leif
2018-1-19 01:43:32

I mean, for introducing new piece of syntax.


leif
2018-1-19 01:43:37

a new piece of syntax.


leif
2018-1-19 01:43:49

Which is why syntax-local-introduce is kind of…an odd name choice.


leif
2018-1-19 01:44:09

But ya, syntax-local-flip-the…. is ..well…ya.


lexi.lambda
2018-1-19 01:44:55

Well, syntax-local-introduce is about introducing a binding into the enclosing, relative-phase–0 scope. #:with is just about binding a pattern variable for use in phase 1 macro code. So I don’t think there’s much of a conflict/ambiguity there?


leif
2018-1-19 01:46:11

There isn’t.


lexi.lambda
2018-1-19 01:46:39

I guess what I’m saying is that Racket tries to be a declarative macro system in the spirit of the original syntax-rules, and it is pretty good at that for a lot of simple things, but I think the abstraction totally breaks down once you start doing slightly nontrivial hygiene bending.


lexi.lambda
2018-1-19 01:47:06

Which isn’t necessarily bad? It’s just an observation.


leif
2018-1-19 01:47:14

But its a common pattern to use with combined with format-id to break hygiene. Which in my monkey brain sounds like introducing new syntax.


leif
2018-1-19 01:47:40

I’m not saying theirs a conflict, just an unfortunate name choice that fucks with my personal intuition. :wink:


lexi.lambda
2018-1-19 01:47:54

Right… the subtlety there is that format-id copies the lexical context from another piece of syntax, and that syntax already has the macro-introduction scope. :upside_down_face:


leif
2018-1-19 01:48:05

Yup


leif
2018-1-19 01:48:09

exactly


leif
2018-1-19 01:48:23

Still….you can’t ‘choose’ what fucks with your brain sadly. :disappointed:


leif
2018-1-19 01:49:12

And ya, I am okay with it being mostly declarative, but the current implementation leads to some leaky cases that causes programmers in other languages to shy away from it.


lexi.lambda
2018-1-19 01:50:57

Definitely! I think the general failure to properly develop any book or documentation that introduces the low-level macro programming facilities gives at least some reason to think that maybe it’s just too complicated (though a simple lack of time is a big part of that problem, too).


lexi.lambda
2018-1-19 01:52:16

I don’t know how to make it better, though. I’m not sure there’s a simpler or more internally-consistent formulation that makes sense?


leif
2018-1-19 01:53:42

Maybe.


leif
2018-1-19 01:53:54

That is the problem @michael.ballantyne is trying to solve.


leif
2018-1-19 01:54:05

Its also what set of scopes tried to solve.


leif
2018-1-19 01:54:28

But every solution seems to break down when you get syntax-local-* and local-expand related stuff.


leif
2018-1-19 01:54:40

(Every solution that I’m aware of anyone trying.)


leif
2018-1-19 01:55:01

I’m still keeping my fingers crossed that there is actually a nice clean mathematical model.


lexi.lambda
2018-1-19 01:55:33

I know some of @michael.ballantyne’s thoughts, though I do personally find sets-of-scopes relatively easy to understand, probably with the exception of inside/outside-edge scopes (which I know are one of Michael’s pet peeves).


lexi.lambda
2018-1-19 01:56:54

It’s just that Racket doesn’t really provide a direct interface to sets-of-scopes. Or, well… it does, but the names are all different! And different functions implicitly do all sorts of different things based on different edge cases and circumstances.


leif
2018-1-19 01:56:55

Oh yes


leif
2018-1-19 01:56:59

I absolutely agree.


leif
2018-1-19 01:57:09

Compared to the mark/anti-mark model, scope sets are a godsend.


leif
2018-1-19 01:57:16

I just don’t think its simple enough. :slightly_smiling_face:


leif
2018-1-19 01:57:45

Hmm..


leif
2018-1-19 01:57:51

Interesting.


leif
2018-1-19 01:58:18

I wonder what it would be like to use a macro system that is still scope sets, but tried, as a principle, to avoid having special cases.


leif
2018-1-19 01:58:28

Like, would it be nice to program in.


lexi.lambda
2018-1-19 02:00:09

Right. Do you think understanding procedural macros would be easier or harder if we had functions like make-fresh-scope instead of make-syntax-introducer, identifier-bindings=? instead of free-identifier=?, and identifier-scopes=? instead of bound-identifier=?? I don’t know. Maybe it’d be a lateral move.


lexi.lambda
2018-1-19 02:01:44

And don’t get me started on syntax-local-identifier-as-binding. :)


leif
2018-1-19 02:07:12

lol…


leif
2018-1-19 02:07:21

I 100% think it would be easier for crazy stuff.


leif
2018-1-19 02:07:29

I just don’t know about simple stuff.


leif
2018-1-19 02:07:45

And its not really a system where you can have a ‘simpler’ api and a ‘complex’ api.


lexi.lambda
2018-1-19 02:07:49

That’s my feeling, too. Maybe it doesn’t make sense for them to share the same names, or even the same set of functions.


leif
2018-1-19 02:07:50

Because that would be worse.


lexi.lambda
2018-1-19 02:08:25

I think it’s not impossible to have a low-level and high-level API. We already have syntax/parse ways of doing things that are different from older approaches.


leif
2018-1-19 02:10:00

True.


leif
2018-1-19 02:10:27

Although to be fair, the current way our docs introduce macros to new people is kind of…bleh? you know?


leif
2018-1-19 02:10:59

Like, they introduce simple syntax-rules like macros, and then sort of jump in at the deep end.


leif
2018-1-19 02:11:13

I really prefer @greg’s approach in fear of macros.


leif
2018-1-19 02:11:24

Where he gives you a simple understanding of the model.


leif
2018-1-19 02:11:29

Which you can then build on.


leif
2018-1-19 02:11:57

So, like, if we were to do that, I would (ideally) want the simple api to grow into the complex api.


leif
2018-1-19 02:12:18

So that new programmers have a path for how to do progressively more crazy things.


lexi.lambda
2018-1-19 02:12:48

I think it’s hard to have a one-size-fits all approach to teaching macros, since for many people, syntax-rules (or define-simple-macro, as the case may be) is enough.


leif
2018-1-19 02:13:35

Yup


leif
2018-1-19 02:13:43

I never said it was easy.


leif
2018-1-19 02:13:47

It might even be impossible.


leif
2018-1-19 02:14:11

Still, its a thing that I strive for…at least ideally.


leif
2018-1-19 02:14:23

I’d also like a solution to the halting problem and a unicorn. :slightly_smiling_face:


ben
2018-1-19 04:20:39

Anyone know how to go from “an identifier exported by Typed Racket” to “the identifier that the programmer defined, before Typed Racket created a new identifier to protect the export” ?


ben
2018-1-19 04:21:03

lexi.lambda
2018-1-19 04:46:51

@ben Dang, before I finished reading your question, my instinct was to respond with “I think there’s an unsafe-reprovide form or something that does that”. :)