clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2020-12-23T05:10:56.349900Z

depending on how simple your tool is, you may not even bother with aliases or a deps.edn at all

2020-12-23T05:12:27.350100Z

for example https://git.sr.ht/~hiredman/lions doesn't have a deps.edn at all, and the README just lists a bunch of different clj -X ... invocations

👍 1
avivak 2020-12-23T06:57:54.351200Z

Can anyone recommend a tool for clojure/cljs code scanning for SAST (Static Application Security Testing)?

kenny 2020-12-23T15:40:49.369Z

I asked about this recently https://clojurians-log.clojureverse.org/clojure/2020-12-06. Essentially - no. Further, most vulnerabilities are found with other methods.

avivak 2020-12-24T09:28:41.423200Z

thanks

wegi 2020-12-23T08:23:40.353300Z

Hi there, I am trying to run clj -X:some-alias to use a tool. But all I get is a -X:some-alias (File or directory not found). So apparently -X is not recognized as a parameter. Any Ideas what might cause this?

p-himik 2020-12-23T08:28:15.353700Z

What version of clj do you use? It's on the first line of clj -h.

wegi 2020-12-23T08:29:13.353900Z

Its not shown for me

clj -h
Usage: clojure [dep-opt*] [init-opt*] [main-opt] [arg*]
       clj     [dep-opt*] [init-opt*] [main-opt] [arg*]

The clojure script is a runner for Clojure. clj is a wrapper

wegi 2020-12-23T08:29:59.354100Z

I installed the 1.10.2 rc1 from the AUR on Arch. Unless something went wrong it should be the newest available.

p-himik 2020-12-23T08:34:12.354300Z

I have no clue, sorry. I've installed the latest release by following the instructions at https://clojure.org/guides/getting_started This is how the very first section of the output looks like:

$ clj -h                                                                
Version: 1.10.1.763

You use the Clojure tools ('clj' or 'clojure') to run Clojure programs
on the JVM, e.g. to start a REPL or invoke a specific function with data.
The Clojure tools will configure the JVM process by defining a classpath
(of desired libraries), an execution environment (JVM options) and
specifying a main class and args. 

p-himik 2020-12-23T08:34:40.354500Z

Perhaps the AUR has something else as clj, something that doesn't come from the original sh installation script.

wegi 2020-12-23T08:38:54.354700Z

Thanks for looking into it. It must be an error on my OS end. I will investigate futher!

👍 1
dharrigan 2020-12-23T08:49:43.357300Z

You could try just clojure?

dharrigan 2020-12-23T08:52:06.357800Z

clj is packaged with the clojure-tools distribution

dharrigan 2020-12-23T08:52:45.358100Z

I use Clojure on arch, and just recently (i.e., 30 mins ago) started to use the updated depstar which uses -X now

dharrigan 2020-12-23T08:52:47.358300Z

all works well

borkdude 2020-12-23T09:56:58.359100Z

@avivak Do you need to have some off the shelve thing that looks for certain security things or do you want a tool that you can scan code with and look for certain things yourself?

avivak 2020-12-23T11:10:10.359700Z

off the shelve tool

Dave Russell 2020-12-23T12:05:05.361100Z

Hey folks! Bit of a security question here. Playing around with read-string :

user> (defn foo [] :bar) => #'user/foo
user> (foo) => :bar
user> (read-string "foo") => foo
user> ((read-string "foo"))
Execution error (ArityException) at user/eval244751 (form-init5501808611653817338.clj:455).
Wrong number of args (0) passed to: clojure.lang.Symbol
user> ((resolve (read-string "foo"))) => :bar
Is there a list of functions to be wary of when used in conjunction with read-string? There's eval and I know about *read-eval* , but now even with *read-eval* set to false someone could inject function calls if the symbols become resolved. Are there other ways people know about where things become dangerous in spite of a disabled *read-eval*?

borkdude 2020-12-23T12:28:55.362100Z

@david.russell What do you mean with inject function calls ?

borkdude 2020-12-23T12:30:12.363100Z

Btw, we just had a conversation about read-string in #clojure-europe which led to this script for finding read-string in libs: https://gist.github.com/borkdude/57984ca1df6c3cf8f302196cb37b0f43 For example I found this namespace that has a couple of them: https://github.com/cognitect-labs/aws-api/blob/master/src/cognitect/aws/shape.clj

borkdude 2020-12-23T12:31:19.363400Z

Maybe continue in a thread. @david.russell

Dave Russell 2020-12-23T12:39:44.363600Z

@borkdude I guess what I mean is that there appear to be certain ways by which clojure forms become malicious. eval is surely one, but in the example above (unless I'm misunderstanding something 🙂) someone could make functions calls in your namespace if your business logic happens to call resolve (and then executes) a symbol parsed by read-string.

Dave Russell 2020-12-23T12:40:46.363800Z

So I'm trying to get a sense of the ways that injected clojure data could be abused (other than being data itself, which should be checked for in user-facing codepaths anyways)

borkdude 2020-12-23T12:42:50.364Z

yes, calling functions resolved by dynamic user input can be dangerous

borkdude 2020-12-23T12:43:14.364200Z

there are ways around this, e.g. using a sandboxed eval like https://github.com/borkdude/sci

❤️ 1
Dave Russell 2020-12-23T12:49:40.364600Z

Ah that's cool. Between sci and edn/read-string I guess most use-cases are handled, at least for code you have control over

thheller 2020-12-23T14:55:33.365400Z

@david.russell use clojure.edn/read-string. that is safe without all the eval concerns.

2020-12-23T15:27:57.366300Z

@david.russell See the long-ish description on this page about bad things that can happen if you use clojure.core/read, all of which apply to clojure.core/read-string, too: https://clojuredocs.org/clojure.core/read

2020-12-23T15:30:42.366400Z

@borkdude that use of read-string in the aws-api lib is qualified with a condition that requires the string to contain only ASCII decimal digits, so looks pretty safe to me. Requires some code examination to determine it is safe, but that one is pretty local to the read-string call, thankfully.

2020-12-23T15:31:31.366600Z

Or rather, one of the calls to read-string is as I described. There are others...

ghadi 2020-12-23T15:32:33.366800Z

thanks for pointing that out @borkdude. the aws-api shape stuff needs an overhaul

Dave Russell 2020-12-23T15:36:50.367Z

@andy.fingerhut thanks! That section on unexpected effects with *read-eval* disabled, is exactly what I was looking for. Super interesting. I'd be curious to look into what other unexpected read-string behavior still exists in Clojure 1.10...

2020-12-23T15:39:59.368Z

The examples there I believe do not work in Clojure 1.5 or 1.6 and later, but they should scare readers enough to make them want to avoid clojure.core/read and read-string except for highly trusted data sources. If you come across scary examples that still exist in Clojure 1.10 when *read-eval* is false, I would be happy to add them to that page. Such examples are not necessarily quick or easy to find, though.

2020-12-23T15:41:01.369200Z

(FYI, anyone can add more examples to that page with a free http://ClojureDocs.org account, not just me)

roklenarcic 2020-12-23T16:08:15.371300Z

I’m using compojure and the recommended way to apply middlewares is to use wrap-routes to avoid middleware from routes that didn’t match from being applied… the issue is that it seems to apply middlewares in reverse… outermost wrap-routes middleware gets entered last instead of first… any way around that?

popeye 2020-12-23T16:28:28.373300Z

Team, If I run below function in repl it is giving me 2 value RX, why this is giving 2 values?

popeye 2020-12-23T16:28:30.373500Z

(re-find #"(\S+)" " RX packets:1871074138 errors:5 dropped:48 overruns:9")

popeye 2020-12-23T16:28:41.373900Z

["RX" "RX"]

joelv 2020-12-23T16:28:42.374200Z

I'm unable to use println in a go block

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (go
    (println "here")))
Am I doing something wrong?

popeye 2020-12-23T16:29:43.374700Z

How you are calling function?

joelv 2020-12-23T16:30:15.374900Z

it's my main function that's invoked when I do lein run

2020-12-23T16:30:41.375100Z

because it uses re-groups to return groups

joelv 2020-12-23T16:30:56.375300Z

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "foo")
  (go
    (println "here")))
This prints foo

popeye 2020-12-23T16:30:57.375500Z

is there any other function go in your file?

joelv 2020-12-23T16:31:26.375700Z

no, i'm just playing around with core.async

2020-12-23T16:32:18.375900Z

the thread which is executing -main function finish before go block

joelv 2020-12-23T16:33:02.376100Z

ahhhh

joelv 2020-12-23T16:33:06.376300Z

Thanks!!!

popeye 2020-12-23T16:33:26.376500Z

Is there any way where we can return 1 value?

2020-12-23T16:35:32.376700Z

When you have NO "capture expressions" in your regex, like the (\S+) part is, then re-find returns only one matching string for the entire regex, or nil if no match was found.

2020-12-23T16:36:14.376900Z

If you have capture expressions and a match is found, then in addition to returning the entire string that matched the complete regex, you also get additional elements in the returned vector that matched each of those capture expressions.

2020-12-23T16:36:15.377100Z

you could change regex like #"\S+" in that case no groups will be returned

2020-12-23T16:37:24.377300Z

If you want that, great. If you want to parenthesize something in a regex but do not want it to be a capture expression, you can put a special character sequence just after the left paren, which if I recall correctly is ?:, i.e. #"(?:\S+)" for your regex.

2020-12-23T16:38:07.377500Z

capture expressions can help you write a single longer regex, but pull out sub-pieces of the match, all at once.

popeye 2020-12-23T16:38:10.377700Z

(def text "My string ${hello_world}") => #'user/text (def nvar-rex #"\$\{(\S*?)\}") => #'user/nvar-rex (def matchr (re-matcher nvar-rex text)) => #'user/matchr (re-find matchr) => ["${hello_world}" "hello_world"]

popeye 2020-12-23T16:38:31.377900Z

how it gave one with $ and one without dollar symbol?

2020-12-23T16:39:53.378100Z

The parenthesized part of your regex does not include the \$

2020-12-23T16:40:35.378300Z

