Many programming languages permit natural manipulation of strings, and some languages permit the manipulations of lists too.
More often then not (always?), these operations are done as procedure calls, or as member functions.
Many programming languages do implement in syntax the fairly typical set {prepend, replace, append} on lists (and/or strings).
I would like to know if there as/was a programming language that has a syntax that minimises/rationalises/orthogonalises the insertion syntax of items into a list by syntax design?
Python – as a simple example – has only: https://stackoverflow.com/questions/18033339/python-insert-operation-on-list
mylist.insert(10,'5')
Note: In python list insertion is implemented as a member function.
But: Python does have some syntactic sugar for removing elements from a list: e.g.
del mylist[4:7]
I like to know of any languages actually try to integrate (or have strategy) for list insertion as part of the syntax?
An example of insertion by construction: Here is some code from a fairly typical “Brand X” language, demonstrating typical prepend/replace/append operations {or operators, vis-à-vis syntatic sugar}, notice there is no obvious syntax for {in place} inserting (or removing) from the middle of a list. {It has to be done “by construction”, or by calling a procedure}
# Demonstration of prefix, replace and append operations to a string {or list} #
string s := "23XX78";
"1" +=: s; # Prefix a char "1" to the string "in place" #
s[4:5] := "46"; # In place replace a char at pos 2 in a string #
s +:= "9!"; # Append a string "9!" char to the string #
#
Although inserting into a list is intuitive,
* it is by construction (hence prone to typos/index-flips)
* it is not "in place"
e.g. ...
#
s:=s[:4]+"5"+s[5:];
print(s)
Output: “123456789!”
Another example for strings:
s[:4]+="5"
3
Python actually supports insertion of arbitrary sub-lists, as a part of list slice assignment. You just assign to an empty slice before the element where you want to insert a new list:
list1 = [1, 2, 3]
list1[1:1] = [10, 20, 30] # insert 3 elements at index 1
print list1 # prints [1, 10, 20, 30, 2, 3]
Many languages view lists as primarily sequential data structures, thus only allowing manipulation at their ends. This has both implementation-related and logical advantages: e.g. sequentially you can handle lists of unknown arbitrary length.
Often when you find yourself in need to insert an element into the middle of a list, it’s a good sign that what’s you’re doing is a hack due to a poor design. (Python’s sys.path[0:0]
manipulation is an example.)
6
F# provides a ::
operator that is used both for construction and destructuring:
(* this will append 1 as a head to a list containing 2 and 3 *)
let lst = 1 :: [2; 3]
> [1; 2; 3]
(* this will use pattern matching to destructure the list and return
the sum of first two elements; if not possible, then the first element; otherwise 0 *)
let func = function | a::b::_ -> a + b | h :: _ -> h | _ -> 0
func lst
> 3
There’s also a @
operator for concatenating lists:
(* this will return a concatenated lists *)
let longer = lst @ lst
> [1; 2; 3; 1; 2; 3]
Using those two, you can insert an element in the ‘middle’ of the list like this:
let a, b = [1; 2], [4; 5; 6]
let c = a @ (3 :: b)
> [1; 2; 3; 4; 5]
We’re talking regular singly linked lists here, however, so no indexing into the list. You have to split it by other means (function calls) if you want the element inserted at an arbitrary position.
The same applies to other ML family members: SML, OCaml, Scala and also Haskell (it uses :
and ++
respectively, though).
Why would you actually want list insertion as part of syntax? It’s a fairly uncommon operation, and I’d question the wisdom of creating special syntax for this when a regular function should work just fine.
Note that if you are using a Lisp, it’s trivial to add new syntax using macros.
Here’s an example in Clojure:
(defmacro insert [list at [start end] in target]
(when-not (and (= "at" (name at)) (= "in" (name in)))
(throw (Error. "Syntax error: should be like (insert <values> at [3 4] in <target-list>)")) )
`(let [target# ~target ]
(concat
(take ~start target#)
~list
(drop ~end target#))))
(insert [:a :b :c] at [3 4] in [1 2 3 4 5])
=> (1 2 3 :a :b :c 5)
Note that this isn’t a function: we have genuinely created new syntax (see the “at” and “in” symbols – this wouldn’t work as a regular function)
I still don’t recommend doing this (you should normally prefer a regular function), but the feature is there if you want it….
2