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

Clunky-looking code

 [1/11] from: sanghabum::aol::com at: 2-Apr-2001 13:25


I'm trying to multiply respective elements of two blocks and get a single sum: e.g. [a b c] * [d e f] = a*d + b*e + c*f I have no problem writing the code .... There are two versions of the function listed below. But it looks irredeemably inelegant compared to almost any other language I know .... I would not like to have to do matrix operations in Rebol! Am I missing some elegant way of running up two blocks in step? ;; ----- Method 1 MultiplyBlocks1: func [Block1 Block2 /local Sum ind] [ sum: 0 for ind 1 Length? Block1 1 [ sum: sum + ((pick Block1 ind) * (pick Block2 ind)) ] ; for return sum ] ; func ;; ----- Method 2 MultiplyBlocks2: func [Block1 Block2 /local Sum] [ sum: 0 Loop (Length? Block1) [ sum: sum + ((first Block1) * (first Block2)) block1: Next Block1 block2: Next Block2 ] ; loop Return Sum ] ; func ;; ----- Example of execution print MultiplyBlocks1 [1 5 10 25] [0 5 6 20] print MultiplyBlocks2 [1 5 10 25] [0 5 6 20] Thanks, Colin.

 [2/11] from: jelinem1:nationwide at: 2-Apr-2001 12:51


To write the most compact piece of code for performing this task one could split some hairs and chop out a few chars here and there, but that does not necessarily make it more readable/maintainable or better. Despite the fact that this email will get like a zillion replies, here's my 2c. If you want to multiply two blocks, once, and have no need to get into this sort of thing any more deeply, put your inelegant code in a function (where it can elegantly be called) and get on with it. It you wish to use the concept over again, and even expound on it, write a dialect. The dialecting is the part that REBOL will excel at over other languages. - Michael Jelinek [Sanghabum--aol--com]@rebol.com on 04/02/2001 12:25:11 PM From: [Sanghabum--aol--com]@rebol.com on 04/02/2001 12:25 PM Please respond to [rebol-list--rebol--com] Sent by: [rebol-bounce--rebol--com] To: [rebol-list--rebol--com] cc: Subject: [REBOL] Clunky-looking code I'm trying to multiply respective elements of two blocks and get a single sum: e.g. [a b c] * [d e f] = a*d + b*e + c*f I have no problem writing the code .... There are two versions of the function listed below. But it looks irredeemably inelegant compared to almost any other language I know .... I would not like to have to do matrix operations in Rebol! Am I missing some elegant way of running up two blocks in step? ;; ----- Method 1 MultiplyBlocks1: func [Block1 Block2 /local Sum ind] [ sum: 0 for ind 1 Length? Block1 1 [ sum: sum + ((pick Block1 ind) * (pick Block2 ind)) ] ; for return sum ] ; func ;; ----- Method 2 MultiplyBlocks2: func [Block1 Block2 /local Sum] [ sum: 0 Loop (Length? Block1) [ sum: sum + ((first Block1) * (first Block2)) block1: Next Block1 block2: Next Block2 ] ; loop Return Sum ] ; func ;; ----- Example of execution print MultiplyBlocks1 [1 5 10 25] [0 5 6 20] print MultiplyBlocks2 [1 5 10 25] [0 5 6 20] Thanks, Colin.

 [3/11] from: rgombert:essentiel at: 2-Apr-2001 20:29


try : MultiplyBlocks: func [ Block1 Block2 /local sum ][ sum: 0 repeat i min length? Block1 length? Block2 [ sum: sum + (Block1/:i * Block2/:i) ] return sum ] Renaud

 [4/11] from: chris:arranfolkfestival at: 2-Apr-2001 14:36


Hi Colin,
> I'm trying to multiply respective elements of two blocks and get a > single sum: > e.g. > [a b c] * [d e f] = a*d + b*e + c*f
This may be neater... Matter of opinion really. multiply-blocks: func [ block-1 [block!] block-2 [block!] ][ sum: make integer! 0 while [and not tail? block-1 not tail? block-2][ sum: add sum ((first block-1) * (first block-2)) block-1: next block-1 block-2: next block-2 ] return sum ] Actually, its a fair bit longer than your suggestions - but it is an alternative :o) - Chris

 [5/11] from: rgombert:essentiel at: 2-Apr-2001 21:09


It's also interesting to notice the relative speed of each function (multiply 2 blocks of 15 integers): multiply-blocs > 0:01:34.32 MultiplyBlocks1 > 0:01:46.32 MultiplyBlocks2 > 0:00:51.06 MultiplyBlocks3 > 0:00:38.46 Note that you don't need to explicitely use RETURN in your functions, since the last value of the affectation is still availlable when Rebol exits the loop. MultiplyBlocks3: func [ Block1 Block2 /local Sum ][ sum: 0 repeat i min length? Block1 length? Block2 [sum: sum + (Block1/:i * Block2/:i)] ] Renaud

 [6/11] from: brett:codeconscious at: 3-Apr-2001 10:20


