f



how to get rid of following code duplication

CL-USER> (defun range (start end)
            (if (<= start end)
                (loop for x from start upto end collecting x)
                (loop for x from start downto end collecting x)))
0
Bigos
4/7/2014 10:46:57 AM
comp.lang.lisp 16861 articles. 5 followers. Post Follow

34 Replies
423 Views

Similar Articles

[PageSpeed] 10

On 2014-04-07, Joost Kremers <joost.m.kremers@gmail.com> wrote:
> The Lisp way:[1]
>
> (defun my-range (start end)
>   (eval `(loop for x from start ,(if (<= start end) 'upto 'downto) end collecting x)))
>
>
> JK
>
>
>
> [1] Irony alert.

Well, that is certainly the NewLisp way.

An equivalent solution in Tcl would also earn honest accolades in that clueless
microcosm.
0
Kaz
4/7/2014 1:01:01 AM
taruss@google.com writes:
> Abandoning loop:
> ;; A clearer version.
> ;;  Slightly clever in building the list backwards.

Scheme style:

(defun range (start end)
  (if (<= start end)
      (range1 start end -1 #'<= nil)
    (range1 start end 1 #'>= nil)))

(defun range1 (first last inc test acc)
  (if (funcall test first last)
      (range1 first (+ inc last) inc test
            (cons last acc))
    acc))
0
Paul
4/7/2014 1:01:01 AM
Kaz Kylheku <kaz@kylheku.com> writes:
> Built into TXR's Lisp dialect with auto decrement for reversed
> arguments: ...

http://www.nongnu.org/txr/ looks nice!  But, I think the auto decrement
is a misfeature because of the possibility of surprises.  

In Haskell of course you could write (untested)

 range a b | a <= b = [a..b]
           | otherwise = [b, b-1 .. a]

but usually you'd know which direction you wanted.
0
Paul
4/7/2014 1:01:01 AM
On 2014-04-07, Bigos <ruby.object@googlemail.com> wrote:
> CL-USER> (defun range (start end)
>             (if (<= start end)
>                 (loop for x from start upto end collecting x)
>                 (loop for x from start downto end collecting x)))

In addition to recursive solution:

(defun range (start end)
  (when (> end start)
    (psetf end start start end))
  (loop for x from start upto end collecting x))

(defun range (start end)
    (loop for x
          from (min start end)
          upto (max start end)
          collecting x))
0
Kaz
4/7/2014 3:05:46 PM
Kaz Kylheku wrote:
> On 2014-04-07, Bigos <ruby.object@googlemail.com> wrote:
>> CL-USER> (defun range (start end)
>>             (if (<= start end)
>>                 (loop for x from start upto end collecting x)
>>                 (loop for x from start downto end collecting x)))
>
> In addition to recursive solution:
>
> (defun range (start end)
>   (when (> end start)
>     (psetf end start start end))
>   (loop for x from start upto end collecting x))
>
> (defun range (start end)
>     (loop for x
>           from (min start end)
>           upto (max start end)
>           collecting x))

The Lisp way:[1]

(defun my-range (start end)
  (eval `(loop for x from start ,(if (<= start end) 'upto 'downto) end collecting x)))


JK



[1] Irony alert.

-- 
Joost Kremers                                   joostkremers@fastmail.fm
Selbst in die Unterwelt dringt durch Spalten Licht
EN:SiS(9)
0
Joost
4/7/2014 3:22:10 PM
In article 
<slrnlk5gl2.1td.joost.m.kremers@j.kremers4.news.arnhem.chello.nl>,
 Joost Kremers <joost.m.kremers@gmail.com> wrote:

