problems to be fixed before next snapshot

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

problems to be fixed before next snapshot

John W. Eaton-6
Does anyone know of any unresolved problems that should be fixed
before I make the next snapshot (2.1.37)?

Thanks,

jwe


Reply | Threaded
Open this post in threaded view
|

Re: problems to be fixed before next snapshot

Paul Kienzle-6
I don't know if it is a problem, but the new behaviour of
        for [key,val] = struct
is a bit disturbing to old code (or is it [val,key] --- I never remember).

val is now a cell array whereas old code expected it to be a octave value.

I understand why it has changed (how else can you process key,val pairs
when struct is an array?), but I would rather that it didn't make
the common case more awkward.  I don't have anything better to suggest
in its place.

- Paul
 
On Tue, Oct 22, 2002 at 04:27:56PM -0500, John W. Eaton wrote:
> Does anyone know of any unresolved problems that should be fixed
> before I make the next snapshot (2.1.37)?
>
> Thanks,
>
> jwe
>


Reply | Threaded
Open this post in threaded view
|

Re: problems to be fixed before next snapshot

John W. Eaton-6
On 22-Oct-2002, Paul Kienzle <[hidden email]> wrote:

| I don't know if it is a problem, but the new behaviour of
| for [key,val] = struct
| is a bit disturbing to old code (or is it [val,key] --- I never remember).
|
| val is now a cell array whereas old code expected it to be a octave value.
|
| I understand why it has changed (how else can you process key,val pairs
| when struct is an array?), but I would rather that it didn't make
| the common case more awkward.  I don't have anything better to suggest
| in its place.

OK, this prompted me to find a couple more bugs in structs.  I've just
checked in some fixes to CVS.  Now we have

  octave:1> x(1).a = 1; x.a
  ans = 1
  octave:2> for [val, key] = x, val, key, end
  val = 1
  key = a
  octave:3> x(2).a = 2; x.a
  ans =
  (
    [1] = 1
    [2] = 2
  )
  octave:4> for [val, key] = x, val, key, end
  val =
  (
    [1] = 1
    [2] = 2
  )
  key = a

This makes the single-element structure array special.  I'm not sure
that's the best choice, but it is backward compatible and somewhat
convenient.

The only trouble is writing code that must work when the number of
elements in the struct array is sometimes one and sometimes more than
one...

Suggestions?

jwe


Reply | Threaded
Open this post in threaded view
|

Re: problems to be fixed before next snapshot

Paul Kienzle-6
On Tue, Oct 22, 2002 at 10:33:40PM -0500, John W. Eaton wrote:

> On 22-Oct-2002, Paul Kienzle <[hidden email]> wrote:
>
> | I don't know if it is a problem, but the new behaviour of
> | for [key,val] = struct
> | is a bit disturbing to old code (or is it [val,key] --- I never remember).
> |
> | val is now a cell array whereas old code expected it to be a octave value.
> |
> | I understand why it has changed (how else can you process key,val pairs
> | when struct is an array?), but I would rather that it didn't make
> | the common case more awkward.  I don't have anything better to suggest
> | in its place.
>
> OK, this prompted me to find a couple more bugs in structs.  I've just
> checked in some fixes to CVS.  Now we have
>
>   octave:1> x(1).a = 1; x.a
>   ans = 1
>   octave:2> for [val, key] = x, val, key, end
>   val = 1
>   key = a
>   octave:3> x(2).a = 2; x.a
>   ans =
>   (
>     [1] = 1
>     [2] = 2
>   )
>   octave:4> for [val, key] = x, val, key, end
>   val =
>   (
>     [1] = 1
>     [2] = 2
>   )
>   key = a
>
> This makes the single-element structure array special.  I'm not sure
> that's the best choice, but it is backward compatible and somewhat
> convenient.
>
> The only trouble is writing code that must work when the number of
> elements in the struct array is sometimes one and sometimes more than
> one...

So what does the array case look like when struct(1) is special?

        [nr,nc] = size(x);
        if nr*nc != 1
          for [val, key] = x,
            for r = 1:nr
              for c = 1:nc
                process val{r,c} key
              end
            end
          end
        else
          for [val, key] = x,
            process val key
          end
        endif

What does the non-array case look like when struct(1) isn't special?

        for [val, key] = x,
          process val{1} key
        end

The fact that the process code needs to be repeated in the array case with
struct(1) special is bad, and IMHO outweighs the convenience gained in the
common case.  Any other suggestions?

If struct(1) is not special, I would like some way to conveniently deal
with the change in semantics.  On possibility is a preprocessor for those
who want to support multiple versions of octave and/or matlab with the same
code base.  Another possibility is to use runtime tests, but I would prefer
to avoid those.  If fact runtime tests won't work for varargin vs ...  
A third possibility is to simply drop support for older versions of octave
from octave-forge.

For a preprocessor I could do something such as

        % code %#if version test
        code %#if version test

Then the preprocessor could add or remove the leading '%' depending on
the version you specify when you run it.  

Suggestions?


Reply | Threaded
Open this post in threaded view
|

Re: problems to be fixed before next snapshot

John W. Eaton-6
On 23-Oct-2002, Paul Kienzle <[hidden email]> wrote:

| So what does the array case look like when struct(1) is special?
|
| [nr,nc] = size(x);
| if nr*nc != 1
|  for [val, key] = x,
|    for r = 1:nr
|      for c = 1:nc
| process val{r,c} key
|      end
|    end
|  end
| else
|  for [val, key] = x,
|    process val key
|  end
|         endif

Hmm.  Currently, Octave can only do one-dimensional struct arrays,
though that should probably change soon.

| What does the non-array case look like when struct(1) isn't special?
|
| for [val, key] = x,
|  process val{1} key
| end
|
| The fact that the process code needs to be repeated in the array case with
| struct(1) special is bad, and IMHO outweighs the convenience gained in the
| common case.  Any other suggestions?

Right, I think it would be better to not have a special case here.

Should I change it back before the release?  If so, then you will have
some backward compatibility problems.

Note that in Matlab, if you write

  x(1).a = 1, x(2).a = 2, x.a

The result of x.a is a "comma-separated list" so you can do

  foo (x.a)

to pass the elements of the comma-separated list as separate arguments
to the function foo, but you can't write

  y = x.a

to capture the elements of the comma-separated list in a single
variable.

If Octave is changed to have multi-dimensional struct arrays, then
something like nd_struct.a would have to return a cell array, not a
simple list.  So there are going to be some more growing pains.  For
now, I think it would be more useful to make 2.1.37 available, so how
about if I leave it as a special case?  That way we are backward
compatible.  I'm planning to work on N-dimensional matrices next
anyway, so that will be a reasonable time to look at this again.

| If struct(1) is not special, I would like some way to conveniently deal
| with the change in semantics.  On possibility is a preprocessor for those
| who want to support multiple versions of octave and/or matlab with the same
| code base.  Another possibility is to use runtime tests, but I would prefer
| to avoid those.  If fact runtime tests won't work for varargin vs ...  
| A third possibility is to simply drop support for older versions of octave
| from octave-forge.
|
| For a preprocessor I could do something such as
|
| % code %#if version test
| code %#if version test
|
| Then the preprocessor could add or remove the leading '%' depending on
| the version you specify when you run it.  

Building your own external preprocessor is always possible, but I'm
not really interested in making a preprocessor a part of Octave.  I
know that's not as convenient, but I think that adding a preprocessor
would add a lot of complexity that I'd rather avoid.

jwe


Reply | Threaded
Open this post in threaded view
|

Re: problems to be fixed before next snapshot

Paul Kienzle-6
On Wed, Oct 23, 2002 at 12:49:31PM -0500, John W. Eaton wrote:

> On 23-Oct-2002, Paul Kienzle <[hidden email]> wrote:
>
> | So what does the array case look like when struct(1) is special?
> |
> | [nr,nc] = size(x);
> | if nr*nc != 1
> |  for [val, key] = x,
> |    for r = 1:nr
> |      for c = 1:nc
> | process val{r,c} key
> |      end
> |    end
> |  end
> | else
> |  for [val, key] = x,
> |    process val key
> |  end
> |         endif
>
> Hmm.  Currently, Octave can only do one-dimensional struct arrays,
> though that should probably change soon.

