From: Tamas K Papp
Subject: copy or not? (style question)
Date: 
Message-ID: <6hdiumFkdhveU1@mid.individual.net>
Hi everyone,

I have a question about programming style.  Before Lisp, I used R, where 
almost all arguments to a function are deeply copied, eg 

> f <- function(a) {
+ a[2] <- 9
+ a
+ }
> a1 <- 1:3
> a1
[1] 1 2 3
> f(a1)
[1] 1 9 3
> a1
[1] 1 2 3

Initially, I tried to imitate this in Lisp, and wrote my programs with 
the following "contract" in mind: a function that uses a non-atomic 
argument has to copy it.

For example, think about a function that calculates a (univariate) spline 
at arbitrary real numbers, where this function is returned by another 
function and the information about the spline (the polynomials) is 
captured in an array, which is in the closure.  Skeleton code:

(defun make-spline-function (knots polynomials)
  ;; [check knots and polynomials]
  (let ((knots (array-copy knots))
        (polynomials (array-copy polynomials)))
    (lambda (x)
      ;; [calculate spline at x]
      )))

The assumption here is that I need to copy, because the user may make 
changes to knots and polynomials after make-spline-function is called,
which can lead to a mess.  For example, knots may not be weakly 
increasing anymore, so the function inside would need to check for that 
each time.

Now I am drifting towards the opposite style, where I do not make copies: 
the assumption is that whoever calls the function should not mess with 
the arrays afterwards.  If the user needs to change the structure, he 
should make a copy and change that.

I think that both styles can be consistent.  The latter seems elegant, 
but less "secure".  OTOH, when I write this code as a library, I guess I 
can just document the fact that arrays are not copied and the user should 
act accordingly.

Which style is more "natural" in Lisp?  What do you use?

Do you worry about "consistency checks" because the data structures that 
are not copied could have changed since when they were captured?

Thanks,

Tamas

From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <e50fe0e2-581b-4726-bdcd-8292e3414ede@r15g2000prd.googlegroups.com>
On Aug 24, 10:09 am, Tamas K Papp <······@gmail.com> wrote:
> Hi everyone,
>
> I have a question about programming style.  Before Lisp, I used R, where
> almost all arguments to a function are deeply copied, eg
>
> > f <- function(a) {
>
> + a[2] <- 9
> + a
> + }> a1 <- 1:3
> > a1
> [1] 1 2 3
> > f(a1)
> [1] 1 9 3
> > a1
>
> [1] 1 2 3
>
> Initially, I tried to imitate this in Lisp, and wrote my programs with
> the following "contract" in mind: a function that uses a non-atomic
> argument has to copy it.

This is why I wrote my functional collections library FSet.  See:

  http://common-lisp.net/project/fset/

FSet gives you the functional semantics you want with the efficiency
you need.

* (defun f (a) (setf (@ a 1) 9) a)
F
* (setq a1 (seq 1 2 3))
#[1 2 3]
* (f a1)
#[1 9 3]
* a1
#[1 2 3]

To be honest, I don't think anyone is using FSet but me.  I know, it
could use more and better documentation -- though what's there is
already well beyond what most open-source projects have.  But I have
other things to work on, and it's just not clear how many users FSet
could attract even if I wrote reams more about it.

Besides, with no feedback it's hard to know what aspects the docs need
to explain better.

The lack of enthusiasm is certainly understandable -- Lisp already has
several kinds of collection primitives, and of them, lists can even be
used functionally (though it sometimes takes a little effort and isn't
efficient for large collections).  It's hard to explain the benefits
of efficient functional collections against that background.

But the benefits of FSet go beyond the functional semantics.  Where CL
just gives you the bare data structures and lets you use them as you
wish, FSet collections are semantically loaded -- sets and sequences,
for instance, are different types and support different operations.
This allows code using them to be written more abstractly, and thus
more elegantly.

Well, that's my opinion, anyway.  I hope you'll give it a try.  I'd
love to hear what you think about it, whether you wind up using it or
not.

-- Scott
From: D Herring
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <qNGdnR7-U48zvy_VnZ2dnUVZ_h6dnZ2d@comcast.com>
Scott Burson wrote:

