Thanks a lot
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
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 ...)
bad site design / UI, but top quality info that's well organized once you figure out how it's meant to be navigated
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]))
(defn something [s]
(if-let [match (re-matches #"^(persons name) *\S+" s)]
(second match)
s))
(something "persons name *ABC12345") => "persons name"
(something "persons name * ABC12345") => "persons name * ABC12345"
Pretty sure it can be done more succinctly using a better capturing group and re-find
Not really better or more idiomatic than what you have here,
(flatten [previous-link links next-link])
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).Perfect @kslvsunil, thanks.
I prefer your flatten
solution that mine. 👍
how do I do get the same result as (rest (rest something))
without looking so stupid? 😄
(nthrest something 2)
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)
This <https://clojuredocs.org/clojure.core/nthrest>
talks about it more detail, in particular the difference between nthrest
and drop
, with drop
being lazy.
Thanks <3
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
~'< reactive
~@body
`(rum/defc
~sym
~'< reactive
~@body))
I can't do the if
inside because then the if gets added to the output...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. :)
well after spending another 30 min on this I feel stupid...
(let [definition `(rum/defc
~sym
~'< reactive
~@body)]
(if docstring
(concat
(take 2 definition)
[docstring]
(drop 2 definition))
definition))
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]]]
> 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
(->> [[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])
of course you can throw vec
on the end if the result needs to be a vector
isn't that what i did above?
my apologies - my eyes blur and I lose cognitive function when I see "flatten" in code
no worries, yours is much cleaner
oh I see now, you put the filtering logic inside the tree-seq child predicate
kind of
yes, i prefer your way, shows that i lack experience =)
@noisesmith mind enlightening why flatten is that bad? :)
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.
(unless the sequential data is inside a hash-map or whatever to dead-end the recursive flatten)
flatten is extremely slow and tends to encourage / facilitate poor design
Got it, time to play with tree-seq and clojure.walk
Thank you all, great help and discussion
(->> [[[1 2 3]] [[12 13 14] [10 50 60]]]
flatten
(partition-all 3))
(this would return a lazy sequence)
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]]]]])
;; => ([1 2] [12 13 14] [10 50 60 70] [1])
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?
user=> (into [] cat [[[1 2 3]] [[12 13 14] [10 50 60]]])
[[1 2 3] [12 13 14] [10 50 60]]
doesn't work for deeply nested elements, 2 levels is the max
Yes, if the input sequence has deeper nesting, that won't work. The original question doesn't say anything about that, though.
true, it's just for me the deep nesting is in the context of flatten
also unintended behavior for vectors on the first level
(into [] cat [[3 4 5] [6 [7]]])
=> [3 4 5 6 [7]]
Whether it's unintended depends on what you need. 🙂
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 () => {
// 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 successDoes what I was looking for. There’s little documentation on the cap function. What does it do?
Actually I should have used (apply concat coll), works as well