glycerine/zygomys

How to Call Go Method/Function (Standard Lib)

Opened this issue ยท 10 comments

dc0d commented

How can a method be called? For example if (def t (now)), is it possible to call the Year() method? Also how to import standard packages? If we evaluate (import "time") (REPL) we get this error:

error in import:-1: Error calling 'infix': Error calling 'import': import error: path 'time' does not exist
in evalGeneratedFunction:3
in infix:0
in __main:3

Is there an inspect function that gives info about the type, fields and methods of an object? Or exported from a package?

Edit

I studied the zygo command and seems extra functionality should be added via Go API (which is fine). Still I'm interested in some answers to questions above.

Hi Kaveh.

There are two mechanisms for reaching out to Go from zygo. The standard library is of course available to import from within Go code, but Go libraries are in general not available without some (light) extra work on the part of the user. That work involves using one of the two extension mechanisms provided by zygo and documented in the wiki: function based extension, or struct based extension.

a) adding functions - wrapping native Go function calls

Here you would add a wrapper for the Year() call, for example. Here is the documentation and pointers to examples of how time.Now() is implimented as an example.

https://github.com/glycerine/zygomys/wiki/Go-API#adding-go-functions

https://github.com/glycerine/zygomys/blob/master/zygo/time.go#L32

https://github.com/glycerine/zygomys/blob/master/zygo/time.go#L101

b) wrapping native Go structs

This provides a bit more flexibility, as we can call methods on structs that are discovered at runtime. However the structs themselves must be registered and thus compiled in during your use of zygo as an embedded libarary. This is also discussed on the wiki pointer above. Here are pointers to a demo of the struct based extension:

https://github.com/glycerine/zygomys/blob/master/zygo/demo_go_structs.go

https://github.com/glycerine/zygomys/blob/master/tests/methodcall.zy

Lastly, to answer your other questions --

Is there an inspect function that gives info about the type, fields and methods of an object?

(methodls) will list methods available when using the struct-based extension described above. Here is sample code:

https://github.com/glycerine/zygomys/blob/master/tests/methodls.zy

Once you have bound your shadow go struct to a zygo SexpHash table, invoking (togo) on the hash table will print the corresponding Go structure.

Or exported from a package?

Does printing the value of the package not give you sufficient information? For example, from the package.zy example in tests/ (https://github.com/glycerine/zygomys/blob/master/tests/package.zy).

zygo> (def hi (package "hello"
   { World := "earth"; (defn Myfun [x] (concat World x)) }
... ... ))
(package hello
     elem 0 of :  global
         (global scope - omitting content for brevity)
     elem 1 of :  scope Name: 'hello'
         Myfun -> (defn Myfun [x] (concat World x))
         World -> "earth"
 )
dc0d commented

First of all I should thank you for this great work!

And thanks for this thorough answer.

Having a bit more descriptive inspect function(ality) (in Elixir sense) helps greatly (IMHO).

I love to see programming languages (and other tools) in pure Go and there is nothing wrong with having special ways of communication with native Go packages. I suppose zygomys can be cross compiled which is great!

Why at the REPL does it show zlisp?

:) Thanks for the nice words.

The REPL should show zygo now, as I pushed a fix just now for that.

inspec would be nice. Currently there are (type?) and (str). e.g.

zygo> (type? a)
"time.Time"
zygo> (str a)
"2018-01-04 01:02:03.408212465 -0600 CST m=+14.206331392"
zygo> 

All s-expressions know how to print themselves, so at a minimum (str x) should give some information for any x.

Also (pretty true) gives nice pretty printing indentation of nested maps/Go structs.

also to note, at the zygo repl, .ls and .gls will show your local and global environments, respectively.

Last, of note, objects just by printing them are fairly informative. I'll make up a two level object heirarchy here, and then print it flat and pretty.

zygo> (defmap house)
zygo> (defmap room)
zygo> h = (house upstairs:(room hwl:[12 20 30] downstream:"oak woodwork" basement: (house name:"dollhouse")))
 (house upstairs: (room hwl:[12 20 30] downstream:"oak woodwork" basement: (house name:"dollhouse")))
zygo> h
 (house upstairs: (room hwl:[12 20 30] downstream:"oak woodwork" basement: (house name:"dollhouse")))
zygo> (pretty true)
zygo> h
 (house
    upstairs: (room
        hwl:[
            12             20             30            ]
        downstream:"oak woodwork"
        basement: (house
            name:"dollhouse" )
 )
 )

zygo> 
dc0d commented

Thanks!

Should I close this? Or will it be labeled as Question (or Discussion or something)?

I think it might be easier for others to find if its left open, so I'll put a question label on it and leave it open for now.

Question about this: the struct approach for this documented in the wiki points to files no longer found:

I'm trying to figure out how to implement Go interop in Zygomys, so would love to see those files ... or pointers to where that code now lives :-)

Thanks!

@oubiwann Yes, the package was renamed, from repl to zygo. I've updated the wiki in 6fcbbcf to try and fix up the links.