> Kaz Kylheku wrote:
> > On 2014-04-07, Bigos <ruby.object@googlemail.com> wrote:
> >> CL-USER> (defun range (start end)
> >>             (if (<= start end)
> >>                 (loop for x from start upto end collecting x)
> >>                 (loop for x from start downto end collecting x)))
> >
> > In addition to recursive solution:
> >
> > (defun range (start end)
> >   (when (> end start)
> >     (psetf end start start end))
> >   (loop for x from start upto end collecting x))
> >
> > (defun range (start end)
> >     (loop for x
> >           from (min start end)
> >           upto (max start end)
> >           collecting x))
> 
> The Lisp way:[1]
> 
> (defun my-range (start end)
>   (eval `(loop for x from start ,(if (<= start end) 'upto 'downto) end 
>   collecting x)))

You need to unquote START and END as well. They're lexical variables, 
and EVAL evaluates in the dynamic environment.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
0
Barry
4/7/2014 7:54:08 PM
On Monday, April 7, 2014 3:46:57 AM UTC-7, Bigos wrote:
| CL-USER> (defun range (start end)
|             (if (<= start end)
|                 (loop for x from start upto end collecting x)
|                 (loop for x from start downto end collecting x))


(defun range (start end)
  (loop with increment = (if (<= start end) 1 -1)
	repeat (1+ (abs (- end start)))
	as v = start then (+ v increment)
	collect v))

Abandoning loop:

;; A clearer version.
;;  Slightly clever in building the list backwards.
(defun range (start end)
  (let ((increment (if (<= start end) -1 1))
        (v end)
        (result nil))
    (dotimes (i (1+ (abs (- end start))))
      (push v result)
      (incf v increment))
    result))

;; Roughly the same, but more compact and less clear:
(defun range (start end)
  (let* ((increment (if (<= start end) -1 1))
	 (v (- end increment))
	 (result nil))
    (dotimes (i (1+ (abs (- end start))) result)
      (push (incf v increment) result))))

;; Even more clever:
(defun range (start end)
  (let* ((increment (if (<= start end) -1 1))
	 (v end)
	 (result (list end)))
    (dotimes (i (abs (- end start)) result)
      (push (incf v increment) result))))

;; And even a loop solution:
(loop repeat (1+ (abs (- 
0
taruss
4/7/2014 10:11:52 PM
On 2014-04-07, Barry Margolin <barmar@alum.mit.edu> wrote:
> In article 
><slrnlk5gl2.1td.joost.m.kremers@j.kremers4.news.arnhem.chello.nl>,
>  Joost Kremers <joost.m.kremers@gmail.com> wrote:
>
>> Kaz Kylheku wrote:
>> > On 2014-04-07, Bigos <ruby.object@googlemail.com> wrote:
>> >> CL-USER> (defun range (start end)
>> >>             (if (<= start end)
>> >>                 (loop for x from start upto end collecting x)
>> >>                 (loop for x from start downto end collecting x)))
>> >
>> > In addition to recursive solution:
>> >
>> > (defun range (start end)
>> >   (when (> end start)
>> >     (psetf end start start end))
>> >   (loop for x from start upto end collecting x))
>> >
>> > (defun range (start end)
>> >     (loop for x
>> >           from (min start end)
>> >           upto (max start end)
>> >           collecting x))
>> 
>> The Lisp way:[1]
>> 
>> (defun my-range (start end)
>>   (eval `(loop for x from start ,(if (<= start end) 'upto 'downto) end 
>>   collecting x)))
>
> You need to unquote START and END as well. They're lexical variables, 

