beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Mitch 2020-09-16T00:18:53.264600Z

I think I found the answer https://gist.github.com/swannodette/4fc9ccc13f62c66456daf19c47692799:

Simply add a new compiler option :infer-externs true to your compiler config. Now when you build your project you will get a new file in your :output-dir named inferred_externs.js. When you do an advanced build, this externs file will be used.
So, your inferred_externs should be in the :output-dir of your advanced build. Therefore, you might need to check it in to source control

Jack Arrington 2020-09-16T02:06:16.266400Z

Is the only reason to using (testing...) in clojure.test for self-documentation? Any reason to use them over just splitting tests into individual (deftest..) blocks?

Cory 2020-09-16T02:14:12.267400Z

you can define deftest scoped let blocks, which can be very useful. which is to say the relation between them is block contextual.

Cory 2020-09-16T02:15:08.267800Z

tests are still just functions and you can compose them as such 😎

Jack Arrington 2020-09-16T02:18:34.270Z

Hm, I'm not sure I know what you mean. Sure I could do:

(deftest my-test
  (let [some-var ...]))
but I could do that same thing with testing:
(testing "something something"
  (let [some var ...]))
I guess I'm asking, what's the point of the testing macro at all when there is deftest?

Jack Arrington 2020-09-16T02:20:33.270400Z

https://clojuredocs.org/clojure.test/testing is what I'm referring to, just to make sure we're on the same page πŸ™‚

dpsutton 2020-09-16T02:49:33.272900Z

(t/deftest foo (t/testing "this could describe what you want" (t/is (= 1 2))))
(foo)

FAIL in (foo) (form-init14706425140162863748.clj:16)
this could describe what you want
expected: 1
  actual: 2
    diff: - 1
          + 2
it can add context and descriptions in error messages, in addition to serving as documentation in the test definitions

πŸ‘ 2
seancorfield 2020-09-16T03:07:23.274Z

I find testing very useful when I have a deftest for a function and want to logically group assertions based on what scenarios they are checking.

seancorfield 2020-09-16T03:09:23.274800Z

See, for example, this test for next.jdbc's get-connection protocol implemented on various data types https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc/connection_test.clj#L88

πŸ‘ 2
seancorfield 2020-09-16T03:09:38.275200Z

^ @mail985 is that a useful example?

sb 2020-09-16T08:10:08.276800Z

how to possible export the full clojurescript project into a single *.js file? (I saw somewhere on github.. but I don’t know where.. could you help me?)

Lu 2020-09-16T08:23:28.277400Z

What tool are you using to build your cljs?

Lu 2020-09-16T08:24:29.278600Z

When you build the js bundle for your prod env all the cljs goes into a js file

Josef Richter 2020-09-16T08:32:45.279400Z

hi, I have a checkbox in a form and I was wondering whether there was a nicer syntax for the submit action here, please:

[:input {:type :checkbox
             :checked checked
             :onchange "this.form.submit()"}]

baptiste-from-paris 2020-09-20T08:16:10.145700Z

If you have a button you don’t need to use this.form.submit fn

Josef Richter 2020-09-20T08:19:32.145900Z

@baptiste-from-paris thank you. I had a button before. But this is a checklist, so I need a checkbox πŸ™‚

baptiste-from-paris 2020-09-20T08:20:48.146100Z

if you have a button you don’t need any js, just put a required attribute on the checkbox and the user has to choose at least one checkbox

Josef Richter 2020-09-22T21:39:16.398700Z

@baptiste-from-paris I need to send a post request to the backend every time the user changes the state of the checkbox. it’s a todo list. I am actually not submitting a whole form. it’s a β€œform” that includes just two elements: one input type=hidden + the checkbox (previously a button type=submit).

Josef Richter 2020-09-16T08:33:29.279500Z

I mean replacing "this.form.submit()" with just :submit or something like that…?

Jack Arrington 2020-09-16T11:44:16.281300Z

Check out shadow-cljs. There is a #shadow-cljs channel here too

rmxm 2020-09-16T12:28:20.282400Z

Hi quick question, can I reference a function in another package without requiring it? Basically I just want to hold references to functions, but would love to avoid requiring it, I can reference using full package.

Mitch 2020-09-16T12:35:48.284800Z

Depending on your use-case, you might just use quoted vars (something like #'reagent.core/ratom ) and then just make sure that the symbol resolves properly before using it

jsn 2020-09-16T12:57:50.285200Z

@roguas why do you want to avoid requiring it, though?

Marcus 2020-09-16T13:34:40.285700Z

hi! When do you use maps and when do you use records?

rmxm 2020-09-16T13:37:25.285800Z

trying to refactor some code that was dynmically loading symbols, so its a step in direction towards require

rmxm 2020-09-16T13:40:56.286Z

I think records are mostly handy when it comes to protocols. So that you can have a generic way of processing different types of records.

Mitch 2020-09-16T13:43:26.286200Z

Accessing fields in records is faster, too, so they are useful when performance is critical

Marcus 2020-09-16T14:04:36.286400Z

@roguas @mitchell_clojure ok thanks! Do you also use it to increase readability of the code? As it adds a bit more structure than maps. Or do you think maps with spec provides the same clarity?

Mitch 2020-09-16T14:18:27.286600Z

I think the general approach is to just use maps with spec. The idea behind this is that the shape of your map is "self-documenting" in a sense. For example {:name "Mitch" :employee-number "1020.12"} is descriptive enough, without going through all of the OOP ceremony of creating decorators (when we want to accrue data) or interfaces (when we only want to act on a subset of the keys).

Marcus 2020-09-16T14:37:49.287300Z

Ok. Great. Then I think we all have the same understanding. Protocols for polymorphism on type, plain maps for data and maps with spec for expressing composability and other rules when needed.

😁 1
j 2020-09-16T14:38:41.288Z

I'd like to make a function that increases each element of a vector by its position in the vector, with position starting at 1. For instance [0 1 2] becomes [1 3 5], or [3 4 5] becomes [4 6 8]. Here's my current attempt: (map + [3 4 5] (range 1 (inc (count a)))) I was wondering if there's a more idiomatic way of doing this? Thanks!

2020-09-16T14:39:41.288100Z

(map-indexed #(+ (inc %1) %2) [3 4 5])

j 2020-09-16T14:42:54.288400Z

Thanks @delaguardo! I didn't know about map-indexed. Why do we need a second argument %2 and where does its values come from?

2020-09-16T14:43:52.288600Z

map-indexed expect first argument to be a function of two arguments where first β€” position of element in collection, second β€” element

j 2020-09-16T14:44:36.288800Z

Ah! I understand now! Thanks again!

2020-09-16T14:45:07.289Z

in anonymous function written via #( dispatch macro you can refer to first argument as % or %1 , second β€” %2 etc.

2020-09-16T14:45:40.289200Z

there is also %& to make a function of variable amount of arguments

πŸ‘ 1
j 2020-09-16T14:46:13.289500Z

I didn't know about %&! That'll be very helpful!

Marcus 2020-09-16T14:47:43.290900Z

I have two local clojure projects A and B (using lein). What is the best way to call functions in B from A?

jsn 2020-09-16T14:48:27.291Z

(map-indexed (partial + 1) [3 4 5]) πŸ™‚

βœ”οΈ 1
Marcus 2020-09-16T14:48:49.291200Z

Thanks! Appreciate your feedback! πŸ™‚

2020-09-16T14:51:06.291400Z

^ even better) cool)

j 2020-09-16T14:51:09.291600Z

Woah!

2020-09-16T14:51:28.291800Z

The best way depends on your goals and desires. One way is to run the command lein install in the root directory of project B, which if successful will create a JAR file for selected files of project B and write it into your $HOME/.m2 directory. Then add that artifact as a dependency in project A's project.clj file, and then require project B's namespace(s) containing the functions you want to call into project A's code.

2020-09-16T14:52:16.292Z

If you later change code in project B, that will have no effect on the contents of that JAR file, unless you do lein install again to create another JAR file.

j 2020-09-16T14:53:30.292200Z

What is happening there with partial? I see that it takes a function + and a variable amount of args.

walterl 2020-09-16T14:53:49.292400Z

If you want to you "live" changes in B, in A, what I've done before is add B as a dep of A, and then (from A's root):

mkdir checkouts
ln -s /path/to/B checkouts/

jsn 2020-09-16T14:54:53.292600Z

it creates a function that calls + with args 1 and any other args provided to it

2020-09-16T14:55:25.292800Z

let me give you a fishing rod ) https://clojuredocs.org/clojure.core/partial

j 2020-09-16T14:55:46.293Z

What are the args in this case? first arg is 1, second arg is index position? , third arg is [3 4 5]?

2020-09-16T14:56:15.293400Z

third is an element from that position

jsn 2020-09-16T14:56:16.293600Z

the 3rd arg is the value at that position, yes

j 2020-09-16T14:57:37.293900Z

oh! I have it backwards! Second arg is [3, 4, 5], and third arg is value at that position?

jsn 2020-09-16T14:57:58.294100Z

no

jsn 2020-09-16T14:58:18.294300Z

see the map-indexed docs perhaps?

j 2020-09-16T14:58:42.294500Z

ok, thanks @jason358, I'll read it again!

jsn 2020-09-16T14:59:19.294700Z

my example can be rewritten as follows:

user=> (def f (partial + 1))
#'user/f
user=> (map-indexed f [3 4 5])
(4 6 8)
user=>

jsn 2020-09-16T14:59:55.294900Z

so, (partial + 1) returns a function, map-indexed then calls that function for each vector element

j 2020-09-16T15:00:21.295100Z

Ahh! I see now, that's why @delaguardo said "third is an element from that position"

j 2020-09-16T15:00:49.295300Z

Thank you both so much! πŸ™ I learned a lot just now

2020-09-16T15:02:04.295500Z

🍻

marshall 2020-09-16T15:54:26.295700Z

clojure tools deps lets you use local paths in your dependency definitions https://clojure.org/guides/deps_and_cli#_using_local_libraries

marshall 2020-09-16T15:54:42.295900Z

so you can reference other local projects via their path in your filesystem

mpemer 2020-09-16T15:58:57.296300Z

this is awesome - good stuff and great community

πŸ‘ 1
2020-09-16T16:40:56.297500Z

does a struct-map have an ordering?

kkruit 2020-09-16T16:43:10.299100Z

Hey all, I'm trying to get the local timezone on my server. I'm running centos in docker and when i run date from bash i get Wed Sep 16 10:41:44 MDT 2020 but when I try to get my timezone in the repl it looks like this. (ZoneId/systemDefault) => #object[java.time.ZoneRegion 0x45024d57 "UTC"]

kkruit 2020-09-16T16:44:41.300100Z

I'm not sure how to narrow down what the cause might be. eg docker, repl, java, centos, clojure

2020-09-16T16:46:21.300500Z

definitely not clojure

2020-09-16T16:46:48.301500Z

but if I may make a suggestion, go in the other direction, get everything on your server in utc

dpsutton 2020-09-16T16:46:48.301600Z

that function will do this https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/TimeZone.html#getDefault() > Gets the default TimeZone of the Java virtual machine. If the cached default TimeZone is available, its clone is returned. Otherwise, the method takes the following steps to determine the default time zone. Use the user.timezone property value as the default time zone ID if it's available. Detect the platform time zone ID. The source of the platform time zone and ID mapping may vary with implementation. Use GMT as the last resort if the given or detected time zone ID is unknown. (System/getProperty "user.timezone") -> "UTC" for me

2020-09-16T16:47:20.302Z

very likely docker

kkruit 2020-09-16T16:49:22.304300Z

okay, thanks guys. @dpsutton mine also returns "UTC" so I think that gives me somewhere to start looking. Thanks!

2020-09-16T16:49:31.304900Z

definitely docker

dpsutton 2020-09-16T16:49:54.306Z

yeah. i'm confused. my system timezone is definitely not UTC but running a repl locally is giving me utc

2020-09-16T16:50:04.306200Z

but consider running in utc, it is good and common practice

2020-09-16T16:50:21.306700Z

are you on a mac?

kkruit 2020-09-16T16:50:35.307300Z

no, i'm on windows

dpsutton 2020-09-16T16:50:36.307400Z

interesting, but running just bare clj i get America/Chicago. yes on a mac

dpsutton 2020-09-16T16:51:35.308500Z

i apologize. i ran that in a project's repl that explicitly sets {:jvm-opts ["-Duser.timezone=UTC"]}. otherwise it is picking it up correctly

kkruit 2020-09-16T16:53:47.310Z

haha maybe that's what i'm doing

kkruit 2020-09-16T16:54:24.310400Z

yeah, that's it LOL

kkruit 2020-09-16T16:54:29.310600Z

thanks!

dpsutton 2020-09-16T16:54:49.310900Z

but as @hiredman mentioned, that's probably actually a good thing

kkruit 2020-09-16T16:56:07.311800Z

is there another way to get the system's timezone? I need to do reporting and it makes more sense for the end user if it show's the servers timezone

kkruit 2020-09-16T16:56:51.312500Z

I usually operate in UTC and that's fine but in this instance I need the systems timezone

2020-09-18T09:22:17.029800Z

(Timezone/getDefault)

dpsutton 2020-09-16T16:57:37.313Z

its common for the server to do everything in UTC and let the client format those times into local timezone

πŸ‘ 1
Nazar Trut 2020-09-16T17:29:29.313600Z

How do i initialize a sequence by another sequence. So kinda like seq1 = seq2

dpsutton 2020-09-16T17:31:12.315200Z

this normally isn't necessary. can you write in pseudocode what you are trying to do?

dpsutton 2020-09-16T17:33:09.316300Z

and the reason this isn't usually necessary is because the sequence you are using is probably immutable.

Nazar Trut 2020-09-16T17:38:42.318100Z

So what im trying to do is remove "not" in an element, So the user has to enter '(not (not x)) for example, and my function needs to remove both of the "not". So I want it to remove the first not first so then it will be 'not 1', then it will remove the last not in that element, but i have to update my expr after removing the first "not"

