I wrote this function that gets an element out of a tree. It's just this:
(defn at [address tree] (reduce nth tree address))
Now the problem with this is that nth has 2 overloads; one that throws an exception if the index is out of range, and one that takes a not-found argument to return instead of throwing and exception.
Now I could make an overload for my function to add this option like so:
(defn at [address tree not-found]
(reduce (fn [curr-tree index] (nth curr-tree index not-found))
tree address))
I could complain about how I have to explicitly make a new function instead of the nice nth by itself.
This isn't the real problem though. I shouldn't have to make an overload for every overload that nth has.
nth only has two overloads, but for other times when I want to write a wrapper-like function, how can I defer decisions to the user. In this example, I'm just wrapping nth; to be consistent, I want at to imitate the behavior of nth. How do I inherit the options of other functions?
I'm asking this from a clojure point of view, but it may or may not apply to other languages.
Why do you design at in terms of nth's design? Whoever calls at shouldn't be thinking about nth's overloads.
at can be passed a function like in #amalloy's answer. But I would suggest starting with a simpler design and refactoring later if need be:
(defn at
([address tree]
(reduce nth tree address))
([address tree not-found]
(reduce #(nth %1 %2 not-found) tree address)))
My rationale is passing a not-found value is easier to understand than passing a function:
(def maybe-x (at addr tree :bummer))
;; See #amalloy's answer
(def maybe-x (at' addr tree #(nth %1 %2 :bummer))))
In fact if I need to pass some other function later, I would make a new at-by function (see group-by).
Maybe something like this?
(defn at [address tree & more]
(reduce (fn [a i] (apply nth a i more)) tree address))
The & more picks up whatever extra arguments the user might supply, and the apply sticks them on to the end of the call to nth, without you having to worry about what nth is going to do with them.
Stylistically, though, I'd prefer to write out the overloads. It will make for better documentation of what options your function supports, and it will be easier to maintain down the road.
You can take a function argument to call instead of nth, and then you don't care how many overloads it has, because the caller will handle the one overload they actually want to use.
(defn at
([address tree]
(at address tree nth))
([address tree f]
(reduce f tree address)))
(at [whatever] some-tree #(nth % %2 nil))
Related
Is there any way to process a changing list using higher-order functions in Clojure and not using explicit recursion? For example, consider the following problem (that I made up to illustrate what I have in mind):
Problem: Given a list of unique integers of unknown order. Write a
that produces an output list as follows:
For any even integer, keep the same relative position in the output list.
For any odd integer, multiply by ten, and put the new number at a new
place: at the back of the original list.
So for example, from original vector [1 2 3 4 5], we get: [2 4 10 30 50]
I know how to solve this using explicit recursion. For example:
(defn process
[v]
(loop
[results []
remaining v]
(if (empty? remaining)
results
(if (even? (first remaining))
(recur (conj results (first remaining)) (rest remaining))
(recur results (conj (vec (rest remaining)) (* 10 (first remaining))))))))
This works fine. Notice that remaining changes as the function does its work. I'm doing the housekeeping here too: shuffling elements from remaining to results. What I would like to do is use a higher-order function that does the housekeeping for me. For example, if remaining did not change as the function does its work, I would use reduce and just kick off the process without worrying about loop or recur.
So my question is: is there any way to process an input (in this example, v) that changes over the course of its operations, using a higher-order function?
(Side note for more context: this question was inspired by Advent of Code 2020, Question 7, first part. There, the natural way to approach it, is to use recursion. I do here (in the find-all-containers function; which is the same way other have approached it, for example, here in the find-outer-bags function, or here in the sub-contains? function.)
This is much easier to do without recursion than with it! Since you only care about the order of evens relative to other evens, and likewise for odds, you can start by splitting the list in two. Then, map the right function over each, and simply concatenate the results.
(defn process [xs]
(let [evens (filter even? xs)
odds (filter odd? xs)]
(concat evens (map #(* 10 %) odds))))
As to the advent of code problem, I recommend working with a better data structure than a list or a vector. A map is a better way to represent what's going on, because you can easily look up the properties of each sub-bag by name. If you have a map from bag color to contents, you can write a simple (recursive) function that asks: "Can color a contain color b?" For leaf nodes the answer is no, for nodes equal to the goal color it's yes, and for branches you recurse on the contents.
I'm working on my first Clojure program. I'm having some issues figuring out how to build a tree based on an input that looks like this:
["A B" "A C" "C D" "D E" "A F" "F G"]
And the output should be something like this:
'(A (B) (C (D (E)) (F (G)))
I'm not sure how to start doing this. When it comes to an imperative programming, for example, I'd use nested loops to find whether this relation already exists or not and when it doesn't, I'd find the parent element and append the child to it. But as far as I know, functional programming would use another approach, one that I would recursively walk all the elements in a vector and in lieu of changing the existent tree I'd built a new one.
I'm not sure whether this works or not, but I have a function that looks like this:
(defn build-tree
[func tree parent child]
(map (fn [i] (if (seq? i)
build-tree
(func i parent child)))))
I'm sure the issue comes from my unfamiliarity with Clojure and functional programming and was hoping someone could explain the best way to use recursion and built this tree.
You are possibly going to receive a few answers much shorter than mine below. I've decided to kind of teach you fish - instead of showing a short program I am going to take you through a systematic way of solving this class of problems. You will have to fill in a few blanks, including converting your data into a more palatable form. These are minor points that will only distract.
The first thing you need to do is break down your output into construction steps. Those steps should match the abstract type your output is representing. In your case the output's concrete type is a list, but it actually represents a tree. These are different abstract types - a list has a head and a tail, that's it, but the tree has nodes, which may have children. You need to think in terms of abstract constructors that build different types of nodes, not about the accidental specific structure you happened to choose to represent your abstract type - a list in your case.
So imagine that you have two constructors that look like
(defn ->branch
[id kids]
...)
(defn ->leaf
[id]
...)
It is of course assumed that every kid is a tree - that is, either a branch or a leaf. In other words, every kid should be a result of either ->branch or ->leaf.
So the only way to build any tree is to have a nested chain of constructor invocations. That's what I mean by "breaking down the output into construction steps." In your case, it means the following chain:
(->branch :A [(->leaf :B) (->branch :C [(->branch :D (->leaf :E))]) (->branch :F [(->leaf :G)])])
(I am going to use keywords instead of symbols for node ids, otherwise we will get bogged down in binding/quoting details.)
Stop here for a second to feel the difference between functional and imperative styles. You outlined the imperative style yourself - you think in terms of updating a tree by finding the right place and adding a new node there. In functional style, you think in terms of creating a value, not updating another value. (Of course nothing technically prevents you from doing the same in an imperative language - like using a nested call to constructors, or using a static factory this way, it's just not something that comes about naturally.)
To get to your specific tree representation as a list, you just need to fill in the implementation of ->branch and ->leaf above, which is very simple. (Left as an exercise for you.)
Now back to building the tree. The task of coding a function that builds a tree is actually creating a chain of constructor calls from the input data. So you need to understand two things:
When to call which constructor (here, when to call ->branch and when call ->leaf)
How to get parameters for the constructors (id for either, and kids for ->branch)
To start, how do we know what node to begin? That depends on what the problem is, but let's assume that it is given us as a parameter. So we assume that we are building the following function:
(defn ->tree
[adj-list node]
...)
The adj-list is your input - which is an adjacency list even if you try to disguise it as a list of strings, and we are going to treat it this way (like #SamEstep suggested in the comments.) Left as an exercise for you to convert your form of input into an adjacency list.
So it should be clear what we use as an id in our constructors - the node. But is it ->branch or ->leaf? Well, the answer depends on whether we have direct descendants of node in the adj-list, so apparently we need a function
(defn descendants
[adj-list node]
...)
which returns a list (possibly empty) of ids of direct descendants of the node. (Left as an exercise.) So we can decide whether to call ->branch or ->leaf depending on whether that list is empty or not, like
(if-let [kid-ids (descendants node)]
(->branch node ...)
(->leaf node))
Ok, then we need to supply these ... to ->branch. Are they kid-ids? No, they must be trees, not ids, either branches or leaves themselves. In other words, we need to first call ->tree on them. See? We hit the recursion point, and it came about naturally (or so I hope). In Clojure, calling a function on every element of a sequence is done by map, which returns a sequence of results, which is exactly what we need:
(if-let [kid-ids (descendants adj-list node)]
(->branch node (map ->tree kid-ids)
(->leaf node))
except that ->tree expects an additional parameter, adj-list. We can use an anonymous function, or we can use partial. We will use a partial with a let binding, which is the cleanest way of doing it:
(let [->tree' (partial ->tree adj-list)]
(if-let [kid-ids (descendants adj-list node)]
(->branch node (map ->tree' kid-ids))
(->leaf node)))
This is it. Let's put it together:
(defn ->tree
[adj-list node]
(let [->tree' (partial ->tree adj-list)]
(if-let [kid-ids (descendants adj-list node)]
(->branch node (map ->tree' kid-ids))
(->leaf node))))
The result:
(def adj-list [[:A :B] [:A :C] [:C :D] [:D :E] [:A :F] [:F :G]])
(->tree adj-list :A)
;; => (:A (:B) (:C (:D (:E))) (:F (:G)))
Let's sum up:
Look at your data in abstract terms. Create constructors, and use them for building your output.
To build output means to create a chain of constructor calls.
Which means you need to map your input's shape to output constructors and their parameters.
In many cases, the recursion will emerge by itself naturally at this step.
After you have done it, you can optimize and short-circuit to your heart's content (like if you look closely, you can do away with ->leaf.) But don't do it prematurely.
Your output looks like an associative structure, is there a reason you're using a list instead of a map here?
Also is the ordering guaranteed to match the tree structure as in your example? I'll assume not. And I think it's easier to not use recursion here...
So let's parse the input into an adjacency list, like:
(reduce
(fn[g edge]
(let [[from to]] (map keyword (str/split " " edge))
(update g from #(conj % to))
{}
["A B" "B C"])
Which should output:
{A [B C F],,,}
which can be used to create your tree as a list if you desire.
I can't test this because I'm in mobile at the moment so forgive any mistakes. :)
Thought user2946753's example was useful. Tweaked it to get it working.
(defn example []
(reduce (fn[g edge]
(let [[from to] (map keyword (str/split edge #" "))]
(update g from #(conj % to))))
{}
["A B" "B C"]))
(example)
=> {:A (:B), :B (:C)}
What's the (most) idiomatic Clojure representation of no-op? I.e.,
(def r (ref {}))
...
(let [der #r]
(match [(:a der) (:b der)]
[nil nil] (do (fill-in-a) (fill-in-b))
[_ nil] (fill-in-b)
[nil _] (fill-in-a)
[_ _] ????))
Python has pass. What should I be using in Clojure?
ETA: I ask mostly because I've run into places (cond, e.g.) where not supplying anything causes an error. I realize that "most" of the time, an equivalent of pass isn't needed, but when it is, I'd like to know what's the most Clojuric.
I see the keyword :default used in cases like this fairly commonly.
It has the nice property of being recognizable in the output and or logs. This way when you see a log line like: "process completed :default" it's obvious that nothing actually ran. This takes advantage of the fact that keywords are truthy in Clojure so the default will be counted as a success.
There are no "statements" in Clojure, but there are an infinite number of ways to "do nothing". An empty do block (do), literally indicates that one is "doing nothing" and evaluates to nil. Also, I agree with the comment that the question itself indicates that you are not using Clojure in an idiomatic way, regardless of this specific stylistic question.
The most analogous thing that I can think of in Clojure to a "statement that does nothing" from imperative programming would be a function that does nothing. There are a couple of built-ins that can help you here: identity is a single-arg function that simply returns its argument, and constantly is a higher-order function that accepts a value, and returns a function that will accept any number of arguments and return that value. Both are useful as placeholders in situations where you need to pass a function but don't want that function to actually do much of anything. A simple example:
(defn twizzle [x]
(let [f (cond (even? x) (partial * 4)
(= 0 (rem x 3)) (partial + 2)
:else identity)]
(f (inc x))))
Rewriting this function to "do nothing" in the default case, while possible, would require an awkward rewrite without the use of identity.
In Clojure, if I have a function f,
(defn f [& r] ... )
and I have a seq args with the arguments I want to call f with, I can easily use apply:
(apply f args)
Now, say I have another function g, which is designed to take any of a number of optional, named arguments - that is, where the rest argument is destructured as a map:
(defn g [& {:keys [a b] :as m}] ... )
I'd normally call g by doing something like
(g :a 1 :b 2)
but if I happen to have a map my-map with the value {:a 1 :b 2}, and I want to "apply" g to my-map - in other words, get something that would end up as the above call, then I naturally couldn't use apply, since it would be equivalent to
(g [:a 1] [:b 2])
Is there a nice way to handle this? May I have gone off track in my design to end up with this? The best solution I can find would be
(apply g (flatten (seq my-map)))
but I surely don't like it. Any better solutions?
EDIT: A slight improvement to the suggested solution might be
(apply g (mapcat seq my-map))
which at least removes one function call, but it may still not be very clear what's going on.
I have stumbled into this problem myself and ended up defining functions to expect one map. A map can have a variable amount of key/value pairs, and if flexible enough, so there is no need for & rest arguments. Also there is no pain with apply. Makes life a lot easier!
(defn g [{:keys [a b] :as m}] ... )
There is no better direct way than converting to a seq.
You are done. You have done all you can.
It's just not really clojurish to have Common Lisp style :keyword arg functions. If you look around Clojure code you will find that almost no functions are written that way.
Even the great RMS is not a fan of them:
"One thing I don't like terribly much is keyword arguments (8). They don't seem quite Lispy to me; I'll do it sometimes but I minimize the times when I do that." (Source)
At the moment where you have to break a complete hash map into pieces just to pass all of them as keyword mapped arguments you should question your function design.
I find that in the case where you want to pass along general options like :consider-nil true you are probably never going to invoke the function with a hash-map {:consider-nil true}.
In the case where you want to do an evaluation based on some keys of a hash map you are 99% of the time having a f ([m & args]) declaration.
When I started out defining functions in Clojure I hit the same problem. However after thinking more about the problems I tried to solve I noticed myself using destructoring in function declaration almost never.
Here is a very simplistic function which may be used exactly as apply, except that the final arg (which should be a map) will be expanded out to :key1 val1 :key2 val2 etc.
(defn mapply
[f & args]
(apply f (reduce concat (butlast args) (last args))))
I'm sure there are more efficient ways to do it, and whether or not you'd want to end up in a situation where you'd have to use such a function is up for debate, but it does answer the original question. Mostly, I'm childishly satisfied with the name...
Nicest solution I have found:
(apply g (apply concat my-map))
I've started to learn clojure but I'm having trouble wrapping my mind around certain concepts. For instance, what I want to do here is to take this function and convert it so that it calls get-origlabels lazily.
(defn get-all-origlabels []
(set (flatten (map get-origlabels (range *song-count*)))))
My first attempt used recursion but blew up the stack (song-count is about 10,000). I couldn't figure out how to do it with tail recursion.
get-origlabels returns a set each time it is called, but values are often repeated between calls. What the get-origlabels function actually does is read a file (a different file for each value from 0 to song-count-1) and return the words stored in it in a set.
Any pointers would be greatly appreciated!
Thanks!
-Philip
You can get what you want by using mapcat. I believe putting it into an actual Clojure set is going to de-lazify it, as demonstrated by the fact that (take 10 (set (iterate inc 0))) tries to realize the whole set before taking 10.
(distinct (mapcat get-origlabels (range *song-count*)))
This will give you a lazy sequence. You can verify that by doing something like, starting with an infinite sequence:
(->> (iterate inc 0)
(mapcat vector)
(distinct)
(take 10))
You'll end up with a seq, rather than a set, but since it sounds like you really want laziness here, I think that's for the best.
This may have better stack behavior
(defn get-all-origlabels []
(reduce (fn (s x) (union s (get-origlabels x))) ${} (range *song-count*)))
I'd probably use something like:
(into #{} (mapcat get-origlabels (range *song-count*)))
In general, "into" is very helpful when constructing Clojure data structures. I have this mental image of a conveyor belt (a sequence) dropping a bunch of random objects into a large bucket (the target collection).