
@lexi.lambda I think (and a test agrees) that marshalling and unmarshalling doesn’t make distinct uninterned symbols equal, but it can make equal uninterned symbols unequal. But if the uninterned symbol stays within a single compiled module, it should work as expected.

Marshalling compile-time gensym
-generated symbols is still bad, though, because it breaks deterministic compilation. But that’s because the gensym counter doesn’t follow the rules for independent compilation of modules, and that affects the symbol names.

I think it was @notjack’s — at least, he did all the work

Are exceptions future safe?

er no, thinking about it I suppose they couldn’t be in the general case.

I’m asking about the case where the exception is thrown and caught in the future.

From the docs: “Similarly, work in a future is suspended if it depends in some way on the current continuation, such as raising an exception. A suspended computation for a future is resumed when touch is applied to the future.”

Can would-be-future
be used to make an experiment that tests this?

I think gensym
should never be used

Should we use (string->uninterned-symbol "temp")
instead? /s


Definitely not :p


Does anybody know if there’s an interface to compile a module down to a linklet and obtain that linklet? I can see compile-linklet
from racket/linklet
. That should allow me to compile the linklet once I get ahold of it, but I can’t seem to find something akin to expand
that will take my module and spit out a linklet bundle/directory for it.

@pocmatos don’t know, but FYI one module compiles to multiple linklets (because phases, mostly) and one source file can contain multiple modules

@notjack right, that’s the linklet directory. that’s what I would like to have. :slightly_smiling_face: trying to find some code already doing that but not being very lucky at that.

@pocmatos I want that too, so if you find something let me know. If you don’t find anything, consider opening an issue in rebellion asking for a nice source-to-linklets compilation API :p

I will remember that. I heard the maintainer is open to feature requests. :slightly_smiling_face:

I am trying just now to run the benchmarks to automate this process in CI. I have attempted the run.rkt
script in shootout
but it breaks due to a missing current-bm.rkt
. I was luckier with auto.rkt
but I assume that using your mini-bar-plot
script I can get fancier results. It seems to take a file
as input but I don’t quite get what this file
is.

@pocmatos there isn’t something like that, and adding it would require being more specific about what you actually want

in particular, what do you want to do with compile-time computation? do you want to get those linklets? or just run them?

ok

so at a certain point in this presentation: https://www.youtube.com/watch?v=t09AJUK6IiM&t=894s

^- by the way, for those who haven’t watched it, you should!

in any case, @mflatt makes the case that given linklets we currently implement compile-linklet
and a couple of other functions and get a different backend. Either normal racket or racketcs.

So, in principle to compile racket to language X
you should be able to grab a linklet and compile to X
.

and then you get Racket -> X
.

I wanted to attempt to do something like this. Implement in Racket, a Racket transpiler to Javascript using the nanopass framework. This would be for my own edification, so I am not concerned about getting all of racket or make it production complete.

That isn’t really an accurate summary of how it works

That might be a problem indeed. :slightly_smiling_face:

Let me try to phrase it simply

and then I can clarify as needed

To write a racket implementation, you do the following:

- write an implementation of
compile-linklet
andinstantiate-linklet
(ie, write an interpreter for the linklet language)

- call
compile-linklet
andinstantiate-linklet
~in~ on the linklet extracted from the expander

step 2 gives you a bunch of values in the resulting linklet instance, which are named things like eval
and read
and current-namespace

- set up some initial state for the expander

- call
eval
(or similar eval-like functions likedynamic-require
) on things

That’s basically it

ok. so although i didn’t get the details it’s not very far from what I expected. However, at the moment you can’t actually get step 2. You say linklet extracted from the expander
but the expander gives you a fully expanded program, not a linklet. As far as I understand, they are not the same thing.

So back to my initial question, what I really wanted was for a way to extract this linklet in racket. Something like extract-linklet (-> path-string? linklet?)

or as mentioned earlier it would probably be a linklet-directory?
, not just a linklet?

My idea initially was to actually start the transpiling experiment from fully expanded programs. It was only after some research that I though… ah, maybe I should get fancy and do it using linklets
… and my evening is suddenly gone. :slightly_smiling_face:

The whole point of this is my own education. I am working at the moment on JavaScript JIT and GC technologies and I thought I should spend some time learning more about JavaScript. And what better way is there than to try to transpile Racket to Javascript…

sorry, step 2 should say “on”

The fundamental issue is that compile-linklet
and instantiate-linklet
are designed to be called inside the implementation of the expander (ie, inside the defintions of expand
and eval
)

you basically don’t call them yourself at all

so for me to use linklets I need to reimplement expand
?

no

but expand gives me a fully expanded program, not a linklet. I see the definition of compile-linklet
, instantiate-linklet
in chez for example but I don’t actually understand how the connection is made.

you’re getting the direction of calls wrong

it might be helpful to look here: https://github.com/pycket/pycket/blob/master/pycket/racket_entry.py#L427

ok. Thanks. I will take a look at the code and see if I understand how these things fit together.

