Clojurians
#beginners
<
2017-02-22
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

sb07:02:12

Hello, possible to create from string a function name or generate a function? for example> '''(defn stringhere ...)''' during run the program, the program create new-sub-processes (functions dynamically). Is that possible in Clojure or how? Sorry, if that is very ugly question.. just I used before this.. and maybe easier send a question.

sb07:02:21

exactly> I would like created new functions and add custom names for this when run the program.

sb07:02:05

Eg. find a new algorithm sheme, identify and from this create a new function

sb07:02:29

what the program could use later

sb08:02:08

Any idea where do I need to start the research or experience with that?

rauh08:02:48

@sb Given an NREPL does nothing else, this is certainly posible with clojure

rauh08:02:22

You could read-string + eval or just load-file

rauh08:02:36

You can dynamicall create namespaces and functions, yes.

sb08:02:27

Ok, in this case I need to write the namespace and after this can use the program. is that true when you compiled to java or how works in the real life?

sb08:02:03

so, I understand what you say for me. thanks.

rauh08:02:47

So the compiler will read the UTF-8 string which will just be a bunch of clojure datastructures for the clojure compiler.

tap08:02:01

Maybe you just want macro?

(defmacro create [name]
  `(defn ~(symbol name) [] "Hello"))
(create "xx")
(xx)

rauh08:02:13

Then it'll macroexpand everything. Then it'll compile the datastructures into Java bytecode which you can use

rauh08:02:43

@tap this won't work with "during run the program" as sb stated

rauh08:02:40

You can see the bytecode generated by calling (compile ...) if you're curious

sb08:02:06

Aha.. thanks! That is very helpful!! :+1:

rauh08:02:02

Though, are you sure you want to do this? This means loading clojure code during runtime, usually a bad idea

sb08:02:35

I don't know yet. I would like to create a self-learning engine.

sb08:02:51

I created in different lang.. but hard to code to clojure now.

sb08:02:03

Clojure is new for me.

sb08:02:32

I would like to find the best way for this.

rauh08:02:31

Yeah, def. not a beginner question. :slightly_smiling_face:

rauh08:02:49

Usually data > code, so better to steer your alg with data instead of code

sb08:02:21

:slightly_smiling_face:

sb08:02:06

Ok, I research what can I do.. what is the best in Clojure. Many thanks the quick answer really!!! :+1:

rauh08:02:13

@sb in general clojure is very dynamic, thanks to the JVM, for instance just like clojure dynamically creates JVM bytecode you can do that too during runtime and swap out your functions with those new versions

nico14:02:45

Hello :wave:

nico14:02:03

I posted in #clojure by accident, but I can copy paste the message

nico14:02:57

>>> clojure beginner here, following the (so far good) braveclojure tutorial and at some point it recommends to implement comp by hand and there's no solution and I'd like someone to look at it :speak_no_evil:

sveri14:02:22

@nico If you click the + button on the left of the input field you can paste a snippet.

nico14:02:55

right :stuck_out_tongue:

nico15:02:09

> Reducing over a collection of functions is not a technique you’ll use often, but it’s occasionally useful

nico15:02:28

it sounds like I should have my-compwith that mechanism maybe

jcromartie15:02:25

I would destructure (reverse fs)

jcromartie15:02:45

like (let [[f & more-fs] (reverse fs)] ...)

nico15:02:25

i noticed that when I wanted to implement the same in js (I'm very proficient in js and it helps me remember things)

nico15:02:53

still lack automatisms in clojure^^

jcromartie15:02:03

wow, that's JavaScript?

nico15:02:07

lol yeah

jcromartie15:02:15

since when? :slightly_smiling_face:

nico15:02:21

recently

nico15:02:31

but you can paste that in your console in chrome

jcromartie15:02:51

I qualify for #beginners in ES6 I guess :slightly_smiling_face:

nico15:02:16

hehe we could help each other :stuck_out_tongue_winking_eye:

tech_hutch15:02:42

I'm the same way, actually. Lots of experience in JS, but new to Clojure.

nico15:02:02

well, let's all learn together :stuck_out_tongue:

nico15:02:22

I still don't know when I'll actually use clojure, but if at least it makes my js code better, it's not a waste

nico15:02:44

I've never thought about reducing lists of functions before, so that's great

tech_hutch15:02:52

Well, you could always write ClojureScript, which compiles to JS :slightly_smiling_face:

nico15:02:02

hehe yeah, thought about it

nico15:02:07

not there quite yet

nico15:02:19

I've heard only good things about om &co

nico15:02:42

so maybe one day :star: :thinking_face:

tech_hutch15:02:52

What are those?

nico15:02:04

om is basically react in clojure

tech_hutch15:02:35

Oh. …I don't know what react is, either. (Never used it.)

nico15:02:48

oh, that explains it^^

nico15:02:07

react is a rendering library (think of it as V of MVC) in javascript

nico15:02:16

it's widely used these days

nico15:02:38

the idea is that the dom is slow and that js is fast. So react is gonna create a virtual dom (a copy of the dom, as a structure), and do operations of that instead

nico15:02:04

and every x milliseconds (rendering cycle), it's gonna apply those changes on the virtual dom to the actual dom

nico15:02:18

it's fairly complex, and you need not to know those details to work with it

nico15:02:48

but basically it gave idea to lots of people and now this paradigm of virtual dom vs dom is popping up everywhere (preact, react, inferno, etc.)

nico15:02:59

and om is the clojure version of what I just described

nico15:02:30

and it also leverage the immutabilty in clojure to make that even faster and better (take that one with a grain of salt, I never tried)

tech_hutch15:02:28

Oh, that's a really good idea. Caching the DOM and applying the changes every so often.

nico15:02:19

it's obviously very simplified

mavbozo15:02:41

@nico have you ever made a large SPA in non-react js? is it laggy compared to the ones made with react ?

nico15:02:45

but I've been working in react for a while now (give or take a year) and i would never go back to angular 1

nico15:02:56

in ng1 and backbone

tech_hutch15:02:08

I've never used Angular, myself, but I know a little about it.

jcromartie15:02:20

I think Reagent is the way to go

jcromartie15:02:24

for React in cljs

mavbozo15:02:26

@nico the ui performance hurts user experience?

nico15:02:32

it's not actually laggy from what I recall. it's just the way you have to put the pieces together that annoyed me

jcromartie15:02:36

om seems a bit incomplete

nico15:02:39

the mess of events is something I don't miss at all

jcromartie15:02:40

Reagent is more pragmatic

nico15:02:24

as I said, I'm a #beginners in clojure, not in js :smile: so I'll just agree with you jcromartie :smile:

nico15:02:23

mavbozo, iirc, the ui was never an issue, this backbone project is still up and running, but I never liked working on it

nico15:02:30

react isn't some magical unicorn

nico15:02:36

but it's a damn pleasure as a dev

mavbozo15:02:35

@nico I never made a large SPA in js before. It's highly likely I'll make one in om.next. Thank you for sharing the experience building a large SPA apps.

nico15:02:05

interesting I would love to hear about that experience later on

nico15:02:16

I only know one website (that I used) made with om

nico15:02:20

and it's pretty smooth

nico15:02:09

apparently figwheel is like the best thing out there for hot code reloading

nico15:02:21

much better than webpack or else

nico15:02:27

still have to try

nico15:02:32

clojure world seems immense

nico16:02:35

is an empty string nil? ?

mavbozo16:02:07

@nico every objects is "true" all the time, unless it's nil or false

mavbozo16:02:03

that's clojure's truth

jcromartie16:02:48

an empty string is not nil? but it is if you call seq on it

jcromartie16:02:02

i.e. (nil? (seq "")) is true

jcromartie16:02:56

but the preferred way of checking an empty (including whitespace) string is clojure.string/blank?

tech_hutch16:02:13

seq returns nil for empty strings because they're empty.

tech_hutch17:02:17

"" is not nil, but seq returns nil when you pass it "".

tech_hutch17:02:19

It, itself, is not nil, but seq returns nil for empty collections.

nico17:02:07

cool thanks!

nico17:02:15

I also noticed empty? works on strings

tech_hutch17:02:50

Oh, I misread. I thought jcromartie was asking a question.

nico17:02:00

oh this is really cool

not-raspberry17:02:06

not-empty is an alternative to calling seq on strings

mavbozo17:02:06

(doc not-empty)

nico17:02:40

oh blank? also works on strings with whitespaces

not-raspberry17:02:36

@mavbozo Doc is in clojure.repl. You have to do /clj (do (use 'clojure.repl) (doc not-empty)) or /clj (clojure.repl/doc not-empty)

nico17:02:37

but there's no not-blank, doesn't seem very consistent with empty? not-empty

mavbozo17:02:11

thanks @not-raspberry

not-raspberry17:02:15

@nico, not-blank would do the same thing for strings as not-empty

nico17:02:33

not exactly

nico17:02:53

>>> clojure.string/blank? ([s]) True if s is nil, empty, or contains only whitespace.

nico17:02:37

so not-blank would return false for "abc", but true for " "

nico17:02:48

while not-empty would return false twice

nico17:02:13

uh oops the other way around,

not-raspberry17:02:21

you mixed not-empty with not-empty?

not-raspberry17:02:21

sorry, with (not empty?)

not-raspberry17:02:34

not-empty is often used when you need a sequential object but want to get nil if it is empty

not-raspberry17:02:30

(if-some [v (not-empty some-vec)] 
  (transform-somehow v)
  [:some :default :result])

tech_hutch17:02:23

Does clojurebot have an open eval we can use? :thinking_face:

sova17:02:01

Hi, when should one use (do ...) versus just stacking a bunch of function calls ?

sova17:02:26

@tech_hutch I think you can evaluate clojure in slack by sending a message to yourself in slack (?)

sova17:02:55

something like that, I forget the exact way. somebody knows.

rootkat17:02:50

"/clj (println "test")"

rootkat17:02:02

minus the enclosing double quotes

not-raspberry18:02:07

@sova use do when you have to. There is no reason to use it in a function body, but it makes sense when you need to do more than one thing in both conditional branches of an if.

(if COND
  (do
    (println "a")
    (println "a"))
  (do
    (println "c")
    (println "d")))
Instead of an if and a single do, you can use when. do is only useful for side effects because in FP if you discard the return value of some function call, you can as well not call it at all.

sova19:02:01

@not-raspberry Thanks, very clear

sova22:02:23

Is it possible to convert from Strings to Vectors

dpsutton22:02:14

can you give sample inputs and outputs?

dpsutton22:02:33

ie, "abc" => ["a" "b" "c"]?

sova22:02:32

Sure! Input: (cljs) "[:nf-token \"$s0omeToken\"][:login-time 1487802419][:user-email \"[email protected]\"][:welcome-string \"Hey, welcome back!\"][:encryption-check true]"

sova22:02:03

Desired output (in cljs) is ideally a map that looks the same

dpsutton22:02:17

so you have a list of key value pairs and want a map?

sova22:02:42

Yes, but more specifically, I have a string that holds this list of kv pairs

sova22:02:52

(and want a map)

dpsutton22:02:03

i'm getting a little lost in all of the stuff

dpsutton22:02:11

can you make a super simple example?

dpsutton22:02:37

"[:a \"bob\"][:b \123]"

sova22:02:38

Haha my bad. I'm just sending some stuff over the wire and my map gets transformed into a string of vector pairs... i should probably be learning how to use Transit instead

dpsutton22:02:58

yeah, i'm guessing there's a setting on whatever is receiving that data to "clojureize" it

sova22:02:08

Right? Single data representation is what I really need to look at...

dpsutton22:02:20

what lib are you calling to get that data?

sova22:02:43

So I'm just passing a {map} in a ring response :body

sova22:02:12

it's the reply of an ajax call. Transit et al. is new territory for me still

dpsutton22:02:47

is it this lib?

sova22:02:21

Ohhh, na I am using Sente.

sova22:02:20

Thinkin' there's a data format toggle in Sente?

dpsutton22:02:38

i can't imagine they would expose the response as a string to you

sova22:02:43

Haha right. That's true. it's a very brilliant library. can't say the same for the implementor at the moment...

dpsutton22:02:12

it looks like sente users a standardizer get-sch-adapter depending upon what transport layer you are using

dpsutton22:02:45

have you registered your transit format?

dpsutton22:02:16

see the make-channel-socket-server that takes an adapter and a serialization format?

dpsutton22:02:42

i've never used sente so i'm hoping i'm near the mark on this one

dpsutton22:02:56

but hopefully you are seeing the result of not telling it how to deserialize responsees

sova22:02:05

Right... I think it's all good, since my websockets comm with Sente is splendid (data works great) but, in this particular case I'm using an Ajax call (because I must manipulate the Ring Session variable, and I cannot do that over web sockets to my knowledge)... so it's kinda a fringe case I'm working on at the moment. I'm not really sure how to pass back data directly over ajax. Although, I suppose I could always do the ajax call to the server to login, set the session, and then web-socket stuff over to the user...

sova22:02:25

( ^ probably more than you want to know about my current foray into web programming land)

dpsutton22:02:33

can you show me the offending line of code?

dpsutton22:02:43

i want to see how you're making the ajax call

sova23:02:18

`
          (dom/button #js{:id "login_submit_button"
                          :onClick ;:onSubmit
                            (fn [e]
                              (.log js/console (str "Submitting:  " login-useremail-input " | " login-password-input))
                              (sente/ajax-lite "/login"
                                {:method :post
                                 :headers {:X-CSRF-Token (:csrf-token @chsk-state)}
                                 :params  {:user-id (str login-useremail-input)
                                           :password (str login-password-input)}}
                                (fn [ajax-resp]
                                  (infof "Ajax login response: %s" ajax-resp)
                                 ..... 
`

sova23:02:41

so the call is sente/ajax-lite

dpsutton23:02:17

i can't find the source for that function for some reason

dpsutton23:02:06

ah, it's in taoensso.encore

dpsutton23:02:32

aren't you serializing it?

dpsutton23:02:34

to a string?

dpsutton23:02:43

(infof "Ajax login response: %s" ajax-resp)

dpsutton23:02:47

you're just printing it

dpsutton23:02:53

are you unable to see it as a map?

dpsutton23:02:21

can you try

(fn [ajax-resp]
    (infof "Is this thing a map? "(map? ajax-resp))
     (other things you want to do)

dpsutton23:02:01

can you post the rest of the callback to ajax-lite that handles the response?

dpsutton23:02:21

because right now you are saying (infof) and just writing it out as a string