pocmatos
2018-4-26 08:40:48

While building racket I saw these lines go past:


pocmatos
2018-4-26 08:41:00
Downloading repository <git://github.com/RenaissanceBug/racket-cookies?path=net-cookies>
Downloading repository <github://github.com/stamourv/optimization-coach/master>
Downloading repository <git://github.com/racket/option-contract?path=option-contract>

pocmatos
2018-4-26 08:41:41

Although nothing seemed to fail, I find the use of github:// strange. Was this a typo or is it actually allowed these days?


greg
2018-4-26 12:43:41

@pocmatos Not newly-allowed. More like earlier-allowed — it’s deprecated. See next to last bullet under Package Sources here: https://docs.racket-lang.org/pkg/Package_Concepts.html#%28part._concept~3asource%29


pocmatos
2018-4-26 12:47:10

Thanks @greg


pocmatos
2018-4-26 12:50:54

I am seeing a strange behaviour with sync and handle-evt for place synchronization with an alarm to deal with a timeout. The problem is that the timeout is never triggered. I am doing a simplified (sync (handle-evt (alarm-evt (+ (current-inexact-milliseconds) (* timeout 1000))) (lambda (_) (printf "timeout~n"))) (handle-evt ...)) I assume, there’s nothing obviously wrong with doing this right?


pocmatos
2018-4-26 12:52:25

Annoyingly this simple example works out of the box in drracket. sigh


greg
2018-4-26 13:03:05

@pocmatos Hmm. - Does it work because it’s running under DrRacket — or because it’s a simpler example? - What happens if (handle-evt ...) is never-evt?


greg
2018-4-26 13:04:57

(I haven’t used places, for real. So I am just trying to be your “rubber duck”.)


pocmatos
2018-4-26 13:05:05

@greg well, it’s because it’s a simple example. With never-evt also works. Trying to reproduce this with a larger but manageable example. My suspicion is that it has to do with how place channels interact with handle-evt.


pocmatos
2018-4-26 13:05:09

Thanks! :slightly_smiling_face:


pocmatos
2018-4-26 13:06:07

Also, the places I create are all computationally heavy… but I am not sure that can influence the behaviour of the original place.


greg
2018-4-26 13:10:57

@pocmatos Does it work if you try something like sync/timeout and test for #f? (To maybe rule out the handle-evt aspect.)


pocmatos
2018-4-26 13:11:20

humm, good idea. will give it a try.


greg
2018-4-26 13:11:21

Well at least rule out the (handle-evt (alarm-evt ...)) composition.


pocmatos
2018-4-26 13:13:08

sync/timeout is not what I expected because the timeout sets a timeout on the synchronization. In my application synchronization happens very rapidly due to messages being sent back and forth so timeout is never triggered. Maybe I can change the structure to test it anyway.


pocmatos
2018-4-26 13:23:03

ok… just crashed drracket :disappointed:


shu--hung
2018-4-26 19:26:16

how can I go to the inside of a submodule in DrRacket or Racket REPL?


shu--hung
2018-4-26 19:28:56

oh, I shouldn’t have quoted the module path


pocmatos
2018-4-26 19:39:19

@greg finally found out the problem. :slightly_smiling_face: Not racket! Issue with how I was dealing with message passing between places. alarm was being triggered but my print was buffered and not displayed so I thought the event was just not being handled. I assumed a printf ending in ~n would flush the buffer but that was not the case. I needed (flush-output). Did manage to crash DrRacket in the process though.


greg
2018-4-26 19:43:48

@pocmatos Ah! BTW you could do this globally with (file-stream-buffer-mode (current-output-port) 'none)


greg
2018-4-26 19:44:08

Or 'line maybe in your case.


cosmez
2018-4-26 19:44:12

is there any library that implements rackjure function literals? only that part. i only use the threading macro and that


pocmatos
2018-4-26 19:44:19

@greg Awesome, thanks for pointing that out!


cosmez
2018-4-26 19:44:22

and theres the threading package now


lexi.lambda
2018-4-26 19:44:45

there are like 3


greg
2018-4-26 19:44:45

@cosmez Yes, @alexknauth has a pkg for just that, IIRC.



lexi.lambda
2018-4-26 19:45:51

greg
2018-4-26 19:46:04

Oh, cool.


greg
2018-4-26 19:46:34

@lexi.lambda and @alexknauth create so many good packages I can’t keep up :smile:


lexi.lambda
2018-4-26 19:46:48

I think I beat Alex to the punch on this one, but I’m not sure :)


