I am starting to learn CLIPS at the moment and asked myself when is it better to use symbols and when strings?
On first sight it seems to me, that symbols are favorable because they are easier to compare than strings.
(eq test test)
is faster than
(= (str-compare "test" "test") 0)
Is there a downside to it too?
The advantage of symbols compared to strings is that you have to enter two fewer characters (the quotation marks). The disadvantage of symbols compared to strings is that some delimiters aren't allowed (notably the space characters). The str-compare function is primarily provided for alphabetic sorting. For equality testing, you can use eq:
CLIPS> (eq "test" "test")
TRUE
CLIPS> (eq "test" "nottest")
FALSE
CLIPS>
Related
Is it possible to quote result of function call?
For example
(quoteresult (+ 1 1)) => '2
At first blush, your question doesn’t really make any sense. “Quoting” is a thing that can be performed on datums in a piece of source code. “Quoting” a runtime value is at best a no-op and at worst nonsensical.
The example in your question illustrates why it doesn’t make any sense. Your so-called quoteresult form would evaluate (+ 1 1) to produce '2, but '2 evaluates to 2, the same thing (+ 1 1) evaluates to. How would the result of quoteresult ever be different from ordinary evaluation?
If, however, you want to actually produce a quote expression to be handed off to some use of dynamic evaluation (with the usual disclaimer that that is probably a bad idea), then you need only generate a list of two elements: the symbol quote and your function’s result. If that’s the case, you can implement quoteresult quite simply:
(define (quoteresult x)
(list 'quote x))
This is, however, of limited usefulness for most programs.
For more information on what quoting is and how it works, see What is the difference between quote and list?.
Arguments will be evaluated during a function call in Lisp. Is there any way besides macro to print the argument without evaluation?
Take an example in Common Lisp:
(defun foo (&rest forms)
(loop for i in forms collect i))
Call "foo" in REPL toplevel:
CL-USER> (foo (= 1 2) (< 2 3))
Got the result:
(NIL T)
Is there any way to get this result?:
((= 1 2) (< 2 3))
You can’t do that in either Scheme or Common Lisp without macros. Of course, it’s also pretty trivial with macros, so feel free to use them if they fit your use case.
That said, there’s a bit more to this question than you may have anticipated. You’re effectively asking for a feature that was present in older Lisps that has fallen out of fashion, known as fexprs. A fexpr is exactly what you describe: a function whose operands are passed to it without being evaluated.
Most modern dialects have done away with fexprs in favor of only using macros, and you can see this Stack Overflow question for more information on why. The gist is that fexprs are hard to optimize, difficult to reason about, and generally less powerful than macros, so they were deemed both redundant and actively harmful and were summarily removed.
Some modern Lisps still support fexprs or something like them, but those dialects are rare and uncommon in comparison to the relative giants that are Scheme and CL, which dominate the modern Lisp world. If you need this sort of thing, just use macros. Better yet, just quote the arguments so you don’t need any macros at all. You’ll be more explicit (and therefore much clearer), and you’ll get the same behavior.
Yes; you can get the result with an operator called quote, if you don't mind one more level of nesting:
(quote ((= 1 2) (< 2 3)))
-> ((1 2) (2 3))
quote isn't a macro; it is a special operator.
Common Lisp provides the lovely ~r directive for printing cardinal English numbers. For example:
(format nil "~r" 27) -> "twenty-seven"
Does lisp provide a directive (or some library function) that does the reverse, from cardinal English numbers to integer values? I'm using Allegro CL on a Windows machine.
EDIT: I'm looking for this type of functionality in a cleaner fashion:
(defconstant +cardinal-number-map+
(loop for number from 0 to 100
collect (cons (format nil "~r" number) number)))
(defun cardinal->int (cardinal)
(cdr (assoc cardinal +cardinal-number-map+ :test #'string-equal)))
Does lisp provide a directive (or some library function) that does the
reverse, from cardinal English numbers to integer values?
The short answer is "no". You can read in different radices, but not the English text. That said, doing this type of reading is a common enough exercise that you can find code out there that will do it. For instance, on the Code Golf site, there's a question, Convert English to a number. I don't see any Lisp solutions there, but there are some short answers that could be translated without too much trouble. (The Javascript answer is short and might be a nice candidate.)
However, because format's output isn't specified precisely, there's not going to be a simple and portable solution that will work with every implementation's format output. For that, you might have to do something like what you suggested in the question.
I'm going through this Scheme tutorial and in section 3 (Making Lists) the guy says you should write '() to represent an empty list. But for every test I've wrote seems that it has the very same effect as using just ().
Also, as far as I understand, the quote means the interpreter won't evaluate the expression, but seems that the interpreter knows what's after the ' symbol, because doing this (cons 1 '()) yields (1), while doing this (cons 1 'abc) yields (1 . abc), so it knows '() is an empty list but 'abc is not.
Some Scheme implementations permit bare () as a synonym for '(), but only the quoted form is standard.
As for your second question: consider
(define abc '(1 2 3))
(define def '(1 2 3))
(cons 0 'abc)
(cons 0 'def)
(cons 0 abc)
(cons 0 def)
In the first two expressions, abc and def are not evaluated, so they stay symbols. In the latter two, they are evaluated to the objects they stand for, which are both equal to the list (1 2 3).
TL;DR: To make sure your applications work as as designed you should quote the empty list since it's unsure if it will work otherwise. see the long answer below.
As for how Scheme works for quoted values, quoting '(+ 3 4 5) makes an expression a constant that is not to be evaluated. It much like making a string with code in it, like "if( a == 0 ) return 4;" in Java or C. The difference is that a quoted expression are structured data rather than byte sequences.
(cons 1 'abc) and (cons 1 '()) does the same. A cons has two placeholders for values and those two expressions sets two values in the exact same manner. It's only display (and the repl) that knows that a list that ends with () should display differently and not (1 . ()) like it actually is stored.
The long answer about the need to quote the empty list
It all boils down to the standard you're using. Most implementations today are R5RS and it requires the empty list be quoted since the empty list is not an expression. Implementations might still allow it though since it won't interfere with a proper Scheme application. Heres a quote from the R5RS report:
Note: In many dialects of Lisp, the empty combination, (), is a
legitimate expression. In Scheme, combinations must have at least one
subexpression, so () is not a syntactically valid expression.
This actually happened in R3RS (under Procedure calls) so it's been around for a while. When looking for it in R6RS however it seems to have disappeared from the section making me think they have reverted it so that it would be self evaluating. However, I cannot find it in the language changes part.
When looking at the R7RS draft (NB: PDF), the part from R5RS is back so I guess this was an error in the R6RS report. This might be the reason racket (and probably other implementors) allow () as an expression in R6RS to be sure it will work even when the report is ambiguous about it.
Is there a way to associate a character to a mathematical operator?
for example, if I can associate the letter "b" as addition then
(b 2 2)
Output
4
Is this possible? If so is there any material or examples I can use as a guide?
It's rather simple, look:
(define b +)
(b 2 2)
> 4
Now b is an alias for +. You can use the same idea for creating aliases for any procedure you want, with any name (it's not restricted to single-character names). Be aware that it won't work for other special forms; for instance this will produce an error:
(define my-and and)
The wording is a little off (take this as a friendly note).
In Scheme/Racket the mathematical functions +, -, *, etc. are not keywords as they are in many programming languages. They are simply names.
The expression + evaluates to a value, namely a function that can add numbers.
In order to introduce your own names for values, you can use define.
(define plus +)
Gives the name plus to the value resulting from evaluating +.
You can therefore give your own one-letter names, like
(define p +)
However one-letter names are not characters. Characters are what a string is made of.