Skip to content

Instantly share code, notes, and snippets.

@GiuseppeChillemi
Last active January 17, 2021 06:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GiuseppeChillemi/93febe44dffd5dfae764b3cd6ad86988 to your computer and use it in GitHub Desktop.
Save GiuseppeChillemi/93febe44dffd5dfae764b3cd6ad86988 to your computer and use it in GitHub Desktop.
Show how relative paths works on containers
Red [
Name: "Power Selector"
Purpose: "Demostrate the working scenario of relative paths"
Notes: {
Idea: Giuseppe Chillemi
Path operator: Toomas Vooglaid
}
]
;---- Create the new "///" operator
path: function [a b][to path! append to block! a to block! b]
///: make op! :path
;------------
;The list of relative accessors
mystruct: [
name: heading/name
size: heading/size
body: body
extra: extra
authors: extra/authors
]
;Now we create 2 contaniers having the same structure
; the second one is the previous version of the first one
software-list: [
[
heading [name "Red" size 1200]
body ["The new merging Full-stack language"]
extra [
authors [
"Nenad Rakočević"
"Quingtian"
"Greg Irvin"
"Valdimir Valiliev"
"Boleslav Březovský"
"Hiiamboris"
]
]
]
[
heading [name "Rebol" size 900]
body ["The Ancestor of our language"]
extra [
authors [
"Carl Sassenrath"
]
]
]
[
heading [name "REN-C" size 650]
body ["Experimental Rebol derived language" ]
extra [
authors [
"Hostile Fork"
]
]
]
]
software-list-Previous: [
[
heading [name "Red" size 1200]
body ["The new merging Full-stack language"]
extra [
Authors [
"Nenad Irvin"
]
]
]
]
; Here we print some elements of the strcuture of the following containers.
containers-to-print: [software-list software-list-Previous]
;The code loops the containers
foreach series containers-to-print [
print ["------- Container name: -------" series]
;All the records
repeat idx length? get series [
Print [
"Software name:" get series /// idx /// mystruct/name lf
"Size is:" get series /// idx /// mystruct/size
]
;And sub records
auth-temp: get series /// idx /// mystruct/authors
forall auth-temp [
print [" Author:" first auth-temp]
]
Print lf
]
Print lf
]
;--- Output: ------
comment {
------- Container name: ------- software-list
Software name: Red
Size is: 1200
Author: Nenad Rakočević
Author: Quingtian
Author: Greg Irvin
Author: Valdimir Valiliev
Author: Boleslav Březovský
Author: Hiiamboris
Software name: Rebol
Size is: 900
Author: Carl Sassenrath
Software name: REN-C
Size is: 650
Author: Hostile Fork
------- Container name: ------- software-list-Previous
Software name: Red
Size is: 1200
Author: Nenad Irvin
}
@Oldes
Copy link

Oldes commented Jan 14, 2021

Using something like:

resolve: func [path [block!] /local out][
	out: copy []
	forall path [append out to block! get path/1]
	get as path! out 
]

instead of:

path: function [a b][probe to path! append to block! a to block! b]

///: make op! :path

would be more efficient and imho I prefer to read:

auth-temp: resolve [series idx mystruct/authors]   

instead of:

auth-temp: get series /// idx /// mystruct/authors    	

@Oldes
Copy link

Oldes commented Jan 14, 2021

You can name it <== instead of resolve to make it shorter:-)

auth-temp: <==[series idx mystruct/authors] 

@GiuseppeChillemi
Copy link
Author

Good! Let's continue this exploration on relative path composition. I will try to stress mine adding calculated elements and a path dialect. I am 100% sure we will discover many creative ways of doing this thing.

@GiuseppeChillemi
Copy link
Author

Note: => is another good symbol combination !

@greggirwin
Copy link

I like resolve. It's a very clean and simple solution, and a good name.

@toomasv
Copy link

toomasv commented Jan 15, 2021

[resolve] would be more efficient ...

Not correct. Speed-wise, ops are more efficient than functions. Experiment:

;;Set-up
;Giuseppe
path: function [a b][to path! append to block! a to block! b]
///: make op! :path

;Oldes
resolve: func [path [block!] /local out][
	out: copy []
	forall path [append out to block! get path/1]
	get as path! out 
]

