orderedhash.map with keys() as argument

35 views
Skip to first unread message

markus.sc...@gmail.com

unread,
Aug 13, 2025, 1:11:44 PMAug 13
to idl-pvwave
What am I doing wrong? or is it a bug?

IDL> ha=orderedhash('a',1,'b',2)
IDL> foreach h,ha,k do print, k+':  '+string(h)      
a:         1
b:         2
IDL> out1=orderedhash()
IDL> foreach h,ha,k do out1[k]= k+':  '+string(h)
IDL> out2=ha.map(lambda("h,k:k+':  '+string(h)"),ha.keys())
% Type conversion error: Unable to convert given STRING to Long.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1094
% Type conversion error: Unable to convert given STRING to Long.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1105
% Type conversion error: Unable to convert given STRING to Long.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1105
% Type conversion error: Unable to convert given STRING to Long64.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1114
% Type conversion error: Unable to convert given STRING to Long.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1094
% Type conversion error: Unable to convert given STRING to Long.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1105
% Type conversion error: Unable to convert given STRING to Long.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1105
% Type conversion error: Unable to convert given STRING to Long64.
% Detected at: LIST::_OVERLOADBRACKETSRIGHTSIDE 1114
IDL> out2
{
    "a": "a:         1",
    "b": "a:         2"
}
IDL> out1
{
    "a": "a:         1",
    "b": "b:         2"
}
IDL> !version
{
    "ARCH": "x86_64",
    "OS": "linux",
    "OS_FAMILY": "unix",
    "OS_NAME": "linux",
    "RELEASE": "8.5",
    "BUILD_DATE": "Jul  7 2015",
    "MEMORY_BITS": 64,
    "FILE_OFFSET_BITS": 64
}

Chris Torrence

unread,
Aug 17, 2025, 10:06:41 AMAug 17
to idl-pvwave
I think this is the way it's supposed to behave (sort of). I had to re-read the docs. The Map function only passes in hash values, not keys. The first argument to the map function is always the hash value (for each key). The second (and other arguments) are either scalars or are also hashes.

Here's what the docs say for the additional arguments:
"Each argument must be either a scalar or a hash. For scalar arguments, ::Map will pass in that same scalar value to each call of the function. For hash arguments, ::Map will pull out the value corresponding to the current key and pass that into your function as a scalar."

I don't think there's any way to retrieve the keys from within the Map function.

Regardless, I don't understand where that actual error message is coming from or why. I'll need to dig into the C code and figure that out - so that part might be a bug...

Cheers,
Chris
IDL Lead Dev

markus.sc...@gmail.com

unread,
Aug 18, 2025, 7:30:34 AMAug 18
to idl-pvwave
Thanks. I figured out the correct way to get what I want, without yielding errors:
out2=ha.map(lambda("h,k:k+':  '+string(h)"),orderedhash((ha.keys()).toArray(),(ha.keys()).toArray()))

Chris Torrence

unread,
Aug 18, 2025, 5:06:45 PMAug 18
to idl-pvwave
Glad you found a solution. I checked the C code - it turns out we were incorrectly identifying that second argument ha.keys() as a hash. It would then try to index into it using the hash keys "a" and "b", which would of course throw conversion errors since it would try to convert those keys into integers.

I've modified the C code so it treats any non-hash object (like a list) as a scalar object and just passes it in unchanged. This doesn't help you with your original code, it just enforces consistency with the documentation. It also throws only a single error message instead of one per element!

So your solution of creating a new orderedhash is probably the best solution regardless. Either that or use a foreach like in your original code. With the foreach at least you get the key for each value.

Cheers,
Chris

Chris Torrence

unread,
Aug 18, 2025, 9:57:57 PMAug 18
to idl-pvwave
One more thing - I just added a /KEYS keyword to the Map method. If you set that, then it will automatically pass in the current key as the _last_ argument to your function. So in IDL 9.3, you should be able to do something like:

IDL> ha=orderedhash('a',1,'b',2)
IDL> out2=ha.map(lambda("h,k:k+':  '+string(h)"),/keys)

Cheers,
Chris

Reply all
Reply to author
Forward
0 new messages