IRC channel logs

2020-10-12.log

back to list of logs

<dustyweb>cbaines: aroun?
<dustyweb>around?
<dsmith>sneek: botsnack
<sneek>:)
<dsmith>goodbot
<libfud>sneek: help
<libfud>sorry, just wanted to see if I could poke the bot
<libfud>neat bot, that's another project on my todolist
<rgrmrts>I'm working through SICP right now and in the first chapter there's a part about re-implementing `if` using `cond`, it goes on to ask what happens to our square root implementation using this new-if and using guile it never terminates. I'm trying to understand why. gist with code: https://gist.github.com/rgrmrts/af34bc6e778176feb87c2cdca59fac3d, any clues?
<rgrmrts>I realize this isn't related to guile specifically, sorry if this is a wrong channel
<ft>You can't implement if as a function in languages that evaluate eagerly, like Scheme. The function only gets applied after *all* its operands have been evaluated.
<libfud>if is a special form
<libfud>the interpreter treats it differently than procedures
<libfud>(to rephrase what ft is saying)
<rgrmrts>thank you both for the response!
<libfud>what's the motivation behind comma commands in guile?
<ft>In the recursive case, your new-if gets its predicate, consequence and alternative arguments, and scheme evaluates all of them. The alternative has the recursive call, so it never can terminate, even if the predicate returns #t.
<libfud>e.g. why ,apropos foo instead of (apropos foo)?
<rgrmrts>was just typing up: so if this weren't a recursive function, the "new-if" would have probably been fine
<ft>(apropos foo) would be subject to the namespace that's currently active. (I guess - I have no insight into the design decision)
<rgrmrts>makes sense! I haven't quite processed _why_ the recursive call doesn't terminate but I can think on that.
<rgrmrts>thanks!
<libfud>well
<libfud>it actually does matter regardless of it it's recursive or not
<libfud>for example (if predicate (set! foo (+ foo 1)))
<ft>Yeah, mutation can be a problem. I/O can. Lots of things can.
<libfud>nothing recursive about that, but you only want to evaluate it on the predicate being true
<ft>Also, vasted CPU cycles. :)
<rgrmrts>hmm
<rgrmrts>ohhh
<rgrmrts>okay, making more sense now
<libfud>I think the purpose of the exercise is to introduce the idea of special forms behaving differently, and why it's desirable for them to behave as much
<libfud>*as such
<rgrmrts>word, I was curious about why special forms exist in some cases
<libfud>to translate it in terms of assembly instructions, conditionals are branching instructions that operate on the program counter, "skipping" over instructions
<ft>In the case of ‘if’, its purpose is to break the usual evaluation rules. :)
<libfud>define and set! are also special forms
<rgrmrts>eureka :)
<rgrmrts>thank you libfud and ft!
<dsmith>libfud: The comma commands at the repl are convenient magic syntax because normally commas are only used in quasi-quote.
<libfud>dsmith: so just a feature of convenience to save some keystrokes?
<libfud>*me is not complaining, just curious
<libfud>er, /me, not *me
<libfud>whatever
<dsmith>I'm just guessing.
<ft>If you're in a module that implements a function or macro called ‘apropos’, (apropos foo) won't work anymore. ",apropos foo" always can, because its a meta-command, independant of the currently active module.
<dsmith>Not so much saving keystrokes. More like (ab)using invalid syntax to provide repl-specific commands.
<ft>And dsmith is probably right about why the comma was chosen.
<libfud>ft: so even if in the global environment I bind apropos to something else, it will still work?
<libfud>or am I mistaken in calling the environment that you start out the REPL in the global environment?
<ft>libfud: ,apropos probably calls out to the global definition, so that probably won't work.
<ft>Yeah, (set! apropos identity) breaks it.
<ft>I wonder if a local definition would shadow this. Hum.
<libfud>it's fun to break things and play in the mud :)
<ft>I tried. It calls out the the global one.
<ft>And only if you override that one using set! things break, understandably.
<ft>So it's more than just convenience.
<libfud>hmmmm... since i'm going over SICP myself, could you implement if as a function with force and delay?
<ft>If you force your users to obey that, yeah.
<ft>That's why you can implement if as a function in lazy languages like Haskell.
<libfud>ah, right, because you can't delay the input expressions in the body
<libfud>is literally everything in haskell lazily evaluated?
<ft>There are ways to force eager evaluation for selected expressions.
<ft>But the default is lazy evaluation.
<libfud>since I don't see this in SICP and it just says "cons-stream is a special form defined so that (cons-stream <a> <b>) is equivalent to (cons <a> (delay <b>))"
<libfud>is the following a good way to express that?
<libfud>(define-syntax cons-stream (syntax-rules () ((cons-stream a b) (cons a (delay b)))))
<rekado>libfud: I don’t know if there’s anything else to it, but you can also use define-syntax-rules here
<RhodiumToad>define-syntax-rule is a very useful shorthand for simple macros
<rekado>(define-syntax-rule (cons-stream a b) (cons a (delay b)))
<rekado>libfud: Guile has srfi-41 for streams, though, so you could use that instead :)
***daviid is now known as Guest14267
<dsmith-work>Hey hey Guilers
<leoprikler>Just a heads up, I think make-variable-transformer is not working correctly in the case of (set! (alias arg ...) value)
<emys>how can I invoke guile for executing a compiled .go file directy (instead of refering to the source file?)
<libfud>guile can execute Go?
<libfud>or is that the extension of compiled guile code?
<justin_smith>libfud: it stands for "guile object" and predates the google funded programming language
<ArneBab>libfud: my guess about the comma-commands is that a comma is always illegal in toplevel-scope, so it can be used to start arbitrary parsing without breaking anything in the very moldable scheme.
<libfud>justin_smith: yeah I figured that out after looking at the documentation
<justin_smith>see also cmucl which has a compailer called "python"
<emys>another question: can I somehow get the 'type' of an object / variable?
<rekado>emys: guile -c '(load-compiled "foo.scm.go")'
<emys>thanks rekado
<rekado>emys: if you’re using GOOPS you can do
<rekado>class-of
<rekado>,use (oop goops)
<rekado>(class-of "hello")
<rekado>but that’s perhaps a little heavy
<justin_smith>I've often wished the logic of "class-of" existed outside goops
<emys>rekado, that will do for me, its just for debugging purposes
<dsmith-work>emys: Outside of goops, you need explicitly check for the type.
<dsmith-work>emys: Like with string? number? pair? etc.
<emys>emys, full story is I did two mistakes, the first one led to the wrong behaviour, the second meant that (write x) debugging did show a different variable, so I didn't realize I was actually using the list/pair instead of the list-element in my code
<emys>class-of gave me the info that I was dealing with a pair, then I realized I was writing out the wrong value and I was able to see what I did wrong
<emys>dsmith-work, thats what I was using class-of for :-) and in this case goops was fine
***jonsger1 is now known as jonsger