;Toomas
//: make op! func [a b][as path! append to block! a to block! b]

;------------

;The list of relative accessors
;Giuseppe & Oldes
mystruct: [
   name:  heading/name
   size:  heading/size
   body:  body
   extra: extra
   authors: extra/authors
]
;Toomas
struct: context [
   name:  'heading/name
   size:  'heading/size
   body:  'body
   extra: 'extra
   authors: 'extra/authors
]

;;Adapted funcs (printing eliminated, containers as originally)
Giuseppe: func [][
	foreach series containers-to-print [
		repeat idx length? get series [
			"Software name:" get series /// idx /// mystruct/name
			"Size is:" get series /// idx /// mystruct/size
			auth-temp: get series /// idx /// mystruct/authors    	
			forall auth-temp [
				"       Author:" first auth-temp
			]
		]
	]
]
Oldes: func [][
	foreach series containers-to-print [
		repeat idx length? get series [
			"Software name:" resolve [series idx mystruct/name]
			"Size is:" resolve [series idx mystruct/size]
			auth-temp: resolve [series idx mystruct/authors]
			forall auth-temp [
				"       Author:" first auth-temp
			]
		]
	]
]
Toomas: func [][
	foreach series containers-to-print bind [
		repeat idx length? get series [
			software: series // idx
			"Software name:" get software // name
			"Size is:" get software // size
			auth-temp: get software // authors    	
			forall auth-temp [
				"       Author:" first auth-temp
			]
		]
	] struct
]

Profiling results:

