I want to run a function but not have it output the result in the terminal. For example, (set 'A 'B) normally returns B in the console like the following:
>>> (set 'A 'B)
B
>>> A
B
I don't want it to return anything; I still want the function to do what it's supposed to, just silently:
>>> (set 'A 'B)
>>> A
B
It's not perfect, but you can use (values) at the end of your expression to suppress output. You get a blank line instead.
Common Lisp:
(progn (set 'A 'B) (values))
I'm not sure of the equivalent in Scheme.
A lisp REPL always prints some return value. If you really didn't want output, you could run your code as a script in the terminal.
Example:
#!/path/to/interpreter
(set 'A 'B)
[rest of program]
Since the value printed is actually a return value of your function, and the return value of a function is the value of last expression evaluated, you can simply add an "empty" (returning e.g. "") instruction at the end of/after your call.
I came to the same solution as user1613254, however I made a macro for this (have it in my .sbclrc):
(defmacro m-ignore (fun &body body)
"ignores the return value of a function"
`(progn (,fun ,#body)
(values)))
You use it like this:
(m-ignore format t "text")
The output would be:
text
instead of:
text
NIL
which would be printed when using
(format t "text")
Related
Coming from a C++ background, I'm trying to figure out how arguments are passed into methods in Elisp. While I acknowledge that maybe the wording could be different, I'm wondering if it is closer to the C++ idea of passing by reference or passing by value? If I alter the parameter in the method itself, will it alter the parameter that was passed in in the function call?
All Lisps (Emacs Lisp, Common Lisp) pass parameters by value, always:
(defparameter x 42) ; defconst in Emacs Lisp
(defun test (x)
(setq x 10))
(test x)
==> 10
x
==> 42
Note, however, that some values are actually pointers (or, rather, objects with components), so a function can modify their content by side effects:
(defparameter x (list 1 2))
(defun test (x)
(setf (first x) 42
(second x) 24
x 17))
(test x)
==> 17
x
==> (42 24)
PS1. Cf. When to use ' (or quote) in Lisp? -- "quoted arguments" are evaluated too: the evaluation strips the quote.
PS2. Cf. add-to-list - it accepts a symbol (variable name) and modifies its value. This only works for global dynamic variables, not for lexical variables. Not a very good idea.
Actually, in Emacs Lisp, there is no such thing like passing a argument by value or by reference, not to mention pointer. But all arguments passed to function will be evaluated in advance except those have a ' prefix. Always remember When you set a variable, you always just create symbol with a value.[1]
So if you want to modify a variable's value in a function, all you need to do is modifying the value of that variable's symbol in that function.
Check my code bellow.
(defvar my-val 1)
(defun my-func-value (val)
(setq val 2))
(defun my-func-symbol (sym)
;; NOTE! using set instead of setq,
;; casue we want symbol "my-val" be evaluated from "sym" here
(set sym 2))
(my-func-value my-val) ; evaluate my-val before passed into function
(message "my-val: %s" my-val) ; my-val: 1
(my-func-symbol 'my-val) ; pass my-val symbol directly into function
(message "my-val: %s" my-val) ; my-val: 2
Note! If the variable is a lexically-bound variable[2], it's still true that you can modified the symbol's value but not the value in the lexical environment.
Here is the code:
(let ((my-lexical-var 1))
(my-func-symbol 'my-lexical-var)
;; evaluate from lexical environment
(message "my-lexical-var: %s" my-lexical-var) ; my-lexical-var: 1
;; evaluate from the symbol
(message "symbol my-lexical-var: %s" (symbol-value 'my-lexical-var))
; symbol my-lexical-var: 2
My question is rather simple (perhaps misleadingly so).
In Common Lisp, when I run the following command, I get the corresponding results:
(eval '''boo) => 'boo
If, on the other hand, I run the following command I get something slightly different.
(eval (eval '''boo)) => boo
My question is this: if the first command's eval "shaves off" two quotation marks from the variable-symbol and leaves it with one mark at the output, how is it possible that the two nested eval functions take off a total of three quotation marks?
This is particularly confusing because the following results in an error:
(eval 'boing) => ERROR. BOING is unbound.
'boo is an abbreviation for (quote boo). In code, quote is a special form that evaluates to whatever it's argument it and nothing more. Thus boo. When this value is passed around it's data and no longer code but in order to create the symbol foo you need quote.
'''boo is an abbreviation for (quote (quote (quote boo))). When evaluating it it does exactly as before and it becomes (quote (quote boo)), a list with two elements where the second element is a list of two elements.
Since eval is a function it first evaluates the argument, then it evaluates the result as the function is supposed to do. Thus (quote (quote foo)) becomes (quote foo) after the first evaluation and eval takes off the second leaving the symbol foo.
If eval gets a symbol foo it means it's supposed to get the value bound by the variable foo in the global namespace. Thus:
(defparameter *test* 5)
(eval '*test*)
; ==> 5
Since the argument is (quote *test*) which after evaluation becomes *test*. eval sees the symbol and fetches the value, 5, which is the result. If *test* is not bound you get the error you got.
(defparameter *test-symbol* '*test)
(eval *test-symbol*)
Same here. Since it's a function *test-symbol* is evaluated to the symbol *test*, this is what eval sees and it fetches the value 5.
(defparameter *result* (eval '''foo))
*result*
; ==> (quote foo) but often the REPL shows 'foo
(consp *result*)
; ==> t
(length *result*)
; ==> 2
(car *result*)
; ==> quote
(cadr *result*)
; ==> foo
Sometimes I see beginners do something like '('(a) '(b)). This is a mistake as when evaluated you end up with the list ((quote (a)) (quote (b))) as the data and it is seldom the intention. When using a function like list the arguments gets evaluated and you need to quote appropriately:
(list '(a) *result* '(b))
; ==> ((a) (quote foo) (b))
eval is a function. Its argument is evaluated before eval is applied to it. That's why it appears that eval "shaves off" two quotation marks. One is removed by the implicit evaluation of function application, the other by the eval application itself.
But when you evoke (eval (eval '''boo)) the outer eval is applied to the value 'boo that is returned from the inner eval. The equivalent is (eval ''boo).
When you try (eval 'boing) the argument is evaluated before eval is applied to it, so eval tries to evaluate boing and goes wrong.
Contrast this with a macro version of eval that doesn't evaluate its argument before applying eval...
? (defmacro meval (form) `(eval ',form))
MEVAL
? (meval 'foo)
FOO
? (meval '''foo)
''FOO
First question:
Evaluating (eval '''boo)
Evaluating '''boo
Result: ''boo
Calling Function EVAL with ''boo
Function EVAL returns 'boo
Result: 'boo
Second question:
Evaluating (eval (eval '''boo))
Evaluating (eval '''boo)
Evaluating '''boo
Result: ''boo
Calling EVAL with ''boo
Function EVAL returns 'boo
Calling Function EVAL with 'boo
Function EVAL returns boo
Result: boo
quick question.
I'm trying to add something to my function where it prints back whatever args I give it as part of a string to the console.
(defun test (testvar)
(format Your number is *testvar*))
After looking around i think that I am supposed to use format but that's as far as I found.
You can interact in Common Lisp through a console within a REPL loop (READ-EVAL-PRINT Loop). So every expression is read, evaluated, and the result of the evaluation is printed;
CL-USER> (defun test (testvar)
(format nil "Your input is ~A" testvar))
TEST
CL-USER> (test 3)
"Your input is 3"
CL-USER> (test 'symbol)
"Your input is SYMBOL"
CL-USER> (test "string")
"Your input is string"
CL-USER>
The format function (reference) when its second argument is nil, returns as string the result of substituting in its second argument (a format string), special marks, like “~a” “~s”, etc., with the remaining parameters.
If the second parameter of format is instead t or a stream, then the formatted string is output to the stream specified (or, in case of t, to the special *standard-output* stream, that initially is the same as the console), and the result of format is returned (and then printed by the REPL). For instance:
CL-USER> (defun test (testvar)
(format t "Your input is ~A" testvar))
TEST
CL-USER> (test 3)
Your input is 3
NIL
CL-USER>
In this case NIL is the result of the format function. Note also that, differently from the first case, in which Your input is 3 is printed surrounded by double quote (since the result of (format nil ...) is a string, and is printed by the REPL as such), the output is left intact from the printing operation.
having a little trouble correctly using "cond" in conjunction with "and" in one of my functions:
(cond (and (find 'hello actionsems)
(find 'formal actionsems))
(print "Chatterbot: Hello, how are you?")
(and (find 'hello actionsems)
(find 'informal actionsems))
(print "Chatterbot: Hey, how's it going?")
)
I am told that I am "attempting to take unbound variable "AND". Could someone point out where in the syntax I made a mistake?
The COND macro takes a list of conditions and evaluate them in turn. The actual syntax from CLHS is:
Syntax:
cond {clause}* => result*
clause::= (test-form form*)
Arguments and Values:
test-form---a form.
forms---an implicit progn.
results---the values of the forms in the first clause whose test-form yields true, or the primary value of the test-form if there are no forms in that clause, or else nil if no test-form yields true.
Taking that, your condition evaluation should look something like below:
(cond ((and (find 'hello actionsems)
(find 'formal actionsems))
(print "Chatterbot: Hello, how are you?"))
((and (find 'hello actionsems)
(find 'infomal actionsems))
(print "Chatterbot: Hey, how's it going?")))
Lately, I've been thinking a lot about the basis of Lisp; I've read several manuals and/or other materials on the Internet, including The Roots of Lisp by P. Graham:
In The Roots of Lisp, quote is described as a primitive that changes code into data, thereby quoting it, but there doesn't seem to be an equivalent inverse primitive, that is an unquote primitive. I thought it might have been eval's business, but eval often runs the data in a null lexical environment, which is not equivalent to changing data back into code.
Ergo, why isn't there an unquote Lisp primitive?
unquote is only useful in the context of quasiquote, and quasiquote can be implemented as a macro (that uses quote behind the scenes). So there's no need to have an unquote primitive; the quasiquote macro simply deals with unquote symbols as they are found.
(quasiquote is the Scheme name for the backtick quote. Thus:
`(foo bar ,baz)
is read in as
(quasiquote (foo bar (unquote baz)))
in Scheme.)
Here's a very simple Scheme quasiquote macro (it only handles lists, unlike standard quasiquote which also handles vectors and other data types):
(define-syntax quasiquote
(syntax-rules (unquote unquote-splicing)
((quasiquote (unquote datum))
datum)
((quasiquote ((unquote-splicing datum) . next))
(append datum (quasiquote next)))
((quasiquote (datum . next))
(cons (quasiquote datum) (quasiquote next)))
((quasiquote datum)
(quote datum))))
Equivalent version using all the standard reader abbreviations:
(define-syntax quasiquote
(syntax-rules (unquote unquote-splicing)
(`,datum
datum)
(`(,#datum . next)
(append datum `next))
(`(datum . next)
(cons `datum `next))
(`datum
'datum)))
I am also relatively new to Lisp, but I think that what you were thinking about is eval. evalis the way to change data back to code.
Namely, consider a simple function.
(defun foo (a b c) (list a b c))
Then, if you do something like this, you get a list of symbols:
CL-USER> (foo 'a 'b 'c)
(A B C)
If you add a quote in the front, the function call itself is treated as a piece of data (list):
CL-USER> '(foo 'a 'b 'c)
(FOO 'A 'B 'C)
Adding one more quote has an expected effect:
CL-USER> ''(foo 'a 'b 'c)
'(FOO 'A 'B 'C)
Let us now unwind it with eval, which in essence may be thought of as the inverse operation for the quote. It is the inverse. The x-axis is the data form. The y-axis is the code form. Hopefully this (somewhat stretched) analogy makes sense.
CL-USER> (eval ''(foo 'a 'b 'c))
(FOO 'A 'B 'C)
Can you guess what will happen if I chain two evals in a row?
Here it is:
CL-USER> (eval (eval ''(foo 'a 'b 'c)))
(A B C)
Matt Brown and Jens Palsberg actually provide a good definition of what unquote would be in Typed self-evaluation via intensional type functions. The eval procedure under that definition is a meta interpreter function which transforms a structured input into a different value with the same type. i.e., accept a Lisp program as an s-expression and return another s-expression as the result.
The quote form should be structure preserving such that if the program is run naturally and then the result is quoted, the resulting representation should be the same as quoting the program and then running eval.
For a more concrete example, suppose you represent JavaScript programs in JavaScript as strings (assume for simplicity that a program is a 0-argument function which returns some JavaScript object). Running this program naturally then taking the JS object output (which for example may be cyclic) and running quote on the output should return the same string as running eval on the string representation of the program.
function program() {
...
return obj;
}
// If we had a true quote operation in JS, we would be
// able to run const quotedProgram = quote(program);
const quotedProgram = `
function program() {
...
return obj;
}
`;
const result1 = program();
const result2 = quote(result1);
const result3 = eval(quotedProgram);
const result4 = unquote(result3);
The above example is a little weird because JS doesn't have a natural way to quote arbitrary functions as strings (toString sort of works in many cases). However, note that if quote/eval are correct, result2 and result3 should be the same; furthermore, if unquote is correct, result1 and result4 should be the same.