From 1b14b5910cc30967346f46d0541a31b8a8d4a929 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 5 Apr 2023 22:47:05 +0200 Subject: [PATCH] Allow iterating over Julia objects from within GAP --- CHANGES.md | 4 ++++ pkg/JuliaInterface/gap/adapter.gi | 38 ++++++++++++++++++++++++++++++ pkg/JuliaInterface/tst/adapter.tst | 9 +++++++ pkg/JuliaInterface/tst/convert.tst | 7 ++++++ 4 files changed, 58 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 49ac1ba5..893900d9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes in GAP.jl +## Version 0.9.5-DEV (released YYYY-MM-DD) + +- Allow iterating over Julia objects from within GAP + ## Version 0.9.4 (released 2023-03-04) - Tweak @gapattribute to not require `import GAP: @gapwrap` diff --git a/pkg/JuliaInterface/gap/adapter.gi b/pkg/JuliaInterface/gap/adapter.gi index a8f53dc2..69022ca1 100644 --- a/pkg/JuliaInterface/gap/adapter.gi +++ b/pkg/JuliaInterface/gap/adapter.gi @@ -84,6 +84,44 @@ InstallOtherMethod( \.\:\=, end ); +############################################################################# +## +## Iterating over Julia objects +## +BindGlobal("NextIterator_Julia", function(it) + local res; + res := it!.state[1]; + it!.state := Julia.iterate(it!.obj, it!.state[2]); + return res; +end); + +BindGlobal("IsDoneIterator_Julia", function(it) + return Julia.isnothing(it!.state); +end); + +BindGlobal("ShallowCopy_Julia", function(it) + return rec(NextIterator := it!.NextIterator, + IsDoneIterator := it!.IsDoneIterator, + ShallowCopy := it!.ShallowCopy, + state := Julia.Base.deepcopy(it!.state), + obj := it!.obj, + ); +end); + +InstallOtherMethod( Iterator, + "for a Julia object", + [ IsJuliaObject ], +function(obj) + return IteratorByFunctions(rec( + NextIterator := NextIterator_Julia, + IsDoneIterator := IsDoneIterator_Julia, + ShallowCopy := ShallowCopy_Julia, + state := Julia.iterate(obj), + obj := obj, + )); +end); + + ############################################################################# ## ## Create random numbers via Julia random number generators. diff --git a/pkg/JuliaInterface/tst/adapter.tst b/pkg/JuliaInterface/tst/adapter.tst index c36d368a..919c8d9e 100644 --- a/pkg/JuliaInterface/tst/adapter.tst +++ b/pkg/JuliaInterface/tst/adapter.tst @@ -89,6 +89,10 @@ gap> TestBinOp({a,b} -> a = b); # gap> l := GAPToJulia([1, 2, 3]); +gap> for i in l do Display(i); od; +1 +2 +3 gap> l[1]; 1 gap> l[2] := false; @@ -101,6 +105,11 @@ gap> l; # gap> m:=JuliaEvalString("[1 2; 3 4]"); +gap> for i in m do Display(i); od; +1 +3 +2 +4 gap> m[3]; 2 gap> m[1,2]; diff --git a/pkg/JuliaInterface/tst/convert.tst b/pkg/JuliaInterface/tst/convert.tst index d2a8500a..2400cc73 100644 --- a/pkg/JuliaInterface/tst/convert.tst +++ b/pkg/JuliaInterface/tst/convert.tst @@ -222,5 +222,12 @@ gap> dict:= GAPToJulia( rec( juliafunc:= Julia.Base.map, gap> JuliaToGAP( IsRecord, dict ); rec( juliafunc := ) +# iterating over dict gives key-value pairs +gap> dict:= GAPToJulia( rec( a := 1, b := 2 ) ); + 1, :b => 2)> +gap> for i in dict do Display(i); od; +Pair{Symbol, Any}(:a, 1) +Pair{Symbol, Any}(:b, 2) + ## gap> STOP_TEST( "convert.tst", 1 );