domain variables

9 views
Skip to first unread message

Ralf Hemmecke

unread,
Jul 29, 2026, 4:52:40 PM (7 days ago) Jul 29
to fricas-devel
Hi Waldek,

may I ask you what exactly happens to a domain variable after

)compile file.spad
or
)lib FOO

Suppose I have the following example domain:

Foo: Exports == Implementation where
S ==> String
H ==> XHashTable(S,S)
Exports ==> with ...
Implementation ==> add
foo(h: H): S->S ==
(s: S): S +-> elt(h, s, "not there")
translateType: Reference(S->S) := ref foo(table()$H)
init(h: H): Void == setref(translateType, foo h)
blah(s: S): S ==
tt: S->S := deref translateType
tt(s)

Suppose I have called init(h) for some table h. Then

blah("hi")

returns some value, say "WORLD".

What can I expect that

blah("hi") returns after

)compile somefile.spad

? And more precisely, what is the value of translateType?
Or is it even dangerous to call blah after )compile?

Thank you in advance
Ralf

Waldek Hebisch

unread,
Jul 29, 2026, 5:58:31 PM (6 days ago) Jul 29
to 'Ralf Hemmecke' via FriCAS - computer algebra system
Currently domain variables (like other data associated with a doamin)
are stored in domain vector. Basically, when you evaluate domain
first evaluation is responsible for creating domain vector. Due
to caching in runtime system subsequent evaluations normally give
you the same domain vector. Thanks to this data stored in
domain vector is persistent. However, when you compile _any_ domain
the cached domains are discarded and re-computed on demad. So
after your compile command you get fresh domain vector where
'translateType' is empty table and behaviour of 'blah("hi") should
reflect this.

Theoretically it would be nice if compilation invalidated minimal
set of possible domains. But to be reasonably safe we should
recursively track users of given domain. Currently according to
HyperDoc (in my working copy of FriCAS) Integer has 757 users.
Add to that trasitive closure and it is not clear if any domain
would remain valid. Note that Integer uses 35 constructors, so
recompilation of any of them would invalidate Integer. Also,
currently we do not update "users" info on the fly, to get
minimal invalidation we would need to keep up to date "users"
info all the time.

--
Waldek Hebisch

Ralf Hemmecke

unread,
Jul 29, 2026, 6:25:00 PM (6 days ago) Jul 29
to fricas...@googlegroups.com
> Currently domain variables (like other data associated with a doamin)
> are stored in domain vector. Basically, when you evaluate domain
> first evaluation is responsible for creating domain vector. Due
> to caching in runtime system subsequent evaluations normally give
> you the same domain vector. Thanks to this data stored in
> domain vector is persistent. However, when you compile _any_ domain
> the cached domains are discarded and re-computed on demad. So
> after your compile command you get fresh domain vector where
> 'translateType' is empty table and behaviour of 'blah("hi") should
> reflect this.

Well, if it were a table, I can understand and accept that, but it is

translateType: Reference(S->S) := ref foo(table()$H)

i.e. translateType is a Reference to a function and this function comes
as a result of calling foo on an empty table.
Can I expect the value of foo(table()$H) to be stored there?
Or is foo(table()$H) computed a second time after a )compile?
In any case, since Reference is, in fact, a Record, I can expect that
this record hold a function S->S, that does something, but definitely
**not** crash FriCAS. And I would be happy if this "something" agreed
with foo(table()$H).

> Theoretically it would be nice if compilation invalidated minimal
> set of possible domains. But to be reasonably safe we should
> recursively track users of given domain.

Well, to be honest, I don't quite understand why it is necessary to
invalidate domain variables. OK, maybe my domain variable returns
something of type Foo and I am recompiling/modifying Foo. Then, of
course, that value of the domain variable most probably makes no sense
anymore.

Yes, yes, compilation shouldn't happen inside a session, only perhaps at
the beginning.

OK, maybe I can ask you about another thing that Kurt told me recently.

https://groups.google.com/g/fricas-devel/c/9nJ7TwyPKCE/m/81iByhJoBgAJ

25/04/2025.02:48
"""
People now seem to write little their own Spad and when they do
they just use ')lib' on each use. But in principle user could
compile own collection of .NRLIB-s in a private directory and
then use 'make_databases' to create version of FriCAS extended
by extra files (so that no ')lib' is needed to use extra functions).
"""

Can you provide some documentation of how I would be able to extend my
local version of FriCAS with my own set of .spad files, so that I only
have to compile them once and then in every future start of "fricas" my
code (say my QEta package) would be as available as any other FriCAS
constructor (maybe after ")expose").
That's not completely necessary, but I want to see it documented because
it avoids the necessity of having to recompile or run )lib at the
beginning of every session.

Thanks in advance.
Ralf

Qian Yun

unread,
Jul 29, 2026, 8:24:04 PM (6 days ago) Jul 29
to fricas...@googlegroups.com
On 7/30/26 6:24 AM, 'Ralf Hemmecke' via FriCAS - computer algebra system
wrote:
> it avoids the necessity of having to recompile or run )lib at the
> beginning of every session.

How long does compiling QEta take? Are you interested in a solution
that is based on ')savesystem' (was removed, but I plan to bring
it back)?

- Qian

Waldek Hebisch

unread,
Jul 29, 2026, 9:56:58 PM (6 days ago) Jul 29
to 'Ralf Hemmecke' via FriCAS - computer algebra system
On Thu, Jul 30, 2026 at 12:24:56AM +0200, 'Ralf Hemmecke' via FriCAS - computer algebra system wrote:
> > Currently domain variables (like other data associated with a doamin)
> > are stored in domain vector. Basically, when you evaluate domain
> > first evaluation is responsible for creating domain vector. Due
> > to caching in runtime system subsequent evaluations normally give
> > you the same domain vector. Thanks to this data stored in
> > domain vector is persistent. However, when you compile _any_ domain
> > the cached domains are discarded and re-computed on demad. So
> > after your compile command you get fresh domain vector where
> > 'translateType' is empty table and behaviour of 'blah("hi") should
> > reflect this.
>
> Well, if it were a table, I can understand and accept that, but it is
>
> translateType: Reference(S->S) := ref foo(table()$H)
>
> i.e. translateType is a Reference to a function and this function comes as a
> result of calling foo on an empty table.
> Can I expect the value of foo(table()$H) to be stored there?
> Or is foo(table()$H) computed a second time after a )compile?

There is new reference and its initialization computes new table.

> In any case, since Reference is, in fact, a Record, I can expect that this
> record hold a function S->S, that does something, but definitely **not**
> crash FriCAS. And I would be happy if this "something" agreed with
> foo(table()$H).

As I write, you get fresh domain. If your domain causes crash without
some extra steps to properly start it, then you will get a crash.
If your domain works from the start, it will work (but old data will
be lost).

> > Theoretically it would be nice if compilation invalidated minimal
> > set of possible domains. But to be reasonably safe we should
> > recursively track users of given domain.
>
> Well, to be honest, I don't quite understand why it is necessary to
> invalidate domain variables.

Well, strictly speaking it is not necessary to invalidate domain
variables. It is necessary to invalidate domain vector so that
the domain will pick new definition of functions that is uses.
But since domain variables are stored in domain vector, invalidating
domain vector also invalidate domain variables.

I was thinking about storing domain variables in Lisp variables.
It is should be not very hard for parameterless domains. And
something like this clearly is needed once we want to move
interpreter variables to Spad (clearly internal interpreter
variables must survive compilation of user domains).

> OK, maybe my domain variable returns something
> of type Foo and I am recompiling/modifying Foo. Then, of course, that value
> of the domain variable most probably makes no sense anymore.
>
> Yes, yes, compilation shouldn't happen inside a session, only perhaps at the
> beginning.

No. Normal Spad developement style is that you recompile your
domain many times keeping test data in interpreter variables.
I would rather say that actual variables as opposed to logically
constant things are rare, and your develpoments suffers when
you depend on them. Note that various caches should only
affect run time, but not the result, so viewed from outside
they are not variable and fact that caches are flushed in
normally minor thing.

> OK, maybe I can ask you about another thing that Kurt told me recently.
>
> https://groups.google.com/g/fricas-devel/c/9nJ7TwyPKCE/m/81iByhJoBgAJ
>
> 25/04/2025.02:48
> """
> People now seem to write little their own Spad and when they do
> they just use ')lib' on each use. But in principle user could
> compile own collection of .NRLIB-s in a private directory and
> then use 'make_databases' to create version of FriCAS extended
> by extra files (so that no ')lib' is needed to use extra functions).
> """
>
> Can you provide some documentation of how I would be able to extend my local
> version of FriCAS with my own set of .spad files, so that I only have to
> compile them once and then in every future start of "fricas" my code (say my
> QEta package) would be as available as any other FriCAS constructor (maybe
> after ")expose").
> That's not completely necessary, but I want to see it documented because it
> avoids the necessity of having to recompile or run )lib at the beginning of
> every session.

Basically, somebody needs to look at the code and test is. I may
do this at some time, but basically anybody could do this. I mean
with the info about file and function, there is modest amount of
code to read. From code and assisted by testing one needs to
infer form of parameters. As I wrote in this thread the code
seem to force relative names, which means that you would need to
put your files in a fixed relative position to FriCAS build
tree. Motivated users in the past digged deeper into FriCAS
internals...

--
Waldek Hebisch

Ralf Hemmecke

unread,
Jul 30, 2026, 3:27:13 AM (6 days ago) Jul 30
to fricas...@googlegroups.com
Well, it takes a minute or so, but since a use an .input File with all
the )lib commands which loads all the constructors in a few seconds, I
actually have no pressure to change to something else.

In fact, since I started with AXIOM, I have never used )savesystem.
I see )savesystem in the initial FriCAS repo, but it is not mentioned in
the index of the Jenks&Sutor AXIOM book.

Anyway, I guess, it would be an interesting feature, especially, if one
can then say

fricas --load-image "somename"

in order to start that image instead of FRICASsys.

Still, I am not sure whether it is worth the effort to bring it back.
I am not sure whether I would use it. It is similarly not clear, whether
I actually want the other method of creating an extension of FriCAS via
make_databases. I was just asking whether it is easy to
investigate/experiment with such an option, but I did not want to invest
much time in such a feature.

Thanks to you and Waldek for your answers.
Ralf
Reply all
Reply to author
Forward
0 new messages