Ah, but maybe they have been declaimed special! Or this is some dumb Lisp
dialect without lexical scope.
0
Kaz
4/7/2014 10:23:14 PM
On 2014-04-07, Paul Rubin <no.email@nospam.invalid> wrote:
> taruss@google.com writes:
>> Abandoning loop:
>> ;; A clearer version.
>> ;;  Slightly clever in building the list backwards.
>
> Scheme style:
>
> (defun range (start end)
>   (if (<= start end)
>       (range1 start end -1 #'<= nil)
>     (range1 start end 1 #'>= nil)))
>
> (defun range1 (first last inc test acc)
>   (if (funcall test first last)
>       (range1 first (+ inc last) inc test
>             (cons last acc))
>     acc))

Built into TXR's Lisp dialect with auto decrement for reversed
arguments:

$ txr -p '(range 1 5)'
(1 2 3 4 5)

$ txr -p '(range 5 -3)'
(5 4 3 2 1 0 -1 -2 -3)

Oh, and range is lazy! Check this:

$ time txr -p '(third (range 1 (expt 15 500)))'
3

real    0m0.009s
user    0m0.008s
sys     0m0.000s

Only a few bignums were actually turned into garbage and killed in this
experiment; very humane.

(Boy, is that "time" ever pointless above.)
0
Kaz
4/7/2014 11:02:19 PM
"Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>>>>>> Built into TXR's Lisp dialect with auto decrement...
>> It is specified as stepping through character codes numerically,
>> are which defined as Unicode.
> Where?  Not in ANSI Common Lisp.

"Built into TXR's Lisp dialect..."  => http://www.nongnu.org/txr/
0
Paul
4/8/2014 1:01:01 AM
And two more slightly goofy options, with some small efficiency costs for high to low ranges:

(defun range (start end)
  (funcall (if (> start end) #'nreverse #'identity)
           (loop for x from (min start end) to (max start end) collect x)))

(defun range (start end)
  (if (> start end)
      (nreverse (range end start))
      (loop for x from start to end collect x)))


0
taruss
4/8/2014 1:01:01 AM
On 2014-04-07, Paul Rubin <no.email@nospam.invalid> wrote:
> Kaz Kylheku <kaz@kylheku.com> writes:
>> Built into TXR's Lisp dialect with auto decrement for reversed
>> arguments: ...
>
> http://www.nongnu.org/txr/ looks nice!  But, I think the auto decrement
> is a misfeature because of the possibility of surprises.

It works with characters too: (range #\a #\z).

I see there is a bug with floats (range 1.0 10.0) isn't
stopping at 10.0.

This is due to a buggered up eql function w.r.t. floats! Ouch!

Pushed out fix ...
0
Kaz
4/8/2014 4:22:08 AM
Kaz Kylheku <kaz@kylheku.com> writes:

> On 2014-04-07, Paul Rubin <no.email@nospam.invalid> wrote:
>> Kaz Kylheku <kaz@kylheku.com> writes:
>>> Built into TXR's Lisp dialect with auto decrement for reversed
>>> arguments: ...
>>
>> http://www.nongnu.org/txr/ looks nice!  But, I think the auto decrement
>> is a misfeature because of the possibility of surprises.
>
> It works with characters too: (range #\a #\z).

And how is that specified?  
Naively I get:

(#\a #\b #\c #\d #\e #\f #\g #\h #\i nil nil nil nil nil
#\Plus-Minus_Sign nil #\j #\k #\l #\m #\n #\o #\p #\q #\r nil nil nil
nil nil nil nil #\~ #\s #\t #\u #\v #\w #\x #\y #\z)


-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"
0
Pascal
4/8/2014 4:29:26 AM
Kaz Kylheku wrote:
>>> The Lisp way:[1]
>>> 
>>> (defun my-range (start end)
>>>   (eval `(loop for x from start ,(if (<= start end) 'upto 'downto) end 
>>>   collecting x)))
>>
>> You need to unquote START and END as well. They're lexical variables, 
>
> Ah, but maybe they have been declaimed special! Or this is some dumb Lisp
> dialect without lexical scope.

It was, actually, I quickly tested it in Emacs... Don't have a CL
environment available ATM.

Anyway, it wasn't a serious contribution to begin with.


-- 
Joost Kremers                                   joostkremers@fastmail.fm
Selbst in die Unterwelt dringt durch Spalten Licht
EN:SiS(9)
0
Joost
4/8/2014 6:29:45 AM
On Tuesday, April 8, 2014 8:29:45 AM UTC+2, Joost Kremers wrote:
.....

But looking at CL-ENUMERATIONS no eh? 3:) 3:) 3:)

Cheers
--
MA
0
Marco
4/8/2014 8:05:43 AM
On 2014-04-08, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> Kaz Kylheku <kaz@kylheku.com> writes:
>
>> On 2014-04-07, Paul Rubin <no.email@nospam.invalid> wrote:
>>> Kaz Kylheku <kaz@kylheku.com> writes:
>>>> Built into TXR's Lisp dialect with auto decrement for reversed
>>>> arguments: ...
>>>
>>> http://www.nongnu.org/txr/ looks nice!  But, I think the auto decrement
>>> is a misfeature because of the possibility of surprises.
>>
>> It works with characters too: (range #\a #\z).
>
> And how is that specified?

It is specified as stepping through character codes numerically,
are which defined as Unicode.
0
Kaz
4/8/2014 2:32:31 PM
Kaz Kylheku <kaz@kylheku.com> writes:

> On 2014-04-08, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>> Kaz Kylheku <kaz@kylheku.com> writes:
>>
>>> On 2014-04-07, Paul Rubin <no.email@nospam.invalid> wrote:
>>>> Kaz Kylheku <kaz@kylheku.com> writes:
>>>>> Built into TXR's Lisp dialect with auto decrement for reversed
>>>>> arguments: ...
>>>>
>>>> http://www.nongnu.org/txr/ looks nice!  But, I think the auto decrement
>>>> is a misfeature because of the possibility of surprises.
>>>
>>> It works with characters too: (range #\a #\z).
>>
>> And how is that specified?
>
> It is specified as stepping through character codes numerically,
> are which defined as Unicode.

Where?  Not in ANSI Common Lisp.


-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"
0
Pascal
4/8/2014 6:03:53 PM
Paul Rubin <no.email@nospam.invalid> writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>>>>>>> Built into TXR's Lisp dialect with auto decrement...
>>> It is specified as stepping through character codes numerically,
>>> are which defined as Unicode.
>> Where?  Not in ANSI Common Lisp.
>
> "Built into TXR's Lisp dialect..."  => http://www.nongnu.org/txr/

Ah! Good.

(You could also just specify a subset of CL that would have this
restriction ;-) )

-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"
0
Pascal
4/8/2014 8:10:02 PM
On 2014-04-08, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> Paul Rubin <no.email@nospam.invalid> writes:
>
>> "Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>>>>>>>> Built into TXR's Lisp dialect with auto decrement...
>>>> It is specified as stepping through character codes numerically,
>>>> are which defined as Unicode.
>>> Where?  Not in ANSI Common Lisp.
>>
>> "Built into TXR's Lisp dialect..."  => http://www.nongnu.org/txr/
>
> Ah! Good.
>
> (You could also just specify a subset of CL that would have this
> restriction ;-) )

When a language is regarded as a set (so that we may talk about subsets),
it is actually a set of instances of the language. (Grammatically correct
strings of symbols, portable programs, or whatever is the measure of being
"in" the given language.)

A program which relies on Unicode is outside of the set of well-defined, highly
portable ANSI CL programs.  That program is effectively in a bigger language:
one which has more specifications that pin down more details, and of which ANSI
CL is a subset, rather than the other way around. Some programs in that
language are portable ANSI CL, some are not.

Language standards like ANSI CL look at implementations and factor out a common
definition is based on a common *subset*, not a superset. The resulting
language is smaller than the union of all implementations; it is
(approximately) their intersection.

Intuitively, we are not restricted when we are given absolutes, like
"characters are Unicode".  We are liberated, because we don't have to code
obtuse hacks in order to enumerate letters from A to Z, or whatever, just to be
ANSI conforming.

What liberates are the extra definitions which replace items marked with
language like "unspecified behavior", "implementation-defined" or "undefined",
with solid assurances. These extra definitions make the language larger.

(The only kinds of definitions which make a language smaller are those which
impose constraints, asserting that some of the possible programs described by
all the the other definitions are to be deemed invalid. Definitions which
replace undefined or unspecified behavior are not of this type; they strictly
extend the language.)
0
Kaz
4/8/2014 8:43:55 PM
On 14/06/14 18:02, Pascal J. Bourguignon wrote:
>
> There's also a reason why loop has two forms, for downto and upto.
> It's because it accepts a end that's beyond limits with respect to
> start, and then the loop does nothing.
>
> If you want to avoid the code duplication, you will have to write the
> loop yourself.  Notice that since this involves parameters, it will make
> the loop slower. (As always, we're trading space for time or time for space).

Thank you for the explanation.
0
Bigos
6/14/2014 1:01:01 AM
Bigos wrote:

> CL-USER> (defun range (start end)
>            (if (<= start end)
>                (loop for x from start upto end collecting x)
>                (loop for x from start downto end collecting x)))

Racket:

 > (range 2 8)
 '(2 3 4 5 6 7)
 > (range 22 8 -1)
 '(22 21 20 19 18 17 16 15 14 13 12 11 10 9)
0
WJ
6/14/2014 5:31:02 AM
WJ wrote:

> Bigos wrote:
> 
> > CL-USER> (defun range (start end)
> >            (if (<= start end)
> >                (loop for x from start upto end collecting x)
> >                (loop for x from start downto end collecting x)))
> 
> Racket:
> 
>  > (range 2 8)
>  '(2 3 4 5 6 7)
>  > (range 22 8 -1)
>  '(22 21 20 19 18 17 16 15 14 13 12 11 10 9)

elisp:

: (number-sequence 2 8)
(2 3 4 5 6 7 8)
: (number-sequence 22 8 -1)
(22 21 20 19 18 17 16 15 14 13 12 11 10 9 8)

: (defun range (start end)
  (number-sequence start end
    (if (< end start) -1 1)))
range
: (range 2 8)
(2 3 4 5 6 7 8)
: (range 22 8)
(22 21 20 19 18 17 16 15 14 13 12 11 10 9 8)
0
WJ
6/14/2014 7:21:16 AM
On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
> CL-USER> (defun range (start end)
>             (if (<= start end)
>                 (loop for x from start upto end collecting x)
>                 (loop for x from start downto end collecting x)))

(defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting x))) (if (<= s e) (f upto) (f downto))))
0
Ben
6/14/2014 2:28:24 PM
Ben Hyde <bhyde@pobox.com> writes:

> On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
>> CL-USER> (defun range (start end)
>>             (if (<= start end)
>>                 (loop for x from start upto end collecting x)
>>                 (loop for x from start downto end collecting x)))
>
> (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
> x))) (if (<= s e) (f upto) (f downto))))

This doesn't remove the duplication of code, in the expanded form.

There's also a reason why loop has two forms, for downto and upto.
It's because it accepts a end that's beyond limits with respect to
start, and then the loop does nothing.  

If you want to avoid the code duplication, you will have to write the
loop yourself.  Notice that since this involves parameters, it will make
the loop slower. (As always, we're trading space for time or time for space).

(defun range (start end)
  (let ((step (if (<= start end) 1 -1))
        (stop (if (<= start end) (function >) (function <)))
        (result (cons '() '())))
    (do ((start start (+ start step))
         (tail result (rest tail)))
        ((funcall stop start end) (rest result))
      (setf (rest tail) (list start)))))

(list (range 0 10) (range 10 0) (range 0 0))
--> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))

-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"
0
Pascal
6/14/2014 5:02:18 PM
Pascal J. Bourguignon wrote:

> Ben Hyde <bhyde@pobox.com> writes:
> 
> > On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
> >> CL-USER> (defun range (start end)
> >>             (if (<= start end)
> >>                 (loop for x from start upto end collecting x)
> >>                 (loop for x from start downto end collecting x)))
> > 
> > (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
> > x))) (if (<= s e) (f upto) (f downto))))
> 
> This doesn't remove the duplication of code, in the expanded form.
> 
> There's also a reason why loop has two forms, for downto and upto.
> It's because it accepts a end that's beyond limits with respect to
> start, and then the loop does nothing.  
> 
> If you want to avoid the code duplication, you will have to write the
> loop yourself.  Notice that since this involves parameters, it will make
> the loop slower. (As always, we're trading space for time or time for space).
> 
> (defun range (start end)
>   (let ((step (if (<= start end) 1 -1))
>         (stop (if (<= start end) (function >) (function <)))
>         (result (cons '() '())))
>     (do ((start start (+ start step))
>          (tail result (rest tail)))
>         ((funcall stop start end) (rest result))
>       (setf (rest tail) (list start)))))
> 
> (list (range 0 10) (range 10 0) (range 0 0))
> --> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))

elisp:

(defun range (start end)
  (let ((offset (min start end))
        (result '()))
    (dotimes (i (1+ (abs (- start end))))
      (push (+ i offset) result))
    (if (< start end) (nreverse result) result)))

(list (range 0 10) (range 10 0) (range 0 0))
--> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))
0
WJ
6/14/2014 6:31:17 PM
On 2014-06-14, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> Ben Hyde <bhyde@pobox.com> writes:
>
>> On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
>>> CL-USER> (defun range (start end)
>>>             (if (<= start end)
>>>                 (loop for x from start upto end collecting x)
>>>                 (loop for x from start downto end collecting x)))
>>
>> (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
>> x))) (if (<= s e) (f upto) (f downto))))
>
> This doesn't remove the duplication of code, in the expanded form.

How do you know? Maybe the compiler, in turn, does some common code
elimination on the two loops.

What duplication of code do we care about? I would say: only two:
duplication of what the programmer has to produce (affecting productivity)
and duplication of machine code (affecting code size, caching, etc).

Duplication in intermediate representation: vanishingly low priority concern.
0
Kaz
6/14/2014 7:22:58 PM
Kaz Kylheku <kaz@kylheku.com> writes:

> On 2014-06-14, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>> Ben Hyde <bhyde@pobox.com> writes:
>>
>>> On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
>>>> CL-USER> (defun range (start end)
>>>>             (if (<= start end)
>>>>                 (loop for x from start upto end collecting x)
>>>>                 (loop for x from start downto end collecting x)))
>>>
>>> (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
>>> x))) (if (<= s e) (f upto) (f downto))))
>>
>> This doesn't remove the duplication of code, in the expanded form.
>
> How do you know? 

Because we know how the CL macroexpansion is specified.  Notice how I
said "in the expanded form", not "in the compiled code".


> Maybe the compiler, in turn, does some common code
> elimination on the two loops.

Whatever.


> What duplication of code do we care about? I would say: only two:
> duplication of what the programmer has to produce (affecting productivity)
> and duplication of machine code (affecting code size, caching, etc).
>
> Duplication in intermediate representation: vanishingly low priority concern.

Indeed.  

-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"
0
Pascal
6/14/2014 8:00:55 PM
On 14/06/14 21:00, Pascal J. Bourguignon wrote:
> Kaz Kylheku <kaz@kylheku.com> writes:
>
>> On 2014-06-14, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>>> Ben Hyde <bhyde@pobox.com> writes:
>>>
>>>> On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
>>>>> CL-USER> (defun range (start end)
>>>>>              (if (<= start end)
>>>>>                  (loop for x from start upto end collecting x)
>>>>>                  (loop for x from start downto end collecting x)))
>>>>
>>>> (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
>>>> x))) (if (<= s e) (f upto) (f downto))))
>>>
>>> This doesn't remove the duplication of code, in the expanded form.
>>
>> How do you know?
>
> Because we know how the CL macroexpansion is specified.  Notice how I
> said "in the expanded form", not "in the compiled code".
>
>
>> Maybe the compiler, in turn, does some common code
>> elimination on the two loops.
>
> Whatever.
>
>
>> What duplication of code do we care about? I would say: only two:
>> duplication of what the programmer has to produce (affecting productivity)
>> and duplication of machine code (affecting code size, caching, etc).
>>
>> Duplication in intermediate representation: vanishingly low priority concern.
>
> Indeed.
>

There's also programmers vanity. The problem is that this priority 
varies wildly from one person to another.


0
Bigos
6/14/2014 9:10:09 PM
Bigos <ruby.object@googlemail.com> writes:

> CL-USER> (defun range (start end)
>            (if (<= start end)
>                (loop for x from start upto end collecting x)
>                (loop for x from start downto end collecting x)))

Use DO instead. Something like:

(defun range (start end)
  (let ((up (<= start end)))
    (unless up (rotatef start end))
    (do ((x start (+ x 1))
         (res (list)))
        ((> x end) (if up (reverse res) res))
      (push x res))))
0
Alexander
6/15/2014 3:16:19 AM
WJ wrote:

> Pascal J. Bourguignon wrote:
> 
> > Ben Hyde <bhyde@pobox.com> writes:
> > 
> > > On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
> > >> CL-USER> (defun range (start end)
> > >>             (if (<= start end)
> > >>                 (loop for x from start upto end collecting x)
> > >>                 (loop for x from start downto end collecting x)))
> > > 
> > > (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
> > > x))) (if (<= s e) (f upto) (f downto))))
> > 
> > This doesn't remove the duplication of code, in the expanded form.
> > 
> > There's also a reason why loop has two forms, for downto and upto.
> > It's because it accepts a end that's beyond limits with respect to
> > start, and then the loop does nothing.  
> > 
> > If you want to avoid the code duplication, you will have to write the
> > loop yourself.  Notice that since this involves parameters, it will make
> > the loop slower. (As always, we're trading space for time or time for space).
> > 
> > (defun range (start end)
> >   (let ((step (if (<= start end) 1 -1))
> >         (stop (if (<= start end) (function >) (function <)))
> >         (result (cons '() '())))
> >     (do ((start start (+ start step))
> >          (tail result (rest tail)))
> >         ((funcall stop start end) (rest result))
> >       (setf (rest tail) (list start)))))
> > 
> > (list (range 0 10) (range 10 0) (range 0 0))
> > --> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))
> 
> elisp:
> 
> (defun range (start end)
>   (let ((offset (min start end))
>         (result '()))
>     (dotimes (i (1+ (abs (- start end))))
>       (push (+ i offset) result))
>     (if (< start end) (nreverse result) result)))
> 
> (list (range 0 10) (range 10 0) (range 0 0))
> --> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))

Shorter:

(defun range (start end)
  (let ((offset (min start end))
        result)
    (dotimes (i (1+ (abs (- start end))))
      (push (+ i offset) result))
    (if (< start end) (nreverse result) result)))
0
WJ
6/16/2014 4:17:25 AM
On Sunday, June 15, 2014 5:16:19 AM UTC+2, Alexander Skobelev wrote:
> Bigos <@googlemail.com> writes:
> 

....

Even "shorter" 3:)

(some-library-somebody-cooked-up-e.g.-cl-enumeration-thankyou:range start end)

Cheers
--
MA
0
Marco
6/16/2014 9:31:36 AM
On 2014-06-15 07:16:19 +0400, Alexander Skobelev wrote:
> Bigos <ruby.object@googlemail.com> writes:
>
>> CL-USER> (defun range (start end)
>>            (if (<= start end)
>>                (loop for x from start upto end collecting x)
>>                (loop for x from start downto end collecting x)))
>
> Use DO instead. Something like:
>
> (defun range (start end)
>   (let ((up (<= start end)))
>     (unless up (rotatef start end))
>     (do ((x start (+ x 1))
>          (res (list)))
>         ((> x end) (if up (reverse res) res))
>       (push x res))))

One can still use loop, just select the end check function.  For a more
Haskell like version of range, where you include the end value and
specify the step by giving the first two values in the sequence:

--8<---------------cut here---------------start------------->8---
(defun range (start next &optional last)
  (let* ((end (if last last next))
         (step (cond (last (- next start))
                     ((> end start) 1)
                     (t -1)))
         (op (cond ((> step 0) #'<=)
                   ((< step 0) #'>=)
                   (t (error "range: step = 0")))))
    (loop for x = start then (+ x step)
       while (funcall op x end)
       collect x)))
--8<---------------cut here---------------end--------------->8---
--
Barry Fishman
0
Barry
6/16/2014 12:43:26 PM
Pascal J. Bourguignon wrote:

> Ben Hyde <bhyde@pobox.com> writes:
> 
> > On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
> >> CL-USER> (defun range (start end)
> >>             (if (<= start end)
> >>                 (loop for x from start upto end collecting x)
> >>                 (loop for x from start downto end collecting x)))
> > 
> > (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
> > x))) (if (<= s e) (f upto) (f downto))))
> 
> This doesn't remove the duplication of code, in the expanded form.
> 
> There's also a reason why loop has two forms, for downto and upto.
> It's because it accepts a end that's beyond limits with respect to
> start, and then the loop does nothing.  
> 
> If you want to avoid the code duplication, you will have to write the
> loop yourself.  Notice that since this involves parameters, it will make
> the loop slower. (As always, we're trading space for time or time for space).
> 
> (defun range (start end)
>   (let ((step (if (<= start end) 1 -1))
>         (stop (if (<= start end) (function >) (function <)))
>         (result (cons '() '())))
>     (do ((start start (+ start step))
>          (tail result (rest tail)))
>         ((funcall stop start end) (rest result))
>       (setf (rest tail) (list start)))))
> 
> (list (range 0 10) (range 10 0) (range 0 0))
> --> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))

elisp:

(require 'dash)

(defun range (start end)
  (let ((step (if (< start end) 1 -1)))
    (--unfold
      (and (not (eq it (+ end step))) (cons it (+ it step)))
      start)))
0
WJ
6/21/2014 3:21:21 AM
Pascal J. Bourguignon wrote:

> Ben Hyde <bhyde@pobox.com> writes:
> 
> > On Monday, April 7, 2014 6:46:57 AM UTC-4, Bigos wrote:
> >> CL-USER> (defun range (start end)
> >>             (if (<= start end)
> >>                 (loop for x from start upto end collecting x)
> >>                 (loop for x from start downto end collecting x)))
> > 
> > (defun r (s e) (macrolet ((f (d) `(loop for x from s ,d e collecting
> > x))) (if (<= s e) (f upto) (f downto))))
> 
> This doesn't remove the duplication of code, in the expanded form.
> 
> There's also a reason why loop has two forms, for downto and upto.
> It's because it accepts a end that's beyond limits with respect to
> start, and then the loop does nothing.  
> 
> If you want to avoid the code duplication, you will have to write the
> loop yourself.  Notice that since this involves parameters, it will make
> the loop slower. (As always, we're trading space for time or time for space).
> 
> (defun range (start end)
>   (let ((step (if (<= start end) 1 -1))
>         (stop (if (<= start end) (function >) (function <)))
>         (result (cons '() '())))
>     (do ((start start (+ start step))
>          (tail result (rest tail)))
>         ((funcall stop start end) (rest result))
>       (setf (rest tail) (list start)))))
> 
> (list (range 0 10) (range 10 0) (range 0 0))
> --> ((0 1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1 0) (0))

Gauche Scheme:

(define (range start end)
  (let* ((inc (if (< end start) -1 1))
         (count (abs (+ inc (- end start)))))
    (iota count start inc)))

(list (range 0 5) (range 5 0) (range 0 0) (range -5 -9))
  ====>
((0 1 2 3 4 5) (5 4 3 2 1 0) (0) (-5 -6 -7 -8 -9))



0
WJ
11/5/2014 3:21:24 PM
Reply:

Similar Artilces:

how to get rid of following code duplication #2
CL-USER> (defun range (start end) (if (<= start end) (loop for x from start upto end collecting x) (loop for x from start downto end collecting x))) * Bigos <lhu1a6$k9l$1@speranza.aioe.org> : Wrote on Mon, 07 Apr 2014 12:14:16 +0100: | CL-USER> (defun range (start end) | (if (<= start end) | (loop for x from start upto end collecting x) | (loop for x from start downto end collecting x))) (if (<= start end) (loop for x from start upto end collecting x) (range end ...

Getting Rid of Duplicates
I find that I have duplicate tubes and duplicate brushes (and probably other duplicate images) in my Paint Shop Pro program files. How would I go about deleting them so I can free up some space? TIA JT "jaytea" <jayteadesigns@sbcglobal.net> wrote in message news:1166845931.027572.17520@i12g2000cwa.googlegroups.com... >I find that I have duplicate tubes and duplicate brushes (and probably > other duplicate images) in my Paint Shop Pro program files. > How would I go about deleting them so I can free up some space? > TIA > JT > Reset your cache so that it...

Getting Rid of Duplicates
I find that I have duplicate tubes and duplicate brushes (and probably other duplicate images) in my Paint Shop Pro program files. How would I go about deleting them so I can free up some space? TIA JT "jaytea" <jayteadesigns@sbcglobal.net> wrote in message news:1166845931.027572.17520@i12g2000cwa.googlegroups.com... >I find that I have duplicate tubes and duplicate brushes (and probably > other duplicate images) in my Paint Shop Pro program files. > How would I go about deleting them so I can free up some space? > TIA > JT > Reset your cache so that it...

Getting rid of duplicates
I have a table, TEST_TABLE, with 6 columns (COL1, COL2, COL3, COL4, COL5, COL6).... I need to be able to select all columns/rows where COL3, COL4, and COL5 are unique.... I have tried using DISTINCT and GROUP BY, but both will only allow me to access columns COL3, COL4, and COL5..... i need access to all columns...I just want to get rid of duplicate rows (duplicates of COL3, COL4, and COL5)... Thanks in advance. Joe If a row is duplicated on (col3, col4, col5) which values do you want for col1 and col2? Here's some example data: CREATE TABLE Sometable (col1 INTEGER NOT NULL, col2 IN...

Getting rid of duplicate tables.
First I wish I knew how this was caused but here is our problem. Sometime in the recent past we got a duplicate table. Here is the result of a pg_dump with a pg_restore for just that table. -- -- TOC entry 59 (OID 11462032) -- Name: order_to_do; Type: TABLE; Schema: public; Owner: www -- Data Pos: 0 -- CREATE TABLE order_to_do ( order_id integer DEFAULT 0 NOT NULL, to_do_id text DEFAULT ''::text NOT NULL, date_time timestamp without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL, csr_id integer DEFAULT 0 NOT NULL...

getting rid of strange coding [fonts]
hi, i'd be grateful if anyone could suggest a solution to such problem. at some point, my system started using strange coding, both in console as in windows [for example the titles and message bars are now unreadable]. due to that normal operation is impossible, cause lots of program titles, or messages in console is unredable console for instance, instead of some letters or other symbols is showing squares, same with the gui windows. thanks in advance, michal ...

Getting rid of packages in VHDL code
Hello, I am working with some VHDL code (http://www.xess.com/projects/sdramtst-1_6.zip), and I would like to use an automated tool to convert the VHDL code to Verilog (http://www.ocean-logic.com/downloads.htm). Unfortunately, the automated tool does not seem to support VHDL packages (containing functions). The "proper way" to convert the code would be to do the conversion by hand, but in the meantime: Is there a way to remove the packages from the VHDL code? Is there another way to bundle functions instead of using packages? There are two files in the download that demons...

Getting rid of hard coded path
I have been running some code from a form's on open event to run regedit if a registry key does not exist in the registry. It has been working fine, but I have had the path to the registry fix file hard coded into the VBA like this. RunReg = Shell("regedit.exe /s F:\MyFolder\SQLfix.reg", 0) Now I wish to make this more generic and allow it to run from any path. I have tried to use CurrentProjectPath like this. RunReg = Shell("regedit.exe /s" & CurrentProjectPath & "\SQLfix.reg", 0) When I do this, I get a 'compile error variable not define...

Is Way to Get Rid of Duplicate Lines ??
I working on array of 150000 names, just first name, in vector. To get this vector all I do was say D is {disclose}[2]C where the C is just the matrix of names with shape of something like 150000 66 But got many duplicate names and wanting to get rid of them, so I do: D {is} {disclose}((D {iota} D) = {iota}{pho} D) / D Maybe this work, I not find out cuz 3 hour later is still running!! Is got to be better faster way? Anyone know? Thank! Alexi On 7/21/2011 4:19 PM, Alexander Smith wrote: > > I working on array of 150000 names, just first name, in vector. To &...

Get Rid of Duplicate Impoint Labels
Hello, I'm trying to find a way to delete duplicate Impoint labels. I am using a PoisitonCallback that looks like this for all of my impoints... Defined as: h.addNewPositionCallback(@(pos) update_coords(h,pos(1),pos(2))); function update_coords(h,x1,y1) global coords points ctrl; for i=1:size(points,2) coords(i,:) = getPosition(points(i)); end set(ctrl, 'XData', coords(:,1), 'YData', coords(:,2)); setString(h,['(',num2str(x1),',',num2str(y1),')']); end This is on an axis in a GUI. The problem here is that when the impoint ...

how do I get rid of the "if" in this code?
Hi All, How do I get rid of the "if" from the following code? <code> #!/usr/bin/perl $ip="192.168.30.10"; if ($ip =~ m/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/ ) { print "$1 $2 $3 $4\n"; $HexIP = ($1 << 24) + ($2 << 16) + ($3 << 8) + $4; }; printf ( "0x%X\n", $HexIP ); </code> $ perl ip.test.pl 192 168 30 10 0xC0A81E0A Le 11/07/2015 10:22, T a écrit : > Hi All, > > How do I get rid of the "if" from the following code? > > <code> &...

how to speed up this code, i want to get rid of nested for
for k=1:length(coeffs1) %coesffs1 is n*3 matrix with unknown n for i=1:length(unique(l)) [r2, c2]= find(l == i & pd<inf); % pd and l are matrices of 300*300 [r3, ~]=find(l==i & nc<inf); % nc is matrix of 300*300 if ~isempty(r2) v=zeros(length(r2),1); for n=1:length(r2) v(n)=pd(r2(n),c2(n)); end zbar=eval2dPoly(r2,c2,coeffs1(k,:)'); % Zbar is estimated new values using function eval2dPoly %%%% m=abs(zbar-v); r1=length(find(m==0)); ...

How to get rid of duplicates without using any group?
I have a dataset as below: serial description ---------------------- 10001 yes no may be 10001 he she them 1002 yes no may be 1002 he she them How can I get rid of additions duplicate values for the same serial? I need only one serial number ( can not do grouping it messes uo the order) as below serial description ---------------------- 10001 yes no may be he she them 1002 yes no may be he ...

Could someone tell me what I should do to get rid of the following error.
Could someone tell me what I should do to get rid of the following error. ------------------------------- 14.pjt - Debug ------------------------------- [Linking...] "C:\CCStudio_v3.1\C6000\cgtools\bin\cl6x" -@"Debug.lkf" <Linking> undefined first referenced symbol in file --------- ---------------- _comm_intr C:\CCStudio_v3.1\MyProjects\124\14\Debug\copy.obj _input_sample C:\CCStudio_v3.1\MyProjects\124\14\Debug\copy.obj _output_left_sa...

Web resources about - how to get rid of following code duplication - comp.lang.lisp

Duplication - Wikipedia, the free encyclopedia
Symmetry , has two meanings. The first is a vague sense of harmonious and beautiful proportion and balance. The second is an exact mathematical ...

Queensland Election: LNP promises Sunshine Coast train line duplication
... rail line. The Sunshine Coast would get an extra 150 train services a week under an LNP plan to duplicate part of the rail line. A line duplication ...

Commission of Audit and duplication
Do you think there is unecessary duplication across state and federal services?

'Role duplication' drives redundancies at M2
... 150 people redundant, the company announced this morning. In a statement issued to the ASX the company said that it had identified "role duplication" ...


Duplication for NBN in Canberra?
NBN might double up in the ACT. And one observer is not happy about it.

Blizzard fixes Diablo III gold duplication bug, but the damage may be done
... would get twice as much gold returned to them, creating an easy source of infinite in-game currency. Blizzard made players aware of the duplication ...

About Entities, Aggregates and Data Duplication.
... so far, for this class, except validation (which as Udi Dahan would say, doesn't necessarily belong to the domain layer) but the smell of duplication ...

SMX West 2012: Duplication, Aggregation, Syndication, Affiliates, Scraping & Info Architecture
... brand, coupons, discounts and bundles, pricing policy, nearest stores, email notifications) photos, videos and other assets Read more of Duplication, ...

Redraw Cuyahoga County to erase duplication and save money: Joe Frolik - cleveland.com
Break out your crayons, pencils and creativity. Cuyahoga County needs a new map. But first, let's talk about why we need a new map. The bottom ...

Resources last updated: 1/27/2016 2:07:04 AM