clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
emccue 2021-04-19T13:26:43.241300Z

Using https://github.com/cognitect/transit-js with webpack and getting this at runtime

emccue 2021-04-19T13:26:46.241600Z

TypeError: goog.isArray is not a function. (In 'goog.isArray(a)', 'goog.isArray' is undefined)

This error is located at:
    in App (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in DevAppContainer (at AppContainer.js:121)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:171:19 in handleException
at node_modules/react-native/Libraries/Core/ReactFiberErrorDialog.js:43:2 in showErrorDialog

emccue 2021-04-19T13:28:43.242Z

wasn't getting any error until it tries to actually parse data

emccue 2021-04-19T13:35:40.242400Z

so, their build is broken?

borkdude 2021-04-19T13:36:07.242600Z

@emccue I made a mention of this now in #cljs-dev

p-himik 2021-04-19T13:38:03.242800Z

@emccue Seems like goog.isArray is only used by the printing function. Are you [implicitly] calling toString on the read value?

emccue 2021-04-19T13:38:21.243Z

I am explicitly calling toString

emccue 2021-04-19T13:38:52.243200Z

(val.status == 'success') ? <Text> {val.data.toString()} </Text> ...

p-himik 2021-04-19T13:40:20.243400Z

Four ways to fix it in your build: 1. Wait till it's fixed in transit-js 2. Use an older version of ClojureScript 3. Patch the goog object (might be finicky in the release build) 4. Roll out your own implementation of toString

borkdude 2021-04-19T13:40:27.243600Z

@emccue a workaround for now would be to downgrade CLJS to the previous release, file an issue at transit-js. wait for them to bump it to the newest closure and then upgrade again

emccue 2021-04-19T13:40:32.243800Z

I'm not using clojurescript

emccue 2021-04-19T13:40:53.244Z

i just am using the npm dep, which says it has no dependencies

borkdude 2021-04-19T13:41:04.244200Z

oh, hmm. then use an older version of closure explicitly

emccue 2021-04-19T13:41:17.244400Z

closure isn't in the dependencies

emccue 2021-04-19T13:41:26.244600Z

so pick an older released build from them?

borkdude 2021-04-19T13:44:21.244800Z

I have no idea how this works, but perhaps ask in #clojurescript

emccue 2021-04-19T13:45:23.245Z

Works if I downgrade to 0.8.861 from 0.8.867

emccue 2021-04-19T13:45:50.245200Z

so confidence in library has gone from an 8 to around a 3

p-himik 2021-04-19T13:47:04.245400Z

FWIW their issues on GitHub are open - you can create an issue there, it might get better traction.

Xarlyle0 2021-04-19T15:52:18.248100Z

Are there any strong opinions on the dot special form for Java interop? I'm using Java interop for my current project and have a feeling that the dot special form somewhat obscures what I'm doing, so I haven't used it, but I wanted to see if there are any opinions about it. When would it be better to use the dot special form for working with Java classes?

2021-04-19T15:58:16.248700Z

I've never had to use . on its own, but it could be convenient in constructing readable macros

2021-04-19T15:58:33.249100Z

for anything else we have regular method calls and member access

nilern 2021-04-19T16:01:36.249800Z

I think most people prefer the (.foo bar) version. But it makes sense to have just one special form . in the end and there is a very long Lisp tradition behind that flow.

borkdude 2021-04-19T16:04:33.249900Z

@emccue Check #cljs-dev for more info

wombawomba 2021-04-19T17:31:14.256900Z

Why precisely aren't nested #()s allowed? Having bindings shadow other bindings seems to be deemed okay in every other situation. Is there another reason?

2021-04-19T17:36:20.258400Z

Perhaps because defining anonymous functions using fn is more general, and #() would get even more confusing when nested than not nested?

2021-04-19T17:36:27.258700Z

I am guessing -- I did not define the language.

2021-04-19T17:37:57.260500Z

Consider #(foo #(inc %) %). If foo applies an anonymous fn to a collection, you might want the outer % to be a collection and the inner % to be one item from the collection, but if foo works like an if, you might want both %’s to be the same value.

☝️ 1
wombawomba 2021-04-19T17:38:59.260700Z

Yeah I guess it could be something like that, but then that seems inconsistent with e.g. allowing nested ->>/`->` when there's the more general and less confusing as->.

2021-04-19T17:39:16.260900Z

#() is a reader macro built into the reader.

2021-04-19T17:39:39.261100Z

->> and -> are macros that anyone could define if they did not exist in the language, and the Clojure compiler never tries to prevent you from nesting macro calls.

2021-04-19T17:40:33.262400Z

Basically, nesting #() is highly likely to generate edge cases that the reader/compiler isn’t going to have a good way to distinguish between.

seancorfield 2021-04-19T17:40:38.262600Z

@wombawomba as-> is not a “more general” threading macro: it is intended to be used in specific cases inside -> pipelines for expressions that require the value to be passed into a slot other than the first or the last.

👍 1
2021-04-19T17:40:41.262900Z

regular macros and "reader macros" are implemented very differently, and Clojure does not allow you to define your own reader macros.

2021-04-19T17:40:57.263700Z

without changing your copy of the Clojure reader source code, that is, which almost no one does.

2021-04-19T17:41:20.264700Z

(fn [%] (foo (fn [%] (inc %)) %)) <- works tho

wombawomba 2021-04-19T17:41:25.264900Z

Wouldn't it be simple to have the innermost % always bind to the 'tightest' #(), and let users use fn if they want something else?

seancorfield 2021-04-19T17:42:05.265600Z

(-&gt; (something) (as-&gt; v (do-stuff :to v :with 13)) (something-else)) is the intended usage. as-&gt; is expected to be very rare in real world code.

2021-04-19T17:42:35.266300Z

When you ask "why is it this way?", part of the full answer is "what was Rich Hickey thinking when he designed it with this restrction?". You might find someone who knows the full answer because they heard Rich Hickey answer that specific question, or found an answer he wrote in the Clojure Google group to link to, but other than that, the best we can do is guess.

✔️ 1
2021-04-19T17:43:02.267400Z

It would not be difficult to change the Clojure reader to enable the behavior you describe. That isn't the way it is now.

2021-04-19T17:43:16.267900Z

@wombawomba I think a decent guess is, “it’s confusing, and rarely necessary.”

wombawomba 2021-04-19T17:43:46.269300Z

Yeah that makes sense. I wonder if there could be historical precedence though? How do other lisps deal with these sorts of anonymous lambdas?

2021-04-19T17:43:55.269700Z

Note: I am not saying "Never ask such questions." I am simply trying to tell you the best kinds of answers you can expect.

2021-04-19T17:44:16.270600Z

Confusing because, by definition, it means you have multiple implicit contexts with unnamed parameters floating around.

NoahTheDuke 2021-04-19T17:44:27.271300Z

i don't know of any other lisps that have a reader for lambdas like clojure does

2021-04-19T17:44:37.271900Z

Common Lisp and Scheme both have something similar to Clojure fn, which nest.

wombawomba 2021-04-19T17:44:46.272200Z

The main reason I ask is that disallowing things just because it might be confusing for users seems to run contrary to the Lisp tendency to make things as simple as possible.

seancorfield 2021-04-19T17:45:18.273600Z

Given that the general guidance for #() is that anonymous functions should be very simple expressions and you should use a named function for anything complex, I would say “nested function uses” would fall outside “very simple expressions” in the first place 🙂

☝️ 1
wombawomba 2021-04-19T17:45:27.274Z

Perhaps the answer is that other Lisps just don't have this thing in the first place, because it's simpler to just have one way to define functions

2021-04-19T17:45:44.274400Z

I do not recall anything quite like #() in Common Lisp or Scheme, although Common Lisp lets you define your own reader macros (which Clojure does not support, by design choice) which might let you define something like #() yourself.

2021-04-19T17:46:27.274500Z

You’re only looking at one side of the tradeoff.

2021-04-19T17:47:03.274700Z

The question isn’t just, “is this confusing vs simple.”

2021-04-19T17:47:16.274900Z

The question is also: What do you get for allowing something?

2021-04-19T17:47:25.275100Z

And the answer here happens to be: Virtually nothing.

2021-04-19T17:47:47.275300Z

You get to type a little less in one specific (and rare) scenario.

2021-04-19T17:48:09.275500Z

And (like Sean said), it’s a scenario you arguably don’t want to be in in the first place.

2021-04-19T17:50:15.276100Z

So, the scenarios are: 1. You have to write a recursive parser for #() and users might find it confusing. 2. Don’t allow it. Users might still find it confusing. No other downsides.

wombawomba 2021-04-19T17:51:11.276500Z

Arguably users might find having just (fn []) be less confusing

wombawomba 2021-04-19T17:51:38.276700Z

Still, fair point

2021-04-19T17:52:38.277100Z

You can write perfectly fine Clojure programs that never use the #() syntax. It still helps to know it if you run across it in other people's code.

Karol Wójcik 2021-04-19T17:59:28.279200Z

How to destructure inner :app properties to keys? Something like, but working

(let [{:app/keys [useragent] :app} {:app {:app/useragent {}}] 

2021-04-19T18:01:31.279800Z

You need an extra pair of {} around your destructured value:

(let [{{:app/keys [useragent]} :app} {:app {:app/useragent {}}}]
  useragent)

dpsutton 2021-04-19T18:11:41.282700Z

i think simple things that have multiple "correct" behaviors are generally avoided for inclusion for clojure core. Deep merge, nested literals like this, and other similar problems. They all have different implementations with solutions that make tradeoffs that all make sense, and so there's no natural one that is better for inclusion. Also, since they don't add a huge benefit they are quite easy to not add to the language

👍 1
yuhan 2021-04-19T18:28:08.283100Z

One surprising example I found early on was dissoc-in which seems like such a natural thing to have in the core family of functions - apparently because there's an ambiguity of whether to keep empty maps around if their last key has been dissoc'ed

psetmaj 2021-04-19T18:36:02.284700Z

https://github.com/weavejester/medley - I find myself often including this library because it has made reasonable decisions on many of those situations (and the documentation states any relevant assumptions http://weavejester.github.io/medley/medley.core.html#var-dissoc-in)

🎉 1
2021-04-19T18:40:52.286100Z

Haha yeah, medley is quite useful. Also as a reality check: what I’m trying to do, is it so common that it is offered in medley 😉

NoahTheDuke 2021-04-19T18:47:10.286800Z

medley is by far my favorite of the "should have been in core" function libraries

➕ 1
dpsutton 2021-04-19T18:51:48.287300Z

i think of medley as lovely and thoughtful functions that the core of the language makes easy to write and include

SK 2021-04-19T19:10:27.288200Z

hi! I'm running a test using clojure.test, but get a lot of assertions reported.. any guess how can this happen? (in my deftest, there is a single "is")

SK 2021-04-19T19:10:34.288400Z

Ran 1 tests containing 3785 assertions.
1 failures, 0 errors.
=&gt; {:test 1, :pass 3784, :fail 1, :error 0, :type :summary}

seancorfield 2021-04-19T19:11:07.289Z

@surf-kid24 Is your is assertion inside a loop perhaps?

SK 2021-04-19T19:11:40.289500Z

no, that would be an easy explanation 🙂

dpsutton 2021-04-19T19:12:14.289800Z

are you running your tests like (clojure.test/run-all-tests)?

seancorfield 2021-04-19T19:12:32.290400Z

That would show multiple tests.

SK 2021-04-19T19:12:39.290700Z

no, using a single namespace via clojure.test/run-tests

seancorfield 2021-04-19T19:12:58.291200Z

Can you share the code, or a simplified version of it?

SK 2021-04-19T19:13:19.291700Z

I cannot see anything obvious that would result in this.. I'm just wondering where I could add some logging or a breakpoint or similar

seancorfield 2021-04-19T19:14:09.292200Z

(doto (is ...) (println 'test))

seancorfield 2021-04-19T19:14:54.293200Z

If that prints just one test line, then you have other assertions being run. If it prints 3,785 test lines, then your is assertion is being run thousands of times.

SK 2021-04-19T19:15:33.293500Z

thanks, I'll check this

SK 2021-04-19T19:16:12.294Z

I have a suspicion that I have accidentally used "is" somewhere else

nilern 2021-04-19T19:52:58.294200Z

Reader macros run in the parser, so a nestable #() would make the grammar context sensitive. This is generally avoided as it makes tooling more difficult to build.

nilern 2021-04-19T19:54:15.294400Z

But I think the real reason is that #() is mostly meant to be used as a generalized (and faster) partial like cut in Scheme and _ in Scala

Linus Ericsson 2021-04-19T20:34:14.295300Z

#() has ordered arguments as well, and I can see that an expression like #(something #(something %1 %2) %2 :a :b) quickly could become inconsistent. Which argument is the inner %2 refering to?

2021-04-19T20:35:59.295500Z

This is the same argument someone else made earlier. The semantics aren’t actually ambiguous. They would always apply to the inner-most scope. This is the same way regular function shadowing works.

2021-04-19T20:36:43.295700Z

It’s not a question of, “is this sensical/consistent/good/bad?”

2021-04-19T20:37:53.295900Z

No one here appears to know the real answer, but a fair assumption is, “It’s not worth it.” (Which isn’t the same as, “This example would be inconsistent.“)