beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Ritchie Young 2020-12-14T01:30:27.153500Z

I’m having trouble understanding Java interop. I was trying to convert this expression from the Java docs into Clojure but it’s not working so I’m obviously getting it wrong:

FileSystems.getDefault().getPath("logs", "access.log");
My best effort was:
(.getPath (java.nio.file.FileSystems/getDefault) "logs" "access.log")
Which earns me:
; eval (root-form): (.getPath (java.nio.file.FileSystems/getDefault) "logs" "...
; (err) Execution error (ClassCastException) at cli.core/eval1683 (form-init9547531439919407953.clj:49).
; (err) class java.lang.String cannot be cast to class [Ljava.lang.String; (java.lang.String and [Ljava.lang.String; are in module java.base of loader 'bootstrap')
Any help getting me unstuck would be appreciated.

Dane Filipczak 2020-12-14T02:04:00.154100Z

(.getPath (java.nio.file.FileSystems/getDefault) "logs" (into-array String ["access.log"]))

Dane Filipczak 2020-12-14T02:05:12.154800Z

https://clojure.org/reference/java_interop#_vararg_methods “Java vararg methods treat the trailing varargs parameter as an array. They can be invoked from Clojure by passing an explicit array in place of the vargs.” you are def not the first to get bitten by this : )

Ritchie Young 2020-12-14T02:24:41.156Z

I’m glad I asked. I would have been there forever figuring that one out. Thanks very much, @dane.email.

2020-12-14T02:40:53.156400Z

the official guide on interop is very short and does mention this, by the way https://clojure.org/reference/java_interop#_vararg_methods

alexmiller 2020-12-14T03:18:34.156900Z

There is a longer faq entry btw

👍 1
alexmiller 2020-12-14T03:19:29.157100Z

https://clojure.org/guides/faq#varargs

alexmiller 2020-12-14T04:12:37.157600Z

Probably should link those up

Jim Newton 2020-12-14T11:11:42.161900Z

I have a macro which expands to lots of concentric (let [x# ~x] ...) constructs. When I look at the macro expansion I have lots of lets with the exact same symbol such as (let [value_19667__auto__ value_19667__auto__] ...) , in this case I could check in my macro and just omit the let (let [a b] ...) where (= a b) , and eliminate the let. Is this a redundant optimization? will the clojure compiler do this optimization for me?

Jim Newton 2020-12-15T10:01:50.222100Z

OK, thanks. in this case I don't need a general purpose code walker, because the lets are begin generated by my own macro, so I know their limited form. So a very limited optimized-let macro is completely sufficient for my needs.

Jim Newton 2020-12-14T11:12:27.162600Z

certainly the expanded macro is more humanly readable, if I expand to code eliminating this useless let.

Jim Newton 2020-12-14T11:12:50.163Z

(defmacro optimized-let [[a b] c]
  (if (= a b)
    c
    `(let [~a ~b] ~c)))

Jim Newton 2020-12-14T11:29:59.163400Z

sorry if that question doesn't make sense...

Ben Sless 2020-12-14T11:40:28.163500Z

It looks like the compiler doesn't optimize this for you. The JIT might, later. You can write a tree walking function or use meander to perform the inlining

Ben Sless 2020-12-14T11:44:16.163700Z

I wrote something similar about a month ago, you can look https://github.com/bsless/contextual/blob/master/src/contextual/impl/let.clj#L130

Jim Newton 2020-12-14T12:35:16.164500Z

Is there a way to write a unit test for a function defined by (defn- ...) ? certainly it is a good idea to test internal function. right?

bronsa 2020-12-14T12:36:06.164900Z

you can access private functions by var

bronsa 2020-12-14T12:36:23.165400Z

instead of (ns/private-f you can do (@#'ns/private-f

1
Jim Newton 2020-12-14T12:39:38.166100Z

do I have to use the real ns name, or can I use an abbreviation?

bronsa 2020-12-14T12:40:14.166300Z

you can use an alias

1
2020-12-14T16:29:46.170300Z

in general, clojure's compiler doesn't tend to optimize things (with a few notable exceptions like locals clearing)

2020-12-14T17:30:37.173600Z

Hi, what the best way to filter the first large maps contains in a list or vector? Do I have to use a loop and acc or filter + predicate is possible? Eg. Turn this collection of maps

(def mymap '({:name "Susan", :id "3", :age "20", :weight "120", :Cool true, :height "48"}
             {:name "Bob", :id "2", :age "23", :weight "90", :Cool false, :height "50", :parent "yes"}
             {:name "John", :id "1", :age "21", :weight "150", :Cool true, :height "45", :parent "yes"}
             {:name "Ben", :id "4", :age "20", :weight "100", :Cool true, :height "43"}))
and return {:name "Bob", :id "2", :age "23", :weight "90", :Cool false, :height "50", :parent "yes"}

dpsutton 2020-12-14T17:32:32.174300Z

can you rephrase your question? "filter the first large maps contains in a list or vector?". You have a collection of maps and you want to filter them?

dpsutton 2020-12-14T17:34:16.174400Z

if you're looking for the map who's name is "Bob" you can

(filter (comp #{"Bob"} :name)
  '({:name "Susan", :id "3", :age "20", :weight "120", :Cool true, :height "48"}
    {:name "Bob", :id "2", :age "23", :weight "90", :Cool false, :height "50", :parent "yes"}
    {:name "John", :id "1", :age "21", :weight "150", :Cool true, :height "45", :parent "yes"}
    {:name "Ben", :id "4", :age "20", :weight "100", :Cool true, :height "43"}))
just filter the records and take the first

dpsutton 2020-12-14T17:34:48.174600Z

or use some

(some (fn [x] (when (= "Bob" (:name x)) x))
  '({:name "Susan", :id "3", :age "20", :weight "120", :Cool true, :height "48"}
    {:name "Bob", :id "2", :age "23", :weight "90", :Cool false, :height "50", :parent "yes"}
    {:name "John", :id "1", :age "21", :weight "150", :Cool true, :height "45", :parent "yes"}
    {:name "Ben", :id "4", :age "20", :weight "100", :Cool true, :height "43"}))
{:name "Bob",
 :id "2",
 :age "23",
 :weight "90",
 :Cool false,
 :height "50",
 :parent "yes"}

2020-12-14T17:37:23.174800Z

also, minor note, it's almost always better to use [{.. .. } ...] instead of '({... ...} ...) - we typically only use ' in clojure when we need unresolved symbols, which is not the case here

👍 2
bnstvn 2020-12-14T17:47:47.175100Z

> also, minor note, it’s almost always better to use `[{.. .. } ...]` instead of `'({... ...} ...)`  - we typically only use `'` in clojure when we need unresolved symbols, which is not the case here is this always the case, even if you know beforehand you only need sequential access?

2020-12-14T17:51:38.175300Z

both style wise and performance, there's zero advantage to using ' to create lists

👍 1
2020-12-14T17:52:15.175600Z

it's a lispism, and I think people do it because they are used to it from other lisps? it usually isn't needed in clojure

dpsutton 2020-12-14T17:52:19.175800Z

and this is just for literals just to be clear

2020-12-14T17:52:47.176Z

right - none of this makes any sense if you aren't talking about data literals

2020-12-14T17:52:54.176200Z

but even when constructing a collection, if you aren't writing a macro you probably shouldn't be using lists

2020-12-14T17:53:39.176500Z

(nb. lazy-seqs as returned by map, filter, etc. are not lists)

dpsutton 2020-12-14T17:54:30.176700Z

and if you're wondering one reason, is that the quote can do way more than just what you intend ("just give me the list of these things")

foo> '(1 2 (+ 1 2))
(1 2 (+ 1 2))
foo> [1 2 (+ 1 2)]
[1 2 3]
foo> 

👍 1
2020-12-14T17:58:34.176900Z

In fact, i want to be able to search and filter the largest hashmap so by its size and not its content

dpsutton 2020-12-14T17:59:16.177100Z

size being the number of key value pairs?

2020-12-14T17:59:30.177300Z

(->> mymap (sort-by count) last ...)

2020-12-14T18:02:07.177800Z

Thank both for the advices.

2020-12-14T18:02:13.178Z

oops - that first should be last (fixing...)

2020-12-14T18:04:23.178300Z

For the eg., I use list instead vector because it's like that that the precedent function output in code. But manually, I always a vector of hashmaps.

2020-12-14T19:49:03.179900Z

How can I update an element in a map that is itself a map. e.g.

(let [foo {:bar 5 :quax {:abc 6 :def 7}}]
  ; I want to update :def in foo
  )
?

2020-12-14T19:52:00.180400Z

@qmstuart update-in is the function that does that

2020-12-14T19:53:01.181Z

user=> (update-in {:bar 5 :quax {:abc 6 :def 7}} [:quax :def] inc)
{:bar 5, :quax {:abc 6, :def 8}}
it takes a one arg function that updates the value at that path

2020-12-14T19:53:36.181700Z

thank you! thats perfect

2020-12-14T19:53:45.181900Z

if you don't always know the path, or need to update multiple leaves, then clojure.walk helps

2020-12-14T20:02:25.184700Z

So I don't have a functino for the last param, just a value.

(update-in memory [:memory location]
                (Integer/parseInt (->> (map (fn [m v] (if (= \X m) v m)) mask (pad v))
                                       (apply str)
                                       2)))
It errors because float can't be converted to a function, because the Integer/parseInt returns a number (which it evaluates eagerly?), Im guessing, and its trying to call that number as a function?

dpsutton 2020-12-14T20:05:45.185Z

read the docstrings of update-in and assoc-in

dpsutton 2020-12-14T20:07:15.186300Z

but if you just use assoc-in here it will work. but understanding the differences will greatly ease your Clojure studies

tanzoniteblack 2020-12-14T20:13:05.187500Z

https://github.com/plumatic/plumbing is this still the generally recommend library for creating computation graphs in clojure? I'm looking at improving the start up time of our API, which pre-loads of a bunch of metadata. A number of the metadata caches depend on each other, and while I could manually create a dependency order to parallelize the startup efforts, but a graph type approach that auto-computes the parallelization would be more flexible & maintainable.

2020-12-14T20:16:40.187800Z

thank you

seancorfield 2020-12-14T20:30:49.187900Z

The function can take an arbitrary number of arguments but the value being updated is passed as the first argument. /pedant

seancorfield 2020-12-14T20:31:25.188200Z

dev=> (update-in {:bar 5 :quax {:abc 6 :def 7}} [:quax :def] + 42)
{:bar 5, :quax {:abc 6, :def 49}}

👍 1
2020-12-14T20:59:02.188700Z

💯

seancorfield 2020-12-14T21:10:26.188900Z

@qmstuart ^ FYI

dgb23 2020-12-14T21:59:35.189400Z

This is the first time I come across this concepts, thank you for sharing!

Mark 2020-12-14T22:04:12.190600Z

Hey folks, is there a simple way to implement a lazy seq where the nth term is defined as f(n-1)?

phronmophobic 2020-12-14T22:07:28.191Z

(->> (range) (map dec))

dpsutton 2020-12-14T22:12:48.192600Z

(iterate f initial-value)

dpsutton 2020-12-14T22:13:01.192800Z

> Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects

🙌 1
Mark 2020-12-14T22:14:31.193100Z

perfect

phronmophobic 2020-12-14T22:26:47.193400Z

whoops. this should probably be

(->> (range) (map dec) (map f))