How to compare string to value without quotation marks - string

I am pretty new to Haskell and today I was trying to make a calculator using Haskell (like most people make when learning a new language to get the hold of if statements) and I had trouble using if values with strings. I want to check if the string the user wrote is "plus" (without "") but if I don't the quotation marks (so it'd look like if op == plus) it doesn't recognize it as a string and outputs an error but if on the other hand I use the quotation marks (so it'd look like this if op == "plus") then it looks for the string "plus" with the quotation marks, how can I compare a string to a value without quotation marks?
Case 1:
calculate x op y = do
if op == "plus"
then x+y
else x
Result: the program looks for "plus" when calling the function and thus if the input when calling the function is for example "1 plus 3" it will give out an error of ':67:13: error: Variable not in scope: plus :: [Char]
Case 2:
calculate x op y = do
if op == plus
then x+y
else x
Result: When trying to load the program I get the error "test.hs:2:33: error: Variable not in scope: plus
Failed, modules loaded: none.", so I can't try and call the function obviously.

The quotation marks are just part of the syntax of string literals, not their contents. That is, if you write op == "plus", this will be true if (and only if) plus contains the characters 'p', 'l', 'u' and 's' (in that order, obviously) - it does not require (or allow) op to contain any quotes.
So if op == "plus" does not produce True for you even when you think it should, op does not contain what you think it does.

Related

How can I stop Applescript from comparing strings to numbers?

So I just found out that strings can be compared to each other in Applescript like this:
"hello world" > "abc"
Returns:
true
However, you can also compare strings to numbers. The string will, however always be greater:
"a" = 10 ^ 308 -- Close to infinity
Returns:
false
Is there a way to only compare numbers without using try- and on error-statements?
The meaning of your exercises is incomprehensible. It is not clear
what is the use? AppleScript is written exactly the way the developers wanted it to be. For example, they thought: why not compare a string to a number. You can't (and it's good that you can't) change the behavior of AppleScript's logical operations. But you can write your "smart equivalents" to them. And use them.
on isNumbersEqual(x, y)
tell {real, integer}
if x's class is not in it then error "LEFT OPERAND ISN'T NUMBER"
if y's class is not in it then error "RIGHT OPERAND ISN'T NUMBER"
end tell
x = y
end isNumbersEqual
-- isNumbersEqual("1", 10 ^ 308) --> ERROR!!
isNumbersEqual(1, 10 ^ 308) --> false
Note: Unlike other programming languages, AppleScript does not throw an error when comparing strings to numbers. Instead, it implicitly coerces the number to a string to perform a legitimate comparison. You can check my statement:
("1" > 10 ^ 308) is ("1" > (10 ^ 308 as string)) --> true
An easy way around this is to check for the class of the variable or string you are passing:
set x to "This is my innocent string"
if x > 0 and class of x ≠ string then --do stuff here.

what does this syntax error means. I wrote my code good. What is the problem?

