How do I save and change the value of a variable in OCaml? - ocaml

This may be a very newbie question, but I didn't find the answer.
I need to store, for example a list and later replace it with another, under the same pointer.

It can be done via references:
let fact n =
let result = ref 1 in (* initialize an int ref *)
for i = 2 to n do
result := i * !result (* reassign an int ref *)
done;
!result
You do not see references very often because you can do the same thing using immutable values inside recursion or high-order functions:
let fact n =
let rec loop i acc =
if i > n then acc
else loop (i+1) (i*acc) in
loop 2 1
Side-effect free solutions are preferred since they are easier to reason about and easier to ensure correctness.

Related

Psum not accumulating (Polymorphic Higher order function) without forcing a type

New to OCaml and Functional Programming as a whole so I was having some problems with keeping the type ambiguous. I'm trying to make a function which takes in a symbol accum(which looks like (+) or (-.) or (*) etc.) and a function f. My current implementation is below and if let's say I passed in (** f (x) = 3x^2 + 5x + 6 **) but I always get '6' instead of '276' because in the else part I'm not summing adding the results of the previous rounds so I just get the final value of '6'.
I get type errors because of the + so when I throw floats in it breaks. How can I overcome this (let partial accept floats or ints but actually accumulate the answer)?
let rec powerSum(sign )(f):'a =
fun x ->
if x = 0 then
f (x)
else if x < 0 then
raise(Failure "Error arg isn't '+'")
else
powerSum sign f (x-1);
Hint: you should use accum at some point.

Lua game development, table seems to delete itself after each interation

