wwall
2019-11-13 09:14:05

hello. i have question - what is faster for extract data - hash, vector, structure?


soegaard2
2019-11-13 09:15:40

Vectors and structures ought to have faster access times than a hash.


wwall
2019-11-13 09:18:37

thanks



wwall
2019-11-13 09:28:57

Here’s the situation - I have a lot of small data that are created only once, the data itself does not change in the process,but only generates new ones. I’m looking for a way to efficiently present them for fast data reading


notjack
2019-11-13 09:30:01

How much data, and how long is it used for?


wwall
2019-11-13 09:31:28

it is list of tokens + some data, used for analize


wwall
2019-11-13 09:31:47

time for live for data - full time work of app


notjack
2019-11-13 09:33:58

thousands of items, millions, billions, or more?


notjack
2019-11-13 09:34:45

a rough guess is fine


wwall
2019-11-13 09:36:37

thousands


notjack
2019-11-13 09:41:58

Quick rule of thumb for how to pick which data structure to use, based on how many items you’re working with:

Thousands: it probably doesn’t matter what you pick, don’t worry about it Millions: it probably matters, but you need benchmarks and to know what access patterns you care about Billions: don’t even try to keep it in memory in a single huge data structure, it will end in tears More: this is the least of your worries


wwall
2019-11-13 09:46:28

thanks


notjack
2019-11-13 09:58:02

happy to help :simple_smile:


spdegabrielle
2019-11-13 14:18:04

samth
2019-11-13 15:00:08

A few thoughts: 1. Do all the places do the same thing? If not, maybe you can have some of them not load plot. 2. You could load some libraries lazily, using lazy-require. 3. Running on RacketCS, provided Herbie works there, might have less per-place overhead. (If Herbie doesn’t work on RacketCS, please report a bug!) 4. RacketCS also has better-implemented memory backtraces. 5. You could investigate which of the libraries are contributing to the memory the most, and see if your use of them is necessary or could be slimmed-down. For example, maybe you can use plot/no-gui.


deactivateduser60718
2019-11-13 15:37:39

I’m trying to make it so when I add a subcommand to my CLI, I automatically get relevant usage help strings. Last time, I did this:

(module+ main
  (void (command-line
         #:program (short-program+command-name)
         #:once-each
         #:args (action . _)
         (parameterize ([current-command-line-arguments (get-subcommand-args action)])
           ((hash-ref action-table action (λ _ show-subcommands)))))))

I didn’t like it because I must manually update help info here when I add a subcommand, and I have to repeat the whole pattern every time I want a nested subcommand. I’m now thinking of trying a Git-style convention that translates command lines into program names, and generating one racket launcher + help given a tree of modules to match the program names.

But before I go do all that, what does raco do to handle this? Is it easy to replicate?


mflatt
2019-11-13 16:00:33

The implementation for raco is in collects/raco/raco.rkt. I think planet had a implementation closer to being general, but I’m not sure; see collects/planet/private/command.rkt. And then there’s collects/pkg/main.rkt, but that’s different and aimed more at the problem of dealing with rough commonality among different subcommands. Maybe there was another effort to generalize (maybe from planet), but I don’t remember that clearly.


deactivateduser60718
2019-11-13 16:01:23

Thanks much.


ryanc
2019-11-13 16:08:07

There’s a very minimal package called command-tree. I haven’t used it, though. I’ve rolled my own a few times now, and I agree it would be nice to have a general solution that just worked.


deactivateduser60718
2019-11-13 16:09:12

I took a look at that, and it’s not what I’m looking for. I’ll take a crack at this.


yilin.wei10
2019-11-13 16:27:40

@yilin.wei10 has joined the channel


deactivateduser60718
2019-11-13 16:31:23

For convenience of reference: planet uses SVN conventions and introduces another wrapper that has a command-line-like form. The one example that stood out is pretty involved, but that’s neither here nor there. It supports my preconception that conventions have a huge design impact.


yilin.wei10
2019-11-13 17:53:35

Hi all, I’m trying do some of Okasaki’s functional data structures to play around with typed racket, but I’m having trouble since some of the data structures rely on some form of ad hoc polymorphism. What would be the best way to go about this in typed racket?


