freenode/#lisp - IRC Chatlog
Search
9:51:56
phoe
Only partially Lisp-related question: is it possible to get something equivalent to (lambda () (go :foo)) or (lambda () (return-from :bar 42)) in some of the currently-popular programming languages? We assume that these lambdas were established in suitable lexical environments within proper TAGBODY/BLOCK forms.
9:52:40
phoe
I'm thinking about this since I'm currently chewing on one comment related to my book that touches this topic.
9:55:27
phoe
I see, so instead of invoking a function that came from the provided lexical environment, one can emulate TAGBODY/BLOCK using an try-catch form, and transfer control via throwing that exception.
10:04:32
phoe
_death: I actually started re-reading that article moments before you posted it now; it was posted recently
10:05:17
_death
another good resource is the book Lisp in Small Pieces, which has a chapter about throw/catch
10:08:38
_death
in metacircular, the catch macro in catch/throw emulated by tagbody/go is missing a parenthesis :x
11:08:50
jackdaniel
speaking of terms, any volunteers for proofreading and testing the terminal access tutorial?
11:53:51
jdz
jackdaniel: If it's about moving cursor around and switching terminal to non-canonical mode count me in.
11:55:41
jdz
Besides the one ECL issue I already reported I'm having another one with receiving SIGWINCH.
12:20:00
adlai
ACTION tried reading all of `man 1 kill`, it is worse than eating a whole page of lsd
12:20:46
adlai
in case you are unfamiliar with the latter metaphor, it does not fit within a metabolic segment, and is thus slang for "way too much"
12:23:49
phoe
I kind of disbelieve that I have an urge to ask "what is a metabolic segment" in context of discussing LSD on #lisp
12:32:45
jackdaniel
jdz: please report it of course. and yes, it is about moving cursor and switching terminal to non-canonical mode
14:10:22
theseb
Is it necessary to sometimes explicitly use eval in your code? I've been racking my brain on little projects and it seems sometimes you *must* use an eval in your code?
14:12:00
theseb
Bike: i'm writing a for loop ...i can do it as a macro or function...in both cases i can't see how to get everything w/o eval
14:12:33
Josh_2
in the one case where I could have used eval, instead I just compiled the source code and called the function
14:12:34
Bike
assuming you mean something like C for, that executes some code in a loop until a condition is met.
14:12:52
theseb
Bike: i create macro that allows....(for i (3 5 6) ....) that executes ..... for i = 3, 5, 6
14:13:20
theseb
Bike: problem is sometimes I need to do (for i foo ...) where foo evaluates to a list
14:13:40
Bike
You don't need eval for that either, and you should decide whether your macro evaluates the list or not.
14:14:26
Bike
e.g., if you have (for x (get-list y z) ...), is that supposed to be a list of three elements GET-LIST, X, Z, or is it supposed to call the GET-LIST function?
14:14:56
theseb
Bike: but if i do that using a regular function...I need eval to actually eval the .... !!! AHHHH!!
14:15:29
Bike
or the evaluated version, (defmacro for (var list &body body) `(loop for ,var in ,list do (progn ,@body)))
14:16:16
phoe
once you solve that problem, please just quote your lists and use (for i '(3 5 6) ...)
14:17:49
Bike
the question is whether (gethash x y) is evaluated, or treated as a list of three symbols
14:18:15
Bike
this is part of the semantics of your macro, and unrelated to using eval or not to implement it
14:18:33
Bike
but just to emphasize, either way, you definitely don't need to use the eval function.
14:19:05
Bike
FOR is a macro. It can just expand into code that involves evaluating the form. You don't need to call eval yourself.
14:19:06
phoe
theseb: (let ((y (make-hash-table)) (x :some-key)) (setf (gethash x y) '(1 2 3 4 5)) (for i (gethash x y) (print i)))
14:19:41
theseb
Bike: i'll need to define for as a regular function so that it evaluates the arguments...hence...i would do (for 'i (gethash x y) '...)
14:20:47
Bike
You need the form evaluated at run time, not at macroexpansion time, which is what you'd get with eval.
14:22:05
Bike
If you don't want to use LOOP, you could define it in terms of tagbody, though it might be too long for me to write as one line in chat.
14:22:07
theseb
Bike: (defmacro for (var list &body body) `(loop for ,var in ,list do (progn ,@body)))
14:22:38
phoe
also, you *never* need eval unless you really, really need it. most of the use cases can be achieved via closures or macroexpansions
14:23:12
phoe
eval usually comes into play when you need to be able to get commands from the programmer, which means that you have a REPL of some sort.
14:23:30
Bike
it's also important to understand that eval doesn't know about the lexical environment it's called in, so in this case you actually cannot use eval to achieve this, given that X and Y are lexical variables.
14:23:40
phoe
otherwise, for purely programmatic means of processing code, you do not really ever need it.
14:28:22
theseb
phoe: is there some general principle here that the magic is in using multiple levels of macros?
14:29:27
theseb
just wondering if that was the trick...regardless...i'll test it and think more today
14:29:39
Bike
and no, like i said, you can do this using tagbody, which is a special operator rather than a macro.
14:30:08
TMA
theseb: the magic is that the macro you write can produce any code you could have written instead. that code might or might not contain references to other macros (or even to the same macro)
14:30:44
Bike
yeah, try writing out how you'd do (for ...) if there is no for macro, and then have the for macro expand into that kind of code.
14:31:23
theseb
Bike: does your brain ever hurt trying to keep in your head which args should be quoted or not?
14:33:06
phoe
(defmacro for (variable value &rest body) `(block nil (let (,variable (list ,value)) (tagbody :check (when (null list) (go :exit)) :iterate (setf ,variable (pop list)) ,@body (go :check) :exit))))
14:34:54
phoe
TMA: (defmacro for (variable value &rest body) `(block nil (let (,variable (list ,value)) (tagbody :check (if (null list) (go :exit)) :iterate (setq ,variable (first list)) (setq list (cdr list)) ,@body (go :check) :exit))))
14:39:00
Bike
the point isn't the macros, anyway, it's that you can see that the macroexpansion does not evaluate the VARIABLE form, but does evaluate the VALUE form, based on their positions in the LET
14:39:54
phoe
or, in other words, the macroexpansion doesn't really evaluate anything, but it may choose what to quote and what not to quote
14:40:09
phoe
so that in the resulting macroexpansion there's stuff like 'I which, after normal evaluation, produces the symbol I
14:40:38
phoe
and there might also be stuff like (GETHASH X Y) which, after normal evaluation, produces the value associated with key X in hashtable Y
14:49:34
phoe
therefore people who write code that abuses EVAL have little feedback from the system to fix it so it does not use EVAL
14:50:08
phoe
and that, in turn, is non-trivial unless you actually reach out to other lispers or get a good code review which implies reaching out to other lispers
14:52:27
phoe
I gotta make a lisp meme sometimes that follows the greentext >learns about quote >notices that quote is the operator that allows stuff to be passed to eval >uses eval everywhere >"damn lisp is so slow"
14:58:18
theseb
Bike: just curious about your (defmacro for (var list &body body) `(loop for ,var in ,list do (progn ,@body)))....did it *have* to be a macro....could you get away with something like (defun for (var list body) (loop for var in list do (progn ???))) and later do (for 'i '(3 4 5) '(print i)) somehow?
14:59:42
Bike
I mean I guess you could do something stupid like (loop for x in list do (eval `(let ((,var ',x)) ,body)))
15:00:26
theseb
Bike: i wanted to see if an eval was necessary ;)...and you seemed to suggest it was ;)
15:00:47
Bike
Yes, if you want code to be evaluated at runtime you need to use EVAL (or COMPILE or something), like i said before
15:01:01
Bike
In this case you are defining that the FOR function must actually evaluate code, so that's natural
15:02:50
theseb
Bike: i'm not sure how you know the answers so fast...it takes me a while to reason thru all this
15:05:47
phoe
one comes after the other, with the exception of macroexpansion time which is usually a part of compilation time
15:07:00
phoe
and there's plenty to do in earlier times, since each of them has its own separate macro system
16:32:46
jmercouris
is it incorrect to say filename = (format nil "~a.~a" (pathname-name path-x) (pathname-type path-x)) ?
16:33:06
jmercouris
given some path, how to get file name? #P"/opt/local/lib/libz.dylib" trying to get "libz.dylib" as as tring, so I am doing the above
16:39:42
_death
the standard namestring functions are basically useless.. you want a native-namestring
17:37:09
yottabyte
I'm using https://www.cliki.net/html-encode but none of the functions listed seem to encode the space character to %20. is this perhaps the wrong library to use?
17:43:18
Bike
when a funcallable instance is updated for a different class, does the copy of the instance passed to update-instance-for-different-class still have the funcallable instance function?
17:44:15
Bike
i mean, it says you can't change-class a generic function, but that doesn't cover everything
17:45:43
phoe
but then again, an implementation might as well state that changing the fin's class, for whatever reason, invalidates the previous function
17:45:47
Bike
well, no, but the user method is passed a copy of the instance, and hypothetically they could call it
17:52:49
phoe
I could bet a few bucks that that some implementors might not even be aware that this might be a question
17:53:14
Bike
i guess you could just set the instance function to be the instance. that works, right? setting the instance function to be an instance?
17:55:32
phoe
I assume that if the function then modifies the original's slots, that's somehow accounted for by the programmer
17:55:50
phoe
because this means that when you funcall the instance, you then funcall the instance, which means that you funcall the instance
17:57:51
phoe
if the fin is implemented in a way where there's some sort of trampoline that jumps to the actual cl:function object, then it may jump to itself and we have an infinite loop
18:59:00
yottabyte
how do I specify query parameters in drakma? I tried to specify the :parameters but I have a GET request and it's trying to put that in the request body (which doesn't exist for GET requests)
19:12:10
yottabyte
I've been trying to add the query parameters explicitly on the end of the uri string, but encoding them is being problematic. for example (do-urlencode:urlencode "=") => %30
20:37:32
theseb
Can someone see https://pastebin.com/tNMse6f5 ??? Trying to understand why function f emits output but not function g
20:41:32
phoe
you tell LOOP that it should "do c". So it does - evaluating the variable C returns the two-element list (PRINT Z), and that's all.
20:41:47
theseb
phoe: yes but because g is a regular function...(g 'z '(5 6 7 8) '(print z)) sets i=z l=(5 6 7 8) and c = (print z)
20:42:15
Bike
you think that if you have a variable bound to the list (PRINT 'Z), every time you read that variable it will call print?
20:44:32
theseb
Bike: but l got replace with (5 6 7 8)....why didn't c also get replaced with its value?
20:48:07
theseb
Bike: CL does a "search and replace" before executing the loop....so it invokes (for z in (5 6 7 8) do (print z))
20:48:55
Bike
You could conceive of it as doing a search and replace. In that case it would replace C with '(print z).
20:49:48
theseb
phoe: "search and replace" may be a newb way to describe it....it is like in math.....f(x) = x + 1....to get f(4) in your head to do a "search and replace" to get 4 + 1..then you "execute" that
20:50:13
Bike
it's not completely unreasonable. But in this case you are doing the substitution incorrectly.
20:50:44
phoe
and so (loop for i in '(5 6 7 8) do '(print z)) becomes (loop for i in '(5 6 7 8) do (print z))
20:50:52
Bike
Substitution semantics also don't work when side effects exist, so you should try to avoid that model.
20:51:05
Bike
Actually it would be (loop for i in (5 6 7 8) do (print z)), so you'd get an illegal function call
20:51:33
phoe
oh, right! if you apply that to the second variable, why do you not apply it to the first one too
20:52:32
Bike
the trick is that, when the substitution is valid, it IS evaluation. It's not evaluate and then substitute, it's just substitute.
20:56:33
theseb
Bike: "It's not evaluate and then substitute, it's just substitute." <--- but i thought regular functions has to evaluate their args before anything happens..at least i think that's what SICP taught me about scheme
20:57:43
Bike
You seem to think that an argument is evaluated, and then the result of that evaluation is again evaluated.
20:58:12
Bike
In your model, first '(print z) evaluates to (print z), and then (print z) is evaluated to print. That's not correct.
20:59:28
Bike
Have you just ignored what we've been telling you for the last twenty minutes? No, it does not. Why would it? Why on earth would everything be evaluated twice?
21:00:58
Bike
Please use the school channel or something. You are misunderstanding very basic aspects of the language.
21:01:19
phoe
it only expands itself into some code that then, upon being evaluated, performs actual iteration
21:01:26
phoe
to simplify your example, (let ((i 'z) (l '(5 6 7 8)) (c '(print z))) (loop for i in l do c))
21:03:21
Bike
if you've read some of SICP, you should write a basic scheme interpreter yourself and see how things are evaluated and how macroexpansion and function calls work.
21:06:35
theseb
phoe: https://www.tutorialspoint.com/execute_lisp_online.php should print it like all the other output?
21:10:29
phoe
please consider (let ((i 'z) (l '(5 6 7 8)) (c '(1 2 3 4))) (loop for i in l do (progn c)))
21:14:21
phoe
I said that the *VALUE* of C is the list (1 2 3 4) because it is a result of eVALUEating '(1 2 3 4)
21:16:27
phoe
Inline: yes, but we were considering an example with LOOP earlier which does not have an implicit progn
21:17:16
theseb
phoe: so your point is function arguments get evaluated and then that DATA is used without being evaluated a second time?
21:18:26
phoe
you can force Lisp values to get evaluated again by using EVAL, but that's explicitly asking the compiler to perform evaluation again.
21:19:37
theseb
phoe: but we both agree that EVERY regular function call must eval its arguments first
21:20:18
theseb
phoe: so if a calls b calls c .... then every time you pass the data to a new function it has to get evaluated again
21:20:46
theseb
phoe: because the rules of function invocation say..."eval the data first and then do something with that"