Is there a standard clojure macro for first-not-nil? - macros

I'm am looking for a macro that does effectively the opposite of this maybe-m. That is, I want the result of the first expression that returns non-nil without evaluating the remaining expressions. This last part is important because if the "solution" uses lazy-sequences then they will be evaluated in chunks...meaning the expressions could be evaluated when I don't want them to.
Here's an example of what I'm looking for:
(defn really-cool-stuff [a b c]
(first-not-nil
(operation1 a b) ; <-- this returns nil,
(operation2 b c) ; <-- this returns non-nil, the result is returned
(operation3 a b c))) ; <-- this is not evaluated

Because nil is falsey, or will do what you are looking for.
(defn really-cool-stuff [a b c]
(or
(operation1 a b)
(operation2 b c)
(operation3 a b c)))
The only exception is if the functions could potentially return false. In that case, you can build a macro that mimics or, except with a more strict conditional.
(defmacro or-nil?
([] nil)
([x] x)
([x & next] `(let [or# ~x] (if (nil? or#) (or-nil? ~#next) or#))))

Related

Getting a scheme macro keyword to match only if at least two arguments are given to it

I am trying to implement a keyword (named =) for a macro transformer (named latex) which is intended to match only if at least two arguments are given to it. My attempt is:
((_ (= a b))
`(,#(latex a) "=" ,#(latex b)))
((_ (= a b ...))
`(,#(latex a) "=" ,#(latex (= b ...))))
but this implementation matches when only one argument is given to = and gives an undesirable result. A table of outputs for various inputs is given below.
Input to latex
Displayed Result
comment
=
=
ok (no match)
(=)
(=)
ok (no match)
(= a)
a=(=)
bad match. result should be (= a)
(= a b)
a=b
ok (match)
(= a b c)
a=b=c
ok (match)
(= a b c d)
a=b=c=d
ok (match)
You may view the source file or the project page if you require more context.

clisp: variable has no value

I want to make user-program which extract elements a which have element b (given by parameter) as pair in list.
Like, if I give c as parameter and list ((c a) (c b) (d f) (d g)),
result should be 'a' 'b';
So I define a function as below,
(defun myr (b a) (if (= CAAR(a) b) CDAR(a) 'nope myr(b CDR(a))));
and call like this
myr(b ((b a) (b c) (a d) (a f)))
But result is like variable myr has no value
Its my first time in Lisp, So just tell me what keyword should I search for will be great help for me.
Thank you for reading.
You really need to start with a good lisp book, e.g., PCL or ACL.
You will save yourself a lot of time.
Lisp syntax is different from C.
In C, you call a function f with arguments х and y like this: f(x,y).
In Lisp, you do it like this: (f x y).
When you invoke your function myr(...), you put the symbol myr in the variable position, not function position, which causes the error you reported.
You also need to use quote as appropriate.

Dynamic let form as part of reify within a macro

Ok, let's try to get this straight: my final intent is to provide a macro as an API to users which will look like:
(defscript [a b]
(println a))
The result has to be an instance of a Script protocol, which looks like:
(defprotocol Script
(run [this model]))
The idea being that the first argument to defscript is a list of symbols that needs to be bound to correspondent keys in the model:
(.run (defscript [a b] (println a)) {:a 1}) ;; yields 1
I can't come up with any code that can effectively produce such effect, as I'm constantly hitting a wall when trying to use the model parameter, since at macro expansion time it's just a symbol:
(defmacro invoke-
[params model body]
(let [p (flatten (map (fn [x] [x (model (keyword x))]) params))]
`(let [~#p]
~body)))
(defmacro defscript
[params & body]
`(reify Script
(run [~'this ~'model]
(invoke- ~params ~'model ~#body))))
invoke- works fine if called directly:
(invoke- [a] {:a 1} (println a)) ;; prints 1
but it doesn't work when used within defscript as model can't be expanded correctly:
(.run (defscript [a] (println a)) {:a 1}) ;; prints nil
How can I get past this point and glue the pieces together?
It seems that basically, your argument vector is a shortcut for a destructuring binding:
(defscript [a b] body) -> (reify Script (run [this {:keys [a b]}] body))
That way, model is destructured at run time, as it should be.

Specifying multiple options in a structure's constructor?

I tried defining a structure with a custom print function and constructor like so:
(defun print-test (a-test stream depth)
(format stream "#<TEST-STRUCT ~A>" (test-struct-a a-test)))
(defstruct (test-struct (:print-function print-test
:constructor create-test
(&key a (b a) c)))
a
b
c)
But on evaluation I get:
Bad defstruct option (:PRINT-FUNCTION PRINT-TEST :CONSTRUCTOR
CREATE-TEST (&KEY A B C)).
[Condition of type CCL::SIMPLE-PROGRAM-ERROR]
But specifying either keyword alone works just fine. How can I fix this?
According to the grammar, options must be parenthesized individually. The defstruct form therefore needs to look like this:
(defstruct (test-struct (:print-function print-test)
(:constructor create-test (&key a (b a) c)))
a
b
c)

let inside cond

I'm working with clojure and while I've dabbled with lisps before, I'm having trouble finding a clean way to nest let statements in cond statements. For example, consider the following function:
(defn operate-on-list [xs]
(let [[unpack vector] (first xs)]
(cond
[(empty? xs) 'empty
unpack vector
:else (operate-on-list (rest xs))])))
It's a pretty standard recursive operation on a list, but it needs to do some work on the first element in the list before it works with the contents. The issue, of course, is that the list may be empty.
In this example, it wouldn't be hard to change unpack to ((first xs) 0) and vector to ((first xs) 1), but this quickly gets ugly if more work needs to be done on (first xs).
Is there any way to effectively use a let statement part-way through a cond?
Thanks.
-Nate
In cases like these, you're best off using if-let:
(defn operate-on-list [xs]
(if-let [[unpack v] (first xs)]
(cond
unpack v
:else (operate-on-list (rest xs)))))
This code walks the given list seq-able (list, vector, array...) of vectors and returns the second element of the first vector whose first element is true (meaning not false or nil). nil is returned if no such vector is found.
Note that vector is a built-in function, so I've chosen v as the variable name, just in case the need to use the function in the body arises in the future. More importantly, you're using too many brackets in your cond syntax; fixed in this version.
UPDATE: Two additional things worth noting about if-let:
The way if-let works, if (first xs) happens to be nil (false would be the same), the destructuring binding never takes place, so Clojure won't complain about not being able to bind nil to [unpack v].
Also, if-let accepts an else clause (in which you can't refer to the variables bound in if-let bindings vector -- though if you're in the else clause, you know they where false or nil anyway).
;use conditional let: http://richhickey.github.com/clojure-contrib/cond-api.html
(use 'clojure.contrib.cond)
(cond-let [b]
nil b
12 (prn (+ b 1))
:else 17 )
;==> 13
Another good example can be found here http://www.mail-archive.com/clojure#googlegroups.com/msg03684.html
Sort of like this, with a let inside the scope of the cond?
(defn operate-on-list [list]
(let [ el_first (first list) ]
(cond
(nil? el_first) (println "Finished")
:else (do
(let [ list_rest (rest list) ]
(println el_first)
(operate-on-list list_rest))))))
(operate-on-list '(1 2 3))
The output is:
1
2
3
Finished