mflatt
2018-4-9 07:18:30

I’ve upgraded all of the native libraries to new versions, so watch out for problems – either package/build problems or regressions due to the actual upgrades


mflatt
2018-4-9 07:39:14

One problem: the package manager will install “draw-<platform>–3”, which replaces the dependency on “draw-<platform>–2” for “draw-lib”, but it won’t automatically uninstall “draw-<platform>–2”. If you’re updating an existing development build, you may need raco pkg remove --auto to clean out “draw-<platform>–2”. (The package manager doesn’t currently detect that those two packages conflict by installing libraries with the same names. It’s likely that "…–3" libraries will overwrite "…–2" libraries, but it’s probably not guaranteed.)


lexi.lambda
2018-4-9 14:04:59

@alexknauth I noticed you forked Hackett this morning. I’m not sure if you care, but fwiw, my (currently very broken) work in progress branch replacing the type representation is wip/syntax-typerep.


alexknauth
2018-4-9 15:46:36

I see it


lexi.lambda
2018-4-9 15:49:28

Good! I figured you would, but just making sure. I’m a little curious why you forked it in the first place. :)


alexknauth
2018-4-9 15:53:26

If I end up using my macrotypes-nonstx repo to make an extension to Hackett, I want the prefab-struct type representation to be an option, since that’s what most of macrotypes-nonstx was designed for.


lexi.lambda
2018-4-9 15:59:38

I think I see. I’m not sure the prefab representation is unworkable, and if you manage to come up with something, certainly let me know. I’m feeling a bit better about the way I’m planning on using syntax objects here, though, since I’m still in control of the type language (unlike the way turnstile currently does it, which doesn’t use a stop list).


abmclin
2018-4-9 16:17:53

@lexi.lambda congratulations on your new PLT@Northwestern position!


githree
2018-4-9 16:31:10

Not that I am selfish but this is great news for Racket (and me by extension ;) I found it to be extreme misallocation of resources that people like Alexis couldn’t work on Racket full-time. Glad this is being fixed! Congratulations Alexis, Northwestern and Racket!


racket588
2018-4-9 19:11:06

I am having some issues with understanding how I can introduce temporary variables into my macros. I am basically compiling my own language to Java and want the output Java to not have any compound expressions.

For example: let’s say I have (def x (= (+ 2 4) (+ 3 8))) and want to expand it to something like (list (def t1 (+ 2 4)) (def t2 (+ 3 8)) (def x (= t1 t2))).


racket588
2018-4-9 19:12:58

The catch, though, is that I don’t actually know the variable name that I will need when handling an arbitrary depth of expressions.


racket588
2018-4-9 19:15:09

I attempted to capture the temp symbol holding the final value of the whole expression in a syntax property, but this is no longer available (as far as I can tell) once the macro has expanded. In other words, the outer macro where I need the value has already expanded its template.


racket588
2018-4-9 19:15:31

So, is there some better way to reference this syntax property?


racket588
2018-4-9 19:17:01

If not, then would the best alternative to be to introduce generate temp values, then inject them into an intermediate form along with the original expressions, then use this to generate the subexpressions? I.e., pass the temps forward through the templates instead of trying to retrieve them backwards through syntax properties?


racket588
2018-4-9 19:17:15

Or, is there a better approach all together for sharing data in this manner?


racket588
2018-4-9 19:22:33

A better example. perhaps:

