Fork me on GitHub
#beginners
<
2020-11-20
>
sova-soars-the-sora00:11:25

So I'm trying to get the size of a file ... (.length (io/file "filename")) is not working ;/

sova-soars-the-sora00:11:35

am i missing something?

phronmophobic00:11:37

are you getting an error?

sova-soars-the-sora00:11:28

Aha. I was getting zero as the file size. but it's because I did not have the full path "resources/"

sova-soars-the-sora00:11:39

because I'm also using resource-response (which adds in "resources/" on its own)

sova-soars-the-sora00:11:14

I'm trying to get this .m4a to play on iOS mobile [webkit] and apparently it needs 3 headers set,

sova-soars-the-sora00:11:44

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/

noisesmith00:11:06

mixing files / resources sometimes works accidentally, but it's not going to work in the general case

sova-soars-the-sora00:11:11

(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") 
  		)))

noisesmith00:11:42

small thing, you don't need that str call, io/file already composes varargs into a path

sova-soars-the-sora00:11:07

hmmm okay, let's do that...

sova-soars-the-sora00:11:06

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/

phronmophobic00:11:20

it probably doesn't matter, but I would also capitalize

Accept-Ranges

sova-soars-the-sora00:11:36

😄 open to any suggestions

sova-soars-the-sora00:11:51

anybody got Tim Cook on speed dial?

phronmophobic00:11:45

are accessing the page from iOS safari?

phronmophobic00:11:27

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

phronmophobic00:11:38

that dev panel might be able to give you more information

sova-soars-the-sora00:11:12

whaat that's awesome i gotta figure out how to do that.

phronmophobic00:11:03

yea, it's quite useful

sova-soars-the-sora00:11:32

welp, I can see the error now, apparently it doesn't know the file type. it just says "other" and it shows a failure

sova-soars-the-sora00:11:32

welp, I can see the error now, apparently it doesn't know the file type. it just says "other" and it shows a failure

phronmophobic00:11:34

progress! try adding a Content-Type header

sova-soars-the-sora00:11:43

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" ...

sova-soars-the-sora00:11:12

It thinks the size is 8.00KB but it transferred all 4.2MB x/

sova-soars-the-sora00:11:59

one resource suggests audio/x-m4a ... let's see

phronmophobic00:11:19

oops. assumed it was video for some reason

sova-soars-the-sora00:11:57

np. it's really weird that it thinks the file size is 8kb but transfers 4.2MB

sova-soars-the-sora00:11:38

pretty badass to move the mouse on the main machine and see the highlights on the device...

parrot 3
phronmophobic00:11:38

if there’s another site that works right, you can try curling their site and copying what they do

sova-soars-the-sora00:11:17

an impressive level of difficulty from the makers of the iPod portable music playing thing.

sova-soars-the-sora00:11:04

maybe a lil too distracting

sova-soars-the-sora00:11:15

didn't expect an embed x)

sova-soars-the-sora00:11:55

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.

phronmophobic01:11:24

i would try finding a site that supports what you want and use the devtools to see they’re doing different

sova-soars-the-sora01:11:04

that's a great idea, i'm not sure how i'd find one 😄

phronmophobic01:11:38

what about sound cloud? or maybe a podcast site

sova-soars-the-sora01:11:41

Hmm that's an idea

sova-soars-the-sora01:11:52

apparently it's trying to get range 0-1 and it's not working so it says hey there's no file here

sova-soars-the-sora01:11:05

the mp3 fallback works, but there is no seekbar, which is what i'm afta

phronmophobic01:11:47

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

sova-soars-the-sora01:11:01

Okay it looks like response/status 206 for "partial content" is important

sova-soars-the-sora01:11:24

and it now knows the correct file type (m4a) with audio/x-m4a content-type

sova-soars-the-sora01:11:31

but still an error ;/

phronmophobic01:11:18

what’s the error?

