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.).
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., ...
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"))
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 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 ...
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 ...
There are lots of different ways to write code that's similar but a bit different. So the question might be closed as being a bit opinion-based.
Anyway, here's one rewrite, which factors some of the stuff. I don't claim it is in any particular way better than what you wrote.
(setq site-matrix '((A 0 1 0 0) (B 1 0 0 0) (C 1 0 1 0) (D 1 1 1 1) (E 0 1 1 1)))...
There are a bunch of things wrong with your code as is:
eq compares two Lisp objects by their identity. This happens to work with integers due to implementation details, but is not guaranteed to work with numbers in general.
For example only (= 1 1.0) works as intended, all other comparisons will fail. Use = for that reason (except when comparing floats, ...
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