but schematically a JS implemenation of racket would look like this: function instantiate_linklet(l, args) { .... }
let expander = ... // some ast for the extracted expander linklet
let expander_instance = instantiate_linklet(expander, [])
while (1) {
console.log(expander_instance.get("eval")(expander_instance.get("read")(get_input_from_user())))
}

where instantiate_linklet
contains a core-racket interpreter + a bunch of primitives

yes, that makes sense. I will need to look better at pycket (don’t think i had heard about it before!!!)

the other thing to note is that you can turn racket modules into linklets yourself using the various tools that are part of the expander implementation

but that won’t give you a linklet directory or really a good way to produce a racket implementation

see for example this entry in racket/src/expander/README
: % racket bootstrap-run.rkt -s -c <dir> --linklets -l <module-path>
Compiles the given file to a set of linklets in S-expression form,
instead of compiling and running it.

oh… ok, i definitely didn’t know about that. thanks.

one other thing you might be interested in is this code, from the original way Pycket worked: https://github.com/pycket/pycket/blob/master/pycket/pycket-lang/expand.rkt

which basically takes a racket source file and produces a JSON file with the fully-expanded result

that, however, doesn’t go to the linklet layer at all, so you’d still have to implement the module system

but if you just want to write something quick that doesn’t deal with require
or anything else complex, that might be useful

That might be a good alternative to start. Thanks for the references.

Do you know who is behind pycket and what’s used for? Looks quite active.

oh wait… you’re one of the pycket authors…

me and my students

embarassing…

ahahah

:wink:

doh! :slightly_smiling_face:

This project creates a racket implementation in python but doesn’t transpile racket to python.

Thanks, you’re right. I could have sworn there was something related to binding or marshalling uninterned symbols that could cause one to get shot in the foot, but I’m not sure what I was thinking about.

right

fundamentally it’s an interpreter for racket written in python

but using a special dialect/tools that generate a JIT along with that interpreter

the jit generation would come from rpython.

yes

ok, thanks.

The auto.rkt
script uses run.rkt
, if I remember correctly, so use auto.rkt
. When you use auto.rkt
, the -o
flag copies the output to a file. The min-bar-plot
script wants that file.

@samth more linklet questions: would sending linklets to a service which instantiates them make sense? would that be a good way to communicate over http with a remote racket runtime?

@notjack I think a repl with a sandbox makes more sense

There’s no real need for the linklet level

And you’d have to run the expander locally

Which would defeat the purpose

linklets are serializable though - I’m wondering if you could store compiled linklets in a database and use that as a reasonable basis for distributed builds

it’s okay if you run the expander locally for -your- code, as long as you can download precompiled stuff for your dependencies

But I don’t have a feel for this stuff yet. Hard to tell what’s a good idea and what isn’t.

I have a macro m
that sometimes expands to (define x 1)
, and sometimes expands to (void)
, depending on the operand. Consequently:
(println (m foo))
might or might not result in an error (because function application arguments are supposed to be expressions and not define
). I want to make it always an error when people try to use this macro in an expression context. How could I do that?

One possible way is to add a dummy define
, though I don’t think that’s a great solution.

You can check what context you’re in with (syntax-local-context)
.

Right, forgot about that. Thanks :slightly_smiling_face:

There’s also prop:expansion-contexts
, but to be honest I’ve never seen it used.

@notjack Linklets don’t have unique names, though

@samth That’s fine. I was thinking something like a /linklets
collection you POST to and get back a URL, then an /instances
collection you POST a message to that says “I want to instantiate the linklet at this url, and here is a list of other instances to use for the linklet’s imports”

That seems potentially interesting but I don’t see what linklets buy you over module source code.

I’m not sure either. But it seems like a much simpler starting point.

I really think “sandbox as a service” will be a simpler starting point.

Why’s that?

Another question about macro. Suppose I have a recursive helper macro. I want to report a syntax error, so I need to keep around the original syntax object. This involves adding an operand to every case in syntax pattern matching, and also macro invocation, which is really tedious. Is there a way to lift the original syntax up somehow so that I can refer to it in the helper macro without making it an operand?
E.g.
(define-simple-macro (foo . xs)
#:with this-stx this-syntax
(helper xs () () this-stx))
(define-syntax-parser helper
[(_ () accum-var-1 accum-var-2 orig-stx) ...... (raise-syntax-error ...... #'orig-stx) ...... (syntax ......)] ; base case
[(_ (x . xs) accum-var-1 accum-var-2 orig-stx)
...... (syntax ...... (helper xs accum-var-1* accum-var-2* orig-stx) ......)]) ; inductive case

Why did Apple remove all non-Thunderbolt 3 ports? :thinking_face: http://snip.ly/u52g4r

Does the helper macro have to be a macro, or can you change it into a compile-time helper function?
If it’s a compile-time helper function you can bind the original syntax object in the scope outside the function-definition so that it doesn’t have to be passed as an extra argument.
If the helper does have to be a macro, the only other thing I can think of is using a syntax-parameter, just like a parameter like current-output-port
can be used instead of an argument to print
.