What I am trying to do is a little addon which would let me know how much time I have spent casting during combat in %,
function()
local spell, _, _, _, _, endTime = UnitCastingInfo("player")
-- getting information from the game itself whether im "Casting"
local inCombat = UnitAffectingCombat("player")
-- getting information form the game if combat is true (1) or not (nil)
local casting = {}
local sum = 0
if inCombat == 1 then
if spell then
table.insert(casting, 1)
else
table.insert(casting, 0)
end
else
for k in pairs (casting) do
casting [k] = nil
end
end
for i=1, #casting, 1 do
sum = sum + casting[i]
end
return( sum / #casting ) end
-- creating a list which adds 1 every frame I am casting and I am in combat,
-- or adds 0 every frame I'm not casting and I'm not in combat.
-- Then I sum all the numbers and divide it by the number of inputs to figure
-- out how much % I have spent "casting".
-- In case the combat condition is false, delete the list
For some reason these numbers don't add up at all, I only see "1" when both conditions are satisfied, or 0 if the combat condition is satisfied.
There might be some better approach I'm sure, but I am kind of new to lua and programming in general.
You say you're new to Lua, so I will attempt to explain in detail what is wrong and how it can be improved, so brace yourself for a long read.
I assume that your function will be called every frame/step/tick/whateveryouwanttocallit of your game. Since you set sum = 0 and casting = {} at the beginning of the function, this will be done every time the function is called. That's why you always get 0 or 1 in the end.
Upvalues to the rescue!
Lua has this nice thing called lexical scoping. I won't go into much detail, but the basic idea is: If a variable is accessible (in scope) when a function is defined, that function remembers that variable, no matter where it is called. For example:
local foo
do
local var = 10
foo = function() return var end
end
print(bar) -- nil
print(foo()) -- 10
You can also assign a new value to the variable and the next time you call the function, it will still have that new value. For example, here's a simple counter function:
local counter
do
count = 0
counter = function() count = count + 1; return count; end
end
print(counter()) -- 1
print(counter()) -- 2
-- etc.
Applying that to your situation, what are the values that need to persist from one call to the next?
Number of ticks spent in combat
Number of ticks spent casting
Define those two values outside of your function, and increment / read / reset them as needed; it will persist between repeated calls to your function.
Things to keep in mind:
You need to reset those counters when the player is no longer casting and/or in combat, or they will just continue where they left off.
casting doesn't need to be a table. Tables are slow compared to integers, even if you reuse them. If you need to count stuff, a number is more than enough. Just make casting = 0 when not in combat and increase it by 1 when in combat.
Thank you for feedback everyone, in the end after your suggestions and some research my code looks like this and works great:
function()
local spell, _, _, _, startTime, endTime, _, _, _ = UnitCastingInfo("player")
local inCombat = UnitAffectingCombat("player")
local inLockdown = InCombatLockdown()
local _, duration, _, _ = GetSpellCooldown("Fireball")
casting = casting or {}
local sum = 0
if inCombat == 1 or inLockdown == 1 then
if spell or duration ~= 0 then
casting[#casting+1] = 1
elseif spell == nil or duration == 0 then
casting[#casting+1] = 0
end
else
local next = next
local k = next(casting)
while k ~= nil do
casting[k] = nil
k = next(casting, k)
end
end
for i=1, #casting, 1 do
sum = sum + casting[i]
end
return(("%.1f"):format( (sum / #casting)*100 ).. "%%") end
what i noticed is there was a problem with reseting the table in the original code:
for k in pairs (casting) do
casting [k] = nil
it seemed like either some zeros stayed there, or the table size didnt "shrink" i dont know.
Maybe intereger would be faster then a table, but honestly i dont see any performance issues even when the table gets ridicolously big (5 min, 60 fps, thats 18k inputs) also for the sake of learning a new language its better to do it harder way in my opinion
Regards

F# tricky recursive algorithm

I have this code in VBA (looping through the array a() of type double):
bm = 0 'tot
b = 0 'prev
For i = 24 To 0 Step -1
BP = b 'prevprev = prev
b = bm 'prev = tot
bm = T * b - BP + a(i) 'tot = a(i) + T * prev - prevprev
Next
p = Exp(-xa * xa) * (bm - BP) / 4 '* (tot - prevprev)/4
I'm putting this in F#. Clearly I could use an array and mutable variables to recreate the VBA. And maybe this is an example of the right time to use mutable that I've seen hinted at. But why not try to do it the most idiomatic way?
I could write a little recursive function to replicate the loop. But it kind of feels like littering to hang out a little sub-loop that has no meaning on its own as a standalone, named function.
I want to do it with List functions. I have a couple ideas, but I'm not there yet. Anyone get this in a snap??
The two vague ideas I have are: 1. I could make two more lists by chopping off one (and two) elements and adding zero-value element(s). And combine those lists. 2. I'm wondering if a list function like map can take trailing terms in the list as arguments. 3. As a general question, I wonder if this might be a case where an experienced person would say that this problem screams for mutable values (and if so does that dampen my enthusiasm for getting on the functional boat).
To give more intuition for the code: The full function that this is excerpted from is a numerical approximation for the cumulative normal distribution. I haven't looked up the math behind this one. "xa" is the absolute value of the main function argument "x" which is the number of standard deviations from zero. Without working through the proof, I don't think there's much more to say than: it's just a formula. (Oh and maybe I should change the variable names--xa and bm etc are pretty wretched. I did put suggestions as comments.)
It's just standard recursion. You make your exit condition and your recur condition.
let rec calc i prevPrev prev total =
if i = 0 then // exit condition; do your final calc
exp(-xa * xa) * (total - prevPrev) / 4.
else // recur condition, call again
let newPrevPrev = prev
let newPrev = total
let newTotal = (T * newPrev - newPrevPrev + a i)
calc (i-1) newPrevPrev newPrev newTotal
calc 24 initPrevPrev initPrev initTotal
or shorter...
let rec calc i prevPrev prev total =
if i = 0 then
exp(-xa * xa) * (total - prevPrev) / 4.
else
calc (i-1) prev total (T * total - prev + a i)
Here's my try at pulling the loop out as a recursive function. I'm not thrilled about the housekeeping to have this stand alone, but I think the syntax is neat. Aside from an error in the last line, that is, where the asterisk in (c * a.Tail.Head) gets the red squiggly for float list not matching type float (but I thought .Head necessarily returned float not list):
let rec RecurseIt (a: float list) c =
match a with
| []-> 0.0
| head::[]-> a.Head
| head::tail::[]-> a.Head + (c * a.Tail) + (RecurseIt a.Tail c)
| head::tail-> a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head + (RecurseIt a.Tail c)
Now I'll try list functions. It seems like I'm going to have to iterate by element rather than finding a one-fell-swoop slick approach.
Also I note in this recursive function that all my recursive calls are in tail position I think--except for the last one which will come one line earlier. I wonder if this creates a stack overflow risk (ie, prevents the compiler from treating the recursion as a loop (if that's the right description), or if I'm still safe because the algo will run as a loop plus just one level of recursion).
EDIT:
Here's how I tried to return a list instead of the sum of the list (so that I could use the 3rd to last element and also sum the elements), but I'm way off with this syntax and still hacking away at it:
let rec RecurseIt (a: float list) c =
match a with
| []-> []
| head::[]-> [a.Head]
| head::tail::[]-> [a.Head + (c * a.Tail)] :: (RecurseIt a.Tail c)
| head::tail-> [a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head] :: (RecurseIt a.Tail c)
Here's my try at a list function. I think the problem felt more complicated than it was due to confusing myself. I just had some nonsense with List.iteri here. Hopefully this is closer to making sense. I hoped some List. function would be neat. Didn't manage. For loop not so idiomatic I think. :
for i in 0 .. a.Length - 1 do
b::
a.Item(i) +
if i > 0 then
T * b.Item(i-1) -
if i > 1 then
b.Item(i-2)
else
0
else
0

OCaml: retain value of variable with control statements

I'm very new to OCaml / functional programming, and I'm confused about the implementation of some things that are relatively simple other languages I know. I could use any and all help.
Chiefly: in a program I'm working on, I either increment or decrement a variable based on a certain parameter. Here's something representative of what I have:
let tot = ref 0 in
for i = 0 to s do
if test_num > 0 then
tot := !tot + other_num
else
tot := !tot - other_num
done;;
This is obviously not the way to go about it, because even if the else statement is never taken, the code acts as if it is, each and every time, presumably because it's closer to the bottom of the program? I know OCaml has pretty sophisticated pattern matching, but within this level of coed I need access to a handful of lists I've already created, and, as far as I understand, I can't access those lists from a top-level function without passing them all as parameters.
I know I'm going about this the wrong way, but I have no idea how to do this idiomatically.
Suggestions? Thanks.
edit
Here's a more concise example:
let ex_list = [1; -2; 3; -4] in
let max_mem = ref 0 in
let mem = ref 0 in
let () =
for i = 0 to 3 do
let transition = List.nth ex_list i in
if transition > 0 then (
mem := (!mem + 10);
) else
mem := (!mem - 1);
if (!mem > !max_mem) then (max_mem := !mem);
done;
print_int !max_mem; print_string "\n";
in !mem;
At the end, when I print max_mem, I get 19, though this value should be (0 + 10 - 1 + 10 - 1 = 18). Am I doing the math wrong, or does the problem come from somewhere else?
Your code looks fine to me. It doesn't make a lot of sense as actual code, but I think you're just trying to show a general layout. It's also written in imperative style, which I usually try to avoid if possible.
The if in OCaml acts just like it does in other languages, there's no special thing about being near the bottom of the program. (More precisely, it acts like the ? : ternary operator from C and related languages; i.e., it's an expression.)
Your code doesn't return a useful value; it always returns () (the quintessentially uninteresting value known as "unit").
If we replace your free variables (ones not defined in this bit of code) by constants, and change the code to return a value, we can run it:
# let s = 8 in
let other_num = 7 in
let test_num = 3 in
let tot = ref 0 in
let () =
for i = 0 to s do
if test_num > 0 then
tot := !tot + other_num
else
tot := !tot - other_num
done
in
!tot;;
- : int = 63
#
If you're trying to learn to write in a functional style (i.e., without mutable variables), you would write this loop as a recursive function and make tot a parameter:
# let s = 8 in
let other_num = 7 in
let test_num = 3 in
let rec loop n tot =
if n > s then
tot
else
let tot' =
if test_num > 0 then tot + other_num else tot - other_num
in
loop (n + 1) tot'
in
loop 0 0;;
- : int = 63
It would probably be easier to help if you gave a (edited to add: small :-) self-contained problem that you're trying to solve.
The other parts of your question aren't clear enough to give any advice on. One thing that I might point out is that it's completely idiomatic to use pattern matching when processing lists.
Also, there's nothing wrong with passing things as parameters. That's why the language is called "functional" -- your code consists of functions, which have parameters.
Update
I like to write let () = expr1 in expr2 instead of expr1; expr2. It's just a habit I got into, sorry if it's confusing. The essence is that you're evaluating the first expression just for its side effects (it has type unit), and then returning the value of the second expression.
If you don't have something after the for, the code will evaluate to (), as I said. Since the purpose of the code seems to be to compute the value of !tot, this is what I returned. At the very least, this lets you see the calculated value in the OCaml top level.
tot' is just another variable. If you calculate a new value straightforwardly from a variable named var, it's conventional to name the new value var'. It reads as "var prime".
Update 2
Your example code works OK, but it has the problem that it uses List.nth to traverse a list, which is a slow (quadratic) operation. In fact your code is naturally considered a fold. Here's how you might write it in a functional style:
# let ex_list = [1; -2; 3; -4] in
let process (tot, maxtot) transition =
let tot' = if transition > 0 then tot + 10 else tot - 1 in
(tot', max maxtot tot')
in
List.fold_left process (0, 0) ex_list;;
- : int * int = (18, 19)
#
In addition to Jeffrey's answer, let me second that this is not how you would usually write such code in Ocaml, since it is a very low-level imperative approach. A more functional version would look like this:
let high ex_list =
let deltas = List.map (fun x -> if x > 0 then 10 else -1) ex_list in
snd (List.fold_left (fun (n, hi) d -> (n+d, max (n+d) hi)) (0, 0) deltas)
let test = high [1; -2; 3; -4]

sml syntax having a hard time looking up documentation

I am trying to "simulate" a pass by value result function with the following code but there seems to be a syntax error. I've been looking through sml tutorials but I'm having a hard time figuring out why this doesn't work
1 val x = ref 0;
2 fun p(y': int ref)=
3 let
4 val y = !y'
5 in
6 let
7 y = 1
8 in
9 let x := 0
10 in
11 y' := y
12 end
13 end
14 end
15 p(x)
In the let <decs> in <exp>, <decs> needs to be one or more declarations.
In your case, on line 7 you do y = 1 - note, this is not an assigment, but a comparison. That is, in C++ it would be equivalent to doing y == 1. You cannot assign to non-ref variables. (And in general, you want to avoid ref variables as much as possible.)
You could do val y = 1 in its place, in which case you create a new value by the name of y, which shadows over the old y (but does not change it; you create a new value).
Likewise, on line 9, you do x := 0, which is not a declaration, but an expression, which assigns the value 0 to the reference value x, and then returns unit.
In addition, you can do multiple declarations in your let statements, so you don't need the nesting you do.
Finally, you write p(x) on the toplevel. You can only write expressions on the toplevel, if the declaration preceding ends with a semicolon; otherwise it believes it to be a part of the declaration. That is
val a = 5
6
is interpreted to be
val a = 5 6
In short, you could rewrite it to this:
val x = ref 0;
fun p(y': int ref)=
let
val y = !y' (* this line might as well be deleted. *)
val y = 1
in
x := 0;
y' := y
end;
p(x)
Or, the shorter version, since the SML has good type inference:
val x = ref 0;
fun p y' = (x := 0; y' := 1);
p x
I will say this, though; if you come from a language like C++ or similar, it may be tempting to use 'a refs a lot, but you will often find, that minimizing the use of them often leads to cleaner code in SML. (And other functional languages.)
let y = 1 ... is wrong. So is let x := 0. Inside let ... in, you need either val or fun declarations.
It seems you have some misunderstandings of SML. let is used to declare new local variables in a scope. It is strange for you to try to declare a variable named y in an inner scope that shadows the y that you declared in the let in the immediately outer scope. You either meant one of two things:
Change the value of the "y" variable defined in the outer scope. This is impossible. You cannot change the value of a variable in ML
You want to declared a new, unrelated variable that is also named "y", and hide the previous "y" within this scope; in this case, you would use let var y = 1 in ...
Also, it is strange that you have let x := 0. x := 0 is a valid expression in itself. It changes the value contained in the reference pointed to by x. You don't need a let. Since x := 0 is only evaluated for side effects, and returns type unit (i.e. nothing useful), you might familiarize yourself with the ; operator, with which you can use to string together a bunch of side-effect "statements" which evaluate to the result of the last one: x := 0; y' := y