Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Oct 20 2019 22:59
    @dockimbel banned @SmackMacDougal
  • Dec 03 2017 05:53
    @PeterWAWood banned @matrixbot
  • Sep 28 2016 12:19
    @PeterWAWood banned @TimeSeriesLord
  • Aug 13 2016 03:23
    @PeterWAWood banned @Vexercizer
Gregg Irwin
@greggirwin
@9214, I was looking for old examples, and this would maybe be good to add to the closure wiki page, because outer contexts are not available for uses cases like you describe. For that, we will probably use a closure mechanism.
nedzadarek
@nedzadarek
@9214 stupid idea: cant you just use stack/tree of contexts? So funA [funB [funC []]]: funA knows his own context, funB knows context of funA and his own context, funC knows context of: funA, funB and his own context.
Vladimir Vasilyev
@9214
@nedzadarek you'll need to extend such tree with new context each time the new argument is captured, too much overhead I guess.
Gregg Irwin
@greggirwin

Function contexts only exist while they are being evaluated. In this example, you are not evaluating the inner funcs while the outer func is active.

https://github.com/red/red/wiki/Guru-Meditations#function-contexts

nedzadarek
@nedzadarek
Of course you would have too keep it alive.
Vladimir Vasilyev
@9214
@greggirwin perhaps @nedzadarek meant explicitly creating object!s with set-word!s as arguments and their values, then rebinding body of the next function, then returning it.
hiiamboris
@hiiamboris
>> specialize func [x y z][g: does [print [x y z]] g] [x: 1]
== func [y z][g: does [print [1 y z]] g]
what's unset here?
Vladimir Vasilyev
@9214
@nedzadarek but you can't keep it alive, that's not the point of currying and partial application.
Or first specialize it and substitute each occurrence of the new argument by its value, then return.
Though I'm not sure how viable it is.
nedzadarek
@nedzadarek
@9214 I mean funA has some context e.g. cA: context [x: 1] (so every x is bound to cA context). In funB you bind every x to cA and other variables to cB... and so on

but you can't keep it alive, that's not the point of currying and partial application.

but you have to keep variables alive, right? So, for example you have too keep x till no other inner function use it.

hiiamboris
@hiiamboris
>> specialize func [x y z][loop 5 [print x: x + 1]] [x: 1]
== func [y z][loop 5 [print 1 1 + 1]]
:D
why not just prepend x: 1 to the body of returned func and remove it from spec and close the case...
Vladimir Vasilyev
@9214
@nedzadarek yes, for that anonymous contexts or specializing proposed by @greggirwin is a way to go, I think.
nedzadarek
@nedzadarek
@9214 then I need to study it with fresh mind (sorry, it's night here)
Vladimir Vasilyev
@9214
@nedzadarek sure, it's night here too ;)
@hiiamboris except that your x is now leaking into global context
hiiamboris
@hiiamboris
hmm okay, add it to /locals then
nedzadarek
@nedzadarek
@hiiamboris other function can use x and every one would use different x(assuming /local x)
Vladimir Vasilyev
@9214
And it will last only for the next function, in the worst-case scenario you need to prepend x: 1 to each and every nested body.
And change /local part.
hiiamboris
@hiiamboris
=( I don't understand... can you make a quick example?
Vladimir Vasilyev
@9214
I don't understand it either, and it's 4:30 AM here.
nedzadarek
@nedzadarek
@9214 it's morning not night ;)
hiiamboris
@hiiamboris
oh I think I see what you mean, that next specialize invocation will have to read that x: 1 and append y: 2 to it
but it can read that, right? if it prepends it in the form set [vars] [values], this form stands
Vladimir Vasilyev
@9214
@hiiamboris kinda like that, yes, you then need to store/update those arg/value blocks somewhere, populate bodies on each invocation with them, and change /local ... in specs.
@nedzadarek night is in my mind. :zzz:
hiiamboris
@hiiamboris
can store them at the start of the body, why not?
func [x y z][loop 5 [print x: x + 1]]
x=1 => func [y z /local x][set [x][1] loop 5 [print [x: x + 1]]
y=2 => func [z /local x y][set [x y][1 2] loop 5 [print [x: x + 1]]
z=3 => func [/local x y z][set [x y z][1 2 3] loop 5 [print [x: x + 1]]
Vladimir Vasilyev
@9214
@hiiamboris it's the other way around - you apply function to one argument and it returns you func [y][...] with other nested functions inside it.
But x value should be preserved somehow, so that those nested functions are able to access it. Same with other arguments.
And this is what closure does - it references a variable in the scope where it was defined.
Localization is an interesting approach, I didn't think about that much.
hiiamboris
@hiiamboris
what if specialize returned a wrapper to itself until there's no more arguments to apply?
Vladimir Vasilyev
@9214
I'd rather wrap myself in a blanket now.
hiiamboris
@hiiamboris
;)
nedzadarek
@nedzadarek

@9214

you apply function to one argument and it returns you

Well... I need some sleep

hiiamboris
@hiiamboris
to clarify the point above:
spec(x0,f(x,y,z)) when called returns spec(y0,f(y,z,x=x0)), and the new one => f(z,x=x0,y=y0)
so you only have to call spec() once on a normal function to construct a currying variant, and then each call just adds an argument until there's only one argument remains and the function itself is returned
it's all great in theory though, but in practice a returned function will be just data (it won't accept arguments yet), so you'll need an operator (or do reduce [..]) to call it
hiiamboris
@hiiamboris
@9214 as a master bindologist, might you have any insight on the following performance data?
x: 1
....
0:00:00.442000001 [get in context? 'x 'x]
0:00:00.238000001 [get bind 'x context? 'x]
Gregg Irwin
@greggirwin
@hiiamboris, bind and in do their work differently, as you can see in the R/S code. We'd have to profile the internals to see what's slower, aside from obvious overhead of extra func calls between find-word/bind-word. Doc might say, but he's busy.
Nenad Rakocevic
@dockimbel
@hiiamboris in requires a stack slot copy while bind just modifies the first argument slot on stack, and re-use it as returned value. The incurred overhead exists because such copy boils down to an expensive memcpy(), which could be replaced in a future (once we start working on optimizations) by a simple read/write using an SSE 128-bit wide register. Once such optimization is done, the difference should become insignificant.
hiiamboris
@hiiamboris
hmm.. interesting, thank you @dockimbel !
Vladimir Vasilyev
@9214
Guh, I'm late :(
@hiiamboris my answer would the basic version of @dockimbel's - bind modifies context pointer in slot and returns it, while in allocates an extra copy, so as to avoid modification of the original word (I guess?).
lepinekong
@lepinekong_twitter
@toomasv I can't find composite in help ?
Toomas Vooglaid
@toomasv
@lepinekong_twitter :point_up: April 6, 2018 1:14 AM
lepinekong
@lepinekong_twitter
I feel frustrated: why this basic switch doesn't work :smile:
type: word!; 

probe type? type ; datatype!
probe type? word! ; datatype!
probe (type = word!); true

switch type [

    unset! [
        print "unset!"
    ] 
    word! string! file! url! block! [
        print "word! string! file! url! block!"
    ]
]
Vladimir Vasilyev
@9214
@lepinekong_twitter switch type?/word
lepinekong
@lepinekong_twitter
@toomasv ah ok thanks I didn't remember