TransWikia.com

Bug in Transpose in Mathematica 12.2?

Mathematica Asked on April 17, 2021

*In[1]=* Transpose[{a, b}]

returned in earlier versions of Mathematica (e.g Mathemtica 12.1) simply

*Out[1]=* Transpose[{a, b}]

together with the warning: "Transpose::nmtx: The first two levels of {a,b} cannot be transposed."

However in Mathematica 12.2 (on Windows10) the output is:

*Out[1]=* {a,b}

The Transpose has disappeared. Is this a bug or a feature?

For me, it is problem, because this new behavior is breaking my existing code, where I have functions similar to:

getfromdatabase[key_String]:=CallToCppCodeAndReturnListsOfValues[key]
getfromdatabase[expr_]:=expr/. key_String :>  getfromdatabase[key]

In previous versions (<12.2) users of my code could execute

getfromdatabase[ Transpose[{"firstname", "lastname", "salary"-"rent"}] ]

and the output was for example:

{ {David, Smith, somenumber}, {Lisa, Garbo, someothernumber}, ... }

Now, in 12.2, one gets:

{ {David, Lisa,...}, {Smith, Garbo, ...}, {somenumber, someothernumber, ...}}

How can I change getfromdatabase to get back the old output using the same input as before?
(Sure, in the example above, one could apply Transpose after calling the function. But in other calls there might be calls of Transpose more nested inside the expression, like getfromdatabase[ Transpose[{"firstname", "lastname", Transpose[{"salary","rent"}]] ])
Thanks!

2 Answers

Presumably, in some part of your code, you check for the head Transpose being present. So, you can make your own head t that behaves like the old transpose, then check for the head t instead of Transpose in those parts of the code. You could possibly define it like this:

t[list : {__List}] := Transpose[list]
t[list_, spec_] := Transpose[list, spec]

so that only lists of lists will be actually transposed, and the rest will remain enclosed with t, as no definition is matched.

Then, we need to give getfromdatabase the attribute HoldAll or HoldFirst, rename the previous definition of getfromdatabase internally as, say, getfromdatabase0, and replace Transpose heads with t before passing to getfromdatabase0. E.g.:

SetAttributes[getfromdatabase, HoldAll]
getfromdatabase[expr_] := getfromdatabase0[ReleaseHold[Hold[expr] /. Transpose -> t]]

This is, of course, just one way to fix your code; disclaimer that there might be other, better ways! :)

Answered by thorimur on April 17, 2021

Inspired by thorimur's answer, I came up with the following, which meets maybe better my original intention of how getfromdatabase should work in general.

SetAttributes[getfromdatabase, HoldFirst]
getfromdatabase[key_String]:=CallToCppCodeAndReturnListsOfValues[key]
getfromdatabase[expr_]:=ReleaseHold[ Hold[expr]/. key_String :>  getfromdatabase[key] ]

However, with this, I do not exactly get back the behavior of my function in ML <12.2. I need to check if this has unwanted side effects for some users. If yes, thorimur's procedure will be better for me, because it specifically adresses the problem with Transpose.

Answered by dnet on April 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP