The function is meant to evaluate an arbitrarily structured expression with references to a list of variables. (I know this question exists, but its answer is poorly written and I cannot understand it.)
My work so far is below:
lookup(X, Env, V) :-
member(val(X,V),Env). //finds the value of a variable in the "environment".
eval(S, Env, V):-
lookup(S,Env,V). //if expression is a single variable name/key, return the value of the pair.
eval(H+T, Env, V):- //if expression is in the form of head+tail...
lookup(H,Env,HVal), //first, make sure that the head can be looked up;
eval(T, Env, V - HVal). //then, treat the tail as its own expression while expecting a modified value.
eval(F+S, Env, V):- //if expression is contains two atoms, evaluate their sum.
lookup(F, Env, FVal),
lookup(S, Env, SVal),
V is FVal + SVal.
... % minus, times etc. implemented similarly
Right now, the code works fine for single-value look up like:
?- eval(a, [val(a,1),val(b,2),val(c,3)], V).
V = 1 .
As well as "diatomic" expressions:
?- eval(a+b, [val(a,1),val(b,2),val(c,3)], V).
V = 3 .
but more than that (i.e. a+b+a) makes the code return false. instantly.
What's wrong with my implementation? How can I fix it?
Related
ans=readline(stdin)
function g(n)
if ans==a
return 1
else
return n
end
This is my code but the readline function only takes strings and i want it to take an expression which i can use in my function. What i want is to assign an expression (a) for variable ans.
You could try something like this:
julia> function check(x)
ans = readline()
val=Main.eval(Meta.parse(ans))
println("val == $x :", val==x)
end;
julia> check(5)
2+3
val == 5 :true
Remarks:
Your functions should not reference global variables (like ans in your example) - if you need to get the value of ans - pass it as parameter.
Parsing the expression is unsafe - a user might want for an example use this functionality to delete your data. Use with care! In some scenarios you might want for an example to use regular expressions to validate user's input.
let list p = if List.contains " " p || List.contains null p then false else true
I have such a function to check if the list is well formatted or not. The list shouldn't have an empty string and nulls. I don't get what I am missing since Check.Verbose list returns falsifiable output.
How should I approach the problem?
I think you don't quite understand FsCheck yet. When you do Check.Verbose someFunction, FsCheck generates a bunch of random input for your function, and fails if the function ever returns false. The idea is that the function you pass to Check.Verbose should be a property that will always be true no matter what the input is. For example, if you reverse a list twice then it should return the original list no matter what the original list was. This property is usually expressed as follows:
let revTwiceIsSameList (lst : int list) =
List.rev (List.rev lst) = lst
Check.Verbose revTwiceIsSameList // This will pass
Your function, on the other hand, is a good, useful function that checks whether a list is well-formed in your data model... but it's not a property in the sense that FsCheck uses the term (that is, a function that should always return true no matter what the input is). To make an FsCheck-style property, you want to write a function that looks generally like:
let verifyMyFunc (input : string list) =
if (input is well-formed) then // TODO: Figure out how to check that
myFunc input = true
else
myFunc input = false
Check.Verbose verifyMyFunc
(Note that I've named your function myFunc instead of list, because as a general rule, you should never name a function list. The name list is a data type (e.g., string list or int list), and if you name a function list, you'll just confuse yourself later on when the same name has two different meanings.)
Now, the problem here is: how do you write the "input is well-formed" part of my verifyMyFunc example? You can't just use your function to check it, because that would be testing your function against itself, which is not a useful test. (The test would essentially become "myFunc input = myFunc input", which would always return true even if your function had a bug in it — unless your function returned random input, of course). So you'd have to write another function to check if the input is well-formed, and here the problem is that the function you've written is the best, most correct way to check for well-formed input. If you wrote another function to check, it would boil down to not (List.contains "" || List.contains null) in the end, and again, you'd be essentially checking your function against itself.
In this specific case, I don't think FsCheck is the right tool for the job, because your function is so simple. Is this a homework assignment, where your instructor is requiring you to use FsCheck? Or are you trying to learn FsCheck on your own, and using this exercise to teach yourself FsCheck? If it's the former, then I'd suggest pointing your instructor to this question and see what he says about my answer. If it's the latter, then I'd suggest finding some slightly more complicated function to use to learn FsCheck. A useful function here would be one where you can find some property that should always be true, like in the List.rev example (reversing a list twice should restore the original list, so that's a useful property to test with). Or if you're having trouble finding an always-true property, at least find a function that you can implement in at least two different ways, so that you can use FsCheck to check that both implementations return the same result for any given input.
Adding to #rmunn's excellent answer:
if you wanted to test myFunc (yes I also renamed your list function) you could do it by creating some fixed cases that you already know the answer to, like:
let myFunc p = if List.contains " " p || List.contains null p then false else true
let tests =
testList "myFunc" [
testCase "empty list" <| fun()-> "empty" |> Expect.isTrue (myFunc [ ])
testCase "nonempty list" <| fun()-> "hi" |> Expect.isTrue (myFunc [ "hi" ])
testCase "null case" <| fun()-> "null" |> Expect.isFalse (myFunc [ null ])
testCase "empty string" <| fun()-> "\"\"" |> Expect.isFalse (myFunc [ "" ])
]
Tests.runTests config tests
Here I am using a testing library called Expecto.
If you run this you would see one of the tests fails:
Failed! myFunc/empty string:
"". Actual value was true but had expected it to be false.
because your original function has a bug; it checks for space " " instead of empty string "".
After you fix it all tests pass:
4 tests run in 00:00:00.0105346 for myFunc – 4 passed, 0 ignored, 0
failed, 0 errored. Success!
At this point you checked only 4 simple and obvious cases with zero or one element each. Many times functions fail when fed more complex data. The problem is how many more test cases can you add? The possibilities are literally infinite!
FsCheck
This is where FsCheck can help you. With FsCheck you can check for properties (or rules) that should always be true. It takes a little bit of creativity to think of good ones to test for and granted, sometimes it is not easy.
In your case we can test for concatenation. The rule would be like this:
If two lists are concatenated the result of MyFunc applied to the concatenation should be true if both lists are well formed and false if any of them is malformed.
You can express that as a function this way:
let myFuncConcatenation l1 l2 = myFunc (l1 # l2) = (myFunc l1 && myFunc l2)
l1 # l2 is the concatenation of both lists.
Now if you call FsCheck:
FsCheck.Verbose myFuncConcatenation
It tries a 100 different combinations trying to make it fail but in the end it gives you the Ok:
0:
["X"]
["^"; ""]
1:
["C"; ""; "M"]
[]
2:
[""; ""; ""]
[""; null; ""; ""]
3:
...
Ok, passed 100 tests.
This does not necessarily mean your function is correct, there still could be a failing combination that FsCheck did not try or it could be wrong in a different way. But it is a pretty good indication that it is correct in terms of the concatenation property.
Testing for the concatenation property with FsCheck actually allowed us to call myFunc 300 times with different values and prove that it did not crash or returned an unexpected value.
FsCheck does not replace case by case testing, it complements it:
Notice that if you had run FsCheck.Verbose myFuncConcatenation over the original function, which had a bug, it would still pass. The reason is the bug was independent of the concatenation property. This means that you should always have the case by case testing where you check the most important cases and you can complement that with FsCheck to test other situations.
Here are other properties you can check, these test the two false conditions independently:
let myFuncHasNulls l = if List.contains null l then myFunc l = false else true
let myFuncHasEmpty l = if List.contains "" l then myFunc l = false else true
Check.Quick myFuncHasNulls
Check.Quick myFuncHasEmpty
// Ok, passed 100 tests.
// Ok, passed 100 tests.
I have an OCaml function that returns the value of a specified cell in a table. The function works correctly but I still get a warning stating:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
([],_)
even though I have in fact accounted for that value in my implementation here:
let cell_value([i;j],table) = match ([i;j],table) with
([],_) -> []
| (_,[]) -> []
| (_::_,_::_) -> List.nth (List.nth table (j-1)) (i-1);;
Like I said, the function returns the correct value, I'm just trying to get rid of the error. I'm still fairly new to OCaml, so any help would be greatly appreciated!
Contrary to what you might believe, the problem is not coming from the pattern-matching introduced by the match keyword but by another one you may not be aware of. Indeed, there is a pattern matching in the following fragment of your definition:
let cell_value ([i;j], table) = ...
because ([i; j], table) actually contains the pattern [i; j]. For this reason, this definition assumes that the first component of the pair given as argument to cell_value is a list containing exactly two elements. In other words, this definition is equivalent to:
let cell_value = function ([i; j], table) -> ...
or also to:
let cell_value x = match x with ([i; j], table) -> ...
Now, you probably understand the warning issued by the compiler: if you provide a value of the form ([], table) to your function, it will fail. The compiler is right:
# cell_value ([], []);;
Exception: Match_failure ("//toplevel//", 1, 14).
I wanted to create a global variable called result that uses 5 string concatenations to create a string containing 9 times the string start, separated by commas.
I have two pieces of code, only the second one declares a global variable.
For some reason it's not registering easily in my brain... Is it just that i used a let in so result in the first piece of code is a local variable? Is there a more detailed explanation for this?
let start = "ab";;
let result = start ^ "," in
let result = result ^ result in
let result = result ^ result in
let result = result ^ result in
let result = result ^ start in
result;;
- : string = "ab,ab,ab,ab,ab,ab,ab,ab,ab"
let result =
let result = start ^ "," in
let result = result ^ result in
let result = result ^ result in
let result = result ^ result in
let result = result ^ start in
result;;
val result : string = "ab,ab,ab,ab,ab,ab,ab,ab,ab"
Let me to be a little bit boring person. There are no local and global variables in OCaml. This concept came from languages with different scoping rules. Also, the word "variable" itself should be taken with care. Its meaning was perverted by C-like languages. The original, mathematical, meaning of this word corresponds to a name of some mathematical object, that is used inside a formula, that represent a range of such values. In C-like languages, a variable is confused with the memory cell, that can change in time. So, to avoid the confusion let's use a more accurate terminology. Let's use word name instead of variable. Since, variables... sorry names are not memory cells, there is nothing to create. When you're using one of the let syntaxes, you're actually creating a binding, i.e., an association between a name and a value. The let <name> = <expr-1> in <expr-2> binds a value of the in the scope of the <expr-2> expression. The let <name> = <expr-1> in <expr-2> is by itself is also an expression, so, for example <expr-2> can also contain let ... in ... constructs inside, e.g.,
let a = 1 in
let b = a + 1 in
let c = b + 1 in
a + b + c
I especially, indented the code in non-idiomatic way to highlight the syntactic structure of the expression. OCaml also allows to use a name, that is already bound in the scope. The new binding will hide the existing one (that is not allowed in C, for example), e.g.,
let a = a + 1 in
let a = a + 1 in
let a = a + 1 in
a + a + a
Finally, the top-level (aka module level) let-binding (called definition in OCaml parlance), has the syntax: let <name> = <expr>, note that there is no in here. The definition binds the <name> to a result of the evaluation of <expr> in the lexical scope that extends form the point of definition to the end of the enclosing module. When you're implementing a module, you must use let <name> = <expr> to bind your code to names (you may omit name by using _). It is a little bit different from the interactive toplevel (interactive ocaml program), that actually accepts an expression, and evaluates it. For example,
let result = start ^ "," in
let result = result ^ result in
let result = result ^ result in
let result = result ^ result in
let result = result ^ start in
result
Is not a valid OCaml program (something that can be put into an ml file and compiled). Because it is an expression, not a module definition.
Is it just that i used a let in so result in the first piece of code is a local variable?
Pretty much. The syntax to define a global variable is let variable = expression without an in. The syntax to define a local variable is let variable = expression in expression which will define variable local to the expression after the in.
When you have let ... in, you're declaring a local variable. When you have just let by itself (at the top level of a module), you're declaring a global name of the module. (That is, a name that can be exported from the module.)
Your first example consists entirely of let ... in. So there is no top-level name declared.
Your second example has one let by itself, followed by several occurrences of let ... in. So it declares a top-level name result.
[<ReflectedDefinition>]
let rec x = (fun() -> x + "abc") ()
The sample code with the recursive value above produces the following F# compiler error:
error FS0432: [<ReflectedDefinition>] terms cannot contain uses of the prefix splice operator '%'
I can't see any slicing operator usage in the code above, looks like a bug... :)
Looks like this is the problem with the quotation via ReflectedDefinitionAttribute only, normal quotation works well:
let quotation =
<# let rec x = (fun() -> x + "abc") () in x #>
produces expected result with the hidden Lazy.create and Lazy.force usages:
val quotation : Quotations.Expr<string> =
LetRecursive
([(x, Lambda (unitVar,
Application
(Lambda (unitVar0,
Call (None,
String op_Addition[String,String,String](String, String),
[Call (None,
String Force[String](Lazy`1[System.String]), // `
[x]), Value ("abc")])),
Value (<null>)))),
(x, Call (None, Lazy`1[String] Create[String](FSharpFunc`2[Unit,String]), [x])),
(x, Call (None, String Force[String](Lazy`1[String]), [x]))], x) // `
So the question is: is this an F# compiler bug or not?
I'd think that this may be caused by the treatment of recursive values in F#. As a workaround, you can turn the recursive reference into a parameter:
[<ReflectedDefinition>]
let foo x = (fun() -> x + "abc") ()
// To construct the recursive value, you'd write:
let rec x = foo x
The last line is of course invalid (just like your original code), because you're creating an immediate recursive reference, but it should give you the idea - in reality, you'd probably enclose x in a lambda function.
EDIT Originally, I thought that the problem may be as below, but I'm not sure now (see comments).
It looks more like a (probably known) limitation to me than an unexpected bug. There is an important difference between the two versions of the code you wrote - in the first case, you're binding a public value (visible to .NET) named x while in the second case, x is just a symbol used only in the quotation.
The quotation that would have to be stored in the meta-data of the assembly would look like this:
let rec x = <# (fun() -> %x + "abc") () #>
The body is quoted, but x is not a quoted symbol, so it needs to be spliced into the quotation (that is, it will be evaluated and the result will be used in its place). Note that this code will fail, because you're declaring a recursive value with immediate reference - x needs to be evaluated as part of its definition, so this won't work.
However, I think that % cannot appear in ReflectedDefinition quotations (that is, you cannot store the above in meta-data), because it involves some runtime aspects - you'd need to evaluate x when loading the meta-data.