Fork me on GitHub
#beginners
<
2019-07-28
>
Daniel Plisetsky12:07:19

Hi guys, I’m writing my first thing in Clojure and I’ve found myself using this pattern over and over

``````(some #(when (some? %) %)
[nil nil 1])
``````
Basically, I’d like to return the first non-nil value from a sequence, or nil. Is there a more idiomatic way to do so?

valtteri12:07:45

One way is this `(some identity [nil nil 1])`

valtteri12:07:43

It returns the first `truthy` value. So for instance `(some identity [nil false 1])` returns `1`

valtteri12:07:20

If you need to check only for `nil` then I think something like this is pretty idiomatic and readable

``````(->> [nil nil 1]
(remove nil?)
first)
``````

Daniel Plisetsky12:07:25

@valtteri Exactly what I was looking for. Thanks!

valtteri12:07:46

No problem!

lepistane17:07:43

This is not clojure specific but more of an algorithm question i am not sure to tackle so i have arbitrary path with checkpoints and i would like to know at which checkpoint i was last and which one is next in efficient way visually it would look something like this i've been stuck with this for few days i dont think i have tool in mindbox to solve this so any input would be helpful

andy.fingerhut17:07:02

What kind of operations do you need to do frequently on a path? e.g. append another checkpoint, maybe also append a "non-checkpoint" point. Anything else?

lepistane20:07:40

that's about it i thought problem would be easier if i had sequence of points meaning i know where is first one, second one... and that is set in stone the only thing is to create algorithm that will know between which 2 is red point

andy.fingerhut20:07:11

If there is some sortable 'key' you can sort the points on, both sorted-set and sorted-map in Clojure let you efficiently retrieve all elements between two keys, in forward or backward order.

andy.fingerhut20:07:13

So if you knew the key of 'where you are now', you could efficiently get all keys from that point later, to get the next point, and get all keys from that point earlier in reverse order, to get the previous point.

andy.fingerhut20:07:58

There are of course simple linear scanning through all points in order method to do what you want, but I am guessing if you are asking, you are asking about methods that would be faster than that.

lepistane20:07:27

my main issue is now knowing how to determine 'where i am' if i found simple solution for this that worked it would be great but having fast, elegant one would be amazing

andy.fingerhut20:07:36

Can you use a number like "number of feet from the start of the path" to represent positions of where you are now, and where the checkpoints are?

lepistane20:07:21

i forgot to state - i dont know what's the path only the checkpoints so the path could be what i put in picture but i could be something totally different for same checkpoints and i know the order of them. so i can't use 'num of feet'

andy.fingerhut20:07:25

How do you represent where you currently are?

lepistane20:07:06

i dont - that's what i want to determine

andy.fingerhut20:07:12

So at different points in time, you want to represent different current positions on this path. You know where the checkpoints are and what relative order they are in, but you do not know how far any of them are from the start as a length (for example).

andy.fingerhut20:07:50

I don't know how you want to represent a position that is not one of the checkpoints.

andy.fingerhut20:07:54

Oh, I just read something you said earlier -- the same checkpoints might be in a different order for different paths

lepistane20:07:18

but the simplest case is i have 1 path 1 set of checkpoints - i dont know path exactly but i know it will follow checkpoints in order how do i know where i am 'i was at 2 going toward 3'

lepistane20:07:37

would it be easier to explain what i am trying to build maybe it would be easier to understand what i am trying to ask

lepistane20:07:52

sorry if i am explaning myself correctly

andy.fingerhut20:07:00

Do you want a path to be something like an ordered sequence of values, some of them representing checkpoints, others representing non-checkpoint positions?

lepistane20:07:42

i have that at the moment but i'd like to not rely on non-checkpoint positions to know where i am. instead i would like to send value 'i am here' and based on that value and values that are checkpoints determine between which 2 i am currently

andy.fingerhut20:07:49

At the very least, it seems you need some notion of a value that represents a checkpoint, and a value that represents where you are now, and some way for a particular path to determine whether "where you are now' is earlier or later than a particular checkpoint.

andy.fingerhut20:07:26

One way would be to have 'where you are now' in a sequential list of positions, which includes at least checkpoints and where you are now, and perhaps other positions as well.

