I am writing a scheme interpreter in scheme (well, Racket). In my parse/eval function, I have the following rule:
(quotation [(Q datum) (string->symbol $2)])
string->symbol is apparently an incorrect definition of quote in such an interpreter.
I have tried many other ways, but none of them worked. Of course, if I try using the Racket quote function it doesn't work, since the $2 is interpreted literally, so everything evaluates to $2.
Now, if I evaluate some examples at the REPL:
$> (eval '1)
$> 1
$> (eval '#f)
$> #f
$> (eval 's)
$> s
VS. the Racket REPL:
$> (eval '1)
$> 1
$> (eval '#f)
$> #f
$> (eval 's)
$> 's
Note the difference: (eval 's) -> s in mine, -> 's in Racket. Furthermore, doing (symbol? (eval x)) also behaves differently.
How I am supposed to implement quote in such a case?
So as stated in the comments, this is an issue with REPL printing, and the correct implementation is:
(quotation [(Q datum) $2])
Thanks to those who helped me!
Related
I really really don't find a solution to this problem:
Say I have a variable that has multiple lines, each line should be one argument in the end.
line 1
line two
...
I only get this data at runtime, but it should be build like this to an command:
answer="$(dialog --menu 'Menu title' 0 0 0 'line 1' - 'line two' - ... 3>&1 1>&2 2>&3)"
(Data has to be separated by an - but this is not a problem.)
I think I really tried every possible combination, but it won't work out. I checked this site already but I >think< it is not offering a solution to my problem: http://mywiki.wooledge.org/BashFAQ/050
Should I try to switch word splitting of?
This is my code as of now:
list=""
while read p; do
list="$list '$p' - "
done <<< $line_separated_input
answer="$(dialog --menu 'Chosse sth' 0 0 0 $list 3>&1 1>&2 2>&3)"
Using an array also didn't work (As suggested here in (5): https://superuser.com/a/360986) :( How to stop word-splitting inside of quoted stuff, even if this quoted stuff is inserted because of variable substitution?
Edit: Thanks everybody, quoting $line_separated_input was part of the solution. Using it together with an array list instead of a variable finally solved my problem.
You can check for yourself, having an additional command substitution makes things harder:
> list="'a a' 'b c'"; echo "$(echo $list)"
'a a' 'b c'
> list="'a a' 'b c'"; echo "$(echo "$list")"
'a a' 'b c'
Both have not the intended output. This is only achieved if I do the following:
> list=('a a' 'b c'); echo "$(echo "${list[#]}")"
a a b c
Tadaa! Thanks everybody :)
As gniourf_gniourf commented, you probably just need to double quote your variable like ... done <<< "$line_separated_input". An argument enclosed in double quotes presents itself as a single word, even if it contains whitespace separators, thus it prevents word splitting, which can lead to unintended consequences.
To better exemplify, see the following examples:
var="/tmp/my directory"
mkdir -p "$var"
Output: the directory /tmp/my directory is created
Now, without double quoting:
var="/tmp/my directory"
mkdir -p $var
Output: the directory /tmp/my is created
I run this command both by typing in Terminal and by executing file on CentOS 6.5 64 bits.
let t='.'; echo $t;
Can't believe that it yields such a wierd error:
-bash: let: t=.: syntax error: operand expected (error token is ".")
As far as I know, single-quoted strings should not be parsed. In fact, in the first place, what I wanted to do is:
let $target_path='./files/mp4';
Can anyone please explain this behavior and guide me to stop this wierd act?
Unless you want to evaluate the variable value as an arithmetical expression, you need to assign the variable value like this:
t='.'
let is for calculation of arithmetical expressions and . or ./files/mp4 produces a syntax error in that arithmetical expression. Check help let.
Here comes an example how let can be used:
a="10*2"
echo "$a" # Prints: 10*2
let a="10*2"
echo "$a" # Prints: 20
If you followed the discussion below you may have noticed that even for mathematical expressions let isn't the best choice. This is because you can use ARITHMETIC EXPANSION in that case which is defined by POSIX in opposite to let. Using ARITHMETIC EXPANSION the above example would look like this:
a=$((10*2))
echo "$a" # Prints: 20
Check this articles for further information:
let
arithmetic expressions
Using let here is not right.
You can do like this:
AMD$ t='.'
AMD$ echo $t
.
AMD$ t='./files/mp4'
AMD$ echo $t
./files/mp4
I am not good at Bash scripting, and trying to learn more. Let me introduce my question with code:
#!/bin/bash
version_num=
isWindows=
MSVC_VER=
VERBOSE=
while getopts “hw:v:m:V” OPTION
do
case $OPTION in
h)
usage
exit 1
;;
w)
isWindows=$OPTARG
;;
v)
version_num=$OPTARG
;;
m)
MSVC_VER=$OPTARG
;;
V)
VERBOSE=1
;;
?)
usage
exit
;;
esac
done
For space, usage function is removed.
My questions are:
First question:
currently, if I use this script, I have to feed parameter values after each option, for example:
`bash test_bash.sh -v 4.2.2.0 -m 10.0 -w 1`
However, assuming that I only need to see whether -w is present, then set some variable value. I don't want to provide -w 1 since 1 is just a flag to do something. I would like the script to work like:
bash test_bash.sh -w -v 4.2.2.0 -m 10.0
How can I achieve this? I would like to do something like rm -r -f, which can have multiple options and does not require that each option is followed by some value.
Second question:
if I remove
V)
VERBOSE=1
;;
and :V from the while line as well as VERBOSE=, this script does not work anymore. Is it because :V is required?
Thanks a lot for your time and help!
Putting a : after a letter in the getopts parameter indicates whether it takes a parameter after it or not. So change to:
while getopts “hwv:m:V” OPTION
Removeing :V from the script breaks it because the : is for the m option that comes before it, not the V option that comes after. When you remove that :, it means that m no longer takes a parameter, but you need that.
How can I reliably get the script name in Chicken Scheme?
It seems that -ss eats up the script name, so it's not visible unless I use dot slash to run my scripts.
scriptedmain.scm:
#!/usr/bin/env csi -q
(display (command-line-arguments))
(display "\n")
(exit)
Trace:
$ ./scriptedmain.scm
(-q ./scriptedmain.scm)
wonko:Desktop andrew$ csi -ss scriptedmain.scm
()
This is a late response, so may not be of use to the original poster. But to any others who may come across this question, the simple answer is to use the parameter:
(program-name)
This should return the correct name for all situations. Docs here.
(argv) should do the job. Example:
#!/usr/local/bin/csi -script
(display (argv)) (newline) (exit)
prints (/usr/local/bin/csi -script ./test.scm)
scriptedmain.scm will run (main) and print the program name in the following cases:
Run from the interpreter:
csi -ss scriptedmain.scm
Run from the interpreter using shebangs:
./scriptedmain.scm
Compiled:
csc -o scriptedmain scriptedmain.scm
./scriptedmain
Added to GitHub.
#!/bin/sh
#|
exec csi -ss $0 ${1+"$#"}
exit
|#
(define (main)
(display (format "Program: ~a\n" (program-name)))
(exit))
(if (not (equal? (program-name) "csi"))
(main))
I have a function to compress my pdf file using pdftk:
(defun compresspdf (filename)
(interactive)
(let ((tmpfile (concat filename "~")))
(start-process-shell-command "pdftk" nil
(format "pdftk %s cat output %s compress dont_ask"
filename tmpfile))
(rename-file tmpfile filename t)))
It compresses the file and saves it as the same name with ~ appended. However, at the point where it's supposed to rename the file, it gives me an error:
let: Renaming: No such file or directory, /pathtofile/mypdf.pdf~, /pathtofile/mypdf.pdf, though clearly, both of these files exist. I can separately evaluate rename-file afterwards and it works fine. Maybe it's trying to rename the ~ file before it's actually created? In that case, how can I make it wait until the process is finished? (and possibly check for errors?)
As opposed to using 'start-process-shell-command, which just spawns the process, so the rename happens before the tmpfile is created. Try using 'shell-command, like so:
(defun compresspdf (filename)
(interactive)
(let ((tmpfile (concat filename "~")))
(with-temp-buffer
(shell-command (format "pdftk %s cat output %s compress dont_ask"
filename tmpfile)
(current-buffer)
(current-buffer)))
(rename-file tmpfile filename t)))
The call to 'shell-command will finish after the process is done (compression is complete).