From: Slobodan Blazeski
Subject: Do I need pattern matching in here?
Date: 
Message-ID: <ef426599-4695-45b9-ad95-f6b6ed00d353@m77g2000hsc.googlegroups.com>
I need a function render that takes as arguments name (always a
string), value (various types) and rendering-instructions.Something
like this:
(render "driver" "Kimi Raikonen" '((:italic t)))
<p>Kimi Raikonen</p>
(render "driver" "Kimi Raikonen" '((:italic t)))
<p><i>Kimi Raikonen</i></p>
(render "driver" "Kimi Raikonen" '((:underlined t) (:bold t)))
<p><u><b>Kimi Raikonen</b></u></p>

How would you write such thing, considering the rendering-instriction
varies ?
Also I would like later to be able to add new description clauses into
rendering-instructions without breaking the previous?

thanks
Slobodan

From: Alessio
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <864c4774-4043-4a49-b0ef-66f26ef12555@n20g2000hsh.googlegroups.com>
On Jan 7, 2:49 pm, Slobodan Blazeski <·················@gmail.com>
wrote:
> I need a function render that takes as arguments name (always a
> string), value (various types) and rendering-instructions.Something
> like this:

[snip]

> How would you write such thing, considering the rendering-instriction
> varies ?
> Also I would like later to be able to add new description clauses into
> rendering-instructions without breaking the previous?
>

hmm one very naive solution which comes to my mind is simply using
keyword arguments, e.g.

(defun render (type value &key italic underlined &allow-other-
keys) ...)

later if you want to add e.g. bold, you just modify the function's
lambda list (and code of course) and recompile it. This should work
most of the time, except maybe if you do

(setq x #'render)
...recompile...
(funcall x ...) ;I think this still calls the old render... not sure
though!

...or, if you wanted a more dynamic approach, you could store in a
global hash table mappings from render instruction to a function which
implements such instruction e.g. (dummy example)

:italic -> (lambda (contents &rest rendering-params) (with-html (:i
(str contents))))

or have a method specialized on (eql <instruction-name>) -

(defmethod rendering-instruction ((instruction (eql :italic)) contents
&rest rendering-params)
  (with-html (:i (str contents))))

and then have render call those functions... so if you
have :italic :underlined you would (funcall (gethash :italic *hash-
table*) (funcall (gethash :underlined *hash-table*) value))

or (rendering-instruction :italic (rendering-instruction :underlined
value)) if you have methods

...or something like that... (warning: highly untested!). BUT this is
harder than it seems since you'll probably have to take into account
html validation rules e.g. you can't put a <p></p> inside a <i></i>
for example... so it might be very complicated, depending on rendering
instructions... hope I've been clear enough!!

cheers
Alessio
From: Øyvin Halfdan Thuv
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <slrnfo4gt9.tu8.oyvinht@decibel.pvv.ntnu.no>
On 2008-01-07, Slobodan Blazeski <·················@gmail.com> wrote:
> I need a function render that takes as arguments name (always a
> string), value (various types) and rendering-instructions.Something
> like this:
> (render "driver" "Kimi Raikonen" '((:italic t)))
><p>Kimi Raikonen</p>
> (render "driver" "Kimi Raikonen" '((:italic t)))
><p><i>Kimi Raikonen</i></p>
> (render "driver" "Kimi Raikonen" '((:underlined t) (:bold t)))
><p><u><b>Kimi Raikonen</b></u></p>
>
> How would you write such thing, considering the rendering-instriction
> varies ?
> Also I would like later to be able to add new description clauses into
> rendering-instructions without breaking the previous?

Hi.

There is more than one way to do it :) 

You could use generic functions to dispatch on different presentation types...
You could also use optional or keyword arguments (as noted by others) or use
GETF with your plist if you want to do thing even more manually. 

However, since your values are always T or NIL (it seems) why not just pass in
a list of things you want to add? Then you can just traverse the list
recursively and replace every list element by the corresponding XML-element to
encapsulate whatever further recursion will produce? E.g.:

(defparameter *dictionary* (list :underline "u" :bold "b" :itallic "i"))

(defun render (name options-left)
  (if options-left
   (let ((option (getf *dictionary* (car options-left))))
    (format nil "<~A>~A</~A>" option (render name (cdr options-left)) option))
   (if name name "")))

Then:

CL-USER> (render "Kimi" '(:underline :bold))
"<u><b>Kimi</b></u>"
CL-USER> 

-- 
Oyvin
From: Slobodan Blazeski
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <10f3ec8e-96e9-4133-90e7-749965675ca5@s8g2000prg.googlegroups.com>
Here's explanation what I want to do http://paste.lisp.org/display/53757

Slobodan
From: Alessio
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <0eef19f9-72cb-44b5-8493-63198b88b0c0@s8g2000prg.googlegroups.com>
I annotated your paste with the solution I was thinking of. I forgot
to make explicit that adding or removing a rendering rule is just a
matter of adding/removing appropriate methods. Is this what you want?
Or are your requirements more complex? (i.e. I have assumed that rules
are orthogonal to each other, if this doesn't hold my solution isn't
valid!)

A.

On 7 Gen, 16:54, Slobodan Blazeski <·················@gmail.com>
wrote:
> Here's explanation what I want to dohttp://paste.lisp.org/display/53757
>
> Slobodan
From: Slobodan Blazeski
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <97c83f6f-3a0d-4c27-b2b9-82b8634b424e@h11g2000prf.googlegroups.com>
Hi Alessio

Thank you for your efforts but my needs are far more complex.
1st I don't know in advance all the keywords nor rules
2nd even if I do know I want to leave option to add additional
keywords and/or rules later
So this should be pefectly valid:
(render "office-mail" ·····@bobi.com"
  '((:underlined t) (:present-as :picture) (:italic t)
    (:font :arial)  (:font-size 14) (:add-trailing-white-space 2)))
Assuminng programmer added
(add-render-rule
   '((:font t) (:font-size t) (:italic italic)
     (:underlined underlined) (:present-as :picture) (:add-trailing-
white-space number))
   #'render-email-link-in-picture)

and defined corresponding function
(defun render-email-link-in-picture (...

cheers
Slobodan
From: Alessio
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <525417d7-d7e3-43be-866b-239f1765c097@j20g2000hsi.googlegroups.com>
Hi Slobodan,

I still think that

1st you don't have to - because
2nd you can just define a new method when you need a new rule

I also see you are also specifying parameters for the various rules,
this would require to also pass such additional parameter(s) to the
method I called raw-render...

...but wait, now I think I see what you mean: what happens if
combining multiple rules is not the same as applying them one after
the other? e.g. (:underline t) (:present-as :picture) probably does
not mean, first draw it as a picture then wrap it in a <u></u>
block :)

So, let's rationalize a bit:

a. we have a (possibly expandable) set of options.
b. we want to map a given subset of these options to some rendering
code.
c. we want to be able to add a new option to a subset X, and the
corresponding function, WITHOUT necessarily touching the code for
subset X.

So yes, I think you need some form of pattern matching. BUT: patterns
should cover any possible case - for *every* valid combination of the
rules, you'd have to provide a function for its rendering... or the
system won't know how to render, e.g., an underlined email link
written right-to-left in ancient Egyptian and presented as a png
image ;) this means, that in general you'll endure a lot of pain as
you add options since if you have defined rendering functions for all
possible combinations of parameters a, b and c, and then you add a
fourth parameter d, you'll have again to specify what happens when d
is present along with every possible combination of a, b, and c! I'd
say this is overkill if you don't somehow restrict the possible
options, e.g. decide that options are at most N, for a very small
value of N, and/or that some options are predefined and MUST always be
present. IMHO of course!

Alessio, now going to sleep ;)

On 7 Gen, 20:23, Slobodan Blazeski <·················@gmail.com>
wrote:
> Hi Alessio
>
> Thank you for your efforts but my needs are far more complex.
> 1st I don't know in advance all the keywords nor rules
> 2nd even if I do know I want to leave option to add additional
> keywords and/or rules later
> So this should be pefectly valid:
> (render "office-mail" ·····@bobi.com"
>   '((:underlined t) (:present-as :picture) (:italic t)
>     (:font :arial)  (:font-size 14) (:add-trailing-white-space 2)))
> Assuminng programmer added
> (add-render-rule
>    '((:font t) (:font-size t) (:italic italic)
>      (:underlined underlined) (:present-as :picture) (:add-trailing-
> white-space number))
>    #'render-email-link-in-picture)
>
> and defined corresponding function
> (defun render-email-link-in-picture (...
>
> cheers
> Slobodan
From: Slobodan Blazeski
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <56f4689a-9631-4c56-9113-e1c387cef8ca@v46g2000hsv.googlegroups.com>
On Jan 8, 2:07 am, Alessio <·············@gmail.com> wrote:
> Hi Slobodan,
>
> I still think that
>
> 1st you don't have to - because
> 2nd you can just define a new method when you need a new rule
Not quite let's take  this for example
(render "driver" "Kimi Raikonen" '((:underlined t) (:font 12)
(:present-as text)))
now let's disregard "driver" "Kimi Raikonen" parameters and add
new function called get-raw-render that will find defined function for
the rule
'((:underlined t) (:fond t) (:present-as text))
or return NIL, meaning deal as default rendering.
if you look more closely you'll see that :underlined & :bold are
keywords.
Assuming the set of keywords is fixed , CLOS could do my job with:
(defgeneric get-raw-render (&key underlined bold present-as))
then I could easily specify various methods.
The problem is that number of keywords is not fixed. Tommorow after I
need a new rule that isn't combination of previous keys I will have to
change generic function.
>
> I also see you are also specifying parameters for the various rules,
> this would require to also pass such additional parameter(s) to the
> method I called raw-render...
>
> ...but wait, now I think I see what you mean: what happens if
> combining multiple rules is not the same as applying them one after
> the other? e.g. (:underline t) (:present-as :picture) probably does
> not mean, first draw it as a picture then wrap it in a <u></u>
> block :)
 :underline and :present-as are not rules they are keys according to
which you find the function that does the actual rendering, ther order
is unimportant,
'((:underline t) (:present-as :picture)) <=> '( (:present-as :picture)
(:underline t))
 it's stupid to force users to memorise number of arguments. I trade
functionality for convenience
This is how the system would ideally work, for the example
(render office-mail" ·····@bobi.com" '((:present-as :picture)
(:underline t)))
1. render calls dispatcher to fund  a function that will find a
function according to rendering-instructions, if it can't find one it
returns nil and render uses default generic function.
(defun render (name value rendering-instructions)
   (let ((specialised-renderer (find-rendering-function rendering-
instructions)))
      (if (specialised-renderer
         (funcall (specialised-renderer name value)
         (default-renderer name value))
2. So the problem is how to implement find-rendering-function. The
streightforward way is
(defvar *rule-database* (make-hash-table :test #'set-equal)

(defun set-equal (set1 set2)
  (null (set-difference set1 set2))

Then adding rules would be as easy as:
(defun add-rule (keylist function)
  (setf (gethash keylist *rule-database*) function)

In our case (render office-mail" ·····@bobi.com" '((:present-
as :picture) (:underline t)))
all we need to do is define is:
(defun render-mail-as-udnerlined-picture (mail)
  (vecto-print-text-to-picture
    (underline-text (string+  "mailto:" mail)))

(add-rule '((:underline t) (:present-as :picture))
          #'render-mail-as-udnerlined-picture))

that's it.

Unfortunately only allowed keys to hash table are eq, eql, equal, or
equalp.

cheers
Slobodan
>
> So, let's rationalize a bit:
>
> a. we have a (possibly expandable) set of options.
> b. we want to map a given subset of these options to some rendering
> code.
> c. we want to be able to add a new option to a subset X, and the
> corresponding function, WITHOUT necessarily touching the code for
> subset X.
>
> So yes, I think you need some form of pattern matching. BUT: patterns
> should cover any possible case - for *every* valid combination of the
> rules, you'd have to provide a function for its rendering... or the
> system won't know how to render, e.g., an underlined email link
> written right-to-left in ancient Egyptian and presented as a png
> image ;) this means, that in general you'll endure a lot of pain as
> you add options since if you have defined rendering functions for all
> possible combinations of parameters a, b and c, and then you add a
> fourth parameter d, you'll have again to specify what happens when d
> is present along with every possible combination of a, b, and c! I'd
> say this is overkill if you don't somehow restrict the possible
> options, e.g. decide that options are at most N, for a very small
> value of N, and/or that some options are predefined and MUST always be
> present. IMHO of course!
>
> Alessio, now going to sleep ;)
>
> On 7 Gen, 20:23, Slobodan Blazeski <·················@gmail.com>
> wrote:
>
> > Hi Alessio
>
> > Thank you for your efforts but my needs are far more complex.
> > 1st I don't know in advance all the keywords nor rules
> > 2nd even if I do know I want to leave option to add additional
> > keywords and/or rules later
> > So this should be pefectly valid:
> > (render "office-mail" ·····@bobi.com"
> >   '((:underlined t) (:present-as :picture) (:italic t)
> >     (:font :arial)  (:font-size 14) (:add-trailing-white-space 2)))
> > Assuminng programmer added
> > (add-render-rule
> >    '((:font t) (:font-size t) (:italic italic)
> >      (:underlined underlined) (:present-as :picture) (:add-trailing-
> > white-space number))
> >    #'render-email-link-in-picture)
>
> > and defined corresponding function
> > (defun render-email-link-in-picture (...
>
> > cheers
> > Slobodan
From: Slobodan Blazeski
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <f3e877dc-e013-428a-a05c-8a6213b3dbc3@z17g2000hsg.googlegroups.com>
On Jan 8, 10:35 am, Slobodan Blazeski <·················@gmail.com>
wrote:
> On Jan 8, 2:07 am, Alessio <·············@gmail.com> wrote:> Hi Slobodan,
>
> > I still think that
>
> > 1st you don't have to - because
> > 2nd you can just define a new method when you need a new rule
>
> Not quite let's take  this for example
> (render "driver" "Kimi Raikonen" '((:underlined t) (:font 12)
> (:present-as text)))
> now let's disregard "driver" "Kimi Raikonen" parameters and add
> new function called get-raw-render that will find defined function for
> the rule
> '((:underlined t) (:fond t) (:present-as text))
> or return NIL, meaning deal as default rendering.
> if you look more closely you'll see that :underlined & :bold are
> keywords.
> Assuming the set of keywords is fixed , CLOS could do my job with:
> (defgeneric get-raw-render (&key underlined bold present-as))
> then I could easily specify various methods.
> The problem is that number of keywords is not fixed. Tommorow after I
> need a new rule that isn't combination of previous keys I will have to
> change generic function.
>
> > I also see you are also specifying parameters for the various rules,
> > this would require to also pass such additional parameter(s) to the
> > method I called raw-render...
>
> > ...but wait, now I think I see what you mean: what happens if
> > combining multiple rules is not the same as applying them one after
> > the other? e.g. (:underline t) (:present-as :picture) probably does
> > not mean, first draw it as a picture then wrap it in a <u></u>
> > block :)
>
>  :underline and :present-as are not rules they are keys according to
> which you find the function that does the actual rendering, ther order
> is unimportant,
> '((:underline t) (:present-as :picture)) <=> '( (:present-as :picture)
> (:underline t))
>  it's stupid to force users to memorise number of arguments. I trade
> functionality for convenience
> This is how the system would ideally work, for the example
> (render office-mail" ·····@bobi.com" '((:present-as :picture)
> (:underline t)))
> 1. render calls dispatcher to fund  a function that will find a
> function according to rendering-instructions, if it can't find one it
> returns nil and render uses default generic function.
> (defun render (name value rendering-instructions)
>    (let ((specialised-renderer (find-rendering-function rendering-
> instructions)))
>       (if (specialised-renderer
>          (funcall (specialised-renderer name value)
>          (default-renderer name value))
> 2. So the problem is how to implement find-rendering-function. The
> streightforward way is
> (defvar *rule-database* (make-hash-table :test #'set-equal)
>
> (defun set-equal (set1 set2)
>   (null (set-difference set1 set2))
>
> Then adding rules would be as easy as:
> (defun add-rule (keylist function)
>   (setf (gethash keylist *rule-database*) function)
>
> In our case (render office-mail" ·····@bobi.com" '((:present-
> as :picture) (:underline t)))
> all we need to do is define is:
> (defun render-mail-as-udnerlined-picture (mail)
>   (vecto-print-text-to-picture
>     (underline-text (string+  "mailto:" mail)))
>
> (add-rule '((:underline t) (:present-as :picture))
>           #'render-mail-as-udnerlined-picture))
>
> that's it.
>
> Unfortunately only allowed keys to hash table are eq, eql, equal, or
> equalp.
>
> cheers
> Slobodan

Seems that you are right, if I set the order or predicate unimportant
I will have to manually add each rule, that's stupid. This problem is
killing me :)

Slobodan
>
>
>
> > So, let's rationalize a bit:
>
> > a. we have a (possibly expandable) set of options.
> > b. we want to map a given subset of these options to some rendering
> > code.
> > c. we want to be able to add a new option to a subset X, and the
> > corresponding function, WITHOUT necessarily touching the code for
> > subset X.
>
> > So yes, I think you need some form of pattern matching. BUT: patterns
> > should cover any possible case - for *every* valid combination of the
> > rules, you'd have to provide a function for its rendering... or the
> > system won't know how to render, e.g., an underlined email link
> > written right-to-left in ancient Egyptian and presented as a png
> > image ;) this means, that in general you'll endure a lot of pain as
> > you add options since if you have defined rendering functions for all
> > possible combinations of parameters a, b and c, and then you add a
> > fourth parameter d, you'll have again to specify what happens when d
> > is present along with every possible combination of a, b, and c! I'd
> > say this is overkill if you don't somehow restrict the possible
> > options, e.g. decide that options are at most N, for a very small
> > value of N, and/or that some options are predefined and MUST always be
> > present. IMHO of course!
>
> > Alessio, now going to sleep ;)
>
> > On 7 Gen, 20:23, Slobodan Blazeski <·················@gmail.com>
> > wrote:
>
> > > Hi Alessio
>
> > > Thank you for your efforts but my needs are far more complex.
> > > 1st I don't know in advance all the keywords nor rules
> > > 2nd even if I do know I want to leave option to add additional
> > > keywords and/or rules later
> > > So this should be pefectly valid:
> > > (render "office-mail" ·····@bobi.com"
> > >   '((:underlined t) (:present-as :picture) (:italic t)
> > >     (:font :arial)  (:font-size 14) (:add-trailing-white-space 2)))
> > > Assuminng programmer added
> > > (add-render-rule
> > >    '((:font t) (:font-size t) (:italic italic)
> > >      (:underlined underlined) (:present-as :picture) (:add-trailing-
> > > white-space number))
> > >    #'render-email-link-in-picture)
>
> > > and defined corresponding function
> > > (defun render-email-link-in-picture (...
>
> > > cheers
> > > Slobodan
From: Alessio
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <df73d7d5-edef-4d03-9798-038b9d045e19@r60g2000hsc.googlegroups.com>
I got it! I got it!!! (well maybe). http://paste.lisp.org/display/53757#2

Lemme think what you think of it. I promise I won't ever think about
this problem again :D yeah, like that was true... stuying is no way as
fun as this...

Cheers!
A.
From: Slobodan Blazeski
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <8e004866-198d-4699-a4be-502965537e77@41g2000hsy.googlegroups.com>
On Jan 8, 9:11 pm, Alessio <·············@gmail.com> wrote:
> I got it! I got it!!! (well maybe).http://paste.lisp.org/display/53757#2
>
> Lemme think what you think of it. I promise I won't ever think about
> this problem again :D yeah, like that was true... stuying is no way as
> fun as this...
>
> Cheers!
> A.

Nice idea, I would have to rethink meaning of the keywords order, but
the rest culd be used as starting point.

cheers
Slobodan
From: Victor Anyakin
Subject: Re: Do I need pattern matching in here?
Date: 
Message-ID: <86bq7wslv0.fsf@victor-mobi.my.domain>
Slobodan Blazeski <·················@gmail.com> writes:

> Hi Alessio
>
> Thank you for your efforts but my needs are far more complex.
> 1st I don't know in advance all the keywords nor rules
> 2nd even if I do know I want to leave option to add additional
> keywords and/or rules later
> So this should be pefectly valid:
> (render "office-mail" ·····@bobi.com"
>   '((:underlined t) (:present-as :picture) (:italic t)
>     (:font :arial)  (:font-size 14) (:add-trailing-white-space 2)))
> Assuminng programmer added
> (add-render-rule
>    '((:font t) (:font-size t) (:italic italic)
>      (:underlined underlined) (:present-as :picture) (:add-trailing-
> white-space number))
>    #'render-email-link-in-picture)
>
> and defined corresponding function
> (defun render-email-link-in-picture (...

Hi!

I am just curious why

(add-render-rule #'(lambda (...some options...) (predicate code))
                 #'(lambda (string) (handler code))) 

But, probably, wrapped in a nice Macro would not work.

ADD-RENDER-RULE adds the given pair in a list *rendering-rules*, then
iterate over these pairs, apply the predicate to the rendering rules
you've got, if the rule matches, apply the handler, strip matched
rules, try to match again, if nothing matches, return.

Or, something like that.

Just an idea, no valid code...

Victor