Re: [libreoffice-users] Basic : How to write a CopyValue() recursive function ?

2018-06-06 Thread Regina Henschel

Hi Patrick,

I have currently no time to look at your problem in detail. But in 
general byval for an array does not copy the array to the subroutine, 
but only hand over a pointer. A discussion of this problem and a 
solution using redim preserve is in 
https://ask.libreoffice.org/en/question/155179/basic-byval-and-arrays/


Kind regards
Regina

Patrick Gelin schrieb am 06.06.2018 um 09:40:

Hi,

I'm traying to build a recursive CopyValue(aVariant) function. The idea
is a simple copy for scalar values, a recursive Items copy for array
(max 5 dimensions arrays), and a call to Clone() method for (pseudo)
objects. The function can't copy structures, I will use (pseudo) objects
Clone() method...

But my code (Cf. "TEST COPY VALUE CODE" below) failed at CopyArray in
Select Case 2 at line :

result(i1 - Bounds(1,1), i2 - Bounds(2,1)) = CopyValue(value)

The error message (in french) is :
"L'erreur #91 (Variable d'objet non définie) s'est produite à la ligne
90 dans _DataUtil"

The error is triggered with the recursive function call at
CopyValue(value). It look's like reentrance is not supported by the
function... I'm using LibreOffice 5.2.7.2. (x32) with Linux Debian. I
tested also with LIbreOffice 5.4.2.2 (x64) with Windows.

So to test recursive call I tried with a recursive sample function,
CalculateFactorial(Number).  And it's work fine. The sample is :

Sub TestFactorial
  Msgbox CalculateFactorial(  42 )' Displays 1,40500611775288E+51
  Msgbox CalculateFactorial( -42 )' Displays "Invalid number for
factorial!"
  Msgbox CalculateFactorial( 3.14 )   ' Displays "Invalid number for
factorial!"
End Sub

Function CalculateFactorial( Number )
  If Number < 0 Or Number <> Int( Number ) Then
CalculateFactorial = "Invalid number for factorial!"
  ElseIf Number = 0 Then
CalculateFactorial = 1
  Else
' This is the recursive call:
CalculateFactorial = Number * CalculateFactorial( Number - 1 )
  Endif
End Function

I'm wondering If my problem is coming from the fact recursive call could
be only at result affectation line. In this sample it's the line :

CalculateFactorial = Number * CalculateFactorial( Number - 1 )

But I can't imagine a simple way to do the same with my algorithm,
because copying an array need a For Next recursive call for each item
... An array is not a Lisp list ...

I may imagine two solutions :
1. Using Lisp paradigm with first() and rest() functions, splitting
array... But how to build an array reference starting with LBound()+1
item of the array ?
2. Trying serialize the recursive array to a large String value and use
an other unserialize function to rebuild the structure 

Do you know if an other CopyValue already exist ? An other Idea ?

Thank you for your advises !
Patrick

Rem
--

Rem TEST COPY VALUE CODE
Rem
--

Sub TestCopyValue()

Dim tableau(1 to 3, 1 to 2)
Dim result As Variant

tableau(1,1) = "AZERTY"
tableau(1,2) = 12
tableau(2,1) = Array("item1", "item2")
tableau(2,2) = Array(Array("11", "12"), Array("21", "22"))
tableau(3,1) = "A"
tableau(3,2) = 99

result = CopyValue(tableau)
End Sub

' #FONCTION#
==
' Nom. ..: ArrayDim
' Description ...: Un tableau avec les indices de chaque dimension du
tableau
'en parametre. Le nombre maximum de dimension du
tableau
'en parametre est limité à 5 sinon une exception n°9
'est émise.
' Parametres :
' Syntaxe ...:
' Resultat . : La première célule de la première ligne du tableau
Result(0, 1)
'contient le nombre de dimensions. Les lignes
Result(1, ) à
'Result(5, ) contiennent les deux indices LBound()
et UBound()
'de chaque dimension.
' Auteur : Patrick
' Modifié ...:
' Remarques .:
' Relations .:
' Liens .:
' Example ...:
Function ArrayDim(anArray As variant) As Variant

Dim Bounds(0 to 6, 1 to 2) As Long 'Le couple des index
(LBound,UBound) d'une dimension du tableau
Dim i As Integer

on local error goto Exit_Function

for i = 1 to 6 step 1
Bounds(i, 1) = LBound(anArray(), i)
Bounds(i, 2) = UBound(anArray(), i)
Next

Exit_Function:
On Error Resume Next
If not EstVide(Bounds(6, 1)) Then
Err = 9 'Index hors de la plage définie. Exit !
Exit Function
EndIf

'Par convention, le nombre de dimensions est indiqué
'dans la première ligne du tableau.
Bounds(0,1) = i-1
ArrayDim = Bounds
End Function

' #FONCTION#
==
' Nom. ..: CopyArray
' Description ...: Copie un tableau par valeur de manière 

[libreoffice-users] Basic : How to write a CopyValue() recursive function ?

2018-06-06 Thread Patrick Gelin

Hi,

I'm traying to build a recursive CopyValue(aVariant) function. The idea 
is a simple copy for scalar values, a recursive Items copy for array 
(max 5 dimensions arrays), and a call to Clone() method for (pseudo) 
objects. The function can't copy structures, I will use (pseudo) objects 
Clone() method...


But my code (Cf. "TEST COPY VALUE CODE" below) failed at CopyArray in 
Select Case 2 at line :


result(i1 - Bounds(1,1), i2 - Bounds(2,1)) = CopyValue(value)

The error message (in french) is :
"L'erreur #91 (Variable d'objet non définie) s'est produite à la ligne 
90 dans _DataUtil"


The error is triggered with the recursive function call at 
CopyValue(value). It look's like reentrance is not supported by the 
function... I'm using LibreOffice 5.2.7.2. (x32) with Linux Debian. I 
tested also with LIbreOffice 5.4.2.2 (x64) with Windows.


So to test recursive call I tried with a recursive sample function, 
CalculateFactorial(Number).  And it's work fine. The sample is :


Sub TestFactorial
  Msgbox CalculateFactorial(  42 )    ' Displays 1,40500611775288E+51
  Msgbox CalculateFactorial( -42 )    ' Displays "Invalid number for 
factorial!"
  Msgbox CalculateFactorial( 3.14 )   ' Displays "Invalid number for 
factorial!"

End Sub

Function CalculateFactorial( Number )
  If Number < 0 Or Number <> Int( Number ) Then
    CalculateFactorial = "Invalid number for factorial!"
  ElseIf Number = 0 Then
    CalculateFactorial = 1
  Else
    ' This is the recursive call:
    CalculateFactorial = Number * CalculateFactorial( Number - 1 )
  Endif
End Function

I'm wondering If my problem is coming from the fact recursive call could 
be only at result affectation line. In this sample it's the line :


CalculateFactorial = Number * CalculateFactorial( Number - 1 )

But I can't imagine a simple way to do the same with my algorithm, 
because copying an array need a For Next recursive call for each item 
... An array is not a Lisp list ...


I may imagine two solutions :
1. Using Lisp paradigm with first() and rest() functions, splitting 
array... But how to build an array reference starting with LBound()+1 
item of the array ?
2. Trying serialize the recursive array to a large String value and use 
an other unserialize function to rebuild the structure 


Do you know if an other CopyValue already exist ? An other Idea ?

Thank you for your advises !
Patrick

Rem 
--

Rem                             TEST COPY VALUE CODE
Rem 
--

Sub TestCopyValue()

    Dim tableau(1 to 3, 1 to 2)
    Dim result As Variant

    tableau(1,1) = "AZERTY"
    tableau(1,2) = 12
    tableau(2,1) = Array("item1", "item2")
    tableau(2,2) = Array(Array("11", "12"), Array("21", "22"))
    tableau(3,1) = "A"
    tableau(3,2) = 99

    result = CopyValue(tableau)
End Sub

' #FONCTION# 
==

' Nom. ..: ArrayDim
' Description ...: Un tableau avec les indices de chaque dimension du 
tableau
'                    en parametre. Le nombre maximum de dimension du 
tableau

'                    en parametre est limité à 5 sinon une exception n°9
'                    est émise.
' Parametres :
' Syntaxe ...:
' Resultat . : La première célule de la première ligne du tableau 
Result(0, 1)
'                    contient le nombre de dimensions. Les lignes 
Result(1, ) à
'                    Result(5, ) contiennent les deux indices LBound() 
et UBound()

'                    de chaque dimension.
' Auteur : Patrick
' Modifié ...:
' Remarques .:
' Relations .:
' Liens .:
' Example ...:
Function ArrayDim(anArray As variant) As Variant

    Dim Bounds(0 to 6, 1 to 2) As Long 'Le couple des index 
(LBound,UBound) d'une dimension du tableau

    Dim i As Integer

    on local error goto Exit_Function

    for i = 1 to 6 step 1
        Bounds(i, 1) = LBound(anArray(), i)
        Bounds(i, 2) = UBound(anArray(), i)
    Next

Exit_Function:
    On Error Resume Next
    If not EstVide(Bounds(6, 1)) Then
        Err = 9 'Index hors de la plage définie. Exit !
        Exit Function
    EndIf

    'Par convention, le nombre de dimensions est indiqué
    'dans la première ligne du tableau.
    Bounds(0,1) = i-1
    ArrayDim = Bounds
End Function

' #FONCTION# 
==

' Nom. ..: CopyArray
' Description ...: Copie un tableau par valeur de manière récursive.
' Parametres : aVariant as variant : Un tableau
' Syntaxe ...:
' Resultat . :  Le résultat est toujours un tableau de variant. La 
limite
'                    LBound est toujours 0, il y a donc un offset 
UBound() - LBound()

'                    des indices du tableau original.
' Auteur : Patrick
' Modifié ...:
'