Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Synonym streams
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
james anderson  
View profile  
 More options Sep 25 2003, 1:56 pm
Newsgroups: comp.lang.lisp
From: james anderson <james.ander...@setf.de>
Date: Thu, 25 Sep 2003 20:01:22 +0200
Local: Thurs, Sep 25 2003 2:01 pm
Subject: Re: Synonym streams

"Steven M. Haflich" wrote:

> Kent M Pitman wrote:

> >>Gray Streams, Simple Streams, any number of streamish window systems,
> >>or anything else that might involve gf discrimination on stream type.

> > These aren't really paradigms.  These are implementation strategies.

> Sorry for being away from this thread so long,

thank you for returning to it. i did not follow your conclusions the first
time and i welcome the chance to understand the issue.

>    but I really cannot agree
> with the above statement.  All these things are not implementation
> strategies; they are APIs avaialble to client code, even extensible APIs.

> ...
> >>Synonym streams present two practical problems.  First, the operational
> >>class of the stream is not apparent via the actual class of the stream.

> > I'm not sure I get your point here.

> The point is that the implementor of any module that defines non-CL-package
> operators must arrange for these operators to discriminate and delegate for
> synonym etc. streams. or else document that they won't work.  The former is
> a tedious and costly load on otherwise sane API implementations.

> > "might have to be extended".  It seems to me that synonym streams _could_
> > be a subclass of a gray stream or a simple stream.

> But a synonym strteam would not automatically be a subclass of a
> terminal-stream-with-double-spacing or a clim:presenting-stream unless
> the implementors of these protocols make it so.

but no specialization relation is autmatic. if one neglects issues of
finalization and encapsulation which would preclude a subclass, why can not a
synonym stream not treat these as protocol classes to be specialized, or,
alternatively, assuming that the api is intended to be extended, why can't it
specialize some abstract class, for which the abstract functions in the
interface are then written? yes, the implementors of the protocol cannot make
it so, but they can allow the users to.

as i noted in my earlier query, delegation in lisp depends on a binding for
the referent. synonym streams effect this with a special variable.
object-based delegation can support it with a slot binding. it would be
possible to do it with closed-over variables, but i'm not acquainted with
implementation which use that technique. given this requirement, that is, that
the referent is bound somewhere, the only difference i can discern between the
special-binding-based delegation and the slot-based delegation is, well, the
nature of the binding.

> > I'm sure it was originally considered when synonym streams were invented
> > since the Lisp Machine uses both synonym streams and "new flavors"
> > (essentially a syntactic variant of CLOS) pretty extensively in the
> > implementation of Dynamic Windows (conceptually very similar to CLIM).

> There was a time, before they went bankrupt, that Symbolics had lotsa money
> and lotsa programmers, and could devise that synonym streams would delegate
> transparently for all the defined operators.  But if I'm a little developer
> trying to write a window system, say, that back ends on the XUL rendering
> language of Mozilla, I might be annoyed that I have to write methods for
> every API function I create for each kind of delegating ANSI stream, or else
> document that they won't work.

this is where i don't understand why that is a problem. that
make-synonym-stream does not include a means to specify the class of the
stream is a problem. which problem is common to all elements of the standard
stream interface, not particular to synonym streams.

> I repeat my opinion that the ANS delegating streams (synonym, contatenating,
> broadcast) are a failed experiment incompatible with modern oo programming
> and which remain an unfortunate weight upon the language.  I think they
> shold be deprecated.

what is the argument against specializing them. if it were possible to specify
the concrete class, to the standard creation functions, what problem would remain?

if i take a tiny example. let's say i would like to generate svg. i have these
data objects which need to be serialized. in order to support delegation,
there has to be some provision for it in the api protocol.

in this case, the base generic function and default definitions are all
generated via
macros. like

(defProjectionOp line (l1 l2 &optional properties))
(defProjectionOp line*2 (x1 y1 x2 y2 &optional properties))
(defProjectionOp line*3 (x1 y1 z1 x2 y2 z2 &optional properties))

in order to provide for delegation - or whatever sort - i would think that
there has to be a definition somewhere which looks something like

