beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
seancorfield 2021-05-23T02:15:45.249200Z

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

raspasov 2021-05-23T02:24:58.249800Z

Watch all Rich Hickey talks.

Lukas 2021-05-23T06:39:55.250800Z

Thanks a lot

indy 2021-05-23T07:19:00.254900Z

Thanks Sean and Rakyi, I read Rich’s explanation and couldn’t quite follow the train of thought. How does “sequences being read from left and being fed from right” along with the "sequence functions like map, filter and having variadic args" influence the choice of having the sequence as the last arg?

indy 2021-05-23T08:17:50.255900Z

Particularly why does “sequences being read from left and being fed from right” influence (map f sequence) , (filter pred sequence) not being (map sequence f) , (filter sequence pred). We could still chain them the same way we do it for other collections (-> sequence (map f) (filter f)) .

indy 2021-05-23T08:22:07.256100Z

Oh okay maybe it is this bit "partial allows for direct parameterization as above" that majorly affected this decision. But I rarely do something like this ((partial map inc) '(1 2)). Can't think of many sequence functions that have more than one arg before the source.

practicalli-john 2021-05-23T09:13:44.260800Z

I think I need some clojure regex help. I'd like to remove a pattern of characters toward the end of a string. For example "persons name ABC12345" would return "persons name". If there is a space after the in the string the pattern would not be removed. I've been experimenting with re-seq, replace and re-pattern but havent found the right regex. Also, any good articles on using boundaries in regex would be useful, as I suspect defining boundaries might help

2021-05-24T16:41:45.323400Z

a note: there's no such thing as a "clojure regex" - on the jvm clojure uses java regex, in cljs clojure uses javascript regex - this is the best cross platform regex guide I've found and I return to it often: http://www.regular-expressions.info/ - it has great comparison of the featureset / syntax of various regex systems (from grep, ed, sed, java, perl, c ...)

2021-05-24T16:42:36.323700Z

bad site design / UI, but top quality info that's well organized once you figure out how it's meant to be navigated

2021-05-23T09:34:34.263500Z

Hi! If I want to concat 3 items: 1. A simple hash map {:url url :label "Previous"} 2. A vector of hash maps [{:url (str url item) :label (str item)}{:url (str url item) :label (str item)}...] return by a for loop 3. A simple hash map {:url url :label "Previous"} Is there a better way - more idiomatic - to do this than to surround simple maps with a vector like I do now?

(let [previous-link {:url url :label "Previous"}
      links (for [item (range 1 (inc page-number))]
              {:url (str url item) :label (str item)})
      next-link {:url url :label "Next"}]
  (concat [previous-link] links [next-link]))

indy 2021-05-23T10:11:08.263600Z

(defn something [s] 
   (if-let [match (re-matches #"^(persons name) *\S+" s)]
     (second match)
     s))

indy 2021-05-23T10:11:53.263800Z

(something "persons name *ABC12345") => "persons name"
(something "persons name * ABC12345") => "persons name * ABC12345"

indy 2021-05-23T10:16:02.264Z

Pretty sure it can be done more succinctly using a better capturing group and re-find

indy 2021-05-23T10:30:51.264200Z

Not really better or more idiomatic than what you have here,

(flatten [previous-link links next-link])

indy 2021-05-23T10:32:59.264400Z

What would've been idiomatic is to have something like

(->> some-list
     (cons el2)
     (push el3))
But push doesn't exist for lists since it's O(n).

2021-05-23T13:00:51.264700Z

Perfect @kslvsunil, thanks. I prefer your flatten solution that mine. 👍

Azzurite 2021-05-23T13:10:00.265400Z

how do I do get the same result as (rest (rest something)) without looking so stupid? 😄

dharrigan 2021-05-23T13:13:21.265800Z

(nthrest something 2)

dharrigan 2021-05-23T13:14:15.266100Z

user=> (def something [1 2 3 4 5 6 7 8])
#'user/something
user=> (rest (rest something))
(3 4 5 6 7 8)
user=> (nthrest something 2)
(3 4 5 6 7 8)

dharrigan 2021-05-23T13:16:02.266700Z

This <https://clojuredocs.org/clojure.core/nthrest> talks about it more detail, in particular the difference between nthrest and drop, with drop being lazy.

Azzurite 2021-05-23T13:20:00.266900Z

Thanks <3

Azzurite 2021-05-23T13:22:49.268Z

and another thing I've been trying to solve for a while but can't do it, is there a way to get rid of the duplication in this macro code:

(if docstring
  `(rum/defc
     ~sym
     ~docstring
     ~'&lt; reactive
     ~@body
  `(rum/defc
     ~sym
     ~'&lt; reactive
     ~@body))
I can't do the if inside because then the if gets added to the output...

kennytilton 2021-05-27T11:34:46.014300Z

That looks brittle. How about using ~@ splicing with the value (when docstring [docstring])? ~@ on nil will not inject a nil or anything else. I think. :)

Azzurite 2021-05-23T14:03:01.268400Z

well after spending another 30 min on this I feel stupid...

(let [definition `(rum/defc
                    ~sym
                    ~'&lt; reactive
                    ~@body)]
  (if docstring
    (concat 
      (take 2 definition)
      [docstring]
      (drop 2 definition))
    definition))

dabrazhe 2021-05-23T14:20:48.271200Z

How can I transform this structure in the flat vector of vectors, without loosing the inner vectors and the order? [[[1 2 3]][[12 13 14][10 50 60]]]

2021-05-24T16:58:11.324500Z

> doesn't work for deeply nested elements, 2 levels is the max if you actually need this, tree-seq is probably the easy way to do it

(-&gt;&gt; [[1 2 3] [[4 5 6]] [[[7 8 9]]]]
     (tree-seq coll? identity)
     (filter #(and (vector? %)
                   (number? (first %)))))
([1 2 3] [4 5 6] [7 8 9])

2021-05-24T16:58:47.324700Z

of course you can throw vec on the end if the result needs to be a vector

Ivan Koz 2021-05-24T16:58:57.324900Z

isn't that what i did above?

2021-05-24T16:59:42.325200Z

my apologies - my eyes blur and I lose cognitive function when I see "flatten" in code

Ivan Koz 2021-05-24T17:00:17.325500Z

no worries, yours is much cleaner

2021-05-24T17:01:10.325800Z

oh I see now, you put the filtering logic inside the tree-seq child predicate

2021-05-24T17:01:25.326Z

kind of

Ivan Koz 2021-05-24T17:01:55.326200Z

yes, i prefer your way, shows that i lack experience =)

indy 2021-05-24T17:26:47.327700Z

@noisesmith mind enlightening why flatten is that bad? :)

2021-05-24T17:29:14.328100Z

In clojure it's an antipattern because it's so common to use vanilla sequential structures to hold data, and a flatten (as in clojure.core/flatten) call in your processing eliminates this structure.

2021-05-24T17:29:51.328300Z

(unless the sequential data is inside a hash-map or whatever to dead-end the recursive flatten)

2021-05-24T17:30:17.328500Z

flatten is extremely slow and tends to encourage / facilitate poor design

indy 2021-05-24T17:32:30.329700Z

Got it, time to play with tree-seq and clojure.walk

dabrazhe 2021-05-24T21:27:11.340700Z

Thank you all, great help and discussion

kennytilton 2021-05-23T14:56:50.271400Z

the "else" above is (identity %). My imagination fails me: how will that be different than %? Otherwise, your approach seems fine.

kennytilton 2021-05-23T15:02:21.271600Z

In a world like Common Lisp where sort is destructive we could use when sorter sort X knowing X will either get sorted or sail on untroubled as is, but not so with clojure.

indy 2021-05-23T15:04:38.271800Z

(-&gt;&gt; [[[1 2 3]] [[12 13 14] [10 50 60]]]
      flatten
      (partition-all 3))

indy 2021-05-23T15:06:31.272Z

(this would return a lazy sequence)

Ivan Koz 2021-05-23T16:02:22.272400Z

for variable size vectors

(defn my-flatten 
  [coll] 
  (filter (comp number? first) 
          (tree-seq (fn [[x :as c]] 
                        (and (sequential? c) 
                             ((complement number?) x))) 
                    seq
                    coll)))

;; (my-flatten [[[1 2]][[12 13 14][10 50 60 70]] [] [[[[1]]]]])
;; =&gt; ([1 2] [12 13 14] [10 50 60 70] [1])

seancorfield 2021-05-23T16:36:17.272800Z

@kslvsunil A lot of those sequence functions have transducer-producing arities: (map f), (filter pred) etc.

seancorfield 2021-05-23T16:37:10.273Z

As you get more familiar with Clojure, this argument ordering will start to make more sense and you’ll come to understand what Rich means.

indy 2021-05-23T16:43:20.274900Z

Okay Sean. But transducers were introduced much later. Will probably have to reread the motive a few times.

seancorfield 2021-05-23T16:45:49.275100Z

Those transducer arities were only possible because of the argument ordering conventions.

indy 2021-05-23T16:50:07.277700Z

Yeah, very interesting. Can’t imagine transducers composing easily without this arg ordering of sequence functions. Not sure if it was extreme foresight or if we just got lucky. :)

indy 2021-05-23T16:58:24.281100Z

Or more like a good design decision allowing the easy evolution and birth of transducers

1👍
dabrazhe 2021-05-23T17:57:08.285500Z

The goal is to transform to a flat vector like this, [[1 2 3] [12 13 14] [10 50 60]] but it can’t be partitioned , because there be can be varied maps instead of numbers. Aren’t there simpler solutions eg with zipmap?

flowthing 2021-05-23T17:58:01.285700Z

user=&gt; (into [] cat [[[1 2 3]] [[12 13 14] [10 50 60]]])
[[1 2 3] [12 13 14] [10 50 60]]

1👍
Ivan Koz 2021-05-23T18:11:54.286200Z

doesn't work for deeply nested elements, 2 levels is the max

flowthing 2021-05-23T18:13:33.287300Z

Yes, if the input sequence has deeper nesting, that won't work. The original question doesn't say anything about that, though.

Ivan Koz 2021-05-23T18:14:46.287500Z

true, it's just for me the deep nesting is in the context of flatten

Ivan Koz 2021-05-23T18:23:43.289Z

also unintended behavior for vectors on the first level

(into [] cat [[3 4 5] [6 [7]]])
=&gt; [3 4 5 6 [7]]

flowthing 2021-05-23T18:27:54.290500Z

Whether it's unintended depends on what you need. 🙂

Dieter 2021-05-23T18:41:58.294200Z

Hi, can someone help to transform a async/await js example into cljs? I use shadow-cljs, installed an npm package and required it in a namespace (package beckhoff-js https://www.npmjs.com/package/beckhoff-js ). The example is:

const AdsClient = require('beckhoff-js');

const options = {
  target: {
    host: "172.16.21.6",
    netID: "5.9.36.191.1.1",
    amsPort: 801
  }
};

const client = new AdsClient.default(options);
client
  .connect()
  .then(async () =&gt; {
    // Read a tag
    const bTest = await client.readTag(".bTest");
    console.log('bTest value is', bTest);
  });
The cljs version so far:
(ns app
  (:require [reagent.core :as r]
            [reagent.dom :as rdom]
            ["beckhoff-js" :as adsclient]))

(comment

  (def client (adsclient/default. #js{:target #js{:host "127.0.0.1" :netID "172.26.0.1.1.1" :amsPort 851}}))

  (.connect client)) 
Creating the client instance works fine. The .connect returns #object[Promise [object Promise]], but the browser console returns an error: Uncaught (in promise) TypeError: net_1.Socket is not a constructor... I had a look at cljs js promise interop and tried some things with .then, but no success

dabrazhe 2021-05-23T20:38:01.296400Z

Does what I was looking for. There’s little documentation on the cap function. What does it do?

dabrazhe 2021-05-23T20:43:27.298100Z

Actually I should have used (apply concat coll), works as well