World: r3wp
[Core] Discuss core issues
older newer | first last |
Graham 5-Apr-2005 [882] | writing my own faq |
JaimeVargas 7-Apr-2005 [883x4] | I hope this is useful for someone REBOL [] rest: func [s [series!]][skip s 1] define-object: func [ spec [block!] /local arg-spec ctx-spec object-name constructor-name predicate-name attributes spec-rule type-spec continue? w ][ arg-names: copy [] continue?: [none] ;used to stop parsing name-rule: [set w word! (insert tail arg-names w)] type-rule: [set w word! (unless datatype? attempt [get w] [continue?: [end skip]])] spec-rule: [name-rule some [name-rule opt [into [some [type-rule continue?]]]]] if any [ not parse spec spec-rule arg-names <> unique arg-names ][ make error! "invalid spec" ] object-name: to-string first arg-names constructor-name: to-word join 'make- object-name predicate-name: to-word join first arg-names '? attributes: rest arg-names arg-spec: copy [] foreach itm attributes [ insert tail arg-spec reduce [ to-word join itm '-value either block? w: select spec itm [w][[any-type!]] ] ] ctx-spec: copy [] arg-names: extract arg-spec 2 1 repeat i length? attributes [ insert tail ctx-spec reduce [to-set-word attributes/:i to-get-word arg-names/:i] ] ;create constructor function set constructor-name make function! compose [(reform ["Makes a new" uppercase object-name "object with attributes" mold attributes]) (arg-spec)] compose/only [make object! (ctx-spec)] ;body ;create predicate function set predicate-name make function! compose [(reform ["Determines if value is a" uppercase object-name "object"]) value [object!] /local types] compose/deep/only [ either (attributes) = rest first value [ foreach itm (attributes) [ unless any [ [any-type!] = types: select (arg-spec) to-word join itm '-value find types type?/word value/:itm ][return false] ] true ][ false ] ] ] |
With it you can create objects that are type checked when constructed. | |
;; usage define-object [name attribute1 [datatype1 ...] ...] ;; creates two functions make-name name? | |
;; example untyped define-object [point x y] point? probe o: make-point 1 2 point? probe o: context [x: 1 y: "two"] ;; example typed define-object [point x [integer!] y [integer!]] point? probe o: make-point 1 2 point? probe o: context [x: 1 y: "two"] | |
Ammon 7-Apr-2005 [887] | Jaime, your REST function (AFAICT) has the same functionality as NEXT is there any reason that you are not using NEXT? |
JaimeVargas 7-Apr-2005 [888x2] | Didn't knew about next. I will use it from now on. |
Do you find define-object useful? | |
Ammon 7-Apr-2005 [890] | I can see how it could be useful in the right environment. |
JaimeVargas 7-Apr-2005 [891x3] | ;-) |
If anyone ever wanted multi-methods or function overload in rebol here is the answer. Enjoy ;-) REBOL [] define-method: func [ 'name [word!] spec [block!] locals [block!] code [block!] /local w type-rule spec-rule continue? register-name methods-name ][ ;; first validate the spec continue?: [none] ;used to stop parsing type-rule: [set w word! (unless datatype? attempt [get w] [continue?: [end skip]])] spec-rule: [some [word! into [type-rule continue?]]] unless parse spec spec-rule [make error! "invalid spec"] register-name: to-word join :name '-register methods-name: to-word join :name '-methods? unless value? name [ context [ dispatch-table: copy [] spec-fingerprint: func [spec [block!] /local types][ types: copy [] foreach itm extract/index spec 2 2 [insert tail types itm/1 ] types ] values-fingerprint: func [values [block!] /local types][ types: copy [] foreach v values [insert tail types type?/word v] types ] retrieve-func: func [values [block!]][select/only dispatch-table values-fingerprint values] set :name func [values [block!]][ do compose [(retrieve-func values) (values)] ] set :register-name func [spec code /local fingerprint pos][ fingerprint: spec-fingerprint spec either found? pos: find/only dispatch-table fingerprint [ poke dispatch-table 1 + index? pos function spec locals code ][ insert tail dispatch-table reduce [fingerprint function spec locals code] ] ] set :methods-name does [probe dispatch-table] ] ] do reduce [register-name spec code] ] define-method f [x [integer!]] [] [x + 1] define-method f [s [block!]] [] [attempt [pick s 2]] define-method f [x [decimal!]] [] [sine x] f[5] == 6 f[[one two three]] == two f[90.0] == 1.0 | |
Are the above functions DEFINE-METHOD and DEFINE-OBJECT worthy for the rebol.org library? | |
Gabriele 7-Apr-2005 [894x2] | Well, why not. :) I'd suggest you to upload them. |
Note that I have something vaguely similar to both in my YourValues code (http://www.colellachiara.com/soft/YourValues/), though that's probably not general enough for your needs. | |
JaimeVargas 7-Apr-2005 [896x2] | Making a few modifications two define-method it will be possible to have multiple inheritance and object based dispatch in rebol. I need to think for a good name to post this in rebol.org. |
Rebol never ends to amaze me. The src code for both functions combined is under 120 lines including comments and tests. | |
Gregg 8-Apr-2005 [898] | Please do put them on REBOL.org! No bookmarks in AltME yet, and others will find them there. Wish I had time to play with them right now! |
Sunanda 8-Apr-2005 [899] | Exactly the sort of useful utility the Library exists for. And, as Gregg says, much more likely to be found by others there. |
JaimeVargas 11-Apr-2005 [900x3] | I had been teaching a few more tricks to DEFINE-METHOD. This is what it is capable off: |
;define-method creates a "fingerprint" for each parameter-spec ;and evals corresponding code according to "fingerprint" define-method f [x: integer!] [x + 1] define-method f [s: block!] [attempt [pick s 2]] define-method f [x: decimal!] [sine x] >> f[1] == 2 >> f[[one two three]] == two >> b: [one two three] >> f[b] == two >> f[90.0] == 1.0 ;instrospection one can always see the methods of a function >> f-methods? [integer!] -> [x + 1] [block!] -> [attempt [pick s 2]] [decimal!] -> [sine x] ;singleton parameter specs are posible. ;This allows for "rule" based programming define-method fact [n: 0] [1] define-method fact [n: integer!][n * fact[n - 1]] >> fact-methods? [0] -> [1] [integer!] -> [n * fact [n - 1]] define-method fact-memoize [n: 0] [1] define-method fact-memoize [n: integer! /local r ][ r: n * fact[n - 1] define-method fact-memoize compose [n: (:n)] reduce [r] r ] >> time-it [fact[12]] == 0:00:00.000434 ;no memoization >> time-it [fact-memoize[12]] == 0:00:00.000583 ;first invoication >> time-it [fact-memoize[12]] == 0:00:00.000087 ;cache lookup ;dispatch for undefined type signals error >> fact[1.0] ** User Error: Don't have a method to handle: [decimal!] ** Near: fact [1.0] ;moization is more dramatic when calculating the fibonacci sequence define-method fib [n: 1] [1] define-method fib [n: 2] [1] define-method fib [n: integer!][ add fib[n - 2] fib[n - 1] ] define-method fib-memoize [n: 1] [1] define-method fib-memoize [n: 2] [1] define-method fib-memoize [n: integer! /local r][ r: add fib-memoize[n - 1] fib-memoize[n - 2] define-method fib-memoize compose [n: (:n)] reduce [r] r ] ;without memoization >> time-it [fib [20]] == 0:00:00.32601 >> time-it [fib [19]] == 0:00:00.207066 ;dramatic gains due to memoization >> time-it [fib-memoize[20]] == 0:00:00.002187 ;first invoication >> time-it [fib-memoize[20]] == 0:00:00.000096 ;cache lookup >> time-it [fib-memoize[19]] == 0:00:00.0001 ;cache lookup ;it is possible to overload some natives! define-method add [x: issue! y: issue!][join x y] add[1 1] == 2 add[1.0.0 1] == 2.1.1 add[#abc #def] == #abcdef | |
So I think polyformism in rebol is quite possible. I wonder how difficult it will be to have something like DEFINE-METHOD implemented natively. | |
Ammon 11-Apr-2005 [903x2] | I like it. |
So have you put this in the library yet? | |
JaimeVargas 11-Apr-2005 [905x2] | It will be ther in a few minutes. |
DEFINE-METHOD and DEFINE-OBJECT posted to the library. http://www.rebol.org/cgi-bin/cgiwrap/rebol/view-script.r?script=multi-methods.r | |
Ammon 11-Apr-2005 [907] | Sweet! I'll have to play with it... |
Louis 11-Apr-2005 [908] | Several scripts I have been using for several years to ftp files to our web server are not working now. I get no error message; the script just sits there. But FTPGadget still works. I phoned our isp and he can't see anything wrong. He can ftp to the server. What could be causing this problem with my scripts? |
Graham 12-Apr-2005 [909] | run trace/net to see what is going wrong |
Sunanda 12-Apr-2005 [910] | Louis, I had a similar problem earlier this week. It might be a firewall issue: try system/schemes/ftp/passive: true In the case I looked at, it seems to be just cruft build-up.....Many things are not working on that machine, and FTP has now broken too. We "solved" the problem by installing SmartFTP -- it works every 2nd time you run it on that machine. |
Louis 12-Apr-2005 [911x2] | Thanks, Graham. I had forgotten about trace. And thanks, Sunanda. system/schemes/ftp/passive: true solved my problem. |
Just wondering. Why does this work? | |
Sunanda 12-Apr-2005 [913] | Either your ISP doesn't allow FTP to negotiate ports -- which is what active means Or your firewall doesn't like it. Passive FTP uses fixed port numbers, so everyone should be happy with it. |
Ingo 12-Apr-2005 [914x2] | Does anyone know about documentation for the system port? |
I know I used it once, but don't remember how, and what I did with it ;-) | |
JaimeVargas 12-Apr-2005 [916x2] | ;; nexted-foreach a simple way of generating nexted foreach loops compose-foreach: func [var data code][reduce ['foreach var data code]] nexted-foreach: func [vars blocks code /local var][ if empty? blocks [return code] compose-foreach first vars first blocks nexted-foreach next vars next blocks code ] |
;; it can be used like this do nexted-foreach [x y] [[1 2 3] [a b c]] [print [x y]] | |
Vincent 12-Apr-2005 [918] | Ingo: on the 'system port, no official doc. Some info: rebolist thread (rebol.org) : http://www.rebol.org/cgi-bin/cgiwrap/rebol/ml-display-thread.r?m=rmlMYFJ 'signal demo script : http://www.rebol.org/cgi-bin/cgiwrap/rebol/ml-display-thread.r?m=rmlNFFJ drag-and-drop demo script: http://www.rebol.org/cgi-bin/cgiwrap/rebol/view-script.r?script=sys-port-drag-accept.r systray demo script: http://compkarori.com/vanilla/display/System+Tray+Functionality It's different for each OS. For MS-WIn, there is: get-modes system/ports/system 'system-modes ;== [window winmsg tray endian] where: 'window : REBOL console window handle, 'winmsg : OS message block, 'tray : systray definition block 'endian : CPU byte order ('big or 'little) For Linux: get-modes system/ports/system 'system-modes ;== [signal read-fd write-fd except-fd signal-names endian] |
Ingo 14-Apr-2005 [919] | Thanks Vincent |
Brock 15-Apr-2005 [920x4] | Is this a bug? 1) I read a directory on our ftp server and return a set of files of which 02 EN AR final.pdf is one of them 2) I then copy a URL address that returns a 404 indicating it couldn't find the file in question ie. http://www.cpcpension.com/files/2002EN AR final.pdf 3) I do a split-paths to-url on the contents of the clipboard:// that contains item in step 2) 4) I compare the file names for equality either using "=" or equal? and both return false 5) I check the type of each file, they are both 'file' types 6) I check the length of each file, the one from step 1) returns 20, step 2) returns 26 So, somewhere it is changing the representation of a space into the actual string " ". Any ideas? 6) |
When I execute this command... print second split-path to-file to-string http://www.cpcpension.com/files/2002EN AR fin al.pdf it returns.... 2002 EN AR final.pdf it converted the 's in the URL | |
oops... url wrapped above | |
when I execute this command... print second split-path to-file to-string read clipboard:// where I have copied the URL above into the clipboard:// it returns.... 2002 EN AR final.pdf | |
MichaelB 15-Apr-2005 [924] | Could someone just show me how to get the 'unset? function return true ?! Maybe I'm a bit stupid, but I simply don't get it working. Isn't really important, but should still work. e.g. unset 'a bl: [a] unset? 'a unset? first bl ????? shouldn't this return true ????? |
Volker 15-Apr-2005 [925] | probe unset? () probe unset? get/any 'hey-what? |
Vincent 15-Apr-2005 [926] | MichaelB: unset? 'a <=> is the word 'a an unset! value -> no it's a word! value unset? first bl <=> is the first element of bl an unset! value -> no it's a word! value to know if a word as a value: value? 'word value? 'a == false but unset? () == true ; paren! are auto-evaluated, empty paren! -> unset! unset? print 2 == true ; 'print returns no value -> unset! unset? get/any 'a == true ; but as "a" is undefined, unset? a -> error! unset? unset 'a == true ; 'unset returns unset! 'unset? -> _value_'s datatype! = unset! unset! is for absence of value too: my-func [an-opt-arg [integer! unset!]][...] |
MichaelB 15-Apr-2005 [927] | - thank you for the answers, I knew there is something like that, just couldn't figure it out any more - actually I tried the unset? get .. version, but of course without the any refinement ... so couldn't work - I didn't know (or forgot) about the optional value possibility, good to know thanks again :-) |
Vincent 15-Apr-2005 [928x2] | Brock: 'to-url converts a string into an url without escaping, escaping is only done when showing the url string: to-url "http://www.cpcpension.com/files/2002EN AR final.pdf" ; works == http://www.cpcpension.com/files/2002EN AR final.pdf ; blanks -> to-url "http://www.cpcpension.com/files/2002EN AR final.pdf" ; don't works == http://www.cpcpension.com/files/2002EN AR final.pdf ; only looks the same, but contains "%" "2" "0" you can use 'do or 'load to interpret the string in clipboard: do read clipboard:// load read clipboard:// (same with 'to-file) |
Off course, I forgot: to-url dehex read clipboard:// | |
Brock 15-Apr-2005 [930] | Thanks for the explanations Vincent. The best solution appears to be to-url dehex read clipboard://. I totally forgot about dehex. |
Louis 18-Apr-2005 [931] | Thanks, Sunanda. Sorry to take so long to respond. I'm traveling and don't always have internet access. |
older newer | first last |