From: Rahul Jain on
Pascal Costanza <pc(a)p-cos.net> writes:

> Unfortunately it [Clojure] brings a little bit too much Java into Lisp, for my
> taste...

And a bit too much scheme for most of my existing code to be portable to it.

--
Rahul Jain
rjain(a)nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: gavino on
On Dec 18, 11:56 pm, Thierry Pirot <0...(a)thierrypirot.net> wrote:
> ccc31807 writes:
> > On page 61 of Graham's ANSI Common Lisp, he defines bin-search and
> > finder, which I have copied below.
>
> > I have struggled with this for days, and still don't understand these
> > definitions completely. This morning, I wrote bin-search-2, which took
> > about ten minutes to write (and about thirty minutes to debug), but I
> > understand it thoroughly -- and I am just the merest beginner, barely
> > a toe in the water.
>
> [...]
>
> > ;;; ---------ch_04.lisp-----------------------
> > (defparameter v (vector 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33
> > 35 37 39 41))
>
> > (defun bin-search (obj vec)
> >   (format t "bin-search ~a ~a~%" obj vec)
> >   (let ((len (length vec)))
> >     (and (not (zerop len)))
> >          (finder obj vec 0 (- len 1))))
>
> The parentheses in that copy of bin-search are wrong.  
> Is this genuinely Graham's ?  I don't own the book to check.  
>
>
>
> > (defun finder (obj vec start end)
> >   (format t "finder obj: ~a, vec: ~a, start: ~a, end: ~a~%" obj vec
> > start end)
> >   (format t "     ~a~%" (subseq vec start (+ end 1)))
> >   (let ((range (- end start)))
> >     (if (zerop range)                      ; outer if test
> >         (if (eql obj (aref vec start))       ; inner if test
> >             obj                              ; the return obj
> >             nil)                             ; else return nil
> >           (let ((mid (+ start (round (/ range 2)))))   ; outer then
> >             (let ((obj2 (aref vec mid)))
> >               (if (< obj obj2)
> >                   (finder obj vec start (- mid 1))
> >                   (if (> obj obj2)
> >                       (finder obj vec (+ mid 1) end)
> >                       obj)))))))
>
> I doubt that such a code might be understandable or correct ;
> indeed it is not : just evaluate (bin-search 0 #(1 2)) and blow the stack..  
>
> What is the origin of this bug and the way to correct it ?  
> The bug is about fiddling with indices and splitting their range.  
> Other posts in this thread have emphasised
> the advantage to separate functionalities amongst functions.  
> finder is a step in that direction, however it still dangerously mixes  
> the job of finding with the job of dichotomy,
> which can be handled in the following quick and dirty protocol
> to deal with ranges --- as conses --- and their splitting.  
>
>   (defun range (start end) ;end inclusive
>     (if (<= start end)
>         (cons start end)
>         (error "Invalid range ~s ~s. " start end)))
>   (defmethod range_of ((v vector))
>     (unless (equalp #() v) (range 0 (1- (length v)))))
>   (defun range_len (range)
>     (if range (1+ (- (cdr range) (car range))) 0))
>   (defun range_mid (range)
>     (when (and range (< (car range) (cdr range)))
>       (+ (car range) (floor (range_len range) 2))))
>   (defmethod range_splits (range)
>     "The cons of two complementary 'even' subranges of the range range. "
>     (let ((mid (range_mid range)))
>       (when mid                         ;is_splittable
>         (cons (range (car range) (1- mid))
>               (range mid     (cdr range))))))
>
> Now, one should wonder about this protocol,
> is it reliable --- anyway it is easy to unit-test ---,  
> is it handy --- more than start and end parameters --- to use ?  
> Let's see,
>
> (defun bin-search (obj vec)
>   (format t "bin-search' ~a ~a~%" obj vec)
>   (unless (equalp #() vec)
>     (labels ((finder (range)
>                (format t "range:~a~%" range)
>                (format t "     ~a~%" (subseq vec (car range) (1+ (cdr range))))
>                (let ((splits (range_splits range)))
>                  (if splits
>                      (if (< obj (aref vec (cadr splits)))
>                          (finder (car splits))
>                          (finder (cdr splits)))
>                      (when (= obj (aref vec (car range))) obj)))))
>       (finder (range_of vec)))))
>
> The original finder was rather self contained and used a lot of variables,
> now it involves a lot of functions,
> although it's essentially only range_splits.  
> It also performs a slightly different algorithm [1], using no pivot :
>   if the range is splittable
>    then search in the appropriate split,
>   else --- the range stands for a singleton ---
>    check if the element of the singleton is the searched obj.  
>
>
>
> > (defun bin-search-2 (obj vec &optional (start 0))
> >   (let*((len (length vec))
> >         (mid (floor (/ len 2))))
> >   (format t "bin-search-2 obj: ~a, vec: ~a, start ~a, end: ~a, mid: ~a~
> > %" obj vec start len mid)
> >   (cond ((zerop len) nil)
> >         ((= obj (svref vec mid)) obj)
> >         ((< obj (svref vec mid)) (bin-search-2 obj (subseq vec start
> > mid)))
> >         ((> obj (svref vec mid)) (bin-search-2 obj (subseq vec (+ mid
> > 1) len))))))
>
> > ;; I don't know how to set 'start' to 0 by default, other than by
> > making it optional.
> > ;; I would appreciate help with this.
>
> You simply don't need it, it is always 0.  
> So your function can be written like
>
>   (defun bin-search (obj vec &key (cmp #'cmp))
>     (format t "bin-search''' obj: ~a vec: ~a ~%" obj vec)
>     (let* ((len (length vec))
>            (mid (floor len 2)))
>       (when (/= 0 len)
>         (case (funcall cmp obj (aref vec mid))
>          (0  obj)
>          (-1 (bin-search obj (subseq vec 0 mid)))
>          (+1 (bin-search obj (subseq vec (1+ mid))))))))
>
> where I added
>
>   (defgeneric cmp (x y)
>     (:documentation "+1, 0, -1 according to x being after, with, before y. "))
>   (defmethod  cmp ((x integer) (y integer)) (signum (- x y)))
>
> To cope with the problem of the consing of subseq, maybe using
>
>   (defun subvec (a_vector start &optional (end (length a_vector)))
>     (make-array (- end start)
>               :displaced-to a_vector
>               :displaced-index-offset start
>               :element-type (array-element-type a_vector)))
>
> instead of subseq can help, but I know little about displaced arrays
> and a quick profiling shows only slight differences in Clisp.  
> I guess it should be different for bitvectors or vectors or big elements.  
> I hope someone will clear this.  
>
> [1] This algorithm exhibits a nice pattern, for processing by dichotomy,
> that can be translated, without further explanations, as
>
> (defun spliterator (rektor f_atom &optional (splitter #'split))
>   (labels ((f (x)
>              (let ((splits (funcall splitter x)))
>                (if splits
>                    (funcall rektor (f (car splits)) (f (cdr splits)) splits)
>                    (funcall f_atom x)))))
>     #'f))
>
> (defun bin-search (obj vec)
>   (unless (equalp #() vec)
>     (funcall
>      (spliterator
>       (lambda (x y splits) (if   (< obj (aref vec (cadr splits))) x y))
>       (lambda (x)          (when (= obj (aref vec (car x)))       obj))
>       'range_splits)
>      (range_of vec))))
>
> --
>    Take it Easy          Don't Hurry            Be Happy
>
>                            Thierry
>
> ((LAMBDA (LAMBDA) `(,LAMBDA ',LAMBDA)) '(LAMBDA (LAMBDA) `(,LAMBDA ',LAMBDA)))

AWESOME
GOOD SHOW!
hardcore!
From: gavino on
On Dec 19, 7:05 pm, Paul Donnelly <paul-donne...(a)sbcglobal.net> wrote:
> "W. James" <w_a_x_...(a)yahoo.com> writes:
> > W. James wrote:
>
> >> def bin_search obj, array
> >>   len = array.size
> >>   len > 0  and  finder( obj, array, 0 ... len )
> >> end
>
> >> def split_range range
> >>   first, last = range.min, range.max
> >>   mid = first + ((last - first) / 2.0).round
> >>   [(first .. [first,mid.pred].max), mid, ([mid.succ,last].min ..
> >> last)] end
>
> > Faster:
>
> > def bin_search obj, array
> >   len = array.size
> >   len > 0  and  finder( obj, array, 0 .. len.pred )
> > end
>
> > def split_range range
> >   first, last = range.first, range.last
> >   mid = first + ((last - first) / 2.0).round
> >   [(first .. [first,mid.pred].max), mid, ([mid.succ,last].min .. last)]
> > end
>
> Even faster: not writing it in Ruby?

?
From: gavino on
On Dec 27, 4:38 pm, Pascal Costanza <p...(a)p-cos.net> wrote:
> On 27/12/2009 13:30, Chris Barts wrote:
>
>
>
> > Pascal Costanza<p...(a)p-cos.net>  writes:
>
> >> On 18/12/2009 03:51, Barry Margolin wrote:
> >>> In article
> >>> <404e1698-289b-441e-9d0b-635b432f7...(a)a21g2000yqc.googlegroups.com>,
> >>>    w_a_x_man<w_a_x_...(a)yahoo.com>   wrote:
>
> >>>> Guy L. Steele, Jr., July 1989:
>
> >>>> I think we may usefully compare the approximate number of pages
> >>>> in the defining standard or draft standard for several
> >>>> programming languages:
>
> >>>>     Common Lisp   1000 or more
> >>>>     COBOL          810
> >>>>     ATLAS          790
> >>>>     Fortran 77     430
> >>>>     PL/I           420
> >>>>     BASIC          360
> >>>>     ADA            340
> >>>>     Fortran 8x     300
> >>>>     C              220
> >>>>     Pascal         120
> >>>>     DIBOL           90
> >>>>     Scheme          50
>
> >>> This is a little unfair, because the Common Lisp base language includes
> >>> lots of things that would be in libraries in most other languages, e.g.
> >>> hash tables, sequences, association lists, and portable pathnames.  In
> >>> fact, even types that are basic primitives in Lisp, such as linked
> >>> lists, imaginary numbers, and symbols, would generally be in libraries
> >>> in traditional languages.
>
> >> I think there is a change in perspective now. Younger generations
> >> nowadays consider that these things should be part of a language, and
> >> that Common Lisp is actually too small and should have even more.
>
> > Which is why we have Clojure (for which there is another little troll in
> > this very group), which brings all of Java into Lisp without actually
> > making Lispers write in Java. The fundamental problem with that is it
> > doesn't bring in any well-designed class libraries along with it.
>
> Unfortunately it brings a little bit too much Java into Lisp, for my
> taste...
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

I am with pascal.
Please no java!
From: gavino on
On Dec 28, 10:47 am, game_designer <alex.repenn...(a)gmail.com> wrote:
> On Dec 16, 8:42 am, ccc31807 <carte...(a)gmail.com> wrote:
>
> > On page 61 of Graham's ANSI Common Lisp, he defines bin-search and
> > finder, which I have copied below.
>
> > I have struggled with this for days, and still don't understand these....
>
> > I have noticed this about CL in general and in Graham's book in
> > particular -- Lispers seem to go to great lengths to make their code
> > obtuse, obscurantist, obscure, and difficult to understand. For
> > example, in the example below, Why the nested ifs? Why the nested
>
> Graham writes nice essays which have helped Lisp a lot. I am thankful
> for that. The reference flavor aspect of ANSI Common Lisp is quite OK
> but for people writing modern applications especially when including
> OOP this is a book that needs to be avoided. It is not clear if Graham
> only hates object oriented programming - there is quite some evidence
> for that elsewhere - or actually does not understand it. In the end it
> does not matter. Common Lisp has a very powerful object system (CLOS).
> If you are planing to write a modern application making use of OO and
> are not just planning to walk down memory lane then look elsewhere.
>
> Alexander Repenning, University of Colorado

Also keep in mind Paul Graham is a lisper who sold his Lisp company
for ~us$50,000,000 to yahoo.
I am not sure CLOS using company did.
http://harmful.cat-v.org/software/OO_programming/