[semantics] copy of context referenced lists

Started by hartrock, August 15, 2013, 01:27:25 AM

Previous topic - Next topic

hartrock

Trying to understand the semantics of copy I've found differences between copying - ordinary - unreferenced lists and context referenced ones: coypy does not copy context referenced lists.

This can change the sematics of code, if sometime later unreferenced lists will be replaced by referenced ones.



The manual says:
Quote
copy

syntax: (copy exp)



Make a copy from evaluating expression in exp. Some built-in functions are destructive, changing the original contents of a list, array or string they are working on. With copy their behavior can be made non-destructive.

Trying to check this non-destructive behavior I've tried with unreferenced and context referenced lists.



Following code:

"(setf c '()): " (setf c '())
(push "s_0" c) (push "s_1" c) (push "s_2" c)
"set-ref no copy......."
(set-ref (c 1) c 1) "c: " c
"set-ref with copy......."
(set-ref (c 1) (copy c) 2) "c: " c
""
"(define C:C): " (define C:C)
(push "s_0" C) (push "s_1" C) (push "s_2" C)
"set-ref no copy......."
(set-ref (C 1) C 1) "C:C : " C:C
"#### set-ref with copy......."
(set-ref (C 1) (copy C) 2) "C:C : " C:C
""
"trying to improve" ;; Update: code contains superfluous copy ops.
(define (alt_copy var)
  (if (context? var)
      (let (v (context var (sym (string var))))
        (if (nil? v)
            '()
            (copy v)))
      (copy var)))
""
"(setf c '()): " (setf c '())
(push "s_0" c) (push "s_1" c) (push "s_2" c)
"set-ref no copy......."
(set-ref (c 1) c 1) "c: " c
"set-ref with copy......."
(set-ref (c 1) (alt_copy c) 2) "c: " c
;;
"(define C:C): " (define C:C)
(push "s_0" C) (push "s_1" C) (push "s_2" C)
"set-ref no copy......."
(set-ref (C 1) C 1) "C:C : " C:C
"#### set-ref with copy......."
(set-ref (C 1) (alt_copy C) 2) "C:C : " C:C
;;

gives following differences between copy and alt_copy:

;; copy
"#### set-ref with copy......."
("s_2" 2 "s_0")
"C:C : "
("s_2" 2 "s_0")

;; alt-copy
"#### set-ref with alt_copy......."
("s_2" 2 "s_0")
"C:C : "
("s_2" 1 "s_0")


The advantage of alt_copy is, that it behaves the same, if an unreferenced list will later be replaced by a refernced one (e.g. for performance reasons).



Are there reasons not to have this as the default behavior?



Update after Lutz' reply

alt_copy contains superfluous copy operations and has other deficiencies: do not use it as it is! See later post for a better version.

Lutz

#1
If C is a context then (copy C) will not give you the contents of the default functor C:C but the contents of identifier C which is the context C again. Contexts are self-evaluating and always tied to a symbol in MAIN.



Only in cases where a newLISP built-in function expects a list or a string, will the context C be interpreted as its default functor C:C.



copy behaves like a generic copy, as a simple set assignment would do, it should not do any default functor conversions.

hartrock

#2
Thanks for the explanation: this helps to understand the language designer philosophy behind newLISP.


Quote from: "Lutz"
copy behaves like a generic copy, as a simple set assignment would do, it should not do any default functor conversions.

Semantically copy could also be formulated as function

(define (fn_copy arg)
  arg)

(please correct me, if I'm wrong).


Quote from: "Lutz"Only in cases where a newLISP built-in function expects a list or a string, will the context C be interpreted as its default functor C:C.

Normal case is call by value, and call by context ref is a special one.

A copy function returning a copy of the default functor for context args could make sense for strings and lists: but there are other kinds of default functors, for which this would not make sense.



Back to my 'use case' of being independent from having function arguments being context referenced or not: a 'ref agnostic' copy with default value for nil args (hopefully good newLISP code now):

Update: code is not so good as it could be: a better version follows in my next post (creating a new topic).

;; 'ref agnostic' copy
(define (ra_copy arg (defaultIfNil nil)) ; defaultIfNil arg may be "" or '()
  (if (context? arg)
      (let (v (context arg (sym (string arg))))
        (if (nil? v)
            defaultIfNil
            v))
      (if (nil? arg)
          defaultIfNil
          arg)))

Is something like ra_copy the way to go for lists and strings?



I'm stressing this point from the POV of a library designer, who wants to have a 'ref agnostic' interface.

Don't know yet, if I need ra_copy of arguments at all for my current use case; but I think the wish of having a 'ref agnostic' interface often arises for library writers.



A subjective note:

newLISP - as I'm knowing it so far - feels very good balanced regarding language features. I'm planning to use it as scripting language at work (instead of learning Perl, which reminds me of shell programming) and for other stuff (there already is an improved - specialized to my needs - version of some *n*x tool).

Lutz

#3
QuoteThanks for the explanation: this helps to understand the language designer philosophy behind newLISP.

... and ...
QuotenewLISP - as I'm knowing it so far - feels very good balanced regarding language features.


Thanks for these notes :). One day there should probably be a write-up about newLISP's philosopy. A few thoughts here:



The main difference to other programming language philosophies is, that some of newLISP's traits are influenced by thinking that is normally not found in the community of programming language geeks.



I think it is less about "consistency" or "it has feature x" as it is about categories like "beauty", "feeling right", "intuitivity", "learnability"  etc. whereby the judges of these categories are not the only the geeks but the average user.  People who are experts in other areas which are not programming languages:



E.g: cormullion, the author of the http://en.wikibooks.org/wiki/Introduction_to_newLISP">http://en.wikibooks.org/wiki/Introduction_to_newLISP writes one of the better written code, you will see in newLISP, he is not a programming language geek but an English writer who happens to program, and he understands how humans use and think in in human language and can transfer that knowledge to a programming language.



FOOP is another example. It was thought up mainly by m i c h a e l . He is not a programmer but a music composer(1) who also happens to program. He knows how to think in rhythms and flow of information. There have been many suggestions for OO systems over the years, but FOOP was the first one, I thought that it would fit into newLISP. It also makes use of context namespaces and default functors in an interesting way.



That does not mean that programming language geeks influences are not important. There are excellent people of this category on this board too, and they have influenced the language too.



What I want to say is, that a programming language designer should look far beyond what is taught in SICP and university CS classes and include expertise from people knowledgeable in other aspects of human communication.





(1) find his stuff here: http://neglook.com/">http://neglook.com/ and here http://neglook.com/site-diagram.html">http://neglook.com/site-diagram.html

cormullion

#4
Thanks for the kind words, Lutz. I'm content to not be a programming geek (anyway I failed the entrance exam). In fact, I studied music at college, so I'm not even a proper writer... :) But as you know I particularly like one aspect of newLISP, and that's its informal and casual nature, even though that can be challenging for the more serious programmer...