So the cut thing will definitely not work then? Good to know.
It seems that syntax/parse has some backtracking mechanism (see #:commit
) but it’s not clear how exactly. Is this better documented somewhere?
I think the backtracking stuff is only relevant when syntax-parse
fails and is trying to figure out what error message to show.
The Fortifying Macros paper is what I’m vaguely remembering that from.
Drat, the paper doesn’t describe the commit mechanisms at all.
> When there are multiple alternatives, such as multiple syntax-parse clauses or multiple variants of a syntax class definition, they are tried in order. When an alternative fails, syntax-parse records the failure and backtracks to the next alternative. As alternatives are tried, syntax-parse accumulates a list of failures, and each failure contains a measure of the matching progress made. If the whole matching process fails, the attempts that made the most progress are chosen to explain the syntax error. Usually, but not always, there is a unique maximum, resulting in a single error explanation. Otherwise, the maximal failures are combined.
Oh I see. Thanks, that’s helpful! A little strange too because this implies that backing can only fail too, which I’m not sure holds. I’m probably missing something though.
Do require
and provide
ignore scopes, under certain circumstances?
No? But if you are producing require
as the output, then beware that if stx=(require foo)
then the context of stx
and require
can be different. If I recall correctly, the context is taken from the require
identifier.
For context: I’m taking a require-spec, then using it to generate (syntax-local-introduce
#'(begin (require <require spec>)
(provide (all-from-out <required module path>))))
I thought that the syntax-local-introduce
would prevent that require/provide fragment from interacting with other requires and provides in the module, however, the all-from-out
seems to include all identifiers required from the module path, from anywhere in the module.
I think, that’s just how all-from-out
works. It doesn’t know about the require forms.
Suppose we have two functions, func1 and func2. The user must call func1 before func2 (like create and destroy functions). Also func1 receives an argument that should be visible to func2 too. To achieve this we can do:
(define global-arg #f) (define (func1 local-arg) (set! global-arg local-arg) …) (define (func2) ;I can use global-arg …)
I was thinking if this can be done in a pure functional way. Is this possible?
Well. Not sure if this is a good idea or not, but: • let func1
return two values: the current result and func2
This way the user can’t call func2
before func1
.
You can use parameters. Func1 could also produce a value that you send to func2, so that func1 is a function
I’d like that user had not to manage the func2 like a return value of func1. But I guess is one of the best solutions
I have not used parameters so much, so I dont understand your solution xdxd
Although this “pattern” isn’t super common in Racket code I’ve seen, it’s not unusual for a “create” or “start” function to return a function that does the “destroy” or “shutdown”.
The web-server does this.
I have to study parameters hehe
There’s also an example in https://docs.racket-lang.org/more/index.html#%28part._.Server_.Thread%29
I think it’s actually a nice, clean, functional way to handle this.
I mean, it can be a PITA to keep track of the various “destroy” or “stop” or “shutdown” procedure values.
OTOH when an app gets a little complicated, sometimes you really do need those things to be explicit — things need to be started/stopped in a certain order.
@hectometrocuadrado ^
@greg Thanks for your explanation!
I think Im going to do that
If the use pattern of these functions is very simple — you call func1, you do some work, and then you call func2 — this can be packaged up with a more convenient interface, like how call-with-input-file[*]
works.
I wouldn’t characterize parameters as purely functional (but they should be used when there are good use cases, I am not trying to denigrate them).
My preferred method of solving this is to pass a lambda to func1 which is executed and the “cleanup” is automatically taken care of at the end of the lambda:
(define (func1 body)
(let ([x #f])
(dynamic-wind
(lambda () (set! x (setup)))
(lambda () (body x))
(lambda () (cleanup x)))))
(func1 (lambda (return-of-func-1) ...))
FYI Sauron IDE https://github.com/racket-tw/sauron/releases/tag/v0.3.0
but they were deceived for another IDE was created
I’m assuming that is a LOTR reference?
yes
from the one ring inscription
To be super pedantic, the ring inscription itself says “one ring to rule them all, and in the darkness bind them”
And the line you quoted is from the explanation of it
happy birthmasyear 43×47 y’all