libera/#commonlisp - IRC Chatlog
Search
20:54:05
pjb
recordgroovy: that's a serious bug I'd say, I define a lot of condition subclasses expecting to be able to use the accessor of the superclass (condition) slots…
20:59:34
pjb
recordgroovy: Note this is a problem only with stream-error it seems: (define-condition tec (type-error) ()) (type-error-datum (make-condition 'tec :datum 42 :expected-type 'character)) -> 42
23:11:45
CptKirk
is there a way to get stringify the value of a symbol maintaining its original casing?
23:15:35
hayley
(Note that, if the read case is set to :upcase, then a symbol which was read was originally all uppercase.)
23:23:43
CptJimKirk
https://codeberg.org/CptJimKirk/adventofcode/src/commit/2ba73ad0e5799b9bd0f63299787beb01496b51b8/cl/aoc-15.lisp#L36
23:26:05
hayley
"Note that, if the read case is set to :upcase [oh, and it is by default], then a symbol which was read was originally all uppercase."
23:31:03
mfiano
If you ignore the value of read case, all symbols are read into uppercase strings unless character-quoted with |..|
23:46:32
CptJimKirk
so that if its something then it would expand to (some form something other stuff)
23:49:15
saturn2
(progn (something) nil (otherthing)) will have the same effect as (progn (something) (otherthing))
23:50:26
CptJimKirk
but if `(some` is a function, then there is a `nil` being passed as the second argument...
0:33:18
pjb
CptJimKirk: (mapcar (lambda (maybe-nothing) (append '(some form) maybe-nothing '(other stuff))) '( (#|nothing|#) (some thing))) #| --> ((some form other stuff) (some form some thing other stuff)) |#
1:17:30
CptJimKirk
https://codeberg.org/CptJimKirk/adventofcode/src/commit/47e343b966c319b166c9fda34b56a7783749e590/cl/aoc-15.lisp#L44
1:17:58
CptJimKirk
saturn2 how is the lisp readtable to work at all when you are expected to set the read table before the invocation of the macro?
1:20:37
CptJimKirk
https://codeberg.org/CptJimKirk/adventofcode/src/commit/1a7491c2636c2fd9e49c039a01ceb3311492a7f2/cl/aoc-15.lisp#L36
1:22:29
CptJimKirk
so your'e saying that I would have to define everything that uses this and needs case insensitive symbosl would need to be done inside that let block
1:24:13
CptJimKirk
is there any way that on the other side of the macro, I can get case insensitivity?
1:24:36
CptJimKirk
something like that, or some other thing... that would achieve the case sensitivity I need?
1:26:32
pjb
CptJimKirk: april-load is a function-like macro: it has no compilation-time side effect. Therefore there's no point in using it in the topleve of your source file.
1:26:47
CptJimKirk
I don't want the user to need to know that they should (defapl |fnName| (args) ...)
1:28:54
CptJimKirk
but the main thing I'm struggling with the case insensitivy of symbols. Is there any way to achieve the behavior of (defmymacro |caseSensitive| (arg) (etc))
1:29:39
CptJimKirk
I basically want exactly a `defun` form but case sensitive and to wrap around April calls
1:31:15
CptJimKirk
... I'm asking for an alternative, not a restatement of the only solution I've found so far
1:31:55
pjb
You can put this on the first line of your source file: (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE) (SETF *READTABLE* (COPY-READTABLE NIL) (READTABLE-CASE *READTABLE*) :PRESERVE))
1:32:31
pjb
An alternative, but which is less pretty IMO, is to put this: (eval-when (:compile-toplevel :load-toplevel :execute) (setf *readtable* (copy-readtable nil) (readtable-case *readtable*) :invert))
1:33:05
pjb
In the first case you could write: (DEFMACRO caseSensitive (arg) (IF arg (etc) (whatever)))
1:33:19
pjb
In the second case, you would write: (defmacro caseSensitive (arg) (if arg (etc) (whatever)))
1:34:27
pjb
But in the second case, (defmacro notlower (arg) (if arg (etc) (whatever))) would define a macro named NOTLOWER, while in the first case, (DEFMACRO yeslower (arg) (IF arg (etc) (whatever))) would define a macro named |yeslower|.
1:35:32
pjb
CptJimKirk: it is a dynamic binding = it is during some time that it will have its effect. And the time the *readtable* is used, is WHEN you READ stuff. Eg. when you load a file, or when you compile a file. (or when you explicitely call READ or READ-FROM-STRING).
1:36:31
CptJimKirk
Well, this is where I'm confused, because I want to be able to define these things interactively in the REPL as you would normally but without breaking the language
1:37:30
CptJimKirk
if I use preserve case, but I type in lowercased expressions, it can't find normal symbols
1:37:32
pjb
You can define a function (activate-apl-readtable) that the user can call at the REPL to start typing with APL conventions.
1:37:56
pjb
CptJimKirk: indeed, You'd have to use uppercase for lisp symbols, since they ARE in uppercase!
1:39:17
pjb
(let ((*readtable* (copy-readtable nil))) (setf (readtable-case *readtable*) :invert) (read-from-string "(hello HELLO Hello)")) #| --> (hello |hello| |Hello|) ; 19 |#
1:39:50
CptJimKirk
but I wouldn't want to write (defun |f| (x) (* x x)) and I don't want to write (defapl |f| (lst) (coerce lst 'vector))
1:40:37
pjb
CptJimKirk: now, you can define a new symbol with the case changed, but this is not pretty either. But you may like it.
1:41:14
pjb
(defmacro defapl (name …) (let ((apl-name (intern (string-downcase name) (symbol-package name)))) … `( … ,apl-name) …))
1:42:09
lotuseater
when people tell me ridicolous things about "all these parentheses" i like to confuse them that those aren't really there ^^
1:42:56
pjb
(cond ((not-any (function lower-case-p) (symbol-name name)) (intern (string-downcase name) (symbol-package name))) ((not-any (function upper-case-p) (symbol-name name)) (intern (string-upcase name) (symbol-package name))) (t name))
1:44:18
pjb
(mapcar (lambda (name) (cond ((notany (function lower-case-p) (symbol-name name)) (intern (string-downcase name) (symbol-package name))) ((notany (function upper-case-p) (symbol-name name)) (intern (string-upcase name) (symbol-package name))) (t name))) '(foobar |FooBar| |foobar|)) #| --> (|foobar| |FooBar| foobar) |#
1:44:52
pjb
(mapcar (lambda (name) (cond ((notany (function lower-case-p) (symbol-name name)) (intern (string-downcase name) (symbol-package name))) ((notany (function upper-case-p) (symbol-name name)) (intern (string-upcase name) (symbol-package name))) (t name))) '(foo-bar |Foo-Bar| |foo-bar|)) #| --> (|foo-bar| |Foo-Bar| foo-bar) |#
1:48:02
pjb
(defmacro |defapl| …) so that when you switch to (SETF (READTABLE-CASE *READTABLE*) :PRESERVE), you can write (defapl FooBar …)
1:50:55
pjb
Why would it be bad if functions defined in lisp were named with uppercase? you could have both f and F in your apl programs, and it would be obvious that F is written in lisp.
2:11:41
CptJimKirk
@saturn the purpose of defapl is that I want CL to be the driver of APL programs, or a means to compose APL programs, so I would like to define LISP funcitons that are able to call into APL functions as needed, by feeding the "return value" of the "function body" to be passed as valid April input
2:17:31
CptJimKirk
So conceptually, I'm passing input to a lisp function, but actually its calling the APL function of the same name
2:19:00
CptJimKirk
so how do defuns intern their symbols so that they are permitted to be case sensitive?
2:20:26
mfiano
Common Lisp Recipes book has good information on symbols. Practical Common Lisp probably touches on it.
2:21:34
mfiano
Understanding the Lisp reader in detail is critical to effective programming. I suggest going back to it if you didn't retain it.
2:23:43
CptJimKirk
I mean, I've spent so much time in the lisp liturgy that I've never actually built anything, but now that I have a project worth building I can't get it done without more bookiness?
2:25:06
CptJimKirk
I'm not offended at the suggestion to turn to a great book for wisdom. I'm more offended at my inability to move past dwelling on reading books instead of building anything
2:25:18
Alfr
CptJimKirk, does your defapl really define something (like a function etc.) in lisp, from your description it sounds to me that it simply should return something that hopefully is valid input for april. You could opt for mapping lispy-names-like-this to not that lispNamesLikeThis.
2:25:19
CptJimKirk
I don't know many peopel who have spent so long with a language to have written so little
2:26:20
CptJimKirk
@alfr if I understand what you're saying, I'm trying to infer the APL name from the name of the (defapl name ...
2:27:05
CptJimKirk
so `(defapl myAplFn (args) (process (to-array (something-else input))))` or some such would pass the result of that body to a function from April called `myAplFn`
2:27:37
CptJimKirk
inside the macro, it expands somewhere `(defmacro defapl name .... (april-c "myApl"fn" results)... )`
2:28:42
CptJimKirk
I thought something like this would work (let ((count 0)) (defun incrmentr () (setf count (1 + count))))`
2:28:49
mfiano
If you have been learning Lisp for a long time, I suggest spending time on the important parts
2:28:58
CptJimKirk
by wrapping the `defmacro` in redefining the reader case, but that def doens't work
2:29:59
CptJimKirk
tell me what other language allows you to manipulate the way its parsed at runtime?
2:30:46
mfiano
I would argue if you don't like the power of Lisp, which requires knowledge to use the power effectively, go back to writing APL in APL
2:31:19
CptJimKirk
@mfiano that is not a concluion that can be drawn from what I'm trying to do here
2:32:22
mfiano
If you're going to argue semantics, I have no more desire to help. This is not #clschool after all.
2:32:58
CptJimKirk
I was trying to direct my line of questioning there before we wound up down this tangent
2:33:26
CptJimKirk
I did change the reader, but it didn't work the way I expected for obvious reasons, the language is read outside of the context of the re defined readtable
2:33:38
CptJimKirk
but also, I don't want the user to have to know to update the read table every time they want to use (defapl
2:34:12
CptJimKirk
and I don't have to toggle a statemachine updating the readtable every time I want to use those
2:34:58
mfiano
Reading happens before everything in the Lisp compiler. I don't know how you plan to accomplish that if you don't want to use a string name.
2:35:00
CptJimKirk
so I'm not playing semantical games, I'm being specific, I want to be able to define in terms of a normal lisp binding form like `defun`, without having to use || or a string
2:35:25
mfiano
Either use the reader, which forces a burden on users, or require them to use strings and do the work at macroexpansion time
2:37:09
lotuseater
CptJimKirk: you could have it with brackets, [define camelCaseFunction ...] so that just the second symbol will be case preserved
2:40:32
Alfr
lotuseater, you'd still have to write |1|, \1 or some such when calling your |1|-function.
2:40:48
mfiano
Which requires the user to switch to your custom readtable, since that is a toplevel form
2:42:22
mfiano
If you do not want to leverage the Lisp reader, you must use what is already available at read time
2:43:04
CptJimKirk
no it isn't doable. The specific conditions I laid out have to this point I've been told that what I specified is not possible
2:43:19
mfiano
You can, you just placed a lot of constraints that only open up 2 paths to a solution.
2:45:04
mfiano
Another option would be to require the user to define their def forms in a file that is not loaded, and manually call #'load in some function, installing a read table around it
2:46:06
CptJimKirk
The user wants to be able to "call apl functions" in their lisp code, appearing like any other lisp function, but which ultimately binds to the April function by the same name, which should be definable ad-hoc without the need to manually update some global state machine for defining, either that or it would need to be defined within a block that
2:46:07
CptJimKirk
shadows the *readtable* which means that not only can I not bind the lisp macro to the april funciton ad-hoc, but its scope specific, and would require a recompilation of the entire reader macro block every time I make any change
2:46:45
CptJimKirk
I can (defun my-fn (args) body) I want to (defapl myAplFn (args) body) just the same
2:48:01
CptJimKirk
I wouldn't assume looking at this expression that there is a lisp function now defined called "myAplFn"
2:48:42
CptJimKirk
and (defapl |caseSensitive| ...) is just a gotcha that you'll have to remember any time there is a apl fn with multiple case
2:49:37
CptJimKirk
I don't understand... Are you suggesting that any time a reader macro is used, that the user of the reader macro has to define all of their code from within the scope of that reader macro?
2:50:15
mfiano
Yes, reader macros are global. There is named-readtables that helps with that a little bit.
2:52:42
specbot
Standard Macro Characters: http://www.lispworks.com/reference/HyperSpec/Body/02_d.htm
2:59:47
CptJimKirk
why was there never any consideration for a (defreader which would pass the remaining expression to the body of the reader, which would then read the body?
3:00:18
saturn2
if you want your system to be usable by lisp programmers the way they expect, without learning anything new or doing anything unusual, the only way is to explicitly map ordinary all-uppercase symbols to apl function names
3:00:59
hayley
That makes no sense. I mean, if you have "the remaining expression", you already read it.
3:01:51
CptJimKirk
@hayley (defreader (............)) the (...) could be a string completely unevaluated
3:04:13
Alfr
CptJimKirk, the problem with what you expect is, that you think that the call to (defreader .............) sees the dots, it doesn't.
3:04:35
hayley
CptJimKirk: The reader always leaves things unevaluated. But it still has to do some "parsing" in order to find the matching ) eventually.
3:05:19
CptJimKirk
does it have to parse, or just match the count of open an closing parens until the stack is 0?
3:06:12
CptJimKirk
(defreader (....)) could be defined as just "reading a text string" until the matching closing paren, no parsing, then pass the string to the custom reader "macro/function" thing
3:06:56
CptJimKirk
i'm not arguing about how it IS, I'm asking why this wouldn't work in a special-case special-form type thing
3:07:52
CptJimKirk
but IF in this hypothetical form that doesn't actually exist, if it didn't EVALUATE, and only read the contents as a string?
3:08:29
beach
The reader would have to parse the name of the "special form" which is not what the reader does or is designed to do.
3:08:48
Alfr
CptJimKirk, once you identify the special form symbol, the reader already has parsed and returned the list (you-new-and-shiny-special-form-symbol-name maybe some args).
3:10:24
CptJimKirk
what about ##'#'*D->(readermacro ...) as some kind of prefix annotation to tell the reader "hey this thing is something else"?
3:10:51
CptJimKirk
that could trigger something in the readers statemachine, oh this is something else
3:15:35
Alfr
CptJimKirk, you can then quite freely determine how you proceed reading; maybe #@, as #a is already used for denoting arrays.
3:17:54
Alfr
mfiano, what? It's undefined, and I assumed he'd start modifying the standard readtable.
3:18:31
mfiano
Just because it is undefined in ANSI doesn't mean a conforming implementation is not allowed to define it
3:21:58
CptJimKirk
I think what I'm learning is I need to stop trying to treat CL as having a pure subset
3:26:45
beach
CptJimKirk: The other thing I recommend you do is avoid phrases such as "a glaring oversight/misstep" about how Common Lisp was designed.
3:29:54
CptKirk92
how else should I say that having a globally specified hook into the reader macro that doesn't mutate global state would be better than mutating global state?
3:31:51
beach
Well, phrases like that seem to suggest that you know how Common Lisp was designed and that the people who designed it made a mistake. But in fact, the design is very consistent and the people who designed it were (are?) very smart and very knowledgeable.
3:33:06
CptJimKirk
Clearly, I have tried and failed at implementing my own languages. To create such a universal grammar for a programming language required keen insight. I probably know more about the history of CL and APL than I do about writing quality applications with them... :/
3:34:53
CptJimKirk
but looking at other reader macro examples, it seems clear that mutating global state is the norm in CL, and I should just get acclimated to that.
3:36:01
Alfr
CptJimKirk, why does it have to modify global state? (let ((*readtable* my-readtable)) (read some-input-stream)) can cover may things.
3:36:26
CptJimKirk
only if all of your definitions using that reader macro are defined within that let block
3:37:17
CptJimKirk
but that json reader macro example showed an enable/disable function which overwrote the reader, copying the original to some stack of read-table history
3:37:57
CptJimKirk
but then he corrected himself about named-readtables and said there is only 1 read-table
3:38:55
Bike
well, there's only one current readtable, yeah. i don't know what having more than one simultaneously would mean. there's only one syntax.
3:40:08
CptJimKirk
My current position is basically that a custom reader macro for this particular case is way nuclear of an option for just trying to maintain case
3:40:12
Bike
*readtable* kind of is the globally specified hook into the reader. there are lots of ways to mutate readtables, though.
3:40:25
Alfr
CptJimKirk, but in a program (let's not consider special variables and threads right now) you can only have one effective readtable at any moment.
3:40:33
CptJimKirk
I'll probbaly roll with saturns suggestion from earlier about (defapl (lisp-fn "AplFn") (args) (body))
6:34:39
lisp123
Does anybody know which implementations are unable to successfully extract a function expression from a function symbol via function-lambda-expression?
6:36:05
beach
I am willing to bet that the commercial implementations will not let you get the source code of their compiler that way.
6:37:17
beach
Also, for the generic functions in any implementation, I don't think there is anything reasonable to return.
6:38:14
lisp123
Thanks on both counts, that's useful to know. I hope the commercial implementations will allow it for user functions..
6:39:00
lisp123
I think its a very useful tool, if I want to create a macro that takes a function as an input and does a transformation, it makes it much easier to just use that
6:54:00
beach
lisp123: The TYPECASE would emulate the discriminating function, and each case would be the method function of one method.
7:16:55
beach
lisp123: The only thing they really had to add to pre-ANSI Common Lisp to get CLOS was the STANDARD-OBJECT and the FUNCALLABLE-STANDARD-OBJECT.
7:19:08
beach
lisp123: Classes are just STANDARD-OBJECTs, and generic functions are just FUNCALLABLE-STANDARD-OBJECTs.
8:26:11
pve
Good morning! I was listening to the Lex Fridman podcast where he discusses "Cyc" with Douglas Lenat, and there's a part that may be of interest to lispers.
8:27:25
moon-child
I believe cyc was implemented in common lisp but itself used only an s-expression syntax
8:31:04
moon-child
see also logicmoo, which is an oss continuation of cyc. It includes this gem https://github.com/logicmoo/wam_common_lisp, which '[Allows] Lisp programs to stop implementing an ad-hoc, informally-specified, bug-ridden, slow implementation of less than half of ISO-Prolog' :D
8:31:43
moon-child
pve: just from scanning filenames, it seems the actual inference engine is in java. See https://github.com/asanchez75/opencyc/blob/master/KB%2Binference_engine/opencyc-0.7.0b.zip