r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3 Schemes] Implementors guide

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.