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

Transpose

 [1/12] from: al::bri::xtra::co::nz at: 6-Oct-2000 1:11


Joel wrote:
> Finally, I'd considered handling the structure-traversing issues
separately from the data-manipulation issues, by defining (this version is VERY quick and dirty):
> >> transpose: function [b [block!]] [w i s r] [ > [ r: make block! w: accum length? b/1 map b :length? :min
<<quoted lines omitted: 9>>
> >> transpose [[1 2 3] [14 15 16] [27 28 29]] > == [[1 14 27] [2 15 28] [3 16 29]]
I've cleaned it up a bit: [ Rebol [ Name: 'Transpose Title: "Transpose" File: %"Transpose.r" Author: "Andrew Martin" eMail: [Al--Bri--xtra--co--nz] Date: 5/October/2000 Enhancement: 'Transpose Acknowledgements: "Joel Neely" Example: [ transpose [[1 2 3 4 5] ["a" "b" "c" "d" "e"]] ; [[1 "a"] [2 "b"] [3 "c"] [4 "d"] [5 "e"]] transpose [[1 2 3] [14 15 16] [27 28 29]] ; [[1 14 27] [2 15 28] [3 16 29]] ] ] Transpose: function [ [catch] "Transposes Matrices" Matrix [block!] ][ Results Width Height Column ][ Results: make block! Width: length? Matrix/1 Height: length? Matrix repeat Index Width [ Column: make block! Width foreach Row Matrix [ insert/only tail Column Row/:Index ] insert/only tail Results Column ] Results ] ]
>> transpose [[1 2 3 4 5] ["a" "b" "c" "d" "e"]]
== [[1 "a"] [2 "b"] [3 "c"] [4 "d"] [5 "e"]]
>> ; [[1 "a"] [2 "b"] [3 "c"] [4 "d"] [5 "e"]] >> transpose [[1 2 3] [14 15 16] [27 28 29]]
== [[1 14 27] [2 15 28] [3 16 29]]
>> ; [[1 14 27] [2 15 28] [3 16 29]] > Critiques/comments/debugging welcome!
I totally agree. :-) Andrew Martin ICQ: 26227169 http://members.nbci.com/AndrewMartin/

 [2/12] from: joel:neely:fedex at: 6-Oct-2000 8:26


(The following note was written while softly humming, " ... I get by with a little help from my friends, Gonna try with a little help from my friends. ... ) I'm really interested in the idea of a common/shared library of functions/objects such as found on www.rebol.com, contained in Ladislav's http://www.rebol.org/advanced/highfun.r (as one example of the MANY sites that REBOLlistfolk have), or some of my scribbles earlier in this thread. I'll address the library issue in a follow-up post. As for the function at hand, let me raise a couple of questions: [Al--Bri--xtra--co--nz] wrote:
> Joel wrote: > > Finally, I'd considered handling the structure-traversing
<<quoted lines omitted: 4>>
> I've cleaned it up a bit: > ...
j> transpose: function [b [block!]] [w i s r] [ A> Transpose: function [ A> [catch] A> Transposes Matrices" A> Matrix [block!] A> ][ A> Results Width Height Column A> ][ Nice choice of names (but I MUST remember to ask you about the caps) Since we're discussing, I'll take the liberty to explain my abbrevs as (w)idth (i)ndex (s)ubresult (r)esult :-/ j> r: make block! w: accum length? b/1 map b :length? :min A> Results: make block! Width: length? Matrix/1 A> Height: length? Matrix That bit of obscurity in the initialization of w is explained in a footnote (1) in case I mangled it so badly that no-one can read it. My real question here is this, if we collectively are going to build up a small pile of useful extensions, would it be good to have some conventions re defensive programming, or would that be the sort of thing that should simply be documented (for each) as "possible failure modes"? Alternately, should we have a rating (I do NOT mean "value judgement", but simply accurate labeling of content!) with values such as: "fragile" - "arguments not vetted, you can crash this if you don't play well with others" "robust" - "good faith argument checking done, but there may be some gotchas left" "ironclad" - "we've collectively banged on this one REALLY hard, and are confident that errors will be pre-empted" j> s: make block! length? b A> Column: make block! Width (Boneheaded mistake on my part -- thanks for the correction!) J> foreach c b [append/only s c/:i] j> append/only r s A> foreach Row Matrix [ A> insert/only tail Column Row/:Index A> ] A> insert/only tail Results Column (Sigh... You'd think I'd have learned by now. Thanks for cleaning append/only up into "insert/only tail" -- repeatedly!)
> > Critiques/comments/debugging welcome! > > I totally agree. :-) >
-jn- FOOTNOTE: 1) Regarding the peculiar initialization code r: make block! w: accum length? b/1 map b :length? :min ------1------- -----2----- --------------------3------------------- Step 1 gets the lengths of all sub-blocks in the argument, step 2 assumes the length of the first as a default, and step 3 sets w to the length of the shortest sub-block. This was done so that a collection of (sub-)blocks of different lengths wouldn't cause an error, but would be transposed as far as possible:
>> transpose [[1 2 3 4 5] [1 2 3] [1 2 3 4]]
== [[1 1 1] [2 2 2] [3 3 3]] Of course, this is still not totally robust, as an empty arg block will still not be swallowable (mea culpa!):
>> transpose []
** Script Error: length? expected series argument of type: series port tuple struct. ** Where: r: make block! w: accum This is easy to handle by adding if 0 = length? b [return copy []] to the very beginning of the function, or wrapping the body with either 0 = length? b [ r: copy [] ][ r: ...etc... ...etc... ] r which would then ensure that the basis for accum given by length? b/1 was well-defined. I assume your [catch] was a faster way of addressing this same issue, by simply passing the error resulting from an empty argument list back to the caller. So... should we prefer a style for common/standard library functions, or at least document which position the author (and maintainers) took?

 [3/12] from: news:ted:husted at: 6-Oct-2000 9:47


[Al--Bri--xtra--co--nz] wrote: "fragile" - "arguments not vetted, you can crash this if you don't play well with others" "robust" - "good faith argument checking done, but there may be some gotchas left" "ironclad" - "we've collectively banged on this one REALLY hard, and are confident that errors will be pre-empted" How about applying the SourceForge nomenclature for applications: 1: Planning 2: Pre-Alpha 3: Alpha 4: Beta ("fragile") 5: Production-Stable ("robust") 6: Mature ("ironclad")
> So... should we prefer a style for common/standard library
functions, or at least document which position the author (and maintainers) took? How about starting with Carl's style guide < http://www.rebol.com/users/scrstyle.html >, and extending from there? -T.

 [4/12] from: joel:neely:fedex at: 6-Oct-2000 11:13


Hi, Andrew, [news--ted--husted--com] wrote:
> [Al--Bri--xtra--co--nz] wrote: > "fragile" - "arguments not vetted, you can crash this if
<<quoted lines omitted: 11>>
> 5: Production-Stable ("robust") > 6: Mature ("ironclad")
I like 'em (especially since this puts tradition on our side...), with one minor reservation. There's an implication among the choices of beta , "production-stable", and "mature" that has to do with an item's progression toward completeness. There is, to my mind, a slightly different implication to describing a function as "fragile" vs. "robust" than as "beta" vs. "production-stable" in that I may want to use the robust version if I'm handling external data (input from console, data file, etc.) but may be willing to use the fragile version (for the speed gain of less checking) if I'm at a point in the code where I'm working with data that has already passed some level of validity checking -- or that I've constructed earlier in a way that ensures its validity.
> > So... should we prefer a style for common/standard library > functions, or at least document which position the author (and > maintainers) took? > > How about starting with Carl's style guide > <http://www.rebol.com/users/scrstyle.html > > , and extending from there? >
I'm sorry... I guess I didn't express that very well. I think Carl's source coding style guide is a great place to start, for all the issues it addresses. I was really thinking more of design style questions, such as the choice between these hypothetical offerings: max-in-block-fragile: func [b /local x] [ x: first b foreach y next b [x: max x y] x ] max-in-block-sturdy: func [[catch] b [block!] /local x] [ x: b/1 foreach y next b [x: max x y] x ] max-in-block-sturdier: func [[catch] b [block!] /local safemax x] [ safemax: func [[catch] a1 a2] [ either any [(type? a1) = (type? a2) all [number? a1 number? a2]] [ max a1 a2 ][ max to-string a1 to-string a2 ] ] x: b/1 foreach y next b [x: safemax x y] x ] ...where we get...
>> max-in-block-fragile []
** Script Error: Out of range or past end. ** Where: x: first b foreach y
>> max-in-block-sturdy []
== none
>> max-in-block-sturdier []
== none
>> max-in-block-fragile [1 #"a" http://www.rebol.com [carl--rebol--com]]
** Script Error: Expected one of: integer! - not: url!. ** Where: x: max x y
>> max-in-block-sturdy [1 #"a" http://www.rebol.com [carl--rebol--com]]
** Script Error: Expected one of: integer! - not: url!. ** Where: x: max x y
>> max-in-block-sturdier [1 #"a" http://www.rebol.com [carl--rebol--com]]
== "http://www.rebol.com" If I built a block (e.g. of numbers) myself, and I already know that it is non-empty, then MAX-IN-BLOCK-FRAGILE may be just fine, but maybe not in the general case... ...and do we ever need the level of protection afforded (at a cost) by MAX-IN-BLOCK-STURDIER ? -jn- -- ; Joel Neely [joel--neely--fedex--com] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C24000000}

 [5/12] from: al:bri:xtra at: 6-Oct-2000 13:40


jn wrote:
> Nice choice of names...
Thanks, Joel.
> (but I MUST remember to ask you about the caps)
Why capitals? Here's the Transpose function again: Transpose: function [ [catch] "Transposes Matrices" Matrix [block!] ][ Results Width Height Column ][ Results: make block! Width: length? Matrix/1 Height: length? Matrix repeat Index Width [ Column: make block! Width foreach Row Matrix [ insert/only tail Column Row/:Index ] insert/only tail Results Column ] Results ] Note that every word that is defined here is in Title case. Also note that every common word that's in Rebol like 'insert, '/only, 'length? etcetera are in lower case. What's _important_ is signalled by the Title case words. Here's Transpose again but in a sea of lower case. transpose: function [ [catch] "transposes matrices" matrix [block!] ][ results width height column ][ results: make block! width: length? matrix/1 height: length? matrix repeat index width [ column: make block! width foreach row matrix [ insert/only tail column row/:index ] insert/only tail results column ] results ] Can you _easily_ see if I've made a mistake? What are the important words?
> My real question here is this, if we collectively are going to build up a
small pile of useful extensions, would it be good to have some conventions re defensive programming... Don't bother with defensive programming. It's just more stuff to debug and put right Put the [catch] attribute in and let the problem in the code be caught as early as possible. I'd still use 'try around disk and net i/o, as this makes sense. And the argument type specifiers are good as well.
> I assume your [catch] was a faster way of addressing this same issue, by
simply passing the error resulting from an empty argument list back to the caller. It's a whole lot simpler and catches the error earlier and it runs faster. Andrew Martin Look what happens when I go to sleep! :-) ICQ: 26227169 http://members.nbci.com/AndrewMartin/

 [6/12] from: al:bri:xtra at: 6-Oct-2000 13:48


Ted wrote:
> How about starting with Carl's style guide: > http://www.rebol.com/users/scrstyle.html, > and extending from there?
Rebol Crew wrote:
> The contents of a block are indented, but the block's enclosing brackets
[] are not. That's because the brackets belong to the prior level of syntax as they define the block, but are not contents of the block. Also it's easier to spot breaks between adjacent blocks when the brackets stand out. I disagree with Carl's reasoning here, but I can cope with it. I prefer the better human readable style like this example: repeat Index Width [ Column: make block! Width foreach Row Matrix [ insert/only tail Column Row/:Index ] insert/only tail Results Column ] Andrew Martin Style Curmudgeon ICQ: 26227169 http://members.nbci.com/AndrewMartin/

 [7/12] from: lmecir:geocities at: 6-Oct-2000 23:46


Hi, Andrew wrote:
> Why capitals? Here's the Transpose function again: > Transpose: function [
<<quoted lines omitted: 18>>
> every common word that's in Rebol like 'insert, '/only, 'length? etcetera > are in lower case. What's _important_ is signalled by the Title case
words. [...snip...]
> > I assume your [catch] was a faster way of addressing this same issue,
by
> simply passing the error resulting from an empty argument list back to the > caller.
<<quoted lines omitted: 4>>
> http://members.nbci.com/AndrewMartin/ > -><-
I would say, that your source is (as long as :make, :block!, :length?, :repeat, :foreach, :insert, :tail are normal, unchanged natives) exactly equivalent to the same function not having [catch] refinement, because there is no Throw for it in the source. Cheers, Ladislav

 [8/12] from: joel:neely:fedex at: 6-Oct-2000 17:00


This is clearly one of those "you say tomato, I say ketchup" issues. Anyone who doesn't like ketchup on his steak (or steak under his ketchup) is welcome to skip this post entirely! -jn- [Al--Bri--xtra--co--nz] wrote:
> Rebol Crew wrote: > > The contents of a block are indented, but the block's enclosing brackets
<<quoted lines omitted: 10>>
> insert/only tail Results Column > ]
I've always understood INdentation as showing what was IN something else. Viewed strictly as a block (i.e. ignoring the fact that I think I know what some of those words mean...) the example above has this shape to my mind's eye (abbreviating a few places -- strictly for space -- and making explicit an enclosing block...): [*] /----------^---------\ repeat Index Width [*] /-------------------------------------------^------------------------\ Column: make block! Width foreach Row Matrix [*] append Results Column /---------^---------\ append Results Column (Those hyphens, carets, asterisks, slashes, and backwardslashes are standing in for the nice pretty lines in my head...) The top level block contains 4 things -- three words and another block. That last block contains 11 things -- the eighth of which is another block. etc... Notice that the contents are UNDER the brackets -- [*] -- that mark the boundaries of the block. Of course, this horizontal layout is not going to work typographically, especially in email, as my lists get longer. So we can rotate it to run vertically. Unfortunately I don't have rotated brackets on my keyboard, so I'll just have to use the same old more-or-less-vertical ones: / repeat / Column: [ | Index | make *-< Width | block! ] | [ | Width | *------< foreach \ ] | Row | Matrix | [ / append | *-------< Results | ] \ Column | append | Results \ Column Notice that the contents of a block are still under the brackets that mark the block's boundaries (although logical "under" is now geometrically to the right ). Of course all these overlapping columns of words and lines are a little cluttered (even though more compact) so let's try to declutter by putting contents between the boundaries of their blocks (but still INdenting to make it clear that they are INside the blocks): [ repeat Index Width [ Column: make block! Width foreach Row Matrix [ append tail Column Row/:Index ] append tail Results Column ] ] Now let's remember that we know what these "words" mean. If we do, we'll tend to think of bigger units, perhaps called "phrases", that group words into fewer, bigger chunks. If I do that, I'll have to keep the first word of a new phrase back at the same level that it had before I started "chunking", so I don't lose track of my levels. If one of these phrases includes a block, I may try to write it out all at once. but if it doesn't fit, I'll try to pull the open brace into the line with the rest of the phrase, but leave the content indented with the closing brace "outdented" back to its own level to make it clear that I've come back up/out a level in the structure. [ repeat Index Width [ Column: make block! Width foreach Row Matrix [ append tail Column Row/:Index ] append tail Results Column ] ] This also lets me work top-down/breadth-first into the structure, only disclosing lower levels as I work my way down to them. To my eye, an empty (or hidden) block is ONE thing even if it's written with two keystrokes "[]". When I have to break the case open, I put the two halves at the same level Level 0 view ("outside"): [] Level 0 opening: [ ] Level 1 revealed: [ repeat Index Width [] ] Level 1 opening: [ repeat Index Width [ ] ] ... Well, no point in beating this dead horse further -- the horse steak is as tender as its going to get! However, notice that (in the spirit of comprimise) I've tried to keep the initial caps on Important Words! ;-) -- ; Joel Neely [joel--neely--fedex--com] 901-263-4460 38017/HKA/9677 REBOL [] print to-string debase decompress #{ 789C0BCE0BAB4A7176CA48CAB53448740FABF474F3720BCC B6F4F574CFC888342AC949CE74B50500E1710C0C24000000}

 [9/12] from: al:bri:xtra at: 6-Oct-2000 16:07


> This is clearly one of those "you say tomato, I say ketchup" issues.
Anyone who doesn't like ketchup on his steak (or steak under his ketchup) is welcome to skip this post entirely! This is religious war territory! :-) I prefer a slightly modified form of: begin-end Block Boundaries from: Code Complete by Steve McDonnell, chapter 18.3. But it's up to people to choose their own style when they're fully informed. And Rebol can put it's own style onto to 'mold-ed scripts. Andrew Martin Ayatollah of my indentation style... ICQ: 26227169 http://members.nbci.com/AndrewMartin/

 [10/12] from: lmecir:geocities at: 7-Oct-2000 1:09


Hi, I don't think, that I can bring any theoretical reasons for preferring one style over the other. I tried both. I must admit, that I liked the style Andrew is evangelizing more and tried to use it exclusively. The difference (for me) has shown itself when I wrote a script having six-page listing. Then I found out, that the orientation in the script using enclosing bracket indentation worsened drastically (for me) against its RT approved version. That is why I am currently using the RT approved version and knowing, that there is a good reason for it. Cheers Ladislav

 [11/12] from: larry:ecotope at: 6-Oct-2000 18:07


Hi Andrew, Joel I'll throw in one more implementation of transpose. Way back last January and December, Gerald Goertzel and I wrote many routines for linear algebra and matrix manipulation. We tested many versions of basic matrix functions like add, multiply, transpose and inverse for speed. Jerry won the speed contest for transpose with this function which assumes matrices are in the form created by the ARRAY function. (row major order) transpose: func [m /local r c mt] [ r: length? m c: length? m/1 mt: array reduce [c r] repeat i r [ repeat j c [ poke pick mt j i pick pick m i j ] ] mt ] Enjoy -Larry

 [12/12] from: jelinem1:nationwide at: 9-Oct-2000 9:38


>I disagree with Carl's reasoning here, but I can cope with it. I prefer
the better human readable style like this example:
> repeat Index Width [ > Column: make block! Width
<<quoted lines omitted: 3>>
> insert/only tail Results Column > ]
Why is this a better "human readable" format? I must not be human. Thanks for pointing me to Carl's style guide, however. I find it interesting that I've been using 4-char tabs and the same indentations for 10 years. - Michael Jelinek

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