Skip to content

Convert inputs of join to strings#302

Merged
01mf02 merged 3 commits intomainfrom
join-string
Jul 7, 2025
Merged

Convert inputs of join to strings#302
01mf02 merged 3 commits intomainfrom
join-string

Conversation

@01mf02
Copy link
Owner

@01mf02 01mf02 commented Jul 3, 2025

This should close #289.

@A4-Tacks
Copy link

A4-Tacks commented Jul 5, 2025

For strange inputs, it may be better to report errors

This is jq implement:

def join($x): reduce .[] as $i (null;
            (if .==null then "" else .+$x end) +
            ($i | if type=="boolean" or type=="number" then tostring else .//"" end)
        ) // "";

Also, the implementation of jq can input object

Examples:

$ jq -n '[1,2,null,3,true]|join(",")'
"1,2,,3,true"
$ jq -n '{x:2,y:3}|join(",")'
"2,3"
$ jq -n '{}|join(",")'
""
$ jq -n '[[0],[1]]|join(",")'
jq: error (at <unknown>): string ("") and array ([0]) cannot be added

@01mf02
Copy link
Owner Author

01mf02 commented Jul 7, 2025

For strange inputs, it may be better to report errors

I do not agree, because it makes the filter harder to describe and thus to understand.
The current implementation in this PR can be described as follows:
join($sep) takes an array [x1, ..., xn] as input and returns "" if the array is empty or "\(x1)" + $sep + ... + $sep + "\(xn)" otherwise. That's it. No "strange inputs", no special handling for null values, nothing. I deeply believe that simpler filters can be understood more easily and compose better, and that is one of my goals. More complex implementations like the one of join in jq are also generally less performant, and performance is another of my goals.

Also, the implementation of jq can input object

To quote the jq manual about join:

Joins the array of elements given as input, using the argument as separator. It is the inverse of split: that is, running split("foo") | join("foo") over any input string returns said input string.

So even if jq supports objects as input to join, this is not documented, nor is it a good idea IMO, because the order of iteration over object values is not guaranteed. {a: 1, b: 2} | .[] may return 1, 2 today, but there is no guarantee that it will do so tomorrow. So if you depend on the order (which is very likely with join), you will get a problem tomorrow. So it makes sense to not support this case.

Just so that you understand my goal with jaq; it is not to implement every implementation-specific detail of jq. Instead, my goal is to make it possible for a large class of programs to behave the same way in jq and jaq. This is doable, as has been shown with e.g. jqjq and now wsjq. Trying to reproduce every behaviour of jq perfectly is an uphill battle that cannot be reasonably won due to Hyrum's law, if one wants to improve aspects of jq.

I am sympathetic to making changes to jaq's behaviour if somebody points me to a concrete instance where its behaviour hurts performance or usability. But I do not intend to reproduce all jq behaviour perfectly. Especially not undocumented or --- in my opinion --- outright confusing cases.

In your case, for example, unless you convince me why join should support objects, I will not change join. @thaliaarchi has given a very valid reason, and in such cases, I am sympathetic to changes. But just pointing out instances where jaq and jq do not give the same output, without providing use cases or reasons, does not convince me in general.

@01mf02 01mf02 merged commit 74dae64 into main Jul 7, 2025
3 checks passed
@01mf02 01mf02 deleted the join-string branch July 10, 2025 09:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support join for number array

2 participants