pocmatos
2019-5-29 09:42:26

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


jerome.martin.dev
2019-5-29 10:47:55

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?


greg
2019-5-29 11:44:49

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


greg
2019-5-29 11:45:50

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.


greg
2019-5-29 11:46:43

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


jerome.martin.dev
2019-5-29 11:56:29

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


greg
2019-5-29 12:04:35

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


greg
2019-5-29 12:06:42

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.


jerome.martin.dev
2019-5-29 12:07:06

Maybe I could use a queue instead


jerome.martin.dev
2019-5-29 12:07:16

and have one dedicated thread to process it


greg
2019-5-29 12:08:30

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


jerome.martin.dev
2019-5-29 12:09:05

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


greg
2019-5-29 12:10:08

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.


jerome.martin.dev
2019-5-29 12:10:30

yep, I think I’m gonna go with that


greg
2019-5-29 12:10:37

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


greg
2019-5-29 12:11:21

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


jerome.martin.dev
2019-5-29 12:11:47

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


greg
2019-5-29 12:12:19

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


jerome.martin.dev
2019-5-29 12:13:04

ahah


greg
2019-5-29 12:13:10

Sorry, sorry. Should avoid geopolitical humor attempts.


jerome.martin.dev
2019-5-29 12:13:27

I didn’t immediately got it x)


jerome.martin.dev
2019-5-29 12:17:27

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


jerome.martin.dev
2019-5-29 12:18:15

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


jerome.martin.dev
2019-5-29 12:18:51

(the other two were British though)


jerome.martin.dev
2019-5-29 12:25:22

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


jerome.martin.dev
2019-5-29 12:31:13

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.


jerome.martin.dev
2019-5-29 12:31:53

Anyways, I should get back to work


todo
2019-5-29 12:47:03

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 ?


greg
2019-5-29 12:54:59

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.


greg
2019-5-29 12:57:57

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.


greg
2019-5-29 12:58:18

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


jerome.martin.dev
2019-5-29 13:00:06

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


d_run
2019-5-29 14:24:45

d_run
2019-5-29 14:29:04

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


d_run
2019-5-29 14:29:22

might help with your multi-threading situation?


alexknauth
2019-5-29 15:23:35

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


jerome.martin.dev
2019-5-29 15:24:19

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


steveh2009
2019-5-29 15:26:37

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.


steveh2009
2019-5-29 15:27:02

…in one place…


ryanc
2019-5-29 15:40:01

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


mflatt
2019-5-29 15:57:38

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


steveh2009
2019-5-29 16:08:21

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.


steveh2009
2019-5-29 16:08:59

…get the full binary release from…


ryanc
2019-5-29 16:32:51

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


joelmccracken
2019-5-29 16:58:08

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


alexknauth
2019-5-29 17:02:05

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


joelmccracken
2019-5-29 17:06:27

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


joelmccracken
2019-5-29 17:06:57

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


sorawee
2019-5-29 17:07:57

joelmccracken
2019-5-29 17:08:05

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


joelmccracken
2019-5-29 17:08:10
(define (extract-id x)
  (match x
      [`(,(? symbol? tag)
         ,(? list? args)
         ,body ...)

       (define result (assoc 'id args))
       (list (second result))
       ]
      )
  )

sorawee
2019-5-29 17:08:14

(See the match example below)


joelmccracken
2019-5-29 17:09:30

oh ty


alexknauth
2019-5-29 17:09:39

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


alexknauth
2019-5-29 17:10:00

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


joelmccracken
2019-5-29 17:11:33

i wonder why there is a specialization of xexprs to txexprs


joelmccracken
2019-5-29 17:11:59

but thats a little neither here nor there


alexknauth
2019-5-29 17:12:16

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


joelmccracken
2019-5-29 17:12:17

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


blerner
2019-5-29 19:25:46

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


notjack
2019-5-29 19:55:01

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


samth
2019-5-29 20:08:45

@notjack there’s a relevant xkcd here


samth
2019-5-29 20:09:01

there’s scribble/html


ben
2019-5-29 20:22:24

@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



ben
2019-5-29 20:28:56

ohhh Kent. Thanks!


robby
2019-5-29 20:35:22

sorry, I must have said something wrong


soegaard2
2019-5-29 20:38:12

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



mflatt
2019-5-29 20:40:49

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


notjack
2019-5-29 20:45:31

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


soegaard2
2019-5-29 20:47:00

foo: turns into ’foo


soegaard2
2019-5-29 20:47:07

So one can write ’foo instead.


greg
2019-5-29 20:53:09

@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")?


blerner
2019-5-29 20:53:47

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…


greg
2019-5-29 20:53:58

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


notjack
2019-5-29 20:54:50

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


notjack
2019-5-29 20:55:14

That way xml node constructors can just be regular functions


blerner
2019-5-29 20:55:48

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


notjack
2019-5-29 20:57:06

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


soegaard2
2019-5-29 20:59:33

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


greg
2019-5-29 21:00:05

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. ¯_(ツ)_/¯


samdphillips
2019-5-29 21:01:04

Legacy of SGML


greg
2019-5-29 21:01:19

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


greg
2019-5-29 21:01:33

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


githree
2019-5-29 21:12:26

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


githree
2019-5-29 21:12:52

justin.hu
2019-5-29 21:15:23

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


blerner
2019-5-29 21:33:24

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?


blerner
2019-5-29 21:33:38

there’s no documentation/examples of it, unfortunately


mflatt
2019-5-29 21:35:51

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


blerner
2019-5-29 21:38:05

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


blerner
2019-5-29 21:52:37

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


mflatt
2019-5-29 22:11:13

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


blerner
2019-5-29 22:13:18

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


alexknauth
2019-5-29 22:21:31

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?


steveh2009
2019-5-29 22:25:10

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


carl.morris.world
2019-5-29 22:47:35

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?


jjwiseman
2019-5-29 23:40:03

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



alexknauth
2019-5-30 01:05:58

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


alexknauth
2019-5-30 01:16:28

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


sorawee
2019-5-30 01:42:53

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


greg
2019-5-30 01:50:36

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?


rokitna
2019-5-30 04:05:45

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


alexknauth
2019-5-30 04:30:17

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.


alexknauth
2019-5-30 04:41:34

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


rokitna
2019-5-30 04:42:22

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)


rokitna
2019-5-30 04:42:23

?


alexknauth
2019-5-30 04:46:21

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.


rokitna
2019-5-30 04:47:16

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


alexknauth
2019-5-30 04:47:23

yes


rokitna
2019-5-30 04:49:53

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


rokitna
2019-5-30 04:51:07

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


alexknauth
2019-5-30 04:52:45

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


alexknauth
2019-5-30 04:53:40

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


rokitna
2019-5-30 04:55:47

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


rokitna
2019-5-30 04:55:54

(or would it be an error?)


alexknauth
2019-5-30 04:57:14

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


alexknauth
2019-5-30 05:04:30

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


rokitna
2019-5-30 05:07:02

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


alexknauth
2019-5-30 05:13:36

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


rokitna
2019-5-30 05:43:12

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


rokitna
2019-5-30 05:51:43

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.


jjwiseman
2019-5-30 06:01:05

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


rokitna
2019-5-30 06:16:38

oh, I didn’t know that about Clojure