Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ctype= Returns nil with Keyword Parameters #18

Open
charJe opened this issue Jan 17, 2023 · 6 comments
Open

ctype= Returns nil with Keyword Parameters #18

charJe opened this issue Jan 17, 2023 · 6 comments

Comments

@charJe
Copy link
Contributor

charJe commented Jan 17, 2023

(assert
 (ctype:ctype=
  (ctype:cfunction (make-instance
                    'ctype:lambda-list
                    :required ()
                    :optional ()
                    :rest (ctype:bot)
                    :keyp t
                    :keys (list (cons 'var (ctype:specifier-ctype 'integer)))
                    :aokp nil)
                   (ctype:values-specifier-ctype '(values integer &rest t)))
  (ctype:specifier-ctype
   '(function (&key (var integer)) integer))))
The assertion
(ctype:ctype=
 #<ctype:cfunction (function (&key (var integer))
                    (values integer &rest t))>
 #<ctype:cfunction (function (&key (var integer))
                    (values integer &rest t))>)

That looks a bit funky to me. Similar experiments work for required, optional, and rest style parameters. Is there something I'm missing when it comes to the keyword parameters?

@Bike
Copy link
Member

Bike commented Jan 21, 2023

You have the rest type as bottom, which is probably not correct. Since the function takes keywords, any type of argument can be validly provided in the rest list (if only through :allow-other-keys). That might not be the problem here though. Did your paste cut off?

@charJe
Copy link
Contributor Author

charJe commented Jan 21, 2023

I thought rest type should be bottom to indicate that there is not rest parameter (no &rest in lambda-list). Are you saying that it should not be the bottom since &key comes after &rest? These functions I'm talking about don't have &allow-other-keys.

@Bike
Copy link
Member

Bike commented Jan 22, 2023

a rest type of bottom indicates that that the function is not passed arguments other than required and optional. so if the rest type is bottom, keyword arguments, which are not required or optional, cannot be accepted. if the function accepts keywords the rest type should be top.

function types are not strictly related to the lambda list of the function: they just describe what calls are valid. It is also permissible to declare local function types that describe calls without bothering with what the function actually accepts. For example you could have (defun mylist (&rest elems) elems); it would then be permissible to declare in some scope that (ftype (function (float float) list) mylist) to indicate that within that scope, mylist is only ever passed two floats.

I was referring to :allow-other-keys, which is a distinct mechanism from the &allow-other-keys lambda list keyword. The short version is that if you pass :allow-other-keys t, any function that accepts keywords can be made to accept any keywords even if the function lambda list does not have &allow-other-keys. See CLHS 3.4.1.4.1 for details.

@charJe
Copy link
Contributor Author

charJe commented Jan 22, 2023

That is all really interesting and makes perfect sense now. Except when I inspect (ctype:specifier-ctype '(function (&key (var integer)))) I get:

All Slots:
[ ]  %required = nil
[ ]  %optional = nil
[ ]  %rest     = #<ctype:disjunction nil>
[ ]  %keyp     = t
[ ]  %keys     = ((var . #<ctype:range integer>))
[ ]  %aokp     = nil

It looks to me like the rest is (ctype:bot).

@Bike
Copy link
Member

Bike commented Jan 23, 2023

It's quite possible keyword parameter types are in fact broken. I have not used this library as thoroughly as I had hoped. I might be able to take a look tomorrow.

@Bike
Copy link
Member

Bike commented Jan 23, 2023

okay, yeah, somewhat more fundamental problem is that I did not implement function type subtypep in the presence of keyword types: https://github.com/s-expressionists/ctype/blob/main/cfunction.lisp#L42-L44

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants