Page 1 of 1

Assesing set-macro-character+deftype vs CLOS...

PostPosted: Fri Jun 23, 2017 6:42 pm
by starfleet
Greetings!
I'm trying to write an Annotated Predicate Calculus (APC) manager. Fundamental units in this manager are called selectors and have the structure:
[<var> <op> <val>]
For example, [color = red], [size >= 35], [age IN 20..40]

With Set-Macro-Character I can get the Lisp reader to correctly parse a selector using:
Code: Select all
(set-macro-character #[
(lambda (stream char)
 (let* ((lst (read-delimited-list #] stream t)))
  (read-selector lst))))   ;; function read-selector handles the selector parsing, for example, suppose it just inverts the list...

(set-macro-character #]
  (get-macro-character #)))

...but I don't know how to make Lisp DISPLAY the selector correctly:
Code: Select all
CL-USER> '[a b c d]
(D C B A)        <-- it displays with parenthesis instead of brackets

So I have two questions:
1) Is there a way, maybe using deftype and some output-configuration trick to make Lisp recognize selectors and display them correctly?
2) In any case, is it worthwhile doing the above instead of defining a CLOS model for the same task?

Thank you in advance for your comments...

Re: Assesing set-macro-character+deftype vs CLOS...

PostPosted: Sat Jun 24, 2017 4:06 am
by pjstirling
It *is* possible to have lists print differently. You can do all sorts of weird things with the pretty printer[1] If you go this way make sure you use a copy of the pprint dispatch table, because the global one is used for printing things like macroexpansions.

Depending on what you want to do it may be simpler to have a clos object with a PRINT-OBJECT method

[1]: http://www.lispworks.com/documentation/HyperSpec/Body/22_bb.htm

Re: Assesing set-macro-character+deftype vs CLOS...

PostPosted: Sat Jun 24, 2017 5:03 pm
by starfleet
I see...

Pjstirling, I have studied the solution you suggested, it seems to me that indeed I can tweak the pretty printer for the sample task but, in the end, my goal is to program fully functional selectors, complexes, stars, and all the other kind of objects in the Annotated Predicate Calculus (APC)...

It was my greed for performance that ultimately got me to explore that solution, but, as you pointed out, a CLOS model seems a much cleaner and safe solution...

Thank you very much. Once I have completed the program I will get back to this idea and try to make a full-range comparison, just to help in the comprehension of the differences, in performance, clarity, robustness, and any other aspect it seems reasonable...

Again, thank you very much...

Re: Assesing set-macro-character+deftype vs CLOS...

PostPosted: Sun Jun 25, 2017 12:08 pm
by starfleet
A brief update...

So, as Pjstirling suggested, i started modeling APC CLOSS-style and I ran into the following which I consider related enough to the original post, that i deserves to be in the same post...

It is easy to write a selector class with a print-object method that instead of something awkward as #<SELECTOR {10047D5E73}>, displays:
#<SELECTOR [X >= 32] :TRUTH T :ACTIVE NIL>, which looks useful when asking the REPL for the value of a symbol bound to a selector...
Code: Select all
(defmethod print-object ((s  selector) out)
     (print-unreadable-object (s out :type T)
     (format out "[~s ~s ~s] :TRUTH ~s  :ACTIVE ~s"
          (slot-value  s 'attribute)
          (slot-value  s 'operator)
          (slot-value  s 'value-expression)
          (slot-value  s 'active)
          (slot-value  s 'truth-value))))

But then, it will be necessary to model complexes: lists of selectors implicitly connected by conjunction, so

Is there a mechanism to preserve the above way of displaying when asking the REPL for a symbol, but change to
([X >= 32] [age < 25] [color = BLUE]) when displaying a list of selectors???

Any help will be greatly appreciated...

Re: Assesing set-macro-character+deftype vs CLOS...

PostPosted: Tue Jun 27, 2017 1:45 pm
by David Mullen
It's easy to print things differently depending on the context, but then you have to keep track of context. How does a selector know if it's in a list or not? It probably doesn't, so you'd need to leverage the pretty-printing mechanism (as pjstirling suggested). Erik Naggum once posted a throwaway example of printing PROGN forms with a curly-brace notation.

Re: Assesing set-macro-character+deftype vs CLOS...

PostPosted: Wed Jun 28, 2017 8:12 am
by marcoxa
Hi

your problem is that you have LISTs in your hand after you have READ in something via your #[ reader macro. That makes it very cumbersome to interact with the other piece of the CL ecosystem that you need to interact with: the pretty printer and PRINT-OBJECT

Essentially you need to use PRINT-OBJECT or SET-PPRINT-DISPATCH; which predates CLOS and somewhat is more expressive when it comes to dispatch on the object it needs to print.

If you want to see how this can be used, you can have a look at (shameless plug) CL-UNIFICATION and XHTMLAMBDA as two different examples.

But you want to produce "objects". I.e., you want to have something like

Code: Select all
(destruct selector var op val)


or

Code: Select all
(destruct (selector (:constructor selector (var op val)) var op val)


And the objects of this struct type are what READ-SELECTOR returns.

Cheers
--
MA