Erlang : Traversing N by N area - functional-programming

I am looking to traverse a NxN area, given the starting points X,Y and the size of the square to traverse. E.g. given X=10,Y=12,Size=2 - i want to generate 10,10 ; 10,11 ; 11,10 and 11,11.
I came up with this, but it seems to go on and on infinitely:
traverse({X,Y,Xend,Yend}) ->
% print X,Y values here....
case (X == Xend-1) andalso (Y == Yend-1) of
true ->
ok;
_->
case (Y < Yend-1) of
true ->
traverse({X,Y+1,Xend,Yend});
_->
traverse({X+1,Y,Xend,Yend})
end
end.
I called the above function from another function using:
Size = 3,
traverse({10,20,10+Size,20+Size}).
What am I doing wrong? I am actually new to the functional paradigm, and I tried implementing this on C, using "return" in the place of "ok" above, and it worked, but I am guessing, i'm not thinking "functionally" enough!

traverse(X0, Y0, S) ->
[
io:format("coords: ~p~n", [{X,Y}])
|| X <- lists:seq(X0, X0 + S - 1),
Y <- lists:seq(Y0, Y0 + S - 1)
],
ok
in shell:
1> traverse(10, 12, 2).
coords: {10,12}
coords: {10,13}
coords: {11,12}
coords: {11,13}
ok

Try this:
traverse({X,Y,Xend,Yend}) ->
dotraverse(X, Y, Xend, Yend, _StartX=X).
dotraverse({Xend,Yend,Xend,Yend}, SX) ->
ok;
dotraverse({X,Y,Xend,Yend}, SX) when X<Xend ->
%print
dotraverse({X+1, Y, Xend, Yend}, SX);
dotraverse({Xend,Y,Xend,Yend}) ->
dotraverse(SX,Y+1, Xend, Yend}, SX).
Note: untested but you get the gist of it.

This is a good question coming from someone new to the functional paradigm. The larger mistake here is the way the code is thought out, not the fact that it doesn't work.
Since you are coming from C, it's natural that you're writing the code in an imperative style, because that's how you're thinking.
In the functional style you have to tell the compiler "what" you want to do, not "how to do it" like you do in imperative languages such as C. The example Zed gives using the list comprehension is the right way.
Writing code is the best way to learn, but make sure you also focus on thinking in a functional manner. It takes a while to make the leap, but keep writing code and you'll get there eventually.
If you're serious about Erlang, read either Joe Armstrong's book or that of Cesarini and Thompson, or read the "OTP Design Principles User's Guide" from erlang.org. These will help you start to think differently, and the time spent will be well worth it.

Related

Monitoring files for modifications

I’m trying to write a simple code that continuously checks when files in a given folder are modified and, upon modification, triggers a function.
I've added a MWE below, it "works" but I was wondering if
there are libraries or utilities that I should look into that help for such a problem?
there was a cleaner way to have something running continuously until some event (here an interruption)
files_and_times = Dict{String, Int}()
for (root, _, files) ∈ walkdir(dirpath)
for f ∈ files
fpath = joinpath(root, f)
files_and_times[fpath] = stat(fpath).mtime
end
end
try
while true
for (f, t) ∈ files_and_times
cur_t = stat(f).mtime
if cur_t > t
files_and_times[f] = cur_t
println("file $f was modified")
end
end
sleep(0.5)
end
catch x
if isa(x, InterruptException)
println("Shutting down.")
else
throw(x)
end
end
The comments by #rickhg12hs and #Colin_T_Bowers effectively answer my question. Posting an answer to close the question.
FileWatching seems to be precisely what I was looking for,
The package Revise seems to have good examples showing how to use it and,
this discourse thread discusses limitations.

How can I get this function to be tail-recursive?

