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

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

Thanks a lot

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

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])

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