cosmez
2018-4-26 19:47:01

thanks a bunch :slightly_smiling_face:


greg
2018-4-26 19:47:19

He’d been helping fix a bug or two in rackjure fn lits, around the same time, I think


greg
2018-4-26 19:48:12

In hindsight rackjure could/should be mostly just a meta pkg that re-provides things like afl and threading, now that those exist.


greg
2018-4-26 19:48:34

I already did that with threading, but maybe could take it further now.


greg
2018-4-26 19:48:47

Or not. I don’t think many people use rackjure for realz.


cosmez
2018-4-26 19:49:54

if youre coming from clojure, is nice to have it.


lexi.lambda
2018-4-26 19:50:17

I use curly-fn liberally.


greg
2018-4-26 21:47:13

Hmm, it’s occurring to me, now, that I rarely seem to use anonymous functions, lately. I wonder why. It’s mostly not intentional. I mean, I do prefer for/list et al to map. And I do sometimes just define a function with a name because I like how that reads, when using it. So it’s a little on purpose. But mostly that’s not it. I wonder why, is there something else about the code I’m writing lately. Hmmm.


cosmez
2018-4-26 22:01:33

theyre good when youre prototyping. and youre not used to the for idiom


cosmez
2018-4-26 22:01:52

right now i have to see the documentation everytime i have to use one of the for alternatives


lexi.lambda
2018-4-26 22:46:08

@mflatt I feel less confident about asking this question than I normally do, since I really don’t known if this behavior is a bug or my own misunderstanding, but I’m trying to figure out why this program behaves the way it does. It seems to only cause a problem when split out over three separate files, but they’re short: ;; ns.rkt #lang racket (require (for-syntax racket syntax/parse/define) syntax/parse/define) (provide (for-syntax type-namespace-introduce) begin-for-type) (begin-for-syntax (define-simple-macro (define-type-introducer type-introducer:id) #:with scopeless-id (datum-&gt;syntax #f 'introducer-id) #:with type-id ((make-syntax-introducer #t) #'scopeless-id) (define type-introducer (make-syntax-delta-introducer #'type-id #'scopeless-id))) (define-type-introducer type-introducer) (define (type-namespace-introduce stx) (type-introducer stx 'add))) (define-syntax-parser begin-for-type [(_ form ...) #:with [form* ...] (map type-namespace-introduce (attribute form)) (syntax/loc this-syntax (begin form* ...))]) ;; p.rkt #lang racket (require syntax/parse/define "ns.rkt") (provide foo) (begin-for-type (define-syntax Foo 'type)) (define-simple-macro (get-typed-value x:id) #:with val (syntax-local-value (type-namespace-introduce #'x)) (quote val)) (define-simple-macro (foo) (get-typed-value Foo)) ;; u.rkt #lang racket (require "p.rkt") (foo)

Running racket u.rkt without compiling any of the modules successfully compiles and prints 'type, but attempting to compile the modules with raco make u.rkt produces an unbound identifier error. I don’t understand why. Is this a bug?


lexi.lambda
2018-4-26 22:47:45

Compiling just ns.rkt and then running racket u.rkt also doesn’t trigger the issue, but compiling p.rkt and then running racket u.rkt does.


notjack
2018-4-27 00:24:57

I use fancy-app so much it feels painful to write code without it. But I don’t use anything else for anonymous functions (like currying) because by that point I find a named definition much clearer.


mflatt
2018-4-27 02:57:06

That’s pretty subtle. The short answer is that you’re exposing the gensym-like nature of scopes. The “ns.rkt” module is carefully set up to embed the relevant scope in a syntax object, so every instantiation of “ns.rkt” will get the same scope. But “p.rkt” also attaches the scope to a syntax object (although indirectly, in the identifer-to-definition mapping). When those two modules are separately unmarshaled, you get two different scopes It’s the same as if you embed the result of one gensym call into two different compiled expressions and then read the expressions individually, so that the gensymed symbol is created twice. I’m not immediately sure of how to do what you want to do. It seems like the kind of thing that submodules are for, but I can imagine why a submodule might not work in this case.


mflatt
2018-4-27 03:04:15

