I've beginning learning programming with Emacs Lisp. I'm so confused by symbol quotation.
For example:
(progn
(setq a '(1 2))
(prin1 a)
(add-to-list 'a 3)
(prin1 a)
(setcar a 4)
(prin1 a)
(push 5 a)
""
)
why the "add-to-list" function need a quoted symbol as its first argument, while the "setcar" and "push" function need no argument quotation?
Here's a diagram that represents the symbol a and its value after (setq a '(1 2)). The boxes are elementary data structures (symbols and conses) and the arrows are pointers (where a piece of data references another). (I'm simplifying a little.)
symbol cons cons
+-------+----------+ +------+------+ +------+------+
|name: |variable: | |car: |cdr: | |car: |cdr: |
| a | | | | 1 | | | | 2 | nil |
+-------+----|-----+ +------+--|---+ +------+------+
| ↑ | ↑
+-------------+ +-------+
The expression '(1 2) builds the two conses on the right, which make up a two-element list. The expression (setq a '(1 2)) creates the symbol a if it doesn't exist, then makes its “variable slot” (the part that contains the value of the symbol) point to the newly created list. setq is a built-in macro, and (setq a '(1 2)) is shorthand for (set 'a '(1 2)). The first argument of set is the symbol to modify and the second argument is the value to set the symbol's variable slot to.
(add-to-list 'a 3) is equivalent to (set 'a (cons 3 a)) here, because 3 is not in the list. This expression does four things:
Create a new cons cell.
Set the new cons cell's car field to 3.
Set the new cons cell's cdr field to the former (and still current) value of a (i.e. copy the contents of a's variable slot).
Set the variable slot of a to the new cons cell.
After that call, the data structures involved look like this:
symbol cons cons cons
+-------+----------+ +------+--|---+ +------+------+ +------+------+
|name: |variable: | |car: |cdr: | |car: |cdr: | |car: |cdr: |
| a | | | | 3 | | | | 1 | | | | 2 | nil |
+-------+----|-----+ +------+--|---+ +------+--|---+ +------+------+
| ↑ | ↑ | ↑
+-------------+ +-------+ +-------+
The call to setcar doesn't create any new data structure, and doesn't act on the symbol a but on its value, which is the cons cell whose car currently contains 3. After (setcar a 4), the data structures look like this:
symbol cons cons cons
+-------+----------+ +------+--|---+ +------+------+ +------+------+
|name: |variable: | |car: |cdr: | |car: |cdr: | |car: |cdr: |
| a | | | | 4 | | | | 1 | | | | 2 | nil |
+-------+----|-----+ +------+--|---+ +------+--|---+ +------+------+
| ↑ | ↑ | ↑
+-------------+ +-------+ +-------+
push is a macro; here, (push 5 a) is equivalent to (set 'a (cons 5 a)).
setq and push are macros (setq is a “special form”, which as far as we're concerned here means a macro whose definition is built into the interpreter and not provided in Lisp). Macros receive their arguments unevaluated and can choose to expand them or not. set, setcar and add-to-list are functions, which receive their arguments evaluated. Evaluating a symbol returns the contents of its variable slot, e.g. after the initial (setq a '(1 2)) the value of the symbol a is the cons cell whose car contains 1.
If you're still confused, I suggest experimenting with (setq b a) and seeing for yourself which of the expressions modify b when you act on a (the ones that act on the symbol a) and which don't (the ones that act on the value of the symbol a).
Functions evaluate their arguments before execution, so quote when you need to pass an actual symbol (as pointer to some data structure, for example) and don't quote when it's a variable value.
add-to-list performs in-place mutation of its first argument, so it needs a quoted symbol.
push is not a function, but a macro; that is why it's able to accept unquoted arguments without evaluation. Builtin forms, like setcar, also do not have that limitation.
The other answers given so far clarify the use of quote and the difference between functions, on the one hand, and macros and special forms on the other hand.
However, they do not get to another part of the question: why is add-to-list as it is? Why does it require its first argument to be a symbol? That's a separate question from whether or not it evaluates the argument. It's the real question behind the design of add-to-list.
One could imagine that add-to-list evaluated its args, and expected the value of the first arg to be a list, and then added the value of the second arg to that list as an element and returned the result (new list or same list). That would let you do (add-to-list foo 'shoe) to add the symbol shoe to the list that is the value of foo -- say (1 2 buckle) --, to give (1 2 buckle shoe).
The point is that such a function would not be very useful. Why? Because the list value isn't necessarily accessible. The variable foo might be thought of as a way to access it -- a "handle" or "pointer" to it. But that is not true of the list that the function returns. That returned list can be composed of new list structure, and there is typically nothing (no variable) pointing to that list. The function add-to-list never sees the symbol (variable) foo -- it has no way of knowing that the list value it receives as first argument is bound to foo. If add-to-list were designed that way then you would still need to assign its returned result to your list variable.
IOW, add-to-list evaluates its args because it is a function, but that doesn't explain much. It expects a symbol as the value of its first arg. And it expects the value of that variable (symbol) to be a list. It adds the value of its second arg to the list (possibly changing the list structure), and it sets the value of the variable that is the value of its first arg to that list.
Bottom line: It needs a symbol as arg because its job is to assign a new value to that symbol (the new value being the same list value or the same value with the new list element added at the front).
And yes, another way to go would be to use a macro or special form, as in push. It's the same idea: push wants a symbol as its second arg. The difference is that push does not evaluate its args so the symbol need not be quoted. But in both cases (in Emacs Lisp) the code needs to get hold of a symbol in order to set its value to the augmented list.
Related
I am experimenting with circular lists and have written a flawed graph viewer. So when I try to draw 2 different graphs
(graph-viewer:graph '#1=(1 2 3 #1#) "a")
(graph-viewer:graph #1='(1 2 3 #1#) "b")
I get who different pictures with the latter version having a quote symbol included in the graph.
You need to think how the reader does its job.
When it sees #1=, it knows to store whatever comes next and re-use it on #1# - think about it as a "binding" for the "variable 1".
When it sees '<blah>, it reads it as (quote <blah>).
Thus, when it sees '#1=(1 2 3 #1#), it reads it as
(quote (1 2 3 *))
^ |
| |
+------+
(quote is outside of "binding of 1")
while #1='(1 2 3 #1#) is read as
(quote (1 2 3 *))
^ |
| |
+-------------+
(quote is inside the "binding of 1").
The "arrow" in the pics above is the reference, i.e., * points along the arrow.
I read in a csv file:
csvFile:1!("SSS"; enlist ",") 0: hsym `$"\\\\location\\of\\csv";
But lists of symbols are read as single symbols. e.g. in the csv file I have 'a'b'c but
csvFile`some_keyed_value
`col1`col2!``a`b`c`
What I want is this - and note how a single ticker should be an empty list:
`col1`col2!(`a`b`c;())
Is there a way to make this cast or read in the csv differently or modify the csv so that it reads in correctly? Any modifications I make to the csv (e.g. replacing ' with () ) simply converts it to a single symbol (e.g. I get '() ).
Here is a screenshot of a few lines from the csv
For your input, the following works. You can also use cut instead of vs, as in previous example.
q)update `$table, `$_[1;]each vs["`";]each writeAllow, `$_[1;]each
vs["`";]each writeLog from ("***";enlist",")0:`:tmp.csv
table writeAllow writeLog
------------------------------------------------------
:/loader/P1 `pg`sec-fg-id `symbol$()
:/loader/P2 `pg`shara`mcdonald `pg`MD`svc
:/loader/P3 `symbol$() `pg`MD`svc
You should probably reconsider storing the sym data with backticks - it would be straightforward to store with a different delimiter to separate the sub-records and have a dedicated function for parsing those fields.
Taking this csv as an example:
cat ex.csv
x,y
`aa`bb,
`cc`dd,`ee`ff
,`gg`hh
You need to load those nested symbol columns in as strings first:
q)show tab:("**";enlist",")0:`:ex.csv
x y
-----------------
"`aa`bb" ""
"`cc`dd" "`ee`ff"
"" "`gg`hh"
From here you then need to drop the backticks and convert the strings to symbols. One possible way to do this is:
q)update {`$1_'where["`"=x]cut x}'[x] from tab
x y
-------------------
`aa`bb ""
`cc`dd "`ee`ff"
`symbol$() "`gg`hh"
You can also utilize the function value to convert a string with embedded backticks to a symbol list.
// read in as strings as others have said
q)("**";1#",")0:`:test.csv
x y
-------------
"`a`b" "`c`d"
"`e`f" "`g`f"
// value each string to convert to symbol lists
q)value#''("**";1#",")0:`:test.csv
x y
-------
a b c d
e f g f
// check its now nested symbol type
q)meta value#''("**";1#",")0:`:test.csv
c| t f a
-| -----
x| S
y| S
You can of course use value on specific columns that you need if it serves your purposes too, ie update value each col1 from ...
q)t
table writeAllow writeLog
----------------------------------------------------------
:loader/p1 "`pg`sec-fg-id" ""
:loader/p2 "`pg`shara`cmacdonald" "`pg`MD`svc"
:loader/p3 "" "`pg`MD`svc"
q)foo:(`$1_"`" vs) each
q)update foo[writeAllow], foo[writeLog] from t
table writeAllow writeLog
------------------------------------------------------
:loader/p1 `pg`sec-fg-id `symbol$()
:loader/p2 `pg`shara`mcdonald `pg`MD`svc
:loader/p3 `symbol$() `pg`MD`svc
Let say I have a configuration file, and each lines contains space separated values. On on the column I have only zeros. Example:
... # there is more configuration before the interesting stuff:
0 0 file /dev/stdin 224.0.68.54:12131
0 0 file /dev/stdin 224.0.68.55:12102
0 0 file /dev/stdin 224.0.68.49:12333
0 0 file /dev/stdin 224.0.68.60:12184
0 0 file /dev/stdin 224.0.68.62:12888
0 0 file /dev/stdin 224.0.68.77:12001
0 0 file /dev/stdin 224.0.68.33:12973
Now I want to increment the second column with its index.
that is I want this result:
0 0 file /dev/stdin 224.0.68.54:12131
0 1 file /dev/stdin 224.0.68.55:12102
0 2 file /dev/stdin 224.0.68.49:12333
0 3 file /dev/stdin 224.0.68.60:12184
0 4 file /dev/stdin 224.0.68.62:12888
0 5 file /dev/stdin 224.0.68.77:12001
0 6 file /dev/stdin 224.0.68.33:12973
How to to that in emacs lisp? Or any other Emacsen way of doing thing please?
You can use the possibility to search and replace by an evaluated expression:
put the point on the first line to process
M-x query-replace-regexp RET
searched string: ^0 \([0-9]+\)
replace with: \,(format "0 %s" (+ \#1 \#))
The meaning is:
search a number preceded by a single zero at the beginning of the line
replace by the result of the evaluation where \#1 is the first matched group (like \1 but converted to number) and \# is the number of replacements already done (begins at 0 for the first replacement). The expression is evaluated for each match.
If the first number is not always a zero, I would use:
searched string: ^\([0-9]+\) \([0-9]+\)
replace with: \,(format "%s %s" \#1 (+ \#2 \#))
You can use a macro with a counter to do that. You start defining a macro with F3 and end the definition with F4. While defining the macro, hitting F3 again will insert the value of the counter and increment it. After defining the macro, run it by hitting F4.
So in your case, move point to the beginning of the first interesting line, hit F3 C-f C-f C-d F3 C-n C-a F4 (i.e. remove the second zero, insert the counter, and move to the beginning of the next line). Then hit F4 as many times as needed to change all the lines.
If you need to change the value of the counter, use M-x kmacro-set-counter.
Similarly to Jonathan Leech-Pepin's answer, you can also use the non-cua rectangle editing commands (albeit in two steps instead of one).
Set mark and point to the corners of the column rectangle
C-xrk to delete the rectangle.
C-uC-xrN to insert a number sequence in its place.
Also see related question:
emacs string-insert-rectangle vector of numbers?
Something you could do using org-mode (I'm not sure of how will you use the result, but this can be one way of doing it)
| N | X | file | stream | ip |
|---+---+------+------------+-------------------|
| 0 | 0 | file | /dev/stdin | 224.0.68.54:12131 |
| 0 | 1 | file | /dev/stdin | 224.0.68.55:12102 |
| 0 | 2 | file | /dev/stdin | 224.0.68.49:12333 |
| 0 | 3 | file | /dev/stdin | 224.0.68.60:12184 |
| 0 | 4 | file | /dev/stdin | 224.0.68.62:12888 |
| 0 | 5 | file | /dev/stdin | 224.0.68.77:12001 |
| 0 | 6 | file | /dev/stdin | 224.0.68.33:12973 |
#+TBLFM: $2=##-2
Some explanation, or rather, how to get your original data and transform it into this table:
Copy your data into file config.org
Create the table by basic string replacement commands. (Just copy the text as you have it now, select all of it and then C-c |)
The #+TBLFM: part is the "formula" for this table, it means the following: assign to every cell in the second column the ordinal of it's row minus 2 (they start counting rows at 1, and this table has a header row).
Whenever you C-c C-c on the formula, it will re-apply it to the table (so you can append more rows as you modify the document, reapplying the formula will automatically update the table.)
You can use cua-set-rectangle-mark.
Evaluate:
(cua-mode 't)
Then in the buffer you can use M-x cua-set-rectangle-mark at the second column then extend the rectangle down to the end of the list.
Then use M-n (sequence), the defaults of Start (0):, Increment (1): and Format (%d): all provide what you need in this case.
Here a very easy way to do this (using the same technique as Seki's answer but easier):
Select all the lines you want the increment to appear in, then issue
M-x replace-regexp "^0 0" "0 \#"
or in more detail:
M-x replace-regexp RET
Searched string: ^0 0
Replace with: 0 \#
This will give you the desired result, because \# replaces to the number of replacements done.
I run into this problem all the time, and I don't enjoy setting up complicated rectangles or macros. So I created an elisp function to do it for me in a single command. I call it...*drumroll*...the downcrementer
Placing your cursor on the second 0 in your example and running M-x downcrementer will sequentially increment all the numbers in the column in one shot.
(defun downcrementer--bounds-of-num-at-point ()
(interactive)
(let (num-start num-end)
(save-excursion
(skip-chars-backward "0-9")
(setq num-start (point)))
(save-excursion
(skip-chars-forward "0-9")
(setq num-end (point)))
(list num-start num-end)))
(defun downcrementer (&optional prefix-arg)
(interactive "P")
(let ((current-number (string-to-number
(apply #'buffer-substring-no-properties
(downcrementer--bounds-of-num-at-point))))
(stride 1)
(orig-truncate-lines truncate-lines))
(when prefix-arg
(setq stride (string-to-number (read-string "Enter stride: "))))
;; Prevent wrapping from causing next-line to go to the wrong place
(toggle-truncate-lines t)
(next-line)
(let ((first-column (current-column)))
(while (thing-at-point 'number t)
(save-excursion
(apply #'delete-region (downcrementer--bounds-of-num-at-point))
(setq current-number (+ current-number stride))
(insert (number-to-string current-number)))
(next-line)
(move-to-column first-column))
(previous-line)
(move-to-column first-column))
;; Restore original truncate-line setting
(toggle-truncate-lines orig-truncate-lines)))
In visual lisp, you can use (atoi "123") to convert "123" to 123. It seems there is no "atoi" like function in clisp ?
any suggestion is appreciated !
Now i want to convert '(1 2 3 20 30) to "1 2 3 20 30", then what's the best way to do it ?
parse-interger can convert string to integer, and how to convert integer to string ? Do i need to use format function ?
(map 'list #'(lambda (x) (format nil "~D" x)) '(1 2 3)) => ("1" "2" "3")
But i donot know how to cnovert it to "1 2 3" as haskell does:
concat $ intersperse " " ["1","2","3","4","5"] => "1 2 3 4 5"
Sincerely!
In Common Lisp, you can use the read-from-string function for this purpose:
> (read-from-string "123")
123 ;
3
As you can see, the primary return value is the object read, which in this case happens to be an integer. The second value—the position—is harder to explain, but here it indicates the next would-be character in the string that would need to be read next on a subsequent call to a reading function consuming the same input.
Note that read-from-string is obviously not tailored just for reading integers. For that, you can turn to the parse-integer function. Its interface is similar to read-from-string:
> (parse-integer "123")
123 ;
3
Given that you were asking for an analogue to atoi, the parse-integer function is the more appropriate choice.
Addressing the second part of your question, post-editing, you can interleave (or "intersperse") a string with the format function. This example hard-codes a single space character as the separating string, using the format iteration control directives ~{ (start), ~} (end), and ~^ (terminate if remaining input is empty):
> (format nil "Interleaved: ~{~S~^ ~}." '(1 2 3))
"Interleaved: 1 2 3."
Loosely translated, the format string says,
For each item in the input list (~{), print the item by its normal conversion (~S). If no items remain, stop the iteration (~^). Otherwise, print a space, and then repeat the process with the next item (~}).
If you want to avoid hard-coding the single space there, and accept the separator string as a separately-supplied value, there are a few ways to do that. It's not clear whether you require that much flexibility here.
I am trying to build a Lisp grammar. Easy, right? Apparently not.
I present these inputs and receive errors...
( 1 1)
23 23 23
ui ui
This is the grammar...
%%
sexpr: atom {printf("matched sexpr\n");}
| list
;
list: '(' members ')' {printf("matched list\n");}
| '('')' {printf("matched empty list\n");}
;
members: sexpr {printf("members 1\n");}
| sexpr members {printf("members 2\n");}
;
atom: ID {printf("ID\n");}
| NUM {printf("NUM\n");}
| STR {printf("STR\n");}
;
%%
As near as I can tell, I need a single non-terminal defined as a program, upon which the whole parse tree can hang. But I tried it and it didn't seem to work.
edit - this was my "top terminal" approach:
program: slist;
slist: slist sexpr | sexpr;
But it allows problems such as:
( 1 1
Edit2: The FLEX code is...
%{
#include <stdio.h>
#include "a.yacc.tab.h"
int linenumber;
extern int yylval;
%}
%%
\n { linenumber++; }
[0-9]+ { yylval = atoi(yytext); return NUM; }
\"[^\"\n]*\" { return STR; }
[a-zA-Z][a-zA-Z0-9]* { return ID; }
.
%%
An example of the over-matching...
(1 1 1)
NUM
matched sexpr
NUM
matched sexpr
NUM
matched sexpr
(1 1
NUM
matched sexpr
NUM
matched sexpr
What's the error here?
edit: The error was in the lexer.
Lisp grammar can not be represented as context-free grammar, and yacc can not parse all lisp code.
It is because of lisp features such as read-evaluation and programmable reader. So, in order just to read an arbitrary lisp code, you need to have a full lisp running. This is not some obscure, non-used feature, but it is actually used. E.g., CL-INTERPOL, CL-SQL.
If the goal is to parse a subset of lisp, then the program text is a sequence of sexprs.
The error is really in the lexer. Your parentheses end up as the last "." in the lexer, and don't show up as parentheses in the parser.
Add rules like
\) { return RPAREN; }
\( { return LPAREN; }
to the lexer and change all occurences of '(', ')' to LPAREN and RPAREN respectively in the parser. (also, you need to #define LPAREN and RPAREN where you define your token list)
Note: I'm not sure about the syntax, could be the backslashes are wrong.
You are correct in that you need to define a non-terminal. That would be defined as a set of sexpr. I'm not sure of the YACC syntax for that. I'm partial to ANTLR for parser generators and the syntax would be:
program: sexpr*
Indicating 0 or more sexpr.
Update with YACC syntax:
program : /* empty */
| program sexpr
;
Not in YACC, but might be helpful anyway, here's a full grammar in ANTLR v3 that works for the cases you described(excludes strings in the lexer because it's not important for this example, also uses C# console output because that's what I tested it with):
program: (sexpr)*;
sexpr: list
| atom {Console.WriteLine("matched sexpr");}
;
list:
'('')' {Console.WriteLine("matched empty list");}
| '(' members ')' {Console.WriteLine("matched list");}
;
members: (sexpr)+ {Console.WriteLine("members 1");};
atom: Id {Console.WriteLine("ID");}
| Num {Console.WriteLine("NUM");}
;
Num: ( '0' .. '9')+;
Id: ('a' .. 'z' | 'A' .. 'Z')+;
Whitespace : ( ' ' | '\r' '\n' | '\n' | '\t' ) {Skip();};
This won't work exactly as is in YACC because YACC generates and LALR parser while ANTLR is a modified recursive descent. There is a C/C++ output target for ANTLR if you wanted to go that way.
Do you neccesarily need a yacc/bison parser? A "reads a subset of lisp syntax" reader isn't that hard to implement in C (start with a read_sexpr function, dispatch to a read_list when you see a '(', that in turn builds a list of contained sexprs until a ')' is seen; otherwise, call a read_atom that collects an atom and returns it when it can no longer read atom-constituent characters).
However, if you want to be able to read arbritary Common Lisp, you'll need to (at the worst) implement a Common Lisp, as CL can modify the reader run-time (and even switch between different read-tables run-time under program control; quite handy when you're wanting to load code written in another language or dialect of lisp).
It's been a long time since I worked with YACC, but you do need a top-level non-terminal. Could you be more specific about "tried it" and "it didn't seem to work"? Or, for that matter, what the errors are?
I'd also suspect that YACC might be overkill for such a syntax-light language. Something simpler (like recursive descent) might work better.
You could try this grammar here.
I just tried it, my "yacc lisp grammar" works fine :
%start exprs
exprs:
| exprs expr
/// if you prefer right recursion :
/// | expr exprs
;
list:
'(' exprs ')'
;
expr:
atom
| list
;
atom:
IDENTIFIER
| CONSTANT
| NIL
| '+'
| '-'
| '*'
| '^'
| '/'
;