Common Lisp Applying Regex-like Patterns to Keys in PLIST - regex

I am wondering if it is possible to apply Regex-like pattern matching to keys in a plist.
That is, suppose we have a list like this (:input1 1 :input2 2 :input3 3 :output1 10 :output2 20 ... :expand "string here")
The code I need to write is something along the lines of:
"If there is :expand and (:input* or :output*) in the list's keys, then do something and also return the :expand and (:output* or :input*)".
Obviously, this can be accomplished via cond but I do not see a clear way to write this elegantly. Hence, I thought of possibly using a Regex-like pattern on keys and basing the return on the results from that pattern search.
Any suggestions are appreciated.

Normalize your input
A possible first step for your algorithm that will simplify the rest of your problem is to normalize your input in a way that keep the same information in a structured way, instead of inside symbol's names. I am converting keys from symbols to either symbols or lists. You could also define your own class which represents inputs and outputs, and write generic functions that works for both.
(defun normalize-key (key)
(or (cl-ppcre:register-groups-bind (symbol number)
("^(\\w+)(\\d+)$" (symbol-name key))
(list (intern symbol "KEYWORD")
(parse-integer number)))
key))
(defun test-normalize ()
(assert (eq (normalize-key :expand) :expand))
(assert (equal (normalize-key :input1) '(:input 1))))
The above normalize-key deconstructs :inputN into a list (:input N), with N parsed as a number. Using the above function, you can normalize the whole list (you could do that recursively too for values, if you need it):
(defun normalize-plist (plist)
(loop
for (key value) on plist by #'cddr
collect (normalize-key key)
collect value))
(normalize-plist
'(:input1 1 :input2 2 :input3 3 :output1 10 :output2 20 :expand "string here"))
=> ((:INPUT 1) 1
(:INPUT 2) 2
(:INPUT 3) 3
(:OUTPUT 1) 10
(:OUTPUT 2) 20
:EXPAND "string here")
From there, you should be able to implement your logic more easily.

Related

How this code translates a number to English?

I'm new to Clojure and found there's a piece of code like following
user=> (def to-english (partial clojure.pprint/cl-format nil
"~#(~#[~R~]~^ ~A.~)"))
#'user/to-english
user=> (to-english 1234567890)
"One billion, two hundred thirty-four million, five hundred sixty-seven
thousand, eight hundred ninety"
at https://clojuredocs.org/clojure.core/partial#example-542692cdc026201cdc326ceb. I know what partial does and I checked clojure.pprint/cl-format doc but still don't understand how it translates an integer to English words. Guess secret is hidden behind "~#(~#[~R~]~^ ~A.~)" but I didn't find a clue to read it.
Any help will be appreciated!
The doc mentions it, but one good resource is A Few FORMAT Recipes from Seibel's Practical Common Lisp.
Also, check §22.3 Formatted Output from the HyperSpec.
In Common Lisp:
CL-USER> (format t "~R" 10)
ten
~#(...~^...) is case conversion, where the # prefix means to capitalize (upcase only the first word). It contains an escape upward operation ~^, which in this context marks the end of what is case-converted. It also exits the current context when there are no more argument available.
~#[...] is conditional format: the inner format is applied on a value only if it is non nil.
The final ~A means that the function should be able to accept one more argument and print it.
In fact, your example looks like the one in §22.3.9.2:
If ~^ appears within a ~[ or ~( construct, then all the commands up to
the ~^ are properly selected or case-converted, the ~[ or ~(
processing is terminated, and the outward search continues for a ~{ or
~< construct to be terminated. For example:
(setq tellstr "~#(~#[~R~]~^ ~A!~)")
=> "~#(~#[~R~]~^ ~A!~)"
(format nil tellstr 23) => "Twenty-three!"
(format nil tellstr nil "losers") => " Losers!"
(format nil tellstr 23 "losers") => "Twenty-three losers!"

Evaluate math string in Clojure

I need to implement a function called eval-math-string in Clojure, which takes a math string as input and evaluates it:
(eval-math-string "7+8/2") => 11
So I've managed to break apart an expression using re-seq, and now I want to evaluate it using Incanter. However, I have an expression like ("7" "+" "8" "/" "2"), but Incanter needs an expression like ($= 7 + 8 / 2), where $= is the incanter keyword. How can I feed the list of one-character strings into a list including $= so that it executes properly. If the arguments are strings, the function won't work, but I can't convert +, *, / etc. to numbers, so I'm a little stuck.
Does anyone know how I can do this, or if there is a better way to do this?
Incanter's $= macro just calls the infix-to-prefix function, so all you need to do is convert your list of strings to a list of symbols and numbers, then call infix-to-prefix.
I'm going to assume that the input is just a flat list of strings, each of which represents either an integer (e.g. "7", "8", "2") or a symbol (e.g. "+", "/"). If that assumption is correct, you could write a conversion function like this:
(defn convert [s]
(try
(Long/parseLong s)
(catch NumberFormatException _
(symbol s))))
Example:
(infix-to-prefix (map convert ["7" "+" "8" "/" "2"]))
Of course, if you're just writing a macro on top of $=, there's no need to call infix-to-prefix, as you would just be assembling a list with $= as the first item. I'm going to assume that you already have a function called math-split that can transform something like "7+8/2" into something like ["7" "+" "8" "/" "2"], in which case you can do this:
(defmacro eval-math-string [s]
`($= ~#(map convert (math-split s))))
Example:
(macroexpand-1 '(eval-math-string "7+8/2"))
;=> (incanter.core/$= 7 + 8 / 2)

Clojure struggling to visualise how the arrow macros work

I am struggling to understand how the -> and ->> expand.
If I have the following:
(-> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up))
How does this expand, I understand that -> is a thread-first macro which inserts the the value as the second item as the first form, and after looking at examples I'm still unsure.
Also how does ->> differ, I know it inserts the item as the last argument of the function but again the wording confuses me.
(->> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up))
When expanded how would these two macros look?
-> and ->> always remind me of Matryoshka dolls because they nest all expressions passed to them.
Let's consider (-> a (b c d) (e f g)). We can now visually cut them (with a pipe) at the 1st argument position in each expression but the first: (-> a (b | c d) (e | f g)). Now that the expressions are cut in halves we can nest them: first (-> (b a c d) (e | f g)) and then (-> (e (b a c d) f g)) which simplifies to (e (b a c d) f g).
->> works in a very similar manner except the insert point is at the end (last argument position): (-> a (b c d |) (e f g |)) which successively expands to (-> (b c d a) (e f g |)), (-> (e f g (b c d a))) and (e f g (b c d a)).
Using clojure.walk/macroexpand to expand the macros:
(clojure.walk/macroexpand-all '(-> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up)))
... produces
(clean-up (send-with-attachment (archiver (write-query-to-excel query db csv-file) archive-password) send-to subject body))
Whereas
(clojure.walk/macroexpand-all '(->> query
(write-query-to-excel db csv-file)
(archiver archive-password)
(send-with-attachment send-to subject body)
(clean-up)))
... produces
(clean-up (send-with-attachment send-to subject body (archiver archive-password (write-query-to-excel db csv-file query))))
Since the result doesn't have to make sense, we can use simpler examples to illustrate the difference:
(clojure.walk/macroexpand-all '(-> a b c d))
;(d (c (b a)))
, the same with -> or ->>. But if there are arguments:
(clojure.walk/macroexpand-all '(-> a (b 1 2 3)))
;(b a 1 2 3)
whereas
(clojure.walk/macroexpand-all '(->> a (b 1 2 3)))
;(b 1 2 3 a)
The answer from #cgrand is good, but I would like to add a bit more.
You could achieve something very similar by putting your thread-first example into a (let...) form as:
; better if descriptive names used for intermediate results
(let [tmp1 (write-query-to-excel db csv-file)
tmp2 (archiver tmp1 archive-password)
tmp3 (send-with-attachment tmp2 send-to subject body)
tmp4 (clean-up tmp3) ]
<process result in tmp4>
...)
This is often the best solution since you can use descriptive variable names for the intermediate results. If, however, you won't really benefit from naming the intermediate results, you can use a generic variable it as a placeholder and still see exactly where each intermediate result is used in the next form. This is how the it-> macro from the Tupelo Core library works:
Imagine using a variable it to mark the location in each form where the result of the previous expression is inserted. Then in your -> example, we get:
(ns my.proj
(:require [tupelo.core :refer [it->]]
... ))
(it-> (write-query-to-excel db csv-file)
(archiver it archive-password)
(send-with-attachment it send-to subject body)
(clean-up it))
Then in your ->> example we would have:
(it-> (write-query-to-excel db csv-file)
(archiver archive-password it)
(send-with-attachment send-to subject body it)
(clean-up it))
However, what do we do if the expressions do not all chain together in either the first or last argument position? Consider this code:
(it-> 1
(inc it)
(+ it 3)
(/ 10 it)
(str "We need to order " it " items." )
;=> "We need to order 2 items." )
In this case, we have expressions where the previous result is chained into the only, first, last, and middle argument positions. In this case, neither -> nor ->> will work, and one must use something like it-> or a generic (let ...) form.
So for simple expression pipelines, using it-> (or the similar as->) can make the code more explicit about how the expressions are chained together. It also allows you to chain expressions that are not all "thread-first" or "thread-last". For more complicated processing chains, using a let form (possible nested) is the best answer as you can name the intermediate results and then combine them in arbitrarily complicated ways.
Would you mind taking a little tour around programming languages?
Ruby
In the world of Ruby there is a common practice of making so-called "method chains". What it is, essentially, is:
calling a method
calling a method on its result
calling a method on that method's result
etc.
Ruby is object-oriented, and such chains look like this:
(-5..5).map(&:abs)
.select(&:even?)
.count
.to_s
take a range of integers from -5 to 5 inclusive
map them into their absolute values
only select those that are even
count how many you have
convert the resuling number into a string
In Ruby, collections are objects, methods like map, count and select are their methods. map returns a collection, on which you can call select. On the result of select we call count that outputs an integer. Then we call to_s on that integer to convert it into a string. The dot-call of object.method calls a method on an object. Familiar stuff.
In some languages you may be exposed to terrible truth that object's methods may be nothing but a simple function that takes an object it acts upon and arguments. Some languages thoroughly hide that fact as an implementation detail, but could that convention actually be a limitation?
Lua
Lua is a nice little and honest language that doesn't hide from you what object's methods are. Consider these two equivalent lines:
obj.increase(obj, 5)
obj:increase(5)
It's a convention enforced on language-level: a method is a function that takes its owner object as a first argument.
...and some others with "static extension"
Defining all the possibly needed methods in a type has proven to be impossible, so some languages have adopted "static extension": it allows you to create a function that takes an "object acted upon" as its first argument (without access to sources of the type itself!). Then with some syntactic sugar you can use x.ext(y) calls instead of ext(x, y):
C# has that.
Haxe has that.
C++ doesn't have that, but there are proposals to add this, that highlight the semantic similarities of x.f(y) and f(x, y)
That feature allows us to chain operations a slightly cleaner way.
g(f(x, y), z) # Before
x.f(y).g(z) # After
Clojure
And we're back! So what does all this have to do with -> and ->>? They provide similar-looking syntax that looks good in longer chains.
We know for sure that our map and filter (same as Ruby's select) are just functions that take collections they act upon as their last (oops, that was unexpected!) argument.
(->> (range -5 6) (map #(Math/abs %)) ; 6 not included
(filter even?)
(count)
(str))
Oh, so we see a bit different way here: functions we treat as methods here take an object they act upon as their last argument. But we just make the "chain" using ->> and that fact becomes less noticeable.
If we had functions that took "object acted upon" as their first argument, as we've seen in Lua, we'd use ->. Depending on the functions you're chaining, -> might make more sense.
We can have it both ways, we can even mix them with a tad more verbose as->.

How to convert an expression in Haskell to a Tree structure to get information in the expression?

is there a way to convert an expression in Haskell language to a Tree like format and extract information from each node. Or Generate all possible trees for a given expression ?
Ex: add 5 3
This is tree where, 3 and 5 are leaf nodes and "add" as the root. So what I need is to get decompose the above expression so that I can do further analysis on the expression.
eg: * to know what are the values that I'm going to "add".
* to know what is the operation that I'm performing over the given numbers (here "add", also it could be "subtraction", "multiplication" etc.)
Really appreciate your help :)
You could use Template Haskell:
Language.Haskell.TH> runQ [e|3 + 5|]
InfixE (Just (LitE (IntegerL 3))) (VarE GHC.Num.+) (Just (LitE (IntegerL 5)))
Or haskell-src-exts:
Language.Haskell.Exts> parse "3 + 5" :: ParseResult Exp
ParseOk (InfixApp (Lit (Int 3)) (QVarOp (UnQual (Symbol "+"))) (Lit (Int 5)))

Lisp, add new list to db in "for" loop, why returning NIL?

I wonder, how can I print in LISP each new value from loop "for" in new list, which each time creates by calling the function.
I have created the func:
(defun make (id name surname) (list :id id :name name :surname surname) )
Here I created the global variable:
(defvar *db* nil)
And here I defined the func for adding each new value to store it in db:
(defun add (cd) (push cd *db*))
So, I'm able to add each new data to db, like that:
(add (make 0 "Oleg" "Orlov" ) )
To look the content of my db , I can use:
*db*
So, I wonder how to put each new record-list to db using "for" loop, I print values in "for" loop in lisp like this:
(loop for i from 1 to 10 do ( ... ))
If , I use:
(loop for i from 0 to 10 do (add (make i "Oleg" "Orlov") ) )
If you read db using *db* you will see, that all evelen records were added, but after calling the last line, you will get NIL result in return.
Why do I catch NIL result, not T and what does it mean?
Thanks, best regards!
Every form in Lisp evaluates to something.
If a form you type in doesn't return a value, it will evaluate to NIL by default (otherwise, it evaluates to the value(s) it returns). Your loop doesn't actually return a value itself; it just performs 10 assignments (each of the intermediate expressions do return a value, but you don't collect and return them). Therefore, that code will return NIL.
If you haven't done so already, check out chapter 3 of Practical Common Lisp, in which Peter Seibel goes step-by-step through creating a simple database. It might give you some insights into the basics of how Lisp works. The specific question you ask (why forms return NIL by default, and what it means specifically in the context of Common Lisp) is answered in chapter 2 of the same book
As for how you would explicitly cause your loop to emit the list of items it added to *db*, try the following
(loop for i from 1 to 10
for elem = (make i "Oleg" "Orlov")
do (add elem)
collect elem)