clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
coby 2020-09-10T02:50:04.041700Z

is there a way to get the entire list (or tree) of namespaces that a given namespace depends on, given just the name (symbol) of the ns? e.g.

(ns-deps 'my.project.namespace)
;; ('my.other.namespace 'some.other.dep ...)

2020-09-10T03:00:26.042600Z

given that you can use a symbol by fully qualified name, that's not really possible - of course we can never use fully qualified names as a reasonable convention

2020-09-10T03:00:50.042800Z

there are ns-aliases and ns-refers

2020-09-10T03:06:22.043500Z

user=> (into #{} (map (comp namespace symbol val)) (ns-refers *ns*))
#{"clojure.pprint" "clojure.java.javadoc" "clojure.core" "clojure.repl"}
(ins)user=> (ns-aliases *ns*)
{}
(ins)user=> (require '[clojure.string :as string])
nil
(cmd)user=> (ns-aliases *ns*)
{string #object[clojure.lang.Namespace 0x73044cdf "clojure.string"]}

coby 2020-09-10T03:23:38.043700Z

so by "never use fully qualified names" you mean always use :as? I think that can work for my use-case, thanks for the suggestion!

2020-09-10T03:39:12.043900Z

I am not sure if this is what you are after, but you can see a log of all namespaces that end up being require'd when you do a require with the :verbose option, e.g. like this (require 'my.project.namespace :verbose)

2020-09-10T03:39:36.044100Z

The output will be longer if none of the namespaces it requires have been loaded already. If any have, the things they require will not be shown in that log

emccue 2020-09-10T04:28:20.044300Z

I think it nukes itself on large sequences

emccue 2020-09-10T04:29:56.044500Z

yeah anything xform or transducer goes over my head still, so i'm gonna pass on those versions

2020-09-10T04:45:43.044800Z

I mean that you need either use or refer (which shows up in ns-refers ) or as (which shows up in ns-aliases, and avoid the situation where in one ns you use require [clojure.string :as string] and in another you use (clojure.string/join ...) - that's the situation where the relationship is invisible / unqueriable

1
2020-09-10T04:46:41.045Z

what about combining :reload-all and :verbose ?

2020-09-10T05:03:12.045200Z

Good idea. That should be more complete than leaving out :reload-all

2020-09-10T06:13:03.054100Z

An adventure in OO (a short story) There's an API which creates something called a Registry. Registry is an object, currently it only contains an id. There's another API that deletes a Registry, it takes the same Registry object. Things changed, and when creating a Registry, people wanted it to also take a name, an owner, and some options. So they changed the Registry class with those additional fields. Now, when you want to delete a Registry, it turns out the delete API only really needs the id from it, but the Registry object now takes a bunch of stuff. The first issue is, people thought they'd be smart, and make that class so you're forced to provide all the mandatory parameters for creating a Registry, but that means when you delete you have to pass in data that's not needed and you might not have. So those validations were removed so everything except id is optional on this object now. But even then, the users of the API for deleting are really confused, why is there all these fields on the Registry? Which one need to be provided? Now, subtyping is the solution to everything (most of the time) in OO. So someone said, ok, we need to change the hierarchy of Registry. It turns out, we have a Registry that only has an id. And we also have a CreationRegistry that extend Registry with the additional fields like name, owner, and some options. Genius yes? Well, sure, except it is a breaking change, because you already have a bunch of clients calling that API and their code does: new Registry(). So if you make that change, you'd break them. The same thing happens if you try to make a DeleteRegistry object. So there's just no real solution to this, and everyone just deals with a stupid Registry object that depending where you use it, some fields are mandatory and in other place they are optional 😛 The End

ryan 2020-09-10T10:18:05.059900Z

Why not add deleteRegistry(id) as an overload? Shouldn't break existing calls but allows people to use the more convenient method going forward

2020-09-11T04:21:54.192300Z

That's not a bad idea. In my case, I don't think my client generator supports overload. But ya, I might look into that as an option.

flowthing 2020-09-10T06:17:24.054800Z

Could that have been avoided if the method that deletes a Registry took only the ID instead of the entire Registry object?

2020-09-10T06:17:59.055Z

Yup

flowthing 2020-09-10T06:18:12.055200Z

I mean, that would also have been a breaking change, but since you have static types, it’s not really a problem, right? 😜

2020-09-10T06:19:03.055400Z

Doing it now would be breaking, if people had had the foresight of this scenario, they could have made the delete take only the id

flowthing 2020-09-10T06:19:17.055600Z

Exactly, yeah.

2020-09-10T06:19:34.055800Z

But I've seen this play out a lot in OO, its because creating new class is cumbersome, people are lazy, so classes get shared as much as possible.

1✔️
2020-09-10T06:20:08.056Z

And people think of things as the class

2020-09-10T06:20:28.056200Z

So an API called: deleteRegistry(...) ? what would it take as input if not a Registry ? 😛

2020-09-10T06:21:37.056500Z

In fact, people would probably do: registry.delete()

2020-09-10T06:24:20.056900Z

Also, for APIs, its kind of common I've seen for people to think... we might need to accept more things in the future, so if you have it take an object, it lets you add optional fields to it in the future. Where if you change the signature to have more argument, its breaking. Which is another reason people avoid doing deleteRegistry(id). But then, they don't think much further, and honestly, its normal, how can you anticipate everything, so I'm pretty sure people thought they were smart using Registry as input 😛

2020-09-10T06:24:40.057100Z

Also, there's an integ test, and the test does:

registry = new RegistryBuilder().withId(123).withName("wtv").withEtc....;

client.createRegistry(registry);
// validate it was created
client.deleteRegistry(registry);
//validate it was deleted
Pretty sure people thought hey how convenient this API 😛 I can just use the same object back to back for both API.

flowthing 2020-09-10T06:28:44.057600Z

Oh, absolutely.

2020-09-10T08:21:20.058700Z

@seancorfield: Yeah there’s definitely not enough reasons to migrate a large existing system from component to integrant; However for greenfield stuff I’d see no reason to pick component over integrant, integrant’s just a lot more flexible, and bakes data/configuration in (and all the benefits that brings) as a default. In terms of high level architecture though, they’ll lead to an almost identical decomposition of a system; it’s just expressed with different primitives, protocols vs multimethods; closures vs data, object references vs namespaced keywords/composite-keys etc.

2020-09-10T08:32:50.059100Z

@jayzawrotny: If you’re looking to do a webstack in integrant, you definitely want to look at duct. We use it for most greenfield web apps. It’s pretty good. You get a pretty standard but configurable ring stack out of the box. I’d definitely recommend it, but it’s also definitely not perfect — but it could be. Duct is also a pretty good starting point that lets you grow beyond duct’s limitations. For example our main app is pretty far from a standard duct app; but it was very easy to tweak ducts primitives for our needs. For example duct assumes an app is for a single customer; yet we were able to easily tweak the project layout etc to support multi-tenant (i.e. each customer of ours has their own build/configuration as a profile layered over a base profile of the app managed in the same source tree). We also use tools.deps not lein, and leverage most of duct’s core ring middleware stack, we do isomorphic SSR’d clj(s) with reagent, shadow-cljs and have full stack integration testing with etaoin, and recently added devcards as a harness and test bed for stand alone front end components.

2020-09-10T08:33:53.059500Z

Anyway #duct is quite a good channel for support around duct etc… there are quite a few folk there with large duct apps.

ryan 2020-09-10T10:18:05.059900Z

Why not add deleteRegistry(id) as an overload? Shouldn't break existing calls but allows people to use the more convenient method going forward

vemv 2020-09-10T10:23:55.061500Z

is there a j.u.concurrent mechanism (or clojure lib) that gives you a "grant" to use something (out of a pool of N items) for M seconds?

vemv 2020-09-10T10:24:39.061600Z

of course clj being clj this is pretty easy to implement from scratch, I'm just curious. I think I had seen this mechanism somewhere

alexmiller 2020-09-10T13:30:17.063Z

Java has a Semaphore for granting but it doesn’t have the time aspect

alexmiller 2020-09-10T13:31:27.063600Z

The time aspect seems nontrivial to me

zilti 2020-09-10T15:14:43.064500Z

Okay, creating uberjars using deps.edn and depstar... is that broken for anyone else? I get:

Execution error (FileAlreadyExistsException) at jdk.nio.zipfs.ZipFileSystem/createDirectory (ZipFileSystem.java:695).
/META-INF/versions/9

Full report at:
/tmp/clojure-13855814055111068112.edn

zilti 2020-09-10T15:32:26.064800Z

Ah I guess uberdeps is the hot new thing now

seancorfield 2020-09-10T15:56:51.065900Z

@zilti depstar is very actively maintained and I take bug reports very seriously. I've not seen that error before but I'm happy to help debug it (and fix it, if it's a bug in depstar).

zilti 2020-09-10T15:57:37.066800Z

Oh, okay! Yes, I will file a bug report soon then. I guess it is fair to say it is in depstar, because uberdeps builds it fine

ghadi 2020-09-10T15:57:56.067400Z

there is a #depstar room, maybe you should post your deps.edn in there

ghadi 2020-09-10T15:58:18.068300Z

I don't think uberdeps handles MR jars, which is what /META-INF/versions/9 indicates you are using

1☝️
seancorfield 2020-09-10T15:58:25.068500Z

Well, it may be that uberdeps simply ignores the problem and the resulting JAR just happens to work 🙂

2➕
ghadi 2020-09-10T15:58:26.068700Z

MR == multi-release

seancorfield 2020-09-10T15:58:32.069Z

Yeah, what he said 🙂

zilti 2020-09-10T15:58:44.069600Z

Yea, could also be

zilti 2020-09-10T15:59:00.070100Z

Oh, I wasn't aware about there being a room 🙂

seancorfield 2020-09-10T15:59:36.070700Z

So far, I've not hit problems with MR JARs -- they are supported by depstar -- but you may have encountered an edge case. The #depstar room is new so we don't flood #tools-deps with chatter about it 🙂

kwladyka 2020-09-10T16:01:11.071400Z

not sure if it is helpful but @zilti take a look on how I use depstar https://github.com/kwladyka/form-validator-cljs/blob/master/.github/workflows/clojars.yaml + prepare https://github.com/kwladyka/form-validator-cljs/blob/master/pom.xml

zilti 2020-09-10T16:02:39.072200Z

I'll save it for now and will have a look

vemv 2020-09-10T17:03:23.073300Z

Thanks! Maybe a "time-expiring hashmap" could kill a big chunk of the problem. The clj/java alternatives seemed to be bit of a heavy dependency though

Yehonathan Sharvit 2020-09-10T17:05:07.075100Z

What’s the idiomatic way to iterate over a sequence and execute a side effect functions for each element of the sequence given that we also want the returned values from the functions? For instance, iterating over do-stuff! that returns a meaninful value. One option is:

(mapv do-stuff! my-seq)

Yehonathan Sharvit 2020-09-10T17:05:24.075700Z

Another option is: (doall (map do-stuff! my-seq))

Yehonathan Sharvit 2020-09-10T17:05:35.076Z

Or, I could write a loop/recur

bronsa 2020-09-10T17:05:48.076200Z

run!

ghadi 2020-09-10T17:06:03.076600Z

run! doesn't return the results though

bronsa 2020-09-10T17:06:24.076900Z

ah, I missed the last part of the question :)

Ben Sless 2020-09-10T17:07:11.077500Z

mapv is good for this use case

Yehonathan Sharvit 2020-09-10T17:26:18.078400Z

mapv doesn’t convey the fact that we are interested in the side effects (At least that’s how I perceive it)

Yehonathan Sharvit 2020-09-10T17:28:18.079100Z

It seems that clojure.core is missing a function for this use case. Could it be that this use case is not interesting?

dpsutton 2020-09-10T17:31:00.081Z

can these fail? do you care about order? should you short circuit if they start failing? lots of different things change what this would look like in practice. can't imagine a single function in core really covering everything. do you need a thread pool to run these things? blocking, etc

3💯
ghadi 2020-09-10T17:32:08.081300Z

reduce/transduce

1☝️
borkdude 2020-09-10T17:40:07.081900Z

Not sure if this is intentional:

user=> #_s/foo [1 2 3] ;; ok, although there is no alias s
[1 2 3]
user=> #_::s/foo [1 2 3] ;; not ok, reader fails!
Syntax error reading source at (REPL:5:10).
Invalid token: ::s/foo
[1 2 3]

ghadi 2020-09-10T17:41:28.082900Z

we filed a similar bug around discarded tagged literals recently. Probably shouldn't try to autoresolve an alias for something that is discarded

borkdude 2020-09-10T17:41:38.083100Z

:thumbsup:

borkdude 2020-09-10T17:41:52.083300Z

should I make a JIRA about it?

ghadi 2020-09-10T17:42:52.083800Z

sure, that would be nice. https://clojure.atlassian.net/jira/software/c/projects/CLJ/issues/CLJ-2577 is the related issue

borkdude 2020-09-10T17:45:38.084600Z

done: https://clojure.atlassian.net/browse/CLJ-2581

2
2020-09-10T17:48:46.085600Z

I dunno, that seems pretty clear cut as the correct behavior for "read a valid form and discard it"

2➕
2020-09-10T17:49:05.086Z

s/foo in the example reads correctly, even is s is not an alias in the current namespace

2020-09-10T17:49:13.086200Z

::s/foo doesn't

2020-09-10T17:49:39.086700Z

so ::s/foo is not a valid form if the alias s doesn't exist in *ns*

borkdude 2020-09-10T17:50:15.087100Z

yeah, maybe you're right

ghadi 2020-09-10T17:50:25.087400Z

it's definitely debatable

borkdude 2020-09-10T17:50:48.088300Z

I just used #_ to comment out a form I just copy pasted from another namespace which then broke my CLJS compilation

ghadi 2020-09-10T17:50:54.088600Z

I was taking valid form meaning not being able to discard 12ab34 because that's not readable at all

borkdude 2020-09-10T17:51:26.089100Z

which is kind of what #_ is for right, commenting out forms temporarily

borkdude 2020-09-10T17:53:28.089900Z

and it does accept s/foo if the alias doesn't exist, which gives kind of a precedent

bronsa 2020-09-10T17:53:52.090400Z

but that's because 's/foo is valid even if s doesn't exist

bronsa 2020-09-10T17:53:56.090700Z

while '::s/foo isn't

2020-09-10T17:54:04.090800Z

you'll get the same behavior from (comment ...) as well

borkdude 2020-09-10T17:54:20.091100Z

that's only because comment is a macro. this is a reader implementation decision

2020-09-10T17:54:33.091500Z

user=> (comment s/foo)
nil
user=> (comment ::s/foo)
Syntax error reading source at (REPL:2:17).
Invalid token: ::s/foo
Syntax error reading source at (REPL:2:18).
Unmatched delimiter: )
user=>

2020-09-10T17:55:05.092400Z

it is because s/foo can be read and not evaled, while ::s/foo cannot be read

1➕
bronsa 2020-09-10T17:55:28.093300Z

resolution of s/foo doesn't happen at read time

ghadi 2020-09-10T17:55:30.093500Z

comment is different though

bronsa 2020-09-10T17:55:52.094400Z

if we make #_::s/foo work then why not #_#{1 1} aswell

ghadi 2020-09-10T17:55:52.094600Z

I'm considering it debatable because of the treatment of unregistered tags in CLJ-2577

ghadi 2020-09-10T17:56:51.095800Z

(though edn has specific language around that, I think it could apply to alias resolution, too)

ghadi 2020-09-10T17:56:55.096Z

(it's a parallel problem)

lilactown 2020-09-10T17:57:10.096300Z

one of the concrete ways this harms application development is if you have a require and an aliased keyword in a reader conditional. I ran into this last week, actually

2020-09-10T17:57:25.096900Z

alias resolution doesn't even exist in the edn spec

ghadi 2020-09-10T17:58:05.098Z

right, but tag handling and alias resolution are similar mechanisms (table lookup)

lilactown 2020-09-10T17:58:52.098700Z

e.g. if you have some namespace:

(ns my-app.feature
   (:require
     #?(:clj [foo.bar :as fb])))

#?(:clj ::fb/baz)
if you try and use this namespace in a CLJS app, the reader will throw because fb doesn’t exist

2020-09-10T17:59:14.099100Z

which it should

borkdude 2020-09-10T18:00:01.100400Z

:/

lilactown 2020-09-10T18:00:04.100600Z

I disagree; while it may match some definition of consistency, it harms CLJS apps. I don’t want to include foo.bar in my app, or literally can’t

lilactown 2020-09-10T18:00:47.101500Z

it can work in the other direction too. I guess I should say it “harms cross-platform code bases”

alexmiller 2020-09-10T18:00:57.101800Z

I personally do not see this as an error - the #_ is for reading, then skipping. ::s/foo where s is undefined is not readable.

borkdude 2020-09-10T18:01:40.103300Z

it still seems inconsistent with #_s/foo to me, all technical details aside

alexmiller 2020-09-10T18:01:48.103700Z

is s/foo readable?

borkdude 2020-09-10T18:02:02.104200Z

I don't care, it's just an implementation decision

bronsa 2020-09-10T18:02:06.104400Z

it's not

alexmiller 2020-09-10T18:02:09.104600Z

it's being consistent

bronsa 2020-09-10T18:02:24.105100Z

the difference is in the semantics, not an implementation detail

bronsa 2020-09-10T18:02:32.105500Z

(read-string "s/foo") doesn't resolve s

alexmiller 2020-09-10T18:02:32.105600Z

#_ means read, then skip

bronsa 2020-09-10T18:02:50.106300Z

(read-string "::s/foo") does

borkdude 2020-09-10T18:04:25.108600Z

so why are symbol namespaces not resolved in the reader again?

bronsa 2020-09-10T18:04:26.108800Z

one could argue that one inconsistency is that

`s/foo
doesn't fail while ::s/foo does

bronsa 2020-09-10T18:05:18.110200Z

@borkdude because how would you read (quote s/foo) if s was resolved by the reader?

2020-09-10T18:05:22.110700Z

(grabs :popcorn )

alexmiller 2020-09-10T18:05:25.110800Z

the difference here is in :: which is inherently contextual

bronsa 2020-09-10T18:05:32.111100Z

it'd be resolved-s/foo by the time quote sees it

borkdude 2020-09-10T18:05:50.111700Z

::pop/corn

2020-09-10T18:05:58.112200Z

right 🙂

ghadi 2020-09-10T18:06:30.113300Z

calling a reader for tagged literal is similarly contextual, but the EDN spec says those should not be called when discarding

ghadi 2020-09-10T18:06:37.113600Z

(I know clojure code != edn)

2020-09-10T18:07:03.113700Z

Any conversation with you, alexmiller, ghadi, and bronsa all submitting examples and points of view is guaranteed to exhibit something I've not thought about before.

2020-09-10T18:08:01.114200Z

Be very very careful with the #=(popcorn) though

1😀
borkdude 2020-09-10T18:08:02.114400Z

Meanwhile I'm littering my emacs buffer with ;; 🍿

alexmiller 2020-09-10T18:08:06.114600Z

yes, that is a clear violation of the intent of the spec

2020-09-10T18:09:05.115500Z

I was going to jump in with ; as my go-to solution, but that was already known to all participants, of course.

borkdude 2020-09-10T18:09:36.116400Z

And a nice recipe for messing up balanced parens

Yehonathan Sharvit 2020-09-10T18:10:10.117400Z

What’s the difference between my use case and the use case covered by run! and doseq ?

dpsutton 2020-09-10T18:10:24.118100Z

i have no idea what your use case is

ghadi 2020-09-10T18:10:26.118300Z

in XML there was a distinction between "well-formed" and "valid". I would like to be able to discard invalid things (tags that don't exist, aliases that don't exist) while maintaining the behavior of throwing when something isn't well-formed

2➕
2020-09-10T18:10:26.118400Z

I have very practiced muscle memory of keeping parens balanced without using slurp/barf kinds of Emacs keybindings. Call me a luddite.

dpsutton 2020-09-10T18:11:01.119400Z

but run! will block and execute things in sequence. and no way to short circuit, all work done on current thread,

dpsutton 2020-09-10T18:11:24.119600Z

if that fits your use case then bob's your uncle and your request for a function in core to handle your use case is satisfied

dpsutton 2020-09-10T18:11:47.120200Z

skip the following s-expression

borkdude 2020-09-10T18:12:35.120800Z

actually emacs clojure-mode does quite well with it, now that I try to mess it up

borkdude 2020-09-10T18:12:55.121500Z

unless it contains unbalanced s-expressions

1
dpsutton 2020-09-10T18:13:19.122500Z

is the obvious choice for the reader tag 🙂

lilactown 2020-09-10T18:14:19.123500Z

this discussion hits on a couple of pain points that I have with using namespace aliases and keywords. I have two concrete use cases: 1. I want to require a namespace in a reader conditional and use that as an alias in a keyword for a reader conditional 2. I want to be able to create and use an alias without having a corresponding concrete namespace I feel like the solution to either of those two problems could be related.

lilactown 2020-09-10T18:15:54.124600Z

specifically focusing on (1) for now, I think there should be some way to inform the reader, “do not progress further” and I would really appreciate if that was baked into reader conditionals

2020-09-10T18:16:51.125500Z

This kind of thing is why I wanted "reader-conditionals" to be a macro and not baked into the reader at all

alexmiller 2020-09-10T18:17:08.126200Z

I think that is open for discussion and may even already have a ticket

1
2020-09-10T18:17:13.126500Z

so it was very clear that whatever the code was for any branch it must be valid and readable on any other branch

alexmiller 2020-09-10T18:17:28.126900Z

and 2 is something we definitely have a ticket for and are aware of as an issue that may see some attention in 1.11

2
2020-09-10T18:18:40.128200Z

I doubt it exists anymore but there used to be a confluence page with a fair bit if discussion about reader conditionals with lots of comments, etc

lilactown 2020-09-10T18:19:04.128600Z

I think that whether or not conditional branches were a macro or a reader form doesn’t really matter to me. I still have use cases that necessitate including code conditionally and using aliased keywords

2020-09-10T18:19:27.129Z

and you insist on using ::

Yehonathan Sharvit 2020-09-10T18:19:36.129300Z

Waht do you mean by “bob is my uncle”?

2020-09-10T18:19:41.130Z

the very simple work around is just don't use ::

2☝️
2020-09-10T18:20:32.130700Z

which is mostly my position on :: regardless of comments and conditionals

dpsutton 2020-09-10T18:20:59.131100Z

its an idiom meaning "you're good to go"

Yehonathan Sharvit 2020-09-10T18:21:06.131300Z

ah ok

1👍
dpsutton 2020-09-10T18:21:24.131700Z

no idea where it comes from 🙂

Yehonathan Sharvit 2020-09-10T18:22:03.133100Z

My use case is that I need something like run! with the slight difference that it returns a sequence of the values returned by the inner function

2020-09-10T18:22:10.133500Z

Hey guys I know reading other people's code can feel worse than waking up after a night of drinking some really cheap vodka. But is anyone willing to do a little code review. Its about 130 loc.

2020-09-10T18:22:31.134300Z

the tying of namespaces for keywords to the namespaces for code is gross, and insisting that the language grow a feature to make generating empty code namespaces so that it is easier to use namespaced keywords is also gross

dpsutton 2020-09-10T18:23:10.134600Z

there's a #code-reviews channel. and also smaller snippets are always fair game in #clojure and #beginners and other topic related channels

2020-09-10T18:23:34.135200Z

Ill head there

borkdude 2020-09-10T18:23:41.135600Z

wasn't this inspired by spec initially?

2020-09-10T18:23:48.135900Z

no

2020-09-10T18:24:03.136500Z

what happened is the example docs for spec, for the sake of brevity use '::'

2020-09-10T18:24:14.136800Z

and people just copied that willy nilly

2020-09-10T18:24:25.137300Z

nothing requires the use of ::

lilactown 2020-09-10T18:24:42.137700Z

> the very simple work around is just don’t use `::` yes that is a simple workaround. I disagree that it is a solution; otherwise, why have ::? I ran into this specifically when using a library that used namespaced keywords with long namespaces. :org.wscode.pathom.connect/input over and over is onerous to write and difficult to validate as a human reader (I have intentionally misspelled something here).

alexmiller 2020-09-10T18:24:49.137900Z

autoresolved keywords have been part of Clojure since 1.0

2020-09-10T18:25:52.138900Z

(def long-key :org.wscode.pathom.connect/input)

1
lilactown 2020-09-10T18:25:57.139Z

I also agree that generating empty code namespaces is gross. I wouldn’t suggest that as a solution

2020-09-10T18:26:50.139300Z

I agree it is gross, I haven't had a problem with long keys

2020-09-10T18:27:03.139700Z

that is what you are pushing for

2020-09-10T18:27:18.140300Z

that is what all this easy alias stuff is

lilactown 2020-09-10T18:27:34.141200Z

I have not suggested any solutions. I have only outlined my motivation for a solution to the use cases I have for my projects

alexmiller 2020-09-10T18:27:52.141800Z

we are not expecting that to be the solution in Clojure

1
lilactown 2020-09-10T18:29:12.143Z

I spend 70% of my time in ClojureScript. generating an empty code namespace is not a workable solution at all in that context IMO

stephenmhopper 2020-09-10T19:12:12.146Z

I seem to recall watching a Clojure talk sometime ago that discussed the functional programming approach with Clojure. The basic steps were: 1. Define the problem 2. Define a data structure which solves the problem 3. Define functions which operate on that data structure I’m fuzzy on the exact details which is why I’m trying to find the original talk again. Does anyone happen to know which talk this might have been? It’s neither this https://www.youtube.com/watch?v=Tb823aqgX_0 nor this https://www.youtube.com/watch?v=vK1DazRK_a0 (although both address similar topics).

alexmiller 2020-09-10T19:27:36.146600Z

there were a couple talks like this at very early conj's

alexmiller 2020-09-10T19:28:10.146800Z

https://www.youtube.com/watch?v=qqNevHwH47w

alexmiller 2020-09-10T19:28:30.147Z

https://www.youtube.com/watch?v=3yvrs9S0RIw

alexmiller 2020-09-10T19:28:40.147400Z

and probably others as well :)

dpsutton 2020-09-10T19:29:03.147900Z

is there any issue with using async/onto-chan with large collections? 500k or so items? is this abusing the notion of channels or can they handle large work queues?

ghadi 2020-09-10T19:29:53.148500Z

not that I know of, but make sure you use onto-chan! or onto-chan!!

dpsutton 2020-09-10T19:30:30.149400Z

is that newer? not seeing it in our copy with (apropos "onto-chan")

ghadi 2020-09-10T19:30:33.149700Z

yeah

alexmiller 2020-09-10T19:30:35.149900Z

in the former case it will spin a go block to push to the channel, in the latter a thread

alexmiller 2020-09-10T19:30:41.150200Z

these were added recently

dpsutton 2020-09-10T19:30:52.150600Z

thanks for the pointers. i'll bump and check it out

alexmiller 2020-09-10T19:31:13.150900Z

1.2.603 or later

dpsutton 2020-09-10T19:31:32.151300Z

yeesh. goodbye "0.3.456" 🙂

alexmiller 2020-09-10T19:31:37.151500Z

https://clojure.github.io/core.async/ - docs

alexmiller 2020-09-10T19:31:58.151900Z

the difference there is not as large as you might presume :)

dpsutton 2020-09-10T19:32:15.152400Z

yeah i figured. i'm bumping and expecting no work to do but use the new goodies

alexmiller 2020-09-10T19:32:18.152600Z

actually, that is pretty old, nvm :)

alexmiller 2020-09-10T19:32:32.152800Z

but shouldn't be anything breaking afaik

stephenmhopper 2020-09-10T20:55:39.157800Z

So I have an ordered sequence of items . I need to map through this sequence with a function that accepts the previous element as well as all elements preceding it in my ordered sequence. Is there a good idiomatic way to do this in Clojure? Should I just map over the range of indices, take the current index + 1, and use butlast? Right now I have this:

(->> (range (count items))
  (map (fn [idx]
         (let [entries (take (inc idx) items)
               prev-items (butlast entries)
               item (last entries)]
              ;;do something interesting here
             ))))
Is there a more idiomatic way to do that?

ghadi 2020-09-10T20:57:02.158200Z

butlast is O(N) complexity, so avoid that

ghadi 2020-09-10T20:57:40.158800Z

clojure
Clojure 1.10.2-alpha1
user=> (doc partition)
-------------------------
clojure.core/partition
([n coll] [n step coll] [n step pad coll])
  Returns a lazy sequence of lists of n items each, at offsets step
  apart. If step is not supplied, defaults to n, i.e. the partitions
  do not overlap. If a pad collection is supplied, use its elements as
  necessary to complete last partition upto n items. In case there are
  not enough padding elements, return a partition with less than n items.

ghadi 2020-09-10T20:58:04.159300Z

use (partition 2 1 coll) for overlapping pairs

stephenmhopper 2020-09-10T20:58:57.159800Z

I don’t think partition will work because the partitions need to be of varying / increasing size

ghadi 2020-09-10T20:59:06.160200Z

oh, I misread you

kenny 2020-09-10T20:59:45.161100Z

Perhaps a loop ?

dpsutton 2020-09-10T20:59:47.161300Z

reduce

ghadi 2020-09-10T21:00:42.162Z

a loop if you're producing N values at the end, where N is the length of the list

ghadi 2020-09-10T21:00:55.162400Z

otherwise a reduce is sufficient

dpsutton 2020-09-10T21:02:51.162900Z

(reduce (fn [[previous acc] x]
          [(conj previous x) (apply + x previous)])
        [[] 0]
        (range 5))

stephenmhopper 2020-09-10T21:05:30.163600Z

Yeah, I suppose either loop or reduce will work. I do need to produce N values at the end so I’ll probably go with loop

dpsutton 2020-09-10T21:05:47.164Z

you could also do some mapping over (reductions conj [] coll) but might run into memory issues?

stephenmhopper 2020-09-10T21:07:27.164700Z

Oh, I like that even more, that should work for my use case.

apbleonard 2020-09-10T22:36:16.182200Z

We use aliasing to shorten long keywords in natural language all the time. In the north of England "tea" means an evening meal, and "dinner" means lunch. A southern colleague was asked to deploy some code at dinnertime, and she stayed late! We could tell everyone to say ":northern/dinner" instead, and it might have helped her out, but they won't because most of the time in our context, there's no need. But you do have to clarify when you're crossing contexts 🙂 Similarly I can tell (and have told) developers their JSON keys in their APIs are too short and ambiguous, sufficing only for the narrow context they had at the time... And I long for namespaced clarity in the overloaded terms that are used multifariously in different contexts at my work. But I'm starting to appreciate that there's always shorthand language for local conversations, and more precise language for general audiences, and so aliasing is inevitable and to be supported.

1👍2❤️
2020-09-10T22:46:00.182600Z

k

Quest 2020-09-10T23:27:01.182700Z

Just an FYI on what happened: I took your advice and asked internally. We do have several interested in Eric’s REPL course. I’m not sure whether we can get funding for subscriptions now, but I’m going to keep pushing on management until we do. Half a year max IMO. Good thinking @seancorfield, though now I owe you too many thanks to count. Do you have a monthly github funds/patreon style thing setup for donations?

seancorfield 2020-09-10T23:28:22.182900Z

Thank you, but I do not. Somehow it always makes me feel a bit odd when folks try to pay me for just being a decent netizen 🙂

seancorfield 2020-09-10T23:28:49.183100Z

Maybe one day we'll meet IRL at a conference and you can buy me a beer? 🍺

Quest 2020-09-10T23:54:56.183800Z

Now that said — I can understand not feeling the need to take donations either! But I’m sincere in my offer to “put my money where my mouth is”, so perhaps that’s worth something by itself 🙂