Clojurians
#lumo
<
2017-08-02
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

rberger08:08:16

If i do something like the following to be able to use an npm library simple-git

(defonce git (node/require "simple-git"))
and I want to use the function tags from that library, how do I do that? (.tags git cb) gives me:
mygit.core.git.tags is not a function
I’m not quite getting how to use the npm libraries in lumo if they have multiple entry points like tags Thanks!

richiardiandrea10:08:23

don't know if worth an issue but I have noticed a couple of warning during compilation of master:

### Compiling Macro Namespaces
cljs.user=>        #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>                 #_=>
WARNING: Use of undeclared Var cljs.spec.test.alpha$macros/eval at line 112 cljs/spec/test/alpha.cljc
WARNING: Use of undeclared Var cljs.spec.test.alpha$macros/eval at line 135 cljs/spec/test/alpha.cljc
WARNING: Use of undeclared Var cljs.spec.test.alpha$macros/eval at line 245 cljs/spec/test/alpha.cljc
nil

metametadata11:08:57

@rberger according to docs, you need to pass a directory first: (defonce git ((node/require "simple-git") "my-dir"))

anmonteiro15:08:47

@richiardiandrea those are expected

anmonteiro15:08:03

We set! eval later

richiardiandrea15:08:24

ok thanks! it was then a good idea to write here first

hlolli17:08:03

I get a difference with requireing from node and lumo

(js/require "web-audio-api")
Octal literals are not allowed in strict mode.
....
> require('web-audio-api')
{ AudioContext: [Function: AudioContext],
  AudioParam: [Function: AudioParam],
  AudioNode: [Function: AudioNode],
  AudioDestinationNode: [Function: AudioDestinationNode],
  AudioBuffer: { [Function: AudioBuffer] filledWithVal: [Function], fromArray: [Function] },
  AudioBufferSourceNode: [Function: AudioBufferSourceNode],
  GainNode: [Function: GainNode],
  constants: { BLOCK_SIZE: 128 } }
> 

anmonteiro17:08:41

@hlolli (.setFlagsFromString (js/require "v8") "--no-use_strict")

hlolli17:08:06

Magic! wow thanks :slightly_smiling_face: @anmonteiro

anmonteiro17:08:26

@hlolli not magic. we set strict mode in lumo by default because it’s slightly faster

anmonteiro17:08:46

we’ve had a few people bumping into this, I don’t know if it’s a good default yet

anmonteiro17:08:03

if more people complain, maybe I can be convinced to change the default to be similar to Node’s

dominicm17:08:59

@anmonteiro crazy idea, can you override the message? If so, you can link to information

anmonteiro17:08:24

@dominicm open a ticket? :slightly_smiling_face:

hlolli17:08:31

yes, or make an FAQ see if that helps.. yes bit old school to use Octal literals, read that its not recommended to be used.

anmonteiro17:08:31

I don’t know if it’s possible but can explore

dominicm17:08:56

On mobile right now, no github login. Will do if I can remember sometime tomorrow

anmonteiro17:08:28

thanks for the suggestion

hlolli17:08:35

I guess I ask the web-audio-api people to clean the octal numbers, now non strict is seemingly conflicting with strict stuff

(new (.-AudioContext (js/require "web-audio-api")))

'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
	 (new)
	 chai.expect (/home/hlolli/csound/panaeolus/node_modules/chai/lib/chai/interface/expect.cljs:9:12)

hlolli17:08:40

to be fair, the blame is not web-audi-api but 'abc'

anmonteiro17:08:47

@hlolli it seems like you’re still in strict-mode

hlolli17:08:36

yes, you were right. Now it works. If I try requireing in strict, then turn if off, try again, then some dirt(state) is stored in the web-audio-api instance, so this works if it's done in right sequence!

anmonteiro17:08:13

@hlolli just set strict mode to false at the beginning of your script

anmonteiro17:08:27

you may run into issues if you enable it again

hlolli17:08:41

yup yup, I will try to do it conditionally, I'm attempting to use webassembly to run csound in my livecoding app, so if a user wants native installation, then I could see a potential efficiency boost from strict.

hlolli17:08:43

that means with electron, if I play the cards right, panaeolus the livecoding app Im making, could be 1 executeable file that could potentially run out of the box without deps.

hlolli17:08:56

if that succeeds, I'll do a release party in Berlin, free wine, all lumoers welcome :slightly_smiling_face:

anmonteiro18:08:25

just built Lumo against Node 8.3.0-rc which has V8 6.0

anmonteiro18:08:06

should have a different perf profile now that TF + I are enabled by default

dominicm18:08:30

What are they?

anmonteiro18:08:06

TurboFan + Ignition

anmonteiro18:08:33

the new V8 execution pipeline

dominicm18:08:50

Sounds exciting

rberger19:08:24

Let me restate my problem. Once I require a npm library (any npm library that has more than a single function) such as:

(defonce git (node/require "simple-git" "."))
How do I access the functions associated with the library? For instance that library has a .tag function. How would I execute that function in the library that would be represented by the object git? I’ve tried several ways and they don’t work, I’m sure I’m missing something easy, but I can’t figure it out.

rberger19:08:18

If I use the javascript accessor method

(.tags git (fn [err, tgs] (println "Yay; " tgs))))
I get :
mygit.core.git.tags is not a function

rberger19:08:14

This is a general question on how to call functions from npm libraries

dominicm19:08:02

The function is .tag, you're calling tags

rberger19:08:16

(.tag git (fn [err, tgs] (println "Yay; " tgs))))
...
mygit.core.git.tag is not a function

rberger19:08:18

(It is .tags for that library)

rberger19:08:34

Its failing the same way for both. I’m pretty sure there is something wrong with how I’m calling the library from clojurscript in lumo

rberger19:08:58

I found that for a npm library that has a single entry I can do the following:

(defonce gitlatest (node/require "git-latest-semver-tag"))
(gitlatest (fn [err,tag] (println "err: " error " tags: " tag))))
And that works

dominicm19:08:54

I'm not familiar with how you're using require in the first example, what does the . Do?

rberger20:08:12

That was in response to @metametadata statement that I needed to have a path passed as an argument to the library. But it doesn’t work with or without the "."

dominicm20:08:14

Yeah, you don't pass it there

rberger20:08:32

Maybe I’m confusing things with this example using simple-git My question is really how do I call a function from an npm library that has mulitple functions in clojurescript in lumo

anmonteiro20:08:38

require takes 1 argument

rberger20:08:50

It fails the same way with no argument

anmonteiro20:08:57

(def my-lib (js/require "my-lib"))

(.someFunction my-lib)

anmonteiro20:08:05

if the exports of my-lib is an object

anmonteiro20:08:14

but the library can also export a single function

anmonteiro20:08:23

in which case you call (my-lib) directly

rberger20:08:37

Here’s my script:

(ns mygit.core
  (:require [cljs.nodejs :as node]))

(node/enable-util-print!)

(def git (js/require "simple-git"))
(defn do-tags []
   (.tags git  (fn [err, tgs] (println "Yay; " tgs))))

(defn -main []
  (do-tags))
And when I run it with: lumo -c src -m mygit.core I get:
mygit.core.git.tags is not a function
	 mygit$core$do_tags (evalmachine.<anonymous>:5:23)
	 mygit$core$_main (evalmachine.<anonymous>:10:27)
	 cljs.core.Var.cljs$core$IFn$_invoke$arity$0 (NO_SOURCE_FILE <embedded>:389:475)
	 Function.cljs.core.apply_to_simple.cljs$core$IFn$_invoke$arity$2 (NO_SOURCE_FILE <embedded>:777:120)
	 Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$2 (NO_SOURCE_FILE <embedded>:790:244)
	 (NO_SOURCE_FILE <embedded>:6352:455)
	 (NO_SOURCE_FILE <embedded>:5947:221)
	 z (NO_SOURCE_FILE <embedded>:5948:13)
	 Object.cljs.js.eval_str_STAR_ (NO_SOURCE_FILE <embedded>:5949:61)
	 Function.cljs.js.eval_str.cljs$core$IFn$_invoke$arity$5 (NO_SOURCE_FILE <embedded>:5952:508)

anmonteiro20:08:09

@rberger I’ll look into it in like 20 min and let you know

anmonteiro20:08:21

in a meeting right now

rberger20:08:28

Really appreciate it!!! In the mean time I’ll try with another library

hlolli20:08:13

@rberger what happens if you do

(def git ((js/require "simple-git") "./"))

rberger20:08:42

Well that seemed to kind of work. The output is:

Yay;  #object[TagList [object Object]]

rberger20:08:26

So the issue was how I initialized even though the simple-git says the path is optional… Do I just do a js->clj on that object now?

hlolli20:08:59

You probably want to get properties of that object, with aget or .-property

rberger20:08:32

Oh, Ok, Looks like you solved my problem… Thanks!!

anmonteiro20:08:39

@rberger you can do js/console.log FWIW

anmonteiro20:08:50

I think it prints JS objects more nicely

anmonteiro20:08:48

glad your problem is solved. In your case, simple-git is of type 2 in the examples I enumerated above

rberger20:08:49

Ok, though the eventual thing will be to actually use the results. Is there any easy way to turn these async calls into sync calls? I’m pretty new to the JS interopt

anmonteiro20:08:51

the module exports a single function

anmonteiro20:08:09

turning async -> sync is not possible

rberger20:08:11

Any pointers on good patterns of using such async calls in clojurescript scripting applications? My hope is to use Lumo in place of bash or other scripting for ops and for use with AWS Lambda. Having the vast npm libraries is the key right now, but this async style is non-intuitive for me. Thanks again for the help getting me past what turned out to be a simple error.

hlolli20:08:23

I was going to write something long, but in your case, you already have a callback on receive, so the difficult part is done for you there, just call a function, a callback within the callback, where you process the response.

rberger20:08:23

So do I need to use something like core.async to mix the async stuff with my more linear flow of the script?

hlolli20:08:55

if you want the script to have some return value instead of just side effects, then maybe core.async could help you.

hlolli20:08:27

you will find it under the name Andare for lumo (patched for self-hostet cljs repls)

rberger20:08:13

Will give it a try. Was hoping to avoid that, but looks unavoidable. There were some interesting attempts to hide this, but I couldn’t quite get it to work and its a bit old now: http://bryangilbert.com/post/code/clojure/escape-callback-hell-core-async/

hlolli20:08:23

in your case you could do something like

(def res-chan (chan 1))
(defn do-tags []
   (.tags git  (fn [err, tgs] (>! res-chan tgs))))

(defn -main []
(go
  (do-tags)
  (<! res-chan))

rberger20:08:16

Thanks! That will give me something to go on. Appreciate the extra effort to help educate me!