I guess you could fairly easily write a macro that automatically created a lexical scope and added some prefixes to variable used within its body - Doug Hoyte's "Let over lambda" book has #CommonLisp examples of this kind of approach as way to cut down the syntactic overhead of using gensym in macros. Without much thought, I'd assume something similar could be done in #EmacsLisp
@The ol' tealeg π‘ I'm thinking something a little more robust involving using a symbol's property list to store everything contained within that namespace.
I'm probably biting off more than I can chew at this point in my understanding of elisp, but I'm sure this idea will stick around in my brain until I have enough of an understanding to pull it (or something comparable) off.
...or I find some already existing thing that does what I want (which is more likely).
SBCL, for example, has the in-package macro set the value of the special variable *PACKAGE* which, I guess, would then ultimately get used in every definition and reference.
I haven't having looked at it, but I imagine that it mostly comes down to switching out in-buffer eval functions to those which are current-package aware. If you resolve and swap out all symbols with their "absolute" versions during definition, you should be able to call that code from different namespaces without problems.
where (:use nil) serves the same purpose as (:use :cl) in Common Lisp.
Afterwards, you can either do
(in-namespace :foo) ...
or
(with-namespace :foo ...)
You should also be able to file-locally set `buffer-namespace', but I haven't tried it.
Here's a working snippet:
(define-namespace :foo (:use nil) (:export bar setq nil))
(define-namespace :baz (:use :foo) (:export bar))
(with-namespace :foo (setq foo 2))
foo:bar ;; => 2
(with-namespace :baz (setq bar 5) (setq quux 10))
foo:bar ;; => 5 baz:bar ;; => 5 baz:quux ;; => 10
although you'll need to patch elisp--preceding-sexp for C-x C-e to see the individual values. Here's the code you need to evaluate (at least on my version, I suggest trying this in a fresh emacs in case something goes wrong): 0x0.st/84sj.txt
I have fleshed it out more (or rather, ported over CL's packages): git.sr.ht/~thuna/cl-package (this is still the same repo, but I've changed the name).
The demo is: - require cl-package / load cl-package.el - require cl-package-reader / load cl-package-reader.el - go to a new buffer (or the scratch buffer) - M-x cl-package-activate-reader RET - Insert the snippet - Do eval-buffer, or after applying the same patch as before (replace `(read...)' with `(funcall load-read-function...)' in `elisp--preceding-sexp') go through each form (you can skip cl-in-package) one by one with C-x C-e - Have fun
The snippet is:
(cl-defpackage test (:use :global) (:shadow baz) (:export baz))
Where the second nil means that no symbol with the literal name "test:baz" exists in emacs, and that the symbol we're referring to with test:baz is something else entirely, which you can also see with:
(eq (intern "test:baz") 'test:baz) => nil
There are probably a lot of problems, some of which are: - defpackage does not play nice with redefinitions (or rather, you can't do it at all), just pop cl-package-registry (but not completely, always leave the last item, if you want to fully reset it set it to (list obarray)) and redefine it again - I have the elisp runtime in the pseudo-package :global, but trying to use :global in your own package will force it to check all (tens of thousands of!) symbols for conflicts, so it'll take a couple seconds during the defpackage in the snippet. I will later define packages containing the various elisp packages for proper modularity, so it should get better - Once you evaluate cl-in-package, eval-buffer starts with cl-in-package, which it probably shouldn't be doing, but I don't know and who knows how many more!
@screwtape Oh come on you understand the situation perfectly ;) You can write hacks to make it look like there are namespaces, but at the end of the day, they are just hacks.
There has been multiple discussions about it on emacs-devel, and there is no way to get elisp out of the dark ages until the usual suspects are replaced. Which is not happening any time soon.
@screwlisp @Nicolas Martyanoff If you think I'd actually have anything interesting to say. I feel I can't really hold a candle to some of your previous guests. I'm just aimlessly noodling around with stuff.
You know I like to set an extremely low bar for quality personally. And after all, everyone eats at your sushi place every week...!
It's also interesting to everyone to get opinions on common lisp from the outside or somewhat recent arrivals. I think you and jeremy_list are both interesting as sort of Haskell/MOO/emacs/common lispers.
Counterpointing the "golang for serious business" long-time lisp-heads like @galdor
Harald
in reply to Jonathan Lamothe • • •Currently there are two options which help for the underlying problem:
gnu.org/software/emacs/manual/β¦
gnu.org/software/emacs/manual/β¦
I use both here:
codeberg.org/harald/eglot-suppβ¦
For the shorthands, check the last few lines of the file.
But, no doubt, some real namespace with an export/import convention would be great.
eglot-supplements/eglot-selran.el at main
Codeberg.orgThe ol' tealeg π‘
in reply to Jonathan Lamothe • • •Jonathan Lamothe
in reply to The ol' tealeg π‘ • •@The ol' tealeg π‘ I'm thinking something a little more robust involving using a symbol's property list to store everything contained within that namespace.
I'm probably biting off more than I can chew at this point in my understanding of elisp, but I'm sure this idea will stick around in my brain until I have enough of an understanding to pull it (or something comparable) off.
...or I find some already existing thing that does what I want (which is more likely).
The ol' tealeg π‘
in reply to Jonathan Lamothe • • •Vassil Nikolov
in reply to The ol' tealeg π‘ • • •@tealeg
Just a sidenote, but `in-package' and Co. are Common Lisp things, not just SBCL's.
And `*package*' is mainly used by the reader.
#CommonLisp
The ol' tealeg π‘
in reply to Vassil Nikolov • • •@vnikolov the specific macro expansion can differ though, right?
Really I was just quickly checking by doing `(macroexpand β(in-package foo))`, I never really thought much about the implementation before now.
Vassil Nikolov
in reply to The ol' tealeg π‘ • • •@tealeg
tealeg@mastodon.online> the specific macro expansion can differ though, right?
Yes, and it often does (and it may well contain implementation-specific items, of course).
And `macroexpand' is certainly a good way to explore things; just consult the specification as well (in this case the excellent Hyperspec, CLHS).
#CommonLisp
#CommonLispHyperSpec
Thuna
in reply to Jonathan Lamothe • • •Thuna
in reply to Thuna • • •Ok, here's a working(?) proof-of-concept for
#emacs namespaces: git.sr.ht/~thuna/namespace-el
In order to use it, go to your scratch buffer (or just any elisp
buffer), do M-x enable-namespace. Then, define a namespace via
(define-namespace :foo
(:use nil)
(:export my-symbols...))
where (:use nil) serves the same purpose as (:use :cl) in Common Lisp.
Afterwards, you can either do
(in-namespace :foo)
...
or
(with-namespace :foo
...)
You should also be able to file-locally set `buffer-namespace', but I
haven't tried it.
Here's a working snippet:
(define-namespace :foo
(:use nil)
(:export bar setq nil))
(define-namespace :baz
(:use :foo)
(:export bar))
(with-namespace :foo
(setq foo 2))
foo:bar ;; => 2
(with-namespace :baz
(setq bar 5)
(setq quux 10))
foo:bar ;; => 5
baz:bar ;; => 5
baz:quux ;; => 10
although you'll need to patch elisp--preceding-sexp for C-x C-e to see
the individual values. Here's the code you need to evaluate (at least
on my version, I suggest trying this in a fresh emacs in case
something goes wrong): 0x0.st/84sj.txt
Thuna
in reply to Thuna • • •I have fleshed it out more (or rather, ported
over CL's packages): git.sr.ht/~thuna/cl-package (this is
still the same repo, but I've changed the name).
The demo is:
- require cl-package / load cl-package.el
- require cl-package-reader / load cl-package-reader.el
- go to a new buffer (or the scratch buffer)
- M-x cl-package-activate-reader RET
- Insert the snippet
- Do eval-buffer, or after applying the same patch as before (replace `(read...)' with `(funcall load-read-function...)' in `elisp--preceding-sexp') go through each form (you can skip cl-in-package) one by one with C-x C-e
- Have fun
The snippet is:
(cl-defpackage test
(:use :global)
(:shadow baz)
(:export baz))
(cl-in-package :test)
(setq test:baz 10)
(message "%S" test:baz) ;; => 10
(intern-soft "test:baz") ;; => nil
Where the second nil means that no symbol with the literal name
"test:baz" exists in emacs, and that the symbol we're referring to
with test:baz is something else entirely, which you can also see with:
(eq (intern "test:baz") 'test:baz) => nil
There are probably a lot of problems, some of which are:
- defpackage does not play nice with redefinitions (or rather, you can't do it at all), just pop cl-package-registry (but not completely, always leave the last item, if you want to fully reset it set it to (list obarray)) and redefine it again
- I have the elisp runtime in the pseudo-package :global, but trying to use :global in your own package will force it to check all (tens of thousands of!) symbols for conflicts, so it'll take a couple seconds during the defpackage in the snippet. I will later define packages containing the various elisp packages for proper modularity, so it should get better
- Once you evaluate cl-in-package, eval-buffer starts with cl-in-package, which it probably shouldn't be doing, but I don't know
and who knows how many more!
#emacs
Nicolas Martyanoff
in reply to Jonathan Lamothe • • •vintage screwlisp account
in reply to Nicolas Martyanoff • • •@galdor
Nicolas Martyanoff
in reply to vintage screwlisp account • • •@screwtape
Oh come on you understand the situation perfectly ;) You can write hacks to make it look like there are namespaces, but at the end of the day, they are just hacks.
There has been multiple discussions about it on emacs-devel, and there is no way to get elisp out of the dark ages until the usual suspects are replaced. Which is not happening any time soon.
vintage screwlisp account
in reply to Nicolas Martyanoff • • •@galdor
jlamothe did say the words introducing rudimentary...!
By the way, should I interview you ("interview") some time?
@me
Jonathan Lamothe
in reply to vintage screwlisp account • •vintage screwlisp account
in reply to Jonathan Lamothe • • •You know I like to set an extremely low bar for quality personally. And after all, everyone eats at your sushi place every week...!
It's also interesting to everyone to get opinions on common lisp from the outside or somewhat recent arrivals. I think you and jeremy_list are both interesting as sort of Haskell/MOO/emacs/common lispers.
Counterpointing the "golang for serious business" long-time lisp-heads like @galdor
Jonathan Lamothe likes this.
Jonathan Lamothe
in reply to Jonathan Lamothe • •Greg A. Woods
in reply to Jonathan Lamothe • • •Have you read this yet?
emacs.stackexchange.com/questiβ¦