Access attribute and method names with slashes or asterisks defined in Hy from Python - hy

If I were to do the following:
(setv a/b 12)
How would I access the variable in Python, such as from a regular python module, or simply using (py)?
(py "print(a/b)")

With mangling:
=> (setv a/b 12)
=> a/b
12
=> (hy.mangle "a/b")
"hyx_aXsolidusXb"
=> hyx_aXsolidusXb
12
=> (py "print(hyx_aXsolidusXb)")
12
=> (py "print(globals()[hy.mangle('a/b')])")
12

Related

Locally rebinding `+`

How to translate this Clojure code to Hy, so it prints 2?
It doesn't need to be like Clojure, i just want to hide + and replace it with - in local environment.
(defmacro q [expr]
`(let ~'[+ (fn [x y] (- x y))]
~expr))
(print (q (+ 3 1)))
In Clojure it prints 2 (let creates a local environment).
In Hy it prints 4.
How to make Hy print 2 also, by replacing the + with - ?
I need those local environments because i am making a DSL.
This doesn't do what you expect in Hy because + is a macro, and macro calls take precedence over function calls:
(defmacro x [] 1)
(defn x [] 2)
(print (x)) ; => 1
Your options are:
Instead of +, use a name doesn't have the same name as a core macro, like my+ or +2.
Only use your new + in contexts other than the head of an Expression (which is the only place Hy expands macro calls), such as (map + (range 10)).
In q, replace the symbol + in the input instead of just setting the variable +, as in something like
(defmacro q [expr]
(import hyrule [coll?])
(defn f [x]
(cond
(= x '+) '-
(coll? x) ((type x) (map f x))
True x))
(f expr))
(print (q (+ 3 1)))
Use defmacro to define a new macro named +. This is a bad idea because you lose access to the original + in this module, including in the expansions of macros you didn't write that expect + to have its usual meaning. Local macros are not yet implemented (#900).

updating a document using the $max operator on arrays

i have the following document:
{
_id: 12,
item: 'envelope',
qty: ISODate("2021-12-05T00:00:00.000Z"),
arrayField: [ 128, 190, 1 ]
}
and i try to update it using this command
products> db.products.update({_id:12},{$max : { arrayField : [1,190,1879]} })
the output is as follows:
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 0,
upsertedCount: 0
}
I don't really understand how the comparison between the existing arrayField and the new one is being done. They are both Arrays, so there should be some kind of comparison on every element, but how exactly does it work?
From the documentation i read this:
With arrays, a less-than comparison or an ascending sort compares the smallest element of arrays, and a greater-than comparison or a descending sort compares the largest element of the arrays. As such, when comparing a field whose value is a single-element array (e.g. 1 ) with non-array fields (e.g. 2), the comparison is between 1 and 2. A comparison of an empty array (e.g. [ ]) treats the empty array as less than null or a missing field.
But i still don't understand exactly... Could someone provide an example in my case?
Thanks in advance
MongoDB takes the min or max, to represent the array in comparisons, for the query operators.
Numbers
{"ar" : [1,2,3]}
(<= ar 1) => (<= min(1,2,3) 3) => (<= 1 3) true
(>= ar 3) => (>= max(1,2,3) 3) => (<= 3 3) true
(= ar 2) => true because it contains the element
For empty arrays either < or > its always false compared to a number
Arrays
(again take the min if < , or max it >)
{"ar" : [1,2,3]}
(<= ar [0 1 2 3]) false because its like min(ar)=1 <min(0,1,2,3)=0
(= ar [1]) false we need all elements =
For the update $max operator
if both are arrays => elements are compared one by one.
max [1 2 3] [5] => [5]
max [1 2] [1 2 -100] => [1 2 -100]
Those are only for the $gte,$gt,$lt,$lte, $eq query operators.
The aggregate ones with same names are strict and don't work like this.
*Its not like complete because we have many types,i think the above are ok, answer might help, it was big to fit in comments.

how to eval a cond case and return function object?

got TypeError: Don't know how to wrap <class 'function'>: <function test_cond_list_fn.<locals>.<lambda> at 0x000001B879FD3D08>
when run
;a fn object
(setv a_fn (fn [x] (+ 1 x)))
;a mock predicator
(setv predicator True)
;inject predicator and a_fn into a (cond ..)
(setv cond_expr `(cond [(~predicator) [~a_fn]]))
;eval at another place
(eval cond_expr)
How to create the "cond_expr" so that get the result [a_fn] ?
In order to eval a HyExpression it must first be compiled to Python ast. While you're allowed to put arbitrary objects into a HyExpression, that does not mean you can compile it. (There has been a little talk of simulating this feature, but it's not available currently.)
The Hy compiler can only do this for a certain set of data types called Hy Model types, or for a few other types that can be automatically converted to these Hy Models.
There's no obvious way to represent a function object in Python ast, so there is no Hy Model for it. But you can compile a function definition.
=> (setv a-fn '(fn [x] (+ 1 x)))
=> (setv cond-expr `(cond [True ~a-fn]))
=> (eval cond-expr)
<function <lambda> at 0x0000020635231598>
Or a function's symbol.
=> (defn b-fn [x] (- x 1))
=> (setv cond-expr2 `(cond [True b-fn]))
=> (eval cond-expr)
<function <lambda> at 0x0000020635208378>

Why Julia produces #undef keys in Dictionary?

I have made a dictionary of histograms on Julia, with a lot of entries. The keys are 4 element integer arrays, as a simple call to the object returns:
In[88] Histogramas
Out[88] Dict{Array{Int64,N},Array{T,N}} with 36540 entries:
[56,8,39,55] => [0,2,4,7,19,44,61,76,124,116 … 0,0,0,0,0,0,0,0,0,0]
[64,20,48,55] => [284,368,202,106,35,3,2,0,0,0 … 0,0,0,0,0,0,0,0,0,0]
[54,9,50,54] => [0,0,0,0,0,0,0,0,0,2 … 1,0,0,0,0,0,0,0,0,0]
[37,26,45,61] => [0,6,11,35,47,86,113,133,136,139 … 0,0,0,0,0,0,0,0,0,0]
[37,15,51,50] => [673,272,48,5,2,0,0,0,0,0 … 0,0,0,0,0,0,0,0,0,0]
[35,22,53,45] => [331,370,201,69,25,4,0,0,0,0 … 0,0,0,0,0,0,0,0,0,0]
[37,25,56,40] => [460,382,127,27,3,0,1,0,0,0 … 0,0,0,0,0,0,0,0,0,0]
....
But if i call Histogramas.keys then I get this very weird output:
Out[90] : 65536-element Array{Array{Int64,N},1}:
#undef
#undef
[56,8,39,55]
#undef
[64,20,48,55]
[54,9,50,54]
#undef
[37,26,45,61]
[37,15,51,50]
...
So I got almost twice keys as there are entries of the dictionary, and most of the extra ones are #undef, which, by the way, I also do not know what that means. ¿Undefined in what sense?
That is not the right way to get a Dict's keys – you're accidentally accessing the private internal fields of the Dict object. The correct way to access a Dict's keys is to call the keys function on the Dict object:
julia> d = Dict(:foo => 1.2, :bar => 2.3, :baz => 3.4)
Dict{Symbol,Float64} with 3 entries:
:bar => 2.3
:baz => 3.4
:foo => 1.2
julia> keys(d)
Base.KeyIterator for a Dict{Symbol,Float64} with 3 entries. Keys:
:bar
:baz
:foo
The output #undef when displaying an array indicates an uninitialized entry in the array. This is similar to a null value in C, C++ or Java, but unlike null, in Julia #undef is non-first-class: it is not a value that you can use or pass around; any use of an undefined field or array slot is an immediate exception.
In general, Julia is not a "dot oriented language": whereas in Python or Java you might expect to do obj.frob to access obj's frob or do obj.frizzle() to frizzle obj, in Julia that is unlikely to be the right thing to do. You would most likely do frob(obj) and frizzle(obj) instead.

Algorithm to get group index of item in chunked array

So I have an arbitrary array of items:
array = [0,1,2,3,4];
and when it's been chunked it looks like:
array.chunk(2) => [[0,1],[2,3],[4]];
array.chunk(3) => [[0,1,2],[3,4]];
What i'd like is an algorithm to get the index of the group that the index is in, based on the group size.
For instance, running the algorithm on each element in array would yield:
array.chunkIndex( chunkSize = 2, index = n )
0 => 0
1 => 0
2 => 1
3 => 1
4 => 2
array.chunkIndex( chunkSize = 3, index = n )
0 => 0
1 => 0
2 => 0
3 => 1
4 => 1
So running the algorithm on the index with chunkSize = 1 would always yield the original index.
How would I go about doing this? To be clear, I don't want to chunk the array, just determine which group it would be in, without looping and without built-in functions, if possible.
Also in psuedo-code:
chunkIndex = index / chunkSize
It's simple integer division which means the only case you have to be careful of is languages that will return a float/decimal/real. For those cases, you will need a floor function to find just the integer part of the result. You may wish to handle negative values also.
floor(index / chunkSize) should work!

Resources