This seems like the liberal expansion of define
, function-name
here is a macro which can do something different with #%app
Ah, indeed, function-name
is a macro. But the question is, why doesn’t #%app
check if the first argument is a kwarg macro and invoke the macro.
Probably it needs to be improved.
And actually, this gets me curious how https://docs.racket-lang.org/fancy-app could have worked on keyword arguments
Shouldn’t (define add2 (add/kw 2 #:to _))
result in a macro invocation?
It would check whether the binding of #%app
has changed. https://github.com/racket/racket/blob/53ef242889f11554470a11f7c97a565136678e5a/racket/collects/racket/private/kw.rkt#L1335
Just checked. In racketcs, schemify could do this optimization.
ah, nice
Oh i see, that makes sense now. So the return value could be either 'yes
or 'maybe
but not 'no
, is that correct?
I think I remember a discussion in which it was mentioned that, although match
can accept non-linear patterns, the algorithm is buggy and such patterns should be avoided. Is that the case?
I would expect bugs to be fixed :slightly_smiling_face: It is tricky to get an intuition for the time usage when non-linear patterns are being used. My way of thinking is: how would a naive recursive function implement the pattern.
for contract-stronger?
, yeah, but maybe a more general interface could have instances that respond “no”
match
is a pretty intricate piece of code, and i would think twice before assuming that computational-order bugs are fixed. Best to track down the discussion and commits, or time it yourself.
That is a limitation of the current implementation. Possibly, it would be better to trigger the optimization through #%app
itself detecting keyword-argument rators, instead of of the rator being a macro that expands to an optimized call.
That optimization is done at compile time
That’s how the kw argument implementation communicates with the optimizer to enable that optimkzy
match has bugs that result in compile time errors with non-linear patterns and …
But in all other cases they work fine and you can tell if you got the compile time error
I think a check in the kw app form to eliminate itself when the operator is bound to a keyword procedure macro would be easy to implement
very nice! I graduated from a university in NC so that’s very interesting to me
@leafac Hi. I am looking at you css-expr
package and it looks interesting. I notice that at the Github repo is archived. Why?
How can I make a macro expand a form to the top-level? The following macro fails with the error “require: not at module level or top level” :
(define-syntax (require-rename stx)
(syntax-parse stx
[(_ path name1 name2)
#'(require (rename-in path (magic-query name) (magic-query-run-all name2)))]
[(_) (error "invalid argument")]))
Actually, nevermind. That macro succeeds. I edited it slightly before posting and I see the problem now.
I’m trying to write a macro that will expand to a sequence of require forms based on the contents of a certain directory. Below are the two macros I’m using. If I call require-magic-rename individually, they work. But include-magic-from-dir does not. (define-syntax (require-magic-rename stx)
(syntax-parse stx
[(_ path)
#:with name-prefix (datum->syntax #'path (last (string-split (string-trim (syntax-e #'path) ".rkt") "/")))
#:with name1 (format-id #'name-prefix "~a-query" (syntax-e #'name-prefix))
#:with name2 (format-id #'name-prefix "~a-query-all" (syntax-e #'name-prefix))
#'(require (rename-in path (magic-query name1) (magic-query-run-all name2)))]
[(_) (error "invalid argument")]))
(define-syntax (include-magic-from-dir stx)
(syntax-parse stx
[(_ path)
(let ([magic-files (filter
file-exists?
(directory-list (syntax-e #'path) #:build? #t))])
(printf "~a~n" magic-files)
#`(begin
#,@(for/list ([file-path magic-files])
#`(require-magic-rename #,(path->string file-path)))))]
[(_) (error "invalid argument")]))
;; elf-query is unbound after calling this line but it seems to expand correctly
(include-magic-from-dir "../magic")
;; these work as expected
(require-magic-rename "../magic/elf.rkt")
(require-magic-rename "../magic/images.rkt")
Does require not perform as expected when wrapped with begin? Is there an alternate form I can use instead of begin. I expect there is a simple solution to this but it is escaping me with my limited experience with macros.
Most likely what you’re seeing is that expanding to a require is tricky
Because require is really a non hygienic macro
Any way I can get around this? I can expand to one require ok, I just need to expand to a number of them. In my case is the begin expanding in module context or expression context?
Basically, I want to drop a large number of files in my custom language into a directory and have them compiled into this application.
You probaly need to use datum->syntax
The begin
is not the issue
Were you thinking the datum->syntax should go in include-magic-rename or require-magic-rename. I’ll probably have to futz with this for a bit as none of my attempts so far are working.
I mean include-magic-from-dir, not include-magic-rename.
Hmm, so is the issue that the bindings I’m creating in require-magic-rename — name1 and name2 in the macro — aren’t the same as the ones used in my program. If so, I think I understand why it is a hygiene problem.
Yes
When I wrap the requires in datum->syntax I get an error as well because the requires are no longer at module level. I see functions like syntax-binding-set and syntax-shift-phase-level. Could any of those help.
?
At least I understand the problem now! Thanks for that.
No, you don’t want to do that. You are almost certainly not using datum->syntax correctly if that started happening when you add them
Here’s my version with syntax->datum: (define-syntax (include-magic-from-dir stx)
(syntax-parse stx
[(_ path)
(let ([magic-files (filter
file-exists?
(directory-list (syntax-e #'path) #:build? #t))])
(printf "~a~n" magic-files)
#`(begin
(datum->syntax #'path
(syntax->datum
#,@(for/list ([file-path magic-files])
#`(require-magic-rename #,(path->string file-path)))))))]
[(_) (error "invalid argument")]))
That gives me the error: require: not at module level or top level ; in: (require (rename-in "../magic/elf.rkt" (magic-query elf-query) (magic-query-run-all elf-query-all)))
which is referring to the line in my require-magic-rename macro.
As a test, I was able to pass some syntax from the module level down into require-magic-rename to use when creating name1 and name2 and it now finds the bindings that I was creating/renaming(name1 and name2), but of course all the other bindings provided by the require are still missing. So this is definitely the problem.
Maybe I can get it to work if I rewrite it such that I’m only using one macro. I may give that a try tomorrow.
The datum->syntax
stuff should happen during the expansion of the macro. Currently, you’re inserting it into the macro result, creating a function call that looks like (syntax->datum (require ...) (require ...) (require ...) ...)
so indeed you now have require forms that aren’t at the top level.
I haven’t tested this, but it might be what you’re looking for:
#,@(for/list ([file-path magic-files])
(datum->syntax #'path
`(,#'require-magic-rename ,(path->string file-path)))))
[edit: code formatting]
I’m fond of literate programming and I have been using noweb for a while. I like the layouts produced by noweb, but I would much rather run a tool like CWEB. I know you guys use Scribble and I think you use it for everything, but I haven’t seen any Scribble-generated PDF that looks as nice as documents produced by noweb. I suppose that would be a matter of producing new Scribble styles, but I suppose that would take a TeX or LaTeX designer that’s proficient enough to do a similar job? I’m sharing a small program I wrote recently that illustrates the sort of final output that I look for in literate programming tools. I would love to find out that all of this is possible to do with Scribble. Any thoughts are very welcome.