Fork me on GitHub
#beginners
<
2017-03-14
>
gamecubate00:03:11

Hello! What’s the idiomatic way to append a key-value pair to a sequence? Say I have:

(defn defaults '(:a 1 :b 2))
and I want to define some function such that:
(my-function defaults :c 3) => '(:a 1 :b 2 :c 3)
?

gamecubate00:03:01

I tried conj but it (of course) appends in reverse order:

(conj defaults :c 3) => (3 :c :a 1 :b 2)

gamecubate00:03:16

What I really want to do is be able to insert an extra argument into a variadic function’s remaining argument sequence prior to invoking another function with the augmented sequence.

rmoehn00:03:20

@alexmiller Thanks! I didn't think of looking for a browser version of Quil, so good that you suggested it. I think I will offer them Quil and Klangmeister for ultimate chaos.

yonatanel01:03:51

@gamecubate Don't you want to use vectors?

gamecubate01:03:56

@tbaldridge concat will do it as long as I wrap the k-v pair in a seq. I guess that’ll do. Thanks.

gamecubate01:03:22

@yonatanel Probably not. I am creating a constructor function (for Threejs) that takes all the arguments I throw at it (

(defn make-scene [& options] …)
and in turn calls separate helper functions (camera …), (renderer …) with same arguments, augmented with a few extra ones the constructor will graft on.

gamecubate01:03:08

Hence my question about appending extra args to a variadic function’s remaining arguments.

gamecubate01:03:47

(defn foo [ & {:keys [a b c] :or {a 0 b 0 c 0}}] [a b c])

(defn bar [ a & options] (foo :a a options :c (* a 3)))

(bar 99 :b 13)

gamecubate01:03:19

As written above, bar fails to forward the args to foo. So needs more work. But that’s the gist of how I would like to invoke bar.

gamecubate01:03:49

Just need to figure out proper way to define bar such that calling

(bar 1 :b 2)
has same results as calling
(foo :a 1 :b 2 :c 3)
.

gamecubate01:03:48

One solution, but seems… heavy:

(defn foo [ & {:keys [a b c] :or {a 0 b 0 c 0}}]
  [a b c])

(defn bar [ a & options]
  (let [c (* a 3)]
    (apply foo (concat [:a a :c c] options))))

(.log js/console (bar 1 :b 2)) ; => [1 2 3]; it works.

gamecubate02:03:42

More concretely:

(defn camera [ & {:keys [fov near far aspect] :or {fov 50, near 1, far 1000, aspect 1.0}}]
  [fov near far aspect])

(defn scene [ w h & options]
  (apply camera (concat [:aspect (/ w h)] options))))

(.log js/console (scene 320 240 :fov 80))

gamecubate02:03:15

So concat was the answer. Thanks for the hint, @tbaldridge .

gamecubate02:03:10

And I did wrap my extra arg into a vector prior to calling concat, so thanks as well, @yonatanel 🙂

decim04:03:58

i’m attempting to set up a very basic clojure app with boot but it’s not pulling in my namespace. https://gist.github.com/anonymous/0763262eebeb829611287ce4e58a1410

rauh05:03:46

@decim What's the error?

seancorfield06:03:46

@decim You have io.pedestal.route in your :require but it should be io.pedestal.http.route instead. See this example https://github.com/pedestal/pedestal/blob/master/samples/hello-world/src/hello_world/service.clj BTW, there's also a #pedestal channel if you have deeper questions about Pedestal.

viveke15:03:20

I am using cljs with react native. I would not like to navigate to another screen on-press. Can anyone please share the peace of example code to do ?

sb15:03:13

Hello, here is a quick function about escape special characters from input boxes? Like (clojure.string/escape “string?” {\? “”}), just I don’t want plus I can’t add all special characters possibilities to this function. Similar function to all spec. characters?

sb15:03:32

I want to check the email input boxes + other adress and else things.

sb16:03:41

Or just with reg-ex? Like this:

sb16:03:42

Is not here something better way to create all things?

ordnungswidrig16:03:44

@sb “Input box”?

sb16:03:00

At registration, where users add the data

sb16:03:21

Sorry, if I use wrong words for this

ordnungswidrig16:03:50

what is the context here? HTML? “special characters” differ from ui technology to ui technology

sb16:03:45

Somebody want to add in the HTML input boxes… something like this.. ?..,.!!’”+”’”+dsds+’”+’ .. and I want to filter it.. or check it.

sb16:03:03

I create the frontend with hiccup and little clojurescript for graphs

sb16:03:24

@ordnungswidrig the question is.. here is a quick solution for this, like clojure repository or example how to create faster than I think..

sb16:03:37

or in-built function

not-raspberry16:03:31

@sb In cljs:

ephyra.core=> (require '[goog.string :as gstring])
nil
ephyra.core=> (gstring/htmlEscape "<script>alert()</script>")
"&lt;script&gt;alert()&lt;/script&gt;"

ordnungswidrig16:03:35

@sb do you want for prevent some characters or simply escape them?

sb16:03:26

Enough the simply escape.

not-raspberry16:03:28

But don't rely on client-side escaping. It can be bypassed easily. Escape it on the server side or make sure templating technologies you use escape variables for you.

sb16:03:38

Ok, thanks!

ordnungswidrig16:03:18

escaping must happen on the client. The server should support the proper processing of virtually the full unicode set.

ordnungswidrig16:03:29

There are nasty unicode characters, like invisible spaces. though.

curlyfry16:03:41

@sb Doesn't hiccup have built-in support for escaping?

ordnungswidrig16:03:43

still the example from @not-raspberry is a good start.

sb16:03:11

@curlyfry I didn’t find.. but maybe yes. therefore I dropped here the question

ordnungswidrig16:03:31

@curlyfry in the output of html, yes. I think here it’s about the return of the values to the server, say by HTTP POST

curlyfry16:03:45

@ordnungswidrig @sb Wasn't it an input box? "Somebody want to add in the HTML input boxes"

ordnungswidrig16:03:51

sombody enters a “dangerous value” into an input box. You want to ensure the client and server process all the characters correctly and the server (and client) does some validation.

sb16:03:30

@curlyfry yes I think, so.. I would like to prevent everything.

sb16:03:49

how did you escape strings in this case?

sb16:03:00

in clojure

sb16:03:38

I do apologize for this.. maybe that is problem just for me, and easy to solve with js

ordnungswidrig16:03:16

the escaping must be done in the request from the client to the server. on the server side you would unencode this (ring form params middleware will do that for you) and then validate and reject invalid values.

sb16:03:49

Thanks! 👍

sb16:03:06

@not-raspberry thank you very.. I see now, you post a solution for this (with clojurescript)

sb16:03:00

Ok, I see now two option with ClojureScript and with clojure.string/escape (little bit more work). Thanks for your help again!!

biofobico17:03:09

I'm learning clojure from reading the Brave and True online book, and like expected I'm struggling in some parts and doing well in others. Since I'm not a programmer I can't see where I can put what I'm learning in practice in the real world (if that makes any sense). So I was wandering if is there a "place" where I can learn clojure while building something?

sbauer18:03:44

Though not clojure specific, you could try implementing a project from one of the lists here https://www.reddit.com/r/learnprogramming/comments/2a9ygh/1000_beginner_programming_projects_xpost/ , or if you were looking for something smaller to do, there is https://www.4clojure.com/ and https://projecteuler.net/

biofobico18:03:58

Maybe something web related since I know html and css

sb19:03:25

@biofobico SafariBooks online > 14 days free trial > clojure videos/ books

sb19:03:43

Lot of content here..

sbauer19:03:11

SafariBooks online is super useful

val_waeselynck20:03:04

@grierson I guess you wan (map (fn [shape] (shape)) shapes) since shapes are 0-arity functions

tbaldridge20:03:16

@grierson sean is right, but the code you want in ? is another function (fn [f] (f))

val_waeselynck20:03:29

which can be shortened to (map #(%) shapes)

tbaldridge20:03:36

or #(%) if you want to be really confusing

tbaldridge20:03:45

lol, @val_waeselynck had the same idea

val_waeselynck20:03:01

@tbaldridge and the same reaction about it 🙂

tbaldridge20:03:07

@grierson but in general we prefer to be a bit more data-driven in Clojure, so we would normally write this the following way: 1) turn your draw functions into a multimethod or protocol 2) turn your list of shapes into data: {:type :circle} {:type :square} 3) Since the draw function is side effecting use doseq instead of map:

(doseq [shape shapes]
  (draw shape))

tbaldridge20:03:35

The idea of a strategy it's as needed in a language where functions are first-class.

grierson20:03:14

Thanks, I will have to read into multimethods and protocols but thanks for pointing me in the right direction.

grounded_sage23:03:44

I've noticed a lot of code now uses a double colon and I'm just wondering what it is?

alexmiller23:03:18

It's an autoresolved keyword

alexmiller23:03:49

It will resolve to a fully qualified keyword

alexmiller23:03:05

With no namespace it will use the current namespace

alexmiller23:03:31

With a namespace like ::foo/confused it will resolve using the namespace aliases

alexmiller23:03:52

^^ pretty good

grounded_sage23:03:23

bookmarked that one thanks!

grounded_sage23:03:03

I'm looking at some code someone wrote for me the other day and they use the double colon to reference an atom. I would normally use the @.

grounded_sage23:03:44

(let [playback-rate (atom 1.0)]
        (add-watch playback-rate ::playback-rate)
         ......

noisesmith23:03:10

that’s not the same as @ at all - in fact that code is very strange

noisesmith23:03:11

that requests that you apply that keyword as a function to the new number if playback-rate changes, which will return nil and do nothing useful

grounded_sage23:03:12

Oh yea I just realised I'm not dereferencing the atom. I'm getting it to watch the actual atom

noisesmith23:03:31

right, but even so, the watch is not doing anything that makes sense

noisesmith23:03:02

that should break, because the function arg to add-watch should take 4 args, and playback-rate takes max 2…

noisesmith23:03:27

anyway, this probably ins’t important, just saying that code makes very little sense

noisesmith23:03:54

oh! - it needs a key, and the function arg is missing

noisesmith23:03:07

I remembered that the function was the last arg, forgot the key arg- never mind

grounded_sage23:03:35

I see the key is to identify the individual watcher and the double colon is to use the current namespace.

noisesmith23:03:52

right, it just needs a function arg after the keyword

grounded_sage23:03:58

all good haha. I wasn't copy pasting so I couldn't be bothered typing it all 😛