Skip to content

Instantly share code, notes, and snippets.

@hiiamboris
Last active February 22, 2023 18:49
Show Gist options
  • Save hiiamboris/c82b5ee7250bab09fcee0289321a199e to your computer and use it in GitHub Desktop.
Save hiiamboris/c82b5ee7250bab09fcee0289321a199e to your computer and use it in GitHub Desktop.
Could INTO be a separate function without breaking the language semantics and/or vastly complicating the interpreter?
Red [title: "An experiment with INTO separation"]
; do %/d/devel/red/common/with.red
buffers*: []
into: func [buffer [series!]] [append/only buffers* buffer exit]
collect': function [code [block!]] [
also buffer: any [
take/last buffers*
make [] 10
]
do code
]
keep: function [value [any-type!] /only] bind [
either only [append/only buffer :value][append buffer :value]
:value
] :collect'
; keep: function [value [any-type!] /only] with :collect' [
; either only [append/only buffer :value][append buffer :value]
; :value
; ]
compose': function [block [block!]] [
head compose/into block tail any [
take/last buffers*
clear copy block
]
]
test: func [code] [prin [mold/only code "^-=> "] probe do code]
test [collect' [keep [1 2 3] keep keep 4]]
test [into [a b c] collect' [keep [1 2 3] keep keep 4]]
test [into [a b c] compose' [(1 + 3) (2 * 4)]]
test [into [a b c] collect' [keep [1 2 3] keep compose' [(1 + 3) (2 * 4)]]]
test [into [-] collect' [
into [a b c]
into [d e f] keep compose' [(1 + 3) (2 * 4)]
keep compose' [(3 * 3) (2 ** 4)]
keep compose' [(10 * 10)]
]]
@hiiamboris
Copy link
Author

hiiamboris commented Feb 21, 2023

Output:

collect' [keep [1 2 3] keep keep 4] 	=> [1 2 3 4 4]
into [a b c] collect' [keep [1 2 3] keep keep 4] 	=> [a b c 1 2 3 4 4]
into [a b c] compose' [(1 + 3) (2 * 4)] 	=> [a b c 4 8]
into [a b c] collect' [keep [1 2 3] keep compose' [(1 + 3) (2 * 4)]] 	=> [a b c 1 2 3 4 8]
into [-] collect' [
    into [a b c] 
    into [d e f] keep compose' [(1 + 3) (2 * 4)] 
    keep compose' [(3 * 3) (2 ** 4)] 
    keep compose' [(10 * 10)]
] 	=> [- d e f 4 8 a b c 9 16 100]

@dockimbel
Copy link

So the accumulating buffer becomes fixed and global? That's really not desirable.

@hiiamboris
Copy link
Author

So the accumulating buffer becomes fixed and global? That's really not desirable.

Agreed. It's also exploitable, as user code might affect the code that called it. This example is to provoke thoughts in others :)

What I would like to have ideally is into buffer affecting only the next expression after it, but that's not possible without some kind of thunks, is it? into buffer expression evaluates expression before it enters into and can assign the buffer to anywhere.

into buffer [expression in a block] is less readable, and has bigger problems if block contains more than one expression:

  • if only first expression uses the buffer, it just looks misleading
  • if all expressions use the buffer, user will have to explicitly reset it (e.g. with into []) when he doesn't want other expressions to use it (it becomes very messy)

I could solve it with a macro: under the hood put everything after into buffer into a separate block argument, but only let the first expression use the buffer. Will be readable, but will trap exit/return and will mess up error reports a lot.

So I don't see a perfect solution yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment