Currently, if the resulting object from an 'interface' invocation is
supposed to implement a method that returns values (like Supplier in Java
8):

(setq String (interface "java.util.function.Supplier" "get" '(() (java
"java.lang.String" T "java.lang.String") ) ) )

Then, if the implemented method is invoked on the object:

(java String "get")

The returned value is of the type PicoLisp$Symbol, since the curent
implementation of interface returns the PicoLisp$Any result from evaluating
the PicoLisp function bound to that method.

Unfortunately, this means that there would be no way to retrieve the values
returned from that interface implementation's method unless you implement
heavy field-based recursion on the Any object.

Fortunately, I've made a modification to interface that allows PicoLisp
users to not only return Java values from interface implementation methods,
but also all 5 possible value types from PicoLisp (T, NIL, Number, Symbol,
and Cell):

What I've done is to replace the "return a;" statement in interface to
"return toObject(a);", which is defined as:

   final static Object toObject(Any a) {
      if (a == T) {
         return true;
      } else if (a == Nil) {
         return null;
      } else if (a instanceof Number) {
         Number n = (Number) a;
         return n.Big instanceof BigInteger ? n.Big : n.Cnt;
      } else if (a instanceof Symbol) {
         Symbol s = (Symbol) a;
         return s.Obj instanceof Object ? s.Obj : s.Name;
      } else if (a instanceof Cell) {
         return toCollection((Cell) a);
      }
      return a;
   }

In turn, the toCollection method is defined as (based on Cell::toString):

   final static Collection<?> toCollection(Cell c) {
      Any x, y;
      List<Object> l;
      l = new ArrayList<Object>();
      if (c.Car == Quote  &&  c != c.Cdr) {
         l.add(toObject(c.Car));
         l.add(toObject(c.Cdr));
         return l;
      }
      x = c;
      if ((y = circ(x)) == null) {
         for (;;) {
            l.add(toObject(x.Car));
            if ((x = x.Cdr) == Nil)
               break;
            if (!(x instanceof Cell)) {
               l.add(toObject(x));
               break;
            }
         }
      }
      else if (y == x) {
         do {
            l.add(toObject(x.Car));
         } while (y != (x = x.Cdr));
      }
      else {
         do {
            l.add(toObject(x.Car));
         } while (y != (x = x.Cdr));
         do {
            l.add(toObject(x.Car));
         } while (y != (x = x.Cdr));
      }
      return l;
   }

Thus, using the previous example, the value returned would be of type
String.

With another example, if the Supplier implementation's get method was made
to return a PicoLisp function:

# Using srborlongan-picolisp's java interop functions
(javaImport java.util.function.Supplier)
(setq Supplier (Supplier.new () Supplier.new) )
# Supplier.new => (Body (interface "java.util.function.Supplier" "get"
(cond ((and (= 1 (length Body)) (fun? (eval (car Body)))) (eval (car
Body))) ((fun? Body) Body) (T (append '(NIL) Body)))))
(.get> Supplier)
# returns the value [Body, [interface, java.util.function.Supplier, get,
[cond, [[and, [=, 1, [length, Body]], [fun?, [eval, [car, Body]]]], [eval,
[car, Body]]], [[fun?, Body], Body], [true, [append, [quote, [null]],
Body]]]]]

Please note that toCollection currently implements infinite lists or lists
that end in atoms as normal lists. I might plan to implement infinite lists
by adding the list itself at the end of the list, to make it easier to
check if the list is looping. I do not know how to implement the other
problematic type, however.

Thanks!


Samuel Dennis R. Borlongan

Reply via email to