Hi vetelko!
Looks good! You didn't leave us much to work with / optimize. :)
I only have one comment, with doesn't really apply here because you are giving a short, illustrative example. However, in production code, I find it useful to separate the "printing code" from the "(answer) building code". In that light, I looked at your example in a different way, that is, I imagined a different context -- one in which I was looking at a process similar to MS Word's mail merge, where one has a template and then a "database" of "addresses" (or any other grouping of values) with which one wants to fill the template.
So, I wrote something very much like your P function, but without the println.
Code: Select all
(define (fill-template TEMPLATE VALUES)
(replace ":([a-z]+):"
TEMPLATE
(if (lookup (sym $1) VALUES)
(string $it)
"<<<value does not exist>>>")
0))
This function fills in the template TEMPLATE with values from VALUES.
TEMPLATE is a string containing "slots" (to fill in) denoted by symbol names surrounded by the colon character ':', e.g., ":name: is at :place:." (That is, it is in exactly the same format that you proposed.)
VALUES is an alist which associates those symbols (sans the colons) to corresponding values, e.g., '((name "Tom") (place "home")). This part is slightly different from your application, but you will soon see why I chose this below.
So, here is an example call, to get a feel for it.
Code: Select all
> (fill-template ":name: is at :place:." '((name "Tom") (place "home")))
"Tom is at home."
See? Very much like your P function.
Now, here's how the "mail merge"-type application works. First, I have a template. I proudly steal yours. :)
Code: Select all
(define *template* ":name: lives in :city: and is :age: years old.")
Next, I have a database of people.
Code: Select all
(define *people*
'(((name "John")
(age 37)
(city "NY"))
((name "Giorgos")
(age 25)
(city "Athens"))
((name "Elena")
(age 43)
(city "Amsterdam"))))
Finally, the "punchline".
Code: Select all
> (map (curry fill-template *template*) *people*)
("John lives in NY and is 37 years old." "Giorgos lives in Athens and is 25 years old."
"Elena lives in Amsterdam and is 43 years old.")
Or, if you want println.
Code: Select all
> (dolist (p *people*) (println (fill-template *template* p)))
John lives in NY and is 37 years old.
Giorgos lives in Athens and is 25 years old.
Elena lives in Amsterdam and is 43 years old.
"Elena lives in Amsterdam and is 43 years old."
Thanks for sharing your solution! This was a fun break for me today. All the best to you!