Fork me on GitHub
#clojure
<
2016-09-26
>
liamd00:09:31

i don’t totally understand the use case for clojure protocols. they seem sort of like traditional OO protocols, but without class instances what exactly implements them?

hjavaheri00:09:06

@liamd Records, defined by defrecord can implement them. You can also extend the protocol to include any types you want.

liamd00:09:34

so i specify a protocol

liamd00:09:43

then i specify a record that has implementations of the protocol

hjavaheri00:09:52

yeah that's one way to use them

liamd00:09:54

then when i create an instance of that record i can call those functions on it

liamd00:09:05

okay that makes sense

liamd00:09:28

are there any inheritance concepts?

hjavaheri00:09:44

Yeah you can use make-hierarchy

liamd00:09:48

so they’re like multimethods in reverse?

liamd01:09:23

i don’t really get why we need multimethods and protocols

ghadi01:09:53

Inheritance is sorta frowned upon

hjavaheri01:09:01

protocols are actually faster, but require more code to implement the behavior compared to multimethods

ghadi01:09:44

Another difference between protocols and mulitmethods is that protocols only offer type based dispatch on the first/primary arg

ghadi01:09:57

mm's offer arbitrary dispatch logic

hjavaheri01:09:01

I agree, when you feel like you need to do inheritance, always double check your design

hjavaheri01:09:12

you probably can get it nicer using functional paradigms

hjavaheri01:09:03

Yup, multimethods give you more flexible dispatch with a performance price.

liamd01:09:18

yeah i’m writing a game and while i’ve gotten my head out of OO space for web services it’s tougher in this domain

hjavaheri01:09:19

It's easy to get trapped in mimicking OO using protocols and inheritance. Do not do it 🙂

liamd01:09:35

to make this concrete: i’m going to have a list of different kinds of units in my game state and i want to map functions over all of them that have them return their new state

liamd01:09:02

i kinda started sketching this out:

(defprotocol Entity
  "An entity is anything that can be represented on the map"
  (draw [x-size y-size] "An entity must be able to draw itself given a size constraint"))

