aspose file tools*
The moose likes Clojure and the fly likes Iteration and Building a List Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Languages » Clojure
Bookmark "Iteration and Building a List" Watch "Iteration and Building a List" New topic
Author

Iteration and Building a List

Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
I'm a newbie so please bare with me. The following code returns a collection of values from the mean-transition function:



I want to run this same function, but for each two digit combination. So I figured I could loop and call the same function as follows:



I can uncomment the pritnln statement and see that the function is returning values, but no matter what I do I can't get the results of the mean-transition function to build the list. I just get back a nil value when the transition-features-numeric function is called. I tried preceeding the mean function with a #. I tried defining a local list binding with (let [myList (list, etc. Nothing works. Do I need to iterate using recursion?
I would bet there's an easy solution this and perhaps if I had a better understanding of functional programming I could get there, but I'm at my wits end.
Any input would be GREATLY appreciated.

Thank you and Happy New Year :-)

Ned
Sean Corfield
Ranch Hand

Joined: Feb 09, 2011
Posts: 267
    
    5

If you look at the documentation for dotimes:

you'll see that it executes the body "(presumably for side effects)". It returns nil.

For folks new to Clojure (and Lisp), looping constructs are probably one of the biggest stumbling blocks. Instead of the imperative style of a loop variable and executing a block of code, what you need in the functional style is to apply a function across of a range of values, e.g., via map and range.

Clojure provides a 'for' macro that expands to a function applied across a sequence:

produces:

much as if you'd written:


The nice thing about the 'for' macro is you can "iterate" over multiple ranges in one expression and you can also apply a conditional to select only the sets of values you want.

For your example, you want something like this:

It will produce a (lazy) sequence of the results - so you don't need to call 'list' because that's what you'll get anyway.

Hope that helps!
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
Thank you Sean for the explanations and for the solution. That's exactly what I was looking for. I've spent many hours over several days trying all kinds of things including nested recursive loops, that was ugly. Right before I saw your post I figured I could just loop from 1 - 100 and using mod and quot, divide accordingly to get the digit values. Your solution is much more elegant. :-) Perhaps I should have posted sooner, but researching and trying different things although frustrating, was an opportunity to help wrap my brain around functional programming. I also ordered the "Joy of Closure" book as well.

Thanks again and Happy New Year

Ned
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
I have another question concerning building a list and loops. Certain loop constructs such as the "For" returns a lazy sequence or a list as you previously mentioned. In a situation where the loop construct is within a list, is it possible to have the loop construct append the value returned from it's embedded function to that list as opposed to returning a lazy sequece. Boy that sounds messy. Hopefully the following code can give you an idea of what I'm trying to do and you can tell me if I'm crazy with my approach.



So basically what I would like is a simple list returned from the defined function above such as this (134, 355, 563, etc). What I get though is a list within a list such as this (134, 355, 563, (343, 434, 432, etc)). I've tried various things to basically eliminate the inner list and just get it's values , but nothing I've tried has worked so far. I'm not even sure this makes sense or if it's even possible. Any help would be GREATLY appreciated. Thank you.
Sean Corfield
Ranch Hand

Joined: Feb 09, 2011
Posts: 267
    
    5

It's hard to be sure exactly what you need, based on what little code you've shown but I suspect either mapcat needs to factor into your solution or just (apply concat ...) on the result.
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
Hey Sean, thanks for the response and sorry for not providing enough code, but essentially what I want to do is simply call the "transition-features-numeric" funtion and have it return a simple list or sequence such as (999, 999, 999, etc.). Because of the For loop in that function, calling the "transition-features-numeric" function instead returns an embedded sequence as part of the result, something like this (999, 999, 999 (777, 777, 777, 777) 999, 999, 999, etc.).

I was wondering if it's possible to modify the loop somehow so the result from calling the function would simply be this (999, 999, 999, 777, 777, 777, 777, 999, 999, 999, etc.). Without breaking out the loop into a separate defn function and then calling both the transition-features-numeric function and the loop function separately and concating the results, is this possible? In other words is it possible to concat the result of the mean-transition function which is in the loop, to the transition-features-numeric result without it being part of the lazy sequence the loop itself returns?