yilin.wei10
2019-11-13 18:00:48

So far I’m just passing through the relation in the function as a first parameter, but it feels a little clunky.


pavpanchekha
2019-11-13 18:01:03

Each worker runs an instance of Herbie. That pulls in a lot of stuff.


pavpanchekha
2019-11-13 18:01:58

We do use plot/no-gui. I haven’t tried RacketCS but the lack of single-floats is going to hurt. We have a (vague) plan for eliminating the dependency but it’ll take some work.


pavpanchekha
2019-11-13 18:02:25

Lazy-require and not loading plot won’t really work, sadly. Every worker does the same thing and that thing involves plotting.


samdphillips
2019-11-13 18:17:31

This seems weird. First noticed in my local documentation but it also appears that way at https://docs.racket-lang.org/gui/Windowing_Classes.html


samth
2019-11-13 18:26:05

The fact that single floats are useful is interesting, when @mflatt changed them for 7.4 our impression was they were mostly unused.


notjack
2019-11-13 18:31:41

Is each worker doing a mix of heavy compute and plotting? You could split those tasks across different pools of workers and hand off the computed data to the rendering worker pool. Then you could scale them separately and avoid paying the price of loading plot so many times.


pavpanchekha
2019-11-13 18:41:29

Well, Herbie naturally cares about the specifics of floating-point, given that it’s about floating point accuracy :slightly_smiling_face:


pavpanchekha
2019-11-13 18:42:04

@notjack The issue is that the data that we plot involves some non-serializable pieces.


pavpanchekha
2019-11-13 18:42:29

(Not the plotting itself of course, but some of the other stuff that worker does, but separating out just plotting would involve a very large-scale rearchitecture


samdphillips
2019-11-13 18:43:14

Looks like it is the documentation for the event% class https://docs.racket-lang.org/gui/.html


samdphillips
2019-11-13 18:47:25

I’m no Scribble expert, maybe it was changed on Apr 11? @defclass/title was removed. https://github.com/racket/gui/commit/7c30526f3b900ef65ecc2bdea207156e366ed298#diff-68750f1d4439a7f67a2dc77bcd3ad47b


mflatt
2019-11-13 18:48:23

I’ve pushed a repair


notjack
2019-11-13 18:49:02

@pavpanchekha what sort of non-serializable pieces?


yilin.wei10
2019-11-13 18:50:12

(To clarify I’m not talking about how to replicate typeclasses in typed racket, simply how it would be best to code the solutions)


pavpanchekha
2019-11-13 18:50:17

Tracebacks or whatever Racket calls them, and also a data structure we use called an alt in which the structure of the pointer graph matters


pavpanchekha
2019-11-13 18:50:53

The second might be doable using graph-printing, somehow. We used to have a custom serializer for the first, but it was way too much code to have around for no benefit


samth
2019-11-13 18:59:33

Can you say more about the use of single floats? Are you using them because you want to analyze the accuracy of computation that uses them, or because they help in the internals of your code?


samth
2019-11-13 19:00:40

Also, why do you want to plot continuation-mark-set values? And could you just use continuation-mark-set->context?


soegaard2
2019-11-13 19:13:18

yilin.wei10
2019-11-13 19:23:10

Thanks


pavpanchekha
2019-11-13 19:34:15

For the first, we interpret that uses single-floats, and use single-floats in the interpreter in the obvious way


pavpanchekha
2019-11-13 19:34:28

For the second, we want to generate nice HTML error traces


pavpanchekha
2019-11-13 19:36:14

This means 1) generating an exception value somehow; 2) passing it to the subroutine that generates the HTML, including plotting; 3) extracting the context and generating the HTML backtrace


pavpanchekha
2019-11-13 19:36:22

In (3) we use continuation-mark-set->context


pavpanchekha
2019-11-13 19:36:36

But the boundary between places would be at (2)


samth
2019-11-13 19:36:48

could you move that use of continuation-mark-set->context to (2)?


pavpanchekha
2019-11-13 19:36:55

So we’d have to mangle exception values before passing them over, which is a pain


pavpanchekha
2019-11-13 19:37:03

Yeah, that’s what we used to do


samth
2019-11-13 19:37:23

