[racket-users] Help implementing an early return macro

2020-10-28 Thread Jack Firth
So I'm a little tired of writing code like this:

(define x ...)
(cond
  [(take-shortcut? x) (shortcut x)]
  [else
   (define y (compute-y x))
   (cond
[(take-other-shortcut? x y) (other-shortcut x y)]
[else
 (define z ...)
 (cond ...)])])

That is, I have some logic and that logic occasionally checks for
conditions that make the rest of the logic irrelevant, such as an empty or
false input or something else that should trigger an early exit. Each check
like this requires me to write a cond whose else clause wraps the remainder
of the body, leading to an awkward nesting of cond forms. I don't have this
issue when the early exits involve raising exceptions: in those cases I can
just use when and unless like so:

(define x ...)
(unless (passes-check? x) (raise ...))
(define y ...)
(unless (passes-other-check? x y) (raise ...))
(define z ...)
...

I'm aware of a few macros in the racket ecosystem that try to solve this
problem. For example, Jay wrote a blog post
 that creates a
condd form that's like cond but allows embedded definitions using a #:do
keyword. I've also seen various approaches that use escape continuations to
implement the early exit. There's drawbacks I'm not happy about however:

   -

   For cond-like macros that allow embedded definitions, it looks too
   different from regular straight-line Racket code. I like my function bodies
   to be a sequence of definitions and expressions, with minimal nesting, just
   like the when and unless version above. I don't have to use a keyword or
   extra parentheses to signal whether a form is a definition or a when /
   unless check in error-raising code, why should I have to do that in code
   that uses early returns?
   -

   Continuation-based solutions impose a nontrivial performance penalty and
   have complex semantics. I don't like that the generated code behaves
   differently from the cond tree I would normally write. What happens if I
   stick an early exit inside a lambda? Or a thread? What if I set up a
   continuation barrier? Does that matter? I don't know and I don't want to
   think about that just to write what would be a simple if (condition) {
   return ... } block in other languages.

So I wrote a basic macro for this and I have some questions about how to
make it more robust. The macro is called guarded-block and it looks like
this:

(guarded-block
  (define x (random 10))
  (guard (even? x) else
(log-info "x wasn't even, x = ~a" x)
-1)
  (define y (random 10))
  (guard (even? y) else
(log-info "y wasn't even, y = ~a" y)
-1)
  (+ x y))

Each guard clause contains a condition that must be true for evaluation to
proceed, and if it isn't true the block takes the else branch and finishes.
So the above would expand into this:

(block
  (define x (random 10))
  (cond
[(not (even? x))
 (log-info "x wasn't even, x = ~a" x)
 -1]
[else
 (define y (random 10))
 (cond
   [(not (even? y))
(log-info "y wasn't even, y = ~a" y)
-1]
   [else (+ x y)])]))

This part I got working pretty easily. Where I hit problems, and where I'd
like some help, is trying to extend this to support two important features:

   -

   I should be able to define macros that *expand* into guard clauses. This
   is important because I want to implement a (guard-match 
else  ...) form that's like match-define but
   with an early exit if the pattern match fails. I'd also really like to add
   a simple (guard-define   else  ...)
   form that expects option-expression to produce an option
   

   (a value that is either (present v) or absent) and tries to unwrap it,
   like the guard let construct in Swift
   .
   -

   Begin splicing. The begin form should splice guard statements into the
   surrounding body. This is really an offshoot of the first requirement,
   since implementing macros that expand to guard can involve expanding
   into code like (begin (define some-temp-value ...) (guard ...) (define
   some-result ...)).

Having been around the Racket macro block before, I know I need to do some
kind of partial expansion here. But honestly I can't figure out how to use
local-expand, syntax-local-context, syntax-local-make-definition-context,
and the zoo of related tools. Can someone point me to some existing macros
that implement similar behavior? Or does anyone have general advice about
what to do here? I'm happy to share more examples of use cases I have for
guarded-block if that helps.

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

[racket-users] Re: Some stuff about "case".

2020-06-03 Thread Jack Firth
Isn't that just match with the == pattern?