(defprotocol Controllable
  "A unit is a controllable entity that the player can interact with"
  (onSelected [this] "Executed when the user selects this entity")
  (onInteractWith [this other] "Executed when this entity is selected and then another entity is selected")
  (onTurnStart [this] "Executed on turn start")
  (onTurnEnd [this] "Executed on turn end”))

hjavaheri01:09:26

sometimes, a simple cond in your functions is the most expressive way to go about this

liamd01:09:58

im starting to think having a multimethod dispatch on some “:type” in the unit records would make more sense

hjavaheri01:09:05

if the functionality does not differ that much from unit to another, I think you can get away with a cond or case on unit type in your functions

liamd01:09:23

well what’s the difference between a case and a multimethod?

ghadi01:09:39

case's dispatch needs to be compile time constant

liamd01:09:42

do multimethod implementations have to be in the same namespace as the defmulti?

ghadi01:09:22

(case k
  42 :foo
  43 :bar 
....)

ghadi01:09:40

nope liamd doesn't have to be in the same ns

hjavaheri01:09:46

you can require the defmulti namespace in defmethod namespaces

ghadi01:09:12

clojure print system is an example of a mm with extensions made by different namespaces:

hjavaheri01:09:22

take a look at core.match as well

hjavaheri01:09:41

in my experience it leads to much more elegant code compared to MM's

hjavaheri01:09:07

If you are not careful, it is easy to create a spaghetti mess of MM's in your code base

hjavaheri01:09:17

which could be hard to maintain in a long run

liamd01:09:25

i’m thinking what might be best is turn each of those methods into multi methods with defaults and then “override” them in unit files

hjavaheri01:09:41

you do not have to override anything

hjavaheri01:09:59

if the method is not defined, it will default to a default implementation

liamd01:09:02

i don’t mean @Override

liamd01:09:08

like literally

liamd01:09:59

i just mean if i need some new behavior it’s easy to add a new multimethod with a default in one place and all my existing “:type”’s will just default to it i guess?

liamd01:09:16

then as i need to specify some behavior for a specific :type i can just add a case in that file

hjavaheri01:09:22

yes, multimethods are great for cases that you need to extend the behavior

hjavaheri01:09:39

but if you have a limited space for your behavior, do not overuse them

liamd01:09:49

what do you mean limited space?

hjavaheri01:09:03

these are of course my personal opinion. Others might have different opinions

hjavaheri01:09:26

if you are adding new units to your game, you are extending it. But if the unit types are already defined and won't be extended regularly, that's a confined (limited) space of types.

jrheard01:09:53

liamd: my completely underequalified 2c: i’ve never built a game before, but i’m working on one in cljs; i don’t really ever use records or protocols/multimethods, i mainly just use functions and maps, and they’ve been working fine for me so far

jrheard01:09:22

code’s at https://github.com/jrheard/voke , work in progress is http://jrheard.com/voke (wasd + arrow keys), i’ve never done this before haven’t made it very far, but am linking this stuff in case it’s at all helpful

jrheard01:09:56

i’m using what i think is a reasonable interpretation of the entity-component-system pattern i’ve read about

liamd01:09:36

@jrheard awesome! i’ll definitely check out your project. it’s great to see prior art and there’s very little in the way of clojure games

jrheard01:09:45

yeah, i’ve had the same issue 😄

jrheard01:09:08

https://github.com/aaron-santos/robinson exists fwiw and seems to be waaaaayyyyy farther along / better in every way than what i’ve got

liamd01:09:08

and i’ve found Unity paradigms… unpleasant

jrheard01:09:25

i haven’t read much of his code, but it looks like a nice goldmine of prior art

jrheard01:09:45

i’ve been keeping notes from the day i started the project, they’re at https://github.com/jrheard/voke/blob/master/dev-diary.txt but likely very unhelpful/scattered, lots of relevant links buried in there though

jrheard01:09:50

anyway that’s all from me, glgl 🙂

liamd01:09:34

thx! i’ll keep in touch if i see anything i’m curious about or as i make progress

witek10:09:06

How to get a namespace or the symbol of a namespace by its name?

witek10:09:17

... the thing I have to pass to (ns-refers) or (ns-map)

kevin4210:09:24

ns-resolve?

witek10:09:43

ns-resolve also needs a ns as parameter. this ns is what I need, but I only have its name as a string

darwin11:09:10

I need an explanation, scratching my head when reading this code: https://github.com/cemerick/piggieback/blob/440b2d03f944f6418844c2fab1e0361387eed543/src/cemerick/piggieback.clj#L294 to me it looks like a fancy way how to use vars as keys in a map to store some information, the comment "ensure that bindings exist so cljs-repl can set!” is not accurate, no bindings are created AFAICS, set! can be called even without this code

darwin11:09:06

I was reading http://clojure.org/reference/vars and I don’t see reason why one would use vars as keys in a map instead of namespaced keywords

darwin11:09:09

also wondering if the author relies on the fact that each new invocation of wrap-cljs-repl will run on a new thread so it will get a new (independent) instances of those dynamic vars (somehow?)

darwin11:09:39

I understand the purpose of the code, it works, but to me it is magic, because I don’t understand exact mechanism here

darwin11:09:47

thanks for the explanation

kokos12:09:59

@witek when I try to call a function from a namespace, knowing namespace and function name as strings, i use this function

(defn- action
 [ns-name function-name]
  (require (symbol ns-name))
  (binding [*ns* (symbol ns-name)]
    (ns-resolve *ns* (symbol function-name))))
it takes the namespace-name and function-name as strings and returns the actual function wanted from the named namespace

pseud13:09:21

I’m playing around with clojure.spec - is there not a way for me to do something like (s/keys :req-un [[:foo keyword?] [:bar string?]]) rather than

(s/def ::foo keyword?)
(s/def ::bar string?)
(s/def my-map (s/keys :req-un [::foo ::bar]))
? Otherwise I’ll end up with awfully many specs which boil down to keyword?/int?/string? and the like

pseud13:09:39

(And reading the docstring for s/keys tells me this is by design….)

pseud13:09:49

Still — I then wonder - what if I need to define specs for multiple :type fields ? (or some other generic field for a map). It just seems like I’ll have to define an awful lot of separate cljs files then

tianshu15:09:11

how to deploy my clojure webapp(single jar, using jetty as server) with jenkins?

seancorfield15:09:21

@pseud Part of the design is to encourage the use of namespaced keywords more widely 🙂

seancorfield15:09:56

But even with unqualified keywords, you can use namespaces in the specs to identify which sort of :type you are referring to:

(s/def ::thing-a (s/keys :req-un [:a/type ::foo ::bar]))
(s/def ::thing-b (s/keys :req-un [:b/type ::bar ::quux]))
This has two separate :type specs — :a/type and :b/type and shares ::bar as a spec.

josh_tackett16:09:57

Anyone know how to run lein clean on heroku?

hugo.corbucci16:09:58

heroku run lein clean

hugo.corbucci16:09:14

Depending on which dyno you want to do it, you might have to change that command a bit

ghadi18:09:09

instrument jdbc/query with robert hooke

ghadi18:09:14

¯\(ツ)

ghadi18:09:36

or a simple alter-var-root wrapper....or handle it at a higher level in your program

ghadi18:09:44

or at a lower layer in the database

dpsutton18:09:02

robert hooke looks like advised functions in emacs, which means they look awesome and terrible

dspiteself18:09:40

It would be really nice to have something like https://lambdaisland.com/blog/25-04-2016-union-types in core.

currentoor18:09:48

Does anyone know how to make a tag like <script src="demo_async.js" async></script> using hiccup?

hugo.corbucci18:09:42

Usually you can simply use :async true in your options and hiccup will do the right thing

timgilbert19:09:26

Or you could use the xhtml variant: [:script {:async "async" :src "foo.js"}]

currentoor19:09:07

@hugo.corbucci, @timgilbert, both of those result in "<script async=\"async\" src=\"foo.js\"></script>"

currentoor19:09:13

is that valid?

hugo.corbucci19:09:31

pretty sure it is… most browsers will treat those key-only attributes to be “truthy” if they’re present with whichever value

currentoor20:09:04

oh ok, thanks

liamd23:09:37

why is there not-any? but not any??

bfabry23:09:36

@liamd in current alpha's there is an any? but it won't mean what you think it does. the function for that is some

hans23:09:37

liamd any? is called some

liamd23:09:40

some? is " Returns true if x is not nil, false otherwise.” so isn’t that just #(not (nil? %))

gfredericks23:09:58

some and some? are different

liamd23:09:03

ah, naturally

gfredericks23:09:14

some is mostly what you'd want any? to do

gfredericks23:09:32

in the same way that sets are almost predicates for their contents

gfredericks23:09:56

there should be a word for a function that does something except for the edge cases of false and nil

gfredericks23:09:35

do other lisps have those kinds of functions too?

hans23:09:45

common lisp has some and notany

gfredericks23:09:11

does some have the same edge case[s]?