How can I make this code tail recursive? - tail-recursion

The following code is intended to append two lists.
fun {AppendLists L1 L2}
if L1 == nil then L2
else
L1.1 | {AppendLists L1.2 L2}
end
end

If you don't see why your code is already tail-recursive, here's the same code with a bit less syntactic sugar. Your function as been converted to a procedure with an extra argument to store the result (this is denoted by a facultative '?').
proc {AppendLists L1 L2 ?R}
if L1 == nil then L2
else K in
R = L1.1 | K
{AppendLists L1 L2 K}
end
end

This code is already tail-recursive. You have recursion as the last statement, so you are calculating the result first, and then call the recursion.

Related

list vs. incremental values security

Can someone tell me the formal reason why list/arrays and such are considered more secure when it comes to incremental steps i.e (List.fold > loops).
Exampel code in F#
Functional way (list)
let rec sum lst =
match lst with
| [] -> 0
| x::xs -> x + sum xs
Imperative way (incremental)
let sum n m =
let mutable s = 0
for i=n to m do
s <- s + i
s
If by security you mean "safer" -- then I think this will explain it some. To begin with if you're summing a list, a fold should be somewhat safer as it removes the need for the programmer to correctly index the list:
let sum lst =
let mutable s = 0
for i=0 to (List.length lst - 1) do
s <- s + lst.[i]
s
You avoid a lot of pitfalls completely by using the library function:
let sum lst =
let folder acc element =
acc + element
List.fold folder 0 lst
The fold handles all the edge cases for you, in terms of indices, and list length. (note: this could also be done with a List.reduce (+) lst however that does not handle an empty list, where as a fold does).
The short of it all is that it keeps the programmer from making mistakes on silly index math, and keeps the focus on the actual logic of what is being done.
EDIT: I ironically messed up the index logic in my initial post

Haskell As-patterns, binding variables to constants