andy.fingerhut20:07:13

If you have no way to compare a 'where you are now' value to a checkpoint position, I don't see how the problem can be solved at all.

lepistane20:07:25

i though of creating square areas between 2 points and asking 'am i in this sequare' then i know that i am between 2nd and 3rd checkpoint

andy.fingerhut20:07:31

So you do know something like (x,y) coordinates on a grid of checkpoints and where you are now?

lepistane20:07:58

another thing that came to mid is to determine based on 3-5 values the shortest path between points and which one is getting shorter and which one is lengthening and based on that i could say 'ok checkpoint 1 is getting further while checkpoing 2 is getting closer so i must be between the two' but i see problems with both approaches

lepistane20:07:27

i know the xy of checkpoints and mine also

andy.fingerhut20:07:38

So from your figure, there are points outside of the 'bounding rectangle' of checkpoints 3 and 4, that are still between 3 and 4 on the path.

andy.fingerhut20:07:44

Is a path always a sequence of (x,y) coordinates, with straight lines between those?

lepistane20:07:57

path is not a straight line

andy.fingerhut20:07:13

Can a path always be represented as a sequence of straight line segments?

lepistane20:07:25

possibly yes

andy.fingerhut20:07:26

or can it have curves

lepistane20:07:31

it can curve also

andy.fingerhut20:07:58

And there is some mathematical description of the shape of these curves?

andy.fingerhut20:07:35

So would you represent a curve by breaking it up into short straight line segments? If not, how do you know the shape of the curve?

lepistane20:07:04

yeah braking into small straight lines

andy.fingerhut20:07:34

ok, so a path is a sequence of straight line segments.

andy.fingerhut20:07:16

So every checkpoint is on one of those line segments, or is an endpoint of one or two of them, and the same is true for where you are now.

andy.fingerhut20:07:27

So is it somehow known when you want to ask the question "what is the previous and next checkpoint?" which line segment you are on now?

andy.fingerhut20:07:43

or do you also need to calculate that from (x,y) of where you are now?

lepistane20:07:44

i am not following but i had an idea to determine between 2 checkpoints i am without knowing the path in advance

lepistane20:07:57

so path can be anyting spirals squres what ever

andy.fingerhut20:07:10

can it cross over itself?

andy.fingerhut20:07:25

i.e. can "where i am now" be two different places on the same path?

lepistane20:07:53

oh good question

lepistane20:07:08

it might happen but on rare occasion

andy.fingerhut20:07:52

if so, you need to think about whether you want "all possible" previous and next checkpoints from where you are now, or just one arbitrary such pair.

andy.fingerhut20:07:43

When you are given a "where you are now", is it in (x,y) coordinates, and you have no idea yet which straight line segment of a path it is on?

lepistane20:07:23

lets say cross over can't happen just to exclude that option to make it less complicated it's a point but i have no idea which straight line segment it belongs to

andy.fingerhut20:07:53

ok, so it sounds like that would be one of the first things you would need to determine. I don't see a way to solve the problem without knowing that first.

lepistane20:07:51

so basically without knowing the path i have no way of knowing betwheen which 2 checkpints i am

andy.fingerhut20:07:21

well, you know exactly where you are in (x,y) coordinates 🙂 But yeah, on the path you would have no idea yet where on the path.

lepistane20:07:33

ye ye (i edited)

lepistane20:07:26

oki thanks if i manage to scramble something that works i will share with u cheers

andy.fingerhut20:07:56

FYI, there is a whole field of computer science study called computational geometry that I know only a bit about, that might already have good solutions for at least parts of the problem.

lepistane20:07:40

any resources that i could use to explore that?

andy.fingerhut20:07:56

Also, depending upon whether you have paths that change only occasionally, and you want to determine the previous and next checkpoints for a billion (x,y) coordinates, or you only want to do a handful of (x,y) coordinates for each path, there are methods of precomputing a bunch of data structures about a path that could likely speed up the problem of finding the answer for a billion (x,y) points.

andy.fingerhut20:07:33

If these (x,y) coordinates are floating point values, as I suspect, remember that arithmetic is approximate for those, and you will likely need "within plus or minus epsilon" approximate equality checks, simply to answer whether (x,y) is on a line segment or not

