soegaard2
2019-3-27 12:15:55

Fun fact: the name of a gensym symbol on Chez is not generated until it is needed. What Racket on Chez does - I don’t know.


mflatt
2019-3-27 12:28:14

There’s no guarantee. In the current implementation, the names will be different when they’re generated in the same place and run of Racket, independent of namespace.


mflatt
2019-3-27 14:09:03

@philip.mcgrath Out of curiosty, why compile example/common explicitly instead of just compiling example/foo (which will recompile whatever example/foo uses)?


mflatt
2019-3-27 14:50:00

Anyone with numerics expertise and an opinion on https://github.com/racket/racket/pull/2565 ? It looks plausible to me…



samth
2019-3-27 15:04:15

@notjack which frustrating things are you thinking of?


lexi.lambda
2019-3-27 15:22:34

Thanks, I suspected that might be the case. For context, I’m trying to figure out how to generate values at phase 1 that will be embedded in expanded phase 0 code and will be unique at runtime (but they only need to be unique within a single module). I see a few ways to do this. I could arrange for runtime definitions to be generated that hold gensyms and reference those definitions instead of generating quoted values directly. That would require some extra bookkeeping to ensure the definitions end up in the right place, though. Another might be to use identifiers instead of symbols, made with generate-temporary and preserved with quote-syntax instead of quote, then compared at runtime with free-identifier=?. That seems heavyweight, since I care about the equality check being fast, but maybe it doesn’t matter. A third way would be to just hold a mutable counter in memory at compile time and generate unique symbols by appending the counter to the end and incrementing the counter atomically using box-cas!, and I think this would guarantee that each symbol would at least be unique from other symbols generated that way during the compilation of a single module, which is all I need. Is there a better option?


pocmatos
2019-3-27 15:23:32

@mflatt not an expert on numerics but i took a look at the paper and the code and they seem to agree. I executed the tests he posted on pasterack and accuracy is higher without the issues at z=18.25 so looks good to me. only thing i would say is that i would prefer to avoid (z . < . X) comparisons in the codebase, but that’s really just a syntactic niggle.


jerome.martin.dev
2019-3-27 15:27:42

pocmatos
2019-3-27 15:33:39

@mflatt should add that a few runs of his tests showed the solution to be slower by 13.6%.


pocmatos
2019-3-27 15:34:21

Wonder if there’s anything that can be done to improve that while still having the same benefits he presented in his method.


samth
2019-3-27 15:54:53

@soegaard2 racket-on-chez doesn’t use chez gensyms


alexknauth
2019-3-27 16:02:55

No, something like .result or .norm, .value, or some other named attribute, is necessary. You can make that attribute a short name, like a single letter… that’s what (expr/c contract) does with its .c attribute.


mflatt
2019-3-27 16:04:01

That last option sounds right. The macro expander does that to generate “unreadable” symbols to represent distinct bindings. A counter that resets with each module expansion has the benefit of generating a consistent result when the same module is recompiled.


lexi.lambda
2019-3-27 16:07:14

Okay, I’ll go with that, then. Thanks!


alexknauth
2019-3-27 16:07:45