I'm still trying to implement 2-3 finger trees and I made good progress (repository). While doing some benchmarks I found out that my quite basic toList results in a StackOverflowException when the tree ist quite large. At first I saw an easy fix and made it tail-recursive.
Unfortunately, it turned out that toList wasn't the culprit but viewr was:
/// Return both the right-most element and the remaining tree (lazily).
let rec viewr<'a> : FingerTree<'a> -> View<'a> = function
| Empty -> Nil
| Single x -> View(x, lazyval Empty)
| Deep(prefix, deeper, One x) ->
let rest = lazy (
match viewr deeper.Value with
| Nil ->
prefix |> Digit.promote
| View (node, lazyRest) ->
let suffix = node |> Node.toList |> Digit.ofList
Deep(prefix, lazyRest, suffix)
)
View(x, rest)
| Deep(prefix, deeper, Digit.SplitLast(shorter, x)) ->
View(x, lazy Deep(prefix, deeper, shorter))
| _ -> failwith Messages.patternMatchImpossible
Looking for the only recursive call it is obvious that this is is not tail-recursive. Somehow I hoped this problem wouldn't exist because that call is wrapped in a Lazy which IMHO is similar to a continuation.
I heard and read of continuations but so far never (had to) use(d) them. I guess here I really need to. I've been staring at the code for quite some time, putting function parameters here and there, calling them other places… I'm totally lost!
How can this be done?
Update: The calling code looks like this:
/// Convert a tree to a list (left to right).
let toList tree =
let rec toList acc tree =
match viewr tree with
| Nil -> acc
| View(head, Lazy tail) -> tail |> toList (head::acc)
toList [] tree
Update 2: The code that caused the crash is this one.
let tree = seq {1..200000} |> ConcatDeque.ofSeq
let back = tree |> ConcatDeque.toList
The tree get built fine, I checked and it is only 12 levels deep. It's the call in line 2 that triggered the overflow.
Update 3: kvb was right, that pipe issue I ran into before has something to do with this. Re-testing the cross product of debug/release and with/without pipe it worked in all but one case: debug mode with the pipe operator crashed. The behavior was the same for 32 vs. 64 bit.
I'm quite sure that I was running release mode when posting the question but today it's working. Maybe there was some other factor… Sorry about that.
Although the crash is solved, I'm leaving the question open out of theoretical interest. After all, we're here to learn, aren't we?
So let me adapt the question:
From looking at the code, viewr is definitely not tail-recursive. Why doesn't it always blow up and how would one rewrite it using continuations?
Calling viewr never results in an immediate recursive call to viewr (the recursive call is protected by lazy and is not forced within the remainder of the call to viewr), so there's no need to make it tail recursive to prevent the stack from growing without bound. That is, a call to viewr creates a new stack frame which is then immediately popped when viewr's work is done; the caller can then force the lazy value resulting in a new stack frame for the nested viewr call, which is then immediately popped again, etc., so repeating this process doesn't result in a stack overflow.

How come julia won't run this code?

I am in the process of trying to learn a little about using Julia by translating an old example code which solves the time dependent Schrodinger equation. Here is what I have so far:
require("setparams.jl")
require("V.jl")
require("InitialRIM.jl")
#require("expevolve.jl")
function doit()
Nspace, R, Im, x0, width, k0, xmax, xmin, V0, a, dx, dx2, n, dt = setparams()
R, Im = initialRIm(width,n,k0,dt,xmin)
ProbDen = zeros(Nspace)
ProbDen = R.*R + Im.*Im
plot(ProbDen)
#Imold = Im;
t=0.0
#t, R =evolve!(R,Im,t,V0,width,a,dx,dx2,dt,xmin,n)
println("Done")
end
After requiring the above code, I then do using Winston. Then I attempt to run the code by typing doit(). Nothing appears.
Can someone please let me know what I am doing wrong? I can provide the innards of setuparame() if needed, as well as initialRIm() but thought at first I'd ask whether my expectations about what should happen are in fault. Note that if I run setuparams() and initialRIm() in a terminal session, then do the plot(ProbDen), the correct graph appears.
Thanks for your help.
Update:
I have now restarted julia, have done using Winston, and then have done doit() to wit:
julia> using Winston
julia> require("driveSch.jl")
julia> doit()
ERROR: dx not defined
in initialRIm at /Users/comerduncan/juliaexamples/TDSch/InitialRIM.jl:8
in doit at /Users/comerduncan/juliaexamples/TDSch/driveSch.jl:11
However, the call to setparams() sets dx along with all the other things. This I see when I run the setparams() interactively. So I am not understanding what is the problem...
It seems like you use dx in initialRIm, but dx is not one of the arguments you pass to it. If you access a variable that is not a parameter nor assigned inside a Julia function, Julia will look for a variable with the same name in the surrounding scopes. When you run
Nspace, R, Im, x0, width, k0, xmax, xmin, V0, a, dx, dx2, n, dt = setparams()
in the global scope, and you create a global variable dx that initialRIm could access. When you wrap the calls into a function, you create a local variable dx that can not be accessed from initialRIm.

