libera/#commonlisp - IRC Chatlog
Search
15:58:38
jcowan
Medley is a programming environment that provides two languages: Interlisp and Common Lisp. Unfortunately, the CL stands somewhere between CLtL1 and CLtL2. This needs fixing.
15:59:21
jcowan
It would pretty much be a Common Lisp project to do so, and I would expect that the CL test suite could drive it.
16:02:24
jcowan
There is an IL interpreter, a CL interpreter, an IL compiler to bytecode, and a CL/IL compiler to bytecode. There is no native code compiler.
16:12:19
jcowan
A fair amount, but IL and CL developed independently for decades. Interoperation is good: CL sees IL functions and fexprs as CL functions and macros (although only some of them return an actual macro definition to CL:MACRO-FUNCTION.
16:13:55
Bike
i'm flipping through the manual now. seems to describe everything as a function... setq, for example
16:16:32
Bike
i was guessing that was what "nlambda" means, but selectq isn't labeled as one (while stuff like cond is)
16:17:12
Bike
"If LAMBDA-WORD is the symboL NLAMBDA, then the arguments to the function are not evaluated" i am a genius
16:17:53
beach
jcowan: And that still leaves duplication between the Common Lisp interpreter and the Common Lisp compiler.
16:18:22
jcowan
Such was the case in Maclisp as well. It was one of Scheme's contributions to CL that locals are lexical unless declared otherwise.
16:20:30
Bike
is interlisp an actual standardized language? i thought it was, but what i'm looking at is obviously an implementation manual
16:20:40
beach
I see. So the reason there is not as much duplication between the Common Lisp interpreter and the Common Lisp compiler is that the interpreter incorrectly uses dynamic binding for lexical variables?
16:24:14
Bike
yeah i can't tell if this thing is being weird about what is and isn't an nlambda. (rpl n form) "evaluates the expression form n times" but it's just listed as a function
16:30:28
beach
jcowan: What would be the special features of Medley that make it the preferred choice over a modern Common Lisp implementation?
16:31:16
beach
Interlisp obviously, but what makes Interlisp preferable to a modern Common Lisp implementation today? And why do you want Common Lisp as one of the languages in Medley?
16:33:34
jcowan
The work rquired to upgrade Medley CL to the ANS should be fairly small; the biggest part is figuriung out wht needs fixing.
16:34:22
jcowan
Admittedly, Medley doesn't look that much like a modern concensus IDE, but more so than Emacs.
16:35:00
Bike
the part of the manual about the environment is longer than the part about the language
16:38:37
jcowan
Maclisp effort wentt into building the language; IL effort into building the environment.
16:40:32
_death
jcowan: one question is how to conciliate a saved image and new changes in the medley repo
16:41:03
jcowan
I have also thought a little about what it would take to implement IL in CL, thus providing the Medley environment with the speed of a modern CL
16:46:17
jcowan
But beyond that you would, I hope, only need to implement the functions currently written in C.
17:40:56
lisp123
one of the ancestors of Common Lisp, there was a discussion earlier today on it. Apparently it had a very good development environment
17:46:48
cosimone
hello, is there some way, to your knowledge, to manipulate the internal representation of floating point numbers as something such as a bit vector?
17:54:28
Bike
there's also https://github.com/Shinmera/float-features which uses implementation specifics to get the actual bits, which is maybe what you want
17:58:58
yitzi
Bike: I saw in the ANSI spec that attempting to delete the cl or keyword package is unspecified behavior. Any idea why that would even be permitted? Some implementation prevent it and some actually let me do it.
17:59:35
Bike
when the standard says something like that i think it's more to let implementations be lazy by not putting in measures to prevent it, rather than because doing it is a good idea
18:00:28
yitzi
Amazing. CCL actually let me do it. SBCL gave me a pile of restarts and then let me do it and then promptly froze.
18:05:43
yitzi
Yeah, both tried to stop me with package locks. So far only ECL and CLASP said no outright. ABCL just did so without complaint.
19:08:38
recordgroovy
ABCL lets me define a condition inheriting stream-error, but doesn't let me apply stream-error-stream to it, hmm...
20:37:44
pjb
recordgroovy: this is indeed an error: (define-condition sec(stream-error) ()) (subtypep 'sec 'stream-error) --> T, T
20:38:26
recordgroovy
I've heard (but haven't experienced) that ABCL has a strange relationship with CL streams, as well
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.