Search code examples
kdb

Getting type error when using $ cond in KDB


I have a dictionary (testDict) in the following format with hostname and region of that hostname

`host1|`LDN
`host2|`NYK

I have a function to return region based on hostname

func1:{[hostname] testDict[hostname]}

When I execute the function, I get enlisted region

 func1[`host1]
 enlist`LDN

I am trying to assign some variables based on the value that is returned by this function but I am getting type error. I have tried both vector conditional and cond. Appreciate your input on this

$[enlist `LDN=func1[`host1]; connDetails:`:hostName:port:id:pass; connDetails:`:newHostName:port:id:pass]

What am I missing here?


Solution

  • Couple of things here. First, kdb+ reads right to left, so this:

    enlist `LDN=func1[`host1]
    

    compares LDN to the output of func1 and then enlists that result, rather than enlisting LDN before the comparison. Use parentheses to force the order of execution you want:

    enlist[`LDN]=func1[`host1]
    

    Secondly, $ expects an atomic value in the conditional, your statement returns a 1 item list. You can use first to convert it to an atom:

    q)type first enlist[`LDN]=func1[`host1]
    -1h
    

    Having said all of that, it looks like the real issue is that your dictionary is storing the values as 1 item lists, rather than atoms. You would be better off to store the atomic values, which will simplify everything for you.

    q)testDict:first each testDict
    q)$[`LDN=func1`host1;connDetails:`:hostName:port:id:pass;connDetails:`:newHostName:port:id:pass]
    `:hostName:port:id:pass
    q)$[`NYK=func1`host1;connDetails:`:hostName:port:id:pass;connDetails:`:newHostName:port:id:pass]
    `:newHostName:port:id:pass
    

    Or simpler still, just store the mapping from hostname to connection details as your dictionary and index that to get the result you want:

    q)d:`host1`host2!`:hostName:port:id:pass`:newHostName:port:id:pass
    q)d`host1
    `:hostName:port:id:pass
    q)d`host2
    `:newHostName:port:id:pass
    

    If you need a default connection string for hosts not in your dictionary, you can use fill (^):

    q)`:default^d`host1
    `:hostName:port:id:pass
    q)`:default^d`host3
    `:default