(define-syntax (constraint-def stx) (syntax-case stx () [(_ ID EXP) #’(list EXP (define-constraint ID ???))]))

Here, I put the expression before the definition so that it will be broken down into sub-expressions before the final assignment. In the ??? I need the name of the last temporary variable used.

The expression gets expanded, more or less, by this:

(define-syntax (comp-expr stx) (define ltemp (new-temp-symbol)) (define rtemp (new-temp-symbol)) (define exptemp (new-temp-symbol)) (syntax-case stx (=) [(_ LEFT "=" RIGHT) #`(list (val-comp #,ltemp LEFT) (val-comp #,rtemp RIGHT) (define-value #,exptemp (= #,ltemp #,rtemp)))]))

So, if I need to either access the exptemp value in the constraint-def macro to fill in the ??? or I need to create a temp variable (or use the ID, I guess) in the constraint-def macro and make it available to use in place of the exptemp value in the comp-expr macro.


racket588
2018-4-9 19:29:45

Should I just generate the temp symbol in constraint-def and add it to a syntax property of the EXP?


ben
2018-4-9 19:32:10

The first thing you described should work


ben
2018-4-9 19:32:46

(expand subexpression, subexpression stores its name as a syntax property, parent expression gets the syntax property)


ben
2018-4-9 19:33:00

but you’d need to call local-expand to expand the subexpression


racket588
2018-4-9 19:35:08

Thanks. I’ll look up local-expand and see what I can do.


racket588
2018-4-9 20:07:14

@ben That worked wonderfully. Is there some kind of cookbook style website for this kind of thing? I don’t mind digging in and learning this stuff, but it seems rather difficult to even know where to look. If such a website existed, that would be great. If not, would there be much benefit in me writing such a website?


ben
2018-4-9 20:07:53

racket588
2018-4-9 20:18:22

I’ll take a look


racket588
2018-4-9 20:18:23

Thanks


racket588
2018-4-10 00:06:16

Is there a cleverer way to unit test a single macro which may expand to something which contains unbound identifiers than to do the following: create a test file, import the macro I need to test, implement a dummy macro that will match the result and quote everything?


racket588
2018-4-10 00:34:46

Also, what circumstances can lead to a single syntax property being returned as a pair?


racket588
2018-4-10 00:35:23

Racket was fun, but I’m starting to question whether or not this was a good idea…


racket588
2018-4-10 00:35:50

Is my problem that I am trying to do this stuff without contracts? Would using typed racket be better?


notjack
2018-4-10 00:37:09

@racket588 not sure if it’s right for your exact use case, but have you seen the syntax/macro-testing module?


racket588
2018-4-10 00:37:29

I have not.


racket588
2018-4-10 00:37:37

Let me take a look at that real quick.


racket588
2018-4-10 00:38:54

@notjack I’ll have to give it a shot, but it sounds like what I’m trying to do.


notjack
2018-4-10 00:40:02

@racket588 also see the expand-once function and similar forms, that’s what I used to build the macro testing utilities of my expect package


racket588
2018-4-10 00:40:39

That also sounds like it might be good for what I’m doing…


racket588
2018-4-10 00:42:22

@notjack Have you read “Programming Languages: Application and Interpretation”?


notjack
2018-4-10 00:42:53

No, but I’m vaguely aware of it


racket588
2018-4-10 00:43:47

I worked through “Beautiful Racket,” and am finding that it’s coverage is not even remotely sufficient for what I’ve gotten into (and the creation of custom macros that have to be reverse engineered when you need to remove the training wheels has caused some problems). I was just wondering if that would provide a better basis for learning these types of things.


racket588
2018-4-10 00:44:00

Or if there is a better resources.


racket588
2018-4-10 00:44:32

My searches so far seem to indicate that my options are: papers, documentation and read other people’s code.


racket588
2018-4-10 00:44:39

Which is fine, but very time consuming.


notjack
2018-4-10 00:50:48

I can’t speak to PLAI but these are the resources I personally have found helpful for learning how to structure nontrivial macros:

  • The examples section in the syntax/parse documentation
  • The “Fortifying Macros” paper
  • The “Keeping It Clean With Syntax Parameters” paper
  • Some of Ryan Culpepper’s blog posts and miscellaneous articles on macros
  • The turnstile library and the paper on it

notjack
2018-4-10 00:51:42

And the mailing lists


notjack
2018-4-10 00:53:33

More approachable resources would be wonderful


notjack
2018-4-10 00:55:08

The set-of-scopes documentation was also very helpful


notjack
2018-4-10 01:01:42

also hackett


racket588
2018-4-10 01:02:43

Yeah, I was digging through hackett the other day to try and figure some things out


lexi.lambda
2018-4-10 01:02:54

@racket588 re: properties becoming pairs, see the documentation at the top of this page on how properties are merged by the expander http://docs.racket-lang.org/reference/stxprops.html


racket588
2018-4-10 01:02:59

Is this the set-of-scopes stuff you meant? https://www.cs.utah.edu/plt/scope-sets/


notjack
2018-4-10 01:03:04

yes


racket588
2018-4-10 01:05:27

re: Hackett, is it possible to define macros, etc. using Hackett? Like, would that basically allow me to get the magic of hygienic macros, etc. that make Racket nice while allowing me to basically use Haskell?


lexi.lambda
2018-4-10 01:05:57

Not yet, but eventually. But there are lots of problems to solve first.


racket588
2018-4-10 01:07:23

darn.


lexi.lambda
2018-4-10 01:07:25

There is not really any theoretical reason you couldn’t (require (for-syntax hackett)) and do business as usual, but you’d be stuck with nothing but syntax-e, datum-&gt;syntax, and quote-syntax, which are sort of a Turing tarpit when it comes to macros.


lexi.lambda
2018-4-10 01:08:06

Figuring out how to properly typecheck all the nice things Racket has for writing macros probably isn’t trivial.


racket588
2018-4-10 01:08:23

I was poking around the other day to see if I could do racket style macros in Haskell and hoped maybe I was just asking the question backwards.


lexi.lambda
2018-4-10 01:09:01

I think the answer to that question is that it’s impossible. At least this way it’s possible, just not there yet. ;)


racket588
2018-4-10 01:09:44

That would be nice.


racket588
2018-4-10 01:10:30

re: pairs, I sort of suspected something like that when I inspected the syntax objects and saw the “source(?)” property, but I wasn’t able to reproduce it.


racket588
2018-4-10 01:10:53

I’ll have to figure out where exactly the two properties are coming from


racket588
2018-4-10 01:11:38

In the meantime I’ll just use car and feel guilty


notjack
2018-4-10 01:12:58

the basic idea is that syntax properties are kind of version controlled by the macro expander


notjack
2018-4-10 01:13:54

macros can’t destroy information about what the syntax property was before they were invoked


lexi.lambda
2018-4-10 01:13:57

The fact that the merging is not controllable by the programmer is absolutely unfortunate.


lexi.lambda
2018-4-10 01:14:36

It’s hard to know how to give more control with a pleasant interface that is backwards-compatible with the existing implementation, though.


notjack
2018-4-10 01:14:55

¯_(ツ)_/¯


racket588
2018-4-10 01:14:57

The weird part for me is that I am handling the properties in the exact same way in my macros, but I get pairs in one place and not the other. So something outside of those two macros is introducing this and I have to get my head wrapped around things a bit to figure out that.


notjack
2018-4-10 01:15:20

it’s the expander itself that introduces that


notjack
2018-4-10 01:15:35

as in, the racket code that recursively crawls the syntax tree and calls your macros


racket588
2018-4-10 01:15:49

So it’s not weird to get a pair of, for example (’temp1 . ’temp1)


lexi.lambda
2018-4-10 01:16:14

That means the input syntax object to your macro and the output syntax from your macro both had 'temp1 for that property’s value.


racket588
2018-4-10 01:16:18

I.e., the exact same property from the same location


racket588
2018-4-10 01:16:35

Yeah, that was my understanding, but I don’t see how (yet)


racket588
2018-4-10 01:16:58

Could it be because I generate a list of expressions from a single expression at some point…


racket588
2018-4-10 01:17:36

I don’t do that in the macro in question, but maybe something before or after that macro does


notjack
2018-4-10 01:19:24
  • your macro is a function from syntax object to syntax object
  • expander sees a use of a macro in the syntax object it’s currently expanding
  • expander notes what syntax properties exist on that syntax object
  • expander calls your macro
  • expander see what properties exist on the syntax object returned by your macro
  • expander alters those properties so they’re now a pair, where the first item of the pair is the value of the property on the returned syntax object and the second item of the pair is what the value of the property was before calling your macro
  • tada! now macros that erase syntax properties (because they construct syntax objects without them) don’t accidentally destroy useful information needed by later macros

notjack
2018-4-10 01:19:53

(I might have gotten some details wrong on how the pair / list is constructed during that “merge” operation but that’s the spirit of it)


racket588
2018-4-10 01:20:21

“expander notes what syntax properties exist on that syntax object”


notjack
2018-4-10 01:20:47

the duplication you see in a property value '(temp1 . temp1) happens because your macro likely directly returns a syntax object it was given as input


notjack
2018-4-10 01:21:17

by “notes” I just mean “remembers in some local variable somewhere in the expander’s implementation”, I don’t mean that it alters the syntax object in any way there


racket588
2018-4-10 01:21:29

Ah, so, for instance: (syntax-case [(_ EXP) #’EXP)])


racket588
2018-4-10 01:21:48

where the EXP then gets expanded and receives a property in another macro?


lexi.lambda
2018-4-10 01:21:53

@racket588 Here’s a tiny program that demonstrates the behavior: #lang racket (require syntax/parse/define) (define-syntax-parser m1 [(_) (syntax-property #'(m1 (+ 1 2)) 'x #t)] [(_ e) (syntax-property #'e 'x #t)]) (m1) If you look in the macro stepper, the resulting (+ 1 2) expression has '(#t . #t) for the 'x property.


notjack
2018-4-10 01:21:54

in spirit, but I think that might not do that sometimes? I forget the details of how pattern variables affect properties


lexi.lambda
2018-4-10 01:23:10

Alternatively, change the first #t to 1 and the second #t to 2 to get '(2 . 1).


racket588
2018-4-10 01:23:36

Yeah, I just don’t see where it’s happening in my code (yet). Could it be related to the use of local-expand?


notjack
2018-4-10 01:23:50

local-expand will do this yes


lexi.lambda
2018-4-10 01:23:51

Depends on your code.


notjack
2018-4-10 01:23:58

because it calls the expander


notjack
2018-4-10 01:24:17

but it depends on how you’re using syntax properties and how exactly your macros construct syntax objects


notjack
2018-4-10 01:25:09

also, there’s a special property called 'origin that works like a normal property except the expander adds it automatically, it tracks the history of what macros expanded a piece of syntax


racket588
2018-4-10 01:26:20

notjack
2018-4-10 01:30:32

@racket588 the temp symbols thing you’re doing makes me suspicious of whether adding static info to an identifier would be simpler than using syntax properties in your case


notjack
2018-4-10 01:31:25

or something with syntax parameters


racket588
2018-4-10 01:32:59

I need to work on finishing this band-aided prototype, then in a couple of days I’ll see about doing how I should have done it :slightly_smiling_face:


notjack
2018-4-10 01:33:33

entirely reasonable :)


racket588
2018-4-10 01:33:34

Once I have more than a couple weeks of Racket under my belt


racket588
2018-4-10 01:33:56

And read some papers, etc.


lexi.lambda
2018-4-10 01:34:47

Can you provide an MCVE? https://stackoverflow.com/help/mcve


notjack
2018-4-10 01:39:14

@lexi.lambda re the discussion on your syntax-parameterize issue: the fact that local-expand doesn’t propagate stop lists is massively surprising to me


racket588
2018-4-10 01:39:24

@lexi.lambda when, I get a chance I definitely will. I was unsuccessful in reducing the code while still reproducing previously and gave up.


lexi.lambda
2018-4-10 01:40:24

@notjack Based on the current API, what would it mean to propagate stop lists? What happens when a local-expand inside another local-expand provides its own stop list?


notjack
2018-4-10 01:43:02

“should the expander stop” seems pretty monoidal to me - nested uses mean the expander stops more often


notjack
2018-4-10 01:43:10

when would that not be what you want?


notjack
2018-4-10 01:43:39

“more often” meaning “when either use says expansion should stop”


notjack
2018-4-10 01:44:24

> ryanc is typing uh oh


ryanc
2018-4-10 01:45:27

@notjack the point of calling local-expand is to turn a form into something from a known grammar; if the context can add things to the stop list, the macro doesn’t know the grammar of the result, and it has no hope of interpreting the result of local-expand in the general case


notjack
2018-4-10 01:47:04

yes, I’d consider that a contract violation between the macro calling the outer local expand and the macro calling the inner one - the former gave the latter an expansion context where it wasn’t allowed to acquire the information it needs


ryanc
2018-4-10 01:47:24

For a concrete example, suppose the macro does head-expansion (stop list = #f) and assumes that only things starting with define-values or define-syntaxes can be a definition. If the macro’s context can add define, or struct, or whatever to the stop list, it breaks that macro’s assumptions.


notjack
2018-4-10 01:48:10

right


notjack
2018-4-10 01:49:49

a macro calling local-expand with a stop list can also assume that some things aren’t expanded because of the stop list (e.g. macros contained within a use of #%expression), and that’s kind of the opposite sort of problem


notjack
2018-4-10 01:52:59

I think my general train of thought is uses of local-expand where you only want to expand something into a partially known grammar


ryanc
2018-4-10 01:58:41

All of the uses of local-expand I can think of pretty much break down into three categories: full local-expand (empty stop list), head expansion (which yields a grammar with unknowns but where the outermost structure is known), and head expansion with extra subforms (eg class and init/public/private/field/etc, unit and import/export (?)). And I guess there are is a fourth class where there’s a protocol between the expansion context and the macros (eg all primitive forms expand to quoted expressions) to trick the macro expander into doing things it wasn’t really designed for originally.


ryanc
2018-4-10 02:01:45

It sounds like you have in mind a protocol or agreement between outer macros and inner macros, but I don’t think that really fits the use cases the local expansion mechanism was designed for. I tend to think of the “stop list” as a bit of a red herring: it invites people to think there’s more flexibility there than there is in practice.


ryanc
2018-4-10 02:07:49

On the other hand, that’s my perspective from “classic” macros. You might discover that stretching the macro expander beyond its original intentions to do new and cool things with languages can make using these mechanisms (local-expand, the stop list) in unusual ways make sense.


notjack
2018-4-10 02:24:38

@ryanc yes I think that’s exactly what I have in mind, this helps clarify things for me


pocmatos
2018-4-10 06:51:49

@ryanc was #2033 merged?


pocmatos
2018-4-10 06:54:08

@ryanc awesome, looks like it was.


felix
2018-4-10 06:57:51

I know this has probably been asked a thousand times, but how do I write a callback for EnumWindows?