Fork me on GitHub
#clojurescript
<
2015-12-29
>
cjmurphy00:12:56

Actually I don't think that will help. I have a suspicion that this is part of the problem:

cjmurphy00:12:04

C:\dev\cardsystem>lein deps :tree
Possibly confusing dependencies found:
[lein-cljsbuild "1.1.1"] -> [lein-cljsbuild/cljs-compat "1.0.0-SNAPSHOT"] -> [or
g.clojure/clojure "1.5.1"]
 overrides

glenjamin00:12:10

cjmurphy: generally i’d suggest requiring the namespace in those cases: goog.string :as str or something

cjmurphy00:12:59

Thanks. Tried all of those but still same problem

cjmurphy00:12:06

;[goog.string :rename {format format-str}]
   [goog.string :as str]

cjmurphy00:12:29

(def format-str str/format)

cjmurphy00:12:44

lein version gives 2.5.3 which I believe is the latest. Have also cleaned (`lein clean`) and reopened the Windows console.

puppybits01:12:42

I wrote a 3 part post on how we use ClojureScript with JavaScript/React at Capital One and why ClojureScript has been so amazing. I just need a couple days to make some graphics for it before posting later this week. I was wondering if anyone would be able to read it over and give any feedback. Please don’t share the links until I publish it later this week. Part 1. F(d)=V for the anti-react crowd (https://medium.com/p/aed339db7da4) Part 2. React and JavaScript using a CLJS lib instead of Flux (https://medium.com/p/a76236d1e1d) Part 3. ClojureScript data layer internals using Components/Core.async/Prismatic Schema/atom-watchers (https://medium.com/p/984ac29da3d7)

cjmurphy01:12:13

Thanks. I solved the issue by reading the [docs](https://github.com/clojure/clojurescript/wiki/Google-Closure-Library) which say you should import not require.

cjmurphy01:12:07

But interestingly I took the require example from code which I'm sure works:

cjmurphy01:12:45

The Om/Next kanban example.

cjmurphy01:12:48

[here](https://github.com/jannis/om-next-kanban-demo), which uses boot which does not work for me on Windows.

mudphone03:12:14

@crocket: I got a sensible cider + figwheel setup going in Emacs. (I saw you ask in #C0B22RS2Y)

blissdev03:12:14

any doo users here?

jaju03:12:41

Oops - sorry! My description got lost and only the snippet was posted. The context is that I’m trying to do a (js/require “…/goog/bootstrap/nodejs”) and I see the above error. My optimization is set to none, if that helps. Have been struggling to find out how I fix this one, but no luck. Anyone able to give pointers?

crocket04:12:49

Does anyone use cats?

blissdev04:12:37

is it possible to run figwheel for dev and doo for testing at the same time?

blissdev05:12:35

perhaps if i use another compilation target?

currentoor05:12:44

If I want to include this lib in my cljs app, how do I go about doing that? For now I won’t use advanced compilation so I don’t need to worry about externs.

currentoor05:12:47

Is there a way to include an npm package into a cljs app?

currentoor05:12:04

Or is there a virtual scroll alternative that you recommend?

crocket05:12:48

@currentoor: If you will run a cljs app on nodejs, just use js/require.

currentoor05:12:17

I see, unfortunately it’s a browser app.

crocket05:12:21

If you will run it on web browsers, compile npm modules into a browserify bundle, include the bundle in HTML, and use js/require.

crocket05:12:39

A browserify bundle can expose js/require.

currentoor05:12:54

what exactly do you mean by js/require? is that the cljs namespace thingy?

crocket05:12:17

CommonJS modules and npm modules can be "js/require"d.

crocket05:12:49

Browserify makes npm modules available on web browsers.

crocket05:12:01

You should familiarize yourself with nodejs.

crocket05:12:37

In cljs, javascript global scope is exposed as "js" namespace.

currentoor05:12:05

I am new to js stuff, why do I need to know nodejs if I’m using cljs for browser apps? And clj for server side?

currentoor05:12:15

I really appreciate the help by the way.

crocket05:12:24

Because nodejs and npm are a big ecosystem.

currentoor05:12:48

oh i see, i thought you meant like a node server

currentoor05:12:16

any suggestions for where to start or should i just hit the googles?

crocket05:12:53

You should first learn nodejs and npm. After you become familiar with nodejs ecosystem, google "clojurescript nodejs"

currentoor05:12:11

thanks a lot!

currentoor05:12:28

this community is always so helpful

crocket05:12:01

Npm is not strictly necessary for react, but it helps in general.

crocket05:12:17

React is available as a plain javascript library.

crocket05:12:51

@currentoor: Actually, since react is available as a plain js lib, you could just start by googling"clojurescript react".

crocket05:12:04

npm libraries work differently from plain js libs.

currentoor05:12:34

i’ll check it out

crocket05:12:36

http://funcool.github.io/cats/latest/ is confusing. Can anyone point me to complementary materials?

crocket05:12:56

I'm new to the concepts of cats.

richiardiandrea05:12:18

@blissdev are you executing Testa with figwheel? To my experience you can mix the two as long as you never include any doo namespace in your figwheel tests. So in replumb at the beginning I had a runner for doo and a runner for browser (figwheel)...if you need it I can try to find the commit. I then switched to doo only as it does too auto testing (in a terminal at least)

richiardiandrea06:12:38

@mudphone did you solve? You have basically forgotten to provide the compiler state, you were almost there :)

blissdev06:12:20

@richiardiandrea: I would be interested in the commit. So if I understand you correctly, currently you don’t run tests while figwheel is running? Or they are running separately?

blissdev06:12:10

basically I’m looking for figwheel to update my frontend code and also run my tests, but it sounds like that may need to be outside of doo then?

mudphone06:12:38

@richiardiandrea: actually haven’t gotten past that error, IDeref?

richiardiandrea06:12:12

@mudphone without passing by replumb you can also have a look at how clojurescript does it.. https://github.com/clojure/clojurescript/blob/master/src/test/self/self_host/test.cljs#L24

richiardiandrea06:12:27

You usually pass an atom containing the state

richiardiandrea06:12:05

But I will dig deeper just give me a sec

mudphone08:12:04

@richiardiandrea: ah it has to be an atom? okay that makes more sense

jaen08:12:28

@currentoor: if you want to use a CJS/AMD/UMD/ES6 modular library from Clojurescript currently the best course of action is to preprocess it using webpack/browserify/what have you to remove the modules and then use the resulting javascript file as a foreign library.

jaen08:12:40

@crocket: it can be confusing if you don't know anything about functors/applicatives/monads. Give me a moment, I'll scour my links for a sensible monad tutorial, without any burrito comparisons.

slink4408:12:13

I am trying to get through the om-next Remote Synchronization Tutorial (https://github.com/omcljs/om/wiki/Remote-Synchronization-Tutorial). There may be something that I am doing wrong, however I think there may be some issues with the tutorial. One problem that I found a solution for is the search-field function should use onChange instead of onKeyUp (https://github.com/omcljs/om/issues/535). But there is a another problem that I have not been able to solve. The following code: (defn send-to-chan [c] (fn [{:keys [search]} cb] (print search) (when search (let [{[search] :children} (om/query->ast search) query (get-in search [:params :query])] (put! c [query cb]))))) Produces the following error: Uncaught TypeError: Cannot read property 'call' of undefined core.js [446] om_tutorial.core.send_to_chan next.js [3034] http://om.next.Reconciler.om$next$protocols$IReconciler$send_BANG_$arity$1 protocols.js [303] om$next$protocols$send_BANG_ next.js [1656] anonymous If I change the following code: (let [{[search] :children} (om/query->ast search) query (get-in search [:params :query])] to the following: (let [{[search] :children} "" query "clojure"] then I get some results, but for some reason using the code from the tutorial is giving me the error. Any help would greatly be appreciated.

jaen09:12:58

Hah, I must say it's hard to choose a good monad tutorial, when you already understand that concept, because anything that uses analogies is probably misleading and on the other hand just staring at the monad definition doesn't give you any intuition on how to use it '

crocket09:12:03

I was planning to learn monad from haskell books. Error handling in nested if statements becomes complex and ugly very quickly. I want to implement a pipeline of processes for cleaning files.

crocket09:12:38

I thought about using transducers, but transducers do not help that much without error types.

jaen09:12:14

Well, for a la monadic pipelining of function you can use some->, but that's just one specific use case.

jaen09:12:41

Yeah, Haskell materials are good for learning about functors/applicatives/monads, in fact most of my links are Haskell-based.

crocket09:12:49

What I want to do is 1) detect character set of a file's content. 2) If confidence of character set detection is below a certain threshold, stop 3) Otherwise, if the character set is not UTF-8, transcode the file content into UTF-8 4) If it has carrage returns, remove them. 5) Save the file.

crocket09:12:24

That is certainly a pipeline. Would cats solve my character set conversion problem elegantly?

jaen09:12:47

Well, anyway those are the links that seemed to made most sense for me as introduction to those concepts: Functor/Applicative/Monad: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html Monad-specific: http://www.idryman.org/blog/2014/01/23/yet-another-monad-tutorial/ http://fsharpforfunandprofit.com/rop/ And afterwards you probably should just read typeclassopedia. It's fairly technical, but I think it's the best way to understand monads, that is through understanding their laws as they are and not analogies. It also tries to suggest what could be the intuition and usages for those typeclasses. https://wiki.haskell.org/Typeclassopedia Also "Haskell Programming from first principles" has really good chapters on those concepts, but it's a book for learning Haskell, so it might be more than you want.

jaen09:12:51

Ok, now to the problem.

jaen09:12:02

This sounds like something you could achieve with just some->

crocket09:12:25

The problem is that I want to extract confidence and report it.

crocket09:12:32

file 1: UTF-8 confidence 0.94, conversion not needed
file 2: EUC-JP confidence 0.93, conversion done.
file 3: confidence 0.80 is below threshold 0.90
...

jaen09:12:57

(some -> file
  (detect-character-set)
  (is-confident?)
  (encode-into-utf8)
  (strip-newlines)
  (write-out))

jaen09:12:55

detect-character-set would probably need to return a map, something like {:character-set "CP1250", :confidence 0.5 :file file}

jaen09:12:54

then is-confident? would have to do something like (fn [arg] (when (> (:confidence arg) threshold) arg))

crocket09:12:56

detect-character-set(file_buffer) -> {:charset_name "UTF-8" :confidence 0.99}

jaen09:12:06

This means if confidence is high enough

jaen09:12:10

You get the map back

jaen09:12:13

otherwise you get nil

jaen09:12:24

and this will short-circuit

jaen09:12:38

You also need to report those you are not confident enough in

jaen09:12:54

So yeah, some->/`Maybe` is not enough.

jaen09:12:57

You need Either.

jaen09:12:10

So yeah, sounds like you need monads to make this elegant.

crocket09:12:52

Currently, it looks like

(defn- clean_file!
  [file]
  (let [content (.readFileSync fs file)
        {:keys [charset_name confidence] :as charset} (detect_charset content)]
    (if (< confidence confidence_threshold)
      (str "The charset confidence of " file " is below the threshold "
           confidence_threshold ".")
      (if (not= target_charset charset_name)
        (if-not (str/index-of (.toString content) "\r")
          (str file " is in a good shape.")
          (let [decoded_content (cr (.decode iconv content charset_name))]
            decoded_content))))))

crocket09:12:04

A simple pipeline became convoluted if statements.

jaen09:12:56

Right, give me a moment.

crocket09:12:34

cr removes carriage returns.

jaen09:12:17

Hm, what happens when file is a wrong path in your case?

jaen09:12:32

Does it return a nil, blows up or does something else?

crocket09:12:05

fs.readFileSync throws ERROR.

crocket09:12:23

> fs.readFileSync("system2.txt")
Error: ENOENT: no such file or directory, open 'system2.txt'

jaen09:12:11

Is that something you want to keep?

crocket09:12:26

I didn't have time to think about it.

jaen09:12:38

So I'll leave that as-is then

crocket09:12:45

Let me upload my code to github.

jaen09:12:25

Now let me just figure out how to run REPL there. Never tried node.

crocket09:12:33

The template upon which the project is based has instructions on launching REPL.

jaen09:12:42

Complains about node-icu-charset-detector, I supose I have to add that to package.json?

crocket09:12:02

@jaen : I pushed a new commit to address npm modules. I also updated README

crocket09:12:58

Sorry, I updated README again.

jaen09:12:36

Should (require 'convert-to-utf8.core) work from the figwheel repl?

crocket09:12:09

You don't have to require. You can move to it. But, figwheel loads everything on every change. So, you can require.

jaen09:12:16

Yeah, it seems so

jaen10:12:33

@crocket: TFW I lost the most time because I misplaced a paren closing let too early and the code still compiled, but was wrong "

jaen10:12:39

But in the end it looks something like this

jaen10:12:51

Though I'm not sure if that will be to your liking - clean-file! now reads really simply, but the definitions of steps are more verbose.

crocket10:12:26

clean-file! was unmaintainable.

crocket10:12:58

I couldn't wrap my mind around if statements.

crocket10:12:24

I think it can become more elegant and less verbose, though.

jaen10:12:50

Well, monads in Clojure are more verbose than in Haskell for example, since they are not a basic building block of the language.

jaen10:12:14

But on the other hand the branching logic is now handled by Either, so you don't need to use if in clean-file!

jaen10:12:50

When is-confident? returns a Left, then convert-to-utf8 becomes a no-op`.

jaen10:12:10

Anyway, feel free to ask questions if something's unclear.

crocket10:12:59

Is there an alternative to monad on clojure?

jaen10:12:32

To monads in general? Sure, Clojure is not Haskell, when you can't, say, do IO without monads.

jaen10:12:07

Before I realised your case also needs information when something fails

jaen10:12:11

I was proposing to use some->

jaen10:12:23

Which is a good alternative to a Maybe monad

jaen10:12:30

That is something that can work, or return nothing.

jaen10:12:47

But in your case you also wanted information on what happened in the failure case.

jaen10:12:59

Which needs a return value on failure.

jaen10:12:10

I suppose you could cheat a bit, and do something like this

jaen10:12:29

No monad in sight

jaen10:12:00

But this is no longer pure - you do a side effect inside is-confident?

jaen10:12:13

And the error is no longer a return value

jaen10:12:21

You can't know what went wrong later in the code

jaen10:12:25

Because all you get is a nil.

jaen10:12:19

Also instead of monads you can try returning tuples like [:sucess value] and [:error "some error"] and then destructure them either with let or core.match, but this will be more verbose in usage than monads

jaen10:12:51

Since you will have to let / if or match when composing things - monadic bind handles that for you.

johannjohann10:12:38

is throwing an exception when its below the threshold out of the question

jaen10:12:33

But is this a really exceptional situation though? I mean, that's another way to do it, but I at least view exceptions as something of a last resort, when everything crashes and burns, not when something mildly unexpected happens.

jaen10:12:11

And catch/try is also more verbose with composition

johannjohann10:12:18

i mean in this case its a branch of logic that just says 'hey this is outside your expectations'

crocket10:12:29

Exceptions are like GOTO.

johannjohann10:12:31

so it would make sense to just assert the condition in the write file

crocket10:12:41

You don't know where exceptions will go if you're not careful

crocket10:12:08

Exceptions are fine for unexpected errors.

crocket10:12:23

Like OutOfMemoryException

johannjohann10:12:17

yeah i dont know--if you had a directory of files

crocket10:12:21

And, my problem is totally expected and modeled.

johannjohann10:12:36

id probably do a group-by with your confidence threshold

johannjohann10:12:34

cool example to mull over simple_smile

crocket11:12:11

group-by would destroy file order.

johannjohann11:12:31

yeah i dont have intuitons about how thats in the scope of the problem, perhaps i shall scroll up a bit and read what your problem is lol

johannjohann11:12:21

i guess i also think it'd be simpler if you just built up a structure for all your files and just did a filter for all those above the confidence threshold

johannjohann11:12:08

basically is-confident can be a field in a hashmap, convert-to-utf8 also

johannjohann11:12:20

ive been reading up on the closure compiler--this is pretty interesting simple_smile https://closure-compiler.googlecode.com/files/closure-compiler-ast.pdf

crocket11:12:30

@jaen : Is haskell superior to clojure, then?

jaen11:12:45

Yes and no.

jaen11:12:18

It depends on the set of tradeoffs you want to accept.

crocket11:12:28

What tradeoffs?

rm11:12:41

crocket: haskell is very complex to write on, but if it's compiling than it's probably works right

jaen11:12:48

For example Haskell has static typing. Static typing is wonderful. You can catch errors before you even run program, more than that - you can type your program in such way, that writing wrong code is literally impossible (to a certain degree of course, Idris for example is even more powerful in that regard), but at the same time you need to learn to think in abstractions that are needed for you to speak in a way Haskell (and Haskellers) understand.

jaen11:12:25

That means you need to invest more effort up front to get accustomed to all the plethora of typeclasses and how to handle them.

jaen11:12:31

But when you grok it, it becomes natural.

jaen11:12:44

On the other hand you can start writing Clojure almost from the get-go.

jaen11:12:17

Because it has no rigid semantic framework on top.

jaen11:12:43

You can just Indina Jones your way through writing a program.

jaen11:12:35

And given Clojure is functional and immutable, you already have an edge over other dynamic languages, like Ruby, but Haskell is above that still.

jaen11:12:51

So then, it's just a question of what you want to accomplish.

jaen11:12:17

For example when writing a website Clojure's ratio of power-to-effort is pretty spot on.

crocket11:12:27

I already told you what I wanted to accomplish today. Is haskell better suited for my needs of today?

jaen11:12:14

But when you want to write code for a Mars rocket and make sure it won't explode en route and astronauts will die, get Haskell or Idris.

jaen11:12:21

If that's the question you phrase

jaen11:12:24

I'd say - no.

jaen11:12:41

You will have to learn too much to efficiently accomplish the same.

jaen11:12:30

If you look at this image here - http://farm4.staticflickr.com/3109/3251176498_c3485a55fb.jpg - Clojure is more like pico, Haskell is more like vim.

jaen11:12:05

You get loads more expressive power, but at an upfront learning cost, that for your task is just prohibitive.

rm11:12:37

crocket: you're creating problem from nothing. Just use monads as jaen adviced. You don't want to learn new language because of 50-lines program

jaen11:12:15

Well, that is not an imaginary problem - it is true that monads in Clojure are somewhat on the verbose side.

jaen11:12:06

The same in Haskell would have probably been more succinct.

crocket11:12:34

I think there is a better abstraction than monads for my problem, but I have to figure it out, yet.

jaen11:12:00

But then imagine this - you can't call print wherever you want in Haskell. In Clojure you are free to do it wherever you want.

krisajenkins11:12:39

FWIW, I don’t think monads work very well in Clojure. Or rather, I don’t think arbitrary higher-kinded types work well in Clojure. The overhead of keeping track of which types are expected where becomes exponentially harder...

jaen11:12:47

@crocket: well, I did offer a version without monads later on for what it's worth.

jaen11:12:19

@krisajenkins: well, that's one thing, but apart from that the syntactic overhead is quite noticeable as well, I think.

crocket11:12:22

My brain is too exhausted, but I had a feeling that there was something better. Something that sticks to clojure idioms. I'll have to wait a day for my brain to fully recover.

krisajenkins11:12:49

@jaen, yes, that’s true too...

jaen11:12:38

@crocket: that sounds like an idea; sometimes things just tend to sort itself out when you sleep over them or something.

johannjohann11:12:31

the main issue with some-> was it doesnt let you do something with the 'left' branch right

govind11:12:36

Probably a macro could help in making the syntax more succinct?

crocket14:12:57

I have to borrow ideas from transducers to remove monads.

crocket14:12:09

Backward comp hurts my brain.

crocket14:12:22

I required goog.string by (ns (:require [goog.string :as gstring])), but I can't invoke gstring/format.

jaen14:12:39

Hm, this is apparently the right way to do it according to - https://github.com/clojure/clojurescript/wiki/Google-Closure-Library

mfikes14:12:05

@crocket: give ns a name

jaen14:12:10

Oh, right. So it interprets the next form (that is (:require ...) ) as the name without a warning?

crocket14:12:50

I have been implementing a variation of transducer.

dnolen14:12:17

@crocket: goog.string.format is its own namespace

mfikes14:12:21

Also, looks like format is special (in its own file, thus needing explicit require)

crocket14:12:39

I guess it was a figwheel loading issue. gstring/format works now.

dnolen14:12:32

@puppybits: looks like cool stuff

dnolen15:12:22

@cjmurphy: not sure if this got sorted out earlier but goog.string.format is a namespace

dnolen15:12:51

you can’t just goog.string :refer [format]

crocket15:12:43

Wait a minute.

crocket15:12:54

How did I invoke goog.string/format?

cjmurphy15:12:53

@dnolan Importing solved the problem. Just then I just went back and required [goog.string.format], and still same problem "TypeError: Cannot read property 'call' of undefined", so I am going to stick with the import solution.

crocket15:12:47

It seems goog.string.format is a function.

crocket15:12:35

(:import goog.string.format) makes format available.

cjmurphy15:12:03

Yes it does. Exactly that works for me.

cjmurphy15:12:29

But in the kanban demo there is require of [goog.string.format], then used as (gstring/format "%s (@%s) " name username).

cjmurphy15:12:37

So that should work too and probably I was being careless and not invoking it in exactly the same way when I surmised that require did not work.

jaen15:12:09

Hmm, I think it's all related to how GClosure modules work

jaen15:12:53

Basically, GClosure modules create a top level structure that corresponds to the structure of namespaces

jaen15:12:24

So goog.provide('goog.string.format') guarantees you will get a top-level goog.string.format object.

jaen15:12:48

And Clojurescript's some.namespace/function will get translated to some.namespace.function in terms of GClosure modules.

jaen15:12:54

And for some reason so it happens

jaen15:12:11

That the format function is in a separate GClosure module

jaen15:12:19

Hence this weird way of requiring it

jaen15:12:31

I guess that's just the Clojurescript namespaces abstraction leaking.

crocket15:12:41

Leaky abstraction

cjmurphy15:12:07

And for practical use you need to require two things:

[goog.string :as gstring]
   [goog.string.format]

cjmurphy15:12:56

, either that or just import [goog.string.format]

jaen15:12:22

But then you have to refer it by the long name, which is kinda awkward.

jaen15:12:36

Though in the interest of curiosity both

jaen15:12:47

(goog.string.format "%05d" 123)
and
(goog.string/format "%05d" 123)

jaen15:12:58

Work, further underlining how this abstraction leaks ; d

cjmurphy15:12:17

With the requiring there's that extra complication as well. So import the simplest.

davertron15:12:36

hey, I'm having issues using cljsjs in my project. I've set up my project.clj like so

davertron15:12:41

` :plugins [[lein-cljsbuild "1.1.2"] [lein-npm "0.6.1"] [cljsjs/tween "16.3.1"]] :cljsbuild {:builds {:min {:source-paths ["src"] :compiler {:output-to "out/clojurescript_threejs.js" :optimizations :none}}}} `

jaen15:12:46

@cjmurphy: require also works, in fact:

cljs.user=> (require 'goog.string.format)
nil
cljs.user=> (goog.string/format "test")
"test"
you just can't alias it in single step that way.

jaen15:12:07

@davertron: you want triple backticks if you want multiline code blocks, like on github

davertron15:12:28

and then in my main cljs file I'm doing (:require [cljsjs.tween :as tween]) but when I run lein cljsbuild auto I see Caused by: clojure.lang.ExceptionInfo: No such namespace: cljsjs.tween, could not locate cljsjs/tween.cljs, cljsjs/tween.cljc, or Closure namespace "cljsjs.tween"

davertron15:12:42

@jaen sorry about that

davertron15:12:18

I see in my ~/.m2 repo that I have clsjs/tween, and If I unzip it and look at the deps.cljs file I see that it exports cljsjs.tween, so not sure what's going wrong

davertron15:12:28

sorry, cljsjs/tween

jaen15:12:21

Nah, that's no problem, just letting you know for future reference.

cjmurphy15:12:05

:dependencies - is :cljsbuild enough?

jaen15:12:24

@davertron: why do you have it in :plugins and not in :dependencies ?

jaen15:12:51

The tween thing that is

davertron15:12:48

@jaen probably because I'm an idiot simple_smile

davertron15:12:57

@jaen I think that's the problem...

jaen15:12:03

Yeah, I think so.

jaen15:12:08

On the problem part, not the idiot part ; d

davertron15:12:25

I'm new to clojurescript so still trying to figure all this stuff out...

davertron15:12:48

I started the project from a lein template(I think that's the right word for it?) mies I believe

davertron15:12:27

it had some scripts for auto-building/watching etc. and I'm trying to move to cljsbuild because that seems like the "right" way to do things

davertron15:12:36

so fumbling around a bit trying to get things working agian...

jaen15:12:06

Well, if you're just starting out allow me to be as bold as trying to start out with boot.

davertron15:12:10

so now i'm getting an error about "goog" not being defined in the browser console...guess I need to monkey with cljsbuild a bit more

jaen15:12:26

This is a pretty nice steb-by-step introduction to that.

davertron15:12:08

alright, i'll take a look at that

davertron15:12:20

not sure if i want to totally upend everything right now though

davertron15:12:28

is it a major change to go from lein to boot?

jaen15:12:52

Somewhat

jaen15:12:00

But IMO for Clojurescript is well worth it

jaen15:12:14

Cljsbuild's workflow feels unpolished by comparison

jaen15:12:02

(though in interest of fairness my last experiences with cljsbuild was a year ago)

roberto15:12:30

I haven’t used cljsbuild since I started using figwheel

jaen15:12:10

But doesn't figwheel require cljsbuild?

magomimmo15:12:44

@davertron: the first edition of the modern-cljs series was based on cljsbuild. I’m not maintaining it any more and I can’t guarantee they are still working , but I did not delete them: https://github.com/magomimmo/modern-cljs/tree/master/doc/first-edition

dnolen15:12:02

@jaen but it doesn’t actually use it

dnolen15:12:19

it just reuses the project.clj settings supplied to cljsbuild

jaen15:12:29

Ah, I see.

magomimmo15:12:01

@davertron: my personal experience with boot/ cljs is pretty positive

roberto15:12:04

this is an example of my setup in lein (using figwheel:

:cljsbuild     {:builds [{:source-paths ["src/zoom_recordings/ui"]
                                                        :figwheel     true
                                                        :compiler     {:output-to            "target/classes/public/js/app.js"
                                                                       :output-dir           "target/classes/public/js/out"
                                                                       :asset-path           "js/out"
                                                                       :optimizations        :none
                                                                       :recompile-dependents true
                                                                       :main                 "zoom-recordings.ui.core"
                                                                       :source-map           true}}]}

roberto15:12:26

I have all my cljs files under src/zoom_recordings/ui

davertron15:12:10

Obviously being new I'm not particularly tied to cljsbuild

davertron15:12:51

i just installed it because I thought the scripts that came along with the template weren't properly pulling in the cljsjs stuff, but they probably do I just had it in plugins instead of deps...

jaen15:12:13

If you're not particularly tied to any toolchain then I would suggest giving boot a go, but that's just me. I'm quite possibly a fanboy : V

davertron15:12:51

I think it's worth checking out

davertron16:12:01

probably later though simple_smile

davertron16:12:16

the thing about templates is they're great for getting started, but horrible for understanding what is going on...

davertron16:12:58

I peeked into the scripts folder and they're pretty simple, but they're using cljs.build.api and I have no idea what that is or what it's doing for me

davertron16:12:50

I shouldn't say horrible, but it's just harder to know how things are working since everything just works fine out of the box. I like knowing how everything works

davertron16:12:02

i actually went through the modern cljs tuts but it was quite awhile ago and haven't done much cljs since then...trying to jump back in

magomimmo16:12:38

@davertron: in my experience the mix of lein templates generating boot projects is very positive. But consider that by using any template you are risking to not understand what is going on under the scene. At the beginning it’s much better to understand any single bit of cljs

davertron16:12:02

well anyway, that definitely fixed my problem. Thanks for the help and the advice!

crocket16:12:06

I implemented a pipeline with a variant of transducer. It is more like idiomatic clojure since it doesn't involve monads.

misha16:12:15

good evening, folks! what are you using these days to render some basic ((multi) line) charts in cljs ?

cjmurphy16:12:00

I did it using Reagent and SVG, so by hand rather than using a library. Not finished but it was all working.

jaen16:12:22

@crocket: that looks interesting; I didn't yet have a chance to play around with them yet.

genRaiy16:12:15

quick question … does CLJS know how to call out to node.js modules? I seem to remember something like that coming out of the GSOC project...

misha17:12:20

@cjmurphy: thanks. at this point I'd like something as easy as calling a single function over a nested hashmap : )

cjmurphy17:12:40

Yes there's a bit more to it because of multiple lines (each with different units) sharing the same x axis and other things (like data arriving at different times). But below all that it would be that simple. A basic chart is just two axis and a wiggly line, so it can be done in SVG. And any js library would not be right I think - every kind of graph is a little different.

cjmurphy17:12:16

Actually a basic chart is just a wiggly line!

jaen17:12:38

@raymcdermott: if you're talking about node server-side then the GSOC doesn't really have all that much to do with it, you can just use (cljs.nodejs/require "whatever")

jaen17:12:13

If you're talking client-side then you probably should look at webpack/browserify/etc. instead, the GSoC work is not enough to use real world libraries.'

misha17:12:46

@cjmurphy: all of that is true if you don't need axis, some legend, etc., which is not that basic anymore. I guess I meant "basic" as in "come on, it is 2016, and there is no standalone hashmap->multi-line-chart function?"

cjmurphy17:12:10

There is certainly a js library you can use.

misha17:12:27

@cjmurphy: after whole 20 minutes of "research" I'll go with http://c3js.org/ which @asolovyov used for his clojurecup entry. I trust him with not wasting time on "basic" charts simple_smile

cjmurphy17:12:54

Looks great. Is that done in cljs?

misha17:12:00

C3.js D3-based reusable chart library

misha17:12:38

basically convenience layer over d3.js

misha17:12:49

cant find repo though

cjmurphy17:12:41

Mine is complex because of having to have multiple lines at once, that have different units. Most of the code has nothing to do with the visual side.

cjmurphy17:12:38

What you found looks fantastic.

genRaiy17:12:57

thanks @jaen - I didn’t know it was that easy!!

misha17:12:45

@cjmurphy: hm, could rendering 2+ c3 charts at the same spot with some transparency do? for different units that is.

cjmurphy17:12:06

The trick is more in the calculation, because the user wants to see them overlapping. But yes hard to show the numbers not overlapping and that sort of thing.

cjmurphy17:12:33

My goal (still going) is an interactive chart.

misha17:12:11

that's entire journey ahead of you ) have fun

cjmurphy17:12:30

Thanks misha.

sveri17:12:41

Hi, any opinions on a graph drawing library for cljs?

sveri17:12:41

Seems like C2 is the only option, but the latest commit was 2 years ago

puppybits18:12:35

I just published a post on Pure Views ( f(d)=V ). If anyone would like to check it out.

ul19:12:35

what in cljs is the closest conceptually to js generators (ES6 function*s)?

ul19:12:32

i mean, suspendable and resumable computation

jaen20:12:31

Couldn't core.async serve that role?

ul20:12:59

Yes, it was my first thought, but I wonder if anything closer exists.

puppybits20:12:09

I use core.async and transducers for defering work (instead of being suspendable). To me core.async is a high level abstraction (and better abstraction) on top of what generators in ES6 provide.

puppybits20:12:42

this is a great overview of generators/await and core.async: https://www.niwi.nz/cljs-workshop/#_introduction_to_core_async

dnolen21:12:35

@ul go macro is function* but doesn’t expose an iterator interface

dnolen21:12:22

don’t forget that Closure supports a good amount ES6 - I see no problems with a well considered exposing of the various bits of ES6 syntax to ClojureScript

dnolen21:12:30

just needs somebody to write up a tasteful plan

dnolen21:12:12

this topic is probably better suited for #C07UQ678E if anyone is actually serious about it

glenjamin22:12:34

does cljs have lazy-seq? that’s fairly similar to the non-control-flow uses of generators?

fappy23:12:54

hello simple_smile Does anyone have a minute to take a look at https://github.com/frankhenderson/boot-cljs-test-question .... ? The single test in test/silliness/test.cljs isn't getting included when I run boot auto-test'

grav23:12:42

How do I handle a javascript collection that can be iterated over with for … of but not much else? How would I convert such one into a cljs vector?

grav23:12:47

Currently, I have some javascript code that converts it into a js array, eg var a = arr; for (x of it) { a.push(x);}, can I replicate this in cljs?