libera/commonlisp - IRC Chatlog
Search
8:59:56
pjb
|smlckz|: sometimes you can use function-lambda-expression, but implementations can drop the info, so you often just get NIL.
9:00:52
pjb
|smlckz|: otherwise, a lot of implementation provide an implementation specific API to get it. You can use swank as a portability layer: (swank/backend:arglist (function sin)) #| --> (ccl::x) |#
9:07:19
pjb
mfiano: so for a specs of (a 1) you would want to expand to a (let ((a <something>)) …) but for a specs of (rgb 3) you would want to expand to (let ((#:arg1 <something>) (#:arg2 <something>) (#:arg3 <something>)) …) ???
12:51:45
lisp123w
I am thinking of writing some 'portable' code (specifically code that can work with both CLIM & CAPI), so at some point I need to access implementation specific functions
12:52:23
lisp123w
So my plan is to define the basic operations in terms of generic functions that take in an optional value, and then have the methods implement for each specific implementation
12:55:07
lisp123w
Right now, I can only think of having to have two functions, something like this: (defvar *impl* :clim) (defun insert-string-at-point (string) (%insert-string-at-point string *impl*)) .. (defgeneric %insert-string-at-point (string impl))
12:55:14
beach
lisp123w: Check out our libraries Eclector, Cluster, Trucler, etc. They all use a CLIENT required parameter that can handle that situation.
12:57:24
phoe
(defgeneric foo-with-client (client ...)) (defun foo (...) (foo-with-client *default-client* ...))
12:57:59
beach
Yes, we do that in Eclector for instance, where we can't alter the signature of READ.
12:58:11
phoe
where *default-client* is both something you provide and something that the clients of your library can rebind themselves as a dynavar
13:02:45
beach
In our case, the default methods provided by the library do not specialize to the CLIENT parameter, but the same client code that binds *client* can provide extending or overriding methods that specialize to the class of their particular client.
13:05:03
beach
We are very pleased with this "discovery". It allows for code for multiple clients to coexist in the same Common Lisp image.
13:05:57
Nilby
and to make it look nice, you can (defmacro foo (..) (foo-with-client *default-client* ...))
13:06:58
beach
Well, in the case of Eclector, READ is defined to be a function, so it can't be a macro.
13:08:43
lisp123w
beach: Is there a reason for the local binding (let ((client *client*))...) in particular?
13:09:59
lisp123w
I would have done it as &optional (client *client*), but maybe there's a particular reason (from what I understand they should be the same)
13:10:26
lisp123w
(well not actually the same, but the effect being the same if client is not supplied in as an optional)
13:11:14
beach
lisp123w: It is a bit more expensive to access a dynamic variable than a lexical one.
13:11:16
phoe
which kind of makes sense because you only need the dynamic binding on the boundary of your system, so you can effectively pass extra function arguments this way
13:11:50
phoe
so what beach said + you guard your code against some funky re-binding that can cause one part of your code to be executed with one client and another part with another
13:12:22
beach
Yes, you send a message to the person reading your code that you intend to use the same value of *client* in the entire function.
13:12:24
phoe
that's what you get when the client object becomes bound to a lexical variable instead of being accessed by a dynavar
13:14:29
phoe
you cannot make a closure over a dynamic variable because it's too dynamic to be closed over™
13:15:08
phoe
you need to grab the value and stuff it into a lexical variable which is less prone to dynamism such as random-seeming changes
13:20:18
lisp123w
beach: Thanks for the heads up, will do! I'm now at the stage where I'm trying to learn from other code vs. learning the concepts
13:22:16
phantomics
In April, you can pass values into an April code invocation from outside. That includes arrays, naturally. APL isn't strongly typed so you can pass in an array, assign an element of an incompatible type, and April will automatically create a copy of the array with a compatible type to assign the new value into
13:22:46
phantomics
The problem is this: If you pass in an outside array and assign a compatible value into it, the array you passed in will be destructively changed
13:23:14
phantomics
But if you assign an incompatible value, the outside array will not be changed because April silently made a copy. This is confusing for some people
13:25:55
sm2n
That seems fine to me? Just have to specify that April takes ownership of arrays passed in, and if you want the old one, make a copy
13:25:58
phantomics
But if that array is of a type incompatible with the 20 value, like (unsigned-byte 4), then the original array would be copied and the side effect would not occur. Confusing, obviously. What do you think is the best approach here? Always copy arrays passed in so that side effects don't occur?
13:26:45
phantomics
sm2n: The issue is with inconsistency, the original array could either be changed or not changed depending on what you're assigning into it, which can throw people for a loop
13:27:38
phoe
let the user pass a dynavar that specifies the behavior: always copy an array/prevent all side effects, versus copy only when necessary due to array specializations, versus never copy and signal an error instead
13:28:15
phantomics
I could just warn users "don't count on April destructively changing arrays unless you know your array's type and exactly how assignment works, otherwise pass the value back out of April explicitly"
13:29:11
phoe
I mean, I think I can find use cases for the two "extreme" behaviors here - one is extreme side effect avoidance, useful for functional programming, one is extreme performance and a situation where the user *wants* to be notified of type errors because they want to fix them
13:29:35
phantomics
A more simple "configuration" would just be for users to use alexandria's copy-array on anything they want to pass in with no possible side effects
13:30:44
phantomics
I can't have type errors, APL is typeless so adding type errors would require extensive rethinking of the entire language, k is typed and has many lexical features dedicated to managing those types in contrast to APL
13:30:44
sm2n
Consider the case where you are using April and you have a library using April, every invocation in the library will have to rebind the config var if it relies on that behavior being consistent, because you could change it globally
13:35:50
phantomics
That sounds reasonable, I'll just add a bit of documentation basically warning "If you assign values to an array passed into April from outside, make sure you know what you're doing as it may or may not have side effects."
15:27:09
lisp123
pjb: Do you remember what your lambda list parser was called? Trying to find it now as its v. useful for macro writing
15:28:30
phoe
alexandria:parse-ordinary-lambda-list is for ordinary ones, can't say anything about others though
16:01:37
jmercouris
lisp123: if you want an example, we use Alexandria in the Nyxt codebase to split lambda lists
16:31:36
pjb
it's easy: just load com.informatimago in your rc file, and then you can (apropos "whatever").