(This code doesn't make much sense, but I need this logic to work in my other complicated function):
import Data.List
elemIndex1 xss#(x:xs) =
if (x == ' ')
then (elemIndex x xss)
else (elemIndex1 xs)
So I want this function to give this:
elemIndex1 "qwe asd zxc"
Just 3
Instead it gives this:
elemIndex1 "qwe asd zxc"
Just 0
As I understand, at the else clause xss actually becomes xs.
So my question is: is there a possibility to bind the variable (x:xs) to a constant and to use this constant at any iteration?
It seems like you are expecting xss#(x:xs) to be the following:
xss: the original string given to elemIndex1
x: the first character of an arbitrary call
xs: the rest of the characters of an arbitrary call
e.g. for your example when x first matches a space
xss = "qwe asd zxc"
x = ' '
xs = "asd zxe"
This is not how the pattern match works. xss is actually equal to x:xs, so in that example it would be " asd zxc".
If you want to keep around the first call to a function, you can use a helper function called inside of the scope of the original function.
weirdElemIndex str = weirdElemIndex' str
where
weirdElemIndex' "" = Nothing
weirdElemIndex' (x:xs) =
if x == ' '
then elemIndex ' ' str
else weirdElemIndex' xs
Note that the str I reference in the body of the helper function will be a constant in its invocation.
For what it’s worth, your contrived example seems to be equivalent to elemIndex ' ' since it deals with the case where there is no space in the string by returning Nothing.

How can I use a function call result in a conditional list comprehension?

I would like to turn this code into a list comprehension:
l = list()
for i in range(10):
j = fun(i)
if j:
l.append(j)
Meaning that I'd like to add only truthy fun() result values to the list. Without the truthy check of that function call, the list comprehension would be:
l = [fun(i) for i in range(10)]
Adding a if fun(i) to the list comprehension would cause two evaluations of fun() per iteration (actually, not always it seems!), thus causing unintended side effects if fun() is not pure.
Can I capture the result of fun(i) and use it in that same comprehension, essentially adding the if j? (Related question here)
You can make an inner generator in the list comp so you will look over the results of func
l = [j for j in (func(i) for i in range(10)) if j]
Or combining two suggested solutions:
filter(None, (func(i) for i in range(10)))
Edit
Much simpler:
[res for res in map(func, range(10)) if res]
Thanks for the hint to falstru.
Old answer
Another option would to use a helper generator function:
def call_iter(func, iterable):
for arg in iterable:
yield func(arg)
[res for res in call_iter(func, range(10)) if res]

Haskell, Length of list returning the value 1

I'm working with some code and there seems to be an issue which I can't figure out.
So I've got a method which decrements an input Int by 1 until it hits 5. (I know if i enter less than 1 it would cause an error but i will fix that later)
I have a second function which calls a takes a List as a parameter which calls this function and returns the list of numbers, I want to call length on this list and populate a separate list (I'm not the best at explaining, i'll show with code examples below)
sub 5 = return [1]
sub x =
do
xs <- sub (x - 1)
return (x:xs)
f xs = [ length (sub x) | x<-xs ]
If I call sub 10 on it's own it gives the output [10,9,8,7,6,1], however if I call length on this, it gives the output [1].
In my head i thought the output would be 6, as it has 6 elements in.
Does anyone have any idea why this is happening and/or a way to fix it?
Thanks in advance.
sub doesn't return [10,9,8,6,1] but [[10,9,8,6,1]] (a list of list) therefore the length is 1. You don't need the return. You are in a list monad, return wraps it's value into a list, this why you end up with nested list. Your code should be
sub 5 = [1] -- or return 1
sub x = do
let xs = sub (x -1)
(x:xs)
The problem is that this sub function is written like you were in an imperative language and that return doesn't mean the same thing in Haskell : it means "wrap this thing in a Monad (which Monad depends on the context)". Here since you use length on the result of sub the list [] monad is used and the result is [ [10, 9, 8, 7, 6, 5] ] a list of one element which happen to be a list of 6 elements. mb14 correctly identified that but then corrected only the first case of your function, the second case is also monadic but shouldn't be...
sub 5 = [1]
sub x = x : sub (x - 1)
is the simple code you should be using, you don't need any monad here...

Julia: Unique sets of n elements with replacement

Given a vector v = [1,..,n], I try to compute all unique sets of n elements with replacements in julia.
Since I want to do this for larger values of n, I'm looking for an efficient solution, possibly using iterators.
For example, let's consider v = [1, 2, 3]: This should results in [1,1,1], [1,1,2], [1,1,3], [1,2,2], [1,2,3], [1,3,3], [2,2,2], [2,2,3], [2,3,3], [3,3,3]. With unique, I mean that if [1,1,2] is a solution, any of its permutations [1,2,1], [2,1,1] is not.
My current solution is based on the partitions function, but does not allow me to restrict the computation on the elements [1,..,n]
for i in n:n^2
for j in partitions(i, n)
## ignore sets which exceed the range [1,n]
if maximum(j) <= n
## accept as solution
end
end
end
In julia v0.5.0, combinatorics.jl has a with_replacement_combinations method.
julia> collect(with_replacement_combinations(1:4,3))
20-element Array{Array{Int64,1},1}:
[1,1,1]
[1,1,2]
[1,1,3]
[1,1,4]
[1,2,2]
[1,2,3]
[1,2,4]
[1,3,3]
[1,3,4]
[1,4,4]
[2,2,2]
[2,2,3]
[2,2,4]
[2,3,3]
[2,3,4]
[2,4,4]
[3,3,3]
[3,3,4]
[3,4,4]
[4,4,4]
I guess, it doesn't get shorter than one-line (using Iterators).
using IterTools
import Combinatorics.combinations
n=3
collect(imap(c -> Int[c[k]-k+1 for k=1:length(c)],combinations(1:(2n-1),n)))
I believe you're looking for the product function from the Iterators package. In your case product(v,v,v) should do what's required.
Here is a function to calculate the required collection:
function calcset(n=3)
res = []
for c in combinations([1:(2n-1)],n-1)
c3 = [c,2n].-[0,c]
push!(res,vcat([fill(i,c3[n-i+1]-1) for i=1:n]...))
end
return res
end
calcset(3)
There is probably some better way to code this, but this should be enough.
Notice the result is generated through repeated push!s, so this is easily turned into an iterator, if necessary.
And in iterator form:
import Base: start, next, done, eltype, length
type ImageTypeIterator
inneritr::Base.Combinations{Array{Int64,1}}
n::Int
end
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n-1),n)
eltype(itr::ImageTypeIterator) = Array{Int64,1}
start(itr::ImageTypeIterator) = start(itr.inneritr)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
c3 = [c,2*itr.n].-[0,c]
(vcat([fill(i,c3[itr.n-i+1]-1) for i=1:itr.n]...),s)
end
done(itr::ImageTypeIterator,s) = done(itr.inneritr,s)
length(itr::ImageTypeIterator) = length(itr.inneritr)
# test with [1,2,3]
for t in imagetype(3) println(t) ; end
The test at the end should print the collection set in the question.
BTW the name ImageTypeIterator is an attempt to characterize the collection as the distinct types of sizes of preimages when looking at a function f : [1:n] -> [1:n]. But a different interpretation might be appropriate. Other names suggestion welcome in comments.
A faster?/clearer? implementation could use:
imagetype(n::Int) = ImageTypeIterator(combinations([1:(2n-1)],n),n)
function next(itr::ImageTypeIterator,s)
(c,s) = next(itr.inneritr,s)
v = Array(Int,itr.n)
j = 1 ; p = 1
for k=1:itr.n
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
(v,s)
end
Its the same logic as above, but without too much slicing. The logic takes a subset of 2n-1 and views non-gaps as repeated values and gaps as a trigger to advance to next value.
OK, a simpler version using Iterators.jl:
using Iterators
function ff(c)
v = Array(Int,length(c))
j = 1 ; p = 1
for k=1:length(c)
while !(j in c) j += 1 ; p += 1 ; end
v[k] = p
j += 1
end
v
end
# test
n = 3
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end
This is perhaps the simplest version, although equivalent in methods to the other answers.
And in the spirit of brevity:
using Iterators
ff(c) = begin
j=1;p=1; [(while !(j in c) j+=1;p+=1 ; end ; j+=1 ; p) for k=1:length(c)]
end
n = 3 # test
for t in imap(ff,combinations([1:(2n-1)],n)) println(t) ; end

Resources