Problem using record selectors

20 views
Skip to first unread message

Paul Onions

unread,
Nov 10, 2019, 5:02:29 AM11/10/19
to fricas-devel
I have a problem with FriCAS 1.3.5 using records inside a function.
As an example consider the following code, where I define a record
type and simple constructor and accessor functions:-

(1) -> R ==> Record(a:Integer, b:Integer)
Type: Void
(2) -> makeR(x:Integer, y:Integer):R == [x,y]
Function declaration makeR : (Integer, Integer) -> Record(a: Integer
,b: Integer) has been added to workspace.
Type: Void
(3) -> getA(r:R):Integer == r.a
Function declaration getA : Record(a: Integer,b: Integer) -> Integer
has been added to workspace.
Type: Void

I then create a record and call my accessor function on it to retrieve
one of its components. This works as expected.

(4) -> r := makeR(2,3)
Compiling function makeR with type (Integer, Integer) -> Record(a:
Integer,b: Integer)

(4) [a = 2, b = 3]
Type: Record(a: Integer,b: Integer)
(5) -> getA(r)
Compiling function getA with type Record(a: Integer,b: Integer) ->
Integer

(5) 2
Type: PositiveInteger

Now I'll create a variable in the global workspace of the same name as
one of the selectors. This breaks things, but this is expected
because the selector name used in my accessor function is evaluated
(as described in the documentation).

(6) -> a := 0
Compiled code for getA has been cleared.

(6) 0
Type: NonNegativeInteger
(7) -> getA(r)
There are 29 exposed and 5 unexposed library operations named elt
having 2 argument(s) but none was determined to be applicable.
Use HyperDoc Browse, or issue
)display op elt
to learn more about the available operations. Perhaps
package-calling the operation or using coercions on the arguments
will allow you to apply the operation.
Cannot find a definition or applicable library operation named elt
with argument type(s)
Record(a: Integer,b: Integer)
NonNegativeInteger
<... snipped ...>

So now I try to create a more robust accessor function to stop this
happening (following guidance in the documentation):-

(7) -> getA2(r:R):Integer == r.'a
Function declaration getA2 : Record(a: Integer,b: Integer) ->
Integer has been added to workspace.
Type: Void

but when I use it I get the following error:-

(8) -> getA2(r)

>> System error:
The value
"a"
is not of type
LIST


and similarly with other variants I've tried, such as:-

getA3(r:R):Integer ==
local a
r.a

getA4(r:R):Integer ==
local avar
avar := 'a
r.avar


So, is this a bug? And if so, is there a workaround?
Thanks.
Paul

Ralf Hemmecke

unread,
Nov 10, 2019, 7:53:00 AM11/10/19
to fricas...@googlegroups.com
Hello Paul,

I'm not a compiler developer, but if you are not afraid of writing a
short spad program, then you can get around it, see attachment.

)compile rec.spad


(2) -> x := makeRec(2,3)

(2) [a = 3, b = 2]
Type: MyRec
(3) -> recA(x)

(3) 3
Type: PositiveInteger
(4) -> a := 0

(4) 0
Type: NonNegativeInteger
(5) -> recA(x)

(5) 3
Type: PositiveInteger

If you don't want to do this, you must wait for some smarter person that
tells you how to define getA in order to refer to the right a.

I've found another workaround.

(1) -> Z ==> Integer
Type: Void
(2) -> R ==> Record(a: Z, b: Z)
Type: Void
(3) -> makeR(x:Integer, y:Integer):R == [x,y]
Function declaration makeR : (Integer, Integer) -> Record(a: Integer
,b: Integer) has been added to workspace.
Type: Void
(4) -> aForGetA := 'a

(4) a
Type: Variable(a)
(5) -> getA(r:R):Integer == r.aForGetA
Function declaration getA : Record(a: Integer,b: Integer) -> Integer
has been added to workspace.
Type: Void
(6) -> r := makeR(3, 5)
Compiling function makeR with type (Integer, Integer) -> Record(a:
Integer,b: Integer)

(6) [a = 3, b = 5]
Type: Record(a: Integer,b: Integer)
(7) -> getA(r)
Compiling function getA with type Record(a: Integer,b: Integer) ->
Integer

(7) 3
Type: PositiveInteger
(8) -> a := 0

(8) 0
Type: NonNegativeInteger
(9) -> getA r

(9) 3


Ralf
rec.spad

Paul Onions

unread,
Nov 10, 2019, 1:00:39 PM11/10/19
to fricas-devel
Hi Ralf,
Thanks for looking at this. As you suggest, I shall probably try
using a SPAD wrapper in some way.

Paul
> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fricas-devel/75d8afcb-9fd6-900a-5b2e-7c22a096cf5f%40hemmecke.org.

oldk1331

unread,
Nov 10, 2019, 8:59:07 PM11/10/19
to fricas...@googlegroups.com
Hi, another workaround I discovered is to use anonymous function:

getA := (r:R):INT +-> r.a

Paul Onions

unread,
Nov 11, 2019, 8:47:08 AM11/11/19
to fricas-devel
Hi oldk1331,

On Mon, 11 Nov 2019 at 01:59, oldk1331 <oldk...@gmail.com> wrote:
>
> Hi, another workaround I discovered is to use anonymous function:
>
> getA := (r:R):INT +-> r.a

But that only works if you do it before evaluating "a := 0" in a
session (because it evaluates "a" during the creation of the anonymous
function). So it works for the specific example I posted but is not a
general technique for robust record access.

Paul

Waldek Hebisch

unread,
Nov 12, 2019, 10:00:48 AM11/12/19
to fricas...@googlegroups.com
<snipped description of errors>
> So, is this a bug? And if so, is there a workaround?

I do not think this is a bug. Rather a deliberate limitation.
If you look deeper you will see consistent pattern: interpreter
language misses features needed for "large scale" programming,
instead tries to be somewhat forgiving for interactive use.

On small scale it is not hard to avoid name clashes, and while
interpreter makes some effort to limit clashes with library
functions it misses features available in Spad.

It would be nice to remove interpreter limitations, but given
that iterpreter design is based on then, this is large task
and prgress is slow.

--
Waldek Hebisch
Reply all
Reply to author
Forward
0 new messages