How to use a non-lambda function with Map.update? - functional-programming

I'm sure I missed something obvious here, but I couldn't get Map.update to work with an externally defined unary function, which I thought should work. Elixir complains:
** (UndefinedFunctionError) function xxx/0 is undefined or private. Did you mean one of:
* xxx/1
Isn't the point of Map.update exactly to have a function that takes in the value being updated and returns a new value? Why would it want a zero-arity function? That doesn't seem to make much sense. I guess I'm just a bit fatigued but I just couldn't wrap my head around this.

Assume we have the following code.
defmodule Foo do
def add_one(x), do: x + 1
end
We can use Map.update/4 as follows.
Map.update(my_map, :a, 3, &Foo.add_one/1)
You can see this in an iex session
iex(1)> my_map = %{b: 3}
%{b: 3}
iex(2)> Map.update(my_map, :a, 3, &Foo.add_one/1)
%{a: 3, b: 3}
iex(4)> my_map = %{a: 12}
%{a: 12}
iex(5)> Map.update(my_map, :a, 3, &Foo.add_one/1)
%{a: 13}
I assume you are trying to use Map.update(my_map, :a, 3, Foo.add_one). When you do that, the compiler will try to call a function named Foo.add_one and pass the resulting value into the function. In your case, that function does not exist so it is giving you an error. Also note the & before the function name and the /1 at the end of it.
The & essentially tells the program to pass the function as an argument instead of calling it and passing in the resulting value.
The /1 says that the program should look for a function with that name with an arity (the number of arguments the function takes) of 1.

Related

How should I map over Maybe List?

I came away from Professor Frisby's Mostly Adequate Guide to Functional Programming with what seems to be a misconception about Maybe.
I believe:
map(add1, Just [1, 2, 3])
// => Just [2, 3, 4]
My feeling coming away from the aforementioned guide is that Maybe.map should try to call Array.map on the array, essentially returning Just(map(add1, [1, 2, 3]).
When I tried this using Sanctuary's Maybe type, and more recently Elm's Maybe type, I was disappointed to discover that neither of them support this (or, perhaps, I don't understand how they support this).
In Sanctuary,
> S.map(S.add(1), S.Just([1, 2, 3]))
! Invalid value
add :: FiniteNumber -> FiniteNumber -> FiniteNumber
^^^^^^^^^^^^
1
1) [1, 2, 3] :: Array Number, Array FiniteNumber, Array NonZeroFiniteNumber, Array Integer, Array ValidNumber
The value at position 1 is not a member of ‘FiniteNumber’.
In Elm,
> Maybe.map sqrt (Just [1, 2, 3])
-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm
The 2nd argument to function `map` is causing a mismatch.
4| Maybe.map sqrt (Just [1, 2, 3])
^^^^^^^^^^^^^^
Function `map` is expecting the 2nd argument to be:
Maybe Float
But it is:
Maybe (List number)
Similarly, I feel like I should be able to treat a Just(Just(1)) as a Just(1). On the other hand, my intuition about [[1]] is completely the opposite. Clearly, map(add1, [[1]]) should return [NaN] and not [[2]] or any other thing.
In Elm I was able to do the following:
> Maybe.map (List.map (add 1)) (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
Which is what I want to do, but not how I want to do it.
How should one map over Maybe List?
You have two functors to deal with: Maybe and List. What you're looking for is some way to combine them. You can simplify the Elm example you've posted by function composition:
> (Maybe.map << List.map) add1 (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
This is really just a short-hand of the example you posted which you said was not how you wanted to do it.
Sanctuary has a compose function, so the above would be represented as:
> S.compose(S.map, S.map)(S.add(1))(S.Just([1, 2, 3]))
Just([2, 3, 4])
Similarly, I feel like I should be able to treat a Just(Just(1)) as a Just(1)
This can be done using the join from the elm-community/maybe-extra package.
join (Just (Just 1)) == Just 1
join (Just Nothing) == Nothing
join Nothing == Nothing
Sanctuary has a join function as well, so you can do the following:
S.join(S.Just(S.Just(1))) == Just(1)
S.join(S.Just(S.Nothing)) == Nothing
S.join(S.Nothing) == Nothing
As Chad mentioned, you want to transform values nested within two functors.
Let's start by mapping over each individually to get comfortable:
> S.map(S.toUpper, ['foo', 'bar', 'baz'])
['FOO', 'BAR', 'BAZ']
> S.map(Math.sqrt, S.Just(64))
Just(8)
Let's consider the general type of map:
map :: Functor f => (a -> b) -> f a -> f b
Now, let's specialize this type for the two uses above:
map :: (String -> String) -> Array String -> Array String
map :: (Number -> Number) -> Maybe Number -> Maybe Number
So far so good. But in your case we want to map over a value of type Maybe (Array Number). We need a function with this type:
:: Maybe (Array Number) -> Maybe (Array Number)
If we map over S.Just([1, 2, 3]) we'll need to provide a function which takes [1, 2, 3]—the inner value—as an argument. So the function we provide to S.map must be a function of type Array (Number) -> Array (Number). S.map(S.add(1)) is such a function. Bringing this all together we arrive at:
> S.map(S.map(S.add(1)), S.Just([1, 2, 3]))
Just([2, 3, 4])

How can I specify the order of curried parameter application

I'm trying to convert the following to pointfree style: a function that partially applies a value to the transformer function add before passing in the collection to be iterated over. (Using Ramda.js)
R.compose(
R.map,
R.add
)(1, [1,2,3])
The problem is that R.add is arity 2, as is R.map. I want the application order to be as follows:
add(1)
map(add(1))
map(add(1), [1,2,3])
[add(1,1), add(1,2), add(1,3)]
But what happens instead is this:
add(1, [1,2,3])
map(add(1, [1,2,3]))
<partially applied map, waiting for collection>
Anyone know of a way to specify this behavior?
A plain compose or pipe won't do this because either will absorb all the arguments supplied into the first function. Ramda includes two additional functions that help with this, converge and useWith. In this case useWith is the one that will help:
useWith(map, [add, identity])(1, [1, 2, 3]); //=> [2, 3, 4]
While identity is not absolutely required here, it gives the generated function the correct arity.
Figured it out. If anyone's curious, here's the gist. (You can try it in the console on RamdaJS.com.)
0) For a baseline, here's the pointed version.
func0 = x => R.map(R.add(x))
addOne = func0(1)
addOne([1,2,3]) // [2,3,4]
1) Here's the pointfree core, but it has the ordering problem from the question above.
func1 = R.compose(R.map, R.add)
addOne = func1(1)
addOne([1,2,3]) // [2,3,4])
func1(1, [1,2,3]) // function
2) If the composition is unary (arity 1) 2 invocations are needed apply all params.
func2 = R.unary(R.compose(R.map, R.add))
addOne = func2(1)
addOne([1,2,3]) // [2,3,4])
3) We want one invocation to apply both params, so we uncurry 2.
func3 = R.uncurryN(2, func2)
func3(1, [1,2,3]) // [2,3,4])
4) To prove func2 is composable, let's double the results.
func4 = R.compose(
R.map(R.multiply(2)),
R.uncurryN(2, func2)
)
func4(1, [1,2,3]) // [4,6,8])
5) Substitution gives us a completely pointfree function.
func5 = R.compose(
R.map(R.multiply(2)),
R.uncurryN(2, R.unary(R.compose(
R.map,
R.add
)))
)
func5(1, [1,2,3]) // [4,6,8])

How does recursion work in Elixir

Simple function in Elixir, returning a list of numbers from to:
defmodule MyList do
def span(_), do: raise "Should be 2 args"
def span(from, to) when from > to, do: [ to | span(to + 1, from) ]
def span(from, to) when from < to, do: [ from | span(from + 1, to) ]
def span(from, to) when from == to, do: [ from ]
end
I have no slightest clue, why this works and return a list of numbers.
MyList.span(1,5)
#=> [1,2,3,4,5]
I just can't get my head around this:
[ from | span(from + 1, to) ]
Ok, first loop, I assume, would return the following:
[ 1 | span(2, 5) ]
What is next? [ 1, 2 | span(3, 5) ] ? Why?
How does it know, when to stop? Why is it even working?
Please, do not chase the points - don't bother answering, if you are not going to make an effort to make things clear(er) for functional programmer noob (OO programmer).
As a bonus to the answer you could provide me with a tips on how to start think recursively? Is there any panacea?
How does it keep track of the head? How does the function creates new list on each iteration keeping the values produced in the previous?
Thanks!
Ok, let's give this a shot.
Erlang evaluates function calls with a call-by-value strategy. From the linked wikipedia:
[call-by-value is a] family of evaluation strategies in which a function's argument is evaluated before being passed to the function.
What this means is that when Elixir (or rather Erlang) sees a function call with some arguments, it evaluates the arguments (which can obviously be expressions as well) before calling the function.
For example, let's take this function:
def add(a, b), do: a + b
If I call it with two expressions as arguments, those expressions will be evaluated before the the results are added up:
add(10 * 2, 5 - 3)
# becomes:
add(20, 2)
# kind of becomes:
20 + 2
# which results in:
22
Now that we get call-by-value, let's think of the | construct in list as a function for a moment. Think of it like if it would be used like this:
|(1, []) #=> [1]
|(29, [1, 2, 3]) #=> [29, 1, 2, 3]
As all functions, | evaluates its arguments before doing its work (which is creating a new list with the first argument as the first element and the second argument as the rest of the list).
When you call span(1, 5), it kind of expands (let's say it expands) to:
|(1, span(2, 5))
Now, since all arguments to | have to be evaluated before being able to actually prepend 1 to span(2, 5), we have to evaluate span(2, 5).
This goes on for a while:
|(1, |(2, span(3, 5)))
|(1, |(2, |(3, span(4, 5))))
|(1, |(2, |(3, |(4, span(5, 5)))))
|(1, |(2, |(3, |(4, [5]))))))
# now, it starts to "unwind" back:
|(1, |(2, |(3, [4, 5])))
|(1, |(2, [3, 4, 5]))
|(1, [2, 3, 4, 5])
[1, 2, 3, 4, 5]
(sorry if I'm using this |() syntax, remember I'm just using | as a function instead of an operator).
Nothing keeps track of the head and no function "keeps the values produced in the previous [iteration]". The first call (span(1, 5)) just expands to [1|span(2, 5)]. Now, in order for the span(1, 5) call to return, it needs to evaluate [1|span(2, 5)]: there you have it, recursion! It will need to evaluate span(2, 5) first and so on.
Technically, the values are kept somewhere, and it's on the stack: each function call is placed on the stack and popped off only when it's able to return. So the stack will look something like the series of calls I showed above:
# First call is pushed on the stack
span(1, 5)
# Second call is pushed on top of that
span(1, 5), span(2, 5)
# ...
span(1, 5), span(2, 5), ..., span(5, 5)
# hey! span(5, 5) is not recursive, we can return [5]. Let's pop span(5, 5) from the stack then
span(1, 5), ..., span(4, 5)
# Now span(4, 5) can return because we know the value of span(5, 5) (remember, span(4, 5) is expanded to [4|span(5, 5)]
This goes on until it goes back to span(1, 5) (which is now span(1, [2, 3, 4, 5])) and finally to [1, 2, 3, 4, 5].
Ok I wrote a lot and I'm not sure I made anything clearer to you :). Please, ask anything that's not clear. There are surely a lot of resources to learn recursion out there; just to name the first bunch I found:
The "Recursion" chapter of Learn You Some Erlang for Great Good, a great book on Erlang
Obligatory Wikipedia page on recursion
A nice page I just found about recursion on the khan academy website
Why not, a couple of Elixir-specific resources: the "Getting started" guide on Elixir's website, this blog post, this other blog post

How to make recursive nested loops which use loop variables inside?

I need to make a nested loop with an arbitrary depth. Recursive loops seem the right way, but I don't know how to use the loop variables in side the loop. For example, once I specify the depth to 3, it should work like
count = 1
for i=1, Nmax-2
for j=i+1, Nmax-1
for k=j+1,Nmax
function(i,j,k,0,0,0,0....) // a function having Nmax arguments
count += 1
end
end
end
I want to make a subroutine which takes the depth of the loops as an argument.
UPDATE:
I implemented the scheme proposed by Zoltan. I wrote it in python for simplicity.
count = 0;
def f(CurrentDepth, ArgSoFar, MaxDepth, Nmax):
global count;
if CurrentDepth > MaxDepth:
count += 1;
print count, ArgSoFar;
else:
if CurrentDepth == 1:
for i in range(1, Nmax + 2 - MaxDepth):
NewArgs = ArgSoFar;
NewArgs[1-1] = i;
f(2, NewArgs, MaxDepth, Nmax);
else:
for i in range(ArgSoFar[CurrentDepth-1-1] + 1, Nmax + CurrentDepth - MaxDepth +1):
NewArgs = ArgSoFar;
NewArgs[CurrentDepth-1] = i;
f(CurrentDepth + 1, NewArgs, MaxDepth, Nmax);
f(1,[0,0,0,0,0],3,5)
and the results are
1 [1, 2, 3, 0, 0]
2 [1, 2, 4, 0, 0]
3 [1, 2, 5, 0, 0]
4 [1, 3, 4, 0, 0]
5 [1, 3, 5, 0, 0]
6 [1, 4, 5, 0, 0]
7 [2, 3, 4, 0, 0]
8 [2, 3, 5, 0, 0]
9 [2, 4, 5, 0, 0]
10 [3, 4, 5, 0, 0]
There may be a better way to do this, but so far this one works fine. It seems easy to do this in fortran. Thank you so much for your help!!!
Here's one way you could do what you want. This is pseudo-code, I haven't written enough to compile and test it but you should get the picture.
Define a function, let's call it fun1 which takes inter alia an integer array argument, perhaps like this
<type> function fun1(indices, other_arguments)
integer, dimension(:), intent(in) :: indices
...
which you might call like this
fun1([4,5,6],...)
and the interpretation of this is that the function is to use a loop-nest 3 levels deep like this:
do ix = 1,4
do jx = 1,5
do kx = 1,6
...
Of course, you can't write a loop nest whose depth is determined at run-time (not in Fortran anyway) so you would flatten this into a single loop along the lines of
do ix = 1, product(indices)
If you need the values of the individual indices inside the loop you'll need to unflatten the linearised index. Note that all you are doing is writing the code to transform array indices from N-D into 1-D and vice versa; this is what the compiler does for you when you can specify the rank of an array at compile time. If the inner loops aren't to run over the whole range of the indices you'll have to do something more complicated, careful coding required but not difficult.
Depending on what you are actually trying to do this may or may not be either a good or even satisfactory approach. If you are trying to write a function to compute a value at each element in an array whose rank is not known when you write the function then the preceding suggestion is dead flat wrong, in this case you would want to write an elemental function. Update your question if you want further information.
you can define your function to have a List argument, which is initially empty
void f(int num,List argumentsSoFar){
// call f() for num+1..Nmax
for(i = num+1 ; i < Nmax ; i++){
List newArgs=argumentsSoFar.clone();
newArgs.add(i);
f(i,newArgs);
}
if (num+1==Nmax){
// do the work with your argument list...i think you wanted to arrive here ;)
}
}
caveat: the stack should be able to handle Nmax depth function calls
Yet another way to achieve what you desire is based on the answer by High Performance Mark, but can be made more general:
subroutine nestedLoop(indicesIn)
! Input indices, of arbitrary rank
integer,dimension(:),intent(in) :: indicesIn
! Internal indices, here set to length 5 for brevity, but set as many as you'd like
integer,dimension(5) :: indices = 0
integer :: i1,i2,i3,i4,i5
indices(1:size(indicesIn)) = indicesIn
do i1 = 0,indices(1)
do i2 = 0,indices(2)
do i3 = 0,indices(3)
do i4 = 0,indices(4)
do i5 = 0,indices(5)
! Do calculations here:
! myFunc(i1,i2,i3,i4,i5)
enddo
enddo
enddo
enddo
enddo
endsubroutine nestedLoop
You now have nested loops explicitly coded, but these are 1-trip loops unless otherwise desired. Note that if you intend to construct arrays of rank that depends on the nested loop depth, you can go up to rank of 7, or 15 if you have a compiler that supports it (Fortran 2008). You can now try:
call nestedLoop([1])
call nestedLoop([2,3])
call nestedLoop([1,2,3,2,1])
You can modify this routine to your liking and desired applicability, add exception handling etc.
From an OOP approach, each loop could be represented by a "Loop" object - this object would have the ability to be constructed while containing another instance of itself. You could then theoretically nest these as deep as you need to.
Loop1 would execute Loop2 would execute Loop3.. and onwards.

Correct User Defined Version of Map Function in Mathematica?

I'm trying to create a user defined version of the Map[] function in Mathematica and I'm running into a few problems.
Here is what I have so far:
map[x_, s_List] := mapAux[x, s, {}];
mapAux[x, s, {}] := Append[{}, First[s]];
mapAux[x, Rest[s], {}];
I'm trying to use it as
map[# + 1 &, {3, 6, 8}]
but this gives a mysterious error beside the output:
Rest::normal: Nonatomic expression expected at position 1 in Rest[s].
mapAux[#1 + 1 &, {3, 6, 8}, {}]
The ideal result would be {4,7,9}. I researched the "Nonatomic expression" error and I'm not sure what it means. I'm passing a list to it, but it's just exploding!
You're not passing s or x as variables, so it's just seeing s (which is an atomic expression) rather than a list. You're definition needs to be mapAux[x_, s_, {}]:=..., which will make x and s take the values of the passed parameters.

Resources