In the Elixir programming language,
there are two similar constructs cond and case.
Both resemble the switch or select statements from other langages
both cond and case are described on this page
Let me put if to the club too. You use if with one condition and a possible else, that's it. You use the cond statement when you have more than one condition and an if statement isn't enough, by the end, the case statement is used when you want to pattern match some data.
Let's explain by examples: suppose you want to eat apple if today is raining or rice if not, then you could use:
if weather == :raining do
IO.puts "I'm eating apple"
else
IO.puts "I'm eating rice"
end
This is a limited world, so you want to expand your options and because of that you will eat different things on some conditions, so the cond statement is for that, like this:
cond do
weather == :raining and not is_weekend ->
IO.puts "I'm eating apple"
weather == :raining and is_weekend ->
IO.puts "I'm will eat 2 apples!"
weather == :sunny ->
IO.puts "I'm happy!"
weather != :raining and is_sunday ->
IO.puts "I'm eating rice"
true ->
IO.puts "I don't know what I'll eat"
end
The last true should be there otherwise it'll raise an exception.
Well so what about case? It is used to pattern match something. Let's suppose you receive the information about the weather and the day of week as a message in a tuple and you depend on that to take a decision, you could write your intentions as:
case { weather, weekday } do
{ :raining, :weekend } ->
IO.puts "I'm will eat 2 apples!"
{ :raining, _ } ->
IO.puts "I'm eating apple"
{ :sunny, _ } ->
IO.puts "I'm happy!"
{ _, :sunday } ->
IO.puts "I'm eating rice"
{ _, _ } ->
IO.puts "I don't know what I'll eat"
end
So the case brings to you the pattern-matching approach to the data, that you don't have with if or cond.
My simple answer is:
cond receives no arguments, and it allows you to use a different condition in each branch.
case receives an argument, and every branch is pattern-matched against the argument.
Related
I am learning haskell at the moment and I'm having troubles with my logic, especially how to go about performing certain actions.
What I'm trying to do
The main goal is to have a function that contains multiple sentences (statements) with missing words, but, it only needs to print one sentence at a time.
We also need to have another function that prints out 4 options that will fill out a complete sentence for each statement that the first function contains/prints (These options are then chosen by the user to fill out the sentence).
Eg. - "This ___ contains ____"
Options:
String, words
List, options
etc
etc
Now we need another function that will take each sentence from function 1, and the options that the user selects from function 2, and create a complete sentence and returns it to the user.
I'm unsure whether we need a separate function that will take the user input and store the value that they choose from function 2 to complete the sentence from function 1, or if we can just add this in function 2 also.
What I was able to create
I was able to perform the actions stated above, but I was only able to do this for one sentence, and all of the actions were in a single function (not making the code efficient and reusable in my opinion).
I tried again with the structure I have in mind (Shown Above) but I am stuck as I said with the logic and unsure of how to go about it. Below I have the 2 versions of code I did, The first version is showcasing what I am aiming to do, but I was only able to do it with one sentence, and the second version is where I am right now with trying to use multiple functions, but I'm unsure of where to go next
Here's the code for the first version
--First Version
import Data.List
import System.IO
main :: IO()
sentences = do
putStrLn "The Cat is ______ from ______ the city \n"
putStrLn "Here are your options:"
putStrLn "A. big, nearby"
putStrLn "B. Nearby, in"
putStrLn "C: You, By"
putStrLn "D: By, Yourself"
option <- getChar
if (option == 'A' || option == 'a')
then putStrLn "The Cat is big from nearby the city"
else if (option == 'B' || option == 'b')
then putStrLn "The Cat is nearby from in the city"
else putStrLn "Error"
main = sentences
Here's the code for the second version (Where I am)
import Data.List
import System.IO
main :: IO()
--This function contains all the sentences
sentences = do
putStrLn "\nThe Cat is ______ from the ______ \n"
putStrLn "\nThe Cow belongs to ______ from ______ ______ \n"
putStrLn "\nThe Man lives in ______ and is neighbours with ______ \n"
-- This function basically prints after each sentence is displayed to signal to the user that they need to select an option
optionsText = do
putStrLn "Here are your options: \n"
-- These Functions contain the different options for different sentences
options1 = do
putStrLn "A. Running, dog"
putStrLn "B. Hiding, Man"
putStrLn "C. Eating, Trash"
putStrLn "D. Calling, Roof"
options2 = do
putStrLn "A. Tom, Next, Door"
putStrLn "B. Rick, My, Neighbour"
putStrLn "C. Man, farm, place"
putStrLn "D. Sheltor, Animal, Factory"
option3 = do
putStrLn "A. Australia, Me"
putStrLn "B. UK, Actor"
putStrLn "C. Florida, Tom"
putStrLn "D. House, Dog"
This seems to be a question about data modelling. Your solution so far operates on the level of characters: You define strings where a specific character, _ acts as a placeholder, and where you want to insert other characters in this place.
Programming is about abstraction. Thus, take a step back and think of your problem not in terms of individual characters, but in terms of sentence fragments and placeholders. Sentence fragments and placeholders make up a sentence. Define data types for these three. Then, look at the functionality you need. You want functions that render sentence fragments and placeholders for display on screen, and you need a function that can combine sentence fragments and placeholders into sentences. Finally, you need a function to display an entire sentence in terms of the display functions of the fragments and placeholders.
Once you have this abstraction in place, you can replace a placeholder by another sentence fragment and display it.
In:
eval x | "?" `isSuffixOf` x = privmsg (if "what" `isPrefixOf` x then "that would be an ecumenical matter" else "yes")
How can I have "what" be any of "what|who|how|why|where|when"?
I know it's not with | like that^, nor is it
eval x | "?" `isSuffixOf` x = privmsg (if "what" "who" "how" "why" "where" "when" `isInfixOf` x then "that would be an ecumenical matter" else "yes")
but I'm unsure of the logic of whatever syntactical fail I'm hitting upon, so everything else I'm trying are similar stabs in the dark, including searches.
(And how can I phrase this question better than "How can I make the target of a conditional be any of many?"? (As in, what are the terms I mean, that will better help me understand the situation and better form the search terms?)
You want any:
interrogatives = ["what", "who", "how", "why", "where", "when"]
eval x | "?" `isSuffixOf` x = privmsg (
if any (`isInfixOf` x) interrogatives
then "that would be an ecumenical matter"
else "yes"
)
Is there a way to pattern match any list without iterating through the two cases: empty or non-empty list ?
I would like to fix the following code:
foo [] = "something else"
foo [_:_] = "something else"
Since the part in something else is the same I would like to remove it from one place.
Thank you.
The pattern _ matches anything without binding it to a name. A name, like say, xs also matches anything. So you can do either:
foo _ = "something else"
or
foo xs = "something else"
If "something else" truly does not depend on the value of xs the first form is preferred, so that another programmer (and you) can quickly spot that the value is irrelevant in this particular equation.
Unfortunately, your first case is already of the second form, so it matches all possibilities. The other cases will never be reached.
I'm trying to write a function in Haskell which checks for some things and then recurses based on some minimal user input. In order to do that I think I have to use do blocks.
cip :: [Argument] -> [Argument] -> Bool -> Bool -> IO()
cip (a:args) pargs burden gameover = do
let nasko = a:pargs
putStrLn (getPremise a)
let newgraph = Carneades.mkArgGraph nasko
let newcaes = (CAES (newgraph,audience2,assStandarts))
let answer = (acceptable (mkProp (getPremise a)) newcaes )
print answer
if(answer==True)
then (cip args nasko burden gameover)
else do
print "One of the arguments is not proved. Here are the premises that need proving"
print (propsForFixing newcaes a)
print "Let's see what you have for the first Propositon"
--add an if to check if no applicable arguments.
print (argumentScanHelp (head (propsForFixing newcaes a)) args)
print "\n Would you like me to apply the firt one? Y/N"
choice <- getLine
if(choice=="Y") then do print "applying the argument"
let applicabee = head (argumentScanHelp (head (propsForFixing newcaes a)) args)
print "Argument targeted"
let newargs = delete applicabee args
let newpargs = applicabee:nasko
print "Argument applied sucsessfuly. Recusing again"
(cip newargs newpargs burden gameover)
return()
It hurts my eyes just by looking at it, but that's do blocks for you.
Everything up to the third do block is okay. But then on this line:
if(choice=="Y") then do print "applying the argument"
let applicabee = head (argumentScanHelp (head (propsForFixing newcaes a)) args)
The complier starts crying:
Main.hs:209:73: parse error on input `let'
Tried a all kinds of different indentations but I can't seem to get it to work.
I don't want to use separate functions, because that means I'll have to pass a lot of arguments around constantly.
Can anyone help me get it right? Also an explanation of what exactly the specifications for nested do block are would be greatly appreciated.
The cause of the error I believe is the misuse of the if expression. You use it as if it were an if statement that exists in most imperative languages. Simply put there must always be an else.
However, in do blocks it makes sense to "not have an else", something like an if statement without an else. Luckily the Control.Monad module will provide you with a function for exactly that:
import Control.Monad (when)
(...)
when (choice=="Y") $ do print "applying the argument"
let applicabee = ...
You seem to already use nested do blocks in the correct way which is good, which basically is that you must indent properly.
PS. Also make sure your last return () is indented like the rest of your code! DS.
Is this efficient for checking multiple statements in Haskell? Or this there a better way?
case ((x > -10) && (x < 20),x /= 9,(x `mod` 2) == 0,x) of
(False,_,_,_) -> error "Not in range"
(_,False,_,_) -> error "Must not be 9"
(_,_,False,_) -> error "Must be even"
(True,True,True,10) -> stuff ()
(True,True,True,20) -> stuff ()
_ -> error "Error Message"
It's sometimes difficult to come up with small examples of this problem which don't look contrived, but they do happen. Sometimes you need a bunch of computed results to figure out how to split a function into its cases.
So yes, I often find it's cleanest to use case on a tuple of things-I-might-care-about to build complex decision processes. I trust laziness to compute the minimum required to resolve which branch to invoke.
It's worth trying to express your tests via Boolean guards (or even pattern guards), but sometimes there's nothing to beat tabulating the computed values you need in a big tuple and then writing a row for each interesting combination of circumstances.
Assuming that caring about efficiency is really important, and is not premature optimization, you should optimize for the case which is most common; I think that even in Haskell, it means that you want to have the True,True,True cases on top.
Actually, in the given case, if x == 10 or x == 20 you don't need to do the other tests - you don't even need to build thunk computing them; and the compiler cannot know (without profile-guided optimization) which is the code path which will be executed the most, while you should have a reasonable guess (in general you need profiling to verify that).
So what you want is something like the following (untested):
case x of
10 -> stuff ()
20 -> stuff ()
_ -> case ((x > -10) && (x < 20),x /= 9,(x `mod` 2) == 0) of
(False,_,_) -> error "Not in range"
(_,False,_) -> error "Must not be 9"
(_,_,False) -> error "Must be even"
_ -> error "Error Message"
Disclaimer: I did not verify what happens to this code and to the original one after all optimizations.
How's this? You're checking the conditions in order, and returning something on the first to fail, so make the conditions into a list and search through it.
fn x = case lookup False conds of
Just ohno -> error ohno
Nothing
| x == 10 -> stuff
| x == 20 -> stuff
| otherwise -> error "Error Message"
where
conds = [
(x > -10 && x < 20, "Not in range"),
(x /= 9, "Must not be 9"),
(even x, "Must be even")]