Re: [racket-users] Re: Re-entrant parameterize modification isolation when using shift/reset

2021-07-30 Thread Greg Rosenblatt
Thanks, I think that makes sense.

Is the `parameter * thread * parameterization -> box` part implemented as 
something like a global weak-hash, or is it built directly into the stack 
representation?


Continuing the other conversation for a moment with a code reference to 
explain to my future self, or anyone else curious, what I meant by 
"algebraic state effects". Here's a simple implementation with a couple 
examples:

```
#lang racket/base
(require racket/control)

(struct state-parameter (tag)
#:property prop:procedure
(case-lambda
  ((self)   (shift-at (state-parameter-tag self) k (lambda (x) ((k 
x)  x
  ((self v) (shift-at (state-parameter-tag self) k (lambda (_) ((k 
(void)) v))

;; Analogous to make-parameter, but without a default value
(define (make-state-parameter)
  (state-parameter (make-continuation-prompt-tag)))

(define-syntax state-parameterize*
  (syntax-rules ()
((_ () body ...)
 (let () body ...))
((_ ((e.p e))  body ...)
 (let ((p e.p) (x e))
   ((reset-at (state-parameter-tag p)
  (let ((result (begin body ...)))
(lambda (_) result)))
x)))
((_ (b bs ...) body ...)
 (state-parameterize* (b) (state-parameterize* (bs ...) body ...)

(define-syntax state-parameterize-etc
  (syntax-rules ()
((_ final   ()   body ...)
 (state-parameterize* final body ...))
((_ (final ...) ((e.p e) bs ...) body ...)
 (let ((p e.p) (x e))
   (state-parameterize-etc (final ... (p x)) (bs ...) body ...)

;; Analogous to parameterize
(define-syntax-rule (state-parameterize etc ...) (state-parameterize-etc () 
etc ...))


;; The same kind of single state example
(define P (make-state-parameter))
(define (show) (displayln (P)))
(define (inc) (P (+ 1 (P

(define K
  (reset
(state-parameterize ((P 0))
  (show)
  (inc)
  (shift k k)
  (show)
  (inc)
  (P

(displayln "with algebraic state:")
(K) ; 2
(K) ; 2
(K) ; 2


;; An example with multiple states
(define R (make-state-parameter))
(define Q (make-state-parameter))
(define (show2) (displayln `(R: ,(R) Q: ,(Q
(define (inc2) (R (+ 1 (R))) (Q (- (Q) 1)))

(define J
  (reset
(state-parameterize ((R 0) (Q 0))
  (show2)
  (inc2)
  (shift k k)
  (show2)
  (inc2)
  (list (R) (Q)

(displayln "with multiple algebraic states:")
(J) ; 2 -2
(J) ; 2 -2
(J) ; 2 -2
```
On Friday, July 30, 2021 at 11:04:09 AM UTC-4 Matthew Flatt wrote:

> At Sun, 25 Jul 2021 10:35:00 -0700 (PDT), Greg Rosenblatt wrote:
> > I was surprised that subsequent re-entries can observe modifications 
> from 
> > the earlier ones, since my mental model of dynamic parameters was that 
> > their values were retrieved from a fresh dynamic calling context, whose 
> > frames are copied each time the delimited continuation is invoked.
> > [...]
> > I'm also interested in the reasons behind the current design. Is there a 
> > downside to storing parameter bindings directly on the stack, rather 
> than 
> > in a thread cell pointed to by the stack?
>
> I think I see what you mean here, but I also think that idea would run
> into trouble. A (delimited) continuation is invoked every time you
> return a value to a continuation, whether or not that continuation was
> captured by `call/cc`. Internally, in fact, the current continuation
> frequently gets reified and invoked through returns. I think it would
> create a bad interaction among features if a distinction were made
> between explicit (applying a captured continuation) and implicit
> (returning a value) continuation invocations.
>
> > I'd like to be able to resume that continuation in the same context
> > multiple times without observing modifications caused by other
> > resumptions. [...] But it looks like dynamic parameters actually rely
> > on a shared mutable cell, in this case a thread cell.
>
> Yes, parameters are based on a mapping
>
> parameter * thread * paramterizization -> box
>
> When you set or look up a parameter value, the thread part comes from
> `current-thread`, and the parameterization part comes from a
> continuation mark. So, that's why capture and restore within a thread
> sees the same box, but capture and restore of a continuation in a
> different thread gets a different box.
>
> I think you want to introduce a notion of "resume" that replaces the
> thread part of the mapping, plus a replacement notion of
> parameterization. That is, each time you resume, the applied
> continuation should extend one that maps an internal mark to the
> current resume. A replacement for `parameterize` would also install a
> mark (with a different key) to identify a "parameterization", while
> also 

[racket-users] Re: Re-entrant parameterize modification isolation when using shift/reset

2021-07-29 Thread Greg Rosenblatt
Thanks for the response, Jack.

I'm looking at: https://docs.racket-lang.org/reference/contmarks.html

I don't see a way to update the value of an existing key without installing 
a new mark.  Is it possible to do that?  Parameters allow you to update the 
value associated with the innermost use of `parameterize` without 
re-parameterizing.  These updates are what I'd like to isolate between 
resumes.

The idea in the example is that `(shift k k)` "throws" the continuation at 
that point up to the enclosing `reset`.  So `K` ends up bound to a 
procedure of one (unused) argument that continues where the `(shift k k)` 
left off, inside the body of the `parameterize`.  You can use continuations 
like these to implement a form of cooperative thread or coroutine, which 
can even be resumed from the same point multiple times.  However in cases 
where you're also using `parameterize`, unlike spawning a real Racket 
thread, it looks like we don't get the benefit of local parameter updates 
being isolated across multiple resumes, so each one sees any further 
updates made by other resumes, like they are sharing mutable state.  I was 
hoping to see each resume begin in the same dynamically-scoped state, 
oblivious to dynamically-scoped updates made by other resumes.

Aside from the thread-wrapping hack, I'm not sure I see a good way to 
recover isolation behavior from non-isolation-by-default (though the 
reverse doesn't seem to be a problem: if we started with 
isolation-by-default, we could recover non-isolation by installing a 
mutable box as the parameter).  An alternative is to abandon parameters 
completely and replace them with algebraic state effects (also using 
delimited continuations), but it seems like a shame to have to do that when 
parameters are already so close to the right thing.
On Thursday, July 29, 2021 at 10:25:54 PM UTC-4 jackh...@gmail.com wrote:

> I don't fully follow the example you gave because I'm not super familiar 
> with shift/reset, but would using continuation marks directly instead of 
> parameters work for your use case? Continuation marks work like what you 
> described, where data is stored directly on the stack rather than in a 
> thread cell pointed to by the stack.
>
> On Sunday, July 25, 2021 at 10:35:00 AM UTC-7 greg@gmail.com wrote:
>
>> I'm using dynamic binding while also using delimited control operators 
>> such as shift and reset.  When shift captures the context of a 
>> `parameterize`, I'd like to be able to resume that continuation in the same 
>> context multiple times without observing modifications caused by other 
>> resumptions.
>>
>> I was surprised that subsequent re-entries can observe modifications from 
>> the earlier ones, since my mental model of dynamic parameters was that 
>> their values were retrieved from a fresh dynamic calling context, whose 
>> frames are copied each time the delimited continuation is invoked.  But it 
>> looks like dynamic parameters actually rely on a shared mutable cell, in 
>> this case a thread cell.
>>
>> Knowing this, I have a strange workaround using a wrapping thread to 
>> force a distinct thread cell to be created for each resumption, providing 
>> isolation.  Is there a better way to do this?
>>
>> I'm also interested in the reasons behind the current design.  Is there a 
>> downside to storing parameter bindings directly on the stack, rather than 
>> in a thread cell pointed to by the stack?
>>
>>
>> Here is an example, including a demonstration of the workaround:
>>
>> ```
>> #lang racket/base
>> (require racket/control)
>>
>> (define P (make-parameter #f))
>> (define (show) (displayln (P)))
>> (define (inc) (P (+ 1 (P
>>
>> (define (re-enter k)
>>   (define result (void))
>>   (define t (thread
>>   (lambda ()
>> (set! result (k (void))
>>   (thread-wait t)
>>   result)
>>
>>
>> (define K (reset (parameterize ((P 0))
>>(show)
>>(inc)
>>(shift k k)
>>(show)
>>(inc)
>>(P
>>
>> ;; The behavior that surprised me:
>> (displayln "without threads:")
>> (K) ; 2
>> (K) ; 3
>> (K) ; 4
>>
>> ;; The behavior I would like:
>> (displayln "with threads:")
>> (re-enter K) ; 5
>> (re-enter K) ; 5
>> (re-enter K) ; 5
>> ```
>>
>>
>> Program output:
>>
>> 0
>> without threads:
>> 1
>> 2
>> 2
>> 3
>> 3
>> 4
>> with threads:
>> 4
>> 5
>> 4
>> 5
>> 4
>> 5
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/0439bf01-baac-462c-ac61-4a218a9efebcn%40googlegroups.com.


[racket-users] Re-entrant parameterize modification isolation when using shift/reset

2021-07-25 Thread Greg Rosenblatt
I'm using dynamic binding while also using delimited control operators such 
as shift and reset.  When shift captures the context of a `parameterize`, 
I'd like to be able to resume that continuation in the same context 
multiple times without observing modifications caused by other resumptions.

I was surprised that subsequent re-entries can observe modifications from 
the earlier ones, since my mental model of dynamic parameters was that 
their values were retrieved from a fresh dynamic calling context, whose 
frames are copied each time the delimited continuation is invoked.  But it 
looks like dynamic parameters actually rely on a shared mutable cell, in 
this case a thread cell.

Knowing this, I have a strange workaround using a wrapping thread to force 
a distinct thread cell to be created for each resumption, providing 
isolation.  Is there a better way to do this?

I'm also interested in the reasons behind the current design.  Is there a 
downside to storing parameter bindings directly on the stack, rather than 
in a thread cell pointed to by the stack?


Here is an example, including a demonstration of the workaround:

```
#lang racket/base
(require racket/control)

(define P (make-parameter #f))
(define (show) (displayln (P)))
(define (inc) (P (+ 1 (P

(define (re-enter k)
  (define result (void))
  (define t (thread
  (lambda ()
(set! result (k (void))
  (thread-wait t)
  result)


(define K (reset (parameterize ((P 0))
   (show)
   (inc)
   (shift k k)
   (show)
   (inc)
   (P

;; The behavior that surprised me:
(displayln "without threads:")
(K) ; 2
(K) ; 3
(K) ; 4

;; The behavior I would like:
(displayln "with threads:")
(re-enter K) ; 5
(re-enter K) ; 5
(re-enter K) ; 5
```


Program output:

0
without threads:
1
2
2
3
3
4
with threads:
4
5
4
5
4
5

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/ae64e2cf-c3fb-4acd-95c0-1239dd98a9f8n%40googlegroups.com.


Re: [racket-users] Top-level unbound identifiers during expansion

2021-06-28 Thread Greg Rosenblatt
Thanks Sam.

I ended up finding another alternative, which is to replace the 
set!-followed-by-define with define-values:

(define-values (name.r ...) (values (lambda (param ...) body ...) ...))


One more related question (though given the hopelessness, I'd understand if 
there isn't a great answer):

Before writing this multi-definition syntax, I originally wrote a 
single-item version that expanded to a single pair of syntax wrapper and 
value definition:

(define-syntax (issue-syntax-single stx)
  (syntax-case stx ()
((_ (name param ...) body ...)
   #'(begin (define-syntax (name stx)
  (syntax-case stx ()
((_ . args) #'(name.r . args))
(_  #'name.r)))
(define name.r (lambda (param ...) body ...))

In fact, I didn't expect to need a multi-definition version.  The hope was 
that I could define these one-by-one, even when they are 
mutually-recursive.  This does work in a module, but fails at the 
top-level.  I also tried the forward-declaration you suggest, but get the 
same error.

> (define-syntaxes (foo bar) (values))  ; attempted forward-declaration 
(did I do this correctly?)
> (issue-syntax-single (foo x) (bar x 1 2))
> (issue-syntax-single (bar a b c) `(bar: ,a ,b ,c))
> (foo 'the-top-level-is-hopeless)
; bar: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
; [,bt for context]
> ,bt
; bar: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
;   context...:
;body of top-level
;readline-input:8:33: name.r
;/Applications/Racket v8.0/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1493:0
;/Applications/Racket v8.0/collects/racket/repl.rkt:11:26

Is there another workaround that would help the single-item version?

On Monday, June 28, 2021 at 9:51:32 AM UTC-4 Sam Tobin-Hochstadt wrote:

> This is indeed an issue where "the top-level is hopeless" is the problem 
> [1].
>
> However, there's a better work-around. You can write `(define-syntaxes
> (name.r ...) (values))` to forward-declare all those names, and then
> the subsequent definitions will work correctly.
>
> Sam
>
> [1] https://lists.racket-lang.org/users/archive/2005-November/010350.html
> is a good short description of the problem here.
>
> On Fri, Jun 25, 2021 at 5:34 PM Greg Rosenblatt  
> wrote:
> >
> > I've encountered an identifier binding order issue that only manifests 
> in the REPL. My current workaround is to use forward definitions followed 
> by set!s. I've heard rumors that the top-level is hopeless, but I'd like to 
> try and make this work without unnecessary workarounds, if possible.
> >
> >
> > To demonstrate the issue, I've defined a syntax transformer that binds 
> temporary names to procedures, and defines wrapper syntax transformers for 
> referencing these procedures.
> >
> > This syntax works fine within a module, or other non-top-level 
> definition context. But when used at the top-level, I get an unbound 
> identifier error as the first procedure body is being expanded. The first 
> procedure references the second via the wrapper.
> >
> >
> > ;; issue.rkt
> > #lang racket/base
> > (provide issue-syntax)
> > (require (for-syntax racket/base))
> >
> > (define-syntax (issue-syntax stx)
> > (syntax-case stx ()
> > ((_ ((name param ...) body ...) ...)
> > (with-syntax (((name.r ...) (generate-temporaries #'(name ...
> > #'(begin (define-syntax (name stx)
> > (syntax-case stx ()
> > ((_ . args) #'(name.r . args))
> > (_ #'name.r))) ...
> > (define name.r (lambda (param ...) body ...)) ...)
> > ;; eof
> >
> >
> > > racket
> > Welcome to Racket v8.0 [cs].
> > > (require "issue.rkt")
> > > (let ()
> > (issue-syntax
> > ((foo x) (bar x 1 2)) ; note the reference to bar
> > ((bar a b c) `(bar: ,a ,b ,c)))
> > (foo 'is-the-top-level-hopeless?))
> > (bar: is-the-top-level-hopeless? 1 2)
> > > (issue-syntax
> > ((foo x) (bar x 1 2)) ; note the reference to bar
> > ((bar a b c) `(bar: ,a ,b ,c)))
> > ; bar4: unbound identifier;
> > ; also, no #%top syntax transformer is bound
> > ; in: bar4
> > ; [,bt for context]
> > > ,bt
> > ; bar4: unbound identifier;
> > ; also, no #%top syntax transformer is bound
> > ; in: bar4
> > ; context...:
> > ; /Applications/Racket v8.0/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1493:0
> > ; /Applications/Racket v8.0/collects/racket/repl.rkt:11:26
> >
> >
> > I can work around this issue by altering issue-syntax to forward-define 
> names before using set! to initialize them:
> >
>

[racket-users] Top-level unbound identifiers during expansion

2021-06-25 Thread Greg Rosenblatt
I've encountered an identifier binding order issue that only manifests in 
the REPL.  My current workaround is to use forward definitions followed by 
set!s.  I've heard rumors that the top-level is hopeless, but I'd like to 
try and make this work without unnecessary workarounds, if possible.


To demonstrate the issue, I've defined a syntax transformer that binds 
temporary names to procedures, and defines wrapper syntax transformers for 
referencing these procedures.

This syntax works fine within a module, or other non-top-level definition 
context.  But when used at the top-level, I get an unbound identifier error 
as the first procedure body is being expanded.  The first procedure 
references the second via the wrapper.


;; issue.rkt
#lang racket/base
(provide issue-syntax)
(require (for-syntax racket/base))

(define-syntax (issue-syntax stx)
  (syntax-case stx ()
((_ ((name param ...) body ...) ...)
 (with-syntax (((name.r ...) (generate-temporaries #'(name ...
   #'(begin (define-syntax (name stx)
  (syntax-case stx ()
((_ . args) #'(name.r . args))
(_  #'name.r))) ...
(define name.r (lambda (param ...) body ...)) ...)
;; eof


> racket
Welcome to Racket v8.0 [cs].
> (require "issue.rkt")
> (let ()
(issue-syntax
  ((foo x) (bar x 1 2))  ; note the reference to bar
  ((bar a b c) `(bar: ,a ,b ,c)))
(foo 'is-the-top-level-hopeless?))
(bar: is-the-top-level-hopeless? 1 2)
> (issue-syntax
((foo x) (bar x 1 2))  ; note the reference to bar
((bar a b c) `(bar: ,a ,b ,c)))
; bar4: unbound identifier;
;  also, no #%top syntax transformer is bound
;   in: bar4
; [,bt for context]
> ,bt
; bar4: unbound identifier;
;  also, no #%top syntax transformer is bound
;   in: bar4
;   context...:
;/Applications/Racket v8.0/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1493:0
;/Applications/Racket v8.0/collects/racket/repl.rkt:11:26


I can work around this issue by altering issue-syntax to forward-define 
names before using set! to initialize them:

(define-syntax (issue-syntax stx)
  (syntax-case stx ()
((_ ((name param ...) body ...) ...)
 (with-syntax (((name.r ...) (generate-temporaries #'(name ...
   #'(begin (define-syntax (name stx)
  (syntax-case stx ()
((_ . args) #'(name.r . args))
(_  #'name.r))) ...
(define name.r #f) ...  ; forward definitions
(set! name.r (lambda (param ...) body ...)) ...)


Is there a better alternative?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/cd8675e8-95d0-4552-badc-d4ec7a430109n%40googlegroups.com.


Re: [racket-users] Synchronizable conjunction of events?

2021-03-16 Thread Greg Rosenblatt
Thanks for the info, lots of reading to do now.

I ran across transactional events, and also "Isolates: Serializability 
Enforcement for Concurrent ML" 
(https://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=2730=cstech) 
which looks like it may extend transactional events.

On Tuesday, March 16, 2021 at 10:03:48 PM UTC-4 Sam Tobin-Hochstadt wrote:

> Reagents are a generalization of core CML, but Racket extends the basics 
> of CML considerably. I think there's definitely implementation complexity 
> in reagents that would need to be added to support conjunction, but I don't 
> know how much. 
>
> Looking back at Aaron's thesis, I see several other systems with forms of 
> conjunction that are relevant here. First, join patterns, which reagents 
> are based on, also include conjunction. Second, transactional events 
> (Donnelly and Fluent) are in some sense exactly what's requested here, the 
> andThen combinator mentioned here is what I think you originally requested: 
> http://www.cs.cornell.edu/people/fluet/research/tx-events/
>
> Sam
>
> On Tue, Mar 16, 2021, 9:48 PM Greg Rosenblatt  wrote:
>
>> Thanks for the help, everyone.
>>
>> Sam, it looks like you've worked with Aaron a bit on reagents in 
>> https://github.com/aturon/Caper.  Is there anything CML can express that 
>> reagents have trouble with?  How does the implementation complexity compare?
>>
>> On Monday, March 15, 2021 at 8:12:03 PM UTC-4 Sam Tobin-Hochstadt wrote:
>>
>>> I think Aaron Turon's reagents (and more generally k-cas) are an example 
>>> of N-way rendezvous. 
>>>
>>> Sam
>>>
>>> On Mon, Mar 15, 2021, 5:50 PM Matthew Flatt  wrote:
>>>
>>>> At Mon, 15 Mar 2021 13:38:46 -0700 (PDT), Greg Rosenblatt wrote:
>>>> > Is there a corresponding event for a logical conjunction (I was 
>>>> looking for 
>>>> > something like `all-evt` or `every-evt`), which requires that all of 
>>>> its 
>>>> > members be ready for synchronization at the same time? 
>>>>
>>>> No. (Although `replavce-evt` is a weak kind of "and", it's not what
>>>> you're looking for.)
>>>>
>>>> > If not, is there a fundamental barrier to its implementation with the
>>>> > ConcurrentML approach?
>>>>
>>>> Yes, at least in the sense that it's not possible to implement N-way
>>>> rendezvous given only CML's rendezvous.
>>>>
>>>> So, N-way rendezvous would have to be implemented in the core. I'm
>>>> certain that some languages have implemented that, but I have forgotten
>>>> the examples.
>>>>
>>>> > Related to this, I've been reading "Kill-Safe Synchronization 
>>>> Abstractions" 
>>>> > (https://www.cs.utah.edu/plt/publications/pldi04-ff.pdf), and found 
>>>> it 
>>>> > notable that the swap channel couldn't be implemented in a way that 
>>>> was 
>>>> > both kill-safe and break-safe (not ruining `sync/enable-break`'s 
>>>> > exclusive-or guarantee).  I'm wondering if both forms of safety could 
>>>> be 
>>>> > achieved by using a hypothetical `all-evt` that behaves as I've 
>>>> described.
>>>>
>>>> Probably so. The citation of [17] in that part of the paper is meant to
>>>> allude to the CML-style rendezvous versus N-way rendezvous constraint.
>>>>
>>>>
>>>> Matthew
>>>>
>>>> -- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Racket Users" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to racket-users...@googlegroups.com.
>>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/racket-users/20210315155008.cc%40sirmail.smtps.cs.utah.edu
>>>> .
>>>>
>>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Racket Users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to racket-users...@googlegroups.com.
>>
> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/racket-users/646ab600-4655-4f5e-ad53-18eba5966fben%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/racket-users/646ab600-4655-4f5e-ad53-18eba5966fben%40googlegroups.com?utm_medium=email_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/01365d33-66e7-4630-aed7-aedc66ad87f5n%40googlegroups.com.


Re: [racket-users] Synchronizable conjunction of events?

2021-03-16 Thread Greg Rosenblatt
Thanks for the help, everyone.

Sam, it looks like you've worked with Aaron a bit on reagents in 
https://github.com/aturon/Caper.  Is there anything CML can express that 
reagents have trouble with?  How does the implementation complexity compare?

On Monday, March 15, 2021 at 8:12:03 PM UTC-4 Sam Tobin-Hochstadt wrote:

> I think Aaron Turon's reagents (and more generally k-cas) are an example 
> of N-way rendezvous. 
>
> Sam
>
> On Mon, Mar 15, 2021, 5:50 PM Matthew Flatt  wrote:
>
>> At Mon, 15 Mar 2021 13:38:46 -0700 (PDT), Greg Rosenblatt wrote:
>> > Is there a corresponding event for a logical conjunction (I was looking 
>> for 
>> > something like `all-evt` or `every-evt`), which requires that all of 
>> its 
>> > members be ready for synchronization at the same time? 
>>
>> No. (Although `replavce-evt` is a weak kind of "and", it's not what
>> you're looking for.)
>>
>> > If not, is there a fundamental barrier to its implementation with the
>> > ConcurrentML approach?
>>
>> Yes, at least in the sense that it's not possible to implement N-way
>> rendezvous given only CML's rendezvous.
>>
>> So, N-way rendezvous would have to be implemented in the core. I'm
>> certain that some languages have implemented that, but I have forgotten
>> the examples.
>>
>> > Related to this, I've been reading "Kill-Safe Synchronization 
>> Abstractions" 
>> > (https://www.cs.utah.edu/plt/publications/pldi04-ff.pdf), and found it 
>> > notable that the swap channel couldn't be implemented in a way that was 
>> > both kill-safe and break-safe (not ruining `sync/enable-break`'s 
>> > exclusive-or guarantee).  I'm wondering if both forms of safety could 
>> be 
>> > achieved by using a hypothetical `all-evt` that behaves as I've 
>> described.
>>
>> Probably so. The citation of [17] in that part of the paper is meant to
>> allude to the CML-style rendezvous versus N-way rendezvous constraint.
>>
>>
>> Matthew
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Racket Users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to racket-users...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/racket-users/20210315155008.cc%40sirmail.smtps.cs.utah.edu
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/646ab600-4655-4f5e-ad53-18eba5966fben%40googlegroups.com.


[racket-users] Synchronizable conjunction of events?

2021-03-15 Thread Greg Rosenblatt
Some context for my question: `choice-evt` constructs an event that behaves 
analogously to a logical disjunction, choosing any of its members that is 
ready for synchronization.

Is there a corresponding event for a logical conjunction (I was looking for 
something like `all-evt` or `every-evt`), which requires that all of its 
members be ready for synchronization at the same time?  If not, is there a 
fundamental barrier to its implementation with the ConcurrentML approach?

Related to this, I've been reading "Kill-Safe Synchronization Abstractions" 
(https://www.cs.utah.edu/plt/publications/pldi04-ff.pdf), and found it 
notable that the swap channel couldn't be implemented in a way that was 
both kill-safe and break-safe (not ruining `sync/enable-break`'s 
exclusive-or guarantee).  I'm wondering if both forms of safety could be 
achieved by using a hypothetical `all-evt` that behaves as I've described.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/1c879735-ee18-40d5-b4a5-3dd12dfe248an%40googlegroups.com.


Re: [racket-users] Possible bug when reading/writing large inexact numbers

2021-03-07 Thread Greg Rosenblatt
Great, thanks.  Out of curiosity, where in the reader was this bug 
originally?  Can you point me to a diff?

On Sunday, March 7, 2021 at 8:42:33 PM UTC-5 sorawe...@gmail.com wrote:

> This is already fixed. Racket 8.0 doesn't have this issue.
>
> On Mon, Mar 8, 2021 at 8:31 AM Greg Rosenblatt  wrote:
>
>> Large inexact numbers may change values after a second round trip between 
>> read and write.  I was expecting to reach a fixed point after the first 
>> round trip.  Is this a bug?
>>
>> Welcome to Racket v7.8 [cs].
>> > 4.57030e+53
>> 4.5703e+53
>> > 4.5703e+53
>> 4.57029995e+53
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Racket Users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to racket-users...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/racket-users/28f2c566-472f-48eb-881f-028dad5b1285n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/racket-users/28f2c566-472f-48eb-881f-028dad5b1285n%40googlegroups.com?utm_medium=email_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/32726ef8-a4fe-4154-b01f-8fc734f1930an%40googlegroups.com.


[racket-users] Possible bug when reading/writing large inexact numbers

2021-03-07 Thread Greg Rosenblatt
Large inexact numbers may change values after a second round trip between 
read and write.  I was expecting to reach a fixed point after the first 
round trip.  Is this a bug?

Welcome to Racket v7.8 [cs].
> 4.57030e+53
4.5703e+53
> 4.5703e+53
4.57029995e+53

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/28f2c566-472f-48eb-881f-028dad5b1285n%40googlegroups.com.


[racket-users] Creating threads that prevent main thread from exiting

2020-11-16 Thread Greg Rosenblatt
What is the best way to create threads that will prevent a program from 
exiting until they have completed their work?   I'd like to be able to do 
this implicitly, without cooperation from the main thread.

My first experiment uses `shift` to insert uses of `thread-wait` after the 
rest of the program:

```
#lang racket
(require racket/control)

(define (thread/wait proc)
  (define t (thread proc))
  (shift k (k t) (thread-wait t)))

(define t1 (thread/wait (lambda () (let loop () (displayln "t1") (sleep 2) 
(loop)
(define t2 (thread/wait (lambda () (let loop () (displayln "t2") (sleep 3) 
(loop)

(displayln "end of main thread")
```

This doesn't work, seemingly due to an implicit `reset`/`prompt` around 
each top-level definition/expression in a module.

Wrapping the entire module in a trivial `(let () _)` fixes the issue, but 
this is not desirable:

```
#lang racket
(require racket/control)

(let ()
  (define (thread/wait proc)
(define t (thread proc))
(shift k (k t) (thread-wait t)))

  (define t1 (thread/wait (lambda () (let loop () (displayln "t1") (sleep 
2) (loop)
  (define t2 (thread/wait (lambda () (let loop () (displayln "t2") (sleep 
3) (loop)

  (displayln "end of main thread"))
```

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/e67b750a-1d9d-42fa-9712-9c03da5475a8n%40googlegroups.com.


[racket-users] Suspending/resuming threads with custodians/benefactors

2020-11-07 Thread Greg Rosenblatt
I'm experimenting with using custodians to manage threads (on Racket 7.8 
[cs]) and encountering behavior I don't understand.

I start a looping thread `t1` under a new custodian `c1`.

I then shutdown `c1` and expect `t1` to stop looping.  If I started `t1` 
with `thread` then this expectation is met.  However, if I start it with 
`thread/suspend-to-kill`, it continues looping even after `c1` is shut 
down.  Is this the correct behavior?

Additionally, I later start a new thread `t2` under a new custodian `c2`, 
which attempts to resume `t1` after the shutdown, using itself as a 
benefactor.  However, `t1` does not seem to resume.  Is this the correct 
behavior?

Here is the code I'm working with:

```
#lang racket

(define c1 (make-custodian))
(define c2 (make-custodian))
(define t1 #f)
(define t2 #f)

(parameterize ((current-custodian c1))
  ;(set! t1 (thread/suspend-to-kill  ;; (custodian-shutdown-all c1) fails 
to suspend this thread
  (set! t1 (thread
 (lambda ()
   (let loop ()
 (displayln "thread 1")
 (sleep 2)
 (loop))

(displayln "ENTER to continue")
(read-line)

(custodian-shutdown-all c1)

(displayln "ENTER to continue")
(read-line)

(parameterize ((current-custodian c2))
  (set! t2 (thread
 (lambda ()
   (thread-resume t1 (current-thread))
   (let loop ()
 (displayln "thread 2")
 (sleep 2)
 (loop))

(displayln "ENTER to continue")
(read-line)

(custodian-shutdown-all c2)

(displayln "ENTER to continue")
(read-line)
```

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/f844779f-9abd-46bd-987f-b2b3ca3d0925n%40googlegroups.com.


Re: [racket-users] Can no longer interactively enter! module from the shell

2020-08-10 Thread Greg Rosenblatt
Thanks, your output helped narrow down the issue.  It looks like the 
problem is actually with the regular (non-Chez) variant.


When running with Racket v7.8 [cs] I see the same (expected) behavior as 
you:

> racket -ie '(enter! "example.rkt")'
Welcome to Racket v7.8 [cs].
loading example
"example.rkt"> example
5
"example.rkt">


However, the regular variant of Racket v7.8 still has an issue:

> racket -ie '(enter! "example.rkt")'
Welcome to Racket v7.8.
loading example
> example
; example: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
; [,bt for context]
> ,bt
; example: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
;   context...:
;eval-one-top
;/Applications/Racket v7.8/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1493:0
;/Applications/Racket v7.8/collects/racket/repl.rkt:11:26


On Monday, August 10, 2020 at 11:09:09 AM UTC-4, Sam Tobin-Hochstadt wrote:
>
> This works for me the way you describe: 
>
> ``` 
> [samth@huor:/tmp cs-snap] r -ie '(enter! "x.rkt")' 
> Welcome to Racket v7.8.0.7 [cs]. 
> loading example 
> "x.rkt"> example 
> 5 
> "x.rkt"> 
> ``` 
>
> Perhaps there was a problem with 7.3 that you're running into? Can you 
> try with the 7.8 release? 
>
> Sam 
>
> On Sun, Aug 9, 2020 at 8:33 PM Greg Rosenblatt  > wrote: 
> > 
> > Given a module defined in example.rkt: 
> > ``` 
> > #lang racket/base 
> > (provide example) 
> > 
> > (displayln "loading example") 
> > 
> > (define example 5) 
> > ``` 
> > 
> > I used to be able to enter example.rkt with an interactive session from 
> the shell like this: 
> > 
> > > racket -ie '(enter! "example.rkt")' 
> > Welcome to Racket v7.3. 
> > loading example 
> > > example 
> > ; example: undefined; 
> > ;  cannot reference an identifier before its definition 
> > ;   in module: top-level 
> > ; [,bt for context] 
> > > ,bt 
> > ; example: undefined; 
> > ;  cannot reference an identifier before its definition 
> > ;   in module: top-level 
> > ;   context...: 
> > ;eval-one-top12 
> > ;/Applications/Racket 
> v7.3/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1477:0 
> > ;/Applications/Racket v7.3/collects/racket/repl.rkt:11:26 
> > 
> > 
> > The module still seems to be loading, but my interactive session hasn't 
> started in the module context.  Racket 6 used to start my interactive 
> session in the module context. 
> > 
> > Was this change in behavior intended?  Is there a new way to achieve 
> what I'm trying to do? 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> Groups "Racket Users" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an email to racket...@googlegroups.com . 
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-users/bbaf1e21-52e8-4514-9b8c-20db6357fb40o%40googlegroups.com.
>  
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/8439126f-f8b8-4a3c-89f2-5973f9932308o%40googlegroups.com.


[racket-users] Can no longer interactively enter! module from the shell

2020-08-09 Thread Greg Rosenblatt
Given a module defined in example.rkt:
```
#lang racket/base
(provide example)

(displayln "loading example")

(define example 5)
```

I used to be able to enter example.rkt with an interactive session from the 
shell like this:

> racket -ie '(enter! "example.rkt")'
Welcome to Racket v7.3.
loading example
> example
; example: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
; [,bt for context]
> ,bt
; example: undefined;
;  cannot reference an identifier before its definition
;   in module: top-level
;   context...:
;eval-one-top12
;/Applications/Racket v7.3/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1477:0
;/Applications/Racket v7.3/collects/racket/repl.rkt:11:26


The module still seems to be loading, but my interactive session hasn't 
started in the module context.  Racket 6 used to start my interactive 
session in the module context.

Was this change in behavior intended?  Is there a new way to achieve what 
I'm trying to do?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/bbaf1e21-52e8-4514-9b8c-20db6357fb40o%40googlegroups.com.


Re: [racket-users] file->bytes with large files

2020-07-17 Thread Greg Rosenblatt
Thanks.

Depending on how the increment compares to the file size, file->bytes might 
be up to 1.5x faster (on my machine at least) than the workaround.  But the 
workaround is still fast enough.

(define (file->bytes2 file-name)
  (define size (file-size file-name))
  (define bs (make-bytes size))
  (call-with-input-file
file-name
(lambda (in)
  (let loop ((i 0))
(cond ((= i size) bs)
  (else (define end (+ i (min 1073741824 (- size i  ;; 1GB 
increment
(read-bytes! bs in i end)
(loop end)))

On Wednesday, July 15, 2020 at 6:32:36 PM UTC-4, Matthew Flatt wrote:
>
> The `file->bytes` function uses the file size with `read-bytes`, and it 
> appears that the Mac OS `read` system call errors on requests of 2GB or 
> more. The right fix is for the `read` call within Racket (at the rktio 
> layer) to limit the size that it passes, and I'll make that change. 
>
> Meanwhile, you could work around the problem by limiting the size of an 
> individual request: Allocate a byte string and then use a sequence of 
> `read-bytes!` calls to read the file in increments. Each time, use the 
> number of read bytes to increment a starting position into the 
> destination byte string (which is the third argument to `read-bytes!`). 
>
> Matthew 
>
> At Wed, 15 Jul 2020 15:05:22 -0700 (PDT), Greg Rosenblatt wrote: 
> > Hi, I'm getting an error while using file->bytes to load a moderately 
> large 
> > file: 
> > 
> > > (time (void (file->bytes "my-7.6GB-file"))) 
> > ; error reading from stream port 
> > ;   port: # 
> > ;   system error: Invalid argument; errno=22 
> > ;   context...: 
> > ;/Applications/Racket v7.7/collects/racket/file.rkt:768:6: temp218 
> > ;/Applications/Racket 
> > v7.7/collects/racket/private/more-scheme.rkt:336:52 
> > ;eval-one-top 
> > ;/Applications/Racket 
> v7.7/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1478:0 
> > ;/Applications/Racket v7.7/collects/racket/repl.rkt:11:26 
> > 
> > Is there a limit to the size of files that can be used with file->bytes? 
> > 
> > I was preferring file->bytes because it seems much faster than manually 
> > reading from a port.  If file->bytes is not appropriate here, can 
> somebody 
> > recommend another fast approach? 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> Groups 
> > "Racket Users" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an 
> > email to racket...@googlegroups.com . 
> > To view this discussion on the web visit 
> > 
> https://groups.google.com/d/msgid/racket-users/e99edda0-06ed-4164-b7bd-46f8a458
>  
> > c6c8o%40googlegroups.com. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/b6d1ff87-c775-4117-8f88-7816f6434212o%40googlegroups.com.


[racket-users] file->bytes with large files

2020-07-15 Thread Greg Rosenblatt
Hi, I'm getting an error while using file->bytes to load a moderately large 
file:

> (time (void (file->bytes "my-7.6GB-file")))
; error reading from stream port
;   port: #
;   system error: Invalid argument; errno=22
;   context...:
;/Applications/Racket v7.7/collects/racket/file.rkt:768:6: temp218
;/Applications/Racket 
v7.7/collects/racket/private/more-scheme.rkt:336:52
;eval-one-top
;/Applications/Racket v7.7/share/pkgs/xrepl-lib/xrepl/xrepl.rkt:1478:0
;/Applications/Racket v7.7/collects/racket/repl.rkt:11:26

Is there a limit to the size of files that can be used with file->bytes?

I was preferring file->bytes because it seems much faster than manually 
reading from a port.  If file->bytes is not appropriate here, can somebody 
recommend another fast approach?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/e99edda0-06ed-4164-b7bd-46f8a458c6c8o%40googlegroups.com.


Re: [racket-users] Unbound identifier error with syntax transformer that uses syntax-generating helper procedure

2018-05-08 Thread Greg Rosenblatt
Thanks, that explanation helped.  I had gaps in my knowledge.

I also ended up daisy-chaining yet another submodule nested within the 
first, to require it both normally and for-template due to braid-shaped 
phase dependencies.  Nothing seems to have gone wrong.


On Tuesday, May 8, 2018 at 5:54:54 PM UTC-4, Alexis King wrote:
>
> The short answer is that you need a (require (for-template racket/base)) 
> in your utilities submodule: 
>
>   (module utilities racket/base 
> (provide compile-test) 
>
> (require (for-template racket/base)) 
>
> (define (compile-test) 
>   #`(lambda (i) (displayln `(input: ,i) 
>
> But this answer probably isn’t especially helpful towards debugging 
> similar problems in the future, so let me give a longer explanation. 
>
> Racket’s macro system has phases. Phase 0 corresponds to runtime, phase 
> 1 corresponds to phase 0’s compile-time, phase 2 corresponds to phase 
> 1’s compile-time, etc. This space of phases is unbounded. Each phase 
> contains a completely distinct set of bindings, so when you write, say, 
> `let` at phase 0, it isn’t necessarily the same `let` as the one you use 
> at phase 1. 
>
> The code you write in the body of a define-syntax definition is in phase 
> 1, since it is evaluated at compile-time. In your top-level module, you 
> use #lang racket, which happens to provide the bindings from racket/base 
> at both phase 0 and phase 1. This is why you can use `let` from 
> racket/base inside your this-works macro — it was provided at that phase 
> by #lang racket. The code in your template, in this case #`(lambda (i) 
> ), ends up getting evaluated at runtime, so it uses the phase 0 
> bindings. 
>
> You might have already known all that, since your question is about the 
> utilities submodule, but I wanted to include that explanation for 
> context. This module is interesting, since you require it for-syntax in 
> your enclosing module. This has the effect of *shifting* the phases of 
> your utilities submodule, so its phase 0 ends up aligning with phase 1 
> of the enclosing module. Now, the language of this submodule is 
> racket/base, which provides bindings for `provide` and `define`, but 
> what about the code in the template? 
>
> Well, from the utilities module’s perspective, that code is actually 
> going to be evaluated one phase level below phase 0: phase -1! This 
> phase-shifting that happens when you import things for-syntax is why 
> negative phases are meaningful — even though phase -1 doesn’t really 
> make any sense in isolation, after the phase-shifting that the 
> for-syntax import causes, phase -1 becomes phase 0. 
>
> Racket manages all this complicated bookkeeping behind the scenes, so 
> you never need to worry about which *absolute* phase your code will be 
> used at. What you do need to worry about is which *relative* phase 
> pieces of code will end up at. In your utilities submodule, the `lambda` 
> identifier in the template will be evaluated at relative phase level -1, 
> so you need to ensure racket/base’s bindings are in scope at phase level 
> -1. This is what for-template does: it is like for-syntax, but it shifts 
> imports a phase level down instead of a phase level up. 
>
> (Note that (for-template (for-syntax )) is a no-op, since the shifts 
> cancel each other out. It may be educational to think about the 
> implications of this for your program.) 
>
> Alexis 
>
>
> > On May 8, 2018, at 16:00, Greg Rosenblatt <greg@gmail.com 
> > wrote: 
> > 
> > Hi, I'm having trouble writing a syntax transformer that uses a 
> syntax-generating procedure defined elsewhere. 
> > 
> > When the procedure is defined locally, everything is fine. 
> > 
> > When the procedure is defined outside the transformer, I have to do a 
> dance to make the procedure visible at the right phase, which seems to 
> work.  However, upon use I get: 
> > 
> > > racket unbound-identifier.rkt 
> > unbound-identifier.rkt:9:7: lambda: unbound identifier; 
> >  also, no #%app syntax transformer is bound 
> >   context...: 
> >#(1973 module unbound-identifier 0) #(2181 module) #(2811 macro) 
> #(2822 local) 
> >#(2823 intdef) #(2824 module (unbound-identifier utilities) -1) 
> >   other binding...: 
> >#<module-path-index:(racket)> 
> >#(1972 module) #(1973 module unbound-identifier 0) 
> >   at: lambda 
> >   in: (lambda (i) (displayln (quasiquote (input: (unquote input) 
> >   context...: 
> >standard-module-name-resolver 
> >   
> > 
> > I wrote this self-contained example using a submodule, but the error 
> also occurs when requirin

[racket-users] Unbound identifier error with syntax transformer that uses syntax-generating helper procedure

2018-05-08 Thread Greg Rosenblatt
Hi, I'm having trouble writing a syntax transformer that uses a 
syntax-generating procedure defined elsewhere.

When the procedure is defined locally, everything is fine.

When the procedure is defined outside the transformer, I have to do a dance 
to make the procedure visible at the right phase, which seems to work.  
However, upon use I get:

> racket unbound-identifier.rkt
unbound-identifier.rkt:9:7: lambda: unbound identifier;
 also, no #%app syntax transformer is bound
  context...:
   #(1973 module unbound-identifier 0) #(2181 module) #(2811 macro) #(2822 
local)
   #(2823 intdef) #(2824 module (unbound-identifier utilities) -1)
  other binding...:
   #
   #(1972 module) #(1973 module unbound-identifier 0)
  at: lambda
  in: (lambda (i) (displayln (quasiquote (input: (unquote input)
  context...:
   standard-module-name-resolver
 

I wrote this self-contained example using a submodule, but the error also 
occurs when requiring the module from another file.  What am I doing 
wrong?  I imagine it's something silly.


#lang racket
(provide this-works this-does-not-work)

(module utilities racket/base
  (provide compile-test)

  (define (compile-test)
#`(lambda (i) (displayln `(input: ,input)

(require (for-syntax 'utilities))


(define-syntax (this-works stx)
  (syntax-case stx ()
((_ input)
 (let ()
   (define (compile-test)
 #`(lambda (i) (displayln `(input: ,input

   #`(#,(compile-test) input)

(define-syntax (this-does-not-work stx)
  (syntax-case stx ()
((_ input to-do ...)
 (let ()

   #`(#,(compile-test) input)

(this-works 3)
(this-does-not-work 3)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Unexpected pattern matching behavior

2018-04-25 Thread Greg Rosenblatt
I'm confused by the behavior of pattern matching in some cases.  I'll 
discuss a few sets of examples involving segment patterns, then a mix of 
`and`, `or`, and `not` patterns.


Here is a basic segment pattern matching the entire contents of a list:
> (match '(1 2 3)
 ((list x ...) `(result: ,x)))
'(result: (1 2 3))

Let's add a prefix to the scrutinized list, and match it with a separate 
pattern variable:
> (match '((1 2 3) 1 2 3)
 ((list w x ...) `(result: ,w ,x)))
'(result: (1 2 3) (1 2 3))

Now let's constrain the prefix to be the same as the matched segment:
> (match '((1 2 3) 1 2 3)
 ((list x x ...) `(result: ,x)))
'(result: (1 2 3))

Everything seems fine so far.  Let's make the segment pattern more 
interesting.

This time, we'll have our segment pattern match elements that are lists of 
two elements:
> (match '((a 1) (b 2) (c 3))
 ((list (list k v) ...) `(result: ,k ,v)))
'(result: (a b c) (1 2 3))

We can add a prefix as before, corresponding to the first element of each 
two-element list in the remaining segment, and match it with a separate 
pattern variable:
> (match '((a b c) (a 1) (b 2) (c 3))
 ((list j (list k v) ...) `(result: ,j ,k ,v)))
'(result: (a b c) (a b c) (1 2 3))

So far so good.  Now let's try constraining the prefix to be the same as 
the first element of each two-element list in the segment pattern:
> (match '((a b c) (a 1) (b 2) (c 3))
 ((list k (list k v) ...) `(result: ,k ,v)))
; k113: unbound identifier;
;  also, no #%top syntax transformer is bound
;   in: k113
; [,bt for context]

Something went wrong.  Is this behavior expected?  This error doesn't look 
like the kind you'd expect a user to see.


Let's try another example with segment patterns:
> (match '(1 2 3 : 1 2 3)
 ((list x ... ': y ...) `(result: ,x ,y)))
'(result: (1 2 3) (1 2 3))

We're using : as a divider, allowing both the x and y segments to be 
non-empty.  In this case, they are bound to the same values.

What happens if we try to constrain the two segments to be identical by 
repeating the variable?:
> (match '(1 2 3 : 1 2 3)
 ((list x ... ': x ...) `(result: ,x)))
non-linear pattern used in `match` with ... at # and 
#
'(result: (1 2 3))

It looks like we got the right result (see the next example), but it looks 
like an error message was printed beforehand.  Is this message intended as 
a warning?  Should it actually be raising an error instead?  It almost 
looks like debug logging.

Why might an error be the expected behavior?  It seems we get the right 
result only coincidentally.  If we remove the divider and use separate 
variables, we can see the greedy behavior of segment patterns:
> (match '(1 2 3 1 2 3)
 ((list x ... y ...) `(result: ,x ,y)))
'(result: (1 2 3 1 2 3) ())

When we try to constrain the segment by repeating the same variable, we get 
the printed warning followed by an unexpected result:
> (match '(1 2 3 1 2 3)
 ((list x ... x ...) `(result: ,x)))
non-linear pattern used in `match` with ... at # and 
#
'(result: (1 2 3 1 2 3))

Is this greedy behavior expected even when the segment pattern variable is 
constrained in this way?  It seems like we should at least get an error.


Moving on, here's an example using `and` and `not` that behaves reasonably:
> (match (list 1 2 3)
   ((and (list a _ _) (not (list _ a _))) `(result: ,a)))
'(result: 1)

We can see how the scrutinized list is being constrained to not repeat the 
same first two elements:
> (match (list 1 1 3)
 ((and (list a _ _) (not (list _ a _))) `(result: ,a)))
; match: no matching clause for '(1 1 3) [,bt for context]

If we swap the order of the sub-patterns, expecting the same behavior as 
the first example, we get a surprise:
> (match (list 1 2 3)
 ((and (not (list _ a _)) (list a _ _)) `(result: ,a)))
; match: no matching clause for '(1 2 3) [,bt for context]

It seems that the order of sub-patterns in an `and` pattern matters, and 
determines logical scoping of pattern variables.  In the first pattern, we 
are getting the behavior of the logical proposition:
(exists (a)
  (and (== VALUE (list a _ _)) (not (== VALUE (list _ a _)

While in the second example, we seem to be getting the behavior of the 
logical proposition:
(exists (a)
  (and (== VALUE (list a _ _)) (not (exists (a) (== VALUE (list _ a _))
Or, pushing the `not` inward slightly:
(exists (a)
  (and (== VALUE (list a _ _)) (forall (a) (not (== VALUE (list _ a _))

Is this non-commutative behavior of `and` intended?


Here's an example involving `and` and `or` that attempts to ensure that a 
three-element list either has identical first and second elements, or 
identical second and third elements:
> (match (list 1 2 2)
   ((and (list a b c) (or (list _ a _) (list _ _ b))) 'success))
; readline-input:2:47: match: variable not bound in all or patterns
;   at: b
;   in: (or (list _ a _) (list _ _ b))
; [,bt for context]

Given the binding behavior we saw with `and` in the previous example, I 
figured 

[racket-users] Unexpected quasiquote and quasisyntax behavior

2018-04-24 Thread Greg Rosenblatt
I'm confused about the behavior of quasiquote and quasisyntax in some cases 
(using Racket v6.10.1).  I'll list some examples alongside my questions.


This vector quasiquote behavior makes sense to me:
> `#(3 ,@'(4))
'#(3 4)

The analogous quasisyntax gives an error, which seems strange.  What's 
going on here?: 
> #`#(3 #,@'(4))
; list->vector: contract violation
;   expected: list?
;   given: #f
; [,bt for context]

Note that quasisyntax-ing a list instead of a vector works:
> #`(3 #,@'(4))
#

Also note that adding a trailing element to the vector quasisyntax avoids 
the error:
> #`#(3 #,@'(4) 5)
#


Next, is this the expected behavior of unquote-splicing a non-list at the 
end of a list quasiquote?  I noticed Chez Scheme gives the same result:
> `(3 ,@4)
'(3 . 4)

When unquote-splicing a non-list elsewhere, we get an error, which makes 
sense:
> `(3 ,@4 5)
; unquote-splicing: contract violation
;   expected: list?
;   given: 4
; [,bt for context]

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Scopes and shadowing syntax-rules literals

2018-01-04 Thread Greg Rosenblatt
Hi,

I've been experimenting with various corner cases of the macro system to 
better understand the implementation.  For comparison, I've also been 
running the experiments in Chez Scheme.

I found a difference of opinions when running the following two tests.  The 
idea is to test under what conditions syntax-rules literals are shadowed.

```
#lang racket

;; test-it bound by let
(define (run-test)
  (let ((it 22))
(let ((test-it
(let ((it 5))
  (let ((test-it
  (syntax-rules (it)
((test_it it) 'found-it!)
((test_it other) '(other: other)
(display `(0 it ,(syntax->datum (test-it #'(test-it it)
(newline)
(display `(0 not-it ,(syntax->datum (test-it #'(test-it 
not-it)
(newline)
(let ((it 11))
  (display `(1 it ,(syntax->datum (test-it #'(test-it 
it)
  (newline)
  (display `(1 not-it ,(syntax->datum (test-it #'(test-it 
not-it)
  (newline)
  test-it)
  (display `(2 it ,(syntax->datum (test-it #'(test-it it)
  (newline)
  (display `(2 not-it ,(syntax->datum (test-it #'(test-it not-it)
  (newline)
  (let ((it 44))
(display `(3 it ,(syntax->datum (test-it #'(test-it it)
(newline)
(display `(3 not-it ,(syntax->datum (test-it #'(test-it not-it)
(newline)

;; test-it bound by let-syntax
(define (run-test2)
  (let ((it 5))
(let-syntax ((test-it
   (syntax-rules (it)
 ((test_it it) 'found-it!)
 ((test_it other) '(other: other)
  (display `(0 it ,(test-it it)))
  (newline)
  (display `(0 not-it ,(test-it not-it)))
  (newline)
  (let ((it 11))
(display `(1 it ,(test-it it)))
(newline)
(display `(1 not-it ,(test-it not-it)))
(newline)

(run-test)
(newline)
(run-test2)
```


Racket output:
(0 it (quote found-it!))
(0 not-it (quote (other: not-it)))
(1 it (quote found-it!))
(1 not-it (quote (other: not-it)))
(2 it (quote found-it!))
(2 not-it (quote (other: not-it)))
(3 it (quote found-it!))
(3 not-it (quote (other: not-it)))

(0 it found-it!)
(0 not-it (other: not-it))
(1 it (other: it))
(1 not-it (other: not-it))


Chez Scheme output:
(0 it 'found-it!)
(0 not-it '(other: not-it))
(1 it '(other: it))
(1 not-it '(other: not-it))
(2 it '(other: it))
(2 not-it '(other: not-it))
(3 it '(other: it))
(3 not-it '(other: not-it))

(0 it found-it!)
(0 not-it (other: not-it))
(1 it (other: it))
(1 not-it (other: not-it))


It's interesting that the behavior under Racket depends on whether test-it 
is let bound or let-syntax bound.  The first block of output in either case 
corresponds to let binding, while the second corresponds to let-syntax 
binding.

I've been reading https://docs.racket-lang.org/reference/syntax-model.html 
and expected the Chez Scheme behavior in both cases.  Racket behaved as I 
expected when test-it is bound by let-syntax.  But I'm pretty confused 
about the normal let binding behavior under Racket.

Can somebody explain what is happening?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.