all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#64919: 28.2; jsonrpc.el: jsonrpc-lambda failed to deal with single value
@ 2023-07-28 16:59 Yue Yi
  2023-07-29 10:14 ` João Távora
  0 siblings, 1 reply; 3+ messages in thread
From: Yue Yi @ 2023-07-28 16:59 UTC (permalink / raw)
  To: 64919; +Cc: João Távora

[-- Attachment #1: Type: text/plain, Size: 1844 bytes --]

Currently I'm trying to write an toturial about using JSON-RPC in
Emacs, so I spent some time to read the source code and document and
found #bug64888.



Here is another bug I find: When I do a async request through
`jsonrpc-async-request' without specifing :success-fn, emacs will
signal an error. Here is the code I use:



---

(defclass yy-rpc (jsonrpc-connection)

  ((place

    :initarg :place

    :accessor yy-place)))

(cl-defmethod jsonrpc-connection-send ((conn yy-rpc)

                                 &key id method params result error)

  (setcar (yy-place conn)

          (append (if id `(:id ,id))

                 (if method `(:method ,method))

                 (if params `(:params ,params))

                 (if result `(:result ,result))

                 (if error  `(:error  ,error)))))

(setq a (cons nil nil))

(setq b (yy-rpc :name "1" :place a))



(jsonrpc-async-request b "add" [1 2])

(jsonrpc-connection-receive b '(:result 3 :id 1))

---



I just make a very simple subclass `yy-rpc' and response to it "by
hand", after evaluating the above code, I get:



---

Debugger entered--Lisp error: (wrong-type-argument listp 3)

---



By reading the code of `jsonrpc--async-request-1', I find the default
:success-fn callback uses the macro jsonrpc-lambda and I know why it
happened:



---

(funcall (jsonrpc-lambda (&rest _ignored) nil) 3)

=> Debugger entered--Lisp error: (wrong-type-argument listp 3)

---



It seems that `jsonrpc-lambda' cannot handle single value. Maybe We
can change its last line from



`(lambda (,e) (apply (cl-function (lambda ,cl-lambda-list ,@body)) ,e))))



to



`(lambda (,e) (apply (cl-function (lambda ,cl-lambda-list ,@body)) ,e ())))



After change it and M-x eval-buffer, I can get the right behavior
using the code above.



Is it the right way?



Regards



YI YUE

[-- Attachment #2: Type: text/html, Size: 7138 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#64919: 28.2; jsonrpc.el: jsonrpc-lambda failed to deal with single value
  2023-07-28 16:59 bug#64919: 28.2; jsonrpc.el: jsonrpc-lambda failed to deal with single value Yue Yi
@ 2023-07-29 10:14 ` João Távora
  2023-07-29 12:17   ` Yue Yi
  0 siblings, 1 reply; 3+ messages in thread
From: João Távora @ 2023-07-29 10:14 UTC (permalink / raw)
  To: Yue Yi; +Cc: 64919-done

Hello Yue Yi,

Yue Yi <includeyy123@gmail.com> writes:

> Currently I'm trying to write an toturial about using JSON-RPC in
> Emacs, so I spent some time to read the source code and document and
> found #bug64888.

That's a great idea.  Have you looked at the jsonrpc.el test application
in test/lisp/jsonrpc-tests.el?  It has a simple application, but it's
not very well commented, so a well-described tutorial that does a
similar simple application is welcome.

> Here is another bug I find.

Yes, you've found a bug.  I have fixed it in master
3bbe6f4abc6c1dd8f414e48af5b6ce344bce34db.  I have closed this bug, but
we can keep chatting.

But read on because I think you are misunderstanding the library in some
aspects.

> When I do a async request through `jsonrpc-async-request' without
> specifing :success-fn, emacs will signal an error. Here is the code I
> use:

Doing jsonrpc-async-request without success-fn is possible but oesn't
make much sense, becase there's nothing to react to whatever the server
returned for this remote proceedure call if the request succeeds.
  
> --- 
> (defclass yy-rpc (jsonrpc-connection)
>   ((place
>     :initarg :place
>     :accessor yy-place)))
> (cl-defmethod jsonrpc-connection-send ((conn yy-rpc)
>                                  &key id method params result error)
>   (setcar (yy-place conn)
>           (append (if id `(:id ,id))
>                  (if method `(:method ,method))
>                  (if params `(:params ,params))
>                  (if result `(:result ,result))
>                  (if error  `(:error  ,error)))))
> (setq a (cons nil nil))
> (setq b (yy-rpc :name "1" :place a))

By the way, this isn't how you make objects in Common Lisp (or in Emacs
Lisp's emulation of it, which is what we have here).  You would have to
use 'make-instance'

I also don't understand what your code is supposed to perform.  Look at 
the test/lisp/jsonrpc-tests.el to get an idea of how to do these kinds
of servers.

You should first be able to describe in plain English what you want this
tutorial example to showcase.  Do you want to make a simple JSONRPC
client that asks the endpoint to perform elementary arithmetic remotely?
Fine.  Where do you want the remote endpoint to live?  The same Emacs?
Another Emacs?  Another process running a program written in another
language?

Try to first answer these questions and have a very clear idea in your
head of what you want to demonstrate in the tutorial.

As I said, it's a very good idea in principle.  But from your
description of it, it seems still a bit fuzzy.

> (jsonrpc-async-request b "add" [1 2])
> (jsonrpc-connection-receive b '(:result 3 :id 1))

Here is what may be a significant mistake: the
'jsonrpc-connection-receive' is not meant to be called by the
_application_ writer.

Instead it is meant to be called by the _library_ writer, i.e. someone
who is extending 'jsonrpc.el' to a new transport (other than TCP/IP
sockets).

In other words, you're mixing up two ways to use jsonrpc.el.  They are
both described in 33.32.1 JSONRPC Overview

  1. A user interface for building JSONRPC applications
  2. A inheritance interface for building JSONRPC transport
     implementations

Thse are two completely separate use cases.

I _think_ you first want to do 1, to get a feeling of how to use the
library as an application writer.  Only then should you move on to 2 to
understand how to user the library an implementor of new transports.

Only then you'll get to mess with 'jsonrpc-connection-receive', which
you're doing right now.

João





^ permalink raw reply	[flat|nested] 3+ messages in thread

* bug#64919: 28.2; jsonrpc.el: jsonrpc-lambda failed to deal with single value
  2023-07-29 10:14 ` João Távora
@ 2023-07-29 12:17   ` Yue Yi
  0 siblings, 0 replies; 3+ messages in thread
From: Yue Yi @ 2023-07-29 12:17 UTC (permalink / raw)
  To: João Távora; +Cc: 64919

[-- Attachment #1: Type: text/plain, Size: 2538 bytes --]

Hello João:

> That's a great idea.  Have you looked at the jsonrpc.el test application
> in test/lisp/jsonrpc-tests.el?  It has a simple application, but it's
> not very well commented, so a well-described tutorial that does a
> similar simple application is welcome.

I haven't read it yet and I will.

> Doing jsonrpc-async-request without success-fn is possible but oesn't
> make much sense, becase there's nothing to react to whatever the server
> returned for this remote proceedure call if the request succeeds.

You're right and what I want to do is to see what will happen if I don't
use :success-fn.

> By the way, this isn't how you make objects in Common Lisp (or in Emacs
> Lisp's emulation of it, which is what we have here).  You would have to
> use 'make-instance'

Yes, 'make-instance' is the better one.

> You should first be able to describe in plain English what you want this
> tutorial example to showcase.  Do you want to make a simple JSONRPC
> client that asks the endpoint to perform elementary arithmetic remotely?
> Fine.  Where do you want the remote endpoint to live?  The same Emacs?
> Another Emacs?  Another process running a program written in another
> language?

All these problems are indeed things I need to consider if I want to write
an
example using JSON-RPC. My initial idea was simply to use RPC in
Emacs to access some functionalities of Python.

> As I said, it's a very good idea in principle.  But from your
> description of it, it seems still a bit fuzzy.

Yeah. While writing this example, I assume that the user acts as the
transport layer
for RPC messages: manually calling 'jsonrpc-connection-send' and
'jsonrpc-connection-receive'
to achieve message transmission. My initial intention is to let readers of
the
tutorial get a simple understanding of how jsonrpc.el works.

> I _think_ you first want to do 1, to get a feeling of how to use the
> library as an application writer.  Only then should you move on to 2 to
> understand how to user the library an implementor of new transports.

can't agree more.

In summary, first, I need to consider with whom I will perform RPC and
address some of the details mentioned above. Afterward, I can proceed to
plan and write the tutorial.

I will carefully consider the suggestions above on how to better introduce
the usage of jsonrpc.el. When I believe that my work is well-prepared, I
may consider submitting a request to emacs-devel for review and feedback.

Regards

YI YUE

[-- Attachment #2: Type: text/html, Size: 4168 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-07-29 12:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-28 16:59 bug#64919: 28.2; jsonrpc.el: jsonrpc-lambda failed to deal with single value Yue Yi
2023-07-29 10:14 ` João Távora
2023-07-29 12:17   ` Yue Yi

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.