TL;DR: when is about side effects, and is for pure boolean expressions.
As you've noticed, and and when differ only in syntax, but are otherwise entirely equivalent.
The syntactic difference is quite important, though: when wraps an implicit progn around all but the first argument forms. progn is an inherently imperative feature: It evaluates all but ...
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 ...
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 ...
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:
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.
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 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"))
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 ...
The function minibufferp contains a doc-string that states: "Return t if BUFFER is a minibuffer. No argument or nil as argument means use current buffer as BUFFER. BUFFER can be a buffer or a buffer name."
To act upon a minibuffer window, I find it helpful to use (with-selected-window (minibuffer-window) ...)
Here is how I ended up solving the problem. In Spacemacs, it seems that two things are needed in the .spacemacs file.
First, the keybindings conditional on modes need to be defined with eval-define-key. Second, it should be done within a eval-after-load call, in order to wait for mode to be loaded before defining:
Maybe you did not indicate the full problem you want to solve. But based only on your description, there are simpler ways to handle it. Two obvious ones come to mind (see below). You might want to specify your problem further, indicating why, for example, these obvious approaches might not be appropriate/sufficient.
Use an optional argument:
This macro does the trick.
(defmacro condstrings (f1 f2 &rest strings)
`(cond ,@(mapcar (lambda (s)
`((,f1 ,s) (,f2 ,s)))
(condstrings firstFunction secondFunction str1 str2 str3 str4 str5)
If it's a concern that the strings are each evaluated twice then you can use the once-only macro defined here
Another answer, unlike to others this doesn't rely on fancy libraries and esoteric features like catch and throw:
(let ((rest (list str1 str2 str3 str4 str5)))
(let ((entry (pop rest)))
(when (firstFunction entry)
(setq rest ())))))
This assumes that the value the original cond expression wasn'...