Fork me on GitHub
#beginners
<
2019-01-18
>
Machado02:01:08

after messing around a little bit

Machado02:01:14

I've come with these two alternatives

Machado02:01:24

(ns people.core
  (:require [people.utils :refer :all]))

(defrecord Person [name age height])

(defmulti create-person
  (fn [data] 
    {:age (contains? data :age) 
     :height (contains? data :height)}))

(defmethod create-person
  {:age true :height false}
  [{:keys [age]}]
  (->Person "Gabriel" age ""))

(defmethod create-person
  {:age false :height true}
  [{:keys [height]}]
  (->Person "Gabriel" "" height))

(defmethod create-person
  :default
  [_]
  (->Person "Gabriel" "" ""))

(defn create-person-2 [ & {age :age height :height size :size :or {age "" height ""}}]
  (prn height)
  (prn age))

Machado02:01:55

I feel that create-person-2 allows me to validate the data a little better

Machado02:01:03

even for extraneous arguments

Machado02:01:13

what are you thoughts on these?

seancorfield02:01:11

Having age and height as empty strings seems a bit odd -- why not nil (which means "were not provided")?

seancorfield02:01:32

Also, when you defrecord you get a map->Person constructor as well which would pretty much give you create-person without any of the multimethod stuff...

seancorfield02:01:50

I guess I'm confused about what you're trying to achieve here... (map->Person {:name "Gabriel"}) or (map->Person {:name "Gabriel" :age 42}) or (map->Person {:name "Gabriel" :age 42 :height 168}) (assuming centimeters 🙂 )

Machado02:01:17

I want to be able to use all of three

Machado02:01:41

I'm looking for a way to have optional fields with default values

Machado02:01:43

for a record

seancorfield02:01:31

(map->Person (merge defaults data)) where defaults is whatever defaults you want as a hash map

5
Machado02:01:32

Oh, that's nice

Lennart Buit07:01:15

It is also common to have some function wrapping your record constructor. There is nothing stopping you from writing a (defn my-person [args} ...) that does arbitrary data mangling before calling map->Person ^^.

pavlosmelissinos11:01:57

Hello! What tools do clojurians prefer for static analysis (e.g. to catch arity exceptions in compile time)

borkdude11:01:11

@pavlos I like joker, I use it as an emacs plugin

👌 5
pavlosmelissinos11:01:55

seems cool, thanks

borkdude11:01:25

also speculative might be nice to enable in your tests or dev. it’s not static, so it needs runtime: https://github.com/borkdude/speculative

borkdude12:01:35

Fortunately CLJS already warns about incorrect arities at compile time

borkdude12:01:32

I think joker limits itself to only one namespace at a time for user built functions, so it doesn’t catch all the things. If you know more tools, let me know 🙂

borkdude12:01:44

I don;t know what that would do in combination of speculative, but it sure looks interesting

dangercoder17:01:47

only me who gets Available Obsolete from melpa -- ?

andy.fingerhut21:01:16

Eastwood should be able to catch such mistakes, as well as other things. https://github.com/jonase/eastwood

👍 5
borkdude21:01:54

I really should be trying eastwood again sometime

andy.fingerhut21:01:22

I suspect one of its primary down sides that remain is warnings that are not problems, and for some of those there is no straightforward way to silence Eastwood about them for future runs.

bbktsk16:01:10

What is the rationale behind the any? function ( https://clojuredocs.org/clojure.core/any_q ) ? I find it very confusing. It seems like a counterpart to every? but is is not and its name is misleading, at least for me 8(

borkdude16:01:49

@bbktsk any? is used mostly in clojure.spec specs

borkdude16:01:17

e.g. (s/fdef :args (s/cat :coll coll? :e any?))

borkdude16:01:54

it’s not a counterpart to every?, but some can be seen as such

borkdude16:01:38

or not-any?

nikola16:01:14

I'm implementing a lazy sequence and at the end of the recursive function I have the following form (concat so-far digits). When executing the function with a large amount of data it fails with a StackOverflowError. If I replace the form with (apply conj so-far digits), it works fine. Do I understand correctly that concat realizes the sequence and apply does not?

borkdude16:01:46

concat does not realize sequences. writing your own lazy sequence is rare btw

nikola16:01:25

I'm solving day 14 of advent of code, it's an exercise, I understand it's strange

nikola16:01:34

I'm learning about lazy sequences

bbktsk16:01:38

@borkdude oh, right. Makes sense, thanks. It’s just this whole family of functions lacks some common naming convention. any? vs. not-any?, similar name but completely different, some vs. every? similar purpose, but different name style… I use clojure just intermittently and every single time need to lookup which one is the right one 8(

borkdude16:01:41

@bbktsk the reason some does not end with a question mark is that it returns the first value for which the predicate holds, or nil, not a boolean

nikola16:01:57

@seancorfield I'll have a look, thanks

dazld16:01:48

say, I have a map of functions, where each function takes a reference to the map as its first argument - I can’t partially apply each function with the map, because .. when you partially apply the function, the map is the original unwrapped functions 😛

dazld16:01:17

if that makes sense..

dazld16:01:17

something like:

(defn icon [_ icon-data]
  [:icon (:url icon-data)])

(defn nav [{:keys [icon]} nav-item]
  (:span 
    (:title nav-item)
    (icon (:icon nav-item))))

(defn header [{:keys [nav]} data]
  [:header (:title data)
   (map nav (:nav-items data))])

(defn page [{:keys [header]} data]
  [:section
   (header (:content data))])


(def foo {:page page
          :header header
          :icon icon
          :nav nav})

dazld16:01:52

ie, avoid having to pass foo around

john18:01:01

Short of storing it in an atom, you could do:

(defn icon [_ icon-data]
  [:icon (:url icon-data)])

(defn nav [{:keys [icon] :as m} nav-item]
  (:span 
    (:title nav-item)
    (icon m (:icon nav-item))))

(defn header [{:keys [nav] :as m} data]
  [:header (:title data)
   (map (partial nav m) (:nav-items data))])

(defn page [{:keys [header] :as m} data]
  [:section
   (header m (:content data))])


(def foo {:page page
          :header header
          :icon icon
          :nav nav})

((:page foo) foo {:content {:nav-items ["blah1" "blah2"]}})
Not sure if that does what you're looking for though.

john18:01:44

Or get fancy with prismatic's fnk/graph stuff http://plumatic.github.io/prismatics-graph-at-strange-loop

❤️ 5
dazld18:01:16

thanks that's a great tool. I'm using a graph library already to resolve dependencies, this might slot in fine.

rcustodio17:01:57

Good evening, is any of you having this problem? WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.

rcustodio17:01:46

Its clj 10, it doesn’t happen when I use clj -m xxx but it does happen when I do the uber jar and start it like java -cp xxxxx

seancorfield18:01:35

@rcustodio How are you building the uberjar?

rcustodio18:01:16

using depstar

rcustodio18:01:37

@seancorfield clj -A:depstar -m hf.depstar.uberjar target/$(NAME)-$(VERSION).jar

rcustodio18:01:57

:depstar {:extra-deps {seancorfield/depstar {:mvn/version "0.1.5"}}

hiredman18:01:13

clj is maybe using a different version of java

rcustodio18:01:45

java -version
java version "11.0.1" 2018-10-16 LTS

hiredman18:01:14

check clj -e '(System/getProperty "java.version")'

rcustodio18:01:43

clj -e '(System/getProperty "java.version")'
"11.0.1"

seancorfield18:01:54

And you're using the same version of Java to run the uberjar?

seancorfield18:01:10

Bing suggests that warning might be coming from log4j2...

seancorfield18:01:20

https://stackoverflow.com/questions/53049346/is-log4j2-compatible-with-java-11 includes a possible workaround, if something in your app is using log4j2 (and other search results point to logging startup too).

seancorfield18:01:55

(if you're running clj -m ... and java -cp ... in different directories, it might be picking up a different logging config?)

rcustodio18:01:03

yes, I’m using l4j

rcustodio18:01:15

So it must be that

rcustodio18:01:25

Sadly there is nothing to do, it seems, just wait a new version of l4j