I guess I don’t see why that’s a pain — is there something else about the exception value that is useful?


pavpanchekha
2019-11-13 19:37:46

We can pass it to the default exception printer, for example, if we want a console stack trace instead of an HTML one


samth
2019-11-13 19:39:22

that makes sense, although it seems like there ought to be a way to make this work for you


pavpanchekha
2019-11-13 19:39:50

I guess you’re suggesting unpacking the exception value into a type and a message and a traceback, and passing around those pieces, all of which are serializable


samth
2019-11-13 19:40:26

or just do the printing and then pass around the string and the stack trace


pavpanchekha
2019-11-13 19:40:32

But we can’t re-pack it, so we’d need to duplicate some Racket code, and all of this is also to create the much more complex architecture where plotting uses one set of workers and everything else uses another


pavpanchekha
2019-11-13 19:41:04

The better decision seems to be to write our own plotting library, which does the plotting in JS


pavpanchekha
2019-11-13 19:41:26

that drops the plot library entirely, and it helps with both memory and possible other goals like interactivity


pavpanchekha
2019-11-13 19:41:41

Plus owning the plotting library seems to make much more sense for Herbie than owning a little exceptions library


pavpanchekha
2019-11-13 19:42:26

(Since our custom plotting library can specialized to our needs and anyway is very user-facing)


samth
2019-11-13 19:43:01

I feel like we ought to be able to come up with a solution that involves neither of those


pavpanchekha
2019-11-13 19:43:37

Well, part of the issue here is that we use places for parallelism


samth
2019-11-13 19:44:02

sure, but that should be a good thing


pavpanchekha
2019-11-13 19:44:28

Is it? Serializability is irrelevant in our application (one process)


pavpanchekha
2019-11-13 19:44:46

And in one process in particular I don’t see why we need to load multiple instances of each library


pavpanchekha
2019-11-13 19:45:00

Except of course that ATM dynamic variables (parameters) and so on live inside the library instance


pavpanchekha
2019-11-13 19:45:05

As I understand it


samth
2019-11-13 19:46:08

right, all the values of the libraries definition are part of the library instance, and the point of places is that they’re shared-nothing


pavpanchekha
2019-11-13 19:46:18

Yep


pavpanchekha
2019-11-13 19:46:28

Shared-nothing gives good guarantees but bad memory usage


pavpanchekha
2019-11-13 19:46:48

Far as I know, there isn’t a “share-everything” option in Racket


pavpanchekha
2019-11-13 19:47:05

In any case, client-side plotting is planned anyway (for interactivity and controlling styling), so I guess I’m just going to bump the priority of that


pavpanchekha
2019-11-13 19:47:13

In the hopes of controlling memory usage


samth
2019-11-13 19:47:26

you can use futures, but those are more limited in terms of parallelism (because sharing a bunch of mutable data is hard)


samth
2019-11-13 19:47:58

what’s the best way for me to try herbie and see the memory consumption?


pavpanchekha
2019-11-13 19:48:29

raco pkg install herbie will install the tool, but the benchmarks will be hard to find, so I recommend git clone <https://github.com/uwplse/herbie>


pavpanchekha
2019-11-13 19:48:49

bThen you just do racket src/herbie.rkt report bench/hamming/ /tmp/out/


pavpanchekha
2019-11-13 19:49:03

On my machine that is on the order of 400MB


pavpanchekha
2019-11-13 19:49:24

I tried futures, but I think even allocations break parallelism there, so it didn’t help


samth
2019-11-13 19:50:58

allocations will cause occasional synchronization but not break parallelism; again things are better in racketcs


pavpanchekha
2019-11-13 19:53:27

Sorry, yeah, when I said “break parallelism” I mean they cause synchronization. Herbie does a lot of allocation. When I tried futures I failed to find any speed-up at all


samth
2019-11-13 20:01:18

yes, that isn’t that surprising; futures can often fail to scale well


sorawee
2019-11-13 20:52:53

If I want to make a POST request, what library is the easiest one to use? There’re at least simple-http, racket-request, http, net/url, and net/http-client.


soegaard2
2019-11-13 20:54:43

I like http-sendrecv from net/http-client



