
Hi folks, I am still stumped on yesterday’s problem but found a different way to present it. Please see this video

Summary: If I use #lang
to configure the reader, I can’t get a require
to find a module I declared within a document. But if I bypass the #lang
and use the read procedure directly, the require
works fine. I don’t understand what changed since to me it just looks like two ways to run the same process.

I don’t know what the solution is, but more generally since “the top-level is hopeless” have you tried the same commands from within an actual racket module instead?

I’m not sure what exactly you’re asking me to try. Do you mean I should try the working case within a normal racket/base
module instead of the REPL?

yes

weird things happen in the REPL

checking now, stand by

Ran this using the racket
launcher. It works fine. #lang racket/base
(require "./lang.rkt")
(define in (open-input-file "./mkup.rkt"))
(void (read-line in))
(markup-read in)
(close-input-port in)

And (require "./mkup.rkt")
reproduces the error

try dynamic-require
maybe?

I assume you meant in the markup, but I used dynamic-require
in both the markup and the racket/base
module. My situation remains the same.

Specifically, the markup read:
#lang polyglot
@mod['what]{
#lang racket/base
(define out (+ 1 1))
(provide out)
}
@dynamic-require[''what 'out]

Then I can’t help you much more, sorry :slightly_smiling_face:

That’s okay. Thanks for looking.

But I meant instead of (require "./mkup.rkt")

Yeah, I changed that too. Nothing different.

good luck then!

I haven’t got a solution: just wanted to say a video was nice way of presenting the problem.

I’m pressed enough to start dumping the values of parameters and whatever the module resolver can tell me. I really don’t know how else to get a lead at this point.

Try wrapping (parameterize ((current-module-declare-name #f)) _)
around the body of run-markup
, maybe at the same time as you parameterize the current namespace.

That… seemed to do it! So the difference was that the declaring module changed?

It looks like this was the solution. Thank you @ryanc!

Here’s what I think happened: The module name resolver sets current-module-declare-name
when it tries to load a module declaration. Since you’re evaluating module declarations at read-time, you accidentally inherit the parameter setting, so when your code tries to eval a declaration for module what
, it gets adjusted to a declaration for whatever the name of the enclosing module is supposed to be.

Do you specifically want all evaluation to happen at read-time? An alternative would be to preserve all of the body forms and eval them at run time when the module is evaluated. See the implementation of the racket/load
language for example.

That makes sense to me. I’ll do that.

I’m considering various mechanisms for returning a small number of values. In the special case of two values it appears that the following are in order of efficiency: (values v1 v2)
, (cons v1 v2)
, (list v1 v2)
- does that match your intuition? I’m inclined to use (values v1 v2)

It matches my intuition in the following sense: • values
merely moves the values around • cons
uses 1 additional cons cell • list
uses 2 cons cells Missing from your comparison, a (struct pair (first second))
, which I think might be on par with list
, but I may be wrong.

I ran this for some timings. #lang racket
(for ([p (in-list (list list cons values))])
(displayln (object-name p))
(time
(for ([i (in-range #e1e8)])
(p 1 2))))

Results for me: overhead.rkt>
list
cpu time: 505 real time: 507 gc time: 51
cons
cpu time: 320 real time: 321 gc time: 6
values
cpu time: 232 real time: 233 gc time: 0

add (collect-garbage)
before the loop

Use a higher loop count to get gc involved more

I was testing with 100M iterations

Like so? (for ([p (in-list (list list cons values))])
(displayln (object-name p))
(collect-garbage)
(time
(for ([i (in-range #e100e6)])
(p 1 2))))

yes, better

why hex values for the loop max? :slightly_smiling_face:

You want free help or not? :smile:

But seriously, I just like consice notation.

oh, I misread the constant as a hex value, not e notation

No worries.

The Racket built-in libraries sometimes use values and sometimes use a cons pair, etc. - not sure if that just reflects different styles of authors, or if there is some other rationale.

IME I find myself switching it up based on how much I want to (re)write for consumers of values. Switching from list
to values
, for example, has a small re-write burden since you have to write matching define-values

Lists and pairs have the benefit of being readily useable for channels, etc.

I’d only speculate that the former motivation would have a bigger impact on style choices.

@deactivateduser60718 Are your tests with the bigger values still running?

Nope, here’s 1 billion.
list
cpu time: 4627 real time: 4642 gc time: 96
cons
cpu time: 3536 real time: 3547 gc time: 56
values
cpu time: 2411 real time: 2414 gc time: 3
overhead.rkt>

collect-garbage
still being outside time
’s body.

@deactivateduser60718 geez - what computer are you running that on?

HP Omen 15, why?

much faster than my 16" Macbook Pro

although I ran in DrRacket

I wonder what’s so different. My hardware is a bit dated.

Lemme try DrRacket

As a rule of thumb, don’t benchmark in DrRacket, as it can do a lot more things under the hood

Yep. But just for grins, #e1e9
+ DrRacket yields: list
cpu time: 5990 real time: 6015 gc time: 298
cons
cpu time: 4315 real time: 4337 gc time: 167
values
cpu time: 2421 real time: 2431 gc time: 2
>

(7.6 CS too, btw. Should have mentioned that)

Odd, when running from the command line, I get: list
cpu time: 1970 real time: 1982 gc time: 21
cons
cpu time: 607 real time: 612 gc time: 11
values
cpu time: 1557 real time: 1558 gc time: 0
badkins@create Desktop % racket bench.rkt
list
cpu time: 1980 real time: 1993 gc time: 17
cons
cpu time: 608 real time: 613 gc time: 7
values
cpu time: 1562 real time: 1564 gc time: 0

not sure why values is higher

In my test, I also extracted the values out into two variables since both the return and destructuring are necessary.

Racket 7.6 CS, linux: list
cpu time: 532 real time: 532 gc time: 8
cons
cpu time: 357 real time: 357 gc time: 5
values
cpu time: 339 real time: 340 gc time: 0

(Sage’s code with #e100e6
)

A colorful max :wink:

haha

@badkins I’m guessing running raco make
wouldn’t make much difference since the code would be compiled by the launcher anyway, but does that affect anything?

With 1e9, and a struct mypair: list
cpu time: 5426 real time: 5427 gc time: 83
cons
cpu time: 3709 real time: 3710 gc time: 44
values
cpu time: 3323 real time: 3324 gc time: 0
mypair
cpu time: 5479 real time: 5481 gc time: 82

This is pretty neat. There’s a lot to extrapolate from that

#lang racket
(define count #e1e9)
(define str-value "qwertyasdf")
(define num-value 7.85)
(define (return-values)
(values str-value num-value))
(define (return-cons)
(cons str-value num-value))
(define (return-list)
(list str-value num-value))
(time
(for ([ i (in-range count) ])
(let-values ([( str num ) (return-values) ])
(void))))
(time
(for ([ i (in-range count) ])
(match-let ([(cons str num ) (return-cons) ])
(void))))
(time
(for ([ i (in-range count) ])
(match-let ([(list str num ) (return-list) ])
(void))))
cpu time: 1146 real time: 1149 gc time: 0
cpu time: 1195 real time: 1198 gc time: 0
cpu time: 7029 real time: 7164 gc time: 331

surprised at how close values
and cons
are here

With 10 values, 1e9 iterations: list
cpu time: 18831 real time: 18834 gc time: 469
values
cpu time: 3763 real time: 3763 gc time: 0
mypair
cpu time: 14752 real time: 14754 gc time: 310
(cons excluded, obviously)

So for a larger number of values, a struct seems a little better than a list, but values is way faster anyway

@badkins My guess is that match-let
might be optimized for cons
but not for list
?

You’re right! I think it could tell the result wasn’t used.

Here’s a more valid one: #lang racket
(define count #e15e7)
(define (return-values)
(values "qwertyasdf" 7.85))
(define (return-cons)
(cons "qwertyasdf" 7.85))
(define (return-list)
(list "qwertyasdf" 7.85))
(time
(for ([ i (in-range count) ])
(let-values ([( str num ) (return-values) ])
(when (not (and (string=? "qwertyasdf" str)
(eqv? 7.85 num)))
(error "bad values")))))
(time
(for ([ i (in-range count) ])
(match-let ([(cons str num ) (return-cons) ])
(when (not (and (string=? "qwertyasdf" str)
(eqv? 7.85 num)))
(error "bad values")))))
(time
(for ([ i (in-range count) ])
(match-let ([(list str num ) (return-list) ])
(when (not (and (string=? "qwertyasdf" str)
(eqv? 7.85 num)))
(error "bad values")))))
cpu time: 171 real time: 172 gc time: 0
cpu time: 900 real time: 913 gc time: 25
cpu time: 1320 real time: 1344 gc time: 33

@greg I’ve noticed that racket-expand-last-sexp
no longer works on this branch. The expansion window opens and when I hit RET
to expand it doesn’t do anything and it writes this
string::2: match-let: unbound identifier;
also, no #%app syntax transformer is bound
at: match-let
in: (match-let (((list str num) (return-list))) (void))
to the minibuffer. Let me know if you want me to open up an issue with more details about it.

@popa.bogdanp Thanks for reporting. We must be on the same psychic wavelength, because I also just noticed this today. Well, racket-expand-file
, and a slightly different error. But also when doing RET
in the racket-stepper-mode
buffer. And probably similar root problem. I’ll take a look.

@chansey97 has joined the channel

Question (particularly for @ryanc I think): is there a way to make syntax-parse
works nicely with syntax-disarm
? I’m trying to do something similar to errortrace which needs to disarm/rearm syntax object for each depth (https://github.com/racket/errortrace/blob/master/errortrace-lib/errortrace/stacktrace.rkt#L385). If I attempt to do any more complex pattern matching, the result will be tainted.

In my previous project I solved the problem by recursively disarming everything (without rearming it afterward), but that’s probably not a good practice…

Here’s a pattern form that disarms the current term and then matches it against the given subpattern. In the simplify
macro below, if you remove the ~disarm
wrapper, you should get a tainted identifier error, but with ~disarm
it works. #lang racket/base
(require (for-syntax racket/base syntax/parse))
(begin-for-syntax
(require (for-syntax racket/base))
;; S-pattern ::= ... \| (~disarm S-pattern)
;; The pattern (~disarm p) matches a term t if p matches the term
;; after being disarmed with syntax-disarm.
(define-syntax ~disarm
(pattern-expander
(lambda (stx)
(syntax-case stx ()
[(_ pattern)
#'(~and x (~parse pattern (syntax-disarm #'x #f)))])))))
(define-syntax thunk
(syntax-parser
[(_ e) (syntax-protect #'(lambda () e))]))
(define-syntax simplify
(syntax-parser
[(_ e)
(define ee (local-expand #'e 'expression null))
(syntax-parse ee
#:literal-sets (kernel-literals)
[(let-values ([(x:id) (~disarm (#%plain-lambda () e:expr))])
(#%plain-app y:id))
#:when (free-identifier=? #'x #'y)
(eprintf "simplifying to ~e\n" (syntax->datum #'e))
#'e]
[e
(eprintf "could not simplify\n")
#'e])]))
(simplify (let ([t (thunk (+ 1 2))]) (t)))

Thanks!

Yeah the problem in both cases was that the proper current-namespace
wasn’t set. For expanding expressions, this needs to come from a REPL for the .rkt file whose context you want to use, to expand. For expanding entire files, it simply needed a make-base-namespace
. I have some code to handle both. “It works”. But I’d like to mull it over before I push a commit, even just to the check-syntax
branch.

@popa.bogdanp I think this is sufficient to fix: https://github.com/greghendershott/racket-mode/commit/c699d417918e7b74141b0d8dd798e93088917efd

Works great now. Thank you!

@programminglinguist has joined the channel

hello all! I was wondering if you could help me out with a racket distribution question. I’m having trouble building a standalone executable with r-cade on a Mac. The repo’s owner pointed me to this slack group. https://github.com/massung/r-cade/issues/20
It relies on some libraries I installed via homebrew. I tried putting whole directories from /usr/local/Cellar/ into my http://main.app\|main.app file under various locations but my friend says it’s not booting on his Mac. It’s one of those “it works on my machine” problems. :confused:

@programminglinguist I recommend using the official racket from http://download.racket-lang.org\|download.racket-lang.org. (Especially if your version is not update).

Hello! I think I am using the official racket program… right?
$ racket --version
Welcome to Racket v7.5.