why do I get this problem: SyntaxError: EOL while scanning string literal. Can someone please tell me where my fault is.
a = 2
b = 4
c = 8
print ("Forced Order:" 'a', '*' ('c' '+' 'b') '=’ a*(c+b))
The EOL error specifically appears because of '*' ('c' '+' 'b'). The computer believes that this code is trying to run a function, much like print(). The error pops up because a string cannot call a function like this.
What I imagine your trying to do is make the function output is Forced Order: a*(c+b)=24.That can be solved with two quick fixes:
First, there's a typo. '=’ should use ' not ’ on both sides.
Second, the parenthesis need to be parts of the string. The parenthesis in ('c' '+' 'b') are not part of any strings. Either they can be individually turned into strings like the rest of the function or, just like with the string "Forced Order:", the string "a*(c+b)" can be written out as one string instead of concatenating a series of single characters.

Prolog: Checking if the first and last character of a string are left and right squiggly brackets('{' & '}')

I am very new to prolog, so assume that I know very little terminology.
I am using swipl in SWI-prolog.
I want to check if a string starts with a left squiggly bracket('{') and ends with a right squiggly bracket('}'}
Some answers that I have read online have lead me to program the following into my knowledge base to check if the string starts with a left squiggly bracket.
start_left_squiggle([Letter|_]):-
Letter = '{'.
But when I run this function, I get false, when I expect it to return true.
?- start_left_squiggle('{hello').
false.
As well, answers that seem correct for checking the if the last character is a squiggly bracket have lead me to code the following.
last_char(str, X):-
name(S, N),
reverse(N, [F|_]),
name(X, [F]).
end_right_squiggle(Werd):-
last_char(Werd, Last),
Last = '}'.
And I again get false when running the function, when I expect it to return true.
?- end_right_squiggle('hello}').
false.
Use sub_atom(Atom, Before, Length, After, Subatom) like so:
?- sub_atom('{abc}',0,1,_,C).
C = '{'.
?- sub_atom('{abc}',_,1,0,C).
C = '}'.
Or just test:
?- sub_atom('{abc}',0,1,_,'{').
true.
?- sub_atom('{abc}',_,1,0,'}').
true.
First thing you need to do is to break the atom into list of characters like this:
start_with_left(H):-
atom_chars(H,X), %here x is a list
X = [L|_], %get the head of the list which is frist element an compare
L == '{'.
You can use a recursive definition to check righ side of the atom after converting the atom into list of characters and when length of the list is 1 then compare it with bracket , it means if last element is same you should get true otherwise False.
Right is like this, it's same but we need last element so we have to use recursion:
start_with_right(H):-
atom_chars(H,X), %here x is a list
length(X,Y),
check_at_end(X,Y).
check_at_end([H|_],1):-
H == '}'.
check_at_end([_|T],Y):-
NewY is Y -1,
check_at_end(T,NewY).
.

Standard ML string to a list

Is there a way in ML to take in a string and output a list of those string where a separation is a space, newline or eof, but also keeping strings inside strings intact?
EX) hello world "my id" is 5555
-> [hello, world, my id, is, 5555]
I am working on a tokenizing these then into:
->[word, word, string, word, int]
Sure you can! Here's the idea:
If we take a string like "Hello World, \"my id\" is 5555", we can split it at the quote marks, ignoring the spaces for now. This gives us ["Hello World, ", "my id", " is 5555"]. The important thing to notice here is that the list contains three elements - an odd number. As long as the string only contains pairs of quotes (as it will if it's properly formatted), we'll always get an odd number of elements when we split at the quote marks.
A second important thing is that all the even-numbered elements of the list will be strings that were unquoted (if we start counting from 0), and the odd-numbered ones were quoted. That means that all we need to do is tokenize the ones that were unquoted, and then we're done!
I put some code together - you can continue from there:
fun foo s =
let
val quoteSep = String.tokens (fn c => c = #"\"") s
val spaceSep = String.tokens (fn c => c = #" ") (* change this to include newlines and stuff *)
fun sepEven [] = []
| sepEven [x] = (* there were no quotes in the string *)
| sepEven (x::y::xs) = (* x was unquoted, y was quoted *)
in
if length quoteSep mod 2 = 0
then (* there was an uneven number of quote marks - something is wrong! *)
else (* call sepEven *)
end
String.tokens brings you halfway there. But if you really want to handle quotes like you are sketching then there is no way around writing an actual lexer. MLlex, which comes with SML/NJ and MLton (but is usable with any SML) could help. Or you just write it by hand, which should be easy enough in this case as well.

Call function based on a string

I am passing in command line arguments to my Lisp program and they are formatted like this when they hit my main function:
("1 1 1" "dot" "2 2 2")
I have a dot function (which takes two vectors as arguments) and would like to call it directly from the argument, but this isn't possible because something like (funcall (second args)...) receives "dot" and not dot as the function name.
I tried variations of this function:
(defun remove-quotes (s)
(setf (aref s 0) '""))
to no avail, before realizing that the quotes were not really a part of the string. Is there a simple way to do this, or should I just check each string and then call the appropriate function?
"1 1 1" is a string of five characters: 1, space, 1, space and 1. The double quotes are not part of the string.
("1 1 1" "dot" "2 2 2") is a list of three strings.
There are no " characters above. The " are used to delimit strings in s-expressions.
If you have a dot function you need to tell us what kind of input data it expects.
Does it expect two lists of numbers? Then you have to convert the string "1 1 1" into a list of numbers.
(with-input-from-string (in "1 1 1")
(loop for data = (read in nil in)
until (eq data in)
collect data)))
To get the function DOT from the string "dot" first find the symbol DOT and then get its symbol function.
(symbol-function (find-symbol (string-upcase "dot")))
For find-symbol one might need to specify also the package, if there is a special package where the symbol is in.
Converting a list to a vector then is the next building block.
So you need to convert the arguments for your function to vectors (probably first converting them to lists as I showed above). Then you need to find the function (see above). If you have then the function and the arguments, then you can call the function using FUNCALL or APPLY (whatever is more convenient).
The question is a bit unclear, but as far as I understand it you want, when given the list ("1 1 1" "dot" "2 2 2") as input to evaluate the expression (dot "1 1 1" "2 2 2"). In that case you can do this:
(defun apply-infix (arg1 f arg2)
(apply (intern (string-upcase f)) (list arg1 arg2)))
(defun apply-list-infix (lst)
(apply 'apply-infix lst))
(apply-list-infix '("1 1 1" "dot" "2 2 2"))
funcall does not accept a string as a function designator. You need to give it a symbol instead. What you probably want to do is:
Convert the string to upper case (Lisp symbols are usually upper case, and even though it may look like Lisp is case-insensitive, that's just because the reader upcases all symbols it reads by default) (string-upcase).
Create or find a symbol with the given name (intern). Note that, if *package* is not set according to the package your function's name lives in, you need to supply the package name as the second argument to intern.
For instance (for a function named dot in package cl-user:
(funcall (intern (string-upcase "dot") 'cl-user) ...)

Resources