freenode/#lisp - IRC Chatlog
Search
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"
21:26:30
phoe
so, yes, EACH function invocation needs to follow the rule of function invocation that says "eval the data first and then do something with it"
21:30:01
White_Flame
theseb: looking back at your original question, you're really wanting either a macro (which does composite together sexprs as literal source code at compile-time) or an inline EVAL (when the code isn't available at compile-time). Neither of these are likely what you really intend for the problem though, they are mappings of your solution to get them to work
21:30:15
theseb
phoe: should this work?...i wrote a for macro that works like this (for i (3 4 5) ....)
21:30:42
theseb
phoe: can i wrap with a regular function...call it for-wrapper...and then do (for-wrapper 'i '(3 4 5) ...)?
21:31:35
theseb
phoe: i got everything you said...but a similar wrapper like ^^^ doesn't work in my lisp implementation and my brain is fried so not sure if it is a bug or my misunderstanding
21:31:45
White_Flame
if you want to pass in functionality, the easiest way is to give it a function object, likely a LAMBDA form
21:32:01
aeth
White_Flame: while (a (b (c 4))) is no different than any other major language, a hypothetical (a (b 4) (c 4)) can often differ between languages because some are left to right, some are right to left, some are unspecified, and a few are probably some weird order.
21:32:58
aeth
White_Flame: quite a few popular languages are unspecified order, iirc including C. Almost every language is eager. But this is getting off-topic.
21:33:24
White_Flame
right,the topic is theseb's understanding as it intersects with Lisp. I don't think that esoteric evaluation semantics are involved
21:34:55
aeth
(well, there might be a few other necessary points to mention, like CL does *not* copy the function arguments when you call a function.)
21:36:21
theseb
phoe: because for-wrapper is a regular function...the input is first evaluated....giving i = i, l = (3 4 5)
21:37:01
phoe
and that's not very impressive when you want to perform some side effects, such as printing stuffs
21:37:58
theseb
(for-wrapper 'i '(3 4 5) ...)....step 1...do eval...so i = i and l = (3 4 5) and c = ...
21:41:05
theseb
phoe: but for-wrapper i thought did the "search and replace" on the i l and c in (for i l c)
21:41:31
phoe
nope, for-wrapper itself is a function. all it has is three variables that are its function arguments.
21:42:32
phoe
once the macro is expanded, then it's expanded; the function is left with whatever expansion the macro produced, but it *still* gets its arguments as data.
21:42:43
Inline
how do you read defmethod forms when they are referencing globals in their respective file ?
21:43:27
White_Flame
"replaced" isn't a standard term. When slicing into such specific details, it's best to use "bound", "evaluated", "referenced", etc
21:44:08
phoe
theseb: then SOME-FUNC will be called with the same set of values that FOR-WRAPPER was called with
21:44:43
White_Flame
theseb: and it would be called _at compile time_, and the results of the SOME-FUNC call would be returned as the new source code to compile & execute at runtime!
21:45:57
White_Flame
theseb: it is extremely likely that you want the intended LOOP exeucted at runtime, with runtime arguments, not at compile-time
21:46:29
theseb
phoe: i think if you can just explain why it becomes (some-func 'i '(3 4 5) '(print z)) i'll be good
21:48:21
phoe
you still have a mental substitution model that implies that after each substitution you need to evaluate again
21:49:24
phoe
also your model seemed to enjoy sticking literal values into code without quoting them first.
21:50:12
phoe
theseb: sooner or later, a person will come at #lisp or #clschool asking novice Lisp questions
21:50:37
phoe
you will repay me well enough by answering them to the best of your ability and fixing up your knowledge in places where you are unable to answer their questions
21:51:20
phoe
theseb: yes, quotes should work well in that case when you're substituting function arguments.
21:52:26
White_Flame
and if you're running the loop at compile-time, (defun foo () (for ..)) will run the loop once, no matter how many times you call FOO
21:53:02
theseb
phoe: that one is interesting because i don't know what the "value" of (print 42) is
21:54:40
phoe
;; it's shamefully convenient for print-style debugging; when you have some function call whose value you want to inspect, just wrap (foo) and get a (print (foo))
21:55:10
phoe
that will work as long as you don't play with multiple values, but that can also be worked around
21:56:42
aeth
(defun multiple-value-print (&rest values) (format t "~{~A~^ ~}" values) (values-list values))
22:00:47
aeth
Technically speaking, you'd probably want to make multiple-value-print a macro that can deal with values and call the function %multiple-value-print or something.
22:02:11
aeth
It's more consistent in the naming, since then you pretend that multiple-value-print is like m-v-c or m-v-b etc.
22:04:05
White_Flame
this is what I use, which prints out "EXPR = values": https://pastebin.com/aA19tPLs (cleaned up a bit)