Come to think about it, you could name the attribute the “empty symbol” \|\|, and then instead of p.result you could use p.(define-splicing-syntax-class pair [pattern {~seq a b} #:attr \|\| #'(list a b)]) (syntax-parse #'(hash 1 "do" 2 "re" 3 "mi" 4 "fa" 5 "sol") [(_ p:pair ...) #'(list p. ...)])


jerome.martin.dev
2019-3-27 16:08:04

Wow, tricky :stuck_out_tongue:


jerome.martin.dev
2019-3-27 16:09:49

My issue is that I’m generating those macros, so I don’t know in advance if the element is gonna be a splicing class or not. To prevent that, I made a dummy class that has a result with it’s own content, and I apply this class to everything. This way, I always have a .result attribute. But I was trying to find a better way.


alexknauth
2019-3-27 16:12:47

I’m curious what the macros look like when you use them, and what they’re meant to do


jerome.martin.dev
2019-3-27 16:19:06

I made a way to declare objects that have attributes, like so: (define-quest-actor fish (attributes (position vec?) (color symbol?))) To create an instance of this fish, you would do like this: (fish (position (vec 1.0 1.0)) (color 'red)) But some contracts, like vec?, trigger a different syntax, in which you can omit the (vec) call: (fish (position 1.0 1.0) (color 'red)) Since I don’t know in advance if the attribute is going to have such a contract, I need to generate a macro that handle having some attributes splicing, and some not.


jerome.martin.dev
2019-3-27 16:20:21

jerome.martin.dev
2019-3-27 16:32:55

I hope it makes sense, cause this macro is starting to get out of control x)


mflatt
2019-3-27 16:54:55

Thanks!


florence
2019-3-27 17:45:20

Interesting… Why doesn’t it?


samth
2019-3-27 17:46:31

I think because it wouldn’t behave the way current racket does, but @mflatt may know for sure


samth
2019-3-27 17:47:33

(currently racketcs gensyms are about 3x slower than Racket gensyms and much much slower than Chez gensyms when you don’t look at them)


florence
2019-3-27 17:51:42

mflatt
2019-3-27 18:01:17

Yes, to “because it wouldn’t behave the way current racket does”. I have been tempted to add Racket gensyms (which are more conventional) to Chez Scheme and vice versa, but the difference has never been big enough to finish either addition.


samth
2019-3-27 18:02:25

It would be interesting to measure how many Racket gensyms are forced in the chez sense


alexknauth
2019-3-27 18:02:46

Does the vec? predicate have the syntax class associated with it or something?


notjack
2019-3-27 18:19:50

@samth I wish I didn’t have to leave racket and use the terminal for so many things. I’d prefer to write a program in a #lang saying how I’d like to compile and test code. I have memory problems so command line APIs and shell scripts are generally very frustrating for me.


samth
2019-3-27 18:20:53

ah, so more racket functions for performing compilation/package tasks?


alexknauth
2019-3-27 18:21:07

I see you’re embedding &lt;own-attr&gt;.parse-pat and &lt;own-attr&gt;.parse-res as syntax objects into the define-syntax struct. I would avoid this, and instead define a syntax class to express this.

Then instead of putting those syntax objects in the define-syntax struct, I would put identifiers that point to those syntax classes.


alexknauth
2019-3-27 18:24:46

This is similar to what you’re already doing with #'any-exp, #'vec-exp, etc, so I would just do that more, for new macro-defined syntax classes in addition to pre-defined syntax classes.


notjack
2019-3-27 18:25:47

Yes. And more determinism / reproducibility, and more APIs like that whereis module proposed by Ryan.


notjack
2019-3-27 18:27:33

I think it would also be interesting to know how many uses of Racket gensyms in macros are unnecessary.


samth
2019-3-27 18:40:19

which things are non-deterministic?


lexi.lambda
2019-3-27 18:49:47

Racket macros generally do not/should not use gensym, because it enforces uniqueness by virtue of being uninterned, but uninterned symbols become interned symbols when they are written to bytecode. Rather, Racket macros that need unique identifiers should use generate-temporary, instead, which enforces uniqueness by adding a fresh scope, which is a kind of uniqueness that cooperates well with the macro system.


notjack
2019-3-27 19:04:11

Things seem pretty deterministic on the same machine. Cross-machine determinism is what I had in mind.


notjack
2019-3-27 19:06:31

Yes. That best practice really needs to be explicitly documented somewhere. Ideally with a link to it in the docs for gensym.


leif
2019-3-27 19:18:02

Hey @alexknauth just an FYI, your hygenic reader macro package doesn’t work if:


leif
2019-3-27 19:18:35
  1. You bind something not in a reader macro.

alexknauth
2019-3-27 19:18:44

“not”?


leif
2019-3-27 19:19:08

Ya, basically if you bind something with a standard macro.


leif
2019-3-27 19:19:37

and then 2. try to reference that thing from a macro generated by a reader macro.


leif
2019-3-27 19:20:08

Like, as an example. Imagine I’ve made a (admittedly silly) macro (define-foo)


leif
2019-3-27 19:21:28

the semantics of (define-foo) is to expand to (define foo 42), where foo is added to the user’s scope.


leif
2019-3-27 19:22:24

Next, you create a reader macro, say #my-super-awesome-macro, which reads to (#%awesome).


leif
2019-3-27 19:22:52

The (#%awesome) macro expands to foo, where foo is whatever foo is bound in the user’s scope.


leif
2019-3-27 19:23:00

If I then write the following program:


leif
2019-3-27 19:23:31
#lang my-reader-macro racket
(define-foo)
#my-super-awesome-macro

You’ll get a foo unbound error.


alexknauth
2019-3-27 19:23:40

So #%awesome is an unhygienic macro, but the reference to it should be generated hygienically?


leif
2019-3-27 19:23:48

(But if you just do: (define-foo) foo it obviously works fine.)


leif
2019-3-27 19:24:00

Yes, ,that is correct.


leif
2019-3-27 19:24:32

I want #my-super-awesome-macro to always be read as this specific (#%awesome) form.


alexknauth
2019-3-27 19:27:10

I assume that if you write (define-foo) (#%awesome) That works?


leif
2019-3-27 19:29:00

Yes it does.


leif
2019-3-27 19:29:19

Because in that case (#%awesome) has the outer scope, not the inner one.


leif
2019-3-27 19:29:57

Unfortunately this might be a fundamental issue, as I can’t find any way to work around it without just dropping hygenic reader macros. :disappointed:


samth
2019-3-27 19:32:30

which things?


samth
2019-3-27 19:32:47

I think you should always get the same zo files, for example


alexknauth
2019-3-27 19:33:56

How is #%awesome defined? Does it use datum-&gt;syntax, or does it use syntax-local-introduce or something?


notjack
2019-3-27 19:40:49

I don’t really know if there’s any specific problems. I just don’t feel like I understand the big picture of how all the different flags, config files, parameters, and environment variables can affect compilation. I also don’t know how I’d test and verify aspects of the compiler.


notjack
2019-3-27 19:41:46

It’s likely much more of a communication and documentation hurdle than a technical one.


alexknauth
2019-3-27 20:25:56

@leif I got some version of this to work in the most useless way. By fiddling with the definitions of define-foo and #%awesome, I was able to get this program to work: (define-foo) #my-super-awesome-macro ;=&gt; 42 However, putting anything around the use of the reader macro causes it to fail: (define-foo) (add1 #my-super-awesome-macro) ;=error&gt; foo: unbound identifier in: foo


leif
2019-3-27 20:34:16

Sorry. my brain feels like it went through a juicer, so I had to step away from my computer for a bit. reading now.


leif
2019-3-27 20:35:00

@alexknauth #%awesome uses datum->syntax.


leif
2019-3-27 20:36:18

Anyway, #%awesome was defined with something like this:


leif
2019-3-27 20:37:03
  (define-elaborate this
    (define/syntax-parse foo (datum-&gt;syntax this-syntax 'foo))
    #'foo))

leif
2019-3-27 20:37:47

Where define-elaborate expands to a define-syntax. (A la the example @lexi.lambda was helping with yesterday.)


leif
2019-3-27 20:38:03

err…define-syntax and syntax-parse.


alexknauth
2019-3-27 20:38:18

Is that the elaborator for the editors?


alexknauth
2019-3-27 20:41:18

Anyway, If I change the definition of define-foo to use syntax-local-identifier-as-binding and syntax-local-introduce and the definition of #%awesome to use syntax-local-introduce, then I get it to work if #my-super-awesome-macro is exactly at the top level, but not within a definition or function call.


alexknauth
2019-3-27 20:46:52

Actually, this program fails the same way: (define-simple-macro (define-it) #:with x (syntax-local-identifier-as-binding (syntax-local-introduce #'it)) (define x 42)) (define-syntax-parser refer-to-it [(_) (syntax-local-introduce #'it)]) in another file: (define-it) (add1 (refer-to-it)) ;=error&gt; it: unbound identifier in: it


alexknauth
2019-3-27 20:47:23

But (define-it) (refer-to-it) ;=&gt; 42 works fine.


leif
2019-3-27 21:01:03

@alexknauth ya, that’s the elaborator for the editors.


leif
2019-3-27 21:03:24

Okay. Although that seems like an odd way to bind a new variable.


leif
2019-3-27 21:04:00

(I know @michael.ballantyne complains all the time about people needing to use syntax-local-introduce for that purpose.)


notjack
2019-3-27 21:06:13

@leif for which purpose exactly? (curious)


leif
2019-3-27 21:07:36

Oh, IIRC, its just that (ideally) syntax-local-introduce should just be an internal implementation detail rather than part of the public API. I forget why though. Anyway, I’m sure Michael would know more about what Michael thinks. :wink:


notjack
2019-3-27 21:08:28

huh :thinking_face:


leif
2019-3-27 21:09:51

Umm… I think its related to the fact that it exposes that inside of a macro is more of a negative space, while outside is a positive space. Which causes @lexi.lambda to make her…uhh….macro-like-apply?


leif
2019-3-27 21:10:16

Anyway, sorry, I’m probably not being very coherent right now. I also don’t really understand the argument entirely myself.


notjack
2019-3-27 21:10:51

sounds like someone somewhere ought to write a blog post


samth
2019-3-27 21:12:07

syntax-local-introduce is just get-the-current-scope + apply-a-scope so it seems like removing it would really mean “don’t expose scopes to macro programmers”


notjack
2019-3-27 21:13:55

I was thinking it meant that there shouldn’t be an introduction scope that’s added to macros by default, and instead evaluating #'(foo ...) should create a scope and add it to things. If anyone remembers that racket-users thread started by lexi that talked about alternate approaches to hygiene, that’s what I’m thinking of.


samth
2019-3-27 21:14:44

@notjack that’s an idea proposed previously by Andre van Tonder


notjack
2019-3-27 21:14:53

yes! that’s the one


samth
2019-3-27 21:15:42

I think you want SRFI 72


notjack
2019-3-27 21:15:57

I think I don’t know what I want


samth
2019-3-27 21:16:13

I mean, SRFI 72 is his spec document


leif
2019-3-27 21:17:09

I think I want to know what I think I want…I think?


notjack
2019-3-27 21:17:47

What I mean is although that’s definitely the right spec for that alternative, I don’t know how I feel about that specific alternative.


leif
2019-3-27 21:18:03

But ya, I think @samth is right, that its having scope sets as part of the public API…probably.


notjack
2019-3-27 21:18:50

Scope sets don’t feel like they are part of the public API now


notjack
2019-3-27 21:19:06

they’re sort of indirectly referred to via introducer functions


notjack
2019-3-27 21:19:19

but there’s no scope? predicate or scope-set? predicate


samth
2019-3-27 21:21:44

the relevant thread is syntax/parse is not hygenic from March 2018


samth
2019-3-27 21:24:17

@notjack I think the docs for make-syntax-introducer make it clear that scopes are part of the API


samth
2019-3-27 21:24:25

it has a bad name for historical reasons


samth
2019-3-27 21:24:52

and it’s encapsulated by a procedure rather than a struct with a procedure that takes it as an argument


notjack
2019-3-27 21:26:10

@samth I don’t think encapsulating scopes in procedures is the same as making scopes part of the API. The functionality is the same, but it feels totally different to users.


leif
2019-3-27 21:27:16

@notjack Is that true? Most of the users I’ve talked to (or been in the past) either have no idea what syntax-local-introduce does, or understands that its basically a toggle switch for a macro scope.


samth
2019-3-27 21:27:18

If there was a scope? function that answered #true to the results of make-syntax-introducer would you feel differently?


notjack
2019-3-27 21:28:01

@leif In fairness, I guess I can’t say if it feels totally different to users. But it does feel totally different to me.


leif
2019-3-27 21:29:07

fair.


notjack
2019-3-27 21:29:16

@samth Yes, provided there were also a few scope-related functions whose names started with scope-. Like (scope-add scope? syntax?), and similar for scope-remove / scope-flip.


leif
2019-3-27 21:29:20

Anyway, there’s also the syntax-binding-set and family.


leif
2019-3-27 21:29:44

(admittedly Mathew made that public because of some really terrible macros I needed to write.)


notjack
2019-3-27 21:30:39

this package is closer in spirit to what I think of as a “public scopes API”: https://docs.racket-lang.org/scope-operations/index.html


samth
2019-3-27 21:31:18

Right but that library is a very simple wrapper over the current API


notjack
2019-3-27 21:32:03

Yup. But it feels totally different and is much more intuitive to me.


samth
2019-3-27 21:32:20

And even more, the concepts and operations in that library are 1–1 with the racket API


samth
2019-3-27 21:32:46

So I can totally agree that such an API would be nicer


samth
2019-3-27 21:33:10

But I think they expose the same things


leif
2019-3-27 21:34:16

Just with nicer names. :wink:


leif
2019-3-27 21:34:23

(for some definition of ‘nicer’ anyway.)


leif
2019-3-27 21:36:09

Anyway, from my (very limited) experience, the more complex the macros you make, the more scope sets pop out of the API. But at least most of the time I don’t have to think about it (too much)


leif
2019-3-27 21:36:13

probably.


notjack
2019-3-27 21:36:43

@samth Think about it this way: what if everywhere racket currently uses numbers, it instead described “successor introducers” which were functions that you had to call with special arguments in order to do math? Like (num1 'add num2)


notjack
2019-3-27 21:36:55

The functionality is the same. But it’s a vastly different experience.


leif
2019-3-27 21:43:23

@notjack Wait, aren’t there some FP languages that do exactly that? And the ‘successor introducers’ do feel like just numbers.


leif
2019-3-27 21:43:26

?


leif
2019-3-27 21:43:32

Like,where 3 is a function.


leif
2019-3-27 21:44:13

And + takes a function that takes two functions and results in another function that is the sum?


notjack
2019-3-27 21:44:26

@leif There are languages that do that for a semi-internal representation of things but they usually have reader-level syntax to support it and go to efforts to simplify / hide this representation in things like error messages. Because it confuses the hell out of people.


notjack
2019-3-27 21:46:40

If you want to write a number like three, you just write the number 3. If you want to add things, you just write 3 + 5. This might be achieved through a representation of numbers as closures and defining + as a closure-accepting-and-returning operator. But you aren’t forced to actually think about that.


notjack
2019-3-27 21:47:16

And docs don’t describe numbers as “successor introducers”, they just call them numbers.


philip.mcgrath
2019-3-27 22:03:34

@mflatt I guess because I thought that didn’t work. I’m not sure exactly what I was doing when I formed that belief (much less a way to reproduce it), because I’ve been doing it this way for a while, but there are points in my workflow when I run into linkage errors, and I thought compiling only example/foo wasn’t enough to solve them if example/common had changed.


philip.mcgrath
2019-3-27 22:07:05

One possibility is that I’m conflating in my memory pressing Run in DrRacket, which I do frequently (I think I have ⌘i + ⌘s + ⌘r in muscle memory), with explicitly running raco setup. I vaguely remember there being some issues where the two interacting caused friction.


leif
2019-3-27 22:29:28

@notjack Okay, then I must be missing something here. Because I don’t see how your description of (num1 'add num2) is substantively different from num1 + num2. But that’s okay. Brain no longer feels like jelly thank god, so I can get back to work. :slightly_smiling_face:


notjack
2019-3-27 22:46:03

@leif There’s no functionality difference. There’s only communication and experience differences. For example, when I put the text cursor over + in DrRacket and press F1, I get taken to documentation for +.


notjack
2019-3-27 22:46:43

People underestimate how much those kinds of differences affect what code people write


leif
2019-3-28 00:40:32

OH! You are literally just talking about documentation, not about API design itself.


leif
2019-3-28 00:40:43

Okay, in that case yes, that makes sense.


leif
2019-3-28 00:42:27

In that case, its hard to say for macros, because there isn’t any good guide in the docs (from my experience), and therefore its pieced together by academic papers, books, and blog-posts.


leif
2019-3-28 00:42:44

That, and poking others…


leif
2019-3-28 00:43:38

So…. null?


leif
2019-3-28 00:44:07

lol slack fail. Srry.


notjack
2019-3-28 00:48:01

Still works :p


krismicinski
2019-3-28 02:18:24

Totally uninformed random question. Is there anything Jekyll-like in Racket? I know I could hack Scribble but I’m looking for something a bit closer to what Jekyll does in Ruby. My guess is that it could be done much more naturally in Racket via macros.


samth
2019-3-28 02:19:26

@krismicinski I think you want frog


krismicinski
2019-3-28 02:19:37

yeah, was just looking at toad too :slightly_smiling_face: https://parametri.city/blog/2015-06-01-toad-design.html


krismicinski
2019-3-28 02:19:46

Thanks for the frog pointer. I’ll check them out.


krismicinski
2019-3-28 02:22:16

Yeah, this looks really nice. I’ll try moving my site over from Jekyll soon!


greg
2019-3-28 02:26:34

Last few days, I’ve been exploring redoing my own blog, using a Makefile driving a few command-line tools, which are mostly a few pieces copied/modified from Frog.


greg
2019-3-28 02:27:43

I might put those pieces in a lib called “tadpole”. :slightly_smiling_face:


greg
2019-3-28 02:28:31

Or I might just make one or two missing Racket packages (e.g. to make Atom and RSS feeds).


samth
2019-3-28 02:28:42

also jekyll is no longer the hotness in static blog generation


greg
2019-3-28 02:28:43

and just share the other glue code in a repo, not a package.


samth
2019-3-28 02:28:58

everything should be a package!


greg
2019-3-28 02:29:27

I don’t plan to abandon Frog. I’m just kind of at the point where, if anyone wants it to do more features or be more configurable, I don’t think I can really do that.


krismicinski
2019-3-28 02:29:56

@samth what is the hottest now?


greg
2019-3-28 02:30:03

I kind of feel like there’s some Greenspun’s Tenth Rule about static blog generators being implementations of make.


samth
2019-3-28 02:30:14

I hear about hugo


krismicinski
2019-3-28 02:30:16

github pages supports jekyll out of the box. But it doesn’t work with the bibtex2html tool I use, so I hand-compile and then upload to generate my site.


krismicinski
2019-3-28 02:30:48

I tried using hakyll a while back. It was nice. Then the API changed from Arrows to Monads and broke 50% of the entire codebase I wrote up laboriously while learning Haskell along the way.


krismicinski
2019-3-28 02:34:38

I’d like to start using Racket-based tools as a matter of principle, though.. :slightly_smiling_face:


jesse
2019-3-28 05:13:26

@krismicinski sounds like Pollen might be useful (https://pollenpub.com)


krismicinski
2019-3-28 05:33:02

You’re right, it does sound good, and I’ve used it once. My intuition tells me that frog is going to take slightly less work to make it do what I want, but I think frog is built on top of Pollen.


sorawee
2019-3-28 05:38:24

Pollen and Frog are different enough that I wouldn’t say one is built on top of the other, but if I must, I would say that Pollen is built on top of Frog. In fact, Pollen’s Markdown mode simply uses Frog’s Markdown parser. Pollen’s syntax highlighting is also borrowed from Frog.


sorawee
2019-3-28 05:40:20

You are right that Frog is going to take less work to make it do basic stuff. Pollen’s main goal is not static blog generation, so it doesn’t have, for example, basic page layout supports.


sorawee
2019-3-28 05:44:33

IMO, deciding whether Frog or Pollen is the right choice depends on how much you want to have control over document manipulation. Frog won’t let you manipulate content much (in a nice way), whereas in Pollen, the intermediate document data structure is xexpr of which you have a complete control.


jesse
2019-3-28 05:51:07

@greg at Racketfest lots of people talked about racket-mode for Emacs — kudos for working on it!


krismicinski
2019-3-28 06:16:06

@sorawee in general I do want pretty low-level control over how HTML and such gets laid out.


krismicinski
2019-3-28 06:16:53

I’m all for building beautiful things, but often when I’m hacking on websites I just need to do something kind of dirty because the time investment often isn’t worth justifying (why I use Jekyll, tbh). That being said, I’d be willing to put in some time to learning a tool if it were in Racket (more than I would in Ruby)


diego
2019-3-28 06:48:39

@krismicinski @samth I use Hugo for my website, it’s very powerful but with a bit of a learning curve. I have now gotten to the point where I have my templates the way I want, and I can produce the Hugo markup for my website from a big org-mode file, so I barely even see it. Netlify automatically then builds and hosts the website itself. Works nicely :slightly_smiling_face:


diego
2019-3-28 06:49:50

@krismicinski you get a lot of low-level control with Hugo, if that’s what you want. I think there might even be a semi-automated Jekyll-to-Hugo converter out there.


diego
2019-3-28 06:50:59

Hugo is in Go though, so you need to learn and get used to the go templating engine, which is kind of weird, but you get used to it.


krismicinski
2019-3-28 06:55:04

Yeah, I use Jekyll very productively now and know how to hack on it well, but I’d be interested in using something Racket-based for catharsis..