Fork me on GitHub
#beginners
<
2023-01-02
>
Chris Lester06:01:11

tldr: I'm wondering if there is a better pattern than the "http-context" where you need to pass around state that gets constantly updated. ... I'm writing a recursive descent parser that needs to keep track of the token stream .. a similar pattern used in my lexer actually (although I wrote a mutable version of that one as well that bugs me because mutable). Passing a state record down that gets updated and passed back up as you parse expressions (or lex tokens). All I can see is the word "state" throughout my code and it's bugging me lol. Is this where one would normally reach for an atom/ref/agent, etc? example for a binary expression:

(defmethod match :binary
  [_ state left-fn right-fn token-types]
  (let [lstate (left-fn state)
        matched? (match? lstate token-types)]
  
    (if-not matched?
      lstate
      (let [op (current lstate)
            rstate (right-fn (advance lstate)) ;; matched so need to advance
            lexpression (first (:expressions lstate))
            rexpression (first (:expressions rstate))
            fstate (store-and-advance rstate (ast/expression :binary
                                                             lexpression
                                                             op
                                                             rexpression))]
        fstate))))

phill11:01:00

A program that "passes around state" is easier to test than a program whose 9,999 methods alter an atom. And after a failure wouldn't the atom have to be reverted back to some prior state in order for the next possibility to be tried? Of course if the state's appearance in the code is completely routine then you could automate it away with a macro, or if the code overall is quite routine then you could either code-generate it or otherwise make it data-driven to reduce the surface area of source code. But - in general - "passing around state" is one of the great things about not-OO.

Chris Lester01:01:52

Thanks! Had forgotten about Pedestal's interceptors .. have used Pedestal before for a web service and quite liked the pattern there.

Chris Lester01:01:32

RE: code generation from data. I had thought about making a parser generator from the bnf grammar (since this is a toy) .. but decided I want to get to done before veering off into the weeds 🙂

stagmoose08:01:18

If I have a text file containing:

- A
  - a
  - b
- B
  - c
- C
What's the recommended way or libs to parse the file and generate something like:
[ [A [a b]] [B [c]] C ]
edit: I also wonder how these nested data are generally represented? If I use key value pairs to represent the data (something like json), the entry "C" doesn't have value at all.

Ferdinand Beyer09:01:18

Looks like YAML, maybe you can use a YAML parser? There are multiple ways to represent this, your suggestion is one example. For consistency, you could represent every (non-leaf?) item as [key children], turning C into [C []] and so on. Another option is to use maps:

{"A" ["a" "b"]
 "B" ["c"]
 "C" []}

stagmoose12:01:16

great suggestion! thanks!

Joseph Graham12:01:50

Have a variable imgfmt and want to check if it equals one of several string values. Came up with two solutions but both seem a bit convoluted? (some #(= imgfmt %) ["webp" "avif" "jpeg"]) or (nil? ({"webp" true "avif" true "jpeg" true} imgfmt))

Joseph Graham12:01:57

OK figured it out: (some #{imgfmt} ["webp" "avif" "jpeg"])

Thomas12:01:25

I was about to suggest the reverse, define a set (def formats #{"webp" "avif" "jpeg"}) and use it as a function: (formats imgfmt)

Joseph Graham12:01:49

ah yes, that's much nicer!

Joseph Graham12:01:33

will need to get used to using sets

Mor Gazith12:01:50

hey, i’m trying to use https://github.com/benedekfazekas/mranderson to shade my library’s dependencies so they won’t interfere with my other repos using this lib. anyone here has any experience using it and can help out?

lread14:01:47

I might not be the best person to answer your question, but I've made a few commits to MrAnderson, so I might be able to help. What problem are you having?

Mor Gazith15:01:07

thanks, so basically it never compiles for me. when using [thomasa/mranderson "0.5.3"] and running lein inline-deps i get

RuntimeException: No reader function for tag Inf, compiling:(mranderson/inlined/parallel/v0v10/parallel/core.clj:323:31)
when using [thomasa/mranderson "0.5.4-SNAPSHOT"] the issue above is resolved and inline-deps complete, but then when i run lein with-profile +plugin.mranderson/config test there are many issues: 1. some source code gets a repeating prefix again and again, like mylib101012.mylib101012.mylib101012.mylib101012.mylib101012.some.ns which i workaround via search&replace. 2. mranderson will inline and add prefix to code which is defined in :prefix-exclusions - again search&replace to workaround 3. then i get NoClassDefFoundError: mylib01012/javax/net/ssl/SSLEngine which i couldn’t resolve, i do see srcdeps/mylib101012/javax but there’s no net under it. thanks for helping out!

Mor Gazith15:01:04

i get a sense that 0.5.4-SNAPSHOT might be still unstable, while 0.5.3 doesn’t play well with something in my lein environment

lread16:01:10

@U04H5V7URR9 is your library public? If so, can you share a link?

Mor Gazith17:01:03

it’s a fork of https://github.com/fullcontact/full.aws/tree/0.10.9 by FullContact, based off tag 0.10.9

Mor Gazith17:01:16

with deps modified to:

:dependencies [[org.clojure/clojure "1.8.0"]
                 [com.amazonaws/aws-java-sdk "1.11.16"]
                 [com.taoensso/faraday "1.7.1"              ; DynamoDB sugar
                  :exclusions [com.amazonaws/aws-java-sdk-dynamodb joda-time]]
                 ^:inline-dep [fullcontact/full.http "1.0.9"]
                 ^:inline-dep [fullcontact/full.json "0.12.0"
                               :exclusions [com.fasterxml.jackson.core/jackson-core]]
                 [fullcontact/full.async "0.9.0"]
                 [fullcontact/full.core "0.10.1"
                  :exclusions [org.clojure/clojurescript]]
                 ^:inline-dep [javax.xml.bind/jaxb-api "2.4.0-b180830.0359"]
                 ^:inline-dep [com.fasterxml.jackson.core/jackson-annotations "2.6.0"]]

andy.fingerhut17:01:42

Not at a laptop at the moment to check, but I see Clojure 1.8.0 in the list there, and the error message mentions Inf. Reader syntax for ##Inf was added in a later Clojure version.

lread18:01:49

of interest: with @U0508JT9N's blessing I've just created a #C04HWRD2D32 channel.

lread18:01:45

Good eyeballs @U0CMVHBL2, no unit tests for that lib, eh @U04H5V7URR9? Would be nice to know if it works before applying MrAnderson.

Mor Gazith18:01:13

yeah it works without mranderson, I've tried with clojure 1.9.0, and also clojure.tools that supports Inf and couldn't get it to compile still

lread19:01:27

If nobody else beats me to it, I can have a deeper peek sometime soon (maybe tomorrow) @U04H5V7URR9. Is your fork public?

Mor Gazith19:01:39

that would be great! my fork is private, but other than the dependencies changes I didn't change a thing

lread20:01:38

Can you make it public? I would want to make sure I'm working with what you are working with.

Mor Gazith20:01:47

I can try running mranderson on the official repo just to make sure I didn't screw anything up myself

đź‘Ť 2
Mor Gazith20:01:02

also, I would mention I'm running with apple silicon M1 which has been the source of the most unusual bugs twice already, so maybe that's somehow related to this conundrum as well

lread20:01:21

good to know!

lread20:01:15

But maybe you found a bug in MrAnderson too. Whatever the case, I expect we'll come to some solution.

Mor Gazith20:01:00

let’s move to #C04HWRD2D32? it might get verbose 🙂

lread20:01:24

Ya, sure would be nice to have some traffic over there. simple_smile