Fork me on GitHub
#clojurescript
<
2016-04-26
>
kenny01:04:27

What is the string type in clojurescript? e.g. If I have a multimethod defined like below, how would I dispatch on the string type?

(defmulti my-method type))
(defmethod my-method ;;string type goes here 
)

tel01:04:21

What’s the best way to access the current ns in Cljs macros?

tel01:04:34

I’ve seen a few hacky approaches and I imagine there’s nothing standard

tel01:04:42

but is there a reasonably straightforward/simple method?

maria01:04:21

@kenny: ClojureScript strings are JavaScript strings, so I would try js/String.

richiardiandrea01:04:01

@tel what do you want to achieve? depending on that you might want to go bootstrap

tel01:04:08

go bootstrap?

tel01:04:26

I’m trying to get unique strings which reference symbols defined statically in a namespace

tel01:04:09

richiardiandrea: what’s “bootstrap” here?

richiardiandrea02:04:44

So you might want to use a clojurescript in clojurescript approach and inspect the compiler state available at runtime, ClojureScript does not reify namespaces as in Clojure

kenny02:04:20

@maria: Do you know how inheritance works in cljs? I am not sure how to dispatch a multimethod on an ISeq. This works fine in Clojure but in Clojurescript you need to call satisfies? instead of instance? to get the proper "inheritance" check.

richiardiandrea02:04:01

@tel I suggest you to have a look at the cljs.js namespace of clojurescript itself, and ask back here whenever you need help, basically you will need to do something among these lines:

1) create an atom to contain the compiler state
2) find out which part of your state is useful for you
3) query the ast
I described part of all this here: http://lambdax.io/blog/posts/2016-03-22-replumb-ast.html

tel02:04:27

interesting—I’ll take a closer look

richiardiandrea02:04:00

np feel free to ask here afterwards, we are pretty responsive on bootstrap topics 😄

kenny02:04:46

For example, it seems strange that this is false:

