anybody know if there is a #crux channel
nvm it exists already! sweet
@mathpunk If you're using an up-to-date clojure
CLI (1.10.1.697 or later), you can use the -P
option. See http://clojure.org/releases/tools
That will just "prepare" things, i.e., download the dependencies you need and then not run anything.
does #datomic exist?
@mojitosmi If you click the ➕ next to Channels
in the left side bar, it lets you Browse channels
You can also try to just switch to a channel (control-k on Windows, cmd-k on Mac) and just start typing.
(I can't remember whether the "quick switcher" is enabled by default -- check Preferences > Advanced under Search Options
)
What's the recommended approach for dealing with dates and times in clojure? It seems like a bit of a mess. Should I stick with Java 8 APIs?
The questions ask whether you use it professionally, and then veer off and assume you do
Either use Java Time directly or a wrapper like cljc.java-time or tick
Is it possible to mix Java and Clojure to implement some complex projects? I mean here is a Clojure open-source project, I need to reconstruct it, So which is the better way? Reconstruct completely by Java or by mix Java and Clojure?
@xu20151211 You can have a Java app that loads and calls into Clojure code, and you can have a Clojure app that calls into Java code.
See https://clojure.org/reference/java_interop for some examples/background.
When we first adopted Clojure at work (a decade ago now), we used it for low-level stuff and gradually replaced parts of our legacy applications -- so we had mixed language projects, calling into Clojure. Over time we rewrote more and more of them in Clojure.
Hello, is it possible to do something like this for spec?
(s/def ::plain-coord
(s/keys :req-un [::row ::col]
:opt-un [::sheet]))
(s/def ::merged-coord
(s/and
(s/keys :req-un [::first-row ::first-col ::last-row ::last-col]
:opt-un [::sheet])
#(<= (:first-row %) (:last-row %))
#(<= (:first-col %) (:last-col %))))
(s/def ::coord
(s/or :merged (s/keys :req [::merged-coord])
:plain (s/keys :req [::plain-coord])))
Or do I have to create a plain-coord?
and merged-coord?
to do the below
(s/def ::coord
(s/or :merged-coord merged-coord?
:plain-coord plain-coord?))
Like what I really want is to be able to do something like
(s/def ::coord
(s/or ::merged-coord
::plain-coord))
but it seems like spec does not work this way :thinking_face:-P is the preferred way to do this
there is both s/merge and s/or
it's unclear to me what you want or what doesn't work
one handy (undocumented) tool for use with s/or is s/nonconforming
as it says at the top, just skip anything that doesn't apply
only the first 2 questions are required
Hmmm, I would like for :coord
to either take the the form of ::plain-coord
or ::merged-coord
in what way does it not work?
(s/def ::coord
(s/or :merged ::merged-coord
:plain ::plain-coord))
should work?Let me try that
Thanks, think that should be working! Not sure why I didn't try that just now
if you're conforming, s/or will conform with the :merged or :plain tag which you likely don't want - in that case, wrap the spec in s/nonconforming. if you're just using s/valid? then it doesn't matter
just using s/valid?
but for subsequent reference, by wrapping you mean ...
(s/def ::coord
(s/or (s/nonconforming ::merged-coord)
(s/nonconforming ::plain-coord)))
?@zackteo (s/nonconforming (s/or ...))
as I recall...
It turns the whole s/or
part into a non-conforming spec, i.e., if it matches, it returns the original data structure.
yeah, wrap the nonconforming around the s/or
it conforms with the spec but returns the original value
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/conform (s/or :int int? :str string?) 42)
[:int 42]
user=> (s/conform (s/or :int int? :str string?) "one")
[:str "one"]
user=> (s/conform (s/nonconforming (s/or :int int? :str string?)) 42)
42
user=> (s/conform (s/nonconforming (s/or :int int? :str string?)) "one")
"one"
we will probably have some kind of nonconforming or option in spec 2
I guess it also prevents similar conformance on any nested specs? (In the arms of the s/or
) Right, @alexmiller?
doesn't prevent, just ignores
it just conforms, then returns the original value
So you'd get a different result to flowing it through (s/conformer second)
(which would still preserve nested conformance and just erase the tag of s/or
)
correct
Just something to be aware if you actually need some conformed values deeper in the data (which I've needed occasionally).
You could try this: https://wiki.helionet.org/features/java You'd need to switch to https://github.com/marchrock/ring-tomcat-adapter I think. And I've never tried them.
But generally, people use VPS hosting, which I do not know of any free options
DigitalOcean, Linode, AWS, are popular options, they have things in the 5$ a month range.
I think Heroku might have a free option for MVPs and personal projects, not sure
good morning 😪
Hello, I was wondering about the difference between "first" and "peek". Would their results ever be different? Is there maybe a performance difference in some cases?
Ya, peek is given a stack, returns the last inserted element. So its LIFO. first is given an ordered collection, return the first one from its order
And it seems that peek can also be: given a queue, return the first inserted element FIFO
Basically, it does something different based on the type of coll, so just make sure you are aware what type of coll you use it with
So my trick is: You peek from a stack or queue. And Lists and Vectors are also Stacks
from the docstrings: first:
Returns the first item in the collection. Calls seq on its
argument. If coll is nil, returns nil.
peek:
For a list or queue, same as first, for a vector, same as, but much
more efficient than, last. If the collection is empty, returns nil.
Got it, thanks 👍
Hi! Would that be a good solution to replicating items in a sequence?
(fn [xs count] (mapcat #(take count (repeat %)) xs))
it works but I’m trying to see if there’s a better way.I don't know if it is better, but you could use #(repeat count %)
in place of #(take count (repeat %))
there to get the same results. Unless one is worried about optimizing run-time performance to the utmost, what you have and that small variation both seem like perfectly good ways to me.
Ah, nice, I thought repeat is a single arg function. That makes it easier to read for sure, thanks!
repeat
has 1-arg and 2-arg variants
Awesome. Thanks!
Transducer option (slightly more verbose but a bit more “decomplected”):
(let [f (fn [xs cnt]
(transduce
(comp
(map #(repeat cnt %))
(mapcat identity))
conj
xs))]
(f [1 2 3] 3))
=> [1 1 1 2 2 2 3 3 3]Nice, I’ll save it for future reference since I’m not comfortable with transducers yet. Thank you 🙂
You’re welcome 🙂
Note that peek returns the value at the insertion point (for stack usage) and for vectors that’s at the end, not the beginning
first is the correct function to use if you want the first element
hmm, why do I get a server error when trying to read a css file
(defn create-image-element [{:keys [object-number width height url]}]
[:html
[:head
[:meta {:charset "utf-8"}]
[:title " Most popular paintings from the Rijksmuseum "]
[:link {:href "public/css/styles.css", :rel "stylesheet"}]]
[:body]])
from the root , there is a styles.css in that directory
A guess would be to remove the “public/” part. To test it you’d want to try and access the css file directly in the browser.
Typically a static file server points into a directory (often called “public”), while your root directory contains all the source code.
sorry, tried it without any luck
do you have a project.clj file or a deps.edn file?
yep, that looks like this :
(defproject paintings "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "<http://example.com/FIXME>"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "<https://www.eclipse.org/legal/epl-2.0/>"}
:dependencies [[org.clojure/clojure "1.10.0"]
[cheshire "5.9.0"]
[clj-http "3.10.3"]
[ring "1.8.2"]
[compojure "1.6.2"]]
:repl-options {:init-ns paintings.core})
You said you have a public/css
directory, is that in the project root, or is it in resources/public/css
?
just public/css` in the root directory
It’s conventional to have resources/public/css
, and you may be libraries that are expecting that.
You might want to have a look at the “Static Files” section at https://learnxinyminutes.com/docs/compojure/
(I had to google that--I’ve switched from using compojure to using reitit, and I didn’t trust my memory of how compojure works.)
Maybe I need to change something then at my routes
(defroutes app
(GET "/" [] (-> (display-data)
(convert-to-hiccup)
(hiccup/html)))
(GET "/favicon.ico" [] ""))
is public
on your classpath?
yes, it working
I had to make the directory resources
and add this to my routes (route/resources "/")
:thumbsup:
except for PersistentQueue, which as designed peeks from the opposite end of its conj
(it's much more rarely used than lists and vectors though)
also, as I correct "seqs" to "lists" above - peek only works with stacks/queues, so doesn't actually work with things like lazyseq
Hi Guys, I have no experience with a clojure, I have to add a new line into the clojure logic, I have a list of strings: "a", "b", "c" etc...
I need to return true/false if the following list contains a string equal to the op-name
variable.
If the list cantains the op-name
I need to return true, otherwise false.
Could you help me with a quick snippet for this. Will appreciate that.
the normal thing is to have resources/public/css
and resources/public/js
etc. since resources is used for other things not just web assets
BTW. I will have to create this list first.
(some (set [op-name]) list-of-strings)
lemme check if that works though 😅
some
could be a useful function for you. "Returns the first logical true value of (pred x) for any x in coll," So (some (fn [x] (= x op-name)) my-list)
would return whether that list had a member equal to op-name
Thank you guys, does the list of string should be a comma separated like
(some (set [op-name]) "a","b","c")
?
commas are literally whitespace in clojure. ["a" "b" "c"]
Also available options: (list "a" "b" "c")
, '("a" "b" "c")
, (vector "a" "b" "c")
All arguably less pretty
Nice! Thank you for a quick help! Have a good day/afternoon 🙂
vector
, not vec
vec takes a coll
ah good shout. Thanks!
did make it
pure vs. referential transparency. Is it the same thing? This article is confusing: https://edward-huang.com/functional-programming/tech/programming/scala/2020/01/30/pure-function-vs-referential-transparency/
not a great article. its premise is that pure functions are a proper subset of referentially transparent functions. Then in an edit, the author says "If a function is referentially transparent, it is also pure." Probably not worth the time if the original was so off the cuff and probably good for #off-topic rather than #beginners
Thank you, I'll try it there
Hi folks - I’m a bit of a beginner, and I’m working on a project that takes a CSV file (through Java interop), does some processing on it, and exports the new file to [filename]-processed.csv
. I’m using https://github.com/clojure/data.csv/ and it works splendidly!
(with-open [reader (io/reader file-info) writer (io/writer new-file)]
(as-> (csv/read-csv reader) $
(map #(eval-line % header-info) $)
(csv/write-csv writer $)))) ; ALL THIS WORKS!
However, these are pretty big files, so the program takes about 15 seconds, and looks like the system locks up. Since I’m already using Java interop, I’d like to add a Java progress bar to show progress. However, I’m having problems wrapping my head around how I would implement it with the lazy processing above. Would it even be possible?I think you could decompose the problem into two parts: 1) calculating the progress and 2) reporting the progress. I understand you have something (ie. rendering a progress bar) in mind already for 2) above.
use reduce (over a possibly partitioned set of data) instead of just passing all the data to write-csv
checkout https://github.com/thebusby/iota
depending on what your processing needs are - sequential access is a lot slower, reducers are much faster.
(and don't use as-> when ->> will do)
For calculating progress (number of lines processed / number of lines in total), you'd need to know the number of lines in total when processing each individual line. You could perhaps make a first pass through the data to just calculate the number of lines if efficiency is not a concern; or perhaps you could figure out the number of lines to process via some other route. Then perhaps just process the data in batches matching some fraction of the total number of lines and reporting progress once per batch.
Oh, as hiredman also mentioned, you'd need to pass batches of data to write-csv for this to work, instead of trying to write the whole thing in one go.
I’ve written a defn to tell me the number of lines.
@hiredman Thanks about the as->
comment. I think I needed it at one point, now I don’t.
Hi! Is there any nice standard function for the use-case of "if expr is true, return expr otherwise return other"
(if expression
expression
(other-expression))
or
thanks 🙂
to easy
Then, perhaps something like
(doseq [batch (partition-all batch-size lines)]
(report-progress!)
(write-csv writer (map #(eval-line % header-info) batch)))
Yeah! I think doseq
is what I needed!
How would (report-progress!)
know what line we’re on, however?
Oh, right. You'd need to pass it some parameters to suit your needs.
Is there any way to get a counter on a doseq
?
`
(let [progress (atom 0)]
(doseq [batch (partition-all batch-size lines)]
(swap! progress inc)
(report-progress! (* @progress batch-size))
(write-csv writer (map #(eval-line % header-info) batch))))
Or perhaps
(doseq [[i batch] (map-indexed vector (partition-all batch-size lines))]
(report-progress! (* (inc i) batch-size))
(write-csv writer (map #(eval-line % header-info) batch)))
Thanks! I will try something like that!
In a video Hickey alludes place oriented programming (even if it's update-in-place) is bad, what problems does PLOP cause?
for one thing, it means you need to understand every function that has access to that place in order to understand the code
but as I recall he went into quite a bit of detail in that same talk
I think the main problem is "fragility"
@kaxaw75836 as a counterexample: when debugging clojure code, I can usually "capture" a value as it appears in a function, and then debug my code based on that value in isolation. In a C++ program that rarely if ever helps, and I need a stepping debugger to understand what happens to the places the function sees.
in good clojure code, what matters is the value, the place isn't my concern
This is one of my favorite clojure advantage. Even if I know this is not an exclusivity
right, even in java you can snapshot some object out of a function to play with it in test code (in c++ this probably leads to a memory leak, or accessing freed data - place problems)
@noisesmith are you referring to immutability? or abstracting the machine?, if so is no different in JS or Python?
@kaxaw75836 I'm referring to the difference between thinking about places as the building blocks of code, vs. thinking of values as the building blocks
it's different than JS or Python because most JS and Python code still works in terms of updating hidden internal state, but those are still less place-bound than c++
sorry, lost track of this yesterday I might have lost my point along the way here, but on further thought it really does come down to immutability (at least on the interface level). vectors and hash-maps do contain mutable internal state, but that's there because it has to be there, and a given object will give you back the same value every time you reference it. but, things like io streams and container types are there specifically to represent a state. that is, their utility is to provide access to something stateful, or create a stateful object over stateless internals) compare this to java / js / c++ where it's normal to have mutable private fields that actually do effect the behavior of the object, and many objects require specific initialization before usage - they are designed to mix state and value rather than separating them but I fear I've gotten too abstract here, and others might provide a better explanation than what I'm going for here (I was motivated to try answering this because I've been trying to go back to C / C++ lately but wanting to use them in a more fp way...)
@kaxaw75836 but this is a very general thing - it even applies to the difference between managing the contents of a tree of files (places) vs. data in a db (values with other values that describe their relations)
Backus's 1977 turing award lecture "Can Programming Be Liberated from the von Neumann Style?" is trying to solve the problems created by plop, so it also describes those problems to some degree
IMHO PLOP has two aspects that are worth considering. Like @noisesmith said, it decreases your facility for reasoning. Another aspect is increasing brittleness: code and data that change over time propagate changes to rigid structures around them.
talking about DBs, he mentions tables in RDBMS is also a place(bad) that creates coupling, and that documents are also a place that create coupling
@denis.baudinot right, in imperative place oriented code 90% of your code is ad-hoc inline adapters between ad-hoc data structures, this kind of thing doesn't even need to exist in clojure
@kaxaw75836 all programs have places, perhaps I picked a bad example, but this isn't a black/white thing, it's a way of guiding a design
The point is that you could use java with only immutable object and the place orientation of java is less an issue.
Clojure is not the only community that concerns itself with disentangling from PLOP. Game programmers have introduced Struct of Arrays, Data Oriented Design and Entity Component systems. They use data structures that are more relational and adaptive, mostly for performance reasons (CPU caching) but this has also a decoupling effect and generalises functionality. Frontend developers are shifting towards using frameworks like React etc., which have a clearer separation of state, data flow and rendering. The problems around PLOP seems to be unspecific to this community.
1977 wow, the summary looks pretty good high level overview will have a read
thanks for sharing!
he also is critical of lambda calculus based programming languages, because he wants a more restricted basis to make things easier to reason about
the system he describes sort of sounds like coding directly in a combinatory logic like SKI, but less bare bones, which seems kind of like a nightmare
so he also do not like Haskell which I like a lot 😢
https://crypto.stanford.edu/~blynn/compiler/ may be of interest, it is a series of blog posts writing a haskell compiler and it goes haskell -> lambda calculus -> ski, it is very cool
By hidden internal state, you mean like some reference of a object that is pass around? or the runtime?
hi what's your favorite way to do websockets or ajax in clojureland?
here's a question i've been wondering about for some time. in the java community (and others) folks will often favor so called "clean code". that can mean all sorts of things, so i'l be more specific. stuff like "one level of abstraction per function". decomposing functions into tiny helpers with "descriptive" names that hide the mechanical details of what you're doing. adding in domain concepts, in the form of function or object names, that hide the mechanical details of what you're doing. i'm in a clojure shop right now, having come from a java shop, and i'm finding that there is a high high tolerance for long functions with many levels of abstraction and few, if any, named helpers to express what you might call intent. just big expressions. stuff that would never have made it past code review at my last place. what do folks think? is there a deliberate preference for more inline, nested, low level expressions over extracted helpers with names? or is it just a tolerance thing? i'm very curious
there's a Martin Odersky talk (that i can't find right now) that expresses this well. he says, well, in scala, we have all these great abstractions and general purpose data manipulation functions (a la clojure). and so you could write a dense, multi-step transformation. but, according to Odersky, that would be a mistake because it would be too impenetrable for future maintainers.
@michael740 I would say that Clojure in general encourages small, pure functions, with good names, that isolation mutable state to the edges of the system -- but not all Clojure programmers produce such code, just like not all Java developers write "clean code".
There is no right and wrong here. http://number-none.com/blow/blog/programming/2014/09/26/carmack-on-inlined-code.html
Clojure advocates dsl which I find very close to language metaphor used in clean code
I think there is no point in putting things into defs that don’t need to be referenced. We have reader macros and a repl to evaluate/ignore things at the expression level
Structure is essential, but wether that structure is composed of function declarations is almost orthogonal to this
The "clean code" concept comes out of the culture of enterprise consultants. The clojure community is smaller, so it attracts fewer of those.
There is also something to be said of the mental overhead of naming things.
having said that, i usually write small functions, it comes naturally. But some functions are just large lists of doing things in sequence, explicitly, that are the kind of functions where keeping them large makes sense.
@denis.baudinot, as told in clean code, I find helpful to tell the intentions. Small functions help to do so
there are also many critiques of the different formulations of "clean code"
@denis.baudinot, even in the case you mention, I find helpful to explode in small local function, it helps readibility and testability . Maybe im too young in the language ...
it’s orthogonal to clojure wether a function/procedure should be large or not
you can visually structure a large function to make it nicer to read
Sorry, I dont understand why you say it is orthogonal
again, I don’t really write a lot of large functions anyways. I’m rather against the notion that there should be some kind of limitation to this
if you haven't read elements of clojure yet (I am behind the times and haven't finished it yet), I don't think it mentions "clean code" by name, but it functions to some degree as a critique of "clean code" and similar stuff
Ah ok. So we re on the same page. Rules are made to be broken
As in “has no dependency on each other”
The only thing I’ve ever used for either is cljs-ajax and sente, and I’ve never had a problem, but I also haven’t worked in large projects with multiple people or tried out a lot of libraries… so might as well bring an entire salt lick for this piece of advice 😅
But this was only a tendancy I was mentionning not a rule
i have read elements of clojure, yes. i'll revisit with that in mind
thanks
ztellman's(author of elements of clojure) last few days of tweets are him being annoyed that bob martin(author of some clean code book) exists and critiquing an exercise bob did
i can see that. bringing up "clean code" is a... hornet's nest, for sure
Ok here is a more specific follow up question: To build up application state, aka ‘load’ we usually do a whole bunch of plumbing in sequence, connect to a db, read some files, load in configuration… Should this be a large, single procedure, where the effects are explicit, in your face and the sequence of steps is clear? Or should this be composed of a abstracted, possibly data-driven configuration system? I think the first one is easier to understand and more “honest”, while the second opens up opportunities to build stuff that is about that process, which has operational benefits.
I want to read the attributes of a file and for that I am using https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#readAttributes-java.nio.file.Path-java.lang.Class-java.nio.file.LinkOption...-
like this (Files/readAttributes (io/file "file-path") BasicFileAttributes [])
but I am getting an exception error: java.lang.IllegalArgumentException: No matching method readAttributes found taking 3 args
how can I represent java varargs in Clojure?
i'll check out the twitter.
in this case you might want to use something like:
(Files/readAttributes (.toPath (io/file "file-path")) (into-array LinkOption [LinkOption/NOFOLLOW_LINKS]))
note that io/file returns a http://java.io.File but that method takes a Path
sweet! Thank you very much!
this is an interesting essay. a lot of what he seems to be concerned about would be mitigated by pure functions, if i'm understanding this correctly
> Besides awareness of the actual code being executed, inlining functions also has the benefit of not making it possible to call the function from other places. That sounds ridiculous, but there is a point to it.... > > Strictly functional functions that only read their input arguments and just return a value without examining or modifying any permanent state are safe from these types of errors, and the nice ability to formally speak about them makes them a good ivory tower topic, but very little of our real code falls into this category. quite a lot of the clojure code i work on does indeed fall into that category
I think it depends. Sometimes you want a dynamic system where capacity and capability can change while the program is running. Sometimes you want a system that is mostly fixed and predictable. Sometimes you want a little of both. It depends on the use case.
He also advocates for a functional style and its tradeoffs here: https://gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php
Oh, yeah, that thread was pretty funny. Zach challenged Bob on (poor) naming choices and Bob was so condescending in response and then cut the discussion short. Bob doesn't like being challenged -- don't be like Bob 🙂
come to think of it, brian will advocates for inlining helpers. he says it decreases the total surface area of the code base, making it more tractable.
I mean that most code relies on objects with stateful internals (clojure has these too, but most of the core language is a set of tools for segregating states from values)
Hello
One question. How can I define a fixed set of values to a map attribute. Like an enum in java
#{}
Just as concise a clojure. It rocks
For clearness, which are those in Clojure?
in general, you usually don't need analogs to Java enums at all
either just use the constant values, or use :keywords for options (instead of public static final String blah). if you really need to collect them (for use of the full set somewhere), put them in a set or sometimes a map if there is ancillary info
or I guess a vector if there is some necessary ordering
you may be tempted to (def my-option :my-option)
- resist the urge, just use :my-option
Is there a function in Clojure to check if a number is in a closed-open range? E.g. a <= x < b
? I know I can use the expression (<= a x b)
, but that's a closed-closed range. I also know that I can use an and
to achieve what I want, but I would prefer something more succinct or more math-aligned. Any suggestions? Thanks
I'm considering defining a function <=<
that does that, but I'm guessing there should be something like this already done in core?
not that i'm aware