(let ([x 'foo])
  (match 'foo
[(== x) 'got-foo]
['x 'got-quote-x])) ; => 'got-foo

On Monday, June 1, 2020 at 11:54:01 AM UTC-7, cwebber wrote:
>
> As I started typing this email and looking into the definition of case, 
> I realized my assumptions are wrong. 
>
> What I needed: something like case which dispatches on symbols, except 
> not auto-quoting the arguments... I needed to evaluate them from the 
> lexical environment.  So: 
>
>   (let ([x 'foo]) 
> (caseish 'foo 
>   [(x) 'got-foo] 
>   [('x) 'got-quote-x]))  ; => 'got-foo 
>
> I figured: case is fast, and I'm pretty sure semi-magical... my 
> intuitive sense was that it did some smart things on a compiler level 
> that would probably be anything I'd hand-code (which would either use an 
> alist or an immutable hashtable).  So I started writing up an email 
> asking if such a thing worked... then I remembered, this is a ~lisp, 
> jumping straight to definition is part of the scene... so I did that. 
> 
> I... was wrong!  From the case macro: 
>
> ;; Symbol and "other" dispatch is either sequential or 
> ;; hash-table-based, depending on how many constants we 
> ;; have. Assume that `alist' does not map anything to `#f'. 
> (define (dispatch-hashable tmp-stx alist make-hashX else-exp) 
>   (if (< (length alist) *hash-threshold*) 
>   #`(case/sequential #,tmp-stx 
>  #,@(map (λ (x) 
>#`[(#,(car x)) #,(cdr x)]) 
>  alist) 
>  [else #,else-exp]) 
>   (let ([tbl (make-hashX alist)]) 
> (if (literal-expression? else-exp) 
> #`(hash-ref #,tbl #,tmp-stx (lambda () #,else-exp)) 
> #`(or (hash-ref #,tbl #,tmp-stx (lambda () #f)) 
>   #,else-exp) 
>
> Am I reading that right?  Here I was assuming writing something like 
> case was for cool kids and I'd never pull such a thing off right. 
>
> But... now it looks like, oh, it's actually just using an alist or an 
> immutable hashtable... same as I would. 
>
> So I almost trashed this email, but thought I'd send it anyway because 
> a) either maybe it's interesting to someone or b) actually maybe I'm 
> misreading and case really is smarter / more performant and I'm just 
> missing it...! 
>
>  - Chris 
>
>

-- 
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/31189b98-2711-448f-90d1-962f2f0bda0a%40googlegroups.com.


[racket-users] Re: foldts-test-suite

2020-06-03 Thread Jack Firth
Nope. A well-designed replacement for those APIs is sorely needed.

On Tuesday, June 2, 2020 at 6:37:17 PM UTC-7, Alex Harsanyi wrote:
>
>
> Are there alternatives to the `folds-test-suite` and `fold-test-results` 
> functions, for people who want to write their own test running and 
> reporting for Rackunit tests?
>
> Alex.
>
> On Wednesday, June 3, 2020 at 2:00:02 AM UTC+8, Jack Firth wrote:
>>
>> The test case folding stuff in RackUnit should mostly be ignored, instead 
>> of extended.
>>
>> On Saturday, May 23, 2020 at 7:52:21 AM UTC-7, Shriram Krishnamurthi 
>> wrote:
>>>
>>> The documentation
>>>
>>>
>>> https://docs.racket-lang.org/rackunit/internals.html?q=run-test-case#%28def._%28%28lib._rackunit%2Fmain..rkt%29._foldts-test-suite%29%29
>>>
>>> says that `folds-test-suite` can be implemented in terms of 
>>> `fold-test-results` as follows:
>>>
>>> (define 
>>> <https://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29>
>>>  (fold-test-results 
>>> <https://www.google.com/url?q=https%3A%2F%2Fdocs.racket-lang.org%2Frackunit%2Finternals.html%3Fq%3Drun-test-case%23%2528def._%2528%2528lib._rackunit%252Fmain..rkt%2529._fold-test-results%2529%2529=D=1=AFQjCNHTl9eRUXdisIiw5GwahXRElfJ4PA>
>>>  suite-fn case-fn seed test)
>>>   (foldts-test-suite 
>>> <https://docs.racket-lang.org/rackunit/internals.html?q=run-test-case#%28def._%28%28lib._rackunit%2Fmain..rkt%29._foldts-test-suite%29%29>
>>>(lambda 
>>> <https://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29>
>>>  (suite name before 
>>> <https://docs.racket-lang.org/rackunit/api.html?q=run-test-case#%28form._%28%28lib._rackunit%2Fmain..rkt%29._before%29%29>
>>>  after 
>>> <https://docs.racket-lang.org/rackunit/api.html?q=run-test-case#%28form._%28%28lib._rackunit%2Fmain..rkt%29._after%29%29>
>>>  seed)
>>>  (before 
>>> <https://docs.racket-lang.org/rackunit/api.html?q=run-test-case#%28form._%28%28lib._rackunit%2Fmain..rkt%29._before%29%29>
>>> )
>>>  (suite-fn name seed))
>>>(lambda 
>>> <https://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29>
>>>  (suite name before 
>>> <https://docs.racket-lang.org/rackunit/api.html?q=run-test-case#%28form._%28%28lib._rackunit%2Fmain..rkt%29._before%29%29>
>>>  after 
>>> <https://docs.racket-lang.org/rackunit/api.html?q=run-test-case#%28form._%28%28lib._rackunit%2Fmain..rkt%29._after%29%29>
>>>  seed kid-seed)
>>>  (after 
>>> <https://docs.racket-lang.org/rackunit/api.html?q=run-test-case#%28form._%28%28lib._rackunit%2Fmain..rkt%29._after%29%29>
>>> )
>>>  kid-seed)
>>>(lambda 
>>> <https://docs.racket-lang.org/reference/lambda.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._lambda%29%29>
>>>  (case 
>>> <https://docs.racket-lang.org/reference/case.html#%28form._%28%28lib._racket%2Fprivate%2Fmore-scheme..rkt%29._case%29%29>
>>>  name action seed)
>>>  (case-fn
>>>(run-test-case 
>>> <https://docs.racket-lang.org/rackunit/internals.html?q=run-test-case#%28def._%28%28lib._rackunit%2Fmain..rkt%29._run-test-case%29%29>
>>>  name action)
>>>seed))
>>>seed
>>>test))
>>>
>>> I'm curious why the value of `seed` in the second argument (the fup 
>>> position) — highlighted — is ignored. I was guessing that, since this is a 
>>> tree-fold, there are values "from across" and "from down", and we don't 
>>> want to throw either one away. Wouldn't we want to take a combinator that 
>>> combines the two?
>>>
>>> Shriram
>>>
>>>

-- 
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/8902b15a-d3e7-4e27-8d65-4ba4dc7243bc%40googlegroups.com.


[racket-users] Re: foldts-test-suite

2020-06-02 Thread Jack Firth
The test case folding stuff in RackUnit should mostly be ignored, instead 
of extended.

On Saturday, May 23, 2020 at 7:52:21 AM UTC-7, Shriram Krishnamurthi wrote:
>
> The documentation
>
>
> https://docs.racket-lang.org/rackunit/internals.html?q=run-test-case#%28def._%28%28lib._rackunit%2Fmain..rkt%29._foldts-test-suite%29%29
>
> says that `folds-test-suite` can be implemented in terms of 
> `fold-test-results` as follows:
>
> (define 
> 
>  (fold-test-results 
> 
>  suite-fn case-fn seed test)
>   (foldts-test-suite 
> 
>(lambda 
> 
>  (suite name before 
> 
>  after 
> 
>  seed)
>  (before 
> 
> )
>  (suite-fn name seed))
>(lambda 
> 
>  (suite name before 
> 
>  after 
> 
>  seed kid-seed)
>  (after 
> 
> )
>  kid-seed)
>(lambda 
> 
>  (case 
> 
>  name action seed)
>  (case-fn
>(run-test-case 
> 
>  name action)
>seed))
>seed
>test))
>
> I'm curious why the value of `seed` in the second argument (the fup 
> position) — highlighted — is ignored. I was guessing that, since this is a 
> tree-fold, there are values "from across" and "from down", and we don't 
> want to throw either one away. Wouldn't we want to take a combinator that 
> combines the two?
>
> Shriram
>
>

-- 
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/7e7fd2ef-92bd-4719-a199-2556295bd2b6%40googlegroups.com.


[racket-users] Re: Puzzler - A Language for Puzzle Games

2020-04-23 Thread Jack Firth
Wow this is really, really cool. It reminds me a lot of Baba Is You.

On Wednesday, April 22, 2020 at 3:51:41 PM UTC-7, Alex Owens wrote:
>
> Hello everyone! 
>
> My name is Alex Owens and I've been a lurker on this mailing list - and in 
> the Racket community in general - for a while. While I'm still relatively 
> new to Racket, I wanted to share a project I worked on called Puzzler.
>
> Puzzler is a DSL to enable easy creation of 2D grid-based puzzle games. It 
> features a very concise and readable syntax for representing puzzle games 
> through a small collection of built-in constructs like win/lose conditions 
> and entity interactions. Most of the actual work for Puzzler was done about 
> a year ago at the end of my undergrad, and while I'm not planning any big 
> new features soon, I have recently been cleaning up the implementation and 
> adding documentation.
>
> Mostly I hope that if you're interested in language-oriented programming 
> for game development you will check it out. It is a small language, but 
> even if it doesn't suit all of your needs you may find it a useful 
> reference project for what a language for puzzle game development might 
> look like! If you do decide to use Puzzler and you find any bugs or 
> functionality you think is missing, feel free to submit an issue (or better 
> yet a pull request) on my GitHub. I can't promise I'll fix things 
> immediately, but I will try my best to respond in a timely fashion - I'm 
> always up to learn more Racket. Of course, you are also free to clone/fork 
> it and build onto it however you see fit.
>
> Puzzler on the package catalog: 
> https://pkgs.racket-lang.org/package/puzzler
> Source code: https://github.com/aowens-21/puzzler
>
> Stay safe and healthy, and I look forward to getting to know you all and 
> being more active here in the future!
>
> - Alex
>

-- 
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/45eb124e-8b3c-4c6c-9982-430e1e8a8307%40googlegroups.com.


[racket-users] How to handle exceptions raised by events?

2020-02-22 Thread Jack Firth
Using wrap-evt and handle-evt, I can transform the synchronization result 
of an event. But events can throw exceptions when they're synchronized. Is 
there a way to wrap an event such that the wrapper can catch (and maybe 
reraise) any exceptions thrown by the wrapped event? I know I can wrap a 
(sync evt) call in a with-handlers block, but that just synchronizes on the 
event instead of wrapping it and producing a new event.

-- 
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/d745d42b-eacf-4b2b-85bd-bcc93e79701a%40googlegroups.com.


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

2020-02-22 Thread Jack Firth
I'm no expert, but I have a feeling that optimizing for Racket CS will 
involve relying more on function calls and indirection, especially to avoid 
generating (or just writing) large amounts of code. So I suspect we'll see 
more of the following:

1. Implementing macro-generating macros by having the root macro expand to 
calls to a helper function to create the generated macro. For example, 
`(define-syntax generated-macro (make-my-generated-macro ...))` instead of 
`(define-syntax-rule (generated-macro ...) ...)`. This is already a good 
idea in Racket BC, because it vastly cuts down on expanded code size. 
Racket CS will probably make the effect more pronounced because the 
function call will be faster and the price of generating unnecessary code 
will rise.

2. More reliance on generic interfaces. The dynamic dispatch of generic 
interfaces is much cheaper on Racket CS, so passing around sequences 
instead of lists suddenly doesn't seem like such a bad idea anymore. Maybe 
we'll even start using generic collections.

3. Less avoidance of generators and similar features that use continuations 
under the hood, since continuations won't tank performance as much anymore.

Further down the line, we might also see more opportunities to leverage 
parallelism. Making the Racket BC VM allow parallel execution (so Racket 
code could use multiple thread without firing up a separate place - and 
thus an entire separate VM - for each thread) would be an infeasible amount 
of work, but on ChezScheme the possibilities look brighter.

For mere mortal users of Racket, I think a good way to contribute to this 
effort would be to explore the performance costs of generic interfaces on 
Racket CS. Make some benchmarks, try using collections other than just 
lists and hashes, and see what happens in real-world codebases. Don't just 
look at the speed differences either: consider what impact the flexibility 
of generic interfaces has on the structure of the codebase.

On Saturday, February 22, 2020 at 8:05:35 AM UTC-8, Matthew Butterick wrote:
>
> Of the convergence of Racket BC and CS performance, Matthew Flatt wrote: 
> [1] 
>
> > development to date has been aimed at making Racket CS match the 
> performance of Racket BC on a code base that was developed and tuned for 
> Racket BC, and that obviously gives Racket BC an advantage. For example, 
> Racket BC makes dormant code relatively cheap, so Racket libraries generate 
> a lot of code. Future Racket libraries will likely shift to take advantage 
> of Racket CS’s cheaper function calls and dramatically cheaper 
> continuations. 
>
> 1) As a package maintainer with zero exposure to Chez Scheme, how do I 
> start to optimize for Racket CS? Are there certain patterns and idioms from 
> BC that should be systematically eradicated? For instance, how would I 
> "take advantage of ... cheaper function calls"? 
>
> 2) With Racket BC, I've generally found that the JIT optimizes my code 
> better than I do. So I write the simplest code and ignore the details. Is 
> that less true with CS? Should I be thinking more about manual tuning? 
>
> 3) Lurking here, I gather, is the bugaboo that even though core Racket 
> runs on CS, the existing base libraries are optimized for BC. Is it 
> considered important to optimize these for CS, in order to get the most 
> benefit from the switch? How can Racket developers contribute to this? 
>
> 4) Building both BC and CS is easy (thank you). What would be the most 
> reliable technique for doing performance comparisons as one refactors code? 
> Is it as simple as running `raco test ···` and `racocs test ···` in 
> succession? 
>
>
>
>
> [1] https://blog.racket-lang.org/2020/02/racket-on-chez-status.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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/5f0815ee-1e02-4dc8-9b2f-d1465263f205%40googlegroups.com.


[racket-users] Re: style guide addition?

2020-01-21 Thread Jack Firth
I think that would be a great addition to the style guide. I agree that 
"expression" is clearer than "term", though I'm not too worried about it 
not covering (define(f x)3). We could add stronger language later on as we 
get a sense of how people react to the initial wording.

On Monday, January 20, 2020 at 10:13:40 PM UTC-8, johnbclements wrote:
>
> I’m grading code, and one of my students keeps leaving out spaces in weird 
> places: 
>
> (cond 
>   [(< x 3)(+ x 1)] 
>   [else (f(g 9))]) 
>
> I took a quick look in the style guide, and it doesn’t seem to have much 
> to say about this. Here’s what it has: 
>
> 6.8 Spaces 
>
> Don’t pollute your code with spaces at the end of lines. 
>
> If you find yourself breaking long blocks of code with blank lines to aid 
> readability, consider refactoring your program to introduce auxiliary 
> functions so that you can shorten these long blocks of code. If nothing 
> else helps, consider using (potentially) empty comment lines. 
>
> *** 
>
> To this text, I would like to add: 
>
> “Every pair of expressions on a line should have at least one space 
> between them, even if they’re separated by parens. 
>
> Wrong: [(< x 3)(+ x 1)] 
> Right: [(< x 3) (+ x 1)] 
>
> Wrong: (f(g 3)) 
> Right: (f (g 3)) 
>
>
> Can anyone think of exceptions to this? One possible nit: since the rule 
> refers to “expressions”, it perhaps wouldn’t rule out (define(f x)3) . You 
> could say “term”, but I think it would be less clear. 
>
> 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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/aa025605-784b-4339-b8b3-b29f05800f45%40googlegroups.com.


[racket-users] Rebellion updates

2020-01-20 Thread Jack Firth
Hello all! Just wanted to give a quick announcement about some of the new 
features that have landed in Rebellion 
 recently:

   - Added comparators 
    and ranges 
   , allowing you to 
   compare data in arbitrary ways and express ranges of data such as "all 
   integers between 7 and 42, inclusive".
   - Added transducers and reducers for sorting 
   

 
   sequences as well as finding the max and min 
   
,
 
   according to an arbitrary comparator.
   - Record, tuple, and wrapper data types 
    now support 
   pattern matching.
   - Added results , 
   which are roughly the same as Haskell's Either data type or Rust's Result 
   data type.
   - Added atomic fixnums 
    and atomic 
   booleans  
   for safe (and fast!) concurrently-mutable data.
   - Improved support for contracts, including contracts for options 
   , reducers 
   
,
 
   comparators 
   
,
 
   and results .
   - Added reducers for more of Racket's standard collections, including 
   vectors , sets 
   , and hash tables 
   .
   - Added vector builders 
    for 
   efficiently and safely building a vector of unknown size by inserting 
   elements into it one at a time.

Install it using `raco pkg install --auto rebellion`. Bug reports, feature 
requests, and patches are all welcome at the github repository 
.

-- 
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/a903a813-32bd-454d-98f7-a2d581be03b5%40googlegroups.com.


Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
Is there a specific instance where you were writing some code and thought
mutexes would help, or is there a specific project with a problem you'd
like to solve with mutexes? Or IVars and LVars?

I started down this road because I noticed that the test result counting
<https://github.com/racket/rackunit/blob/master/testing-util-lib/rackunit/log.rkt>
in rackunit seems like it might experience data races if test cases in the
same namespace are run from different threads. So I tried to rewrite it
with a semaphore-based lock and found it frustrating, and I got it wrong to
boot.

On Sat, Jan 18, 2020 at 3:06 AM Alexis King  wrote:

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

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
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 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 Fir

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
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 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  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  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 
>> 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  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 sema

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
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  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  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  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  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 
>> 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  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
>

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
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  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  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  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  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 
>> 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
&g

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
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  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  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 
> 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, s

Re: [racket-users] Breaking semaphores

2020-01-18 Thread Jack Firth
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  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 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 di

[racket-users] Breaking semaphores

2020-01-17 Thread Jack Firth
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/a41b4aa6-08df-4506-9ae2-6447775dfcfc%40googlegroups.com.


Re: [racket-users] What's the point of make-continuation-mark-key?

2020-01-11 Thread Jack Firth
That makes sense. I think the thing that seems most confusing to me is that 
using the continuation-mark-key data type is *optional*. Why bother 
allowing arbitrary kinds of keys?

On Saturday, January 11, 2020 at 8:02:44 PM UTC-8, Matthew Flatt wrote:
>
> It would be reasonable to generalize `chaperone-continuation-mark-key` 
> to apply in cases where `chaperone-struct` could work, with similar 
> sorts of evidence that chaperoning is allowed provided by a caller of 
> `chaperone-continuation-mark-key`. I guess we just didn't think about 
> it that way when `chaperone-continuation-mark-key` was added, so it was 
> added in a way more like `chaperone-vector` and other chaperones that 
> apply to more specialized representations. 
>
> Other kinds of keys, like symbols, can't be impersonated because their 
> representations don't accommodate chaperones. (In other words, they're 
> like structs declared with `#:authentic`.) 
>
> At Sat, 11 Jan 2020 19:48:17 -0800 (PST), Jack Firth wrote: 
> > Based on my reading of Continuation Frames and Marks 
> > <
> https://docs.racket-lang.org/reference/eval-model.html#(part._mark-model)>, 
>
> > any value at all can be used as a key for a continuation mark. So why 
> does 
> > make-continuation-mark-key 
> > <
> https://docs.racket-lang.org/reference/contmarks.html#%28def._%28%28quote._~23
>  
> > ~25kernel%29._make-continuation-mark-key%29%29> 
> > exist, and why is there a special continuation-mark-key 
> > <
> https://docs.racket-lang.org/reference/contmarks.html#%28def._%28%28quote._~23
>  
> > ~25kernel%29._continuation-mark-key~3f%29%29> 
> > data type? Couldn't you use any arbitrary gensym, or a singleton struct? 
> > The docs for make-continuation-mark-key mention that the returned key 
> can 
> > be impersonated and other kinds of keys can't, but they don't explain 
> why 
> > that would be the 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...@googlegroups.com . 
> > To view this discussion on the web visit 
> > 
> https://groups.google.com/d/msgid/racket-users/773a2caa-d6b3-48b8-becf-cc3105a6
>  
> > 60e0%40googlegroups.com. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/9ac7e680-f32e-4a79-8cb7-4799ea5e953c%40googlegroups.com.


[racket-users] What's the point of make-continuation-mark-key?

2020-01-11 Thread Jack Firth
Based on my reading of Continuation Frames and Marks 
, 
any value at all can be used as a key for a continuation mark. So why does 
make-continuation-mark-key 

 
exist, and why is there a special continuation-mark-key 

 
data type? Couldn't you use any arbitrary gensym, or a singleton struct? 
The docs for make-continuation-mark-key mention that the returned key can 
be impersonated and other kinds of keys can't, but they don't explain why 
that would be the 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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/773a2caa-d6b3-48b8-becf-cc3105a660e0%40googlegroups.com.


[racket-users] How do I provide a name as both a match expander and contracted function?

2019-12-30 Thread Jack Firth
If I'm making my own data types, one common thing I want to do is make 
smart constructors that double as match expanders. I could use 
`define-match-expander` with two transformers, but then I can't add a 
contract to the smart constructor with `contract-out`. If I try to write 
this:

(provide
 (contract-out
  [foo (->* (widget?) (#:name symbol?) foo?)]))

(define (make-foo widget #:name [name #f])
  ...)

(define-match-expander foo
  (syntax-parser [(_ widget) #'(? foo? (app foo-widget widget))])
  (syntax-parser [(_ arg ...) #'(make-foo arg ...)]))

...then the use of `contract-out` hides the fact that `foo` is a match 
expander. What should I do?

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


[racket-users] Re: Inadvertedly requiring racket/unsafe/ops

2019-12-14 Thread Jack Firth
I think that documentation fix is a good idea. More broadly, it seems 
awkward that all of the unsafe ops for different data types are combined 
together into a single module. I would instead expect there to be modules 
like racket/fixnum/unsafe, racket/struct/unsafe, racket/vector/unsafe, etc. 
But I've never used the unsafe ops before, maybe those who have can chime 
in?

On Saturday, December 14, 2019 at 1:03:14 PM UTC-8, Dominik Pantůček wrote:
>
> Hello, 
>
> the documentation at https://docs.racket-lang.org/reference/fixnums.html 
> is misleading at best. If you - as I did - use the suggested approach of 
> requiring optimized (and unsafe) fx... operations from racket/unsafe/ops 
> with: 
>
> (require (filtered-in 
>   (λ (name) (regexp-replace #rx"unsafe-" name "")) 
>   racket/unsafe/ops)) 
>
> You end up using _all_ symbols from racket/unsafe/ops. All of them are - 
> of course - uncontracted. Which means that if you issue for example 
> vector-ref on something that is not a vector, it can crash the runtime 
> without any apparent reason - instead of just throwing an exception as 
> one would expect. 
>
> A simple documentation fix should probably go along the lines: 
>
> (require racket/require 
>  (filtered-in 
>   (λ (name) 
> (and (regexp-match #rx"^unsafe-fx" name) 
>  (regexp-replace #rx"unsafe-" name ""))) 
>racket/unsafe/ops)) 
>
> Or is it just me running into corner cases with optimized Racket code? 
>
>
> Cheers, 
> Dominik 
>

-- 
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/c118c47e-fccd-4fab-b252-7a24afe6eef1%40googlegroups.com.


Re: [racket-users] Re: srfi-171 transducers for racket

2019-12-10 Thread Jack Firth

>
> The "tdelete-duplicates" uses a hash-table to store already seen elements: 
> if the element is in the hash table, just filter it out.  If it is not, we 
> do: (hash-set! already-seen element #t). That should be constant timeish.
>
 
I understand how that works for the usual eq? / eqv? / equal? equality 
relations, but how could that work for *arbitrary* equivalence relations? 
If you passed a case-insensitive string comparison function to 
tdelete-duplicates, storing already seen elements in a hash table wouldn't 
help because two "equal" strings could have different hash codes.

-- 
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/90506548-c7fc-4f0d-9321-00cb03490aec%40googlegroups.com.


[racket-users] Re: srfi-171 transducers for racket

2019-12-10 Thread Jack Firth
This is great! Thank you for your work on this srfi. Transducers are 
relatively new to Racket's ecosystem and I'm happy to see more of the 
design space being explored.

The documentation in the SRFI document still holds with some small caveats: 
> bytevector-u8-reduce/transduce is now bytes-transduce/reduce and 
> tdelete-duplicates now takes three symbols 'eq?, 'eqv? or 'equal? instead 
> of arbitrary equality predicates.
>

I have a question about that. While implementing the deduplicating 

 
transducer, I tried to figure out a way to make it support arbitrary 
equality relations. But as far as I could tell 
, 
it's impossible to do that in less than quadratic time because there's no 
way to check whether something is a duplicate without comparing it to every 
unique element seen so far. Is there an implementation of this SRFI that 
figured out an efficient way to do this in the general case?

I have really no idea how to package things for racket, nor do I have much 
> interest in doing so. I have played with it a bit, it seems to work. There 
> is a small test-suite still written in guile scheme, which should be 
> trivial to port. If someone wants to package this as a proper racket 
> package, I would be happy to accept pull requests or even transfer the 
> repository to someone else. The license used is sub-licenseable, so feel 
> free. If I find the repo to my liking I will deprecate my port and link to 
> you.
>
> Ideas for changes I would have done if I was using racket more than I 
> actually do: a (transduce ...)-form that uses rackets sequence interface. 
> Package it so It could be installed using raco. Port the test-suite. 
> Another part is figuring out what to call the library. 


I'd be happy to write an `info.rkt` that packages the code. For a package 
name, I suggest `srfi-171`. Would you be interested in writing Scribble 
documentation for the package?

The rebellion transducers seem to be aimed at another use-case (streaming 
> data, and parallelism) with other kind of guarrantees. It has a 
> _significantly_ higher overhead. I tried the following in rebellion 
>
> #lang racket 
> (require rebellion/streaming/transducer) 
> (require rebellion/collection/list) 
>
> (define lst (build-list 10 values)) 
>
> (time (length (transduce (in-list lst) 
>  (filtering odd?) 
>  (mapping (lambda (x) (* x x))) 
>  #:into into-list))) 
>
> and it takes about 5 seconds. The same thing using srfi-171 styled 
> transducers takes about 3ms (if my head is with me this morning, that is 
> about 1650x). I suspect I might be doing something wrong, or that there 
> might be some quadratic behaviour somewhere.
>

You're not doing anything wrong. Rebellion's transducers have awful 
constant (but not quadratic) factors and make lots of unnecessary 
allocations. There's no fundamental reason for this; the protocol can 
support efficient zero-allocation transducer implementations perfectly 
fine. I just haven't put work into that yet. See this issue 
 for a summary of the 
problem and some possible ways to improve performance. For anyone reading 
this who's interested in benchmarking and optimizing tight loops, I'd love 
to hear your input.

-- 
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/8c036a47-6d90-4bcd-bfd3-fdfdd2f8d05b%40googlegroups.com.


Re: [racket-users] Vector length and indices contracts

2019-12-05 Thread Jack Firth
What if we had a `(vector-index/c vec)` contract combinator? It would be 
equivalent to `(integer-in 0 (sub1 (vector-length vec)))`.

On Wednesday, December 4, 2019 at 1:29:22 PM UTC-8, Matthew Flatt wrote:
>
> At Wed, 4 Dec 2019 22:24:10 +0100, Dominik Pantůček wrote: 
> > What about all the vector-ref, -set! and basically all indices 
> > contracts? That should probably be the same. 
>
> I'm less enthusiastic about that change. It turns out that a non-fixnum 
> argument won't work for `vector-ref`, but the stronger constraint is 
> that the argument needs to be less than the vector's length. So, it 
> seems redundant in an unhelpful way to require that the argument 
> individually is a fixnum --- but I'm not completely sure. 
>
>

-- 
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/6bf86e11-ca19-4619-845c-98b0478a7ebc%40googlegroups.com.


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

2019-11-20 Thread Jack Firth
Would it have helped if the get-directory documentation had included 
examples? Many parts of Racket's documentation are lacking in example code, 
especially the less-commonly-encountered parts.

On Tuesday, November 19, 2019 at 10:52:14 PM UTC-8, pow bam wrote:
>
> Indeed I would have likely never even known that section existed - and 
> looking at it now I see that it is very dense reading material. I turns my 
> mind to mush trying to interpret what's being said there. I also happen to 
> be, by and large, a self-learning lone wolf type. I am a complete novice to 
> programming but when it came to AutoIt I managed to figure out how to piece 
> together a fairly complicated and large-ish program only using Google, 
> typing in Autoit + whateverineededtoknowabout and it invariably led me to 
> not only just the documentation but a community forum FULL of questions and 
> answers from years of community involvement. Sadly, Racket has no such 
> structure in place except this very secluded, small Google group and 
> smattering of tuts about the web - hardly any of which actually focus in 
> any depth upon GUI app creation to any real extent, seemingly more 
> concerned with various game making and animation activities.
>
> As an example take a look at what happens if I type this into Google for 
> an AutoIt function:
> https://www.google.com/search?q=autoit+get+window+size
>
> I wind up with a list of forum entries that I can read for clues on what 
> to do OR I can read the documentation along with all that and if you look 
> at the documentation..
> https://www.autoitscript.com/autoit3/docs/functions/WinGetClientSize.htm
> ..it not only gives me a more traditional breakdown of the function it 
> then goes on to show me it in real world use/action. That's a powerful 
> thing to getting new people and beginners in the door and using your 
> language. I would actually be much happier with a true official forum. 
> Nothing against Google, I guess, but it feels so spartan and limited 
> compared to what it could be.
>

-- 
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/62cc63a4-196c-4294-b147-6c1ec3023732%40googlegroups.com.


[racket-users] Re: Looking for transducer early-adopters

2019-11-15 Thread Jack Firth
That's perfect! Thank you very much Alex.

On Friday, November 15, 2019 at 5:15:10 AM UTC-8, Alex Harsanyi wrote:
>
>
> I'm not sure if this would be useful to you, but, as part of writing my 
> tzgeolookup package, I wrote a blog post exploring the performance of 
> different ways in which the underlying data is organized.  As a result of 
> that, I have a repository with 10 variants of the same program using 
> different strategies, and these programs are all instrumented, so running 
> them will run a test suite and print out the time taken by each procedure.  
> You could implement a variant using transducers and compare it with all the 
> others.
>
> The repository is here: https://github.com/alex-hhh/time-zone-lookup-tests, 
> and the blog post explains how the hole thing works:  
> https://alex-hhh.github.io/2019/08/timezone-lookup.html
>
> The final package uses vectors, so I am not sure that would be useful in 
> converting it to transducers, but if you want to look at it, it is here: 
> https://github.com/alex-hhh/tzgeolookup
>
> Alex.
>
>
>
> On Friday, November 15, 2019 at 3:18:23 PM UTC+8, Jack Firth wrote:
>>
>> Hello all! I'd like to get Rebellion's 
>> <https://docs.racket-lang.org/rebellion/> transducer 
>> <https://docs.racket-lang.org/rebellion/Transducers.html> and reducer 
>> <https://docs.racket-lang.org/rebellion/Reducers.html> libraries up to 
>> feature parity with Racket's ordinary list-processing functions. So I'm 
>> looking for people interested in migrating some of their open-source Racket 
>> code to use transducers instead of using map / filter / fold / append-map / 
>> etc. Even just pointing me to some of your code on GitHub that does list 
>> processing would be a great help, since I could attempt to migrate it 
>> myself and see if there's any functionality I'm missing that stands in the 
>> way of migrating. Huge bonus points if your code has benchmarks I can run, 
>> so I can compare the performance of manual list processing v.s. Rebellion 
>> stream processing v.s. optimized for loops.
>>
>

-- 
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/9ea24052-b090-4f74-9adf-1c4d52c13049%40googlegroups.com.


[racket-users] Looking for transducer early-adopters

2019-11-14 Thread Jack Firth
Hello all! I'd like to get Rebellion's 
 transducer 
 and reducer 
 libraries up to 
feature parity with Racket's ordinary list-processing functions. So I'm 
looking for people interested in migrating some of their open-source Racket 
code to use transducers instead of using map / filter / fold / append-map / 
etc. Even just pointing me to some of your code on GitHub that does list 
processing would be a great help, since I could attempt to migrate it 
myself and see if there's any functionality I'm missing that stands in the 
way of migrating. Huge bonus points if your code has benchmarks I can run, 
so I can compare the performance of manual list processing v.s. Rebellion 
stream processing v.s. optimized for loops.

-- 
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/01a0a03b-f535-4466-a10b-d22761d5e935%40googlegroups.com.


Re: [racket-users] Efficient idiom for converting key-set of a hash-map into a hash-set

2019-10-26 Thread Jack Firth
A dict doesn't guarantee unique keys, but it *does* guarantee that dict-ref 
returns a single value and dict-set accepts a single value, which is really 
strange to guarantee if you're not also going to guarantee unique keys.

Honestly, I think association-lists-as-dicts were a mistake. If you want to 
allow multiple values per key, then use a collection interface that's 
actively designed around that (such as multidicts 
). Racket needs to 
grow beyond using lists as a bunch of different ad-hoc collection types.

On Friday, October 25, 2019 at 11:40:16 PM UTC-7, Matthew Butterick wrote:
>
>
> On Oct 25, 2019, at 7:28 AM, Thomas Dickerson <
> thomas_d...@alumni.brown.edu > wrote:
>
> For reasons that are unclear to me, hash-keys and dict-keys both return a 
> list? instead of a set?(frankly, this seems like a bug in the API...).
>
>
>
> A dict doesn't guarantee unique keys. So `dict-keys` returns a list, not a 
> set. 
>
> #lang racket
> (require racket/dict)
> (define kvs '((a 1) (a 2)))
> (dict? kvs) ; #t
> (dict-keys kvs) ; '(a a)
>
> Why does `hash-keys` also return a list? For consistency, I suppose, 
> because every hash is a dict.
>

-- 
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/f01e6c65-7e1e-49eb-bb7c-2dbb299602f1%40googlegroups.com.


[racket-users] [ANN] Transducers library

2019-10-23 Thread Jack Firth
Rebellion  now provides
the rebellion/streaming/transducer
 library for
processing streams of data using transducers.

A *transducer* is a kind of sequence transformation that comes with
guarantees about memory usage and about how much of the sequence is
consumed in between each produced output. Transducers are first class
objects that chain together fluently, without any macros involved. For
example, this code defines a function that finds and reports all of the
lines in a string that are longer than 80 characters and it uses *no macros
at all*:


(require rebellion/streaming/reducer
 rebellion/streaming/transducer)

(define (report-all-long-lines str)
  (transduce str
 (batching into-line)
 enumerating
 (filtering long-line?)
 #:into (into-for-each report-long-line)))

(define (long-line? e)
  (define line (enumerated-element e))
  (> (string-length line) 80))

(define (report-long-line e)
  (define line (enumerated-element e))
  (define number (enumerated-position e))
  (printf "Line ~a is longer than 80 characters: ~a\n" number line))


You may find transducers more useful than for-style loops in the following
cases:

   - The for/xxx form you need doesn't exist
   - You want to sort
   

   elements or search for the N largest or N smallest elements
   - You're reading data from external sources and want control over when
   resources are acquired and released
   - You're processing a stream that's too large to fit into memory
   - You care a lot about processing your streams in only one pass
   - You want to combine elements into batches
   

   or group
   

   them by key
   - You want to remove duplicate
   

   elements
   - You prefer writing sequence transformations in a point-free style
   - You already like reducers
   
   - You've got a rebellious streak

For some real-world examples of transducers in action, I cannot thank Sam
Phillips enough for putting together this gist

containing scripts he wrote for his day job using transducers.

-- 
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/CAAXAoJUbF3Gog2az44kvDYq7rxrqdefMUJYnSceY_utinTSjxQ%40mail.gmail.com.


Re: [racket-users] Scribble examples performance

2019-10-19 Thread Jack Firth
I think the evaluators are being closed, because I'm using
make-base-eval-factory and the #:close option. Do evaluator *factories*
need to be closed?

On Sat, Oct 19, 2019, 8:05 AM Sam Tobin-Hochstadt 
wrote:

> One thing that's important that we've found improves performance is to
> close the evaluator at the end of the module.
>
> Sam
>
> On Sat, Oct 19, 2019, 3:43 AM Jack Firth  wrote:
>
>> The Scribble docs for my Rebellion
>> <https://github.com/jackfirth/rebellion> package take nearly two minutes
>> to build. I have a hunch that most of the time is spent compiling,
>> evaluating, and rendering example code. Every one of my Scribble modules is
>> structured roughly like this:
>>
>> #lang scribble/manual
>>
>> (require ...)
>>
>> (define make-evaluator
>>   (... build an evaluator factory using make-base-eval-factory ...))
>>
>> ...
>>
>> @defwhatever[...]{
>>
>>  @(examples
>>#:eval (make-evaluator) #:once
>>... example code here ...)}
>>
>> Does this pattern have any performance or memory usage problems? Is there
>> more I can do to speed things up? How do I profile Scribble docs? Is it
>> normal for `raco setup` to spend much more time building my documentation
>> than it spends actually compiling my library's 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.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/racket-users/ecf4481e-601f-4883-92bd-0506b35957c5%40googlegroups.com
>> <https://groups.google.com/d/msgid/racket-users/ecf4481e-601f-4883-92bd-0506b35957c5%40googlegroups.com?utm_medium=email_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAAXAoJUOKjf1M%3DuvjCTe%3DTQGV23CX2naY%2B7HcfKu6pa-5hRaHA%40mail.gmail.com.


[racket-users] Scribble examples performance

2019-10-19 Thread Jack Firth
The Scribble docs for my Rebellion  
package take nearly two minutes to build. I have a hunch that most of the 
time is spent compiling, evaluating, and rendering example code. Every one 
of my Scribble modules is structured roughly like this:

#lang scribble/manual

(require ...)

(define make-evaluator
  (... build an evaluator factory using make-base-eval-factory ...))

...

@defwhatever[...]{

 @(examples
   #:eval (make-evaluator) #:once
   ... example code here ...)}

Does this pattern have any performance or memory usage problems? Is there 
more I can do to speed things up? How do I profile Scribble docs? Is it 
normal for `raco setup` to spend much more time building my documentation 
than it spends actually compiling my library's 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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/ecf4481e-601f-4883-92bd-0506b35957c5%40googlegroups.com.


[racket-users] Re: providing classes from a module

2019-10-02 Thread Jack Firth
(provide fish%) ought to work. Classes created with racket/class are 
values, just like numbers, strings, and functions, so you can provide them 
like you would other values.

On Wednesday, October 2, 2019 at 1:09:40 PM UTC-7, Tim Meehan wrote:
>
> Say for instance, I have a class in "tastyfish.rkt"
>
> #lang racket
> (require racket/class)
>
> ; What `provide` statement would I put here so that another module
> ; (like "market.rkt" for instance) can require fish%?
>
> (define fish%
>   (class object%
> (super-new)
> (init size)
> (define current-size size)
> (define/public (get-size)
>   current-size)))
>

-- 
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/93a0b623-a91b-42ed-a262-23915a8aa1b8%40googlegroups.com.


[racket-users] Happy Hacktoberfest!

2019-10-01 Thread Jack Firth
Every October, DigitalOcean and GitHub run an event called Hacktoberfest 
. If you sign up for it and you 
open at least four pull requests on GitHub during the month of October, 
you'll get a free T-shirt. To get Racketeers in the Hacktoberfest spirit, 
I've organized and labeled a bunch of starter tasks in my Rebellion 
 repository with the hacktoberfest 

 
label and the good first issue 

 
label. Contributors welcome!

Feel free to add these issue labels to your own projects as well: any 
issues labeled with a "hacktoberfest" label will show up in this GitHub 
search query 
,
 
and any issues labeled with a "good first issue" label will show up in this 
query 

.

-- 
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/9c1d4615-7d18-4b1d-9600-de94dc521ac5%40googlegroups.com.


[racket-users] REPL printing importance?

2019-09-11 Thread Jack Firth
Survey question: how important is it that values print nicely at a REPL? Do 
any of you have pet peeves in this area, or cases you wished Racket handled 
better? Tales of woe gladly welcomed!

-- 
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/a52b7215-15c2-4538-8024-ba2de2d5e5df%40googlegroups.com.


[racket-users] [ANN] Racket-on-ChezScheme docker images now available

2019-09-07 Thread Jack Firth
Thanks to the hard work of Bogdan Popa 
, you can now run 
Racket-on-ChezScheme inside docker containers using the jackfirth/racket 
 DockerHub repository. The 
ChezScheme image variants are tagged as jackfirth/racket:{version}-cs or 
jackfirth/racket:{version}-cs-full, depending on whether you want the 
minimal installation of Racket or the full installation. For example, this 
command:

  docker run -it jackfirth/racket:7.4-cs

...will pull the minimal Racket-on-ChezScheme 7.4 image and run a REPL 
inside it. Note that running on ChezScheme is only possible for version 7.4 
and above. For more information about the Racket images, see the 
jackfirth/racket-docker  GitHub 
repository.

-- 
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/fd9a44f8-1897-4d93-a429-3cb2e40950df%40googlegroups.com.


Re: [racket-users] [racket users] make-keyword-procedure follow-up

2019-08-31 Thread Jack Firth
You might have some success using my arguments 
 package, which defines 
an arguments? data structure wrapping a bundle of positional and keyword 
args. It also provides some functions that are like make-keyword-procedure 
and keyword-apply, but with a nicer interface based on the arguments 
structure:

> (apply/arguments sort
   (arguments '("fo" "bar" "bazz") < #:key 
string-length))
'("bar" "bazz" "fo")
> (define/arguments (keywords-product args)
(for/product ([(k v) (in-hash (arguments-keyword args))])
  v))
> (keywords-product #:foo 2 #:bar 3)
6
> (keywords-product 'ignored #:baz 6 #:blah 4)
24

-- 
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/83554d22-5863-4aa8-9d62-cbf6caef14c2%40googlegroups.com.


Re: [racket-users] Would it help to call racket2 something else?

2019-08-29 Thread Jack Firth
On Thursday, August 29, 2019 at 12:46:53 AM UTC-4, David Storrs wrote:
>
>
> On Wed, Aug 28, 2019, 11:43 PM Sage Gerard  > wrote:
>
>>
>> Maybe I'm overthinking this. I already know that nothing in #lang racket 
>> is getting thrown out or anything.
>
>
> Yes, it is.
>

I believe Sage's statement was that all current #lang racket modules will 
continue to work exactly the same, which is true. Nothing changes unless a 
module decides to use #lang racket2, and modules will not have to know 
whether or not their dependencies are written in #lang racket, in #lang 
racket2, or in a mixture of both. Backwards compatibility for existing 
unchanged modules will be preserved.

-- 
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/c130f310-d035-44d6-9c1e-011f2a6f2070%40googlegroups.com.


[racket-users] [ANN] Reducers, a better way to fold

2019-07-15 Thread Jack Firth
I've recently added another library to Rebellion, this one for reducers 
. A *reducer* is a 
way to combine a series of values:


> (require rebellion/streaming/reducer)
> (reduce into-sum 1 2 3 4 5)
15


You can reduce any sequence using `reduce-all`:


> (reduce-all into-product (in-range 1 20))
121645100408832000


You can make a reducer from any fold:


> (define into-reversed-list (make-fold-reducer (lambda (lst v) (cons v 
lst)) '()))
> (reduce-all into-reversed-list (in-range 1 10)
'(9 8 7 6 5 4 3 2 1)


You can use `for/reducer` and `for*/reducer` to fold over any `for`-loop 
using a reducer:


> (for/reducer into-reversed-list
   ([n (in-range 2 20)]
#:when (prime? n))
n)
'(19 17 13 11 7 5 3 2)


And you can implement your own `for/...` macros using a reducer:


> (define-syntaxes (for/reversed-list for*/reversed-list)
(make-reducer-based-for-comprehensions #'into-reversed-list))
> (for/reversed-list ([n (in-range 2 20)]
  #:when (prime? n))
n)
'(19 17 13 11 7 5 3 2)


Folds are only the most basic type of reducer: not all reducers are as 
simple as a plain fold. Reducers can use hidden mutable state to make 
reduction performant, and reducers can short-circuit and return a result 
without iterating through the entire sequence. See the 
rebellion/streaming/reducer 
 documentation for 
more details, as well as instructions on how to make your own reducers. To 
use, install Rebellion with `raco pkg install rebellion` and import the 
reducers library with `(require rebellion/streaming/reducer)`.

This library is currently in an *experimental alpha* state. I might break 
your code. Warn me before seriously depending on this, *especially* if you 
won't be using it in an open-source package in the package catalog (where 
the package build server can alert me if I break you).

-- 
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/7dbbaa2a-2e6e-4253-9ae4-e2e1ef9a90b2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Re: why scribble may be slow

2019-07-15 Thread Jack Firth
I believe the reason Scribble is slow on your file has to do with 
algorithms and logic in Scribble that have poor performance characteristics 
on large files, and nothing at all to do with the fact that Scribble is 
implemented in Racket. With a reproducible performance benchmark for 
running Scribble on large files, I'm sure a dedicated Scribble expert could 
do a lot to optimize the internals of Scribble and fix the performance 
problems you're experiencing. That said, I'm no Scribble expert.

On Monday, July 15, 2019 at 6:06:51 PM UTC-6, Hendrik Boom wrote:
>
> On Mon, Jul 15, 2019 at 05:38:17PM -0400, Hendrik Boom wrote: 
> > I'm thinking of trying Scribble again now that I have a new computer. 
> > I found it unacceptably slow years ago when I tried it on a 80,000 word 
> novel. 
> > I now, however, have a modern machine and it may be fast enough. 
>
> A theory why scribble is slow: 
>
> I looked at the scribble installed on my computer (which runs Devuan, a 
> Debian derivative) and discovered that it's all Racket source code. 
>
> So my guess is that Racket is interpreting Scribble, and the the already 
> interpreted Scribble is interpreting the scribble input. 
>
> Stacking interpreters is usually a recipe for sloth. 
>
> So ... is this likely the reason? 
>
> Processing an 800,000 character text file without any at signs (so that I 
> don't invoke any fancy scribble features) took six minutes on a modern 
> laptop 
> with 16 gigabytes of RAM. 
>
> Hand-coded C processed the same file faster than I can blink my eye.  Both 
> systems produced usable HTML.  (but the hand-coded C is limited as to what 
> it 
> will do. It won't handle tables of category-theoretic diagrams, for 
> example, 
> and maybe Scribble can someday manage to do all this) 
>
> If this is the reason for scribble being slow, what can be done about it? 
> Can it, for example, be compiled to something more like machine code? 
>  (I'm 
> using a 64-bit intel processor.) 
>
> -- 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/73523467-14eb-472c-b5c1-ea736a22e320%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


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

2019-07-15 Thread Jack Firth
Matthias, I ask that you please not respond to discussion about the 
diversity of the Racket community by saying it's a political topic and 
politics have no place here. That statement alone is political and makes 
many people feel unwelcome, including me.

On the topic of a new syntax: I am strongly in favor. I think it will 
remove barriers to entry that have deterred many potential Racketeers. And 
if there's one community I trust to put care and thoughtfulness into a 
surface syntax design, it's the Racket community.

On Monday, July 15, 2019 at 10:19:16 AM UTC-6, Matthias Felleisen wrote:
>
>
>
> > On Jul 14, 2019, at 1:44 PM, someone wrote: 
> > 
> > - I am indeed very for growth in the community, though my main interest 
> >   in growth is in seeing a wider diversity of participants than just 
> >   raw numbers.  Obviously other peoples' mileage may vary. 
>
>
> This is politics and politics has no business whatsoever on this mailing 
> list. I believe there are things such as Facebook, Instagram and other 
> Web-chambers where political opinions are welcome and echoes will always 
> confirm your opinions. 
>
> ;; - - - 
>
> Our policy has always been that everyone, absolutely everyone, is welcome 
> on this technical list to discuss technical issues. We don’t exclude 
> anyone. And everyone gets treated the same and gets productive responses if 
> possible. In particular, politics stays off this list; it’s divisive enough 
> in the rest of the world. 
>
> Thank you — Matthias 
>
>

-- 
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/a63d9bdb-4d5d-49e8-9451-d6524ac24752%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Re: Language-Specific Plugins: Toolbar button functionality to call drracket:eval:expand-program

2019-06-25 Thread Jack Firth
This sounds very similar to pict3d , 
particularly if you adopt the approach suggested by Phillip of using a main 
submodule to render things instead of a drracket plugin. Is pict3d close to 
what you're trying to do? Not saying you *should* use pict3d or do things a 
similar way—I'm just curious about your use 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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/8b216851-996b-41bd-93d5-bbe9bd1273ac%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] [ANN] Rebellion collection libraries: multisets, multidicts, and association lists, oh my!

2019-06-22 Thread Jack Firth
The rebellion  package 
recently acquired a few new collection libraries:

   - rebellion/collection/multiset 
    - A library for 
   *multisets*, which are like sets that can contain duplicate values
   - rebellion/collection/multidict 
    - A library for 
   *multidicts,* which are like hashes from keys to sets of values
   - rebellion/collection/association-list 
    - A 
   library for *association lists*, which are like hashes from keys to 
   lists of values
   - rebellion/collection/entry 
    - A small 
   supporting library that defines an (entry key value) struct, in order to 
   make it clearer when a pair is being used as a key-value mapping rather 
   than as an arbitrary pair

All of the new collection types are immutable, but they don't (yet) support 
efficient persistent updates (e.g. there's no multiset-add function yet). 
These libraries are currently in early alpha versions, so not much beyond 
the basics is implemented and their APIs might change without warning. Let 
me know what you think and please feel free to file feature requests and 
bugs in the rebellion github repository 
!

-- 
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/f954d1a4-fc88-4fc6-9103-58837bc02c26%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Breaks and events

2019-03-07 Thread Jack Firth
Question for synchronizable event experts: why is there no `break-evt`? The
existence of `sync/enable-break` suggests to me that it is possible to have
mutually exclusive choice between synchronizing on an event or raising a
break. And we have an analogous construct for `sync/timeout` in the form of
`alarm-evt`. Is there something about breaks that makes this idea
impossible?

-- 
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] R6RS history

2019-02-26 Thread Jack Firth
What exactly is the history surrounding scheme, racket, and r6rs? I've
gotten vague impressions of serious scheme community conflicts around that
time but nothing specific. Does anyone have a timeline of important events
related to that?

-- 
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] Struct properties and recursion

2019-02-22 Thread Jack Firth
Does it seem weird to anybody else that there's no way to set struct
properties without mutual recursion?

Say I'm defining a 2d point struct and want to set the prop:custom-write
property to control how points print. I might start with this:

(struct point (x y)
  #:property prop:custom-write
  (lambda (this out _)
(write-string "(point " out)
(write (point-x this) out)
(write-string " " out)
(write (point-y this) out)
(write-string ")" out)))

This works fine. But if I try to extract that lambda into a named function:

(struct point (x y) #:property prop:custom-write write-point)
(define (write-point pt out _) ...)

That doesn't work, and the error complains that I'm using write-point
before it's defined. This error makes sense to me. The property value is
associated with the type, not with instances, and the struct form is
essentially a macro that expands to a call to `make-struct-type` with a
list of property values. So I understand that I need to define those
properties before using them in the struct definition:

(define (write-point pt out _) ...)
(struct point (x y) #:property prop:custom-write write-point)

All well and good. But then I decide that defining write-foo for every one
of my struct types is tedious, so I define a make-list-type-writer helper
function and try to use it:

(define ((make-list-type-writer name . accessors) this out _)
  (write-string "(" out)
  (write-string name out)
  (for ([accessor (in-list accessors)])
(write-string " " out)
(write (accessor this) out))
  (write-string ")" out))

(define write-point (make-list-type-writer "point" point-x point-y))
(struct point (x y) #:property prop:custom-write write-point)

And now we've got a problem. This doesn't work because I can't pass the
point-x and point-y accessors as arguments to make-list-type-writer. They
don't exist yet! So in order to make my property value, I need the struct
defined. But in order to define the struct, I need the property value. A
workable fix is to delay evaluation somewhere with lambdas:

(define write-point
  (make-list-type-writer
"point"
(lambda (this) (point-x this))
(lambda (this) (point-y this

This feels tedious and unnecessary. Looking at the underlying API of
make-struct-type, I can't see any way to avoid this mutual recursion. Which
is *weird* to me, because when else are you forced to use mutual recursion?
Mutually recursive functions can be transformed into functions that accept
the other function as an argument. Mutually recursive modules can (usually)
be broken down into smaller modules that don't have any cyclic
dependencies. But I can't seem to do the same for structs, which makes it
difficult to write nice helper functions for building struct types in a
first-class 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.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Collections and data structures wishlist?

2019-01-25 Thread Jack Firth
I don't intend to make these operations impossible or even difficult. One
of the other things on my wishlist is a transducers library, which would
IMO be a good fit for a lot of the logic that Racket currently provides as
list-processing functions. So if you want to process tuples as generalized
streams of values, you'd use transducers on them. But if you want to
process tuples as *tuples*, you'd use tuple-processing functions. I think
mapping and filtering fit the first category more than the second. This
kind of divide makes it much easier to support a wide array of data
structures without copying the entire list processing API for each one.

On Fri, Jan 25, 2019 at 12:51 PM Matthias Felleisen 
wrote:

>
> > On Jan 25, 2019, at 3:46 PM, Thomas F. Burdick 
> wrote:
> >
> >
> >
> > On January 25, 2019 8:33:09 PM GMT+01:00, Jack Firth <
> jackhfi...@gmail.com> wrote:
> >>
> >> Due to the kind of data that would go in tuples - namely, a fixed-sized
> >> heterogeneous collection of values - a function probably *shouldn't*
> >> use
> >> map and filter to process tuples. A program that calls filter on an
> >> x-y-z
> >> coordinate tuple is likely incorrect and not what the programmer
> >> intended.
> >
> > Funny you should pick that as an example. I work in a CAD environment
> where points are two-item lists, and polygon outlines are lists of points.
> You'd be surprised how often it's useful to use ordinary list functions on
> points.
>
>
> That’s precisely the kind of programming I had in mind. Racket is one of
> the few languages where you can eat your cake and have it anyways. Why take
> away that strength?

-- 
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] Collections and data structures wishlist?

2019-01-25 Thread Jack Firth
>
> Maybe you'll need to clarify what Racket2 is? I am not familiar.


Racket2 is the (unofficial) name of what Racket could hypothetically be if
we made lots of breaking changes to the existing APIs. It's named that
because it would likely mean creating a `#lang racket2` language with all
of the new APIs instead of breaking existing code that uses `#lang racket`.

(define tuple/c list/c)
> The key to list/c and listof is that the code inside of
> functions contracted with either of them can use map
> and filter and everything else to process the arguments.


Due to the kind of data that would go in tuples - namely, a fixed-sized
heterogeneous collection of values - a function probably *shouldn't* use
map and filter to process tuples. A program that calls filter on an x-y-z
coordinate tuple is likely incorrect and not what the programmer intended.
The same is true for a function that calls map on a tuple containing many
wildly different kinds of data.

Well also, I thought `list/c` already means "tuple"?
>
> (listof number?) is a list of many numbers.
> (list/c number?) is a list of one number.
>

And this has tripped me up numerous times. I often forget which is the one
I meant to use and have to look it up in the docs, assuming I even notice I
used the wrong one. With distinct list and tuple types, these two contracts
could be named `list/c` and `tuple/c` and we wouldn't need this strange
"foo-collection/c vs foo-collectionof" distinction in our contract
combinators.

Tables are pretty cool!
> https://www.pyret.org/docs/latest/tables.html


I love this idea.

On Thu, Jan 24, 2019 at 11:20 AM Matthias Felleisen 
wrote:

>
> (define tuple/c list/c)
>
> The key to list/c and listof is that the code inside of
> functions contracted with either of them can use map
> and filter and everything else to process the arguments.
>
>
>
> > On Jan 24, 2019, at 8:33 AM, Gustavo Massaccesi 
> wrote:
> >
> > I also like the idea of a contract like "tuple/c", perhaps with a more
> rackety name.
> >
> > Gustavo
> >
> > On Wed, Jan 23, 2019 at 12:02 PM Greg Hendershott <
> greghendersh...@gmail.com> wrote:
> > >> - A separation between using lists as homogeneous collections and
> using lists as fixed-size tuples. So there'd be a separate `tuple?` data
> type that's structurally equivalent to a list but meant to be used
> differently. For example, `(list/c number?)` would mean a list of many
> numbers, but `(tuple/c number?)` would mean a tuple of size 1 containing a
> number.
> > >
> > > "It is better to have 100 functions operate on one data structure than
> 10 functions on 10 data structures.”
> http://www.cs.yale.edu/homes/perlis-alan/quotes.html
> > > "It is better to have 100 transducers operate on one data structure
> interface than 10 functions on 10 data structures.” Rich Hickey, History of
> Clojure
> >
> > Well also, I thought `list/c` already means "tuple"?
> >
> > (listof number?) is a list of many numbers.
> > (list/c number?) is a list of one number.
> >
> >
> > I think it's within the Racket spirit to make a little #lang for
> > certain audiences or projects. At some org, "tuple/c" might be a
> > helpful alias. Or, for some other team, it's not, and in fact even
> > "list/c" is redefined to raise an error, "Please use structs instead
> > of ad hoc tuples."
> >
> > --
> > 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.


[racket-users] Questions about module encapsulation guarantees

2018-09-09 Thread Jack Firth
If I make a symbol with `gensym` (or do anything else that creates a new 
value that's not `eq?` to any other value) in some module, what are the 
absolute upper limits on my ability to use that symbol within the module 
without allowing any other modules to get ahold of the symbol? What do code 
inspectors, namespaces, sandboxes, eval, `unsafe` APIs, the FFI, etc. make 
possible for malicious code in external modules?

Context: I'm exploring a "contract witness" idea whose implementation 
currently relies on the eq?-ness of opaque struct instances for security. 
But I vaguely recall hearing once that the The Only Way To Be Sure when it 
comes to struct encapsulation is to put the definition of a struct inside a 
lambda, otherwise some sort of nebulous "bad things" are possible in 
external code that wants to break the invariants of  a struct type.

-- 
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] Re: Experience with REST APIs in Racket

2018-04-12 Thread Jack Firth
I think this is an area where Racket's ecosystem could be significantly 
improved. However, this would probably only be worth the investment for 
those developing on both the client and server side of multiple services. 
Do you have plans to develop your own HTTP service APIs in Racket as well?

On Wednesday, April 11, 2018 at 11:36:50 AM UTC-7, Paulo Matos wrote:
>
> Hi, 
>
> I am interested in developing a Racket wrapper for hetzner cloud rest 
> api. This is a REST API defined in: 
> https://docs.hetzner.cloud/ 
>
> I however, have no experience with accessing REST APIs in racket much 
> less developing one. 
>
> 1. Are there any examples out there of wrapping rest apis in racket? 
> 2. If you look at how this is done in Python[1] as expected everything 
> is an object. However, from what I generally see, libraries seem to 
> rarely touch the racket object system (although I think it's great). So, 
> I guess instead of having an object 'Client' to which you would do (send 
> client login "username" "password"), is it generally preferable to have 
> a (make-client ...), which you would follow with (client-login 
> "username" "password")? 
>
> Any thoughts would be appreciated before I commit myself, only to find 
> it goes against the racket way once I publish it. :) 
>
> [1] https://github.com/elsyms/hetznercloud-py/ 
> -- 
> Paulo Matos 
>

-- 
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] Re: Question about Racket design philosophy: returning (void)

2018-04-10 Thread Jack Firth
Racket's also flexible enough that you can say "to hell with void, I want 
function chaining" if you decide it's more appropriate:

(require fancy-app) ;; now (+ _ 1) means (lambda (v) (+ v 1))
(require point-free) ;; now (~> x f g h) means (h (g (f x)))

;; makes voidful procedures return their argument
(define ((action! proc) v)
  (proc v)
  v)

;; like ~>, but turns all procedures into actions first
(define (act~> v . procs)
  (apply ~> v (map action! procs)))

;; voila!
(act~> (make-vector 5)
   (vector-fill! _ 'blank)
   (vector-set! _ 2 'grapefruit)
   (vector-set! _ 0 'watermelon)
   (vector-map! symbol->string _)
   (vector-sort! _ stringhttps://groups.google.com/d/optout.


Re: [racket-users] Another pkgs badge improvement, re needing documentation

2018-03-26 Thread Jack Firth
You could get very close to this by making the package catalog and naming 
system hierarchical rather than flat. A package `foo` would be both a 
package and it's own package catalog, nested within the parent catalog. 
Each of the `foo-lib`, `foo-doc`, and `foo-test` packages would instead be 
`lib`, `doc`, and `test` packages within the `foo` catalog. Federated 
namespaces are fantastic for this sort of problem and there's a lot of 
precedent for using them in package naming. The npm package system recently 
added "user scopes" so every user account gets their own slice of the 
package namespace (foo@jack and foo@jay refer to two packages both named 
foo but with different owners), and docker image registries do something 
similar.

On Monday, March 26, 2018 at 1:44:23 PM UTC-7, Jay McCarthy wrote:
>
> I agree that such a tool would be very useful and awesome. One 
> coherent thing might be a way to create a piece of data in the info 
> file that lists which modules & collections go in which packages in a 
> "virtual" way and have them split by "raco pkg", then extend that 
> language with the ability to splice out a submodule. 
>

-- 
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] Re: Splitting up a GUI source file?

2018-03-25 Thread Jack Firth
On Friday, March 23, 2018 at 8:39:52 AM UTC-7, HiPhish wrote: 
>
> I might reconsider the rentals part, but that's not relevant at the 
> moment. My
> problem is that even though the three panes don't need to know anything 
> about
> each other, they need to know about their parent (the main tab view), I 
> cannot
> split the code into a module hierarchy like the tree.
>
>   (define main-window (new frame% [label "Library"]))
>   (define main-tab-view (new tab-panel% [parent main-window]))
>
>   (define books-panel (new vertical-panel% [parent main-tab-view]))
>   (define books-table (new list-view% [parent books-pane]))
>   (define books-buttons-pane (new horizontal-pane% [parent books-panel]))
>   (define add-button (new button% [parent books-buttons-pane]))
>   (define remove-button (new button% [parent books-buttons-pane]))
>   (define rent-button (new button% [parent books-buttons-pane]))
>
>
> And so on. This isn't much code, but add in all the callbacks and events, 
> and
> repeat that for all the three views, and the code quickly starts adding up.
> How should I break it up into smaller modules?
>

What about defining functions that accept the parent as an argument? That's 
essentially what creating a subclass with an init parameter does, but in a 
less roundabout way:

  (define main-window (new frame% [label "Library"]))
  (define (main-tab-view p) (new tab-panel% [parent p]))
  (define (books-panel p) (new vertical-panel% [parent p]))
  (define (books-table p) (new list-view% [parent p]))
  (define (books-buttons-pane p) (new horizontal-pane% [parent p]))
  (define (add-button p) (new button% [parent p]))
  (define (remove-button p) (new button% [parent p]))
  (define (rent-button p) (new button% [parent p]))

This assumes that the only thing tying these objects together is the 
parent-child relationship. If you've got more cross-component references 
then subclasses might be more manageable. Disclaimer: I'm not very familiar 
with Racket's class system or its GUI system, as I don't typically use 
either in my projects.

-- 
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] Re: Understanding 'curry'

2018-02-28 Thread Jack Firth
Thanks everyone for the headache. I think I'll stick to the `fancy-app` 
package and reserve curry for adventurous dinner outings.

-- 
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] Re: How to check if a symbol is defined before calling it?

2018-02-18 Thread Jack Firth

>
> The recent plot library introduces a new function, `point-pict` which is 
> not yet available as part of a Racket distribution, and the plot package 
> has to be installed separately from GitHub for this function.
>
> In my code I would like to be able to check if this function is available 
> before calling it, so my code compiles correctly even if the function is 
> not available.
>

In addition to the `dynamic-require` solution, you can do this statically 
with macros and `identifier-binding`:

(define-simple-macro (begin-when-bound id:id body ...+)
  #:with (body* ...) (if (identifier-binding #'id) #'(body ...) #'())
  (begin body* ...))

Warning: I have only written the above code, not run it. See also the 
version-case  package 
for a similar, more fleshed out concept.

-- 
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] Path to file in dynamic-place

2018-01-23 Thread Jack Firth
A rule of thumb you can follow to avoid tricky bugs like this: *never use 
string literals as dynamic module names.* Anywhere you see a dynamic / 
reflective function on modules called with a literal string, a 
contradiction exists between the programmer and the dynamic function:

1. The programmer intends to use a specific module referenced in the 
context of the program source code.
2. The dynamic function intends to operate on an arbitrary unknown module 
referenced in the context of the program execution environment.

This is why define-runtime-path exists. It acts as a bridge between the two 
worlds of the module system used to compile a program source and the module 
system that compiled program interacts with at runtime. The two systems 
cannot be assumed identical because 1) a program may be compiled on one 
machine and executed on another and 2) modules only used at compilation 
time may be excluded from the compiled form of a program.

The "place-worker.rkt" example in the places docs is somewhat misleading 
since it refers to the place-launching code as if it wasn't in a module 
(note that no file names are mentioned in the example other than 
"place-worker.rkt"). It would be clearer if it named the launcher code 
"place-launcher.rkt", clarified that "place-launcher.rkt" and 
"place-worker.rkt" must be in the same directory, and used 
(define-runtime-path worker-mod "place-worker.rkt") to refer to the worker 
module from the launcher module.


-- 
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] Re: Installing Racket Package `gregor` inside a Docker container

2017-12-29 Thread Jack Firth
With the Docker images I use for Racket, gregor installs fine. I ran the 
command `docker run -it jackfirth/racket:6.11 raco pkg install --auto 
gregor` and it completed without error. You can find the dockerfile being 
used to produce those images in the Github repo 
. 
Maybe there's something off with the dockerfile you're using?

-- 
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] Re: Best way to deploy to the package server if the module relies on a DB?

2017-12-13 Thread Jack Firth
In my fixture  package I'm 
attempting to (hopefully) make this sort of thing easier for RackUnit-based 
tests (see this github issue 
), so if you're 
using RackUnit I'm interested in seeing what your tests look like and how 
you go about setting up a database for them.

-- 
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] Re: how can I approximate syntax properties with `make-rename-transformer`?

2017-11-28 Thread Jack Firth
What about passing the configuration data to `other-module-begin` via 
keyword arguments or tagged expressions in the body of the 
`(other-module-begin ...)` expansion? Is there a particular reason `mb` and 
`other-module-begin` need to communicate with syntax properties?

On Tuesday, November 28, 2017 at 7:15:50 PM UTC-8, Matthew Butterick wrote:
>
> I'm making a #%module-begin macro, but I want to delegate it to an 
> existing one. 
>
> OK, let's start with a rename transformer: 
>
> (provide (rename-out [mb #%module-begin])) 
> (define-syntax mb (make-rename-transformer #'other-module-begin)) 
> (define-syntax other-module-begin (λ (stx) #'foo)) 
>
> That works, but I also need to pass some extra data to 
> `other-module-begin` that controls how it's configured during this 
> delegation. 
>
> OK, let's add a syntax property. But wrapping the property around the 
> transformer doesn't work, because a rename transformer is not `syntax?`: 
>
> (provide (rename-out [mb #%module-begin])) 
> (define-syntax mb (syntax-property (make-rename-transformer 
> #'other-module-begin) 'foo "bar")) 
> (define-syntax other-module-begin (λ (stx) #'foo)) 
>
> ;; syntax-property: contract violation 
>
>
> I can wrap the property around the target identifier, but the syntax 
> property doesn't stick: 
>
> (provide (rename-out [mb #%module-begin])) 
> (define-syntax mb (make-rename-transformer (syntax-property 
> #'other-module-begin 'foo "bar"))) 
> (define-syntax other-module-begin (λ (stx) #'foo)) 
>
> (syntax-property #'mb 'foo) ; #f 
>
>
> Other possibilities with equivalent effect?

-- 
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: #lang languages and cyclic dependencies

2017-11-28 Thread Jack Firth
Huh, I must have missed this the first time around. I've run into this sort 
of thing multiple times before and it usually brings me to this question:

What if the configuration file was the main module of your app, instead of 
something imported by your app?

Think about it. The "my-project/config/local" and 
"my-project/config/production" modules are essentially saying "to run the 
app locally, set the project config to these values". What module could 
possibly have a use for that information other than the main "app startup" 
module? It seems like all other code should only depend on modules that 
define the *schema *of configuration, rather than any modules that set that 
configuration to specific values. It seems odd for the schema definition 
module (my-project/config) to depend on modules that actually use that 
schema to set config values (my-project/config/local). The reverse sounds 
more sensible.

If you make a module written in `#lang my-project/config` expand to a 
`main` submodule that starts up your app you get some other neat Rackety 
things to show off to your colleagues: not only will they get an IDE with 
syntax highlighting and good error messages "for free",  pressing the Run 
button with a config file open will launch the app automatically! This 
might not work if launching your app is especially complicated, but I'm 
curious if you've explored this direction and what your thoughts are.

On Tuesday, November 28, 2017 at 1:28:06 PM UTC-8, Philip McGrath wrote:
>
> For the benefit of posterity, while I haven't actually solved the 
> cycle-in-loading error, I was able to get the results that I wanted in this 
> case by:
>
>1. Implementing the language as a `module` (not `module*` or 
>`module+`) submodule of "my-project/config.rkt", including a
>(module reader syntax/module-reader
>  #:language '(submod my-project/config lang))
>2. In the body of the outer `my-project/config` module, instead of 
>requiring the values from "my-project/config/local.rkt" etc. as usual, 
>getting them lazily/dynamically, which I am doing with a little wrapper on 
>top of `define-runtime-module-path-index`, though `racket/lazy-require` 
>would probably also work well.
>
> Evaluating the configuration files lazily was particularly good for me 
> because it lets me write, say, "production.rkt" assuming that various 
> things from the production server exist and just raising an error if not, 
> rather than having to make everything in every configuration file run on 
> every machine.
>
> -Philip
>

-- 
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] Unit test inner procedures

2017-11-28 Thread Jack Firth
I like it. Added an issue <https://github.com/racket/rackunit/issues/85> to 
figure out a Rackety way to do this; feedback strongly encouraged.

On Tuesday, November 28, 2017 at 11:05:50 AM UTC-8, Benjamin Lerner wrote:
>
> (Pyret co-lead dev here.)
>
> The way nested tests work for us in Pyret is actually simpler than that: 
> As a dummy example, consider a curried addition function
>
> fun make-adder(num1 :: Number):
>   fun result(num2 :: Number):
> num1 + num2
>   where:
> result(5) is num1 + 5
> result(10) is num1 + 10
>   end
>   result
> where:
>   make-adder(3)(6) is 9
>   make-adder(4)(2) is 6
> end
>
> This definition will run *six* test cases — the two test cases for 
> make-adder will each run the two nested test cases for result. These will 
> be reported as three blocks of test cases: one block for make-adder and 
> two blocks for result. The test cases for result run in the lexical scope 
> of the body of make-adder, so they have closed over num1 as part of their 
> environment.
>
> (In practice, this can lead to many, many test cases, obviously. So when 
> running a program in Pyret, by default we only run the test cases lexically 
> present in the main module of the program.)
>
> ~ben
>
> On 11/28/2017 01:53 PM, Jack Firth wrote:
>
> BUT, one could easily imagine an extension to the unit testing framework 
>> where inner tests work, too. With a combination of coverage and unit 
>> testing, you can usually get these inner unit tests to run and record their 
>> status the same way outer ones do in module+. Pyret, for example, does 
>> exactly this, so we should be able to do it too.
>>
>
> Looking at Pyret, you're referring to the "where" syntax right? So this:
>
> fun sum(l):
>   cases (List) l:
> | empty => 0
> | link(first, rest) => first + sum(rest)
>   end
> where:
>   sum([list: ]) is 0
>   sum([list: 1, 2, 3]) is 6
> end
>
> ...means that the "where" body is composed of tests of the `sum` function. 
> I like this a lot and want it for Racket (in a way that's more direct than 
> submodules). But I have no idea how it should work for nested functions 
> that close over variables of the outer function. Would the tests specify 
> the closure bindings maybe?
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users...@googlegroups.com .
> 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] Unit test inner procedures

2017-11-28 Thread Jack Firth

>
> BUT, one could easily imagine an extension to the unit testing framework 
> where inner tests work, too. With a combination of coverage and unit 
> testing, you can usually get these inner unit tests to run and record their 
> status the same way outer ones do in module+. Pyret, for example, does 
> exactly this, so we should be able to do it too.
>

Looking at Pyret, you're referring to the "where" syntax right? So this:

fun sum(l):
  cases (List) l:
| empty => 0
| link(first, rest) => first + sum(rest)
  end
where:
  sum([list: ]) is 0
  sum([list: 1, 2, 3]) is 6
end

...means that the "where" body is composed of tests of the `sum` function. 
I like this a lot and want it for Racket (in a way that's more direct than 
submodules). But I have no idea how it should work for nested functions 
that close over variables of the outer function. Would the tests specify 
the closure bindings maybe?

-- 
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] Re: Unit test inner procedures

2017-11-27 Thread Jack Firth
I don't think you can directly test an inner procedure while keeping your 
test code separately loadable (e.g. different file or module). It doesn't 
seem like a good idea to me, personally. Inner procedures communicate to me 
that I can change, reorganize, delete, and otherwise do whatever I want to 
them without breaking any code outside the definition of the outer 
procedure. Breaking tests in a different file with a refactoring of an 
inner procedure would be *very *surprising to me.

Instead, I recommend not using inner procedures so extensively. Instead 
define functions within modules (or possibly submodules) and use `provide` 
with `contract-out` to declare which functions make the public API of your 
module. You can then add a test submodule which has access to the inner 
workings of the outer module and test "private" helper functions that way. 
Here's an example:

#lang racket;; note that using #lang implicitly creates a module around the 
whole file

(provide
  (contract-out
[my-public-function (-> input? output?)]))

(define (my-public-function input)
  (helper2 (helper1 input)))

(define (helper1 input) ...)
(define (helper2 input) ...)

(module+ test ;; inside this submodule we can see helper1 and helper2, even 
though they're not provided
  (require rackunit)
  (check-equal? (helper1 test-input) test-output)
  ... more tests 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.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Re: single-file packages and embedded documentation and metadata

2017-11-10 Thread Jack Firth

>
> I have to redo my tools once more, and am sick of my current `(doc ...)` 
> and `@doc` format, *and the resulting dependency on McFly.* 
>

Could you elaborate on your experience with this? For a module with 
embedded docs I'd want to treat them the same as tests: in a special 
submodule which results in "build-time" dependencies instead of runtime 
dependencies. With the current package build system, users could install my 
package with embedded docs in pre-built form without installing build-time 
dependencies using `raco pkg install 
--catalog https://pkg-build.racket-lang.org/server/built/catalog/ --binary 
mypackage`, assuming they're running the same version of Racket as the 
package build server.

My gut instinct is that I'd like to explore making pre-built package 
installations more automatic and pain-free for package users, rather than 
asking package developers to avoid adding dependencies entirely by using 
special comments and separately installed special tools. Putting docs in 
specially-formatted comments means running my code in DrRacket won't check 
my docs for syntax errors.

-- 
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] where does DrRacket get its environment variables on OS X?

2017-11-08 Thread Jack Firth

>
> I wonder whether a submodule is a better approach here. DrRacket 
> implicitly runs a `test` submodule, while `racket` doesn't, and you 
> could add more submodules to the list in DrRacket. But that approach 
> doesn't work if the conditional adjustment goes in a library, instead 
> of the main module. 
>

The library could provide a language that added the needed submodules 
automatically, much like how `configure-runtime` submodules are currently 
added.

What about an `interaction` submodule that worked sort of like `main`, but 
was run when a program is both run as the main program *and *run in an 
environment where the user expects to interact with the live running 
program in some way? The default `#%module-begin` of `racket/base` could 
add an `interaction` submodule that implements the normal racket REPL, 
while a domain specific language for configuring a server (think of 
something like #lang htaccess) could provide a "REPL" that lets you "do 
stuff" to the server, like restart it, reload config, etc.

My thinking is that the important distinction is not about whether a 
program is running in a dev environment or a prod environment - it's about 
whether the programmer wishes to *interact* with the program after running 
it. How to interact with the running program should be defined by the 
program itself, not tools on top of the program. Tools should only allow a 
programmer to declare their intent to interact.

-- 
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] Re: Open source projects

2017-10-19 Thread Jack Firth
Welcome, we're very glad to have you!

Open source Racket projects are scattered all over the place, but here are 
some good ways to find actively maintained and hopefully accessible 
projects that might interest you:

- Watch some talks from recent RacketCons, especially the most recent one 
(which, conveniently, was barely a week and a half ago). A lot of talks are 
on interesting and wildly unusual open source projects, and as a bonus most 
presenters give out their contact information so people can reach out if 
they have questions or might be interested in contributing. You can find 
information on the most recent RacketCon at con.racket-lang.org including 
video and livestream recordings, talk descriptions, and slides for each 
talk. Info for previous RacketCons are available at 
con.racket-lang.org/2016/, con.racket-lang.org/2015/, etc. Alas we don't 
yet have individual prettily-edited videos for each talk at RacketCon 2017; 
they're only viewable via the saved livestream on youtube.
- Search the official package catalog at pkgs.racket-lang.org for packages 
whose descriptions sound interesting and which are hosted on GitHub / 
GitLab / some other platform that makes it easy to contribute. Every 
package includes links to its docs and repostiory, as well as a contact 
email address for whoever maintains it. If you're not looking for a package 
in a particular problem domain your best bet is probably to restrict your 
search to only packages that build, have passing tests, and have docs. 
Decent issue / todo lists in the project repo are a nice bonus.
- Browse around the front page of the online Racket documentation at 
docs.racket-lang.org. The online docs includes all docs from all 
successfully built user packages at pkgs.racket-lang.org, grouped into top 
level categories. Once you find some docs for a project that's interesting, 
it's (hopefully!) not difficult to find the package containing those docs 
by searching pkgs.racket-lang.org.
- Hop in the Racket IRC (#racket on freenode) or the Racket Slack channel 
(signup at racket-slack.herokuapp.com) and ask around about what people are 
working on. I'm sure many folks will be delighted to talk about their 
projects. And this mailing list isn't a bad place to ask either.
- If you want to try something more ambitious, you can take a peek at the 
Github repos in the "racket" organization (https://github.com/racket). 
These are all (or mostly? not sure) packages in the "main distribution", 
meaning they ship directly with Racket and don't have to be installed by 
users. Contributing to these packages can be a little trickier because 
sometimes they depend on the latest version of Racket's core, meaning 
you'll have to compile Racket's core from source.

Also, all throughout this month Github and DigitalOcean are hosting an 
online event called Hacktoberfest. By signing up 
at https://hacktoberfest.digitalocean.com/ you'll get a free tshirt mailed 
to you if you submit four or more pull requests to any public repositories 
on Github before October ends. It doesn't matter how large each pull 
request is and a pull request to your own repo counts. And speaking from 
experience, they're very comfortable shirts.

>

-- 
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] Intro and projects inquiry

2017-10-14 Thread Jack Firth

>
> > Racket doesn't play well with existing code bases (except C things) 
> > and so my hypothesis is simply that to gain adoption of Racket, you 
> > need to solve problems that aren't in the "production path." Good 
> > thing there are *lots* of those! All those Python scripts you have? 
> > All of those Perl scripts that no one understands anymore? Those are, 
> > in my opinion, the way in. 
>
> Funny story: That's how I cam back to Racket/Scheme. Several years ago I 
> worked on a web application written in Common Lisp. I needed some 
> "electronic duct tape" work done. I didn't use Common Lisp because of 
> its slow startup time and I was unhappy with shell scripts either. 
> Therefore I remembered that there was PLT Scheme/Racket around with 
> "batteries included". So nowadays lot of these tasks are now done using 
> Racket. 
>

There are some really neat packages that help make writing these sorts of 
scripts in Racket
easier. The Rash  language is designed 
with a line-based syntax and pipelining features similar
to traditional shell scripting languages, but because it's a Racket lang 
you can import Racket
libraries for use in your script and you can extract parts of your shell 
script into regular Racket
modules as the script grows in complexity.

There's also the Scripty  language, 
which does something a bit weird: it lets you write what
packages a script depends on inside the script itself, and when the script 
is run it will automatically
check to see if they're installed and prompt the script user to install 
them if they're not. This lets
you use whatever packages you like in your Racket scripts without burdening 
your coworkers with
the task of making sure those packages are installed and up to date before 
trying to run the script.

-- 
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] Re: code reflection

2017-10-14 Thread Jack Firth

>
> So is there a way ... from normal code ... to get at the locals of 
> functions higher in the call chain?  Or at least the immediate caller? 
> Some reflective capability that I haven't yet discovered? 
>

I'm not sure if there's a way to do that, but I'm wondering if what you 
want to do can be achieved more simply with plain functions and a very 
small macro wrapper. In particular, I suspect putting too much logic in the 
macro is what led you to eval which is the root of all evil. From what I 
can tell there shouldn't be any need at all for eval or any sort of dynamic 
runtime compilation to do things like what you're describing. Could you 
give a few more details about your use case? Ideally with some example code 
illustrating the problem?

-- 
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] Re: [ANN] Porting PAIP's Prolog interpreter from Common Lisp to Racket, 1st version

2017-10-14 Thread Jack Firth
This is really cool, thanks for writing about it and sharing it! And thanks 
for showing me another book I ought to get around to reading.

There were some very interesting talks last weekend at RacketCon 2017 
related to logic programming, program synthesis, and unification that you 
might be interested in. You can find a list of talks and links to the 
livestreams at con.racket-lang.org.

-- 
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] Intro and projects inquiry

2017-10-11 Thread Jack Firth

>
> Web back-ends are my wheelhouse. It sure would make my professional life 
> easier... Not gonna lie, this isn't something I'd look forward to banging 
> out alone.
>

I've been looking into web stuff for Racket quite a bit, specifically web 
microservices. Shoot me an email if you're interested in more details.

-- 
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 newbie, myfunctionname undefined

2017-09-29 Thread Jack Firth
A few other notes / tips:

- The `scribble/example` library is meant to replace the legacy 
`scribble/eval` library, as the `examples` form provided by 
`scribble/example` will make documentation building fail if example code 
throws an unexpected error.
- Did you add a `scribblings` field to your package's `info.rkt` module? If 
so just running `raco setup` from anywhere will render your docs; no need 
to `cd` into the right directory and fiddle with the scribble CLI. Unless 
you're doing that on purpose, in which case I'm curious why.
- It's simpler for package scribblings to import the package implementation 
module via its name instead of a relative path, e.g. `(require foo)` 
instead of `(require "../main.rkt")`. This means you don't have to worry 
about breaking relative paths when moving your documentation files around, 
and in particular it makes it easier to extract documentation into a 
separate `foo-doc` package if you find you want to do that.

-- 
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] Re: tabular text display

2017-09-21 Thread Jack Firth
I've implemented this for board games occasionally, so +1 to someone making 
a package.

-- 
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] Re: Efficient & "nice" communication mechanism between Racket and other languages

2017-09-07 Thread Jack Firth
On Thursday, September 7, 2017 at 9:11:47 AM UTC-7, Brian Adkins wrote:
> I'm considering having a group of programmers create micro-services in 
> various programming languages to be glued together into a single application. 
> I would like a communication mechanism with the following characteristics:
> 
> * More efficient than HTTP

Unfortunately Racket doesn't have an HTTP/2 implementation, or I would 
recommend that. Could you elaborate on your efficiency requirements? It's 
possible a proxy that handled HTTP/2 connections could work for you and I 
suspect that would be much simpler than trying to make your own APIs atop a 
lower-level messaging protocol like ZeroMQ.

-- 
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: Racket Web servlet performance benchmarked and compared

2017-09-05 Thread Jack Firth
On Tuesday, September 5, 2017 at 3:17:38 AM UTC-7, Piyush Katariya wrote:
> Wow.  ~7K looks like good number.
> 
> Is it common practice to spawn Thread for each request ? Is it that cheap 
> from resource point of view ? can ThreadPool could be of some help here ?

Racket threads are not OS threads. They're "green threads" and are 
cooperatively scheduled by the Racket runtime. They're very cheap to create, 
even with a short life span.

-- 
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] Re: Mapping over pattern variables

2017-09-01 Thread Jack Firth
I recommend splitting this macro in two so you don't need to escape out of the 
template language:

(define-syntax (macro stx)
  (syntax-parse stx
[(_ (var1:id ...) (~and vars (var2:id ...))
 #'(begin (macro/var2 (#freeze var1) vars) ...)]))

(define-syntax (macro/var2 stx
  (syntax-parse stx
[(_ var1/freeze (var2:id ...))
 (begin (do-something var1/freeze var2) ...)]))

This also lets you get more information out of the macro stepper when 
debugging, since you'll see two separate expansion steps.

-- 
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] pkgs.racket-lang.org log in is down

2017-08-29 Thread Jack Firth
On Tuesday, August 29, 2017 at 10:42:31 AM UTC-7, Tony Garnock-Jones wrote:
> It'd also be great for Racket in general to have better visibility into 
> running programs to see what's going wrong with them in situations like 
> this.

I think it's possible to do this with existing features and libraries. You 
could use a thread group[1] to make two sets of threads: one for normal user 
requests, and one for debugging and introspection requests from administrators. 
Then, if somehow the request threads got locked up on some CPU-bound infinite 
loop you could still handle debugging requests. A good debugging endpoint might 
be one that uses a statistical profiler[2] to get a sense of what the user 
request threads are doing. A package that provided some convenience wrappers 
around thread groups, the statistical profiler, and the web server library to 
automatically make such a debugging endpoint would be a good project for any 
web-oriented Racketeers out there.

[1] http://docs.racket-lang.org/reference/threadgroups.html
[2] http://docs.racket-lang.org/profile

-- 
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: Racket dotenv file loading

2017-08-27 Thread Jack Firth
On Sunday, August 27, 2017 at 7:57:52 PM UTC-7, Royall Spence wrote:
> And it's ready to consume:
> https://pkgd.racket-lang.org/pkgn/package/dotenv
> 
> This is the first Lisp-family code I've published, so that's exciting.
> Any feedback the list has to offer regarding style, approach, or
> packaging would be welcome.

Looks great! I'll keep this in mind next time I'm working with env configs. 
Here are
some comments:

- Using `for` expressions would make recursion unnecessary, and it cooperates 
well with in-lines.
- Racket style generally prefers lists, first, and rest to raw pairs and the 
c*r functions.
- You can put your test submodules anywhere, they don't have to be in main.rkt. 
So in dotenv/private/tests.rkt you don't need to define and export a suite, you 
can just use (module+ test ...). Running raco test -p  will 
run all test submodules found anywhere in the package.
- It looks like the generated scribble files got included in your repo. I 
typically add html, js, and css files to my .gitignore to avoid that.
- If you move your (require rackunit) expressions into your test submodules, 
rackunit will be a build dependency instead of a runtime dependency.
- Using @defproc[] in your scribble docs will make the exports of dotenv 
searchable.
- Contracts and contract-out make it easy to add argument checking to 
functions, I recommend using them.

-- 
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] Re: Racket dotenv file loading

2017-08-27 Thread Jack Firth
On Sunday, August 27, 2017 at 11:01:17 AM UTC-7, Royall Spence wrote:
> I'm starting work on a Racket library for loading .env files to override 
> environment variables. This is a common way of doing things for people who 
> want to run multiple web applications on a single server without their 
> environment variables competing for namespace. The classic example is this 
> Ruby library: https://github.com/bkeepers/dotenv
> 
> Just checking to make sure I haven't overlooked an already existing library 
> that provides this behavior. Should I keep going?

There is the Envy library for parsing environment variables, but there doesn't 
seem to be anything for loading .env files. Personally, I think this would be a 
great place to make a #lang that worked something like this:

#lang dotenv
my-library-num-workers = 5
my-library-tmpdir = "/tmp/my_library"

... and then if you `require` it, it sets the current environment. Or maybe it 
gives you a function to execute a thunk with the new environment. The advantage 
to using a #lang here instead of a file is your dotenv file is you no longer 
need to do any parsing or file IO at runtime and your env file is just a normal 
code module imported like any other. Plus you could write a syntax highlighter 
to make it easy to edit the env files in DrRacket.

-- 
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] Re: Contract for function of either one or two arguments?

2017-08-24 Thread Jack Firth
> I want to be able to say "the rest argument is a list that has an even number 
> of elements and more than zero elements", but I'm not sure how to capture 
> that.  Thoughts?

I've run into this multiple times as well, and would like someone (maybe me) to 
write a package (maybe named `sugar-contract`) that provides this.

-- 
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] Re: How to introspect a function? (and/or other things)

2017-08-22 Thread Jack Firth
> Likewise, I haven't had much luck figuring out how to introspect structures.  
> I can say (object-name strct) to get the name of the struct, but I cannot 
> find any way to answer the questions:
> 
> 
>     - What are the names of your fields?
> 
>     - What are the accessor / mutator functions for your fields? [The actual 
> function, not just the name]

I think the Structure Inspectors 
(http://docs.racket-lang.org/reference/inspectors.html?q=struct%20reflection) 
docs has what you're looking for here.

> If this were a thing then I could create nicer printers for structures such 
> that they labeled their field names or created a representation equivalent to 
> the creation command.
> 
> 
> What about functions?  Is there a way to answer the following questions?:
> 
>  - How many arguments do you require?
>  - How many values do you return?
>  - What is your contract?

You can get the contract attached to a value with `value-contract` - see 
Contract Utilities 
(http://docs.racket-lang.org/reference/contract-utilities.html?q=get-contract)

-- 
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] Re: "Test did not clean up resources" message from GUI test runner

2017-08-21 Thread Jack Firth
On Sunday, August 20, 2017 at 6:28:20 PM UTC-7, Alex Harsanyi wrote:
> I just noticed that the GUI test runner displays "test did not clean up 
> resources" messages on my tests, but it is not clear to me what resources are 
> not being cleaned up.  
> 
> I tried to reproduce the problem in the following test case:
> 
> #lang racket
> (require rackunit rackunit/gui db)
> 
> (define ts
>   (test-suite
>"test suite"
>(test-case
> "test-case"
> (check-not-exn
>  (lambda ()
>(define db (sqlite3-connect #:database 'memory #:mode 'create))
>(disconnect db))
> 
> (test/gui ts)
> 
> Here, a sqlite database is created in memory than the connection is closed.  
> The test runner complains that the data base connection is not cleaned up.  
> It also complains about a thread not being cleaned up, but the test does not 
> create any threads (at least not explicitly).   See attached picture for 
> details.
> 
> Can someone explain to me how to clean up properly in such a test?
> 
> Thanks,
> Alex.

Which version of racket are you using? And if you're using 6.10, do you get the 
same message on any older versions 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] [ANN] MessagePack implementation for Racke

2017-07-24 Thread Jack Firth
> Just to make sure I understood correctly: ‘msgpack’ is the umbrella module 
> that users import, ‘msgpack/test/pack’ (and ‘unpack’) are the test modules 
> that will be run for testing only. How about the directory structure? I like 
> to keep all source files in a source directory (my original reason for doing 
> ‘multi), can I still do something like this?
> 
> |-README
> |-LICENSE
> |-info.rkt
> |-source
>   |-msgpack.rkt
>   |-pack.rkt
>   |-unpack.rkt
> |-test
>   |-pack.rkt
>   |-pack
> |- ...
>   |-unpack.rkt
>   |-unpack
> |- …
> 
> It doesn’t have to be exactly this structure, but the idea is that all 
> project-realted files are in the root, all the source files in the source 
> directory and all the test files in the test directory.

That you cannot do, and if you wish to do that keeping your code as one package 
might be a little unidiomatic. If you want to keep your test code completely 
separate from your implementation code, and you want both to be separate from 
the top level root of the project, you could have two separate packages each 
with a single collection like so:

|-README
|-LICENSE
|-msgpack-lib
  |-info.rkt ;; collection is "msgpack"
  |-main.rkt
  |-pack.rkt
  |-unpack.rkt
|-msgpack-test
  |-info.rkt ;; collection is "msgpack"
  |-pack-test.rkt
  |-unpack-test.rkt

Having said that, have you considered test submodules? They allow you to write 
your tests in the same file as the code they're testing, while keeping test 
dependencies separate from your library's normal runtime dependencies. With 
test submodules, your code would probably look like this:

(define (pack ...) ...)

(module+ test
  test pack ...)

(define (unpack ...) ...)

(module+ test
  test unpack ...)

And your directory structure would look like this:

|-README
|-LICENSE
|-info.rkt ;; collection is "msgpack"
|-main.rkt
|-pack.rkt ;; has test submodule
|-unpack.rkt ;; has test submodule

You could also put the code into a subdirectory package like above, if you 
really want to keep the project files and the source files separate.

-- 
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] [ANN] New package: disposable

2017-07-21 Thread Jack Firth
I recently published `disposable`, an experimental package for safely handling 
external resources.

Features:

- representation of a "disposable", a producer of values with external 
resources that must be disposed
- safe handling of disposables for multiple usage patterns, including:
  - for a series of expressions, `(with-disposable ([v disp]) body ...)`
  - for the lifetime of the program with the resource cleaned up on program 
exit, `(acquire-global disp)`
  - for the lifetime of the current thread, with a single resource reused 
automatically in the same thread, `(acquire-virtual disp)` (heavily inspired by 
virtual connections in the `db` library)
  - until an arbitrary event is ready for synchronization, `(acquire disp 
#:dispose-evt (alarm-evt 1000))`
- abstractions over disposables and combinators for extending disposables, 
including:
  - creating a pool of disposable values with reuse, `(disposable-pool disp)`
  - asynchronously deallocating disposables, `(disposable/async-dealloc disp)`
  - monadically composing disposables with concurrent allocation and 
deallocation, `(disposable-apply f disp ...)` and `(disposable-chain disp f)`
- temporary files and directories as disposables
- utilities for testing disposables, including observing when allocation and 
deallocation occur

If you're familiar with AutoClosable in Java or IDisposable in C#, think of 
disposables as thunks that produce AutoClosable or IDisposable values.

The API is still in the early stages, and there's a few concurrency bugs to 
work out but the features above should work as advertised. Feedback strongly 
welcomed.

Docs: http://docs.racket-lang.org/disposable/
Source code: https://github.com/jackfirth/racket-disposable

-- 
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] Re: low-friction app extensibility in racket

2017-07-06 Thread Jack Firth
On Thursday, July 6, 2017 at 2:53:43 AM UTC-7, Neil Van Dyke wrote:
> * Pretty similar alternative: user has a Racket file "my-foo", which is 
> the immediate program the user runs.  This file does a `(require foo)`, 
> as well as a `(start-foo #:pref1 x #:pref2 y ...)`.

You may be interested in a recent change to Greg Hendershott's Frog static site 
generator, which does basically this: 
https://github.com/greghendershott/frog/pull/194

-- 
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] Re: Removing undocumented exports of rackunit/text-ui

2017-06-25 Thread Jack Firth
On Monday, June 12, 2017 at 11:55:31 AM UTC-7, Jack Firth wrote:
> The rackunit/text-ui module[1] provides `run-tests` along with a handful of 
> other random undocumented functions with unclear purposes such as 
> `display-ticker`. I have a PR to rackunit open[2] that removes the 
> undocumented exports (it does *not* remove `run-tests`). So far I've found no 
> callers of these functions with Github search, but if you happen to use them 
> please speak up so I don't merge a PR that breaks your code. If you have 
> historical insight into this module and these exports, please comment on the 
> PR so I know more about what I'm removing.
> 
> [1] 
> http://docs.racket-lang.org/rackunit/api.html?q=rackunit%2Ftext-ui#%28mod-path._rackunit%2Ftext-ui%29
> [2] https://github.com/racket/rackunit/pull/34

Just a heads up that after no responses for two weeks, this is now being 
merged. To any users of rackunit nightly, look out for weird missing export 
failures.

-- 
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] Re: GLPK: how many chickens to invite to your picnic?

2017-06-23 Thread Jack Firth
On Friday, June 23, 2017 at 10:13:36 AM UTC-7, 'John Clements' via 
users-redirect wrote:
> Doing some operations research in Racket? Frustrated by the lack of linear 
> programming libraries? Well, be frustrated no more!
> 
> Actually, this is just a package announcement: I built a nice clean 
> one-function interface to GLPK, the Gnu Linear Programming Kit, allowing 
> primal simplex to do optimization on linear functions subject to linear 
> constraints on variables with arbitrary bounds. Hope it’s useful!
> 
> John Clements

Hooray! Thanks for the package! The docs are great for teaching linear 
programming too; I haven't done that since a college class years ago and 
appreciate the refresher.

Pot-stirring question: do you think it would make more sense to name the 
collection `math/glpk` instead of just `glpk`? I don't have a preference, just 
idly wondering.

-- 
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] Re: Naive question on how to capitalize only the first word of a string

2017-06-19 Thread Jack Firth
Given how many solutions everyone's giving, this would be a good rosetta code 
task :)

-- 
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] Re: Naive question on how to capitalize only the first word of a string

2017-06-19 Thread Jack Firth
On Monday, June 19, 2017 at 5:12:10 PM UTC-7, Glenn Hoetker wrote:
> I'm quite new to Racket/LISP, so I hope this isn't breathtakingly obvious.  
> Can someone please tell me the best way to capitalize just the first word in 
> a multiword string.  So, given the string "it was a dark and stormy night", I 
> would like to get "It was a dark and stormy night". I see functions for 
> turning everything lower case, everything uppercase or capitalizing each 
> word, but nothing in line with what I hope to do.
> 
> > (define it "cat dog")
> > (string-titlecase it)
> "Dog Cat"  ; So close, but not quite "Dog cat" as I want.
> 
> Many thanks.

You'll want to split the string into a list of words and apply the 
capitalization function to only the first word.

(define (capitalize-first sentence-str)
  (string-join (list-update (string-split sentence-str) 0 string-titlecase)))

Disclaimer: this will do some weird things to the whitespace in sentence-str 
(e.g. convert newlines to spaces); you might want to tweak that.

-- 
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] RacketCon Code of Conduct

2017-06-19 Thread Jack Firth
> These are invariably motte and bailey style arguments and the notion that the 
> only reason I or anyone else could possibly resent CoCs is some desire to 
> abuse their absence is astonishing. How you could not find such groupthink 
> "censorious" is beyond my ability to sympathize with. I can only reiterate 
> that CoCs are not some kind of dealbreaker for me personally but as this is 
> an open discussion I will just say I don't think they're all benefit and no 
> cost. My disagreement on this matter does not constitute an admission of 
> guilt; to abuse a racket construct: there's a bug in your contract spec, it's 
> blaming the wrong party.

The important point is that a CoC is a choice to prioritize the safety, 
welfare, and happiness of minority groups over the privilege of individuals to 
say / do whatever they want. Sure, you might say that's a tradeoff, and sure, 
you could call that censorship, but whatever "cost" there is of hypothetically 
blaming a party inappropriately is worth paying ten times over for the benefit 
of making traditionally less-welcomed people more included. I guarantee you the 
incidents a CoC is designed to prevent occur *far* more often than any 
incidents of mis-applying the CoC to an innocent individual. Not realizing that 
is willful ignorance.

-- 
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] Re: RacketCon Code of Conduct

2017-06-16 Thread Jack Firth
Agreed. Possibly with someone(s) to be the official point of contact for issues 
related to it.

-- 
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] Wanted: Easier way to contribute docs

2017-06-13 Thread Jack Firth
> It might also be a good idea to have the documentation generator put a 
> standard sentence at the top of each page: "Click on a section header to find 
> out how to link to it or edit it."

A lot of sites show a hyperlink icon (two chain links typically) when you mouse 
over a section title. We could do that along with an edit icon instead of 
requiring users click the section header. That would be more discoverable and 
more in line with what other sites like Github do IMO.

-- 
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] Removing undocumented exports of rackunit/text-ui

2017-06-12 Thread Jack Firth
The rackunit/text-ui module[1] provides `run-tests` along with a handful of 
other random undocumented functions with unclear purposes such as 
`display-ticker`. I have a PR to rackunit open[2] that removes the undocumented 
exports (it does *not* remove `run-tests`). So far I've found no callers of 
these functions with Github search, but if you happen to use them please speak 
up so I don't merge a PR that breaks your code. If you have historical insight 
into this module and these exports, please comment on the PR so I know more 
about what I'm removing.

[1] 
http://docs.racket-lang.org/rackunit/api.html?q=rackunit%2Ftext-ui#%28mod-path._rackunit%2Ftext-ui%29
[2] https://github.com/racket/rackunit/pull/34

-- 
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] Re: ANN: syntax-parse-example 0.0

2017-05-18 Thread Jack Firth
On Wednesday, May 17, 2017 at 10:58:59 PM UTC-7, Ben Greenman wrote:
> The syntax-parse-example package is a showcase of useful macros written using 
> syntax-parse.
> https://pkgs.racket-lang.org/package/syntax-parse-example
> 
> 
> 
> At the moment, the showcase is nearly empty ... but it's easy to contribute!
> 
> 
> 0. Design a beautiful macro, give it a name e.g. BOB
> 1. Run `raco pkg install --clone syntax-parse-example; cd 
> syntax-parse-example`
> 2. Run `raco syntax-parse-example --new BOB`. This generates a directory and 
> 3 files:
>   - `BOB/BOB.rkt` : the macro goes here
>   - `BOB/BOB-test.rkt` : for unit tests
>   - `BOB/BOB.scrbl` : for documentation
> 3. Fill in the blanks in the new files, add `BOB` to the top-level file 
> `index.scrbl`.
> 
> 
> 
> 
> Then, if you run `raco setup syntax-parse-example` it will render your 
> documentation on the page for the `syntax-parse-example` module.
> 
> 
> - - -
> 
> 
> Example doc:
> http://docs.racket-lang.org/syntax-parse-example/index.html?q=syntax-parse-example#%28part._first-class-or%29
> 
> 
> 
> The doc's source:
> https://github.com/bennn/syntax-parse-example/blob/master/first-class-or/first-class-or.scrbl

This is really neat, documentation like this can go a long way towards making 
Racket macros more accessible to everyone. Thank you Ben!

-- 
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] Best way to write run-once-and-cache functions?

2017-04-26 Thread Jack Firth
On Wednesday, April 26, 2017 at 9:48:56 AM UTC-7, David K. Storrs wrote:
> On Wed, Apr 26, 2017 at 12:21 AM, Jon Zeppieri  wrote:
> I don't know that there's a right way, but if your functions are
> 
> nullary, then promises are a decent fit:
> 
> 
> 
> (define conf
> 
>   (delay
> 
>     (with-input-from-file ...)))
> 
> 
> 
> Then just (force conf) whenever you want the value.
> 
> 
> 
> Yeah, that works well.  Thanks!
> 
> 
> Any thoughts on how to do it for non-nullary functions? 

For non-nullary functions, you're looking for memoization / caching. There's a 
couple packages that do this, along with relate

- In the `sugar` package, the `sugar/cache` module gives you exactly this, in 
the form of a `define/caching` macro.
- The `tmemoize` package provides similar functionality for Typed Racket 
functions.
- The `with-cache` package gives you promise-like behavior for thunks that use 
an external storage system.
- The `remember` package gives you caching behavior for compile-time 
expressions that can be remembered across compilation runs.

-- 
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] Re: Best way to write run-once-and-cache functions?

2017-04-26 Thread Jack Firth
A `define/delay` macro for this might be a good addition to `racket/promise`:

(define-simple-macro (define/delay id:id expr:expr)
  (begin (define p (delay expr)) (define (id) (force p

(define/delay conf
  (with-input-from-file "db.conf" read-json))

(conf) ;; forces promise

-- 
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: Setting parameters between files does not work as expected

2017-04-24 Thread Jack Firth
Whoops! That's what I get for assuming Racket makes the same mistake that
Python does :)

On Mon, Apr 24, 2017 at 1:58 PM, Sam Tobin-Hochstadt <sa...@cs.indiana.edu>
wrote:

> On Mon, Apr 24, 2017 at 4:43 PM, Jack Firth <jackhfi...@gmail.com> wrote:
> > Default values for function arguments are computed once when the
> function is defined, not each time the function is called. You'll want to
> make the defaults all false and get the parameter values inside the
> function body.
>
> This is not accurate about default arguments -- they are evaluated
> every time. See this example: http://pasterack.org/pastes/65766
>
> Sam
>

-- 
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] Re: Setting parameters between files does not work as expected

2017-04-24 Thread Jack Firth
Default values for function arguments are computed once when the function is 
defined, not each time the function is called. You'll want to make the defaults 
all false and get the parameter values inside the function body.

-- 
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] Re: Racket Package Catalog Site and Raco Commands

2017-04-24 Thread Jack Firth
A `raco` tag for all packages that add raco commands is a great idea. I don't 
think we should build some sort of system tag that's automatically added 
though; I'd much rather have some way of granting "tagging rights" to a set of 
catalog users and let them figure out what tags are appropriate for the variety 
of packages we have today. Not all sensible tags will have automatic means of 
detection. Here's a sample list of tags I'd like to have used consistently 
across the catalog:

- raco: provides a raco command
- testing: provides something useful for testing code
- data: provides a data structure of some sort
- graphics: provides something related to drawing, images, or GUIs
- lang: provides a #lang language
- reader: provides something that modifies the racket reader, such as adding 
reader syntax for shorter anonymous functions
- sugar: provides a simple shortcut that's generally useful and not specific to 
a particular library
- documenting: provides something useful for documenting code
- syntax: provides something useful for macros and other syntax object 
manipulations
- concurrency: provides something useful for concurrent programming
- network: provides something useful for making network calls and implementing 
various protocols
- storage: provides something useful for persistent storage of values, such as 
database clients

Dear package catalog maintainers: I volunteer to scour the catalog and tag 
everything under the sun.

-- 
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] Re: minimal vs full racket performance issues

2017-03-16 Thread Jack Firth
On Thursday, March 16, 2017 at 3:25:34 PM UTC-7, Dan Liebgold wrote:
> Is there a way to do minimal installs of packages?  I imagine skipping any 
> gui elements would cut down the dependencies quite a bit.

You can install a package in binary form with `raco pkg install --binary foo`, 
which fetches pre-built bytecode and pre-rendered documentation from the 
package catalog build server. This requires you use the same Racket version the 
build server uses, which is usually the latest released version. This also 
completely skips installing dependencies only needed for build time (build-deps 
in a package's info.rkt). You can further omit installing pre-rendered 
documentation by using --binary-lib instead of --binary.

Side question for Racket package system folks: will the migration to Chez 
scheme affect binary installs of packages? I seem to recall discussion that 
bytecode might be going away as part of the Chez transition.

-- 
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 types first class values in typed/racket

2017-02-15 Thread Jack Firth
That's not possible in Typed Racket, no. Type checking is after macro expansion 
so type information doesn't even exist when your macro would expand.

However, hope is not lost. There is a new approach to typechecking with macros 
outlined in the Types as Macros paper by Stephen Chang and Alex Knauth, and 
reified in the `turnstile` Racket package. This approach interleaves 
typechecking and macro expansion, making types essentially macros with extra 
compile time metadata that alter the flow of macro expansion. In this case, 
types are actual *things* that exist at macro expansion time, so you could make 
a macro that interacted with types and used type information to decide how to 
expand.

On Tuesday, February 14, 2017 at 5:32:30 AM UTC-8, Robert Kuzelj wrote:
> given a type definition in typed/racket like
> 
> (define-type BinaryTree (U Number (Pair BinaryTree BinaryTree)))
> 
> would it be possible to feed that type into a macro (aka not runtime) so that
> 
> (define-transformed-type MyBinaryTree BinaryTree)
> 
> and would that macro be able to access the constituent elements and their 
> types of given type?

-- 
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] Re: Programming paradigms supported by Racket (according to wikipedia)

2017-02-12 Thread Jack Firth
Somewhat reductionally, anyone can write a Racket library that implements a 
`#lang` with the semantics of any language on that list, so Racket therefore 
supports all paradigms. This doesn't really say anything useful.

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