With multi-dimensional struct arrays this gets even uglier because
we don't know how many loops we need.  

Should we extend all of our primitives to handle cell arrays?  

E.g., is f({A, B, C}) == {f(A), f(B), f(C)} for all of our mappers?

How about functions which operate on arrays?  Is

        [Q,R]=qr({A,B,C})

equivalent to

        X={A,B,C};
        for i=1:length(X),
            [Q{i}, R{i}] = qr(X{i})
        end


>
> | What does the non-array case look like when struct(1) isn't special?
> |
> | for [val, key] = x,
> |  process val{1} key
> | end
> |
> | The fact that the process code needs to be repeated in the array case with
> | struct(1) special is bad, and IMHO outweighs the convenience gained in the
> | common case.  Any other suggestions?
>
> Right, I think it would be better to not have a special case here.
>
> Should I change it back before the release?  If so, then you will have
> some backward compatibility problems.
>
> Note that in Matlab, if you write
>
>   x(1).a = 1, x(2).a = 2, x.a
>
> The result of x.a is a "comma-separated list" so you can do
>
>   foo (x.a)

Ick.

>
> to pass the elements of the comma-separated list as separate arguments
> to the function foo, but you can't write
>
>   y = x.a
>
> to capture the elements of the comma-separated list in a single
> variable.

But can you write the following?

        y = { x.a }

>
> If Octave is changed to have multi-dimensional struct arrays, then
> something like nd_struct.a would have to return a cell array, not a
> simple list.  So there are going to be some more growing pains.  For
> now, I think it would be more useful to make 2.1.37 available, so how
> about if I leave it as a special case?  That way we are backward
> compatible.  I'm planning to work on N-dimensional matrices next
> anyway, so that will be a reasonable time to look at this again.

Okay.

>
> | If struct(1) is not special, I would like some way to conveniently deal
> | with the change in semantics.  On possibility is a preprocessor for those
> | who want to support multiple versions of octave and/or matlab with the same
> | code base.  Another possibility is to use runtime tests, but I would prefer
> | to avoid those.  If fact runtime tests won't work for varargin vs ...  
> | A third possibility is to simply drop support for older versions of octave
> | from octave-forge.
> |
> | For a preprocessor I could do something such as
> |
> | % code %#if version test
> | code %#if version test
> |
> | Then the preprocessor could add or remove the leading '%' depending on
> | the version you specify when you run it.  
>
> Building your own external preprocessor is always possible, but I'm
> not really interested in making a preprocessor a part of Octave.  I
> know that's not as convenient, but I think that adding a preprocessor
> would add a lot of complexity that I'd rather avoid.

A preprocessor in octave does very little good in the short term.  Old
versions don't have it, so I can't use it to make code work on old and
new versions.  In the long term it doesn't help people who want to support
both matlab and octave because matlab won't have the same preprocessor.
So yes it should be an external preprocessor.

I'm thinking that it should be run at build time, which makes it part
of our package manager if/when such a beast ever evolves into being.

The trick is to automatically update the installed packages when a new
version of octave is installed.  In addition to rebuilding the oct-files
we will also need to reprocess the script files [yes, Dirk, I know R
does this already ;-].  But this is a topic for another day.

- Paul


Reply | Threaded
Open this post in threaded view
|

Re: problems to be fixed before next snapshot

John W. Eaton-6
On 23-Oct-2002, Paul Kienzle <[hidden email]> wrote:

| Should we extend all of our primitives to handle cell arrays?  
|
| E.g., is f({A, B, C}) == {f(A), f(B), f(C)} for all of our mappers?
|
| How about functions which operate on arrays?  Is
|
| [Q,R]=qr({A,B,C})
|
| equivalent to
|
| X={A,B,C};
| for i=1:length(X),
|    [Q{i}, R{i}] = qr(X{i})
| end

Probably just about as good to have an "apply" function for this (and
certainly less work to implement!).

| > to pass the elements of the comma-separated list as separate arguments
| > to the function foo, but you can't write
| >
| >   y = x.a
| >
| > to capture the elements of the comma-separated list in a single
| > variable.
|
| But can you write the following?
|
| y = { x.a }

Yes.  I had forgotten about that.  This is another change that is
needed for Octave's parser.

jwe