i need to do a sort-by inside a macro,
i have a map set like this:
(def persons '({:id 1 :name "olle"} {:id 2 :name "anna"} {:id 3 :name "isak"} {:id 4 :name "beatrice"}))
if i try to do (sort-by :name persons) it works fine and sort it
but within the macro:
(defmacro select
[columns _ map _ where _ order]
`(sort-by ~order ~#map))
it doesnt sort.
REPL (clojure.core/sort-by :name persons)
You've got an error in ~#map clause. You do not need # here. That symbol expands a sequence in place, e.g. [1 2 3] -> 1 2 3.
The working code:
(defmacro select
[columns _ map _ where _ order]
`(sort-by ~order ~map))
Check with expanding the macro:
(macroexpand '(select nil nil persons nil nil nil :id))
(clojure.core/sort-by :id persons)
Related
I have a string:
{:id 1, :name "Ab Bc Cd", :sex "M", :birth "01.01.1999", :address "Street 1", :oms "0001"}
And i need to convert it to HashMap but
(hash-map my-str)
returns {}
So i splited it:
(s/split my-str ",")
And it returns
[:id 1 :name "Ab Bc Cd" :sex "M" :birth "01.01.1999" :address "Street 1" :oms "0001"]
Then
for [x my-arr]
(hash-map x)
returns
({} {} {} {} {} {})
How can i do this?
If you got this string intentionally, then use
clojure.edn/read-string
E.g.
user=> (require 'clojure.edn)
nil
user=> (clojure.edn/read-string (slurp "x.edn"))
{:id 1, :name "Ab Bc Cd", :sex "M", :birth "01.01.1999", :address "Street 1", :oms "0001"}
your example is almost there!
you can finish it with a call to
(into {} your-result-so-far)
into comes up a lot of you get into the habit of looking for it.
The shortest way would be clojure.core's read-string - it reads from the string and executes the command for building an object:
(def s "{:id 1, :name \"Ab Bc Cd\", :sex \"M\", :birth \"01.01.1999\", :address \"Street 1\", :oms \"0001\"}")
(read-string s)
;; => {:id 1, :name "Ab Bc Cd", :sex "M", :birth "01.01.1999", :address "Street 1", :oms "0001"}
The documentation says:
Reads one object from the string s. Optionally
include reader options, as specified in read. Note that read-string
can execute code (controlled by read-eval), and as such should be
used only with trusted sources. For data structure interop use
clojure.edn/read-string
Edit:
There are tons of great answers here till I do not know which to select as the "answer". Based on a comment suggestion, this question should be marked as "off topic". Hence, I'm sorry but I will not choosing an answer and I shall leave this here in case someone else has the same question I have.
Is there a difference between:
(1)
a = {
:x => 1
}
And
(2)
b = {
:x => 1,
:y => nil
}
Given that for (1), a[:y] returns nil
And for (2), b[:y] returns nil as well
The only difference I see is that when I output:
(1)
{
:x => 1
}
And (2)
{
:x => 1
:y => nil
}
There are several differences. Let me describe two, so you know where to look:
Hash#fetch raises error (or calls a block if it's provided) if key is not present:
a.fetch(:y)
# >> KeyError: key not found: :y
> a.fetch(:y){ "100" }
# => "100"
b.fetch(:y)
# => nil
b.fetch(:y){ "100" }
# => nil
Hash#map (and all other iterators) takes the key with nil value into account:
a.map{|k, v| [k, v]}
# => [[:x, 1]]
b.map{|k, v| [k, v]}
# => [[:x, 1], [:y, nil]]
Yes, the hash has a different number of pairs. hsh.keys will return [:x, :y]
Both hashes return nil value for :x and :y keys because they are configured to return nil when no key is found. This is the default behaviour in Ruby.
However you can change that behaviour when initializing your hash
c = Hash.new("foo")
c[:x] = 1
c[:x]
# => 1
c[:y]
# => "foo"
I am new to clojure and need some help.
In clojurescript I build up a html table using a map (stored in atom) e.g.
[{:id 2, :category "Big bang theory", :name "The Big Bang!"}
{:id 3, :category "The big Lebowski", :name "Ethan Coen"}
{:id 4, :category "Chitty Chitty Bang Bang", :name "Roald Dahl"}]
I want to create a search that searches for a word (i.e. "ban") en return a map with those entries that have that word (or part of it) in one of its key values.
In case of "ban" it should return
[{:id 2, :category "Big bang theory", :name "The Big Bang!"}
{:id 4, :category "Chitty Chitty Bang Bang", :name "Roald Dahl"}]
Based on the above map the table updates with only those two entries.
I found some interesting solutions, but they all focus on one key (i.e. :category or :name) but not all keys in the map entry.
I think this tries to achieve the same, but I don't think someone gave the answer. Any help is appreciated :D
(def maps
[{:id 2, :category "Big bang theory", :name "The Big Bang!"}
{:id 3, :category "The big Lebowski", :name "Ethan Coen"}
{:id 4, :category "Chitty Chitty Bang Bang", :name "Roald Dahl"}])
(filter
#(some
(fn [v]
(when (string? v)
(-> v
(str/lower-case)
(str/includes? "ban"))))
(vals %))
maps)
I am confused with how puts _|_ works in Ruby. If you type in a variable and then call that statement
3
puts _|_
you get the name of the variable followed by nil
3
=> nil
However, if you type it again, you get false
puts _|_
=> false
It doesn't seem like one of those Perl-like variables that begin with a dollar sign.
What in the world does this weird symbol mean and how does it work?
The underscore in a console (IRB or pry) stands for the result of the previous command. So
3
=> 3
puts _|_
3
=> nil
Here the above puts statement becomes equivalent to
puts 3 <bit-wise or> 3
which puts 3|3 equals puts 3.
Since puts returns nil, when you repeat the puts _|_ it becomes
puts nil|nil
... which is puts false.
In ruby _ is a valid identifier.
In IRB _ contains the value of the last expression.
2.1.5 :001 > 100
=> 100
2.1.5 :002 > _
=> 100
_ is a ruby special variable, it is used to get the result of the previous expression.
irb(main):030:0> 3
=> 3
irb(main):031:0> _
=> 3
irb(main):032:0> _.to_s
=> "3"
irb(main):033:0> _
=> "3"
A ruby variable whose name begins with a lowercase letter (a-z) or underscore (_) is a local variable or method invocation. Uninitialized instance variables have a value of nil.
irb(main):001:0> _
=> nil
irb(main):002:0> _ | _
=> false
irb(main):003:0> nil | nil
=> false
_ is a ruby special variable, this variable stores out put of the previous expression/command, so when you do:
1.9.3-p0 :043 > 3
=> 3
'_' contains the value 3, because return value of previous expression is 3. When you use puts as below:
1.9.3-p0 :045 > puts _|_
3
=> nil
its return value is nil.Next time when you execute the | as below:
1.9.3-p0 :049 > _|_
=> false
it returns false because it is same as below expression:
1.9.3-p0 :050 > nil|nil
=> false
that is why puts | returns false.
Sometimes while dealing with API responses, I'll end up writing something like:
what_i_need = response["key"]["another key"]["another key 2"]
The problem with that is, it'll throw an error if, say, "another key" is missing. I don't like that. I'd be a lot happier if what_i_need turned up a nil if something along the process broke.
Is there a more elegant solution than:
what_i_need = nil
begin
what_i_need = response["key"]["another key"]["another key 2"]
rescue Exception => e
end
I also thought about monkey patching NilClass you try to access nil["something"] it would return nil, but I'm not sure if that's the best way to go about it either of if it's possible even.
Use Hash#fetch with default value.
h = {:a => 2}
h.fetch(:b,"not present")
# => "not present"
h.fetch(:a,"not present")
# => 2
Without default value it will throw KeyError.
h = {:a => 2}
h.fetch(:b)
# ~> -:2:in `fetch': key not found: :b (KeyError)
But with nested Hash like your one you can use :
h = {:a => {:b => 3}}
val = h[:a][:b] rescue nil # => 3
val = h[:a][:c] rescue nil # => nil
val = h[:c][:b] rescue nil # => nil
Ruby 2.0 has NilClass#to_h.
what_i_need = response["key"].to_h["another key"].to_h["another key 2"]
Taking some inspiration from Objective-C's key-value coding system, you can do this with a lightweight DSL to walk a series of keys in an arbitrarily-nested data structure:
module KeyValue
class << self
def lookup(obj, *path)
path.inject(obj, &:[]) rescue nil
end
end
end
h = { a: { b: { c: 42, d: [ 1, 2 ] } }, e: "test"}
KeyValue.lookup(h, :a, :b, :d, 1) # => 2
KeyValue.lookup(h, :a, :x) # => nil
Or if you just want the one-liner:
(["key", "another key", "another key 2"].inject(h, &:[]) rescue nil)
To expand on #Priti’s answer a bit, you can use a chain of Hash#fetch instead of Hash#[] to return empty hashes till you get to the last in the chain, and then return nil:
what_i_need = response.fetch('key', {})
.fetch('another key', {})
.fetch('another key 2', nil)
or rely on the KeyError exception being raised (maybe not the best, as exceptions as control flow should be avoided):
what_i_need = begin
response.fetch('key').fetch('another key').fetch('another key 2')
rescue KeyError
nil
end