Fork me on GitHub
#clojure
<
2017-12-26
>
qqq08:12:58

(:require [clojure.string :as ...])

qqq08:12:03

what is a good name, as str is already a function

andy.fingerhut08:12:27

Lots of people use str as an alias for clojure.string, because str/lower-case doesn't cause any conflict with the clojure.core/str function.

andy.fingerhut08:12:37

@souenzzo You can use clojure.core/compare to get a result of -1, 0, or +1 when comparing two #inst's to each other.

souenzzo12:12:37

what is the conceptual difference between compare and >?

noisesmith13:12:37

> is for numbers. See also +, *, /, - etc. - in other languages they might be overloaded for other data types but in jvm clojure they are only for numbers

qqq09:12:17

what is the simplest string manip function which does camelCase to hypen-separated

qqq09:12:28

ah, found this:

(defn kebab-case
  "Converts CamelCase / camelCase to kebab-case"
  [s]
  (str/join "-" (map str/lower-case (re-seq #"\w[a-z]+" s))))

qqq09:12:08

@andy.fingerhut: I have n oidea why that works, but yes, it appears that namespace alias str does not collide with buildin function

bronsa10:12:20

aliases and vars live in different "namespaces"

andy.fingerhut19:12:31

@qqq When a textual identifier contains a "/" character, the thing before the "/" is tried to be resolved as either a full namespace, or as an alias of a namespace (I don't know off hand which order is checked for between those two). If there is no "/", no part of it is considered a namespace or alias, just a symbol on its own.

synthomat21:12:27

meh, can’t come to a solution 😩 I have a lazyseq (file-seq) which I have to iterate through while occasionally change a local data structure (fill and read a hash-table in this loop). Is loop/recur the right approach?

noisesmith21:12:40

if you always move through the lazy-seq in order, reduce is simpler / more direct than loop

synthomat21:12:04

so it’s okay to work with only one hash-structure for both the “actual” work data and help data?

synthomat21:12:31

I’m not super experienced with functional programming yet…

noisesmith21:12:01

using one reduce argument to hold both an accumulated result and ancillary data is common

synthomat21:12:02

technically it is possible, question is about whether it is a good way of implementation

synthomat21:12:18

alrighty, thanks! will try it out immediately

noisesmith21:12:58

if you use transduce, you can even specify the function that gets the real result out of the accumulator

synthomat22:12:58

@noisesmith yeah, works as expected! didn’t try transduce yet, though

noisesmith22:12:35

transduce is mainly useful if you are doing some transform on each item as it comes in

noisesmith22:12:05

eg. replacing (reduce f init (map g coll)) with (transduce (map g) f init coll)

synthomat22:12:39

I’m iterating through a list of files keeping some information to exclude duplicates from being inserted into a DB… (file-hash, last-modified, path)

synthomat22:12:49

reduce might be enough for now, I think

noisesmith22:12:40

sounds about right - the note about transduce was because including that feature indicates that it’s idiomatic to transform the accumulator to get your value out at the end

synthomat22:12:30

one advantage of loop/recur might be, that one can continue the loop from an arbitrary position, whereas with reduce, your nested if-clauses have always to return something…

synthomat22:12:32

just a guess

synthomat22:12:20

I should refactor a bit first

scriptor22:12:25

not arbitrary, it has to be from the "tail" position, so to speak

synthomat22:12:31

maybe it’s not that bad

synthomat22:12:00

oh I thought calling “recur” is similar to “continue” in other langs

synthomat22:12:08

plus new bindings of course…

scriptor22:12:26

you do always have to "return something"

synthomat22:12:39

it seems I didn’t understand loop-recur 😅

scriptor22:12:41

whether you're using loop/recur, or reduce, or anything else in clojure

synthomat22:12:48

does it mean if I have a nested structure, that i can’t call “recur” from the most inner level to jump straight into the next iteration?

scriptor22:12:43

you can, as long as that recur is still in the tail position

scriptor22:12:52

meaning, it needs to be the last thing that could get called

synthomat23:12:04

I should stop talking and try it out myself - I’m concerned that I start explaining my misunderstandings and embarrass myself 😄

scriptor23:12:05

(loop []
  (if blah-blah
    (if something-else
      (recur)
      (other-stuff))
    (foo))

scriptor23:12:42

in that example, recur is in the tail position

synthomat23:12:44

but your example would look almost exactly the same with reduce, wouldn’t it?

scriptor23:12:59

coincidentally, other-stuff and foo are also in tail positions

synthomat23:12:11

just that the else-branches would return the untouched collection

scriptor23:12:35

well, it's a fairly contrived example, the else branches here are breaking out of the loop

synthomat23:12:47

ah, of course!

synthomat23:12:08

on can’t “break out” of reduce. one has basically to walk though the entire collection…

scriptor23:12:30

well, it's actually possible to break out of a reduce

scriptor23:12:01

because clojure provides a special way to signal that you want to break out early

scriptor23:12:27

but I'd avoid that until you're more comfortable with reduce and FP in general

scriptor23:12:32

loop/recur's name is a bit unlucky, since newcomers often think it's similar to an imperative loop

synthomat23:12:49

it’s an end-tailed recursion, right?

scriptor23:12:08

you can recur without loop, too

scriptor23:12:25

in which case it'll just recurse from the beginning of the function

synthomat23:12:27

*tail recursion

synthomat23:12:32

but without the tail optimization, correct? stack or heap would fill up

scriptor23:12:55

*with the optimization, you mean?

scriptor23:12:33

recur tells clojure to use tail optimization

synthomat23:12:34

just calling recur would omit optimizations

synthomat23:12:48

what does loop do then?

scriptor23:12:52

if you just called the function itself you'd fill up the stack

scriptor23:12:57

loop just localizes it

synthomat23:12:00

ah loop is just the jump-point for recur?

scriptor23:12:17

for when you don't want to go all the way back to the beginning of a function