let x = ref 100 in
let f () = !x in
let x = ref 50 in
??? ; f ()
You are supposed to get the answer to be 50 by plugging something into the ??? (not shadowing). But I don't know how to change the value of your original ref now, considering x := 50 is going to apply to the SECOND x now....
If it really is a "beginner question", that's probably not the expected answer. But I don't know what the "expected answer" is, so let's hack around instead.
Obj.(obj (field (repr f) 1)) := 42;;
relevant link
There is no way to access original x now. So.. shadow f!
Related
I'm trying to learn OCaml on my own, and I've reached imperative programming. I found this little exercise that I'm just completely stuck on how to even approach. It seems so simple, but I think my understanding is just lacking.
The problem asks me to write the function for factorial without using the rec keyword, and without loops. It's supposed to teach me the environment model, but that's also confusing to me.
My first thought was to try something like this:
let factorial =
let f = ref (fun n -> 0) in
let temp_factorial n =
if n = 0
then 1
else
begin
f := n * !f*(n-1)
!f
end
But I'm not sure if this works. Any help would be greatly appreciated :)
Your code is a little strange and wrong, but the basic idea is workable. Once you have a reference f to a function of type int -> int, you can use !f freely in later code. In fact you can assign f so it refers to a function that uses !f. This is equivalent to recursion, but it uses the imperative part of OCaml.
let f = ref (fun n -> n + 1)
f :=
(fun n ->
if n < 2 then 1
else (* ... left as an exercise ... *)
)
let factoral n = !f n
The key is that the part left as an exercise can use !f.
fun count_wcs p =
let
val count = 0
in
g (fn () => count + 1) (fn y => 1) p
end
I'm doing homework and we're not supposed to use mutations, this doesn't reassign the value to anything but it doesn't feel right. Please, don't say what is the right way to do this, because I'm supposed to figure this out.
datatype pattern = Wildcard
| Variable of string
| UnitP
| ConstP of int
| TupleP of pattern list
| ConstructorP of string * pattern
fun g f1 f2 p =
let
val r = g f1 f2
in
case p of
Wildcard => f1 ()
| Variable x => f2 x
| TupleP ps => List.foldl (fn (p,i) => (r p) + i) 0 ps
| ConstructorP(_,p) => r p
| _ => 0
end
This function g has to receive a type unit -> int function as the first argument. I checked the count after I called the function and got 0, so it is ok to write it like this, right? But still, it does feel sloppy.
Added the context (function g and the datatype used). The function count_wcs is supposed to count the number a Wildcard pattern appears in a pattern.
This does not count as a mutation, but it does resemble what you might do if you had them and is probably not going to work, depending on what it is you're doing. Mutations require references and they're made with ref and are de-referenced with !. So just stick away from those. :-)
You're doing something that will be of little benefit:
let
val count = 0
in
...
end
will bind count to 0, but will never cause count to have any other value; I presume that you want to eventually have that count increases. If it had been a reference, val count = ref 0, you could increment it by doing count := !count + 1, but since it's not, you have to make count a variable of some function for it to change.
For example:
fun count_4s ([], count) = count
| count_4s (x::xs, count) = count_4s (xs, if x = 4 then count + 1 else count)
In each call count is constant, but in each subsequent, recursive call it is possibly incremented.
This function g has to receive a type unit -> int function as first argument.
...
g (fn () => count + 1) (fn y => 1) p
...
[...] But still it does feel sloppy.
Assuming that g's first arguments have no side-effects and do not throw exceptions and do not loop forever, all they can do is return the same thing on every call. This makes them rather boring. Typically functions that either take as input or return () : unit do something else, like read or write from a source external to the program.
I wouldn't call it sloppy. Just a bit weird, without knowing the context.
It's very easy to identify mutation in standard ML - if you don't use ref variables and assign them new values with :=, it's not mutation.
And you don't, so you aren't mutating anything.
Also, your function can be simplified to
fun count_wildcards p = g (fn () => 1) (fn _ => 1) p
which makes it even clearer that nothing gets mutated.
(It's not at all clear what it's supposed to accomplish, so it's impossible to tell whether your solution is correct.)
I'm struggling to understand the way that the "in" instruction works, I have an exam in a few days and even though I fell pretty confident with the way ocaml works, there's a lot of previous exams that brings me to some scoping questions, as far as I know ocaml is a static scope language, so if for example you declare a value and you use it inside a function (without passing it as an argument of course), even if you overwrite the value the function will still use the previous one, for example
let a = 5;;
let f x = a+x;;
let a = 1;;
f 1;;
Will return 6 even though the a value has been overwritten, but there are some pretty sketchy questions in the exam, like for example
let a = 6 in
let b x = a + x in
let a = 42 in
b a;;
This one confuses me a lot, how does the "in" work? I know that this returns 48, but I'm struggling to see a pattern that I can use to understand how the scoping works when you use the "in" instruction.
Any explanation will be appreciated really much
Thanks in advance :D
Will return 6 even though the a value has been overwritten
It's not overwritten. You create a new variable with the same name. I.e., you don't change the existing variable - you create a new one which hides the existing one. What happens is this:
let a1 = 5;;
let f x = a1 + x;;
let a2 = 1;;
f 1;;
The same in the second example:
let a1 = 6 in
let b x = a1 + x in
let a2 = 42 in
b a2;;
I want to calculate f(..f(x)) p times. The following is my code.
let rec function f x p = if p = 0 then x else function f (f x) p-1;;
I wonder how I should make it right.
This is very close, but your code has syntax errors that are going to make it hard to make progress. I think the main problem is that you're using function as an identifier, but it is a keyword in OCaml. If you change to myfun, things should start working quite a bit better.
You also need to watch your precedences. The following code:
f a b-1
is parsed like this:
(f a b) - 1
not like this:
f a (b - 1)
You need to write the parentheses explicitly to get this second parse.
You can define a recursive function ch to apply a function f many times (Church numeral??) as follows:
let rec ch f p x = if p = 0 then x else f (ch f (p-1) x);;
The problems in your original code are that:
need to name the function as something, such as ch here.
need to call the same function ch to get the recursion going as shown above. In your original code, there is no recursion.
Example
let p1 x = x + 1 ;;
ch p1 3 1 ;;
this will give you
- : int = 3
as intended.
I wonder when working with list in ml, how to change a variable with specific location of the list. For instance, when I have a list [1,2,3,4], I want to change the list to [1,2,5,4] with the 5 subtitle for the 3. What i'm thinking is to write a function that take a location, the variable and the list, return the new list with the update variable. For example,
change(i, var, list) = let val valup = var in (list # [i]) end
So with this code, if my input is change(2, 5, [1,2,3,4]), my out put will be [1,2,3,4,2] which incorrect compare to [1,2,5,4]. I'm new with ml and not good with the list setup in the language so any help would be really appreciate.
You have to realise that values are not mutable in ML. This means that once you create a value, you can't change it!
So if we have these two statements
x = [2,3,4]
y = 1::x
then y and x live in seperate memory locations on the computer.
What you can do is the following:
fun swapFirst [] y = raise Empty
| swapFirst (x::xs) y = y::xs
val test_swapFirst_00 = [1,2,3,4] = swapFirst [2,2,3,4] 1
which will swap the first element of a list out with something else.
Now I have a feeling that this could be for an answer for some course work, so I'm not going to give a complete code that solves your problem, but this information should at least clear some things up, and make it easier for you to solve the problem!
I come up with the solution for the problem.
fun change(i,v,[]) = raise Error
| change(0, v, x::xs) = v :: xs
| change(i, v, x::xs) = if i < 0 then raise Error
else x :: change((i-1), v, xs)