you parenthesize the parts of the regex you want, to capture the parts you want (or disable capturing if you use (?: ...)

popeye 2020-12-23T16:42:46.379100Z

Oh I understood 🙂 Thanks 🙂

ghadi 2020-12-23T16:43:38.379800Z

you shouldn't print from a go block or do any IO because it can/will starve the executor pool

ghadi 2020-12-23T16:44:50.381700Z

(it's fine while exploring but I have seen many deadlocks in the wild caused by IO in the go block)

👍 1
heefoo 2020-12-23T16:49:03.386100Z

I am trying to use jSerialComm (https://fazecast.github.io/jSerialComm/javadoc/com/fazecast/jSerialComm/SerialPort.html) from clojure, and I have stumble to the following issue: i am trying to use setComPortTimeouts method (https://fazecast.github.io/jSerialComm/javadoc/com/fazecast/jSerialComm/SerialPort.html#setComPortTimeouts-int-int-int-) with both TIMEOUT_READ_BLOCKING and TIMEOUT_WRITE_BLOCKING and the docs indicate that I should OR them in the first argument which i am not sure how to achive it via java interop. As an example i found the following snipet:

public SerialPort openSerialPort(final SerialPort serialPort,
                                 final long timeout) {
    serialPort.setComPortParameters(getSerialPortBaudRate(),
            getSerialPortDataBits(), getSerialPortStopBits(),
            getSerialPortParity());
    serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING
                    | SerialPort.TIMEOUT_WRITE_BLOCKING, (int) timeout,
            (int) timeout);

    if (!serialPort.openPort()) {
        throw new IllegalStateException("failed to open serial port: "
                + serialPort.getSystemPortName());
    }


    return serialPort;
}

ghadi 2020-12-23T16:53:25.387100Z

user=> (run! prn (sort (apropos "bit")))
clojure.core/bit-and
clojure.core/bit-and-not
clojure.core/bit-clear
clojure.core/bit-flip
clojure.core/bit-not
clojure.core/bit-or
clojure.core/bit-set
clojure.core/bit-shift-left
clojure.core/bit-shift-right
clojure.core/bit-test
clojure.core/bit-xor
clojure.core/unsigned-bit-shift-right

rgm 2020-12-23T16:53:39.387500Z

I’m intrigued by the connecting-things-together setup in Clojure Applied using Component, where all components get supplied core.async channels to take in and give out data. This seems to rely on the (component/system-map ,,,) being called within a system-map generating function, so that there’s one obvious to actually make those channels: a let before calling system-map. Does anyone have any analogous examples for integrant or clip with aero, where the component map is more usually an edn file?

2020-12-23T16:54:14.387700Z

As an example of pulling out the pieces of interest, if you were parsing lines like this "RX 1234 packets TX 4321 packets", you can do the following:

user=> (re-find #"RX (\d+) packets TX (\d+) packets" "RX 1234 packets TX 4321 packets")
["RX 1234 packets TX 4321 packets" "1234" "4321"]

👍 1
p-himik 2020-12-23T16:54:14.387900Z

For that particular case, you need bit-or - it's the equivalent of Java's |.

heefoo 2020-12-23T16:58:06.388900Z

thanks i am going to try them

2020-12-23T16:59:25.389300Z

Hi! What does the dash/minus symbol in front of protocol method mean?

2020-12-23T17:00:40.389800Z

usually - nothing, just part of symbol

2020-12-23T17:01:05.390300Z

I think it may be sometimes used as a convention to mean "internal implementation function, not intended for casual/public use" ?

2020-12-23T17:02:32.390600Z

But given that when one use :gen-class in Clojure and then defines a function named -main, I suspect there may be more to it than merely convention.

2020-12-23T17:03:08.390800Z

that is true for top level public functions, but not for protocols

2020-12-23T17:03:23.391Z

Yes, my question is more about protocols.

2020-12-23T17:04:27.391500Z

cc @seancorfield

2020-12-23T17:04:36.391700Z

I think you can ask author here

2020-12-23T17:50:11.392Z

Maybe I just copied what I saw and rationalized it later, but at least in my code, the - is because there's typically an API function with the same name but without the dash. That one then calls the one with the dash, which gets dispatched.

seancorfield 2020-12-23T17:54:53.392200Z

The protocol functions use a leading - when they are "just" implementations for wrapper functions. Protocols can't be variadic so it's common to provide multi-arity wrappers.

seancorfield 2020-12-23T17:56:02.392400Z

In next.jdbc, the execute and transaction functions all have multi-arity wrappers. prepare and the two get-* protocol functions only have the specified arity so I didn't bother with wrappers.

seancorfield 2020-12-23T17:56:45.392600Z

(it would probably be more consistent to have wrappers for all of them but it isn't necessary and I have tried to avoid unnecessary overhead in that library)

2020-12-23T17:56:46.392800Z

Thank you for explanation, that makes sense.

2020-12-23T18:05:04.393Z

Pretty minor nitpick but > Protocols can't be variadic this isn't true is it?

(defprotocol X
  (foo [this] [this n]))

(foo
  (reify X (foo [_] 3)))
;;;3 
(foo
  (reify X (foo [_ n] n))
  6)
;;; 6

seancorfield 2020-12-23T18:13:09.393300Z

Variadic: & args -- they can have multiple arities.

2020-12-23T18:14:47.393500Z

Ohhhh, gotcha

seancorfield 2020-12-23T18:14:49.393700Z

But in next.jdbc the multi-arity wrappers exist to provide default argument values. Mostly (foo x y) means (foo x y {}). But there's no point in declaring multiple arities of protocols for that since all implementations would need to be provided when reifying it.

seancorfield 2020-12-23T18:15:30.394100Z

If the implementations were likely to be different for different arities, then yes, you'd definitely want explicit multiple arities in the protocol itself.

seancorfield 2020-12-23T18:16:40.394500Z

There are other reasons for wrapping protocols: you can't instrument a protocol function so you need wrappers for those, as I recall.

borkdude 2020-12-23T18:41:59.395900Z

@seancorfield I wonder why not:

user=> (defprotocol Foo (bar [_]))
Foo
user=> (var? #'bar)
true

popeye 2020-12-23T18:46:58.398200Z

Hi Team, I am new to clojure , I was debugging some production code (which has reduce inside reduce.).. Can some one guide me how can I debug clojure code in a best way?

seancorfield 2020-12-23T18:49:59.400900Z

https://clojure.atlassian.net/browse/CLJ-2109 does not explain why... 😞

clyfe 2020-12-23T18:50:19.401100Z

That's a broad question; try https://github.com/gfredericks/debug-repl

2020-12-23T18:51:01.401500Z

there’s a debugger in cider and one in cursive (maybe others but those are the ones I’ve used). But honestly I hardly ever use them and don’t miss them. Typically the best approach is to break up complicated code in smaller functions, and use the repl to check the individual parts. I also very frequently use timbre/spy to print out intermediate results in threaded parts of code.

👍 1
seancorfield 2020-12-23T18:52:24.401900Z

If that codebase is running on Clojure 1.10, you could add tap> calls in various places and then use add-tap to capture/log the "tap"'d values.

👍 1
seancorfield 2020-12-23T18:53:05.402100Z

The nice thing about tap> is that you can leave it in production code and it does "nothing" unless you have an active add-tap listener in place (since you can remove-tap when you're done).

seancorfield 2020-12-23T18:53:59.402300Z

But, yeah, mostly the recommended way to work is to debug these things locally via the REPL (connected to your editor) and focus on small functions.

popeye 2020-12-23T19:02:03.402500Z

Does reduce inside reduce is same as for loop inside for loop?

clyfe 2020-12-23T19:06:35.405200Z

There was an article going at length about using "-foo" in protocols and providing fn wrappers "foo" but I can't find it now 😞. Read it ~5 years back. CLJS does this extensively:

(defprotocol IIterable
  (-iterator [coll]))

popeye 2020-12-23T19:11:58.405400Z

Thanks team for response

borkdude 2020-12-23T19:16:52.406800Z

I was looking into the implementation of source because I have my own implementation in sci/babashka, but this relies on location information which I might want to get rid off some day. So I took a closer look at clojure.repl/source and figured it's a bit too straightforward in reading the source. E.g. it can't deal with aliases used in functions without throwing:

(ns foo.core
  (:require [clojure.string :as s]))

(defn foo []
  ::s/foo)
user=> (source foo.core/foo)
Execution error at user/eval277 (REPL:1).
Invalid token: ::s/foo

borkdude 2020-12-23T19:21:27.407800Z

Part of me wishes you could just parse any Clojure form without any namespace / alias context, but for the source function that doesn't even matter: it's only interested in the string it successfully parsed, not the form itself.

borkdude 2020-12-23T19:24:13.408300Z

This could potentially be fixed with (binding [*reader-resolver* resolver] ..), I'll try that

clyfe 2020-12-23T19:28:11.408400Z

All I found is this thread: https://groups.google.com/g/clojure/c/YwhOGCWquIM/m/bLC1YYGxe8MJ

clyfe 2020-12-23T19:28:31.408600Z

Gist: "Recently the received wisdom has been: protocols are a low-level implementation detail. Actual APIs should be built with normal functions that call the protocol methods."

1
borkdude 2020-12-23T19:29:54.409100Z

That works. Let me know if an issue / patch for this is welcome... (cc @alexmiller)

borkdude 2020-12-24T08:48:57.422800Z

I see there is already any issue for it: CLJ-2359. I found it through ask.

borkdude 2020-12-23T19:31:50.409400Z

This fixed worked:

(if (= :unknown *read-eval*)
              (throw (IllegalStateException. "Unable to read source while *read-eval* is :unknown."))
              (binding [clojure.core/*reader-resolver*
                        (reify clojure.lang.LispReader$Resolver
                          (currentNS [_] 'user)
                          (resolveClass [_ _] 'class)
                          (resolveAlias [_ sym] 'alias)
                          (resolveVar [_ _] 'var))]
                (read read-opts (java.io.PushbackReader. pbr))))

seancorfield 2020-12-23T19:40:25.409600Z

@popeyepwr For basic questions, you'll find #beginners a much more welcoming space. Folks there have opted in to spend plenty of time with folks who are new to Clojure.

2020-12-23T19:45:38.410Z

thx @seancorfield: i remember reading about the tap> mechanism in the release notes back then, but completely forgot about it 🙂

seancorfield 2020-12-23T19:51:09.410200Z

tap> is awesome 🙂

clyfe 2020-12-23T19:53:37.410400Z

My 6th sense says taps were added to deal with dynamic bindings being hijacked; like trying to debug a macro in cljs prints into the compiler output instead stdout because *out* is hijacked for that purpose.

dgb23 2020-12-23T20:02:35.415900Z

Popeye I would recommend you read Programming Clojure, or Brave Clojure. I found it is more practical to go through a comprehensive introduction. The question is answered by the concepts of recursion, seq functions, function composition. These things require a bit of a mental shift if you’re used to imperative programming, so it’s very beneficial to open a REPL and follow through increasingly more complex examples, while doing some explorations yourself. The REPL is the best teacher I found.