Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search

[REBOL] Re: X.10 serial port control from Rebol

From: greggirwin:mindspring at: 7-Sep-2003 11:42

Hi Parki, Thanks for posting that. Good stuff! Makes me want to go out and find an X10 controller so I can play with things again. :) BP> I have looked BP> at this in C (working with a developer to port to Mac OS X) as well as BP> Perl and Java, and can certainly say that the Rebol approach, which BP> built in serial:// protocol, makes life a snap. Good to know. We all have different experience, so I always like hearing where REBOL works well and where it doesn't. BP> This also contains some playing around with the notions of Singleton BP> idiom and data hiding. It's likely overkill. BP> I am posting it here as people might be interested, and I welcome any BP> feedback on style and whatevernot. It could be overkill. One of the things about REBOL, or the approach *I* tend to use with REBOL, as compared to some other languages is that I don't try to exert too much control over how modules may be used. That is, REBOL is very flexible, so if I build a module that is locked down really tight in how it can be used, that makes more work for me, and more work for the person who wants to use it differently. It's sort of an accountability thing, and it's a fine line. On one hand, I don't want to write things so knowledge of internals is required for people to use it (some VID styles suffer from this IMO), but on the other hand, in REBOL people can find a way around almost any blockades you try to put up to protect them. In this case, I'd weigh the pros and cons of the singleton stuff versus just using an object. What happens if they create more than one? Would that ever be useful? Stuff like that. Now, I can make some comments on your code (already very good) which are related more to REBOL style and idioms than correct code. First, your posting line-wrapped heavily here. REBOL is free form, so you can often adjust the formatting to suit shorter lines if you want. Second, great comments! Don't forget the COMMENT function for long comments that may wrap. Also, glad to see you used doc attributes on your ex function parameters! Where you use: repeat count 100 [ You're not using 'count, so you could use LOOP instead. loop 100 [ Where you use: if not reply = #{} [ return 0 ] Consider: if not empty? reply [ return 0 ] EMPTY? is often clearer, as to the intent of what you're checking, than comparing equality against specific values. Just as FUNC is a shortcut for FUNCTION, DOES and HAS are shortcuts for functions with no params or those with only local var decls, respectively. Don't be afraid of one-liner functions. deinit: func [] [ close serialPort_ ] Could be: deinit: does [close serialPort_] Standard REBOL style doesn't use CamelCase for words. It uses all lowercase, with hyphens, and hyphens are used in place of underscores in most cases. Also, all-caps aren't used for constants, maybe because, well, there really *aren't* any constants in REBOL. :) ex: function [ deviceCode [ number! ] "Device code number: 1,..,16" funcWord [word!] "The function to run: 'on, 'off, etc" ] [ houseVal deviceVal functionVal addrHex funcHex ... Vs: ex: function [ device-code [ number! ] "Device code number: 1,..,16" func-word [word!] "The function to run: 'on, 'off, etc" ] [ house-val device-val function-val addr-hex func-hex ... You've made good use of data, but consider how else you might express your data, and how that would affect the code. e.g. house-codes: [ #"A" 96 #"B" 224 #"C" 32 #"D" 160 #"E" 16 #"F" 144 #"G" 80 #"H" 208 #"I" 112 #"J" 240 #"K" 48 #"L" 176 #"M" 0 #"N" 128 #"O" 64 #"P" 192 ] ... house-code_: #"A" ... house-val: house-codes/:house-code_ You could even validate house codes valid-house-codes: charset [#"A" - #"P"] ; or, with the above house-codes definition ;valid-house-codes: charset extract house-codes 2 valid-house-code?: func [house-code [char!]] [ found? find valid-house-codes house-code ] You could also use a function for your data conversion lines on the address and function values. You could even define it locally in EX. I'm sure you would have done this in your next cut anyway as it's not really a REBOL specific thing. I do this, sometimes, so I can take the function and play with it out of context--often in the console. X10ify: func [val] [ debase/base (to-string copy/part at to-hex val 5 4) 16 ;?? will this work here instead? ;at debase/base to-hex val 16 3 ] ... addr-hex: X10ify 1024 + house-val + device-val func-hex: X10ify 1536 + house-val + function-val Another handy idiom is to write your function, or a wrapper for it, to allow multiple values to be iterated over, rather than calling the function manually with one argument, or arg list, multiple times. cm11aSend addrHex cm11aSend #{00} cm11aSend funcHex cm11aSend #{00} Versus: send-cmds: func [cmds [block!] [ foreach cmd cmds [cm11aSend cmd] ] send-cmds reduce [addrHex #{00} funcHex #{00}] If the #{00} command has a special meaning, or is used after every command, you could give it a special name or just send it silently in 'cm11aSend, maybe based on a refinement. SEND-CMDS could even treat the block as a simple dialect so you could include WAIT commands and such. It's good stuff in any case! I hope my comments give you some thoughts and ideas. There's certainly nothing wrong with your code as it stands now. -- Gregg