OCaml while true do loop

I have the following code:
let a = 1 in
while a<10 do
let a = a+1 in
done
Printf.printf "the number is now %d\n" a
The interpreter is complaining about line 4, which is done and I have no idea what is wrong here.
I understand that OCaml is a functional language and the variables are immutable. I should not try to change the value of a here.
But still, there is a while true do .. done loop in OCaml. I hope you get the idea of what I am trying to do here. How shall I modify the code to do this job with while true do .. done?
I am very new to functional programming. Please teach me the right way to get started with it. I find myself stuck in the deadlock of thinking imperatively.
The let ... in construct expects another expression behind. You can, for example use the () value (which basically means "nothing")
So the code
let a = 1 in
while a<10 do
let a = a+1 in
()
done
Printf.printf "the number is now %d\n" a
It will compile. But it will loop indefinitely because the a defined as 1 at start is different than the a declared as a+1.
Both are constant different values on different scopes, and a declaration inside the body of a while is limited to that occurence of the body.
You may get what you want by specifying a as mutable using the ref function and its handlers:
let a = ref 1 in
while !a < 10 do
a := !a + 1
done
Printf.printf "the number is now %d\n" !a
Note that you loose all the benefits of FP by using a while loop and mutable values.
To do it in a functionnal manner, you can use a recursive function:
let rec f a =
if a < 10
then f (a+1)
else a
in
let a = f 1 in
Printf.printf "the number is now %d\n" a
This one is the true right manner to do the job. If you want to do FP, avoid at all costs to use a while loop.

Opa: What Is the Fastest Way to Reverse a String?

What is the most performant way to implement a "reverse a string" function in Opa?
I am aware of String.reverse(). It does get the job done, but its source code is bound to some external function. I want to understand what the best (fastest) tools are for reordering a string.
So, for example, this works, but isn't particularly fast:
reverse(s:string) =
p = parser
| x=(.) xs=(.*) -> Text.concat(reverse(Text.to_string(xs)), x)
| x=(.*) -> x
Parser.parse(p, s)
How can I make this perform better?
Edit: Another Implementation Based on akoprowski's Answer
I think this is what he has in mind. This one is much faster than the parser version, but the built-in String.reverse is the way to go if all you need to do is reverse a string.
reverse_list(l:list(string)):list(string) =
match l with
| [x|xs] -> reverse_list(xs) ++ [x]
| _ -> []
reverse_string(s:string) =
string_list = List.init((i -> String.get(i, s)), String.length(s))
String.flatten(reverse_list(string_list))
Edit: The Above Implementation Is Not Ideal
Check out the accepted answer for a better option.
Why don't you want to use String.reverse? (which is the preferred way of reversing a string). Or is that just an exercise?
I'd suggest using List.init to generate a list of characters, String.get (to get n'th character of the string) and String.flatten to convert a list of characters back to a string.
That should be faster than the parsing-based approach, which btw. has quadratic complexity so no wonder it's slow.
Edit: the solution I had in mind:
reverse_string(s:string) =
n = String.length(s)
rev_list = List.init((i -> String.get(n - i - 1, s)), n)
String.flatten(rev_list)

Resources