(defmethod op ((instance delegate) &rest args)
  (apply #'op (delegate-referent instance) args))

are there alternatives? given that, the generation function for delegatable
operations needs an additional clause. some thing like

(push `(:method ((delegate delegate-context) ,@lambda-list)
                (,do-call #',operator-name
                     (delegate-referent delegate) ,@arguments))
      methods)

which is not that complex and provides for any class which specializes
delegate-context and implements delegate-referent. it is not material whether
the class specializes synonym-stream or some other abstract class. assuming
that the projection operations above are so defined, the alternative
delegation forms do not look very different.

(defClass svg-presenter () ()
  (:documentation
   "the protocol class which specifies the presence of the svg presentation methods"))

(defClass svg-context (aspect-context)
  ((stream
    :initform nil :initarg :stream
    :reader context-stream
    :documentation "bound to an output stream for svg-envoded output."))
  (:documentation
   "a context which implements graphics operations as svg serialization."))

(defclass svg-wrapper-context (delegate-context svg-presenter stream)
  ((context :reader effective-context :initarg :context))
  (:documentation
   "a wrapper which implements svg presentation methods through delegation to
a context which implements graphics operations."))

(defParameter *svg-output* nil)

(defClass svg-synonym-context (delegate-context svg-presenter synonym-stream)
  ()
  (:default-initargs :symbol '*svg-output*)
  (:documentation
   "a synonym context which delegates through a spacial variable binding
rather than a slot binding."))

(defMethod effective-context ((synonym-context svg-synonym-context))
  (symbol-value (synonym-stream-symbol synonym-context)))

[ ignoring the stream operations which the wrapper needs to act as a stream ]

the concrete serialization looks something like this

(defun svg-line*3 (x1 y1 z1 x2 y2 z2 &optional aspects)
  "serialize a line given the 3d location"
  #+og.assert-types (progn (assert-types (x1 y1 z1 x2 y2 z2) number)
                           (assert-type aspects sequence))
  (flet ((emit-line ()
           (xml ({svg}line ({}x1  x1) ({}y1  y1)
                           ({}x1  x2) ({}y1  y2)
                           ({}stroke *svg-stroke-color*)))))
    (declare (dynamic-extent #'emit-line))
    (call-with-aspects #'emit-line aspects)))

(defMethod .og.::line*3 ((context svg-context) x1 y1 z1 x2 y2 z2 &optional aspects)
  "draw a line given two extreme 3d vertices"
  (svg-line*3 x1 y1 z1 x2 y2 z2 aspects))

(defMethod .og.::line*2 ((context svg-context) x1 y1 x2 y2 &optional aspects)
  "draw a line given two extreme 2d vertices"
  (svg-line*3 x1 y1 0.0d0 x2 y2 0.0d0 aspects))

(defMethod .og.::line ((context svg-context) l1 l2 &optional aspects)
  "draw a line given the end locations (2-d or 3-d) in object/world coordinates"
  ;; ignoring that svg is only 2d
  (with-location-coordinates (((x1 y1 z1) l1) ((x2 y2 l2) l2))
    (svg-line*3 x1 y1 z1 x2 y2 l2 aspects)))

the projection interface looks something like this

(defgeneric present (instance context)
  (:method ((instance line) (context svg-presenter))
           (line context (location instance) (end instance)
                       (presentation-properties instance context))))

and the usage looks something like this

(defParameter *svgc* (make-instance 'svg-context :stream *trace-output*))
;(context-stream *svgc*)

(defParameter *svg-wc* (make-instance 'svg-wrapper-context :context *svgc*))
;(effective-context *svg-wc*)
;(context-stream (effective-context *svg-wc*))

(defParameter *svg-sc* (make-instance 'svg-synonym-context :symbol '*svg-output*))

(setq *svg-output* *svg-wc*)

(with-projection-context (*svgc*)
  (let ((line (make-instance 'line
                :location #@(|3| 0.0 0.0 0.0)
                :end #@(|3| 1.0 1.0 1.0))))
    (format *svg-wc* "~%~%<!-- presenting to a svg-wrapper-context: -->~%")
    (present line *svg-wc*)
    (format *svg-sc* "~%~%<!-- presenting to a svg-synonym-context: -->~%")
    (present line *svg-sc*)))

wherein i discern no difference between synonym classes and wrapper classes.
do the problems surrounding a terminal-stream-with-double-spacing a
clim:presenting-stream has a shape which is so different from this?

...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.