2 arguments into a one parameter function - clojure

People,
I started studying clojure a few time ago and i have one question.
In this function:
(defn print-coords [coords]
(let [lat (first coords)
lon (last coords)]
(println (str "Latitude: " lat " - " "Longitude: " lon))))
=> #'dev-projects.core/print-coords
I'm defining a global function with one parameter.
But, if i invoke these arguments:
(print-coords [54 32])
Latitude: 54 - Longitude: 32
=> nil
I will get a sucessful answer.
Why does it work? The original function shouldn't only work with one argument?

I think you confuse (print-coords [53 32]) to be (print-coords 54 32).
In the first case, coords is the vector [53 32] whose first is 54 -> lat and whose second indeed is lon 32. Return value is correctly nil, since println returns nil.
However:
user=> (print-coords 54 32)
Execution error (ArityException) at user/eval141 (REPL:1).
Wrong number of args (2) passed to: user/print-coords

The question is how [coords] in the defn is compatible with [53 32] in the call.
A defn's parameters are surrounded by square brackets, but a function call's arguments are not wrapped in any punctuation. Thus [53 32] is literally a vector passed as the 1 argument to the function call. [53 32] corresponds to coords.
By the way, print-coords could be defined more idiomatically like this:
(defn print-coords [[lat lon]]
(println (str "Latitude: " lat " - " "Longitude: " lon)))
It is still a function of 1 argument. The only difference is that the 1 argument is immediately destructured and names are bound to the first two members. Now it is pleasantly clear how [53 32] corresponds [lat lon].

Related

Is posible create a void list on CLIPS, then through insert add elements?

I have a problem defining a list on CLIPS, whe i run I have this error message:[EXPRNPSR1] verificacion.clp, Line 10: A function name must be a symbol.
This is mi portion of code, where i have problem
(deffacts initial-facts
)
(defrule insert_in_list
=>
(bind ?lista (create$ ))
(insert$ (?lista ) 1 (3 5 1)))

Do records guarantee order when seq'd?

I'm writing some code where I need to map format over each value of a record. To save myself some duplicate writing, it would be super handy if I could rely on records having a set order. This is basically what it looks like right now:
(defrecord Pet [health max-health satiety max-satiety])
(let [{:keys [health max-health satiety max-satiety]} pet
[h mh s ms] (mapv #(format "%.3f" (double %))
[health max-health satiety max-satiety])]
...)
Ideally, I'd like to write this using vals:
(let [[h mh s ms] (mapv #(format "%.3f" (double %)) (vals pet))]
...)
But I can't find any definitive sources on if records have a guaranteed ordering when seq'd. From my testing, they seem to be ordered. I tried creating a massive record (in case records rely on a sorted collection when small):
(defrecord Order-Test [a b c d e f g h i j k l m n o p q r s t u v w x y z
aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu vv ww xx yy zz])
(vals (apply ->Order-Test (range 52)))
=> (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51)
And they do seem to maintain order.
Can anyone verify this?
For this exact scenario, I supposed I could have reduce-kv'd over the record and reassociated the vals, then deconstructed. That would have gotten pretty bulky though. I'm also curious now since I wasn't able to find anything.
As with many things in Clojure, there is no guarantee because there is no spec. If it's not in the docstring for records, you assume it at your own risk, even if it happens to be true in the current version of Clojure.
But I'd also say: that's not really what records mean, philosophically. Record fields are supposed to have individual domain semantics, and it looks like in your record they indeed do. It is a big surprise when an operation like "take the N distinctly meaningful fields of this record, and treat them all uniformly" is the right thing to do, and it deserves to be spelled out when you do it.
You can at least do what you want with a bit less redundancy:
(let [[h mh s ms] (for [k [:health :max-health, :satiety :max-satiety]]
(format "%.3f" (get pet k)))]
...)
Personally I would say that you are modeling your domain wrong: you clearly have a concept of a "resource" (health and satiety) which has both a "current" and a "max" value. Those deserve to be grouped together by resource, e.g.
{:health {:current 50 :max 80}
:satiety {:current 3 :max 10}}
and having done that, I'd say that a pet's "set of resources" is really just a single map field, rather than N fields for the N resources it contains. Then this whole question of ordering of record fields doesn't come up at all.

Error when using ismatch() function with regex in Julia

I'm trying to do a very simple program to find matches with ismatch() function in Julia. Suppose my pattern is
e_pat = r".+#.+"
Then I make a list called input with some random elements:
input= ["pipo#gmail.com", 23, "trapo", "holi#gmail.com"]
Now I want to identify how many matches exist and then print them using e_pat as reference:
for i in input
println(ismatch(e_pat, i)) && println(i)
end
With that code I just get "true" and the error displayed below:
true
TypeError: non-boolean (Void) used in boolean context
Stacktrace:
[1] macro expansion at ./In[27]:4 [inlined]
[2] anonymous at ./<missing>:?
[3] include_string(::String, ::String) at ./loading.jl:522
What can I do in order to get the following?
"pipo#gmail.com"
"holi#gmail.com"
I read ismatch() documentation but found nothing useful.
Any help will be much appreciated
The problem is that while this expression returns true:
julia> #show ismatch(e_pat, "pipo#gmail.com");
ismatch(e_pat,"pipo#gmail.com") = true
Using println, just prints true but returns nothing:
julia> #show println(ismatch(e_pat, "pipo#gmail.com"));
true
println(ismatch(e_pat,"pipo#gmail.com")) = nothing
Which is of type Void:
julia> typeof(nothing)
Void
And the error is telling you that you cant use an object of type Void in a boolean context (nothing) is just an instance of Void treated like a singleton in Julia:
julia> nothing && true
ERROR: TypeError: non-boolean (Void) used in boolean context
After fixing that also notice that this is also another error:
julia> #show ismatch(e_pat, 42);
ERROR: MethodError: no method matching ismatch(::Regex, ::Int32)
Closest candidates are:
ismatch(::Regex, ::SubString{T<:AbstractString}) at regex.jl:151
ismatch(::Regex, ::SubString{T<:AbstractString}, ::Integer) at regex.jl:151
ismatch(::Regex, ::AbstractString) at regex.jl:145
...
This is telling you that ismatch has no such method, you can't use it with a combination of arguments of types: (Regex, Int).
You could do something like this instead to make sure all the objects are Strings:
julia> input = string.(["pipo#gmail.com", 23, "trapo", "holi#gmail.com"])
4-element Array{String,1}:
"pipo#gmail.com"
"23"
"trapo"
"holi#gmail.com"
Finally, you could use the macro #show (which prints an expression and its result and finally returns the result) instead of the println function (which prints the result and returns nothing, to debug whats going on:
julia> for i in input
#show(ismatch(e_pat, i)) && println(i)
end
ismatch(e_pat,i) = true
pipo#gmail.com
ismatch(e_pat,i) = false
ismatch(e_pat,i) = false
ismatch(e_pat,i) = true
holi#gmail.com
So in order to print your expected result just remove the left hand side println:
julia> for i in input
ismatch(e_pat, i) && println(i)
end
pipo#gmail.com
holi#gmail.com
If you want to store them instead of printing them you could us an array comprehension instead:
julia> result = [str for str in input if ismatch(e_pat, str)]
2-element Array{String,1}:
"pipo#gmail.com"
"holi#gmail.com"
Or an indexing expression like this one:
julia> ismatch.(e_pat, input)
4-element BitArray{1}:
true
false
false
true
julia> result = input[ismatch.(e_pat, input)]
2-element Array{String,1}:
"pipo#gmail.com"
"holi#gmail.com"
That way you could print them later without having to repeat the computation:
julia> println.(result)
pipo#gmail.com
holi#gmail.com

How do I do substitution with a call to format?

I have a function
(defn f-test [c-width] (format "%-(c-width)s" "boogey"))
This is what happens when I try to evaluate it
(f-test 10)
FormatFlagsConversionMismatchException Conversion = c, Flags = ( java.util.Formatter$FormatSpecifier.failMismatch (Formatter.java:4041)
But this is what I am trying to do
(format "%-10s" "boogey")
"boogey "
how can I substitute in c-width inside the format call?
Try this one:
(defn f-test
[c-width]
(format (str "%-" c-width "s") "boogey"))

better way of handle clojure exceptions and why my exception is not captured inside go block

I'm trying to found a better way of handle exceptions in clojure, I'm using https://github.com/alaisi/postgres.async which thrown an exeption when fail, but I would prefer return false (because I'm using a validator) or even better something like a Either monad (or something more simple like this http://adambard.com/blog/acceptable-error-handling-in-clojure/ )
1) I'm trying to catch the exception and if exist return false, but the code doesnt works (doesnt return false and thrown the exception).
(try
(dosql [tx (<begin! db)
ucount (<execute! tx ["UPDATE groups SET garticlescounter=garticlescounter + 1 WHERE gid=$1"
groupid])
uartc (<execute! tx ["UPDATE subtopics SET starticlescount=starticlescount + 1 WHERE stid=$1"
sid])
uartins (<insert! tx
{:table "articles"}
{:aurl url :atitle title :asuttopicid sid :acommentcount 0 :alikescount 0 :auid uid})
ok? (<commit! tx)]
ok?)
(catch Exception _ false))
2)would be possible wrap in a way where if works return ok? and if doesnt works return false, or maybe [ok? nil] and [nil error] maybe a macro?
----thanks to swinn I did this
;must receive an optional parameter for error response or
; build a [nil ok] response but just know this works for me...
(defmacro async-try-block! [block]
`(let [chn# (!/chan 1)]
(!/go
(let [response# (try
~block
(catch Throwable e#))]
(if (instance? Throwable response#) (!/put! chn# false) (!/put! chn# response#))))
chn#))
(async-try-block!
(dosql [tx (<begin! db)
ucount (<execute! tx ["UPDATE groups SET garticlescounter=garticlescounter + 1 WHERE gid=$1"
groupid])
uartc (<execute! tx ["UPDATE subtopics SET starticlescount=starticlescount + 1 WHERE stid=$1"
sid])
uartins (<insert! tx
{:table "articles"}
{:aurl url :atitle title :asuttopicid sid :acommentcount 0 :alikescount 0 :auid uid})
ok? (<commit! tx)]
ok?))
I'm not familiar with the postgres.async library, butException is not the root of all Exceptions in the JVM, Throwable is.
Changing your catch to Throwable would be the first change I would suggest, but it seems that (<execute! ...) actually catches the exception for you and returns it, so you need to check the return value using (instance? Throwable)