Ah, so instead of:
(cond
[(box-cas! ...) ...]
[else ...])
I would need to change it to:
(let loop ()
(cond
[(box-cas! ...) ...]
[(old-value? (unbox ...)) (loop)]
[else ...]))
I have some variant of <https://github.com/Bogdanp/koyo/blob/a140c9dadfeef80a69355aaff025d5c5cfc06a00/koyo-lib/koyo/util.rkt#L10-L14|this function> in multiple projects (sometimes it returns the result of the application, and sometimes it doesn’t). It would be nice to have something like it in base.
:wave: GUI Q I have a small GUI that makes a web request and I need to display the returned JSON text in a %text
field. Has anyone done any work on formatting/beautifying JSON in Racket? Any tips on direction if not?
Just curious: Any particular reason why you’re calling unbox at each iteration?
If two threads race to change the value, one will succeed and the other will fail. If the one that succeeded changed the value in the box, the new one has to read the new value before it can change it (because box-cas!
only changes the value in the box if its current value is eq?
to the old
argument).
Here’s an example:
#lang racket/base
(define (box-swap! b f)
(let loop ([v (unbox b)])
(unless (box-cas! b v (f v))
(loop (unbox b)))))
(define b (box 0))
(define sema (make-semaphore))
(define thds
(for/list ([_ (in-range 100)])
(thread
(lambda ()
(sync sema)
(for ([_ (in-range 10)])
(box-swap! b (λ (x)
(sleep 0)
(add1 x))))))))
(for ([_ (in-range (length thds))])
(semaphore-post sema))
(for-each thread-wait thds)
(unbox b)
If you change (loop (unbox b))
to (loop v)
, the code will most likely go into an infinite loop.
Makes perfect sense, thanks!
I don’t know of a Racket JSON pretty formatter, so:
If the GUI’s audience were Racketeers? I might turn the JSON into a jsexpr
, pretty-print
that s-expression, and declare mission accomplished. :)
If the audience were “normal people”? I might system
out to some command-line JSON pretty formatter. (That’s probably fast enough, especially on *nix. If it weren’t, I might process
to keep one instance running and pipe to/from it.)
• I don’t think it would make sense to have a dedicated keyword for each strategy. • If there are only two possibilities, a flag makes sense. • With the exception that if we want to extend the ordering options later, it should be a keyword argument taking symbols. • 'lazy
sounds much too vague for me. If it’s a particular strategy, it could be 'szudzik
etc., unless we may want to change this strategy later, i. e. 'lazy
would be intentionally vague. But then, 'lazy
doesn’t say anything without a proper explanation, at which point we probably want the more specific term(s) anyway. • I miss “my” ordering that led to this thread :satisfied: (@sorawee’s second implementation). It was (or would have been) actually needed for the use case.
I found someone that’s done work: https://gist.github.com/carl-eastlund/5398440 . Haven’t tried it
oh nice, in the meantime I system
‘d out to jq
to do it quick and dirty. Will look at Carls’ code.
Is there in Racket a simple way to “unpack” a pair to two identifiers? For example (unpack-pair (first second) pair)
would be equivalent to (define-values (first second)
(values (car pair) (cdr pair)))
I’m sure that could be achieved with a custom macro, but I wonder if there’s something in the standard-library.
Now i’m wondering if I can package up jq
into the app bundle…
I think you want racket/match
. But I tend to just use a similar approach with values
for small destructures.
to add: (require racket/match)
(match-define (cons fst snd) '(5 . 3))
As @shu—hung said, match-define
is what you asked for. In fact it probably expands to something very like your definition of unpack-pair
. There’s also a let
flavor, match-let
.
All of these will of course throw an exception if pair
isn’t a pair. When you want to handle that possibility, see match
, which is more cond
-like. You try matching against successive patterns. The final pattern can be an identifier (conventionally _
) which binds to/matches anything, which is your “else”.
(You could make that final pattern the identifier else
, but it’s not a special keyword, it could be any identifier, and will be bound to the value you gave to match
.)
Right, I always forget about racket/match
, sorry. I usually avoid it because it doubles the startup time for simple programs (using racket/base
), so it seems my brain refuses all recollection of racket/match
. ;-/
But thanks, of course.
Otherwise I really like pattern matching.
If the program is pre-compiled using raco make
(for a single file) or raco setup
(for a package), the startup time should reduce
Well, I’m not sure how mucn though
Yes, it’s reduced, but not very much.
Turns out racket/match
had accidentially added a dependency on racket/contract/base
which made the startup time larger; that should be fixed soon.
Follow on from my earlier question, is it possible to embed something like jq
(https://stedolan.github.io/jq/) into a distributable app bundle?
Yes, you should be able to use define-runtime-path
and raco distribute
to do that.
yeah
How large is the difference?
I thought racket/match
took so much time because it pulled in lots of stuff from modules to match against.
It’s most of the difference.
Awesome! :slightly_smiling_face:
On my machine, loading (roughly) racket/base
takes 0.11 real, loading racket/contract/base
takes 0.25 real and loading the old racket/match
takes 0.30 real