
Hi, I am new to Racket and have a couple of questions about what is possible to implement in a #lang, and how I should proceed to implement the following features for my #lang and my ideal Racket development environment:
- I want to build a #lang without Garbage Collection with rust’s memory model, is there a way to implement such a #lang in Racket? Maybe someone already did it?
- I need a Racket environment running under wasm in a Native Web App, is there a way to compile Racket to wasm and have it generate wasm code? Thanks in advance, a curious but still very new Racketeer

- Do you need “no garbage collection” or just something that behaves the same way?

(I don’t have any answers - I am just trying to unpack the question)

@soegaard2, Ideally I would like a full Racket environment with no GC and rust’s ownership and borrowing methodology instead. That is ideally, in the very long run, because I think it would require a lot of time. But for now, I want to learn how to make a #lang that doesn’t use the GC and handles memory manually. I will then try to make the rust’s ownership system through macros

Racket has GC. You can disable it per instruction at https://docs.racket-lang.org/reference/garbagecollection.html and I think you can use the unsafe API to manage memory yourself. It won’t come with “rust’s ownership and borrowing methodology”.

From the description that you provided, I don’t think Racket would be suitable for your task.

Okay, thanks for the feedback, I will look into this documentation. I will probably mostly use Racket as a prototyping tool then :)

How accurate is it to say that Racket (#lang racket
, not typed/racket
) is a softly typed language? I think what the term “softly typed” is where we can choose whether something is statically typed or dynamically typed? I think Racket is said to be softly typed because of contracts (?), but not entirely sure.

Also, I should have started with this one because it is the most important in my case : > <https://racket.slack.com/archives/C06V96CKX/p1618564624039600|2. I need a Racket environment running under wasm in a Native Web App, is there a way to compile Racket to wasm and have it generate wasm code?>

(some-form-a foo)
(some-form-b foo)
two foo
s are free-identifier=
. say I have some syntax property on the first foo. How can I access that property through the second foo?

Here’s the source list of mirrors used at http://download.racket-lang.org\|download.racket-lang.org (note that many are commented out): https://github.com/racket/racket-lang-org/blob/master/download/data.rkt#L58

I don’t think there’s any way to do that. Properties are associated with syntax objects, not bindings.

:sadpanda:

@phanthero I don’t think “softly typed” is a term I’ve heard before. I would say that Racket (meaning #lang racket
) is not typed. Contracts are not types.

@thybault.alabarbe If you want Racket compiled to the web, I recommend looking at racketscript, here: https://github.com/vishesh/racketscript/

@thybault.alabarbe You could implement a #lang that was like Rust, in that it called malloc
and free
explicitly under the hood based on where Rust does the same. However, you can’t do what Rust does with stack allocation in Racket. You would of course need to implement the rust type system and borrow checker.

Ok yes, I had most of these in mind, but when you say: > you can’t do what Rust does with stack allocation in Racket > do you mean that Racket cannot modify the way it interacts with the stack?

Would the 6502 asssmbler approach used in https://docs.racket-lang.org/asi64/\|https://docs.racket-lang.org/asi64/ be suitable to target another language(wasm)?

I mean that Racket values, except for fixnums (and flonums in some cases) are always heap-allocated.

That’s interesting, I’ll follow the project but the lack of tail call optimization might be a bit of a trouble for performance

It’s definitely still early for that project, if you are looking to compile real racket applications to javascript we’d be happy to have you contriibute.

Ok I think I get it, not even pointers to heap allocated data are stored in the stack frame?

pointers are stored in the stack frame (or in registers)

but except for fixnums, all Racket values are pointers to heap-allocated data

Sure! I’ll probably build up on some of the tooling. And I think this is my last question since you seem to be involved in the project, do you know if the compiler can itself run in the browser?

Not yet, but that’s a goal.

Alright, thanks!

Ok got it, thanks for your help!

I guess @phanthero might be referring to “soft typing”


