
@leif thanks for looking at the openhub stuff. I am waiting for it to update. Hasn’t happened yet.

Hello Racketeers! I’m trying to implement a CSRF check on my web-server. How would one go about coding that using the Racket web-server lib? (I know continuations are really similar, but I’m not using continuations, I disabled them on my server) I was thinking about using a global shared list of valid csrf tokens, but as the web-server responses are multi-threaded, I fear I would get some locks and conflicts. Did anyone tried this before? How do you do this on your own servers?

@jerome.martin.dev My usual step 0 for things like this would be a mutable hash-table from make-hash
. Safe for multi threads to insert and remove. In some cases I might use the file system as a local key/value store. Either way, usually also need some little worker thread to remove expired items from the cache.

Step 1 could be idk use memcached or redis or postgres instead. But the actual real-world utilization might mean really, there’s no need fuss with anything like that. Depends.

Things like confirm-your-email-address tokens, I put in postgres.

@greg Thanks for the tips! Yeah I considered using a database or the filesystem, but it feels overengineered for such a simple and ephemeral thing like a token. I guess there’s not a lot of choices anyway.

I guess the TL;DR is, from https://docs.racket-lang.org/reference/hashtables.html > Caveats concerning concurrent modification: A mutable hash table can be manipulated with hash-ref, hash-set!, and hash-remove! concurrently by multiple threads, and the operations are protected by a table-specific semaphore as needed. Three caveats apply, however: > > - If a thread is terminated while applying hash-ref, hash-set!, hash-remove!, hash-ref!, or hash-update! to a hash table that uses equal? or eqv? key comparisons, all current and future operations on the hash table may block indefinitely. > > - The hash-map, hash-for-each, and hash-clear! procedures do not use the table’s semaphore to guard the traversal as a whole. Changes by one thread to a hash table can affect the keys and values seen by another thread part-way through its traversal of the same hash table. > > - The hash-update! and hash-ref! functions use a table’s semaphore independently for the hash-ref and hash-set! parts of their functionality, which means that the update as a whole is not “atomic.”

So the good news is, you can mutate it safely from different threads. Of the bad news, I think mainly you just need to be aware of the second point, for any thread that culls expired items. On any given cull, it might not see all the items, or see some more than once.

Maybe I could use a queue instead

and have one dedicated thread to process it

My first reaction is that a queque (if you mean FIFO or LIFO) won’t necessarily match the HTTP requests for CSRF.

yeah, never mind, I was thinking about something else that required a queue in the same time, and got mixed up in my thoughts

One thing I’ve done is, store the expiration time in the hash-table, and, some thread runs every (say) 10 or 60 seconds to cull expired items. If it misses some on one run, it will catch them later. Often that’s good-enough.

yep, I think I’m gonna go with that

(When the expiration time isn’t strict, it’s more just about “cleaning up eventually”.)

Maybe someone will chime in with a better idea. I just happen to be awake semi-early US ET today. ¯_(ツ)_/¯

yeah, I was like “wait, was greg european again?”

I’m not in the UK if that’s what you mean :smile:

ahah

Sorry, sorry. Should avoid geopolitical humor attempts.

I didn’t immediately got it x)

Well some times ago at Fosdem, I stumbled upon three people speaking British English, talking about UK and awaiting the official results, and I told them “I hope for the best, maybe you will be able to stay with us a bit longer”. And one of them said “Oh you know, I don’t care, for I’m actually Swedish”.

He had a really convincing british accent, and a perfectly cut mustache. I was fooled x)

(the other two were British though)

They were joking about the possibility that they may not be able to fly back home, with their european identity cards expiring following the decision

I think they had a plan B using their driver license or something, which is supposedly a valid ID card in UK. Not sure about that, though.

Anyways, I should get back to work

is syntax parse “just”
unification + rewrite a way to handle "…" repetition patterns a way to handle “syntax classes” via “var_name : type”
?
Are there any other main ideas to syntax-parse ?

I don’t know if “remove various syntax-case foot-guns” qualifies as a main idea but I think that’s a main benefit, for me.

Also I think a lot of the motivation is help you write macros with better error messages. So syntax classes are a DRY convenience, yes, but as importantly they help syntax-parse automatically tell the user what was expected in an error message.

It’s kind of two sides of the same coin.

I don’t know if syntax-case
has the ~@
and ~?
helpers? I find them really useful in syntax-parse

would it be possible to put the hash in a box and use box-cas! https://docs.racket-lang.org/reference/boxes.html#%28def._%28%28quote._~23~25kernel%29._box-cas%21%29%29

