| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#21
| |||
| |||
| On Sep 16, 10:38*pm, namekuseijin <namekusei...@gmail.com> wrote: > On Sep 16, 4:56*pm, "jos...@corporate-world.lisp.de" <jos...@corporate- .... > My main purpose was eliminating slow list processing from my coding, > relying primarily on the iterator-building range. *Thus, when I need > some specific order, I simply invert the terms to range. *I range over > vectors and strings as well. How do you know it was slow? A bunch of functions calling each other is not necessarily faster. In Common Lisp one gets rid of the intermediate lists by using LOOP/ITERATE/SERIES/.... and stays descriptive. > Though I also give small lists a chance by permitting them in the > input. *Reversing the output list may be more efficient, since you're > likely filtering elements out. > > > Personally I either use small functional building blocks > > which do one thing: remove, reverse, map, reduce and so on > > or I use something that is declarative like LOOP. > > > So either: > > > (mapcar #'sqr (remove-if-not (lambda (x) (> x 20)) '(12 31 2 33))) > > In that small list argument, it's not evident, but mapping over large > sequences sucks. *That's one of the reasons I decided for range. Really? Does it matter? Often? > > (loop for i in '(12 31 2 33) when (> i 20) collect (sqr i)) > > Then, what you do with the collected data? *Run some function over it > to produce a final result, right? Sometimes. Often not. Then I do something else. > ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) init function) > > Done, without producing intermediary lists or anything. *It's also > almost the same written size as the macroed code above. Yeah, but without any clue what the terms do and how it works. Especially a function that gets a function and returns a function and then gets called with another function. That's a rube-goldberg-device. > > > and it can be used in a multitude of ways, not simply to return a > > > list: > > > That makes it worse. > > This coming from a CLisper! ![]() > > > It should do one thing right or do > > multiple things but be descriptive. > > ah, lack of keywords... no problem when the interface is always the > same: *reducers are always of the form (lambda (i r) ...) where i is > the current item from the iterator, r the current result and reducer > itself produces the next result to be fed recursively. > > > * the user interface is confused and adhoc > > It's not adhoc, like I said above: *all and range return an iterator > and receive 2 arguments -- an initial value for the reducer and the > reducer. *That's all. Yeah, and from reading source code using this constructs one could not even guess what it does. > It's always (iterator init f) and it's result is always passed around > as the r argument and as the final value. *It's the same as fold/ > reduce, except for the lack of a sequence/list argument. > > You can also freely ignore the result, though, and then you have a > simple imperative construct, like in the print example. > > > * the code is debugger-resistent > > There's nothing to debug there. *It's perfect! ![]() I'm talking about code that uses such constructs. Bad. Very bad. > > * code using that is not self-descriptive > > Hmm, perhaps you should break out of CL's loops and have a look at > more applicative programming? See below. > > * there is no simple model behind it (say like streams in SICP) > > It looks pretty simple and consistent to me. Reread the chapter on streams and accumulation in SICP. > > You can make it worse, though. By rewriting it as a set of macros. > > Not rewriting a set of macros, but simply wrapping it behind a macro. > Like: > (all (sqr x) (x in (range 1 100)) (and (> x 20) (odd? x))) > > Which would equaly return an iterator. > > > From looking > > at the forms I would never guess what it does. > > Probably you should give Scheme another chance. ![]() Actually I have written much more complicated stuff in Scheme than what you have posted here. I prefer Common Lisp because it is much more descriptive and much better to use interactively. > > > ((all sqr '(12 31 2 33) (lambda (x) (> x 20))) 0 +) > > > ((all sqr '(12 31 2 33) (lambda (x) (and (> x 20) (odd? x))) 1 *) > > > > Order is not important in many applications. > > > Haha. Right, that's the Scheme way. > > That's functional programming way. No, your code is the obfuscated way of functional programming. Reread SICP to get back on the right way. |
|
#22
| |||
| |||
| On 16 set, 18:51, "jos...@corporate-world.lisp.de" <jos...@corporate- world.lisp.de> wrote: > On Sep 16, 10:38*pm, namekuseijin <namekusei...@gmail.com> wrote: > > On Sep 16, 4:56*pm, "jos...@corporate-world.lisp.de" <jos...@corporate- > > > My main purpose was eliminating slow list processing from my coding, > > relying primarily on the iterator-building range. *Thus, when I need > > some specific order, I simply invert the terms to range. *I range over > > vectors and strings as well. > > How do you know it was slow? mapcar is not much used for serious large dataset prossessing. You guys are known to abuse of loop. > A bunch of functions calling each other > is not necessarily faster. It's really the application of just 2 function. > In Common Lisp one gets rid of the intermediate lists > by using LOOP/ITERATE/SERIES/.... and stays descriptive. There's none of that in Scheme and even if had, I'd not use them any more than I'd use C/C++... Besides, is this (all sqr '(12 31 2 33) (lambda (x) (> x 20))) really so different from this? [x**2 for x in [12,31,2,33] if x > 20] In all, it takes 3 arguments: a final step function to process the current item, a list or an iterator for a sequence and an optional predicate. Is there really any complication here? Does it need more description than the order and naming of the arguments? I purposefully put the order of the arguments in the same order they appear in the popular comprehensions in Haskell or Python exactly to match them. The only difference is that my function returns an iterator while the Python one directly returns a list. I'd argue my function is better since I can directly apply the resultant iterator to any function I want together with its initial argument. > > > (mapcar #'sqr (remove-if-not (lambda (x) (> x 20)) '(12 31 2 33))) > > > In that small list argument, it's not evident, but mapping over large > > sequences sucks. *That's one of the reasons I decided for range. > > Really? Does it matter? Often? Only when iterating large data sets. > > > (loop for i in '(12 31 2 33) when (> i 20) collect (sqr i)) > > > Then, what you do with the collected data? *Run some function over it > > to produce a final result, right? > > Sometimes. Often not. Then I do something else. Like printing it? ((all sqr (range 1 10000) (lambda (x) (prime? x))) #f (lambda (i r) (display i)(newline) r)) Passing it to another function? ((all sqr (range 1 10000) (lambda (x) (prime? x))) init something- else) Perhaps you're just mad because it makes Lisp look a bit like Forth? ![]() > > Done, without producing intermediary lists or anything. *It's also > > almost the same written size as the macroed code above. > > Yeah, but without any clue what the terms do and how it works. I can't use any one function without knowing its arguments, its interface. Its the contract between the creator and the user. The interface for my function is pretty simple, self-evident and pretty much the same as in the other popular comprehensions of other languages. There should also be no doubt for a Lisp programmer: anything at the head position of a list is a function to be evaluated. So (all self ls) should necessarily return a function. It shouldn't also come as surprise to most functional programmers used to fold. > Especially > a function that gets a function and returns a function and then gets > called > with another function. That's a rube-goldberg-device. No, that's functional programming. > > It's not adhoc, like I said above: *all and range return an iterator > > and receive 2 arguments -- an initial value for the reducer and the > > reducer. *That's all. > > Yeah, and from reading source code using this constructs one > could not even guess what it does. Then again, why am I discussing code from my personal libs with you? It fits my thinking and I feel warm and cosy with that. ![]() > Reread the chapter on streams and accumulation in SICP. SICP is a lovely book, but I have my own way of doing things, like everyone else. There are many stream and even comprehension libs available for Scheme out there, including the ones from SRFI. I just find mine more sexy. ![]() > No, your code is the obfuscated way of functional programming. I like to call it myscm. ![]() I thought one of the professed pro-Lisp arguments is that it's a language that suits to your style of programming, not otherwise. So please, don't laugh at my preferences... > Reread SICP to get back on the right way. Just because I read Shakespeare I don't feel a sudden urge to speak in old English... :P |
|
#23
| |||
| |||
| William James schrieb: > On Aug 22, 5:47 pm, David Golden <david.gol...@oceanfree.net> wrote: >> defn noob wrote: >>> I am trying to learn lisp macros and I generally find >>> listcomprehensions to be elegant and they dont exist in lisp. >>> This has to be a macro right? Cant be a function? >> You might want to look at the COLLECT macrohttp://user.it.uu.se/~svenolof/Collect/ >> >>> [x**2 for x in [12,31,2,33] if x > 20] >>> [961, 1089] >> (collect list ((expt x 2)) (in x '(12 31 2 33)) (when (> x 20))) >> => (961 1089) > > Ruby: > [12,31,2,33].select{|n| n>20}.map{|n| n**2} > ==>[961, 1089] Yes, also in Ruby one can have a nice solution as you showed. But still, the Lisp solution shown is the preferrable one, because it is the shorter program. Not character wise. But that doesn’t count. If the function is called slct or select or if it had a 14-char name, it won’t matter. It’s all just one point in the program, and therewith a complexity unit. The Lisp code has these: collect, list, (), expt, x, 2, in, x, ', (), 12, 31, 2, 33, when, >, x, 20 That gives us 18 points. But your Ruby code has 19: [], 12, 31, 2, 33, select, {}, ||, n, n, >, 20, map, {}, ||, n, n, **, 2 Lisp wins, although this time only by a small margin, compared to your other examples which often be solved only in a noticable more complex way than in Lisp. Please don’t forget that advances in programming languages should help us to remove complexity and make things easier. If you wanted you could do exactly the same thing in Lisp as in [12, 31, 2, 33].select{|n| n>20}.map{|n| n**2} like this: (mapcar (lambda (n) (expt n 2)) (select '(12 31 2 33) (lambda (n) (< n 20)))) Because Lisp uses lengthier names the solution looks longer when counting chars. But algorithmically it is the same. If you had to write tons of such small functions you would introduce a macro and do: (map [ˆ2] (select '(12 31 2 33) [< _ 20])) Here we renamed functions to reflect the preferrence of short names. We have the function ˆ2 which squares its argument. We curry away the variable and introduce anonymous currying for the lambda to select. Think about how you can add implicit currying to Ruby without touching the C code which it is implemented in, but instead doing it with a pure Ruby solution. André -- |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.