So I'm trying to get the size of a file ... (.length (io/file "filename")) is not working ;/
am i missing something?
are you getting an error?
Aha. I was getting zero as the file size. but it's because I did not have the full path "resources/"
because I'm also using resource-response (which adds in "resources/" on its own)
I'm trying to get this .m4a to play on iOS mobile [webkit] and apparently it needs 3 headers set,
it works on desktop firefox and stuff... but on iOS mobile it just doesn't want to play nice. It used to say "Live Broadcast" and now it just says "Error" where there ought be a seek bar x/
mixing files / resources sometimes works accidentally, but it's not going to work in the general case
(GET "/members/:filename" [filename :as r]
(let [file-size-in-bytes (.length (io/file (str "resources/members/" filename)))
content-range (str "bytes 0-" (dec file-size-in-bytes) "/" file-size-in-bytes)]
(println filename ": " file-size-in-bytes ": " content-range ": " )
(->
(response/resource-response (str "members/" filename))
(response/header "Content-Length" file-size-in-bytes)
(response/header "Content-Range" content-range)
(response/header "accept-ranges" "bytes")
)))
small thing, you don't need that str call, io/file already composes varargs into a path
hmmm okay, let's do that...
Is very weird ... webkit just says "Error" where there ought be a seek bar. And so I try and undo the code I have added, and it doesn't go back to saying "Live Broadcast" but remains on "Error" x/
it probably doesn't matter, but I would also capitalize
Accept-Ranges
π open to any suggestions
anybody got Tim Cook on speed dial?
I have words.
are accessing the page from iOS safari?
if so, I believe you can pull up a dev panel using safari on your computer and connecting to the safari running on your iOS device
that dev panel might be able to give you more information
whaat that's awesome i gotta figure out how to do that.
yea, it's quite useful
progress! try adding a Content-Type
header
I suspect your problem is related to the Parts (http-ranges). I did some implementation in the past on java+spring but the principle of the solution I think applies. Here you can find how to calculate the parts in java and that maybe gives you an indication on how to use it in CLJ: https://stackoverflow.com/questions/28427339/how-to-implement-http-byte-range-requests-in-spring-mvc
it might be an interesting exercise to have it working on clj:smile: β¦ I will need the weekend for that
Haha awesome. Thanks @sdmoralesma i'm just gonna throw jQuery in there and configure jPlayer to do it and call it a day on that one
I thought flash player was being retired... I wonder if this will be a thing in the future for the flash fallback on jPlayer x|
Hey what is this `
"Content-Range", "bytes */"
Use Absolute File Path instead of Relative File Path for html5 Audio elements and it works
do I stop screaming into the void now or keep going?
probably one of these video mime types https://www.iana.org/assignments/media-types/media-types.xhtml#video
Hmmm, it's just an audio file... I tried both audio/m4a and video/m4a as a "Content-Type" but curiously I get byte-ranges 0-1 as an error and also the content type remains "other" ...
It thinks the size is 8.00KB but it transferred all 4.2MB x/
one resource suggests audio/x-m4a ... let's see
oops. assumed it was video for some reason
np. it's really weird that it thinks the file size is 8kb but transfers 4.2MB
pretty badass to move the mouse on the main machine and see the highlights on the device...
if thereβs another site that works right, you can try curl
ing their site and copying what they do
an impressive level of difficulty from the makers of the iPod portable music playing thing.
maybe a lil too distracting
didn't expect an embed x)
Welp. Back to screaming into the void. I have mp3 versions of all the files and the mp3 version works but it says "Live Broadcast" instead of being able to seek to arbitrary points.
i would try finding a site that supports what you want and use the devtools to see theyβre doing different
that's a great idea, i'm not sure how i'd find one π
what about sound cloud? or maybe a podcast site
Hmm that's an idea
apparently it's trying to get range 0-1 and it's not working so it says hey there's no file here
the mp3 fallback works, but there is no seekbar, which is what i'm afta
yea, if normal google-fu is failing, i would also consider searching http://greg.app for the content type and content range headers youβre using and see if anyone else has figured it out
Is there an easy way to benchmark some code?
ideally a single function in the repl
criterium is excellent for producing more accurate results than time as it warms up the JVM and runs testsany times to give tha average. I also use memory meter too https://github.com/practicalli/clojure-deps-edn#performance-testing
Oh that is very nice
I have not figured out what the deal is with deps.edn yet - i'm "simply" using lein now because that is what I know - but it looks like I need to investigate π
With Leiningen and Clojure CLI tools (deps.edn), the Clojure code is the same (unless lein plugins are writing code for you). However Clojure CLI is a simple wrapper around the JVM with some tools to manage dependencies. One advantage is this is faster than Leiningen, which spins up two virtual machines. The list of community tools that are in practicalli/clojure-deps-edn are used instead of a specific plugin system like Leiningen, so it's easier to add all sorts of tooling to Clojure CLI. This approach is being extended via Clojure exec (and there are whispers about something called tools.build...)
time
: eg.
> (time (count (range 1e7)))
"Elapsed time: 1466.041527 msecs"
10000000
Okay it looks like response/status 206 for "partial content" is important
and it now knows the correct file type (m4a) with audio/x-m4a content-type
but still an error ;/
whatβs the error?
but note that a) Java uses a just in time compiler, so code gets faster as you run it more and b) garbage collection can throw unexpected pauses into the mix
It tries to get bytes 0-1 and that doesn't work
so even doing a repeated series of (time (dotimes [_ 1000] (whatever)))
will give you a much better sense than timing one op
Yeah that is what I did .. it is good enough for an indication ...
criterium is a good library for benchmarking
If you're using the CLI and my dot-clojure file, you can just use the :bench
alias to bring that in:
seanc@DESKTOP-30ICA76:~/clojure$ clj -M:bench
Downloading: criterium/criterium/maven-metadata.xml from clojars
Downloading: criterium/criterium/0.4.6/criterium-0.4.6.pom from clojars
Downloading: criterium/criterium/0.4.6/criterium-0.4.6.jar from clojars
Clojure 1.10.1
user=> (require '[criterium.core :refer [bench quick-bench]])
nil
user=> (defn foo [n] (* n n n))
#'user/foo
user=> (quick-bench (foo 13))
Evaluation count : 71598534 in 6 samples of 11933089 calls.
Execution time mean : 2.927325 ns
Execution time std-deviation : 2.830385 ns
Execution time lower quantile : 0.853802 ns ( 2.5%)
Execution time upper quantile : 7.650605 ns (97.5%)
Overhead used : 7.242216 ns
Found 1 outliers in 6 samples (16.6667 %)
low-severe 1 (16.6667 %)
Variance from outliers : 83.1399 % Variance is severely inflated by outliers
nil
user=>
this query using clojure core.logic baffles me:
(logic/run* [what]
(logic/membero '(a b ~what) '((a b c))))
it returns ()
when I would have expected '((a b c))
. Could you explain me why?I see that
(logic/run* [what]
(logic/membero '(a b c) '((a b c))))
is always satisfied, so there must be something wrong in the way I'm using the logical variablenevermind, figured it out. The correct form is:
(logic/run* [what]
(logic/membero ('a 'b what) '((a b c))))
hindsight is 20/20 π
but why is ('a 'b what)
not equivalent to
`(a b ~what)
?because a and b will be transformed into (quote user/a)
not to simple symbol a
I see, so I probably should use keywords instead of symbols in this case, right?
wait who transforms a
in (quote user/a)
?
oh I see, the backtick... why does it do that?
when I'm in emacs with cider, how do I get documentation for a library function?
cider-doc
unsurprisingly
I'd like to know why in:
(logic/run* [what]
(logic/membero (:a :b what) '((:a :b :c))))
I don't need to quote (:a :b what)
, and in fact why quoting it is wrong, and how should I have knownInside of backtick symbols expand to fully qualified form. Unless symbol is not quoted
I guess because membero is macro and expects a form.
but where is that documented? How would I know? By reading the source code of membero?
(defne membero
"A relation where l is a collection, such that l contains x."
[x l]
([_ [x . tail]])
([_ [head . tail]]
(membero x tail)))
(defmacro defne
"Define a goal fn. Supports pattern matching. All
patterns will be tried. See conde."
[& rest]
`(defnm conde ~@rest))
it's unclear for me where I should get that information
membero is not a macro
the only macro there is run*
, and that's what defines the evaluation semantics of its whole body
Is there any way to add an "id" attribute to a re-com
component? I tried all the combinations of adding the :id
in a map or straight into the component, but it does not work. This is my component:
[single-dropdown
:width "200px"
:choices (reagent/atom tags)
:model (reagent/atom nil)
:placeholder "Issue Group"
:filter-box? true
:on-change #(print "Dropdown: " %)]
Regarding :model (reagent/atom nil)
, every time through the render loop, the component will be passed a new reagent atom with value nil, so while I haven't tested it, I don't think that's what you want. I would move the atom to a let block, using a Form-2 component: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md#form-2--a-function-returning-a-function
Did you try using the :attr
param? e.g. :attr {:id "myid"}
I did not, and it worked π Thank you!
Just checked with source code. You right this is not a macro but it meant to work in macro context as a function transforming unevaluated arguments into a form.
Hey guys, I just checked my system's deps.edn
located at /usr/local/lib/clojure/deps.edn
and I found this :
:aliases {
:deps {:replace-deps {org.clojure/tools.deps.alpha {:mvn/version "0.9.833"}
org.slf4j/slf4j-nop {:mvn/version "1.7.25"}}
:ns-default clojure.tools.cli.api}
:test {:extra-paths ["test"]}
}
Does anyone know what the :deps
alias can be used for ?It seems to me it is there to provide some tooling to mess around with your project dependencies/structure
You mean for editor integration for example ? So it should not be used manually
no, it should :)
see https://clojure.org/reference/deps_and_cli#_other_programs
it provides a number of built-in apps you can run
probably will be more over time
Alright, great ! Thanks, it will be usefull
Hey guys, how else can you write this code without using macros?
(defn hex->rgb [[_ & rgb]]
(map #(->> % (apply str "0x") (Long/decode))
(partition 2 rgb)))
defn
is a macro but you're probably ok with that one? Do you just want to not use the threading macro ->>
?
I'll keep track of this then : https://github.com/clojure/tools.deps.alpha/blob/master/src/main/clojure/clojure/tools/cli/api.clj
yes
(fn [rgbs] (Long/decode (apply str "0x" rgbs))
should do it then as the function you are mapping
The expression (->> % (apply str "0x") (Long/decode))
is equivalent to (Long/decode (apply str "0x" %))
#
is the dispatch macro so i got rid of that one too π
why did you want to get rid of the macro? just curious
thanks! it's just for learning, i'm reading the web-dev-with-clojure and I read that you can choose to use the threading-macros or not..
great reason! π Take some time to see how that worked as threading macros are pretty much everywhere and often used interchangeably with what they expand to
will do
also try evaluating (macroexpand '(->> (range 3) (map inc) (map dec)))
What is the deal with globals in Clojure? Are they acceptable because they are mostly immutable? Or should I work on eliminating them?
> Are they acceptable because they are mostly immutable? @st3fan As I understand you can manipulate just about everything in Clojure at any time. Your vars, namespaces and so on.
I now realize that what I am really asking is probably more about how do I structure an application that has some state associated with it. Both static (configuration settings) and dynamic (a redis connection). In Go I usually create an application struct
to capture these things .. create one in main, then call functions on that struct.
Understanding how this maps to Clojure is a gap in my knowledge
There is a distinction of side-effects, like opening and closing connections, writing to sockets etc. And state, which lives inside your application.
Are there some good examples available?
There are patterns and libraries that are specifically used to deal with side-effects and configuration in a nice way like integrant. But generally yes, youβd use (defβ¦) and store your connections there
Generally people donβt concern themselves too much with making stuff inaccessible. Its rather a matter of communicating clearly what your public API is
I am not so worried about visibility (inaccessible) - more about good structure and being able to test properly.
the standard trifecta for application state usually are: β’ https://github.com/stuartsierra/component β’ https://github.com/weavejester/integrant β’ https://github.com/tolitius/mount each has their drawbacks/paradigms so you'll have to find what suits your needs best
there are others like https://github.com/juxt/clip and https://github.com/aroemers/mount-lite (my current fav, though i haven't tried clip yet)
Is there a way to destructure a map parameter to get the remaining keys? I thought it might look like this:
(defn f [{:keys [a & remaining]}] remaining)
(let [[item1 :as all] names]
(println "The first name from" all "is" item1))
you mean this?
Yes like that but for a map rather than a vector
Not quite what you want, but close (defn f [{:keys [a b] :as all}] (println "All: " all))
?
no, there is no way to do that
ok makes sense, I couldn't find a section on it. I'll just dissoc
the other keys from map
Probably preaching before the choir here - but the thing I love the most about working in Clojure is the REPL - I just figured out a weird base64 decoding bug by augmenting my server code to store data in a temp var and then I figured out the problem by just playing around with that interactively.
Heyo! I'm looking to improve my more professional coding skills, so I completed question 140 on 4clojure with the goal of creating the most understandable solution, with concise documentation that can lead someone through a difficult problem. Would anyone be willing to take a look at my solution and give feedback with regards to that goal? My username on 4clojure is xarlyle0.
I think #code-reviews is the right place for that, you can post it there without asking permission
This message is perfectly appropriate for the #beginners channel. I also wanted to point out #code-reviews channel.
Cool! I didn't know about the #code-reviews channel. Good to know, thanks
There are a lot of helpful people in the #beginners channel so I figured this would be a good place
But I don't know if people can actually access my code on 4clojure, so I didn't know if I would need to post the code here or not.
people can access it based on your user name, if they have an account that has solved the problem already
probably best to share the code here
okay. Here is the code.
(fn [s]
(letfn [; take a set #{A b c D}, and make #{#{A b c "D"} #{A b "C" D} #{A "B" c D} #{"A" b c D}}, note both lower and upper case symbols become capital Strings
(get-subsets [coll] (set (map #(conj (disj coll %) (clojure.string/upper-case (str %))) coll)))
; for each set #{A b c D}, make a map entry: {#{A b c D}, #{#{A b c "D"} #{A b "C" D} #{A "B" c D} #{"A" b c D}}}
(get-subset-map [sets] (into {} (map #(vector % (get-subsets %)) sets)))
; take one of the subsets #{A b c "D"} #{A b "C" D} #{A "B" c D} #{"A" b c D} and filter them by if they have a copy in the other subsets
(get-intersect [subset-map pair]
(clojure.set/intersection
(second pair)
(apply clojure.set/union (vals (dissoc subset-map (first pair))))))
; #{A b "C" D} -> #{A b D}
(remove-strings [i]
(set (map #(set (filter (comp (partial not= java.lang.String) type) %)) i)))
; for each answer, filter the original sets by whether none of the other answers is a subset. If the result is empty, then that answer is redundant, and is removed
(remove-redundant [sets] (set
(filter (fn [ex] (seq
(filter
(fn [entry] (not-any? (fn [a] (clojure.set/subset? a entry)) (disj sets ex)))
s)))
sets)))
; Create a subset-map and use get-intersect on the values of each entry to see if there are any copies in the subsets.
; If not, then the key for that entry is NOT SIMPLIFIABLE. Then, remove the strings from the intersection to get the new simplified sets.
; Repeat until all sets are NOT SIMPLIFIABLE
(simplify [sets]
(let [subsets (get-subset-map sets)
intersect (partial get-intersect subsets)
final-entries (set (keys (filter (comp empty? intersect) subsets)))
remaining-entries (remove-strings (apply clojure.set/union (map intersect subsets)))]
(if (empty? remaining-entries)
final-entries
(clojure.set/union (simplify remaining-entries) final-entries))))]
(remove-redundant (simplify s))))
For lein projects I use lein test-refresh
, is their an equivalent test runner that watches for changes and re-runs tests for deps.edn projects?
@qmstuart Most CLI tools are listed on this page https://github.com/clojure/tools.deps.alpha/wiki/Tools#testing and it looks like Kaocha has a "watch" mode...
@seancorfield, thank you, wasn't aware of that page
...that said, I think it's a better workflow to get used to evaluating code as you write it and running tests against them from your editor, so you don't need to switch contexts, and you don't need to worry about saving partially edited code causing a test watcher to fail etc. If you're evaluating code as you write it (and have "test" expressions in Rich Comment Forms) you can get fast, localized feedback directly in your editor (against the REPL), and you can eval and test code without even needing to save it to disk.
I stopped using test watchers completely after I'd been doing Clojure for a couple of years. I still run test suites from the command-line as sanity checks on features/bug fixes before I push a branch, but mostly I run tests in my editor, as I'm working on code.
by rich comment blocks you mean (comment ,,, )
Yes. A term coined by Stu Halloway to describe Rich Hickey's use of (comment ,,,)
forms in code to contain scratch code/setup/REPL-based tests etc. I'd been doing that myself for quite a while before I heard Stu call them that -- has a nice ring to it!
Examples in one of my OSS projects: https://github.com/seancorfield/next-jdbc/search?q=comment&type=code