Skip to content

Instantly share code, notes, and snippets.

@hiiamboris
Last active May 17, 2023 08:33
Show Gist options
  • Save hiiamboris/4cc8923304f60ef425fd5b71060b3219 to your computer and use it in GitHub Desktop.
Save hiiamboris/4cc8923304f60ef425fd5b71060b3219 to your computer and use it in GitHub Desktop.
interesting `apply` scenarios gathered in one place for comparison

unordered key/value pairs with word shortcuts (original mezz impl):

	apply parse [case part length  input: series rules: =rule=]

path + args + k/v pairs (hybrid):

	apply 'parse/:case/:part [series =rule= length]

operands then refinements (reduced k/v syntax):

	apply parse [series =rule=  case: case  part: part length]

op-ref-2 (operands then refinements 2):

	apply parse [series =rule=  /case case  /part part length]

a.1 (path with get-words)

	parse/:case/:part series =rule= length

https://codeberg.org/hiiamboris/red-common/src/commit/f4928e2145ca1c71e27b5e3ed23853c3ea447d6a/new-each.red#L407

unordered key/value pairs with word shortcuts (original mezz impl):

	apply for-each [spec series case same code  reverse: back]

path + args + k/v pairs (hybrid):

	apply/with 'for-each/:case/:same [spec series code] [reverse: back]

operands then refinements (reduced k/v syntax):

	apply for-each [
		spec series code
		case: case
		same: same
		reverse: back
	]

op-ref-2 (operands then refinements 2):

	apply for-each [
		spec series code
		/case case
		/same same
		/reverse back
	]

a.1 (path with get-words)

	reverse: back
	for-each/:case/:same/:reverse spec series code

https://codeberg.org/hiiamboris/red-common/src/commit/f4928e2145ca1c71e27b5e3ed23853c3ea447d6a/new-each.red#L429

unordered key/value pairs with word shortcuts (original mezz impl):

	apply map-each [spec series case same code  self: drop: yes]

path + args + k/v pairs (hybrid):

	apply 'map-each/:case/:same/self/drop [spec series code]

operands then refinements (reduced k/v syntax):

	apply map-each [
		spec series code
		case: case
		same: same
		self: yes
		drop: yes
	]

op-ref-2 (operands then refinements 2):

	apply map-each [
		spec series code
		/case case
		/same same
		/self yes
		/drop yes
	]

a.1 (path with get-words)

	map-each/self/drop/:case/:same spec series code

https://codeberg.org/hiiamboris/red-spaces/src/commit/7ce7517d78a8061cc9980a988657229af32a52ee/auxi.red#L711

original:

	either side = 'left									;@@ use apply 
		[reproject    frame/x1D->x1D' x-1D]
		[reproject/up frame/x1D->x1D' x-1D]

unordered key/value pairs with word shortcuts (original mezz impl):

	apply reproject [
		fun: frame/x1D->x1D'
		x:   x-1D
		up:  side = 'left
	]

path + args + k/v pairs (hybrid):

	apply/with 'reproject [frame/x1D->x1D' x-1D] [up: side = 'left]

operands then refinements (reduced k/v syntax):

	apply reproject [frame/x1D->x1D' x-1D  up: (side = 'left)]

op-ref-2 (operands then refinements 2):

	apply reproject [frame/x1D->x1D' x-1D  /up side = 'left]

a.1 (path with get-words)

	up: side = 'left
	reproject/:up frame/x1D->x1D' x-1D

https://codeberg.org/hiiamboris/red-spaces/src/commit/7ce7517d78a8061cc9980a988657229af32a52ee/traversal.red#L166

original:

	loop: pick [										;@@ use apply
		foreach-*ace/next
		foreach-*ace/next/reverse
	] dir = 'forth 
	do compose/only [
		(loop) path found: focused [..code..]			;-- default to already focused item (e.g. it's the only focusable)
	]

unordered key/value pairs with word shortcuts (original mezz impl):

	apply foreach-*ace [
		spec:    path
		path:    (found: focused)
		code:    [..code..]
		reverse: dir = 'forth
		next:    on
	]

path + args + k/v pairs (hybrid):

	apply/with 'foreach-*ace/next [path found: focused [..code..]] [
		reverse: dir = 'forth
	]

operands then refinements (reduced k/v syntax):

	apply foreach-*ace [
		path (found: focused) [..code..]
		reverse: (dir = 'forth)
		next:    on
	]

op-ref-2 (operands then refinements 2):

	apply foreach-*ace [
		path (found: focused) [..code..]
		/reverse dir = 'forth
		/next    on
	]

a.1 (path with get-words)

	reverse: dir = 'forth					;-- blocks usage of reverse native should it be needed in the `code`
	reverse': :system/words/reverse			;-- workaround
	foreach-*ace/:reverse/next path (found: focused) [..code..] 

https://codeberg.org/hiiamboris/red-spaces/src/commit/7ce7517d78a8061cc9980a988657229af32a52ee/rendering.red#L189

unordered key/value pairs with word shortcuts (original mezz impl):

	apply render-space [
		space crude
		window: on  xy1 xy2
		on: on  canvas fill-x fill-y
	]

path + args + k/v pairs (hybrid):

	apply 'render-space/window/on/:crude [space xy1 xy2 canvas fill-x fill-y]

operands then refinements (reduced k/v syntax):

	apply render-space [
		space 
		crude:  crude
		window: on  xy1 xy2
		on:     on  canvas fill-x fill-y
	]

op-ref-2 (operands then refinements 2):

	apply render-space [
		space 
		/crude  crude
		/window on  xy1 xy2
		/on     on  canvas fill-x fill-y
	]

a.1 (path with get-words)

	window: on
	render-space/:crude/:window/:on space xy1 xy2 canvas fill-x fill-y

https://codeberg.org/hiiamboris/red-view-test-system/src/commit/571f9d8e0725120e29d3c5afac07c0c40c53ece1/testing.red#L525

original unordered key/value pairs with word shortcuts (original mezz impl):

	apply test-issue [title: key  no-review: not show-every/data]

path + args + k/v pairs (hybrid):

	apply/with 'test-issue [key] [no-review: not show-every/data]

operands then refinements (reduced k/v syntax):

	apply test-issue [key  no-review: (not show-every/data)]

op-ref-2 (operands then refinements 2):

	apply test-issue [key  /no-review not show-every/data]

a.1 (path with get-words)

	no-review: not show-every/data
	test-issue/:no-review key

original unordered key/value pairs with word shortcuts (original mezz impl):

	apply view [
		spec: main-window
		flags: options: yes
		flgs: [resize]
		opts: [...]
		no-wait: system/console/gui?
	]

path + args + k/v pairs (hybrid):

	apply/with 'view/flags/options [main-window [resize] [...]] [
		no-wait: system/console/gui?
	]

operands then refinements (reduced k/v syntax):

	apply view [
		main-window
		flags:   yes [resize]
		options: yes [...]
		no-wait: system/console/gui?
	]

op-ref-2 (operands then refinements 2):

	apply view [
		main-window
		/flags   yes [resize]
		/options yes [...]
		/no-wait system/console/gui?
	]

a.1 (path with get-words)

	no-wait: system/console/gui?
	view/flags/options/:no-wait main-window [resize] [...]

original unordered key/value pairs with word shortcuts (original mezz impl):

	view-path: apply view [
		no-wait: yes
		spec:    layout
		tight:   tight
		options: with  opts: opts
		flags:   flags flgs: flgs
	]

can be shortened to (but it makes it worse):

	view-path: apply view [
		flags flgs opts tight
		no-wait: yes
		spec:    layout
		options: with  
	]

path + args + k/v pairs (hybrid):

	view-path: apply/with 'view/no-wait/:tight/:flags [layout flgs] [
		options: with opts: opts
	] 

operands then refinements (reduced k/v syntax):

	view-path: apply view [
		layout
		no-wait: yes
		tight:   tight
		options: with  opts
		flags:   flags flgs
	]

op-ref-2 (operands then refinements 2):

	view-path: apply view [
		layout
		/no-wait yes
		/tight   tight
		/options with  opts
		/flags   flags flgs
	]

a.1 (path with get-words)

	options: with
	view-path: view/no-wait/:tight/:options/:flags layout opts flgs

https://codeberg.org/hiiamboris/red-view-test-system/src/commit/571f9d8e0725120e29d3c5afac07c0c40c53ece1/testing.red#L283

original unordered key/value pairs with word shortcuts (original mezz impl):

	top-window: apply display [layout tight with opts]

path + args + k/v pairs (hybrid):

	top-window: apply 'display/:tight/:with [layout opts]

operands then refinements (reduced k/v syntax):

	top-window: apply display [layout  tight: tight  with: with opts]

op-ref-2 (operands then refinements 2):

	top-window: apply display [layout  /tight tight  /with with opts]

a.1 (path with get-words)

	display/:tight/:with layout opts

https://codeberg.org/hiiamboris/red-view-test-system/src/commit/571f9d8e0725120e29d3c5afac07c0c40c53ece1/visuals.red#L91

original unordered key/value pairs with word shortcuts (original mezz impl):

	img: apply capture-face [
		face:  layout
		real:  real
		with:  not real  img: img
		whole: whole
	]

can be shortened to (but unlikely easier to read):

	img: apply capture-face [
		real whole img
		face:  layout
		with:  not real
	]

path + args + k/v pairs (hybrid):

	img: apply/with 'capture-face/:real/:whole [layout] [
		with: not real  img: img
	]

operands then refinements (reduced k/v syntax):

	img: apply capture-face [
		layout
		real:  real
		with:  (not real) img
		whole: whole
	]

op-ref-2 (operands then refinements 2):

	img: apply capture-face [
		layout
		/real  real
		/with  not real img
		/whole whole
	]

a.1 (path with get-words)

	with: not real							;-- blocks usage of `with` function in the calling function's body
	with': :system/words/with				;-- workaround
	img: capture-face/:real/:with/:whole layout img

unordered key/value pairs with word shortcuts (original mezz impl):

	apply find [case same only part length  series: pos value: :pattern]

path + args + k/v pairs (hybrid):

	apply 'find/:case/:same/:only/:part [pos :pattern length]

operands then refinements (reduced k/v syntax):

	apply find [
		pos :pattern 
		case: case
		same: same
		only: only
		part: part length
	]

op-ref-2 (operands then refinements 2):

	apply find [
		pos :pattern 
		/case case
		/same same
		/only only
		/part part length
	]

a.1 (path with get-words)

	find/:case/:same/:only/:part pos :pattern length

unordered key/value pairs with word shortcuts (original mezz impl):

	apply find [case same only part length  series: pat-pos value: :pattern tail: true]

path + args + k/v pairs (hybrid):

	apply 'find/:case/:same/:only/:part/tail [pat-pos :pattern length]

operands then refinements (reduced k/v syntax):

	apply find [
		pat-pos :pattern  
		case: case 
		same: same
		only: only 
		part: part length
		tail: true
	]

op-ref-2 (operands then refinements 2):

	apply find [
		pat-pos :pattern  
		/case case 
		/same same
		/only only 
		/part part length
		/tail true
	]

a.1 (path with get-words)

	find/:case/:same/:only/:part/tail pat-pos :pattern length

https://codeberg.org/hiiamboris/red-common/src/commit/f4928e2145ca1c71e27b5e3ed23853c3ea447d6a/new-replace.red#L40

unordered key/value pairs with word shortcuts (original mezz impl):

	apply replace [pattern value once deep case same only part length  series: lst-pos/1]

hybrid (direct):

	apply 'replace/:part/:only/:case/:same/:deep/:once [lst-pos/1 length value]

