case is an alias for cl-case, so there is no difference, there.
This aspect of the behavior is the same in Common Lisp.
There is nothing very weird here. You just need to read the doc, which tells you that the first arg to case is evaluated and the result is compared with the car entries of the following lists. cl-case is a macro, so in general (i.e., ...
cl-case uses eql for comparisons, so string get tested for identity not for equality in the sense of string=. You can fix this by just switching to pcase (or, if you really want to use case, convert to symbols instead: match (intern mymachine) against 'HP, etc.).
Traditional Emacs Lisp "in my time we didn't have that new-fangled CL stuff" style:
(dolist (str (list str1 str2 str3 str4))
(if (firstFunction str)
(throw 'foo (secondFunction str))))
Traditional Emacs Lisp "when I was at MIT..." style:
(mapc #'(lambda (str)
(if (firstFunction str)
Another way using dash.el. You could also do this with cl-lib functions.
(-when-let (found (-find 'firstFunction (list str1 str2 str3 str3)))
Or, if you know at least one condition will always match:
(secondFunction (-find 'firstFunction (list str1 str2 str3 str3)))
BTW, I recommend the use of pcase, which is more powerful.
The equivalent code to what you wrote, would be:
(let ((x 1))
Making it clear that x is not evaluated. This said, it would probably confuse you as well, because if you naively write:
(let ((x 1))
it will tell you Yes ...
Forms in the function body are executed in order, just as you would expect.
When you choose "y" if does not "jump" past the first message call. If looks like it did because the first message gets immediately replaced by the second one.
To check that this is true, open the *Messages* buffer and then do M-x foo. You will see that foo adds two messages to the ...
Let me start off by saying that (and a b) and (when a b) in your example do the same thing: First a is evaluated. b is evaluated if a is true#.
But and and when are used for different things.
You would use (and a b) to return true# if BOTH a and b are true# (or non-nil); and nil otherwise.
You would use (when a b) or to be more correct,
Use progn or prog1. progn takes a list of body forms, evaluates them one by one, then returns the value of the last one. prog1 does the same but returns the value of the first one.
Emacs Lisp doesn't have any support for automatic type checking, whether in the byte compiler or at runtime.
The idiomatic way to report an error at runtime is to check the argument against a predicate function, and signal the error `wrong-type-argument if it doesn't match.
Furthermore, to express a choice between a small, fixed number of items, the ...
Since Emacs 26, the underscore (or any variable symbol in general) can be omitted:
if-let is a Lisp macro in `subr-x.el'.
(if-let SPEC THEN &rest ELSE)
Probably introduced at or before Emacs version 25.1.
Bind variables according to SPEC and evaluate THEN or ELSE.
Evaluate each binding in turn, as in `let*', stopping if a
binding value is nil. If ...
The first part of each clause in a case form is a value (or a list of values), not an expression. The x before 'Yes is syntactically interpreted as a value. The x after case, on the other hand, is interpreted as an expression, i.e. it is evaluated; its value is 1. The value 1 (which is an integer) is not equal to the value x (which is a symbol). Contrast:
Your second version would more typically be written as a cond form:
(cond ((string= system-name "HP")
(setq package-user-dir (concat user-emacs-directory "packages/hp")))
((string= system-name "DELL")
(setq package-user-dir (concat user-emacs-directory "packages/dell")))
((string= system-name "MBP.local")
Standard elisp does not allow you to put restrictions on the arguments in the header in the way you're specifying, but you may wish to check out cl-defun in the Common Lisp extension library to get more options in your defuns.
In the meantime, a fairly simple way to handle your use case is to do a preliminary check before you get into the body of the ...
It's not being skipped. The second message is printed after the first message is printed, but there is no wait between the two, so you do not notice the first message. Look in buffer *Messages* and you will see both messages.
To give the user time to see the first message, you can use sit-for or sleep-for after it:
(defun foo (str bool)
I just happened to notice this while looking for a an already implemented wsl-browse-url (thanks!), so will offer one other option:
(when (string-match "-[Mm]icrosoft" operating-system-release)
;; WSL: WSL1 has "-Microsoft", WSL2 has "-microsoft-standard"
It looks like that works on both my Debian WLinux WSL 2 environments.
You could also do (string-match-p "Microsoft" (shell-command-to-string "uname -a"))
Likely in your my-browse-url-function you're probably depending on a Windows
specific path to exist. You could just check that it exists and is executable
with file-executable-p like the following code does. However, this may not be
enough if you dual boot and mount the ...
I would check for an environment variable using getenv. You may want to check what variables are available in your typical WSL shell, but one option would be to check for a Windows-specific PATH entry, perhaps:
(string-match-p "Windows" (getenv "PATH"))
If you wanted this for a function you would use apply, but as or is a special form you can't do that. In particular, or only evaluates as many arguments as it needs to.
You could write a macro:
(defmacro or-list (list)
`(or ,@(eval list)))
(setq mylist '(a b c))
(or-list mylist) then expands to (or a b c)
Apologies for not helpfully answering the question posed, but hoping this might help anyway...
Instead of something "similar to the first", I'd likely use something that (I think) is simpler than either of them.
Your first example macro-"expands" to code that I think is clearer, than either of your examples:
(macroexpand '(if-let* ((foo (...
I think indexing org tables by column and row names is such a general task that it deserves a general function org+-table-get.
You could put the following code into your initialization file.
(defsubst org+-table-get-row (table row-id &optional start noerror)
"Get Org TABLE row by ROW-ID.
Search for ROW-ID from START.
START is zero-based. It defaults ...
That behavior is actually described there, albeit in terse form:
"Macro: cl-case keyform clause...": cl-case is a macro, macros do not evaluate their arguments.
"This macro evaluates KEYFORM [...]": One of the arguments is evaluated, the rest aren't.
Therefore the key forms aren't evaluated.
If you find yourself in that situation, just ...
How about this?
(defun or-list (list)
(cl-some #'identity list))
Here cl-some takes two arguments: a predicate and a list and returns non-nil if the predicate applied to some member of the list is non-nil. In our case, the identity function is a good predicate since we only want to test whether our list members are themselves non-nil.
I think this is what you want:
(let ((flag1 nil)
if flag2 return 1
else return 0
else return 2))
if flag1 is nil, you get 2
if flag1 is t, and flag2 is nil you get 0
if flag1 is t, and flag2 is t you get 1
Or to replicate the original pseudo code (complete with its infinite loop scenario):
I might be missing the point of the question, but I think the main reason this looks messy is that the cond statement has 5 branches. A nested conditional on its own doesn't look that bad to me, so noticing that the only thing changing in the main cond branch is the argument to nth, I would rewrite the function as
(defun site-charac-4 (site charac)
This is an X-Y-problem.
Just avoid the multi-branched conditionals if you actually do not need them.
I show you one way to do that with the code below.
The most important details of the code:
If you use the :colnames no header argument you get the characteristics in the first line of the matrix.
You can get the column number of the given characteristic ...