> But the benefits of FSet go beyond the functional semantics.  Where CL
> just gives you the bare data structures and lets you use them as you
> wish, FSet collections are semantically loaded -- sets and sequences,
> for instance, are different types and support different operations.
> This allows code using them to be written more abstractly, and thus
> more elegantly.

Is there a comparison between FSet and cl-containers?

Thanks,
Daniel
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <a30487e4-de67-48be-8261-a5915821d75c@1g2000pre.googlegroups.com>
On Aug 24, 8:10 pm, D Herring <········@at.tentpost.dot.com> wrote:
> Scott Burson wrote:
> > But the benefits of FSet go beyond the functional semantics.  Where CL
> > just gives you the bare data structures and lets you use them as you
> > wish, FSet collections are semantically loaded -- sets and sequences,
> > for instance, are different types and support different operations.
> > This allows code using them to be written more abstractly, and thus
> > more elegantly.
>
> Is there a comparison between FSet and cl-containers?

I don't have a detailed comparison, but I can see right off that the
cl-containers classes have imperative semantics.  It appears
furthermore that the projects have rather different design goals.  CL-
containers gives you ways to make certain kinds of imperative
algorithms more efficient, and (perhaps secondarily) easier to write.
FSet's goal, on the other hand, is to make it easier (and efficient
_enough_) to write programs in a more functional and more abstract
style, which will be more elegant and thus easier to write and
understand.

Also, it appears that the emphasis of cl-containers is to provide a
broad choice of data structures, where FSet is more about providing a
rich interface to each of four fundamental types: sets, bags, seqs
(sequences), and maps.

So don't think of FSet primarily as a way to make your code faster.
Think of it as enabling you to write in a functional style, at least
where collection operations are concerned.

-- Scott
From: Pascal J. Bourguignon
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <87y72ltxet.fsf@hubble.informatimago.com>
Scott Burson <········@gmail.com> writes:
> To be honest, I don't think anyone is using FSet but me.  I know, it
> could use more and better documentation -- though what's there is
> already well beyond what most open-source projects have.  But I have
> other things to work on, and it's just not clear how many users FSet
> could attract even if I wrote reams more about it.

(and remembering Kenny complaining about the lack of Cell followers).

So it would seem the problem of Lisp is not so much the lack of
libraries than the lack of library users...  

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Klingon function calls do not have "parameters" -- they have
"arguments" and they ALWAYS WIN THEM."
From: Lennart Staflin
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <mqr68dczvp.fsf@sellafield.lysator.liu.se>
Scott Burson <········@gmail.com> writes:

> To be honest, I don't think anyone is using FSet but me.  I know, it
> could use more and better documentation -- though what's there is
> already well beyond what most open-source projects have.  But I have
> other things to work on, and it's just not clear how many users FSet
> could attract even if I wrote reams more about it.

Well, I tried to use it. Found a couple of bugs, but no way of
reporting bugs. I gave up on using it.

Common-lisp.net kinda sucks. I got as far as to a trac page that
didn't even mention bugs. Much less how to create a bug report.

-- 
Lennart Staflin  <·····@lysator.liu.se>
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <dbf244a0-1a4a-4314-8e07-30af624d4076@l33g2000pri.googlegroups.com>
On Aug 25, 12:33 am, Lennart Staflin <·····@lysator.liu.se> wrote:
> Scott Burson <········@gmail.com> writes:
> > To be honest, I don't think anyone is using FSet but me.  I know, it
> > could use more and better documentation -- though what's there is
> > already well beyond what most open-source projects have.  But I have
> > other things to work on, and it's just not clear how many users FSet
> > could attract even if I wrote reams more about it.
>
> Well, I tried to use it. Found a couple of bugs, but no way of
> reporting bugs. I gave up on using it.
>
> Common-lisp.net kinda sucks. I got as far as to a trac page that
> didn't even mention bugs. Much less how to create a bug report.

Oh!  Well, you could have emailed them to the FSet-devel list, or even
just posted them here -- I probably would have seen them.  I see what
you mean about the Trac page not explaining itself very well -- I've
just added a sentence that should help.

Do you recall what the bugs were?

