From: fft1976 Date: 2009-08-03T13:05:05+09:00 Subject: Re: RUBY vs COMMON LISP On Aug 1, 10:26 pm, fft1976 wrote: > On Aug 1, 8:55 pm, p...@informatimago.com (Pascal J. Bourguignon) > wrote: > > > w_a_x_man writes: > > > On Aug 1, 9:32 am, Bata wrote: > > >> Use (cl-ppcre:split " " string-name) to get a list of the different > > >> words in the string. > > > >> Check out the cl-ppcre package's functionality, its quite amazing. > > > > Ruby: > > > > string_name.split > > > Don't you realize how ugly Ruby syntax is? > > > Here is in 150 lines of lisp, a simplified lisp reader that is able to > > read all the lisp syntax needed to write it. > > > Try to parse Ruby syntax in Ruby and see how useless a language it is. > > I much prefer CL to Ruby, but this argument is useless. How many lines > of code do you need to read Brainfuck in Brainfuck? > > (If you wanted to show the inferiority of Ruby to Common Lisp, the > shootout makes a much more compelling argument) > > > -----(simple-reader.lisp)------------------------------------------------------ > > ;;;; -*- mode:lisp;coding:utf-8 -*- > > ;;;;************************************************************************** > > ;;;;FILE:               simple-reader.lisp > > ;;;;LANGUAGE:           Common-Lisp > > ;;;;SYSTEM:             Common-Lisp > > ;;;;USER-INTERFACE:     NONE > > ;;;;DESCRIPTION > > ;;;;     > > ;;;;    Simple Lisp Reader. > > ;;;;    This reader implements a subset of the Common Lisp reader, > > ;;;;    but it should be extensible enough to be able to read most > > ;;;;    of Common Lisp syntax. > > ;;;;    Not supported: the preserving whitespace flag, the recursive flag > > ;;;;    (therefore no references), character traits (escapes). > > ;;;;    Otherwise, reader macros and dispatching  macros can be written > > ;;;;    to read most of CL syntax. > > ;;;;    Only integers, keywords and symbol tokens are parsed (a more > > ;;;;    sophisticated parse-token function can be configured). > > ;;;;     > > ;;;;AUTHORS > > ;;;;     Pascal J. Bourguignon > > ;;;;MODIFICATIONS > > ;;;;    2009-08-02 Created. > > ;;;;BUGS > > ;;;;LEGAL > > ;;;;    GPL > > ;;;;     > > ;;;;    Copyright Pascal J. Bourguignon 2009 - 2009 > > ;;;;     > > ;;;;    This program is free software; you can redistribute it and/or > > ;;;;    modify it under the terms of the GNU General Public License > > ;;;;    as published by the Free Software Foundation; either version > > ;;;;    2 of the License, or (at your option) any later version. > > ;;;;     > > ;;;;    This program is distributed in the hope that it will be > > ;;;;    useful, but WITHOUT ANY WARRANTY; without even the implied > > ;;;;    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR > > ;;;;    PURPOSE.  See the GNU General Public License for more details. > > ;;;;     > > ;;;;    You should have received a copy of the GNU General Public > > ;;;;    License along with this program; if not, write to the Free > > ;;;;    Software Foundation, Inc., 59 Temple Place, Suite 330, > > ;;;;    Boston, MA 02111-1307 USA > > ;;;;************************************************************************** > > > (defstruct character-description > >   non-terminating-p > >   reader-macro > >   dispatching-macro-characters) > > > (defstruct (simple-readtable (:constructor %make-simple-readtable)) > >   (default-character-description (make-character-description)) > >   (macro-characters (make-hash-table)) > >   (parse-token (function identity)) > >   (whitespaces  #(#\space #\tab #\newline #\linefeed #\return #\page #\vt))) > > > (defun simple-get-macro-character (character &optional (readtable *simple-readtable*)) > >   (let ((description (or (gethash character (simple-readtable-macro-characters readtable)) > >                          (simple-readtable-default-character-description readtable)))) > >     (values (character-description-reader-macro description) > >             (character-description-non-terminating-p description)))) > > > (defun simple-set-macro-character (character function &optional non-terminating-p > >                                    (readtable *simple-readtable*)) > >   (setf (gethash character (simple-readtable-macro-characters readtable)) > >         (make-character-description :non-terminating-p non-terminating-p > >                                     :reader-macro function)) > >   't) > > > (defun simple-get-dispatch-macro-character (character subchar > >                                             &optional (readtable *simple-readtable*)) > >   (setf subchar (char-upcase subchar)) > >   (let ((description (gethash character (simple-readtable-macro-characters readtable)))) > >     (unless (and description > >                  (character-description-dispatching-macro-characters description)) > >       (error "#\\~C is not a dispatching macro character" character)) > >     (gethash subchar (character-description-dispatching-macro-characters description)))) > > > (defun simple-set-dispatch-macro-character (character subchar function > >                                             &optional (readtable *simple-readtable*)) > >   (setf subchar (char-upcase subchar)) > >   (let ((description (gethash character (simple-readtable-macro-characters readtable)))) > >     (when (or (null description) > >               (null (character-description-dispatching-macro-characters description))) > >       (setf (gethash character (simple-readtable-macro-characters readtable)) > >             (make-character-description :non-terminating-p t > >                                         :reader-macro (function simple-reader-dispatching-macro) > >                                         :dispatching-macro-characters (make-hash-table))))) > >   (let ((description (gethash character (simple-readtable-macro-characters readtable)))) > >     (setf (gethash subchar  (character-description-dispatching-macro-characters description)) > >           function)) > >   't) > > > (defun simple-reader-dispatching-macro (character stream) > >   (let* ((subchar  (read-char stream)) > >          (macro    (simple-get-dispatch-macro-character character subchar))) > >     (assert macro () "~C~C is not a dispatching macro" character subchar) > >     (funcall macro character subchar stream))) > > > (defun simple-read-vector-dmacro (char subchar stream) > >   (declare (ignore char)) > >   (let ((contents (simple-read-list-macro subchar stream))) > >     (coerce contents 'vector))) > > > (defvar *character-names* (list (cons "SPACE"    (code-char 32)) > >                                 (cons "NEWLINE"  (code-char 10)) > >                                 (cons "RETURN"   (code-char 13)) > >                                 (cons "PAGE"     (code-char 12)) > >                                 (cons "VT"       (code-char 11)) > >                                 (cons "LINEFEED" (code-char 10)) > >                                 (cons "TAB"      (code-char 9))) > >   "An a-list mapping character names to characters.") > > > (defun simple-read-character-dmacro (char subchar stream) > >   (declare (ignore char subchar)) > >   (let ((object (read-char stream))) > >     (if (alpha-char-p (peek-char nil stream nil #\space)) > >         (loop > >            :with buffer = (make-array 8 :element-type 'character :adjustable t :fill-pointer 1 > >                                       :initial-element object) > >            :do (vector-push-extend (read-char stream) buffer) > >            :while (alpha-char-p (peek-char nil stream nil #\space)) > >            :finally (return (or (cdr (assoc (string-upcase buffer) *character-names* > >                                             :test (function string=))) > >                                 (aref buffer 0)))) > >         object))) > > > (defun simple-parse-token (buffer) > >   ;; We only deal with integers, keywords and symbols. > >   (or (ignore-errors (parse-integer buffer :junk-allowed nil)) > >       (if (char= #\: (aref buffer 0)) > >           (intern (string-upcase (subseq buffer (position #\: buffer :test (function char/=)))) > >                   "KEYWORD") > >           ;; We don't deal with other packages in this simple parse-token. > >           (intern (string-upcase buffer))))) > > > (defun simple-read-quote-macro (character stream) > >   (declare (ignore character)) > >   (list 'quote (simple-read stream))) > > > (defun simple-read-list-macro (character stream) > >   (declare (ignore character)) > >   (loop > >      :until (char= #\) (peek-char t stream)) > >      :collect (simple-read stream) > >      :finally (read-char stream))) > > > (defun simple-read-string-macro (character stream) > >   (handler-case > >       (loop > >          :with buffer = (make-array 8 :element-type 'character :adjustable t :fill-pointer 0) > >          :for ch = (read-char stream) > >          :until (char= character ch) > >          :do (vector-push-extend (if (char= #\\ ch) > >                                      (read-char stream) > >                                      ch) > >                                  buffer) > >          :finally (return (copy-seq buffer))))) > > > (defun simple-read-comment-macro (character stream) > >   (declare (ignore character)) > >   (read-line stream) > >   (values)) > > > (defun make-simple-readtable () > >   (let ((readtable > >          (%make-simple-readtable > >           :default-character-description (make-character-description :non-terminating-p t) > >           :parse-token (function simple-parse-token)))) > >     (simple-set-macro-character #\( (function simple-read-list-macro)     nil readtable) > >     (simple-set-macro-character #\) nil                                   nil readtable) > >     (simple-set-macro-character #\' (function simple-read-quote-macro)    nil readtable) > >     (simple-set-macro-character #\" (function simple-read-string-macro)   nil readtable) > >     (simple-set-macro-character #\; (function simple-read-comment-macro)  nil readtable) > >     (simple-set-dispatch-macro-character #\# #\\ (function simple-read-character-dmacro) readtable) > >     (simple-set-dispatch-macro-character #\# #\( (function simple-read-vector-dmacro)    readtable) > >     readtable)) > > > (defparameter *simple-readtable* (make-simple-readtable)) > > > (defun simple-read (&optional (stream *standard-input*) (eof-error-p t) eof-value) > >   (peek-char t stream nil) > >   (let ((char (read-char stream nil nil))) > >     (cond > >       (char > >        (multiple-value-bind (macro non-terminating-p) (simple-get-macro-character char) > >          (if macro > >              (let ((object (multiple-value-list (funcall macro char stream)))) > >                (if object (first object) (simple-read stream eof-error-p eof-value)))         > >              (loop > >                 :with buffer = (make-array 8 :element-type 'character :adjustable t :fill-pointer 0) > >                 :for ch = (peek-char nil stream nil #\space) > >                 :initially (vector-push-extend char buffer) > >                 :until (or (position ch (simple-readtable-whitespaces *simple-readtable*)) > >                            (not (nth-value 1 (simple-get-macro-character ch)))) > >                 :do (vector-push-extend (read-char stream eof-error-p eof-value) buffer) > >                 :finally (return (funcall (simple-readtable-parse-token *simple-readtable*) > >                                           buffer)))))) > >       (eof-error-p (error 'end-of-file :stream stream)) > >       (t eof-value)))) > > > -------------------------------------------------------------------------------- > > > (with-open-file (input "simple-reader.lisp") > >   (loop > >      :for sexp = (simple-read input nil input) > >      :until (eq sexp input) > >      :do (pprint sexp) (terpri))) > > > -- > > __Pascal Bourguignon__ > > By the way, here is in 1 line of BF, a complete BF reader that is able to read all the BF syntax needed to write it: ,+[-.,+] Here's how to try it: $ sudo apt-get install bf $ cat > reader.bf ,+[-.,+] $ bf reader.bf < reader.bf Your 150 lines don't look very impressive now, do they? Ruby < Lisp <<< BF!