set-nth on strings

Started by cormullion, September 18, 2008, 03:02:02 PM

Previous topic - Next topic

cormullion

How would I do this in newLISP 9.9...


newLISP v.9.3.0 on OSX UTF-8, execute 'newlisp -h' for more info.

> (set 's "abc")
"abc"
> (set-nth 0 s "z")
"zbc"


Is this a job for setf now...?

Lutz

#1
Most of the following would work in either 9.3, 9.4 or 9.9.x -> 10.0 versions. If not it is noted.



The easiest would be:


(set 's "abc")

(replace "a" s "z") => "zbc"


which assumes you know that the first character is a "a"; if not, you could work on the string with regular expressions:


(set 's "abc")

(replace "^." s "z" 0) => "zbc"


'replace' has also the advantage, that is returns a string reference in 9.9x and after, so you could do:


; v 9.9.2 and after only
(set 's "abc")

(pop (replace "a" s "z") -1) => "c"

s => "zb"


Replace together with regular expressions is probably the most versatile in string manipulation, but there are also combinations of 'string', 'rest' and 'sclice' which are useful.


(set 's "abc")

(set 's (string "z" (rest s))) => "zbc"

(set 's (string "z" (1 s))) => "zbc"


Then there is also 'push' and 'pop' which can insert or extract single or multi-character pieces from a string:


(set 's "abc")

(pop s) (push "z" s)

s => "zbc"


All of these of course would work with multi-character strings to extract or insert (including 'push' and 'pop')

newBert

#2
This can work too:


> (set 's "abc")
"abc"
> (replace (first s) s "z") ; or (replace (s 0) s "z")
"zbc"

:)
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

cormullion

#3
But you're saying that you're removing the ability to directly modify strings using indexes to character locations?



(replace (nth i s) s "") is OK but not as good as (nth-set - the repetition of the string...



And I used to like the way that many functions such as nth-set worked on both strings and lists... Made newLISP easy to learn, I thought.



I'm trying hard to like newLISP 10 but I'm not finding it very likeable yet...

Lutz

#4
I have 'setf' working on string references: (setf (s idx) str) . But cannot guarantee yet that this will stay (it is not thought thru fully and not enough tested yet).



From the beginning I have been aware of the loss of old 'set-nth' for strings (and some other things), but still think that the improvements overall outweigh the loss of other conveniences.



But perhaps we are lucky and can have it all ;-)

DrDave

#5
Quote from: "cormullion"But you're saying that you're removing the ability to directly modify strings using indexes to character locations?



(replace (nth i s) s "") is OK but not as good as (nth-set - the repetition of the string...



And I used to like the way that many functions such as nth-set worked on both strings and lists... Made newLISP easy to learn, I thought.



I'm trying hard to like newLISP 10 but I'm not finding it very likeable yet...

But if it goes away and you really find it useful, it's not hard in newLISP to write your own implementation of nth-set.
...it is better to first strive for clarity and correctness and to make programs efficient only if really needed.

\"Getting Started with Erlang\"  version 5.6.2

cormullion

#6
Quote from: "Lutz"I have 'setf' working on string references: (setf (s idx) str) . But cannot guarantee yet that this will stay


do you think it'll make the v10 release?

Kazimir Majorinc

#7
Reviewing the situation, I now incline to Cormullion's side and I think set-nth and nth and company should be kept. The main reason is that "implicit indexing" of the syntax is on the way of elimination of lambda in Pico Lisp style. It could be one of the big issues in future Lisps, especially in Newlisp. On the other side, implicit indexing is irregular syntax that has some - but little advantage, while it has more disadvantages.



I think it would be best
  • * to undefine (L idx) as evaluable expression. ('(4 5) 1) should return error,

    * to keep (L i) syntax to some extent in function calls, like (nth (L i)) and (set-nth (L i) x). Still, the functions with different names, like (set-nthx L i x) and (set-nthi (L i) x) have sense,

    * to define polymorphic versions like setf on the base of specific versions setq, set-nth, but not to dump specific versions.

So, it is not completely lost case for polymorphism, but I think that specific versions have important advantages:
  • * its easier to analyze program if it contains specific information,

    * specific functions are slightly faster,

    * polymorphism depends on context. For example, there are many ways to define product on list.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

Lutz

#8
Regarding 'setf' for strings:


Quotedo you think it'll make the v10 release?


it is already there since 9.9.4 and you can find examples in the reference section of the manual http://www.newlisp.org/downloads/development/newlisp_manual.html#setf">http://www.newlisp.org/downloads/develo ... .html#setf">http://www.newlisp.org/downloads/development/newlisp_manual.html#setf


QuoteI think set-nth and nth and company should be kept


'nth' is still there, implicit indexing is purely optional and both explixit and implicit indexing works with 'setf'


(set 'lst '(a b c))

(setf (nth 1 lst) 'B) ; explicit for better readability

lst => (a B c)

(setf (lst 1) 'Z) ; implicit and higher speed

lst => (a Z c)


'setf' when used with explicit 'nth' or 'first' or 'last' is still descriptive when reading source.



Implicit indexing means overloading the string, list or array data type with operator functionality and fits well into the LISP evaluation paradigm (see here: http://www.newlisp.org/ExpressionEvaluation.html">http://www.newlisp.org/ExpressionEvaluation.html ). The same is done with numbers for implicit slicing or the context symbol in operator position, where it gets interpreted as the default functor <symbol>:<symbol>.



Implicit indexing has been received enthusiastically by many since version 8.5 more than three years ago, and newLISP was the first to introduce it (Arc adopted it too). It brings Lisp closer to other programming languages where the combination of container and index to express a place in that container, is a common thing to do. 'setf' ties it together with other parts of the language. Where implicit indexing obscures code readability explicit indexing and slicing can still be used.



Ps: note that list or string slices are not a valid place (yet) to use 'setf', use a combination of 'pop' and 'push' instead.

cormullion

#9
Oh yes, so it is! I'm sorry.



I'm switching between newLISP versions quite often at the moment, and I re-installed 9.9.2 by mistake...



You're up early today Lutz!