>> recycle/off
>> profile/show/count [[Giuseppe][Oldes][Toomas]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.04   | 0:00:00      |     4220284 | [Toomas]
0:00:00.055  | 0:00:00      |     6048440 | [Giuseppe]
0:00:00.065  | 0:00:00      |     4032284 | [Oldes]
>> profile/show/count [[Giuseppe][Oldes][Toomas]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.042  | 0:00:00      |     4220284 | [Toomas]
0:00:00.053  | 0:00:00      |     6048440 | [Giuseppe]
0:00:00.061  | 0:00:00      |     4032284 | [Oldes]
>> profile/show/count [[Giuseppe][Oldes][Toomas]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.041  | 0:00:00      |     4220284 | [Toomas]
0:00:00.054  | 0:00:00      |     6048440 | [Giuseppe]
0:00:00.062  | 0:00:00      |     4032284 | [Oldes]
>> profile/show/count [[Giuseppe][Oldes][Toomas]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.039  | 0:00:00      |     4220284 | [Toomas]
0:00:00.053  | 0:00:00      |     6048440 | [Giuseppe]
0:00:00.061  | 0:00:00      |     4032284 | [Oldes]

@toomasv
Copy link

toomasv commented Jan 15, 2021

And this is even better:

get-path: func [block [block! hash! paren! object! map!] path [path! block!]][
	foreach i path [block: block/:i]
]
Toomas2: func [][
	foreach series containers-to-print bind [
		repeat idx length? get series [
			software: get series // idx
			"Software name:" get-path software name
			"Size is:" get-path software size
			auth-temp: get-path software authors    	
			forall auth-temp [
				"       Author:" first auth-temp
			]
		]
	] struct
]
>> profile/show/count [[Giuseppe][Oldes][Toomas][Toomas2]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.03   | 0:00:00      |      620596 | [Toomas2]
0:00:00.039  | 0:00:00      |     3116672 | [Toomas]
0:00:00.055  | 0:00:00      |     6050212 | [Giuseppe]
0:00:00.064  | 0:00:00      |     4032596 | [Oldes]

@toomasv
Copy link

toomasv commented Jan 15, 2021

And still better :)

context [
	//: make op! :get-path
	set 'Toomas3 does [
		foreach series containers-to-print bind [
			repeat idx length? series: get series [
				software: series/:idx
				"Software name:" software // name
				"Size is:" software // size
				auth-temp: software // authors    	
				forall auth-temp [
					"       Author:" first auth-temp
				]
			]
		] struct
	]
]
>> profile/show/count [[Giuseppe][Oldes][Toomas][Toomas2][Toomas3]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.022  | 0:00:00      |       44284 | [Toomas3]
0:00:00.031  | 0:00:00      |      620284 | [Toomas2]
0:00:00.04   | 0:00:00      |     3116284 | [Toomas]
0:00:00.053  | 0:00:00      |     6048440 | [Giuseppe]
0:00:00.064  | 0:00:00      |     4032284 | [Oldes]

@toomasv
Copy link

toomasv commented Jan 15, 2021

And, surprisingly, ultimate solution seems to be stepping back a bit:

context [
	//: make op! :get-path
	set 'Toomas4 does [
		foreach series containers-to-print [
			repeat idx length? series: get series [
				"Software name:" series/:idx // mystruct/name
				"Size is:" series/:idx // mystruct/size
				auth-temp: series/:idx // mystruct/authors    	
				forall auth-temp [
					"       Author:" first auth-temp
				]
			]
		] 
	]
]
>> profile/show/count [[Giuseppe][Oldes][Toomas][Toomas2][Toomas3][Toomas4]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.022  | 0:00:00      |         284 | [Toomas4]
0:00:00.024  | 0:00:00      |       44284 | [Toomas3]
0:00:00.029  | 0:00:00      |      620284 | [Toomas2]
0:00:00.04   | 0:00:00      |     3116284 | [Toomas]
0:00:00.055  | 0:00:00      |     6048440 | [Giuseppe]
0:00:00.062  | 0:00:00      |     4032284 | [Oldes]

@greggirwin
Copy link

I love naming the tests this way. Will try to review the code later.

@GiuseppeChillemi
Copy link
Author

GiuseppeChillemi commented Jan 15, 2021

It is becoming a Toomas VS Toomas battle, as Computer VS Computer chess games. I hope there are enough computing resources and stack space in yourself otherwise, you could generate an error!

@toomasv
Copy link

toomasv commented Jan 16, 2021

Sorry! Got excited. Going away.

@GiuseppeChillemi
Copy link
Author

GiuseppeChillemi commented Jan 16, 2021

Toomas, when I have looked at all the solutions you have been able to create, I have thought about you as a supreme computer fighting against itself to create the best possible one. The observation must be read as my admiration for your incredible coding and combinatorial skills. Especially, the last solution has raised many questions to me about the very low amount of memory used if compared to the others:

0:00:00.022 | 0:00:00 | 284 | [Toomas4]

EDIT: it should be someone else to say this but it is fantastic when you are excited!!! :-D

@greggirwin
Copy link

It is becoming a Toomas VS Toomas battle

This made me laugh. I like it. When any of get excited by an idea it can help to run with it and see where it goes. Getting into a state of flow, and understanding a problem in order to think more deeply about it is 90% of the battle. That's what makes working quickly so powerful.

@greggirwin
Copy link

The memory pressure reduction comes from not binding the block to the context every time.

@GiuseppeChillemi
Copy link
Author

It's huge, about 21.200 times. Which block is being bound so often to generate such memory consumption?

@toomasv
Copy link

toomasv commented Jan 16, 2021

:)
Oldes' resolve can be restructured in a somewhat similar way to get-path:

resolve2: func [block [block!] path [block! path!]][
	forall path [
		block: either any-block? path/1 [
			resolve2 block path/1
		][
			block/(path/1)
		]
	]
]

And main procedure reformulated as

Oldes2: does [
	foreach series containers-to-print [
		repeat idx length? series: get series [
			;print [
				"Software name:" resolve2 series/:idx mystruct/name
			;] print [
				"Size is:" resolve2 series/:idx mystruct/size
			;]
			auth-temp: resolve2 series/:idx mystruct/authors
			forall auth-temp [
				;print [
					"       Author:" first auth-temp
				;]
			]
		]
	]
]

with similar results:

>> profile/show/count [[Oldes2][Toomas4]] 1000
Count: 1000
Time         | Time (Per)   |      Memory | Code
0:00:00.021  | 0:00:00      |         284 | [Toomas4]
0:00:00.038  | 0:00:00      |         596 | [Oldes2]

@toomasv
Copy link

toomasv commented Jan 17, 2021

Ah, sorry, resolve2 doesn't work this way.

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