Fork me on GitHub
#beginners
<
2022-03-10
>
aratare10:03:18

Hi there, I'm migrating a project from lein to deps at the moment and I was wondering if it's possible to have aliases inherit from other aliases? For example, if I have a dev alias with all my dev-related deps, is it possible to further have a server-dev alias that inherits all the stuff from the dev alias? Thanks in advance.

Ferdinand Beyer11:03:03

This is currently not possible

Ferdinand Beyer11:03:15

I usually work around that by writing a very simple Makefile for often used commands, as calls to the clojure CLI tend to be a bit cryptic. e.g. make test will invoke clojure -M:test:test/run etc

aratare11:03:56

Ah I see. That's a shame. I really love the simplicity of CCLI compared to lein but it comes with a tradeoff I guess. In the meantime, I've figured out a way to go about this, which is to make different aliases and combine them when I run the project. So basically a dev and server aliases and just use them together. Works very well in my case 😄

Ferdinand Beyer11:03:04

Yes, I do the same. E.g. test for things to run tests, dev for repl development, maybe things like cljs when I need Clojurescript build support etc. Still, it can get tricky to remember when to use -M or -X or -T , so I like my Makefiles to unburden me from that 🙂

1
Ferdinand Beyer11:03:57

I think tools.deps has a different goal than Leiningen. It is not a build tool, but focuses on building classpaths and running commands on top of this. Probably good to keep it simple.

aratare11:03:58

Yep one of the reason I wanted to move away from lein is because my project.clj has gotten a tiny bit too big and complicated.

aratare11:03:12

Thanks a lot for all the helps 😄

👍 1
practicalli-johnny12:03:35

Aliases can be used together, :dev:test:runner and their configuration merged. This provides composition of configuring which is far simple than the complexities involved with inheritance of aliases (as with OO languages, composition is far cleaner approach than Inheritance) For examples of aliases, take a look at https://github.com/practicalli/clojure-deps-edn

Ferdinand Beyer12:03:00

@U05254DQM I think @U013F1Q1R7G is aware of that and is using multiple aliases together 🙂

sheluchin15:03:09

What's the shortest way to generate [{1 1} {2 2} ...]?

Ben Sless15:03:01

(mapv (fn [i] {i i}) (range n)) , I think

sheluchin15:03:52

Some short way to have it generate a lazy infinite sequence?

Alex Miller (Clojure team)15:03:13

you asked for a vector, which is never lazy

👍 2
Ben Sless15:03:23

replace mapv with map and remove n from range

Ben Sless15:03:19

what do you plan to do with that sequence?

sheluchin15:03:47

Generating mock data for testing. Keeping Spec out of it for now.

sheluchin15:03:37

Is there some way to combine map literals with the likes of iterate to do it? Something like {:x (iterate inc 0)} to produce a seq of maps with an increasing :x?

dpsutton15:03:08

(take 4 (iterate (fn [m] (update m :x inc)) {:x 0})). but that’s more clumsy than just the obvious (map (fn [x] {:x x}) (range)

👍 1
sheluchin15:03:43

Definitely is. Should Spec be used to generate test data but for the simplest of cases?

Alex Miller (Clojure team)15:03:11

spec is a tool, use it if it's useful

dpsutton15:03:53

yeah. think in terms of your problem and how you can solve it. Making your own data or using spec’s generators are two different avenues you can take to get there. Don’t think in terms of the right answer but what you want to accomplish

Alex Miller (Clojure team)15:03:55

spec generators are a bad tool to generate exhaustive input, but are a good tool (usually) to generate random increasingly "large" inputs

Alex Miller (Clojure team)15:03:18

and separate from either of those are "examples" (classic unit tests)

sheluchin15:03:20

Bad for exhaustive inputs? I thought Spec was commonly used for generative testing (where exhaustive inputs sound natural), although I haven't touched generative testing myself yet... I just stick with unit tests for the most part.

sheluchin15:03:00

Anyhow, thanks for the input, everyone.

Alex Miller (Clojure team)15:03:57

spec generators will give you random inputs so whether they are exhaustive depends on the size of the potential value space

Alex Miller (Clojure team)15:03:11

and how many values you generate :)

Alex Miller (Clojure team)15:03:19

in the limit they're the same I guess, but either the number of samples covers the space (in which case exhaustive is more efficient) or it doesn't (in which case spec's randomly more complex sampling is probably better)

Alex Miller (Clojure team)15:03:11

nothing stopping you from doing some of all of these of course

sheluchin15:03:03

Yes, that makes sense. Whether its exhaustive is defined by the problem space, not the tool 🙂 thank you for the nuance, @U064X3EF3.

James Amberger16:03:22

Hi, what’s accepted way to println x and produce x instead of nil?

andy.fingerhut16:03:34

(do (println x) x) should do it

andy.fingerhut16:03:40

or a let with x as the last form

James Amberger16:03:30

What if evaluating x is expensive? I guess the (let [y x] (println y) y) would solve that

delaguardo16:03:12

(doto x (println))

dpsutton16:03:29

that’s a worry in macro expansion not in regular code usage. your (let [y x] ...) is equivalent to just using the original binding x

James Amberger16:03:49

What if x isn’t a binding though, what if it’s (naive-fibonacci-generator 10000) ?

solf17:03:42

both let and delaguardo solution using doto will evaluate the argument once

solf17:03:09

(btw, I learned something new with the doto solution! thanks @U04V4KLKC)

delaguardo17:03:55

btw, it is also very useful for injecting "debug logs" into -> flow

(-> 42
  (do-something useful)
  (doto (println))
  (do-something else))

🤯 1
🧠 1
oddsor18:03:00

Also not necessary to wrap println in parens if you’re experiencing parens-fatigue 😊

(-> 42
  (do-something useful)
  (doto println)
  (do-something else))

jumar20:03:10

It's also possible to use doto println for thread-last macro but it's a bit more verbose

(-> 42
  (do-something useful)
  (#(doto % println))
  (do-something else))

parens 1
👍 1
Hao Liang16:03:25

Hi, I tried to perform a FileChannel/Open on a local file, like this:

(FileChannel/open (.toPath f)
                    (into-array OpenOption [StandardOpenOption/READ
StandardOpenOption/WRITE
StandardOpenOption/CREATE])))
When I tried to evaluate the form, I got an FileSystemException like:
Unhandled java.nio.file.FileSystemException
   /Users/lianghao/Documents/a.w3i: Operation not permitted
 UnixException.java:  100  sun.nio.fs.UnixException/translateToIOException
        UnixException.java:  106  sun.nio.fs.UnixException/rethrowAsIOException
        UnixException.java:  111  sun.nio.fs.UnixException/rethrowAsIOException
UnixFileSystemProvider.java:  182  sun.nio.fs.UnixFileSystemProvider/newFileChannel
          FileChannel.java:  298  java.nio.channels.FileChannel/open
          FileChannel.java:  357  java.nio.channels.FileChannel/open
                  base.clj:    9  clj-w3x.io.base/file-chan
                  base.clj:    8  clj-w3x.io.base/file-chan
                      REPL:   27  clj-w3x.io.base/eval16427
                      REPL:   27  clj-w3x.io.base/eval16427
             Compiler.java: 7181  clojure.lang.Compiler/eval
             Compiler.java: 7136  clojure.lang.Compiler/eval
                  core.clj: 3202  clojure.core/eval
                  core.clj: 3198  clojure.core/eval
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  667  clojure.core/apply
                  core.clj: 1977  clojure.core/with-bindings*
                  core.clj: 1977  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  218  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  217  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  833  java.lang.Thread/run
I was using emacs + cider on a macbook. But everything was ok when I tried to evaluate the same code using Intellij + cursive,

Hao Liang16:03:59

I was using leiningen. It seems that the exception only occurs when I used a cider nrepl. I get no exception when I tried to connect an running repl in cider.

ghadi16:03:26

my guess is that not all programs can write to ~/Documents due to macOS security settings

ghadi16:03:42

emacs+cider might not be allowed in System Preferences, but IntelliJ is?

solf16:03:32

Yeah, I think that’s the issue

solf16:03:03

I’m also using emacs on a macbook and when I try to access a new folder, I get an OSX prompt asking me if I want emacs to be able to access that directory

solf16:03:16

Like this:

Hao Liang16:03:24

Thank you both.🙂 I’ll explore macOS security settings.

solf16:03:03

Try navigating to the folder/file you want to write to using emacs, it should trigger the popup

Hao Liang17:03:52

@U7S5E44DB Emacs opened the file, but the opened file was blank.

Hao Liang17:03:19

Didn’t trigger the popup.

solf17:03:43

Try writing something and saving the file

Hao Liang17:03:39

Emacs told me the file was written, but I tried to reopen the file and it became blank again.😕

solf17:03:51

Hum, that doesn’t sound right

Hao Liang17:03:59

And I tried to provide full disk access to emacs in Security and Privacy, but it still didn’t work.

solf17:03:23

maybe… restart emacs? 😅

solf17:03:49

I don’t know if you need to restart the program to update it’s access rights

Hao Liang17:03:17

I have restarted emacs after update it’s access rights.

solf17:03:02

It can’t read/write any file in Documents?

Hao Liang17:03:04

Seems it can write, but can’t read.

Hao Liang17:03:39

I wrote something in the new file, and the file was saved successfully.

solf17:03:03

and you can see what you wrote using something else than emacs? like cat

solf17:03:26

I wonder if it’s a file format issue, w3i seems to be a warcraft file

solf17:03:54

Maybe try again with clojure, with the full access rights it might work now

Hao Liang17:03:56

But I can’t see what I wrote if I reopen it in emacs.

Hao Liang17:03:14

I tried text file, still the same.

solf17:03:15

The last thing I can think of, but it’s just a workaround, is to start clojure on the terminal

solf17:03:32

and then connect to the running clojure process using CIDER

solf17:03:43

that way it won’t be using emacs access rights

Hao Liang17:03:15

Yes, it works if I connect to a running nrepl using CIDER.

solf17:03:26

Sorry, can’t help more

solf17:03:43

There’s many ways to install emacs on osx, I personally use brew install --formula emacs-mac

solf17:03:11

you might want to try it. It has some osx-specific patches

Hao Liang17:03:18

That’s ok, thanks a lot for your help,

Hao Liang17:03:17

I installed emasc as a standalone application, since I was not familiar with brew.

Hao Liang17:03:27

Finally I found the solution here: https://emacs.stackexchange.com/questions/53904/why-cant-i-list-the-contents-of-desktop-on-macos-using-dired. Besides emacs, I should provide full disk access rights to /usr/bin/ruby. Another way to solve the problem is simply move the files outside ~/Documents. 🙂

Hao Liang17:03:24

Thanks again for all the help.

🎉 1
James Amberger17:03:01

namespaced keywords are really hurting my brain

James Amberger17:03:39

I’ll provide example asap sorry

Yosevu Kilonzo22:03:12

Hello! What functions should I look into or what is a functional/idiomatic way to find a specific size? For example if I want to find {:id 6} , do I have to use 3 nested loops since there are 3 levels of lists?

[{:id "a",
  :colors
  [{:name "blue", :sizes [{:id 1} {:id 2}]}
   {:name "green", :sizes [{:id 3} {:id 4}]}]}
 {:id "b",
  :colors
  [{:name "black", :sizes [{:id 4} {:id 6}]}
   {:name "white", :sizes [{:id 7} {:id 8}]}]}] 

tschady22:03:24

checkout https://github.com/redplanetlabs/specter . YMMV. Maybe not idiomatic, but definitely terse and fast.

👍 1
hiredman23:03:46

(for [m [{:id "a",
          :colors
          [{:name "blue", :sizes [{:id 1} {:id 2}]}
           {:name "green", :sizes [{:id 3} {:id 4}]}]}
         {:id "b",
          :colors
          [{:name "black", :sizes [{:id 4} {:id 6}]}
           {:name "white", :sizes [{:id 7} {:id 8}]}]}]
      [k v] m
      :when (= k :colors)
      m' v
      [k' v'] m'
      :when (= k' :sizes)
      m'' v']
  m'')

craftybones02:03:28

I am not sure if you want the sizes or the entity that contains the colors. Depending on that problem you can have different approaches

craftybones02:03:21

If you only want the {:id 6} then you can do the following

(def data [{:id "a",
  :colors
  [{:name "blue", :sizes [{:id 1} {:id 2}]}
   {:name "green", :sizes [{:id 3} {:id 4}]}]}
 {:id "b",
  :colors
  [{:name "black", :sizes [{:id 4} {:id 6}]}
   {:name "white", :sizes [{:id 7} {:id 8}]}]}])

(def xform (comp (mapcat :colors) (mapcat :sizes) (filter #(= 6 (:id %)))))

(into [] xform data)

craftybones02:03:44

But I’m guessing you want the entity. In which case, you could still write a function that answers if a size is present among a list of sizes and filter on that

Yosevu Kilonzo15:03:17

Thanks all, looking through these responses and I’ll check out specter too @U1Z392WMQ!

Yosevu Kilonzo15:03:47

@U8VE0UBBR. That is definitely helpful for filtering sizes! I need to find a specific size by id e.g. only return the {:id 6} and return it and stop iterating.

craftybones15:03:51

You are welcome

tschady16:03:02

with specter: (select [ALL :colors ALL :sizes ALL #(= 6 (:id %))] data)

👍 1