Technomancy wrote a nice swap!
function that uses box-cas! to create a Clojure style atom in https://technomancy.us/175

might help with your multi-threading situation?

The ~@
and ~?
forms are tied to the syntax
form, or #'
, not to the pattern-matching form, so you should be able to use them with either syntax-parse
or syntax-case

Ok! I had doubts because their documentation is in the syntax-parse section

Is there a standard practice to put all the shared libraries used in packages which call ffi’s on one place in the installed Racket directory tree? I’m using Windows 10. Thanks.

…in one place…

@steveh2009 yes, see the copy-foreign-libs
setup option in the docs. For an example, see the source for https://pkgs.racket-lang.org/package/ffmpeg-i386-win32; go to “Code” and then “info.rkt”. When the package is installed, raco
copies the listed files to the Racket lib dir, which is searched by ffi-lib
if you use a relative path.

For those who are not on the racket-users mailing lists: Does anyone use single-flonums? (See https://groups.google.com/d/msg/racket-users/Di-fTifWyWg/J_GQ2_3hBwAJ for more.)

Great. Problem I’m having is that I did “raco install zeromq” and need to figure out where the libzmq.dll should go (which isn’t part of the package install, had to get the full from the http://zeromq.org\|zeromq.org site). Setting up PATH to point to where the dll got installed works but was wanting to move it into the Racket tree.

…get the full binary release from…

@steveh2009 In that case, you can manually copy the libraries to one of the paths reported by (begin (require setup/dirs) (get-lib-search-dirs))
. BTW, I recommend the zeromq-r package instead (I wrote it).

I have a fairly hard time understanding the docs for match
; is there a good place to see many examples of it?

Did you look at the Guide section on match
, as opposed to the Reference section? https://docs.racket-lang.org/guide/match.html

yes; so the basics are pretty clear. I am trying to use match to process an xexpr, so it can be nested etc fairly complicatedly

the quasiquote syntax seems much nicer, but its even more unlear to me whats possible

Specifically for xexpr, you might want to use https://docs.racket-lang.org/txexpr/#%28def._%28%28lib._txexpr%2Fmain..rkt%29._txexpr%29%29 instead

For example, I wrote this to extract the id attribute of an xexpr:

(define (extract-id x)
(match x
[`(,(? symbol? tag)
,(? list? args)
,body ...)
(define result (assoc 'id args))
(list (second result))
]
)
)

(See the match
example below)

oh ty

The txexpr
package has both a txexpr
pattern and a attr-ref
function

So (define (extract-id x) (attr-ref x 'id))
I guess

i wonder why there is a specialization of xexprs to txexprs

but thats a little neither here nor there

Because “xexpr” contains atom elements such as plain strings, and you can’t get the tag or attributes of those

ty, y’all gave me some stuff to think about/look at

Low-level scribblers: is there a way for me to define (register-file-for-copy "src/path/to/file.foobar" "dest/subdir")
, such that file.foobar
gets automatically copied into builddir/dest/subdir
as part of running scribble? I think I want (send my-render install-file ...)
, but I can’t figure out the argument values

I really wish there was an alternative to xexpr / txexpr that just used keyword arguments for the attributes

@notjack there’s a relevant xkcd here

there’s scribble/html

@robby can you help me find this paper by Ken about cycles & equal?
? I assume this is Ken Shan, but I haven’t found anything yet


ohhh Kent. Thanks!

sorry, I must have said something wrong

@notjack Have you tried scribble/html (or urlang/html for a few extras)?


I think you want the the link-resource
or install-resource
property. (I had trouble remembering/finding that myself.)

@samth @soegaard2 The treatment of attribute names as colon-suffixed strings is hard to read

foo: turns into ’foo

So one can write ’foo instead.

@notjack re using “keyword args”, is the motivation to avoid attributes as a list of lists with a bunch of extras parens? instead of (p ([class "class"][id "id]) "some" nbsp "content")
you could have (p #:class "class" #:id "id" "some" nbsp "content")
?

Thanks. But those resources just turn around and call (for ([r (in-list resources)]) (install-file r))
(in html-render.rkt), so those don’t let me specify the destination directory…

were you even thinking of full-on kw arg pos flexibility like (p #:class "class" "some" nbsp "content" #:id "id)
:smile: ?

Yes, the extra parens are confusing and I’d like that last form

That way xml node constructors can just be regular functions

In my scenario, I already have a customized render% mixin, so I can add helper methods as needed. I think I can co-opt install-file to do what I want by suitably messing with helper-file-prefix
and/or dest-dir
, but I’m reading base-render.rkt#install-file right now, and I can’t figure out how it manages to stash files inside a directory, when both dest-dir
and helper-file-prefix
are both #f
so far

Which would let me do stuff like use fancy-app
with them: (map (p #:class "class" _ nbsp) (list "foo" "bar" "baz"))

I believe the scribble/html
version looks like: (map (p class: "class" _ nbsp) (list "foo" "bar" "baz"))

That reminds me, whenever I think about it too much, I get mildly irritated that XML has both child elements, and also this side dict bag o’ attributes. And in some XML I can’t tell why people choose to use which. ¯_(ツ)_/¯

Legacy of SGML

I guess it’s just surface syntax for, “It’s a simple ‘flat’ dictionary, and one mapping is an implicit "kids” to list of more elements."

And then I get bored thinking about it and do something else instead.

LAML was attempting something similar (with symbols instead of keywords): http://people.cs.aau.dk/~normark/laml-distributions/laml/index.html


This doesn’t seem to work correctly when I provide draw-arrow, and use it in a teaching language.

ahhhh, found it — it’s a parameter
that sets the current-subdirectory
parameter during the render pass. So…now I’m stuck again. It seems that for me to produce a hyperlink to this installed file, I need to call install-file
during the render pass, which is the only time that the parameter is set. So I think I need to use a render-element
for this, but according to the base-render
file, it’ll call the render-element-render method only for its side effects, not its content — and I won’t know the correct content until the render phase! So how do I use a render-element properly?

there’s no documentation/examples of it, unfortunately

Maybe delayed-element
, whose callback is also run at render time, but the callback returns replacement content?

per the docs, delayed-element
is run at resolve time

darn! I tried sticking a delayed-element
in as the content of a render-element
, but that was foiled :disappointed: the delayed-element function gets run before the render-element one does

Well, clearly I’m getting lost too easily to be much help, either :slightly_smiling_face:

so far, I’m stuck trying to copy/paste/modify the bits of render-multi-mixin that affect these parameters

If I have the program above saved in "controlling-drracket-arrows-2.rkt"
, then the program below has an arrow pointing to the <<OVER HERE!>>
place in the comments #lang htdp/isl+
(require "controlling-drracket-arrows-2.rkt")
(draw-arrow)
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
; 1234567890 1234567890 1234567890 1234567890 1234567 <<OVER HERE!>>
; 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890
Do you mean something else about what’s not working?

@ryanc Does your zeromq lib work with 3.2 or 4.0?

I agree it seems like I’m reinventing the wheel. I notice now that parse
from a #lang brag
returns a syntax object already, but I can’t figure out how to use the syntax object to do something: #lang br
(define-syntax record
(syntax-rules ()
[(record content) (list 'interpreted content)]))
@module/lang[parser]{
#lang brag
record: DATA ["," DATA]*
}
(require 'parser brag/support)
(parse (list (token 'DATA "a")))
Since I’ve defined the syntax record
I would’ve expected the syntax resulting from parse
to be interpreted somehow. What am I missing?

i often wish for a more concise hash literal syntax, that could be used in this scenario along with many others. along the lines of clojure’s {:class "container" :id "map"}
. it’s funny how in comparison to #hash((#:class . "container") (#:id . "map"))
, it’s a relatively minor difference but feels very different (to me, at least).


In general, I like Clojure’s approach to “literals” for data structures a lot more than Racket’s. Closure has [expression ...]
for vectors and {expression expression ... ...}
for dictionaries. While Racket has #(datum ...)
for vectors and #hash((datum . datum) ...)
for dictionaries, where the datums are not expressions for some reason, they’re auto-quoted and I hate the fact that they’re auto-quoted.
Clojure allows them to be expressions and that makes it much nicer. Also no superfluous .
in the middle

Does anyone know why “auto-quoting” ever became a thing?

Isn’t it from Scheme? E.g., #(1 2 3)
creates a vector in Scheme.

There are situations where I write (hash k v ... ...)
and I know it’s not as efficient as #hash((k . v) ...)
but I rationalize that it doesn’t matter in many cases. And/or if it turns out to matter, I can come back and change it later. Does that make me a bad person?

If something like {'a 1 'b 2}
would be treated as a hash table at read time, that opens up some cans of worms… nothing that can’t be ironed out, but a bunch of choices to make:
- What order do the expressions evaluate in? Should they go from left to right, like Racket guarantees in most places, or should they go in whatever the hash iteration order is?
- What happens if the keys aren’t unique at read time? Does
{'a 1 'a 2}
cause a reader error or silently succeed somehow? How about{(gensym) 1 (gensym) 2}
, where the keys are the same at read time but would become different at run time? How about quasiquotations like(quasiquote {',(gensym) 1 ',(gensym) 2})
? - Do there need to be different syntaxes for different kinds of hashes (different comparators, mutability, etc.)?
For people who want this kind of thing, what motivation do you have in mind? I tend to consider (hash 'a 1 'b 2)
nicer to work with than {'a 1 'b 2}
already, largely because its parens and explicit prefix operator are consistent with most of the rest of the language. And if did at some point discover I needed read-time representations of other data types, is there something special about hashes? Or would hashes fit in better among a whole extensible system of compound read-time data constructors like (##hash ...)
, (##hasheq ...)
, (##make-hash ...)
, (##vector ...)
, (##vector-immutable ...)
?

There should be a distinction between “value” and “syntax that would evaluate to that value”. For example a list value (list 1 2 3)
is different from the syntax that would evaluate to it which would be (list 'list 1 2 3)
with some extra wrappers for syntax objects. In the same way it makes sense for the value {'a 1 'b 2}
to be different from the syntax that would evaluate to it. The syntax returned by the reader or manipulated by the compiler should be something other than a hash table, so that it preserves order for evaluation.

Clojure gets around this by having its “straight-out-of-the-reader” representation of dictionaries remember the order, so it’s not a pure hash-table

if '{'a 1 'b 2}
would return something other than a hash table, how about having it return the same thing as '(hash 'a 1 'b 2)

?

I don’t think '{'a 1 'b 2}
should be the same as (list 'hash ''a 1 ''b 2)
, I think it should be some kind of representation for dictionary expressions that preserved order. It could still implement the “dictionary” interface, but it wouldn’t be a run-of-the-mill hash-table, it would be a representation known to the compiler with an extra operation for determining the order.

this would be an ordered hash that evaluates to an unordered hash?

yes

for the sake of being explicit, what would you expect to happen with {(gensym) 1 (gensym) 2}
?

I mean I asked “this would be an ordered hash” just now, but another option you might intend would be for it to be more of an assoc list, since you were talking about dictionaries

It would get read as a “hash-expression” that implemented the dictionary interface and the “ordered dictionary” interface (isomorphic to an assoc list). It could get evaluated to a normal hash-table which doesn’t care about order

But to someone who only has access to the dictionary interface and doesn’t have the “ordered dictionary” interface, they wouldn’t be able to tell the difference

what would be the return value of {'a 1 'a 2}
, with a duplicate key at run time?

(or would it be an error?)

The expression '{(gensym) 1 (gensym) 2}
should definitely not be an error

An “ordered dictionary”, though maybe that’s a bad name, would allow duplicate “ordered-entries” so that '{(gensym) 1 (gensym) 2}
could work, but the dictionary methods would behave the same as if the other duplicate instances didn’t exist, for example dict-keys
would only include one (list 'gensym)
key

you saw that I was asking about the expression {'a 1 'a 2}
this time, right?

The expression '{'a 1 'a 2}
should also be a valid “ordered dictionary” for the same reason. The runtime could redefine quote
as a function that called gensym
, and then it would evaluate to a proper non-duplicate-entry dictionary then

@alexknauth What would {'a 1 'a 2}
do without the quote around it, or is that just something you don’t have an expectation about?
(I hope I’m not trying your patience by asking the same thing again. I’m just interested in case I hear the same kinds of answers from multiple people. I think of this as a gnarly system of questions, which is why I’ve been avoiding it altogether by preferring (hash ...)
. If it turns out enough people have compatible expectations around this, maybe I’m making a big deal out of nothing.)

The last time this came up for me was on Arc Forum, where I think a couple of people had expectations based on Clojure. I think at least one of them found it surprising that Arc tables (based on Racket hashes) didn’t traverse in insertion order already. I think having insertion-order traversal in the first place gives an obvious resolution to at least the problem of evaluation order, if nothing else.

“Clojure gets around this by having its “straight-out-of-the-reader” representation of dictionaries remember the order, so it’s not a pure hash-table” — @alexknauth are you referring to clojure’s {...}
syntax sometimes returning an array-map? (though it can also sometimes return a hash-map)

oh, I didn’t know that about Clojure