Fork me on GitHub
#clojurescript
<
2016-06-29
>
danburton00:06:53

Does it have to be that dynamic? If you know the set of functions that can be called this way, then just (def funcs {"func1" func1, "func2" func2}) etc, and look it up when it's time to call.

anisoptera00:06:07

yeah, it doesn't have to be arbitrarily dynamic, though reverse lookup is the trick

anisoptera00:06:55

basically i want to call a function that calls the intended function, and as a side effect caches the key that i can use to look it up for next time

anisoptera00:06:43

is there, like, a bidirectional map, maybe?

danburton00:06:10

There should be, don't know of any

anisoptera00:06:54

ok, thanks for the map idea šŸ™‚ i usually just reach straight for the power tools in clj, but sometimes simpler is better

danburton00:06:03

Unrelated: am I reinventing a wheel here or does bidi provide a way for parsing query params?

(defn my-match-route [rs s]
  (let [url (cemerick.url/url s)]
    (when-let [r (bidi.bidi/match-route rs (:path url))]
      (assoc r :query-params (:query url)))))

cfleming04:06:07

@dnolen: One thing Iā€™ve noticed with this - for some reason, arglists and params seem to be gensymā€™ed - is that expected or am I doing something wrong?

cfleming04:06:12

(get-in result [:cljs.analyzer/namespaces 'om.dom :defs 'br :meta])
=>
{:arglists (quote ([opts__9332__auto__ & children__9333__auto__])),
 :top-fn {:variadic true,
          :max-fixed-arity 1,
          :method-params [(opts__9332__auto__ children__9333__auto__)],
          :arglists ([opts__9332__auto__ & children__9333__auto__]),
          :arglists-meta (nil)},
 :file nil}

cfleming04:06:32

Actually, this isnā€™t all of them - it might just be a problem with the way that om.dom is generated.

cfleming04:06:27

It is, sorry for the noise.

wildermuthn05:06:22

Iā€™m running cljs in electronjs on Windows 10, and am hitting an interesting and hard problem regarding cljs.core.load_file being passed forward slashes instead of backslashes. Anyone run into this before? Iā€™m requiring a cljsjs namespace. The forward slashes end up as tabs, as in ā€œapp\target\moment.inc.jsā€ -> ā€œapp argetmoment.inc.js"

wildermuthn05:06:02

Is there a way to ensure the slashes get escaped?

groglogic06:06:48

my fuzzy answer: experiment with double slashes. because Unix/Java world and Windows world generally have opposite leaning slashes, so anything that bridges those two worlds ends up with counter-intuitive multiple level of slash escaping. // \/ \\ etc etc. may be faster to try several permutations quickly, see which passes through

wildermuthn06:06:56

ns and the compiler construct the path, so I think either I need to change some sort of compiler option or thereā€™s some kind of environmental variable

wildermuthn06:06:59

that I might need to use

wildermuthn06:06:32

Or, itā€™s a weird bug?

groglogic06:06:47

@wildermuthn: you might need 3 or more levels of escapes, potentially. depends on how many parsing/encoding phases it must survive through before hitting the real file system query

groglogic06:06:17

@wildermuthn: longer/slower answer is stop using Windows/Microsoft and get away from heavily indirect/abstracted toolsets (Clojurescript/Clojure/Java/Unixy/Windows?) which are more prone to this kind of pain. but that's a longer term solution, I know, sorry. šŸ™‚

wildermuthn06:06:11

Iā€™ll try giving up tomorrow. šŸ˜‰

groglogic06:06:38

@wildermuthn another fuzzy partial answer, almost every smart language/stdlib has the notion of FILEPATH_SEPARATOR, which lets you build filepath strings using it, and it provides a signal that can more robustly pass-through down to the bottommost layers of the call graph, and more likely to safely get translated into the host OS expected filepath separator. if Clojurescript/Clojure has such a thing, use that, rather than a hard-coded "\" inside your strings. Does this make sense? sorry for the indirect answer. am a Clojure newb, though have dealt with many languages over the years, this is a recurring problem.

wildermuthn07:06:37

Thanks @groglogic, I think I only needed to include the js library manually rather than letting cljsjs define foreign paths that use backslashes.

wildermuthn07:06:36

There is probably a better way to do this, but I ended up calling (cljs.core/load-file ā€œapp\\resources\\public\\js\\lib\\moment.min.jsā€) and that seems to work! šŸ™‚

wildermuthn07:06:14

Running nodejs on electron, trying to get around path problems on Window with cljsj/moment ^

