how to have nested lists in Lua - list

I am trying to solve this problem from the 99 lisp problems
Flatten a nested list structure.
Transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively).
Example:
(my-flatten '(a (b (c d) e)))
(A B C D E)
Hint: Use the predefined functions list and append.
Problem is, I don't know how to create that nested list to begin with so I can try to flatten it myself. Please help thankyou

In Lua "a list possibly holding lists as elements" is just a table possibly holding tables as elements.
From the Lua manual:
Tables can be heterogeneous; that is, they can contain values of all
types (except nil).
...
Like indices, the values of table fields can be of any type
That of course includes tables.
The most trivial case is local t = {{}} or for the mentioned example (a (b (c d) e)) local t = {a, {b, {c, d}, e}}
Assuming a,b,c,d and e are strings your list would look like so:
local t = {"a", {"b", {"c", "d"}, "e"}

Related

Interpreter representation of a tuple to allow for efficient unpacking

My Implementation Attempt
I'm attempting to implement tuple unpacking in my interpreter. To represent a tuple, I'm using a class Tuple with a vector members that can store any value Value in the language:
typedef std::variant<int, float, std::string, Tuple> Value; //Note - ignore the "Tuple" circular dependency - this code is just for illustration purposes
class Tuple {
public:
const std::vector<Value> members;
Tuple(std::vector<Type> _members) : members(_members) {}
};
The unpacking of a tuple is python-like in syntax with a variable list on the LHS and the tuple on the right.
(a, (b, c), d) = (1, (2, 3), 4)
The RHS of the above code is represented by the tuple class above as Tuple example({1, Tuple({2, 3}), 4});
For some background, in my interpreter I'm using a AST with the visitor pattern to construct Value objects and assign them to variables when a assign statement is visited. The above RHS tuple object example is generated when a TupleNode representing the expression ((1, (2, 3), 4)) is visited. The entire statement ((a, (b, c), d) = (1, (2, 3), 4)) is represented by a UnpackNode with left side pointing to a vector of identifiers ((a, (b, c), d)) and right side pointing to the TupleNode previously discussed.
When a UnpackNode is visited, it first works out what the Tuple Object (example) and then iterates over every identifier on the LHS of the statement, assigning it to a members value of the Tuple object at the same index of the identifier on the LHS.
Concerns
Using the approach described above has caused significant performance hits when using tuples. The two code snippets below yields the same results but using the tuples and unpacking is approx ~20x slower.
(a, b, c) = (1, 2, 3) //approx 20x slower then equivalent code below
_______
a = 1
b = 2
c = 3
Is representing the contents of a Tuple with a vector of vectors a good idea (performance wise) considering that it will be iterated over quite frequently? Would it instead be a better idea to flatten the vector and use some other system to work out how to index the tuple (for situations where there is tuples of tuples)? What would be an efficient way to iterate over a tuple in order to extract certain values?
If anyone has any general advice or tips on tuple implementations of resources they could link that would very much be appreciated. Or if anyone has any criticisms with my approach or can suggest a better way of doing so please feel free to let me know. There's not a lot of material on tuple unpacking in relation to compiler/interpreter design so I would be very appreciative of any information that could be provided in the context of their implementation.

F# list of key value pairs to variable assignments

Given a list of key/value pairs:
do
[("A", 1);("B",2)]
|> (fun list ->
for item in list do
match item with
| ("A", x) -> //expression assigning x to variable "A"
| ("B", x) -> //expression assigning x to variable "B"
| _ -> //default expression
)
Are there some expressions I can write that will accomplish the same thing as
let A = 1
let B = 2
I know in advance that the list has no more than 10 items, and that the items are tuples of <string, int> but don't know in advance whether "A" or "B" or other keys may be present or if the list is be empty.
Basically, decompose the list into a set of typed variables.
UPDATE: Notes on Context
In my app I receive a list of key/value pairs just like this from an upstream program maintained by a different team. I expect certain keys to be in the list, which i want to assign to typed variables for later processing. I'll throw an exception if ones I need are missing. However I don't want to be locked in to any given set of variable names, except for the expected ones. For all of them, I want to be able to assign them at run time.
If you want to do something with the variables later on in the code, then they will need to be in scope - so you will inevitably have to declare the variables in some way. The easiest option is to make them mutable and mutate them according to the values in the list:
let mutable A = 0
let mutable B = 0
To make the mutation a bit easier, you can create a lookup table with setters:
let setters =
dict [ ("A", fun x -> A <- x); ("B", fun x -> B <- x) ]
This now lets you iterate over the inputs, use dictionary lookup to get the appropriate setter and invoke it to set the variable value:
for var, value in [("A", 1);("B",2)] do
setters.[var] value
With the limited context of your question, it is a bit hard to say whether this is a good way of achieving what actually motivated your question - as F# code, it does look like a bit ugly and it is likely that if you add more context, someone can suggest a better way.
It sounds like you have some dynamic data that can be represented well as a map:
let data = Map [ ("A", 1); ("B", 2) ]
let a = Map.find "A" data
// throws an exception if "A" is not present
let b = Map.find "B" data
// throws an exception if "B" is not present
let c = Map.tryFind "C" data
// "C" is not present so c = None
Note: In F# the convention is for binding names (variable names) to start with a lower case letter.

Understanding Prolog's empty lists

I am reading Bratko's Prolog: Programming for Artificial Intelligence. The easiest way for me to understand lists is visualising them as binary trees, which goes well. However, I am confused about the empty list []. It seems to me that it has two meanings.
When part of a list or enumeration, it is seen as an actual (empty) list element (because somewhere in the tree it is part of some Head), e.g. [a, []]
When it is the only item inside a Tail, it isn’t an element it literally is nothing, e.g. [a|[]]
My issue is that I do not see the logic behind 2. Why is it required for lists to have this possible ‘nothingness’ as a final tail? Simply because the trees have to be binary? Or is there another reason? (In other words, why is [] counted as an element in 1. but it isn't when it is in a Tail in 2?) Also, are there cases where the final (rightmost, deepest) final node of a tree is not ‘nothing’?
In other words, why is [] counted as an element in 1. but it isn't when it is in a Tail in 2?
Those are two different things. Lists in Prolog are (degenerate) binary trees, but also very much like a singly linked list in a language that has pointers, say C.
In C, you would have a struct with two members: the value, and a pointer to the next list element. Importantly, when the pointer to next points to a sentinel, this is the end of the list.
In Prolog, you have a functor with arity 2: ./2 that holds the value in the first argument, and the rest of the list in the second:
.(a, Rest)
The sentinel for a list in Prolog is the special []. This is not a list, it is the empty list! Traditionally, it is an atom, or a functor with arity 0, if you wish.
In your question:
[a, []] is actually .(a, .([], []))
[a|[]] is actually .(a, [])
which is why:
?- length([a,[]], N).
N = 2.
This is now a list with two elements, the first element is a, the second element is the empty list [].
?- [a|[]] = [a].
true.
This is a list with a single element, a. The [] at the tail just closes the list.
Question: what kind of list is .([], [])?
Also, are there cases where the final (rightmost, deepest) final node of a tree is not ‘nothing’?
Yes, you can leave a free variable there; then, you have a "hole" at the end of the list that you can fill later. Like this:
?- A = [a, a|Tail], % partial list with two 'a's and the Tail
B = [b,b], % proper list
Tail = B. % the tail of A is now B
A = [a, a, b, b], % we appended A and B without traversing A
Tail = B, B = [b, b].
You can also make circular lists, for example, a list with infinitely many x in it would be:
?- Xs = [x|Xs].
Xs = [x|Xs].
Is this useful? I don't know for sure. You could for example get a list that repeats a, b, c with a length of 7 like this:
?- ABCs = [a,b,c|ABCs], % a list that repeats "a, b, c" forever
length(L, 7), % a proper list of length 7
append(L, _, ABCs). % L is the first 7 elements of ABCs
ABCs = [a, b, c|ABCs],
L = [a, b, c, a, b, c, a].
In R at least many functions "recycle" shorter vectors, so this might be a valid use case.
See this answer for a discussion on difference lists, which is what A and Rest from the last example are usually called.
See this answer for implementation of a queue using difference lists.
Your confusion comes from the fact that lists are printed (and read) according to a special human-friendly format. Thus:
[a, b, c, d]
... is syntactic sugar for .(a, .(b, .(c, .(d, [])))).
The . predicate represents two values: the item stored in a list and a sublist. When [] is present in the data argument, it is printed as data.
In other words, this:
[[], []]
... is syntactic sugar for .([], .([], [])).
The last [] is not printed because in that context it does not need to. It is only used to mark the end of current list. Other [] are lists stored in the main list.
I understand that but I don't quite get why there is such a need for that final empty list.
The final empty list is a convention. It could be written empty or nil (like Lisp), but in Prolog this is denoted by the [] atom.
Note that in prolog, you can leave the sublist part uninstantiated, like in:
[a | T]
which is the same as:
.(a, T)
Those are known as difference lists.
Your understanding of 1. and 2. is correct -- where by "nothing" you mean, element-wise. Yes, an empty list has nothing (i.e. no elements) inside it.
The logic behind having a special sentinel value SENTINEL = [] to mark the end of a cons-cells chain, as in [1,2,3] = [1,2|[3]] = [1,2,3|SENTINEL] = .(1,.(2,.(3,SENTINEL))), as opposed to some ad-hoc encoding, like .(1,.(2,3)) = [1,2|3], is types consistency. We want the first field of a cons cell (or, in Prolog, the first argument of a . functored term) to always be treated as "a list's element", and the second -- as "a list". That's why [] in [1, []] counts as a list's element (as it appears as a 1st argument of a .-functored compound term), while the [] in [1 | []] does not (as it appears as a 2nd argument of such term).
Yes, the trees have to be binary -- i.e. the functor . as used to encode lists is binary -- and so what should we put there in the final node's tail field, that would signal to us that it is in fact the final node of the chain? It must be something, consistent and easily testable. And it must also represent the empty list, []. So it's only logical to use the representation of an empty list to represent the empty tail of a list.
And yes, having a non-[] final "tail" is perfectly valid, like in [1,2|3], which is a perfectly valid Prolog term -- it just isn't a representation of a list {1 2 3}, as understood by the rest of Prolog's built-ins.

Interleaving in OCaml

I am trying to create a function which interleaves a pair of triples such as ((6, 3, 2), ( 4, 5 ,1)) and create a 6-tuple out of this interleaving.
I made some research but could understand how interleaving is supposed to work so I tried something on my own end ended up with a code that is creating a 6-tuple but not in the right interleaved way. This is my code
let interleave ((a, b, c), (a', b', c')) =
let sort2 (a, b) = if a > b then (a, b) else (b, a) in
let sort3 (a, b, c) =
let (a, b) = sort2 (a, b) in
let (b, c) = sort2 (b, c) in
let (a, b) = sort2 (a, b) in
(a, b, c) in
let touch ((x), (y)) =
let (x) = sort3 (x) in
let (y) = sort3 (y) in
((x),(y)) in
let ((a, b, c), (a', b', c')) = touch ((a, b, c), (a', b', c')) in
(a, b', a', b, c, c');;
Can someone please explain to me how with what functions I can achieve a proper form of interleaving. I haven't learned about recursions and lists in case you would ask why I am trying to do it this way.
Thank you already.
The problem statement uses the word "max" without defining it. If you use the built-in compare function of OCaml as your definition, it uses lexicographic order. So you want the largest value (of the 6 values) in the first position in the 6-tuple, the second largest value next, and so on.
This should be pretty easy given your previously established skill with the sorting of tuples.
For what it's worth, there doesn't seem to be much value in preserving the identities of the two 3-tuples. Once inside the outermost function you can just work with the 6 values as a 6-tuple. Or so it would seem to me.
Update
From your example (should probably have given it at the beginning :-) it's pretty clear what you're being asked to do. You want to end up with a sequence in which the elements of the original tuples are in their original order, but they can be interleaved arbitrarily. This is often called a "shuffle" (or a merge). You have to find the shuffle that has the maximum value lexicographically.
If you reason this out, it amounts to taking whichever value is largest from the front of the two tuples and putting it next in the output.
This is much easier to do with lists.
Now that I understand what your end-goal is . . .
Since tuples of n elements are different types for different n's, you need to define helper functions for manipulating different sizes of tuples.
One approach, that basically mimics a recursive function over lists (but requires many extra functions because of tuples all having different types), is to have two sets of helper functions:
functions that prepend a value to an existing tuple: prepend_to_2, up through prepend_to_5. For example,
let prepend_to_3 (a, (b, c, d)) = (a, b, c, d)
functions that interleave two tuples of each possible size up to 3: interleave_1_1, interleave_1_2, interleave_1_3, interleave_2_2, interleave_2_3, and interleave_3_3. (Note that we don't need e.g. interleave_2_1, because we can just call interleave_1_2 with the arguments in the opposite order.) For example,
let interleave_2_2 ((a, b), (a', b')) =
if a > a'
then prepend_to_3 (a, interleave_1_2 (b, (a', b')))
else prepend_to_3 (a', interleave_1_2 (b', (a, b)))
(Do you see how that works?)
Then interleave is just interleave_3_3.
With lists and recursion this would be much simpler, since a single function can operate on lists of any length, so you don't need multiple different copies of the same logic.

OCaml map on a tuple

I have several places in my code which look like this:
let (a,b,c) = (f "a", f "b", f "c")
It would be nice if I can write something like:
let (a,b,c) = map f ("a", "b", "c")
If there is way to do something like this in OCaml?
You can easily write map for triples of one type of element:
let map_triple f (a, b, c) = (f a, f b, f c)
let a, b, c = map_triple String.length ("foo", "bar", "quux")
It will only work for one length of tuple, however.
It would be possible to write a GADTified tuple type and write a map over that type that is polymorphic in the length of the tuple, but that kind of trickery is best avoided unless the advantage is large, which does not seem to be the case here.
The best answer is that you can't do this, if you want it to work for tuples of different sizes. Each tuple size is a different type in OCaml. So there's no OCaml type representing the idea of "a tuple of any size whose elements are strings."
But in fact this sounds like a list more than a tuple. If you can use lists instead of tuples, you can use the plain old List.map function.