This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-05-23
Channels
- # announcements (19)
- # babashka (6)
- # beginners (47)
- # cljs-dev (4)
- # cljsrn (3)
- # clojure (18)
- # clojure-australia (3)
- # clojurescript (50)
- # code-reviews (1)
- # conjure (16)
- # datomic (6)
- # editors (4)
- # emacs (1)
- # fulcro (10)
- # graphql (3)
- # helix (7)
- # jackdaw (10)
- # malli (1)
- # off-topic (3)
- # pathom (4)
- # sci (2)
- # shadow-cljs (39)
- # testing (3)
- # tools-deps (5)
- # vscode (1)
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
(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"
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]))
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 @UMPJRJU9E, thanks.
I prefer your flatten
solution that mine. 👍
how do I do get the same result as (rest (rest something))
without looking so stupid? 😄
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
talks about it more detail, in particular the difference between nthrest
and drop
, with drop
being lazy.
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...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))
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. :)
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]]]
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]]
Yes, if the input sequence has deeper nesting, that won't work. The original question doesn't say anything about that, though.
also unintended behavior for vectors on the first level
(into [] cat [[3 4 5] [6 [7]]])
=> [3 4 5 6 [7]]
Does what I was looking for. There’s little documentation on the cap function. What does it do?
> Does what I was looking for. There’s little documentation on the cap function. What does it do?
cat
is a transducer (https://clojure.org/reference/transducers). I like to think of it as just the cat
part of mapcat
or concat
.
> Actually I should have used (apply concat coll), works as well
Yeah, there are many ways to skin this cat (pun intended, I guess): https://web.archive.org/web/20190925191622/http://chouser.n01se.net/apply-concat/
apply concat
works, but doesn't return a vector. You can vec
it, of course, but then there's little reason to use it over into [] cat
.
If you don't actually need a vector, then you can also do either (sequence cat [[[1 2 3]] [[12 13 14] [10 50 60]]])
to get a lazy seq or (eduction cat [[[1 2 3]] [[12 13 14] [10 50 60]]])
to get an eduction, depending on what you need. Transducers are nice in that they are performant and they compose well.
But yes, apply concat
is another option, as is mapcat identity
, or mapcat seq
, etc.
> 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
my apologies - my eyes blur and I lose cognitive function when I see "flatten" in code
oh I see now, you put the filtering logic inside the tree-seq child predicate
kind of
@U051SS2EU 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
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 success