Curious why begin0
is a core form rather than a macro
I guess it’s difficult to do that efficiently due to multiple values?
How would an expansion of (begin0 e0 e ...)
look like?
(call-with-values (lambda () e0) (lambda vs e ... (apply values vs)))
should be functionally equivalent.
Yeah, much simpler to keep begin0
- apply is expensive.
Is it also equivalent in the case (begin0 e0)
where e0
is a tail call?
Well, doesn’t matter - one can use the long form only if there is more than one subexpression.
Right, yes. I imagine begin0
is useful for the compiler, and there’s little reason not to expose it directly.
It is pretty simple to handle for a byte code interpreter.
I would admittedly hope that the bigger expression using call-with-values
would be compiled exactly the same way as begin0
, but I don’t know if the Racket optimizer actually does that optimization, especially since I doubt the call-with-values
code appears very often in the wild.
Even trickier to find out now, that Chez is the backend.
I found there’s a way to see the optimizer output—you have to set an environment variable and compile a module. I think it’s PLT_SHOW_CP0
or something like that.
Nice tip.
Ah, it’s PLT_LINKLET_SHOW_CP0
.
Hmm. Here is begin0 in Chez: https://github.com/cisco/ChezScheme/blob/68fe2d780c3b891bad493dd97457e3a2d4af88a3/examples/compat.ss#L31
(define-syntax begin0
(syntax-rules ()
((_ x y ...) (let ((t x)) y ... t))))
That’s not equivalent to a Racket begin0
.
No, in fact it looks like begin0
for Racket-on-Chez is defined here, and it does, in fact, expand into call-with-values
: https://github.com/racket/racket/blob/020c75792ca4649ed0b6994aa095cb3d02793be8/racket/src/cs/rumble/begin0.ss
I suspect the ChezScheme turns the single value case into something reasonable.
?!?
I haven’t seen that and don’t know why it would happen, so I recommend “Don’t Allow”!
The context: I picked “Open…” then got a file window. Clicked through the correct folder. Then entered a search term in the text field used to filter results.
Digging a little. It seems macOS will display these dialogs when access to certain folders is attempted. Similar situation here: https://github.com/atom/atom/issues/17687 So I guess, it’s just the way things work.
A bit confusing though.
From reading that issue, the only way we can avoid that is by adding some paths to be excluded from whatever directory traversal it was doing
@mflatt I played with RacketCS and found that function that returns multiple values won’t work well with cp0
when callsite is at top level. Is there a way to improve this?
For instance:
(define-values (foo bar) (values 1 2))
(+ foo 10)
cp0
could propagate foo
, reducing (+ foo 10)
to 11
at compile time.
However, if we have
(define (call) (values 1 2))
(define-values (foo bar) (call))
(+ foo 10)
then cp0
is stuck at
(letrec ([call (lambda () (#2%values 1 2))])
(variable-set!/define call121 call 'consistent)
(call-with-module-prompt (lambda () (#2%values 1 2))
'(foo bar) '(constant constant) foo120 bar119)
(let ([foo (#3%$object-ref 'scheme-object foo120 9)])
(call-with-module-prompt
(letrec ([procz122 (lambda () (#2%+ foo 10))])
(lambda () (#%call-with-values procz122 print-values118))))
(#2%void)))
(presumably due to call-with-module-prompt
?)