sova-soars-the-sora02:11:11

It tries to get bytes 0-1 and that doesn't work

sova-soars-the-sora02:11:22

I think the solution is: use jPlayer.

Sergio09:11:20

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

Sergio09:11:08

it might be an interesting exercise to have it working on clj:smile: … I will need the weekend for that

sova-soars-the-sora15:11:58

Haha awesome. Thanks @UQN9ESJ00 i'm just gonna throw jQuery in there and configure jPlayer to do it and call it a day on that one

👍 3
sova-soars-the-sora15:11:12

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|

sova-soars-the-sora02:11:53

Hey what is this `

"Content-Range", "bytes */"

sova-soars-the-sora03:11:42

Use Absolute File Path instead of Relative File Path for html5 Audio elements and it works

sova-soars-the-sora03:11:50

do I stop screaming into the void now or keep going?

st3fan01:11:20

Is there an easy way to benchmark some code?

st3fan01:11:37

ideally a single function in the repl

phronmophobic01:11:07

time: eg.

> (time (count (range 1e7)))
"Elapsed time: 1466.041527 msecs"                                                                                                                                                       
10000000  

Alex Miller (Clojure team)02:11:43

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

Alex Miller (Clojure team)02:11:23

so even doing a repeated series of (time (dotimes [_ 1000] (whatever))) will give you a much better sense than timing one op

st3fan02:11:28

Yeah that is what I did .. it is good enough for an indication ...

seancorfield03:11:28

criterium is a good library for benchmarking

seancorfield03:11:13

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=>

practicalli-johnny09:11:22

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

st3fan18:11:26

Oh that is very nice

st3fan21:11:02

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 🙂

practicalli-johnny23:11:53

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...)

sova-soars-the-sora02:11:22

I think the solution is: use jPlayer.

Carlo10:11:58

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?

Carlo10:11:30

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 variable

Carlo10:11:26

nevermind, figured it out. The correct form is:

(logic/run* [what]
  (logic/membero ('a 'b what) '((a b c))))

Carlo10:11:39

hindsight is 20/20 😂

Carlo10:11:39

but why is ('a 'b what) not equivalent to

`(a b ~what)
?

delaguardo10:11:48

because a and b will be transformed into (quote user/a) not to simple symbol a

Carlo10:11:10

I see, so I probably should use keywords instead of symbols in this case, right?

Carlo10:11:25

wait who transforms a in (quote user/a)?

Carlo10:11:01

oh I see, the backtick... why does it do that?

delaguardo11:11:18

Inside of backtick symbols expand to fully qualified form. Unless symbol is not quoted

Carlo10:11:05

when I'm in emacs with cider, how do I get documentation for a library function?

Carlo10:11:52

cider-doc unsurprisingly

Carlo10:11:06

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 known

delaguardo11:11:07

I guess because membero is macro and expects a form.

Carlo11:11:04

but where is that documented? How would I know? By reading the source code of membero?

Carlo11:11:36

(defne membero
  "A relation where l is a collection, such that l contains x."
  [x l]
  ([_ [x . tail]])
  ([_ [head . tail]]
    (membero x tail)))

Carlo11:11:30

