Fork me on GitHub
Drew Verlee02:07:17

I like how the problems on 4clojure are 2x harder then any i have solved in my professional career so far… This one is a puzzler. I keep getting close but then their is some flaw to my plan. Like, the problem is handling the numbers that dont fit. Its easy to keep the full structure by filtering out the bad ones, but the answer doesn’t have the same structure of collections. Or its easy to stop at the last number that doesn’t fit, but then i can’t construct a function that doesn’t return nil for that number and muck up the whole thing.


oh yeah, horribilus is right


that one took me a long time (I stopped doing 4clojure for a while when I hit it, came back and approached it totally differently later)


@vinai I sometimes use spyscope for this especially when debugging. Specifically the #spy/p reader tag is the one that pretty-prints the form that follows.


I think one thing that makes the puzzle particularly hard to solve in clojure is that its logic doesn't really respect the structure of the data, which makes us deal with the input in ways that are "weird" compared to our usual facility with data transforms


like, a deeper element might cause us to erase elements that are higher, or a higher element might make us remove ones that are deeper... it doesn't really fit our usual patterns very well

Drew Verlee11:07:08

@noisesmith thanks for the perspective!


drewverlee: thanks for reminding me of this problem, it’s a hard one. I ended up deciding I didn’t like my old answer (using an atom for a counter) and I replaced it with what turned out to be: a hand rolled monad pairing a subseq or element with a number representing remaining capacity


it doesn’t work with laziness though… I think I might need to turn to something like reify to make that work

Drew Verlee16:07:12

Hmm yes I also went for an atom, I'll have to take a look at your solution when I finally get something to work


> it looks like I solved it, but pretty hacky, using keywords for returning multiple results


Seems like something that might be suited to zippers... no idea if they work on infinite sequence


no zippers, just a recursive function with 2 arities


Oh, I didn't read the sum part, I thought it was a nested filter. Not sure if zippers can be told to "remove everything else" I suspect not in a way that's safe lazily, so probably not good.


found a bug in my soulution and an absent testcase on 4clojure 🙂


fixed 🙂


modern-cljs related boot question. Unclear whether to post a bug to the github project, ask here in #beginners, or ask in #boot.


in tutorial 16 there’s a note that says, basically, if you do a (merge-env! :source-paths dirs) where dirs contains nonexistent paths, that there should be no error.


but I’m getting an exception “Exception in thread “Thread-18" java.nio.file.NoSuchFileException: test/clj” where the path test/clj does not exist… ?


nevermind - I just opened a ticket in modern-cljs (


@gonewest818 I’ll take care of it in a couple of days. Thanks.


ever had a test inside a with-test, mysteriously ignored by leiningen even when *load-tests* is true?

Drew Verlee20:07:55

Super nooby question, but what are the pros and cons of accessing your data only through functions you define? (defn make-person [f-name l-name] {:first-name f-name :last-name}) (def drew (make-person "drew" "verlee")) Now say i want to access my first name. I could do this: (:first-name drew) which is direct but relies i know about the structure of drew. Or i could build a function that does that. (defn get-first-name [person] (:first-name person) and then access it using this getter… (get-first-name drew) ;;=> drew The way i see it, the later is more flexible as it lets you change the structure of the data containing the name. The downside is that you have to build lots of getters, which generally leaves me feeling lke i’m doing something wrong. Possible this is because setters are the real code smell but my mind associates them together.


this also prevents things like get-in


unless get-in also knows about the structure of course


@drewverlee I think you've summed up the pros and cons alright.


also note that most of the things that make clojure great depend on not using accessors


@drewverlee unlike Java, you're not forced to have a getter for everything under the sun


great question @drewverlee -- what @noisesmith says about get-in applies to the rest of the standard library too


see my comment in #clojure at 4:01

Drew Verlee20:07:50

@ghadi I might be some of the context from what your saying around 4:01. I wasn’t suggesting building a new type. Just making it so that access to the object went through a user defined functions rather then relying on functions that were Data structure specific. I dont see how this would effect the rest of the program. (map get-first-name [person-a person-b]) vs (map :first-name [person-a person-b]) However even as as i write this i feel like the trade off in creating accessor is greater then i originally thought. I mean [person-a person-b] is data, should i make an api for that? Where would it end? So are we suggesting that its worth breaking your code if the data has to change. {:first-name drew :last-name verlee} -> {:names {:first drew :middle alan :last verlee}} which would mean i have to change every place is access the first name via a keyword. e.g (:first-name person) In order to avoid the overhead of creating accessors? In essence keep the data as generic as possible so we can re-use as much of clojure core as possible?


in clojure the data (generally) is the API


as you say, the accessors have a high cost of reusability


if you make an accessor like get-first-name that does something non-obvious with its argument (like assembling/computing a value, etc.) then anything else in the program needs to call that accessor instead of looking at the (immutable) data


definitely not trying say there's never a use case for something like that


but i think it's rare. most accessors in java end up exposing object innards as information


not very common over here in clojure

Drew Verlee20:07:57

@ghadi so in general, you would recommend accessing data using data? e.g

({:3 "3"} "3") => "3"
([0 1 2 3 4] 3) => 3
(#{1 2 3} 3) => 3


in general use :first-name instead of making a micro-API (a function) get-first-name


in general


some good (old) discussion here from 6 years ago


I think it would be more accurate to say the real reason is that since (in clojure) data is immutable, there's no need for a getter.


it’s also an isomorphism thing


That said, if you wish to access only a certain piece of some data, or a transformation of it, you may write a function that derives it for you; not a getter, but mildly reminiscent


get-in/`update-in` take vectors


that you can manipulate like regular data structures


because they are regular data structures