hybrid (using #5):

	apply/with 'replace 'local [series: lst-pos/1]

operands then refinements (reduced k/v syntax):

	apply replace [
		lst-pos/1 pattern value
		once: once
		deep: deep
		case: case
		same: same
		only: only
		part: part length
	]

op-ref-2 (operands then refinements 2):

	apply replace [
		lst-pos/1 pattern value
		/once once
		/deep deep
		/case case
		/same same
		/only only
		/part part length
	]

a.1 (path with get-words)

	replace/:once/:deep/:case/:same/:only/:part lst-pos/1 pattern value length

https://gitlab.com/rebolek/castr/-/blob/master/client-tools.red#L361

unordered key/value pairs with word shortcuts (original mezz impl):

	response: apply send-request [
		method
		link:    url
		data:    post
		content: data
		with:    yes  args: compose/only [...]
	]

path + args + k/v pairs (hybrid):

	response: apply/with 'send-request/with [url method compose/only [...]] [
		data:    post 
		content: data
	] 

operands then refinements (reduced k/v syntax):

	response: apply send-request [
		method url
		data:    post data
		with:    yes  (compose/only [...])
	]

op-ref-2 (operands then refinements 2):

	response: apply send-request [
		method url
		/data    post data
		/with    yes  compose/only [...]
	]

a.1 (path with get-words)

	data2: data					;-- preserve data from being overridden
	data:  post
	send-request/:data/with method url data2 compose/only [...]
	data:  data2				;-- restore data for further usage

(/draw spec is user-defined)

original:

	spec:    spec-of :draw
	on?:     find spec /on
	window?: find spec /window
	code: case [
		all [on? window?] [[draw/window/on xy1 xy2 canvas fill-x fill-y]]
		window?           [[draw/window    xy1 xy2                     ]]
		on?               [[draw/on                canvas fill-x fill-y]]
		'else             [[draw                                       ]]
	]
	draw: do copy/deep code			;@@ workaround for #4854 - remove me!!

#3 (non-erroring implementation, maybe /quiet refinement):

	apply/quiet draw [window xy1 xy2 on canvas fill-x fill-y]

path + args + k/v pairs (hybrid):

	apply/quiet/with 'draw [] [
		window: window xy1: xy1 xy2: xy2
		on: on canvas: canvas fill-x: fill-x fill-y: fill-y
	]

operands then refinements (reduced k/v syntax):

	apply/quiet draw [
		window: window xy1 xy2
		on:     on canvas fill-x fill-y
	]

op-ref-2 (operands then refinements 2):

	apply/quiet draw [
		/window window xy1 xy2
		/on     on canvas fill-x fill-y
	]

a.1 (path with get-words)

	not applicable here - code will be the same as the original
@greggirwin
Copy link

greggirwin commented May 11, 2023

On /with chat

apply/with 'for-each/:case/:same [spec series code] [reverse: back]

could be

reverse: back
apply 'for-each/:case/:same/:reverse [spec series code]

apply/with 'reproject [frame/x1D->x1D' x-1D] [up: side = 'left]

could be

up: side = 'left
apply 'reproject/:up [frame/x1D->x1D' x-1D]

Boris noted that resetting the values after using them is the problem in his context. We don't have use from R2 in Red.

@greggirwin
Copy link

Use was not something I did a lot, but a few times. It's basically:

with: func [
	object [object! none!]
	body   [block!]
][
	do bind/copy body object
]
using: func [
	"Like USE, but combines the local words and their initial values in a spec block."
	spec [block!] "Spec-block format of words and values"
	body [block!] "Block to evaluate"
][
	with context spec body
]

Making the last example

using [up: side = 'left][
    apply 'reproject/:up [frame/x1D->x1D' x-1D]
]

@greggirwin
Copy link

greggirwin commented May 11, 2023

The context creation overhead is ~2-4x plus memory pressure (est.) for minimal bodies, but the more work your body does, the less the relative overhead.

@hiiamboris
Copy link
Author

bind/copy + new context (HUGE) + 2 more func calls will have the effect of mezz-level apply :)

@hiiamboris
Copy link
Author

by the way, my with covers your using case:

>> do with [x: 1] [context? 'x]
== make object! [
    x: 1
]

@greggirwin
Copy link

But suffers the same issues you complained about (overhead), right?

@hiiamboris
Copy link
Author

Of course.

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