Fork me on GitHub
#clojurescript
<
2017-03-23
>
john01:03:10

Suppose I have a javascript function as a string in cljs. Such as: (def s (str inc)) (= s "function cljs$core$inc(x){\nreturn (x + (1));\n}") how could I then call s, as in: (s 1) => 2

javahippie02:03:29

Hi everybody. I’ve been using Clojure on the backend for some time now, and I would like to start with cljs, too. I have a toy web project in mind (Scrum Poker Web App), where users can simultainously pick cards, and the selection is pushed to other webclients immediately. Right now I need to pick frameworks, and found this page: https://github.com/hantuzun/awesome-clojurescript#web-framework—template. What would be a popular, but already well established choice for a front- and backend combination? My frontend experience is mainly restricted to Angular JS and the bloaty Java server side frameworks (I am not a fan of server side html generation…).

javahippie02:03:00

(I don’t have any experience with reactive programming, but also would like to have a shot at it)

john03:03:36

@javahippie you could go with something like chord: https://github.com/jarohen/chord

john03:03:03

and then choose any clj backend or cljs frontend you like

john03:03:11

But if all you are doing is mostly broadcasting state changes between clients, you don't need too much on the backend

john03:03:29

@javahippie on the frontend there's been a lot of interest in re-frame and Reagent

john03:03:19

Does anyone know if it is possible to get the source of a function using cljs.repl/source programmatically, while not at the repl?

javahippie03:03:06

chord looks great, and I will check re-frame and reagent. Thank you very much, I appreciate your recommendations!

john03:03:14

I'm guessing after advanced compilation, cljs.repl/source will no longer have access to the original symbols?

jimmy04:03:18

hi guys, I would like to use this package https://github.com/algolia/instantsearch.js/tree/v2/packages/react-instantsearch in my application. What is the easiest way to do it ? Thanks

thheller07:03:41

@john why do you need the source of a function? that will only lead to very questionable results at best

john08:03:43

@thheller in order to serialize functions to be evaled in a webworker

thheller08:03:06

don't do that 🙂

john08:03:22

why not? 🙂

thheller08:03:50

can you guarantee that the function doesn't call other functions?

thheller08:03:02

their source won't be in there

thheller08:03:24

but why would you? just load the code in the webworker and send data over?

thheller08:03:21

also it doesn't work with :advanced optimizations at all

thheller08:03:54

since closure can't tell if you use things via eval

john08:03:45

it's moreso of an experiment. I'd like to make a defworker which does a defn (with-meta name {:source (actual source)}).

john08:03:48

then you can pass that function to a worker like you would to an agent. And the worker then updates its state, like a worker.

john08:03:19

like an *agent, rather

john08:03:44

Any defworkers you evaluate on an agent could potentially remember the function definitions on the worker side, allowing you to feed in a series of definitions to initialize it for something in particular

thheller08:03:25

that doesn't work

john08:03:45

But you wouldn't need the defworker if you could always get the source

thheller08:03:49

the worker will always need more than just the source of one function

thheller08:03:31

ie. cljs.core to have access to the collections CLJS offers

thheller08:03:46

but webworkers makes this really easy

thheller08:03:58

you can do importScripts in the worker

john08:03:18

@thheller got all that. I've got a full replum repl running in the webworker with libraries loaded.

john08:03:33

with butler shuttling data between them

thheller08:03:02

then why send the function over if its already over there?

john08:03:15

Why send a function to an agent?

john08:03:49

I guess if you've already defined all your functions, you can just call a look up table on the worker side

john08:03:08

but sometimes you're probably sending in functions created dynamically

thheller08:03:48

I don't know what you are trying to do but serializing functions is bad in JS

thheller08:03:09

pretty much bad in every language probably

john08:03:16

Yea I'm noticing it's not easy, and maybe a bad idea 🙂

thheller08:03:16

definitely bad idea yes 😉

thheller08:03:06

I tried doing something similar a few years back in clojure

john08:03:09

agents in clojurescript is too cool to resist though, so it's a fun experiment 🙂

thheller08:03:16

horrible idea in the end 🙂

thheller08:03:32

they are not agents though

john08:03:49

Well, they don't participate with an stm

john08:03:35

They don't share data and scope in the same way agents do

john08:03:22

but clojure agents are meant to be asynchronous anyway, so it's somewhat similar

thheller08:03:25

I prefer to think in terms of core.async

thheller08:03:35

you send things on one channel and get things back on another

john08:03:59

Yea, but a webworker is a potentially real system thread

thheller08:03:24

technically its more like a new process

thheller08:03:47

threads share memory, webworkers dont

john08:03:10

right, so you have to marshal code. It's not pretty

thheller08:03:12

so everything back and forth has to be serialized

thheller08:03:32

in many instances that is more expensive than just not using a worker in the first place

thheller08:03:00

well depends on the calculations you are doing I guess

john08:03:52

round robin on a pool of hot webworkers couldn't hurt, depending on the load 🙂

thheller08:03:02

doesn't change a thing

thheller08:03:14

the main thread still has to read the data the workers produce

thheller08:03:35

but yeah it all depends on the cost of the calculation

thheller08:03:17

you can still easily starve the main thread if its reading too much data

john08:03:28

well, if your calculation blocks longer than 40 milliseconds, why not send it off?

thheller08:03:54

how much data does it require to send and receive?

thheller08:03:21

assume you are using transit, how long do the write/read take?

thheller08:03:37

the more data the worker needs the longer that takes

john08:03:50

Yeah, it'll be interesting to see what the performance characteristics will be

danbunea09:03:41

Hi, I am trying to do a simple function check using spec in ClojureScript (:require [cljs.spec :as s] [cljs.spec.test :as test]... (defn my-index-of "Returns the index at which search appears in source" [source search] (clojure.string/index-of source search)) (s/fdef my-index-of :args (s/cat :source string? :search string?) :ret nat-int? :fn #(<= (:ret %) (-> % :args :source count))) and (test/check 'my-index-of) instead of returning a problem , always returns [] meaning basically that it doesn't do anything?

danbunea09:03:27

I am basically trying this in ClojureScript https://www.youtube.com/watch?v=W6crrbF7s2s

baptiste-from-paris10:03:50

Hi, I also have a spec question, is there any way to add a humain friendly message to a spec when failing ?

timrichardt11:03:38

i have a problem deploying. everything runs fine in figwheel but the release build throws an Error: [object Object] is not ISeqable...

:dependencies [[org.clojure/clojure "1.8.0" :scope "provided"]
                 [org.clojure/clojurescript "1.9.229" :scope "provided"]
                 [reagent "0.6.0"]
                 [org.clojure/data.xml "0.2.0-alpha2"]]
do i maybe need to include some external js?

timrichardt11:03:12

my lein build profile:

{:source-paths ["src" "env/prod/cljs"]
                        :compiler
                        {:output-to "public/js/app.js"
                         :output-dir "public/js/release"
                         :asset-path   "js/out"
                         :source-map false
                         :optimizations :advanced
                         :pretty-print false}}}}

witek13:03:44

Is there any reason not to have clj/cljs/cljc files containing the same namespace? For example lib.clj + lib+cljc + lib.cljs

dnolen13:03:17

not a good idea

dnolen13:03:09

since it’s possibly ambiguous (to someone looking at the codebase) which file you want lib.cljs to load for macros - I think .clj gets precedence?

dnolen13:03:01

it’s more common to just lib.cljc + lib.cljs

dnolen13:03:45

another optinon is just lib.cljc + self require for macros

Janet A. Carr13:03:49

@timrichardt Looks like you're trying to perform a sequence operation on a javascript object.

timrichardt13:03:29

@janetacarr indeed, the whole thing is related to the externs stuff. i have to spend some time reading how the compiler works... 🙂

timrichardt14:03:08

with :optimizations :simple it works

borkdude16:03:55

I’ve run this code through an extern generator, but it doesn’t generate one for a function named clearAll in the React Virtualized library Generator: http://jmmk.github.io/javascript-externs-generator/ Loaded JavaScripts: * https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-with-addons.js * https://cdnjs.cloudflare.com/ajax/libs/react-virtualized/9.0.3/react-virtualized.js

juhoteperi17:03:18

@borkdude I think react-virtualized does some dynamic magic to add those methods the the class

juhoteperi17:03:58

You can search for clearAll in the JS file to find some suspicious code where methods are defined as array of JS objects

borkdude17:03:01

@juhoteperi What’s the recommended way for cljsjs to add something manually to a generated extern file?

juhoteperi17:03:27

@borkdude Just manually edit the code and add a comment to the top of the file that it has been modified manually

borkdude17:03:39

return (0, _createClass3.default)(CellMeasurerCache, [ {
                    key: "clear",
                    value: function(rowIndex, columnIndex) {
                        var key = this._keyMapper(rowIndex, columnIndex);
                        delete this._cellHeightCache[key], delete this._cellWidthCache[key];
                    }
                }, {
                    key: "clearAll",
                    value: function() {
                        this._cellHeightCache = {}, this._cellWidthCache = {};
                    }

juhoteperi17:03:59

TypeScript has type definitions for react-virtualized (and hundreds of other libraries): https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react-virtualized/index.d.ts

juhoteperi17:03:18

It is on my todo list to write tool to convert typescript definitions to Closure externs

anmonteiro17:03:37

@borkdude it’s just a normal class

CellMeasurerCache.prototype.clearAll = function () {}

juhoteperi17:03:21

@anmonteiro Problem is that in webpack output it is not, so extern generator doesn't find it

anmonteiro17:03:43

yeah, I’m saying for the extern stuff

anmonteiro17:03:57

sorry, meant for writing the manual extern

anmonteiro17:03:13

should work if you write that, right?

anmonteiro17:03:32

there you go, that’s all I’m saying

borkdude17:03:36

wow, ((gobject/get “clear”) 0 0) instead of (.clear cache 0 0) doesn’t even work because of this being the wrong value?

Uncaught TypeError: this._keyMapper is not a function

darwin17:03:55

@borkdude right, in such case (.call f this p1 p2 …)

darwin17:03:39

this expected, you would run into the same issue in javascript as well

darwin17:03:22

(.call (gobject/get cache "clear") cache 0 0)

borkdude17:03:54

Thanks 🙂

darwin17:03:58

btw. cljs-oops does “this retargeting” for you: https://github.com/binaryage/cljs-oops/releases/tag/v0.5.0

darwin17:03:20

it would be (ocall cache “clear” 0 0)

borkdude17:03:30

I’ll use that immediately

borkdude17:03:06

What’s the deal again with refer-macros, isn’t that needed anymore?

anmonteiro17:03:31

so the CLJS compiler can infer them automatically

darwin17:03:47

I just recently discovered that this can be used to avoid writing reader conditionals when requiring macros from cljc files - for code targeting both clojure and clojurescript: https://github.com/binaryage/env-config/blob/master/src/lib/env_config/impl/macros.cljs

darwin17:03:21

and inside macro, I can decide what kind of code I want to generate, depending on current environment: https://github.com/binaryage/env-config/blob/master/src/lib/env_config/impl/macros.clj#L20

darwin17:03:33

...hate to sprinkle reader conditionals all over my code

abarylko18:03:25

I need help trying to make a clj project compatible with cljs

abarylko18:03:51

I renamed the main file from core.clj to core.cljc

abarylko18:03:05

but when I do lein compile it does not generate any classes

noisesmith18:03:23

abarylko what is your :aot setting in project.clj?

noisesmith18:03:34

if it’s not present, compile won’t output anything

noisesmith18:03:01

you could try lein compile :all

abarylko18:03:21

I have :aot :all

borkdude18:03:58

D’oh, the answer was right below that code fragment

john18:03:53

@noisesmith won't @abarylko want to switch to cljsbuild?

abarylko18:03:22

@john Do I need cljsbuid in order to compile cljc ?

john18:03:21

@abarylko I'm guessing not. But if my memory serves, cljsbuild will compile cljc files as well.

john18:03:32

most cljs consumers of your library will be using cljsbuild though. So it couldn't hurt to test with it.

baptiste-from-paris19:03:21

hello guys, is there a way to resolve a symbol in cljsand then apply the function with the Var ?

abarylko19:03:40

Thanks @john & @noisesmith I'll try it out ....

abarylko19:03:14

or perhaps if you know of a project that uses cljc that I could take a look ...

baptiste-from-paris19:03:17

yep, I just saw that

mikepence21:03:10

what is the preferred library to integrate react and cljs, these days?

mikerod21:03:32

@mikepence reagent, re-frame, quiescent, om

mikerod21:03:41

it isn’t clear to me if there is a “preferred"

mikerod22:03:27

I probably would suck at summarizing, but: * reagent = thin wrapper over react that just makes it more "cljs idiomatic” to use (not so OO). slightly “opinionated” (I guess) in its usage of RAtom (cljs atom wrapper) * re-frame = larger “framework” that uses reagent but also pulls together more libs to do things like routing, etc * quiesent = sort of like reagent with a few different goals in mind (good readme there), tries to be very “un-opionated" * om = another wrapper over react, more “opinionated" than others perhaps and was started(?) by David Nolen (lead cljs contributor)

mikerod22:03:47

I’m sure others could correct me on a bunch of that. However, all these projects seem to have pretty good docs.

john22:03:19

after trying to create a macro that updates the meta data of a function, based on examples here: https://cljs.github.io/api/cljs.core/defn- and here: https://stackoverflow.com/questions/9177709/constant-definition-in-clojure

john22:03:47

The results always have no metadata

john22:03:11

it's like the meta data is getting stripped after the macro compiles

john22:03:49

Anyone have an idea why they won't hold their meta data?

john22:03:12

when testing from the repl

anmonteiro22:03:12

@john an example of your macro would be helpful

anmonteiro22:03:24

I’ve done that before and it worked

anmonteiro22:03:54

also, do you want the metadata on the function or on the var?

john22:03:22

@anmonteiro just going with the defn- example:

john22:03:23

(defmacro defn- [name & decls] (list* `defn (with-meta name (assoc (meta name) :private true)) decls))

john22:03:55

If I put that in my macros.cljc file, it will run from the repl, the result has no attached metadata

anmonteiro22:03:02

so you should be seeing your metadata on the var

anmonteiro22:03:24

(my-def my-name …)

(meta #‘my-name)

john22:03:46

@anmonteiro I'm not sure if I'd be better off working with the metadata of the fn or the var.

john22:03:38

I was forgetting to extract the var

anmonteiro22:03:49

Vars are static, so you’ll need to always have the name of the function at hand (i.e. can't get a function via a param and expect it to have metadata)

anmonteiro22:03:16

if you put the metadata on the function, you can call meta on the actual function value, which means the above use case will work

anmonteiro22:03:39

on the other hand, it’s not a JS function anymore, but a JS instance that implements IFn

anmonteiro22:03:41

tradeoffs...

john22:03:45

in the above example, is it adding metadata to the fn or the var?

john23:03:45

Would something like this be attaching it to the fn?

john23:03:45

(defmacro defn- [name & decls (with-meta (list* `defn name decls) (assoc (meta name) :private true))])

john23:03:55

well, parinfer clobbered my binding form 🙂

anmonteiro23:03:01

you’ll probably want (def symbol (with-meta (fn …)))

anmonteiro23:03:42

defn may return the function, or the var, depending if you’re in the REPL or not

john23:03:56

Okay, so I'm getting close. But for some reason the metadata is dropping key-vals selectively:

john23:03:58

(defmacro defn-with-source [name bindings & forms] `(def ~name (with-meta `(fn bindings ~@forms) (assoc (meta name) :const true :source true))))

john23:03:13

(m/defn-with-source o [& a] (apply + a))

john23:03:32

=> (meta o) {:const true}

john23:03:54

:source true is not showing up

darwin23:03:53

@john what are you going to build? some kind of dev tool? wonder why do you need fn sources, just curious

john23:03:44

@darwin I'm experimenting with building agents, similar to clj agents, on top of webworks. So I have to shuttle code over to the worker agents.

darwin23:03:54

and in the example above, I think ~(with-meta ... part is wrong

darwin23:03:02

you want to emit with-meta I guess

john23:03:43

I send the straight javascript to the worker, but I couldn't figure out how to easily apply the then compiled js to potentially cljs parameters, on the worker side