Open loziniak opened 1 year ago
tag1<tag2>>
is a problem of tags, not of rejoin
. And in fairness the block/path issue can be fixed by rewriting the docstring of rejoin
. So what are you proposing in the end?
I see rejoin like this:
rejoin: func [
"Reduces and joins a block of values."
block [block!] "Values to reduce and join"
] [
if empty? block: reduce block [return block]
joined: either series? first block [copy first block] [to string! first block]
while [not empty? block: next block] [
append joined first block
]
joined
]
And I'd get over the tags, as well as emails and urls.
Good to keep an eye on #134 too.
I see rejoin like this:
Given its importance, this won't cut, because:
;; minimal code
>> clock/times [append form 1 [2 3 4 5 6 7 8 9 10]] 1e5
2.52 μs [append form 1 [2 3 4 5 6 7 8 9 10]]
== "12345678910"
;; native rejoin, interpreted
>> rejoin: func spec-of :rejoin body-of :rejoin
>> clock/times [rejoin [1 2 3 4 5 6 7 8 9 10]] 1e5
5.86 μs [rejoin [1 2 3 4 5 6 7 8 9 10]]
== "12345678910"
;; your one
>> clock/times [rejoin [1 2 3 4 5 6 7 8 9 10]] 1e5
16.1 μs [rejoin [1 2 3 4 5 6 7 8 9 10]]
== "12345678910"
At least it's not an order of magnitude. Perhaps it could be optimized, I did not write it with speed in mind.
While I don't press for TDD most of the time, I do think that spec'ing expected results would be a good plan for this. So then we know what the edge cases and designed behavior are.
This would be slower than now, but faster than @loziniak's.
rejoin-foreach: function [
"Reduces and joins a block of values."
block [block!] "Values to reduce and join"
] [
if empty? block: reduce block [return block]
joined: either series? first block [copy first block] [to string! first block]
foreach val next block [append joined val]
joined
]
But we have to consider breaking code as well. In this case I can't guess how much depends on the current behavior, and feel fairly safe if we decide to change it. But this also falls into design chat on join/combine
in this space.
spec'ing expected results would be a good plan for this
I'd start with examples from OP:
>> rejoin [[2 3][4 5]]
== [2 3 4 5] ; not: [2 3 [4 5]]
>> rejoin [quote (2 3) quote (4 5)]
== (2 3 4 5) ; not: (2 3 (4 5))
>> p: rejoin [quote a/b quote c/d]
== a/b/c/d
>> a: [b [c [d 10]]]
== [b [c [d 10]]]
>> get p
== 10 ; not: none
>> to block! p
== [a b c d] ; not: [a b c/d]
This seems nice and predictable but how would one make it output a string (primary use case)?
a: [b [c [d 10]]]
Same as now I suppose, by putting a string as the first value in the block. Or any non-block value for that matter.
But we should look at this vs repend
as well. As Boris notes, building strings is the primary use case, but I imagine a lot of us have code that builds blocks with it as well. Also handy for building paths, given a root path.
Old join/combine
idea: https://gist.github.com/greggirwin/24c022cb5dde5771531a8939309ccb43
I have an updated version with /only/case/exclude
thoughts.
I tried
rejoin
on some different combinations of values, and it gives some unexpected results for me, given a description, that it "joins a block of values":I'd expect it to work like that:
And there is also a strange behavior with paths: