Hello
Is it possible make the following code shorter
(e.g. avoid SETF) in some way ?
(defun parse-session (line)
(declare (type string line))
(let ((a (pregexp-match
<skipped>
line)))
(assert a (line) "'~A': Bad format." line)
(let ((s (make-session)))
(destructuring-bind (login tty connect date start end elapsed)
(cdr a)
(setf (session-login s) login)
(setf (session-tty s) tty)
(setf (session-connect s) connect)
(setf (session-date s) (parse-time date :error-on-mismatch t))
(setf (session-start s) (parse-time3 start))
(setf (session-end s) (parse-time3 end))
(setf (session-elapsed s) (parse-time3 elapsed)))
s)))
Where SESSION defined with DEFSTRUCT with appropriate fields.
PREGEXP-MATN returns list of strings, where each string corresponds
to matched part of the line.
Thanks
--
Vladimir Zolotych ······@eurocom.od.ua
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
> Hello
>
> Is it possible make the following code shorter
> (e.g. avoid SETF) in some way ?
> ...
Try this (deduced from recent thread on apply usage :):
> (defun parse-session (line)
> (declare (type string line))
> (let ((a (pregexp-match
> <skipped>
> line)))
> (assert a (line) "'~A': Bad format." line)
(apply #'make-session
(mapcan #'list
'(:login :tty :connect :date :start :end :elapsed)
(cdr a)))
> ))
Janis Dzerins
--
If million people say a stupid thing it's still a stupid thing.
Janis Dzerins <·····@latnet.lv> writes:
> "Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
>
> > Hello
> >
> > Is it possible make the following code shorter
> > (e.g. avoid SETF) in some way ?
> > ...
>
> Try this (deduced from recent thread on apply usage :):
>
> > (defun parse-session (line)
> > (declare (type string line))
> > (let ((a (pregexp-match
> > <skipped>
> > line)))
> > (assert a (line) "'~A': Bad format." line)
>
> (apply #'make-session
> (mapcan #'list
> '(:login :tty :connect :date :start :end :elapsed)
> (cdr a)))
>
> > ))
Bad habit to post in haste. And to followup my own post. But I only
now realized that I did not read all the body of parse-session (just
first 3 setf's) and that my version applies only if data in (cdr a)
does not need any processing before storing into the session
structure. And this is was not such a case.
Janis Dzerins
--
If million people say a stupid thing it's still a stupid thing.
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
> Hello
>
> Is it possible make the following code shorter
> (e.g. avoid SETF) in some way ?
>
> (defun parse-session (line)
> (declare (type string line))
> (let ((a (pregexp-match
> <skipped>
> line)))
> (assert a (line) "'~A': Bad format." line)
> (let ((s (make-session)))
> (destructuring-bind (login tty connect date start end elapsed)
> (cdr a)
> (setf (session-login s) login)
> (setf (session-tty s) tty)
> (setf (session-connect s) connect)
> (setf (session-date s) (parse-time date :error-on-mismatch t))
> (setf (session-start s) (parse-time3 start))
> (setf (session-end s) (parse-time3 end))
> (setf (session-elapsed s) (parse-time3 elapsed)))
> s)))
>
> Where SESSION defined with DEFSTRUCT with appropriate fields.
> PREGEXP-MATN returns list of strings, where each string corresponds
> to matched part of the line.
>
Then why not do
(defun parse-session (line)
(declare (type string line))
(let ((a (pregexp-match
<skipped>
line)))
(assert a (line) "'~A': Bad format." line)
(destructuring-bind (login tty connect date start end elapsed)
(rest a)
(make-session :login login
:tty tty
:connect connect
:date (parse-time date :error-on-mismatch t)
:start (parse-time3 start)
:end (parse-time3 end)
:elapsed (parse-time3 elapsed)))))
?
Cheers
--
Marco Antoniotti =============================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://galt.mrl.nyu.edu/valis
Like DNA, such a language [Lisp] does not go out of style.
Paul Graham, ANSI Common Lisp
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
> (defun parse-session (line)
> (declare (type string line))
> (let ((a (pregexp-match
> <skipped>
> line)))
> (assert a (line) "'~A': Bad format." line)
> (let ((s (make-session)))
> (destructuring-bind (login tty connect date start end elapsed)
> (cdr a)
> (setf (session-login s) login)
> (setf (session-tty s) tty)
> (setf (session-connect s) connect)
> (setf (session-date s) (parse-time date :error-on-mismatch t))
> (setf (session-start s) (parse-time3 start))
> (setf (session-end s) (parse-time3 end))
> (setf (session-elapsed s) (parse-time3 elapsed)))
> s)))
>
I think this is really fine -- it's kind of tedious, but sometimes
things just are. I'd personally use the multiple-argument SETF
thing, so you say
(setf (session-login s) login
... ...)
Five years ago I would have stressed about how ugly this was and tried
to invent some clever cleaner version of it, but I don't think I would
any more. What I would do, if I did the make-object, destructure,
set-slots bit a lot would be to write a function to do just that, but
myt guess is that you only call it from one place, so there's no real
virtue in it.
--tim
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
> Is it possible make the following code shorter (e.g. avoid SETF) in
> some way ?
> (let ((s (make-session)))
> (destructuring-bind (login tty connect date start end elapsed)
> (cdr a)
> (setf (session-login s) login)
> ....
I may be missing some point here, but can't you do
(destructuring-bind (login tty connect date start end elapsed)
(cdr a)
(make-session :login login :tty tty ...))
--
Frode Vatvedt Fjeld
In article <················@naggum.net>, Erik Naggum <····@naggum.net> wrote:
> Frankly, I don't see the point in stuffing this in a structure, but
> that's probably immaterial.
A solution that makes creating the structure from that list simple, but
still provides the nice accessors, would be to define the structure with
the :TYPE LIST option. So the list would already be in the format that the
accessors expect -- it wouldn't be necessary to call a constructor at all.
--
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Erik Naggum wrote:
>
> ......How big is the final regexp that is _correct_?
"^>\\s+([-_\\w]+)\\s+(\\S+)\\s+(.*?)\\s+(\\w+\\s+\\w+\\s+\\d+\\s+\\d+)\\s+(\\S+)[-\\s]+(\\S+)\\s+\\((\\S+)\\)$"
> It would probably be much faster for both you and the machine to write up
> a real parser,
Unfortunately I know almost nothing about writing such things.
* (time (alt-x "alt.orig" "alt.09"))
........
Evaluation took:
9.02 seconds of real time
7.54 seconds of user run time
0.85 seconds of system run time
[Run times include 2.38 seconds GC run time]
46 page faults and
60237320 bytes consed.
$ wc -l alt.orig
1749 alt.orig
alt-x calls PARSE-SESSION, do some things wiht SESSION
object, then prints the resulted object. Each line in a file
represents an SESSION object.
--
Vladimir Zolotych ······@eurocom.od.ua
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
> Erik Naggum wrote:
> >
> > ......How big is the final regexp that is _correct_?
>
> "^>\\s+([-_\\w]+)\\s+(\\S+)\\s+(.*?)\\s+(\\w+\\s+\\w+\\s+\\d+\\s+\\d+)\\s+(\\S+)[-\\s]+(\\S+)\\s+\\((\\S+)\\)$"
>
> > It would probably be much faster for both you and the machine to write up
> > a real parser,
>
> Unfortunately I know almost nothing about writing such things.
Check out Henry Baker's paper ``Pragmatic Parsing in Common Lisp''
His web site was down for a while, but there seems to be a mirror at
ftp://samaris.tunes.org/pub/food/papers/people/Henry.Baker/hbaker/
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
Joe Marshall <···@content-integrity.com> wrote:
+---------------
| Check out Henry Baker's paper ``Pragmatic Parsing in Common Lisp''
| His web site was down for a while, but there seems to be a mirror at
| ftp://samaris.tunes.org/pub/food/papers/people/Henry.Baker/hbaker/
+---------------
There's also a mirror at <URL:http://linux.rice.edu/~rahul/hbaker/home.html>
-Rob
-----
Rob Warnock, 31-2-510 ····@sgi.com
SGI Network Engineering <URL:http://reality.sgi.com/rpw3/>
1600 Amphitheatre Pkwy. Phone: 650-933-1673
Mountain View, CA 94043 PP-ASEL-IA
Erik Naggum wrote:
>
> ....you should just try to do this with real code
> instead of regexp components. .....
I'll try to write parser.
--
Vladimir Zolotych ······@eurocom.od.ua
"Vladimir V. Zolotych" <······@eurocom.od.ua> writes:
> Erik Naggum wrote:
> >
> > ....you should just try to do this with real code
> > instead of regexp components. .....
>
> I'll try to write parser.
I first saw how simple that is while reading html parser code from
Franz. All you need is a Finite State Automaton, which is really easy
to make. You can find link to it here: http://opensource.franz.com/
Janis Dzerins
--
If million people say a stupid thing it's still a stupid thing.
"Vladimir V. Zolotych" wrote:
>
> Erik Naggum wrote:
> >
> > ....you should just try to do this with real code
> > instead of regexp components. .....
I've learn the things more closely.
1) Regexps isn't necessary for this particular case.
(The input data are machine generated and have strict
format except few fields.)
2) I've rewrite code without regexps.
With regexp
Evaluation took:
9.27 seconds of real time
7.43 seconds of user run time
1.04 seconds of system run time
[Run times include 2.39 seconds GC run time]
71 page faults and
60230568 bytes consed.
W/o regexp (real code)
Evaluation took:
5.31 seconds of real time
4.34 seconds of user run time
0.42 seconds of system run time
[Run times include 1.04 seconds GC run time]
26 page faults and
29273560 bytes consed.
My code is rather crude. The results would differ
more when my knowledge of the Lisp improved.
--
Vladimir Zolotych ······@eurocom.od.ua
Erik Naggum <····@naggum.net> writes:
> * "Vladimir V. Zolotych" <······@eurocom.od.ua>
> > "^>\\s+([-_\\w]+)\\s+(\\S+)\\s+(.*?)\\s+(\\w+\\s+\\w+\\s+\\d+\\s+\\d+)\\s+(\\S+)[-\\s]+(\\S+)\\s+\\((\\S+)\\)$"
>If this is a/the _correct_ regexp, your date and time parsing
>functions must make good use of conditions and your code good use of
>handlers for exceptional conditions... I think you dramatically
>underestimate what a correct regexp needs to match and fail to match.
>Most regexp users do.
> > Unfortunately I know almost nothing about writing such things.
>I actually doubt that. You know enough about regexps to use
>character classes, there is no backtracking and no _searching_ in
>your regexp that I can see, and you end up only selecting a few
>fields separated by simple delimiters.
Ah, but how to do this sort of thing in a reasonably "idiomatic"
Lisp-based way is the rub.
There's a reasonably rich literature out there for the YACC/LALR/
"generate parser and connect to C" approach. There's starting to be a
fair bit of stuff on parsing XML and attaching code to parse trees
using DOM.
It seems harder to find the equivalent sort of literature for Lisp.
Henry Baker's paper seems pretty good; what is missing is the "general
literature" side of it.
PAIP codes up a full-scale Othello playing program; what would be nice
to see would be:
-> An implementation of an "opening book" scheme for chess (or
Othello) where the point of the exercise is to generate possible
responses, and then serialize them and write them out for future
reference.
This would _probably_ be best done by writing the data structures
out as Lispy s-expressions, perhaps resulting in using a custom
reader, but compactness might dictate a denser representation,
mandating a "real parser."
Or, [and I certainly stand to be corrected on this,] it might be
more efficient to read in strings and transform them into symbols
only as needed, rather than having CL generate interned symbols
with all the attendant data and work attached to that...
-> Tools for parsing mail and/or news postings, perhaps transforming
them into an associative list.
I recently had call for this for doing some statistical analysis on
mail messages.
CLTL2 alludes to the notion that one might customize the reader into a
customized parser; seeing some interesting examples worked out would
be _really useful_.
--
(reverse (concatenate 'string ····················@" "454aa"))
http://vip.hyperusa.com/~cbbrowne/lisp.html
The hypochondriac's epitaph: "NOW will you believe me?"
Erik Naggum <····@naggum.net> writes:
> * ········@hex.net
> > -> Tools for parsing mail and/or news postings, perhaps transforming
> > them into an associative list.
> >
> > I recently had call for this for doing some statistical analysis on
> > mail messages.
>
> GNU Emacs users may find a shot at this in lisp/mail/mailheader.el.
>
> > CLTL2 alludes to the notion that one might customize the reader into a
> > customized parser; seeing some interesting examples worked out would
> > be _really useful_.
Since I "grew up" at NYU I had my share of Ada and of the more
obscure, yet very interesting language SETL. SETL is a very high
level language that uses "sets" and "tuples" as its primary "objects
of discourse". The development of SETL spearheaded the concurrent
development of many interesting algorithms for set manipulation.
Let me show an example of what SETL can do. Then I will go on and
talk about the reason I still use Common Lisp instead. :)
A SETL program to compute the primes up to
==============================================================================
-- primes.setl -- Prints the primes from 3 to 100.
program primes;
print([n in [3, 5 .. 100] | not (exists m in [3, 5 .. (floor(sqrt(float(n))) + 2) min (n - 1)] | n mod m = 0)]);
end test;
-- end of file -- primes.setl --
==============================================================================
This is a one-liner where most of the features of SETL are shown.
Essentially the "tuple-constructor"
[ <expression> | <iterator and filtering condition> ]
Regular sets are built using '{' '}' instead.
Apart from some of the underlying machinery to efficiently manipulate
sets (essentially hash tables), what is most useful in SETL is that
its "notation" is very mathematically oreinted (R. Gabriel would say
"too much") and that many useful algorithms are more easily expressed
using this set notation.
Now, sitting where I sit, I get in regular "poors' wars" with the SETL
people here. :) So I finally decided to rewrite the previous program
in Common Lisp. Here it is
==============================================================================
;;; primes.lisp -- A function that prints the primes from 3 to MAX.
(in-package "SETL-USER")
(defun primes (max)
[n in (range 3 max 2) / (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2) / (= (mod n m) 0)))])
;;; end of file -- primes.lisp --
==============================================================================
Aparto from the change in notation for "ranges", the program looks
pretty much the same as the original. The function produces a list by
expanding the form in a series of nested loops. The whole of SETL
notation is captured in the 300 lines of CL macrology and macro character
manipulations which make up the SETL and SETL-USER packages.
I rest my case :)
Cheers
--
Marco Antoniotti =============================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://galt.mrl.nyu.edu/valis
Like DNA, such a language [Lisp] does not go out of style.
Paul Graham, ANSI Common Lisp
Marco Antoniotti <·······@cs.nyu.edu> writes:
>
> Now, sitting where I sit, I get in regular "poors' wars" with the SETL
> people here. :) So I finally decided to rewrite the previous program
> in Common Lisp. Here it is
>
> ==============================================================================
> ;;; primes.lisp -- A function that prints the primes from 3 to MAX.
>
> (in-package "SETL-USER")
>
> (defun primes (max)
> [n in (range 3 max 2) / (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2) / (= (mod n m) 0)))])
>
> ;;; end of file -- primes.lisp --
> ==============================================================================
>
> Aparto from the change in notation for "ranges", the program looks
> pretty much the same as the original. The function produces a list by
> expanding the form in a series of nested loops. The whole of SETL
> notation is captured in the 300 lines of CL macrology and macro character
> manipulations which make up the SETL and SETL-USER packages.
>
> I rest my case :)
>
You could show them the CL way with SERIES.
(defun primes (max)
(choose-if #'(lambda (n)
(collect-and (mapping ((x (scan-range :from 3
:by 2
:upto (+ 1 (isqrt n)))))
(not (zerop (mod n x))))))
(scan-range :from 3 :by 2 :upto max))
--
Lieven Marchand <···@wyrd.be>
Gla�r ok reifr skyli gumna hverr, unz sinn b��r bana.
Lieven Marchand <···@wyrd.be> writes:
> Marco Antoniotti <·······@cs.nyu.edu> writes:
>
> >
> > Now, sitting where I sit, I get in regular "poors' wars" with the SETL
> > people here. :) So I finally decided to rewrite the previous program
> > in Common Lisp. Here it is
> >
> > ==============================================================================
> > ;;; primes.lisp -- A function that prints the primes from 3 to MAX.
> >
> > (in-package "SETL-USER")
> >
> > (defun primes (max)
> > [n in (range 3 max 2) / (not (exist m in (range 3 (min (1- n) (+ 2 (sqrt n))) 2) / (= (mod n m) 0)))])
> >
> > ;;; end of file -- primes.lisp --
> > ==============================================================================
> >
> > Aparto from the change in notation for "ranges", the program looks
> > pretty much the same as the original. The function produces a list by
> > expanding the form in a series of nested loops. The whole of SETL
> > notation is captured in the 300 lines of CL macrology and macro character
> > manipulations which make up the SETL and SETL-USER packages.
> >
> > I rest my case :)
> >
>
> You could show them the CL way with SERIES.
>
> (defun primes (max)
> (choose-if #'(lambda (n)
> (collect-and (mapping ((x (scan-range :from 3
> :by 2
> :upto (+ 1 (isqrt n)))))
> (not (zerop (mod n x))))))
> (scan-range :from 3 :by 2 :upto max))
Yes. However that was not my intent :) SERIES do not use the sets and
tuple notation. E.g. in the SETL-USER package.
SETL-USER[1]> (== {1 2 {3 4}} {1 {4 3} 2})
T
SERIES may be a good implementation tool for
the guts of a real CL SETL extension, but time is a killer :)
Cheers
--
Marco Antoniotti =============================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://galt.mrl.nyu.edu/valis
Like DNA, such a language [Lisp] does not go out of style.
Paul Graham, ANSI Common Lisp