World: r3wp
[!REBOL3 Schemes] Implementors guide
older newer | first last |
Pavel 13-Aug-2010 [2162] | Anyway many thanks Steve for hints! |
Andreas 13-Aug-2010 [2163] | You can also use the /seek and /part refinements to pass arguments to your READ actor. |
Steeve 13-Aug-2010 [2164] | My convention is to simulate the behavior of a standard block (I called my schemle virtual-block). So it's the main reason why I don't use read or write but copy/append instead |
Pavel 13-Aug-2010 [2165x2] | Seems the standard functions are overloaded somehow even when you writes your own, (because you want different functionality of course) aah deep lake, deep lake |
Steeve your virtual block is more persisten block isnt it? ;) | |
Steeve 13-Aug-2010 [2167x2] | true |
there are lot of rooms for improvement in my code, perhaps some day... | |
Pavel 13-Aug-2010 [2169x4] | OK I'll try to finish simple rif:// scheme and update rif.r in rebol.org thanks guys for hepl! Documentation should be improved in file schemes, there is almost nothink. |
nothing sorry | |
Another curriosity when I defined actors put/get when used port returns error message "no put actor" | |
Anyway when defined /seek refinement the sheme start to work as expected | |
Graham 13-Aug-2010 [2173x3] | I don't think you can define your own actors ... |
You're limited to the ones defined ... | |
When you use an actor like 'open, it checks to see if the actor is defined in the network scheme and invokes that. | |
Pavel 13-Aug-2010 [2176] | The functions Steeve mimick for his virtual block scheme are not originaly actors but works for him |
Graham 13-Aug-2010 [2177] | Let me rephrase that .. you can't define an actor if that word is already in use |
Pavel 13-Aug-2010 [2178] | What? that is exactly what Steeve does if I understand |
Graham 13-Aug-2010 [2179] | which actor is that? |
Pavel 13-Aug-2010 [2180] | the funtions defined in actor object aren't actually actors? |
Graham 13-Aug-2010 [2181x3] | ;** MISSING !!! native FOREACH has not port! as parameter |
so they can't be used actors | |
You can use them as local functions .. just not as actors | |
Steeve 13-Aug-2010 [2184] | the allowed actors are the function with port! as parameter |
Andreas 13-Aug-2010 [2185] | action!s, to be precise |
Graham 13-Aug-2010 [2186] | and if they don't take a port, you can't use them without redefining their behaviour |
Pavel 13-Aug-2010 [2187] | ok i'll try to understand :-( my scheme works used port: open rif:// ... read/seek port 1 but don't work the easy way: read rif://data/file 1, cant access locales |
Andreas 13-Aug-2010 [2188x2] | locales? |
you can easily make `read/seek rif://data/file 1` work, by creating a custom open? actor and using that in your read actor | |
Pavel 13-Aug-2010 [2190x2] | I use locales to stor opened files (I need two files ) |
Andreas any simple example of open? ? | |
Andreas 13-Aug-2010 [2192] | Assuming you store port-local state in port/state, you can simply check port/state for not being none. |
Pavel 13-Aug-2010 [2193] | isn't it the right way? : actor: [ open: func [port [port!] /local path ] [ parse port/spec/ref [thru #":" 0 2 #"/" path:] append port/spec compose [path: (to-file path)] port/locals: [] either (0 = length? port/locals) [ append port/locals open/seek rejoin [port/spec/path ".dat"] append port/locals open/seek rejoin [port/spec/path ".idx"] ][ port/locals/1 open/seek rejoin [port/spec/path ".dat"] port/locals/2 open/seek rejoin [port/spec/path ".idx"] ] return port |
Andreas 13-Aug-2010 [2194x2] | you'll most likley want `port/locals: copy []` |
but based on that, your open? actor would simply be: `open?: func [port [port!]] [not none? port/locals]` | |
Pavel 13-Aug-2010 [2196] | OK I'll try it |
Gregg 13-Aug-2010 [2197] | 0 = length? port/locals can be empty? port/locals |
Andreas 13-Aug-2010 [2198] | and in your read actor, you'll then simply do: either open? port [{read was invoked as `open rif:// + read`}] [{read was invoked directly as read rif://}] |
Pavel 13-Aug-2010 [2199x2] | >> read/seek rif://data/file 1 ** Script error: cannot access locals in path port/locals/2 ** Where: Get-RIF read ** Near: Get-RIF port number |
OK andreas | |
Andreas 13-Aug-2010 [2201x3] | Maybe also a simple `if not open? port [open port]` will suffice in your case. |
(Within the read actor.) | |
But typically you'll also want to add code to close the port again, afterwards. | |
Steeve 13-Aug-2010 [2204] | can't you paste the whole code somewhere ? |
Pavel 13-Aug-2010 [2205] | This automatic open close is not clear to me after Andreas there is no such automation? where is the magic? :-O |
Andreas 13-Aug-2010 [2206] | There is no magic. |
Pavel 13-Aug-2010 [2207] | Rebol [ file: %prot-rif.r title: "RIF protocol" author: "Pavel" rights: 'PD date: 13-Aug-2010 ] ;; Local functions Append-RIF: func [port [port!] record [binary!] ][ write/append port/locals/2 to-binary length? head port/locals/1 ;index port the end of data file will be beginning of new record write/append port/locals/1 record ;data port new record into data file return shift length? head port/locals/2 -3 ;number of records 8 bytes per record ] Get-RIF: func [ port [port!] i [integer!] /local numentry indexpos recpos recend value ][ numentry: shift length? head port/locals/2 -3 ;number of records 8 bytes per record if any [i = 0 i > numentry] [return none] ;numbering starts at 1 ends at file end indexpos: multiply subtract i 1 8 ;compute index offset recpos: to-integer read/seek/part port/locals/2 indexpos 8 either ( (8 * i) = length? head port/locals/2 ) [ ;last record special case recend: length? head port/locals/1 ][ recend: to-integer read/seek/part port/locals/2 add indexpos 8 8 ;internal record ] return read/seek/part port/locals/1 recpos subtract recend recpos ] ;; Scheme definition make-scheme [ name: 'rif title: "RIF Protocol" spec: make system/standard/port-spec-head [] awake: none actor: [ open: func [port [port!] /local path ] [ parse port/spec/ref [thru #":" 0 2 #"/" path:] append port/spec compose [path: (to-file path)] port/locals: copy [] either (0 = length? port/locals) [ append port/locals open/seek rejoin [port/spec/path ".dat"] append port/locals open/seek rejoin [port/spec/path ".idx"] ][ port/locals/1 open/seek rejoin [port/spec/path ".dat"] port/locals/2 open/seek rejoin [port/spec/path ".idx"] ] return port ] close: func [port [port!]] [ foreach port port/locals [close port] ] read: func [port [port!] /seek number [integer!] ] [ Get-RIF port number ] write: func [port [port!] record [binary!]] [ Append-RIF port record ] ] ] |
Steeve 13-Aug-2010 [2208] | arghh... not here ;-) |
Andreas 13-Aug-2010 [2209x3] | There are action!s in R3, which operate in port!s. |
If you define custom schemes, you can implement how those actions behave for ports using your scheme by writing what we call "actors". | |
This is the elementary principle to understand. | |
older newer | first last |