There's also a concern of in what sequence the results are inserted: in the code
>> x: [] collect/into [loop 5 [parse [3] [(keep 1 append x 2) collect into x keep skip]]] x
== [3 3 3 3 3 1 2 1 2 1 2 1 2 1 2]
the result will depend strongly on the implementation of each insertion operation.
I think append
at the core of keep
is easiest to reason about and implement, and keeps one safe from forgetting to provide series tail to collect/into
. Isn't that the complexity reduction we're all striving for? ;)
@loziniak
It's sad because you sometimes have to work with callbacks, when you want to use C library that uses them.
R/S has no issue passing callbacks to imported functions from external C libraries. Such feature is used in many places in the Red's runtime library souce code.
Between R/S functions, passing a pointer!
instead of a function!
, then casting it to a function!
works fine.
r: make object! [
a: [1 2 3]
b: [4 5 6]
on-deep-change*: func [owner word target action new index part][
print ['on-deep-change* tab word]
]
on-change*: func [word old new][
print ['on-change* tab word]
]
]
reverse/part r/a 2
r/a: [3 2 1] ; <-- set field to a new series which object does not 're-owns'
reverse/part r/a 2 ; I expect this to fire on-deep-change*, but since new series is not owned by an object...
reactor!
or deep-reactor!
instead, which provide general event handlers for that: https://github.com/red/red/blob/master/environment/reactivity.red#L30 (you can also extract the relevant lines from there and build your own event handler, and bypass the reactive stuff to improve performance).
own new
function inside -change*
or something like that.
omg.. I'm at a loss guys
collect1: :collect
collect2: func spec-of :collect body-of :collect
profile/count/show [
[collect1 [repeat i 10 [keep i]]]
[collect2 [repeat i 10 [keep i]]]
] 10000
Count: 10000
Time | Time (Per) | Memory | Code
0:00:00.138 | 0:00:00 | 8978432 | [collect1 [repeat i n [keep i]]]
0:00:00.214 | 0:00:00 | 11243520 | [collect2 [repeat i n [keep i]]]
is magick at work here?
>> profile/count/show [[collect [repeat i 10 [keep i]]][collect1 [repeat i 10 [keep i]]][collect2 [repeat i 10 [keep i]]]] 10000
Count: 10000
Time | Time (Per) | Memory | Code
0:00:00.123 | 0:00:00 | 8978432 | [collect [repeat i 10 [keep i]]]
0:00:00.131 | 0:00:00 | 8978432 | [collect1 [repeat i 10 [keep i]]]
0:00:00.184 | 0:00:00 | 11243520 | [collect2 [repeat i 10 [keep i]]]
>> profile/count/show [[collect [repeat i 10 [keep i]]][collect1 [repeat i 10 [keep i]]][collect2 [repeat i 10 [keep i]]]] 10000
Count: 10000
Time | Time (Per) | Memory | Code
0:00:00.123 | 0:00:00 | 8978432 | [collect1 [repeat i 10 [keep i]]]
0:00:00.125 | 0:00:00 | 6877184 | [collect [repeat i 10 [keep i]]]
0:00:00.183 | 0:00:00 | 11243520 | [collect2 [repeat i 10 [keep i]]]
>> profile/count/show [[collect [repeat i 10 [keep i]]][collect1 [repeat i 10 [keep i]]][collect2 [repeat i 10 [keep i]]]] 10000
Count: 10000
Time | Time (Per) | Memory | Code
0:00:00.122 | 0:00:00 | 6877184 | [collect1 [repeat i 10 [keep i]]]
0:00:00.123 | 0:00:00 | 8978432 | [collect [repeat i 10 [keep i]]]
0:00:00.195 | 0:00:00 | 11243520 | [collect2 [repeat i 10 [keep i]]]
@hiiamboris
moreover in all tests of compiled vs interpreted code I've tried - interpreted was faster by 20% or so ;)
That would be odd, I suspect something is flawed with your measurement method. Remember that blocks of code run by do
cannot be compiled (by design, as it's the way to invoke the interpreter).
@dockimbel cool! I didn't know we can reflect the source of compiled funcs.
And you're right, I was using loop N [do code]
since the compiler won't let me compile loop N code
, so that explains it all, thanks!
Just checked:
x: 0
f: does [x: x + 1]
t: [now/precise/time/utc]
t1: do t
loop 1000000 [f]
t2: do t
print t2 - t1
is really about 2x faster when compiled
collect
a bit with more magic :) Faster, less allocation-prone. Makes sense only for compiled code though or for small collections (n < 10) https://gist.github.com/hiiamboris/a624c3d767dfe4e4ed20f23bc96433ff
also
. Why not just body': body coll': coll' shoot :keep coll
?owner
the series/object? none
ing old
's owner works fine but when I try to modify
new series I get access violation
at the last line (reverse/part r/a 2
):r: make object! [
a: [1 2 3]
b: [4 5 6]
on-deep-change*: func [owner word target action new index part][
print ['on-deep-change* tab word]
]
on-change*: func [word old new][
print ['on-change* tab word]
unless all [block? :old block? :new same? head :old head :new][
if any [series? :old object? :old][modify old 'owned none]
if any [series? :new object? :new][modify new 'owned reduce [self word]]
]
]
]
reverse/part r/a 2
r/a: [3 2 1] ; <-- set field to a new series which object does not 're-owns'
reverse/part r/a 2
named-func: func [_func-name spec body] [func spec bind body context [func-name: _func-name] ]
foo: named-func 'foo [a b] [probe a + b probe func-name]
foo 2 3
; 5
; foo
set
so you don't have to repeat yourself (foo: named-func 'foo
):named-func2: func [_func-name spec body] [set _func-name func spec bind body context [func-name: _func-name] ]
named-func2 'qux [a b] [probe a + b probe func-name]
qux 2 3
; 5
; qux
>> foo: has [dummy][print pick find body-of system/words context? 'dummy -1]
== func [/local dummy][print pick find body-of system/words context? 'dummy -1]
>> foo
foo
system/words
to be more flexible.