From bf1db6c9b58d240dfe8d73634dde07b493133262 Mon Sep 17 00:00:00 2001 From: Andrew Janke Date: Sat, 3 Feb 2024 20:50:46 -0500 Subject: [PATCH] add idempotent one-arg constructor forms for string, datetime, etc (but not table) The table class does not get one, because that's not how Matlab's table(x) constructor works, and would be a type discontinuity. Instead, it creates a new one-variable table whose variable contains the table passed to the constructor. (That is, it creates a table containing a nested table.) --- inst/calendarDuration.m | 5 +++++ inst/categorical.m | 4 ++++ inst/datetime.m | 9 ++++++--- inst/duration.m | 7 +++++-- inst/localdate.m | 5 ++++- inst/string.m | 14 +++----------- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/inst/calendarDuration.m b/inst/calendarDuration.m index 23d583f5..6ea5062b 100644 --- a/inst/calendarDuration.m +++ b/inst/calendarDuration.m @@ -125,6 +125,11 @@ # this = calendarDuration (..., 'Format',displayFormat) args = varargin; + if (nargin == 1 && isa (args{1}, 'calendarDuration')) + this = args{1}; + return + endif + # Peel off options knownOptions = {'Format'}; opts = struct; diff --git a/inst/categorical.m b/inst/categorical.m index 706d29ee..ef34f619 100644 --- a/inst/categorical.m +++ b/inst/categorical.m @@ -238,6 +238,10 @@ if (nargin == 0) return endif + if (nargin == 1 && isa (x, 'categorical')) + this = x; + return + end validOptions = {'Ordinal', 'Protected'}; [opts, args] = peelOffNameValueOptions (varargin, validOptions); diff --git a/inst/datetime.m b/inst/datetime.m index d67da593..5f219252 100644 --- a/inst/datetime.m +++ b/inst/datetime.m @@ -129,9 +129,9 @@ # Peel off options args = varargin; - knownOptions = {'Format','InputFormat','Locale','PivotYear','TimeZone'}; + knownOptions = {"Format", "InputFormat", "Locale", "PivotYear", "TimeZone"}; opts = struct; - while (numel (args) >= 3 && isa (args{end-1}, 'char') ... + while (numel (args) >= 3 && isa (args{end-1}, "char") ... && ismember (args{end-1}, knownOptions)) opts.(args{end-1}) = args{end}; args(end-1:end) = []; @@ -147,7 +147,10 @@ dnums = now; case 1 x = args{1}; - if (isnumeric (x)) + if (isa (x, 'datetime')) + this = x; + return + elseif (isnumeric (x)) # Convert date vectors dnums = datenum (x); elseif (ischar (x) || iscellstr (x) || isa (x, 'string')) diff --git a/inst/duration.m b/inst/duration.m index b9d8b72e..de6c8ecf 100644 --- a/inst/duration.m +++ b/inst/duration.m @@ -96,7 +96,7 @@ #DURATION Construct a new duration array args = varargin; # Peel off options - knownOptions = {'InputFormat','Format'}; + knownOptions = {'InputFormat', 'Format'}; opts = struct; while (numel (args) >= 3 && isa (args{end-1}, 'char') ... && ismember (args{end-1}, knownOptions)) @@ -109,7 +109,10 @@ return case 1 in = args{1}; - if (isnumeric (in)) + if (isa (in, 'duration')) + this = in; + return + elseif (isnumeric (in)) switch (size (in, 2)) case 3 [H, MI, S] = deal (in(:,1), in(:,2), in(:,3)); diff --git a/inst/localdate.m b/inst/localdate.m index 5e389c5d..fadc65c9 100644 --- a/inst/localdate.m +++ b/inst/localdate.m @@ -105,7 +105,10 @@ dnums = floor (now); case 1 x = args{1}; - if (isnumeric (x)) + if (isa (x, 'localdate')) + this = x; + return + elseif (isnumeric (x)) # Convert datenums mustBeIntOrNanOrInf (x, 'input'); dnums = double (x); diff --git a/inst/string.m b/inst/string.m index de387751..e9b9236c 100644 --- a/inst/string.m +++ b/inst/string.m @@ -174,23 +174,15 @@ ## @end itemize ## ## @end deftypefn - function this = string(in, varargin) - # TODO: Support a 'MapMissing' option to map "standard missing values" - # (empty strings, NaN, NaT) to string missings. - # + function this = string(in) # TODO: Maybe fall back to calling cellstr() on arbitrary input objects. if (nargin == 0) return endif if (isa (in, "string")) - # Copy properties, because I don't know if a full-array pass-through - # works in Octave. -apj - # this = in; % That is, don't do this. - this.strs = in.strs; - this.tfMissing = in.tfMissing; + this = in; return - endif - if (ischar (in)) + elseif (ischar (in)) this.strs = cellstr (in); this.tfMissing = false (size (this.strs)); elseif (iscell (in))