What does || mean in Erlang? - erlang

I found that there is a || in list manipulation. What does the || mean? Are there any examples about ||?
lists:sum([A*B || {A, B} <- Foo]).

It is used in List comprehensions. List comprehensions is a shorter way to create lists without having to use funs, maps or filters.
From Programming Erlang:
If we have a list L:
L = [1,2,3,4,5].
And we want to double every element, we can do:
lists:map(fun(X) -> 2*X end, L).
But with List comprehensions we can do:
[2*X || X <- L].

Nomenclature most likely comes from mathematical notion of sets, where || means "such that".
e.g. copied from Wikipedia
F = {n2 − 4 : n is an integer; and 0 ≤ n ≤ 19}
In this notation, the colon (":") means "such that", and the description can be interpreted as "F is the set of all numbers of the form n2 − 4, such that n is a whole number in the range from 0 to 19 inclusive." Sometimes the vertical bar ("|") is used instead of the colon.
Applying same thing to
lists:sum([A*B || {A, B} <- Foo]).
means:- generate A*B such that A and B belong to list of tuples "Foo"

Related

What does | and || mean in Erlang?

I have checked the erlang websites operators etc but i cannot find what || and | Means.
I read somewhere that || means "such that" but what does just one " | " mean?
| is the "cons" operator: It puts an element in front of a list:
1> [1 | [2,3]].
[1,2,3]
2> [[1, 2] | [3,4,5]].
[[1,2],3,4,5]
|| is used in list-comprehensions. In its simplest form, it can be used as a short-hand for map:
3> [2 * X || X <- [1,2,3]].
[2,4,6]
But it becomes much more handy when you want to write multiple generators, creating the cartesian product:
4> [{X, Y} || X <- [1,2,3], Y <- [4, 5, 6]].
[{1,4},{1,5},{1,6},{2,4},{2,5},{2,6},{3,4},{3,5},{3,6}]
You can also do filter along the way. Compare:
5> [X+Y || X <- [1,2,3], Y <- [4,5,6]].
[5,6,7,6,7,8,7,8,9]
to:
6> [X+Y || X <- [1,2,3], Y <- [4,5,6], X+Y > 6].
[7,7,8,7,8,9]
The | operator is essential, in the sense that it is the canonical way how you construct a new list out of an existing head element and a tail of the list. The same notation also works in pattern matching, i.e., it is also how you deconstruct a list.
On the other hand, list comprehensions are mostly syntactic sugar: They can be written using regular function applications and hence is not fundamental to the language. But they can significantly improve readability by getting rid of syntactic noise, mimicking set-comprehension like mathematical notation directly within the language.

Pumping Lemma Assistance

I recently had an assignment where I was asked to use pumping lemma to show that a language was not regular, and unfortunately got the wrong answer.
The language to prove is non-regular is as follows:
L = {ai bj ck: i = j or j = k}
The definition of a pumping lemma that I was given is as follows:
opponent picks m
I want to pick w to contradict the pumping lemma. Use m to pick a string w ∈ L where |w| ≥ m
opponent picks a decomposition of w subject to constraints.
I try to pick an i so that the pumped string wi ∉ L. If found, L is not regular
This subject has proven to be very difficult for me to understand and I feel like a complete airhead because of it, so a detailed explanation as to how I would properly apply a pumping lemma would be appreciated.
Intuitively, the pumping lemma says that long enough words (the length depends only on the language L) in a regular language L must contain a section (of length > 0) which can be repeated as often as desired. Repeating that section ('pumping' the original word) any number of time results in some longer words which are also in the language L.
The minimal length for the word is the m in the first step of the above definition; the number of times the section is repeated is the i in the 4th step of the above definition.
The pumping lemma is usually used to show that a language L is not regular. It is a proof by contradiction: assume that L is regular and thus the pumping lemma for regular languages is true for L. Then pick a word w which is in L of sufficient length* and show that regardless of how it is decomposed* some pumped word is not in the language. This contradicts the pumping lemma - which we know to be true. Thus our assumption that the language is regular was wrong and thus the language is not regular. The parts marked with an * cannot be chosen to make things easy - that's why in steps 1 and 3 the 'opponent' selects them.
The word w is rewritten as w = x y z, where | y | > 0 and |x y| <= m. Both x and z may be of length 0.
The usual approach is to pick xy to be a string consisting of the same letter such that having more of that same letter (after the pumping) leads to a word not in L.
No restrictions are specified for the i or the k in the language L in the post, so assuming that i = 0 is allowed, a suitable word might be b^m c^m (that is m bs followed by m cs). Now whatever decomposition the opponent might select, the y will always consist of some bs. Repeating those bs leads to a word with more bs than cs and no as, and thus i != j and j!= k and the word is not in the language.

QuickSort example in Erlang

I have a question about an Erlang QuickSort implementation:
qsort([]) -> [];
qsort([Pivot|T]) -> qsort([X || X <- T, X < Pivot]) ++ [Pivot] ++ qsort([X || X <- T, X >= Pivot]).
The code above is from a book named Erlang Programming, and I don't understand why the second function has a code snippet X >= Pivot. Why >= but not > when there is already ++[Pivot]++ in the middle of this section of the function?
[Pivot] basically puts the single element Pivot into a list for the purpose of concatenating with the other 2 lists. It doesn't account for other elements with the same value in your input. Therefore, you need to handle it in either the left or right side of your implementation to ensure that such values are not left out when returning the sorted list.
e.g. Let's say your input list is [5,3,6,5,2,7]. There are three sublists that you need to deal with:
[Pivot] = [5]
[X || X <- T, X < Pivot] = [3,2]
[X || X <- T, X > Pivot] = [6,7]
But what about the second "5" in your input? It doesn't figure in any of the above sublists, so when you combine them to get the sorted list out, it's not there any more! Now, if you were to modify either sublist 2 or 3 to check for equality as well, you would get new sublists [3,2,5] or [6,5,7], making sure that all elements in input are considered. Note that it is symmetrical, so you can use "<=" in the left side instead of ">=" in the right side as in your example.

removing piped dot in string common lisp

my task is to parse that list
(100 30 5 . 50 6)
to number 135.56
format of input list is always the same
and I've wrote:
(reduce
'string-concat
(mapcar
(lambda (x) (remove #\0 x))
(mapcar
'write-to-string
l
)
)
)
and output I've "135|.|56"
and then read-from-string does'n read it, so...
have You any idea how I can do this parsing?
using or not code above
Your approach does not look particular robust. Also it is kind of difficult to understand what the input list is. Is the dot a symbol, like in |.|? The vertical bars are escaping the name, so that it does not collide with the built-in usage of the dot character in Lisp. It is used in dotted pairs, which stand for cons cells: (a . b).
If it is a symbol, then you can write the symbol without escaping to a string. First, with escaping:
CL-USER 5 > (write-to-string '|.|)
"\\."
Next, without:
CL-USER 6 > (princ-to-string '|.|)
"."
Your list (100 30 5 . 50 6) isn't a valid list structure in Common Lisp. A "dotted pair" must have only one element after the dot. If you want to know more about it, look at your favorite Common Lisp Book how lists are build from cons cells. (For example Peter Seibels "Practical Common Lisp")
So you cannot parse this string as a list as such - you need to have a pre-processing step.
(defun pre-processing (str)
(let ((idx (position #\. str)))
(list (read-from-string (concatenate 'string (subseq str 0 idx) ")"))
(read-from-string (concatenate 'string "(" (subseq str (1+ idx)))))))
This function splits your string in two lists that you can process the way you want to.
CL-USER 1 > (pre-processing "(100 30 5 . 50 6)")
((100 30 5) (50 6))

List comprehension stop generating certain lists if sublist fails on check

I have a code, which generates all the possible variation (with the legnth of N) with repetition.
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L)].
For variation(3, [1,2,3,4]) it will generate:
[[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,1,4],[1,1,2,1],...]
I would like to check a condition during the generation of the lists. If a sublist fails, it should stop generating lists, that begins with the certain sublist.
For example if [1,1] sublist fails that condition (check), than it should not generate [1,1,1,1], [1,1,1,2] etc (all of those that begin with [1,1]).
I don't know if its possible with 1 list comprehension.
So far, I have this code:
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L), check([H|T]) ].
This solution will only return those lists, that doesn't fail the condition (it works, but really slow for big input).
If [1,1] fails, it will try to generate [1,1,1,2], but those will fail the check as well. I would need a solution, which doesn't try to generate lists that begin with [1,1,...] (or with a previously failing sublist).
One small detail first: According to your question, variations(3, [1,2,3]). should generate [[1,1,1,1], [1,1,1,2], …] but it actually generates [[1,1,1], [1,1,2], …]. I will assume the code was right and you meant to say that variations(4, [1,2,3]). should generate [[1,1,1,1], [1,1,1,2], …]
I wrote an alternative version of your function that, using a different order on the right side of the LC, avoids generating list when their prefix is already false when checked with check/1:
variation(1, L) ->
[ [Elem] || Elem <- L ];
variation(N, L) ->
[ Init ++ [Last] || Init <- variation(N-1, L), check(Init), Last <- L].
As you can see, since check(Init) happens before Last <- L, Last is only generated if check(Init) == true.
That will likely have the effect you were looking for.
But… be careful. I'm using ++ in the left side of the LC. You should definitely benchmark your code and see if that has an impact on performance or not.
If it does, and only if it does, you might want to consider using something like this:
variation3(1, L) ->
[ [Elem] || Elem <- L ];
variation3(N, L) ->
[ lists:reverse([Last|lists:reverse(Init)]) || Init <- variation2(N-1, L), check(Init), Last <- L].
Maybe worth it, maybe not… you will need to benchmark your stuff to figure that out.

Resources