problem solved — I was able to generate the error in a call to sort
I thought my code was safe (I’m working in TR) but I managed to get the type checker to pass, even though the code probably shouldn’t type check.
@samth is it a known thing that sort
might cause some problems with TR? I was able to generate a crash even though the type checking succeeded. I see that there’s a fairly complex type annotation for sort
, with a bunch of unsafe stuff thrown in, so maybe this is a sign that this is not entirely unexpected.
Are you running into this? https://github.com/racket/typed-racket/pull/1008
it might be! Thanks for taking a look. I think it isn’t, because I wasn’t using the #:key
argument of sort. It was just (sort items pred)
the PR there seems to be about the #:key
part of sort
The PR is that, when elements in items
and pred
have different types, a #:key
extraction function should be demanded to be present
the current type of sort
allows #:key
to be omitted which isn’t right
OTOH, the test case looks kind of like what I’m doing
for example, (sort '((1 . a) (2 . b)) <)
— shouldn’t type check
I could probably try out this change with my local TR and see if it makes a difference
nice! I can confirm that, if I just inject the diff from the PR into my local TR, I get a type check error, as expected
I added that as a comment to the PR, in the hopes of prompting Fred to fix things
@ryanc I have created a PR for iracket to allow starting the kernel with a trusted sandbox by specifying a kernel parameter
Yes, it sounds like a bug.
I do not know what “branch day” means. If it means the day the release
branch is created, then I would like to bump a couple of PRs that I think are ready to be merged. It would be nice if they make it in time for v8.0
@javier123mendoza has joined the channel
“Branch day” is defined here: https://github.com/racket/racket/wiki/Release-overview
I strongly vote for 3599 to be merged—I pressed the ‘like’ button very hard.
Hello, everybody. I have a question about how racket/serialize works. I am creating a struct by macro with its corresponding deseriaze But it doesn’t work when I call it from the file source. In the interactions window it does work. The error is namespace-variable-value: given name is not defined
@sorawee can you rebase 3594?
#lang racket
(require racket/serialize (for-syntax syntax/parse racket/syntax))
(provide des-pie (struct-out pie))
(define-syntax (my-struct stx)
(syntax-parse stx
[(_ ID:id DESERIALIZE:id FIELD-REF:id FIELD-SET!:id)
#'(begin
(define DESERIALIZE
(make-deserialize-info
(λ (type)
(ID type))
(λ ()
(define pie-pattern (pie 'transporter-error))
(values pie-pattern
(λ (type)
(FIELD-SET! pie-pattern type))))))
(struct ID (type)
#:mutable
#:transparent
#:property prop:serializable
(make-serialize-info
(λ (this)
(vector (FIELD-REF this)))
'DESERIALIZE
#t
(or (current-load-relative-directory) (current-directory)))))]))
(my-struct pie des-pie pie-type set-pie-type!)
(deserialize '((3) 1 ((#f . des-pie)) 0 () () (0 apple)))
Done!
The serialize-info needs to embed some sort of reference to the deserializer in the serialization output. Usually, this consists of a pair of a symbol and a module path. Including the module path means that the program calling deserialize
doesn’t have to know about all the deserializers it might want to call; they can be loaded on demand. If you change 'DESERIALIZE
in the call to make-serialize-info
to (quote-syntax DESERIALIZE)
instead, then your existing test won’t work, but (deserialize (serialize (pie 'apple))
will work. (Racket can extract the right module path from the identifier.) On the other hand, the way to make your current example (which omits the module path) work would be to make sure that the current namespace has a binding for des-pie
when you call deserialize
. You can do that with the following code: (define-namespace-anchor anchor)
(parameterize ((current-namespace
(namespace-anchor->namespace anchor)))
(deserialize '((3) 1 ((#f . des-pie)) 0 () () (0 apple))))
DrRacket does something like this automatically when it runs a module. But now if you have multiple deserializers that you want to be available, you need to create an environment (that is, namespace) that contains references to all of them. That’s usually a pain, which is why we usually use the other form. (But that form does require committing to a stable module path.)
Thank you for your response!!! I was able to solve the problem I was having with a more complex macro.
Racket Users Video Meetup ️ Saturday 2021/01/09 :: 8pm CET / 7pm UK / 11am Pacific https://gather.town/app/wH1EDG3McffLjrs0/racket-users
Agenda • What have you been working on? • Paper for discussion: > Macros for Domain-Specific Languages by MICHAEL BALLANTYNE, ALEXIS KING & MATTHIAS FELLEISEN > https://2020.splashcon.org/details/splash-2020-oopsla/105/Macros-for-Domain-Specific-Languages Kind regards, Sam Phillips & Stephen De Gabrielle
is the next version of racket chez scheme as default is 7.10 or is it 8.0? https://github.com/racket/racket/wiki/Release-Calendar
It will be 8.0 (barring a last-minute change that causes BC to continue being the default)
BC will be the default still for next release :open_mouth:?
No, that’s not what I said
The plan is that CS will be the default, and the next release will be 8.0
ahh ok, misunderstood
I’m just saying that in the unlikely event that the plans change, it will be 7.10
ahh i see
thanks
Yes, the braces are probably my fault. :) But I do it for exactly the reason Sorawee mentions: it makes it easier to tell that (foo bar baz)
matches or constructs a list of three elements, while {~foo bar baz}
matches or constructs something in a less literal way. Strictly speaking, the ~
disambiguates that without needing the braces, but I started doing it at one point and have gotten so used to it that I often forget it’s not a universal convention!
As an aside, I really wish ~@
were just also named ~seq
, since that would make for a nice duality between use site and pattern site, just like list
constructs lists and matches against them in match
patterns. But that would have been difficult to do in a backwards-compatible way.
Oh nevermind I missed a provide clause in the diff
I would have been less confused by ~seq instead of ~@ I think. Those pattern matchers are so magical that sometimes it’s a little hard to predict the behaviour without really knowing how things work inside
(I know some, but I can’t say I understand syntax-parse deeply)
Odd behavior. Trying to produce (another koan) (hash #\a '(1 2 3 4 5) #\b #(1 4 9 16 25) #\c "bdcea")
; I have a working approach, but I got tired of writing (list …)
and (,… …)` , so I wrote it with `'(…)` and used `(eval …)` in a few places. Suddenly I get this strange error:
list: unbound identifier;
also, no #%top syntax transformer is bound
in: list
context...:
"/Users/Knoble/code/learn-racket/racket-koans/koans/iterations.rkt": [running body]
Here’s the code that gives the error:
(for/hash ([ch "abc"]
[build '(list vector string)]
[xform '(identity (λ (i) (* i i)) integer->char)]
[seq '((range 1 6) (range 1 6) '(98 100 99 101 97))])
(values ch
(apply (eval build) (map (eval xform) (eval seq)))))
And here’s a “check” version:
(check-equal?
(for/hash ([ch "abc"]
[build '(list vector string)]
[xform '(identity (λ (i) (* i i)) integer->char)]
[seq '((range 1 6) (range 1 6) '(98 100 99 101 97))])
(values ch
(apply (eval build) (map (eval xform) (eval seq)))))
(hash
#\a '(1 2 3 4 5)
#\b #(1 4 9 16 25)
#\c "bdcea"))
Probably a hopeless top-level situation, but this is even more strange:
> ,enter koans/iterations.rkt
'#hash((#\a . (1 2 3 4 5)) (#\b . #(1 4 9 16 25)) (#\c . "bdcea"))
``
that’s to be expected because as a program, the namespace of eval
is different from when you type it in REPL
Is this what you are trying to avoid? (for/hash ([ch "abc"]
[build (list list vector string)]
[xform (list identity (λ (i) (* i i)) integer->char)]
[seq (list (range 1 6) (range 1 6) '(98 100 99 101 97))])
(values ch
(apply build (map xform seq))))
In an improper list: (head-template ...+ . template)
there can 1 or more head templates and … what do we called the spot after the dot?
Okay reported; thanks!
Yes; I’m not sure I follow your comment about eval though
I don’t know if it’s the official term, but I’d call it a, “rest template”.
As far as I understand that in the context of the syntax
documentation, template
there is just a template — the kind of template syntax
is for.
Perhaps to be more specific, it’s a template for creating a syntax object, so I might say it’s a “syntax object template.”
A head-template
is a template for creating something else, namely a finite sequence of syntax objects. I assume they called it a "head-template
" since it’s only used at the beginning of a list, vector, or prefab struct, and they didn’t need it to have a meaningful name outside the context of the syntax
documentation. A more general term might be “syntax object sequence template.”
See https://docs.racket-lang.org/guide/eval.html#%28part._.Local_.Scopes%29 and subsequent sections
If the context you’re trying to describe things in is “a template can be an improper list made up of a sequence of head-template
productions called its ‘head templates’ and another template at the end called its ’[???],’” then I think it would make sense to go with “tail” as a complement to “head.” “Rest” works just as well on its own, but combined with “head,” I feel like there’s some mixing and matching terminology there.
Ah, that reminds me that we should probably fix the tutorial to parameterize the current namespace instead. But at least the concept is the same as the one explained in 15.1.2 and 15.1.3. And you can do this: (define-namespace-anchor here)
(define (eval-here s-expr)
(parameterize ([current-namespace (namespace-anchor->namespace here)])
(eval s-expr)))
(for/hash ([ch "abc"]
[build '(list vector string)]
[xform '(identity (λ (i) (* i i)) integer->char)]
[seq '((range 1 6) (range 1 6) '(98 100 99 101 97))])
(values ch
(apply (eval-here build) (map (eval-here xform) (eval-here seq)))))
Since you’re finding #%top
and list
are unbound, it’s likely (current-namespace)
is an empty namespace. Using a namespace anchor (as shown above) and setting up current-namespace
explicitly can make eval
a bit more reliable about what’s in scope.
The fact that doc examples about loading are evaluated in the REPL is really not ideal, IMO. when people copy the code and use it in a module, the code is almost surely not going to work.
Oh yeah, using REPL semantics for Racket examples… when Racket isn’t really designed for the REPL semantics to be intuitive on their own (“hopeless”)… That does seem like a choice worth revising if possible, particularly in a case like this where it matters.