Scheme style blocks in Snap!

Because of something Brian said, I tried to make Lisp-style lists in Snap!, and this is what I came up with.
You can drag the block above into Snap! to try it out.

The this works by turning a list into nested pairs.

Here's the link

Whoa, that's an amazing piece of code. It would never have occurred to me to do that! I still haven't quite worked out why it works...

Honestly, I wouldn't focus so much on improper lists. These days, when memory is free, I hardly ever see a situation in which it's really practical to use them. What I do, see, though, is the use of a single pair as a pattern to match (first . rest) of a regular list. And there's an aesthetic symmetry to using car and cdr as the selectors in a situation in which there are always exactly two components of something, such as x and y coordinates in the plane.

In implementing streams, I suppose it'd be aesthetically pleasing if the tail of a stream used the same selector as the tail of a list.

But if I really felt strongly about improper lists, I'd (sorry, Jens) write a JS Function-based CONS, i.e., an IN FRONT OF whose second input could be any value. But you'd also have to read all of lists.js to make sure that using one wouldn't make some other list primitive explode.

Why, thank you!

It's actually quite simple. A Linked list is just a pair of items, with the second item being a link to a second pair, and so on. So, I thought $$\textrm{ "Why not drop the link, and put the second pair into the first?"}$$ The specifics of the implementation came to me in a dream last night. (That happens a lot for me.)

I figured that COMBINE doesn't have to use a JOIN or +. I just combine items from the inside out in nesting lists. It's as easy as that.

I just created the SELECTOR block!

Scheme Lambda using metaprogramming!

Oh I see, that's why you have to reverse; now I just have to understand why doing it two levels deep (rather than recursively) is good enough.

Cool! I point out that your RUN OVER LISP LIST could just be RUN OVER; there's nothing specific to lists in it.

Combine does it for me!


I get the pun! funny! (Poor toddler.)­

Or maybe this?

Oh... what if the input is a list of lists? Or a list of list of lists? That's what's confusing me.

There's a PIPE block?! Does it work like the | operator on UNIX systems?

I updated the XML.

I can't seem to tell what's wrong with my custom call var block.

(In this script, the (double 4))

No, the | is the OR operator in binary, like:

---- |

This is a bitwise operator, it's like:
untitled script pic (34)

The pipe is not the OR operator.

Weird, I don't know how to solve it...

Oh I love you! This is a great inspiration. But I need one little change: It should instead report

and the next time you call your λ block it should use G3 and G4, etc.

I think that'll solve my problem about scope of script variables by finessing it--never having conflicting variable names.

(Historical note: The "G" stands for "gensym," i.e., "generated symbol." You want a reporter GENSYM, no inputs, that reports the next variable name.)

The UNIX terminal | is not used as a bitwise operator - it is a pipe operator that lets you send the output of one command into the next one

ps aux

gives list of all processes running

ps aux | grep mosquitto
pipes the ps aux output into grep which then searches for a process called mosquito

(08:00 at 2/4/2024 edit)

I'm talking about the | operator on the UNIX command line, as in:
ps -aux | grep virus, which passes the output of ps as the input to grep.

Would I use a variable to keep track of the last G?

Why, thank you! (Note, that was a joke.)

Is pic what you're looking for?
You can totally pass something that isn't a list to it
, and lists, to!
Lisp-Style Lists script pic

(09:00 on 2/4/2024 edit)

I'm not sure how to properly replace the upvars inside the λ with the G name, in
I probably need to not use an iteration, since it's a tree, but I'll figure it out.

I now that, if any item in the tree is pic (i.e. a list of two items containing car: a ring of a blank variable reporter cadr: a string that is in the list of inputs), I need to replace the cadr with the proper Gx name.

I think I just figured out what you mean in this. You wouldn't use a normal Snap! list in it, as it doesn't recursively loop over the list, as in

It expects you to pass in only Lisp-style lists, as in
. (You can use the veradic input to cast a list.)

(10:00 at 2/4/2024 edit)

(let ((^ (lambda (num exp)
        (if (= exp 1)
         (* num (^ num (- exp 1)))
(^ 3 2)


It's nice to see a Scheme program I wrote working with minimal effort to translate it!

(13:00 at 2/4/2024 edit)

I'm still not sure what to do with pic.

I think you may have set the record for number of edits to a post! :~)

Yes. I'd settle for a global variable, although maybe you could get away with a block variable (in the Jens sense, right-click on the hat block in the editor) if you only ever use one physical copy of the gensym block. That would arguably be cleaner.

Computationally, yes, but what's in those speech balloons doesn't look like dotted pairs, and the lists don't look like lists either -- that is, they don't look like the lists they're meant to represent. We already have linked lists in Snap!, so I'd want to make the minimal change to allow those lists to be improper. We'd have to invent an output representation like
or something, too.

This is my nominee for the most beautiful piece of code ever.

That's still only two deep. What about

'(((a b c) (d e f)) (g h i))



This is the problem I'm trying to solve, for which I need gensyms.

I don't see what the problem is. A QUOTEd list is just treated like a single item of the list, even if it contains more QUOTEd lists.

Gee, thanks! I'll use that!

I see. I'll look at lists.js...

Yay, λ Calc!

I'm not sure of that...

(17:01 at 2/4/2024 edit)

My new λ mostly working, but I'm not sure how to fix this bug...

Okay, they all seem to be un-reversed, so I'm convinced.

Umm. I'm not sure where that problem comes from.

Oh, I see, you want to allow literal text as inputs. But there isn't any text in lambda calculus! The only data type is Reporter. So I think your problem doesn't arise.

[offtopic]i'm making a command line thing, should i include something like that?

That would be good.

just one thing though... how does it actually work?

(20:08 at 2/4/2024 edit)

I made a COND block!

That was similar to my reporter version of the multi-branched conditional block but that was exceptional. :smiley:


"Young adult" means 18-21? I think to librarians it means middle school (11-14) and up.