From: Raffael Cavallaro on
On 2010-05-10 05:49:30 -0400, Alan Malloy said:

> I had somehow gotten the idea that the idiomatic way to use sexps to
> store data in lisp is to have appropriate macros defined so that when
> you read/eval the "data", it is transformed into code that creates the
> in-memory data structure you want.

Have I ever mentioned cl-prevalence on this forum?

;^)

warmest regards,

Ralph

--
Raffael Cavallaro

From: His kennyness on
Alan Malloy wrote:
> Pascal J. Bourguignon wrote:
>> Tim X <timx(a)nospam.dev.null> writes:
>>
>>> Alan Malloy <alan.NO.SPAM(a)malloys.org> writes:
>>>
>>>> I'm trying to represent a hierarchical data structure, one with a
>>>> lot of
>>>> sub-trees which are each identical but with slightly different
>>>> modifiers. This
>>>> seems like a perfect example to design a domain-specific language for
>>>> concisely specifying data files (for now, the user can type these by
>>>> hand),
>>>> which I'd like to expand (presumably with macros) into a tree of
>>>> fully-specified nodes so that it's easier to determine what
>>>> properties a given
>>>> node has. My plan is to have the user define "template" sub-trees
>>>> (which may
>>>> contain other templates) and then set their modifiers. A simple
>>>> example using
>>>> less obscure object-types:
>>>>
>>>> (template building
>>>> (...some specification for buildings))
>>>> (template suburb
>>>> (neighborhood uptown
>>>> (speed-limit 25)
>>>> (building house)
>>>> (building park))
>>>> (neighborhood downtown
>>>> (speed-limit 35)
>>>> (building strip-mall)))
>>>> (template urban-area
>>>> (...same kind of stuff as suburb))
>>>> (city
>>>> (name "New York")
>>>> (rent-per-month 10000)
>>>> (urban-area))
>>>>
>>>>
>>>> speed-limit, name, and rent-per-month are properties that should
>>>> apply to each
>>>> sibling and all of their descendant nodes, so that if, after
>>>> expansion, I have
>>>> a reference to a strip-mall building I don't have to trace up the
>>>> tree until I
>>>> find a speed-limit definition. There are a fixed number of such
>>>> persistent
>>>> properties, so they can be hard-coded, but the definition of how to
>>>> construct
>>>> a city is up to the user, and will involve deeply-nested templates.
>>>> The final
>>>> output is just a tree of buildings (they nest within each other,
>>>> which is
>>>> where my "building" example breaks down) with varying properties.
>>>>
>>>> So I know what I want my data format to look like, but I don't
>>>> really know how
>>>> to get started on defining the macros that will be needed to
>>>> transform this
>>>> into a more-usable in-memory representation. Some sample output
>>>> might be a
>>>> list like:
>>>> '(...
>>>> (:type park :name "New York Park" :speed-limit 35
>>>> :rent-per-month 10000 :neighborhood downtown)...)
>>>> #don't have to specify "building", because everything is a building
>>>>
>>>> Can someone give me a push in the right direction?
>>> I would start by just defining some functions that abstract the
>>> creation/update/printing of your basic data structures. Once you have
>>> these functions defined, you will be in a better position to judge
>>> whether your initial data bastraction is the right one and you will have
>>> a better feel for it.
>>
>> Indeed. Macros would be useful only if you wanted to integrate these
>> data definition (the templates) and data manipulation (the "insert" data
>> declarations) languages into normal lisp code.
>>
>> If you keep these data in separate files, or separate input streams
>> (ie. user input), then you can merely define functions to read and
>> process them:
>>
>> (defun load-area-data (file &key verbose print
>> (if-does-not-exist :error)
>> (external-format :default))
>> ...
>> (loop
>> ...
>> collect (read-area-data stream)
>> ...))
>>
>>
>> (defun read-area-data (&optional (input-stream *standard-input*)
>> (eof-error-p t) eof-value)
>> (let* ((my-eof-value (load-time-value (gensym)))
>> (form (read stream eof-error-p my-eof-value)))
>> (if (eq form my-eof-value)
>> eof-value
>> (eval-area-data form))))
>>
>> (defvar *templates* '() "The collection of templates defined so far.")
>>
>> (defun eval-area-data (form)
>> (if (atom form)
>> (error "~S cannot be an Area data expression.~%" form)
>> (case (first form)
>> ((template) (destructuring-bind (op ...) form
>> ...
>> (register-template ...)))
>> (otherwise
>> ;; parse the form to find called up templates
>> ;; and build the data objects.
>> ...))))
>>
>>
>>
>>
>
> Hmmm, thanks. I had somehow gotten the idea that the idiomatic way to
> use sexps to store data in lisp is to have appropriate macros defined so
> that when you read/eval the "data", it is transformed into code that
> creates the in-memory data structure you want.

You were not wrong, but then the the first atom of every form would be a
macro, templates would expand into macrolets (or defclasses (or
something)) and they would come to life by being compiled. If you are
just reading in a tree of data (with templates being the only fancy bit)
it is not clear why you need a macro. If you just write code to take
apart the data as read to assemble the runtime data structures, that
then would be much the same code you would have in a macro generating
the macro's expansion, so it is a nice intermediate step to macrohood.

kt


> I've written a few simple
> I/O functions for reading basic text data, and if the "right" way to do
> this is to read my tree (or other abstraction, as Paul points out)
> through a set of actual functions it should be a fair bit easier for me
> to grasp anyway.
>
From: RG on
In article <hs8kr5$odc$1(a)news.eternal-september.org>,
Alan Malloy <alan.NO.SPAM(a)malloys.org> wrote:

> Pascal J. Bourguignon wrote:
> > Tim X <timx(a)nospam.dev.null> writes:
> >
> >> Alan Malloy <alan.NO.SPAM(a)malloys.org> writes:
> >>
> >>> I'm trying to represent a hierarchical data structure, one with a lot of
> >>> sub-trees which are each identical but with slightly different modifiers.
> >>> This
> >>> seems like a perfect example to design a domain-specific language for
> >>> concisely specifying data files (for now, the user can type these by
> >>> hand),
> >>> which I'd like to expand (presumably with macros) into a tree of
> >>> fully-specified nodes so that it's easier to determine what properties a
> >>> given
> >>> node has. My plan is to have the user define "template" sub-trees (which
> >>> may
> >>> contain other templates) and then set their modifiers. A simple example
> >>> using
> >>> less obscure object-types:
> >>>
> >>> (template building
> >>> (...some specification for buildings))
> >>> (template suburb
> >>> (neighborhood uptown
> >>> (speed-limit 25)
> >>> (building house)
> >>> (building park))
> >>> (neighborhood downtown
> >>> (speed-limit 35)
> >>> (building strip-mall)))
> >>> (template urban-area
> >>> (...same kind of stuff as suburb))
> >>> (city
> >>> (name "New York")
> >>> (rent-per-month 10000)
> >>> (urban-area))
> >>>
> >>>
> >>> speed-limit, name, and rent-per-month are properties that should apply to
> >>> each
> >>> sibling and all of their descendant nodes, so that if, after expansion, I
> >>> have
> >>> a reference to a strip-mall building I don't have to trace up the tree
> >>> until I
> >>> find a speed-limit definition. There are a fixed number of such
> >>> persistent
> >>> properties, so they can be hard-coded, but the definition of how to
> >>> construct
> >>> a city is up to the user, and will involve deeply-nested templates. The
> >>> final
> >>> output is just a tree of buildings (they nest within each other, which is
> >>> where my "building" example breaks down) with varying properties.
> >>>
> >>> So I know what I want my data format to look like, but I don't really
> >>> know how
> >>> to get started on defining the macros that will be needed to transform
> >>> this
> >>> into a more-usable in-memory representation. Some sample output might be
> >>> a
> >>> list like:
> >>> '(...
> >>> (:type park :name "New York Park" :speed-limit 35
> >>> :rent-per-month 10000 :neighborhood downtown)...)
> >>> #don't have to specify "building", because everything is a building
> >>>
> >>> Can someone give me a push in the right direction?
> >> I would start by just defining some functions that abstract the
> >> creation/update/printing of your basic data structures. Once you have
> >> these functions defined, you will be in a better position to judge
> >> whether your initial data bastraction is the right one and you will have
> >> a better feel for it.
> >
> > Indeed. Macros would be useful only if you wanted to integrate these
> > data definition (the templates) and data manipulation (the "insert" data
> > declarations) languages into normal lisp code.
> >
> > If you keep these data in separate files, or separate input streams
> > (ie. user input), then you can merely define functions to read and
> > process them:
> >
> > (defun load-area-data (file &key verbose print
> > (if-does-not-exist :error)
> > (external-format :default))
> > ...
> > (loop
> > ...
> > collect (read-area-data stream)
> > ...))
> >
> >
> > (defun read-area-data (&optional (input-stream *standard-input*)
> > (eof-error-p t) eof-value)
> > (let* ((my-eof-value (load-time-value (gensym)))
> > (form (read stream eof-error-p my-eof-value)))
> > (if (eq form my-eof-value)
> > eof-value
> > (eval-area-data form))))
> >
> > (defvar *templates* '() "The collection of templates defined so far.")
> >
> > (defun eval-area-data (form)
> > (if (atom form)
> > (error "~S cannot be an Area data expression.~%" form)
> > (case (first form)
> > ((template) (destructuring-bind (op ...) form
> > ...
> > (register-template ...)))
> > (otherwise
> > ;; parse the form to find called up templates
> > ;; and build the data objects.
> > ...))))
> >
> >
> >
> >
>
> Hmmm, thanks. I had somehow gotten the idea that the idiomatic way to
> use sexps to store data in lisp is to have appropriate macros defined so
> that when you read/eval the "data", it is transformed into code that
> creates the in-memory data structure you want.

That only works insofar as the information available to do that
transformation is available at compile time (well, strictly speaking, at
macroexpasion time, but the point being that the information must be
available BEFORE run time.) If that information is not available until
run-time then you have to get very sophisticated about doing partial
compilation into a representation that fills in the missing information
at run time. It can be done, but unless you really need efficiency it's
usually more trouble than it's worth. So don't get too hung up on
trying to shoehorn your code into a macro if you can accomplish what you
want to accomplish without one.

rg
From: Thomas A. Russ on
Alan Malloy <alan.NO.SPAM(a)malloys.org> writes:

> I'm trying to represent a hierarchical data structure, one with a lot of
> sub-trees which are each identical but with slightly different
> modifiers. This seems like a perfect example to design a domain-specific
> language for concisely specifying data files (for now, the user can type
> these by hand), which I'd like to expand (presumably with macros) into a
> tree of fully-specified nodes so that it's easier to determine what
> properties a given node has. My plan is to have the user define
> "template" sub-trees (which may contain other templates) and then set
> their modifiers. A simple example using less obscure object-types:

Snip...

> Can someone give me a push in the right direction?

You might also try looking at one of the knowledge representation
languages that have been developed over the years.

One choice (which I worked on) is the description logic LOOM:

http://www.isi.edu/isd/LOOM/

Another choice would be one of the frame languages.

--
Thomas A. Russ, USC/Information Sciences Institute




From: fortunatus on
On May 10, 11:48 am, RG <rNOSPA...(a)flownet.com> wrote:
> That only works insofar as the information available to do that
> transformation is available at compile time (well, strictly speaking, at
> macroexpasion time, but the point being that the information must be
> available BEFORE run time.)

No reason couldn't LOAD the data file at run time - in which case
macros can expand to top-level forms which add data onto some global
list.

On the other hand, that gives a bit much control to a data file -
consider the data file is free to do absolutely anything, including
define/run a brand new application or hijack the existing application.

Kenny's point is good - you'd write pretty much the same code to do a
more traditional READ at runtime to get basis SEXPs and then use
functions to expand the data into the final form.

The advice from a couple others to look into existing libraries - why
not?
First  |  Prev  |  Next  |  Last
Pages: 1 2 3
Prev: hunchentoot start
Next: (expt 2 #c(2d0 0))?