Re: per-defmulti hierarchies
Hello, Am 07.01.2009 um 17:44 schrieb Meikel Brandmeyer: Please find attached another patch going for IRef instead of Var directly. And without the other cruft. Another update in sync with updated issue #8. Sincerely Meikel issue-8b.diff Description: Binary data smime.p7s Description: S/MIME cryptographic signature
Re: Ugly Sudoku solver
On 11.01.2009, at 08:56, Tzach wrote: > Following your good advice, I also update the next-cell function to > work in a lazy way instead of sorting the values of the entire board. Good idea! > (defn next-cell [board] > "return the next potential cell to set, and the valid alternatives" > (first (for [n (range 1 10)] > (filter >#(= n (count (second %))) >(map-board board valid-values) Your implementation has the disadvantage of recomputing (map- board ...) nine times. You can avoid this with a simple modification: (defn next-cell [board] "return the next potential cell to set, and the valid alternatives" (let [vv (map-board board valid-values)] (first (for [n (range 1 10)] (filter #(= n (count (second %))) vv) Since the values of the lazy sequence vv are cached, nothing will ever be recomputed. However, I think there is also a bug in your function: (first (for ..)) will return the result of the first iteration of the for, even if it is emtpy. What you want is the first element of the first non-empty element of the for sequence. You can get this with (first (apply concat (for [n ...))). Concat again creates a lazy sequence, so nothing is computed unless necessary. Konrad. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
On Jan 11, 6:32 am, "Nick Vogel" wrote: > Ok, first of all, here's how I translated that python code: > > (defn msort [myList] > (if (> (count myList) 1) > (let [l1 (first myList) l2 (second myList)] > (recur (concat (drop 2 myList) (my-merge l1 l2 > (first myList))) I'd change (> (count myList) 1) to (rest myList). It should work the same way, and won't take O(N) time on seqs. - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
Hi, I'm just learning Clojure too, so I don't have much to add to what everyone else has said, but here's my crack at a full implenentation of merge-sort in Clojure. I'm sure that there is plenty of room for improvement (especially wrt. the merge function) but in case it's helpful, here it is: (defn lazy-merge [seq1 seq2] (cond (<= (count seq1) 0) (lazy-cons (first seq2) (rest seq2)) (<= (count seq2) 0) (lazy-cons (first seq1) (rest seq1)) :else (let [h1 (first seq1) h2 (first seq2)] (if (< h1 h2) (lazy-cons h1 (lazy-merge (rest seq1) seq2)) (lazy-cons h2 (lazy-merge seq1 (rest seq2))) (defn merge-sort [seq] (if (> (count seq) 1) (apply lazy-merge (map merge-sort (split-at (/ (count seq) 2) seq))) seq)) - John On Jan 10, 9:21 pm, e wrote: > I'm just trying to understand basic stuff. > say I have a local list called "myList" (assigned using 'let' . . . > should I have used something else?) Who cares what's in it. Maybe I > set it up from a list comprehension from some input to my function. > > I have no idea how to iteratively mess with it since everything is > persistent. Ok, like, say it's a list of lists and I am going to be > merging the lists, like Tarjan's mergesort from some book from > college. > > so I have myList with contents [[11] [2] [4] [1] [99]] > > here's how I would do it in python: > > def msort(myList): > myList = [[x] for x in someList] > while len(myList) > 1: > l1 = myList.pop(0) > l2 = myList.pop(0) > listmerge = some_merge_function(l1, l2) > myList.append(listmerge) # important that newly merged go > to back of queue to get proper runtime > return myList[0] > > here's what I'm trying to do for clojure, and it's a mess: > > (defn msort [toSort] > (def sorted (let > [myList (for [x toSort] [x])] <- so far so good (not a > real comment. I don't know how, yet) > [ > (while (> (count myList) 1) <--- infinite loop the way > written? I don't know how to overwrite myList > (let [l1 (nth myList 0)][]) > (let [l2 (nth myList 1)][]) > (let [listmerge (some_merge_func l1 l2)][]) > (let [myList (concat (drop 2 myList) listmerge)][myList]) <--- > probably a different local variable > ) > ])) > sorted) > > doesn't compile anyway . . . I see that the let is causing the scope > to be all screwed up. l1 and l2 can't be seen for the merge function. > > should I be using let at all here? Can things be redefined using > def? see how much simpler it is not to say anything? Which is > it def or let in python? Answer: No . . .but I'm sure there's > value. This seems like something that might be in the FAQ. . . .or > somewhere back in these discussions. I'll look around. > > Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: SLIME: trouble with java.lang.OutOfMemoryError
Hello, If you like eclipse and would like to see where clojuredev (eclipse plugin) is right now, you can give a quick look at the current state of clojuredev by trying to immediately install it via the update site link : http://clojure-dev.googlecode.com/svn/updatesite/ Still not ready for public availability (it's alpha alpha), but that's a start. And you could subscribe to clojuredev user ml: very very low traffic (no message right now :-), and we could jut publish announces when something interesting for users is ready on the update site. Quickly, what is available right now : - enable a java project with clojure dev nature (contextual menu of the java project, -> Clojure submenu) - wizard for creation of clojure project (= java project + clojure nature) - syntax coloring - some keyboard accelerators for : - jump to matching bracket : Ctr+Shift+P - Go to start of top level defun : Ctrl+Alt+A (or AltGr+A) - Go to end of top level defun : Ctrl+Alt+E (or AltrGr+E) - Select (highlight) top level defun : Ctrl+Altr+H (or AltrGr+H) - Launch configuration for clojure : enable to select which files to load on startup, and other things similar to java launch configuration. Not yet possible to select a main method other than clojure.lang.Repl (will change at some point in time) If you have time, please give it a try, do some feedback, and fill free to submit tickets if you find bugs (in the features listed above, the other ones you may find via menus are not yet ready, even if the menu are there). Regards, -- Laurent On Jan 11, 3:18 am, e wrote: > seems like enclosjure addresses a bunch of my problems/questions. It > also seems to work like we wanted SLIME to work, more or > less . . .where you attach to the vm that's used for execution . . . > only you attach to the REPL, I think, which still accomplishes the > goal of keeping the editor separate from the memory, but what about > having the REPL being able to attach to the vm it is managing. Then > it wouldn't be something that NetBeans/enclosure is doing . . . rather > something that's part of the language. > > So, yeah. enslojure sets up a HelloWorld that you can play with right > away. In fact, when you click on "build" it even tells you how you > could run your application from the command line using a java > command. It jars up you whole clojure project and everything. Nice. > On the other hand, I couldn't figure out how to use NetBeans' run > button. it couldn't find main or something. So I also couldn't debug > using NetBeans' debugger because of this. Also, it isn't clear how to > get different clojure files to work together. Do you use the (load) > function? If so, I don't know how the project thinks of relative file > locations. It's not as clean/clear as java (for a beginner, at least) > where you just import classes you want to use . . and make > packages. . . . or modules in python. I don't know what the notion of > "path" is in clojure. I see the namespace stuff but have no clue how > to make it work yet. Are you just supposed to use one giant file for > all your work? That wouldn't be good for teams, for sure. . . only > for hacking. Also the REPL errors are USELESS to a beginner. > something about iSeq all the time. The moral for me there was no to > make an error. Better than where I was before enclojure. Again, I > contend that a language is only as good as the IDE that has been > written for it, which is why it's cool to see enclojure coming along > (even though it means learning NetBeans instead of Eclipse). > > On Jan 10, 5:31 pm, Paul Mooser wrote: > > > If I'm not mistaken, this is fairly close to how SLIME works, when > > connected to a remote VM. The remote VM is running some server code > > which allows it to communicate with SLIME, which is running inside of > > emacs. > > > On Jan 10, 2:15 pm, e wrote: > > > > exactly. . . .but I bet a lot of people would just reply that this is > > > not possible to address since the REPL is the one and only vm. > > > Disclaimer, I'm only guessing at that, too. I don't understand any of > > > this, yet. But if that's the case, fix that. Have the REPL send > > > messages to the vm that's running the program . . . instead of the > > > REPL being the program. > > > > On Jan 10, 5:00 pm, Paul Mooser wrote: > > > > > Yeah, I'm not really sure how I think the problem would be ideally > > > > solved. It would just be nice for an interactive programming > > > > environment to be able to recover from all exceptions that happen at a > > > > higher level than the VM itself. > > > > > On Jan 10, 12:20 pm, "Christian Vest Hansen" > > > > wrote: > > > > > > I don't think it is possible to define a way to deal with heap > > > > > saturation that is general enough to cover all programs written in > > > > > Clojure, and therefor I don't think this is something that the Clojure > > > > > runtime should deal with at all. > > > > > > Personally, I only know of two ways
Re: non recursive impl in presence of persistence?
thanks for all the help. just to answer the last question, 'sorted' should have taken on the new def before getting returned. that return happens after the def is complete. Will check out refs. I think that's what I need to understand. On Jan 11, 1:27 am, "Eric Lavigne" wrote: > > I have no idea how to iteratively mess with it since everything is > > persistent. Ok, like, say it's a list of lists and I am going to be > > merging the lists, like Tarjan's mergesort from some book from > > college. > > Sorting is done much more easily with recursion than with iteration. > However, it looks like you are focused on learning language features rather > than programming strategy, so I will just answer your questions. > > I have not actually done any iterative programming in Clojure, as I prefer > the functional approach, so my answers are based on my limited understanding > of the Clojure documentation. > > so I have myList with contents [[11] [2] [4] [1] [99]] > > > > > > > here's how I would do it in python: > > > def msort(myList): > > myList = [[x] for x in someList] > > while len(myList) > 1: > > l1 = myList.pop(0) > > l2 = myList.pop(0) > > listmerge = some_merge_function(l1, l2) > > myList.append(listmerge) # important that newly merged go > > to back of queue to get proper runtime > > return myList[0] > > > here's what I'm trying to do for clojure, and it's a mess: > > > (defn msort [toSort] > > (def sorted (let > > Be careful with def. I think that it creates a global, and it looks like you > want something with a scope limited to this function. > > http://clojure.org/Vars > > > [myList (for [x toSort] [x])] <- so far so good (not a > > real comment. I don't know how, yet) > > Use a semicolon to create a comment: > > some code ; a comment > > > [ > > (while (> (count myList) 1) <--- infinite loop the way > > written? I don't know how to overwrite myList > > (let [l1 (nth myList 0)][]) > > The line above does nothing. When you write "(let [x 1] expr1) expr2" the > new value of x has a narrow scope so that it only affects expr1. > > You are wanting to create a local variable that you can change. Refs can do > that: > > (let [x (ref 3)] > (dosync > (while (> @x 0) > (ref-set x (- @x 1))) > @x)) > > http://clojure.org/Refs > > > (let [l2 (nth myList 1)][]) > > (let [listmerge (some_merge_func l1 l2)][]) > > (let [myList (concat (drop 2 myList) listmerge)][myList]) <--- > > probably a different local variable > > ) > > ])) > > sorted) > > After all that work you just return the original list? I must have missed > the part where you tried to change sorted. Any such attempt would fail, > though, because Clojure collections are immutable. Maybe sorted should be a > ref to a list instead of just a list. > > Here is a discussion of sorting implementations in Clojure. I hope that you > find it useful. > > http://www.fatvat.co.uk/2008/12/bubbling-clojure.html > > -- > Education is what survives when what has been learned has been forgotten. > > - B. F. Skinner --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
that looks interesting, except it is missing the part where you take the original list and make it into a list of lists using list comprehension. That works in python and clojure for me ... "the so far so good part". If the recur were to do that repeatedly, the algorithm would get messed up. Still awesome to find out about . . .and actually that's another way to do it because I can call a helper function after the original divide (list comprehension) step . . . remembering that mergesort is a divide and conquer problem. On Jan 11, 1:32 am, "Nick Vogel" wrote: > Ok, first of all, here's how I translated that python code: > > (defn msort [myList] > (if (> (count myList) 1) > (let [l1 (first myList) l2 (second myList)] > (recur (concat (drop 2 myList) (my-merge l1 l2 > (first myList))) > > The main thing that might need explaining is the recur, which basically goes > back to either the last function definition or last loop and rebinds > whatever parameters werre passed in. In this case it goes back and is as if > it's calling msort with (concat (drop 2 myList) (my-merge l1 l2)) as > myList. The let is just for clarity's sake, you could have just put them in > place of l1 and l2 in the recur. > > On Sun, Jan 11, 2009 at 12:21 AM, e wrote: > > > I'm just trying to understand basic stuff. > > say I have a local list called "myList" (assigned using 'let' . . . > > should I have used something else?) Who cares what's in it. Maybe I > > set it up from a list comprehension from some input to my function. > > > I have no idea how to iteratively mess with it since everything is > > persistent. Ok, like, say it's a list of lists and I am going to be > > merging the lists, like Tarjan's mergesort from some book from > > college. > > > so I have myList with contents [[11] [2] [4] [1] [99]] > > > here's how I would do it in python: > > > def msort(myList): > > myList = [[x] for x in someList] > > while len(myList) > 1: > > l1 = myList.pop(0) > > l2 = myList.pop(0) > > listmerge = some_merge_function(l1, l2) > > myList.append(listmerge) # important that newly merged go > > to back of queue to get proper runtime > > return myList[0] > > > here's what I'm trying to do for clojure, and it's a mess: > > > (defn msort [toSort] > > (def sorted (let > > [myList (for [x toSort] [x])] <- so far so good (not a > > real comment. I don't know how, yet) > > [ > > (while (> (count myList) 1) <--- infinite loop the way > > written? I don't know how to overwrite myList > > (let [l1 (nth myList 0)][]) > > (let [l2 (nth myList 1)][]) > > (let [listmerge (some_merge_func l1 l2)][]) > > (let [myList (concat (drop 2 myList) listmerge)][myList]) <--- > > probably a different local variable > > ) > > ])) > > sorted) > > > doesn't compile anyway . . . I see that the let is causing the scope > > to be all screwed up. l1 and l2 can't be seen for the merge function. > > > should I be using let at all here? Can things be redefined using > > def? see how much simpler it is not to say anything? Which is > > it def or let in python? Answer: No . . .but I'm sure there's > > value. This seems like something that might be in the FAQ. . . .or > > somewhere back in these discussions. I'll look around. > > > Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
great. I wondered about that, too! thanks. On Jan 11, 7:27 am, James Reeves wrote: > On Jan 11, 6:32 am, "Nick Vogel" wrote: > > > Ok, first of all, here's how I translated that python code: > > > (defn msort [myList] > > (if (> (count myList) 1) > > (let [l1 (first myList) l2 (second myList)] > > (recur (concat (drop 2 myList) (my-merge l1 l2 > > (first myList))) > > I'd change (> (count myList) 1) to (rest myList). It should work the > same way, and won't take O(N) time on seqs. > > - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
I'm trying to follow. Can you explain in pseudo code? That's impressive that it follows the classic approach on persistent data structures . . .. from what I can tell. You successively divide the list in halves of halves of halves. Then the lists of size 1 are merged together as the stack unwinds . . .then I kinda lose it. Are lists of equal length merged like what's needed for the runtime? I mean, if all the size one lists are just merged in with the first list as they come, then it won't run out of lists NEARLY as quickly as it should. so as long as it does that. so here's the psuedo code I'm trying to implement in clojure. . . . python code also worked. The trouble is I can't just do the pop_front thing below, which makes the code ugly. . . . or can I? given a list of items in myOriginalList: 1) myBrokenUpList = {[x], foreach x in myOriginalList} do while myBrokenUpList has more than one mini-list in it: 2) a = pop_front the first list in myBrokenUpList 3) b = pop_front the first list in myBrokenUpList 4) merged = some_merge_func(a, b) 5) myBrokenUpList = myBrokenUpList + merged <--- important that the merged list go in at the back. Is that what yours does? or does it merge all the singleton lists into one growing list? If it is the latter, then that seems to be O (n^2) time instead of O(n logn) On Jan 11, 2:41 am, John wrote: > Hi, > > I'm just learning Clojure too, so I don't have much to add to what > everyone else has said, but here's my crack at a full implenentation > of merge-sort in Clojure. I'm sure that there is plenty of room for > improvement (especially wrt. the merge function) but in case it's > helpful, here it is: > > (defn lazy-merge [seq1 seq2] > (cond (<= (count seq1) 0) (lazy-cons (first seq2) (rest seq2)) > (<= (count seq2) 0) (lazy-cons (first seq1) (rest seq1)) > :else (let [h1 (first seq1) > h2 (first seq2)] > (if (< h1 h2) > (lazy-cons h1 (lazy-merge (rest seq1) seq2)) > (lazy-cons h2 (lazy-merge seq1 (rest seq2))) > > (defn merge-sort [seq] > (if (> (count seq) 1) > (apply lazy-merge (map merge-sort (split-at (/ (count seq) 2) > seq))) > seq)) > > - > John > > On Jan 10, 9:21 pm, e wrote: > > > I'm just trying to understand basic stuff. > > say I have a local list called "myList" (assigned using 'let' . . . > > should I have used something else?) Who cares what's in it. Maybe I > > set it up from a list comprehension from some input to my function. > > > I have no idea how to iteratively mess with it since everything is > > persistent. Ok, like, say it's a list of lists and I am going to be > > merging the lists, like Tarjan's mergesort from some book from > > college. > > > so I have myList with contents [[11] [2] [4] [1] [99]] > > > here's how I would do it in python: > > > def msort(myList): > > myList = [[x] for x in someList] > > while len(myList) > 1: > > l1 = myList.pop(0) > > l2 = myList.pop(0) > > listmerge = some_merge_function(l1, l2) > > myList.append(listmerge) # important that newly merged go > > to back of queue to get proper runtime > > return myList[0] > > > here's what I'm trying to do for clojure, and it's a mess: > > > (defn msort [toSort] > > (def sorted (let > > [myList (for [x toSort] [x])] <- so far so good (not a > > real comment. I don't know how, yet) > > [ > > (while (> (count myList) 1) <--- infinite loop the way > > written? I don't know how to overwrite myList > > (let [l1 (nth myList 0)][]) > > (let [l2 (nth myList 1)][]) > > (let [listmerge (some_merge_func l1 l2)][]) > > (let [myList (concat (drop 2 myList) listmerge)][myList]) <--- > > probably a different local variable > > ) > > ])) > > sorted) > > > doesn't compile anyway . . . I see that the let is causing the scope > > to be all screwed up. l1 and l2 can't be seen for the merge function. > > > should I be using let at all here? Can things be redefined using > > def? see how much simpler it is not to say anything? Which is > > it def or let in python? Answer: No . . .but I'm sure there's > > value. This seems like something that might be in the FAQ. . . .or > > somewhere back in these discussions. I'll look around. > > > Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: SLIME: trouble with java.lang.OutOfMemoryError
great. will do. On Jan 11, 9:14 am, lpetit wrote: > Hello, > > If you like eclipse and would like to see where clojuredev (eclipse > plugin) is right now, you can give a quick look at the current state > of clojuredev by trying to immediately install it via the update site > link : > > http://clojure-dev.googlecode.com/svn/updatesite/ > > Still not ready for public availability (it's alpha alpha), but that's > a start. > > And you could subscribe to clojuredev user ml: very very low traffic > (no message right now :-), and we could jut publish announces when > something interesting for users is ready on the update site. > > Quickly, what is available right now : > - enable a java project with clojure dev nature (contextual menu of > the java project, -> Clojure submenu) > - wizard for creation of clojure project (= java project + clojure > nature) > - syntax coloring > - some keyboard accelerators for : > - jump to matching bracket : Ctr+Shift+P > - Go to start of top level defun : Ctrl+Alt+A (or AltGr+A) > - Go to end of top level defun : Ctrl+Alt+E (or AltrGr+E) > - Select (highlight) top level defun : Ctrl+Altr+H (or AltrGr+H) > - Launch configuration for clojure : enable to select which files to > load on startup, and other things similar to java launch > configuration. Not yet possible to select a main method other than > clojure.lang.Repl (will change at some point in time) > > If you have time, please give it a try, do some feedback, and fill > free to submit tickets if you find bugs (in the features listed above, > the other ones you may find via menus are not yet ready, even if the > menu are there). > > Regards, > > -- > Laurent > > On Jan 11, 3:18 am, e wrote: > > > seems like enclosjure addresses a bunch of my problems/questions. It > > also seems to work like we wanted SLIME to work, more or > > less . . .where you attach to the vm that's used for execution . . . > > only you attach to the REPL, I think, which still accomplishes the > > goal of keeping the editor separate from the memory, but what about > > having the REPL being able to attach to the vm it is managing. Then > > it wouldn't be something that NetBeans/enclosure is doing . . . rather > > something that's part of the language. > > > So, yeah. enslojure sets up a HelloWorld that you can play with right > > away. In fact, when you click on "build" it even tells you how you > > could run your application from the command line using a java > > command. It jars up you whole clojure project and everything. Nice. > > On the other hand, I couldn't figure out how to use NetBeans' run > > button. it couldn't find main or something. So I also couldn't debug > > using NetBeans' debugger because of this. Also, it isn't clear how to > > get different clojure files to work together. Do you use the (load) > > function? If so, I don't know how the project thinks of relative file > > locations. It's not as clean/clear as java (for a beginner, at least) > > where you just import classes you want to use . . and make > > packages. . . . or modules in python. I don't know what the notion of > > "path" is in clojure. I see the namespace stuff but have no clue how > > to make it work yet. Are you just supposed to use one giant file for > > all your work? That wouldn't be good for teams, for sure. . . only > > for hacking. Also the REPL errors are USELESS to a beginner. > > something about iSeq all the time. The moral for me there was no to > > make an error. Better than where I was before enclojure. Again, I > > contend that a language is only as good as the IDE that has been > > written for it, which is why it's cool to see enclojure coming along > > (even though it means learning NetBeans instead of Eclipse). > > > On Jan 10, 5:31 pm, Paul Mooser wrote: > > > > If I'm not mistaken, this is fairly close to how SLIME works, when > > > connected to a remote VM. The remote VM is running some server code > > > which allows it to communicate with SLIME, which is running inside of > > > emacs. > > > > On Jan 10, 2:15 pm, e wrote: > > > > > exactly. . . .but I bet a lot of people would just reply that this is > > > > not possible to address since the REPL is the one and only vm. > > > > Disclaimer, I'm only guessing at that, too. I don't understand any of > > > > this, yet. But if that's the case, fix that. Have the REPL send > > > > messages to the vm that's running the program . . . instead of the > > > > REPL being the program. > > > > > On Jan 10, 5:00 pm, Paul Mooser wrote: > > > > > > Yeah, I'm not really sure how I think the problem would be ideally > > > > > solved. It would just be nice for an interactive programming > > > > > environment to be able to recover from all exceptions that happen at a > > > > > higher level than the VM itself. > > > > > > On Jan 10, 12:20 pm, "Christian Vest Hansen" > > > > > wrote: > > > > > > > I don't think it is possible to define a way to deal with heap > > > > > > saturat
Re: update-values for clojure.contrib.sql
On Jan 2, 2009, at 2:21 AM, budu wrote: Hi, I was experimenting with clojure-contrib's sql features and found that there wasn't any update-values function. I've written my own and I'm sharing it here: (defn update-values [table where column-names & values] "Update columns of a table with values. columns-names is a vector of column names (strings or keywords) and the rest of arguments are the values for those columns." (let [columns (map #(str (the-str %) " = ?") column-names) template (if (seq column-names) (apply str (interpose "," columns)) "")] (apply do-prepared (format "update %s set %s where %s" (the-str table) template where) [values]))) It only send one set of values to do-prepared because of the where clause that would have to change according to each sets. I'm ready for your commentaries and/or suggestions. Hi budu, I'd like to include something like this in clojure.contrib.sql. That will go smoothest if I can base it directly on what you've written and that's only possible if you send in a contributor agreement. Would you please send one in? Please see http://clojure.org/contributing for more info. Thanks, --Steve smime.p7s Description: S/MIME cryptographic signature
Re: non recursive impl in presence of persistence?
refs seem silly in this context! Now I REALLY have to get my head wrapped around clojure. sooo I only have one thread, but I have to do a dosync? Why can this whole function just work in a thread agnostic way? It's a local variable! If a thread calls it, then a thread should own the memory that's created. Each thread should have its own asynchronous stack to push local variables onto that no one else is allowed to see. Seems like all that transaction, dosync stuff ought to be optional. I made my own, local list . . . that no one else in the world can see. I should be able to call pop_front on it to get back the first item while also mutating the the list to only contain the rest. Oh, and my other choice is to use recursion. I'll look into that recur thing. On Jan 11, 1:27 am, "Eric Lavigne" wrote: > > I have no idea how to iteratively mess with it since everything is > > persistent. Ok, like, say it's a list of lists and I am going to be > > merging the lists, like Tarjan's mergesort from some book from > > college. > > Sorting is done much more easily with recursion than with iteration. > However, it looks like you are focused on learning language features rather > than programming strategy, so I will just answer your questions. > > I have not actually done any iterative programming in Clojure, as I prefer > the functional approach, so my answers are based on my limited understanding > of the Clojure documentation. > > so I have myList with contents [[11] [2] [4] [1] [99]] > > > > > > > here's how I would do it in python: > > > def msort(myList): > > myList = [[x] for x in someList] > > while len(myList) > 1: > > l1 = myList.pop(0) > > l2 = myList.pop(0) > > listmerge = some_merge_function(l1, l2) > > myList.append(listmerge) # important that newly merged go > > to back of queue to get proper runtime > > return myList[0] > > > here's what I'm trying to do for clojure, and it's a mess: > > > (defn msort [toSort] > > (def sorted (let > > Be careful with def. I think that it creates a global, and it looks like you > want something with a scope limited to this function. > > http://clojure.org/Vars > > > [myList (for [x toSort] [x])] <- so far so good (not a > > real comment. I don't know how, yet) > > Use a semicolon to create a comment: > > some code ; a comment > > > [ > > (while (> (count myList) 1) <--- infinite loop the way > > written? I don't know how to overwrite myList > > (let [l1 (nth myList 0)][]) > > The line above does nothing. When you write "(let [x 1] expr1) expr2" the > new value of x has a narrow scope so that it only affects expr1. > > You are wanting to create a local variable that you can change. Refs can do > that: > > (let [x (ref 3)] > (dosync > (while (> @x 0) > (ref-set x (- @x 1))) > @x)) > > http://clojure.org/Refs > > > (let [l2 (nth myList 1)][]) > > (let [listmerge (some_merge_func l1 l2)][]) > > (let [myList (concat (drop 2 myList) listmerge)][myList]) <--- > > probably a different local variable > > ) > > ])) > > sorted) > > After all that work you just return the original list? I must have missed > the part where you tried to change sorted. Any such attempt would fail, > though, because Clojure collections are immutable. Maybe sorted should be a > ref to a list instead of just a list. > > Here is a discussion of sorting implementations in Clojure. I hope that you > find it useful. > > http://www.fatvat.co.uk/2008/12/bubbling-clojure.html > > -- > Education is what survives when what has been learned has been forgotten. > > - B. F. Skinner --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
On Sun, Jan 11, 2009 at 10:50 AM, e wrote: > > refs seem silly in this context! Now I REALLY have to get my head > wrapped around clojure. sooo I only have one thread, but I have > to do a dosync? Why can this whole function just work in a thread > agnostic way? It's a local variable! If a thread calls it, then a > thread should own the memory that's created. Each thread should have > its own asynchronous stack to push local variables onto that no one > else is allowed to see. Seems like all that transaction, dosync stuff > ought to be optional. > > (let [x (ref 3)] > (dosync > (while (> @x 0) > (ref-set x (- @x 1))) > @x)) Refs synchronize within a transaction. Atoms only synchronize within a single operation. swap! takes an atom and a function that should be atomically applied to that atom. (let [x (atom 3)] (while (> @x 0) (swap! x dec)) @x) http://clojure.org/atoms But you want to use the (set x (- x 1)) form that is common in many other languages? We can create an unsafe-set that does that and completely ignores synchronization, since you know that synchronization won't be needed. compare-and-set! takes an atom, the atom's expected value, and a new value. Since you want to just assume that there will be no conflicts, we can make an unsafe-set that skips the comparison and just performs the operation. (defn unsafe-set [a v] (compare-and-set! a @a v) v) (let [x (atom 3)] (while (> @x 0) (unsafe-set x (- @x 1))) @x) > Oh, and my other choice is to use recursion. I'll look into that > recur thing. The Clojure standard library is designed to support functional programming (including recursion) and concurrency. I recommend going with the flow, but the language is flexible enough to work the way you want. Just define the operations that you like to use. Also, you have access to Java libraries, which have mutable collections. > > > On Jan 11, 1:27 am, "Eric Lavigne" wrote: > > > I have no idea how to iteratively mess with it since everything is > > > persistent. Ok, like, say it's a list of lists and I am going to be > > > merging the lists, like Tarjan's mergesort from some book from > > > college. > > > > Sorting is done much more easily with recursion than with iteration. > > However, it looks like you are focused on learning language features > rather > > than programming strategy, so I will just answer your questions. > > > > I have not actually done any iterative programming in Clojure, as I > prefer > > the functional approach, so my answers are based on my limited > understanding > > of the Clojure documentation. > > > > so I have myList with contents [[11] [2] [4] [1] [99]] > > > > > > > > > > > > > here's how I would do it in python: > > > > > def msort(myList): > > > myList = [[x] for x in someList] > > > while len(myList) > 1: > > >l1 = myList.pop(0) > > >l2 = myList.pop(0) > > >listmerge = some_merge_function(l1, l2) > > >myList.append(listmerge) # important that newly merged go > > > to back of queue to get proper runtime > > > return myList[0] > > > > > here's what I'm trying to do for clojure, and it's a mess: > > > > > (defn msort [toSort] > > > (def sorted (let > > > > Be careful with def. I think that it creates a global, and it looks like > you > > want something with a scope limited to this function. > > > > http://clojure.org/Vars > > > > > [myList (for [x toSort] [x])] <- so far so good (not a > > > real comment. I don't know how, yet) > > > > Use a semicolon to create a comment: > > > > some code ; a comment > > > > > [ > > >(while (> (count myList) 1) <--- infinite loop the way > > > written? I don't know how to overwrite myList > > > (let [l1 (nth myList 0)][]) > > > > The line above does nothing. When you write "(let [x 1] expr1) expr2" the > > new value of x has a narrow scope so that it only affects expr1. > > > > You are wanting to create a local variable that you can change. Refs can > do > > that: > > > > (let [x (ref 3)] > > (dosync > > (while (> @x 0) > > (ref-set x (- @x 1))) > > @x)) > > > > http://clojure.org/Refs > > > > > (let [l2 (nth myList 1)][]) > > > (let [listmerge (some_merge_func l1 l2)][]) > > > (let [myList (concat (drop 2 myList) listmerge)][myList]) <--- > > > probably a different local variable > > > ) > > > ])) > > > sorted) > > > > After all that work you just return the original list? I must have missed > > the part where you tried to change sorted. Any such attempt would fail, > > though, because Clojure collections are immutable. Maybe sorted should be > a > > ref to a list instead of just a list. > > > > Here is a discussion of sorting implementations in Clojure. I hope that > you > > find it useful. > > > > http://www.fatvat.co.uk/2008/12/bubbling-clojure.html > > > > -- > > Education is what survives when what has been learned has been forgotten. > > > >- B. F.
Re: non recursive impl in presence of persistence?
Thinking functionally is hard when you're used to programming imperatively. So instead of leaping straight into Clojure, lets stick with Python for the time being. So let's take your Python code: def msort(someList): myList = [[x] for x in someList] while len(myList) > 1: l1 = myList.pop(0) l2 = myList.pop(0) listmerge = some_merge_function(l1, l2) myList.append(listmerge) return myList[0] (I'm assuming you meant msort(someList) and not msort(myList)) Remove all functions and methods that change their arguments, and replace them with equivalent assignments: def msort(someList): myList = [[x] for x in someList] while len(myList) > 1: l1 = myList[0] l2 = myList[1] myList = myList[2:] listmerge = some_merge_function(l1, l2) myList = myList + [listmerge] return myList[0] Next we need to turn the while loop into a recursive function. We can do this by identifying what the while loop changes (myList), and then using that as the function's input and output: def msort(someList): myList = [[x] for x in someList] def recursive_loop(myList) if len(myList) > 1: l1 = myList[0] l2 = myList[1] myList = myList[2:] listmerge = some_merge_function(l1, l2) myList = myList + [listmerge] myList = recursive_loop(myList) return myList else: return myList return recursive_loop(myList)[0] Once you've replaced mutable functions and methods with assignments, and replaced loops with recursive functions, you can convert your code into Clojure: (defn msort [some-list] (let [my-list (vec (map vector some-list)) recursive-loop (fn [my-list] (if (> (count my-list) 1) (let [l1 (my-list 0) l2 (my-list 1) my-list(rest (rest my-list)) list-merge (some-merge-function l1 l2) my-list(conj my-list listmerge) my-list(recursive-loop my-list)] my-list) my-list))] ((recursive-loop my-list) 0))) Now we have a functional program, it's time to start taking advantage of all the nice Clojure functions and macros. Let's start with the loop/recur form, which we can use to replace the recursive-loop function: (defn msort [some-list] (loop [my-list (vec (map vector some-list))] (if (> (count my-list) 1) (let [l1 (my-list 0) l2 (my-list 1) my-list(rest (rest my-list)) list-merge (some-merge-function l1 l2) my-list(conj my-list listmerge)] (recur my-list)) (my-list 0 Clojure also supports destructuring binding in let forms, so lets use that: (defn msort [some-list] (loop [my-list (vec (map vector some-list))] (if (> (count my-list) 1) (let [[l1 l2 & my-list] my-list list-merge (some-merge-function l1 l2) my-list (conj my-list list-merge)] (recur my-list)) (my-list 0 And we can use rest to check if the list has more than one attribute: (defn msort [some-list] (loop [my-list (vec (map vector some-list))] (if (rest my-list) (let [[l1 l2 & my-list] my-list list-merge (some-merge-function l1 l2) my-list (conj my-list list-merge)] (recur my-list)) (first my-list This could be neatened up a bit, but that's basically a functional version of your algorithm. - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
list merge help
this seemed like a clean, nice way to merge to sorted lists into one sorted list. I'm not getting clojure syntax, it seems: (defn listmerge [l1 l2] (let [l1first (first l1) l2first (first l2)] (if (= l1first nil) l2) (if (= l2first nil) l1) (if (< l1first l2first) (cons l1first (listmerge (rest l1) l2)) (cons l2first (listmerge (rest l2) l1))) )) psuedocode: listmerge (list l1, list l2): if l1 is empty, return l2 if l2 is empty return l1 if l1[0] is less than l2[0], return l1[0] + listmerge(rest(l1), l2) otherwise return l2[0] + listmerge(rest(l2), l1) . I see one thing. I could move that second cons statement out of the 3rd if and put it as the return for the let. I doubt it will help. Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Setting a value inside a map of map of maps...
Hi, I'm just wondering if there's a clever way of creating a new map from an existing map of map of maps.. with a key deep inside altered. ie. given this map: {:a {:b {:c {:d 3 i want to create a new map, with the value at :d increased by 5. I wrote a macro to do this, but it's quite ugly. Thanks for the tip -Patrick -- In case this helps at all, this is the macro that I wrote. Usage: (set_map mymap [:a :b :c :d] (+ it 5)) (defmacro -set_map [mymap mykeys expr] (let [syms (take (dec (count mykeys)) (repeatedly gensym)) bindings (interleave (concat syms ['it]) (map list mykeys (concat [mymap] syms)))] `(let [...@bindings] ~((fn assoc_fn [maps keys expr] (if (empty? keys) expr `(assoc ~(first maps) ~(first keys) ~(assoc_fn (rest maps) (rest keys) expr (concat [mymap] syms) mykeys expr (defmacro set_map [map keys expr] `(let [map# ~map] (-set_map map# ~keys ~expr))) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
that's awesome, and I hope it helps others, too. Thanks for starting with python. This gets to my question perfectly. Why is your code "my-list (rest (rest my-list)) " legal? I wouldn't have even thought to try that because, in essence, you are changing my-list. I mean, I know how persistence works. You are just reassigning what you think of as the start of my-list, and if no one else is looking at the old version then it can get gc'd. I guess I just assumed it would be harder some how. how do people feel about the list comprehension thing I did? seems like: [my-list (for [x some-list] [x])] is simpler to understand than: [my-list (vec (map vector some-list))] The former is just like math. says, "give me a list of '[x]' for each element 'x' in some-list" The second says, "apply the vector operation to each element of some- list and then make a vector of those." seems lower level, more rudimentary. Thanks for all the help. This is great fun. On Jan 11, 12:07 pm, James Reeves wrote: > Thinking functionally is hard when you're used to programming > imperatively. So instead of leaping straight into Clojure, lets stick > with Python for the time being. > > So let's take your Python code: > > def msort(someList): > myList = [[x] for x in someList] > while len(myList) > 1: > l1 = myList.pop(0) > l2 = myList.pop(0) > listmerge = some_merge_function(l1, l2) > myList.append(listmerge) > return myList[0] > > (I'm assuming you meant msort(someList) and not msort(myList)) > > Remove all functions and methods that change their arguments, and > replace them with equivalent assignments: > > def msort(someList): > myList = [[x] for x in someList] > while len(myList) > 1: > l1 = myList[0] > l2 = myList[1] > myList = myList[2:] > listmerge = some_merge_function(l1, l2) > myList = myList + [listmerge] > return myList[0] > > Next we need to turn the while loop into a recursive function. We can > do this by identifying what the while loop changes (myList), and then > using that as the function's input and output: > > def msort(someList): > myList = [[x] for x in someList] > def recursive_loop(myList) > if len(myList) > 1: > l1 = myList[0] > l2 = myList[1] > myList = myList[2:] > listmerge = some_merge_function(l1, l2) > myList = myList + [listmerge] > myList = recursive_loop(myList) > return myList > else: > return myList > return recursive_loop(myList)[0] > > Once you've replaced mutable functions and methods with assignments, > and replaced loops with recursive functions, you can convert your code > into Clojure: > > (defn msort [some-list] > (let > [my-list (vec (map vector some-list)) > recursive-loop > (fn [my-list] > (if (> (count my-list) 1) > (let [l1 (my-list 0) > l2 (my-list 1) > my-list (rest (rest my-list)) > list-merge (some-merge-function l1 l2) > my-list (conj my-list listmerge) > my-list (recursive-loop my-list)] > my-list) > my-list))] > ((recursive-loop my-list) 0))) > > Now we have a functional program, it's time to start taking advantage > of all the nice Clojure functions and macros. Let's start with the > loop/recur form, which we can use to replace the recursive-loop > function: > > (defn msort [some-list] > (loop [my-list (vec (map vector some-list))] > (if (> (count my-list) 1) > (let [l1 (my-list 0) > l2 (my-list 1) > my-list (rest (rest my-list)) > list-merge (some-merge-function l1 l2) > my-list (conj my-list listmerge)] > (recur my-list)) > (my-list 0 > > Clojure also supports destructuring binding in let forms, so lets use > that: > > (defn msort [some-list] > (loop [my-list (vec (map vector some-list))] > (if (> (count my-list) 1) > (let [[l1 l2 & my-list] my-list > list-merge (some-merge-function l1 l2) > my-list (conj my-list list-merge)] > (recur my-list)) > (my-list 0 > > And we can use rest to check if the list has more than one attribute: > > (defn msort [some-list] > (loop [my-list (vec (map vector some-list))] > (if (rest my-list) > (let [[l1 l2 & my-list] my-list > list-merge (some-merge-function l1 l2) > my-list (conj my-list list-merge)] > (recur my-list)) > (first my-list > > This could be neatened up a bit, but that's basically a functional > version of your algorithm. > > - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups
Re: list merge help
On Jan 11, 5:53 pm, e wrote: > this seemed like a clean, nice way to merge to sorted lists into one > sorted list. I'm not getting clojure syntax, it seems: > > (defn listmerge [l1 l2] > (let [l1first (first l1) l2first (first l2)] > (if (= l1first nil) l2) > (if (= l2first nil) l1) > (if (< l1first l2first) > (cons l1first (listmerge (rest l1) l2)) > (cons l2first (listmerge (rest l2) l1))) > )) You need to nest the ifs, or use a cond: (defn listmerge [l1 l2] (let [l1first (first l1) l2first (first l2)] (cond (empty? l1) l2 (empty? l2) l1 (< l1first l2first) (cons l1first (listmerge (rest l1) l2)) :else (cons l2first (listmerge (rest l2) l1)) if statements in Clojure are inline, like the (x if y else z) syntax in Python. - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: list merge help
> > > this seemed like a clean, nice way to merge to sorted lists into one > sorted list. I'm not getting clojure syntax, it seems: > > > (defn listmerge [l1 l2] > (let [l1first (first l1) l2first (first l2)] >(if (= l1first nil) l2) >(if (= l2first nil) l1) >(if (< l1first l2first) > (cons l1first (listmerge (rest l1) l2)) > (cons l2first (listmerge (rest l2) l1))) >)) > > psuedocode: > > listmerge (list l1, list l2): > if l1 is empty, return l2 > if l2 is empty return l1 > if l1[0] is less than l2[0], >return l1[0] + listmerge(rest(l1), l2) > otherwise return l2[0] + listmerge(rest(l2), l1) > Read James' answer first. I just wish to add something. When you say (let [bindings...] expr1 expr2 expr3) the result is the return value of expr3. expr1 and expr2 return values are relevant, so the only reason to have expr1 and expr2 is if they have side-effects, such as changing the value of a Ref or updating a database or printing to the terminal. -- Education is what survives when what has been learned has been forgotten. - B. F. Skinner --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Setting a value inside a map of map of maps...
I think you can just use the update-in function like: 1:1 user=> (def m {:a {:b {:c {:d 3) #'user/m 1:2 user=> (update-in m [:a :b :c :d] - 5) {:a {:b {:c {:d -2 On Sun, Jan 11, 2009 at 11:08 AM, CuppoJava wrote: > > Hi, > I'm just wondering if there's a clever way of creating a new map from > an existing map of map of maps.. with a key deep inside altered. > > ie. given this map: {:a {:b {:c {:d 3 > > i want to create a new map, with the value at :d increased by 5. > > I wrote a macro to do this, but it's quite ugly. > > Thanks for the tip > -Patrick > > -- > In case this helps at all, this is the macro that I wrote. > Usage: (set_map mymap [:a :b :c :d] (+ it 5)) > > (defmacro -set_map [mymap mykeys expr] > (let [syms (take (dec (count mykeys)) > (repeatedly gensym)) >bindings (interleave > (concat syms ['it]) > (map list > mykeys > (concat [mymap] syms)))] >`(let [...@bindings] > ~((fn assoc_fn [maps keys expr] > (if (empty? keys) > expr > `(assoc ~(first maps) ~(first keys) > ~(assoc_fn (rest maps) (rest keys) expr > (concat [mymap] syms) mykeys expr > > (defmacro set_map [map keys expr] > `(let [map# ~map] > (-set_map map# ~keys ~expr))) > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
i see that "my-list (rest (rest my-list))" is in a let section. That seems like the scope would mean we are talking about a different my- list. On Jan 11, 1:19 pm, e wrote: > that's awesome, and I hope it helps others, too. Thanks for starting > with python. > > This gets to my question perfectly. Why is your code "my-list > (rest (rest my-list)) " legal? > I wouldn't have even thought to try that because, in essence, you are > changing my-list. I mean, I know how persistence works. You are just > reassigning what you think of as the start of my-list, and if no one > else is looking at the old version then it can get gc'd. I guess I > just assumed it would be harder some how. > > how do people feel about the list comprehension thing I did? > > seems like: > [my-list (for [x some-list] [x])] > > is simpler to understand than: > [my-list (vec (map vector some-list))] > > The former is just like math. says, "give me a list of '[x]' for each > element 'x' in some-list" > The second says, "apply the vector operation to each element of some- > list and then make a vector of those." seems lower level, more > rudimentary. > > Thanks for all the help. This is great fun. > > On Jan 11, 12:07 pm, James Reeves wrote: > > > Thinking functionally is hard when you're used to programming > > imperatively. So instead of leaping straight into Clojure, lets stick > > with Python for the time being. > > > So let's take your Python code: > > > def msort(someList): > > myList = [[x] for x in someList] > > while len(myList) > 1: > > l1 = myList.pop(0) > > l2 = myList.pop(0) > > listmerge = some_merge_function(l1, l2) > > myList.append(listmerge) > > return myList[0] > > > (I'm assuming you meant msort(someList) and not msort(myList)) > > > Remove all functions and methods that change their arguments, and > > replace them with equivalent assignments: > > > def msort(someList): > > myList = [[x] for x in someList] > > while len(myList) > 1: > > l1 = myList[0] > > l2 = myList[1] > > myList = myList[2:] > > listmerge = some_merge_function(l1, l2) > > myList = myList + [listmerge] > > return myList[0] > > > Next we need to turn the while loop into a recursive function. We can > > do this by identifying what the while loop changes (myList), and then > > using that as the function's input and output: > > > def msort(someList): > > myList = [[x] for x in someList] > > def recursive_loop(myList) > > if len(myList) > 1: > > l1 = myList[0] > > l2 = myList[1] > > myList = myList[2:] > > listmerge = some_merge_function(l1, l2) > > myList = myList + [listmerge] > > myList = recursive_loop(myList) > > return myList > > else: > > return myList > > return recursive_loop(myList)[0] > > > Once you've replaced mutable functions and methods with assignments, > > and replaced loops with recursive functions, you can convert your code > > into Clojure: > > > (defn msort [some-list] > > (let > > [my-list (vec (map vector some-list)) > > recursive-loop > > (fn [my-list] > > (if (> (count my-list) 1) > > (let [l1 (my-list 0) > > l2 (my-list 1) > > my-list (rest (rest my-list)) > > list-merge (some-merge-function l1 l2) > > my-list (conj my-list listmerge) > > my-list (recursive-loop my-list)] > > my-list) > > my-list))] > > ((recursive-loop my-list) 0))) > > > Now we have a functional program, it's time to start taking advantage > > of all the nice Clojure functions and macros. Let's start with the > > loop/recur form, which we can use to replace the recursive-loop > > function: > > > (defn msort [some-list] > > (loop [my-list (vec (map vector some-list))] > > (if (> (count my-list) 1) > > (let [l1 (my-list 0) > > l2 (my-list 1) > > my-list (rest (rest my-list)) > > list-merge (some-merge-function l1 l2) > > my-list (conj my-list listmerge)] > > (recur my-list)) > > (my-list 0 > > > Clojure also supports destructuring binding in let forms, so lets use > > that: > > > (defn msort [some-list] > > (loop [my-list (vec (map vector some-list))] > > (if (> (count my-list) 1) > > (let [[l1 l2 & my-list] my-list > > list-merge (some-merge-function l1 l2) > > my-list (conj my-list list-merge)] > > (recur my-list)) > > (my-list 0 > > > And we can use rest to check if the list has more than one attribute: > > > (defn msort [some-list] > > (loop [my-list (vec (map vector some-list))] > > (if (rest my-list) > > (let [[l1 l2 & my-list] my-list > > list-merge (some-merge-function l1 l2) > > my-list (conj my-list list-merge)] > > (recur my-list)) > > (first
Re: non recursive impl in presence of persistence?
> > > This gets to my question perfectly. Why is your code "my-list > (rest (rest my-list)) " legal? > I wouldn't have even thought to try that because, in essence, you are > changing my-list. I mean, I know how persistence works. You are just > reassigning what you think of as the start of my-list, and if no one > else is looking at the old version then it can get gc'd. I guess I > just assumed it would be harder some how. > The expression (rest (rest my-list)) does not change anything. Its return value is a list that has fewer elements, and the original (unchanged) list still exists. This is common in the functional style of programming - most operations do not modify their arguments. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
> > i see that "my-list (rest (rest my-list))" is in a let section. That > seems like the scope would mean we are talking about a different my- > list. > Yes, it is a new my-list with a smaller scope. I didn't search for the expression (rest (rest my-list)) before my earlier response. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Setting a value inside a map of map of maps...
That's exactly what I was looking for. Thank you Brian. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
On Jan 11, 6:19 pm, e wrote: > This gets to my question perfectly. Why is your code "my-list > (rest (rest my-list)) " legal? Because you're not actually changing anything. In theory, the let form can be derived from anonymous functions. So (let [x y] ...) is the same as ((fn [x] ...) y). Or, to give you a more practical example: (defn f [x] (let [x (+ x 1)] (* 2 x))) Is the same as the following Python code: def f(x): def g(x): return x * 2 return g(x + 1) We're not changing the value of x, we're just rebinding it within the scope of the function. The value of x in g is not the same as the value of x in f. In practice, let forms are never actually implemented as nested functions, because that would be far too slow. But in theory, nested functions are equivalent to let forms. > seems like: > [my-list (for [x some-list] [x])] > > is simpler to understand than: > [my-list (vec (map vector some-list))] It probably is :) - I just haven't had the opportunity to use the for macro yet. - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
if it has tighter scope, then I don't understand why you don't have an infinite loop. The nested my-list that you redefined should have nothing to do with the my-list that you are doing the 'rest' check on. (rest my-list) should always be non-nil because the inner let is operating on a different my-list. That's how it looks to me, at least. I saw that there's a re-def function that I bet would work, but everyone says to avoid def because of it's global scope. hm that must be some magic about the loop construct. I dunno. I'm still confused. Every version of the python code makes sense. I've got this reference to my-list, and I can change that reference. I see the same thing happening here, but it's scoped inside a let barrier. I seem to remember in clisp, there was a setq. maybe that's what I'm missing. On Jan 11, 1:41 pm, James Reeves wrote: > On Jan 11, 6:19 pm, e wrote: > > > This gets to my question perfectly. Why is your code "my-list > > (rest (rest my-list)) " legal? > > Because you're not actually changing anything. > > In theory, the let form can be derived from anonymous functions. So > (let [x y] ...) is the same as ((fn [x] ...) y). > > Or, to give you a more practical example: > > (defn f [x] > (let [x (+ x 1)] > (* 2 x))) > > Is the same as the following Python code: > > def f(x): > def g(x): > return x * 2 > return g(x + 1) > > We're not changing the value of x, we're just rebinding it within the > scope of the function. The value of x in g is not the same as the > value of x in f. > > In practice, let forms are never actually implemented as nested > functions, because that would be far too slow. But in theory, nested > functions are equivalent to let forms. > > > seems like: > > [my-list (for [x some-list] [x])] > > > is simpler to understand than: > > [my-list (vec (map vector some-list))] > > It probably is :) - I just haven't had the opportunity to use the for > macro yet. > > - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
oh. I missed the "recur my-list" in your answer. So we still don't have an iterative solution. Recursion should never be necessary. I agree that it simplifies things sometimes and you can use it when you are stuck. . . . .but no need to push a whole stack frame for such a simple problem, I would posit. On Jan 11, 1:41 pm, James Reeves wrote: > On Jan 11, 6:19 pm, e wrote: > > > This gets to my question perfectly. Why is your code "my-list > > (rest (rest my-list)) " legal? > > Because you're not actually changing anything. > > In theory, the let form can be derived from anonymous functions. So > (let [x y] ...) is the same as ((fn [x] ...) y). > > Or, to give you a more practical example: > > (defn f [x] > (let [x (+ x 1)] > (* 2 x))) > > Is the same as the following Python code: > > def f(x): > def g(x): > return x * 2 > return g(x + 1) > > We're not changing the value of x, we're just rebinding it within the > scope of the function. The value of x in g is not the same as the > value of x in f. > > In practice, let forms are never actually implemented as nested > functions, because that would be far too slow. But in theory, nested > functions are equivalent to let forms. > > > seems like: > > [my-list (for [x some-list] [x])] > > > is simpler to understand than: > > [my-list (vec (map vector some-list))] > > It probably is :) - I just haven't had the opportunity to use the for > macro yet. > > - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: list merge help
ahhh I see. That makes sense. So it's not like procedural programming. You could see what I was trying to understand. I didn't want case/swtich semantics. like the (cond) or if, else if style. I was trying to return at the first true thing, but it doesn't work like that. it always gets to expr3. the thing I thought was returning after expr1 was just an opportunity to do a side effect. Thanks. On Jan 11, 1:26 pm, "Eric Lavigne" wrote: > > this seemed like a clean, nice way to merge to sorted lists into one > > sorted list. I'm not getting clojure syntax, it seems: > > > (defn listmerge [l1 l2] > > (let [l1first (first l1) l2first (first l2)] > > (if (= l1first nil) l2) > > (if (= l2first nil) l1) > > (if (< l1first l2first) > > (cons l1first (listmerge (rest l1) l2)) > > (cons l2first (listmerge (rest l2) l1))) > > )) > > > psuedocode: > > > listmerge (list l1, list l2): > > if l1 is empty, return l2 > > if l2 is empty return l1 > > if l1[0] is less than l2[0], > > return l1[0] + listmerge(rest(l1), l2) > > otherwise return l2[0] + listmerge(rest(l2), l1) > > Read James' answer first. I just wish to add something. > > When you say (let [bindings...] expr1 expr2 expr3) the result is the return > value of expr3. expr1 and expr2 return values are relevant, so the only > reason to have expr1 and expr2 is if they have side-effects, such as > changing the value of a Ref or updating a database or printing to the > terminal. > > -- > Education is what survives when what has been learned has been forgotten. > > - B. F. Skinner --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
On Jan 11, 7:09 pm, e wrote: > if it has tighter scope, then I don't understand why you don't have an > infinite loop. The nested my-list that you redefined should have > nothing to do with the my-list that you are doing the 'rest' check > on. That's what the loop/recur form does. Again, loop/recur can be defined in terms of functions: (defn f [xs] (loop [ys xs, s 0] (if ys (recur (rest ys) (+ s 1)) s))) Is equivalent to the following Python: def f(xs): def g(ys, s): if ys: return g(xs[1:], s + 1) return s return g(xs, 0) When recur is called, it acts similarly to a recursive call. The loop part defines the arguments the loop acts on. The recur part signifies the loop should be repeated with new arguments. Just like the inner function, g. So in my previous code, it's true that the new my-list has a small scope. But I pass it back to the loop which defines a new variable, also called my-list, for the next iteration. I guess it would be clearer if I used different names: (defn msort [some-list] (loop [list-A (vec (map vector some-list))] (if (rest my-list) (let [[l1 l2 & list-B] list-A list-merge (some-merge-function l1 l2) list-C (conj list-B list-merge)] (recur list-C)) (first my-list So list-A is used to make list-B, which is used to make list-C, and on the next iteration of the loop, list-C becomes bound to list-A again. > that must be some magic about the loop construct. I dunno. I'm still > confused. Every version of the python code makes sense. I've got > this reference to my-list, and I can change that reference. I see the > same thing happening here, but it's scoped inside a let barrier. Basically, everything to do with scoping in Lisp can be explained in terms of functions: (let [x y] ...) = ((fn [x] ...) y) (loop [x y] (recur x) = (defn f [x] (f x) Though loop and let are more efficient than their function equivalents. - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
On Jan 11, 7:19 pm, e wrote: > oh. I missed the "recur my-list" in your answer. So we still don't > have an iterative solution. Recursion should never be necessary. I > agree that it simplifies things sometimes and you can use it when you > are stuck. . . . .but no need to push a whole stack frame for such a > simple problem, I would posit. Actually, that's the nice thing about loop/recur: it looks recursive but is actually iterative. So a recursive function like this: (defn sum [total list] (if list (sum (+ total (first list)) (rest list)) total)) Can be turned into an iterative one via recur: (defn sum [total list] (if list (recur (+ total (first list)) (rest list)) total)) Note that if there is no matching loop construct, it uses the containing function instead. Most functional languages actually optimize functions like the one above automatically, without a need for an explicit recur. It's called tail call optimization; if a function calls itself last of all, there's no need to keep the stack around. Unfortunately, the JVM doesn't have this capability, so we need to explicitly tell Clojure to do it via recur. Note that for recur to work, it needs to be the last thing called. So a more naive implementation of sum wouldn't be able to use recur: (defn sum [list] (if list (+ (first list) (sum (rest list))) 0)) In this case, the last function called is +, so you can't substitute "sum" for "recur" in this case. - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
thanks for your patience. I think I'm starting to get it. Interesting discussion on tail recursion. Add a lot of depth to what Rich was talking about. Really smart work-around! On Jan 11, 2:50 pm, James Reeves wrote: > On Jan 11, 7:19 pm, e wrote: > > > oh. I missed the "recur my-list" in your answer. So we still don't > > have an iterative solution. Recursion should never be necessary. I > > agree that it simplifies things sometimes and you can use it when you > > are stuck. . . . .but no need to push a whole stack frame for such a > > simple problem, I would posit. > > Actually, that's the nice thing about loop/recur: it looks recursive > but is actually iterative. > > So a recursive function like this: > > (defn sum [total list] > (if list > (sum (+ total (first list)) > (rest list)) > total)) > > Can be turned into an iterative one via recur: > > (defn sum [total list] > (if list > (recur (+ total (first list)) > (rest list)) > total)) > > Note that if there is no matching loop construct, it uses the > containing function instead. > > Most functional languages actually optimize functions like the one > above automatically, without a need for an explicit recur. It's called > tail call optimization; if a function calls itself last of all, > there's no need to keep the stack around. Unfortunately, the JVM > doesn't have this capability, so we need to explicitly tell Clojure to > do it via recur. > > Note that for recur to work, it needs to be the last thing called. So > a more naive implementation of sum wouldn't be able to use recur: > > (defn sum [list] > (if list > (+ (first list) (sum (rest list))) > 0)) > > In this case, the last function called is +, so you can't substitute > "sum" for "recur" in this case. > > - James --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Dead code in generated bytecode
While trying to run clojure on JNode I noticed that some dead code in the ASM generated bytecode of clojure makes it fail because it confuses the JIT. One example of the problem can be seen with javap: javap -c clojure.core\$last__2780 Result (relevant part) : public java.lang.Object invoke(java.lang.Object) throws java.lang.Exception; Code: 0: getstatic #22; //Field const__0:Lclojure/lang/Var; 3: invokevirtual #37; //Method clojure/lang/Var.get:()Ljava/ lang/Object; 6: checkcast #39; //class clojure/lang/IFn 9: aload_1 10: invokeinterface #41, 2; //InterfaceMethod clojure/lang/ IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object; 15: dup 16: ifnull 47 19: getstatic #47; //Field java/lang/Boolean.FALSE:Ljava/ lang/Boolean; 22: if_acmpeq 48 25: getstatic #22; //Field const__0:Lclojure/lang/Var; 28: invokevirtual #37; //Method clojure/lang/Var.get:()Ljava/ lang/Object; 31: checkcast #39; //class clojure/lang/IFn 34: aload_1 35: invokeinterface #41, 2; //InterfaceMethod clojure/lang/ IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object; 40: astore_1 41: goto0 44: goto65 47: pop 48: getstatic #26; //Field const__1:Lclojure/lang/Var; 51: invokevirtual #37; //Method clojure/lang/Var.get:()Ljava/ lang/Object; 54: checkcast #39; //class clojure/lang/IFn 57: aload_1 58: aconst_null 59: astore_1 60: invokeinterface #41, 2; //InterfaceMethod clojure/lang/ IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object; 65: areturn By investigating the bytecode one can notice that line: "44: goto 65" in unreachable. This creates the problem. After some investigation of the clojure source code I came to the conclusion that for this particular case changing the clojure.lang.Compiler, r1193 at line 2367 to: if(!(thenExpr instanceof RecurExpr)) gen.goTo(endLabel); That is: if the thenExpr of the if node is such that it wouldn't fall through to the elseExpr then there is no need to emit a goto bytecode for jumping to the end of the if statement, bacause it will be unreachable. With this change I rebuilt clojure and apparently it's working fine, the bytecode of the method above is correct, but unfortunately there are similar situations in other parts of the code where usesless bytecode is emited. For instance clojure.core$partition__3754.invoke(Object,Object,Object) also contains deadcode similar to the above and it's related to the if node. If clojure will be used on other experimental, limited or non- mainstream Java platforms such problems in the generated bytecode will surface and create problems. The bugs in such paltforms (their intolerance to various non-fatal byecode problems) can stay hidden because the bytecode generated by javac doesn't have such problems. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Java interop question
Is it possible to access a constant inside a public static class which is defined inside a public interface? For example: package com.rabbitmq.client; import java.io.IOException; [...skipped...] public interface AMQP { public static class PROTOCOL { public static final int MAJOR = 8; public static final int MINOR = 0; public static final int PORT = 5672; } public static final int FRAME_METHOD = 1; public static final int FRAME_HEADER = 2; public static final int FRAME_BODY = 3; [...skipped...] } I did a lot of experimentartion in the REPL, but no success yet - I can't figure out how to access com.rabbimq.client.AMQP.PROTOCOL.PORT constant in Clojure. It is possible to (import 'com.rabbitmq.client.AMQP), but (import 'com.rabbitmq.client.AMQP.PROTOCOL) gives ClassNotFoundException. (. com.rabbimq.AMQP FRAME_METHOD) returns 1, but neither (. com.rabbitmq.client.AMQP.PROTOCOL PORT), nor (com.rabbitmq.client.AMQP.PROTOCOL/PORT) works. What I'm doing wrong? Best regards, Vladimir --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Newbie: Creating a macro that just calls a function but evaluates its arguments lazily
Let's say I have a function, alt: (defn alt [& functions] (fn [tokens] (some #(% tokens) functions))) It creates a function from a bunch of sub-functions that accepts one collection of tokens and figures out which sub-function returns a true value when the tokens are plugged into it. Is there a way to change alt—maybe to a macro—that lazily evaluates the functions? This is so that with: (defn a-meta-meta-function [c] (alt (sub-function1 c) (sub-function2 c) (sub-function3 c))) ...calling ((a-meta-meta-function foo) some-tokens) doesn't evaluate (sub-function 2 c) and (sub-function3 c) until needed to receive some- tokens. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Java interop question
On Sun, Jan 11, 2009 at 3:30 PM, wal wrote: > > Is it possible to access a constant inside a public static class which > is defined inside a public interface? > > For example: > > package com.rabbitmq.client; > > import java.io.IOException; > [...skipped...] > > public interface AMQP > { >public static class PROTOCOL { >public static final int MAJOR = 8; >public static final int MINOR = 0; >public static final int PORT = 5672; >} > >public static final int FRAME_METHOD = 1; >public static final int FRAME_HEADER = 2; >public static final int FRAME_BODY = 3; > > [...skipped...] > } Probably com.rabbitmq.client.AMQP$PROTOCOL/PORT without parens since it's a field not a method. Documented at http://clojure.org/java_interop -- search for NestedClass --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie: Creating a macro that just calls a function but evaluates its arguments lazily
"some" is already lazy, so you may not need to change anything at all. You might also be able to use "filter", which will not do anything until you consume the output sequence. -Stuart Sierra On Jan 11, 4:44 pm, samppi wrote: > Let's say I have a function, alt: > > (defn alt [& functions] > (fn [tokens] > (some #(% tokens) functions))) > > It creates a function from a bunch of sub-functions that accepts one > collection of tokens and figures out which sub-function returns a true > value when the tokens are plugged into it. > > Is there a way to change alt—maybe to a macro—that lazily evaluates > the functions? This is so that with: > > (defn a-meta-meta-function [c] > (alt (sub-function1 c) (sub-function2 c) (sub-function3 c))) > > ...calling ((a-meta-meta-function foo) some-tokens) doesn't evaluate > (sub-function 2 c) and (sub-function3 c) until needed to receive some- > tokens. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Newbie: Creating a macro that just calls a function but evaluates its arguments lazily
The problem is that even though "some" and "filter" are lazy, "alt" is still not, so calling "(alt (sub-function1 c) ...)" in the meta-meta- function still evaluates (sub-function1 c), etc. It could be shown in the REPL: Clojure user=> (defn alt [& functions] (fn [tokens] (some #(% tokens) functions))) #'user/alt user=> (defn sub-function1 [c] (println "1:" c) (fn [c] false)) #'user/sub-function1 user=> (defn sub-function2 [c] (println "2:" c) (fn [c] true)) #'user/sub-function2 user=> (defn sub-function3 [c] (println "3:" c) (fn [c] false)) #'user/sub-function3 user=> (defn a-meta-meta-function [c] (alt (sub-function1 c) (sub-function2 c) (sub-function3 c))) #'user/a-meta-meta-function user=> ((a-meta-meta-function "CONTEXT") [:a :b :c]) 1: CONTEXT 2: CONTEXT 3: CONTEXT true What I wish is for calling '((a-meta-meta-function "CONTEXT") [:a :b :c])' to output: 1: CONTEXT 2: CONTEXT ...only, which means that the sub-functions are called only until a sub-function's created function returns a true value. The root of the problem is that in Clojure's rules (I think), the arguments of a regular function are all evaluated before being plugged into the function. That's why I'm wondering if a macro could solve my problem. Thanks for your answers! On Jan 11, 3:02 pm, Stuart Sierra wrote: > "some" is already lazy, so you may not need to change anything at > all. You might also be able to use "filter", which will not do > anything until you consume the output sequence. > -Stuart Sierra > > On Jan 11, 4:44 pm, samppi wrote: > > > Let's say I have a function, alt: > > > (defn alt [& functions] > > (fn [tokens] > > (some #(% tokens) functions))) > > > It creates a function from a bunch of sub-functions that accepts one > > collection of tokens and figures out which sub-function returns a true > > value when the tokens are plugged into it. > > > Is there a way to change alt—maybe to a macro—that lazily evaluates > > the functions? This is so that with: > > > (defn a-meta-meta-function [c] > > (alt (sub-function1 c) (sub-function2 c) (sub-function3 c))) > > > ...calling ((a-meta-meta-function foo) some-tokens) doesn't evaluate > > (sub-function 2 c) and (sub-function3 c) until needed to receive some- > > tokens. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: what does -> mean?
One use I've found for -> (though there are others I haven't come to appreciate yet) is when I have something like: (f1 (f2 (f3 (f4 x which can be re-written as (-> x f4 f3 f2 f1) I find the latter expression easier to read. Kev On Dec 30 2008, 2:49 pm, wubbie wrote: > Very criptic for newbie. > What does "Threads the expr through the forms." mean? > Does it create a thread to execute? > > thanks > sun > > On Dec 29, 10:07 pm, Paul Barry wrote: > > > You can look up the documentation for a function/macro interactively > > from the repl: > > > user=> (doc ->) > > - > > clojure.core/-> > > ([x form] [x form & more]) > > Macro > > Threads the expr through the forms. Inserts x as the > > second item in the first form, making a list of it if it is not a > > list already. If there are more forms, inserts the first form as the > > second item in second form, etc. > > nil > > > On Dec 29, 8:27 pm, wubbie wrote: > > > > Hi all, > > > > Looking intoants.clj, I came across > > > (defn place [[x y]] > > > (-> world (nth x) (nth y))) > > > > What -> mean here? > > > > thanks > > > sun --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: what does -> mean?
I've also found this useful for accessing members in nested maps. For example: (let [me {:person {:name {:first "Mark" :last "Triggs"} :email "mark.h.tri...@gmail.com"}}] (-> me :person :name :first)) => "Mark" On Jan 12, 1:04 pm, kkw wrote: > One use I've found for -> (though there are others I haven't come to > appreciate yet) is when I have something like: > (f1 (f2 (f3 (f4 x > > which can be re-written as > (-> x f4 f3 f2 f1) > > I find the latter expression easier to read. > > Kev > > On Dec 30 2008, 2:49 pm, wubbie wrote: > > > Very criptic for newbie. > > What does "Threads the expr through the forms." mean? > > Does it create a thread to execute? > > > thanks > > sun > > > On Dec 29, 10:07 pm, Paul Barry wrote: > > > > You can look up the documentation for a function/macro interactively > > > from the repl: > > > > user=> (doc ->) > > > - > > > clojure.core/-> > > > ([x form] [x form & more]) > > > Macro > > > Threads the expr through the forms. Inserts x as the > > > second item in the first form, making a list of it if it is not a > > > list already. If there are more forms, inserts the first form as the > > > second item in second form, etc. > > > nil > > > > On Dec 29, 8:27 pm, wubbie wrote: > > > > > Hi all, > > > > > Looking intoants.clj, I came across > > > > (defn place [[x y]] > > > > (-> world (nth x) (nth y))) > > > > > What -> mean here? > > > > > thanks > > > > sun --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
How to create and read from a stream of random characters?
Hi, For the purposes of testing another function (not discussed here), I wrote a function to generate random strings. This is what I ended up with after some trial and error. (defn generate-data [size maxlength] ; Returns a collection of 'size random strings, each at most 'maxlength chars. (let [alphabet "abcdefghijklmnopqrstuvwxyz" rand-letter (fn [_] (nth alphabet (rand-int 26))) rand-stream (map rand-letter (iterate inc 0)) rand-string (fn [n] (apply str (take n rand-stream)))] (map (fn [_] (rand-string (rand-int maxlength))) (range size ; test (generate-data 25 19) The output of the testing function is something like ("gr", "gry", "gr", "g", "gry"). That is, is always _takes_ from the same sequence of random characters. Is there a way I might modify the above code so rand-stream is indeed a stream (with new random data each time) instead of a sequence (where every _take_ starts from the beginning)? Of course, I'd love to see other people's approach to implementing 'generate-data, but I'm also curious about the idea of streams themselves. Cheers, Gavin [second post] --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Why aren't lists callable?
Why aren't all sequences callable, i.e. why don't they all implement IFn? I'd like to use lists like this sometimes. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
> thread should own the memory that's created. Each thread should have > its own asynchronous stack to push local variables onto that no one > else is allowed to see. Just for the record, Clojure does support local variable that behave exactly as you would expect them: (with-local-vars [x 3] (while (> @x 0) (var-set x (- @x 1))) @x) -> 0 Using an atom is unnecessary in this case because access is totally local. Using an unsafe atom set is a bad habit, as discussed in detail on another thread: http://groups.google.com/group/clojure/browse_thread/thread/6497e7c8bc58bb4e/c5b3c9dbe6a1f5d5 However as you have already seen there are more elegant ways to write the solution without either. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: SLIME: trouble with java.lang.OutOfMemoryError
I have had similar problems with enclojure. But having gone through similar IDE pain working in Ruby on Rails, the Netbeans support ended up being way ahead of most IDEs, so I have hopes that enclojure will get there in time. (My biggest annoyance? The fact that you can't open existing code as a new project - I want to browse clojure-contrib, but I can only do it by creating a new "hello world" project first!) I'd kind-of like to re-learn emacs - many years ago I was a keen emacs user - my biggest problem is that I'm on a Mac, and I have to keep switching between IDEs and PCs (my work desktop is Linux) not to mention languages. I don't have the spare brain cells to learn another set of key bindings! I need an IDE with easy built-in help, and while "M-x slime-cheatsheet" is handy, it doesn't spare me the world-o-pain when I hit "Alt-w" (one of the few keystrokes my fingers remember from last time) and my emacs window closes! Argh! So I try to stick with IDEs that have everything on menus, so when I forget the "open file anywhere in project" command for a particular IDE, I can look it up. (Does Emacs have this, by the way? It doesn't really have a "project" concept... ) I might look at the JEdit plugin though - JEdit is nice, for simple editing, which might be good enough for me for now. Incidentally, if you want a language with an editor built in, why not look at Smalltalk? I vaguely recall that was a big part of the original language concept. I haven't ever played with it myself, but the most popular current flavour seems to be Squeak: http://www.squeak.org/ - Korny On Sun, Jan 11, 2009 at 1:18 PM, e wrote: > > seems like enclosjure addresses a bunch of my problems/questions. It > also seems to work like we wanted SLIME to work, more or > less . . .where you attach to the vm that's used for execution . . . > only you attach to the REPL, I think, which still accomplishes the > goal of keeping the editor separate from the memory, but what about > having the REPL being able to attach to the vm it is managing. Then > it wouldn't be something that NetBeans/enclosure is doing . . . rather > something that's part of the language. > > So, yeah. enslojure sets up a HelloWorld that you can play with right > away. In fact, when you click on "build" it even tells you how you > could run your application from the command line using a java > command. It jars up you whole clojure project and everything. Nice. > On the other hand, I couldn't figure out how to use NetBeans' run > button. it couldn't find main or something. So I also couldn't debug > using NetBeans' debugger because of this. Also, it isn't clear how to > get different clojure files to work together. Do you use the (load) > function? If so, I don't know how the project thinks of relative file > locations. It's not as clean/clear as java (for a beginner, at least) > where you just import classes you want to use . . and make > packages. . . . or modules in python. I don't know what the notion of > "path" is in clojure. I see the namespace stuff but have no clue how > to make it work yet. Are you just supposed to use one giant file for > all your work? That wouldn't be good for teams, for sure. . . only > for hacking. Also the REPL errors are USELESS to a beginner. > something about iSeq all the time. The moral for me there was no to > make an error. Better than where I was before enclojure. Again, I > contend that a language is only as good as the IDE that has been > written for it, which is why it's cool to see enclojure coming along > (even though it means learning NetBeans instead of Eclipse). > > > On Jan 10, 5:31 pm, Paul Mooser wrote: >> If I'm not mistaken, this is fairly close to how SLIME works, when >> connected to a remote VM. The remote VM is running some server code >> which allows it to communicate with SLIME, which is running inside of >> emacs. >> >> On Jan 10, 2:15 pm, e wrote: >> >> > exactly. . . .but I bet a lot of people would just reply that this is >> > not possible to address since the REPL is the one and only vm. >> > Disclaimer, I'm only guessing at that, too. I don't understand any of >> > this, yet. But if that's the case, fix that. Have the REPL send >> > messages to the vm that's running the program . . . instead of the >> > REPL being the program. >> >> > On Jan 10, 5:00 pm, Paul Mooser wrote: >> >> > > Yeah, I'm not really sure how I think the problem would be ideally >> > > solved. It would just be nice for an interactive programming >> > > environment to be able to recover from all exceptions that happen at a >> > > higher level than the VM itself. >> >> > > On Jan 10, 12:20 pm, "Christian Vest Hansen" >> > > wrote: >> >> > > > I don't think it is possible to define a way to deal with heap >> > > > saturation that is general enough to cover all programs written in >> > > > Clojure, and therefor I don't think this is something that the Clojure >> > > > runtime should deal with at
Re: Why aren't lists callable?
On Sun, Jan 11, 2009 at 9:38 PM, Ethan Herdrick wrote: > > Why aren't all sequences callable, i.e. why don't they all implement > IFn? I'd like to use lists like this sometimes. When you call maps and vectors, it acts as if you're calling 'get'. But 'get' doesn't do anything useful for lists. So what should a list do when called? --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: SLIME: trouble with java.lang.OutOfMemoryError
> > > Incidentally, if you want a language with an editor built in, why not > look at Smalltalk? I vaguely recall that was a big part of the > original language concept. I haven't ever played with it myself, but > the most popular current flavour seems to be Squeak: > http://www.squeak.org/ > Smalltalk is an excellent language (though I have a personal preference for Lisp). It also provides a glimpse into what the term "object-oriented" originally meant. In case anyone reading this thread decides to explore Smalltalk, here are a few pointers to introductory information. Yes, Squeak is popular, mostly because it is very portable, easy to install, and open source. It is also developed primarily as an introductory programming environment for children, and that has held it back as an environment for professional programmers. Pharo is a recent fork of Squeak, with the intention of completely ignoring the needs of children and focusing on making a good environment for professional programmers. http://code.google.com/p/pharo/ Also, there is a very nice web development framework for Smalltalk. Smalltalk is worth learning just for a chance to see a new way of doing web development. http://seaside.st/ I would recommend starting with Squeak as it is very easy to work with (if children can handle it, so can you), and switch to Pharo later when you are ready for production deployment. The following book is a good starting point for either environment (and is available for free online). http://squeakbyexample.org/ --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: SLIME: trouble with java.lang.OutOfMemoryError
>I might look at the JEdit plugin though - JEdit is nice, for simple >editing, which might be good enough for me for now. I similarly haven't had time to relearn emacs and have used jedit quite sucessfully with jedit-mode. I keep one or more terminal window tabs open each with a REPL launched with rlwrap and then just copy and paste from the associated jedit tab/buffer. With up_arrow and dn_arrow bound to "back_history" and "forward_history" in rlwrap, it's easy to try stuf in the REPL, recall/edit previous lines, etc, and copy/paste back to jedit when necessary. The main advantage for me is this works identically when I have an ssh session open to a server with REPL/rlwrap. I can similarly copy/paste from jedit and do very interactive development directly on the server as well as on my local machine, switching between everything with one or two keystrokes. I'm just about down to a pure keystroke driven dev environment with almost never touching the mouse. Primiive and a bit messy, but it works well. [Footnote to the above - I also have a terminal tab open just for compiles. Using ant (build.xml's adapted from clojure's build), the full cycle includes then tabbing to the ant terminal, recalling/running the build and using rsync to copy changed classes to the server. I can then immediately switch to the server/ssh tab and reload/work with the newly built code.] On Mon, Jan 12, 2009 at 5:28 AM, Korny Sietsma wrote: > > I have had similar problems with enclojure. But having gone through > similar IDE pain working in Ruby on Rails, the Netbeans support ended > up being way ahead of most IDEs, so I have hopes that enclojure will > get there in time. (My biggest annoyance? The fact that you can't > open existing code as a new project - I want to browse > clojure-contrib, but I can only do it by creating a new "hello world" > project first!) > > I'd kind-of like to re-learn emacs - many years ago I was a keen emacs > user - my biggest problem is that I'm on a Mac, and I have to keep > switching between IDEs and PCs (my work desktop is Linux) not to > mention languages. I don't have the spare brain cells to learn > another set of key bindings! I need an IDE with easy built-in help, > and while "M-x slime-cheatsheet" is handy, it doesn't spare me the > world-o-pain when I hit "Alt-w" (one of the few keystrokes my fingers > remember from last time) and my emacs window closes! Argh! > > So I try to stick with IDEs that have everything on menus, so when I > forget the "open file anywhere in project" command for a particular > IDE, I can look it up. (Does Emacs have this, by the way? It doesn't > really have a "project" concept... ) > > I might look at the JEdit plugin though - JEdit is nice, for simple > editing, which might be good enough for me for now. > > Incidentally, if you want a language with an editor built in, why not > look at Smalltalk? I vaguely recall that was a big part of the > original language concept. I haven't ever played with it myself, but > the most popular current flavour seems to be Squeak: > http://www.squeak.org/ > > - Korny > > > On Sun, Jan 11, 2009 at 1:18 PM, e wrote: >> >> seems like enclosjure addresses a bunch of my problems/questions. It >> also seems to work like we wanted SLIME to work, more or >> less . . .where you attach to the vm that's used for execution . . . >> only you attach to the REPL, I think, which still accomplishes the >> goal of keeping the editor separate from the memory, but what about >> having the REPL being able to attach to the vm it is managing. Then >> it wouldn't be something that NetBeans/enclosure is doing . . . rather >> something that's part of the language. >> >> So, yeah. enslojure sets up a HelloWorld that you can play with right >> away. In fact, when you click on "build" it even tells you how you >> could run your application from the command line using a java >> command. It jars up you whole clojure project and everything. Nice. >> On the other hand, I couldn't figure out how to use NetBeans' run >> button. it couldn't find main or something. So I also couldn't debug >> using NetBeans' debugger because of this. Also, it isn't clear how to >> get different clojure files to work together. Do you use the (load) >> function? If so, I don't know how the project thinks of relative file >> locations. It's not as clean/clear as java (for a beginner, at least) >> where you just import classes you want to use . . and make >> packages. . . . or modules in python. I don't know what the notion of >> "path" is in clojure. I see the namespace stuff but have no clue how >> to make it work yet. Are you just supposed to use one giant file for >> all your work? That wouldn't be good for teams, for sure. . . only >> for hacking. Also the REPL errors are USELESS to a beginner. >> something about iSeq all the time. The moral for me there was no to >> make an error. Better than where I was before enclojure. Again, I >> contend that
Re: Why aren't lists callable?
I can't imagine this idea will be met warmly, but I have a suggestion. It requires ending maps and vectors as functions of keys. Instead, make the first argument to a collection be a function which is mapped to across the collection. Any additional arguments are passed to the function on each invocation. For maps and hashes, this would only be applied to the values. Keys would remain the same. Some examples: ('(1 2 3) * 2) => (2 4 6) ({:greet "hello" :farewell "goodbye"} str " Mark") => {:greet "hello Mark" :farewell "goodbye Mark"} If the primary type used as keys are keywords or symbols, we don't give up much. As (:key map) still works in place of (map :key). I'm not tied to this idea. I thought of it a while ago, and it certainly has its draw backs. I wouldn't suggest a 1/2 way solution -- making lists functions of functions and maps functions of keys -- thats certainly a world of headaches. Anyway, back to business as usual. Cheers, -Mark On Jan 11, 2009, at 9:59 PM, Chouser wrote: > > On Sun, Jan 11, 2009 at 9:38 PM, Ethan Herdrick > wrote: >> >> Why aren't all sequences callable, i.e. why don't they all implement >> IFn? I'd like to use lists like this sometimes. > > When you call maps and vectors, it acts as if you're calling 'get'. > But 'get' doesn't do anything useful for lists. So what should a list > do when called? > > --Chouser > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
here's a good explanation: http://groups.google.com/group/clojure/browse_thread/thread/3c22b35f079e0de6/95fc0b334ab77c1f I wasn't thinking about closures since I've only recently even learned what they are. I actually don't know if it will ever occur to me to use them, but it sounds like they are the reason we are encouraged to jump through such hoops even for local variables. closures allow them to "leak". It's funny, whenever I tried to be all safe like this and take the time to make stuff safe in C++, coworkers would say, "we are grown-ups. At some point you gotta stop being a paranoid programmer. Document the usage, and woe be it unto the user who doesn't 'RTFM'". Another thing is to make the common case easy . . . .and uh, mutable local variables are pretty darn common, as Rich anticipated when he predicted that people would be excited about the 'with-local-vars' macro. I was thinking the same thing, "fine, I'll learn how to write macros, then". I can see that this issue comes up again and again with everyone who walks in the door, and it probably will continue to. Who knows, maybe Rich will change the world. It sure will take a lot of energy. That's for sure. On Sun, Jan 11, 2009 at 10:27 PM, Timothy Pratley wrote: > > > thread should own the memory that's created. Each thread should have > > its own asynchronous stack to push local variables onto that no one > > else is allowed to see. > > Just for the record, Clojure does support local variable that behave > exactly as you would expect them: > (with-local-vars [x 3] > (while (> @x 0) >(var-set x (- @x 1))) > @x) > -> 0 > > Using an atom is unnecessary in this case because access is totally > local. Using an unsafe atom set is a bad habit, as discussed in detail > on another thread: > > http://groups.google.com/group/clojure/browse_thread/thread/6497e7c8bc58bb4e/c5b3c9dbe6a1f5d5 > > However as you have already seen there are more elegant ways to write > the solution without either. > > > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
when performance matters
I have recently found out about Clojure and am rather impressed. I am seriously considering whether Clojure is a viable language for use at work. The main stumbling block would be if performance (both speed and memory) turns out to be insufficent. I currently use C++, but I'd love to be able to leave C++ behind and use Clojure (or similar) instead. The programs I write perform applied mathematical optimization (using mainly integer arithmetic) and often take hours (occasionally even days) to run. So even small percentage improvements in execution speed can make a significant practical difference. And large problems can use a large amount of memory - so memory efficiency is also a concern. Given these performance considerations, at first glance Clojure does not seem like a good choice. But I don't want to give up on the idea just yet. The allure of modernized lisp-style programming is really tempting. There are three key factors that still give me hope: 1. Some of the algorithms I use have the potential to be parallelized. I am hoping that as the number of cores in PCs increase, at some point Clojure's performance will beat C++'s due to Clojure's superior utilization of multiple cores. (Any ideas on how many cores are needed for this to become true?) 2. The JVM is continually being improved. Hopefully in a year or two, the performance of HotSpot will be closer to that of C++. (But maybe this is just wishful thinking.) 3. Maybe I can implement certain performance critical components in C++ via the JNI. (But I get the impression that JNI itself isn't particularly efficient. Also, the more I pull over into the C++ side, the fewer advantages to using Clojure.) If all else fails, maybe I could use Clojure as a prototyping language. Then when I get it right, I code up the actual programs in C++. But probably a lot would get lost in the translation from Clojure -> C++ so would it be worth it? I'd love to be convinced that Clojure is a viable choice, but I need to be a realist too. So what do people think? How realistic are my three "hopes"? And are there any other performance enhancing possibilities that I have not taken into account? Thanks, Mark P. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
is the @ symbol the same as a var-get . . . or is that and atom. Your sentence about atoms was very compound. I'm not sure if you said that you used an atom but you didn't have to . . . .or you didn't use an atom because it wasnt necessary . . . . or you did use an atom because it was necessary with 'with-local-vars', but it wasn't necessary to use 'with-local-vars'? So I don't understand your point, even after reading the thread you referred me to. Did you use an unsafe atom? I assume that's what you were saying. . . incidentally, the following code works: (with-local-vars [x 3] (while (> (var-get x) 0) (var-set x (- (var-get x) 1))) (var-get x)) did I replace your use of unsafe atoms with closure.lang.Vars or, again, is @ just short hand for var-get? Thanks. On Sun, Jan 11, 2009 at 10:27 PM, Timothy Pratley wrote: > > > thread should own the memory that's created. Each thread should have > > its own asynchronous stack to push local variables onto that no one > > else is allowed to see. > > Just for the record, Clojure does support local variable that behave > exactly as you would expect them: > (with-local-vars [x 3] > (while (> @x 0) >(var-set x (- @x 1))) > @x) > -> 0 > > Using an atom is unnecessary in this case because access is totally > local. Using an unsafe atom set is a bad habit, as discussed in detail > on another thread: > > http://groups.google.com/group/clojure/browse_thread/thread/6497e7c8bc58bb4e/c5b3c9dbe6a1f5d5 > > However as you have already seen there are more elegant ways to write > the solution without either. > > > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
Bear with the trials and tribulations (of grokking functional/clojure). It takes a few weeks of trying things out, absorbing the documentation and group archives, watching the group posts and then suddenly there are one or two "aha" moments and then the flood gates open! When you've crossed the threshold, it's too late - you can never go back. You'll want to go and redo everything you've ever done imperatively! For me the "aha" moments came when I first (really) understood reduce, map and fn. I'd reccomend focusing on those and trying to (first) do all your looping constructs with those rather than loop/recur - that forces you to learn to think functional while loop/recur still lets your mind stick to imperative patterns. Regards, Adrian. On Mon, Jan 12, 2009 at 7:24 AM, e wrote: > here's a good explanation: > http://groups.google.com/group/clojure/browse_thread/thread/3c22b35f079e0de6/95fc0b334ab77c1f > > I wasn't thinking about closures since I've only recently even learned what > they are. I actually don't know if it will ever occur to me to use them, > but it sounds like they are the reason we are encouraged to jump through > such hoops even for local variables. closures allow them to "leak". > > It's funny, whenever I tried to be all safe like this and take the time to > make stuff safe in C++, coworkers would say, "we are grown-ups. At some > point you gotta stop being a paranoid programmer. Document the usage, and > woe be it unto the user who doesn't 'RTFM'". > > Another thing is to make the common case easy . . . .and uh, mutable local > variables are pretty darn common, as Rich anticipated when he predicted that > people would be excited about the 'with-local-vars' macro. I was thinking > the same thing, "fine, I'll learn how to write macros, then". I can see > that this issue comes up again and again with everyone who walks in the > door, and it probably will continue to. Who knows, maybe Rich will change > the world. It sure will take a lot of energy. That's for sure. > > On Sun, Jan 11, 2009 at 10:27 PM, Timothy Pratley > wrote: >> >> > thread should own the memory that's created. Each thread should have >> > its own asynchronous stack to push local variables onto that no one >> > else is allowed to see. >> >> Just for the record, Clojure does support local variable that behave >> exactly as you would expect them: >> (with-local-vars [x 3] >> (while (> @x 0) >>(var-set x (- @x 1))) >> @x) >> -> 0 >> >> Using an atom is unnecessary in this case because access is totally >> local. Using an unsafe atom set is a bad habit, as discussed in detail >> on another thread: >> >> http://groups.google.com/group/clojure/browse_thread/thread/6497e7c8bc58bb4e/c5b3c9dbe6a1f5d5 >> >> However as you have already seen there are more elegant ways to write >> the solution without either. >> >> >> > > > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
My point was that it is not a missing capability, Say you want to accumulate some changes, in this case sum odd numbers: In C++ someone might write this: int x = 0; for (int i=0; i<100; i++) { if ( i%2==1 ) x+=i; } However in Clojure you have a choice: (reduce + (range 1 100 2)) Or you could do a direct translation to Clojure: (with-local-vars [i 0, x 0] (while (< @i 100) (if (= 1 (rem @i 2)) (var-set x (+ @x @i))) (var-set i (inc @i))) @x) Both get the same result, but have very different styles. The version without variables is much easier to understand, provided you know what reduce does. So it takes a little bit of work initially to stop using variables, but it is well worth the effort. Regards, Tim. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
On Sun, Jan 11, 2009 at 10:33 PM, e wrote: > thanks for your patience. I think I'm starting to get it. > Interesting discussion on tail recursion. Just to add $0.02... The fact that 'recur' in Clojure is actually used to implement iterative and not recursive processes is easier to understand after reading SICP (chapter 1, http://mitpress.mit.edu/sicp/full-text/book/book.html). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
I'm sure you are right. I'm going to have to be good at making these arguments with my coworkers (or find somewhere else to work, maybe? :) ) so I appreciate the depth people are going to. One of my next bouts of confusion is going to come from trying to figure out what's already done. Like I read a Brodal paper once one purely functional heaps implemented using a forest of persistent skew-binomial trees. But is that sort of thing already all done? Do I just find a heap and know that find-min and reduce-key are as fast as they can be? That'll be interesting. I also want to play around with a parallel knapsack solver. Also I want to integrate clojure with JMonkeyEngine and do some parallel graphics/physics stuff. Still, the riskiest part of this all is the programming environment, as I see it. The language is pretty unreadible, so say many people who haven't given it the 3 weeks (that part doesn't bother me -- just gotta learn it). But things like the errors not referencing clojure line numbers? No way that I have figured out how to step through code in a debugger? Well, it's a hard sell without an 800-core machine sitting right in the room begging to be programmed on. On Mon, Jan 12, 2009 at 12:53 AM, Adrian Cuthbertson < adrian.cuthbert...@gmail.com> wrote: > > Bear with the trials and tribulations (of grokking > functional/clojure). It takes a few weeks of trying things out, > absorbing the documentation and group archives, watching the group > posts and then suddenly there are one or two "aha" moments and then > the flood gates open! When you've crossed the threshold, it's too late > - you can never go back. You'll want to go and redo everything you've > ever done imperatively! For me the "aha" moments came when I first > (really) understood reduce, map and fn. I'd reccomend focusing on > those and trying to (first) do all your looping constructs with those > rather than loop/recur - that forces you to learn to think functional > while loop/recur still lets your mind stick to imperative patterns. > > Regards, Adrian. > > On Mon, Jan 12, 2009 at 7:24 AM, e wrote: > > here's a good explanation: > > > http://groups.google.com/group/clojure/browse_thread/thread/3c22b35f079e0de6/95fc0b334ab77c1f > > > > I wasn't thinking about closures since I've only recently even learned > what > > they are. I actually don't know if it will ever occur to me to use them, > > but it sounds like they are the reason we are encouraged to jump through > > such hoops even for local variables. closures allow them to "leak". > > > > It's funny, whenever I tried to be all safe like this and take the time > to > > make stuff safe in C++, coworkers would say, "we are grown-ups. At some > > point you gotta stop being a paranoid programmer. Document the usage, > and > > woe be it unto the user who doesn't 'RTFM'". > > > > Another thing is to make the common case easy . . . .and uh, mutable > local > > variables are pretty darn common, as Rich anticipated when he predicted > that > > people would be excited about the 'with-local-vars' macro. I was > thinking > > the same thing, "fine, I'll learn how to write macros, then". I can see > > that this issue comes up again and again with everyone who walks in the > > door, and it probably will continue to. Who knows, maybe Rich will > change > > the world. It sure will take a lot of energy. That's for sure. > > > > On Sun, Jan 11, 2009 at 10:27 PM, Timothy Pratley < > timothyprat...@gmail.com> > > wrote: > >> > >> > thread should own the memory that's created. Each thread should have > >> > its own asynchronous stack to push local variables onto that no one > >> > else is allowed to see. > >> > >> Just for the record, Clojure does support local variable that behave > >> exactly as you would expect them: > >> (with-local-vars [x 3] > >> (while (> @x 0) > >>(var-set x (- @x 1))) > >> @x) > >> -> 0 > >> > >> Using an atom is unnecessary in this case because access is totally > >> local. Using an unsafe atom set is a bad habit, as discussed in detail > >> on another thread: > >> > >> > http://groups.google.com/group/clojure/browse_thread/thread/6497e7c8bc58bb4e/c5b3c9dbe6a1f5d5 > >> > >> However as you have already seen there are more elegant ways to write > >> the solution without either. > >> > >> > >> > > > > > > > > > > > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Some code review for clj-record?
Hi Emeka, Sorry for the slow response. I don't get that message with the latest clojure, clojure-contrib, and clj-record. (load-file just returns nil.) What version of clojure are you running? Do you have the base directory of clj-record on your classpath? Also, that file just contains the library, so you probably want to require it rather than load-file. Or if you want to run the tests, (load-file "clj_record/test/main.clj") On Thu, Jan 8, 2009 at 7:01 AM, Emeka wrote: > > user=> (load-file "clj_record/core.clj") > I got clj_record/util not in system path. Why is it so? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: when performance matters
I can't speak for clojure, so I'm interested in seeing how people who can will answer. There's so much to consider. I've heard Haskell is getting faster and has (or will have) parallel programming under the scenes (automatically doing independent parts of operations). There are other fast functional languages, like OCaml and Clean, but I don't know about concurrency. As for C++, can you afford a Cray? They have pragmas for making parallelism easy, and a special CPU that can do like 128 operations (one for each of 128 simultaneous streams of input) in a single cycle . . . which I think is really cool! If THAT becomes mainstream, I'm not sure one could argue that C++ will be left in the dust. Now, if Cray, stays super duper expensive, then it's not really part of the discussion. On Mon, Jan 12, 2009 at 12:41 AM, Mark P wrote: > > I have recently found out about Clojure and am > rather impressed. I am seriously considering > whether Clojure is a viable language for use at > work. The main stumbling block would be if > performance (both speed and memory) turns out > to be insufficent. I currently use C++, but I'd love > to be able to leave C++ behind and use Clojure > (or similar) instead. > > The programs I write perform applied mathematical > optimization (using mainly integer arithmetic) > and often take hours (occasionally even days) > to run. So even small percentage improvements > in execution speed can make a significant > practical difference. And large problems can use > a large amount of memory - so memory efficiency > is also a concern. > > Given these performance considerations, at first > glance Clojure does not seem like a good choice. > But I don't want to give up on the idea just yet. > The allure of modernized lisp-style programming > is really tempting. > > There are three key factors that still give me > hope: > > 1. Some of the algorithms I use have the potential > to be parallelized. I am hoping that as the number > of cores in PCs increase, at some point Clojure's > performance will beat C++'s due to Clojure's > superior utilization of multiple cores. (Any ideas > on how many cores are needed for this to become > true?) > > 2. The JVM is continually being improved. Hopefully > in a year or two, the performance of HotSpot will be > closer to that of C++. (But maybe this is just > wishful thinking.) > > 3. Maybe I can implement certain performance critical > components in C++ via the JNI. (But I get the impression > that JNI itself isn't particularly efficient. Also, the more > I pull over into the C++ side, the fewer advantages to > using Clojure.) > > If all else fails, maybe I could use Clojure as a prototyping > language. Then when I get it right, I code up the actual > programs in C++. But probably a lot would get lost in > the translation from Clojure -> C++ so would it be worth > it? > > I'd love to be convinced that Clojure is a viable choice, > but I need to be a realist too. So what do people think? > How realistic are my three "hopes"? And are there > any other performance enhancing possibilities that I > have not taken into account? > > Thanks, > > Mark P. > > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Java interop question
On 12 янв, 01:01, Chouser wrote: > On Sun, Jan 11, 2009 at 3:30 PM, wal wrote: > > > Is it possible to access a constant inside a public static class which > > is defined inside a public interface? > > > For example: > > > package com.rabbitmq.client; > > > import java.io.IOException; > > [...skipped...] > > > public interface AMQP > > { > > public static class PROTOCOL { > > public static final int MAJOR = 8; > > public static final int MINOR = 0; > > public static final int PORT = 5672; > > } > > > public static final int FRAME_METHOD = 1; > > public static final int FRAME_HEADER = 2; > > public static final int FRAME_BODY = 3; > > > [...skipped...] > > } > > Probably com.rabbitmq.client.AMQP$PROTOCOL/PORT without parens since > it's a field not a method. > > Documented athttp://clojure.org/java_interop-- search for NestedClass > > --Chouser Yes, it worked! Thanks a lot! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
> is the @ symbol the same as a var-get . . . or is that an atom. @ is a reader macro that translates to (deref ) which works on vars, atoms, refs, agents. and yes is interchangeable with var-get. > Your sentence about atoms was very compound. I'm not sure if you said that >you > used an atom but you didn't have to . . . .or you didn't use an atom because > it wasnt necessary . . . . or you did use an atom because it was necessary > with 'with-local-vars', but it wasn't necessary to use 'with-local-vars'? > So I don't understand your point, even after reading the thread you referred > me to. Did you use an unsafe atom? I assume that's what you were saying. I should have been more clear. Someone else recommended using an atom, I was explaining why that might not be a good idea. I am not advocating using either a variable or atom. > incidentally, the following code works: > > (with-local-vars [x 3] > (while (> (var-get x) 0) > (var-set x (- (var-get x) 1))) > (var-get x)) > > did I replace your use of unsafe atoms with closure.lang.Vars or, > again, is @ just short hand for var-get? Yup, just shorthand for var-get. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
looks like an awesome book. will check it out more. thanks. On Mon, Jan 12, 2009 at 1:06 AM, Josip Gracin wrote: > > On Sun, Jan 11, 2009 at 10:33 PM, e wrote: > > thanks for your patience. I think I'm starting to get it. > > Interesting discussion on tail recursion. > > Just to add $0.02... The fact that 'recur' in Clojure is actually used > to implement iterative and not recursive processes is easier to > understand after reading SICP (chapter 1, > http://mitpress.mit.edu/sicp/full-text/book/book.html). > > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
I'm not planning on programming like this, but just to try to finish this up . . . .it's still not working. I get an odd error when I actually try to sort something that iSeq doesn't work on integers. I have no idea where to still the (first my-list) at the end so it returns, too. No need to reply, per se. Just reporting on how far I got tonight. I'm sure someone answered this already and I haven't read through it all enough. (defn listmerge [l1 l2] (let [l1first (first l1) l2first (first l2)] (cond (empty? l1) l2 (empty? l2) l1 (< l1first l2first) (cons l1first (listmerge (rest l1) l2)) :else (cons l2first (listmerge (rest l2) l1)) (defn msort [toSort] (with-local-vars [my-list (for [x toSort] [x])] (while (rest (var-get my-list)) (let [[l1 l2 & my-list2] (var-get my-list)] (var-set my-list (concat my-list2 (listmerge l1 l2 (first my-list ;; test it out (msort [4 53 54 3 5 7 8]) On Mon, Jan 12, 2009 at 1:29 AM, e wrote: > looks like an awesome book. will check it out more. thanks. > > > On Mon, Jan 12, 2009 at 1:06 AM, Josip Gracin wrote: > >> >> On Sun, Jan 11, 2009 at 10:33 PM, e wrote: >> > thanks for your patience. I think I'm starting to get it. >> > Interesting discussion on tail recursion. >> >> Just to add $0.02... The fact that 'recur' in Clojure is actually used >> to implement iterative and not recursive processes is easier to >> understand after reading SICP (chapter 1, >> http://mitpress.mit.edu/sicp/full-text/book/book.html). >> >> >> >> > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: non recursive impl in presence of persistence?
a few fixes. still not there yet. (defn elisort [toSort] (with-local-vars [my-list (for [x toSort] [x])] (while (rest (var-get my-list)) (let [[l1 l2 & my-list2] (var-get my-list)] (var-set my-list (concat my-list2 (listmerge [l1] [l2] (first (var-get my-list) On Mon, Jan 12, 2009 at 1:47 AM, e wrote: > I'm not planning on programming like this, but just to try to finish this > up . . . .it's still not working. I get an odd error when I actually try to > sort something that iSeq doesn't work on integers. I have no idea where to > still the (first my-list) at the end so it returns, too. No need to reply, > per se. Just reporting on how far I got tonight. I'm sure someone answered > this already and I haven't read through it all enough. > > (defn listmerge [l1 l2] > (let [l1first (first l1) l2first (first l2)] >(cond > (empty? l1) l2 > (empty? l2) l1 > (< l1first l2first) >(cons l1first (listmerge (rest l1) l2)) > :else >(cons l2first (listmerge (rest l2) l1)) > > (defn msort [toSort] > (with-local-vars [my-list (for [x toSort] [x])] >(while (rest (var-get my-list)) > (let [[l1 l2 & my-list2] (var-get my-list)] >(var-set my-list (concat my-list2 (listmerge l1 l2 (first > my-list > > ;; test it out > (msort [4 53 54 3 5 7 8]) > > > > On Mon, Jan 12, 2009 at 1:29 AM, e wrote: > >> looks like an awesome book. will check it out more. thanks. >> >> >> On Mon, Jan 12, 2009 at 1:06 AM, Josip Gracin wrote: >> >>> >>> On Sun, Jan 11, 2009 at 10:33 PM, e wrote: >>> > thanks for your patience. I think I'm starting to get it. >>> > Interesting discussion on tail recursion. >>> >>> Just to add $0.02... The fact that 'recur' in Clojure is actually used >>> to implement iterative and not recursive processes is easier to >>> understand after reading SICP (chapter 1, >>> http://mitpress.mit.edu/sicp/full-text/book/book.html). >>> >>> >>> >>> >> > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: How to create and read from a stream of random characters?
On Sun, Jan 11, 2009 at 9:35 PM, GS wrote: > > Hi, > > For the purposes of testing another function (not discussed here), I > wrote a function to generate random strings. This is what I ended up > with after some trial and error. > > (defn generate-data [size maxlength] >; Returns a collection of 'size random strings, each at most 'maxlength > chars. >(let [alphabet "abcdefghijklmnopqrstuvwxyz" > rand-letter (fn [_] (nth alphabet (rand-int 26))) > rand-stream (map rand-letter (iterate inc 0)) > rand-string (fn [n] (apply str (take n rand-stream)))] > (map (fn [_] (rand-string (rand-int maxlength))) > (range size > >; test > (generate-data 25 19) > > The output of the testing function is something like ("gr", "gry", > "gr", "g", "gry"). That is, is always _takes_ from the same sequence > of random characters. > > Is there a way I might modify the above code so rand-stream is indeed > a stream (with new random data each time) instead of a sequence (where > every _take_ starts from the beginning)? That generates a single rand-stream and then takes various amounts from it in your 'map'. To get a new random sequence each time, you'd have to move the definition of rand-stream into your 'map' fn so that each item of the map gets its own random stream. Here's one way to do that: (defn generate-data [size maxlength] (for [i (range size)] (apply str (take (rand-int maxlength) (repeatedly #(char (+ (int \a) (rand-int 26 But since this is returning a lazy stream (as your original did), there's not much value in passing in the size: (defn seq-of-rand-strings [maxlength] (repeatedly (fn [] (apply str (take (rand-int maxlength) (repeatedly #(char (+ (int \a) (rand-int 26) user=> (take 3 (seq-of-rand-strings 10)) ("kae" "xwuwyp" "xa") --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---