Thanks Sean. Always apprecaite your input.
Sean Corfield
Ranch Hand

Joined: Feb 09, 2011
Posts: 267
    
    5

Again, you're not providing enough detail for me to say anything more specific than go read about mapcat and concat.
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
Hey Sean. Sorry about that. Here's the code:



And here are the results from calling the above function: (242 11 0 0 0 0 ([0 0] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0] [0 0])). It appears that the For Loop is including a collection of vectors within the list result. What I want is the result to be as follows: (242 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0).
Is there any easy way to accomplish this without having to separate out the loop in it's own defn function and then combine it's results with the transition-features-numeric function?
Thanks
Sean Corfield
Ranch Hand

Joined: Feb 09, 2011
Posts: 267
    
    5

Again, your code is incomplete and can't be run.

Please go read about mapcat, concat and perhaps flatten.
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
Hello Sean. Once again sorry. I wasn't understanding that you wanted some working code (even though you asked 3 times). The code below exemplifies what I'm asking.

So if you call the code with (some-function 2), you should get back a result like this (21 42 63 (0 0 15 15 21 60 25 135 30 240 33 375 36 540 39 735 42 960 45 1215)). Using flatten helps, but what I really want to get back is this (21 42 63 0 0 15 15 21 60 25 135 30 240 33 375 36 540 39 735 42 960 45 1215). Preferably without having to breakup some-function to do so.
Thanks Sean and again I really appreciate your patience.
Sean Corfield
Ranch Hand

Joined: Feb 09, 2011
Posts: 267
    
    5

FWIW, that doesn't run either because sqrt and pow are not defined but it was closer.

Since you don't really explain your use case, it's hard to know what the general solution ought to look like - which is why I suggested you go and read the docs. Creating an arbitrary list of computed values seems... odd... so I couldn't really see what you were trying to do.

Normally you'd have some function that you map across some sequence - or a sequence of functions that you'd invoke for a given input (essentially mapping the input across the functions) - and you'd ensure the result of the function(s) was of a compatible type. If you need sequences as results - which you get from `for` - then you'd just make all the others return a sequence too (of a single item) and use mapcat to ensure the result is the concatenation of all those sequences.
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
I'm running Clojure from within Eclipse and was able to use sqrt and pow and just assumed you would be to. Anyway this is the use case. I've inherited a home grown software tool written in Clojure that extracts feature measurements relating to a biometrics dissertation I'm working on. I need to modify this code to have it produce many more features and obviously don't know what I'm doing which makes this process both painful and exciting. These feature measurements are calculations that boil down to a series of numbers. The existing code for these features are functions that return a sequence list of these measurements similar to the "some-function" from my example, but with more complexity.

Because I don't want to mess around with this code too much (and because I'm a complete newbie to Clojure and functional programming) I want to be minimally invasive. Now these sequence list functions that return the feature measurement do so by calling other functions that return a single value or feature. So if there are 50 features, there will be 50 function call statements within the (list) function. Now I'm adding a couple hundred more features so to avoid adding 200 of these call statements, I figure I could just loop and include that call statement one time within the loop. And I figure I could just stick this loop right in the features list function with all the other feature measurement calls (similar to the "some-function" example). But it doesn't quite work this way because the loop itself returns a sequence list as opposed to just returning the result of it's embedded function call one value at a time that could magically be appended to the list function the loop resides in.

So what I'll need to do is break out the For loops from the features list function and make them their own separate functions, call these loop functions to get their result, call the existing list functions to get their result and concat them (which I believe is what you're suggesting). I'm just frustrated because I've spent days trying to do something that I thought would be simple and have gotten no where. Ugh! I'm obviously frustrated at me of course. This has nothing to do with you. On the contrary, you've been very helpful and exceptionally patient. Thank you again Sean. I do appreciate that.
Sean Corfield
Ranch Hand

Joined: Feb 09, 2011
Posts: 267
    
    5

Did you read the code I provided? I added a call to flatten which produces the result you want.
Ned Bakelman
Greenhorn

Joined: Nov 25, 2011
Posts: 12
I did not notice the code you provided until just now. I implemented it and it works PERFECTLY. And makes perfect sense. THANKS Sean. And I apologize for my last rambling post.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Iteration and Building a List