Why can't I aplly anonymous functions to lists? - functional-programming

So I'm trying to learn Elixir (I have a background o F# and Haskell) and I'm having difficulties understanging what is going on in my code:
fizz_buzz = fn
(0, 0, _) -> "FizzBuzz"
(0, _, _) -> "Fizz"
(_, 0, _) -> "Buzz"
(_, _, c) -> c
end
fizz_buzz_rem = fn n -> fizz_buzz.(rem(n, 3), rem(n, 5), n) end
# This works
IO.puts(fizz_buzz_rem.(10))
IO.puts(fizz_buzz_rem.(11))
IO.puts(fizz_buzz_rem.(12))
IO.puts(fizz_buzz_rem.(13))
IO.puts(fizz_buzz_rem.(14))
IO.puts(fizz_buzz_rem.(15))
IO.puts(fizz_buzz_rem.(16))
IO.puts(fizz_buzz_rem.(17))
IO.puts("----------------")
inputs =
10..17
|> Enum.to_list
# Doesn't work
inputs
|> Enum.map(fizz_buzz_rem)
|> IO.puts
IO.puts("----------------")
# Doesn't work
inputs
|> Enum.map(fn n -> fizz_buzz.(rem(n, 3), rem(n, 5), n) end)
|> IO.puts
IO.puts("----------------")
manual_inputs = [10, 11, 12, 13, 14, 15, 16, 17]
# Doesn't work
manual_inputs
|> Enum.map(fizz_buzz_rem)
|> IO.puts
IO.puts("----------------")
# Doesn't work
manual_inputs
|> Enum.map(fn n -> fizz_buzz.(rem(n, 3), rem(n, 5), n) end)
|> IO.puts
IO.puts("----------------")
# The idiotic way (that doesn't work)
result = [
fizz_buzz_rem.(10),
fizz_buzz_rem.(11),
fizz_buzz_rem.(12),
fizz_buzz_rem.(13),
fizz_buzz_rem.(14),
fizz_buzz_rem.(15),
fizz_buzz_rem.(16),
fizz_buzz_rem.(17),
]
IO.puts result
# ???????????
When I run elixir ex_02.exs the output is:
Buzz
FizzBuzz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
----------------
Buzz
FizzBuzz
----------------
Buzz
FizzBuzz
----------------
Buzz
FizzBuzz
----------------
Buzz
FizzBuzz
So as you can see when I apply the anonymous function to each value individually I get the right answer bu when I try to use ranges, maps and even apply the function to each element of a list manually I end up with the wrong result.
What am I getting wrong about aplying a anonymous function to a list in elixir?

If you use IO.inspect instead of IO.puts, you can see what's going on:
["Buzz", 11, "Fizz", 13, 14, "FizzBuzz", 16, 17]
Your fizzbuzz function returns either a string or an integer, depending on the input. IO.puts treats integers differently depending on whether they're in a list:
iex(1)> IO.puts(65)
65
:ok
iex(2)> IO.puts([65])
A
:ok
So in your code, IO.puts actually prints the control codes corresponding to the integers 11, 13, 14, 16 and 17. In my terminal it shows up as:
Buzz^KFizz^M^NFizzBuzz^P^Q
You can fix this by making your function always return strings:
fizz_buzz = fn
(0, 0, _) -> "FizzBuzz"
(0, _, _) -> "Fizz"
(_, 0, _) -> "Buzz"
(_, _, c) -> "#{c}"
end

Related

Create a repeat function in SML

I am working on creating a function called repeat that takes two int lists lst1 and lst2. Assume that lst2 only has nonnegative integers, repeats the integers in the first list lst1 according to the numbers indicated by the second list lst2. If both lists are empty, return an empty list. You may need a local function.
Example:
repeat ([1,2,3], [4,0,3]) -> [1,1,1,1,3,3,3]
I am having a little trouble with getting started with this function. What should I put after the xs?
fun repeat(lst1, lst2) =
case lst1 of
[] => []
| x::xs' => [] (* what should I put here *)
Like any recursion problem, what's your base case? I'd say in this case it's both lists are empty and it gives you an empty list.
fun repeat([], []) = []
What if one is empty but the other isn't? That's a failure. Let's define an exception we can throw if this happens.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
Now the real question is what we do the rest of the time. Fortunately, SML makes it easy to pattern match both lists and extract their first elements.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) = ...
At this point, we need a recursive function to repeat an element of the list a certain number of times. As with the overall function, here we see the two hallmarks of recursion: at least one base "exit" condition, and an update step where we converge toward the base condition by updating n to n - 1.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) =
let
fun repeat'(_, 0) = []
| repeat'(x, n) = x :: repeat'(x, n - 1)
in
...
end
Now, we just need to put it all together, by feeding x and y to repeat' and then concatenating that with the result of calling repeat again with xs and ys. By doing this, we converge down toward the base case of repeat([], []) or we may converge toward a mismatched scenario where a MismatchedArguments exception is raised.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) =
let
fun repeat'(_, 0) = []
| repeat'(x, n) = x :: repeat'(x, n - 1)
in
repeat'(x, y) # repeat(xs, ys)
end
Now repeat([1, 2, 3], [4, 0, 3]) will yield [1, 1, 1, 1, 3, 3, 3].

How do I abort a scan but retain the flag element of the sequence: skipToOrDefault

I have a sequence of Result and I would like to accumulate all the Error values yet abort processing and return the first Ok value found. Specifically, I would like to abort processing the remainder of the list. Unfortunately, the approach I have preserves the first Ok found but does not abort processing the rest of the list.
let process : Result<'t, string list> -> Result<'t, string list> =
let st0 = Error []
let acc st e =
match st, e with
| Ok _ , _ -> st
| _ , Ok _ -> e
| Error v, Error vs -> Error (v ++ vs)
Seq.scan acc st0
|> Seq.last
Ideally, a Seq.skipToOrDefault and Seq.takeToOrDefault methods would be nice to have for this.
From your comments, it has become clear that what you'd like to do is to avoid iterating over the whole sequence, stopping once you encounter the first Ok.
Well, sequences already do that by default (they're lazy), and the scan function preserves that property. Let's check:
let mySeq = seq {
for i in 0..3 do
printfn "Returning %d" i
yield i
}
mySeq |> Seq.toList |> ignore
> Returning 0
> Returning 1
> Returning 2
> Returning 3
mySeq |> Seq.take 2 |> Seq.toList |> ignore
> Returning 0
> Returning 1
mySeq
|> Seq.scan (fun _ x -> printfn "Scanning %d" x) ()
|> Seq.take 3
|> Seq.toList |> ignore
> Returning 0
> Scanning 0
> Returning 1
> Scanning 1
Look: we never see "Returning 2" and "Returning 3" after the scan. That's because we're not iterating over the whole sequence, only the piece we need, as determined by Seq.take 3.
But the thing that does force the full iteration in your code is Seq.last. After all, in order to get the last element, you need to iterate over the whole sequence, there is no other way.
But what you can do is stop iteration when you need via Seq.takeWhile. This function takes a predicate and returns only the elements for which the predicate is true, excluding the first one that yields false:
mySeq |> Seq.takeWhile (fun x -> x < 2) |> Seq.toList |> ignore
> Returning 0
> Returning 1
> Returning 2
> val it : int list = [0; 1]
The difficulty in your case is that you also need to return the element that breaks the predicate. In order to do that, you can deploy a little hack: keep around in your folding state a special flag stop: bool, initially set it to false, and switch to true on the element immediately succeeding the one where you need to stop. To keep such state, I am going to use a record:
let st0 = {| prev = Error []; stop = false |}
let acc (s: {| prev: Result<_,string>; stop: bool |}) x =
match s.prev, x with
| Ok _, _ -> {| s with stop = true |} // Previous result was Ok => stop now
| _, Ok _ -> {| s with prev = x |} // Don't stop, but remember the previous result
| Error a, Error b -> {| s with prev = Error (a # b) |}
sourceSequence
|> Seq.scan acc st0
|> Seq.takeWhile (fun s -> not s.stop)
|> Seq.last
|> (fun s -> s.prev)
P.S. also note that in F# list concatenation is #, not ++. Are you coming from Haskell?
I think this is a better solution. However, there is some confusion as to whether Seq.tryPick is always side effect free regardless of the underlying sequence. For list it is such that Seq.tail is required here to advance through it...
let rec scanTo (pred:'u -> bool) (acc:'u -> 'a -> 'u) (st0:'u) (ss:'a seq) = seq {
let q =
ss
|> Seq.tryPick Some
|> Option.bind (acc st0 >> Some)
match q with
| None -> yield! Seq.empty
| Some v when pred v -> yield v
| Some v -> yield v; yield! (scanTo pred acc v (Seq.tail ss))
}
For instance...
let process : Result<'v, string list> seq -> Result<'v, string list> seq = fun aa ->
let mergeErrors acc e =
match acc, e with
| Error ms, Error m -> Error (m # ms)
| _, Ok v -> Ok v
| _, Error m -> Error m
let st0 = Error []
let isOk = function
| Ok _ -> true
| _ -> false
scanTo isOk mergeErrors st0 aa

Elixir Get Map containing maximum values of specific field

I'm a beginner in Elixir programming language.
I have an object something like this:
{
id: uuid,
created_at: DateTime.t,
updated_at: DateTime.t,
type: my_type
}
let's say my_type is one of ~w[A B C D]
I want to write a function which takes a list of these objects and returns a following map:
%{
A: 120,
B: 220,
C: 560,
D: 0,
any: 560
}
The values here has to be the MAXIMUM difference between updated_at and created_at columns(Timex.diff(updated_at, created_at, :seconds)) per my_type + any in addition.
In case of any the my_type is not considered and takes the maximum among all objects in the list.
What is the best way to do it in Elixir? Thanks.
The following will group the list by its type, then calculate the max difference for each group, and finally result in a map containing each type as the key and max difference as the value.
map = list
|> Enum.group_by(& &1.type)
|> Enum.map(fn {type, values} ->
max =
values
|> Enum.map(fn %{created_at: created_at, updated_at: updated_at} ->
# return the difference here
end)
|> Enum.max
{type, max}
end)
|> Map.new
This should give you something like:
%{
A: 120,
B: 220,
C: 560,
D: 0
}
You can calculate the value for any now by doing map |> Map.values |> Enum.max.
I am posting this here for the sake of formatting and diversity. The answer by #Dogbert is likely better fit, although this approach could be more straightforward and arguably flexible.
list = [%{type: :a, v1: 10, v2: 20},
%{type: :a, v1: 10, v2: 30},
%{type: :b, v1: 10, v2: 20},
%{type: :c, v1: 10, v2: 20}]
kw = for %{type: t, v1: v1, v2: v2} <- list,
do: {t, v2 - v1}, into: []
#⇒ [a: 10, a: 20, b: 10, c: 10]
kw
|> Enum.sort_by(fn {_, v} -> v end, &>=/2)
|> Enum.uniq_by(fn {k, _} -> k end)
#⇒ [a: 20, b: 10, c: 10]

Julia splat operator unpacking

In Python, one can use the * operator in the unpacking of an iterable.
In [1]: head, *tail = [1, 2, 3, 4, 5]
In [2]: head
Out[2]: 1
In [3]: tail
Out[3]: [2, 3, 4, 5]
I would like to produce the same behavior in Julia. I figured that the equivalent ... operator would work, but it seems to just produce an error in this context.
julia> head, tail... = [1, 2, 3, 4, 5]
ERROR: syntax: invalid assignment location "tail..."
I was able to produce the results I want using the following, but this is an ugly solution.
julia> head, tail = A[1], A[2:end]
(1,[2,3,4,5])
Can I unpack the array such that tail would contain the rest of the items after head using the splat (...) operator? If not, what is the cleanest alternative?
Edit: This feature has been proposed in #2626. It looks like it will be part of the 1.0 release.
As of Julia 1.6
It is now possible to use ... on the left-hand side of destructured assignments for taking any number of items from the front of an iterable collection, while also collecting the rest.
Example of assigning the first two items while slurping the rest:
julia> a, b, c... = [4, 8, 15, 16, 23, 42]
# 6-element Vector{Int64}:
# 4
# 8
# 15
# 16
# 23
# 42
julia> a
# 4
julia> b
# 8
julia> c
# 4-element Vector{Int64}:
# 15
# 16
# 23
# 42
This syntax is implemented using Base.rest, which can be overloaded to customize its behavior.
Example of overloading Base.rest(s::Union{String, SubString{String}}, i::Int) to slurp a Vector{Char} instead of the default SubString:
julia> a, b... = "hello"
julia> b
# "ello"
julia> Base.rest(s::Union{String, SubString{String}}, i=1) = collect(SubString(s, i))
julia> a, b... = "hello"
julia> b
# 4-element Vector{Char}:
# 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
# 'l': ASCII/Unicode U+006C (category Ll: Letter, lowercase)
# 'l': ASCII/Unicode U+006C (category Ll: Letter, lowercase)
# 'o': ASCII/Unicode U+006F (category Ll: Letter, lowercase)
That does indeed sound like a job for a macro:
function unpack(lhs, rhs)
len = length(lhs.args)
if len == 1
# just remove the splatting
l, is_splat = remove_splat(lhs.args[1])
return :($l = $(esc(rhs)))
else
new_lhs = :()
new_rhs = quote
tmp = $(esc(rhs))
$(Expr(:tuple))
end
splatted = false
for (i, e) in enumerate(lhs.args)
l, is_splat = remove_splat(e)
if is_splat
splatted && error("Only one splatting operation allowed on lhs")
splatted = true
r = :(tmp[$i:end-$(len-i)])
elseif splatted
r = :(tmp[end-$(len-i)])
else
r = :(tmp[$i])
end
push!(new_lhs.args, l)
push!(new_rhs.args[4].args, r)
end
return :($new_lhs = $new_rhs)
end
end
remove_splat(e::Symbol) = esc(e), false
function remove_splat(e::Expr)
if e.head == :(...)
return esc(e.args[1]), true
else
return esc(e), false
end
end
macro unpack(expr)
if Meta.isexpr(expr, :(=))
if Meta.isexpr(expr.args[1], :tuple)
return unpack(expr.args[1], expr.args[2])
else
return unpack(:(($(expr.args[1]),)), expr.args[2])
end
else
error("Cannot parse expression")
end
end
It is not very well tested, but basic things work:
julia> #unpack head, tail... = [1,2,3,4]
(1,[2,3,4])
julia> #unpack head, middle..., tail = [1,2,3,4,5]
(1,[2,3,4],5)
A few Julia gotchas:
x,y = [1,2,3] #=> x = 1, y = 2
a = rand(3)
a[1:3], y = [1,2,3] #=> a = [1.0,1.0,1.0], y = 2
The macro follows this behavior
#unpack a[1:3], y... = [1,2,3]
#=> a=[1.0,1.0,1.0], y=[2,3]

Return the index for a list from a list in Erlang

I've been practicing using recursion to define the index in Erlang. Here I need to implement a function to return the index for a list from a list.
eg.
([2, 4, 4], [1, 1, 2, 4, 4, 3, 4 ]) ----> 2
([1, 3], [5, 2, 2, 3, 1, 3, 5]) ----> 4
([1], [3, 2, a, {1, 1}, 1] ----> 4
Here is my code:
-module(project).
-export([index/2]).
index([X|XS],[_]) -> index([X|XS],[_],1).
index(_,[],_) -> [];
index([X|XS],[X|_], ACC) -> ACC;
index([X|XS],[_|rest],ACC) ->index([X|XS],rest,ACC+1).
I modified and coded logically but it still can not being compiled. I hope someone who can help me with it. Thanks!
Just for fun, here is an implementation that is not written a very clean way, but illustrates the techniques I think you are looking for. Note there are two basic states: "checking" and "matching".
-module(sublistmatch).
-export([check/2]).
check(Segment, List) ->
SegLen = length(Segment),
ListLen = length(List),
Index = 1,
check(Segment, List, SegLen, ListLen, Index).
check(S, S, _, _, I) ->
{ok, I};
check(_, _, SL, LL, _) when SL >= LL ->
nomatch;
check(S = [H|Ss], [H|Ls], SL, LL, I) ->
case matches(Ss, Ls) of
true -> {ok, I};
false -> check(S, Ls, SL, LL - 1, I + 1)
end;
check(S, [_|L], SL, LL, I) ->
check(S, L, SL, LL - 1, I + 1).
matches([H|S], [H|L]) -> matches(S, L);
matches([], _) -> true;
matches(_, _) -> false.
Note that this depends on knowing the lengths of both the segment you are checking for, and the current length of the remaining list to check. Consider why this is necessary. Also consider how using the utility function matches/2 gives us a natural place to explore whether an option matches, and backtracks if it does not.
In real programs you would use the standard library functions such as lists:prefix/2, lists:suffix/2, or sets:is_subset/2, or maybe some key or member operation over a gb_tree, dict, map or array depending on the situation.
To Compile the code you have to change it to:
-module(project).
-export([index/2]).
%%index([X|XS],[_]) -> index([X|XS],[_],1).
index([X|XS],List) -> index([X|XS],List,1).
%% you shuld not pass '_' as parameter it's will be marked as unbound
index(_,[],_) -> [];
index([X|XS],[X|_], ACC) -> ACC;
%%index([X|XS],[_|rest],ACC) ->index([X|XS],rest,ACC+1).
index([X|XS],[_|Rest],ACC) ->index([X|XS],Rest,ACC+1).
%% rest is an atom, it's not the case you need to use here.
%%Variables should start with upper case letter.
This code will compiled but wrong results as some cases.

Resources