soegaard2
2019-11-13 20:56:08

I can’t remember whether I spent much time comparing though.


sorawee
2019-11-13 20:58:35

That’s very helpful. What I’m really looking for, I guess, are some examples, and you give me exactly that.


sorawee
2019-11-13 21:27:37

Oh… so #:data is only for POST and not GET…


soegaard2
2019-11-13 21:27:59

Sounds right.


notjack
2019-11-13 21:28:26

Don’t use the request package, I don’t actively maintain it anymore and it’s got some weirdness.


sorawee
2019-11-13 21:38:35

Does this look right to you, @soegaard2?

(match method
          ['get (http-sendrecv
                 api-url
                 (~a "/w/api.php?" (alist-&gt;form-urlencoded info))
                 #:ssl? #t
                 #:version "1.1")]
          ['post
           (http-sendrecv
            api-url
            "/w/api.php"
            #:ssl? #t
            #:version "1.1"
            #:method "POST"
            #:data (alist-&gt;form-urlencoded info)
            #:headers
            '("Content-Type: application/x-www-form-urlencoded"))])

soegaard2
2019-11-13 21:40:09

yes


sorawee
2019-11-13 21:40:18

Slightly disappointed that info can’t be shared in both methods


deactivateduser60718
2019-11-13 21:49:51

In command-line, some clauses like #:ps call for string literals and not string expressions.

Here’s some incorrect code. I don’t think I can use begin b/c I am not meaning to use implicit top-level forms. That, and I think I should be operating at a higher phase level. How do I change this such that the syntax object expands to multiple string literals?

#lang racket/base
(require racket/cmdline (for-syntax racket/base))

(define-syntax (place-lines stx)
  (datum-&gt;syntax stx (begin "A" "B" "C")))

(command-line #:ps (place-lines))

soegaard2
2019-11-13 21:53:26

Here command-line is a macro, so (command-line #:ps (place-lines)) expands from the outside in. That is, the syntax transformer of command-line recieves #'(command-line #:ps (place-lines)).

You need to use with-syntax to insert “arguments” to a macro call.


soegaard2
2019-11-13 21:55:48

Something like (untested) (define-syntax (my-command-line stx) (syntax-parse stx [(_my-command-line arg ...) (syntax/loc stx (with-syntax ([(line ...) #'("A" "B" "C")]) (command-line arg ... #:ps line ...)))])) and then use it as: (my-command-line).


deactivateduser60718
2019-11-13 21:57:22

Gotcha, thanks. I was honestly a little afraid of hiding command-line due to its complexity. For some reason I figured it was possible to have higher-phase macros expand before lower-phase macros.


soegaard2
2019-11-13 21:58:59

Above my-command-line and command-line have the same phase.


soegaard2
2019-11-13 22:00:06

I think the order of the arguments of command-line might be important. So putting line ... at the end might not be what you want.


deactivateduser60718
2019-11-13 22:00:33

That and I was hoping to avoid the work of preventing the user from (implicitly) specifying #:ps twice.


notjack
2019-11-13 22:11:18

> the much more complex architecture where plotting uses one set of workers and everything else uses another

Would that be more complex, or just different? Making task-specific worker pools seems simpler to me than using a single shared pool. I’m imagining a macro like:

(define-task (compute-foo x y z)
  ... regular function body ...)

…which under the hood creates a pool of places, binds compute-foo to a function that sends its inputs over a place channel and receives the output, and generates an implementation with the body of compute-foo that reads inputs from a place channel and sends the output back.


notjack
2019-11-13 22:13:16

Could also allow require statements inside the body to make the dependencies of the worker places explicit: (define-task (compute-foo x y z) (require x y z) ... body ...)


pavpanchekha
2019-11-13 23:24:53

@notjack Maybe so, but the architecture we are currently using (place per task) already exists, so there’s a lot of rewriting involved to change it


deactivateduser60718
2019-11-13 23:40:11

Feedback request: Here’s a short demo of a prototype for quickly writing CLIs with subcommands + summary docs.


deactivateduser60718
2019-11-13 23:43:04

TL;DW: It builds directories that look like this

delta.rkt
delta_build.rkt
delta_build_once.rkt
delta_build_live.rkt
delta_query.rkt
delta_version.rkt

That you can use like this: $ delta $ delta build $ delta build once ... $ delta build live ... $ delta query ... $ delta version ...


sorawee
2019-11-14 00:15:42

How can I get cookies to work with net/http-client?


sorawee
2019-11-14 00:15:58

Is there something equivalent to requests.Session in Python?



sorawee
2019-11-14 00:17:07

Ughh.. this is kinda inconvenient…



soegaard2
2019-11-14 00:23:55

sorawee
2019-11-14 00:26:18

Thanks. Really appreciate your help


soegaard2
2019-11-14 00:29:55

Part of the reason I wrote racket-stories was to get an actual example of using Racket for web apps. It’s difficult to find public examples.


soegaard2
2019-11-14 00:30:59

I wonder why Bogdan’s koyo doesn’t show up on http://docs.racket-lang.org\|docs.racket-lang.org ?


sorawee
2019-11-14 00:34:18

I think these are primarily for server side, though, right?


sorawee
2019-11-14 00:34:44

My work is mostly client side. Just making a bunch of requests to servers


soegaard2
2019-11-14 00:36:19

Ah I thought you needed server side sessions.


samth
2019-11-14 01:20:51

I think @popa.bogdanp hasn’t put it there


notjack
2019-11-14 02:05:10

Ah, yeah that makes sense


notjack
2019-11-14 02:06:23

Does that mean that if there existed a good library that made it easy to set up pools per task type, and if you had used it, that would have prevented the performance problems your architecture has now?


notjack
2019-11-14 02:06:49

Asking because I’ve thought about making such a library but haven’t prioritized it


notjack
2019-11-14 02:13:59

Skimmed the video, I think this is an interesting approach.


sorawee
2019-11-14 02:15:52

Cool, it works now.


sorawee
2019-11-14 02:16:51

Last question: if I have a (in-generator) sequence that I want to cleanup after it completely enumerates the sequence, how should I do that? I know there’s dynamic-wind. Is that what it’s for?

EDIT: I think dynamic-wind wouldn’t do it, since it would log me out before I completely finish API queries


samdphillips
2019-11-14 02:17:16

net/cookies is the way I’ve used cookies, but I don’t have an example with raw net/http-client


notjack
2019-11-14 02:18:01

Implicitly composing things based on directory structure often makes for sharp API edges. What do you think about making the wiring explicit with a module that says “this command group is made of these commands”?


notjack
2019-11-14 02:19:32

You sort of… can’t. The sequence protocol doesn’t have a place to attach cleanup logic.


samdphillips
2019-11-14 02:19:42

IME using dynamic-wind with sequences ends sadly.


sorawee
2019-11-14 02:20:41

OK, so using sequence-append with the cleanup code in the second sequence?


notjack
2019-11-14 02:20:45

I’m trying to improve the state of things here with transducers. Would you be willing to share more details about your use case?


samdphillips
2019-11-14 02:21:05

In the case of in-generator if you know it will always run to the end you could probably do: (in-generator () (acquire-resources) ... (yield a bunch) ... (release-resources))


samdphillips
2019-11-14 02:21:22

But if you don’t use the whole sequence I probably won’t release.


notjack
2019-11-14 02:21:26

It won’t run if something doesn’t consume the whole sequence


notjack
2019-11-14 02:22:15

What cleanup are you doing?


sorawee
2019-11-14 02:22:36

I’m querying a lot of information from an API. In the beginning, I need to login. At the end, I need to logout.


sorawee
2019-11-14 02:23:04

Since there are a lot of information, it needs to be separated into chunks. Hence generator.


samdphillips
2019-11-14 02:23:12

You could use dynamic-wind but you need to attach it around the whole usage of the sequence.


badkins
2019-11-14 02:24:06

Would shelling out to curl work for your use case? It handles redirects, cookies, etc.


samdphillips
2019-11-14 02:25:06

Like if the sequence escapes the dynamic scope of the dynamic-wind the resources will be released and then error.


sorawee
2019-11-14 02:25:15

yup, that’s not what I want


samdphillips
2019-11-14 02:25:23

But if you use it all in the body it will be OK.


samdphillips
2019-11-14 02:27:02

You might be able to use one of the weak memory management things if you don’t need to release immediately.


sorawee
2019-11-14 02:27:36

Would this work? I’m slightly worried about yield-from since it looks like it needs to hold a lot of data in memory

(define (foo) (in-generator ...))

(define (bar)
  (login!)
  (in-generator
    (yield-from (foo)
    (logout!)))

sorawee
2019-11-14 02:28:38

where yield-from is

(for ([x xs]) (yield x))

sorawee
2019-11-14 02:29:08

@samdphillips you meant Will & Executor thing?


sorawee
2019-11-14 02:29:32

I used it in my previous project. It doesn’t really work… I probably did something wrong


badkins
2019-11-14 02:29:37

How well does DrRacket work on Linux? I’ve been developing on a Mac for 11 years, but every single one of my friends who have upgraded to a recent Macbook Pro have had their computers in the shop at least once, and often two or three times. I mostly live in Emacs all day, but I am fond of DrRacket, so I thought I’d check before I do something crazy like try Linux as my dev machine again :slightly_smiling_face:


samdphillips
2019-11-14 02:30:02

Wills or ephemerons. But I don’t know what the best practice is for that.


notjack
2019-11-14 02:30:56

You need to log out? Why not just let it expire?


samth
2019-11-14 02:31:01

@badkins works just as well on linux as on mac


samth
2019-11-14 02:31:14

I’ve used linux for 20 years


samth
2019-11-14 02:31:19

including DrRacket


badkins
2019-11-14 02:31:20

Awesome - nice to have options!


badkins
2019-11-14 02:32:13

Maybe the new 16" model with scissor keys won’t have so many reliability issues, but hard to say.


sorawee
2019-11-14 02:32:22

My account kinda has a lot of privileges. So as a safety measure, I want to avoid the risk of it being compromised as much as possible.


sorawee
2019-11-14 02:35:16

I wanna know how far can I go with Racket. Otherwise, I would just use Python’s requests.


badkins
2019-11-14 02:35:25

On another note, it’s now been over a year since I switched to Racket as my primary language, and I’m more pleased with it now than a year ago when I switched - it’s been the most fun I’ve had in over three decades of programming - so thanks Racket folks!


sorawee
2019-11-14 02:46:52

Here’s another hacky way:

#lang racket

(require racket/generator)

(define (logout-after! xs)
  (sequence-append
   xs
   (in-generator (displayln "logging out..."))))

(define xs
  (logout-after!
   (in-generator
    (yield 1))))

(displayln "logging in")
(for/list ([x xs])
  x)

samdphillips
2019-11-14 03:00:30

I’ve never worked with a web API that required logout. In most cases it just invalidates the credentials you’re using.


ericpn400
2019-11-14 03:02:34

@ericpn400 has joined the channel


notjack
2019-11-14 03:03:57

@sorawee What’s the authentication protocol between you and the server look like?



notjack
2019-11-14 03:31:59

Oh dear. That is a terrible API.


sorawee
2019-11-14 04:24:36

Can you enlighten me how it’s terrible?


notjack
2019-11-14 04:57:32

@sorawee A few things: - The GET method is supposed to be safe, i.e. essentially read only. That allows crawlers and caches to work without fear of causing harm. But caching that logout request would cause a lot of problems. - HTTP already has a standard authentication protocol, there’s no need for them to roll their own POST endpoint and cookie-based system. Especially if your client is a robot and not a browser. - Query string parameters are often better represented as content in the request body.


notjack
2019-11-14 05:02:54

For that first item, the HTTP spec even calls out that antipattern specifically: >For example, it is common for Web-based content editing software to use actions within query parameters, such as “page?do=delete”. If the purpose of such a resource is to perform an unsafe action, then the resource owner MUST disable or disallow that action when it is accessed using a safe request method. Failure to do so will result in unfortunate side effects when automated processes perform a GET on every URI reference for the sake of link maintenance, pre-fetching, building a search index, etc.


notjack
2019-11-14 05:16:11

(Whoa, you can link to individual paragraphs of the http spec??? https://httpwg.org/http-core/draft-ietf-httpbis-semantics-latest.html#rfc.section.7.2.1.p.6)