andy.fingerhut20:07:05

I had one graduate level class on computational geometry about 25 years ago, and it was done from professor's own notes, no text, so I don't have one to recommend. There is this Wikipedia article that gives some overview of the kinds of problems people have worked on, and it might have a link to other good resources: https://en.wikipedia.org/wiki/Computational_geometry

andy.fingerhut20:07:08

It links to a page of books on the subject, but unfortunately I don't have a particular one to recommend.

andy.fingerhut20:07:19

Sorry, that is a pretty broad net to cast there 🙂

lepistane21:07:32

no worries tnx for your time!

andy.fingerhut17:07:49

And is there actual 2D or 3D geometry involved in the problem, or are these paths just sequences of points?

dharrigan19:07:27

What's the view on using `defn-` over `defn ^:private`? Is there a particular trend to use one or the other?

andy.fingerhut20:07:15

Personal preference, I believe, really. Some people like that ^:private works consistently across def, defn, and maybe a few other things. Some people like brevity of defn-

dharrigan20:07:02

right, so long as it's consistently applied. Like most things in life 🙂

andy.fingerhut20:07:01

Some people might fret over consistent use of one or the other in a code base, or have a personal or project style guide for one over the other. Some people might just read a mix of some of each in the same project and not worry too much about it 🙂

seancorfield20:07:12

I go back and forth on even using private functions at all, to be honest.

seancorfield20:07:36

I mean, you can still call a private function, so they're not like private in some other languages.

jaihindhreddy20:07:44

So do you prefer having public and private namespaces?

seancorfield20:07:12

In a library, I'll use `defn-` to separate implementation from API. But in application code, I don't use private functions much at all -- unless I refactor a "big" function into small, composable pieces and they'll start off private.

👍 2
jaihindhreddy20:07:15

And the info about which namespaces are public is communicated out of band through docs maybe

seancorfield21:07:03

The only benefit I find with private functions is that Joker (used as a linter, in my editor, Atom) will highlight an unused private function. 🙂

👍 1
dharrigan21:07:44

Yes, I'm debating that too, a private is only a "hint" that it's private...one can always jump into the namespace and get the value anyhooo.

dharrigan21:07:51

So, perhaps I'll just keep them public 🙂

jaihindhreddy21:07:28

But for library code, it makes sense to keep em private, just to make clear they are impl detail and may be broken in the future.

dharrigan21:07:00

I'll ponder on what works best for my code 🙂

🙃 1
seancorfield21:07:15

With libraries, it's important to signal "don't use this" -- so you have the freedom to change those parts (or remove them). In `next.jdbc`, for example, there are some parts that I really don't want to support so I don't want people using them. Private is a good way to keep functions out of the documentation. And if something gets into the documentation, you can bet folks want to use it. One problem in `next.jdbc` is that `next.jdbc.prepare/create` is public because it's used in other namespaces, and I've had to update the docstring to make it clear that it is not supposed to be used.

lilactown21:07:30

I’ve seen people advocate for an `impl` namespace where you keep things that aren’t public, but are shared across namespaces

lilactown21:07:30

e.g. `next.jdbc.impl.prepare/create` to signal “This is an implementation detail and subject to breaking changes without warning”

seancorfield21:07:20

Yeah, that's one option.

seancorfield21:07:59

(but since `next.jdbc.prepare/create` is public -- even tho' it says "do not use me" -- I'm committed to not moving/renaming/breaking it)

fbgava21:07:14

Hi, I'm trying to create an app with 'lein new pedestal-service' to deploy it to Heroku. In my service.clj file I've changed ::http/port to (Integer. (or (System/getenv "PORT"), 5000) but my app is crashing "Error R10 (Boot timeout) -> Web process failed to bind to \$PORT within 60 seconds of launch". Does anyone knows what config I'm missing?

fbgava21:07:59

It's working properly local with env PORT set. I've tried creating a Procfile to just run -main, but I'm getting the same error.

lilactown21:07:25

have you ruled out that it’s not taking longer than 60 seconds to boot?

fbgava21:07:29

yup, tail logging it and it's saying that jetty started @ 7000ms.

fbgava21:07:38

needed to uncomment ::http/host in service.clj and set to "0.0.0.0" and it's working now.