APPLY II: The Revenge!

I'd said "It's time to bring back APPLY".

...and by "it's time" I apparently meant "within the next year, maybe?"...

But better late than never, right? It's in!

Refinements Can be Provided In Any Order

[a b c d e d e] = apply append/ [[a b c] [d e] dup: 2]
[a b c d e d e] = apply append/ [dup: 2 [a b c] [d e]]
[a b c d e d e] = apply append/ [[a b c] dup: 2 [d e]]

[a b c d d] = apply append/ [dup: 2 [a b c] [d e] part: 1]
[a b c d d] = apply append/ [[a b c] [d e] part: 1 dup: 2]

Any Parameter (Not Just Refinements) Can Be Used By Name

Once a parameter has been supplied by name, it is no longer considered for consuming positionally.

[a b c d e] = apply append/ [series: [a b c] value: [d e]]
[a b c d e] = apply append/ [value: [d e] series: [a b c]]

[a b c d e] = apply append/ [series: [a b c] [d e]]
[a b c d e] = apply append/ [value: [d e] [a b c]]

Commas Are Ok So Long As They Are Interstitial

[a b c d e d e] = apply append/ [[a b c], [d e], dup: 2]
[a b c d e d e] = apply append/ [dup: 2, [a b c] [d e]]

>> apply :append [dup:, 2 [a b c] [d e]]
** Script Error: end was reached while trying to set dup:

Giving Too Many Arguments Defaults To An Error

>> apply append/ [[a b c] [d e] [f g]]
** Script Error: Too many values in processed argument block of APPLY.

If you want, you can ask it to :RELAX

>> apply:relax append/ [[a b c] [d e] [f g]]
== [a b c [d e]] 

SET-WORD Must Be Followed By A Non-SET-WORD

>> apply append/ [dup: part: 1 [a b c] [d e]]
** Script Error: end was reached while trying to set dup:

But you can pass SET-WORD as arguments to refinements...just use a quote! (or a $ if you want to bind it)

>> tester: func [:refine [any-value!]] [refine]

>> apply tester/ [refine: 'ta-da!:]
== ta-da!:

No-Arg Refinements Permit OKAY and NULL

Remember: the EVAL FRAME! mechanics do not change anything. So if a refinement doesn't take an argument, the only legal values for that refinement in the frame are OKAY and NULL.

>> testme: func [:refine] [refine]

>> apply testme/ [refine: okay]
== \~okay~\  ; antiform

>> apply testme/ [refine: null]
== \~null~\  ; antiform

>> apply testme/ [refine: 1020]
** Error: No-Arg refinements can only be ~okay~ and ~null~ antiforms

^META Arguments Are Accounted For

APPLY detects when a parameter is meta and handles it for positional arguments:

>> non-detector: func [arg] [arg]  ; not a meta argument, no unstable antiforms

>> apply non-detector/ [pack [10 20]]
== 10

>> detector: func [^arg] [^arg]  ; unstable antiforms allowed

>> apply detector/ [pack [10 20]]
== \~['10 '20]~\  ; antiform

I know not everyone has gotten their heads around isotopes yet, but they are critical... this stuff was the missing link to making it all gel.

:dizzy: :dizzy: :dizzy:

2 Likes

6 posts were split to a new topic: Naming The Infix APPLY Operator

A post was split to a new topic: Critiquing Red's Updated APPLY Implementation

And now APPLY has an infix shorthand...

Meet The // Operator!

The choice to use slashes for the operator became obvious, now that /WORD Runs Functions

>> append // [[a b c] <d> dup: 2]
== [a b c <d> <d>]

>> append // [dup: 2 [a b c] spread [e f]]
== [a b c e f e f]

>> append:dup // [[a b c] [e f] 2]
== [a b c [e f] [e f]]

It's strange but also it's a mixture of heavy and light, as a kind of "joiner" or concatenator, almost as if you were sticking the things together into a single thought.

append//[[a b c] <d> dup: 2]

I know it's not perfect, but nothing will be. I don't like an APPLY operator that sits to the left and quotes:

apply append [[a b c] <d> dup: 2]  ; !!! bad

Because that makes it look too much like the BLOCK! is the first argument to APPEND. So you really have to do APPLY with an inert form:

apply get $append [[a b c] <d> dup: 2]

apply append/ [[a b c] <d> dup: 2]

So if quoting is in play, there has to be something learnable and infix to jolt the flow. I've tried a lot of things at this point, this feels like the logical conclusion.

append // [[a b c] <d> dup: 2]
1 Like