-- Scott
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <569b4072-d260-4150-be5e-da52e17c0055@w24g2000prd.googlegroups.com>
On Aug 25, 8:34 am, Scott Burson <········@gmail.com> wrote:
> On Aug 25, 12:33 am, Lennart Staflin <·····@lysator.liu.se> wrote:
>
> > Scott Burson <········@gmail.com> writes:
> > > To be honest, I don't think anyone is using FSet but me.  I know, it
> > > could use more and better documentation -- though what's there is
> > > already well beyond what most open-source projects have.  But I have
> > > other things to work on, and it's just not clear how many users FSet
> > > could attract even if I wrote reams more about it.
>
> > Well, I tried to use it. Found a couple of bugs, but no way of
> > reporting bugs. I gave up on using it.
>
> > Common-lisp.net kinda sucks. I got as far as to a trac page that
> > didn't even mention bugs. Much less how to create a bug report.
>
> Oh!  Well, you could have emailed them to the FSet-devel list, or even
> just posted them here -- I probably would have seen them.  I see what
> you mean about the Trac page not explaining itself very well -- I've
> just added a sentence that should help.

Whoops, it's worse than that -- you have to have a common-lisp.net
account to submit Trac tickets.  My error was in recommending Trac on
the FSet page as the default bug submission mechanism.  Sorry for
that.  I have changed it to recommend the mailing list.

I do hope you can remember what the bugs were.

-- Scott
From: Stelian Ionescu
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <pan.2008.08.25.18.36.15@common-lisp.net>
On Mon, 25 Aug 2008 09:19:17 -0700, Scott Burson wrote:
> Whoops, it's worse than that -- you have to have a common-lisp.net
> account to submit Trac tickets.  My error was in recommending Trac on
> the FSet page as the default bug submission mechanism.  Sorry for that. 
> I have changed it to recommend the mailing list.

you just need to do:
trac-admin /project/fset/trac/ permission add anonymous TICKET_CREATE
TICKET_APPEND

-- 
Stelian Ionescu a.k.a. fe[nl]ix
Quidquid latine dictum sit, altum videtur.
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <1027ea08-853b-4b85-b0b6-7c98ee813d39@v26g2000prm.googlegroups.com>
On Aug 25, 11:36 am, Stelian Ionescu <········@common-lisp.net> wrote:
> you just need to do:
> trac-admin /project/fset/trac/ permission add anonymous TICKET_CREATE
> TICKET_APPEND

Thanks.  I may leave it as is, though -- now that I stop to think
about it, I think it's probably better if bug reports go to the
mailing list first.

> Quidquid latine dictum sit, altum videtur.

Hoc amo :)

-- Scott
From: Kenny
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <48b2fa4c$0$29526$607ed4bc@cv.net>
>>Scott Burson <········@gmail.com> writes:
>>
>>>To be honest, I don't think anyone is using FSet but me. 

I have added it to my toolbox. No current requirement, but I am sure 
there will be. I think it is a solid hack and all round Good Thing to 
have at one's disposal.

kt
From: Kenny
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <48b5b229$0$29505$607ed4bc@cv.net>
Kenny wrote:
> 
>>> Scott Burson <········@gmail.com> writes:
>>>
>>>> To be honest, I don't think anyone is using FSet but me. 
> 
> 
> I have added it to my toolbox. No current requirement, but I am sure 
> there will be. I think it is a solid hack and all round Good Thing to 
> have at one's disposal.

Ah, hello requirement! for maps, specifically.

But I need ISAM (start with an indexed read (equal, >, or >=), then 
continue sequentially from there) and all I can find are do-map and 
iterator that traverse the whole collection. And no lookup with the comp 
(gt, ge, lt, le, eq) specifiable.

Did I miss these? I can see how I would create them given the existing 
code but will not bother until I am sure they do not already exist.

I agree, btw, that more doc will not help spread the word, but my 
attempts to surf the code -- boy, there is a lot of it! One thing that 
might have helped was having all code specific to a collection type in 
its own source.

kt
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <75991951-23b5-4c58-9b79-e823f3994601@s1g2000pra.googlegroups.com>
On Aug 27, 1:00 pm, Kenny <·········@gmail.com> wrote:
> Ah, hello requirement! for maps, specifically.
>
> But I need ISAM (start with an indexed read (equal, >, or >=), then
> continue sequentially from there) and all I can find are do-map and
> iterator that traverse the whole collection. And no lookup with the comp
> (gt, ge, lt, le, eq) specifiable.

You're right -- things like this are needed.  Here's how I think about
them.  In unreleased code I have a class called `interval-set', which
implements sets of intervals; each interval can be open or closed at
either end.  One of these could be intersected with an ordinary set to
yield the set of those members of the ordinary set that are within one
of the intervals.  Similarly the `restrict' operation (q.v.) on a map
and an interval set would give you the portion of the map with keys
within one of the intervals.  (Am I correctly understanding that this
is what you want?)

I don't think the interval-set code is really ready to release, but I
could make it more of a priority and have something out in a month or
two, I guess.  If you need anything like this before then, there are
certainly simpler ways to do it -- maybe you can undertake one of
them.

> I agree, btw, that more doc will not help spread the word, but my
> attempts to surf the code -- boy, there is a lot of it! One thing that
> might have helped was having all code specific to a collection type in
> its own source.

Okay, maybe I'll break it up a little.  (In general, I like large
source files.)

-- Scott
From: Kenny
Subject: FSet Intervals [was Re: copy or not? (style question)]
Date: 
Message-ID: <48b665e0$0$7362$607ed4bc@cv.net>
Scott Burson wrote:
> On Aug 27, 1:00 pm, Kenny <·········@gmail.com> wrote:
> 
>>Ah, hello requirement! for maps, specifically.
>>
>>But I need ISAM (start with an indexed read (equal, >, or >=), then
>>continue sequentially from there) and all I can find are do-map and
>>iterator that traverse the whole collection. And no lookup with the comp
>>(gt, ge, lt, le, eq) specifiable.
> 
> 
> You're right -- things like this are needed.  Here's how I think about
> them.  In unreleased code I have a class called `interval-set', which
> implements sets of intervals; each interval can be open or closed at
> either end.  One of these could be intersected with an ordinary set to
> yield the set of those members of the ordinary set that are within one
> of the intervals.  Similarly the `restrict' operation (q.v.) on a map
> and an interval set would give you the portion of the map with keys
> within one of the intervals.  (Am I correctly understanding that this
> is what you want?)

That sounds super-powerful and expressive. I like it. But all we need is 
  a lookup on a map that returns a new map that is a subset of the 
original containing only keys optionally GE or GT the lookup value. ie, 
we want to do ISAM (index-sequential access) on a map: start with a 
lookup GE or GT that returns a map, not a member, and then do-map the 
result. Application code would decide when to stop, but a nice touch 
would be to optionally specify a count or end value, or in the case of 
strings to return a submap of those keys starting with that string -- 
what we used to call generic keys back in my DEC RMS days where the 
keywords were FIND to set a cursor and GET to read one record and 
advance the cursor.

I started on hacking this out of the existing code and it looked like a 
couple hours work (just a matter of finding the node in the btree GE or 
GT the lookup value and returning a map with the node or roght branch as 
the root I am guessing) so I thought I would make sure it was not 
already there.

> 
> I don't think the interval-set code is really ready to release, but I
> could make it more of a priority and have something out in a month or
> two, I guess.  If you need anything like this before then, there are
> certainly simpler ways to do it -- maybe you can undertake one of
> them.

I'll give it a shot if the existing mechanism used by the project for 
such browsing comes up short.

> 
> 
>>I agree, btw, that more doc will not help spread the word, but my
>>attempts to surf the code -- boy, there is a lot of it! One thing that
>>might have helped was having all code specific to a collection type in
>>its own source.
> 
> 
> Okay, maybe I'll break it up a little.  (In general, I like large
> source files.)

Oh, then don't mind me. Until you have a few contributors your 
productivity is all that matters. My2.

thx, ken
From: Lennart Staflin
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <mqiqtodc10.fsf@sellafield.lysator.liu.se>
Scott Burson <········@gmail.com> writes:

> Do you recall what the bugs were?

One was a missing function definition. map-merge isn't defined, but
used in map reader syntax.


-- 
Lennart Staflin  <·····@lysator.liu.se>
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <f5faab79-f38c-4790-a785-e82667e221d7@w39g2000prb.googlegroups.com>
On Aug 25, 2:23 pm, Lennart Staflin <·····@lysator.liu.se> wrote:
> Scott Burson <········@gmail.com> writes:
> > Do you recall what the bugs were?
>
> One was a missing function definition. map-merge isn't defined, but
> used in map reader syntax.

Gack!  Thank you :)

-- Scott
From: Marcus Breiing
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <w5exec4dcy94v@breiing.com>
* Scott Burson

> Gack!  Thank you :)

While we're at it... I noticed that

  (fset:compare (make-symbol "FOO") (make-symbol "FOO"))
  --> :EQUAL

-- 
Marcus
From: Marco Antoniotti
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <dbc6b4a7-b181-4eb3-8351-7320fca9158d@v1g2000pra.googlegroups.com>
On Aug 26, 3:36 am, Marcus Breiing <······@2008w34.mail.breiing.com>
wrote:
> * Scott Burson
>
> > Gack!  Thank you :)
>
> While we're at it... I noticed that
>
>   (fset:compare (make-symbol "FOO") (make-symbol "FOO"))
>   --> :EQUAL

Well...  What should (FSET:COMPARE (+ 2.0 40) (* 2.0 21)) return?
I'd
bet it returns :EQUAL as well (I have not tried it and I am just
reading Scott's mind here :) )


Cheers
--
Marco
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <1b411be0-85e4-4fff-8f30-64980a23d63f@s20g2000prd.googlegroups.com>
On Aug 26, 8:24 am, Marco Antoniotti <·······@gmail.com> wrote:
> On Aug 26, 3:36 am, Marcus Breiing <······@2008w34.mail.breiing.com>
> wrote:
>
> > * Scott Burson
>
> > > Gack!  Thank you :)
>
> > While we're at it... I noticed that
>
> >   (fset:compare (make-symbol "FOO") (make-symbol "FOO"))
> >   --> :EQUAL
>
> Well...  What should (FSET:COMPARE (+ 2.0 40) (* 2.0 21)) return?
> I'd
> bet it returns :EQUAL as well (I have not tried it and I am just
> reading Scott's mind here :) )

Yes, but (compare (+ 2.0 40) (* 2 21)) returns :UNEQUAL, as the
numbers are of equal value but different types.  This is also what
Marco's example should return.

-- Scott
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <8565db2b-c002-467a-91b0-ffb8e88ad771@z11g2000prl.googlegroups.com>
On Aug 26, 12:36 am, Marcus Breiing <······@2008w34.mail.breiing.com>
wrote:
> * Scott Burson
>
> > Gack!  Thank you :)
>
> While we're at it... I noticed that
>
>   (fset:compare (make-symbol "FOO") (make-symbol "FOO"))
>   --> :EQUAL

Yes, I already have a fix for that one that I haven't released yet.

I'll try to release some of these bug fixes this weekend.

-- Scott
From: Tamas K Papp
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <6hfk6vFl4sqaU1@mid.individual.net>
On Sun, 24 Aug 2008 19:22:09 -0700, Scott Burson wrote:

> But the benefits of FSet go beyond the functional semantics.  Where CL
> just gives you the bare data structures and lets you use them as you
> wish, FSet collections are semantically loaded -- sets and sequences,
> for instance, are different types and support different operations. This
> allows code using them to be written more abstractly, and thus more
> elegantly.
> 
> Well, that's my opinion, anyway.  I hope you'll give it a try.  I'd love
> to hear what you think about it, whether you wind up using it or not.

Hi Scott,

I looked at your library, and I find the idea nice, but I won't be using 
it.  Mostly because I use matrices and vectors, and don't want to deal 
with the overhead and possible bugs.  Also, when I call foreign 
functions, I would have to convert, which would be a large PITA.

Best,

Tamas
From: Scott Burson
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <b24849dd-72c8-422a-8b36-4d97b5bfaa6a@v26g2000prm.googlegroups.com>
On Aug 25, 4:43 am, Tamas K Papp <······@gmail.com> wrote:
> On Sun, 24 Aug 2008 19:22:09 -0700, Scott Burson wrote:
> > But the benefits of FSet go beyond the functional semantics.  Where CL
> > just gives you the bare data structures and lets you use them as you
> > wish, FSet collections are semantically loaded -- sets and sequences,
> > for instance, are different types and support different operations. This
> > allows code using them to be written more abstractly, and thus more
> > elegantly.
>
> > Well, that's my opinion, anyway.  I hope you'll give it a try.  I'd love
> > to hear what you think about it, whether you wind up using it or not.
>
> Hi Scott,
>
> I looked at your library, and I find the idea nice, but I won't be using
> it.  Mostly because I use matrices and vectors, and don't want to deal
> with the overhead and possible bugs.

Overhead?  Yes, there is some, but compared with frequently making
copies, it's probably faster.

And obviously nobody wants to use a collections package that's going
to lose data -- which is why I tested FSet very thoroughly before I
released it.  (I'm using it too, and I certainly don't want it to
screw up!)

> Also, when I call foreign
> functions, I would have to convert, which would be a large PITA.

Ah yes, well, that could be an annoyance.

Oh well, thanks for taking a look at it anyway.

-- Scott
From: Pascal J. Bourguignon
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <87iqtquv2i.fsf@hubble.informatimago.com>
Tamas K Papp <······@gmail.com> writes:
> Now I am drifting towards the opposite style, where I do not make copies: 
> the assumption is that whoever calls the function should not mess with 
> the arrays afterwards.  If the user needs to change the structure, he 
> should make a copy and change that.
>
> I think that both styles can be consistent.  The latter seems elegant, 
> but less "secure".  OTOH, when I write this code as a library, I guess I 
> can just document the fact that arrays are not copied and the user should 
> act accordingly.
>
> Which style is more "natural" in Lisp?  

Both.


In CL, there are functions that are specified not to change the
arguments, and others that are allowed to change them.

For example:

(let ((a (list 1 2 3 2 4 2 5 2)))
  (print (remove 2 a))
  a)
prints:
(1 3 4 5) 
--> (1 2 3 2 4 2 5 2)


On the other hand:

(let ((a (list 1 2 3 2 4 2 5 2)))
  (print (delete 2 a))
  a)
prints:
(1 3 4 5) 
--> (1 3 4 5)


For a lot of functions there's a pair F / NF, F doesn't modify its
arguments, while NF must avoid consing, and therefore is allowed to
modify its arguments. ((substitute nsubstitute) (reverse nreverse) ...)



However,  in a programming language without a garbage collector it's
rather hard to manage structure sharing and functions returning new
structures, so it is customary in these programming languages to make
a lot of copies.  But in Lisp we have a garbage collector, so we can
on the contrary optimize out time and space, by sharing structures.
Therefore I would rather advise using pure functions, that won't
modify their arguments, and for which it is useless to copy them.


> What do you use?

Both.  See above.



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Cats meow out of angst
"Thumbs! If only we had thumbs!
We could break so much!"
From: Tamas K Papp
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <6hdqcnFkdhveU2@mid.individual.net>
On Sun, 24 Aug 2008 20:28:05 +0200, Pascal J. Bourguignon wrote:

> For a lot of functions there's a pair F / NF, F doesn't modify its
> arguments, while NF must avoid consing, and therefore is allowed to
> modify its arguments. ((substitute nsubstitute) (reverse nreverse) ...)
> 
> However,  in a programming language without a garbage collector it's
> rather hard to manage structure sharing and functions returning new
> structures, so it is customary in these programming languages to make a
> lot of copies.  But in Lisp we have a garbage collector, so we can on
> the contrary optimize out time and space, by sharing structures.
> Therefore I would rather advise using pure functions, that won't modify
> their arguments, and for which it is useless to copy them.

For me, the issue is not really about optimization, but enforcing some 
consistency on shared structures.  Imagine that a closure uses shared 
structure, which is required to satisfy some condition.  One could

1) check the structure at the time of the closure's creation,
2) check the structure each time the closure is called,
3) both,
4) neither

1) catches obvious misunderstandings (eg the function expecting a vector 
of weakly increasing numbers, but called with one that does not satisfy 
this), and is reasonably fast.  But the shared structure can be modified 
in the meantime.

2) always catches inconsistencies, but it is slow and mostly 
unnecessary.  3) ditto.

4) can be bad.  Some inconsistencies are caught as an error (such as 
division by 0).  But with numerical computations, errors can creep in 
unnoticed, and are hard to debug.  The worst-case scenario is having an 
inconsistency that influences computation but is not noticed at all.

I think that there is another way: make error checking dependent on 
something, possibly the safety declaration, for example.  If I recall 
correctly, Eiffel compilers had a feature like this which you could turn 
off after the code has been tested.  How could I do this in CL?  Suppose 

(declaim (optimize (safety 3)))

was used.  How can I make code dependent on the safety level?

But even this would be a compilation-time feature, not something I can 
toggle at runtime - that's OK I guess.

I wonder if this is the way to go, opinions and suggestions are welcome.

Thanks,

Tamas
From: Rainer Joswig
Subject: Re: copy or not? (style question)
Date: 
Message-ID: <joswig-55D8AC.21312224082008@news-europe.giganews.com>
In article <··············@mid.individual.net>,
 Tamas K Papp <······@gmail.com> wrote:

> On Sun, 24 Aug 2008 20:28:05 +0200, Pascal J. Bourguignon wrote:
> 
> > For a lot of functions there's a pair F / NF, F doesn't modify its
> > arguments, while NF must avoid consing, and therefore is allowed to
> > modify its arguments. ((substitute nsubstitute) (reverse nreverse) ...)
> > 
> > However,  in a programming language without a garbage collector it's
> > rather hard to manage structure sharing and functions returning new
> > structures, so it is customary in these programming languages to make a
> > lot of copies.  But in Lisp we have a garbage collector, so we can on
> > the contrary optimize out time and space, by sharing structures.
> > Therefore I would rather advise using pure functions, that won't modify
> > their arguments, and for which it is useless to copy them.
> 
> For me, the issue is not really about optimization, but enforcing some 
> consistency on shared structures.  Imagine that a closure uses shared 
> structure, which is required to satisfy some condition.  One could
> 
> 1) check the structure at the time of the closure's creation,
> 2) check the structure each time the closure is called,
> 3) both,
> 4) neither
> 
> 1) catches obvious misunderstandings (eg the function expecting a vector 
> of weakly increasing numbers, but called with one that does not satisfy 
> this), and is reasonably fast.  But the shared structure can be modified 
> in the meantime.
> 
> 2) always catches inconsistencies, but it is slow and mostly 
> unnecessary.  3) ditto.
> 
> 4) can be bad.  Some inconsistencies are caught as an error (such as 
> division by 0).  But with numerical computations, errors can creep in 
> unnoticed, and are hard to debug.  The worst-case scenario is having an 
> inconsistency that influences computation but is not noticed at all.
> 
> I think that there is another way: make error checking dependent on 
> something, possibly the safety declaration, for example.  If I recall 
> correctly, Eiffel compilers had a feature like this which you could turn 
> off after the code has been tested.  How could I do this in CL?  Suppose 
> 
> (declaim (optimize (safety 3)))
> 
> was used.  How can I make code dependent on the safety level?
> 
> But even this would be a compilation-time feature, not something I can 
> toggle at runtime - that's OK I guess.
> 
> I wonder if this is the way to go, opinions and suggestions are welcome.
> 
> Thanks,
> 
> Tamas


It is relatively simple. If you need to protect
data against modifications then do it.

* let routines hand out copies of the original data

* let routines hand out shallow objects (value objects)
  with just the necessary data set

* let routines hand out data that only it knows how to
  change. For example in CLOS you could use slot names
  that are not global symbols. So slots could
  be read with a reader function, but there would be
  no writer and no way to set the SLOT-VALUE (without
  knowing the private slotname).

* if there is some concurrent access the use locks
  (or similar) to protect the data against concurrent
  changes

* in some cases you might want to make sure that the
  changing operations are atomic

* some routines might want to make copies of argument data first

If your software needs to check the integrity of some data,
the write assertions (see ASSERT and CHECK-TYPE).

If your needs are more demanding, then you might think
about some kind of transaction handling.

-- 
http://lispm.dyndns.org/