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.
Related
I need to convert Elixir function into Erlang function:
In Elixir I have:
Enum.map(0..n, fn i-> fun(i) end)
And I need to re-write to Erlang.
Any Idea? Thanks
Erlang doesn't have a single generic function that can handle mapping over any data structure like Enum.map in Elixir. The simplest way to do this would be to use lists:seq to generate the list and lists:map:
1> lists:map(fun(X) -> X * X end, lists:seq(0, 10)).
[0,1,4,9,16,25,36,49,64,81,100]
Using list comprehensions:
[ F(X) || X <- lists:seq(0, 10) ].
aka
[ X*X || X <- lists:seq(0, 10) ].
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.
Is the -> operator in Clojure (and what is this operator called in Clojure-speak?) equivalent to the pipeline operator |> in F#? If so, why does it need such a complex macro definition, when (|>) is just defined as
let inline (|>) x f = f x
Or if not, does F#'s pipeline operator exist in Clojure, or how would you define such an operator in Clojure?
No, they are not the same. Clojure doesn't really have a need for |> because all function calls are enclosed in lists, like (+ 1 2): there's no magic you could do to make 1 + 2 work in isolation.1
-> is for reducing nesting and simplifying common patterns. For example:
(-> x (assoc :name "ted") (dissoc :size) (keys))
Expands to
(keys (dissoc (assoc x :name "ted") :size))
The former is often easier to read, because conceptually you're performing a series of operations on x; the former code is "shaped" that way, while the latter needs some mental unraveling to work out.
1 You can write a macro that sorta makes this work. The idea is to wrap your macro around the entire source tree that you want to transform, and let it look for |> symbols; it can then transform the source into the shape you want. Hiredman has made it possible to write code in a very Haskell-looking way, with his functional package.
It's called the "thread" operator. It's written as a macro as opposed to a normal function for performance reasons and so that it can provide a nice syntax - i.e. it applies the transformation at compile time.
It's somewhat more powerful than the |> operator you describe, as it's intended to pass a value through several functions, where each successive value is "inserted" as the first parameter of the following function calls. Here's a somewhat contrived example:
(-> [1]
(concat [2 3 4])
(sum)
((fn [x] (+ x 100.0))))
=> 110.0
If you want to define a function exactly like the F# operator you have described, you can do:
(defn |> [x f] (f x))
(|> 3 inc)
=> 4
Not sure how useful that really is, but there you are anyway :-)
Finally, if you want to pass a value through a sequence of functions, you can always do something like the following in clojure:
(defn pipeline [x & fns]
((apply comp fns) x))
(pipeline 1 inc inc inc inc)
=> 5
It is also worth noting that there is a ->> macro which will thread the form as the last argument:
(->> a (+ 5) (let [a 5] ))
The Joy of Clojure, chapter 8.1 talks about this subject a bit.
When reading source code (especially when speaking), I always pronounce the -> operator as "thread-first", and the ->> operator as "thread-last".
Keep in mind that there is now an operator as-> which is more flexible than either -> or ->>. The form is:
(as-> val name (form1 arg1 name arg2)...)
The value val is evaluated and assigned to the placeholder symbol name, which the user can place in ANY position in the following forms. I usually choose the word "it" for the placeholder symbol. We can mimic thread-first -> like so:
user=> (-> :a
(vector 1))
[:a 1]
user=> (as-> :a it
(vector it 1) )
[:a 1]
We can mimic thread-last ->> like so:
user=> (->> :a
(vector 2))
[2 :a]
user=> (as-> :a it
(vector 2 it) )
[2 :a]
Or, we can combine them in a single expression:
user=> (as-> :a it
(vector it 1)
(vector 2 it))
[2 [:a 1]]
user=> (as-> :a it
(vector it 1)
(vector 2 it)
(vector "first" it "last"))
["first" [2 [:a 1]] "last"]
I use this last form so much I have made a new operator it-> in the Tupelo Library:
(it-> 1
(inc it) ; thread-first or thread-last
(+ it 3) ; thread-first
(/ 10 it) ; thread-last
(str "We need to order " it " items." ) ; middle of 3 arguments
;=> "We need to order 2 items." )
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"
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.