Re: [racket-users] ask the type of a value (partial solution)

2020-08-03 Thread Alexis King
> On Aug 3, 2020, at 11:48, Hendrik Boom  wrote:
> 
> Still, it would be nice to find out how to get this information more 
> directly instead of relying on functions that do much more than 
> what I was asking for.

In general, there aren’t any. The ability of struct->vector to extract a 
symbolic name for any value really is specific to struct->vector (and it’s only 
really useful for debugging, for the reason Ryan points out).

If you only care about bona fide structs, not primitive values like strings and 
ports, you can do a little better using struct-info:

(define (type-name v)
  (match/values (struct-info v)
[(#f _) #f]
[((app struct-type-info name _ _ _ _ _ _ _) _) name]))

(struct point (x y) #:transparent)
(type-name (point 1 2)) ; => 'point

But this doesn’t work for non-transparent structs unless you own a sufficiently 
powerful inspector:

(let ()
  (struct point (x y))
  (type-name (point 1 2))) ; => #f

(let ()
  (struct point (x y)
#:inspector (make-inspector))
  (type-name (point 1 2))) ; => 'point

But again, this just gets you a symbolic name, which is subject to the same 
issue Ryan points out. The value you get back from struct-info is truly unique 
to that particular type, so it’s a more useful value than the symbolic name. 
But again, it’s not clear to me why you’d want to do this (except for 
debugging/instrumentation), since you still can’t possibly do anything useful 
with a value of a truly unknown type.

On the other hand, if it *is* for debugging, then meddling with the inspector 
is a valid thing to do (and is in fact one of the main reasons inspectors 
exist). You can change current-inspector to a weaker inspector during the 
instantiation of the modules you want to debug, and then you can use 
struct-info to get information about any values of the struct types they create.

Alexis

-- 
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/5CAB018A-6F47-4FBA-A249-6A7472D8A896%40gmail.com.


Re: [racket-users] ask the type of a value

2020-08-03 Thread Alexis King
In general, the answer is “no,” mostly because it’s not clear in Racket what 
“the type of a value” means. It’s difficult to come up with a definition that 
would be useful enough to satisfy your criterion of not “having to guess it 
first.” Consider: suppose you had a hypothetical `type-of` operation that 
returned a value’s type:

(type-of 'hello) ; => 'symbol
(type-of "hello") ; => 'string

Now suppose you apply type-of to a value you know nothing about and get back 
'widget. Well, you don’t know what a widget is, so that didn’t actually get you 
any further from where you started: you still don’t know what to do with the 
value.

Furthermore, types are not actually disjoint. You can write a struct definition 
with properties like prop:procedure and prop:evt, and if a struct has both, 
should type-of return the struct’s name, 'procedure, or 'evt? It’s not really 
clear. You might be able to come up with some more sophisticated system with 
(potentially multiple) inheritance that could capture these relationships, but 
I can say with confidence that no such system currently exists in Racket.

Alexis

> On Aug 3, 2020, at 09:19, Hendrik Boom  wrote:
> 
> In plain, untyped Racket:
> 
> It is possible to ask if a value is a symbol with symbol?
> It is possible to ask if a value is a string with string?
> etc.
> 
> Is there a way to ask the type of a value without having to guess it first?
> 
> -- hendrik

-- 
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/C561F2A9-0C78-4EDA-A401-4FB067D79849%40gmail.com.


Re: [racket-users] Why does this counter behave differently in different runtimes?

2020-06-17 Thread Alexis King
This is quite curious. It appears to be a compiler bug. Here’s a very slightly 
smaller test case:

#lang racket/base
(define count!
  (let ([i 0])
(λ () (begin0
(set! i (add1 i))
(+ i)
(count!)

The fully-expanded program looks fine, so it isn’t the expander’s fault:

(module counter racket/base
  (#%module-begin
   (module configure-runtime '#%kernel
 (#%module-begin (#%require racket/runtime-config) (#%app configure 
'#f)))
   (define-values
(count!)
(let-values (((i) '0))
  (lambda () (begin0 (set! i (#%app add1 i)) (#%app + i)
   (#%app call-with-values (lambda () (#%app count!)) print-values)))

But `raco decompile` reveals that begin0 has been mysteriously replaced with 
begin in the compiled program:

(module counter 
  (require (lib "racket/base.rkt"))
  (provide)
  (define-values
   (count!)
   (let ((local54 '0))
 (begin
   (set! local54 (#%box local54))
   (lambda ()
 '#(count! # 4 4 53 63 #f)
 '(flags: preserves-marks single-result)
 '(captures: (val/ref local54))
 (begin
   (#%set-boxes! (local54) (add1 (#%unbox local54)))
   (+ (#%unbox local54)))
  (#%apply-values print-values (count!))
  (void)
  (module (counter configure-runtime) 
(require '#%kernel (lib "racket/runtime-config.rkt"))
(provide)
(print-as-expression '#t)
(void)))

It seems perhaps an optimization has gone awry. The bug appears to be quite 
old: I can reproduce it as far back as 6.1.1. (I didn’t test any versions 
earlier than that.) Unsurprisingly, the issue does not occur on Racket CS, 
which is consistent with the hypothesis that this is a compiler bug.

Alexis

> On Jun 17, 2020, at 02:04, Sage Gerard  wrote:
> 
> I attached a video demonstrating what I'm seeing. In case it does not load or 
> is not available, I'll summarize here. Forgive any typos; it's been a late 
> night of coding.
> 
> Here's a module with an incorrect counter. It's incorrect because it uses 
> begin0, and is therefore expected to return void instead of an incrementing 
> integer.
> 
> #lang racket
> (provide count!)
> (define count!
>   (let ([i 0])
> (λ () (begin0
> (set! i (add1 i))
> (~v i)
> 
> Notice that I added the ~v to format the return value. If I launch Racket 
> v7.7.0.5 using racket -it prog.rkt, (count!) returns the formatted value. But 
> if I remove the ~v, it behaves as written (returning void).
> 
> The video shows the behavior with and without ~v, both in DrRacket and 
> racket. DrRacket is the only environment that consistently runs the code 
> correctly.
> 
> ~slg

-- 
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/781BE0E5-E6E5-4F0B-8B46-5227FDFB8835%40gmail.com.


Re: [racket-users] identifier used out of context

2020-06-07 Thread Alexis King
> On Jun 7, 2020, at 17:44, Sorawee Porncharoenwase  
> wrote:
> 
> Wow, so block is currently buggy?!
> 

This issue isn’t with `block`, per se (though `block` could cooperate more 
nicely with definition context expansion to avoid this problem). You can 
reproduce it without any first-class definition contexts at all:

#lang racket
(define-syntax-rule (m) (displayln 'old))
(let ()
  (m)
  (define-syntax-rule (m) 'new)
  (void))

Arguably, the real issue is the mechanism behind Check Syntax. Check Syntax 
collects information about uses and bindings from the fully-expanded program, 
but that is not straightforward for macro uses and local macro bindings, since 
those go away after expansion. So the expander annotates the program with 
information about disappeared identifier uses and disappeared local bindings 
using the 'origin, 'disappeared-use, and 'disappeared-binding syntax properties.

The hope is that the binding structure of the source program can be 
reconstructed from the fully-expanded program by inspecting identifiers’ 
scopes. This seems plausible, since the scopes of a fully-expanded program 
dictate the binding structure of runtime variables by definition. However, this 
example reveals a flaw in that logic: resolution of macro bindings also 
involves a temporal component, since the compile-time binding table evolves as 
the program is expanded.

Frankly, this temporal dependency is unsatisfying. For runtime bindings, we 
enjoy predictable recursive definition contexts and inter-module lexical 
binding, courtesy of the module system. But to paraphrase Matthew, resolution 
of compile-time bindings is “distressingly like the top level,” since it 
requires interleaving of expansion and evaluation in a similar way.

I think this suggests that perhaps there is something fundamentally incomplete 
in our model of macroexpansion. However, it seems impossible to solve this 
problem without somehow restricting the macro language: the status quo allows 
macros to both (a) expand to absolutely anything via arbitrary procedural logic 
and (b) perform arbitrary side-effects, which allows them to observe expansion 
order. A more restrictive model could require macros to declare more 
information up front (which would allow the macroexpander to learn more about 
the binding structure of a program without fully expanding macros) or could 
provide access to state through restricted channels in such a way that the 
expander could “speculatively” expand a macro, then go back later and change 
its mind.

Of course, these would both require radical, deeply incompatible changes to the 
Racket macro system, so I do not expect them to actually be implemented! But 
perhaps they can be food for thought.

Alexis

-- 
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/D48BCCBB-AE1F-47CC-93E8-B90D1129E169%40gmail.com.


Re: [racket-users] How to change package name on the package index?

2020-06-04 Thread Alexis King
> On Jun 4, 2020, at 21:23, Siddhartha Kasivajhula  wrote:
> 
> I'd prefer to avoid that since (1) it would lose the package metadata and (2) 
> it could be off the package index for up to a day (the package index refresh 
> cycle) during which time other packages depending on it would be broken

This isn’t quite right: it’s true that the pkg-build service only runs once 
every 24 hours, but the only thing that depends on that is built documentation. 
The actual package index is refreshed much more rapidly—on the order of 
minutes. You wouldn’t have to wait very long at all to update other packages.

But even if you did, it wouldn’t matter, because there’s an easier solution: 
add your package under the new name before you delete the old name. Then you 
can delete the old name once you’ve ensured that everything you care about is 
updated. It’s perhaps a bit strange to have the same package simultaneously 
indexed under two different names, but it shouldn’t cause any trouble.

Alexis

-- 
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/3D0CF409-7E1E-431B-A0E3-D075445FA98E%40gmail.com.


Re: [racket-users] Testing for Packages

2020-05-26 Thread Alexis King
> On May 26, 2020, at 21:36, Robert Postill  wrote:
> 
> One thing that troubled me was that the tests seemed to be dependant on the 
> package already being installed.

I think this is very common within the Racket ecosystem. I would guess that 
very few packages are consciously designed to be “relocatable” in the way you 
describe.

> I've always considered the point at which a package gets transferred into the 
> domain of raco pkg's management to be a pivotal moment. It has this implied 
> social contract that if I'm mixing with code into a system area managed by 
> the language, the package needs to be trustworthy. Testing *after* installing 
> seems a bit like I'm putting the cart before the horse?

I cannot speak to the cultural norms of the Ruby community, as I am not 
terribly familiar with them, but I will admit that I find this mentality 
somewhat curious. In Racket, “installing” a package doesn’t affect very much 
beyond module path resolution. Running a package’s tests can do all the same 
things—install a keylogger, steal your private key, encrypt your hard 
drive—whether it is installed or not. Installation is also not very permanent; 
it’s very easy to undo or change.

So from my perspective, going out of your way to download package code and run 
it without officially installing it via `raco pkg` seems like a mostly 
pointless exercise. You’re basically doing all the same things—downloading it, 
unpacking it to a particular location on your computer, and giving it all the 
privileges of the user you run it as—just manually, rather than letting raco do 
the work for you. It is entirely possible that there is some additional 
distinction or utility I am not seeing, but my first instinct is to recommend 
that you just install the package. You can always uninstall it.

Alexis

-- 
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/2134D9EC-8870-4181-9BEF-2BEC6971ADEC%40gmail.com.


Re: [racket-users] Hunting a possible fsemaphore-post/wait bug

2020-05-24 Thread Alexis King
I realized a little while after writing my previous message that I was probably 
misinterpreting you. I was envisioning you using box-cas! on a box containing a 
functional queue, so there would be no need to synchronize. You’d just pull the 
queue out of the box, functionally update it, and use box-cas! to store the new 
result back. But your original program is using an imperative queue, so it 
seems plausible you really were using box-cas! to implement a spinlock. Then 
you would indeed be busy-waiting, after all!

Rereading Matthew’s original email, I have no idea if he was suggesting to use 
a spinlock or to do something closer to what I had in mind. Either way, I 
thought it sounded fun to try to implement a lock-free imperative queue in 
Racket. Then (theoretically) you’d get the best of both worlds: less duplicated 
work and less allocation than the functional approach (and allocation is 
expensive for futures!), but no busy-waiting. Here is my solution: 
https://gist.github.com/lexi-lambda/c54c91867f931b56123e3c595d8e445a

As far as I can tell, it works nicely, and it’s not terribly complicated. 
Inspecting the behavior of my test cases in the futures visualizer, it seems to 
be doing good things. But I found I needed to use Matthew’s threads + futures 
trick, and in the process, I discovered a small subtlety needed to make it 
actually work. Here’s a self-contained program that reproduces the issue I ran 
into:

#lang racket
(require racket/logging)

(define (slow-sum)
  (for/sum ([j (in-range 1)]) 1))

(define (go)
  (define workers
(for/list ([i (in-range 8)])
  (thread (λ () (touch (future slow-sum))
  (for-each thread-wait workers))

(with-logging-to-port
 #:logger (current-logger)
 (current-output-port)
 (thunk (go) (newline) (newline) (newline) (go))
 'debug
 'future)

This runs the `go` procedure twice back-to-back, printing future trace messages 
to stdout. The first execution is good; futures start up in parallel:

future: id -1, process 0: created; time: 1590334415654.675049
future: id 1, process 1: started work; time: 1590334415654.749023
future: id 1, process 0: paused for touch; time: 1590334415654.894043
future: id -1, process 0: created; time: 1590334415654.912109
future: id 2, process 2: started work; time: 1590334415654.934082
future: id 2, process 0: paused for touch; time: 1590334415655.214111
future: id 1, process 1: completed; time: 1590334415878.041992
future: id 1, process 1: ended work; time: 1590334415878.049072
future: id 1, process 0: resumed for touch; time: 1590334415878.070068
future: id 2, process 2: completed; time: 1590334415878.167969
future: id 2, process 2: ended work; time: 1590334415878.173096
future: id 2, process 0: resumed for touch; time: 1590334415878.217041

(I reduced the number of futures here from 8 to 2 for this run to keep the log 
messages from being uselessly verbose for an email.)

However, on the second execution, I get no parallelism at all:

future: id -1, process 0: created; time: 1590334415878.292969
future: id 3, process 0: started work; time: 1590334415878.298096
future: id -1, process 0: created; time: 1590334415903.156006
future: id 4, process 0: started work; time: 1590334415903.163086
future: id 3, process 0: completed; time: 1590334416300.748047
future: id 3, process 0: ended work; time: 1590334416300.749023
future: id 4, process 0: completed; time: 1590334416322.684082
future: id 4, process 0: ended work; time: 1590334416322.684082

What’s going on? The problem is that `touch` is getting called before the 
futures have a chance to get started (possibly because the VM is now warmed up 
and things run faster?). Normally, that would only happen if the futures were 
really, really short: the first `touch` would run the first future on the main 
thread, and the other futures would start up in parallel while that first one 
is running. But in this program, each future is started on its own (green) 
thread, so I essentially created a race between the thread scheduler and the 
future scheduler.

It seems splitting the future creation from the thread creation is enough to 
make this issue go away:

(define (go)
  (define futures (for/list ([i (in-range 8)]) (future slow-sum)))
  (define workers (for/list ([f (in-list futures)])
(thread (λ () (touch f)
  (for-each thread-wait workers))

Now the futures always start up in parallel. This seems like it’s probably 
pretty reliable, so it isn’t really a problem, but I found the behavior 
surprising. It suggests the thread and future schedulers are blissfully unaware 
of one another: the thread scheduler is perfectly happy to run dozens of 
futures concurrently on the main OS thread rather than kick some of them onto 
another core. Normally this is something that work-stealing could fix, but it 
doesn’t seem like the futures scheduler ever steals work from futures executing 

Re: [racket-users] Hunting a possible fsemaphore-post/wait bug

2020-05-24 Thread Alexis King
> On May 24, 2020, at 02:10, Dominik Pantůček  
> wrote:
> 
> At first I was surprised that you are basically suggesting using
> spinlocks (busy-wait loops) instead of futex-backed (at least on Linux)
> fsemaphores. That is a waste of CPU time.

Performing CAS operations in a loop isn’t really directly comparable to 
spinlocking. With a spinlock, the blocked thread is spending cycles doing 
absolutely nothing for an arbitrarily-long time. The blocked thread is 
completely at the mercy of the thread that holds the lock, which may not 
release it for a lengthy duration even if the blocked thread only needs to 
acquire it briefly.

In contrast, lock-free concurrency approaches that use atomic operations never 
spend CPU time busy-waiting. All threads are always doing useful work; the 
worst case scenario is that work is duplicated. The burden here is reversed: if 
one thread needs to use the shared resource for a short period of time while a 
long-running computation is in progress on another thread, it doesn’t have to 
wait, it just wins and continues with its business. It’s the long-running 
computation that loses here, since it has to throw away the work it did and 
retry.

This means lock-free approaches are bad if you have (a) lots of contention over 
a shared resource, plus (b) long-running computations using the resource, which 
would be prohibitively-expensive to duplicate. But if contention is low and/or 
the operation is sufficiently cheap, the overhead of work duplication will be 
irrelevant. (This is why lock-free concurrency is sometimes called “optimistic 
concurrency”—you’re optimistically hoping nobody else needs the resource while 
you’re using it.) Furthermore, note that acquiring a mutex must ultimately use 
atomic operations internally, so if there is no contention, the lock-free 
approach will fundamentally be faster (or at least no slower) than the locking 
approach.

Now consider what blocking on a mutex must do in addition to the atomic 
operation: it must return to the thread scheduler, since a blocked thread must 
be added to a wakeup list and unscheduled. This incurs all the overhead of 
context-switching, which is small, but it isn’t zero. Compare that to the cost 
of a single enqueue or dequeue operation, which involve just a couple reads and 
a single write. Soon you end up in a situation where the cost of 
context-switching outweighs any work you might duplicate even if there is 
thread contention, and now you’re always beating the mutex under all usage 
patterns!

tl;dr: Even though lock-free approaches and spinlocks are superficially similar 
in that they involve “spinning in a loop,” it isn’t fair to conflate them! 
Optimistic concurrency is a bad idea if you have operations that need access to 
the shared resource for a long time, since you’ll end up duplicating tons of 
work, but if the operation is cheap, you lose nothing over a mutex-based 
approach and potentially gain a little extra performance.

Alexis

-- 
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/C4901A78-33A7-40B7-AA20-6D5B504D9716%40gmail.com.


Re: [racket-users] rackunit and logging

2020-05-23 Thread Alexis King
> On May 23, 2020, at 08:53, Shriram Krishnamurthi  wrote:
> 
> Alex, thanks for that information. I'm going to go investigate that next.

Related to that, I just remembered the existence of rackunit/text-ui and 
rackunit/gui, which implement two different reporters for RackUnit test 
cases/suites. Looking at their source might be informative, since neither is 
particularly complicated. The text reporter uses fold-test-results, and the GUI 
reporter uses foldts-test-suite.

-- 
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/3E7DA1AD-851F-4F95-A65B-565D9953A7D5%40gmail.com.


Re: [racket-users] rackunit and logging

2020-05-23 Thread Alexis King
> On May 22, 2020, at 18:47, Shriram Krishnamurthi  wrote:
> 
> As an aside, I'm not entirely sure what `test-log!` is there for. Presumably 
> it's to record in the log "tests" run by operations that are not part of 
> rackunit? I'm curious how people have used it.

Other people have answered other parts of your question, but I don’t think 
anyone has answered this point. The answer is that test-log! isn’t really part 
of RackUnit at all—it comes from the module rackunit/log, but note that it 
comes from the package testing-util-lib, not rackunit-lib. (I can’t say for 
certain, but my guess is that the module is named rackunit/log for historical 
reasons more than anything else.)

test-log! is really mostly an API for cooperating with `raco test`. When you 
run `raco test`, you’ll find that it reports how many tests were run and how 
many of them passed, even if you test multiple modules at once. Somehow, test 
frameworks need to communicate this information to `raco test`, and test-log! 
is the mechanism through which they do that.

Aside from that, `raco test` mostly just instantiates modules in the usual way. 
All of the other success or failure reporting is just ordinary side-effectful 
printing performed by test frameworks themselves. All of RackUnit’s “check info 
stack” machinery is specific to RackUnit; `raco test` doesn’t know or care 
about that at all. RackUnit calls test-log! internally during execution of each 
check, so if you use define-check, you don’t have to call test-log! yourself 
(and indeed, you shouldn’t, or else your tests will be counted twice).

> TL;DR: If I want to record what happened on all the checks for post-execution 
> processing, do I need to (a) create my own log and, to do so, (b) rewrite all 
> the checking predicates to provide the information that the detailed log 
> needs?

As the above explanation implies, if you don’t want to use RackUnit, you can do 
whatever you want. You can print your own (arbitrary) messages upon failure, 
and if you want to integrate with `raco test`, you should just make sure to 
call test-log! once for each executed test case.

If you do want to use RackUnit, then yes, you have to cooperate with all of 
RackUnit’s machinery for implementing checks. Personally, I find RackUnit’s 
design frustrating here. As you have discovered, checks aren’t very 
compositional, so it’s not easy to implement a new check in terms of an 
existing one (while still providing good error messages on failure).

If what you’re doing is difficult to express in RackUnit, consider just 
ditching it and doing your own thing. Test suites in Racket are just simple, 
side-effectful programs, and RackUnit doesn’t do that much all things 
considered.

Alexis

-- 
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/6744FD8B-9427-44D0-A603-C040FB1CC07B%40gmail.com.


Re: [racket-users] Do I misunderstand set! ?

2020-04-23 Thread Alexis King
> On Apr 23, 2020, at 21:15, Hendrik Boom  wrote:
> 
> (fprintf anomaly "resEEEulttyope was ~s~n" resulttype)
> (fprintf anomaly "set resulttyoe to ~s~n" ty)
> `(set! resulttype ty)
> (fprintf anomaly "resEEulttyope now ~s~n" resulttype)

(Re-sending this because I forgot to CC the list the first time.)

Assuming it is not some strange artifact of your email client’s formatting, you 
have a backtick at the beginning of the line your set! expression appears on, 
so it is quasiquoted and will not do anything. Both DrRacket and racket-mode 
communicate this information to you in various ways: DrRacket won’t draw 
binding arrows for set! or resulttype, and I believe racket-mode has similar 
functionality (albeit displayed in a different way).

-- 
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/6C5015F4-B5F8-46CB-85EF-F04BE3B0D7AA%40gmail.com.


Re: [racket-users] How to find source file loaded by/relevant for (require )?

2020-03-27 Thread Alexis King
I recommend Ryan Culpepper’s whereis package: 
https://docs.racket-lang.org/whereis/index.html 
 It provides both a 
programmatic interface and a raco command.

Alexis

> On Mar 27, 2020, at 03:56, Marc Kaufmann  wrote:
> 
> Hi,
> 
> I am trying to set up vim such that it jumps to the correct source file when 
> I see a `(require some-module)`. With packages that I have installed myself, 
> I have managed to do so (80% solution), since they get installed in 
> $HOME/.racket//pkgs. However, I can't quite figure out where all the 
> things are. Some are in 
> /usr/share/racket/pkgs/-lib/, but 
> others like racket/match seem to be in /usr/share/racket/collects/... . Are 
> there any other places for the core modules?
> 
> Rather than me trying to do something error-prone, is there a Racket function 
> that I can call on  that returns the right path on my machine? 
> That way I don't write stupid error-prone regexes.
> 
> Cheers,
> Marc

-- 
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/DB1F4C09-837E-4586-BB0D-272AB14FCD63%40gmail.com.


Re: [racket-users] questions about top-level-bind-scope in root-expand-context

2020-03-23 Thread Alexis King
> On Mar 23, 2020, at 13:46, George Neuner  wrote:
> 
> I've run into this problem before ... I don't recall the official
> explanation, but my takeaway was that Racket does not permit you to
> directly *export* a value - you have to export a function or macro
> that produces the value.
> 
> E.g., 
>  #lang racket
>  (provide fib)
>  (define (fib) "fib")

I’m not sure what issue you may have run into in the past, but Racket certainly 
has no issue with exporting a value. (After all, functions are values.) The 
issue described in this thread is (a) entirely syntactic (it’s an issue of 
binding/scoping, not runtime behavior), and (b) only occurs at the top-level 
(i.e. in the REPL, outside of a module). Matthew has already provided a 
detailed explanation of why the issue occurs.

It’s true that you cannot set! imported bindings, but that’s quite separate 
from the problem discussed in this thread (which appears to be resolved).

-- 
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/DB94641E-A018-4A1D-BEE3-47DD183D7B54%40gmail.com.


Re: [racket-users] Starting racket with at-exp

2020-03-02 Thread Alexis King
The -l option loads a module path. As `racket --help` documents, `-l ` is 
equivalent to `-e '(require (lib ""))'`. Since (require (lib "at-exp 
racket")) won’t help you much, neither will `-l 'at-exp racket'`. I’m not 
totally sure why you thought `-l` was the right option here, but it doesn’t set 
the language.

It would be useful to have an option that does set the language, but it isn’t 
completely clear precisely what such an option ought to do. Unfortunately, the 
way the #lang protocol interacts with the REPL is indirect and complicated. The 
protocol is documented in the section of the reference entitled “Language 
Run-Time Configuration”: 
https://docs.racket-lang.org/reference/running-sa.html#%28part._configure-runtime%29
 


The root problem is the protocol operates on a module. A module written in a 
given #lang can generate a configure-runtime submodule or attach a syntax 
property property to its read body, but these both require a module written in 
the #lang already exist. The DrRacket REPL always operates in the context of 
some module (given in the definitions window), but the REPL run from the 
command line has no such luxury. Theoretically, some option could be added to 
generate an empty module in a specified #lang and use it to configure the REPL 
environment, but an empty module may not be a legal program in every #lang.

Furthermore, `at-exp racket` is not really a #lang, anyway. The #lang is just 
`at-exp`; the body of the module happens to start with the symbol `racket`. The 
`at-exp` reader reads the first symbol of its body and uses that symbol as a 
language path, then calls that language’s reader after installing the 
@-expression readtable. Again, this protocol only makes sense in the context of 
reading a module, and a module that starts with `#lang at-exp racket` doesn’t 
really have an empty body at all.

> On Mar 2, 2020, at 18:52, Faré  wrote:
> 
> On Mon, Mar 2, 2020 at 5:22 PM Michael MacLeod
>  wrote:
>> 
>> $ racket -i -l scribble/reader -e "(use-at-readtable)" -l 
>> your-lang-without-@-support
>> 
>> should do the trick.
>> 
> Thanks. It works like a charm. But isn't a very nice recipe.
> Are there reasons why -l 'at-exp racket' sdhouln't be made to work?
> (Beside resource availability)
> 
> —♯ƒ • François-René ÐVB Rideau •Reflection• http://fare.tunes.org
> The people cannot delegate to government the power to do
> anything which would be unlawful for them to do themselves.
>— John Locke, "A Treatise Concerning Civil Government"

-- 
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/68443BE8-9CE7-4417-82CC-C727CAFDB38D%40gmail.com.


Re: [racket-users] how to adapt BC code for Racket CS?

2020-02-23 Thread Alexis King
> On Feb 23, 2020, at 18:28, Matthew Flatt  wrote:
> 
> None of Racket BC, Racket CS, or Chez Scheme by itself will optimize
> away the unused loop argument. That kind of interprocedural dead-code
> elimination is out of reach for the current compilers, except to the
> degree that inlining turns them into intraprocedural questions.

Got it, thanks, that makes sense. For perspective, I am coming from GHC-land, 
where such optimizations are near-guaranteed: the demand analyzer would see the 
argument is unused and drop it after a worker/wrapper split. That said, I 
realize the luxury of purity and non-strict evaluation makes it easier for GHC 
to be much more aggressive.

> Converting loops into closed form requires more sophisticated and
> general induction reasoning than is typical in a compiler. Or it needs
> ad hoc pattern patching to cover a few cases --- which I have seen gcc
> do, but I don't think that's very common.

Yes, that makes sense, and this part is not shocking. I don’t think GHC manages 
that optimization, either.

-- 
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/821102D5-8C7B-4B3E-91CB-C495E7E2A4D2%40gmail.com.


Re: [racket-users] how to adapt BC code for Racket CS?

2020-02-22 Thread Alexis King
I have a related but distinct question about the blog post: I’m curious what 
guarantees I can come to expect from the Racket CS optimizer. The post includes 
the following example:

(for/fold ([v #f]) ([i (in-range N)]) i)

On both Racket BC and Racket CS, I’d expect the optimizer to turn this into a 
tight recursive loop that looks something like this:

(let loop ([v #f]
   [i 0])
  (define j (add1 i))
  (if (< j N)
  (loop i j)
  i))

But my understanding is that Chez’s optimizer is much more sophisticated than 
Racket BC’s. At the very least, I’d expect it to be able to identify that `v` 
is never used here and simplify it to this:

(let loop ([i 0])
  (define j (add1 i))
  (if (< j N)
  (loop j)
  i))

Now I’d wonder: if N is a known constant, could the optimizer just delete the 
loop? Could the whole thing be optimized to (sub1 N)? Given the performance 
numbers in the blog post, I’m guessing the answer is no. Is the reason just 
that Chez doesn’t perform this kind of optimization, or is there something more 
fundamental?

-- 
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/20521455-F33B-4296-A768-3561D02BC269%40gmail.com.


Re: [racket-users] Megaparsack and where errors happen

2020-02-21 Thread Alexis King
Hi Matt,

I think you probably want to read this section of the docs: 
https://docs.racket-lang.org/megaparsack/parsing-branching.html#%28part._.Backtracking_with_caution%29

The core idea is that `try/p` is a heavy hammer. It causes any failure inside 
its scope to backtrack, so you might end up accidentally ruining your error 
messages. Usually, what you really want is to do a small amount of lookahead to 
determine which branch is the correct one to take, then commit to the branch so 
that future parse failures are reported immediately.

Without seeing your `base-type/p`, `convert/p`, and `chain/p` parsers, it’s 
hard to suggest a concrete solution. But consider using `try/p` to do only 
whatever parsing you need to do in order to disambiguate the parsers, then exit 
the scope of `try/p`. Something like this:

(or/p (do (try/p base-type-initial/p) base-type-remainder/p)
  (do (try/p convert-initial/p) convert-remainder/p)
  ...)

There are other approaches as well, and if you provide more information I might 
be able to suggest something better.

This complication is unfortunately fundamental to the Parsec parsing model. The 
syntax/parse model of tracking “progress” and reporting the error associated 
with the parse that made it the farthest is much nicer, but syntax/parse has 
the luxury of parsing a well-known tree structure. A more tractable improvement 
might be to add some kind of explicit committing construct.

Hope this helps,
Alexis

> On Feb 21, 2020, at 20:19, Matt Jadud  wrote:
> 
> Hi all,
> 
> This might be a Lexi question, but perhaps someone else will have some 
> insight as well.
> 
> I'm wrestling with how to get errors to propagate down in megaparsack. For 
> example:
> 
> (define convert/p
>   (do (string/p "convert")
>  ...
>   [assigns ← (many/p #:min 0
>  assignment-statement/p
>  )]
>  ...
>   (pure ...)))
> 
> (Assume I have a bunch of other parsing bits around the call to 
> `assignment-statement/p`.)
> 
> Currently, if I have a malformed assignment statement, the error is at the 
> top level of `convert`. `convert/p` is part of a backtracking conditional:
> 
> (define conversion/p
>   (do
> [result ← (many/p (or/p (try/p base-type/p)
> (try/p convert/p)
> (try/p chain/p)
> )
>   #:sep space0+/p
>   )]
> eof/p
> (pure result)))
> 
> What should I do to get the error to report/fail down the parse tree, as 
> opposed to the top? I would rather know that there's something wrong down in 
> my assignment statement, as opposed to getting an error that "c" was 
> unexpected (because the entire conversion/p failed on account of an error 
> somewhere down inside).
> 
> I need to give the docs a more careful read, but I thought I'd ask, as it 
> seems both simple and, given the nature of the parsing tools, possibly subtle.
> 
> Many thanks,
> Matt
> 
> 
> -- 
> 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/CAAGM45761tRo%2Bj0Rh078ngriYiMDum%3DyDyRgwQ1LLiuPZDFj6A%40mail.gmail.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/69FA9918-BD9C-4041-85A7-BCF87867%40gmail.com.


Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
Oh: something more ambitious that I would enjoy having would be an 
implementation of IVars and LVars to avoid needing to think about locking 
entirely.

> On Jan 18, 2020, at 05:00, Alexis King  wrote:
> 
> 
> I would use mutexes in relatively standard ways, I think, to protect critical 
> sections that access shared mutable state or external resources that may 
> require some form of serialization. The usual approach of using a semaphore 
> works fine, but it does require the aforementioned break manipulation song 
> and dance to be entirely robust, and it would be nice to not have to worry 
> about it.
> 
>>> On Jan 18, 2020, at 04:46, Jack Firth  wrote:
>>> 
>> 
>> I appreciate the sentiment about prior art, but I'm already familiar with 
>> both of those links and a significant part of my day job involves working on 
>> concurrency frameworks. Specific use cases are more what I'm after. For 
>> instance, what would you like to use mutexes for?
>> 
>>> On Sat, Jan 18, 2020 at 2:34 AM Alexis King  wrote:
>>> Oh, an addendum: I would be remiss not to mention the excellent paper on 
>>> the design of Haskell’s asynchronous exception system, which provides both 
>>> examples of problems in the wild and more general elaboration on both the 
>>> design space and the particular point within it the authors chose for 
>>> Haskell. The paper is “Asynchronous Exceptions in Haskell” by Marlow, 
>>> Peyton Jones, Moran, and Reppy, and it is available here:
>>> 
>>> https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/asynch-exns.pdf
>>> 
>>> Another thing worth reading is this recent blog post by Simon Marlow (the 
>>> first author of the aforementioned paper) on asynchronous exceptions:
>>> 
>>> https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html
>>> 
>>>> On Jan 18, 2020, at 04:27, Alexis King  wrote:
>>>> 
>>>> I don’t personally have any problems with Racket’s semaphore interface as 
>>>> it exists today. I think having the choice of whether or not to enable 
>>>> breaks mostly makes sense as something the ambient environment controls, 
>>>> not individual pieces of synchronization logic, since you usually want 
>>>> control structures like `with-handlers` and `dynamic-wind` to be the 
>>>> things that mask interrupts in the appropriate places. A hypothetical 
>>>> `with-critical-section` form would be similar in that respect. This allows 
>>>> a limited form of composability between concurrency constructs that is 
>>>> otherwise hard to achieve.
>>>> 
>>>> For the reasons I’ve already given, I think it would be more useful to 
>>>> offer higher-level concurrency primitives like events, mutexes, etc., 
>>>> since those could offer more structure based on the particular use case in 
>>>> question. (Also, I realized Haskell’s MVars are basically just Racket 
>>>> channels, though Racket’s channels don’t have a peek operation.)
>>>> 
>>>> More generally, I think Haskell’s concurrency libraries are good prior art 
>>>> here that would be worth looking at. Haskell’s “asynchronous exceptions” 
>>>> are directly analogous to Racket’s breaks, though Haskell allows arbitrary 
>>>> exceptions to be raised asynchronously rather than only allowing the more 
>>>> restrictive interface of `thread-break`. Haskell’s `mask` operator 
>>>> correspond’s to Racket’s `parameterize-break`. Even though the primitives 
>>>> are essentially the same, Haskell’s libraries provide a much richer set of 
>>>> higher-level abstractions, both in the standard library (see 
>>>> Control.Exception and Control.Concurrent.*) and in other packages.
>>>> 
>>>>> On Jan 18, 2020, at 04:04, Jack Firth  wrote:
>>>>> 
>>>>> I am making a new concurrency abstraction, and I already have to work 
>>>>> around the interface because it forces me to make this choice at every 
>>>>> use site. What I was planning on doing was pushing this decision into the 
>>>>> value itself, rather than the use site. So what if `make-semaphore` had a 
>>>>> `#:break-handling-mode` argument that controlled whether or not waiting 
>>>>> on that particular semaphore would either enable breaks, or check that 
>>>>> breaks or disabled, or neither of those?
>>>>> 
>>>>>> On Sat, Jan 18, 2020 at 1:45 AM Alexis King 

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
I would use mutexes in relatively standard ways, I think, to protect critical 
sections that access shared mutable state or external resources that may 
require some form of serialization. The usual approach of using a semaphore 
works fine, but it does require the aforementioned break manipulation song and 
dance to be entirely robust, and it would be nice to not have to worry about it.

> On Jan 18, 2020, at 04:46, Jack Firth  wrote:
> 
> 
> I appreciate the sentiment about prior art, but I'm already familiar with 
> both of those links and a significant part of my day job involves working on 
> concurrency frameworks. Specific use cases are more what I'm after. For 
> instance, what would you like to use mutexes for?
> 
>> On Sat, Jan 18, 2020 at 2:34 AM Alexis King  wrote:
>> Oh, an addendum: I would be remiss not to mention the excellent paper on the 
>> design of Haskell’s asynchronous exception system, which provides both 
>> examples of problems in the wild and more general elaboration on both the 
>> design space and the particular point within it the authors chose for 
>> Haskell. The paper is “Asynchronous Exceptions in Haskell” by Marlow, Peyton 
>> Jones, Moran, and Reppy, and it is available here:
>> 
>> https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/asynch-exns.pdf
>> 
>> Another thing worth reading is this recent blog post by Simon Marlow (the 
>> first author of the aforementioned paper) on asynchronous exceptions:
>> 
>> https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html
>> 
>>> On Jan 18, 2020, at 04:27, Alexis King  wrote:
>>> 
>>> I don’t personally have any problems with Racket’s semaphore interface as 
>>> it exists today. I think having the choice of whether or not to enable 
>>> breaks mostly makes sense as something the ambient environment controls, 
>>> not individual pieces of synchronization logic, since you usually want 
>>> control structures like `with-handlers` and `dynamic-wind` to be the things 
>>> that mask interrupts in the appropriate places. A hypothetical 
>>> `with-critical-section` form would be similar in that respect. This allows 
>>> a limited form of composability between concurrency constructs that is 
>>> otherwise hard to achieve.
>>> 
>>> For the reasons I’ve already given, I think it would be more useful to 
>>> offer higher-level concurrency primitives like events, mutexes, etc., since 
>>> those could offer more structure based on the particular use case in 
>>> question. (Also, I realized Haskell’s MVars are basically just Racket 
>>> channels, though Racket’s channels don’t have a peek operation.)
>>> 
>>> More generally, I think Haskell’s concurrency libraries are good prior art 
>>> here that would be worth looking at. Haskell’s “asynchronous exceptions” 
>>> are directly analogous to Racket’s breaks, though Haskell allows arbitrary 
>>> exceptions to be raised asynchronously rather than only allowing the more 
>>> restrictive interface of `thread-break`. Haskell’s `mask` operator 
>>> correspond’s to Racket’s `parameterize-break`. Even though the primitives 
>>> are essentially the same, Haskell’s libraries provide a much richer set of 
>>> higher-level abstractions, both in the standard library (see 
>>> Control.Exception and Control.Concurrent.*) and in other packages.
>>> 
>>>> On Jan 18, 2020, at 04:04, Jack Firth  wrote:
>>>> 
>>>> I am making a new concurrency abstraction, and I already have to work 
>>>> around the interface because it forces me to make this choice at every use 
>>>> site. What I was planning on doing was pushing this decision into the 
>>>> value itself, rather than the use site. So what if `make-semaphore` had a 
>>>> `#:break-handling-mode` argument that controlled whether or not waiting on 
>>>> that particular semaphore would either enable breaks, or check that breaks 
>>>> or disabled, or neither of those?
>>>> 
>>>>> On Sat, Jan 18, 2020 at 1:45 AM Alexis King  wrote:
>>>>> No, I don’t think so, and here’s why: imagine a library provides an 
>>>>> abstraction that internally uses semaphores as events. The library uses 
>>>>> `semaphore-wait` to wait on the event. The client of this library now has 
>>>>> the option to disable breaks if it turns out this code is actually going 
>>>>> to be used inside a larger critical section, and they don’t want breaks 
>>>>> to be re-enabled by the 

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
Oh, an addendum: I would be remiss not to mention the excellent paper on the 
design of Haskell’s asynchronous exception system, which provides both examples 
of problems in the wild and more general elaboration on both the design space 
and the particular point within it the authors chose for Haskell. The paper is 
“Asynchronous Exceptions in Haskell” by Marlow, Peyton Jones, Moran, and Reppy, 
and it is available here:

https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/asynch-exns.pdf
 
<https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/asynch-exns.pdf>

Another thing worth reading is this recent blog post by Simon Marlow (the first 
author of the aforementioned paper) on asynchronous exceptions:

https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html 
<https://simonmar.github.io/posts/2017-01-24-asynchronous-exceptions.html>

> On Jan 18, 2020, at 04:27, Alexis King  wrote:
> 
> I don’t personally have any problems with Racket’s semaphore interface as it 
> exists today. I think having the choice of whether or not to enable breaks 
> mostly makes sense as something the ambient environment controls, not 
> individual pieces of synchronization logic, since you usually want control 
> structures like `with-handlers` and `dynamic-wind` to be the things that mask 
> interrupts in the appropriate places. A hypothetical `with-critical-section` 
> form would be similar in that respect. This allows a limited form of 
> composability between concurrency constructs that is otherwise hard to 
> achieve.
> 
> For the reasons I’ve already given, I think it would be more useful to offer 
> higher-level concurrency primitives like events, mutexes, etc., since those 
> could offer more structure based on the particular use case in question. 
> (Also, I realized Haskell’s MVars are basically just Racket channels, though 
> Racket’s channels don’t have a peek operation.)
> 
> More generally, I think Haskell’s concurrency libraries are good prior art 
> here that would be worth looking at. Haskell’s “asynchronous exceptions” are 
> directly analogous to Racket’s breaks, though Haskell allows arbitrary 
> exceptions to be raised asynchronously rather than only allowing the more 
> restrictive interface of `thread-break`. Haskell’s `mask` operator 
> correspond’s to Racket’s `parameterize-break`. Even though the primitives are 
> essentially the same, Haskell’s libraries provide a much richer set of 
> higher-level abstractions, both in the standard library (see 
> Control.Exception and Control.Concurrent.*) and in other packages.
> 
>> On Jan 18, 2020, at 04:04, Jack Firth > <mailto:jackhfi...@gmail.com>> wrote:
>> 
>> I am making a new concurrency abstraction, and I already have to work around 
>> the interface because it forces me to make this choice at every use site. 
>> What I was planning on doing was pushing this decision into the value 
>> itself, rather than the use site. So what if `make-semaphore` had a 
>> `#:break-handling-mode` argument that controlled whether or not waiting on 
>> that particular semaphore would either enable breaks, or check that breaks 
>> or disabled, or neither of those?
>> 
>> On Sat, Jan 18, 2020 at 1:45 AM Alexis King > <mailto:lexi.lam...@gmail.com>> wrote:
>> No, I don’t think so, and here’s why: imagine a library provides an 
>> abstraction that internally uses semaphores as events. The library uses 
>> `semaphore-wait` to wait on the event. The client of this library now has 
>> the option to disable breaks if it turns out this code is actually going to 
>> be used inside a larger critical section, and they don’t want breaks to be 
>> re-enabled by the library! They really want everything in the critical 
>> section to keep breaks disabled. So in that case, the break-agnostic 
>> behavior of `semaphore-wait` really is the right one.
>> 
>> This is what I mean by semaphore’s being a low-level primitive, though. 
>> There are lots of different behaviors one might want that could be better 
>> served by higher-level abstractions that can make more assumptions about how 
>> they’ll be used, but semaphores have to support all of them. I think it 
>> makes sense that they provide the minimal set of behaviors needed to 
>> implement those things—it keeps the building blocks as simple and modular as 
>> possible. You can always implement the more complex behavior on top, but 
>> it’d be annoying to discover you needed to work around the interface trying 
>> to protect you from yourself while you’re implementing a new concurrency 
>> abstraction.
>> 
>>> On Jan 18, 2020, at 03:36, Jack Firth >> <mailto:

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
I don’t personally have any problems with Racket’s semaphore interface as it 
exists today. I think having the choice of whether or not to enable breaks 
mostly makes sense as something the ambient environment controls, not 
individual pieces of synchronization logic, since you usually want control 
structures like `with-handlers` and `dynamic-wind` to be the things that mask 
interrupts in the appropriate places. A hypothetical `with-critical-section` 
form would be similar in that respect. This allows a limited form of 
composability between concurrency constructs that is otherwise hard to achieve.

For the reasons I’ve already given, I think it would be more useful to offer 
higher-level concurrency primitives like events, mutexes, etc., since those 
could offer more structure based on the particular use case in question. (Also, 
I realized Haskell’s MVars are basically just Racket channels, though Racket’s 
channels don’t have a peek operation.)

More generally, I think Haskell’s concurrency libraries are good prior art here 
that would be worth looking at. Haskell’s “asynchronous exceptions” are 
directly analogous to Racket’s breaks, though Haskell allows arbitrary 
exceptions to be raised asynchronously rather than only allowing the more 
restrictive interface of `thread-break`. Haskell’s `mask` operator correspond’s 
to Racket’s `parameterize-break`. Even though the primitives are essentially 
the same, Haskell’s libraries provide a much richer set of higher-level 
abstractions, both in the standard library (see Control.Exception and 
Control.Concurrent.*) and in other packages.

> On Jan 18, 2020, at 04:04, Jack Firth  wrote:
> 
> I am making a new concurrency abstraction, and I already have to work around 
> the interface because it forces me to make this choice at every use site. 
> What I was planning on doing was pushing this decision into the value itself, 
> rather than the use site. So what if `make-semaphore` had a 
> `#:break-handling-mode` argument that controlled whether or not waiting on 
> that particular semaphore would either enable breaks, or check that breaks or 
> disabled, or neither of those?
> 
> On Sat, Jan 18, 2020 at 1:45 AM Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> No, I don’t think so, and here’s why: imagine a library provides an 
> abstraction that internally uses semaphores as events. The library uses 
> `semaphore-wait` to wait on the event. The client of this library now has the 
> option to disable breaks if it turns out this code is actually going to be 
> used inside a larger critical section, and they don’t want breaks to be 
> re-enabled by the library! They really want everything in the critical 
> section to keep breaks disabled. So in that case, the break-agnostic behavior 
> of `semaphore-wait` really is the right one.
> 
> This is what I mean by semaphore’s being a low-level primitive, though. There 
> are lots of different behaviors one might want that could be better served by 
> higher-level abstractions that can make more assumptions about how they’ll be 
> used, but semaphores have to support all of them. I think it makes sense that 
> they provide the minimal set of behaviors needed to implement those things—it 
> keeps the building blocks as simple and modular as possible. You can always 
> implement the more complex behavior on top, but it’d be annoying to discover 
> you needed to work around the interface trying to protect you from yourself 
> while you’re implementing a new concurrency abstraction.
> 
>> On Jan 18, 2020, at 03:36, Jack Firth > <mailto:jackhfi...@gmail.com>> wrote:
>> 
>> Wouldn't you want to force the first thread to wait with 
>> semaphore-wait/enable-break in that case? Since if they're disabled then 
>> that thread can't be cooperatively terminated. If you use `semaphore-wait` 
>> it seems like you completely hand off control over whether breaks are 
>> enabled or not, which seems like something that use sites should care about 
>> one way or the other. What sort of semaphore-based communication would be 
>> truly indifferent to whether breaking is enabled?
>> 
>> On Sat, Jan 18, 2020 at 1:28 AM Alexis King > <mailto:lexi.lam...@gmail.com>> wrote:
>> Actually, I change my mind, I can trivially think of a case where it’s fine: 
>> if you’re just using a semaphore as an event. One thread waits with 
>> `semaphore-wait`, another thread calls `semaphore-post`, and after the count 
>> is decremented, it’s never re-incremented. It’s just used to gate execution, 
>> not guard access to a resource. No need to disable breaks here.
>> 
>> (Also, an aside: I think your `car`/`cdr` example is different, because 
>> `car`/`cdr`’s checks on pairs guard against memory corruption in the Racket 

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
No, I don’t think so, and here’s why: imagine a library provides an abstraction 
that internally uses semaphores as events. The library uses `semaphore-wait` to 
wait on the event. The client of this library now has the option to disable 
breaks if it turns out this code is actually going to be used inside a larger 
critical section, and they don’t want breaks to be re-enabled by the library! 
They really want everything in the critical section to keep breaks disabled. So 
in that case, the break-agnostic behavior of `semaphore-wait` really is the 
right one.

This is what I mean by semaphore’s being a low-level primitive, though. There 
are lots of different behaviors one might want that could be better served by 
higher-level abstractions that can make more assumptions about how they’ll be 
used, but semaphores have to support all of them. I think it makes sense that 
they provide the minimal set of behaviors needed to implement those things—it 
keeps the building blocks as simple and modular as possible. You can always 
implement the more complex behavior on top, but it’d be annoying to discover 
you needed to work around the interface trying to protect you from yourself 
while you’re implementing a new concurrency abstraction.

> On Jan 18, 2020, at 03:36, Jack Firth  wrote:
> 
> Wouldn't you want to force the first thread to wait with 
> semaphore-wait/enable-break in that case? Since if they're disabled then that 
> thread can't be cooperatively terminated. If you use `semaphore-wait` it 
> seems like you completely hand off control over whether breaks are enabled or 
> not, which seems like something that use sites should care about one way or 
> the other. What sort of semaphore-based communication would be truly 
> indifferent to whether breaking is enabled?
> 
> On Sat, Jan 18, 2020 at 1:28 AM Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> Actually, I change my mind, I can trivially think of a case where it’s fine: 
> if you’re just using a semaphore as an event. One thread waits with 
> `semaphore-wait`, another thread calls `semaphore-post`, and after the count 
> is decremented, it’s never re-incremented. It’s just used to gate execution, 
> not guard access to a resource. No need to disable breaks here.
> 
> (Also, an aside: I think your `car`/`cdr` example is different, because 
> `car`/`cdr`’s checks on pairs guard against memory corruption in the Racket 
> runtime, and Racket is a memory-safe language. A better comparison would be 
> that `car`/`cdr` don’t check whether or not their argument is a proper 
> list—the higher-level `first`/`rest` do that, instead.)
> 
>> On Jan 18, 2020, at 03:21, Jack Firth > <mailto:jackhfi...@gmail.com>> wrote:
>> 
>> It isn't clear to me either. I can't think of a use case for it, but I'm 
>> hoping either somebody else can or somebody can confirm that it's not a good 
>> API precedent. I'm trying to build some concurrency libraries 
>> <https://github.com/jackfirth/rebellion/issues/397> and I'd like to be sure 
>> there isn't some important use case I'm missing.
>> 
>> On Sat, Jan 18, 2020 at 1:14 AM Alexis King > <mailto:lexi.lam...@gmail.com>> wrote:
>> Like I said, it isn’t clear to me that all uses of `semaphore-wait` when 
>> breaks are enabled are incorrect. You could argue that then you should have 
>> a `semaphore-wait/trust-me-even-though-breaks-are-enabled`, and sure, I 
>> don’t think that would necessarily be bad. I just imagine the API just 
>> wasn’t originally designed that way for some reason or another, possibly 
>> simply because it wasn’t considered at the time. Maybe Matthew can give a 
>> more satisfying answer, but I don’t know; I’m just speculating.
>> 
>>> On Jan 18, 2020, at 03:10, Jack Firth >> <mailto:jackhfi...@gmail.com>> wrote:
>>> 
>>> I don't see how it has to do with semaphores being low-level. If waiting on 
>>> a semaphore while breaks are enabled is almost certainly wrong, checking 
>>> whether breaks are enabled and raising an error seems like a way more 
>>> sensible default behavior than just silently doing something that's almost 
>>> certainly wrong. If car and cdr can check their arguments by default, 
>>> shouldn't semaphores guard against misuse too?
>>> 
>>> On Sat, Jan 18, 2020 at 1:04 AM Alexis King >> <mailto:lexi.lam...@gmail.com>> wrote:
>>> It is guaranteed to leave the semaphore in a consistent state, from the 
>>> perspective of the implementation of semaphores. No matter what you do, you 
>>> won’t ever corrupt a semaphore (assuming you’re not using unsafe operations 
>>> and assuming the runtime is not buggy).
>>> 
>>

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
Actually, I change my mind, I can trivially think of a case where it’s fine: if 
you’re just using a semaphore as an event. One thread waits with 
`semaphore-wait`, another thread calls `semaphore-post`, and after the count is 
decremented, it’s never re-incremented. It’s just used to gate execution, not 
guard access to a resource. No need to disable breaks here.

(Also, an aside: I think your `car`/`cdr` example is different, because 
`car`/`cdr`’s checks on pairs guard against memory corruption in the Racket 
runtime, and Racket is a memory-safe language. A better comparison would be 
that `car`/`cdr` don’t check whether or not their argument is a proper list—the 
higher-level `first`/`rest` do that, instead.)

> On Jan 18, 2020, at 03:21, Jack Firth  wrote:
> 
> It isn't clear to me either. I can't think of a use case for it, but I'm 
> hoping either somebody else can or somebody can confirm that it's not a good 
> API precedent. I'm trying to build some concurrency libraries 
> <https://github.com/jackfirth/rebellion/issues/397> and I'd like to be sure 
> there isn't some important use case I'm missing.
> 
> On Sat, Jan 18, 2020 at 1:14 AM Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> Like I said, it isn’t clear to me that all uses of `semaphore-wait` when 
> breaks are enabled are incorrect. You could argue that then you should have a 
> `semaphore-wait/trust-me-even-though-breaks-are-enabled`, and sure, I don’t 
> think that would necessarily be bad. I just imagine the API just wasn’t 
> originally designed that way for some reason or another, possibly simply 
> because it wasn’t considered at the time. Maybe Matthew can give a more 
> satisfying answer, but I don’t know; I’m just speculating.
> 
>> On Jan 18, 2020, at 03:10, Jack Firth > <mailto:jackhfi...@gmail.com>> wrote:
>> 
>> I don't see how it has to do with semaphores being low-level. If waiting on 
>> a semaphore while breaks are enabled is almost certainly wrong, checking 
>> whether breaks are enabled and raising an error seems like a way more 
>> sensible default behavior than just silently doing something that's almost 
>> certainly wrong. If car and cdr can check their arguments by default, 
>> shouldn't semaphores guard against misuse too?
>> 
>> On Sat, Jan 18, 2020 at 1:04 AM Alexis King > <mailto:lexi.lam...@gmail.com>> wrote:
>> It is guaranteed to leave the semaphore in a consistent state, from the 
>> perspective of the implementation of semaphores. No matter what you do, you 
>> won’t ever corrupt a semaphore (assuming you’re not using unsafe operations 
>> and assuming the runtime is not buggy).
>> 
>> But perhaps you mean inconsistent from the point of view of the application, 
>> not from the point of view of the Racket runtime. In that case, it’s true 
>> that when using semaphores as locks, using them in a context where breaks 
>> are enabled is almost certainly wrong. It’s not immediately clear to me that 
>> there aren’t any valid uses of semaphores where you would want breaks to be 
>> enabled, but I admit, I have no idea what they are.
>> 
>> Semaphores are low-level primitives, though, so I think it makes some sense 
>> for them to just do the minimal possible thing. Perhaps a library ought to 
>> offer a slightly more specialized “critical section” abstraction a la 
>> Windows (or perhaps something like Haskell’s MVars) that manages disabling 
>> interrupts in the critical section for you. (Why doesn’t this exist already? 
>> My guess is that most Racket programmers don’t worry about these details, 
>> since they don’t call `break-thread` anywhere, and they want SIGINT to just 
>> kill their process, anyway.)
>> 
>>> On Jan 18, 2020, at 02:54, Jack Firth >> <mailto:jackhfi...@gmail.com>> wrote:
>>> 
>>> I do understand all of that, and you're right that "kill-safe" isn't what I 
>>> meant.
>>> 
>>> What I'm confused about is why, if it's inherently not guaranteed to leave 
>>> the semaphore in a consistent state, semaphore-wait attempts to work at all 
>>> if breaks are enabled. Why not raise some helpful error like "it's unsafe 
>>> to wait on a semaphore while breaks are enabled, did you forget to disable 
>>> breaks?". What's the actual use case for calling semaphore-wait (and not 
>>> semaphore-wait/enable-break) while breaks are enabled?
>>> 
>>> On Sat, Jan 18, 2020 at 12:47 AM Alexis King >> <mailto:lexi.lam...@gmail.com>> wrote:
>>> Killing a thread is different from breaking a thread. Killing a thread 
>>> kills the thread u

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
Like I said, it isn’t clear to me that all uses of `semaphore-wait` when breaks 
are enabled are incorrect. You could argue that then you should have a 
`semaphore-wait/trust-me-even-though-breaks-are-enabled`, and sure, I don’t 
think that would necessarily be bad. I just imagine the API just wasn’t 
originally designed that way for some reason or another, possibly simply 
because it wasn’t considered at the time. Maybe Matthew can give a more 
satisfying answer, but I don’t know; I’m just speculating.

> On Jan 18, 2020, at 03:10, Jack Firth  wrote:
> 
> I don't see how it has to do with semaphores being low-level. If waiting on a 
> semaphore while breaks are enabled is almost certainly wrong, checking 
> whether breaks are enabled and raising an error seems like a way more 
> sensible default behavior than just silently doing something that's almost 
> certainly wrong. If car and cdr can check their arguments by default, 
> shouldn't semaphores guard against misuse too?
> 
> On Sat, Jan 18, 2020 at 1:04 AM Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> It is guaranteed to leave the semaphore in a consistent state, from the 
> perspective of the implementation of semaphores. No matter what you do, you 
> won’t ever corrupt a semaphore (assuming you’re not using unsafe operations 
> and assuming the runtime is not buggy).
> 
> But perhaps you mean inconsistent from the point of view of the application, 
> not from the point of view of the Racket runtime. In that case, it’s true 
> that when using semaphores as locks, using them in a context where breaks are 
> enabled is almost certainly wrong. It’s not immediately clear to me that 
> there aren’t any valid uses of semaphores where you would want breaks to be 
> enabled, but I admit, I have no idea what they are.
> 
> Semaphores are low-level primitives, though, so I think it makes some sense 
> for them to just do the minimal possible thing. Perhaps a library ought to 
> offer a slightly more specialized “critical section” abstraction a la Windows 
> (or perhaps something like Haskell’s MVars) that manages disabling interrupts 
> in the critical section for you. (Why doesn’t this exist already? My guess is 
> that most Racket programmers don’t worry about these details, since they 
> don’t call `break-thread` anywhere, and they want SIGINT to just kill their 
> process, anyway.)
> 
>> On Jan 18, 2020, at 02:54, Jack Firth > <mailto:jackhfi...@gmail.com>> wrote:
>> 
>> I do understand all of that, and you're right that "kill-safe" isn't what I 
>> meant.
>> 
>> What I'm confused about is why, if it's inherently not guaranteed to leave 
>> the semaphore in a consistent state, semaphore-wait attempts to work at all 
>> if breaks are enabled. Why not raise some helpful error like "it's unsafe to 
>> wait on a semaphore while breaks are enabled, did you forget to disable 
>> breaks?". What's the actual use case for calling semaphore-wait (and not 
>> semaphore-wait/enable-break) while breaks are enabled?
>> 
>> On Sat, Jan 18, 2020 at 12:47 AM Alexis King > <mailto:lexi.lam...@gmail.com>> wrote:
>> Killing a thread is different from breaking a thread. Killing a thread kills 
>> the thread unrecoverably, and no cleanup actions are run. This usually isn’t 
>> what you want, but there’s always a tension between these kinds of things: 
>> defensive programmers ask “How do I make myself unkillable so I can safely 
>> clean up?” but then implementors of a dynamic environment (like, say, 
>> DrRacket) find themselves asking “How do I kill a runaway thread?” Assuming 
>> you’re not DrRacket, you usually want `break-thread`, not `kill-thread`.
>> 
>> But perhaps you know that already, and your question is just about breaking, 
>> so by “kill-safe” you mean “break-safe.” You ask why `semaphore-break` 
>> doesn’t just disable breaking, but that wouldn’t help with the problem the 
>> documentation alludes to. The problem is that there’s fundamentally a race 
>> condition in code like this:
>> 
>> (semaphore-wait sem)
>> ; do something important
>> (semaphore-post sem)
>> 
>> If this code is executed in a context where breaks are enabled, it’s not 
>> break-safe whether or not `semaphore-wait` were to disable breaks while 
>> waiting on the semaphore. As soon as `semaphore-wait` returns, the queued 
>> break would be delivered, the stack would unwind, and the matching 
>> `semaphore-post` call would never execute, potentially holding a lock 
>> forever. So the issue isn’t that the semaphore’s internal state gets somehow 
>> corrupted, but that the state no longer reflects the value

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
It is guaranteed to leave the semaphore in a consistent state, from the 
perspective of the implementation of semaphores. No matter what you do, you 
won’t ever corrupt a semaphore (assuming you’re not using unsafe operations and 
assuming the runtime is not buggy).

But perhaps you mean inconsistent from the point of view of the application, 
not from the point of view of the Racket runtime. In that case, it’s true that 
when using semaphores as locks, using them in a context where breaks are 
enabled is almost certainly wrong. It’s not immediately clear to me that there 
aren’t any valid uses of semaphores where you would want breaks to be enabled, 
but I admit, I have no idea what they are.

Semaphores are low-level primitives, though, so I think it makes some sense for 
them to just do the minimal possible thing. Perhaps a library ought to offer a 
slightly more specialized “critical section” abstraction a la Windows (or 
perhaps something like Haskell’s MVars) that manages disabling interrupts in 
the critical section for you. (Why doesn’t this exist already? My guess is that 
most Racket programmers don’t worry about these details, since they don’t call 
`break-thread` anywhere, and they want SIGINT to just kill their process, 
anyway.)

> On Jan 18, 2020, at 02:54, Jack Firth  wrote:
> 
> I do understand all of that, and you're right that "kill-safe" isn't what I 
> meant.
> 
> What I'm confused about is why, if it's inherently not guaranteed to leave 
> the semaphore in a consistent state, semaphore-wait attempts to work at all 
> if breaks are enabled. Why not raise some helpful error like "it's unsafe to 
> wait on a semaphore while breaks are enabled, did you forget to disable 
> breaks?". What's the actual use case for calling semaphore-wait (and not 
> semaphore-wait/enable-break) while breaks are enabled?
> 
> On Sat, Jan 18, 2020 at 12:47 AM Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> Killing a thread is different from breaking a thread. Killing a thread kills 
> the thread unrecoverably, and no cleanup actions are run. This usually isn’t 
> what you want, but there’s always a tension between these kinds of things: 
> defensive programmers ask “How do I make myself unkillable so I can safely 
> clean up?” but then implementors of a dynamic environment (like, say, 
> DrRacket) find themselves asking “How do I kill a runaway thread?” Assuming 
> you’re not DrRacket, you usually want `break-thread`, not `kill-thread`.
> 
> But perhaps you know that already, and your question is just about breaking, 
> so by “kill-safe” you mean “break-safe.” You ask why `semaphore-break` 
> doesn’t just disable breaking, but that wouldn’t help with the problem the 
> documentation alludes to. The problem is that there’s fundamentally a race 
> condition in code like this:
> 
> (semaphore-wait sem)
> ; do something important
> (semaphore-post sem)
> 
> If this code is executed in a context where breaks are enabled, it’s not 
> break-safe whether or not `semaphore-wait` were to disable breaks while 
> waiting on the semaphore. As soon as `semaphore-wait` returns, the queued 
> break would be delivered, the stack would unwind, and the matching 
> `semaphore-post` call would never execute, potentially holding a lock 
> forever. So the issue isn’t that the semaphore’s internal state gets somehow 
> corrupted, but that the state no longer reflects the value you want.
> 
> The right way to write that code is to disable breaks in the critical section:
> 
> (parameterize-break #f
>   (semaphore-wait sem)
>   ; do something important
>   (semaphore-post sem))
> 
> This eliminates the race condition, since a break cannot be delivered until 
> the `semaphore-post` executes (and synchronous, non-break exceptions can be 
> protected against via `dynamic-wind` or an exception handler). But this 
> creates a new problem, since if a break is delivered while the code is 
> blocked on the semaphore, it won’t be delivered until the semaphore is 
> posted/unlocked, which may be a very long time. You’d really rather just 
> break the thread, since it hasn’t entered the critical section yet, anyway.
> 
> This is what `semaphore-wait/enable-break` is for. You can think of it as a 
> version of `semaphore-wait` that re-enables breaks internally, inside its 
> implementation, and it installs an exception handler to ensure that if a 
> break is delivered at the worst possible moment (after the count has been 
> decremented but before breaks are disabled again), it reverses the change and 
> re-raises the break exception. (I have no idea if this is how it’s actually 
> implemented, but I think it’s an accurate model of its behavior.) This does 
> exactly what we want, since it ensures th

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Alexis King
Killing a thread is different from breaking a thread. Killing a thread kills 
the thread unrecoverably, and no cleanup actions are run. This usually isn’t 
what you want, but there’s always a tension between these kinds of things: 
defensive programmers ask “How do I make myself unkillable so I can safely 
clean up?” but then implementors of a dynamic environment (like, say, DrRacket) 
find themselves asking “How do I kill a runaway thread?” Assuming you’re not 
DrRacket, you usually want `break-thread`, not `kill-thread`.

But perhaps you know that already, and your question is just about breaking, so 
by “kill-safe” you mean “break-safe.” You ask why `semaphore-break` doesn’t 
just disable breaking, but that wouldn’t help with the problem the 
documentation alludes to. The problem is that there’s fundamentally a race 
condition in code like this:

(semaphore-wait sem)
; do something important
(semaphore-post sem)

If this code is executed in a context where breaks are enabled, it’s not 
break-safe whether or not `semaphore-wait` were to disable breaks while waiting 
on the semaphore. As soon as `semaphore-wait` returns, the queued break would 
be delivered, the stack would unwind, and the matching `semaphore-post` call 
would never execute, potentially holding a lock forever. So the issue isn’t 
that the semaphore’s internal state gets somehow corrupted, but that the state 
no longer reflects the value you want.

The right way to write that code is to disable breaks in the critical section:

(parameterize-break #f
  (semaphore-wait sem)
  ; do something important
  (semaphore-post sem))

This eliminates the race condition, since a break cannot be delivered until the 
`semaphore-post` executes (and synchronous, non-break exceptions can be 
protected against via `dynamic-wind` or an exception handler). But this creates 
a new problem, since if a break is delivered while the code is blocked on the 
semaphore, it won’t be delivered until the semaphore is posted/unlocked, which 
may be a very long time. You’d really rather just break the thread, since it 
hasn’t entered the critical section yet, anyway.

This is what `semaphore-wait/enable-break` is for. You can think of it as a 
version of `semaphore-wait` that re-enables breaks internally, inside its 
implementation, and it installs an exception handler to ensure that if a break 
is delivered at the worst possible moment (after the count has been decremented 
but before breaks are disabled again), it reverses the change and re-raises the 
break exception. (I have no idea if this is how it’s actually implemented, but 
I think it’s an accurate model of its behavior.) This does exactly what we 
want, since it ensures that if we do enter the critical section, breaks are 
disabled until we exit it, but we can still be interrupted if we’re blocked 
waiting to enter it.

So it’s not so much that there’s anything really special going on here, but 
more that break safety is inherently anti-modular where state is involved, and 
you can’t implement `semaphore-wait/enable-break`-like constructs if you only 
have access to the `semaphore-wait`-like sibling.

> On Jan 17, 2020, at 22:37, Jack Firth  wrote:
> 
> The docs for semaphores say this:
> 
> In general, it is impossible using only semaphore-wait to implement the 
> guarantee that either the semaphore is decremented or an exception is raised, 
> but not both. Racket therefore supplies semaphore-wait/enable-break (see 
> Semaphores), which does permit the implementation of such an exclusive 
> guarantee.
> 
> I understand the purpose of semaphore-wait/enable-break, but there's 
> something about semaphore-wait that confuses me: why does it allow breaking 
> at all? My understanding is that if breaks are enabled, semaphore-wait still 
> tries to block and decrement the counter, even though a break at any time 
> could destroy the integrity of the semaphore. Does that mean it's not 
> kill-safe to use a semaphore as a lock? Wouldn't it be safer if 
> semaphore-wait automatically disabled breaks while waiting?

-- 
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/DB641B34-F5E8-4512-B7AD-D421021B8631%40gmail.com.


Re: [racket-users] fcontrol and dynamic-wind

2019-11-30 Thread Alexis King
> On Nov 30, 2019, at 20:52, Matthew Flatt  wrote:
> 
> They are, as long as any invoked `dynamic-wind` thunks are safe in
> atomic mode. (After all, `unsafe-abort-current-continuation/no-wind`
> and `unsafe-call-with-composable-continuation/no-wind` were created to
> support `unsafe/try-atomic`.)

Alright, thanks, that does make sense. I think it’s still probably not the 
right solution, since the idea is that effect handlers ought to be 
implementable in user code, and I wouldn’t want to ask users to regularly 
interact with atomic mode. Maybe it can play a role in a safe abstraction, 
though.

Also, I realized shortly after I wrote my last email that I actually did see an 
effect system paper a while back that addressed these issues: “Algebraic Effect 
Handlers with Resources and Deep Finalization” by Daan Leijen. Looking at it 
again, it even cites Sitaram’s “Unwind-protect in portable Scheme” article I 
mentioned earlier! I may have forgotten about it because it appears to have 
only ever been released as a Microsoft Research technical report, not published 
at any academic conference. In any case, I didn’t really understand it when I 
first saw it, so I need to reread it more carefully, but an initial skim seems 
promising.

-- 
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/E6F8DAA0-8CF6-4745-B071-AAC1BFB3D880%40gmail.com.


Re: [racket-users] fcontrol and dynamic-wind

2019-11-30 Thread Alexis King
> On Nov 30, 2019, at 09:23, Matthew Flatt  wrote:
> 
> There's not a safe way. In many cases, Racket lets you write new things
> that have the power of built-in through unsafe APIs --- and it turns
> out that there are unadvertised procedures (provided by the primitive
> `#%unsafe` module) for this particular case:
> 
>  unsafe-abort-current-continuation/no-wind
>  unsafe-call-with-composable-continuation/no-wind

Thanks, those operations look helpful. I do worry a little bit that maybe they 
only solve the `dynamic-wind` problem, though, and don’t solve some other, 
related problems. For example, imagine I were to replace `dynamic-wind` with 
`parameterize-break`:

  (run-amb/first
(thunk
  (parameterize-break #f
(+ (amb 1 2) (amb 3 4)

Presumably, breaks would still be re-enabled and local exception handlers would 
be uninstalled during the handling of `amb`, even with the use of those unsafe 
operations, right? That seems wrong, too, since presumably the client would be 
surprised if a break were delivered inside the scope of `(parameterize-break #f 
_)`.

I think what it comes down to is I somehow want the ability to “atomically” 
insert some new continuation frames around the current prompt without 
uninstalling the current break state, exception handlers, continuation marks, 
and so on. I want to be able to go from

  E_1[(run-amb/first E_2[(amb e_1 e_2)])]

to

  E_1[(run-amb/first (or E_2[e_1] E_2[e_2]))]

in a single “step.” I guess I could resort to atomic mode, but that seems like 
a very heavy hammer, and I’m not even sure if continuation operations are safe 
in atomic mode. On the other hand, I don’t really know what a safe API for what 
I’m trying to do would look like.

> I don't know of any published work on this topic (so let me know if you
> find something!). As you probably have seen already, our ICFP'07 paper
> just points out that `dynamic-wind` causes problems, but doesn't try to
> hold `dynamic-wind` itself responsible for those problems.
> 
> An opinion and some pointers to newsgroup discussions:
> 
>  http://okmij.org/ftp/continuations/against-callcc.html#dynamic_wind
> 
> It would be interesting to check whether `dynamic-wind` is really
> needed in Racket libraries, at least in its current form. Most uses are
> really a "finally" mechanism that could be tied to explicit escapes
> like exceptions, instead of imposed for all continuation jumps. Maybe
> the uses that don't fit that pattern would be better expressed with
> another mechanism. Maybe the guarantees on `dynamic-wind` just need to
> be weakened and the `/no-wind` variants declared "safe" by defining
> away the unsafety.

Yes, most of the relevant discussions I’ve found have been about Lisp’s 
`unwind-protect` and how it relates to Scheme’s `dynamic-wind`. It’s alluded to 
in Matthias’s original POPL ’88 paper and mentioned explicitly in the following 
LASC paper, but neither address this particular issue. I also found Dorai 
Sitaram’s “Unwind-protect in portable Scheme”[1] and the related commentary by 
Kent Pitman[2] and Will Clinger[3], but though obviously related, both Sitaram 
and Clinger seem to imagine a system where the author of the program defines 
all control operations, so there isn’t as much of a problem. I’ve also been 
trying to find if any of these issues are discussed in any algebraic effects 
literature, but I haven’t found anything there yet, either.

[1]: http://www.ccs.neu.edu/~dorai/uwcallcc/uwcallcc.html
[2]: 
http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-overview.html
[3]: http://www.ccs.neu.edu/home/will/UWESC/uwesc.sch

-- 
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/AE70AFAC-89FA-4260-A8AE-6726A1AFE261%40gmail.com.


[racket-users] fcontrol and dynamic-wind

2019-11-30 Thread Alexis King
Hello,

I have been playing with implementing algebraic effects using delimited 
control, and Dorai Sitaram’s `fcontrol` and `%` operators are a natural fit. 
For example, it’s straightforward to implement McCarthy’s `amb` operator using 
them:

  (define amb-tag (make-continuation-prompt-tag 'amb))

  ; -> none/c
  (define (fail) (fcontrol 'fail #:tag amb-tag))
  ; -> boolean?
  (define (choice) (fcontrol 'choice #:tag amb-tag))

  (define-syntax amb
(syntax-rules ()
  [(_)  (fail)]
  [(_ e)e]
  [(_ e0 e ...) (if (choice) e0 (amb e ...))]))

The whole point of algebraic effect handlers is that we can interpret the same 
effect multiple ways, and `%` makes that easy. For example, we can write one 
`amb` handler that returns only the first result and another one that returns 
all results:

  (define (run-amb/first proc)
(% (proc)
   (λ (op k)
 (match op
   ['fail   #f]
   ['choice (or (run-amb/first (thunk (k #t)))
(run-amb/first (thunk (k #f]))
   #:tag amb-tag))

  (define (run-amb/all proc)
(let go ([proc (thunk (list (proc)))])
  (% (proc)
 (λ (op k)
   (match op
 ['fail   '()]
 ['choice (append (go (thunk (k #t)))
  (go (thunk (k #f]))
 #:tag amb-tag)))

This mostly works nicely, but the way it interacts with `dynamic-wind` leaves 
something to be desired:

  > (run-amb/first
  (thunk
(dynamic-wind
  (thunk (displayln "--> in"))
  (thunk (+ (amb 1 2) (amb 3 4)))
  (thunk (displayln "<-- out")
  --> in
  <-- out
  --> in
  <-- out
  --> in
  <-- out
  4

This is a little bit silly, since control is jumping out of the extent of 
`dynamic-wind` only to immediately re-enter it. If `dynamic-wind` is being used 
to guard access to a lock or pooled resource, we probably don’t want it to be 
released and reacquired on every call to `amb`.

However, I’m not sure how I can rearrange things to make that possible. I can’t 
just store the current `amb` handler in a parameter/continuation mark because 
it really does need to extend the continuation of the whole computation. Is 
there any way to do that with Racket’s continuation machinery, or would I need 
to use mutable state to imperatively extend a list of continuations maintained 
by the current handler? Also, is this kind of thing discussed anywhere in the 
literature?

Thanks,
Alexis

-- 
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/9EEF26EF-C60C-49B7-92D4-27648C111213%40gmail.com.


Re: [racket-users] GUI (get-directory)

2019-11-21 Thread Alexis King
> On Nov 21, 2019, at 11:21, James Platt  wrote:
> 
> If we can direct more of the energy of this community into, not just 
> improving the documentation, but the way we do documentation, it would be a 
> major improvement.  Requiring lots of parentheses doesn't bother me.  Lack of 
> infix notation doesn't bother me.  Lack of documentation does.

Every so often I see this sentiment expressed, and I’ll be entirely honest: I 
find it very surprising! I don’t at all want to suggest your experiences are 
untrue, or that they’re somehow your fault or not worth fixing, but they’re so 
contrary to my own that I must be missing something. I would go so far as to 
say that my experience with Racket’s documentation is far and away the best of 
every programming language I have ever used, even without adjusting for its 
comparatively small community.

I will concede that racket/draw and racket/gui are particularly sparse in the 
way of inline examples—perhaps something about the amount of context setup 
often necessary—but as the main distribution goes, that feels more like an 
exception than the norm! If you pick any section in the Datatypes chapter of 
the Racket Reference, for example, virtually every binding has typeset examples 
(using the scribble/example library you mention). Sections with fewer inline 
examples usually at least have links to example-heavy companion sections in the 
Guide. Even a library like pict, which is visual in the same way racket/draw 
and racket/gui are, has typeset examples for nearly every documented export.

I agree that it would be nice to make contributing small documentation 
improvements more accessible, but your wording seems to suggest you feel there 
is a deeper, systemic problem with the existing documentation. Could you say 
more on what that is? Or, maybe better yet, could you point to some other 
language’s documentation that you feel does things better that we might take 
inspiration from? I, at least, would find that extremely helpful to understand 
what steps Racket could take to do better.

-- 
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/12BB5A99-B6AD-4474-AFC8-4AA66D47E52E%40gmail.com.


Re: [racket-users] Custom scribble renderers and xref information

2019-11-17 Thread Alexis King
Thanks for the prompt reply!

> On Nov 17, 2019, at 11:15, Matthew Flatt  wrote:
> 
> Making mutual references work is the job of info-in and info-out files.
> Document A's info-out file is the info-in file for any document that
> needs to reference document A. Yes, you have to run to a fixed point
> where none of the info-out/info-in files change. That requires a fancy
> `make` rule, indeed. :)

Yes, perhaps I’ll try to avoid the need for recursive references for now. :) I 
do have two related followup questions, though. First, how does `raco setup` 
know what the dependencies are in the first place, so it knows what it needs to 
rerender? I’ve noticed it seems to do things in at least two passes—“running” 
the documentation before “rendering” it—is that somehow involved?

Second, I’d like to better understand how “tag prefixes” work, since they seem 
to be the mechanism by which tags from different documents are distinguished. 
What I don’t really understand is what the resolution logic actually is or 
where it happens. The documentation on tags says this:

> The prefix is used for reference outside the part, including the use of tags 
> in the part’s tags field. Typically, a document’s main part has a tag prefix 
> that applies to the whole document; references to sections and defined terms 
> within the document from other documents must include the prefix, while 
> references within the same document omit the prefix.


What part of the pipeline implements this prefix-sensitive lookup behavior? Is 
it the `resolve-get` family of functions, so I can just put things in the 
`tag-prefixes` field of a `part` during the collect phase and everything else 
will happen automatically? Or do I need to do something more myself? Also, I 
don’t completely understand the way the resolution works… is it possible for 
there to be some kind of “ambiguous match,” where two different tag definitions 
are equally-specific matches for a given reference? If so, what happens in that 
scenario? (And if not, why not?)

-- 
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/3C4C998F-F21B-46A0-909B-00598ADF3CEE%40gmail.com.


[racket-users] Custom scribble renderers and xref information

2019-11-17 Thread Alexis King
I’ve been playing on and off with writing a custom scribble renderer for a 
blog, and my experiments have mostly been fine, but I am very confused about 
xref information. I want to use a URL fragment format for my blog that is 
different from the one used by the Racket documentation, but I would also like 
to be able to generate external links to the Racket documentation. My first 
idea was to use `resolve-get/ext?` to see if a reference was external and 
handle it differently, but I soon realized I have no idea what “external” means 
there.

Initially, I assumed that if I called `render` from `scribble/render` with 
multiple parts in the `docs` argument, references between the parts would be 
considered external. However, this does not appear to be the case. On the other 
hand, if I reference something in The Racket Reference and I pass `#:xrefs 
(list (load-collections-xref))`, those references are considered external. 
Strictly speaking, that is what I want, so I am not unhappy with the result, 
but that discovery led me to other questions:

I probably want each of my blog posts to be its own “document,” since they 
should have their own namespace of tags, but passing multiple values to 
`render` seems to use one namespace. I interpret that to mean that I should be 
doing something else, but in that case, I don’t think I know how to properly 
set up a context where two posts can recursively reference one another. Do I 
need to invoke `traverse`/`collect`/`resolve`/`render` manually?

To generate links to the Racket documentation with the right fragment format, 
should I use `xref-tag->path+anchor`, using the default value for `#:render` to 
use the built-in HTML renderer? And does it make sense to override 
`collect-part-tags`/`collect-target-element` to use my own collect info format 
so I can distinguish references to my blog posts from references to the Racket 
docs?

I would like to avoid re-rendering every single one of my blog posts when just 
one of them changes, which seems possible, since `raco setup` appears to do 
dependency tracking. However, I wouldn’t know where to begin if I wanted to do 
that dependency tracking myself.

I took a look at the code for the part of `raco setup` that renders scribble 
documentation, but it seems to do a lot of work, and I don’t really understand 
it. That said, I’m guessing I don’t actually need something nearly that 
complicated. I’m mostly just interested in understanding how the pieces fit 
together. Is the idea that I could use `#:info-out-file` to serialize 
information about provided tags to disk, then just use GNU Make or something 
similar to track a dependency on those serialized xref files and pass them to 
`#:info-in-file`? And if I wanted to have mutually recursive documents, would I 
need to run them until reaching a fixpoint?

Thanks,
Alexis

-- 
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/E77B36F9-65E5-4922-AB34-3FE0ECE3689C%40gmail.com.


Re: [racket-users] Modeling a context-sensitive evaluation context with PLT Redex?

2019-11-09 Thread Alexis King
> On Nov 9, 2019, at 09:18, Jay McCarthy  wrote:
> 
> "remember that an evaluation context is just a way of describing more
> succinctly what you could otherwise define by hand as a big,
> complicated relation on individual terms."

Yes, that makes sense — I wasn’t really considering what it would look like to 
define these rules without evaluation contexts until you mentioned that in your 
first email. They’re a very nice way of thinking about these things, though! 
I’m not sure if it is worth it to me right now to go to the effort to define 
the “big, complicated relation” in this particular case just to get an 
executable version of the rules I’ve written down with pen and paper, but maybe 
it would be a good exercise; I don’t know.

> There is nothing special about evaluation contexts. I think they are
> beautiful, but they don't, for example, automatically come with a set
> of free theorems, like monads. The best thing they have going for them
> is that they decouple the specification of evaluation rules and where
> those rules occur (i.e. there are no "congruence" rules in the
> reduction relation.) But, a reduction system can always have extra
> rules that don't use them, so you don't get anything "for free". It is
> possible that the thing you want can't be done using contexts, but
> that doesn't mean redex or even redex's reduction-relation is wrong
> tool to use.
> 
> That said, I don't think the idea of a "first-class" context or
> evaluation rule makes sense, because the whole point of a proof theory
> is to have a fixed set of proof schemas which you can reason about. If
> you want to take term data and turn that into new rule cases, then
> you'll have to have a more general rule that inspects the term data
> and acts on it. For example, if you wanted your term data to be able
> to cause evaluation anywhere, then one technique would be to by
> default have evaluation happen everywhere, but then the evaluation
> rule will inspect the context to see if evaluation is enabled in any
> specific case. I think that makes sense from an implementation
> perspective too.

I should be clear: the main reason I decided to think about this in terms of 
reduction rules defined using evaluation contexts in the first place is because 
I didn’t even know what I thought the system I was trying to build ought to do 
in the edge cases. Writing down rules in terms of evaluation contexts has been 
an exercise in figuring out what I think the system I’m building means, and 
specifically, it is an attempt to find a system that reflects the equational 
reasoning rules I already intuitively believe ought to hold. From that 
perspective, the “expressive power” of evaluation contexts is precisely what 
appeals to me — it makes it easier to sketch out variations on the rules I have 
and see how they interact with one another.

I don’t think the set of rules I have is directly useful for either proving 
things about my effect system or actually practically implementing it. I just 
don’t know how to express some of the more complicated interactions I’m 
thinking about (such as, for example, distributivity of the continuation over 
nondeterministic choice) more clearly and simply than with evaluation contexts. 
If the takeaway here is that I am better served doing that with pen and paper, 
and maybe putting something in Redex once I have a firmer grasp on what I 
actually want to model, that’s fine; it’s helpful to know.

> Maybe not useful, but I believe that delimited control was really made
> by Matthias to solve the same problem as algebraic effects are solving
> today. Read his papers again in that light and it may be helpful.

Thanks, I will certainly do so. I read a couple of them several years ago when 
I was first learning about delimited control, but I think you’re right I would 
benefit from looking at them again. (Algebraic effects are appealing to me not 
because of their expressive power necessarily but because of certain 
implementation advantages, especially in a typed setting, but it is quite clear 
that they have an intimate relationship with delimited control. I could do to 
be more familiar with that literature.)

Alexis

-- 
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/D19B5D53-7D2B-4513-820C-989F57B0727C%40gmail.com.


Re: [racket-users] Modeling a context-sensitive evaluation context with PLT Redex?

2019-11-09 Thread Alexis King
;-less contexts.) Chapter 8 of
> SEwPR [1] covers this kind of thing. The delimited control example has
> more complicated things like this too [2] but it might be too
> complicated to understand just this piece of it. Another example to
> look at is the context-based semantics of call-by-need. Stephen's ESOP
> 2012 paper [3] is a great place to look because it talks about a
> standard old way and a clever new way, and is very readable, the key
> is a rule like: "(\x. E[x]) v -> (\x. E[v]) v" where the terms in the
> reduction relation don't use contexts only on the outside.
> 
> I don't really understand what you're trying to do, but it may be
> possible to have a LHSes like
> 
> PhiContext [ GammaContext [ (gamma f v ExprContext [ (f e) ]) ] ]
> 
> to get what you want
> 
> Jay
> 
> 1. https://redex.racket-lang.org/sewpr-toc.html
> 2. 
> https://github.com/racket/redex/tree/master/redex-examples/redex/examples/delim-cont
> 3. http://www.ccs.neu.edu/home/stchang/pubs/Chang-Felleisen-ESOP2012.pdf
> 
> --
> Jay McCarthy
> Associate Professor @ CS @ UMass Lowell
> http://jeapostrophe.github.io
> Vincit qui se vincit.
> 
> 
> --
> Jay McCarthy
> Associate Professor @ CS @ UMass Lowell
> http://jeapostrophe.github.io
> Vincit qui se vincit.
> 
> 
> On Sat, Nov 9, 2019 at 4:10 AM Alexis King  wrote:
>> 
>> Hello,
>> 
>> I am trying to model a (not quite algebraic) effect system in PLT Redex, but 
>> I’m struggling to encode my evaluation contexts into Redex’s pattern 
>> language. My question is best explained via example, so I’ll start with a 
>> bog-standard call-by-value lambda calculus:
>> 
>>(define-language lam
>>  [v ::= boolean (λ x e)]
>>  [e ::= x v (e e) (if e e e)]
>>  [E ::= hole (E e) (v E) (if E e e)]
>>  [x ::= variable-not-otherwise-mentioned]
>>  #:binding-forms
>>  (λ x e #:refers-to x))
>> 
>> My reduction relation for lam is the usual one. Next, I define an extended 
>> language:
>> 
>>(define-extended-language eff lam
>>  [e ::=  (ψ x e) (γ (x p ...) e) (x e ...)]
>>  [E ::=  (ψ x E) (γ (x p ...) E)]
>>  [p ::= :v :e :E]
>>  #:binding-forms
>>  (ψ x e #:refers-to x))
>> 
>> This is a severe simplification of the actual language I’m trying to model, 
>> but it’s enough to illustrate my problem: the definition for E I’ve given 
>> above is inadequate. What I actually want is to have some kind of 
>> “dynamic”/“context-sensitive” evaluation context, where γ can introduce 
>> scoped evaluation rules for identifiers bound by ψ.
>> 
>> To give an example, if I have the expression
>> 
>>(ψ f
>>  (γ (f :E :e)
>>(f (if #t #f #t) (if #t #f #t
>> 
>> I would like it to reduce to
>> 
>>(ψ f
>>  (γ (f :E :e)
>>(f #f (if #t #f #t
>> 
>> because (γ (f :E :e) e_1) effectively extends E with a new production rule 
>> (f E e) inside e_1, allowing reduction to recur into the first argument to 
>> f, but not the second.
>> 
>> If I were to define these rules on pen and paper, without using Redex, my 
>> instinct would be to create some kind of “parameterized” evaluation context. 
>> That is, I would define something like this:
>> 
>>r ::= (x p ...)
>> 
>>(E r ...) ::=
>>  hole ((E r ...) e) (v (E r ...)) (if (E r ...) e e)
>>  (ψ x (E r ...)) (γ r_0 (E r_0 r ...))
>>  (E-r r r ...) ...
>> 
>>(E-r (x p ...) r ...) ::= (x (E-p p r ...) ...)
>> 
>>(E-p :v _ ...) ::= v
>>(E-p :e _ ...) ::= e
>>(E-p :E r ...) ::= (E r ...)
>> 
>> Though a little complicated to define, I think decomposition using these 
>> evaluation contexts is still entirely syntax-directed (assuming the r 
>> arguments are only used as inputs; i.e. E, E-r, and E-p are “metapatterns”). 
>> Proving anything in this system seems like it could be a massive headache, 
>> but it’s much too soon for me to be worrying about that — I just want a 
>> super-flexible model I can throw some examples at to see what it does. Redex 
>> seems like it would be ideal for that, but I have no idea how to encode this 
>> kind of complicated decomposition into Redex’s pattern language.
>> 
>> I suspect that doing it directly is completely impossible, so I was 
>> wondering if there are any tricks or techniques I might use to encode it 
>> indirectly. Is there something clever I can do with a judgment form? I’ve 
>> been thinking about ways I might define my reduction relation inductively or 
>> something like that, but I really want to have access to the evaluation 
>> context (actually multiple evaluation contexts) in my reduction rules, since 
>> I’m using the language to define complicated control operators.
>> 
>> Thanks,
>> Alexis

-- 
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/1F0DAEA5-9BDD-40DA-BE95-08652781D9D8%40gmail.com.


[racket-users] Modeling a context-sensitive evaluation context with PLT Redex?

2019-11-09 Thread Alexis King
Hello,

I am trying to model a (not quite algebraic) effect system in PLT Redex, but 
I’m struggling to encode my evaluation contexts into Redex’s pattern language. 
My question is best explained via example, so I’ll start with a bog-standard 
call-by-value lambda calculus:

(define-language lam
  [v ::= boolean (λ x e)]
  [e ::= x v (e e) (if e e e)]
  [E ::= hole (E e) (v E) (if E e e)]
  [x ::= variable-not-otherwise-mentioned]
  #:binding-forms
  (λ x e #:refers-to x))

My reduction relation for lam is the usual one. Next, I define an extended 
language:

(define-extended-language eff lam
  [e ::=  (ψ x e) (γ (x p ...) e) (x e ...)]
  [E ::=  (ψ x E) (γ (x p ...) E)]
  [p ::= :v :e :E]
  #:binding-forms
  (ψ x e #:refers-to x))

This is a severe simplification of the actual language I’m trying to model, but 
it’s enough to illustrate my problem: the definition for E I’ve given above is 
inadequate. What I actually want is to have some kind of 
“dynamic”/“context-sensitive” evaluation context, where γ can introduce scoped 
evaluation rules for identifiers bound by ψ.

To give an example, if I have the expression

(ψ f
  (γ (f :E :e)
(f (if #t #f #t) (if #t #f #t

I would like it to reduce to

(ψ f
  (γ (f :E :e)
(f #f (if #t #f #t

because (γ (f :E :e) e_1) effectively extends E with a new production rule (f E 
e) inside e_1, allowing reduction to recur into the first argument to f, but 
not the second.

If I were to define these rules on pen and paper, without using Redex, my 
instinct would be to create some kind of “parameterized” evaluation context. 
That is, I would define something like this:

r ::= (x p ...)

(E r ...) ::=
  hole ((E r ...) e) (v (E r ...)) (if (E r ...) e e)
  (ψ x (E r ...)) (γ r_0 (E r_0 r ...))
  (E-r r r ...) ...

(E-r (x p ...) r ...) ::= (x (E-p p r ...) ...)

(E-p :v _ ...) ::= v
(E-p :e _ ...) ::= e
(E-p :E r ...) ::= (E r ...)

Though a little complicated to define, I think decomposition using these 
evaluation contexts is still entirely syntax-directed (assuming the r arguments 
are only used as inputs; i.e. E, E-r, and E-p are “metapatterns”). Proving 
anything in this system seems like it could be a massive headache, but it’s 
much too soon for me to be worrying about that — I just want a super-flexible 
model I can throw some examples at to see what it does. Redex seems like it 
would be ideal for that, but I have no idea how to encode this kind of 
complicated decomposition into Redex’s pattern language.

I suspect that doing it directly is completely impossible, so I was wondering 
if there are any tricks or techniques I might use to encode it indirectly. Is 
there something clever I can do with a judgment form? I’ve been thinking about 
ways I might define my reduction relation inductively or something like that, 
but I really want to have access to the evaluation context (actually multiple 
evaluation contexts) in my reduction rules, since I’m using the language to 
define complicated control operators.

Thanks,
Alexis

-- 
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/E7A24480-1E87-42AB-A580-33FB3A2B3C04%40gmail.com.


Re: [racket-users] Typed Racket needs annotation to realize (Mutable-HashTable Symbol Symbol) is of a more general type

2019-11-06 Thread Alexis King
The point Sam is making is about the variance of Mutable-HashTable 
specifically. Its relationship to the HashTable supertype is a red herring 
(which is why changing the type to Mutable-HashTable didn’t help).

Immutable data structures, like lists and immutable hash tables, are covariant 
in their type parameters. That means, for example,

a <: b  =>  (List a) <: (List b)

where “=>” means “implies” and “<:” means “is a subtype of.” The intuitive 
justification for this is that “a <: b” means “a value of type a can always be 
used in place of a value of type b.” For example, a list of integers can always 
be given to a function that expects a list of numbers.

This is not true of mutable data structures. Imagine you have bindings with the 
following types:

v : (Vectorof Integer)
f : (-> (Vectorof Number) Void)

Is (f v) well-typed? The answer is no. The reason is that f’s implementation 
could very well be the following:

(define (f x)
  (vector-set! x 0 0.5))

If (f v) were allowed, it would insert 0.5 into v, but v is supposed to only 
contain integers! (This is the “two-way communication channel” Sam was alluding 
to.) Therefore, (Vectorof Integer) cannot be a subtype of (Vectorof Number). We 
say Vectorof is *invariant* in its type parameter, since

(Vectorof a) <: (Vectorof b)  iff  a = b.

The same issue applies to mutable hashtables. If your DB type is defined to be 
(Mutable-HashTable (U Symbol Number) (U DB DBValue)), and you try to pass a 
value of type (Mutable-HashTable Symbol Integer), the typechecker rightly 
rejects your program, as Mutable-HashTable is invariant in its type parameters, 
so the two types must be precisely identical.

A solution to your problem is therefore to ensure the types really do match 
precisely. That is what the type annotation you wrote does: it forces the type 
to be identical to DB, overriding the type that was inferred. One might hope 
that TR’s type inference could be better here, but it’s a trickier case than it 
looks.

An aside: some typed languages support “bounded polymorphism” to give the 
programmer more fine-grained control over variance. For example, in Java, a 
function that accepts a Map can promise not to mutate it by giving the function 
a bounded type:

void f(Map m)

The question marks serve as “wildcards” that indicate f may be called with any 
Map where K <: Foo and V <: Bar. It is a compile-time error for f to 
attempt to add new elements to m, but it is perfectly fine for it to access 
elements. However, I don’t believe Typed Racket supports any form of bounded 
quantification or bounded polymorphism at the time of this writing, so 
functions in Typed Racket that operate on mutable data structures are forced to 
be invariant.

Alexis

> On Nov 6, 2019, at 01:53, Marc Kaufmann  wrote:
> 
> I assumed it was something to do with mutability, but I don't understand what 
> you mean when you say there is a two-way channel. The reference in typed 
> racket 
> (https://docs.racket-lang.org/ts-reference/type-ref.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fbase-types..rkt%29._.Hash.Table%29%29)
>  says this:
> 
> ```
> (HashTable k v)
> 
> is the type of a mutable or immutable hash table with key type k and value 
> type v.
> Example:
> > (make-hash '((a . 1) (b . 2)))
> - : (HashTable Symbol Integer) [more precisely: (Mutable-HashTable Symbol 
> Integer)]
> 
> '#hash((a . 1) (b . 2))
> 
> ```
> 
> That suggests to me that HashTable includes both Mutatable-HashTable and 
> Immutable-HashTable. The example given even states that the HashTable Symbol 
> Integer is more precisely of Mutable-HashTable Symbol Integer type - does 
> that *not* mean that (Mutable-HashTable Symbol Integer) is a subtype of 
> (HashTable Symbol Integer) in the reference example? 
> 
> I now tried to redefine DB as Mutable-HashTable to avoid this issue, but that 
> doesn't work either. It still doesn't accept `(make-hash (list (cons 
> 'study-type study-type)))` as something of type DB. How is (Mutable-HashTable 
> Symbol Symbol) not a subtype of DB, which is (Mutable-HashTable DBKey (U DB 
> DBValue)), and DBKey is (U Symbol ... ;other stuff) and same for DBValue?
> 
> You wrote that make-hash is of type `(Listof (Pairof Symbol Symbol))`. Is 
> there a way to expand and print the type of something in terms of primitive 
> types (well, or maybe step through one layer of abstraction) so that I could 
> play around with some toy examples to get a sense of what types are returned? 
> I am clearly confused by what type `make-hash` returns and what `hash-ref` 
> expects. 
> 
> Cheers,
> Marc
> 
> 
> On Tue, Nov 5, 2019 at 3:22 PM Sam Tobin-Hochstadt  
> wrote:
> The problem is that the `DB` type is _not_ a super-type of
> `(Mutable-HashTable Symbol Symbol)`, because mutable data structures
> are two way communications channels. If you used an immutable hash,
> that's a one-way communication and you would have the expected result.
> 
> However, the 

Re: [racket-users] Need a scribble identity wrapper. A no-op.

2019-11-03 Thread Alexis King
Use the search box in the documentation: 
https://docs.racket-lang.org/search/index.html?q=elem 


> On Nov 3, 2019, at 18:34, Hendrik Boom  wrote:
> 
> On Sun, Nov 03, 2019 at 02:46:42PM -0800, William J. Bowman wrote:
>> I think ‘elem’ will do what you want.
> 
> Indeed.  Thank you.  That works.
> 
> But I haven't been able to find where 'elem' is documented.
> 
> -- hendrik
> 
>> 
>> -- 
>> Sent from my phoneamajig
>> 
>>> On Nov 3, 2019, at 14:07, Hendrik Boom  wrote:
>>> 
>>> I've tried defining a function that reads a file, and then tries to 
>>> pass it back to be part of a scribble document.
>>> 
>>> Unfortunately, the list returned needs to be processed somehow before I 
>>> can return it.
>>> 
>>> Just returning the raw text results in complaints.  Apparently a list 
>>> of items needs to bave some kind of prefix or wrapper is if it to be 
>>> accepted.
>>> 
>>> I can get it to work by applying italic to it:
>>> 
>>> (define (include-here s)
>>> (let* ((in (open-input-file s))
>>>  (text (read-inside in))
>>>  )
>>>  (apply italic text)
>>> )
>>> )
>>> 
>>> This works just fine, except that I do not want italics.
>>> I really want not to specify a style at all.
>>> Is there some kind of wrapper that lets me do that?
>>> 
>>> I guess I need something like an identity wrapper.
>>> 
>>> -- hendrik
>>> 
>>> -- 
>>> 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/20191103220714.grt7v4tojaudvgmu%40topoi.pooq.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/20191104003409.j4pjzowlxng5lcje%40topoi.pooq.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/3BA83741-A2B0-4C9C-81B6-1F79E3E70FEE%40gmail.com.


Re: [racket-users] Does match against list traverse the whole list?

2019-10-29 Thread Alexis King
> On Oct 29, 2019, at 12:41, Christopher Lemmer Webber  
> wrote:
> 
> But the documentation says that the `list?` predicate is O(n).

I’m not sure where you’re seeing that, but the documentation actually says just 
the opposite. Specifically, it says this:

> This procedure effectively takes constant time due to internal caching (so 
> that any necessary traversals of pairs can in principle count as an extra 
> cost of allocating the pairs).

In other words, `list?` is amortized constant time.

-- 
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/4E904F54-3605-4964-AC19-EB6617A5D9F7%40gmail.com.


Re: [racket-users] eq? of quoted expressions

2019-10-25 Thread Alexis King
> On Oct 25, 2019, at 11:34, David Thrane Christiansen 
>  wrote:
> 
> I'm not sure why Guile returns #t for this. If pairs are mutable there, then 
> it could lead to aliasing problems.

The Scheme standard has historically left the behavior of mutation on quoted 
values unspecified to permit precisely this kind of implementation decision 
(but it does not require any particular behavior). I would imagine Guile makes 
quoted pairs immutable even if other pairs are mutable.

-- 
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/A0556DC5-5F2F-45B9-BB5F-BC6753EC2391%40gmail.com.


Re: [racket-users] eq? of quoted expressions

2019-10-25 Thread Alexis King
Unlike eq? on symbols, eq?’s behavior on quoted lists is unspecified, so I do 
not think there is a significantly deeper reason than “that isn’t what the 
current implementation chooses to do.” Whether the answer is #t or #f could 
change tomorrow, on a different VM, on a different architecture, or on Friday 
the 13th.

Is there a reason you would like the answer to be #t?

> On Oct 25, 2019, at 09:34, wanderley.guimar...@gmail.com wrote:
> 
> Why (eq? (quote a) (quote a)) is #t but (eq? (quote (a)) (quote (a)))
> is #f?  I would expect that if (quote (a)) was a mutable pair but it
> is not since (quote (a)) returns #f.  It seems that guile returns #t
> as I was expecting.

-- 
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/93BC7A92-F63C-4273-AB56-C001372DE93E%40gmail.com.


Re: [racket-users] Syntax pattern to match a sequence with x identical elements?

2019-10-13 Thread Alexis King
I think that error is a bug in syntax/parse. I have reported it here:

https://github.com/racket/racket/issues/2856 
<https://github.com/racket/racket/issues/2856>

> On Oct 12, 2019, at 21:45, Jonathan Simpson  wrote:
> 
> I'm not sure exactly why my syntax class wasn't working, but it is working 
> now. I had an extra set of parentheses around the ~between pattern, so it may 
> have been related to that. Whatever the case may be, the non-splicing syntax 
> class is working now.
> 
> I am very close to getting everything working but I am still having trouble 
> using ~between as part of a ~seq. Here's an example:
> 
> (syntax-parse #'(1 2 'bar 4 5 'bar 'foo) [((~seq (~between x:integer 2 2) ... 
> z) ...+ expr) #'foo])
> ; >: contract violation
> ;   expected: real?
> ;   given: #
> ;   argument position: 1st
> ;   other arguments...:
> ;0
> 
> I want to match one or more sequences of two integers and an expression, 
> finally ending in one final expression. This is a contrived example but 
> demonstrates how I'll eventually need to use ~between. The syntax error I'm 
> getting here isn't particularly enlightening.
> 
> Once again, I really appreciate any help here.
> 
> -- Jonathan
> 
> On Saturday, October 12, 2019 at 2:28:05 PM UTC-4, Alexis King wrote:
> I believe your two syntax classes are identical, except for the fact that the 
> splicing variant will not be allowed as a single term pattern. Therefore, I 
> don’t think there’s ever any reason to prefer the splicing version.
> 
> I tried an example using your mag-lvl syntax class with ~between, and it 
> worked fine. This program successfully prints a list of length 3:
> 
> #lang racket
> 
> (require syntax/parse)
> 
> (define-syntax-class mag-lvl
>   (pattern ({~datum level})))
> 
> (syntax-parse #'((level) (level) (level))
>   [((~between lvls:mag-lvl 3 3) ...)
>(attribute lvls)])
> 
> So I’m not sure what problem you’re bumping into, and it’s not something I 
> can guess without knowing more information.
> 
>> On Oct 12, 2019, at 11:13, Jonathan Simpson gmail.com 
>> <http://gmail.com/>> wrote:
>> 
>> Regarding my custom syntax-class issue, I realize now that it is probably 
>> because ~between only accepts splicing syntax classes. So, I created one 
>> that matches my regular syntax class. I'm not 100 percent sure that these 
>> are interchangeable in my use case though:
>> 
>> (define-syntax-class mag-lvl
>> (pattern ({~datum level})))
>> 
>> (define-splicing-syntax-class mag-slvl
>> (pattern ({~datum level})))
>> 
>> Does anyone know if :mag-slvl is interchangeable with :mag-lvl in most uses? 
>> Are there cases where :mag-slvl won't work the way I expect it to. I'm not 
>> confident in my understanding of the differences between using head patterns 
>> and single term patterns.
>> 
>> -- Jonathan
>> 
>> On Friday, October 11, 2019 at 10:55:19 PM UTC-4, Jonathan Simpson wrote:
>> Thank you Alexis for the clear explanation. I now understand how to use 
>> ~between and it is working for me.
>> 
>> One small hitch I encountered is a custom syntax class I defined doesn't 
>> work in the ~between statement but works elsewhere within the same syntax 
>> pattern. This isn't a huge issue for me as I just copied the pattern in 
>> place of the syntax class but I am curious why the :integer syntax class 
>> works and my custom one doesn't.
>> 
>> Once again, thanks for taking the time to explain this!
>> 
>> -- Jonathan
>> 
>> On Thursday, October 10, 2019 at 11:17:53 PM UTC-4, Alexis King wrote:
>> tl;dr: You need to use an ellipsis, so your pattern should be ((~between 
>> x:integer 3 3) ...). A (much) more detailed explanation of why follows.
>> 
>> ~between is an ellipsis-head pattern. The most common ellipsis-head pattern, 
>> ~optional, also works as a plain head pattern, but ~between does not. What’s 
>> the difference?
>> 
>> Let’s start by answering what a head pattern is. The simplest kind of 
>> syntax/parse pattern is a single-term pattern, which (as the name implies) 
>> only matches a single syntax object at a time. Head patterns are special in 
>> that they can match zero or more consecutive syntax objects in the head of a 
>> list. What is the head of a list? Well, if you have a list like '(1 2 3 4), 
>> its head is the sequence of elements “1 2 3 4” and its tail is simply the 
>> empty list, '(). It’s possible to write the list '(1 2 3 4 . ()) to make 
>> that more explicit.
>> 
>> So when you have a head pattern like (~optional x:integ

Re: [racket-users] Syntax pattern to match a sequence with x identical elements?

2019-10-12 Thread Alexis King
I believe your two syntax classes are identical, except for the fact that the 
splicing variant will not be allowed as a single term pattern. Therefore, I 
don’t think there’s ever any reason to prefer the splicing version.

I tried an example using your mag-lvl syntax class with ~between, and it worked 
fine. This program successfully prints a list of length 3:

#lang racket

(require syntax/parse)

(define-syntax-class mag-lvl
  (pattern ({~datum level})))

(syntax-parse #'((level) (level) (level))
  [((~between lvls:mag-lvl 3 3) ...)
   (attribute lvls)])

So I’m not sure what problem you’re bumping into, and it’s not something I can 
guess without knowing more information.

> On Oct 12, 2019, at 11:13, Jonathan Simpson  wrote:
> 
> Regarding my custom syntax-class issue, I realize now that it is probably 
> because ~between only accepts splicing syntax classes. So, I created one that 
> matches my regular syntax class. I'm not 100 percent sure that these are 
> interchangeable in my use case though:
> 
> (define-syntax-class mag-lvl
> (pattern ({~datum level})))
> 
> (define-splicing-syntax-class mag-slvl
> (pattern ({~datum level})))
> 
> Does anyone know if :mag-slvl is interchangeable with :mag-lvl in most uses? 
> Are there cases where :mag-slvl won't work the way I expect it to. I'm not 
> confident in my understanding of the differences between using head patterns 
> and single term patterns.
> 
> -- Jonathan
> 
> On Friday, October 11, 2019 at 10:55:19 PM UTC-4, Jonathan Simpson wrote:
> Thank you Alexis for the clear explanation. I now understand how to use 
> ~between and it is working for me.
> 
> One small hitch I encountered is a custom syntax class I defined doesn't work 
> in the ~between statement but works elsewhere within the same syntax pattern. 
> This isn't a huge issue for me as I just copied the pattern in place of the 
> syntax class but I am curious why the :integer syntax class works and my 
> custom one doesn't.
> 
> Once again, thanks for taking the time to explain this!
> 
> -- Jonathan
> 
> On Thursday, October 10, 2019 at 11:17:53 PM UTC-4, Alexis King wrote:
> tl;dr: You need to use an ellipsis, so your pattern should be ((~between 
> x:integer 3 3) ...). A (much) more detailed explanation of why follows.
> 
> ~between is an ellipsis-head pattern. The most common ellipsis-head pattern, 
> ~optional, also works as a plain head pattern, but ~between does not. What’s 
> the difference?
> 
> Let’s start by answering what a head pattern is. The simplest kind of 
> syntax/parse pattern is a single-term pattern, which (as the name implies) 
> only matches a single syntax object at a time. Head patterns are special in 
> that they can match zero or more consecutive syntax objects in the head of a 
> list. What is the head of a list? Well, if you have a list like '(1 2 3 4), 
> its head is the sequence of elements “1 2 3 4” and its tail is simply the 
> empty list, '(). It’s possible to write the list '(1 2 3 4 . ()) to make that 
> more explicit.
> 
> So when you have a head pattern like (~optional x:integer), it might parse an 
> integer, but it also might parse nothing. In the latter case, the next head 
> pattern in the sequence would get a chance to parse the same element that 
> (~optional x:integer) did. Head patterns are able to do this because lists 
> introduce a kind of linear sequencing (not just tree-like nesting), so 
> “skipping” an element is an operation that makes sense.
> 
> But what about ellipsis-head patterns? These are patterns that don’t just 
> appear inside a list pattern, they appear inside a list pattern and under an 
> ellipsis. For example, in the pattern (x y ... z), x and z are head patterns, 
> but y is an ellipsis-head pattern. While head patterns introduce the ability 
> to consume one or more elements at a time, ellipsis-head patterns extend that 
> with the power to match elements in the list out of order. This is most 
> useful when parsing keyword options, such as in the following pattern:
> 
> ((~alt (~once (~seq #:foo foo:integer)) (~once (~seq #:bar bar:string))) 
> ...)
> 
> The above pattern will match (#:foo 1 #:bar "two") or (#:bar "two" #:foo 1), 
> but not (#:foo 1) or (#:foo 1 #:foo 2 #:bar "three"). This is because ~alt 
> introduces a set of alternatives that can be matched, but unlike a simple 
> ~or* pattern, it also keeps track of how many times each case matched, and 
> patterns like ~once, ~optional, and ~between introduce constraints on the 
> number of times a given case must match for the overall parse to be 
> successful.
> 
> Interestingly, note that pattern variables bound under ~once and ~optional 
> don’t have an ellipsis depth of 1, they 

Re: [racket-users] Syntax pattern to match a sequence with x identical elements?

2019-10-10 Thread Alexis King
tl;dr: You need to use an ellipsis, so your pattern should be ((~between 
x:integer 3 3) ...). A (much) more detailed explanation of why follows.

~between is an ellipsis-head pattern. The most common ellipsis-head pattern, 
~optional, also works as a plain head pattern, but ~between does not. What’s 
the difference?

Let’s start by answering what a head pattern is. The simplest kind of 
syntax/parse pattern is a single-term pattern, which (as the name implies) only 
matches a single syntax object at a time. Head patterns are special in that 
they can match zero or more consecutive syntax objects in the head of a list. 
What is the head of a list? Well, if you have a list like '(1 2 3 4), its head 
is the sequence of elements “1 2 3 4” and its tail is simply the empty list, 
'(). It’s possible to write the list '(1 2 3 4 . ()) to make that more explicit.

So when you have a head pattern like (~optional x:integer), it might parse an 
integer, but it also might parse nothing. In the latter case, the next head 
pattern in the sequence would get a chance to parse the same element that 
(~optional x:integer) did. Head patterns are able to do this because lists 
introduce a kind of linear sequencing (not just tree-like nesting), so 
“skipping” an element is an operation that makes sense.

But what about ellipsis-head patterns? These are patterns that don’t just 
appear inside a list pattern, they appear inside a list pattern and under an 
ellipsis. For example, in the pattern (x y ... z), x and z are head patterns, 
but y is an ellipsis-head pattern. While head patterns introduce the ability to 
consume one or more elements at a time, ellipsis-head patterns extend that with 
the power to match elements in the list out of order. This is most useful when 
parsing keyword options, such as in the following pattern:

((~alt (~once (~seq #:foo foo:integer)) (~once (~seq #:bar bar:string))) 
...)

The above pattern will match (#:foo 1 #:bar "two") or (#:bar "two" #:foo 1), 
but not (#:foo 1) or (#:foo 1 #:foo 2 #:bar "three"). This is because ~alt 
introduces a set of alternatives that can be matched, but unlike a simple ~or* 
pattern, it also keeps track of how many times each case matched, and patterns 
like ~once, ~optional, and ~between introduce constraints on the number of 
times a given case must match for the overall parse to be successful.

Interestingly, note that pattern variables bound under ~once and ~optional 
don’t have an ellipsis depth of 1, they have an ellipsis depth of 0. This is 
why, in the given example, you can refer to the foo and bar pattern variables 
in a template without any ellipses. ~between, however, still increments the 
ellipsis depth, since the pattern can actually match multiple times.

In the pattern I suggested at the beginning of this email, ((~between x:integer 
3 3) ...), you’re creating an ellipsis-head context with exactly one 
alternative: (~between x:integer 3 3). That is exactly what you want, so 
everything works out fine.

The one remaining question, however, is why ~between is only allowed as an 
ellipsis-head pattern, but ~optional is also allowed as a head pattern. I can’t 
say for certain, since you can think of ((~optional x:integer)) as being sort 
of implicitly expanded to ((~optional x:integer) ...), and the same could be 
done for ~between. However, my guess is that it isn’t allowed because ~between 
increments the ellipsis depth of its sub-pattern, and Ryan thought it would be 
confusing for a pattern variable’s ellipsis depth to be incremented despite 
there not actually being any ellipses in the pattern. Therefore, when using 
~between, you have to write the ellipsis explicitly.

Alexis

> On Oct 10, 2019, at 20:37, Jonathan Simpson  wrote:
> 
> This seems like it should be simple but I've never been able to figure out 
> how to do this. What I've been doing instead is this:
> 
> (x:integer ...+) to match two or more integers.
> 
> (x:integer y:integer ...+) to match three or more.
> 
> And so on.
> 
> I'm at a point now where I need to build patterns dynamically to match an 
> exact number of elements. I'd also like to avoid having to create unique 
> names for a bunch of pattern variables. ~between seems like what I want but I 
> haven't been able to get it to work. I've been using ~seq without issue but 
> that isn't exactly what I need.
> 
> Example of an attempt to use ~between:
> 
> (syntax-parse #'(1 1 1) [((~between x 3 3)) #'(x ...)])
> ; stdin::2631: syntax-parse: pattern keyword not allowed here
> ;   at: ~between
> 
> 
> Can anyone give me a quick example of how to do this, using ~between or 
> otherwise? I'm using syntax-parse, if that makes a difference.
> 
> Thanks!
> 
> -- Jonathan

-- 
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 

Re: [racket-users] read-eval-print-loop, #%top-interaction, and define

2019-09-24 Thread Alexis King
> On Sep 24, 2019, at 23:01, Jesse Alama  wrote:
> 
> The question is: we do we get the error with define if we know that step is 
> undefined? Shouldn't we learn, first, that step is undefined?


The top level is hopeless.

Unlike in a module, an unbound identifier at the top level is not a syntax 
error, as it might be a forward reference to a variable that is not yet defined 
(think mutually recursive functions). Therefore, the expander assumes that all 
unbound references at the top-level are variable references, and it expands 
(step e) like a function application applying the function `step` to the 
argument `e`. Function arguments are expressions, so when the expander goes to 
expand a definition in place of `e`, it raises an error.

Obviously, the assumption that `step` is a forward variable reference was wrong 
here, as it was intended to refer to a macro. But the expander can’t know that, 
so it silently does the wrong thing. This behavior of the top-level seems like 
a misfeature—I’d be happy if mutually-recursive functions needed to be grouped 
with a `begin` at the top level—but it’s historically how Scheme programmers 
have expected the REPL to behave, and that behavior was much more important 
prior to the introduction of the modern Racket module system.

Alexis

-- 
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/7D26C5BC-3010-40E7-9056-A6070CC22542%40gmail.com.


Re: [racket-users] Is it possible to sell commercial use rights to an open source Racket package?

2019-08-28 Thread Alexis King
> On Aug 28, 2019, at 11:54, Neil Van Dyke  wrote:
> 
> If someone violates (their non-lawyer interpretation of) the Racket license, 
> in a conspicuous manner like you suggest, would they not expect the SFC to 
> send them a nastygram -- perhaps if only for the SFC to show that they defend 
> the copyright, if not for other reasons?

You don’t have any risk of losing a copyright just because you don’t choose to 
enforce it; you’re thinking of trademark law. If a copyright holder chooses not 
to pursue legal action against a violator, they may do so, and it does not in 
any way prevent them pursuing action against them or someone else in the future.

That said, your following sentence is absolutely right: it doesn’t matter if 
the Racket core team chooses not to enforce their copyright if they are not the 
exclusive copyright holders, and as I have already opined, I believe they are 
not. Any copyright holder may pursue legal action against violations of their 
copyright if they so choose, whether they are members of the Racket core team, 
the SFC, or independent Racket contributors.

On the other hand, if I were Joel, I probably wouldn’t be losing sleep over the 
potentiality of a Racket contributor taking me to court over my infringement. 
As I said previously, I don’t know how much Racket code is still exclusively 
licensed under the LGPL, but I’d bet the large majority is now licensed under 
the MIT and Apache licenses as well. Unless Joel starts making millions off his 
project and some contributors come out of the woodwork to try and get a piece 
of that action, I doubt his assessment is incorrect… and if that happens, well, 
he can probably afford to pay them enough to negotiate a license with them.

Still, a calculated risk is still a risk. YMMV, IANAL, and obviously this is 
not qualified legal advice.

-- 
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/74B3531F-9A18-4F01-9A30-B5F5DB627EF8%40gmail.com.


Re: [racket-users] Is it possible to sell commercial use rights to an open source Racket package?

2019-08-23 Thread Alexis King
Thank you for the link. I read through it, along with the (much longer) blog 
post linked at the beginning. The first thing it made me realize is that I 
should be more clear: I am not advocating for a CLA! I agree with most of the 
arguments against them that both posts make.

All I was saying is that, given Racket does not have any form of copyright 
assignment agreement, as the blog post calls them, Racket as an organization 
does not possess the copyright to contributors’ code, and they do not control 
enforcement of that copyright. AFAICT, the linked blog post supports that 
(though it argues that’s a good thing, which I agree with, and it also makes an 
argument that a CLA doesn’t necessarily change that in a simple way, either, 
which was indeed news to me and was interesting to read).

I feel like I have reason to believe my interpretation is correct, as it isn’t 
entirely theoretical. In 2014, the developers of the popular, open-source 
Minecraft server modding framework, CraftBukkit, decided to retire the project 
after years of volunteer work. Mojang, Minecraft’s developer, announced they 
had secretly purchased ownership of the project from its co-founders years 
before when they had hired several of them to become Mojang employees, and they 
said would continue the project themselves. That upset several of the 
volunteers, as they realized Mojang had been knowingly exploiting their unpaid 
labor for years without offering any help. One of the developers of CraftBukkit 
proceeded to send Mojang a DMCA takedown request for his own source code, as 
CraftBukkit was GPL-licensed, and the whole project was technically illegal to 
begin with (since it modified and redistributed proprietary Minecraft source 
code).

Assuming the takedown request was legal (which is to say, assuming the 
developer really did hold the copyright), then to comply with it, Mojang would 
have needed to either release the Minecraft server code under the GPL, 
something they were clearly not about to do, or abandon CraftBukkit (or at 
least the parts of it that developer wrote). They chose the latter, despite 
surely having a perfectly capable legal team. Realistically, do I think any 
Racket contributors are going to start DMCAing projects in violation of the 
LGPL for parts of the Racket codebase they hold copyright on? No. But I don’t 
see why the situation would legally be any different for Racket than it was for 
CraftBukkit.

> On Aug 23, 2019, at 14:48, Matthew Butterick  wrote:
> 
> Bradley Kuhn, director of the SFC, has explained why FLOSS projects don't 
> need CLAs, along with some underlying legal truths about FLOSS contributions. 
> [1] 
> 
> [1] https://sfconservancy.org/blog/2014/jun/09/do-not-need-cla/ 
> <https://sfconservancy.org/blog/2014/jun/09/do-not-need-cla/>
> 
> 
>> On 23 Aug 19, at 12:29 PM, Alexis King > <mailto:lexi.lam...@gmail.com>> wrote:
>> 
>> Maybe so, but that is, in fact, why I sent the email. I was hoping you could 
>> clue me in as to what I was missing. (Maybe it’s unfair of me to ask you for 
>> free legal analysis, but I don’t feel like it’s all that unreasonable to ask 
>> for just a little clarification here.)
>> 
> 

-- 
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/897EB36B-EBAC-4013-92D1-54B58419856A%40gmail.com.


Re: [racket-users] Is it possible to sell commercial use rights to an open source Racket package?

2019-08-23 Thread Alexis King
> On Aug 23, 2019, at 14:19, Matthew Butterick  wrote:
> 
> You're omitting some key facts.

Maybe so, but that is, in fact, why I sent the email. I was hoping you could 
clue me in as to what I was missing. (Maybe it’s unfair of me to ask you for 
free legal analysis, but I don’t feel like it’s all that unreasonable to ask 
for just a little clarification here.)

-- 
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/EFE00069-B811-49A3-8FFF-C594A541A7B3%40gmail.com.


Re: [racket-users] Is it possible to sell commercial use rights to an open source Racket package?

2019-08-23 Thread Alexis King
> On Aug 23, 2019, at 13:03, Matthew Butterick  wrote:
> 
> In some cases, SFC takes ownership of trademarks and copyrights [1] which 
> means that in terms of license interpretation & enforcement, assumedly the 
> buck would now stop with them. 

AFAIK, copyright of the Racket codebase is not the Racket core team’s to give. 
Racket has no CLA, so its copyright belongs to all of the individual 
contributors, core team members or not. If the Racket core team did own the 
copyright, the relicensing effort would have amounted to little more than a 
decision. But as-is, whether the SFC takes ownership of copyrights held by the 
core team or not is irrelevant, as any individual Racket contributor could 
choose to enforce the terms of the license for their contributions should they 
desire. But I’m sure you knew all that already—you’re the lawyer—so I’m curious 
what you know that I don’t.

At any rate, I second your desire to know what the status of the relicensing 
effort actually is. Are we looking at three stragglers left on the list who 
still haven’t signed? A dozen? A hundred? And maybe more importantly, how many 
lines of code do they really own? At what point can we not just rewrite those 
portions of the codebase? I know that figuring out ownership can be tricky for 
long-running software projects like these, since the question of what 
constitutes derivative work from the original contribution is often unclear, 
but even just a ballpark estimate would be nice to know.

-- 
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/0DAEBB67-5E77-465B-AC5D-4E8EA1BAEB9E%40gmail.com.


Re: [racket-users] Is it possible to sell commercial use rights to an open source Racket package?

2019-08-23 Thread Alexis King
Disclaimer: I am not a lawyer. (But, as others have mentioned, the answer is 
yes.)

In the subject of your subject, you mention “an open source Racket package,” 
but in the body of your email, you talk about “an open source Racket project.” 
If you are genuinely talking about a Racket package (in the `raco pkg` sense, 
distributed as source code), then you are likely not distributing Racket, in 
which case you are not restricted by Racket’s license at all. You are free to 
license your package however you want, commercially or otherwise. You’re only 
bound to the terms of Racket’s license if you redistribute Racket itself.

If you are instead talking about a Racket application, distributed bundled with 
a Racket runtime or any Racket libraries (such as a bundle created with `raco 
distribute`), then you are beholden to the terms of the Racket license. You are 
likely required by the terms of the LGPL to make your application’s source 
files available to your users, as Racket’s ubiquitous use of macros generally 
precludes replacing library dependencies without recompiling their dependents. 
However, that does not force you to license your source files under the LGPL, 
only make them available under your commercial, proprietary license.

Distributing a closed-source, non-LGPL Racket application without violating 
Racket’s licensing terms is likely to be very difficult or impossible, pending 
the still-ongoing MIT + Apache 2 relicensing effort. But you already said your 
project is open source, anyway, so that doesn’t matter for you.

Alexis

P.S. I think the interpretation of the LGPL given in the page you linked is 
wrong, as it seems to assume that access to your bytecode files is sufficient 
to relink your application against modified versions of Racket. In the presence 
of macros (and, to a lesser extent, cross-module inlining), this is very often 
not true. However, there is scant legal precedent for the interpretation of the 
LGPL, so ultimately it’s hard to guess what a court would find convincing.

> On Aug 23, 2019, at 08:24, Sage Gerard  wrote:
> 
> --I believe this email was lost due to me not being subscribed to the list 
> last time I sent it. Sorry if this is a duplicate.
> 
> Has someone tried to release an open source Racket project under a license 
> that enforces paid commercial use of that project? Light Googling suggests 
> this would be antithetical to the LGPL if not open source in general, but 
> https://download.racket-lang.org/license.html 
>  says "the Racket license does 
> not restrict you at all."
> 
> I understand no replies here or any web page constitutes legal advice, so 
> please take my question in the spirit of respecting the LGPL's sublicensing 
> restrictions and learning what other people are doing to earn money 
> independently using Racket.
> 
> ~slg

-- 
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/8A9E4341-78EC-4ECD-B9E1-15197CEABEA8%40gmail.com.


Re: [racket-users] Re: on-boarding new racketeers

2019-08-13 Thread Alexis King
Oh, come on. “Adding labels to repositories” and “adding issue templates” isn’t 
“increasing lock-in.” There’s no slippery slope here. I think the time and 
energy Stephen has dedicated to the community should be thanked and 
appreciated, not discouraged. I’m frustrated by the number of words you spend 
on this list suggesting other people do or not do certain things while 
volunteering zero of your time yourself.

Yes, every platform has potential costs, some more than others. But GitHub in 
particular has provided the open source community[1] immeasurable value with 
few meaningful costs, and that does not currently seem likely to change under 
Microsoft. I don’t think taking advantage of their exceptionally useful service 
is the same as thinking they are “our friend,” nor does allowing themselves to 
be purchased by someone with sufficient capital to continue providing those 
services for free instantly make them our enemy. There is no evidence that 
Microsoft is embracing open source software only to extend and exterminate it. 
Please preach elsewhere.

Alexis

[1]: Perhaps not the free software community, but Racket isn’t free software, 
so that’s hardly on topic.

> On Aug 13, 2019, at 12:28, Neil Van Dyke  wrote:
> 
> I know this particular one is a minor thing, but they add up, over time...
> 
> Please consider approaches that are open, rather than owned, and try not to 
> increase lock-in by big-business plays.
> 
> It's pragmatic to keep using GitHub in limited ways right now, *but* part of 
> that is being judicious about creeping lock-in, which is a pattern we've seen 
> for decades (and the current owner of GitHub has been one of the most epic 
> abusers).
> 
> To use GitHub as an example, though this is not specific to them: They are 
> not your friend.  They used to seem like your friend, but that friendship was 
> worth fewer than 7.5 billion dollars.
> 
> When you effectively partner with such a company, approach it as an temporary 
> alliance, limit their power over you, and keep trying to increase your 
> options/freedom.
> 
> Also, consider what you're promoting, especially to impressionable students 
> around Racket.  Every use is effectively you endorsing something questionable.
> 
> Maybe it's time to poke the Conservancy.  It should be on their radar by now, 
> and some of the solution applies to all projects.
> 
> (I suggested wait on moving the repos from GitHub, partly since it's 
> unclear which competitors will sell out next for GitHub/Slack/etc.-type 
> lock-in billions.  And I don't have time to see which non-profit ones are 
> just an old PC under someone's dorm bed, and will disappear as soon as that 
> person gets a job.  The Conservancy is in a better position to investigate, 
> and to audit/fund to make sure whatever project has sustainable funding. In 
> the meantime, that doesn't mean we have to keep increasing our non-repo 
> feature dependence, and make it harder to move once we have a chance.)

-- 
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/BD6A4F3B-EE9F-4C88-B014-E59337E69942%40gmail.com.


Re: [racket-users] Racket2 possibilities

2019-07-22 Thread Alexis King
> On Jul 22, 2019, at 14:16, Dexter Lagan  wrote:
> 
> A parens-less Racket2 would become Crystal.


No it won’t. I am quite confident that Racket with any syntax will not be like 
any other language that currently exists. What other language has Racket’s 
advanced, robust compile-time metaprogramming support, its higher-order 
contract system, its #lang mechanism (applied to great effect in technologies 
like Scribble and Typed Racket), its language-as-an-operating-system support 
for runtime sandboxing and introspection, and its featureful and extensible 
FFI, among many other things? To say that Racket is so defined by its syntax 
that it will cease to be distinguishable from any other language if it is 
changed is absurd, and it’s frankly insulting to all the people who have put so 
much effort into every part of Racket.

If you believe Racket’s syntax is its most important feature, and that 
everything else that sets it apart from other languages is pragmatically 
irrelevant, I can’t really argue with that. I disagree, but it’s a matter of 
opinion. That said, that kind of criticism isn’t very constructive, since I 
don’t know how to interpret it beyond “I really like parentheses,” which is 
hardly actionable or debatable.

I make no claims of representing the will of PLT, so I could be wrong, but I 
think discussing what about s-expressions you like—and what about other 
syntaxes you dislike—is on-topic and can produce constructive discussion. But 
although it’s possible I didn’t read it carefully enough, the link you provided 
doesn’t seem to have much in the way of that sort of explanation… it seems to 
focus on how to most usefully take advantage of s-expressions, but it doesn’t 
compare them to other formats.

-- 
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/9AA3072F-1688-4424-B911-3C0190622661%40gmail.com.


Re: [racket-users] Racket2 possibilities

2019-07-21 Thread Alexis King
> On Jul 21, 2019, at 00:19, Matthew Flatt  wrote:
> 
> I have in mind "Honu: Syntactic Extension for Algebraic Notation through 
> Enforestation", GPCE 2012. It shows how we can bridge the relatively linear 
> structure of non-() programs to the tree structure of S-expressions. 
> Specifically, the bridge is called "enforestation". It sits roughly between 
> the reader and the expander, but enforestation needs to be interleaved with 
> expansion to get the level of expressiveness that Racketeers would expect.

To add a few of my own thoughts on this: in light of recent events, I reread 
the Honu paper more closely this past week, and I would strongly encourage 
anyone who is invested in surface syntax to do the same. It is a beautiful 
paper. Crucially, it is beautiful not because it does anything complex but 
because it solves a hard problem in a simple, elegant way. If you have any 
misgivings about what might happen to the expressiveness of the macro system if 
we were to move away from s-expressions, it is required reading.

What the paper does not do is editorialize (as it shouldn’t), so I will do so 
myself. The techniques described in the Honu paper are dramatically superior to 
alternative approaches I have seen, for two reasons:

“Automatic parenthesis insertion” approaches like sweet, wisp, liso, etc. 
invariably demand users think about the desugared, parenthesized form. Macros 
are ultimately still defined by parsing syntax objects built from 
s-expressions, so every extra pair of parentheses suddenly matters, even if 
they’re invisible and no reasonable built-for-purpose syntax would care about 
them. This is a terrible experience, and it forever condemns these approaches 
to be second-class citizens.

Honu’s macros, in contrast, operate much closer to the concrete syntax, and 
they don’t require thinking about implementation details of the language. We 
demand our Racket macros be real abstractions, and Honu lets them stay that way.

It is easy to foresee a transition away from s-expressions as a restriction on 
what can be expressed via macros, mostly since non-s-expression languages with 
macro systems (such as Haskell and Elixir, to name just two) usually impose 
such restrictions. But that is what is so remarkable about Honu: its macros 
allow what is really a superset of Racket’s current syntactic flexibility. I 
think the paper has a good explanation of why this is, I just don’t think it 
points out the implications explicitly enough, so if this is a surprise to you, 
go back and take another look.

Of course, it’s not all roses. The existing Honu implementation lays sturdy 
foundations, but it doesn’t include a syntax/parse equivalent: there’s no 
Honu-native DSL for writing Honu macros. A lot of the ideas in syntax/parse 
should carry over, but there are more than a few new wrinkles to be ironed out. 
On top of that, there are open questions about everything from documentation to 
tooling to what the appropriate syntax for the base language ought to be.

I understand that many people in the Racket sphere are very fond of 
s-expressions for a variety of reasons, something that was made abundantly 
clear to me in the several dozen replies I got to a twitter comment I made on 
the matter.  I 
certainly can’t assuage all fears of losing them, but I sincerely hope that the 
second point I made above sinks in for others like it has for me: there are 
ways a change in syntax can be enabling, not simply a compromise for some 
non-specific “other people.” Wouldn’t it be wonderful if we could design new 
languages, embedded or otherwise, with whatever syntax we wish as easily as we 
can design them in Racket today using s-expressions? Going down this path has 
the potential to move us much closer to that reality, and I, for one, think 
that’s exciting.
 

-- 
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/FE3BEE8D-4380-4540-B478-F0BB424A5C4E%40gmail.com.


Re: [racket-users] The case, and a proposal, for elegant syntax in #lang racket2

2019-07-16 Thread Alexis King
> On Jul 16, 2019, at 15:32, rocketnia  wrote:
> 
> I find it worrying that racket2 would be kicked off with infix syntax 
> (something which I think of as an unnecessary sticking point in the way of 
> prospective macro writers and language designers, and hence a move *toward* 
> elitism *as opposed to* welcoming everyone)


I think this fear is natural and understandable, but I want to take a moment 
and urge everyone to think bigger than that, even if we as programmers are 
often trained not to. Do not think “because we are moving to a syntax for which 
macros are harder to express, the language we create will have an inferior or 
more difficult to use macro system.” If we were setting out to responsibly 
engineer a new language on a deadline, that thought would be right on the 
money… but we’re not doing that. Racket is a research language, from an 
ever-growing community full of very smart people who have produced lots of 
quite significant research results. They have taken problems that used to seem 
untenable and made them perfectly achievable (and indeed, often achieved!).

So instead of thinking about all the ways Matthew’s proposed syntax is a 
compromise that necessarily comes with certain downsides, think of it as a 
challenge: how do we take all the lovely things we’ve come to enjoy and take 
for granted in #lang racket and do them in a language with a less regular 
syntactic structure? How do we make writing great macros as easy in #lang 
racket2 as it already is in #lang racket? That means figuring out both what the 
primitives are and what the DSLs look like—syntax/parse did not naturally 
follow from hygiene and syntax objects, as much as it sometimes feels that way. 
I am not saying it is easy, and I’m not saying it’s even guaranteed to 
eventually succeed: perhaps we will fail. But I don’t think we have any reason 
to suspect we will just yet.

It can’t start by being everything we want it to be, of course; things take 
time. I just think that thinking about things as such a stark dichotomy is 
disingenuous and self-defeating. Obviously, we should not aim to become more 
elitist, on any axes, so let’s aim not to be. This is time for pie-in-the-sky 
brainstorming, not risk management. Having existing research to build on helps, 
but even that isn’t required. So although I know firsthand how hard it can be 
as an software engineer to think about what we want without worrying about how 
we can build it, let’s be aspirational and exploratory for a bit.

Alexis

P.S. If your qualm with moving from s-expressions is one of aesthetics, not 
ease or ability, I admit I can’t argue with you there. But I don’t imagine 
those kinds of discussions are likely to go anywhere productive, anyway—see 
Wadler’s law.

-- 
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/B0910168-AB4F-43B7-A690-B01281CC8E59%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Racket2 and syntax

2019-07-14 Thread Alexis King
Well! While I am sure that everyone at RacketCon has already discussed this to 
death, and I’m sure there has been plenty of support to counterbalance the 
tomato-throwing, let me be the first to say something positive on the mailing 
list so the optics from here aren’t so gloomy: I find this idea extremely 
exciting. :) It’s a surprise, for sure, but I will not be doing any panicking.

I don’t have any significant commentary right now, given how vague and 
open-ended the direction still is, but I am excited by the idea of continuing 
the Honu line of research. I, too, don’t mind parentheses, but after straddling 
the Haskell and Racket communities for a few years, I’ll happily defend the 
readability advantages of a more irregular syntax. I keep coming back to Racket 
because nothing lets me extend the language like Racket does, but if I could 
get that kind of flexibility and robustness without s-expressions? It sounds 
hard to achieve, but if Racket can pull it off (and I am confident Racket can 
do it as well as anyone), I doubt I would do much looking back.

If anything, the one thing I’m disappointed about is that I could not be at 
RacketCon this year, as it seems like it’s been a bad one to miss, but it’s 
been fun to follow everything as best as I can from the sidelines. Many thanks 
to everyone who’s had a part in the organizing, speaking, recording, and 
streaming! I look forward to seeing where this goes.

Alexis

> On Jul 14, 2019, at 21:29, Matthew Flatt  wrote:
> 
> tl;dr DON'T PANIC
> 
> At RacketCon today, after summarizing the state of work on Racket CS, I
> recommended that we next explore the possibly of changing to an
> infix-oriented syntax in "Racket2".
> 
> You can find the recording here:
> 
> https://www.youtube.com/watch?v=dnz6y5U0tFs
> 
> Start at 32:27 for the part about what Racket2 could be.
> 
> I'll produce a text version of the rationale soon. For now, I'd like to
> offer a few clarifications:
> 
> * There is no specific proposal for a new syntax, yet. Our next step
>   will be creating a process to explore a possible new syntax.
> 
> * The talk does include some initial constraints that might guide the
>   choice of a syntax. Even that meta level (i.e., the set of
>   constraints) remains subject to a community process.
> 
> * `#lang racket` is not going away and will always have its current
>   parenthesis-oriented syntax. In the same way that Racket still
>   supports `#lang scheme` and `#lang mzscheme` and even `(module
>mzscheme )` and even top-level programs, the Racket
>   compiler and runtime system will always support `#lang racket`
>   programs. We believe that Racket's `#lang`-based ecosystem makes it
>   uniquely positioned for trying new language variants while
>   preserving and building on our past investments.
> 
> * Any new syntax must specifically preserve Racket-style
>   language-oriented programming, which means everything from defining
>   simple pattern-based macros to building whole new `#lang`s with a
>   smooth path in between. Again, our current macro technology must be
>   an enabler for a new surface syntax, not a casualty.
> 
> As I hope comes across in the talk, I like the current Racket syntax
> --- and how could I not, after 24 years of helping to define it? ---
> and I am aware of many potential technical and social pitfalls that
> this kind of shift could create. Still, in addition to keeping the core
> Racket implementation running, I feel obliged to recommend changes that
> I think would be good for the Racket language and community. We've been
> lining up some technical solutions for a while. I don't know where the
> community discussion will lead, but I'm pretty sure it's time to start
> the conversation.
> 
> Whether or not we eventually decide on a different syntax, the design
> of Racket2 will require community input and participation. If you want
> to know more about how we're thinking about that process, see the
> keynote by Aaron Turon:
> 
>  https://www.youtube.com/watch?v=xSjk2PdQm5k
> 
> (We'll have professionally edited videos of all talks available soon.)
> 
> Thanks,
> 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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/E3D28E85-DB14-4734-B18E-5DFAF6CD9AB0%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Avoiding needless work in `dynamic-wind` during downward jumps?

2019-06-02 Thread Alexis King
Is there any way for dynamic-wind to know about the context of the continuation 
being jumped to in order to skip doing useless work?

To explain I mean and why I want such a thing, I have written some code that 
uses semaphores as mutexes, and most of my code acquires the mutex using 
call-with-semaphore. However, some functions need to do slightly more than what 
call-with-semaphore allows, because a sub-computation may also temporarily 
release the mutex, then re-acquire it when the sub-computation returns. To make 
that more concrete, here’s some code that does just that, using a 
call-with-semaphore/release function that I’ve written:

(call-with-semaphore/release mutex
  (lambda (call-with-released)
(do-something-with-the-mutex-locked!)
(call-with-released
 (lambda ()
   (do-something-with-the-mutex-unlocked!)))
(do-some-more-with-the-mutex-locked!)))

The call-with-semaphore procedure provided by racket/base installs a 
continuation barrier on every call, but I would like to be able to capture a 
continuation inside the inner portion, within the call-with-released thunk, so 
I’ve implemented call-with-semaphore/release using two uses of dynamic-wind: 
one to lock the mutex on entrance and unlock it on exit, and another to do 
precisely the inverse for around the code for which the mutex is released.

The problem with that is if I have code like

(call-with-semaphore/release mutex
  (lambda (call-with-released)
(call-with-released
 (lambda ()
   (call/cc
(lambda (k)
  (stash-continuation-and-abort! k)))

then when the continuation k is invoked from outside the dynamic extent of the 
call-with-semaphore/release application, the continuation will not start 
executing until it can acquire the mutex, even though it will release the mutex 
as soon as it acquires it. This is very wasteful, since it creates a lot of 
unnecessary contention for the mutex.

I guess one way I could avoid this would be to make every call to 
call-with-semaphore/release install a fresh prompt, then make 
call-with-released capture the current continuation, abort to that prompt, 
execute the inner thunk in the outer context without the lock acquired, and 
finally apply the captured continuation to the result. This would mean the 
above example would end up effectively doing something like this:

(let ([tag (make-continuation-prompt-tag)])
  (call-with-continuation-prompt
   tag
   (lambda ()
 (call-with-semaphore mutex
   (lambda ()
 (call/comp
  (lambda (reacquire-k)
(abort-current-continuation
 tag
 (lambda ()
   (call-with-values
(lambda ()
  (call/cc
   (lambda (k)
 (stash-continuation-and-abort! k
reacquire-k
  tag
   (lambda (thunk) (thunk

…which sure is wordy, but the real problem is that any continuation marks or 
prompts installed by the thunk passed to call-with-semaphore/release before 
calling call-with-released would get dropped. I’ve tried to come up with a way 
to avoid the needless re-locking outlined above without suffering from that 
problem, but I haven’t come up with any solutions, not even by bringing mutable 
state into the picture. Is it possible?

Thanks,
Alexis

-- 
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/BCB3DDF0-95B1-49EB-9FDA-8C3B6FC045DE%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] New Package: Dynamic FFI - Write C Code Inline

2019-06-01 Thread Alexis King
This looks extremely cool. Thanks for your hard work—I will probably give this 
a try next time I use the FFI.

Alexis

> On Jun 1, 2019, at 14:06, David Benoit  
> wrote:
> 
> Hi All,
> 
> I've recently released a new library 
>  for dynamically generating 
> FFI bindings to C by parsing header files.
> It also allows users to create FFI libraries by writing C functions directly 
> inline in Racket programs.  
> 
> The library works as a native extension to Racket by linking with Clang's 
> parser libraries and converting AST declarations into FFI objects.
> As a result, the package depends on Clang and LLVM headers and libraries.  
> See the documentation  
> for info on installing dependencies.
> 
> I've only built the package on GNU/Linux so far.  If anyone is interested in 
> building the library on other OSes, it should be a fairly trivial port.
> 
> I'd like to give a special thanks to Jay McCarthy, who came up with the idea 
> for this project and was my adviser during its implementation.
> I hope its something the Racket community might find useful!
> 
> More usage examples are available in the docs and the test directory 
>  in the source 
> code.
> 
> Thanks!
> David B
> 
> I'll sign off with a quick preview:
> 
> #lang at-exp racket/base
> 
> (require dynamic-ffi/unsafe)
> 
> @define-inline-ffi[struct-test]{
>   #include 
>   #include 
>   #include 
> 
>   typedef struct {
> char *name;
> uint64_t value;
>   } number;
> 
>   char* names[] = {"zero", "one", "two", "three", "four", "five", "six"
>  "seven", "eight", "nine", "ten", "eleven", "twelve"};
> 
>   number add(number a, number b) {
> number c;
> c.value = a.value + b.value;
> if (c.value >12)  {
>   fprintf(stderr, "error: this example can only count to twelve...\n");
>   exit(1);
> }
> c.name = names[c.value];
> return c;
>  }
> }
> 
> ;; _list-structs are created by default.  I hope to optimize this in the 
> future.
> 
> (define n2 (list "two" 2))
> 
> (define n7 (list "seven" 7))
> 
> (printf "add(n2, n2): ~a\n" (struct-test 'add n2 n2))  ;; output: add(n2, 
> n2): (four 4)
> (printf "add(n7, n7): ~a\n" (struct-test 'add n7 n7))  ;; output: error: this 
> example can only count to twelve...
> 
> 
> 
> 
> 
> -- 
> 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/eff63a65-d1b7-475b-9240-7158b024d740%40googlegroups.com
>  
> .
> For more options, visit https://groups.google.com/d/optout 
> .

-- 
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/7F378714-5C17-4DD1-AA56-C6DE868E%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Trouble writing unhygienic macro

2019-05-27 Thread Alexis King
> On May 27, 2019, at 22:28, Jonathan Simpson  wrote:
> 
> I may be missing something, but I didn't think I could use the name as valid 
> syntax since this is the form that is creating it. If passing a symbol in 
> would work then I could potentially change my lexer to do that instead of a 
> string.

I might not be understanding your question properly, but I think the answer is: 
yes, if your macro were to accept an identifier in the `magic-name` position 
instead of a string, then you could put that identifier in the expansion and it 
would “just work.” See this macro, for example:[^1]

#lang racket
(require (for-syntax syntax/parse))

(define-syntax (macro-that-defines-a-name stx)
  (syntax-parse stx
[(_ some-name)
 #'(define some-name 42)]))

Hygiene ensures that `some-name` will be bound wherever the identifier itself 
comes from, so it will be bound in whatever context uses 
`macro-that-defines-a-name`:

> (macro-that-defines-a-name my-name)
> my-name
42

If you really want to pass a string to your macro instead of an identifier, you 
can use what you have in combination with `datum->syntax` to create a new 
identifier that “copies” scoping information from some piece of input syntax. 
You currently have this:

(string->symbol (syntax->datum #'magic-name))

...and that will produce a symbol, but it won’t have any scope information 
associated with it (since `syntax->datum` threw it all away).[^2]

To copy scoping information from the input, you can add a use of 
`datum->syntax`, supplying the “source” of the copy operation as the first 
argument:

(let ([magic-name-sym (string->symbol (syntax->datum #'magic-name))])
  (with-syntax ([magic-name-id
 (datum->syntax #'magic-name magic-name-sym)])
))

This will create an identifier with the scopes I think you want.

Alexis

[^1]: You should use `syntax-parse` instead of `syntax-case`. There’s nothing 
wrong with using `syntax-case` per se, but `syntax-parse` is just better on all 
axes (except perhaps compilation time, but you know what they say about 
premature optimization). It will provide significantly better syntax error 
messages even if you stick purely to the `syntax-case` subset.

Also, with `syntax-parse`, you can improve upon the above examples somewhat. 
You can write a pattern binding of the shape `name:id` or `name:str` to 
restrict matching to an identifier or string, respectively, and syntax errors 
will be improved accordingly. Also, you can replace the uses of `let` and 
`with-syntax` with `syntax-parse`’s built-in `#:do` and `#:with` directives, 
which are used like this:

(syntax-parse stx
  [(_ name:str)
   #:do [(define name-sym (string->symbol (syntax->datum #'name)))]
   #:with name-id (datum->syntax #'name name-sym)
   #'(define name-id 42)])

[^2]: By default, when given a value that isn’t a syntax object, `with-syntax` 
automatically coerces it to one, copying whatever scoping information is 
present on the `with-syntax` form itself, i.e. the macro scopes. This is 
different from explicitly writing

(with-syntax ([foo (datum->syntax #f 'bar)])
  )

since that will bind `foo` to a syntax objects with no scopes at all. In 
contrast, writing `(with-syntax ([foo 'bar]) )` is equivalent to writing 
`(with-syntax ([foo #'bar]) )`.

As a final note, `syntax-parse`’s `#:with` form is slightly different from 
`with-syntax` in this respect, as it really will use `(datum->syntax #f )` 
instead of trying to guess at what scopes you might have wanted.

-- 
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/49B6B0B9-1D03-4E66-B5C1-C70C45A22235%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] What is the difference between foo/c and foo? when creating contracts?

2019-05-22 Thread Alexis King
Your intuition is right, but let me make it more precise: foo? is used when 
something is a flat contract, and foo/c is used otherwise. Flat contracts only 
check first order properties of values, which is a technical term that captures 
what you mean by “general nature.”

The important distinction is that first order properties can be checked 
immediately, whereas checking of higher-order properties may need to be 
delayed. For example, when you write the contract

(-> integer? string?)

then you can check immediately that the value is a procedure (via the 
procedure? predicate), but you have to wait until the function is called to 
check that it is actually passed an integer. Therefore, non-flat contracts add 
proxying wrappers to values that do the deferred checking.

Since flat contracts only perform first-order checks, a flat contract can be 
used as a predicate, so you can write (foo? x) to get back a boolean. Likewise, 
all predicates can be used as flat contracts. This is why the foo? naming 
scheme is used for those contracts, since foo? is the historical naming 
convention in Scheme and its descendants for naming predicates. The foo/c 
naming convention is newer, and is specific to contracts, so it is used for 
contracts and contract combinators that are not simple predicates, and 
therefore cannot use the foo? naming convention.

Alexis

> On May 22, 2019, at 12:06, David Storrs  > wrote:
> 
> Is the idea that foo/c is used only when it will specify structure (e.g. 
> (hash/c any/c symbol?)) whereas foo? is used to check that a thing has a 
> general nature?

-- 
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/3D2F671B-9322-43FC-B51D-2BA6542E2D67%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] What is the difference between foo/c and foo? when creating contracts?

2019-05-22 Thread Alexis King
Your intuition is right, but let me make it more precise: foo? is used when 
something is a flat contract, and foo/c is used otherwise. Flat contracts only 
check first order properties of values, which is a technical term that captures 
what you mean by “general nature.”

The important distinction is that first order properties can be checked 
immediately, whereas checking of higher-order properties may need to be 
delayed. For example, when you write the contract

(-> integer? string?)

then you can check immediately that the value is a procedure (via the 
procedure? predicate), but you have to wait until the function is called to 
check that it is actually passed an integer. Therefore, non-flat contracts add 
proxying wrappers to values that do the deferred checking.

Since flat contracts only perform first-order checks, a flat contract can be 
used as a predicate, so you can write (foo? x) to get back a boolean. Likewise, 
all predicates can be used as flat contracts. This is why the foo? naming 
scheme is used for those contracts, since foo? is the historical naming 
convention in Scheme and its descendants for naming predicates. The foo/c 
naming convention is newer, and is specific to contracts, so it is used for 
contracts and contract combinators that are not simple predicates, and 
therefore cannot use the foo? naming convention.

Alexis

> On May 22, 2019, at 12:06, David Storrs  wrote:
> 
> Is the idea that foo/c is used only when it will specify structure (e.g. 
> (hash/c any/c symbol?)) whereas foo? is used to check that a thing has a 
> general nature?

-- 
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/53A5FA54-2623-4B0A-8E02-2924B7AA2226%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] How would you implement autoquoted atoms?

2019-04-23 Thread Alexis King
I find this email fascinating, as about three weeks ago, Spencer Florence and I 
discussed something almost identical, from the module path + symbol protocol 
all the way down to the trouble with `quote`. I had been intending to 
experiment with implementing the idea at some point, but I already have a few 
too many balls in the air right now (from the intdef changes I’ve been 
exploring to the `hash-key` implementation I started fiddling with, plus 
starting the process of looking for a new job), so I probably won’t get to it 
any time soon. But I’ll go on record as being interested in doing so.

> On Apr 23, 2019, at 09:57, Matthew Flatt  wrote:
> 
> This response will be rambling, too. :)
> 
> Especially with your follow-up message, I think you're getting to a
> problem that we've wrestled with for a while. Sometimes we've called it
> the "graphical syntax" problem, because it's related to having non-text
> syntax, such as images in DrRacket (which are currently implemented in
> an ad hoc way). Another example could be adding quaternion literals,
> analogous to complex-number literals. In the cases that we've
> considered, we want the language to be extensible with a new kind of
> literal, but there's not necessary any specific import the language
> extension in the program. That means there's a set of binding,
> evaluation, and composition problems to solve.
> 
> 
> I've discussed the problem the most with William Hatch, and here's as
> far as we got with some ideas.
> 
> There could be a new primitive datatype --- at the levels of symbols,
> pairs, vectors, etc. --- to let the reader and expander communicate.
> Just to have some concrete syntax for the default reader and printer,
> let's say that the new kind of value can be written with `#q`, perhaps
> of the form
> 
>  #q(  )
> 
> The intent of the  and  components is to give
> the value a kind of binding. That binding is analogous to syntax
> objects, but without actually using syntax objects, which is arguably
> the wrong concept to pull into the reader level. The remaining
>  is payload to be interpreted by the  and
>  combination, such as image data or real numbers for the
> components of a quaternion.
> 
> Of course, a reader might construct these values as a result of parsing
> some other text, but the idea is that printing out the result from that
> reader with the default printer would use this `#q` notation, and then
> that printed form could be read back in. That is, the values can be
> consistently marshaled and unmarshaled, just like pairs and vectors and
> numbers.
> 
> The benefit of a new datatype is that it can have its own dispatch rule
> in the expander. Probably a `#q` in an expression position would get
> wrapped by an implicit `#%q-expression`, or something like that, which
> would give a language control over whether it wants to allow arbitrary
> literal values. But the default `#%q-expression` would consult the
> value's "binding" via the  and  to expand the
> value, which might inline an image or quaternion construction, or
> something like that. In effect, the reader form carries its own
> `require` at all times.
> 
> Maybe interning corresponds to an expansion that lifts out a
> calculation (in the sense of `syntax-local-lift-expression`), or maybe
> that's not good enough; I'm not sure.
> 
> We imagined that the primitive `quote` form might do something similar
> to `#%q-expression` in the case that an image or quaternion is part of
> a quoted S-expression. But, then, does there need to be an even
> stronger `quote` that doesn't try to expand the `#q` content? I don't
> know.
> 
> Meanwhile, the  and  combination could also
> identify a value-specific printer, where images might recognize when
> the output context can support rendering the actual image, while
> quaternions might print using "+" and "i" and "j". Or maybe that
> problem should be left to `prop:custom-write`.
> 
> At the level of writing down programs, the examples or images and
> quaternions seem different. For images, DrRacket and other editors have
> to include the concept of images somehow, and they insert values that
> turn into `#q` forms when the program is viewed as a character
> sequence. But quaternions are written with characters, so maybe that
> syntax is more like `@` reading in that a language constructor on the
> `#lang` line would add quaternion syntax to the readtable (which would
> work for S-expression languages).
> 
> 
> Overall, this reply is intended as a kind of endorsement and
> elaboration of your thoughts: Yes, this is an interesting problem, and
> it seems to need something new in Racket. And, yes, adding some new
> datatype (with some default syntax) seems like the right direction,
> mainly because it could trigger a new kind of dispatch in the expander.
> Probably that new datatype should have something built-in that amounts
> to a binding for it's compile-time and run-time realization.
> 
> I would be really happy to see someone 

[racket-users] Defeating Racket’s separate compilation guarantee

2019-04-21 Thread Alexis King
Hello all,

I just published a blog post on defeating Racket’s separate compilation 
guarantee. While I don’t imagine such a thing is actually a good idea, I think 
the path to getting there is interesting anyway, and it touches lots of 
different parts of the Racket system. For those who are interested, the blog 
post is available here:


https://lexi-lambda.github.io/blog/2019/04/21/defeating-racket-s-separate-compilation-guarantee/

Comments welcome,
Alexis

-- 
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.


Re: [racket-users] Re: catch and bind an unbound id in a macro

2019-04-20 Thread Alexis King
The third argument to identifier-binding, top-level-symbol?, controls the 
result of identifier-binding when the identifier is bound to a top-level 
binding (and both the REPL and sandboxed evaluators are kinds of top-level 
evaluation). The docs elaborate this way:
> The result is (list source-id) if id-stx has a top-level binding and 
> top-level-symbol? is true.
> 
> The result is #f if id-stx has a top-level binding and top-level-symbol? is 
> #f or if id-stx is unbound. An unbound identifier is typically treated the 
> same as an identifier whose top-level binding is a variable.

I’m not actually sure what the full implications are of passing #t for that 
argument, but you might try that and see if it works for you. A disadvantage of 
using syntax-local-value is that it will fail if the identifier is bound to a 
runtime variable rather than syntax.

Alexis

> On Apr 20, 2019, at 16:56, Ryan Kramer  wrote:
> 
> Below is a short example showing that identifier-binding doesn't seem to work 
> quite right with Scribble's make-base-eval. It works fine with make-evaluator 
> from racket/sandbox.
> 
> I'm not sure why this is, but using syntax-local-value instead works 
> everywhere. (Implementation here: 
> https://github.com/default-kramer/plisqin/commit/2723d7c11be5b6938e681ea869e8b9f4957849b0#diff-1a91d998f2be05413392d588a89323d3R31)
> 
> #lang racket
> (require scribble/eval
>  racket/sandbox)
> 
> (define (setup eval)
>   (eval
>'(define-syntax (define-if-not stx)
>   (syntax-case stx ()
> [(_ id val)
>  (identifier-binding #'id)
>  #'(void)]
> [(_ id val)
>  #'(define id val)]
> 
> (define scribble-eval (make-base-eval))
> (scribble-eval '(require racket))
> (setup scribble-eval)
> 
> (define racket-eval (make-evaluator 'racket))
> (setup racket-eval)
> 
> (scribble-eval '(define-if-not foo 1))
> (scribble-eval '(define-if-not foo 2))
> (scribble-eval 'foo) ; want 1, get 2
> 
> (racket-eval '(define-if-not bar 3))
> (racket-eval '(define-if-not bar 4))
> (racket-eval 'bar) ; want 3, get 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.


Re: [racket-users] [macro help] How can I render a parenthesized set of elements optional?

2019-02-15 Thread Alexis King
Jon is right. Here’s an explanation why.

Think of `...` as a postfix operator. It repeats what comes before it a certain 
number of times. In order for `...` to know how many times to repeat the 
previous head template, it looks inside the head template for any attributes 
bound at the appropriate ellipsis depth, and it repeats the head template once 
for each value of the attributes. The `...` operator essentially creates a 
loop, iterating through each value of the attribute.

The value of attributes bound under ellipses are therefore lists. You can see 
this for yourself if you use the `attribute` accessor to explicitly get at the 
value of an attribute matched under an ellipsis:

  > (syntax-parse #'(a b c)
  [(x:id ...)
   (attribute x)])
  '(#
#
#)

But what happens to the value of an attribute when it is completely 
unspecified, since it has been marked `~optional`? If the `~optional` wraps the 
whole sequence, such that the ellipsis is inside the `~optional` pattern, then 
the attribute is not a list at all, but `#f`:

  > (syntax-parse #'()
  [({~optional (x:id ...)})
   (attribute x)])
  #f

This causes problems. If we were to write #'(x ...) when `x` is bound to `#f`, 
then the template will raise an error, since `x` isn’t a list, and therefore 
the ellipses don’t know how many times to repeat the preceding template.

What you tried to do is silence that error by wrapping the offending template 
with `~?`. This is a natural thing to try, but it doesn’t work. Why? Well, it’s 
true that {~? x} turns into {~@} when `x` is `#f`, but this does not matter, 
since you essentially wrote ({~? x} ...). This means that the `x` under the 
ellipsis doesn’t refer to the attribute `x` as a whole, but instead refers to 
each *element* of `x`, since `...` creates a loop. So the template attempts to 
iterate through the values of (attribute x), but it finds that value isn’t a 
list at all, gets confused, and explodes.

Jon’s fix changes this. It moves the looping *inside* the `~?`, which means 
that `~?` is now looking at `x` as a whole (not each element of `x`), and just 
skips the loop altogether, avoiding the error. It’s morally the difference 
between this code:

  (for/list ([x (in-list (attribute x))])
(if x x #'{~@}))

and this code:

  (if (attribute x)
  (for/list ([x (in-list (attribute x))])
x)
  #'{~@})

---

A secondary question: is the template #'({~? x} ...) ever useful? And the 
answer is: YES! It just does something different.

Since #'({~? x} ...) iterates through the values of `x` before checking for 
`#f`-ness, then it is useful when `x` itself is never `#f`, but elements of it 
may be. This can appear when parsing, say, a list of pairs, where the second 
element of each pair is optional:

  > (define parse-pairs
  (syntax-parser
[([x:id {~optional n:nat}] ...)
 #'([x ...]
[{~? n} ...])]))
  > (parse-pairs #'([a 1] [b] [c 3]))
  #
  > (parse-pairs #'([a] [b] [c]))
  #

Note that when there are no numbers in the input, the output list is still 
present but is simply empty, while when some but not all numbers are provided, 
the missing numbers are simply skipped in the output.

---

One final point: you may think to yourself “all of this is confusing and 
procedural, why should I have to think about attributes?” While I think 
understanding what’s going on internally can be helpful, it isn’t strictly 
necessary. There’s actually a declarative intuition to guide whether you should 
write #'({~? {~@ x ...}}) or #'({~? x} ...). This intuition is as follows.

There is a dualism in `syntax-parse`’s pattern language and in the `syntax` 
form’s template language. For example:

  - Writing `x` in a pattern, where `x` is an identifier, matches a term, and 
writing `x` in a template constructs the same term.

  - Writing (a . b) in a pattern matches a pair, and writing (a . b) in a 
template constructs a pair.

  - Writing `p ...` in a pattern matches zero or more occurrences of the 
pattern `p`, and writing `t ...` in a template that contains variables bound in 
`p` constructs the same number of occurrences in the template.

To put things another way:

  - Variables in patterns correspond to variables in templates.
  - (a . b) in patterns corresponds to (a . b) in templates.
  - `...` in patterns corresponds to `...` in templates.

This might seem obvious, but it turns out that `~?` and `~@` have cousins in 
the pattern language, too. They are just less obvious, because their cousins 
have different names:

  - `~optional` in patterns corresponds to `~?` in templates.
  - `~seq` in patterns corresponds to `~@` in templates.

(I would have liked `~?` and `~@` to be named `~optional` and `~seq` to make 
this duality clearer, but sadly, since `~?` and `~@` were added recently, 
reusing existing names would make them backwards incompatible with older code 
that expanded to `syntax-parse` patterns.)

Since `~optional` corresponds to 

Re: [racket-users] Why ChezScheme?

2019-02-09 Thread Alexis King
> On Feb 9, 2019, at 16:49, Hendrik Boom  wrote:
> 
> Just wndering -- What was the original purpose in moving Racket to Chez?

You probably want to read Matthew’s original email on the subject, from about 
two years ago:

https://groups.google.com/d/msg/racket-dev/2BV3ElyfF8Y/4RSd3XbECAAJ

Alexis

-- 
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.


Re: [racket-users] Are the terms "function" and "procedure" synonymous in Racket?

2019-01-13 Thread Alexis King
Disclaimer: this answer is extremely non-authoritative.

I think that, in Racket, the terms are used more or less interchangeably. The 
technical term is “procedure”, but as you point out, the term “function” is 
also used to mean the same thing. I don’t believe there is any distinction 
there that would be universally understood.

On the other hand, in How to Design Programs (and its various teaching 
languages), my understanding is that “function” is the correct term and 
“procedure” is strongly discouraged. The documentation on implementing new 
teachpacks supports this understanding, in a section entitled Prohibited Words 
. It 
states explicitly that “function” should be used instead of “procedure”, 
“selector”, “constructor”, or any number of other terms. It includes the 
following justification:

> These guidelines use few terms intentionally, emphasizing commonality among 
> concepts rather than technical precision (which most students do not 
> appreciate anyway).

I imagine others on this list who wrote the above words can give a more 
authoritative answer should they find this one inadequate. :)

Alexis

> On Jan 13, 2019, at 11:37, Ellen Spertus  wrote:
> 
> Are "procedure" and "function" synonymous in Racket? It seems to be implied 
> by the documentation . For 
> example, the documentation for compose 
> 
>  describes it as a procedure that
> 
> [r]eturns a procedure that composes the given functions...The compose 
> function allows the given functions to consume and produce any number of 
> values...
> 
> (All of the above italicization was added by me.)
> 
> 
> 
> I understand that procedure? is a library procedure and function? is not. I 
> also understand the difference between a mathematical function and a computer 
> procedure (which might have side effects). What I'm trying to determine is 
> what language to use with my students this semester. (I like to use both 
> "procedure" and "function" because it's sometimes useful to have two 
> different words, as in the above documentation excerpt.)
> 
> 
> 
> FYI, I posted a version of this question to Stack Overflow 
> .
>  I got an answer but was referred here.
> 
> 
> 
> Thanks.
> 
> 
> 
> Ellen
> 
> 
> -- 
> 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 
> .

-- 
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.


Re: [racket-users] Communicating the purpose of Racket (was: hackernews)

2018-12-29 Thread Alexis King
> On Dec 29, 2018, at 21:32, Philip McGrath  wrote:
> 
>> Respectfully, I would also concentrate on Rackets web presence.  If I was to 
>> google any of the popular languages, I would find the answer to these 
>> questions in spades, with real life applications, and examples.  You can 
>> also compare Pythons website to Rackets.   Pythons website seems to be 
>> design more for advertising Python.  If I go to the Pythons web page there 
>> is a section “use Python for” in it, it has various topics such as web 
>> development, GUI development, scientific and numeric, with all the 
>> applicable packages needed.   If you knew nothing about Python, but where 
>> interested in using it for web development, it easy to see where to go, etc. 
>>  
> 
> I would be interested to hear more about your experience with Racket's web 
> site, because it tries to include these things, but evidently it did not 
> succeed in communicating them to you. When I go to https://racket-lang.org/ 
> and scroll down about one screen's worth, I see short, runable examples of a 
> few flashy features including web development and GUI applications 
> specifically, with links to tutorials and documentation.

The previous version of the Racket website (before its redesign two years ago) 
included such things more explicitly, in a format non-Racketters (which is who 
the homepage is for, after all!) are more likely to comprehend. It included, 
among other things, a clear purpose statement for the language at the very top 
of the page, a set of small, to the point code examples that showed off various 
kinds of general-purpose programming (with explanations), and a set of links to 
further resources clearly geared towards programmers of different skill levels. 
To give you a sense for how this website used to be targeted, here’s the 
aforementioned purpose statement, in its entirety:

> Racket is a full-spectrum programming language. It goes beyond Lisp and 
> Scheme with dialects that support objects, types, laziness, and more. Racket 
> enables programmers to link components written in different dialects, and it 
> empowers programmers to create new, project-specific dialects. Racket's 
> libraries support applications from web servers and databases to GUIs and 
> charts.

The concepts enumerated in the above statement are linked to the relevant 
sections in the Guide for those interested in learning more.

The following code snippets showed Racket doing mundane but useful tasks an 
“ordinary” programmer would likely understand. They included things like simple 
scripting using the filesystem, a small web server, basic terminal I/O, 
creating a GUI window, a toy web scraper, and even sending e-mail. Towards the 
end of this carousel of snippets, some of Racket’s language-oriented 
programming features start to sneak in — there’s a small Typed Racket program, 
a document written in Scribble, and even a tiny datalog database — but these 
are clearly secondary to the main point: Racket is a full-spectrum, 
general-purpose programming language, and if you already know how to program, 
it is grounded in things familiar to you.

If you are interested in seeing the old homepage, in all its late aughts design 
glory, it is preserved with full functionality here:

https://web.archive.org/web/20161129144201/http://www.racket-lang.org:80/

The redesign of the Racket website shifted the emphasis from Racket as a 
general-purpose programming language to Racket as a language workbench. There 
is no doubt that this shift has its advantages — Racket’s support for 
language-oriented programming is one of its features that sets it apart most 
significantly from other ecosystems. Unfortunately, I don’t think we’ve gotten 
far enough to really push #lang as a killer feature to the working programmer 
yet, so I don’t think the current design does much to convey why the average 
person should care (especially since it focuses a lot on building languages 
while the old homepage focused more on using languages). I expressed some of 
these concerns, among others, when the redesign was first proposed; if you are 
interested, you can read the discussion here:

https://github.com/racket/racket-lang-org/pull/28

Now, admittedly, it’s easy to complain, but actions speak louder than words: I 
have put zero effort into making the website better, while I’m sure MB 
volunteered several days of his time. The website is open source, and perhaps 
if I truly cared, I would invest some of my own free time into suggesting (and 
implementing) concrete changes. I simply have not. I’m sure a pull request 
would be welcomed, should anyone submit one to clarify some confusion they 
bumped into. On the other hand, it obviously isn’t the responsibility of those 
outside of the Racket community to invest time into making Racket’s website 
better, especially given the effort involved, so it does not surprise me it has 
been left largely unchanged.

Alexis

-- 
You received 

Re: [racket-users] How to disallow certain characters in identifiers?

2018-12-10 Thread Alexis King
I think your initial instinct was right: if you want to change the lexical 
structure of your language, the right place to start is in the reader. The 
reader is the part of Racket’s language facilities that interprets the 
structure of sequences of characters, and your notion of dotted identifiers 
clearly treats the two components as distinct lexemes. Any attempts to reuse 
the unmodified Racket reader but treat certain shapes of identifiers in a 
particular way will likely be hopeless, as those lexemes have been fused.

That said, modifying the reader is usually only part one, a jumping-off point. 
While the reader interprets the lexical structure of your language, and it 
weakly collects the results into some sort of tree, it doesn’t say anything 
about what that tree means. When the Racket reader sees (define x 1), it reads 
a list containing two symbols and a number, not a definition. It is the module 
language that determines which bindings are in scope and imbues those 
identifiers with meaning.

In this sense, you likely can’t get away with just modifying the reader: you 
need to modify both the reader and the module language. It isn’t really clear 
to me what you want (define a.b 3) to do—whether it should signal an error or 
do some useful thing—but it seems to me like you may wish to wrap various forms 
from racket/base in your own macros that handle the dotted expressions produced 
by your reader.

(Theoretically, Racket could do some things differently so that you’d have to 
do less work to at least render nonsense like the above illegal, such as 
provide an extensible syntax object language. This would make reader extensions 
more watertight abstractions. For better or for worse, however, this is not the 
way Racket currently works, and this shows in various ways even in #lang 
racket… such as, for example, the fact that (+ 1 . (2 3)) is a totally legal 
Racket expression that evaluates to 6.)

Alexis

> On Dec 10, 2018, at 17:31, Ryan Kramer  wrote:
> 
> It turns out expanding the syntax object isn't the right approach. It seems 
> easy enough for defining values and simple procedures, but as soon as you 
> consider optional arguments and keyword arguments, the resulting expansion 
> gets too complicated to analyze.
> 
> I don't see an easy way to do this, unless there is some hook that I am 
> unaware of. For example, applications get piped through #%app and unbound 
> identifiers get piped through #%top. If there is #%something that new 
> identifiers get piped through, that would be what I want. But I don't think 
> it exists.
> 
> So my next attempt will be to go back to the reader, and make it so that 
> certain characters (like dot and +) are always treated as individual tokens. 
> Meaning that (define foo+bar 42) will come out of the reader as (define foo + 
> bar 42). The resulting error message should be good enough for my purposes, I 
> think.

-- 
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.


Re: [racket-users] How do I launch a REPL in the context of a file?

2018-11-30 Thread Alexis King
> On Nov 30, 2018, at 08:23, Sam Tobin-Hochstadt  wrote:
> 
> I'm not sure why `-e` doesn't evaluate in the same namespace as the
> REPL, but if you put `(enter! "my-file.rkt")` in `enter.rktl` then:

I’m curious about this, too. At first I thought it was just a misfeature, not 
necessarily a bug, but now I’m not so sure. The namespaces are not actually 
separate, as the following interaction demonstrates:

$ racket -ie '(define x 3)'
Welcome to Racket v7.1.0.1.
> x
3

So then what gives? After further experimentation, my running theory is that 
any mutation of `current-namespace` inside of -e is reverted when the REPL 
starts up. You can see this by skipping `enter!` completely and just modifying 
`current-namespace` directly:

$ racket -ie '(define ns (make-base-namespace)) (current-namespace ns)'
Welcome to Racket v7.1.0.1.
> (eq? ns (current-namespace))
#f

I don’t know if this is intentional behavior or just a bug.

Alexis

-- 
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.


Re: [racket-users] cons-specific optimizations?

2018-11-28 Thread Alexis King
> On Nov 28, 2018, at 07:15, Matthew Flatt  wrote:
> 
> Yes, that's special handling for pairs in the sense that the
> traditional Racket implementation takes advantage of leftover bits in a
> pair object, and it uses two of them for "is a list" and "not a list".
> 
> Racket-on-Chez doesn't have the extra bits to work with, so "is a list"
> and "not a list" information is recorded separately in an `eq?`-based
> hash table.

Why does keeping track of “is a list” and “not a list” require two bits? It 
seems like a pair either is or is not a list, so one bit of information would 
be sufficient. Are there situations where the system can neither be sure that 
something is or is not a list? Circular lists, or something like that?

(This is not really important, of course, I’m just curious.)

Alexis

-- 
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.


Re: [racket-users] Destructuring a list in (for ...)

2018-11-23 Thread Alexis King
The trouble, sadly, is that this grammar is ambiguous. In

  (for ([(x y) s])
)

should (x y) be parsed as a single match pattern or as two binders for a 
two-valued sequence (such as one produced by in-hash, for example)? You could 
make it unambiguous in various ways, such as by requiring uses of match 
patterns to all use the multi-valued binder syntax (with an extra set of 
parens), but that’s a bit clumsy. Unfortunately, I can’t think of any 
particularly elegant way to support match patterns in for loop binders in a 
backwards-compatible way.

Alexis

> On Nov 22, 2018, at 20:14, Greg Hendershott  wrote:
> 
>> (define-syntax (match-for stx)
> 
> That's nice.
> 
> Sometimes I wish I could do the general thing -- use `match` patterns
> in the binding clauses for any `for`-family form.
> 
> I often do something like this:
> 
>(define xs (list (cons 1 2) (cons 3 4)))
> 
>(for ([x (in-list xs)])
>  (match-define (cons a b) x)
>  (use a b))
> 
> Instead it would be nice to write:
> 
>(for ([(match-define (cons a b)) (in-list xs)])
>  (use a b))
> 
> Or even just:
> 
>(for ([(cons a b c) (in-list xs)])
>  (use a b))
> 
> In the grammar, `id` becomes `id-or-match-pattern`.
> 
> On the other hand, this would only really help in simple
> `match-define` destructuring -- as opposed to using `match` to handle
> variations in the data. And although I do the former a lot, I do the
> latter even more.

-- 
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.


Re: [racket-users] Creating truly unique instances of structure types?

2018-11-06 Thread Alexis King
> On Nov 5, 2018, at 20:01, Ryan Culpepper  wrote:
> 
> You could use a chaperone to prohibit `struct-info`

Good point! I had forgotten that `struct-info` is a chaperoneable operation. 
This isn’t ideal, though, since I don’t think `struct-info` is ever actually 
supposed to raise an error, it’s just supposed to return #f, instead. It’s 
possible to call `struct-info` on absolutely anything, even things like 
numbers, and get a result:

> (struct-info 3)
#f
#t

If I understand correctly, this is because all values in Racket are “morally 
structures”, and reflective operations on values that are not actually 
implemented with structures should behave identically to reflective operations 
on values for which you do not have a sufficiently powerful inspector to 
inspect.

Unfortunately, it isn’t possible to regain this behavior with 
`impersonate-struct`, since `impersonate-struct` does not allow you to 
impersonate `struct-info`.

> On Nov 6, 2018, at 02:47, Philip McGrath  wrote:
> 
> A variant on Alexis' example lets you circumvent Typed Racket's protections:
> 
> [snip]
> 
> Maybe this is well-known to everyone who's thought about it before, but I 
> hadn't. Though I guess, while I don't think about inspectors very often, I 
> think of them as a way for one module to put others under its control, in 
> which case maybe the module with the more powerful inspector should be able 
> to break subordinate modules' invariants.

I’m not sure, either. Personally, I feel like it should be possible to have 
invariants that truly cannot be broken, but maybe there are use cases I don’t 
understand. Anyway, in the case of Typed Racket, this is clearly a soundness 
hole, but a fixable one — either Typed Racket or the contract system is not 
applying `chaperone-struct-type` where it ought to be. I’ll file a bug.

Alexis

-- 
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] Creating truly unique instances of structure types?

2018-11-05 Thread Alexis King
To my knowledge, there are two main techniques for creating unique values in 
Racket: `gensym` and structure type generativity. The former seems to be 
bulletproof — a value created with `gensym` will never be `equal?` to anything 
except itself – but the latter isn’t. Using reflective operations, it’s 
possible to circumvent the encapsulation afforded by the module system.

To provide an example, `racket/contract` exports a value called 
`the-unsupplied-arg`, which is created using the usual structure type 
generativity trick:

(define-struct the-unsupplied-arg ())
(define the-unsupplied-arg (make-the-unsupplied-arg))
(provide the-unsupplied-arg)

The constructor is not exported, and this value is intended to be unique. 
However, if we can arrange for the contract library to be loaded on our terms, 
we can thwart this encapsulation by supplying it with a weaker inspector:

#lang racket/base

(define the-unsupplied-arg
  (parameterize ([current-inspector (make-inspector)])
(dynamic-require 'racket/contract 'the-unsupplied-arg)))

(define-values [info skipped?] (struct-info the-unsupplied-arg))

(define another-unsupplied-arg ((struct-type-make-constructor info)))

(equal? the-unsupplied-arg another-unsupplied-arg) ; => #t
(eq? the-unsupplied-arg another-unsupplied-arg); => #f

Perhaps this isn’t the end of the world, as after all, we can’t do anything 
especially nefarious with this value, and we wouldn’t be able to do it in the 
first place if we didn’t have complete control of the inspector hierarchy. 
Still, it seems a little unsatisfying.

So, my question: is there any way to create a structure type for which there 
can truly ever only be one instance? If not, is there a fundamental reason why 
not?

Alexis

-- 
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] Higher-order units

2018-10-17 Thread Alexis King
Imagine I have the following signature:

(define-signature collector^
  [(contracted
[item/c contract?]
[collect (-> item/c ... item/c)])])

Writing a unit that exports this signature is easy. For example, here’s one 
that sums its arguments:

(define-unit sum-collector@
  (import)
  (export collector^)

  (define item/c number?)

  (define (collect . xs)
(apply + xs)))

But imagine I want to instead write a higher-order unit that implements 
collector^ by wrapping an existing collector^ implementation. For example, I 
could write a unit that applies the “base” collector to a doubled list:

(define-unit twice-collector@
  (import (rename collector^ [base:collect collect]))
  (export collector^)

  (define (collect . xs)
(apply base:collect (append xs xs

However, this fails with the following error message:

define-unit: import item/c is exported

The error message is not wrong — item/c is indeed re-exported by 
twice-collector@, but this is because twice-collector@ doesn’t care about 
item/c, only collect. However, I can accept that this program is rejected, 
since it isn’t clear how to link twice-collector@ with a base collector; there 
would be two different units that export collector^ in a single compound unit. 
Therefore, it seems that the intended solution would be to tag the import:

(define-unit twice-collector@
  (import (tag base (rename collector^ [base:collect collect])))
  (export collector^)

  (define (collect . xs)
(apply base:collect (append xs xs

However, this program is still rejected with the same error message. In this 
case, I can’t understand why.

One alternative is to avoid using the import mechanism altogether and instead 
define twice-collector@ as a function, creating a sort of “unit mixin”:

(define (twice-collector@ base-collector@)
  (unit
(import)
(export collector^)

(define-values/invoke-unit base-collector@
  (import)
  (export (rename collector^ [base:collect collect])))

(define (collect . xs)
  (apply base:collect (append xs xs)

This works, but it seems a little bit silly, since it effectively performs the 
linking manually and runs around the linker.

What is the “correct” way to write higher-order units? I looked for ideas in 
the original units paper (Units: Cool Modules for HOT Languages), and it seems 
to just use the function approach I mentioned above, but the system it 
describes is meaningfully different from the one implemented in Racket, and I 
can’t find very much information about the design of the Racket system.

Alexis

-- 
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.


Re: [racket-users] Scribble xref links in frog

2018-10-08 Thread Alexis King
IIRC, --redirect-main only applies to packages installed in installation scope, 
not packages installed in user scope. I don’t know why this is the case, and I 
don’t know if it’s a bug or a (mis)feature, I just vaguely remember running 
into that problem before when using --redirect-main. You might try moving 
everything into installation scope to see if that changes things.

> On Oct 8, 2018, at 15:07, Greg Hendershott  wrote:
> 
> Is this for .md or .scrbl sources?
> 
> If scribble: It's been some years since I worked on this, but at a
> quick glance Frog is running Scribble with --redirect-main
> http://docs.racket-lang.org/
> 
>
> https://github.com/greghendershott/frog/blob/master/frog/private/read-scribble.rkt
> 
> So I'm not sure what's going on. Maybe easier (for me anyway) if you
> open an issue there to discuss and investigate more?
> 
> p.s. It would probably be nice to update the docs.racket-lang.org URL
> to use https, if that's an easy PR you wanted to do?
> 
> On Mon, Oct 8, 2018 at 2:50 PM Eric Griffis  wrote:
>> 
>> My frog-generated blog is almost ready, but there's one detail stopping
>> the show:
>> 
>> Is there a way to make frog link to docs.racket-lang.org for all scribble
>> cross-references?
>> 
>> Exports from the "special" modules (racket/base, racket, ...) already
>> point to docs.racket-lang.org, but cross-referencing into other
>> locally-installed packages produces relative URLs to the local docs.
>> 
>> In the Scribble docs (7.2 Handling Cross-References), I found this:
>> 
>>The --redirect-main flag for HTML output redirects links to the local
>>installation’s documentation to a given URL, such as
>>http://docs.racket-lang.org/.
>> 
>> Is there some way to pass this flag or emulate its behavior in frog?
>> 
>> Eric

-- 
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.


Re: [racket-users] Racket-on-Chez snapshots

2018-10-02 Thread Alexis King
> On Oct 1, 2018, at 13:07, Brett Gilio  wrote:
> 
> Hey, could you provide a resource with more information on Chez possibly
> replacing the Racket VM? I haven't been keeping up to date on this.

>From an interaction between Greg Trzeciak and Matthew Flatt on the slack 
>channel:

> Greg: is there a chance for a post (blog or mailing list) summarizing the 
> "state of racket" talk for those of us who didn't attend racketcon?
> 
> Matthew: Yes (or planned, at least), in two parts. The first part will be a 
> blog post that mostly reflects the Racket-on-Chez results that I reported at 
> the Scheme workshop. That talk was recorded, so I expect it will be available 
> as video at some point. The second will be a how-to post on modifying 
> Racket-on-Chez.

So even if you weren’t at RacketCon, there are plans to provide a more current 
update at some point (hopefully soon).

-- 
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.


Re: [racket-users] Compilation/Embedding leaves syntax traces

2018-09-25 Thread Alexis King
(Sorry, Paulo, for the duplicate message; I forgot to Reply All the
first time.)

This is sort of subtle. When we consider a macro-enabled language, we
often imagine that `expand` takes a program with some phase ≥1 code,
expands all the macros in the program by running the phase ≥1 code, and
produces a fully-expanded program with only phase 0 code left. There is
some truth to this, but it doesn’t paint the whole picture.

Let’s start with the things that ARE true:

   1. When a module is compiled, it is fully expanded.

   2. Fully-expanded code contains no macro uses.

   3. Instantiating a compiled module at phase 0 does not normally run
  any phase ≥1 code, unless the module uses reflective operations
  like dynamic-require that may trigger compilation of other
  modules at runtime or explicitly instantiate modules into a
  namespace at phase ≥1.

These three things align with our intuition. If you have the program

   (+ (mac) 1 2)

where `mac` is a macro, then when the module is compiled, the use of
`mac` goes away, and it is replaced with its expansion.

Now, let’s add one more true thing to the list that aligns with our
intuition, but hints at something more complicated:

   4. When a module is expanded, all LOCAL macro definitions disappear.

This means that if you define a macro with let-syntax (or, equivalently,
define-syntax in an internal definition context), then all of the code
that implements that macro goes away after expansion. This is consistent
with our intuition, but it begs the question: why does this only happen
for local macros? Shouldn’t this happen for all macros?

Sadly, no. Consider the following module:

   (module m racket
 (provide mac)
 (define-syntax (mac stx)
   ))

In this case, the RHS of the `mac` definition must remain in the
compiled code, since some other module could require `m` and use `mac`.
Although the RHS of the `mac` definition is not evaluated when `m` is
instantiated at phase 0 (as is specified by rule 3 above), it must be
evaluated during compilation of another module that uses `m`.

(The technical term for this in Racket is called “visiting” the module.
This process of evaluating the RHS of define-syntax forms during module
visits also applies to any forms inside begin-for-syntax blocks, and a
visit also instantiates any modules required for-syntax by the visited
module. The nitty-gritty details are subtle, but this explains why code
on the RHS of module-level define-syntax forms or inside
begin-for-syntax blocks must be kept around in compiled code.)

The above explains why Racket retains some phase ≥1 code. However, it
may be unsatisfying: while it’s true that the phase ≥1 code might be
necessary for compilation of other modules, once you have compiled your
whole program, it shouldn’t be necessary to keep that information
around, right? No other modules will ever need to be compiled against
the macro-providing module. However, this is not necessarily true!
Racket provides a set of reflective operations for compiling modules at
runtime, and it makes no assumptions that all modules will be loaded
from compiled code. In this sense, Racket includes an “open-world
assumption” when compiling modules, and it retains any phase ≥1 code
necessary for compiling new modules at any time.

This sort of thing is necessary to implement tools like DrRacket, which
frequently compile new modules at runtime, but admittedly, most programs
don’t do any such thing. Personally, I would appreciate a way to ask
Racket to strip all phase ≥1 code and phase ≥1 dependencies from a
specified program so that I can distribute the phase 0 code and
dependencies exclusively. However, to my knowledge, Racket does not
currently include any such feature.

For more information on declaring, instantiating, and visiting modules,
and how that relates to compilation, see this very helpful section in
The Racket Guide:

   http://docs.racket-lang.org/guide/macro-module.html

Alexis

> On Sep 25, 2018, at 07:32, 'Paulo Matos' via Racket Users 
>  wrote:
> 
> 
> Hi,
> 
> I reached a point at which I don't think I am exactly understanding how
> the racket compilation pipeline works.
> 
> My software has several compile time options that use environment
> variables to be read (since I can't think of another way to do it) so I
> define a compile time variable as:
> 
> (define-for-syntax enable-contracts?
> (and (getenv "S10_ENABLE_CONTRACTS") #true))
> 
> And then I create a macro to move this compile-time variable to runtime:
> (define-syntax (compiled-with-contracts? stx)
> (datum->syntax stx enable-contracts?))
> 
> I have a few of these so when I create a distribution, I first create an
> executable with (I use create-embedding-executable but for simplicity,
> lets say I am using raco):
> S10_ENABLE_CONTRACTS=1 raco exe ...
> 
> I have a bunch of other options that don't matter for the moment.
> 
> One of the things I noticed is that in some cases when I run my
> 

Re: [racket-users] colon keywords

2018-09-19 Thread Alexis King
I’m surprised this hasn’t been discussed yet: Alex Knauth has a set of 
meta-languages that add support for :kw or kw: syntax for keywords to arbitrary 
#langs (assuming they use readtables).

http://docs.racket-lang.org/colon-kw/index.html

Whether or not actually using these meta-languages is a good idea is left up to 
the reader. :)

> On Sep 19, 2018, at 03:56, Neil Van Dyke  wrote:
> 
> Currently, in main Racket reader, `#:` starts a keyword, as in `#:foo`.
> 
> Who on this email list would also like (or not like) `:` to start a keyword, 
> as in `:foo`?
> 
> And, if you want the reader to also support `:foo`, would you want the writer 
> to default to writing `:foo` rather than `#:foo` (and how much would you want 
> that)?  And in the documentation?
> 
> (I've wanted "colon keywords" since keywords were first added to Racket, but 
> have been dutifully enduring the "hash-colon", rather than make anyone who 
> uses my open source packages depend on an additional package for my own 
> variant of `#lang racket/base`.  But, after many years of this, I still 
> dislike typing and looking at `#:`.  I know some people don't understand why 
> anyone cares (or suspect bikeshedding), but I get the impression that this is 
> getting into cog-sci differences between individual programmers.  Maybe one 
> way to look at it is a vague "programmer preference", like light vs. dark 
> screen background, rather than try to argue that no one should want to do it 
> that way.  Then the question might be: how popular is this "colon keyword" 
> programmer preference?  Which is why I'm asking the email list.)

-- 
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.


Re: [racket-users] [Racket Users] Macros and literals question

2018-09-17 Thread Alexis King
> On Sep 17, 2018, at 12:21, Kevin Forchione  wrote:
> 
> That seems to be the nature of macros, and I’m not sure what the solution to 
> that paradox is, apart from perhaps building a symbol/function hash table as 
> part of a define. Presumably Racke does something like that for eva & 
> namespaces, but I’m surprised there isn’t a symbol->procedure function. 

In general, I think Philip has hit the nail on the head. I, too, thought of 
other Lisp systems when you used the wording “associated procedure” for a 
symbol, and I agree that concept makes less sense in Racket. In a more 
traditional Lisp, symbols themselves are rich values with lots of information 
attached to them, but Racket follows the Scheme approach, which treats symbols 
as nothing more than interned strings. They are just names, not bindings.

To elaborate a little more on this, it might make sense to think of the 
“associated procedure” for a symbol in Common Lisp, but in Racket, that 
information is stored in a separate place: namespaces. A Racket namespace 
represents an environment, and it maps names to values. At runtime, if you want 
to get the value bound to a particular symbol in a given namespace, you can use 
namespace-variable-value[1], but there are some caveats to that.

As mentioned above, in Common Lisp, a package-qualified symbol is precise, but 
a Racket symbol is only meaningful in context. This means that the symbol 'foo 
might be mapped to one thing in one namespace but something completely 
different in another namespace. This is a philosophically different approach to 
binding, but the practical takeaway is that you need to be really careful to 
use the *right* namespace if you want to use namespaces in Racket. A namespace 
can be created that corresponds to the top-level of a module, using 
module->namespace, or it can be an entirely independent, “free-floating” 
top-level environment created with make-base-namespace. You can acquire a 
namespace that corresponds to the surrounding lexical environment using 
define-namespace-anchor[2] and namespace-anchor->namespace[3] or 
#%variable-reference[4] and variable-reference->namespace[5].

However, beware! As Philip alludes to, namespaces only include top-level or 
module-level bindings, *not* local bindings! Racket provides no reflective 
capabilities to inspect local bindings (at least not in general; you could 
theoretically write a #lang that implements this capability yourself). These 
are opaque, and indeed, the Racket compiler does not maintain information about 
the structure of local bindings.

To summarize: Racket is a relatively static language relative to other Lisps, 
and even to other Schemes. The language is entirely {lexically, statically} 
bound. It provides limited reflective capabilities to manipulate top-level 
namespaces and inspect module-level bindings, but no more. There are definitely 
various advantages to this (e.g. local reasoning, encapsulation, optimization), 
but you may need to think differently about Racket’s binding model if coming 
from other Lisp systems.

Alexis

[1]: 
http://docs.racket-lang.org/reference/Namespaces.html#%28def._%28%28quote._~23~25kernel%29._namespace-variable-value%29%29
[2]: 
http://docs.racket-lang.org/reference/Namespaces.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define-namespace-anchor%29%29
[3]: 
http://docs.racket-lang.org/reference/Namespaces.html#%28def._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._namespace-anchor-~3enamespace%29%29
[4]: 
http://docs.racket-lang.org/reference/Locationsvariable-reference.html#%28form._%28%28quote._~23~25kernel%29._~23~25variable-reference%29%29
[5]: 
http://docs.racket-lang.org/reference/Namespaces.html#%28def._%28%28quote._~23~25kernel%29._variable-reference-~3enamespace%29%29

-- 
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.


Re: [racket-users] How do I get negative blame information?

2018-09-10 Thread Alexis King
I think the answer here really is “don’t use `contract` directly”. The
actual implementation of the contract system does some fancy rebinding
of my-func when you use define/contract, turning this:

   (define/contract x ctc rhs)

into this:

   (define x-awaiting-neg
 (let ([tmp rhs])
   (lambda (neg) (contract ctc tmp 'x neg

So specifying the negative party is deferred. It then defines an
additional syntax binding that supplies the negative party based on the
use site of x, which works like something along these lines:

   (define-syntax x
 (make-variable-like-transformer
   #'(x-awaiting-neg (quote-module-name

where `quote-module-name` comes from syntax/location.

This isn’t 100% accurate to what the contract system actually does, but
the gist is that the negative party represents the client, so somehow
you need to arrange for a different value to be supplied depending on
what the client party actually is.

Getting this right is tricky, so stick to contract-out, define/contract,
with-contract, and define-struct/contract, which are the sanctioned
contract attachment forms. For macros, there’s also `expr/c` syntax
class from syntax/parse and the equivalent `wrap-expr/c` function from
syntax/contract. Those will work out the tricky machinery for you behind
the scenes, and they usually cover all the potential use cases. If you
have some other use case that isn’t served by those contract attachment
forms, by all means share it, but it’s hard to advise how to use
`contract` properly in a vacuum.

> On Sep 10, 2018, at 12:40, David Storrs  wrote:
> 
> (define (my-func thunk-arg)
> (contract  integer? (thunk-arg) 'my-func ))
> 
> What should I replace  with?
> 
> 
> NB: I know that in the example I could do 
> (define/contract (my-func thunk-arg) (-> (-> integer?) integer?) 
> (thunk-arg))
> but I'm looking for an answer to the generic case.

-- 
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.


Re: [racket-users] How to handle define forms in a scribble-like language

2018-08-16 Thread Alexis King
You might find make-wrapping-module-begin from syntax/modbeg useful here:

  
http://docs.racket-lang.org/syntax/module-helpers.html#%28def._%28%28lib._syntax%2Fwrap-modbeg..rkt%29._make-wrapping-module-begin%29%29

Alexis

> On Aug 16, 2018, at 18:58, Vityou  wrote:
> 
> I'm attempting to make a language similar to scribble.  I'm using the 
> `make-at-reader` that scribble provides, and have my module-begin as this:
> 
> (define-syntax md-module-begin
>   (syntax-parser
> [(_ (expr1 ...)) #'(#%module-begin (define doc (parse-markdown 
> (string-append (begin expr1) ...)))
>(provide doc)
>doc)]))
> 
> This works good for normal expressions, but when I try to do something like 
> `define`, it complains that it is not allowed in expression context.  I tried 
> fixing this by wrapping expressions in `begin`, but I still get the same 
> error.  Is there any way to fix this?  Thanks for any help.

-- 
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.


Re: [racket-users] all-fields-visible? attribute of struct-id -- What is it?

2018-08-16 Thread Alexis King
> On Aug 16, 2018, at 15:35, David Storrs 
> wrote:
> 
> struct-id from (require syntax/parse/class/struct-id)  has an
> all-fields-visible? attribute.  I've looked around and can't figure
> out what would cause a field to not be visible.  Can someone point me
> to the relevant part of the FM?


Unfortunately, I’m not sure this is super well-documented. The most
relevant section is the one entitled “Structure Type Transformer
Binding”[1], which describes the pieces of information associated with
a structure type at compile-time. However, it doesn’t really explain why
certain fields might not be known.

The only way all-fields-visible? can be #f, as far as I know (assuming
you’re not doing anything weird with prop:struct-info), is if you use
the #:super option of the struct form. This allows you to specify the
supertype of a struct using a (runtime!) structure type descriptor,
which may have been created directly using make-struct-type rather than
using the struct form. Since this is a dynamic value that can be
produced by an arbitrary expression, nothing can be known in this case
about the supertype at compile-time.

If you aren’t using the #:super option of the struct form, I don’t think
all-fields-visible? should ever be #f.

Alexis

[1]: http://docs.racket-lang.org/reference/structinfo.html

-- 
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.


Re: [racket-users] What are disappeared-uses?

2018-08-16 Thread Alexis King
> On Aug 16, 2018, at 15:25, David Storrs 
> wrote:
> 
> I see 'record-disappeared-uses' and 'with-disappeared-uses' in the
> docs, but there's nothing that makes clear what you would use them
> for.  Some digging around on the mailing list suggests that they allow
> Dr Racket to draw an arrow to a relevant source location.  Do they
> have any use outside of Dr Racket?


They’re also utilized by racket-mode (since racket-mode uses the same
Check Syntax implementation that DrRacket does), as well as a couple
other tools that statically analyze Racket programs (such as Ryan’s
check-requires tool). They are only used by tooling, and they do not
otherwise affect the behavior of Racket programs, but they should be
used by “well-behaved” macros so that various tools can understand
things lost in the process of macroexpansion.

To give an example, consider syntax-parse’s pattern language. When you
write a pattern like

(~optional (~seq #:opt opt-val))

then the identifiers ~optional and ~seq do not actually appear anywhere
in the expansion, since they get compiled by syntax-parse into
pattern-matching forms. However, users would still like to be able to,
say, open the documentation for ~optional in DrRacket or racket-mode. A
naïve implementation of syntax-parse would make this impossible, since
DrRacket and racket-mode inspect the fully-expanded program, and by the
time the program has been expanded, those identifiers are gone.

You can see this for yourself by writing a small macro that uses the
#:literals feature of syntax-parse. For example:

(define-syntax-parser m
  #:literals [=>]
  [(_ x => f)
   #'(f x)])

If you write the expression (m #t => not), then DrRacket or racket-mode
will be able to open the documentation or report the location of the
definition of the not function, but they won’t be able to tell you
anything about the => binding, even though it is documented and is
defined in racket/base. To help Check Syntax out, a “well-behaved” macro
should add the 'disappeared-use syntax property to the expansion for use
by tools, like this:

(define-syntax-parser m
  #:literals [=>]
  [(_ x (~and => arrow) f)
   (syntax-property
#'(f x)
'disappeared-use
(list (syntax-local-introduce #'arrow)))])

Now, tools will be able to detect the use of the => identifier and
behave accordingly.

Doing this bookkeeping is laborious, so I’m happy to report that, when
using syntax-parse, disappeared uses of #:literals can be tracked
automatically as of Racket v7.0. A simpler way to define the
well-behaved version of m would be to use the new #:track-literals
option:

(define-syntax-parser m
  #:literals [=>]
  #:track-literals
  [(_ x => f)
   #'(f x)])

This will work as intended. For all uses of #:literals or ~literal,
syntax-parse will automatically add the necessary 'disappeared-use
property to the output when #:track-literals option is specified.
(Sadly, making this the default could not be done in a completely
backwards-compatible way, so it needs to be opt-in for now.)

In general, when a macro inspects syntax from its input, but throws that
syntax away in its expansion, it should probably include a
'disappeared-use property to communicate this information to tools.
Otherwise, in addition to potentially causing DrRacket and racket-mode
to be less helpful than they could ideally be, it might also cause tools
to mistake identifiers as being completely unused when they actually are
— for example, a require might be marked as unused if it’s only imported
to access a particular literal identifier.

Macros that don’t properly record disappeared-uses are not going to
cause any catastrophic problems, so the bookkeeping might not be worth
the mental overhead to you. It would be nice if the manual annotations
weren’t necessary at all. Still, I think it’s a nice feature, and I find
it annoying when macros I use don’t properly report their disappeared
uses.

Alexis

-- 
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.


Re: [racket-users] Testing & global variables

2018-08-07 Thread Alexis King
I guess I’ll take the bait and give the obvious-but-unhelpful answer,
“Don’t use global variables.” :)

I’m joking, but only just barely. It seems difficult to give concrete
advice without knowing more details about your program and why you felt
it was necessary to use global mutable state in the first place, so
absent some reason why you need them, I have to recommend you just
refactor your code to eliminate the globals. The standard techniques for
writing testable code in other languages still apply in Racket, most
notably dependency injection (aka “passing arguments to functions”).
Racket also provides a few tools of its own for managing that kind of
dynamic parameterization, such as parameters and units.

Theoretically, an alternative solution would be to create a separate
namespace (via racket/sandbox or otherwise) for each test file, allowing
each test to use its own instantiation of the library. This almost
certainly isn’t what you actually want, though, since real (non-test)
clients of your library will bump into the same problem, and expecting
them to do the same workaround is unreasonable. Indeed, I think the
difficulty of testing an API like this means the the test suite is doing
what it probably should: hinting that your API is hard to work with and
needs to be changed.

Alexis

> On Aug 7, 2018, at 12:29, Kevin Forchione  wrote:
> 
> I’ve got a library that takes  maintains global variables. I’d like
> to be able to test different test files that require this library, but
> of course if I require those files into a single test file for testing
> various combinations of data it corrupts the global variables, which
> are only valid for a single instance of test file.
> 
> Conceptually it looks like:
> 
> Library-File
>   global a
>   library-functions
> Test-file-1
>   require Library-file
>   test-data-file-1
> Test-file-2
>   require Library-file
>   test-data-file-2
> Master-test-file
>   require Test-file-1 Test-file-2 ;; doesn’t work of course….
> 
> Any suggestions are appreciated.
> 
> Kevin

-- 
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.


Re: Parameters considered often harmful (was: Re: [racket-users] Re: A (long) question regarding parameters and scope)

2018-08-03 Thread Alexis King
Maybe this isn’t really a direct response to the direction this thread
has taken, but given the question proposed in the original message, I
think it’s relevant to share a particular design pattern for parameters
that seems to work well. In a number of different APIs provided by
Racket, a function’s behavior can be controlled by an optional argument
(often a keyword argument), and that argument’s default value is the
value of a parameter. For example, the eval function accepts an optional
namespace as its second argument, and if it isn’t supplied, it uses
(current-namespace).

>From a user’s point of view, this is the best of both worlds, since they
can parameterize a set of function calls in a single parameterize block
without needing to thread an argument everywhere, taking advantage of
parameters’ capability for implicit configuration, but they can also
pass an argument directly if they’re only calling a function once or
twice. However, this *also* has benefits for implementors, since it
sidesteps the inability to close over the value of the current
parameterization since the value becomes entirely lexical when it is
bound to the formal argument of the function.

For a simple example, consider a contrived function configured by a
parameter:

  (define current-summand (make-parameter 0))

  (define (make-adder)
(lambda (n) (+ (current-summand) n)))

This is a silly function, but one can see how it is broken in the way
Alex describes (which he shows can happen in more realistic situations).
The intent is to close over the current value of (current-summand) when
make-adder is invoked, but a naïve implementation doesn’t capture the
current value and always produces the same function. Adjusting this
function that the summand is provided as an optional argument both
improves the user-facing API and fixes the bug:

  (define (make-adder [summand (current-summand)])
(lambda (n) (+ summand n)))

This also ensures that if a parameter-configured function defers to
other functions as part of its implementation, it will pass the value
lexically rather than dynamically by explicitly providing the optional
argument, so the dynamic configuration is effectively “terminated” at
the API boundary.

Now, this isn’t to say this technique doesn’t have some drawbacks. For
one, it means API users get to benefit from the dynamic configuration,
but API implementors do not, and in fact have to do extra work.
Furthermore, one might find the very existence of a “design pattern” in
Racket to be suspect, given we generally try to avoid boilerplate
patterns in favor of new linguistic abstractions. Maybe this hints at
some shortcoming in parameters that would be better solved by a new
language feature, but I can’t immediately come up with one. Perhaps
others have better ideas than I do in that department.

> On Aug 2, 2018, at 12:24, 'John Clements' via Racket Users
>  wrote:
> 
> I hate to turn a little question into a big one, but… are parameters
> the right choice, here? It seems to me that optional parameters would
> be more suitable.
> 
> Unfortunately, I’ve been on the other side of this fence, too:
> parameters are vastly more convenient for implementors than adding
> optional parameters to every one of the internal calls. This certainly
> came up for me in the construction of a CSV writing library.
> 
> I can imagine a bunch of programming patterns that might assist this;
> the most obvious one would be an object-like metaphor where parameter
> values are represented as an object to which calls are made. Do others
> have ideas on a “best practice” for this situation and others like it?
> 
> John

-- 
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.


Re: [racket-users] Questions on functional-setter generator macro

2018-05-26 Thread Alexis King
This isn’t a direct answer to your question, but as Matthias notes, my
struct-update package already implements a macro that generates
functional setters from structure definitions. Here’s a link to the
documentation:

http://docs.racket-lang.org/struct-update/index.html

Of course, that isn’t especially helpful if your goal is to get better
at authoring macros, not just generate functional setters. For that, you
might find the (short) source code of struct-update helpful, located
here:


https://github.com/lexi-lambda/struct-update/blob/8ce456cde8764ae27c348123ec9e01e76826d536/struct-update-lib/struct-update/main.rkt

Admittedly, your make-functional-setter function does a bit more than
define-struct-updaters, since it allows for a wrapper function. So I’ll
also give some brief answers to a few of your unrelated questions.

> On May 26, 2018, at 10:46, David Storrs 
> wrote:
> 
> A) Is there a way to test if a syntax class has a particular attribute
> before trying to use it?

Yes, use the attribute form. If x is an optional attribute, (attribute
x) will be #f if the attribute was not bound and the value of the
attribute if it was bound. If you want, you can change the default value
to something else other than #f by providing the #:defaults option to
~optional.

> B) Alternatively, is there a way to create a null syntax object that
> expands to nothing?  Not (void), not "", literally nothing.   Then I
> could have each pattern bind all the attributes via #:with and just
> have some of them be blank.

Not in an arbitrary context. In a definition context, (begin)
effectively expands into nothing, since begins are spliced into the
enclosing context, but in an expression context, you can’t have
something that expands into nothing.

That said, it sounds like what you might actually want is the template
and ?? forms from syntax/parse/experimental/template. This allows you
to write something like this:

(template (foo (?? x)))

The above will be like #'(foo x) if (attribute x) is non-#f, but if it
is #f, it will be like #'(foo). In Racket 6.12 and earlier, you must use
the template form for ?? to work, but in Racket 7 and later, ?? will
also work with the ordinary syntax (aka #') form, so if the word
“experimental” spooks you, don’t worry about it too much.

Alexis

-- 
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.


Re: [racket-users] How to handle circular 'requires'

2018-05-14 Thread Alexis King
In addition to what Matthias says, you can also sometimes break these
kinds of cycles using lazy-require, which defers the requiring the other
module until it is first needed. This is simpler than using units and
provides stronger guarantees than using callbacks, but it is a bit more
ad-hoc than both of them, and it only works when the lazily-loaded
module isn’t needed as part of module initialization (that is, the
function isn’t called from the top level of a module). When it works,
though, it can be a less invasive solution to the problem.

Alexis

> On May 14, 2018, at 4:28 PM, David Storrs  wrote:
> 
> My application retrieves chunks of files from the network and writes
> them to disk, as well as writing certain data about them to the
> database (e.g. where they are on disk and where they came from on the
> network).
> 
> I've split these functions into separate files:
> 
> app/network/chunks.rkt
> app/lib/db/chunks.rkt
> 
> This worked fine until now, but I've gotten to a point where they're
> circular -- the network code needs to receive the chunk and then
> forward it to the DB code, but if certain error conditions come up
> then the DB code needs to tell the network code to re-request the
> data.
> 
> There's various ways I could work around this (simplest being to put
> all the functions in one file), but I'm wondering if there's a
> recommended way?  C would solve this with a .h file.  Perl would solve
> it with function prototypes (or simply be able to sort it out without
> intervention).  What is the preferred Racket way, or am I simply not
> thinking about it correctly?

-- 
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.


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

2018-05-08 Thread Alexis King
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  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...:
>#
>#(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 

Re: [racket-users] question on quasisyntax/loc

2018-05-08 Thread Alexis King
This behavior is intentional, though it could perhaps be more clearly
documented. The behavior is hinted at in the documentation for
syntax/loc:

> Like syntax, except that the immediate resulting syntax object takes
> its source-location information from the result of stx-expr (which
> must produce a syntax object), unless the template is just a pattern
> variable, or both the source and position of stx-expr are #f.

Note the “unless the template is just a pattern variable” condition. The
idea is that syntax/loc and quasisyntax/loc only ever adjust the source
location information on fresh syntax introduced in the template, never
on syntax from external pattern variables or syntax objects inserted
with unsyntax. For this reason, (quasisyntax/loc stx #,x) is always
equivalent to x.

If you do actually want to modify the source location information on a
syntax object, you can do it with syntax-e and datum->syntax:

  (define (replace-outer-srcloc src-stx stx)
(datum->syntax stx (syntax-e stx) src-stx stx))

Then you could write (replace-outer-srcloc here y) to get the behavior
you want.

Alexis

> On May 8, 2018, at 09:56, Luke Whittlesey 
> wrote:
> 
> I'm having trouble understanding quasisyntax/loc in some cases.
> 
> If I have the following example code:
> 
> 
> #lang racket
> 
> (define here #'here)
> (define stx0 (syntax/loc here #'Y))
> (define y #'Y)
> (define stx1 (quasisyntax/loc here #,y))
> 
> (displayln (format "here : line ~a" (syntax-line here)))
> (displayln (format "stx0 : line ~a" (syntax-line stx0)))
> (displayln (format "stx1 : line ~a" (syntax-line stx1)))
> 
> 
> It prints :
> 
> here : line 3
> stx0 : line 3
> stx1 : line 5
> 
> 
> I expect stx1 to also be at line 3 where `here` is defined. Is this
> example an incorrect use of quasisyntax/loc? What am I missing?
> 
> Thanks,
> Luke

-- 
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.


Re: [racket-users] what do people use for number formatting?

2018-05-07 Thread Alexis King
I second ~r. It will round when given a precision.

> On May 7, 2018, at 18:56, Stephen Chang  wrote:
> 
> Oops, I didnt see the rounding.
> 
> On Mon, May 7, 2018 at 7:53 PM, Ben Greenman
>  wrote:
>> I use this:
>> http://docs.racket-lang.org/gtp-util/index.html#%28def._%28%28lib._gtp-util%2Fmain..rkt%29._rnd%29%29
>> 
>> I didn't know about SRFI 54 --- looking forward to reading other responses.

-- 
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.


Re: [racket-users] Parametric composition?

2018-05-04 Thread Alexis King
Your composex macro is very similar to the various forms from the (as far as I 
can tell) fairly well-known threading package:

 http://docs.racket-lang.org/threading/index.html

Disclaimer: I am the author of the threading package.

In any case, there are some differences, but it has the same general feel, and 
it might suit your needs.

Alexis

> On May 4, 2018, at 14:57, dexterla...@gmail.com wrote:
> 
> Hi there,
> 
>  This is my first post, pardon my ignorance. I have been using a homemade 
> macro to compose functions together, but still allow semi-currying of 
> functions (with lambdas) to keep control of the parameters :
> 
> (define-syntax (composex stx)
>  ; macro to compose functions passing an 'x' parameter
>  (syntax-case stx ()
>((_ f1 ...)
> (with-syntax ([x-var (datum->syntax stx 'x)])
>   #'(compose1 (λ (x-var) f1) ...)
> ; unit test
> (check-equal? ((composex (string-replace x " " "-")
> (string-downcase x)
> (string-trim x)) "Hello World")
>  "hello-world")
> 
> 
> I often use this or (apply composex (reverse v)) to keep function 
> applications in order.
> 
> Can you comment on this? Do you think this could be part of the language?
> 
> Cheers,
> 
> Dexter
> 
> P.S. For use in the wild, see provide-generator. Makes generate-provide more 
> readable :
> https://github.com/DexterLagan/provide-generator

-- 
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] On Richard P. Gabriel’s “The Structure of a Programming Language Revolution”

2018-04-18 Thread Alexis King
Hello all,

I have a rather different sort of question to ask about from my usual
fare. A month or two ago, I read an essay written by Richard P. Gabriel
and published at Onward! 2012 called “The Structure of a Programming
Language Revolution”. The essay itself is available here to those
interested in reading it:

http://dreamsongs.com/Files/Incommensurability.pdf

The essay covers a number of things, from CLOS and Smalltalk to the
concept of incommensurability, but one of the things I found most
intriguing was this thesis:

> The real paradigm shift? Systems versus languages. Before 1990, a
> person interested in programming could work comfortably both in
> programming languages and in programming systems, but not so easily
> after. To tell the truth, I never even noticed the different words —
> language versus system — never attached any significance to the word
> choice until this exploration. I used the phrases interchangeably for
> many years: Programming System / Programming Language.

Gabriel goes onto elaborate on the difference between so-called “systems
thinking” and “language thinking”. From his perspective, Common Lisp
sits squarely in the “systems” camp, and Scheme in the “language” camp.
He makes the claim that the amount of effort Common Lisp dedicates to
things like redefinition to support a running system are the effect of
systems thinking, which has more or less fallen out of favor in the
academic community in recent decades.

This got me thinking about Racket, since much of Racket sits firmly in
the language thinking camp. Racket focuses on the language being a
single source of truth, on soundness, on syntactic properties and formal
semantics. It discourages things like long-running systems and dynamic
reflection. On the other hand, Racket is clearly made up of many systems
in addition to its many languages: the macro system, the
chaperone/impersonator system, and the namespace system all come to
mind. (On the other hand, perhaps the line is much blurrier than Gabriel
would have one believe: do contracts really belong cleanly to either
philosophy?)

Since then, I’ve wondered what thoughts other Racketeers would have in
response to Gabriel’s essay. The ability to have a live, dynamic system
akin to Common Lisp’s images is a useful feature, but it certainly
requires “systems thinking”, and it is unsatisfying from a “language
thinking” point of view. To pose a question to those who have been doing
this longer than me, do you think this proposed philosophical binary
really makes sense?  Does Racket really fit in more closely with one or
the other?  Philosophically, does Racket reject things like CLOS and
redefinition/long-running images just because they don’t work in the
edge cases, or is there some bigger picture here that I’m not seeing?

Thanks in advance for your thoughts,
Alexis

-- 
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] Reimplementing Hackett’s type language: expanding to custom core forms in Racket

2018-04-15 Thread Alexis King
Hello all,

I wrote a blog post about my recent experience rewriting the
implementation of Hackett’s internal type representation, and on writing
languages that expand to custom core forms in Racket in general. For
those interested in Hackett and/or (ab)uses of some of the lesser-known
features of Racket’s macro system, you might be interested:

  
https://lexi-lambda.github.io/blog/2018/04/15/reimplementing-hackett-s-type-language-expanding-to-custom-core-forms-in-racket/

I’ve refrained in the past from posting my blog to this list, since it
does not seem like something other people normally do and many of the
interested parties seem to find it through some other channel. Still, I
thought I’d try posting it here this time. Feedback is welcome and
appreciated, both on the blog post itself and on whether or not people
appreciate posting things like this to this list.

Alexis

-- 
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.


Re: [racket-users] Question about Racket design philosophy: returning (void)

2018-04-10 Thread Alexis King
> On Apr 10, 2018, at 14:00, David Storrs 
> wrote:
> 
> Aside from I/O, I can't think of too many cases where (void) is the
> intuitively correct or most useful return value, but it is extremely
> common throughout the built-in Racket functions.  I'm not sure where
> you're drawing the lines on 'API design' vs 'comprehensive
> guidelines', but I'd sure like it if the guideline "Always return
> something useful unless there's a really good reason not to" got
> included.

There is definitely a school of thought that buys into the idea of
returning “the thing being operated on” rather than returning nothing
for side-effectful functions. I think this is most characterized by
so-called “fluent interfaces”[1], a way of encoding DSLs into
object-oriented languages. As far as I can tell, this was style has been
around for a very long time, but it was really forced into mainstream
usage by the runaway success of jQuery in the mid to late aughts.

The advantage of fluent interfaces is significant if you have an API
that involves frequent object creation and mutation. It makes it
possible to program in a more expression-oriented style, similar to the
way the GoF builder pattern is useful in C++/Java-style OO languages.
However, it has a cost of imprecision: it’s not always clear which thing
is the most obvious to return, and it masks when functions exist solely
for side-effects. For an example of the first problem, consider the
jQuery $.append function[2]:

$('.foo').append($('Hello!'))

Which element does this return? Does it return the set of elements
produced by $('.foo'), or does it return the new element created by
$('Hello!')? Both answers are useful, and indeed, jQuery actually
includes a separate $.appendTo function[3] that does the exact same
thing as $.append but flips the arguments around, mostly to make the
method chaining work out more nicely in certain situations. This is an
awkward thing for an API designer to worry about; it is confusing for a
library to provide the exact same function that just happens to return
a different one of its arguments.

The other problem with always returning something is that returning
# is extremely meaningful: it means the function’s only purpose
is to perform a side-effect. When contracts (or, in a statically typed
language, types) are used precisely, they can be quite communicative
without having to read anything but the signatures alone. When given a
Racket function with the following signature:

(-> vector? exact-integer? any/c void?)

...it’s pretty likely that function is vector-set!. But now imagine the
same function returned the mutated vector:

(-> vector? exact-integer? any/c vector?)

Now it’s much less immediately clear that this function is intended to
be used to perform a side-effect, and I might misinterpret it as
returning a new vector instead of updating the existing one.

You might argue that the benefit in chaining outweighs the cost of
signature clarity, but I think Racket mostly eschews that idea because
Racket is a language with a functional bent. It discourages using
mutability where immutable structures will do, and of course, useful
functions on immutable data cannot return #. Therefore, it’s both
(1) rare for idiomatic Racket to use lots of functions that produce
#, so they wouldn’t benefit much from threading arguments through,
and (2) especially important that side-effectful functions are called
out as such as efficiently as possible.

Racket makes it easy to use the same value twice without forcing library
authors to arbitrarily pick certain arguments to thread through
side-effectful functions. Internal definition contexts are available
almost everywhere, and there is a plethora of local binding forms.
Ultimately, the choice to return # instead of some input argument
probably doesn’t dramatically help or harm the language (it would still
be Racket if it aligned with the other school of thought), but I happen
to like the choice Racket makes.

Alexis

[1]: https://en.wikipedia.org/wiki/Fluent_interface
[2]: http://api.jquery.com/append/
[3]: http://api.jquery.com/appendTo/

-- 
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.


Re: [racket-users] struct-copy question

2018-03-21 Thread Alexis King
> On Mar 21, 2018, at 15:32, Eric Griffis  wrote:
> 
> This would be a code smell if I didn't trust that our Racket ancestors
> knew what they were doing, so the notion of "fixing" structs (or even
> struct-copy) seems misguided.
> 
> [snip]
> 
> I can appreciate the architectural decision that structs represent for
> the core -- flexibility often comes with a cost to conciseness and
> convenience.

Without necessarily responding to all of your message, I think that it
would be an exaggeration to state that structs are the way they are
because they need to or ought to be that way. I was by no means using
Racket when most of the features that exist in the current struct system
were designed and implemented, but I believe I have heard or read it
said that certain choices are well-known to have been the wrong ones in
retrospect (#:transparent not being the default, for example).
Unfortunately, as you yourself say, they are used to represent nearly
everything in Racket, and redesigning them in a backwards-compatible way
is a daunting task.

On the one hand, I think Racket’s structures are fundamentally
challenging because they must accommodate dozens of use cases that are
necessary for Racket-the-platform but probably not directly relevant to
the majority of Racket programmers. For users, they would often like
them to be boring, plain old data types, but all sorts of other systems
need to be in place for other things to work. For example, they must be
chaperoneable/impersonatable in order for the contract system to work,
structure type properties exist to facilitate some sort of low-level
generic protocol mechanism, and structure inspectors allow privileged
tools to inspect the structure of “opaque” structures (though I’m not
actually sure what depends on this feature... DrRacket? ...the compiler
itself?).

On the other hand, certain things seem almost certainly incidentally
complex, like how the way the default printer prints structures is tied
to the structure’s inspector and how #:auto works. Generally, I think
#:auto is better avoided and replaced with your own wrapping
constructor, possibly using #:constructor-name to adjust the underlying
constructor name, but #:auto can’t be removed because Racket tries
pretty hard to never break backwards compatibility.

Alexis

P.S. Every so often someone kicks around the idea of “maybe we’ll fix
these things in a #lang racket2”, but that’s really just wishful
thinking at this point, given that I don’t believe anyone is working or
planning to work on implementing such a thing. Doing so is not trivial,
either, given that the two systems would need to be able to interoperate
to some extent.

-- 
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.


Re: [racket-users] Just how hard would it be to add a mutable toplevel language to Racket?

2018-03-21 Thread Alexis King
I haven’t actually used it myself, but Tony Garnock-Jones’s
racket-reloadable library seems interesting and relevant.

https://github.com/tonyg/racket-reloadable

Alexis

> On Mar 21, 2018, at 11:16, Christopher Lemmer Webber
>  wrote:
> 
> Hi Sam!  I wasn't familiar with racket/load and it seems neat.  But
> it either seems too hopeless, or not hopeless enough:
> 
>  Since all forms within a racket/load module are evaluated in the top
>  level, bindings cannot be exported from the module using provide.
> 
> This seems like a bit too much unfortunately.  If I were to be writing
> for instance a web application or a game or what have you, I'd still
> want the dynamism of being able to redefine things, but I'd also want
> to be able to export things from a module.
> 
> Maybe here's a properly hopeless level of indirection?  What if we had
> something like a lambda-box that for toplevel definitions of functions
> instead wrapped the function in a box.  It can still be invoked, but
> if redefined, the contents of the box could be swapped out with a new
> function?  That's not too far off from how Guile's redefining works
> presently, if I understand right.  Redefining a toplevel non-function
> could just set! the variable.
> 
> I guess maybe you couldn't provide more than what you've already
> provided from the module.  But that's probably okay?

-- 
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.


Re: [racket-users] struct-copy question

2018-03-19 Thread Alexis King
I’m late to this thread, but perhaps I can clarify some things that I
don’t think have been made entirely clear.

First of all, you are absolutely correct that structures, at runtime,
know nothing whatsoever about field names. At runtime, structures are
fancy vectors; the names provided for their fields just end up being
used to generate accessor functions that look up values at the
appropriate index.

So how do macros like match and struct-copy know what to do? Well, the
struct macro creates a transformer binding that holds static information
about the structure type, including the names of field accessors. As
Eric already demonstrated, you can access that information using
syntax-local-value combined with extract-struct-info, but that just
produces a list containing an assortment of information.

There is a library that provides a struct-id syntax class that makes it
easier to consume structure type transformer bindings:

  
http://docs.racket-lang.org/syntax-classes/index.html#%28form._%28%28lib._syntax%2Fparse%2Fclass%2Fstruct-id..rkt%29._struct-id%29%29

It works with syntax/parse, and it defines attributes with names that
handle the different sorts of things that can be produced by
extract-struct-info. Disclaimer: I am the author of the library.

Finally, I am not sure about the particular issue with struct-copy and
#:auto fields (which sounds fixable), but I think it is worth mentioning
that struct-copy is irreparably broken and cannot be fixed without
fundamental changes to Racket’s struct system. Namely, it has the
“slicing” problem familiar to C++ programmers when using struct
inheritance, and the way it synthesizes field accessors from the
provided field names is unhygienic and can be easily thwarted. See this
GitHub issue for more details:

  https://github.com/racket/racket/issues/1399

Alexis

-- 
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.


Re: [racket-users] syntax/parse is not hygienic

2018-03-05 Thread Alexis King
For those interested, it turns out you can get a loose approximation of
the van Tonder system in Racket in just a few dozen lines of code.
Namely, you can write a helper that undoes the macro-introduction scope
added by the Racket macro system:

(begin-for-syntax
  (define ((make-unscoped-transformer proc) stx)
(syntax-local-introduce (proc (syntax-local-introduce stx)

Then you can write some functions and forms for keeping track of which
scopes to add when users write quote-syntax:

(begin-for-syntax
  (define current-syntax-introducer (make-parameter #f))
  (define (current-syntax-introduce stx)
((or (current-syntax-introducer)
 (make-syntax-introducer))
 stx))

  (define (call-with-shared-syntax-introducer proc)
(if (current-syntax-introducer)
(proc)
(parameterize ([current-syntax-introducer
(make-syntax-introducer)])
  (proc
  (define (call-with-masked-syntax-introducer proc)
(parameterize ([current-syntax-introducer #f])
  (proc)))

  (define-simple-macro (with-shared-syntax-introducer
 body:expr ...+)
(call-with-shared-syntax-introducer (λ () body ...)))
  (define-simple-macro (with-masked-syntax-introducer
 body:expr ...+)
(call-with-masked-syntax-introducer (λ () body ...

You can define an introducing variant of quote-syntax in terms of
Racket’s quote-syntax:

(begin-for-syntax
  (define-simple-macro (quote-syntax form)
(current-syntax-introduce (quote-syntax/no-introduce form

And finally, you can implement syntax and quasisyntax in terms of these
other forms and functions. That part is the most amount of work, so I
haven’t implemented full versions of either, but I implemented
simplified versions that don’t handle ellipses and generate less optimal
code. The only interesting thing in their implementations is the
placement of with-shared-syntax-introducer and
with-masked-syntax-introducer. Both expand into uses of
with-shared-syntax-introducer, which is wrapped around the entire
expansion, and unsyntax must wrap its expression in
with-masked-syntax-introducer in its expansion. This produces a system
that seems to have the properties of van Tonder’s system in simple
situations.

Experimentation leads to some interesting behavior. For example, the
following macro is completely uninteresting in a system that uses scoped
expansion, but it’s quite interesting in one that uses scoped quotation:

(define x 'module)

(define-syntax mac
  (make-unscoped-transformer
   (syntax-parser
 [(_)
  #`(let ([x 'local])
  (list x #,#'x))])))

(mac)

Under scoped-expansion, the program produces the boring result '(local
local), but under scoped-quotation, it produces the much more
interesting result '(local module)! Maybe some people would find this
confusing, but I think it’s a little neat.

If anyone is interested in playing with my hacky, incomplete, and
probably buggy embedding of this system in Racket, I’ve posted it here:

  https://gist.github.com/lexi-lambda/a32aab1bb3eccd416764ef90cbd55b67

As a testament to the power of Racket’s macro system and its
macro-writing facilities, the whole thing is only 80 lines of code.

-- 
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.


Re: [racket-users] syntax/parse is not hygienic

2018-03-05 Thread Alexis King
Thank you to both of you for your detailed responses! I think this is
all fascinating.

> On Mar 5, 2018, at 05:18, Ryan Culpepper  wrote:
> 
> 1. Yes. To me, at least :) That aspect of hygiene is triggered by a
> macro expansion step, and the macro expansion step also defines the
> boundary of its effect. In other words, the expansion of a macro
> introduces a scope, but syntax classes do not. Compare with the
> following examples:

Yes, this is what I meant when I wrote that “Syntax classes behave like
phase 1 functions, not macros.” It is worth pointing out, however, that
not all things that behave like macros are strictly within the realm of
the macroexpander — things like match expanders and syntax/parse pattern
expanders manually emulate hygienic expansion despite not ever actually
yielding to “the” macroexpander.

> 2. I think the main technical challenge is finding all of the syntax
> objects to flip the scope on, given that syntax classes allow
> attributes to have arbitrary values (like opaque structures and
> closures), not just syntax objects. We have a similar problem with
> syntax properties, which are invisible to the hygiene algorithm.
> 
> It might be easier in a macro system like Andre van Tonder's system,
> as Matthew and Sam mentioned.

The parallel with syntax properties is a good one, and it’s something
that came to mind to me, too. It seems hard to solve in general
automatically, but some cooperation from the user might be enough (via
some generic protocol like structure type properties). That’s a bit
ugly, though.

> 3. Maybe. Half-baked musings follow:

If these are your half-baked musings, I would like to see what your
fully baked ones look like. :)

Your points are good ones, and I agree that I have virtually no
intuition for which places the boundaries make sense. I will say this,
however: while I have developed over the years a reasonably strong
intuition for how Racket macros operate, when I was learning the macro
system for the first time, I did not find some parts of the hygiene
algorithm terribly intuitive. The fact that quoted syntax could be in
wildly different lexical contexts but capture and bind the same
identifiers because they were in the same dynamic context seemed
antithetical to hygiene to me (which I heard described as “respecting
the lexical structure of the program as-written”).

I find André van Tonder’s system compelling, but I also agree I can’t
really evaluate it without trying to write some programs with it. Maybe,
with Racket 7, it’d be easier to implement such a macro system in a fork
of Racket for experimentation... but the result might be too
incompatible with existing code to serve any purpose. It would be an
interesting experiment.

> On Mar 5, 2018, at 06:45, Matthew Flatt  wrote:
> 
> Adding to Ryan's answer, I note that Andre van Tonder's SRFI-72 system
> has `quasisyntax` is a primitive. That is,
> 
>  #`(x #,y x)
> 
> is not like
> 
> (datum->syntax #'here (list #'x y #'x))
> 
> because the scope introduced by a `quasisyntax` spans the whole
> `quasisyntax` form and causes nested `syntax` forms to not introduce
> a fresh scope.

Yes, I noticed that, too. My assumption was that a form like
with-fresh-renaming-scope would be necessary, but it would be a little
bit different from the version originally described. Rather than require
it in order to produce distinct scopes from distinct uses of quotation,
keep the behavior of the final version of SRFI 72, but allow
with-fresh-renaming-scope (or, most likely, something similar but with
a more appropriate name) to *weaken*, not strengthen, the hygiene rules.

To illustrate, this would lead to the following behavior:

(bound-identifier=? #'x #'x) ; ==> #f

(with-fresh-renaming-scope
  (bound-identifier=? #'x #'x)) ; ==> #t

If uses of with-fresh-renaming-scope are nested, the outermost use
“wins”, yielding the following behavior:

(with-fresh-renaming-scope
  (bound-identifier=? (with-fresh-renaming-scope #'x)
  (with-fresh-renaming-scope #'x)))
; ==> #t

This would allow forms like quasisyntax to introduce
with-fresh-renaming-scope in their expansions to avoid distinct uses of
syntax from generating distinct identifiers while simultaneously
allowing new abstractions to be defined in terms of quasisyntax just as
quasisyntax is defined in terms of syntax.

Some parts of this are still a little unsatisfying, however. The draft
of SRFI 72 you link defines with-fresh-renaming-scope as applying
lexically, not dynamically, but it isn’t immediately obvious to me which
is the correct behavior in this case. Furthermore, if it applies
lexically, what does it mean when with-fresh-renaming-scope is
introduced by a macro? If it applies to all identifiers inside its
expansion, that feels unhygienic enough to cause trouble... so my own
intuition here is nonexistent.

As for looking at the discussion, it doesn’t appear to be 

Re: [racket-users] syntax/parse is not hygienic

2018-03-04 Thread Alexis King
Actually, what I wrote was wrong. The key piece of information I
overlooked was the following rule:

> A binding for an identifier can only capture a reference to another
> if both were present in the source or introduced during a single
> evaluation of a syntax or quasisyntax form, with the understanding
> that the evaluation of any nested, unquoted syntax or quasisyntax
> forms counts as part of the evaluation of an enclosing quasisyntax.

The key phrase is “single evaluation”, so quote-syntax becomes
generative: multiple evaluations of the same quote-syntax form use
distinct scopes.

This is interesting to me. It’s stricter than Racket’s model for
hygiene, since Racket makes it legal to do things like this:

(with-syntax ([def #'(define x 42)])
  #'(begin def x))

...which produces a piece of syntax that will evaluate to 42, unlike in
van Tonder’s model, in which it would produce an unbound identifier
error. Of course, this problem is not difficult to solve; it just
requires lifting #'x into a separate binding:

(with-syntax* ([id #'x]
   [def #'(define id 42)])
  #'(begin def id))

This model... makes sense to me. I like it. It seems, on the surface,
more intuitive than Racket’s model of introducing fresh scopes in the
expander itself. That said, it’s still quite different from Racket’s
model, so some of what I said in my last message still applies, I think.
I also wouldn’t be surprised if there were some infelicities in the
alternative approach I’m not immediately seeing (corner cases,
perhaps?).

While it’s a bit of a tangent, I’d be quite interested to finding more
information on this alternate model of hygiene from anyone familiar with
the tradeoffs (the SRFI that describes it does not include much in the
way of comparisons). Are there strong reasons to prefer Racket’s model
aside from backwards compatibility and mild convenience when
procedurally assembling pieces of syntax?

> On Mar 4, 2018, at 19:28, Alexis King <lexi.lam...@gmail.com> wrote:
> 
> Sam suggested I take a look at van Tonder’s work as well on Slack, and
> it’s interesting, though it isn’t what I originally had in mind. I
> think it would solve the first example of mine, but it would not solve
> the second. In the second example, all uses of tmp come from the same
> quote-syntax form, merely multiplied via ellipsis. My first mental
> model was to treat syntax classes under ellipses like distinct macro
> invocations, which would require a dynamic, not lexical, treatment of
> scope to be consistent with Racket’s model of hygiene.
> 
> If I’m understanding correctly, attaching fresh scopes at quotation
> rather than expansion treats the source text of the program as the
> ground truth for all scoping information — if two identifiers come
> from the same location in the user’s source code, they can bind each
> other.  This seems like a good model for most things, but it seems
> radically different from Racket’s model when internal definitions are
> involved, since such an interpretation would imply that this program
> should produce a duplicate definition error:
> 
>(define-syntax-rule (def-x)
>  (define x 42))
> 
>(def-x)
>(def-x)
> 
> That seems to me like an enormous break from Racket’s model of
> hygiene, but it doesn’t seem wrong, just different. I could picture a
> different programming language with a different macroexpander using
> such a model successfully. Still, unless I’m misunderstanding the
> implications here, it seems like attaching the scopes at expansion
> (even if “expansion” is really “parsing with syntax classes”) rather
> than quoting would be more consistent with the rest of Racket?

-- 
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.


Re: [racket-users] syntax/parse is not hygienic

2018-03-04 Thread Alexis King
> On Mar 4, 2018, at 15:11, Matthew Flatt  wrote:
> 
> I think scope-flipping would work, but FWIW, I thought you were going
> a different direction here. The scope-flipping approach is a way to
> infer an intended scope dynamically. It sounds to me like you want
> something more static --- a way of applying a fresh scope to a textual
> region of syntax literals.
> 
> An extreme end of that approach would be applying a fresh scope on the
> evaluation of each `quote-syntax` form (essentially as van Tonder
> explored), but it's possible that larger regions would work better.

Sam suggested I take a look at van Tonder’s work as well on Slack, and
it’s interesting, though it isn’t what I originally had in mind. I think
it would solve the first example of mine, but it would not solve the
second. In the second example, all uses of tmp come from the same
quote-syntax form, merely multiplied via ellipsis. My first mental model
was to treat syntax classes under ellipses like distinct macro
invocations, which would require a dynamic, not lexical, treatment of
scope to be consistent with Racket’s model of hygiene.

If I’m understanding correctly, attaching fresh scopes at quotation
rather than expansion treats the source text of the program as the
ground truth for all scoping information — if two identifiers come from
the same location in the user’s source code, they can bind each other.
This seems like a good model for most things, but it seems radically
different from Racket’s model when internal definitions are involved,
since such an interpretation would imply that this program should
produce a duplicate definition error:

(define-syntax-rule (def-x)
  (define x 42))

(def-x)
(def-x)

That seems to me like an enormous break from Racket’s model of hygiene,
but it doesn’t seem wrong, just different. I could picture a different
programming language with a different macroexpander using such a model
successfully. Still, unless I’m misunderstanding the implications here,
it seems like attaching the scopes at expansion (even if “expansion” is
really “parsing with syntax classes”) rather than quoting would be more
consistent with the rest of Racket?

-- 
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.


  1   2   3   >