Fork me on GitHub
#beginners
<
2019-12-22
>
andy.fingerhut00:12:01

There are some examples of numbered capture groups using re-find on this page: https://clojuredocs.org/clojure.core/re-find

Calyce00:12:31

I tried with numbered but was not able to make it work the way i need it

Calyce00:12:43

I'll have a look at the examples

andy.fingerhut00:12:50

If you are trying to match things like "<some_string><other_thing><some_string>" where the second <some_string> is an identical sequence of characters as the first, that is a semi-special extension to regexes that some regex engines have, but others do not.

Calyce00:12:48

This is effectively what I'm looking for

andy.fingerhut00:12:56

It is not a regular expression in the computer science automata theory class sense of a regular expression, which is one of the reasons it is a semi-special extension. I do not recall if the Java regex engine can do that or not, as I never venture that far from automata theory regexes.

andy.fingerhut00:12:39

If you find that the Java regex engine cannot do it, a parser for a larger kind of languages can be parsed using other libraries, like Instaparse: https://github.com/Engelberg/instaparse

Calyce00:12:33

I'll have a look to that

andy.fingerhut00:12:31

According to the Java regex page https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html there is something called "Backreferences" that looks like it might be what you want.

andy.fingerhut00:12:24

Search on that page for both of "back references" and "backreferences" (with and without the space) to find all occurrences where it is mentioned

andy.fingerhut00:12:49

I have never used those before, so can't speak to their effectiveness in Java's regex engine.

andy.fingerhut00:12:21

And it looks like there are named capture groups

andy.fingerhut00:12:49

Which I have no idea what those do if you try to use one with Clojure's re-find

Calyce00:12:53

This is the page I was directed to when searching. I might have read it too fast...

andy.fingerhut00:12:42

From a quick experiment at the REPL, it seems like re-find returns the same thing on a match for named or unnamed capture groups:

user=> (re-find #"(?<foo>\S+)\s+(?<bar>\S+)" "the quick brown fox")
["the quick" "the" "quick"]

andy.fingerhut00:12:19

But the names might be nice if you have a complex enough regex that you want to use named back references and not have to keep count of them.

Calyce00:12:17

Ok, found a working regex: #"([a-z]).\1"

Calyce00:12:40

Many thanks for pointing me in the right direction 😉

andy.fingerhut00:12:41

Cool. Sounds like you are off to the races, then.

andy.fingerhut00:12:37

Yeah, once you get outside of concatenation, alternation/or using | , and + and * , not a whole lot is portable between different regex engines in different libraries/languages.

andy.fingerhut00:12:37

but most of them support a whole lot more than that, if you are willing to write them non-portably.

charlie engelhard00:12:26

I'm trying to use https://github.com/HCADatalab/powderkeg #powderkeg because I like the design of it a lot, but it hasn't been maintained in a while, and I'm struggling even to get a fork to compile. I'm kind of a beginner, so I may just be missing something. the issues are all concerning this module "ouroboros", and I'm getting everything from "namespace not found" to complicated errors involving (proxy) overriding things it apparently shouldn't be, as well as "illegal reflective access operation". I don't know enough about Java interop and (proxy) to figure it out. Has anyone here had any similar issues? Is there a gotcha that I'm hitting? I'd really like to use this library, I love the way it uses transducers so it doesn't have to reimplement all of Spark.

charlie engelhard00:12:14

Is "namespace not found" just lein repl's way of saying "something went wrong"?

andy.fingerhut00:12:31

"illegal reflective access operation" might be something you can ignore, assuming you are using JDK 9 or later, if they are warning messages: https://clojure.org/guides/faq#illegal_access

charlie engelhard00:12:08

I'm using OpenJDK 13...

andy.fingerhut01:12:56

If you have easy access to OpenJDK 8, I have no idea if that would work better for the issues you are facing, but you should not get those particular warnings, and in general that version of the JDK is perhaps closer to the most commonly used one when that Clojure library was last actively maintained. Just a shot in the dark on my part there.

andy.fingerhut01:12:43

e.g. AdoptOpenJDK 8 is available for multiple OS's here: https://adoptopenjdk.net

andy.fingerhut01:12:56

They are likely to be only warnings that aren't the root cause of other issues, though.

charlie engelhard01:12:46

I will try that. Something else of note: I'm now using io.aviso/pretty so I have a better error message: "java.lang.UnsupportedClassVersionError: powderkeg/Agent has been compiled by a more recent version of the Java Runtime (class file version 57.0), this version of the Java Runtime only recognizes class file versions up to 55.0"

charlie engelhard01:12:09

55 is java 11, 57 is java 13, so I'll try Java 11

charlie engelhard01:12:59

Although I don't understand where the inconsistency is coming from in the first place... still new to this.

charlie engelhard01:12:51

I don't get this error in the lein REPL, only in the Cursive REPL

andy.fingerhut01:12:50

If a project uses Leiningen, the command lein clean should remove any cached .class files that might contribute to that error, if you are switching between different JDK versions in your experiments.

andy.fingerhut01:12:37

If you still see it after doing lein clean it is possible that perhaps some library you are using, or depending upon transitively through other projects, has precompiled .class files in it.

charlie engelhard01:12:15

Looks like the problem was that Cursive was set up to use 11 and I had 13 installed.

charlie engelhard01:12:34

io.aviso/pretty is a life saver ❤️

charlie engelhard01:12:43

thanks for your help.

charlie engelhard02:12:30

also yeah I did have to switch to 8.

bortexz15:12:26

Is there any kind of short circuit logic for comp ? e.g (comp int :number) that would return nil instead of throw NPE when number does not exist on object?

bortexz15:12:12

Like using some-> but with comp

bortexz16:12:59

What I’ve thought is to wrap the int coercer to allow & return nil in a custom int* fn

Adrian Smith16:12:23

Why do I get two zeros in a vector here? Is it because of the spec/and?

Adrian Smith16:12:47

hmm no because:

hindol17:12:20

Is there a way to log an argument which is a function? Printing it gives something like #object[user$square 0x4f20a5e0 "user$square@4f20a5e0"]. I want the source instead.

andy.fingerhut17:12:10

In a REPL session, (source ) will show the source code, if it was loaded from a file (i.e. not entered in the REPL)

andy.fingerhut17:12:38

I haven't tried that for logging, but you could give it a go and see what happens in a small experiment.

Alex Miller (Clojure team)18:12:24

The short answer to the question above is, no

Alex Miller (Clojure team)18:12:12

If you have a function object, that’s an opaque compiled function instance that is invoke Le but not much else

Alex Miller (Clojure team)18:12:32

It is possible to demunge the class name of the instance and make something readable (demunge will not working in every case, but most)

Alex Miller (Clojure team)18:12:35

If you want the actual expression that was compiled into the function instance you have, you can’t get that

Santiago18:12:07

I need to prepare some JSON files for my clojure app. They're loaded when the app starts and used as a in-memory database of sorts. Currently I created a Bash script that downloads a csv, converts to json, handles it with jq and does a couple more things with the data in a folder I called scripts on my lein project root. If I change it to a clj script, still in the scripts folder i.e. not in the src path, can I run it as a script like clj myscript.clj or will my external libraries/dependencies not be loaded because I'm not using lein?

andy.fingerhut18:12:40

If you have a deps.edn file (or provide its contents on the clj command line), you can specify directories to put on its class path, and what dependencies the program needs. Providing that on the clj command line means that its contents can override/merge-with a deps.edn file in the directory where you run the clj command.

Santiago18:12:26

is this good practice though? I would be using lein and deps.edn in the same project

andy.fingerhut18:12:04

If you and the people that use it can keep it straight how it works, and update it/fix things when needed, then I don't see a problem. A mention in a README for the project somewhere that "the main project uses Leiningen with the project.clj file, but this tools in scripts/foo uses this scripts/deps.edn file and must be run when your current directory is 'scripts'" (or whatever rules/conventions you want to establish that might be different than that merely-an-example-text), seem reasonable to me.

4
andy.fingerhut18:12:06

Leiningen will never read the deps.edn file (until and unless someone makes some special plug-in/add-on that does so), and clj will ignore the contents of the project.clj file.

Alper Cugun20:12:12

Wow. This whole, “We’re going to fix your editor so that you don’t have to think about matching parens anymore” thing takes a bit of getting used to, but then it’s pretty awesome.

andy.fingerhut20:12:14

There are varying levels of editor behavior for that -- some like parinfer style things, others prefer merely showing matching parens, but you still type them yourself. I am in the latter camp, personally.

Alper Cugun20:12:41

Yeah, it borders on the hostile but I’m going with it for now.

Alper Cugun20:12:56

‘What do you mean you wont let me delete this paren!?!!?’

andy.fingerhut20:12:21

It doesn't bother me, if I can disable it in my editor 🙂

Alper Cugun20:12:28

I’m also a big fan of stuff like black (for Python).

andy.fingerhut21:12:35

Some people would like to create something similar for Clojure, but I don't recall if they produced something that runs yet.

hindol03:12:20

I find strict parens modes quite helpful. After getting used to it of course. For example, if I want to delete a line where all the paren endings are piled up, I can just do d d (Emacs with evil, this will delete the whole line normally), the pile of parens are moved to the previous line.

jaihindhreddy04:12:43

Paredit takes some getting used to, but is really beneficial IMHO. You start thinking about your code structurally. Beware, writing non-LISPs may feel like smashing rocks together after this.

sova-soars-the-sora20:12:49

Hi, what does this mean? Reflection warning: ... 87:7 all to java.lang.Integer ctor can't be resolved. ?

andy.fingerhut20:12:54

Are you familiar with reflection warnings in Clojure in general, and are confused about this particular one? Or new to the idea of a reflection warning in general?

andy.fingerhut21:12:38

If new to reflection warnings in general, basically the Clojure compiler, when it sees Java interop forms, tries at compile time to determine what Java method or field is involved. Because Java allows one to define multiple methods with the same number of parameters, but different types of arguments, sometimes it cannot distinguish between multiple methods from what is in the program.

andy.fingerhut21:12:32

In this case, it will emit "reflection" code, meaning it uses the Java reflection API to find all matching methods at run time, look up the actual types of the arguments at run time, and pick which method to call, each time that call occurs during run time, which is much slower than if it could narrow it down to one possible method at compile time.

andy.fingerhut21:12:11

The message is a warning that performance may be bad for that call. It is not a correctness warning.

andy.fingerhut21:12:27

In many cases, there are ways to add "type hints" in Clojure source code that give the compiler enough clues to narrow down the number of possible methods to 1.

😎 4
🔥 4
sova-soars-the-sora21:12:04

Thank you that is very helpful and clear. I am simply trying to convert a string to an integer.

sova-soars-the-sora21:12:12

it is proving quite problematic

sova-soars-the-sora21:12:40

Thanks! Your explanation helped me greatly and i was able to resolve the issue.

ghadi21:12:38

@sova Don’t use the Integer constructors, they’re deprecated in Java: use Integer/parseInt

ghadi21:12:38

@sova Don’t use the Integer constructors, they’re deprecated in Java: use Integer/parseInt

Eric Ihli23:12:55

What's a good process for tracing/debugging code in a dependency? In Python, I could just go into my site-packages directory where pip installs packages and I could make edits to dependencies to add print s and breakpoints. Is there a similar way to hack around in dependencies in Clojure/ClojureScript?

seancorfield23:12:25

@ericihli If you're running your code from inside the REPL, with your editor connected, then you can edit the code in the dependencies (assuming you've cloned them locally), and evaluate it into the running REPL, with your debugging changes in place.

Eric Ihli23:12:56

> assuming you've cloned them locally Right now all my dependencies are as .jar files in an m2/repository directory. I'm trying to figure out how to point to a dependency that is a local directory, like a git repo.

seancorfield23:12:37

In the scenario I described, you don't need the dependencies changed from the JARs. You just edit the source (elsewhere) and eval it into the running program.

seancorfield23:12:53

It's the same as editing code and eval'ing it into a live, running, production process 🙂 No need to restart the process or anything. The changes only hold while the process is running.