Possibly, the solution is to arrange for a separate type-introducer in every module that uses define-type-introducer


lexi.lambda
2018-4-27 03:05:34

That makes sense, though it’s rather unfortunate. I’m not sure what the right thing to do is, either. I’ve been thinking about potential workarounds, but I haven’t been able to come up with any. At first, I thought it wouldn’t be important for the namespace scopes to span multiple modules, but I’ve realized lately that it (unfortunately) actually is.


mflatt
2018-4-27 03:05:36

@michael.ballantyne This reminds me of what you were doing with scope-based, textually interleaved namespaces. Is it the same?


lexi.lambda
2018-4-27 03:07:24

The reason it’s necessary for the scope to be consistent across modules stems from the problem I actually ran into before reducing the issue to this minimal test case. Namely, I had a macro written in one module that expands to a form like (instance (forall [x] (Show x) =&gt; (Show (Maybe x))) ....), and the instance knows that things like forall and Show should be bound in the type namespace. But until the macro is expanded, that information isn’t known.


lexi.lambda
2018-4-27 03:09:16

In the existing Hackett implementation, I use a syntax/parse pattern transformer named ~type that is used to annotate pieces of syntax that should be interpreted in the right namespace, which is really the API I want. It makes sense from the mental model of a macro-writer. It just doesn’t work, due to the way the scopes can end up inconsistent, as demonstrated in this example.


lexi.lambda
2018-4-27 03:12:16

I thought the make-syntax-delta-introducer trick would be enough to fix the scopes across instantiations, and I guess it is, as you say. But also as you say, the way scopes are unmarshalled means the “same” scope is not necessary actually the same after being stuffed in bytecode, if that scope ends up being embedded in multiple modules. :(


mflatt
2018-4-27 03:14:26

I’m not clear on why type-namespace-introduce can’t be a macro that triggers a module-local type-namespace-introduce definition (once per module) and replaces itself with a call to the module-local one.


lexi.lambda
2018-4-27 03:17:13

The problem is that the use of type-namespace-introduce might be in a different module from the syntax it gets called upon, in which case that won’t work. I compressed the code in my reproduction into just three modules, but my actual problem involved six! Specifically, imagine if the foo macro and the Foo type were defined in a different module from the get-typed-value macro.


lexi.lambda
2018-4-27 03:18:45

In more practical terms, imagine the instance macro for defining typeclass instances is defined in one module, and it calls type-namespace-introduce on a piece of input syntax. But a macro that expands into an instance form is defined in a separate module, and it references bindings in scope in that separate module (which, if I understand your suggestion properly, would use a distinct type namespace scope, and therefore the scope introduced by the instance macro wouldn’t be the right one).


mflatt
2018-4-27 03:20:40

I imagine that anything that calls type-namespace-introduce would also need to be module-local, so use the same localizing strategy for get-typed-value – or, probably more simply, pass the right type-namespace-introduce to it. That way, it would never the case that type-namespace-introduce or (effectively) get-typed-value is from a different module.


mflatt
2018-4-27 03:22:02

I’m not sure I’m mapping things right to instance, but it feels like this is one of those problems that is solved by one more level of indirection


lexi.lambda
2018-4-27 03:22:08

Unless I’m misunderstanding you, I don’t think it’s possible to implement a namespace abstraction if users are required to either only reference locally-defined macros or to thread type-namespace-introduce around manually when they write macros.


lexi.lambda
2018-4-27 03:22:57

That is to say that this is not code that is exclusively internal to Hackett; it also exists as part of the API to users of Hackett writing their own macros that expand into Hackett forms.


lexi.lambda
2018-4-27 03:27:50

If it helps at all, I can point to the actual code on GitHub in a branch of Hackett that ran into this problem. I just figured that probably wouldn’t be very helpful to someone unfamiliar with the codebase (that is, everyone except me).


mflatt
2018-4-27 03:30:30

Ok – I’ll look tomorrow.


lexi.lambda
2018-4-27 03:31:10

Yes, no rush. It’s late. :) It’s also not exactly urgent.


lexi.lambda
2018-4-27 03:33:03

On the other hand, while it definitely isn’t urgent, it’s also something I do need to fix to make Hackett work (or abandon separate type/value namespaces entirely), and I don’t currently have a workaround or even a path to a solution in the expander (unlike some other things I’ve bumped into that I can deal with myself).