> I'm trying to multiply respective elements of two blocks and get a single
sum:
> e.g. > [a b c] * [d e f] = a*d + b*e + c*f >
As you describe, you have two operations 1) Multiply the respective elements of two series. 2) Sum a series
> I have no problem writing the code .... There are two versions of the > function listed below. But it looks irredeemably inelegant compared to
almost
> any other language I know .... I would not like to have to do matrix > operations in Rebol!
I don't think Rebol was optimised as a language for doing matrix operations and as far as I remember is no worse than any other language I know for this type of operation - except for APL which I only experiemented in briefly. As Michael Jelinek points out the best way to make it look elegant is to code up your functions and call them. Functions effectively extend the language to make it more expressive and perhaps elegant. If you could assume things about your blocks then you can do the following: vector-multiply: function [a b][result][ if not equal? length? a length? b [throw "Only accepts vectors of the same size."] result: array reduce [length? a] for i 1 length? a 1 [ poke result i multiply a/:i b/:i ] RETURN result ] vector-sum: function [a][result][ result: 0 for i 1 length? a 1 [result: add result a/:i] RETURN result ] And therefore more elegantly code in you main function: vector-sum vector-multiply [2 3 5] [3 5 7] Next option would be to use Ladislav's %highfun.r script (http://www.rebol.org/advanced/index.html). There you will find functions that will make this work more elegant, or a technique to make the functions I've shown more generic. Last alternative is to ask RT really really nicely if they would consider changing the semantics of "multiply" in order to accept two blocks and of add to accept a block to sum. But they could only go so far - at some point such changes will conflict with pre-existing functionality/semantics. Brett. --- http://www.codeconscious.com

 [7/11] from: sanghabum:aol at: 3-Apr-2001 19:00


Thanks Renaud, <Renaud> MultiplyBlocks: func [ Block1 Block2 /local sum ][ sum: 0 repeat i min length? Block1 length? Block2 [ sum: sum + (Block1/:i * Block2/:i) ] return sum ] </Renaud> What was missing from my knowledge was how to reference a block using a variable (pardon my non-Rebol terminology) ..... When I'd tried things like Block1/Ind I got told that was a bad path. Your little colon makes all the difference. <Renaud> Note that you don't need to explicitly use RETURN in your functions, since the last value of the affectation is still available when Rebol exits the loop. </Renaud> True for MultiplyBlocks1. But MultiplyBlocks2 does need an explicit return, at least on my machine. And, maybe it's a matter of style, but I'd rather have an explicit return: it helps a stranger's eye when looking at code. It also means I can add debugging code without breaking assumptions. <Renaud> It's also interesting to notice the relative speed of each function (multiply 2 blocks of 15 integers):
<snip>
</Renaud> I've changed my code to your "block/:i" format. It knocks 15% of the application run time. A worthwhile improvement indeed. <Brett> Next option would be to use Ladislav's %highfun.r script (http://www.rebol.org/advanced/index.html). There you will find functions that will make this work more elegant, or a technique to make the functions I've shown more generic. </Brett> Thanks for this reference. I certainly don't want to spend my life reinventing the wheel, and especially not clunky wheels <Michael> To write the most compact piece of code for performing this task one could split some hairs and chop out a few chars here and there, but that does not necessarily make it more readable/maintainable or better. </Michael> I wasn't trying to write the shortest possible code. But I like to think that I write code that is easy to follow. Which is why the PICKs and FIRSTs in my two samples niggled. They cluttered a function that ought to be simple. Call it programmer's intuition, but I knew there must be a better way. But my RTFMing skills had failed to find it. Thanks for all the help guys. I think I am beginning to get the hang of this language! Colin

 [8/11] from: athena:pop3-dfw:myfirstlink at: 7-Apr-2001 9:16


Can someone explain exactly what this code is doing? I'm confused by this usage of ":" and its relationship to a block. [Sanghabum--aol--com] wrote:

 [9/11] from: rgombert:essentiel at: 7-Apr-2001 16:56


Not too difficult... the function take 2 blocs of numbers, say [2 3 4] and [3 4 5 6], and return the sum of the corresponding terms in each bloc, i.e. : 2*3 + 3*4 +4*5 + (0)*6 the code : repeat i min length? Block1 length? Block2 [...] is used to loop i from 1 to the size of the smaller block, and then : Block1/:i is similar to "pick Bloc1 i", and so is looped as Bloc1/1 when i=1, Block1/2 when i=2 and so on... Hope that answer to your question ;-) Renaud

 [10/11] from: gjones05:mail:orion at: 7-Apr-2001 10:01


From: "Harold Grovesteen"
> Can someone explain exactly what this code is doing? I'm confused by > this usage of ":" and its relationship to a block.
<<quoted lines omitted: 13>>
> > ] > > </Renaud>
Hi, Harold, Using the colon before a word retrieves its value. In the case where it is used as a part of a path, then the value serves as an index. A different example: a: [cat dog] :a ;returns the value of the word a, which is the block a/1 ;returns cat i: 1 a/:i ;returns cat Hope this helps. --Scott Jones

 [11/11] from: athena:pop3-dfw:myfirstlink at: 8-Apr-2001 12:26


Thanks, Did not understand this aspect of "paths". Harold Grovesteen GS Jones wrote:

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted