This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-31
Channels
- # aws-lambda (4)
- # beginners (152)
- # boot (19)
- # cider (45)
- # cljs-dev (14)
- # clojure (54)
- # clojure-dev (33)
- # clojure-greece (11)
- # clojure-italy (4)
- # clojure-nl (8)
- # clojure-norway (2)
- # clojure-russia (6)
- # clojure-sg (1)
- # clojure-spec (1)
- # clojure-uk (40)
- # clojure-ukraine (5)
- # clojurescript (40)
- # community-development (13)
- # component (8)
- # core-async (3)
- # cursive (25)
- # data-science (11)
- # datomic (13)
- # duct (1)
- # emacs (2)
- # events (16)
- # figwheel (3)
- # fulcro (53)
- # graphql (2)
- # jobs (5)
- # jobs-rus (1)
- # juxt (10)
- # leiningen (4)
- # off-topic (82)
- # other-languages (5)
- # portkey (3)
- # protorepl (13)
- # re-frame (22)
- # reagent (15)
- # ring-swagger (4)
- # shadow-cljs (69)
- # spacemacs (7)
- # specter (16)
- # sql (13)
- # vim (5)
- # yada (2)
i would have expected ["foo" ""]
from (str/split "foo/" #"/")
maybe im used to how python does this.
I find it odd i can't figure out a way to verify is a string is a valid path where i could write a to.
Like, it seems your best bet is to try to write the file and catch the exception.
the java File object has .exists
and .isDirectory
that you can use
Yea. But i want to know if the program can write to a location. its getting kind of tricky. "/" => nope "A" => yep "valid/path/foo" => yep "invalid/path/foo" => nope "valid/path/" => nope (no file name)
@drewverlee maybe something like this?
+user=> (defn valid-file? [f] (let [file ( f)] (or (.isDirectory file) (.exists (.getParentFile file)))))
#'user/valid-file?
+user=> (valid-file? "/etc/passwd")
true
+user=> (valid-file? "/etc/passwd-not-on-disk")
true
+user=> (valid-file? "/etc-no-such-dir/passwd-not-on-disk")
false
oh, now that you clarify, make it (and (not (.isDirectory file)) (.exists (.getParentFile file)))
oh - that still doesn't work for "A"
although, there might be other reasons you can’t write to the file
like out of space or permissions
Yea. I agree, checking everything would be somewhat involved and mean a lot of trade offs. I was just curious about the basic stuff concerning file paths
This is what i have so far:
(s/def ::valid-file?
(s/and
#(not (str/blank? %))
(s/or
:can-write #(.canWrite (io/file %))
:in-current-dir #(nil? (.getParentFile (io/file %)))
:valid-file-path (s/and
#(.isDirectory (.getParentFile (io/file %)))
#(not (str/blank? (last (str/split % #"/"))))))))
the last condition doesn't wok because of how string split works.
it looks like this one meets your spec
+user=> (defn valid-file? [f] (let [file ( f)] (and (not (.isDirectory file)) (.exists (.getParentFile (.getCanonicalFile file))))))
#'user/valid-file?
+user=> (valid-file? "A")
true
+user=> (valid-file? "A/B")
false
+user=> (valid-file? "project.clj")
true
Thanks! Ill admit i felt like getCanonicalFile might have been the missing piece to making this easy, but i couldn't figure out what it did. Thane name and docs seem to assume some background i dont have.
the canonicalFile is absolute and has a parent (even if it's implicit in the original) while the raw file is dependent on your pwd
i don’t know a lot about your use case, but it seems like that spec definition might cause headaches later
my intuition is that if some data conforms to a spec, it should always conform to the spec
oh - yeah, that's highly contingent isn't it
and not depend on things like what’s on the filesystem where the spec code is being run
Why would that limitation be helpful.
It will make that spec somewhat meaningless for generators, i admit.
it makes the spec function not pure anymore
which means that if you, for example, use spec to check conformance on a build server and it fails
then you don’t know if it’s a problem with the data you’re checking or if there’s some setup problem on your build server
in other words, it means that any code that uses that spec now has the implicit argument of the filesystem
and it’s generally harder to test implicit arguments
Sure. But the thing im trying to verify depends on the state of the filesystem.
My plan was to verify inputs with it, so that i could give better feedback to the user.
yea, it does seem like a useful thing to specify, that your function expects a writable file path
or, as another example, your function expects an active socket connection or something
ok, nevermind. seems like a useful thing to do
i wonder if there’s a convention for saying your spec has implicit arguments
I'm glad you brought that up, its worth thinking about.
like ::valid-file?!
is protobuf a good choice for clojrue or not? is anyone using it? https://github.com/ghaskins/clojure-protobuf
@rcustodio What problem are you trying to solve that you think protobuf might be (part of) the solution for?
Between arbitrary processes? Or between Clojure processes?
I've found transit very useful - it's faster than edn, and supports all the clojure data types, and the customization for extra types is first class and local instead of implicit and global
I guess it will be between clojure processes only, idk if the project will adopt others Lang in the future
If you're doing Clojure-to-Clojure for now, I'd stick to EDN for the first version, then switch to Transit and see if it improves performance etc.
For EDN, there are other language readers/writers. I assume there are for Transit too?
It's a pass-through-able as Protobuf 🙂
http://blog.cognitect.com/blog/2014/7/22/transit -- https://github.com/cognitect/transit-clj --
"Transit is supported in Ruby, Python, Clojure, JavaScript, Java."
yeah, transit might have better multi language support than edn, and it's definitely better performing and more flexible compared to using pr-str and custom reader tags or whatever
a lot easier to use, at least
is it good practice to set up infinite "go" processes to listen to channels?
e. g. (go (while true (some-func (<! input-channel)))
i tried (close! channel)
but it doesn't seem to help.
a closed channel won't interrupt a loop that reads from it - if you read from a closed channel it instantly returns nil, and the consumer should be checking for that
cool, i can do that
(go (when-some [v (<! input-channel)] (some-func v) (recur)))
i'm traversing a graph asynchronously. i need a way of keeping track of visited nodes. would an atom be a suitable ref type for that?
that seems reasonable, yeah - just be aware that if you hit conflicts (two or more threads trying to alter the value at once), you will end up seeing retries. You'll want to make sure that the inevitable retries don't break things with your core.async usage, and if performance matters at all you probably want to do batching of some sort, or limit the recursion branches somehow
i think it should be because i don't need - i don't need any kind of transaction logic
with something like graph traversal, the retries can easily be more expensive than the navigation is, making the parallel version slower than the single threaded synchronous one
no kidding
it's faster to look up a value in a hash and put it in a set, than it is to look up a value in a hash, create a mutation checkpoint, attempt to put the value in a hash, check the checkpoint, and either retry or return the new value
but I don't know what your data looks like or how it is acquired, only testing will tell you what performs best
it's urls. it's a scraping project.
@michael740 specifically the big problem is with parallelizing something like that is that the lookups of nodes in the graph is so much faster than the mutating transactions that the larger the number of threads, the larger of your percentage of time is spent on automatic retries, so the slower the whole thing gets
OK - with URLs that's different - try different parallelisms to see what has the best throughput though
so i send a request, parse the html for more links to fetch, go fetch them in parallel, ...
also you could check out memoize - if you memoize the "get links from URL" function that might simplify some of your logic and eliminate retries
but then again there's no predicate to see if a memoize has seen an arg already, so that's probably a bad choice
if i have a get-links-from-url
function and i've seen the url already, i think i just want to move on.
right, that's fair - and I checked and memoize is just doing a swap! anyway
cool, cool
i appreciate your help!
is there an 'identity' transducer? I'm thinking (map identity) if nothing else.
thnks!
hi, im new to programming, but i want to start from clj, plz give me some advice where to start ?
my suggestion would be to start here: https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/
best condensed guide http://riemann.io/clojure.html
if you go with sicp
please take reaaaaaally small bites, especially if you're new to programming
make sure you get what you're reading
@seancorfield and @noisesmith I’m checking out about transit to communication, now to validate data is schema a good choice? (https://github.com/plumatic/schema)
Yes, definitely look at clojure.spec
first as that is "built-in" to Clojure 1.9.
Since I’m still developing my app, it will be out march or later, is it wise to use clojure 1.9?
Alex said they plan no changes between Beta 4 and "gold", except to fix any regression bugs introduced.
We're using Beta 3 in production, with Beta 4 in testing right now.
(we've had 1.9 in production since one of the first Alpha builds)
if you're going to do sicp, there's a really great online version http://sarabander.github.io/sicp/html/index.xhtml
Hey friends, I’m aware of destructuring with keys which allows me to write
(defn foo [{:keys [foo bar baz]} some-map]
(println foo bar baz))
I was wondering if the inverse of destructuring, (restructuring?) exists or if I’m just googleing the wrong name or if this is even a good idea at all.
I’m thinking it would look like this
user> (let [foo "foo" ;; This let is just used to create lexically scoped values
bar "my-bar"
baz [1 2 3]]
(->map {:keys [foo bar baz]})) ;; or some other syntax, I didn't put a ton of thought into it.
=> {:foo "foo" :bar "my-bar" :baz [1 2 3]}
Am I totally missing something?I have a gist for that
Update: Just found https://stackoverflow.com/questions/8999794/map-restructuring and https://gtrak.wordpress.com/2012/06/11/separation-of-concerns-or-let-map-birth-of-a-clojure-macro/
thanks @noisesmith, it looks like it captures all locals, which isn’t quite what I was looking for but this looks super cool.
it’s easy to combine it with select-keys
(or just write a macro that expands to a map with a key for each symbol)
great, I see what you’re saying now. Thanks @noisesmith
(ins)user=> (defmacro restructure [syms] (into {} (for [sym syms] [(keyword (name sym)) sym])))
#'user/restructure
(ins)user=> (def a 0)
#'user/a
(ins)user=> (def b 1)
#'user/b
(ins)user=> (let [c 2] (restructure [a b c]))
{:a 0, :b 1, :c 2}
it’s only so often you can write a macro with no quoting, heh
what's idiomatic way to name a map as argument to function I know that seq
is used for sequences (lists, vectors...)
Hello everyone!
I am playing around with clojure (and cljs) and I just found out thing (i guess the only thing) i don't like in clojure (actually, in lisp and languages without dot syntax):
It's too uncomfortable to write as you think.
Let me explain on example:
1. I have names
2. Now I sort them: names.sort
3. And take first: names.sort.first
I type synchronously with my thoughts. In Lisp (or some procedural languages as C) I should move cursor back and add another function invocation with closing bracket (oh my god!).
How did you deal with it? I am using emacs, btw (if it helps).
Sorry for my english
@non.dmitriy the answer is here: https://clojure.org/guides/threading_macros
well that's how you're used to working with it. but you want the first sorted name. (first (sorted names))
"write as you think" is pretty language specific - when I use languages that aren't lisps I have the problem that I can't write as I think
but yes, using ->
and ->>
lets you put things in the order you are more familiar with
@schmee hey, thank you! Actually, I knew about this feature. But is it common to use it everywhere?
no, using it everywhere is a bad idea
if you aren't willing to learn to write lisp, there are many great languages out there that aren't lisps - but I encourage actually taking the time to learn it
@dpsutton well, I guess my mind is completely different, because I often find myself in situation when I am typing sort before first.
@schmee are you telling me that a majority of your functions contain threading macros?
perhaps I took "everywhere" too literally - I've read really bad code that overuses -> and ->>
@noisesmith I played with Common Lisp back in school. Actually I very like the syntax (homoiconicity) but something was wrong. And today I found out what exactly. So I joined this channel to ask other people about it
my example was just saying what you want to do. i want the first name in a sorted list of names. so then it would be natural to describe it as (first (sorted names))
. but i agree i will often think the other way as well
also, don't be afraid to use let blocks instead of deeply wrapping / long chains of operations