(defmacro defne
  "Define a goal fn. Supports pattern matching. All
   patterns will be tried. See conde."
  [& rest]
  `(defnm conde ~@rest))

Carlo11:11:46

it's unclear for me where I should get that information

bronsa11:11:19

membero is not a macro

delaguardo12:11:47

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.

bronsa11:11:26

the only macro there is run* , and that's what defines the evaluation semantics of its whole body

Iulian12:11:28

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: " %)]

herald12:11:47

Did you try using the :attr param? e.g. :attr {:id "myid"}

Iulian12:11:44

I did not, and it worked 🙈 Thank you!

🎉 3
gregg01:11:49

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

Lyderic Dutillieux14:11:11

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 ?

kschltz15:11:07

It seems to me it is there to provide some tooling to mess around with your project dependencies/structure

Lyderic Dutillieux15:11:15

You mean for editor integration for example ? So it should not be used manually

Alex Miller (Clojure team)15:11:09

it provides a number of built-in apps you can run

Alex Miller (Clojure team)15:11:45

probably will be more over time

Lyderic Dutillieux15:11:14

Alright, great ! Thanks, it will be usefull

Rebecca Nzioki15:11:25

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)))

dpsutton15:11:47

defn is a macro but you're probably ok with that one? Do you just want to not use the threading macro ->>?

dpsutton15:11:49

(fn [rgbs] (Long/decode (apply str "0x" rgbs)) should do it then as the function you are mapping

andy.fingerhut15:11:09

The expression (->> % (apply str "0x") (Long/decode)) is equivalent to (Long/decode (apply str "0x" %))

dpsutton15:11:25

# is the dispatch macro so i got rid of that one too 🙂

dpsutton15:11:23

why did you want to get rid of the macro? just curious

Rebecca Nzioki15:11:33

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..

dpsutton15:11:43

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

dpsutton15:11:23

also try evaluating (macroexpand '(->> (range 3) (map inc) (map dec)))

✔️ 3
st3fan18:11:40

What is the deal with globals in Clojure? Are they acceptable because they are mostly immutable? Or should I work on eliminating them?

dgb2318:11:16

> 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.

st3fan18:11:49

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.

st3fan18:11:09

Understanding how this maps to Clojure is a gap in my knowledge

dgb2318:11:05

There is a distinction of side-effects, like opening and closing connections, writing to sockets etc. And state, which lives inside your application.

st3fan18:11:37

Are there some good examples available?

dgb2318:11:44

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

dgb2318:11:30

Generally people don’t concern themselves too much with making stuff inaccessible. Its rather a matter of communicating clearly what your public API is

st3fan18:11:27

I am not so worried about visibility (inaccessible) - more about good structure and being able to test properly.

Darin Douglass18:11:06

the standard trifecta for application state usually are: • https://github.com/stuartsierra/componenthttps://github.com/weavejester/integranthttps://github.com/tolitius/mount each has their drawbacks/paradigms so you'll have to find what suits your needs best

👍 6
Darin Douglass18:11:44

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)

edye19:11:54

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)

dgb2319:11:00

(let [[item1 :as all] names]
  (println "The first name from" all "is" item1))

dgb2319:11:29

you mean this?

edye19:11:48

Yes like that but for a map rather than a vector

dorab19:11:58

Not quite what you want, but close (defn f [{:keys [a b] :as all}] (println "All: " all)) ?

Alex Miller (Clojure team)19:11:36

no, there is no way to do that

edye19:11:48

ok makes sense, I couldn't find a section on it. I'll just dissoc the other keys from map

st3fan19:11:21

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.

👍 12
Xarlyle019:11:42

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.

noisesmith19:11:00

I think #code-reviews is the right place for that, you can post it there without asking permission

andy.fingerhut19:11:06

This message is perfectly appropriate for the #beginners channel. I also wanted to point out #code-reviews channel.

Xarlyle019:11:48

Cool! I didn't know about the #code-reviews channel. Good to know, thanks

Xarlyle019:11:34

There are a lot of helpful people in the #beginners channel so I figured this would be a good place

Xarlyle019:11:08

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.

noisesmith20:11:10

people can access it based on your user name, if they have an account that has solved the problem already

noisesmith20:11:14

probably best to share the code here

Xarlyle020:11:48

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))))

Stuart21:11:26

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?

seancorfield21:11:12

@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...

Stuart21:11:59

@seancorfield, thank you, wasn't aware of that page

seancorfield22:11:08

...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.

seancorfield22:11:30

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.

Stuart22:11:08

by rich comment blocks you mean (comment ,,, )

seancorfield22:11:32

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!