Welcome to the new home of the KX Community and KX Academy! Existing users are required to reset their passwords to log in

Forum Replies Created

Page 3 of 4
  • gyorokpeter-kx

    Member
    July 10, 2023 at 12:00 am in reply to: Issue with flip in Table Joins

    This is hinted at in the docs of flip: the values are lists of the same count (or atoms). The “(or atoms)” part is relevant here. If any of the values are atoms, they are extended to the same length as the lists. Therefore it is enough to have only one value be a list and the rest can be atoms. But if there are multiple lists, they must have the same length.

  • gyorokpeter-kx

    Member
    July 6, 2023 at 12:00 am in reply to: Performance using a table to combine where phrases

    If you have a list of where clauses separated by a comma, it is executed sequentially, successively reducing the number of rows processed. On the other hand if you use the & operator, all operations will run on the full table.

  • gyorokpeter-kx

    Member
    June 26, 2023 at 12:00 am in reply to: Retrieving values from a dictionary using namespacing

    Probably because this syntax is only intended to use with regular namespaces (whose names begin with a dot). When you create a namespace it always has a mixed list in its values because a  ` | :: item is implicitly inserted into it. So the lookup code might be written with the assumption that this always needs to be the case.

  • .Q.trp[(0;)@value@;x;{(1;.Q.sbt y)}]

    means roughly the same as

    .Q.trp[{(0;value x)};x;{(1;.Q.sbt y)}]

    The only difference is that the second form uses a lambda, which appears as an additional level in the stack trace.

    The @ at the end of an expression forces it to be a projection (since it’s a binary operator and we haven’t given it a right argument). But in order to compose this with the (0;) operation (which puts the result in the 2nd element of the list) we need to include another @ otherwise we would be composing the wrong functions.

    .Q.trp[{value x};x;{(1;.Q.sbt y)}] works but it returns a different value in the success case (just the value instead of a list).

  • .Q.par doesn’t check where the partition is, only where it should be according to par.txt. It assigns the segments by taking the modulus of the date by the number of par.txt entries.

  • gyorokpeter-kx

    Member
    June 15, 2023 at 12:00 am in reply to: md5 – getting the original string back.

    It would be helpful if you could describe your use case.

    MD5 is a hash function. The main characteristic of a hash function is that it reduces the amount of information contained in the input. There is no way to get back the exact original data as there are infinitely many possible byte sequences that lead to the same hash. Usually when you want to use the hash for anything, it’s for comparing against another hash to check if the two are equal (an example is downloading a file, where you can check if your download is corrupted by comparing its hash to the one found on the website).

  • gyorokpeter-kx

    Member
    May 30, 2023 at 12:00 am in reply to: domain and range

    The letters refer to the datatypes as listed at Reference card | kdb+ and q documentation – Kdb+ and q documentation (kx.com) . b = boolean, i = int etc.

    The domain is the data type of the input and the range is the data type of the output. So if you give it a boolean you get an int, if you give it a real or float you get a real or float back etc. GUID, char and symbol are marked with a dot to indicate that these types are not supported.

  • gyorokpeter-kx

    Member
    May 2, 2023 at 12:00 am in reply to: Issue with xkey

    The phenomenon you are seeing is because there are two columns named c in complexTab!example. In general duplicated column names in a table are a bad idea, and some functions even check for this and throw an error. But xkey just uses the # operator, which takes the first occurrence of the column to determine its value, so the first c column gets duplicated. ! is a built-in operator so it can use a different implementation to rearrange some pointers in memory that doesn’t rely on the column names.

     

  • gyorokpeter-kx

    Member
    April 17, 2023 at 12:00 am in reply to: Issues with Filling Missing Values in Dictionaries

    Note that there should be some consideration whether using a symbol is appropriate for the data in question. Chances are, if it is, you should already have been using symbols in the first place. Casting arbitrary strings to symbols will cause them to persist in memory until the process exits. This might not have an impact if you are just trying out toy examples, but it can lead to “symbol leak” if it happens on a production system that processes a large amount of data.

  • gyorokpeter-kx

    Member
    April 17, 2023 at 12:00 am in reply to: How to walkthrough a tree and calculate value on path?

    This gets it done while remaining somewhat readable:

    child:select (child,'data) by parent from tree; 
    res:(); 
    a:([]start:key[child];end:key[child];val:1); 
    while[count a; res,:select from a where not end in key child; b:ungroup update nxt:child end from (delete from a where not end in key child); a:select start, end:nxt[;0], val*nxt[;1] from b; ];

    The answer is given by

    q)`start`end xasc res 
    start end val 
    ------------- 
    A     C   2 
    A     D   3 
    A     F   5 
    A     G   24 
    A     H   28 
    B     F   5 
    B     G   24 
    B     H   28 
    E     G   6 
    E     H   7
  • gyorokpeter-kx

    Member
    April 15, 2023 at 12:00 am in reply to: Issues with Filling Missing Values in Dictionaries

    1. The fill operator works on atomic values. When you try to use it between a dictionary and a string, it attempts to match up each character in the string with the corresponding element in the dictionary, so it tries to do “eu”^”n” (first element) and “eu”^”a” (second element) but there it can’t go further as the list on the right doesn’t have enough elements, but even if it did, this is not the operation that you want. Since a string is a list of characters, ^ cannot be used to fill an empty one with a non-empty one like it would be possible with atoms. So your only option is to check the length of the string and replace it if it’s zero.

    2. When assigning by index, the item on the right must have the same number of elements as the number of indices you are assigning. Once again there is special handling for atoms in that you can assign them to more than one index at once, but a string is a list, so that doesn’t work. Instead you need to provide as many copies of the string as there are indices. It can be simplified a bit by assigning the index list to an intermediate variable that you can take the count of:

    ind:where 0=count each myDict; 
    myDict[ind]:count[ind]#enlist"na"

    3. As explained in 1., fill works element-wise, so the 99 is expanded to match the size of the dictionary (3×3) and then every element is filled in with the 99 individually. This works because the atom can extend to any size, but lists don’t auto-extend so they must match in length.

  • gyorokpeter-kx

    Member
    April 3, 2023 at 12:00 am in reply to: how does "block ipc" work

    When you invoke a handle to wait for an async message it bypasses .z.ps.

    However I’m confused what happens with the 7+7 and 8+8 messages. Normally these go through .z.pg and this works even if the server is blocking waiting for an async message. So the observation should be that when sending a sync 7+7 while the server is blocking, you should still get back the result of 14 immediately.

    However there are instances where combining sync and async messages in a single query cycle, with two processes sending messages to each other before returning, can lead to the messages being confused and a query returning the wrong reply.

  • gyorokpeter-kx

    Member
    March 13, 2023 at 12:00 am in reply to: Heap is a lot larger than used, how to find the cause?

    As a first step you could insert printouts of .Q.w[] in between the actual operations in the query, even breaking down expressions into single operator invocations if necessary. Additionally .Q.ts can be used to figure out the time and space used by an operation, similarly to ts but it also returns the result (it is parameterized like . (dot) for multi-parameter apply).

     

  • gyorokpeter-kx

    Member
    March 13, 2023 at 12:00 am in reply to: In-place attribute removal

    According to the docs at Set Attribute | Reference | kdb+ and q documentation – Kdb+ and q documentation (kx.com) :

    Setting or unsetting an attribute other than sorted causes a copy of the object to be made.

     

    Using a C function as a workaround might work but it might also break in a future version when kdb+ internals change.

  • gyorokpeter-kx

    Member
    February 28, 2023 at 12:00 am in reply to: Changing column type fails

    Can you make sure that the res variable you do the meta on is the same that you are trying to update? E.g. global vs local variable, or other queries changing it in the meantime. Or there being a space in the column name (possible if parsing from CSV).

    This works:

    q)res:([]id:("AA";"BB");first_name:("CC";"DD");last_name:("EE";"FF");email:("GG";"HH")) 
    q)meta res 
    c         | t f a 
    ----------| ----- 
    id        | C 
    first_name| C 
    last_name | C 
    email     | C 
    
    q)update "S"$id from res 
    id first_name last_name email 
    ----------------------------- 
    AA "CC" "EE" "GG" 
    BB "DD" "FF" "HH"
Page 3 of 4