In the following function, which reverses an array/list:
let rec rev l =
match l with
[] -> []
| h::t -> rev t # [h];;
One will notice that there is a pipe | before the following line:
h::t -> rev t # [h];;
I was wondering if anyone would be kind enough to explain what the purpose of this vertical bar | is in OCaml, and perhaps other uses? Thank you.
In your example it serves as a pattern separator for a multiple selection statement, sorta like the case of a switch statement in C like languages.
let is_vowel c = match c with
'a' | 'e' | 'i' | 'o' | 'u' -> true
| _ -> false ;;
function is_vowel(c){
switch(c){
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return true;
default:
return false;
}
}
These 2 pieces of code would generate the same output, however this is where the similarity's end. I found this documentation to be very helpful, it go's more into detail what else you can or cannot do with match.
Other uses of the pipe operator are:
enumerated type declaration
type typ = N1 | N2 | N3
union type declaration
type typ = N1 of typ1 | N2 of typ2
It separates the pattern match cases.
Related
let rec createSentence(list) = (
match list with
case [] -> failwith "błędna lista"
| case [_] -> List.hd list
| case [_,_] -> List.hd list ^ createSentence(List.tl list)
| case _ -> List.hd list ^ " " ^ createSentence(List.tl list);;
);;
Ocaml returns a Syntax error: operator expected. I have no idea how to move forward with this
The pattern-matching in OCaml has the following syntax,
match <expr> with
| <pattern1> -> <action1>
| <pattern2> -> <action2>
...
e.g.,
match ["hello"; "world"] with
| [word1; word2] -> print_endline (word1 ^ word2)
| _ -> assert false
Also, note that the list elements in OCaml are separated with ;
I would suggest reading the Introduction to OCaml or some OCaml book
Update: to make it more clear, there is no case keyword in OCaml and you shouldn't write case before a pattern, i.e., instead of | case [], just write | [].
How can I write a function in Ocaml, that would accept two boolean values (for instance a and b, that would represent logical values 0 and 1) and a character, that would determine the operation between these two logical values? The function would then return true or false, depending on the corresponding logical value input.
There is both a semantic, as well as a syntax error in this code; well, maybe there are more, but the compiler only made a complaint about this one so far:
line 2, characters 27-30:
Error: This expression has type char but an expression was expected of type
bool
This is what the compiler has stated about the code and here's what I've wrote:
let logic (a, b) operation = match operation with
| true -> if (operation == 'A') then match (a,b) with
| (true, true) -> true
| _ -> false
else if (operation == '0') then match (a,b) with
| (false,false) -> false
| _ -> true
else if (operation == 'X') then match (a,b) with
| (true,true) -> false
| (false,false) -> false
| _ -> true
else if (operation == 'I') then match (a,b) with
| (true, false) -> false
| _ -> true
else then match (a,b) with
| _ -> false
| false -> end;;
logic (a,b) 'A';;
--------------------------------------------------------------------------
OK, I've made some progress,at least it compiles now. However I still get an error, when I try to call the "logic" function with this line:
logic (true, false) 'A';;
The error states this:
Error: This expression has type bool
This is not a function; it cannot be applied.
Here's what I wrote now:
let logic (a, b) operation = match operation with
| 'A' -> (match (a,b) with
| (true, true) -> true
| _ -> false
)
| '0' -> (match (a,b) with
| (false,false) -> false
| _ -> true
)
| 'X' -> (match (a,b) with
| (true,true) -> false
| (false,false) -> false
| _ -> true)
| 'I' -> (match (a,b) with
| (true, false) -> false
| _ -> true
)
| _ -> (match (a,b) with
| _ -> false
)
To expand on the comment of #Elan-Hamburger a little bit.
You have this:
match operation with
| true -> ...
But your operation is a character. So this won't work. You can only match operation against specific characters.
It's especially strange since you later compare operator to various characters using ==. But the match will do that for you.
In other words you can have something like this:
match operation with
| 'A' -> ...
| '0' -> ...
| 'X' -> ...
| 'I' -> ...
| _ -> ...
There are many other problems with your code. Here are some comments:
You have nested match statements, which requires parentheses to work out right. If you try to nest without parentheses there's no way to tell when the inner match is over and further alternatives (starting with |) of the outer match are given.
Nested match statements look like this:
match expr with
| X ab ->
(match ab with
| A -> 4
| B -> 2
)
| Y _ -> 0
(You can also use begin/end instead of parentheses if you prefer the way that looks.)
You're using == to compare values. The ordinary equality comparison operator is =. The special operator == should only be used when you have a specific reason for it.
You have code that reads like this:
else then match ...
This can't be syntactically correct. Possibly the then is left over from an edit.
You can simplify this expression
match (a, b) with
| _ -> false
to this simpler expression:
false
Update
I can't reproduce your new reported problem. In fact your new code works OK for me in two quick tests.
. . .
val logic : bool * bool -> char -> bool = <fun>
# logic (true, false) 'A';;
- : bool = false
# logic (true, true) 'A';;
- : bool = true
Possibly there was some extraneous input (or extraneous definitions) in your top-level session. I suggest just trying again with a fresh session.
I want to build a list of type (char, 'a list) list where each char is an upper case letter of the alphabet. I'am getting a warning Warning 11: this match case is unused. for the second match case on get_list. I did some prints on the first case and found out len get's there with value 0, so it never uses the second case. What's happening?
let rec get_list abc i len =
match i with
| len -> []
| _ -> ((String.get abc i), [])::get_list abc (i + 1) len
in
let rec print_list l =
match l with
| [] -> ()
| h::t -> print_char(fst h);print_list t
in
let abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" in
let abc_l = get_list abc 0 (String.length abc) in
print_list abc_l;;
The reason it doesn't work
When you write
match i with
| len -> []
| _ -> ["..."]
len is a generic pattern, which hasn't anything to do with the len define above. In a pattern matching you define only how the variable should look like, you describe it's general "structure", the variable names are used to name the differents parts of the pattern matching, and are new variables. For example with lists you can do:
match my_list with
| [x,y,z] -> x+y+z
| x :: r -> x + (List.length r)
| anything_else -> List.length anything_else
When you put '_' it's only a convention to say "I don't mind which value it is, I don't need it". Here is another example with tuples:
match my_tuple with
| (a,b) -> a+b
A solution : conditionnal pattern matching
If you want to put condition in a pattern matching you can use the when keyword :
match i with
| n when n = len -> []
| _ -> ["..."]
Another example that "sort" a tuple:
match my_tuple with
| (a,b) when a>b -> (a,b)
| (a,b) -> (b,a)
Or just use conditions with integers :
if i = len then []
else ["..."]
You can also note that you can do pattern matching within functions :
let f (a,b) = a+b
The len in your pattern is a new variable introduced by the pattern. As a pattern, its meaning is that it will match anything at all. Thus, the next pattern _ will never match.
As #AlexanderRevyakin says, this new variable len is hiding the parameter that's also named len.
It is not the case that the len in your pattern represents the value of the parameter len. OCaml patterns contain only new variables (to which pieces of the matched value are bound) and constants. They don't contain expressions that are evaluated at run time. For that you want to use if/then/else (as #AntonTrunov points out).
I'm playing around a little with F# syntax.
In Sweden we have a game called "Backslang" (googletranslated from "Rövarspråk")
The rules are quite simple. All words you say must be said in a specific way. While vocals are the same, each consonant must be pronounced with an "o" followed by the consonant again.
I.e. "L" would be "LOL", "FRIDAY" would be
"FOFRORIDODAY" and "BALL" would be "BOBALOLLOL".
I wrote some code that looks really stupid but does its job.
let myWord (x:string) =
x.Replace("q","qoq").Replace("w","wow").Replace("r","ror").Replace("t","tot").Replace("p","pop").Replace("s","sos").Replace("d","dod").Replace("f","fof").Replace("g","gog").Replace("h","hoh").Replace("j","joj").Replace("k","kok").Replace("l","lol").Replace("z","zoz").Replace("x","xox").Replace("c","coc").Replace("v","vov").Replace("b","bob").Replace("n","non").Replace("m","mom").Replace("Q","QOQ").Replace("W","WOW").Replace("R","ROR").Replace("T","TOT").Replace("P","POP").Replace("S","SOS").Replace("D","DOD").Replace("F","FOF").Replace("G","GOG").Replace("H","HOH").Replace("J","JOJ").Replace("K","KOK").Replace("L","LOL").Replace("Z","ZOZ").Replace("X","XOX").Replace("C","COC").Replace("V","VOV").Replace("B","Bob").Replace("N","Non").Replace("M","Mom").ToLower()
myWord "ball"
F# Interactive: val it : string = "bobalollol"
For the sake of readability, is there any way to give this code a better look?
I'm a newbie to F# and Functional Programming so any advices, protips and pointers are warmly welcome!
Perhaps something like this:
let isVowel = function
| 'a' | 'e' | 'i' | 'o' | 'u' | 'y' | 'å' | 'ä' | 'ö'
| 'A' | 'E' | 'I' | 'O' | 'U' | 'Y' | 'Å' | 'Ä' | 'Ö' -> true
| _ -> false
let lollify s =
[| for c in s do if isVowel c then yield c else yield c; yield 'o';yield c |]
|> System.String
[<EntryPoint>]
let main argv =
printfn "%A" <| lollify "Ball"
0
Note; this also has the benefit of not creating alot of temporary string objects.
Another option would be this:
let lollify s =
s
|> Seq.map (fun c -> if isVowel c then [|c|] else [|c;'o';c|])
|> Seq.collect id
|> Seq.toArray
|> System.String
String.collect (string >> function
| vowel when "aeiouyåäöAEIOUYÅÄÖ".Contains vowel -> vowel
| consonant -> consonant + "o" + consonant )
String.collect applies a function to each char of a string.
I am trying to write a code such that, given a list of parenthesis, I will check if the order is valid or not.
For simpleness, the follwoing datatype is defined.
datatype par = LPAR | RPAR
type pList = par list
What I have until now is:
fun valid(nil:plist): bool = true
| valid([Lpar]) = false
| valid([Rpar]) = false
| valid([Lrap,Rpar) = true
| valid(L::L1) =
For instance, "(()()"--> [Lpar,Lpar,Rpar,Lpar,Rpar] will return false
You can see that the parenthesis is in string format. I am confused since I will have to check to two things: that the left ( are equal to the left ) and that each ( matches a ). If so then I will need to make some helper functions.
Can you please provide me with information about what my helper functions should be or a better implementation of this?
ty
I have found out a way to solve my problem by counting the parenthesis. The logic goes like this:
I start from 0, if i find a left p I add 1, other wise I minus 1. Once I enter -1 i return false right away since I cannot have a right p come first. Then I recurse. If the final output is 0, the its true since this means that every left p matches a right p.
Q.E.D
I didn't try this in the repl but it should look something like this
fun valid_paren xs : bool =
fun aux (xs, ctr) = case xs of
[] => ctr = 0
| (x:xs') => case x of
'(' => aux (xs', ctr+1)
')' => aux (xs', ctr-1)
_ => aux (xs', ctr)
in
aux (xs, 0)