user=> ((symbol "or") true false)
false
user=> (or true false)
true
Why does the first form evaluate to false? I'd imagine the two input forms being equivalent.
Strangely, reversing the order of the arguments works:
user=> ((symbol "or") false true)
true
user => (or false true)
true
When you evaluate the list (or true false), Clojure first evaluates the first item. In this case, the first item is a symbol that names a macro, so Clojure expands the macro and evaluates the resulting data structure (which would be a let form in this case).
On the other hand, when you evaluate the list ((symbol "or") true false), Clojure again first evaluates the first item, but in this case, the first item is another list! The first element of that list is the symbol symbol, which names a function, so Clojure calls that function with the parameter "or", again producing the symbol or. In other words, you are basically evaluating ('or true false).
Here's the catch: Clojure does not take that thing that it just evaluated and then go and evaluate it again. Rather, since it wasn't a symbol in the first place, Clojure evaluates it and then assumes that it must be a function. Is it a function? Indeed, the answer is yes!
user> (ifn? 'do)
;=> true
Here's where it gets a little tricky. The implementation of invoke on the Symbol class is the same as the implementation of invoke on the Keyword class: it assumes that the first argument is a map and tries to look itself up in that map. If you provide a second argument, it will use that as a default value.
Now, obviously, if you try to treat true as a map and look up the symbol or in that map, you'll find nothing. So Clojure helpfully returns the default value that you provided: false. You could put any value you'd like in that second parameter spot, and as long as your symbol doesn't exist as a key in the first argument, you'll always get back your default value.
Related
my #g = (1,2,3,4);
say reduce {is-prime}, #g; # ==> gives error
say reduce {is-prime *}, #g; #==> gives error
say reduce {is-prime}, (1,2,3,4); # ==> gives error
say so is-prime #g.all; # ==> gives error
How to check if all elements of list are prime in Raku?
The answers above are all helpful, but they fail to explain why your solution does not work. Basically reduce is not going to apply a function (in your case, is-prime) to every member of a list. You want map for that. The error says
Calling is-prime() will never work with signature of the proto ($, *%)
Because reduce expects an infix, thus binary, function, or a function with two arguments; what it does is to apply them to the first pair of elements, then to the result and the third element, and so on. Last statement does not work for a similar reason: you are calling is-prime with a list argument, not a single argument.
You're basically asking: are there any elements in this list which are not prime? I would write that as:
say "not all prime" if #g.first: !*.is-prime;
Please note though, that apparently 1 is not considered prime according to the is-prime function:
say 1.is-prime; # False
so the first would trigger on the 1 in your example, not on the 4.
There are of course may ways to do this. A very explicit way is using a for loop:
for #g -> $g {
if $g.is-prime {
say $g;
}
}
Or with a grep (you could leave the $_ implicit):
#g.grep({ $_.is-prime }).say
Both above are assuming you really want to filter the primes out. Of course you can also really check each number and get a boolean:
#g.map({ .is-prime }).say
There is a big problem with this:
say reduce {is-prime}, #g;
You created a lambda:
{ }
The only thing it does is calls a function:
is-prime
You didn't give the function any arguments though.
Is it just supposed to guess what the arguments should be?
If you meant to pass in is-prime as a reference, you should have used &is-prime rather than {is-prime}.
Of course that still wouldn't have worked.
The other problem is that reduce operates by recursively combining values.
It can't do that if it operates on one argument at a time.
The bare block lambda {}, takes zero or one argument, not two or more.
reduce is often combined with map.
It happens so often that there is a Wikipedia page about MapReduce.
say ( map &is-prime, #g ==> reduce { $^a and $^b } );
# False
say ( map &is-prime, 2,3,5 ==> reduce { $^a and $^b } );
# True
I wrote it that way so that map would be in the line before reduce, but perhaps it would be more clear this way:
say reduce {$^a and $^b}, map &is-prime, 2,3,5;
# True
reduce with an infix operator is so common that there is a shorter way to write it.
say [and] map &is-prime, 2,3,5;
# True
Of course it would be better to just find the first value that isn't prime, and say the inverse.
Since if there is even a single value that isn't prime that would mean they can't all be primes.
You have to be careful though, as you may think something like this would always work:
not #g.first: !*.is-prime;
It does happen to work for the values you gave it, but may not always.
first returns Nil if it can't find the value.
not (2,3,5).first: !*.is-prime;
# not Nil === True
not (2,3,4).first: !*.is-prime;
# not 4 === False
not (2,3,0,4).first: !*.is-prime;
# not 0 === True
That last one returned 0 which when combined with not returns True.
You could fix this with defined.
not defined (2,3,0,4).first: !*.is-prime;
# False
This only works if first wouldn't return an undefined element that happens to be in the list.
(Int,Any).first: Real
# Int
defined (Int,Any).first: Real
# False
You could fix that by asking for the index instead of the value.
You of course still need defined.
(Int,Any).first: :k, Real
# 0
defined (Int,Any).first: :k, Real
# True
The other way to fix it is to just use grep.
not (2,3,0,4).grep: !*.is-prime;
# not (0,4) === False
Since grep always returns a List, you don't have to worry about checking for 0 or undefined elements.
(A List is True if it contains any elements, no matter what the values.)
grep is smart enough to know that if you coerce to Bool that it can stop upon finding the first value.
So it short-circuits the same as if you had used first.
This results in some fairly funky code, with those two negating operators. So it should be put into a function.
sub all-prime ( +#_ ) {
# return False if we find any non-prime
not #_.grep: !*.is-prime
# grep short-circuits in Bool context, so this will stop early
}
This could still fail if you give it something weird
all-prime 2,3,5, Date.today;
# ERROR: No such method 'is-prime' for invocant of type 'Date'
If you care, add some error handling.
sub all-prime ( +#_ ) {
# return Nil if there was an error
CATCH { default { return Nil }}
# return False if we find any non-prime
not #_.grep: !*.is-prime
}
all-prime 2,3,5, Date.today;
# Nil
use the all junction:
say so all #g».is-prime; # False
So I'm trying to make a single line to check if a single element in Python list fits the criteria, but my current code will keep the loop going even if it hits a "True" -mark and thus only the last element counts for the check:
if [[CheckStatus(value, outsidevalue)] for value in valuelist] is True:
magic
(CheckStatus returns either True or False for every single value compared to outsidevalue and is supposed to accept is as true if a single value returns True)
that will always be false:
if [[CheckStatus(value, outsidevalue)] for value in valuelist] is True:
because you're comparing a list with a boolean.
What you want is any:
if any(CheckStatus(value, outsidevalue) for value in valuelist):
any iterates on the generator comprehension, calling your function on all elements until True is found (note that the inside square brackets have been removed, and we don't need to create a list comprehension, just a generator comprehension, which is faster)
tl;dr
How can I derive a keyword from a number in ClojureScript:
(keyword 22)
;;=> :22 but in fact returns nil.
Background
In my ClojureScript/Hoplon application I make HTTP requests via cljs-http. Parts of the response I receive look like this:
{:companies
{:22 {:description ... } ; A company.
:64 {:description ... }
... }
{:offers
[{:description ... } ; An offer.
{:description ... }
... ]
Each offer within the vector behind :offers has a :companyId which represents a key in :companies. As soon as I receive the response, I reset! a cell (similar to an atom) query.
Now, I'd like to iterate over each offer and call a function offer-tpl that creates the corresponding HTML. In order to do so, offer-tpl needs the offer itself as well as the related company:
(for [offer (:offers #query)]
(offer-tpl offer (get-in #query [:companies (keyword (:companyId offer))]))))))
Despite the fact that this surely can be done more elegant (suggestions very appreciated), the get-in doesn't work. (:companyId offer) returns a number (e.g. 22) but (keyword (:companyId offer)) returns nil. Calling (keyword (str (:companyId offer))) does the trick, but aren't there any other ways to do this?
(keyword "22") or (keyword (str 22)) returns :22
The reason you are getting :22 is likely because of the keywordize-keys option of a JSON translation. For example:
cljs-http defaults to keywordize-keys for jsonp:
https://github.com/r0man/cljs-http/blob/1fb899d3f9c5728521786432b5f6c36d1d7a1452/src/cljs_http/core.cljs#L115
But you can (and should) in this case pass in a flag to disable keywordization.
Not all keys in JSON are appropriate for Clojure keywordization. For example spaces in a JSON key are valid, but not in Clojure.
Please be aware that numeric keywords are probably incorrect.
https://clojuredocs.org/clojure.core/keyword#example-542692cec026201cdc326d70
It seems like that caveat has been removed from the current Clojure website, so perhaps that means something but I'm not sure what.
http://clojure.org/reference/reader Currently states that
Keywords - Keywords are like symbols, except: They can and must begin
with a colon, e.g. :fred. They cannot contain '.' or name classes.
Like symbols, they can contain a namespace, :person/name A keyword
that begins with two colons is resolved in the current namespace: In
the user namespace, ::rect is read as :user/rect
and that
Symbols begin with a non-numeric character and can contain
alphanumeric.
This definition of a keyword excludes :22 and :with spaces
The keyword function returns a result for invalid input, but this is not an endorsement, it is simply because checking for incorrect input would be a performance overhead in a core part of Clojure.
In short, not all JSON keys translate to keywords, so you should avoid keywordize-keys unless you know the keyspace and/or doing so provides some conveniences.
I am currently in the course of learning Python 2.7 and have come across the Equality and Boolean operators
My question is:
Why False and 1 is False but True and 1 is 1
Likewise, False or 1 is 1 but True or 1 is True
Can someone kindly explain why this is happening
Many thanks
and returns the first 'falsy' (False, zero, empty string or list, etc.) value it sees, or the final value if none were falsy. Further values are not even evaluated, since they can't change the result.
or likewise returns the first 'truthy' (True, non-zero, non-empty string or list, etc.) value it sees (or the final one if there were none), and doesn't evaluate the rest.
This behavior is sometimes more convenient than strictly returning only True or False.
Can someone please explain these functions for me in racket. I`m totally lost. Please help me with some examples. Thanks! I just cannot figure these functions out for the life of me.
First, the If:
(if (positive? 1) 1 -1)
Racket first evaluates if 1 is positive (which is the first expresion (positive? 1)). If it is, returns 1, else, return -1. This is equivalent to c-like languages doing:
if ( positive?(1))
return 1
else
return -1
The Cond is basically a if that has multiple options. The equivalent in C-like languages would be else-if
(cond [(first-condition) (what-to-do)]
[(second-condition) (what-to-do)]
[(third-condition) (you-get-the-idea)])
And and Or are just the logical operators, equivalent to && and || in C-like languages
(and true true) => true
(and true false) => false
(or true true) => true
(or true false) => true
(or false false) => false
If is the turnary operator. It has three arguments, unless the first argument has a value of #f it will return the value of the second argument, otherwise the value of the third argument.
OR accepts one or more arguments, evaluates them one at a time left to right, and returns the first value if finds that is not #f, and returns #f if no argument satisfies that condition.
AND accepts one or more arguments evaluate them one at a time left to right, if it finds one that is #f it returns #f, otherwise it returns the value of the last argument that it evaluates.
COND accepts one or more arguments, each with one or more sub arguments (2 is the usual number though). It evaluates each argument left to right one at a time by evaluating the first subargument. If it is not #f then it evaluates each of the rest of the sub-arguments (if any) in order and returns the value of the last argument. Otherwise it moves onto the next argument and evaluates it the same way. else is a special sytax within these sub-arguments that is always treated as if it is not #f.
And here argument is understood to mean any valid s-expression.
NB: If you are familiar with non-lisp languages this is the answer for you. I'm not trying to explain them in other way than other code. Other answers do however so this is just a supplement.
None of those are functions, but special forms.
(if predicate
consequent
alternative)
is pretty much like Algol-dialects if
if( predicate )
{
consequent
}
else
{
alternative
}
Note that predicate, consequent and alternative can be anything from a complex expression to a simple value.
cond works more like an if, elseif..., else:
(cond (predicate1 consequent1)
(predicaten consequentn)
(else alternative))
and works like && in algol dialects. Thus false && print("Do it!") doesn't print anything since it short circuits.
(and #f (display "Do it!")) ; ==> #f (and does not display anything since first term was false)
(and 1 2 3) ; ==> 3 (3 is the last true value. In Scheme everything except #f is true.)
or works like || in algol dialects. thus true || print("Do it!") doesn't print since first term was true.
(or 'mama (display "Do it")) ; ==> mama (first true value, does not print "do it")