apjanke / octave-tablicious

Table (relational, tabular data) implementation for GNU Octave
https://apjanke.github.io/octave-tablicious/
GNU General Public License v3.0
29 stars 11 forks source link

"empty" static method for string #98

Closed gllmflndn closed 2 years ago

gllmflndn commented 2 years ago

Matlab defines an "empty" static method for string that returns a 0x0 empty string array:

>> string.empty

ans = 

  0x0 empty string array
gllmflndn commented 2 years ago

An alternative way to create an empty string array in Matlab is as follow:

>> a = string ();
>> a(1) = [];
>> a = reshape (a, [0 0]);
>> a

a = 

  0x0 empty string array

but that doesn't work either here:

>> a(1) = [];
error: =: nonconformant arguments (op1 is 1x1, op2 is 0x0)
error: called from
    subsasgnParensPlanar at line 1093 column 33
    subsasgn at line 1052 column 16
apjanke commented 2 years ago

Added a string.empty static method in https://github.com/apjanke/octave-tablicious/commit/c61f19ef25dff08aaaf2e29786db13c54fc74b51.

This code sequence:

a = string ();
a(1) = [];
a = reshape (a, [0 0]);

is a little bit roundabout. a = string () creates a scalar string array containing the empty string (""). Then a(1) = [] deletes the first and only element of that array, leaving you with a 1-by-0 empty string array. Then a = reshape (a, [0 0]) changes its size. You could skip the element deletion step and do a = string ([]); a = reshape(a, [0 0]); (for any empty size, not just specifically [0 0]). That way works in Tablicious.

The a(1) = [] element deletion step is what's broken here. That (and your whole code sequence) should work, but I'm having some issues with the underlying Octave OOP stuff related to subsref overriding; not sure how to fix that. Want to submit that as a separate bug report?

gllmflndn commented 2 years ago

Thank you! Didn't think of the string ([]) syntax.

I will open a new bug report for a(1) = [].

apjanke commented 2 years ago

Cool! Yeah, constructors for string arrays and the like have always struck me as a little weird: The default string() constructor gets you a scalar nonmissing blank string (""), and so will string('') for an empty 0-by-0 char input (due to the weird edge case in '' semantics from Matlab's historical string behavior). string([]) (or categorical([]) or basically anytype([]) is a conventional way of getting an empty array of something, even if their constructors don't normally support numeric inputs.

But personally I like the blah.empty() static method that you brought up here. It was just an oversight on my part that I didn't include one for string. (I probably forgot them for categorical and datetime too; I should go check that.)

gllmflndn commented 2 years ago

I only heard about the empty static method very recently while Matlab documentation mentions it was introduced for R2008a!

apjanke commented 2 years ago

Aha! From your link:

image

So in Matlab, there's a default Static empty method you get for free in your classdef classes, and only need to supply a definition for one if you want to customize it. Like, here's a jl.code.CodeBase classdef class I wrote in another project, which does not define an empty method, running in Matlab R2021a:

>> which jl.code.CodeBase
/Users/janke/repos/janklab-core/Mcode/classes/+jl/+code/CodeBase.m  % jl.code.CodeBase constructor
>> jl.code.CodeBase.empty
ans = 
  0×0 CodeBase array with properties:
    paths
    codeRoots
>> jl.code.CodeBase.empty([0 0 3 4])
ans = 
  0×0×3×4 CodeBase array with properties:
    paths
    codeRoots

Looks like Octave doesn't provide the default empty method, at least not in the versions we're using here, so all classdefs need to define their own? Maybe that's why I missed adding one here.

apjanke commented 2 years ago

Yeah, I'm going to pursue this issue about Octave not providing a default Static empty method for classdefs with the core Octave developers. @gllmflndn would you like to get notifications for that discussion? If so, I'll reopen this issue here; if not, I'll create a new separate issue for that.