pesterhazy07:06:29

@danburton: ah wait you actually used that in your example, right there. d'uh!

kino09:06:12

Hey Folks šŸ™‚ Wondering if anyone may be able to help me out? I've been learning ClojureScript & Om for a couple of days now. I also shared this post in the Om channel. I am having a problem in regards to the following code snippet below:

;; Build the todo-input area to enter a todo task and then when
;; a user hits the return key, add the todo to the list area.
(defn todo-input [todos owner]
  (om/component
   (html
    [:input ;; Type input -> text.
     {:type "text"
      :placeholder "What needs doing?"
      :on-key-up (fn [event] ;; Trigger an event handler.
                   (let [input (.-target event)]
                     (when (= 13 (.-keyCode event)) ;; When user hits ENTER.
                       (om/transact! todos ;; Evlautation closure.
                                     (partial add-todo (.-value input))) ;; Take the value of input.
                       (set! (.-value input) ""))))} ;; After add-todo method has been executed -> reset input.
     ])))
;; Build the add-todo button to capture the input value and add
;; task to the list of todo items. No return key functionality required.
(defn todo-add-btn [todos owner]
  (om/component
   (html
    [:button {:class "add-btn" ;; Button type with class add-btn.
              :on-click (fn [event] ;; Trigger an event and function.
                   (let [input (.-target event)] ;; Event handler.
                       (om/transact! todos ;; Begin evaluation closure.
                                     (partial add-todo (.-value input))) ;; Take the value of input.
                       (set! (.-value input) "")))} "Add task" ;; After adding todo item -> reset input.
     ])))
Essentially, I am unable to capture the value of input when the todo-add-btn submits on-click? My assumptions are that the input is a global variable that also needs to be in the scope of the function todo-add-btn? How would I go about doing this or have I got it wrong?

kauko10:06:21

@kino: So you mean (.-value input) => nil?

kino10:06:52

@kauko: Yeah, it seems as though the method to add any todo task entered into the input field works when hitting the todo-add-btnā€¦ However, nothing is returned or captured, just a blank task. From discussions elsewhere, it looks like the on-key-up (fn [event]ā€¦ and -target event in the todo-input method is binded to the input html element itself, capturing the value. This makes sense as to why it works. In the todo-add-btn method, the on-click is trying to do the same but as the element is a button it attaches itself to the button, hence capturing nothing. It may be best to perhaps have some sort of state in between, that can be used in both the methods to capture the input value?

kino10:06:19

So something like In on-key-up, we have a state called editing-text or (om/transact! :editing-text ā€¦.. Then in on-click, we take the data stored in editing-text as (om/transact! todos ā€¦ editing-text ā€¦) passing it through? Would a strategy like this be achievable?

kauko11:06:46

Sorry, can't help really help you. Seems pretty related to Om.

kauko11:06:30

@dnolen: What is the purpose of the IAtom protocol? What kinds of things should satisfy it? If I have something that can be watched and dereferenced, but not reset or swapped (so it's read-only), should it be an IAtom? Should IAtoms be writable?

anmonteiro11:06:39

@kauko: there's IDeref and IWatchable

kauko11:06:46

@anmonteiro: there's also IReset and ISwap, I'd like to know if I should use a combination of these for checking whether an atom is writable, or just use IAtom

kauko12:06:06

or should IAtom be satisfied if IDeref and IWatchable are satisfied

anmonteiro12:06:38

@kauko: I can't be sure but I'd say that IAtom should be just for atoms (or your own atom impl). If you're implementing something that's not writable just go with IWatchable and IDeref IMO

kauko12:06:47

so if I have my own atom implementation that is writable and readable, that should satisfy IAtom?

anmonteiro12:06:00

Yes if you want transparent support for other libs that might rely on that check

kauko12:06:47

Wondering which one is better. I don't think there's an objective answer here.

kauko12:06:12

Checking for IReset and ISwap is more explicit, but I feel IAtom is the one that should be used

kauko12:06:38

it's just entirely possible that some "custom" atom implementations forget to implement IAtom, but I guess that'd be on them

isak14:06:22

anyone know if the api was broken with figwheel-sidecar recently? was using figwheel-system

bhauman14:06:46

Sorry about that guys

dfornika14:06:50

Hello, I'd like to get familiar with om.next, so I'm working through the Quick Start on the github page. I'm unable to get the first 'Hello world' example up and running. Here's an exerpt from the error message. Is anyone familar with this error?

Compiling target/figwheel_temp/dev/figwheel/connect.cljs
{:tag :cljs/analysis-error}
ANALYSIS ERROR: No such namespace: om-tutorial.core, could not locate om_tutorial/core.cljs, om_tutorial/core.cljc, or Closure namespace "om-tutorial.core" on file null, line null, column null
Exception in thread "main" clojure.lang.ExceptionInfo: Error in component :figwheel-system in system com.stuartsierra.component.SystemMap calling #'com.stuartsierra.component/start {:reason :com.stuartsierra.component/component-function-threw-exception, :function #'com.stuartsierra.component/start, :system-key :figwheel-system, :component #figwheel_sidecar.system.FigwheelSystem{:system #object[clojure.lang.Atom 0x22e9f4f3 {:status :ready, :val #<SystemMap>}]}, :system #<SystemMap>}, compiling:(/home/dfornika/Code/om-tutorial/script/figwheel.clj:4:1)
	at clojure.lang.Compiler.load(Compiler.java:7239)

isak14:06:18

no worries

bhauman14:06:43

@dfornika: yeah it's not able to find your source files

dfornika14:06:58

@bhauman Thanks. I've got the project set up just as suggested in the Quick Start. My figwheel script is:

(require '[figwheel-sidecar.repl :as r]
         '[figwheel-sidecar.repl-api :as ra])

(ra/start-figwheel!
  {:figwheel-options {}
   :build-ids ["dev"]
   :all-builds
   [{:id "dev"
     :figwheel true
     :source-paths ["src"]
     :compiler {:main 'om-tutorial.core
                :asset-path "js"
                :output-to "resources/public/js/main.js"
                :output-dir "resources/public/js"
                :verbose true}}]})

(ra/cljs-repl)

bhauman14:06:38

so you have made it through the checkpoint and have a om_tutorial directory and that directory name has underscores__

dfornika14:06:54

@bhauman: I've got a clojure source file in src/om_tutorial/core.clj

bhauman14:06:11

you need a cljs source file ...

bhauman14:06:36

not a clj source file

dfornika14:06:48

missing the 's'!

dfornika14:06:22

@bhauman: Thanks, I feel silly. Good to have another pair of eyes. Cheers.

dfornika14:06:39

@bhauman: It's running now.

dnolen16:06:02

@dfornika: thereā€™s an #C06DT2YSY specific channel btw, lots of knowledgeable people there

dnolen16:06:26

@wildermuthn: weā€™ve spent some time solving Windows issues but itā€™s possible we missed something

dnolen16:06:44

we just need more Windows user to identify issues and submit patches

dnolen16:06:08

@kauko: IAtom is just a marker protocol

kauko16:06:42

Yeah, but what is it supposed to mean?

kauko16:06:03

Obviously I have to just trust that people use it correctly, but what is "correct use" in this case?

kauko16:06:50

If I get an IAtom, does it mean that the thing can be deref'd, watched, swapped, and reset?

dnolen16:06:15

it probably should yes

dnolen16:06:48

the point of the protocol is to say something satisfies all the the things that the provided Atom type implements

dnolen16:06:28

thereā€™s no enforcement here or anything - but important to do everything otherwise nasty surprises for someone who tries to drop in your Atom replacement

kauko16:06:32

yeah absolutely

kauko16:06:37

that's why I asked šŸ™‚

urbanslug16:06:41

Hey, so Iā€™m reading some docs and in them thereā€™s "The HTTP response will return a Location header pointing on the uploaded image.ā€ So how would I call a function like getResponseHeader(key) or getResponseHeader(ā€œLocationā€) I have nothing past (.getResponseHeader ...)

urbanslug16:06:06

(.getResponseHeader ā€œLocationā€ ...)

rohit16:06:26

@urbanslug: could you give more context? It could be (js/getResponseHeader key) or (js/getResponseHeader ā€œLocation")

dfornika17:06:00

@dnolen: Thanks for the tip on #C06DT2YSY, I'm sure I'll be spending some time there soon.

henriklundahl18:06:57

@urbanslug: (.getResponseHeader response "Location") where response is the object that has the getResponseHeader method.

anisoptera18:06:29

ok, i have a very basic (probably) question

anisoptera18:06:39

basic in terms of understanding level, at least

anisoptera18:06:31

i have some JS code that i'd like to translate into cljs, or, failing that, some way to just insert the code raw into my main js file

anisoptera18:06:08

it's here: https://github.com/screepers/screeps-stats , under "Enhanced Stats Collection"

anisoptera18:06:25

var ScreepsStats = require('screepsstats')
global.Stats = new ScreepsStats()

module.exports.loop = function () {

  // Do code stuff!

  // Run Stats Last.
  Stats.runBuiltinStats()
}

anisoptera18:06:26

i already have the module.exports.loop bit working (from previous work), but my code to do those first two lines does not appear to be working the way it's supposed to - I don't actually get the prototype created properly

anisoptera18:06:44

looking at the generated source, it seems to be equivalent, but it's not exact

anisoptera18:06:09

(set! js/ScreepsStats (js/require "screepsstats"))
(goog.object.set js/global "Stats" (js/ScreepsStats.))

anisoptera18:06:37

and ((goog.object.get (goog.object.get js/global "Stats") "runBuiltinStats")) in my loop

anisoptera18:06:02

(I have an externs file, but this seemed more low-level and thus less prone to error)

anisoptera18:06:51

but when I call runBuiltinStats, it doesn't actually have the prototype for ScreepsStats so the first method call on it fails

anisoptera18:06:39

the generated code has ScreepsStats = require(..., not var ScreepsStats, so I suspect that's what is going wrong. so my question is: how can I get the compiler to generate that var?

rorydouglas18:06:51

blerk- somehow the ā€œenable sourcemapsā€ checkbox in devtools settings got unchecked šŸ˜” - iā€™ll delete the waffle above

rorydouglas18:06:33

probably the first thing i should have checked šŸ˜„

dnolen19:06:49

@anisoptera: is this for Node.js?

anisoptera19:06:16

@dnolen: no, but I think the semantics are the same

anisoptera19:06:34

it's for a game about AI programming

dnolen19:06:15

@anisoptera: Iā€™m asking because it matters mostly whether you actually need advanced optimizations

dnolen19:06:22

if Node.js you donā€™t need to bother

dnolen19:06:51

but if thatā€™s not for Node.js then I would not deal with it in that way

dnolen19:06:02

I just use Webpack or whatever to build a foreign lib

anisoptera19:06:04

I do need optimizations, it makes my dealings with the game API much smoother if it comes out in one big file, and I think I have a somewhat restrictive limit on how much code I can upload

anisoptera19:06:28

(it sure does make my life a lot harder when debugging, though. no source maps = sad panda)

dnolen19:06:28

sure but you cannot apply optimizations to random JS libraries

dnolen19:06:37

hardly anything written for Node.js tooling is going to work

anisoptera19:06:58

it's not written for node.js, it's written for this game's framework

anisoptera19:06:09

but i think the same principles apply

anisoptera19:06:15

i'm uploading the library .js directly

dnolen19:06:28

right so build that stuff separately

anisoptera19:06:30

not trying to optimize that šŸ™‚

dnolen19:06:38

if this is for the browser js/require isnā€™t going to work

anisoptera19:06:48

it's not for the browser, though

dnolen19:06:57

youā€™re missing my point

dnolen19:06:00

it doesnā€™t matter

anisoptera19:06:05

like i can see in the code that js/require is generating the proper call

dnolen19:06:16

if itā€™s for the browser js/require isnā€™t something youā€™re ever going to write

anisoptera19:06:15

right, because you just import it via some other method, i saw the various ways to accomplish this in non-play environments

anisoptera19:06:51

require isn't a JS feature, right? it's provided by whatever framework you're using

anisoptera19:06:01

(I know very little about JS itself)

anisoptera19:06:22

so in this case require is doing something specific to the game's framework

mattyulrich22:06:28

Iā€™m trying to compile/evaluate some cljs in the browser and getting back the following error: "No *load-fn* setā€ Looking around on the web, this appears to be how cljs knows how to load libraries from a :require directive. Am I interpreting that correctly?

richiardiandrea23:06:19

@mattyulrich: yes you need to hook up a load-fn inside the cljs.js/eval-str method. Depending on what you're trying to do I'd suggest also to have a look at https://github.com/Lambda-X/replumb

richiardiandrea23:06:22

I assoc :load-fn! here and then pass the option map as 4th param in eval-str https://github.com/Lambda-X/replumb/blob/master/src/cljs/replumb/repl.cljs#L591

venantius23:06:26

Iā€™m working with some foreign libs written in es6

venantius23:06:55

using lein-cljsbuild, which should just be invoking the compiler, if I specify :language-in and :language-out, will that target my foreign-libs as well?

venantius23:06:04

or will I need to transpile those foreign libs first and then include them