I just ran into some weird behavior (from my perspective in any case). I have this module: #lang racket/base
(struct foo (x)
#:name Foo
#:constructor-name Foo)
(define my-foo (Foo 1))
(displayln my-foo)
When I run this in DrRacket, I get the output #<foo>
, as expected.
Now I add a contract: #lang racket/base
; Only this `require` and the `provide` form are new here.
(require racket/contract)
(provide
(contract-out
(struct Foo ([x integer?]))))
(struct foo (x)
#:name Foo
#:constructor-name Foo)
(define my-foo (Foo 1))
(displayln my-foo)
When I run this, I get: foo: unbound identifier in: foo
with the foo
in (struct foo (x)
highlighted.
In case you wonder, I also tried using foo
as the contract name in the provide
. When run, this gives me contract-out: expected a struct name in: foo
This is what I had expected.
I wonder what’s going on here. Is this a bug? If not, what am I doing wrong? What fix or workaround do you recommend?

This is a bug in contract-out

I experimented a bit more. I get the confusing message only when I use #:name
and #:constructor-name
together.

Is it a known bug, i. e. in the tickets? I didn’t find anything in the ticket system (but I also checked the open bugs so far).

It looks like this is probably a bug in struct
where a combination of #:name
and #:constructor-name
with this same identifier doesn’t work right.

I don’t think so

I only recently noticed this while investigating related behavior in Typed Racket with @capfredf

Ok, I’ll enter a ticket then.

You probably saw my other reply, but just in case: I think it’s probably a bug in struct
instead of contract-out
.

Yes, I saw your reply. Thanks for reminding me still, so I can add this information (that it’s a bug in struct
) to the ticket.

I think there are some issues in contract-out
when you use #:name
as well.

As a workaround, I can probably get by with leaving out the #:name
for now, since I don’t use match
with this type and don’t use the type as a super-type. Still, if you have other suggestions for the contract to achieve what the contract should do, I’m listening. :wink:

Maybe I should leave out the information where the bug probably is? I suggest you two add this information after further checks.

I think @mflatt is right about the specific error you got.

Ok, thanks!


Speaking of this issue, @mflatt, do you remember why did you make a change at https://github.com/racket/racket/commit/096ec546a62b7f36b15ee086c389e59887a0250d?

It causes an issue at https://github.com/racket/racket/issues/3277, but it’s unclear which one between struct-out
and contract-out
is more “correct”

I added a comment in the issue.

I have the following struct
definition: (struct progress-data ([records #:auto])
#:auto-value (gvector)
#:constructor-name Progress-Data)
and the following contract: (provide
(contract-out
(struct progress-data ([records gvector?]))
[add-progress-record! (-> progress-data? integer? integer? integer? any)]
))
In this module, I can use (Progress-Data)
, as expected due to the #:auto
field.
When I import the above module into another module and there invoke (Progress-Data)
, I get an arity mismatch error (expected: 1, given: 0). This corresponds to the contract, but not the struct definition. On the other hand, if I delete the field from the contract, i. e. (provide
(contract-out
(struct progress-data ())
[add-progress-record! (-> progress-data? integer? integer? integer? any)]
))
Racket gives me an error contract-out: found 1 field in struct, but 0 contracts
How does the contract have to look like to allow using (Progress-Data)
in the importing module?

@capfredf Instead of putting a syntax property on the identifier, what you can do is (define-syntax foo <data you want>)
then, you can retrieve the data with (syntax-local-value #'foo)
in a macro.

Hi @soegaard2, I made another attempt at fixing this, on the “ah/macos” branch, can you please try it out?

@sschwarzer This looks to me like a bug in either contract-out
, or struct
, possibly related to the relatively recent changes. But #:auto-value
is rarely a good idea: in this case it would create a single mutable gvector shared by all Progress-Data
instances.

Yes, I think #:auto fields are not supported correctly by contract-out; it would need you to provide #:auto in the contract-out spec

Ouch, I don’t want a shared vector. I thought this would be evaluated for each struct instance. And I even wouldn’t have noticed because for the time being, I’ll probably need only one Progress-Data
instance.

So I guess I should go with a “constructor function” like make-progress-data
instead that creates a Progress-Data
with an empty gvector
?