How do I convert "generic" expressions into asserted predicate expressions? (Clojure) - clojure

I am attempting to write a macro that converts "generic" expressions into expressions evaluated for a particular given value.
Let us say that I have a vector of unevaluated expressions of the form,
'[(map? %)
(-> % :value string?)
(fn[x] (apply #(pos? %) (- x 2))]
I have a gensymed value v, that I wish to "pass" to the above expression at runtime. So, assume that v will be the name of the symbol used at compile time. I also wish to assert the converted expression. Basically, for the example above, I wish to convert the above vector expression into the form below. Note that I am passing the value v to % in the first two expressions, and to x in the third expression. The code below isn't correct, but only illustrates what I want to happen. I have no idea how to actually get v into any of the below expressions assertions.
'[(assert (map? %)) ;; % is equal to v
(assert (-> % :value string?)) ;; % is equal to v
(assert (fn[x] (apply #(pos? %) (- x 2)))] ;; x is equal to v
As a guiding example, I wish to be able to do what the :post part of a prepost-map? does on a defn expression. Any help is appreciated.

Don't do this with expressions. Instead, use functions. Then it's easy to just call each of the functions with whatever value you want.

Related

Specifying bindings syntax with :as

Say I have a binding such as:
loop [[x & more :as tree] tree, minVal 99, maxVal -99]
What does :as do? I have tried looking around but can't find anything about it.
There's an explicitly-on-point example in https://clojure.org/guides/destructuring --
(def word "Clojure")
(let [[x & remaining :as all] word]
(apply prn [x remaining all]))
;= \C (\l \o \j \u \r \e) "Clojure"
Here all is bound to the original structure (String, vector, list, whatever it may be) and x is bound to the character \C, and remaining is the remaining list of characters.
As this demonstrates, :as binds the original, pre-destructuring value, thus in the example of your loop making tree retain its original value. That's not particularly useful when that value already has a name, but is very useful when it itself is a return value or otherwise as-yet-unnamed.

How to correctly check if a string is equal to another string in Clojure?

I am looking for better ways to check if two strings are equal in Clojure!
Given a map 'report' like
{:Result Pass}
, when I evaluate
(type (:Result report))
I get : Java.Lang.String
To write a check for the value of :Result, I first tried
(if (= (:Result report) "Pass") (println "Pass"))
But the check fails.
So I used the compare method, which worked:
(if (= 0 (compare (:Result report) "Pass")) (println "Pass"))
However, I was wondering if there is anything equivalent to Java's .equals() method in Clojure. Or a better way to do the same.
= is the correct way to do an equality check for Strings. If it's giving you unexpected results, you likely have whitespace in the String like a trailing newline.
You can easily check for whitespace by using vec:
(vec " Pass\n")
user=> [\space \P \a \s \s \newline]
As #Carcigenicate wrote, use = to compare strings.
(= "hello" "hello")
;; => true
If you want to be less strict, consider normalizing your string before you compare. If we have a leading space, the strings aren't equal.
(= " hello" "hello")
;; => false
We can then define a normalize function that works for us.
In this case, ignore leading and trailing whitespace and
capitalization.
(require '[clojure.string :as string])
(defn normalize [s]
(string/trim
(string/lower-case s)))
(= (normalize " hellO")
(normalize "Hello\t"))
;; => true
Hope that helps!

Clojure pattern matching macro with variable arity that goes beyond explicit match cases

I'm in the process of translating some code from Scheme to Clojure.
The Scheme code uses a macro called pmatch (https://github.com/webyrd/quines/blob/master/pmatch.scm) to pattern match arguments to output expressions. Specifically, it allows for variable capture as follows:
(define eval-expr
(lambda (expr)
(pmatch expr
[(zero? ,e)
(zero? (eval-expr e)))
...
In this use example, some input expression to eval-expr, '(zero? 0), should match the the first case. The car of the list matches to zero? and the arity of the input matches. As a consequence, 0 is bound to ,e and passed to (zero? (eval-expr e)), and this expr is evaluated recursively.
In Haskell, which supports pattern matching natively, the code might translate to something like the following:
Prelude> let evalexpr "zero?" e = (e == 0) -- ignoring recursive application
Prelude> evalexpr "zero?" 0
True
In Clojure, I first tried to substitute pmatch with core.match (https://github.com/clojure/core.match), which was written by David Nolen and others, but, to my knowledge, this macro seems to
only support a single arity of arguments per use
only support explicit matching, rather than property based matching (available as guards)
Another option I'm trying is a lesser known macro called defun (https://github.com/killme2008/defun), which defines pattern matching functions. Here's an example:
(defun count-down
([0] (println "Reach zero!"))
([n] (println n)
(recur (dec n))))
I'm still exploring defun to see if it gives me the flexibility I need. Meanwhile, does anyone have suggestions of how to pattern match in Clojure with 1. flexible arity 2. variable capture?
Ignoring recursive application:
(ns test.test
(:require [clojure.core.match :refer [match]]))
(def v [:x 0])
(def w [:x :y 0])
(defn try-match [x]
(match x
[:x e] e
[:x expr e] [expr e]
))
(try-match v)
;; => 0
(try-match w)
;; => [:y 0]
;; Matching on lists (actually, any sequences)
(defn try-match-2 [exp]
(match exp
([op x] :seq) [op x]
([op x y] :seq) [op x y]))
(try-match-2 '(+ 3))
;; => [+ 3]
(try-match-2 '(+ 1 2))
;; => [+ 1 2]
See https://github.com/clojure/core.match/wiki/Overview for more details.
Additionally, I suggest you have a close look at Clojure destructuring. Lots of things can be done with it without resorting to core.match, actually your use case is covered.

Reverse a string (simple question)

Is there a better way to do this in Clojure?
daniel=> (reverse "Hello")
(\o \l \l \e \H)
daniel=> (apply str (vec (reverse "Hello")))
"olleH"
Do you have to do the apply $ str $ vec bit every time you want to reverse a string back to its original form?
You'd better use clojure.string/reverse:
user=> (require '[clojure.string :as s])
nil
user=> (s/reverse "Hello")
"olleH"
UPDATE: for the curious, here follow the source code snippets for clojure.string/reverse in both Clojure (v1.4) and ClojureScript
; clojure:
(defn ^String reverse
"Returns s with its characters reversed."
{:added "1.2"}
[^CharSequence s]
(.toString (.reverse (StringBuilder. s))))
; clojurescript
(defn reverse
"Returns s with its characters reversed."
[s]
(.. s (split "") (reverse) (join "")))
OK, so it would be easy to roll your own function with apply inside, or use a dedicated version of reverse that works better (but only) at strings. The main things to think about here though, is the arity (amount and type of parameters) of the str function, and the fact that reverse works on a collection.
(doc reverse)
clojure.core/reverse
([coll])
Returns a seq of the items in coll in reverse order. Not lazy.
This means that reverse not only works on strings, but also on all other collections. However, because reverse expects a collection as parameter, it treats a string as a collection of characters
(reverse "Hello")
and returns one as well
(\o \l \l \e \H)
Now if we just substitute the functions for the collection, you can spot the difference:
(str '(\o \l \l \e \H) )
"(\\o \\l \\l \\e \\H)"
while
(str \o \l \l \e \H )
"olleH"
The big difference between the two is the amount of parameters. In the first example, str takes one parameter, a collection of 5 characters. In the second, str takes 5 parameters: 5 characters.
What does the str function expect ?
(doc str)
-------------------------
clojure.core/str
([] [x] [x & ys])
With no args, returns the empty string. With one arg x, returns
x.toString(). (str nil) returns the empty string. With more than
one arg, returns the concatenation of the str values of the args.
So when you give in one parameter (a collection), all str returns is a toString of the collection.
But to get the result you want, you need to feed the 5 characters as separate parameters to str, instead of the collection itself. Apply is the function that is used to 'get inside' the collection and make that happen.
(apply str '(\o \l \l \e \H) )
"olleH"
Functions that handle multiple separate parameters are often seen in Clojure, so it's good to realise when and why you need to use apply. The other side to realize is, why did the writer of the str function made it accept multiple parameters instead of a collection ? Usually, there's a pretty good reason. What's the prevalent use case for the str function ? Not concatenating a collection of separate characters surely, but concatenating values, strings and function results.
(let [a 1 b 2]
(str a "+" b "=" (+ a b)))
"1+2=3"
What if we had a str that accepted a single collection as parameter ?
(defn str2
[seq]
(apply str seq)
)
(str2 (reverse "Hello"))
"olleH"
Cool, it works ! But now:
(let [a 1 b 2]
(str2 '(a "+" b "=" (+ a b)))
)
"a+b=(+ a b)"
Hmmm, now how to solve that ? :)
In this case, making str accept multiple parameters that are evaluated before the str function is executed gives str the easiest syntax. Whenever you need to use str on a collection, apply is a simple way to convert a collection to separate parameters.
Making a str that accepts a collection and have it evaluate each part inside would take more effort, help out only in less common use cases, result in more complicated code or syntax, or limit it's applicability. So there might be a better way to reverse strings, but reverse, apply and str are best at what they do.
Apply, like reverse, works on any seqable type, not just vectors, so
(apply str (reverse "Hello"))
is a little shorter. clojure.string/reverse should be more efficient, though.

What's the difference between quote and string in this case with Clojure?

The following two commands prints out the same thing in repl:
user=> (println "(foo bar)")
(foo bar)
nil
user=> (println (quote (foo bar))
(foo bar)
nil
So in this case, what's the difference between a quote and a string?
Edit:
(+ 3 2) and (+ (quote 3) 2) are the same. The docs say quote yields the unevaluated form (so maybe I'm answering my own question here but please verify) that a quote is an optimization with lazy evaluation?
They're indeed different things:
user=> (class '(foo bar))
clojure.lang.PersistentList
user=> (class "foo bar")
java.lang.String
Even if they might have an identical println result, they're not the same.
For the rest, #bmillare is right: you don't quote for laziness, you quote to express literals.
The reason they look the same is because println is specified to print the content of strings and quoted forms, including the name of the symbols, to stdout. If you want to print the forms as how they would look like when inputted to the reader, use prn (pr if you don't want the newline)
user=> (prn "(foo bar)")
"(foo bar)"
nil
user=> (prn (quote (foo bar)))
(foo bar)
nil
For the other question,
Quote is not an optimization with lazy evaluation. The reason you get (+ 3 2) and (+ (quote 3) 2) is that you are quoting a literal e.g. a number, a keyword, or a string. (http://clojure.org/reader) Literals are evaluated at read time, before the form is passed to the upper form. Another way to think of it is quoting literals simply is defined to be an identity.