Nazar Trut 2020-09-16T17:38:45.318300Z

(defn remoove-nots
  [expr]
  (loop [x 1]
    (when (>= x 0)
      (if (= fourth-test (first expr))
          (expr (nth expr 1))                               ;;HERE i want to update expr

        )
      (recur (- x 1))
      )

    )

  )

dpsutton 2020-09-16T17:49:54.318900Z

can't quite follow what's going on here but just use expr wherever you want. you haven't changed it.

Nazar Trut 2020-09-16T17:50:19.319100Z

I want to chagne it tho

dpsutton 2020-09-16T17:50:41.319800Z

you want to change it twice then? sounds like you want to change the result of your change?

Nazar Trut 2020-09-16T17:50:45.320Z

So instead of holding '(not(not x)), i want it to hold '(not x) after goinmg through once

Nazar Trut 2020-09-16T17:51:00.320200Z

yeah i wanna change it twice

dpsutton 2020-09-16T17:51:34.321100Z

oh, you probably want to add that to your loop and recur. (loop [e expr x 1] ... (recur (rest e) (inc x))) something like that

Nazar Trut 2020-09-16T17:55:00.321500Z

what does (rest e) do?

seancorfield 2020-09-16T18:02:56.322500Z

@ntrut Returns the rest of the sequence that is in e. I think in your case you want (second e) instead to turn (not (not x)) into just (not x)?

dpsutton 2020-09-16T18:12:58.323800Z

Yeah sorry. That was just an example function that returns a β€œmodified” version of expr (I called it e because shadowing can get confusing)

Nazar Trut 2020-09-16T18:41:32.324300Z

Yeah i want to turn (not(not x) into (not x)

Nazar Trut 2020-09-16T18:41:59.324600Z

but i cant figure out how to update expr in my case

bronsa 2020-09-16T18:42:39.324800Z

clojure data structures are immutable

bronsa 2020-09-16T18:42:44.325100Z

you don't make changes to data

bronsa 2020-09-16T18:42:47.325300Z

you return new instances of transformed data

Nazar Trut 2020-09-16T18:43:29.326100Z

aaaa i see

bronsa 2020-09-16T18:44:10.327300Z

I recommend you maybe read a few introductory articles/guides on clojure, it's probably a much different paradigm than what you're used to and it will be really hard to hack your way through it in the dark

Nazar Trut 2020-09-16T18:44:17.327500Z

So i need to create a seperate function that returns a new instance of my transformed data and have that loop twice

Nazar Trut 2020-09-16T18:44:58.328Z

I have read a few things but its different once i gotta start coding projects haha

2020-09-16T19:40:00.329Z

If you are looking for a kind of map with ordering guarantees on the key/value pairs, there are several linked from the Clojure cheatsheet in the "Maps" section: https://clojure.org/api/cheatsheet

2020-09-16T19:40:15.329200Z

I do not know whether a struct-map has any ordering guarantees.

2020-09-16T19:41:01.329400Z

I don't know if struct-map's are considered deprecated, but typically record or plain maps are much more commonly used.

2020-09-16T19:41:44.329600Z

thanks for the insights

2020-09-16T19:41:54.329800Z

invoking sorted? suggests that it doesn’t

2020-09-16T19:42:40.330Z

sorted? might only return true for a few sorted collection types built into Clojure. Third party ones, which several of the ones linked from the Cheatsheet are, I have no idea what they return when passed to sorted?

πŸ‘ 1
Marcus 2020-09-16T20:18:47.330300Z

@andy.fingerhut @clojurians-slack100 @marshall thank you very much. I will check out these variants. :)

πŸ‘ 1
2020-09-16T22:04:42.332200Z

I wonder if you memoize a function foo of 3 arguments, and then use it in a map expression, mapping (partial foo first-fixed-arg initial-but-changing-second-arg) onto a collection, will your desire for memoization survive the use of partial ?

2020-09-16T22:05:48.332300Z

It seems like it should to me. If foo is memoized, (partial foo ...) is creating another function that calls foo, which is still memoized.

2020-09-16T22:08:31.332500Z

by which I mean, if foo is memoized, it should not become unmemoized by having other functions call it, and (partial foo ...) is just another function that calls foo . (partial foo ...) does not cause any changes in foo's behavior.

2020-09-16T22:10:34.332700Z

In a small test scenario, it should be straightforward to verify this by having foo do println or some other kind of debug output, to see when it is being called versus not.

1
jsn 2020-09-16T22:13:42.333Z

@fappy in case it's not clear: partial doesn't immediately call foo, so nothing is immediately memoized. Only when the function returned by partial is called, only then foo is called (and that call is memoized)