2

I have this for array :

ary1d_new(Size,Sym,ArySym,Ary) :- 
    functor(Ary,ArySym,Size), 
    forall(arg(X,Ary,_), nb_setarg(X,Ary,Sym)).
ary1d_get(Pos,Ary,Val) :- arg(Pos,Ary,Val).
ary1d_set(Pos,Ary,Val) :- nb_setarg(Pos,Ary,Val).

trying to turn it to logtalk object, but is not happening for me

:- object(array, instantiates(array)).

    :- initialization(init).
    :- private(init/0).

    :- public(ary/1).
    :- dynamic(ary/1).
    ary(_).

    :- public([new1d/2, set1d/2, get1d/2]).

    new1d(Size,Sym) :- 
        functor(Ary,ary,Size), 
        forall(arg(X,Ary,_), nb_setarg(X,Ary,Sym)),writeln(Ary).
    get1d(Pos,Val) :- arg(Pos,::ary,Val).
    set1d(Pos,Val) :- nb_setarg(Pos,::ary,Val).

    init :- true.

:- end_object.

:- object(g, instantiates(array)).
:- end_object.


?- g::new1d(5,0).
ary(0,0,0,0,0)
true.

?- g::set1d(2,7).
false.

?- g::get1d(2,D).
false.

what is the correct way ? functor vs ::ary is confusing me


came up with this for Obj attributes out of the array storage :

:- public(test/2).
test(Size, Value) :- test(Size,Value,i(Size)).
:- public(test/3).
test(Size, Value, Info) :-
    functor(A, s, Size),
    forall(
        arg(Arg, A, _),
        nb_setarg(Arg, A, Value)
    ),
    _Array_ = a(Info,A).

?- ary(A)::test(5,0).
A = a(i(5), s(0, 0, 0, 0, 0)).
sten
  • 7,028
  • 9
  • 41
  • 63

1 Answers1

1

Note that you can only call the nb_setarg/3 on compound term arguments. A possible alternative could be to use a parametric object:

:- object(array(_Array_)).

    :- public(new/2).
    new(Size, Value) :-
        functor(_Array_, a, Size),
        forall(
            arg(Arg, _Array_, _),
            nb_setarg(Arg, _Array_, Value)
        ).

    :- public(get/2).
    get(Arg, Value) :-
        arg(Arg, _Array_, Value).

    :- public(set/2).
    set(Arg, Value) :-
        nb_setarg(Arg, _Array_, Value).

:- end_object.

A sample query would be:

?- {arrays}.
% [ .../arrays.lgt loaded ]
% (0 warnings)
true.

?- array(Array)::(new(5,0), set(2, 7), get(2, Value)).
Array = a(0, 7, 0, 0, 0),
Value = 7.

Note that the _Array_ parameter variable is a logical variable. Therefore, it doesn't survive from top-level query to top-level query:

?- array(Array)::(new(5,0), set(2, 7), get(2, Value)).
Array = a(0, 7, 0, 0, 0),
Value = 7.

?- array(Array)::new(5,0).
Array = a(0, 0, 0, 0, 0).

?- array(Array)::set(2, 7).
ERROR: Arguments are not sufficiently instantiated
Paulo Moura
  • 18,373
  • 3
  • 23
  • 33
  • why this works ..,arg(2,Array,V) ...but not ..., Array::get(2,V)? – sten Apr 15 '22 at 19:16
  • For something like `Array::get(2,V)` to work, `Array` would need to be a compound term. That's not the case in your example. – Paulo Moura Apr 15 '22 at 19:55
  • havent seen this syntax a(A)::(....) . is this compound term ? Also can u pass Array around ? – sten Apr 15 '22 at 21:21
  • See the link in my answer. Not sure I understand your question: any term can be passed around. – Paulo Moura Apr 15 '22 at 21:57
  • i guess i'm asking how do i do .... array(A)::(new(5,0)), ..... , set(2, 7), .... , get(2, Value) .. i.e when i have to do something in between .. it is probably a syntax issue – sten Apr 15 '22 at 22:09
  • 1
    In the sample query in my answer, that's just syntactic sugar. You can do instead e.g. `array(Array)::new(5,0), foo,array(Array):: set(2, 7), bar, array(Array)::get(2, Value), baz.`. – Paulo Moura Apr 15 '22 at 22:25
  • thats what i was looking for. last Q: does param-objs allow attributes that are not part of the "compound term" ... f.e. for 2D array i have to store somewhere Width, Height outside of the term that act as storage – sten Apr 16 '22 at 00:26
  • Why not store width and height as part of the term? That would mean that when passing the term around, all necessary data would be part of the term. – Paulo Moura Apr 16 '22 at 09:03
  • cause i want to implement different inherited structures such as 2D, 1D-row-based 2D, views, ... out of storage data is the reason i want to use objects – sten Apr 16 '22 at 15:07