(isa? ISeq '())
=> false

kenny02:04:36

And this is true:

(satisfies? ISeq (list 1))
=> true

kenny02:04:08

Is there a way to create the inheritance relationship in such a way that isa? will recognize that relationship?

kenny02:04:26

Or maybe I should use a function other than type for the dispatch function. Not sure..

maria02:04:00

@kenny: ISeq is a protocol, that’s why isa? returns false.

kenny02:04:01

@maria: Do you know if there is a way to get multimethods to dispatch on protocol inheritance then?

maria02:04:24

@kenny: Not really sure how this would look like, since an object can implement multiple protocols.

kenny02:04:51

@maria: I think I am asking the wrong question.. The multimethod dispatching would work on interfaces if the object had a hierarchy. For example:

;; in clojure
(parents (type '()))
=>
#{clojure.lang.IPersistentList
  clojure.lang.Obj
  java.util.List
  clojure.lang.IHashEq
  clojure.lang.ISeq
  clojure.lang.Counted}

;; in clojurescript
(parents (type '()))
=> nil
I think this is the problem. The parents function is returning nil.

kenny02:04:32

Also in Clojure:

(parents (class '()))
=>
#{clojure.lang.IPersistentList
  clojure.lang.Obj
  java.util.List
  clojure.lang.IHashEq
  clojure.lang.ISeq
  clojure.lang.Counted}

kenny02:04:50

I believe if (parents (type '())) returned the protocols and types inherited by '() (in this case cljs.core/EmptyList) the multimethod would properly dispatch.

jannis11:04:40

Do we have any web audio experts here? 😉

mmeix11:04:20

a bit of expert, so maybe can help

jannis11:04:06

@mmeix: Cool, I'd appreciate any ideas. Let me push some code up as a reference

jannis11:04:19

I'm designing an audio pipeline that shall eventually record audio, filter it with a lookahead gate, then chunk it up into short audio blobs and encode those separately.

jannis11:04:37

Right now I'm testing the audio chunking in isolation.

jannis11:04:37

For this, I've set up an AudioSourceBufferNode that is fed with input data (44100 samples linearly distributed from -1.0 to 1.0). The chunker uses a ScriptProcessorNode that at the moment simply copies all audio from in- to output and, in parallel, adds samples to chunks that are then delivered using a callback once they are complete.

jannis11:04:12

So far so good. What troubles me is that in my test code, the ScriptProcessorNode doesn't receive exactly the same samples that I feed the AudioSourceBufferNode with.

jannis11:04:11

Here's a graph visualizing the original input data and the data passed through the script processor: https://i.imgur.com/fxw3RVM.png

mmeix11:04:01

yes, looks weird ...

jannis11:04:02

The values don't start at -1.0, there are sudden jumps and the overall number of samples is way less than 44100.

jannis11:04:14

Which makes me really curious.

mmeix11:04:36

I'll have to play with it myself, can't say at the moment

jannis11:04:12

Ok. You can try the whole thing by running boot dev and opening http://localhost:3000/public/index.html#!/audio_utils.devcards.audio_chunker in your browser.

mmeix11:04:49

never used ScriptProcessorNode

jannis11:04:53

I've experimented with different buffer sizes for the script processor - the image was generated with 4096. It gets better with 8192 and 16384 but still there are samples missing.

mmeix11:04:54

Note: As of the August 29 2014 Web Audio API spec publication, this feature has been marked as deprecated, and is soon to be replaced by Audio Workers.

jannis11:04:06

Yeah, sadly I don't believe AudioWorkers are a thing yet: "These are not implemented in any browsers yet"

jannis11:04:10

From the same page.

mmeix11:04:35

will play with, can't promise anything

jannis11:04:52

Of course not, who would I be to expect that simple_smile

jannis11:04:09

It doesn't make a difference whether or not you connect a MediaStreamAudioDestinationNode to the script processor or the default destination of the AudioContext. That eliminates one potential source of the problem.

Yehonathan Sharvit14:04:04

A question about self-host: what’s the difference between :context :expr and :context :statement in cljs.js/eval-str??

bronsa14:04:19

@viebel: :statement means the return value is discarded

Yehonathan Sharvit14:04:35

@bronsa: I don’t understand (cljs/eval-str (cljs/empty-state) " (def x 12) (if 45 23 21) (+ 1 2)" "bla" {:eval cljs/js-eval :context :statement} identity)

Yehonathan Sharvit14:04:44

returns {:ns cljs.user, :value 3}

Yehonathan Sharvit14:04:01

the return value is 3. right?

Yehonathan Sharvit14:04:08

and it’s not discarded

bronsa14:04:17

s/discarded/not needed/

Yehonathan Sharvit14:04:38

what do u mean by “not needed”?

bronsa14:04:52

that it can be discarded

bronsa14:04:16

in the clojure compiler statement means it will get discarded, I guess that's not necessarily true for cljs

Yehonathan Sharvit14:04:21

(cljs/eval-str (cljs/empty-state) " (def x 12) (if 45 23 21)" "bla" {:eval cljs/js-eval :context :statement} identity)

Yehonathan Sharvit14:04:33

returns {:ns cljs.user, :value 12}

Yehonathan Sharvit14:04:49

here the return value is discarded

Yehonathan Sharvit14:04:22

Are you saying that with :statement the return value is sometimes discarded and sometimes not?

bronsa14:04:40

@viebel: I'm saying that if you need the return value, it's not a :statement. I have no idea what cljs compiles to and what's actually returned in :statement expressions, but taking the return value of a :statement is meaningless

Yehonathan Sharvit14:04:37

what’s the scenario where :statement is relevant?

bronsa14:04:29

(do _1_ _2_ 3)

bronsa14:04:01

1 and 2 are analyzed as :statement, that whole expression will compile down to just 3 and discard 1&2 alltogether

bojan.matic14:04:25

i thought everything was an expression in clojure?

bojan.matic14:04:24

is this just for special forms like if?

Yehonathan Sharvit14:04:10

what :context should I use when I want to evaluate all the expressions?

bronsa14:04:41

:expression if you're interested in the value of the last expression, :statement if you're just compiling them

bronsa14:04:12

@bojan.matic: in clojure, yes. In javascript/jvm no

Yehonathan Sharvit14:04:53

(cljs/compile-str (cljs/empty-state) " (if (> 45 10) 23 21)" "bla" {:eval cljs/js-eval :context :statement} identity)

Yehonathan Sharvit14:04:02

returns {:value "if(((45) > (10))){\n} else {\n}\n”}

bronsa14:04:49

please don't highlight me to get answers, I reply when I can, I'm working ATM. again, if you want the results, use :expr, if you are ok with ignoring them use :statement. In what you just pasted you're trying to access the result and using :statement, which I told you doesn't make sense

Yehonathan Sharvit14:04:22

:expressions seems to work fine

Yehonathan Sharvit14:04:40

But I can’t find any clue to it in cljs source code

Yehonathan Sharvit14:04:46

Is it documented somewhere?

bronsa14:04:46

it's an internal compiler option, not public API

Yehonathan Sharvit14:04:32

how could :expressions work in self-host if it’s not on the source code?

jannis17:04:00

@mmeix: I've investigated the audio issue more closely now. The skipped samples and jumps in the data received by the script processor are caused by it processing data too slowly, resulting in the audio system trying to "keep up the pace". If I let the script processor do nothing apart from copying from in to out and if I trigger the playback/recording only after the web page has finished loading, it's ok. No skipped samples, no jumps.

jannis17:04:48

But as soon as the script processor takes a bit too long or if the machine/browser is under heavier load (like during the initial page load/render), it'll show these problems.

mmeix17:04:02

@jannis ah ... I had an idea like that ... thanks for info!

jannis17:04:13

I guess that's why audio workers are the future - too much interference with the script processor and the rest of the JS running in the same thread.

mmeix17:04:26

yes, obviously

jannis17:04:30

It's way too fragile this way.

mmeix17:04:34

real time systems are not easy

jannis17:04:48

Yeah. Data processing needs to be really fast to not cause glitches. And trying to achieve that in the same thread as the UI is using for rendering... not a good idea. 😉

jannis17:04:09

Luckily, my pipeline is going to run in a web worker, so that should help.

ghaskins23:04:27

hi all, i had a question about the relationship between clojure libraries and cljs

ghaskins23:04:24

is each library generally required to be explicitly ported to cljs before its accessible, most work out of the can, its spotty, or something else?

ghaskins23:04:49

i ask because, while I am not a clojure expert by any stretch, i have a little experience in clojure and am now trying to utilize cljs…i am running into some problems that I am not yet experienced enough to know whether I am just not doing something right or whether its something not available within the cljs environment

ghaskins23:04:56

for instance, i have a nodejs/command-line based cljs script, I was trying to bring in clojure.tools.cli for access to parse-opts, but its not resolving

ghaskins23:04:11

my first question is: should it?

ghaskins23:04:07

if not, is there a registry somewhere that indicates what is and isnt available

ghaskins23:04:38

i apologize in advance if this is a noob mistake